@sherwoodagent/cli 0.85.1 → 0.86.1

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 (50) hide show
  1. package/dist/{chat-DNWTI4CZ.js → chat-ETZSKQDI.js} +13 -13
  2. package/dist/chat-ETZSKQDI.js.map +1 -0
  3. package/dist/{chunk-ARSQ5UQA.js → chunk-3IAZQMAW.js} +2 -2
  4. package/dist/{chunk-FPB23SDH.js → chunk-6QBGTX2Q.js} +93 -19
  5. package/dist/chunk-6QBGTX2Q.js.map +1 -0
  6. package/dist/{chunk-65G5BFYR.js → chunk-EA65CDQH.js} +3 -3
  7. package/dist/{chunk-53W6CYYV.js → chunk-EVUKJ7CJ.js} +2 -2
  8. package/dist/{chunk-AM6MI2JF.js → chunk-IAM4VIU2.js} +146 -23
  9. package/dist/chunk-IAM4VIU2.js.map +1 -0
  10. package/dist/{chunk-M4GX5PL2.js → chunk-OUYMZ5ZC.js} +2 -2
  11. package/dist/{chunk-TWT56FTL.js → chunk-XPVXNG2K.js} +3 -3
  12. package/dist/{chunk-6N7EVSAZ.js → chunk-YAS52NEF.js} +19 -6
  13. package/dist/{chunk-6N7EVSAZ.js.map → chunk-YAS52NEF.js.map} +1 -1
  14. package/dist/{chunk-VR4VHX4D.js → chunk-YMB4RJOR.js} +2 -2
  15. package/dist/{chunk-VR4VHX4D.js.map → chunk-YMB4RJOR.js.map} +1 -1
  16. package/dist/{chunk-I2BBOJNC.js → chunk-ZN2MHIB7.js} +2 -2
  17. package/dist/{eas-D3BVHBJH.js → eas-KMDAMLXW.js} +3 -3
  18. package/dist/{governor-35IXAEDJ.js → governor-JNSWPJVQ.js} +7 -5
  19. package/dist/{identity-3A2D7DGS.js → identity-ATWV2O7Y.js} +4 -4
  20. package/dist/index.js +239 -148
  21. package/dist/index.js.map +1 -1
  22. package/dist/{ipfs-EJ7IHXCU.js → ipfs-M56BLMCW.js} +2 -2
  23. package/dist/{price-I5T77X7Y.js → price-YNPYE2EO.js} +3 -3
  24. package/dist/{research-GZNVG3SP.js → research-W74PNYPO.js} +14 -14
  25. package/dist/research-W74PNYPO.js.map +1 -0
  26. package/dist/{session-M5QB25PK.js → session-HVRZ6AJM.js} +7 -7
  27. package/dist/{trade-TCQ5NUNA.js → trade-EOQY72L7.js} +10 -10
  28. package/dist/trade-EOQY72L7.js.map +1 -0
  29. package/dist/{vault-K2R4VHVI.js → vault-HWJQJW5U.js} +6 -6
  30. package/dist/{xmtp-R25Q5GWY.js → xmtp-KW73BGVO.js} +3 -3
  31. package/package.json +2 -2
  32. package/dist/chat-DNWTI4CZ.js.map +0 -1
  33. package/dist/chunk-AM6MI2JF.js.map +0 -1
  34. package/dist/chunk-FPB23SDH.js.map +0 -1
  35. package/dist/research-GZNVG3SP.js.map +0 -1
  36. package/dist/trade-TCQ5NUNA.js.map +0 -1
  37. /package/dist/{chunk-ARSQ5UQA.js.map → chunk-3IAZQMAW.js.map} +0 -0
  38. /package/dist/{chunk-65G5BFYR.js.map → chunk-EA65CDQH.js.map} +0 -0
  39. /package/dist/{chunk-53W6CYYV.js.map → chunk-EVUKJ7CJ.js.map} +0 -0
  40. /package/dist/{chunk-M4GX5PL2.js.map → chunk-OUYMZ5ZC.js.map} +0 -0
  41. /package/dist/{chunk-TWT56FTL.js.map → chunk-XPVXNG2K.js.map} +0 -0
  42. /package/dist/{chunk-I2BBOJNC.js.map → chunk-ZN2MHIB7.js.map} +0 -0
  43. /package/dist/{eas-D3BVHBJH.js.map → eas-KMDAMLXW.js.map} +0 -0
  44. /package/dist/{governor-35IXAEDJ.js.map → governor-JNSWPJVQ.js.map} +0 -0
  45. /package/dist/{identity-3A2D7DGS.js.map → identity-ATWV2O7Y.js.map} +0 -0
  46. /package/dist/{ipfs-EJ7IHXCU.js.map → ipfs-M56BLMCW.js.map} +0 -0
  47. /package/dist/{price-I5T77X7Y.js.map → price-YNPYE2EO.js.map} +0 -0
  48. /package/dist/{session-M5QB25PK.js.map → session-HVRZ6AJM.js.map} +0 -0
  49. /package/dist/{vault-K2R4VHVI.js.map → vault-HWJQJW5U.js.map} +0 -0
  50. /package/dist/{xmtp-R25Q5GWY.js.map → xmtp-KW73BGVO.js.map} +0 -0
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  parseAlignedOverrides,
32
32
  resolveToken,
33
33
  selectBestFeeTier
34
- } from "./chunk-ARSQ5UQA.js";
34
+ } from "./chunk-3IAZQMAW.js";
35
35
  import {
36
36
  DEFAULT_ISSUING_CHAIN_ID,
37
37
  appendVidTag,
@@ -47,9 +47,10 @@ import {
47
47
  encodeGuardianStake,
48
48
  encodeGuardianUnstake,
49
49
  encodeJoinRequest,
50
+ encodeMgmtSplit,
51
+ encodePerfSplit,
50
52
  encodePropose,
51
53
  encodeProposeWithSandbox,
52
- encodeProtocolFeeBps,
53
54
  encodeRedeem,
54
55
  encodeRegisterAgent,
55
56
  encodeSettle,
@@ -64,7 +65,7 @@ import {
64
65
  setCalldataOnly,
65
66
  stripVidTag,
66
67
  verifyVidTag
67
- } from "./chunk-FPB23SDH.js";
68
+ } from "./chunk-6QBGTX2Q.js";
68
69
  import {
69
70
  createApproval,
70
71
  createJoinRequest,
@@ -74,20 +75,20 @@ import {
74
75
  queryJoinRequests,
75
76
  revokeJoinRequest,
76
77
  stripReferrerPrefix
77
- } from "./chunk-M4GX5PL2.js";
78
+ } from "./chunk-OUYMZ5ZC.js";
78
79
  import {
79
80
  createFund,
80
81
  getActiveFunds,
81
82
  getFund,
82
83
  subdomainExists,
83
84
  updateMetadata
84
- } from "./chunk-53W6CYYV.js";
85
+ } from "./chunk-EVUKJ7CJ.js";
85
86
  import {
86
87
  resolveFund,
87
88
  resolveVaultFund,
88
89
  searchFundAcrossChains,
89
90
  setTextRecord
90
- } from "./chunk-I2BBOJNC.js";
91
+ } from "./chunk-ZN2MHIB7.js";
91
92
  import {
92
93
  approveDepositor,
93
94
  deposit,
@@ -110,8 +111,8 @@ import {
110
111
  removeDepositor,
111
112
  setAgentFeeBps,
112
113
  setVaultAddress
113
- } from "./chunk-TWT56FTL.js";
114
- import "./chunk-65G5BFYR.js";
114
+ } from "./chunk-XPVXNG2K.js";
115
+ import "./chunk-EA65CDQH.js";
115
116
  import {
116
117
  PROPOSAL_STATE,
117
118
  PROPOSAL_STATES,
@@ -144,12 +145,13 @@ import {
144
145
  setExecutionWindow,
145
146
  setMaxPerformanceFeeBps,
146
147
  setMaxStrategyDuration,
147
- setProtocolFeeBps,
148
+ setMgmtSplit,
149
+ setPerfSplit,
148
150
  setVetoThresholdBps,
149
151
  setVotingPeriod,
150
152
  settleProposal,
151
153
  vote
152
- } from "./chunk-6N7EVSAZ.js";
154
+ } from "./chunk-YAS52NEF.js";
153
155
  import {
154
156
  AERODROME,
155
157
  MOONWELL,
@@ -158,7 +160,7 @@ import {
158
160
  TOKENS,
159
161
  UNISWAP,
160
162
  VENICE
161
- } from "./chunk-AM6MI2JF.js";
163
+ } from "./chunk-IAM4VIU2.js";
162
164
  import {
163
165
  GAS_UNITS,
164
166
  estimateGasCushion,
@@ -217,7 +219,7 @@ import {
217
219
  fetchMetadata,
218
220
  mergeFundMetadata,
219
221
  uploadMetadata
220
- } from "./chunk-VR4VHX4D.js";
222
+ } from "./chunk-YMB4RJOR.js";
221
223
 
222
224
  // src/index.ts
223
225
  import { config as loadDotenv } from "dotenv";
@@ -490,7 +492,7 @@ function registerGuardianCommands(program2) {
490
492
  }
491
493
  });
492
494
  guardian.command("prepare-owner-stake <amount>").description(
493
- "Bond WOOD as a prospective vault owner \u2014 required before `fund create`. Amount in WOOD (min = swood.minOwnerStake, default 10000)."
495
+ "Bond WOOD as a prospective vault owner \u2014 required before `vault create`. Amount in WOOD (min = swood.minOwnerStake, default 10000)."
494
496
  ).action(async (amountStr) => {
495
497
  const amount = parseUnits(amountStr, 18);
496
498
  await ensureWoodAllowance(amount);
@@ -564,7 +566,7 @@ var TEMPLATES = [
564
566
  {
565
567
  name: "Moonwell Supply",
566
568
  key: "moonwell-supply",
567
- description: "Supply tokens to Moonwell lending market, earn yield",
569
+ description: "Supply tokens to the Moonwell lending market",
568
570
  addressKey: "MOONWELL_SUPPLY"
569
571
  },
570
572
  {
@@ -582,13 +584,13 @@ var TEMPLATES = [
582
584
  {
583
585
  name: "wstETH Moonwell Yield",
584
586
  key: "wsteth-moonwell",
585
- description: "WETH \u2192 wstETH \u2192 Moonwell \u2014 stack Lido + lending yield",
587
+ description: "WETH \u2192 wstETH \u2192 Moonwell \u2014 Lido staking plus lending",
586
588
  addressKey: "WSTETH_MOONWELL"
587
589
  },
588
590
  {
589
591
  name: "Mamo Yield",
590
592
  key: "mamo-yield",
591
- description: "Deposit into Mamo for optimized yield across Moonwell + Morpho vaults",
593
+ description: "Deposit into Mamo \u2014 routes across Moonwell + Morpho vaults",
592
594
  addressKey: "MAMO_YIELD"
593
595
  },
594
596
  {
@@ -940,7 +942,7 @@ function registerStrategyProposeCommands(strategy2) {
940
942
  `--proposer ${proposer} is not a registered agent on ${vault}; cloneAndInitDeterministic and propose will both revert.`
941
943
  )
942
944
  );
943
- console.error(chalk3.yellow(` Register first: sherwood fund approve --wallet ${proposer}`));
945
+ console.error(chalk3.yellow(` Register first: sherwood vault approve --wallet ${proposer}`));
944
946
  process.exit(1);
945
947
  }
946
948
  if (paused) {
@@ -977,7 +979,7 @@ function registerStrategyProposeCommands(strategy2) {
977
979
  process.exit(1);
978
980
  }
979
981
  if (!opts.agent) opts.agent = proposer;
980
- const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-35IXAEDJ.js");
982
+ const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-JNSWPJVQ.js");
981
983
  const strategyDuration2 = parseDuration3(opts.duration);
982
984
  const chainId = getChain().id;
983
985
  try {
@@ -1048,7 +1050,7 @@ function registerStrategyProposeCommands(strategy2) {
1048
1050
  console.error(
1049
1051
  chalk3.red(
1050
1052
  ` Signer ${account.address} is not a registered agent on ${vault}.
1051
- Register first via: sherwood fund approve --wallet ${account.address}`
1053
+ Register first via: sherwood vault approve --wallet ${account.address}`
1052
1054
  )
1053
1055
  );
1054
1056
  process.exit(1);
@@ -1208,9 +1210,9 @@ function registerStrategyProposeCommands(strategy2) {
1208
1210
  console.error(chalk3.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
1209
1211
  process.exit(1);
1210
1212
  }
1211
- const { propose: propose2 } = await import("./governor-35IXAEDJ.js");
1212
- const { pinJSON } = await import("./ipfs-EJ7IHXCU.js");
1213
- const { parseDuration: parseDuration2 } = await import("./governor-35IXAEDJ.js");
1213
+ const { propose: propose2 } = await import("./governor-JNSWPJVQ.js");
1214
+ const { pinJSON } = await import("./ipfs-M56BLMCW.js");
1215
+ const { parseDuration: parseDuration2 } = await import("./governor-JNSWPJVQ.js");
1214
1216
  const strategyDuration = parseDuration2(opts.duration);
1215
1217
  const metaSpinner = ora2("Pinning metadata to IPFS...").start();
1216
1218
  let metadataURI;
@@ -1242,11 +1244,11 @@ function registerStrategyProposeCommands(strategy2) {
1242
1244
  metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
1243
1245
  }
1244
1246
  try {
1245
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-K2R4VHVI.js");
1247
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-HWJQJW5U.js");
1246
1248
  const feeBps = await getAgentFeeBps2(vault);
1247
1249
  console.log(
1248
1250
  chalk3.yellow(
1249
- ` Agent fee for this proposal: ${Number(feeBps) / 100}% (the vault's current agentFeeBps). Run \`sherwood fund set-agent-fee --bps <bps>\` first to change it.`
1251
+ ` Agent fee for this proposal: ${Number(feeBps) / 100}% (the vault's current agentFeeBps). Run \`sherwood vault set-agent-fee --bps <bps>\` first to change it.`
1250
1252
  )
1251
1253
  );
1252
1254
  } catch {
@@ -1513,7 +1515,7 @@ function registerStrategyTemplateCommands(strategy2) {
1513
1515
  let prices = [];
1514
1516
  let priceSource = null;
1515
1517
  try {
1516
- const { getTokenPricesInAsset } = await import("./price-I5T77X7Y.js");
1518
+ const { getTokenPricesInAsset } = await import("./price-YNPYE2EO.js");
1517
1519
  prices = await getTokenPricesInAsset({
1518
1520
  tokens: allocations.map((a, i) => ({
1519
1521
  token: a.token,
@@ -1943,7 +1945,7 @@ function registerVeniceCommands(program2) {
1943
1945
  console.log(chalk5.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
1944
1946
  console.log(chalk5.dim(" Saved to ~/.sherwood/config.json"));
1945
1947
  try {
1946
- const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-D3BVHBJH.js");
1948
+ const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-KMDAMLXW.js");
1947
1949
  const attestation = await createVeniceProvisionAttestation(account.address);
1948
1950
  if (attestation) {
1949
1951
  console.log(chalk5.dim(` Attested: ${getEasScanUrl(attestation.uid)}`));
@@ -2299,7 +2301,7 @@ ${opts.prompt}`;
2299
2301
  console.log(chalk5.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
2300
2302
  }
2301
2303
  try {
2302
- const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-D3BVHBJH.js");
2304
+ const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-KMDAMLXW.js");
2303
2305
  const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
2304
2306
  const { getChainContracts: getChainContracts2 } = await import("./config-ZGFS4I7K.js");
2305
2307
  const { getChain: getActiveChain } = await import("./network-FEHRFDPJ.js");
@@ -3298,7 +3300,7 @@ function printSimulationResult(result, callType) {
3298
3300
  }
3299
3301
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
3300
3302
  try {
3301
- const xmtp = await import("./xmtp-R25Q5GWY.js");
3303
+ const xmtp = await import("./xmtp-KW73BGVO.js");
3302
3304
  const { getAccount: getAccount2 } = await import("./client-3SE632Q2.js");
3303
3305
  const group = await xmtp.getGroup("", subdomain);
3304
3306
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
@@ -4774,7 +4776,7 @@ function registerProposalCommands(program2) {
4774
4776
  process.exit(1);
4775
4777
  }
4776
4778
  });
4777
- proposal.command("simulate").description("Simulate proposal calls via Tenderly (or eth_call fallback)").option("--id <proposalId>", "Proposal ID to simulate").option("--vault <address>", "Vault address (required \u2014 proposal IDs are per-vault)").option("--execute-calls <path>", "Path to JSON execute calls file").option("--settle-calls <path>", "Path to JSON settlement calls file").option("--notify <subdomain>", "Send results to fund XMTP chat").action(async (opts) => {
4779
+ proposal.command("simulate").description("Simulate proposal calls via Tenderly (or eth_call fallback)").option("--id <proposalId>", "Proposal ID to simulate").option("--vault <address>", "Vault address (required \u2014 proposal IDs are per-vault)").option("--execute-calls <path>", "Path to JSON execute calls file").option("--settle-calls <path>", "Path to JSON settlement calls file").option("--notify <subdomain>", "Send results to vault XMTP chat").action(async (opts) => {
4778
4780
  try {
4779
4781
  let vault;
4780
4782
  let executeCalls;
@@ -5386,14 +5388,78 @@ function registerGovernorCommands(program2) {
5386
5388
  succeed: (v) => `Cooldown period updated to ${v}s (reverts if the vault has an open proposal).`,
5387
5389
  failText: "Failed to set cooldown"
5388
5390
  });
5389
- governor.command("set-protocol-fee").description("Set the protocol fee in bps on ProtocolConfig (protocol owner only)").requiredOption("--bps <n>", "New protocol fee in bps (e.g. 500 = 5%, max 1000 = 10%)").action(async (opts) => {
5390
- const rawValue = String(opts.bps);
5391
+ const parseSplitLeg = (raw, label) => {
5392
+ const v = Number(parseBigIntArg(String(raw), label));
5393
+ if (v > 1e4) {
5394
+ console.error(chalk10.red(`--${label} must be <= 10000 bps, got ${v}`));
5395
+ process.exit(1);
5396
+ }
5397
+ return v;
5398
+ };
5399
+ const requireSum = (legs) => {
5400
+ const sum = Object.values(legs).reduce((a, b) => a + b, 0);
5401
+ if (sum !== 1e4) {
5402
+ const parts = Object.entries(legs).map(([k, v]) => `--${k} ${v}`).join(" ");
5403
+ console.error(
5404
+ chalk10.red(`split legs must sum to 10000 bps, got ${sum} (${parts})`)
5405
+ );
5406
+ process.exit(1);
5407
+ }
5408
+ };
5409
+ const fmtSplit = (legs) => Object.entries(legs).map(([k, v]) => `${k} ${Number(v) / 100}%`).join(" / ");
5410
+ governor.command("set-mgmt-split").description("Set the management-fee split on ProtocolConfig (protocol owner only; legs sum to 10000 bps)").requiredOption("--agent <bps>", "Agent share in bps (e.g. 6000 = 60%)").requiredOption("--protocol <bps>", "Protocol share in bps").requiredOption("--guardian <bps>", "Guardian share in bps").action(async (opts) => {
5411
+ const s = {
5412
+ agentBps: parseSplitLeg(opts.agent, "agent"),
5413
+ protocolBps: parseSplitLeg(opts.protocol, "protocol"),
5414
+ guardianBps: parseSplitLeg(opts.guardian, "guardian")
5415
+ };
5416
+ requireSum({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps });
5417
+ if (isCalldataOnly()) {
5418
+ try {
5419
+ emitCalldata(
5420
+ encodeMgmtSplit(
5421
+ { protocolConfig: await getProtocolConfigAddress(), ...s },
5422
+ getChain().id
5423
+ )
5424
+ );
5425
+ } catch (err) {
5426
+ console.error(chalk10.red(formatContractError(err)));
5427
+ process.exit(1);
5428
+ }
5429
+ return;
5430
+ }
5431
+ const spinner = ora8("Setting management-fee split...").start();
5432
+ try {
5433
+ const hash = await setMgmtSplit(s);
5434
+ const configAddress = await getProtocolConfigAddress();
5435
+ spinner.succeed(
5436
+ G4(`Management-fee split updated to ${fmtSplit({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps })} on ProtocolConfig (${configAddress}). In-flight proposals keep their propose-time snapshot.`)
5437
+ );
5438
+ console.log(DIM4(` ${getExplorerUrl(hash)}`));
5439
+ } catch (err) {
5440
+ spinner.fail("Failed to set management-fee split");
5441
+ console.error(chalk10.red(formatContractError(err)));
5442
+ process.exit(1);
5443
+ }
5444
+ });
5445
+ governor.command("set-perf-split").description("Set the performance-fee split on ProtocolConfig (protocol owner only; legs sum to 10000 bps)").requiredOption("--agent <bps>", "Agent share in bps (e.g. 5000 = 50%)").requiredOption("--protocol <bps>", "Protocol share in bps").requiredOption("--guardian <bps>", "Guardian share in bps").requiredOption("--owner <bps>", "Vault-owner share in bps").action(async (opts) => {
5446
+ const s = {
5447
+ agentBps: parseSplitLeg(opts.agent, "agent"),
5448
+ protocolBps: parseSplitLeg(opts.protocol, "protocol"),
5449
+ guardianBps: parseSplitLeg(opts.guardian, "guardian"),
5450
+ ownerBps: parseSplitLeg(opts.owner, "owner")
5451
+ };
5452
+ requireSum({
5453
+ agent: s.agentBps,
5454
+ protocol: s.protocolBps,
5455
+ guardian: s.guardianBps,
5456
+ owner: s.ownerBps
5457
+ });
5391
5458
  if (isCalldataOnly()) {
5392
5459
  try {
5393
- const value = parseBigIntArg(rawValue, "bps");
5394
5460
  emitCalldata(
5395
- encodeProtocolFeeBps(
5396
- { protocolConfig: await getProtocolConfigAddress(), value },
5461
+ encodePerfSplit(
5462
+ { protocolConfig: await getProtocolConfigAddress(), ...s },
5397
5463
  getChain().id
5398
5464
  )
5399
5465
  );
@@ -5403,16 +5469,16 @@ function registerGovernorCommands(program2) {
5403
5469
  }
5404
5470
  return;
5405
5471
  }
5406
- const spinner = ora8("Setting protocol fee...").start();
5472
+ const spinner = ora8("Setting performance-fee split...").start();
5407
5473
  try {
5408
- const hash = await setProtocolFeeBps(parseBigIntArg(rawValue, "bps"));
5474
+ const hash = await setPerfSplit(s);
5409
5475
  const configAddress = await getProtocolConfigAddress();
5410
5476
  spinner.succeed(
5411
- G4(`Protocol fee updated to ${Number(rawValue) / 100}% on ProtocolConfig (${configAddress}).`)
5477
+ G4(`Performance-fee split updated to ${fmtSplit({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps, owner: s.ownerBps })} on ProtocolConfig (${configAddress}). In-flight proposals keep their propose-time snapshot.`)
5412
5478
  );
5413
5479
  console.log(DIM4(` ${getExplorerUrl(hash)}`));
5414
5480
  } catch (err) {
5415
- spinner.fail("Failed to set protocol fee");
5481
+ spinner.fail("Failed to set performance-fee split");
5416
5482
  console.error(chalk10.red(formatContractError(err)));
5417
5483
  process.exit(1);
5418
5484
  }
@@ -7985,9 +8051,9 @@ try {
7985
8051
  } catch {
7986
8052
  }
7987
8053
  var require2 = createRequire(import.meta.url);
7988
- var CLI_VERSION = "0.85.1";
8054
+ var CLI_VERSION = "0.86.1";
7989
8055
  async function loadXmtp() {
7990
- return import("./xmtp-R25Q5GWY.js");
8056
+ return import("./xmtp-KW73BGVO.js");
7991
8057
  }
7992
8058
  async function loadCron() {
7993
8059
  return import("./cron-E3UAZF5B.js");
@@ -8007,7 +8073,7 @@ function validateAddress(value, name) {
8007
8073
  }
8008
8074
  function fundShareUrl(subdomain, refParam) {
8009
8075
  const host = isTestnet() ? "https://testnet.sherwood.sh" : "https://sherwood.sh";
8010
- return `${host}/fund/${subdomain}${refParam}`;
8076
+ return `${host}/vault/${subdomain}${refParam}`;
8011
8077
  }
8012
8078
  function resolveVault(opts) {
8013
8079
  if (opts.vault) {
@@ -8015,7 +8081,22 @@ function resolveVault(opts) {
8015
8081
  }
8016
8082
  }
8017
8083
  var program = new Command();
8018
- program.name("sherwood").description("CLI for agent-managed investment funds").version(CLI_VERSION).addOption(
8084
+ program.name("sherwood").description("CLI for agent-managed onchain vaults").version(CLI_VERSION).configureHelp({
8085
+ subcommandTerm: (cmd) => {
8086
+ const args = cmd.registeredArguments.map((arg) => {
8087
+ const name = arg.name() + (arg.variadic ? "..." : "");
8088
+ return arg.required ? `<${name}>` : `[${name}]`;
8089
+ }).join(" ");
8090
+ return cmd.name() + (cmd.options.length ? " [options]" : "") + (args ? ` ${args}` : "");
8091
+ },
8092
+ commandUsage: (cmd) => {
8093
+ const names = [cmd.name()];
8094
+ for (let ancestor = cmd.parent; ancestor; ancestor = ancestor.parent) {
8095
+ names.unshift(ancestor.name());
8096
+ }
8097
+ return `${names.join(" ")} ${cmd.usage()}`;
8098
+ }
8099
+ }).addOption(
8019
8100
  new Option(
8020
8101
  "--chain <network>",
8021
8102
  "Target network (default: robinhood-fork, chain 9994663 \u2014 where the product lives; robinhood-testnet is chain 46630)"
@@ -8029,11 +8110,21 @@ program.name("sherwood").description("CLI for agent-managed investment funds").v
8029
8110
  setCalldataOnly(Boolean(opts.calldataOnly));
8030
8111
  setNetwork(opts.chain);
8031
8112
  });
8032
- var fund = program.command("fund").alias("syndicate");
8033
- fund.command("create").description("Create a new fund via the factory (interactive)").option("--subdomain <name>", "ENS subdomain (skip prompt)").option("--name <name>", "Fund name (skip prompt)").option("--agent-id <id>", "ERC-8004 agent identity token ID (skip prompt)").option("--asset <symbol-or-address>", "Vault asset: USDC, WETH, or a token address").option("--description <text>", "Short description").option("--metadata-uri <uri>", "Override metadata URI (skip IPFS upload)").option("--open-deposits", "Allow anyone to deposit (default: whitelist only)").option("--public-chat", "Enable dashboard spectator mode", false).option("-y, --yes", "Skip confirmation prompt (non-interactive mode)", false).action(async (opts) => {
8113
+ var LEGACY_GROUP_ALIASES = ["fund", "syndicate"];
8114
+ var vaultCmd = program.command("vault").alias("fund").alias("syndicate").description("Vaults \u2014 launch, inspect, join, and manage deposits").hook("preSubcommand", () => {
8115
+ const typed = process.argv.slice(2).find((arg) => arg === "vault" || LEGACY_GROUP_ALIASES.includes(arg));
8116
+ if (typed && typed !== "vault") {
8117
+ console.error(
8118
+ chalk17.dim(
8119
+ `note: 'sherwood ${typed}' is now 'sherwood vault' \u2014 the old name keeps working for now`
8120
+ )
8121
+ );
8122
+ }
8123
+ });
8124
+ vaultCmd.command("create").description("Launch a new vault via the factory (interactive)").option("--subdomain <name>", "ENS subdomain (skip prompt)").option("--name <name>", "Vault name (skip prompt)").option("--agent-id <id>", "ERC-8004 agent identity token ID (skip prompt)").option("--asset <symbol-or-address>", "Vault asset: USDC, WETH, or a token address").option("--description <text>", "Short description").option("--metadata-uri <uri>", "Override metadata URI (skip IPFS upload)").option("--open-deposits", "Allow anyone to deposit (default: whitelist only)").option("--public-chat", "Enable dashboard spectator mode", false).option("-y, --yes", "Skip confirmation prompt (non-interactive mode)", false).action(async (opts) => {
8034
8125
  try {
8035
8126
  console.log();
8036
- console.log(LABEL5(" \u25C6 Create Fund"));
8127
+ console.log(LABEL5(" \u25C6 Launch Vault"));
8037
8128
  SEP6();
8038
8129
  if (!isCalldataOnly()) {
8039
8130
  const wallet = getAccount();
@@ -8046,7 +8137,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8046
8137
  const name = opts.name || (nonInteractive ? (() => {
8047
8138
  throw new Error("--name is required in non-interactive mode (-y)");
8048
8139
  })() : await input({
8049
- message: G6("Fund name"),
8140
+ message: G6("Vault name"),
8050
8141
  validate: (v) => v.length > 0 || "Name is required"
8051
8142
  }));
8052
8143
  const subdomain = opts.subdomain || (nonInteractive ? name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "") : await input({
@@ -8054,9 +8145,9 @@ fund.command("create").description("Create a new fund via the factory (interacti
8054
8145
  default: name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, ""),
8055
8146
  validate: (v) => v.length >= 3 || "Must be at least 3 characters"
8056
8147
  }));
8057
- const description = opts.description || (nonInteractive ? `${name} \u2014 a Sherwood fund` : await input({
8148
+ const description = opts.description || (nonInteractive ? `${name} \u2014 a Sherwood vault` : await input({
8058
8149
  message: G6("Description"),
8059
- default: `${name} \u2014 a Sherwood fund`
8150
+ default: `${name} \u2014 a Sherwood vault`
8060
8151
  }));
8061
8152
  const agentIdStr = opts.agentId || (savedAgentId ? nonInteractive ? String(savedAgentId) : await input({ message: G6("Agent ID (ERC-8004)"), default: String(savedAgentId) }) : nonInteractive ? "0" : await input({ message: G6("Agent ID (ERC-8004)"), validate: (v) => /^\d+$/.test(v) || "Must be a number" }));
8062
8153
  const openDeposits = opts.openDeposits !== void 0 ? opts.openDeposits : nonInteractive ? false : await confirm({
@@ -8128,7 +8219,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8128
8219
  console.log(W6(` Open deposits: ${openDeposits ? chalk17.yellow("yes (anyone can deposit)") : G6("no (whitelist)")}`));
8129
8220
  SEP6();
8130
8221
  if (!nonInteractive) {
8131
- const go = await confirm({ message: G6("Deploy fund?"), default: true });
8222
+ const go = await confirm({ message: G6("Deploy vault?"), default: true });
8132
8223
  if (!go) {
8133
8224
  console.log(DIM6(" Cancelled."));
8134
8225
  return;
@@ -8180,12 +8271,12 @@ fund.command("create").description("Create a new fund via the factory (interacti
8180
8271
  const callerAddress = getAccount().address.toLowerCase();
8181
8272
  if (existingInfo.creator.toLowerCase() !== callerAddress) {
8182
8273
  console.error(chalk17.red(`
8183
- \u2716 Subdomain '${subdomain}' is already taken by another fund.
8274
+ \u2716 Subdomain '${subdomain}' is already taken by another vault.
8184
8275
  `));
8185
8276
  process.exit(1);
8186
8277
  }
8187
8278
  console.log(chalk17.yellow(`
8188
- \u26A0 Fund '${subdomain}' already exists \u2014 resuming setup...
8279
+ \u26A0 Vault '${subdomain}' already exists \u2014 resuming setup...
8189
8280
  `));
8190
8281
  const spinner2 = ora9({ text: W6("Resuming setup..."), color: "green" }).start();
8191
8282
  const chainId2 = getChain().id;
@@ -8228,7 +8319,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8228
8319
  }
8229
8320
  spinner2.stop();
8230
8321
  console.log();
8231
- console.log(LABEL5(" \u25C6 Fund Setup Resumed"));
8322
+ console.log(LABEL5(" \u25C6 Vault Setup Resumed"));
8232
8323
  SEP6();
8233
8324
  console.log(W6(` ID: ${G6(`#${existingId}`)}`));
8234
8325
  console.log(W6(` Vault: ${G6(existingInfo.vault)}`));
@@ -8237,7 +8328,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8237
8328
  const refParam2 = getAgentId() ? `?ref=${getAgentId()}` : "";
8238
8329
  console.log(W6(` Share: ${G6(fundShareUrl(subdomain, refParam2))}`));
8239
8330
  SEP6();
8240
- console.log(G6(" \u2713 Fund saved to ~/.sherwood/config.json (set as primary)"));
8331
+ console.log(G6(" \u2713 Vault saved to ~/.sherwood/config.json (set as primary)"));
8241
8332
  console.log();
8242
8333
  return;
8243
8334
  }
@@ -8266,7 +8357,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8266
8357
  // agentAddress = creator EOA (direct execution)
8267
8358
  );
8268
8359
  } catch (regErr) {
8269
- console.warn(chalk17.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `fund add`"));
8360
+ console.warn(chalk17.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `vault add`"));
8270
8361
  }
8271
8362
  spinner.text = W6("Setting up chat...");
8272
8363
  try {
@@ -8295,7 +8386,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8295
8386
  }
8296
8387
  spinner.stop();
8297
8388
  console.log();
8298
- console.log(LABEL5(" \u25C6 Fund Created"));
8389
+ console.log(LABEL5(" \u25C6 Vault Launched"));
8299
8390
  SEP6();
8300
8391
  console.log(W6(` ID: ${G6(`#${result.fundId}`)}`));
8301
8392
  console.log(W6(` Vault: ${G6(result.vault)}`));
@@ -8306,7 +8397,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
8306
8397
  const refParam = getAgentId() ? `?ref=${getAgentId()}` : "";
8307
8398
  console.log(W6(` Share: ${G6(fundShareUrl(subdomain, refParam))}`));
8308
8399
  SEP6();
8309
- console.log(G6(" \u2713 Fund saved to ~/.sherwood/config.json (set as primary)"));
8400
+ console.log(G6(" \u2713 Vault saved to ~/.sherwood/config.json (set as primary)"));
8310
8401
  console.log();
8311
8402
  } catch (err) {
8312
8403
  console.error(chalk17.red(`
@@ -8314,8 +8405,8 @@ fund.command("create").description("Create a new fund via the factory (interacti
8314
8405
  process.exit(1);
8315
8406
  }
8316
8407
  });
8317
- fund.command("list").description("List active funds (queries subgraph, falls back to on-chain)").option("--creator <address>", "Filter by creator address").option("--all-chains", "Aggregate active funds across all supported chains (on-chain only)").action(async (opts) => {
8318
- const spinner = ora9("Loading funds...").start();
8408
+ vaultCmd.command("list").description("List active vaults (queries subgraph, falls back to on-chain)").option("--creator <address>", "Filter by creator address").option("--all-chains", "Aggregate active vaults across all supported chains (on-chain only)").action(async (opts) => {
8409
+ const spinner = ora9("Loading vaults...").start();
8319
8410
  try {
8320
8411
  let funds = [];
8321
8412
  if (opts.allChains) {
@@ -8358,11 +8449,11 @@ fund.command("list").description("List active funds (queries subgraph, falls bac
8358
8449
  }
8359
8450
  spinner.stop();
8360
8451
  if (funds.length === 0) {
8361
- console.log(chalk17.dim("No active funds found."));
8452
+ console.log(chalk17.dim("No active vaults found."));
8362
8453
  return;
8363
8454
  }
8364
8455
  console.log();
8365
- console.log(chalk17.bold(`Active Funds (${funds.length})`));
8456
+ console.log(chalk17.bold(`Active Vaults (${funds.length})`));
8366
8457
  if (!process.env.SUBGRAPH_URL && !opts.allChains) {
8367
8458
  console.log(chalk17.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
8368
8459
  }
@@ -8388,13 +8479,35 @@ fund.command("list").description("List active funds (queries subgraph, falls bac
8388
8479
  console.log();
8389
8480
  }
8390
8481
  } catch (err) {
8391
- spinner.fail("Failed to load funds");
8482
+ spinner.fail("Failed to load vaults");
8392
8483
  console.error(chalk17.red(formatContractError(err)));
8393
8484
  process.exit(1);
8394
8485
  }
8395
8486
  });
8396
- fund.command("info").description("Display fund details by ID or subdomain").argument("<id>", "Fund ID or subdomain name").action(async (idStr) => {
8397
- const spinner = ora9("Loading fund info...").start();
8487
+ vaultCmd.command("info").description("Display vault details by ID or subdomain (omit the ID to read the configured vault)").argument("[id]", "Vault ID or subdomain name (default: the vault from --vault or config)").option("--vault <address>", "Vault address (default: from config)").action(async (idStr, opts) => {
8488
+ if (!idStr) {
8489
+ resolveVault(opts);
8490
+ const spinner2 = ora9("Loading vault info...").start();
8491
+ try {
8492
+ const info = await getVaultInfo();
8493
+ spinner2.stop();
8494
+ console.log();
8495
+ console.log(chalk17.bold("Vault Info"));
8496
+ console.log(chalk17.dim("\u2500".repeat(40)));
8497
+ console.log(` Address: ${info.address}`);
8498
+ console.log(` Total Assets: ${info.totalAssets}`);
8499
+ console.log(` Agent Count: ${info.agentCount}`);
8500
+ console.log(` Redemptions Locked: ${info.redemptionsLocked}`);
8501
+ console.log(` Management Fee: ${Number(info.managementFeeBps) / 100}%`);
8502
+ console.log();
8503
+ } catch (err) {
8504
+ spinner2.fail("Failed to load vault info");
8505
+ console.error(chalk17.red(formatContractError(err)));
8506
+ process.exit(1);
8507
+ }
8508
+ return;
8509
+ }
8510
+ const spinner = ora9("Loading vault info...").start();
8398
8511
  try {
8399
8512
  let id;
8400
8513
  let crossChainHint = null;
@@ -8409,7 +8522,7 @@ fund.command("info").description("Display fund details by ID or subdomain").argu
8409
8522
  spinner.text = `Searching across chains...`;
8410
8523
  const hits = await searchFundAcrossChains(idStr);
8411
8524
  if (hits.length === 0) {
8412
- spinner.fail(`Fund "${idStr}" not found on any supported chain`);
8525
+ spinner.fail(`Vault "${idStr}" not found on any supported chain`);
8413
8526
  process.exit(1);
8414
8527
  }
8415
8528
  const active = getNetwork();
@@ -8430,16 +8543,16 @@ fund.command("info").description("Display fund details by ID or subdomain").argu
8430
8543
  if (crossChainHint) {
8431
8544
  const others = crossChainHint.others.length > 0 ? ` (also on: ${crossChainHint.others.join(", ")})` : "";
8432
8545
  console.log(chalk17.yellow(` Found on chain: ${chalk17.bold(crossChainHint.network)}${others}`));
8433
- console.log(chalk17.dim(` Re-run with --chain ${crossChainHint.network} to interact with this fund.`));
8546
+ console.log(chalk17.dim(` Re-run with --chain ${crossChainHint.network} to interact with this vault.`));
8434
8547
  console.log();
8435
8548
  }
8436
8549
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
8437
- console.log(chalk17.red(`Fund #${id} not found.`));
8550
+ console.log(chalk17.red(`Vault #${id} not found.`));
8438
8551
  process.exit(1);
8439
8552
  }
8440
8553
  const date = new Date(Number(info.createdAt) * 1e3).toLocaleDateString();
8441
8554
  console.log();
8442
- console.log(chalk17.bold(`Fund #${info.id}`));
8555
+ console.log(chalk17.bold(`Vault #${info.id}`));
8443
8556
  console.log(chalk17.dim("\u2500".repeat(40)));
8444
8557
  if (info.subdomain) {
8445
8558
  console.log(` ENS: ${chalk17.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
@@ -8467,20 +8580,20 @@ fund.command("info").description("Display fund details by ID or subdomain").argu
8467
8580
  console.log(` Management Fee: ${Number(vaultInfo.managementFeeBps) / 100}%`);
8468
8581
  console.log();
8469
8582
  } catch (err) {
8470
- spinner.fail("Failed to load fund info");
8583
+ spinner.fail("Failed to load vault info");
8471
8584
  console.error(chalk17.red(formatContractError(err)));
8472
8585
  process.exit(1);
8473
8586
  }
8474
8587
  });
8475
- fund.command("update-metadata").description("Update fund metadata (creator only)").requiredOption("--id <id>", "Fund ID").option("--name <name>", "Fund name").option("--description <text>", "Short description").option("--uri <uri>", "Direct metadata URI (skips IPFS upload)").action(async (opts) => {
8476
- const spinner = ora9({ text: W6("Loading fund..."), color: "green" }).start();
8588
+ vaultCmd.command("update-metadata").description("Update vault metadata (creator only)").requiredOption("--id <id>", "Vault ID").option("--name <name>", "Vault name").option("--description <text>", "Short description").option("--uri <uri>", "Direct metadata URI (skips IPFS upload)").action(async (opts) => {
8589
+ const spinner = ora9({ text: W6("Loading vault..."), color: "green" }).start();
8477
8590
  try {
8478
8591
  const fundId = BigInt(opts.id);
8479
8592
  let metadataURI = opts.uri;
8480
8593
  if (!metadataURI) {
8481
8594
  const info = await getFund(fundId);
8482
8595
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
8483
- spinner.fail(`Fund #${opts.id} not found.`);
8596
+ spinner.fail(`Vault #${opts.id} not found.`);
8484
8597
  process.exit(1);
8485
8598
  }
8486
8599
  spinner.text = W6("Fetching current metadata...");
@@ -8515,7 +8628,7 @@ fund.command("update-metadata").description("Update fund metadata (creator only)
8515
8628
  process.exit(1);
8516
8629
  }
8517
8630
  });
8518
- fund.command("approve-depositor").description("Approve an address to deposit (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to approve").action(async (opts) => {
8631
+ vaultCmd.command("approve-depositor").description("Approve an address to deposit (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to approve").action(async (opts) => {
8519
8632
  resolveVault(opts);
8520
8633
  const depositor = validateAddress(opts.depositor, "depositor");
8521
8634
  if (isCalldataOnly()) {
@@ -8538,7 +8651,7 @@ fund.command("approve-depositor").description("Approve an address to deposit (ow
8538
8651
  process.exit(1);
8539
8652
  }
8540
8653
  });
8541
- fund.command("remove-depositor").description("Remove an address from the depositor whitelist (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to remove").action(async (opts) => {
8654
+ vaultCmd.command("remove-depositor").description("Remove an address from the depositor whitelist (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to remove").action(async (opts) => {
8542
8655
  resolveVault(opts);
8543
8656
  const spinner = ora9("Removing depositor...").start();
8544
8657
  try {
@@ -8552,7 +8665,7 @@ fund.command("remove-depositor").description("Remove an address from the deposit
8552
8665
  process.exit(1);
8553
8666
  }
8554
8667
  });
8555
- fund.command("set-agent-fee").description("Set the vault's agent performance fee in bps (vault owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption(
8668
+ vaultCmd.command("set-agent-fee").description("Set the vault's agent performance fee in bps (vault owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption(
8556
8669
  "--bps <bps>",
8557
8670
  `Agent fee in bps (e.g. 1000 = 10%; max ${MAX_AGENT_FEE_BPS} = ${MAX_AGENT_FEE_BPS / 100}%). The governor clamps the realized fee to its configured maxPerformanceFeeBps, which may be lower.`
8558
8671
  ).action(async (opts) => {
@@ -8571,7 +8684,7 @@ fund.command("set-agent-fee").description("Set the vault's agent performance fee
8571
8684
  process.exit(1);
8572
8685
  }
8573
8686
  });
8574
- fund.command("add").description("Register an agent on a fund vault (creator only)").option("--vault <address>", "Vault address (default: from config)").option("--agent-id <id>", "Agent's ERC-8004 identity token ID (resolved from wallet if omitted)").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
8687
+ vaultCmd.command("add").description("Register an agent on a vault (creator only)").option("--vault <address>", "Vault address (default: from config)").option("--agent-id <id>", "Agent's ERC-8004 identity token ID (resolved from wallet if omitted)").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
8575
8688
  if (isCalldataOnly()) {
8576
8689
  resolveVault(opts);
8577
8690
  const agentWallet = validateAddress(opts.wallet, "wallet");
@@ -8602,7 +8715,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
8602
8715
  const { creator, subdomain } = await resolveVaultFund(vaultAddress);
8603
8716
  const callerAddress = getAccount().address.toLowerCase();
8604
8717
  if (creator.toLowerCase() !== callerAddress) {
8605
- spinner.fail("Only the fund creator can add agents");
8718
+ spinner.fail("Only the vault creator can add agents");
8606
8719
  process.exit(1);
8607
8720
  }
8608
8721
  const agentWallet = validateAddress(opts.wallet, "wallet");
@@ -8611,7 +8724,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
8611
8724
  agentId = BigInt(opts.agentId);
8612
8725
  } else {
8613
8726
  spinner.text = "Looking up ERC-8004 identity from wallet...";
8614
- const { lookupAgentIdByWallet } = await import("./identity-3A2D7DGS.js");
8727
+ const { lookupAgentIdByWallet } = await import("./identity-ATWV2O7Y.js");
8615
8728
  const resolved = await lookupAgentIdByWallet(agentWallet);
8616
8729
  if (resolved === null) {
8617
8730
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
@@ -8647,11 +8760,11 @@ fund.command("add").description("Register an agent on a fund vault (creator only
8647
8760
  process.exit(1);
8648
8761
  }
8649
8762
  });
8650
- fund.command("share").description("Print the shareable dashboard URL for your fund").option("--subdomain <name>", "Fund subdomain (default: primary)").action(async (opts) => {
8763
+ vaultCmd.command("share").description("Print the shareable dashboard URL for your vault").option("--subdomain <name>", "Vault subdomain (default: primary)").action(async (opts) => {
8651
8764
  try {
8652
8765
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
8653
8766
  if (!subdomain) {
8654
- console.error(chalk17.red(" No fund configured. Pass --subdomain <name> or run 'fund create/join' first."));
8767
+ console.error(chalk17.red(" No vault configured. Pass --subdomain <name> or run 'vault create/join' first."));
8655
8768
  process.exit(1);
8656
8769
  }
8657
8770
  const fundInfo = await resolveFund(subdomain);
@@ -8659,12 +8772,12 @@ fund.command("share").description("Print the shareable dashboard URL for your fu
8659
8772
  const refParam = agentId ? `?ref=${agentId}` : "";
8660
8773
  const dashboardUrl = fundShareUrl(subdomain, refParam);
8661
8774
  console.log();
8662
- console.log(LABEL5(" \u25C6 Share Your Fund"));
8775
+ console.log(LABEL5(" \u25C6 Share Your Vault"));
8663
8776
  SEP6();
8664
8777
  console.log(W6(` Dashboard: ${G6(dashboardUrl)}`));
8665
8778
  console.log(W6(` ENS: ${DIM6(`${subdomain}.sherwoodagent.eth`)}`));
8666
8779
  console.log(W6(` Vault: ${DIM6(fundInfo.vault)}`));
8667
- console.log(W6(` Join CLI: ${DIM6(`sherwood fund join --subdomain ${subdomain}`)}`));
8780
+ console.log(W6(` Join CLI: ${DIM6(`sherwood vault join --subdomain ${subdomain}`)}`));
8668
8781
  SEP6();
8669
8782
  try {
8670
8783
  const { exec } = await import("child_process");
@@ -8682,12 +8795,12 @@ fund.command("share").description("Print the shareable dashboard URL for your fu
8682
8795
  process.exit(1);
8683
8796
  }
8684
8797
  });
8685
- fund.command("join").description("Request to join a fund (creates an EAS attestation)").option("--subdomain <name>", "Fund subdomain to join").option("--ref <agentId>", "Referrer agent ID (from invite link)").option("--message <text>", "Message to the creator", "Requesting to join your fund").action(async (opts) => {
8686
- const spinner = ora9("Resolving fund...").start();
8798
+ vaultCmd.command("join").description("Request to join a vault (creates an EAS attestation)").option("--subdomain <name>", "Vault subdomain to join").option("--ref <agentId>", "Referrer agent ID (from invite link)").option("--message <text>", "Message to the creator", "Requesting to join your vault").action(async (opts) => {
8799
+ const spinner = ora9("Resolving vault...").start();
8687
8800
  try {
8688
8801
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
8689
8802
  if (!subdomain) {
8690
- spinner.fail("No fund configured. Pass --subdomain <name> or run 'fund create' first.");
8803
+ spinner.fail("No vault configured. Pass --subdomain <name> or run 'vault create' first.");
8691
8804
  process.exit(1);
8692
8805
  }
8693
8806
  const agentId = getAgentId();
@@ -8695,18 +8808,18 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8695
8808
  spinner.fail("No agent identity found. Run 'sherwood identity mint' first.");
8696
8809
  process.exit(1);
8697
8810
  }
8698
- let fund2;
8811
+ let fund;
8699
8812
  try {
8700
- fund2 = await resolveFund(subdomain);
8813
+ fund = await resolveFund(subdomain);
8701
8814
  } catch {
8702
8815
  spinner.text = "Searching across chains...";
8703
8816
  const hits = await searchFundAcrossChains(subdomain);
8704
- spinner.fail(`Fund "${subdomain}" not found on ${getNetwork()}`);
8817
+ spinner.fail(`Vault "${subdomain}" not found on ${getNetwork()}`);
8705
8818
  if (hits.length === 0) {
8706
8819
  console.error(chalk17.red(` Not found on any supported chain.`));
8707
8820
  } else if (hits.length === 1) {
8708
8821
  console.error(chalk17.yellow(` Found on chain: ${chalk17.bold(hits[0].network)}`));
8709
- console.error(chalk17.dim(` Re-run: sherwood --chain ${hits[0].network} fund join --subdomain ${subdomain}`));
8822
+ console.error(chalk17.dim(` Re-run: sherwood --chain ${hits[0].network} vault join --subdomain ${subdomain}`));
8710
8823
  } else {
8711
8824
  const chains = hits.map((h) => h.network).join(", ");
8712
8825
  console.error(chalk17.yellow(` Found on chains: ${chalk17.bold(chains)}`));
@@ -8730,10 +8843,10 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8730
8843
  emitCalldata(
8731
8844
  encodeJoinRequest(
8732
8845
  {
8733
- fundId: fund2.id,
8846
+ fundId: fund.id,
8734
8847
  agentId: BigInt(agentId),
8735
- vault: fund2.vault,
8736
- creator: fund2.creator,
8848
+ vault: fund.vault,
8849
+ creator: fund.creator,
8737
8850
  message: joinMessage,
8738
8851
  referrerAgentId: referrerAgentId2
8739
8852
  },
@@ -8744,10 +8857,10 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8744
8857
  }
8745
8858
  const callerAddress = getAccount().address;
8746
8859
  spinner.text = "Checking membership...";
8747
- setVaultAddress(fund2.vault);
8860
+ setVaultAddress(fund.vault);
8748
8861
  const alreadyAgent = await isAgent(callerAddress);
8749
8862
  if (alreadyAgent) {
8750
- spinner.succeed("You are already a registered agent on this fund");
8863
+ spinner.succeed("You are already a registered agent on this vault");
8751
8864
  try {
8752
8865
  const xmtp = await loadXmtp();
8753
8866
  await xmtp.getXmtpClient();
@@ -8768,12 +8881,12 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8768
8881
  return;
8769
8882
  }
8770
8883
  spinner.text = "Checking pending requests...";
8771
- const pendingRequests = await queryJoinRequests(fund2.creator);
8884
+ const pendingRequests = await queryJoinRequests(fund.creator);
8772
8885
  const existingRequest = pendingRequests.find(
8773
- (r) => r.attester.toLowerCase() === callerAddress.toLowerCase() && r.decoded.vault.toLowerCase() === fund2.vault.toLowerCase()
8886
+ (r) => r.attester.toLowerCase() === callerAddress.toLowerCase() && r.decoded.vault.toLowerCase() === fund.vault.toLowerCase()
8774
8887
  );
8775
8888
  if (existingRequest) {
8776
- spinner.succeed("You already have a pending join request for this fund");
8889
+ spinner.succeed("You already have a pending join request for this vault");
8777
8890
  console.log(chalk17.dim(` Attestation: ${existingRequest.uid}`));
8778
8891
  console.log(chalk17.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
8779
8892
  try {
@@ -8788,10 +8901,10 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8788
8901
  spinner.text = "Creating join request attestation...";
8789
8902
  const referrerAgentId = opts.ref ? parseInt(opts.ref, 10) : void 0;
8790
8903
  const joinAttestation = await createJoinRequest(
8791
- fund2.id,
8904
+ fund.id,
8792
8905
  BigInt(agentId),
8793
- fund2.vault,
8794
- fund2.creator,
8906
+ fund.vault,
8907
+ fund.creator,
8795
8908
  joinMessage,
8796
8909
  referrerAgentId
8797
8910
  );
@@ -8804,7 +8917,7 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8804
8917
  spinner.succeed("Join request created");
8805
8918
  console.warn(chalk17.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
8806
8919
  }
8807
- addFund(getChain().id, { subdomain, vault: fund2.vault, role: "agent" });
8920
+ addFund(getChain().id, { subdomain, vault: fund.vault, role: "agent" });
8808
8921
  setPrimaryFund(getChain().id, subdomain);
8809
8922
  try {
8810
8923
  const cron = await loadCron();
@@ -8819,9 +8932,9 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8819
8932
  console.log();
8820
8933
  console.log(LABEL5(" \u25C6 Join Request Submitted"));
8821
8934
  SEP6();
8822
- console.log(W6(` Fund: ${G6(`${subdomain}.sherwoodagent.eth`)}`));
8935
+ console.log(W6(` Vault: ${G6(`${subdomain}.sherwoodagent.eth`)}`));
8823
8936
  console.log(W6(` Agent ID: #${agentId}`));
8824
- console.log(W6(` Creator: ${DIM6(fund2.creator)}`));
8937
+ console.log(W6(` Creator: ${DIM6(fund.creator)}`));
8825
8938
  if (joinAttestation) {
8826
8939
  console.log(W6(` Attestation: ${DIM6(joinAttestation.uid)}`));
8827
8940
  console.log(W6(` Explorer: ${DIM6(getEasExplorerUrl(joinAttestation.hash))}`));
@@ -8829,9 +8942,9 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8829
8942
  console.log(W6(` Attestation: ${DIM6("skipped on this chain")}`));
8830
8943
  }
8831
8944
  SEP6();
8832
- console.log(G6(" \u2713 Fund saved to ~/.sherwood/config.json (set as primary)"));
8945
+ console.log(G6(" \u2713 Vault saved to ~/.sherwood/config.json (set as primary)"));
8833
8946
  console.log(G6(" \u2713 The creator can review with:"));
8834
- console.log(DIM6(` sherwood fund requests --subdomain ${subdomain}`));
8947
+ console.log(DIM6(` sherwood vault requests --subdomain ${subdomain}`));
8835
8948
  console.log();
8836
8949
  } catch (err) {
8837
8950
  spinner.fail("Join request failed");
@@ -8839,7 +8952,7 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
8839
8952
  process.exit(1);
8840
8953
  }
8841
8954
  });
8842
- fund.command("requests").description("View pending join requests for a fund (creator only)").option("--subdomain <name>", "Fund subdomain").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
8955
+ vaultCmd.command("requests").description("View pending join requests for a vault (creator only)").option("--subdomain <name>", "Vault subdomain").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
8843
8956
  const spinner = ora9("Loading join requests...").start();
8844
8957
  try {
8845
8958
  let creatorAddress;
@@ -8860,7 +8973,7 @@ fund.command("requests").description("View pending join requests for a fund (cre
8860
8973
  }
8861
8974
  const callerAddress = getAccount().address.toLowerCase();
8862
8975
  if (creatorAddress.toLowerCase() !== callerAddress) {
8863
- spinner.fail("Only the fund creator can view join requests");
8976
+ spinner.fail("Only the vault creator can view join requests");
8864
8977
  process.exit(1);
8865
8978
  }
8866
8979
  spinner.text = "Querying EAS attestations...";
@@ -8908,9 +9021,9 @@ fund.command("requests").description("View pending join requests for a fund (cre
8908
9021
  console.log();
8909
9022
  }
8910
9023
  console.log(G6(" To approve:"));
8911
- console.log(DIM6(` sherwood fund approve --agent-id <id> --wallet <addr>`));
9024
+ console.log(DIM6(` sherwood vault approve --agent-id <id> --wallet <addr>`));
8912
9025
  console.log(G6(" To reject:"));
8913
- console.log(DIM6(` sherwood fund reject --attestation <uid>`));
9026
+ console.log(DIM6(` sherwood vault reject --attestation <uid>`));
8914
9027
  console.log();
8915
9028
  } catch (err) {
8916
9029
  spinner.fail("Failed to load requests");
@@ -8918,7 +9031,7 @@ fund.command("requests").description("View pending join requests for a fund (cre
8918
9031
  process.exit(1);
8919
9032
  }
8920
9033
  });
8921
- fund.command("approve").description("Approve an agent join request (registers agent + creates EAS approval)").option("--vault <address>", "Vault address (default: from config)").option("--subdomain <name>", "Fund subdomain (alternative to --vault)").requiredOption("--agent-id <id>", "Agent's ERC-8004 identity token ID").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
9034
+ vaultCmd.command("approve").description("Approve an agent join request (registers agent + creates EAS approval)").option("--vault <address>", "Vault address (default: from config)").option("--subdomain <name>", "Vault subdomain (alternative to --vault)").requiredOption("--agent-id <id>", "Agent's ERC-8004 identity token ID").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
8922
9035
  const spinner = ora9("Verifying creator...").start();
8923
9036
  try {
8924
9037
  const approveSubdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
@@ -8948,7 +9061,7 @@ fund.command("approve").description("Approve an agent join request (registers ag
8948
9061
  }
8949
9062
  const callerAddress = getAccount().address.toLowerCase();
8950
9063
  if (creator.toLowerCase() !== callerAddress) {
8951
- spinner.fail("Only the fund creator can approve agents");
9064
+ spinner.fail("Only the vault creator can approve agents");
8952
9065
  process.exit(1);
8953
9066
  }
8954
9067
  spinner.text = "Registering agent on vault...";
@@ -9023,7 +9136,7 @@ fund.command("approve").description("Approve an agent join request (registers ag
9023
9136
  process.exit(1);
9024
9137
  }
9025
9138
  });
9026
- fund.command("reject").description("Reject a join request by revoking its attestation").requiredOption("--attestation <uid>", "Join request attestation UID to revoke").action(async (opts) => {
9139
+ vaultCmd.command("reject").description("Reject a join request by revoking its attestation").requiredOption("--attestation <uid>", "Join request attestation UID to revoke").action(async (opts) => {
9027
9140
  const spinner = ora9("Revoking attestation...").start();
9028
9141
  try {
9029
9142
  const hash = await revokeJoinRequest(opts.attestation);
@@ -9039,10 +9152,10 @@ fund.command("reject").description("Reject a join request by revoking its attest
9039
9152
  process.exit(1);
9040
9153
  }
9041
9154
  });
9042
- fund.command("leave").description("Leave a fund \u2014 removes participation crons and session state").option("--subdomain <name>", "Fund subdomain to leave").action(async (opts) => {
9155
+ vaultCmd.command("leave").description("Leave a vault \u2014 removes participation crons and session state").option("--subdomain <name>", "Vault subdomain to leave").action(async (opts) => {
9043
9156
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
9044
9157
  if (!subdomain) {
9045
- console.error(chalk17.red(" No fund configured. Pass --subdomain <name>."));
9158
+ console.error(chalk17.red(" No vault configured. Pass --subdomain <name>."));
9046
9159
  process.exit(1);
9047
9160
  }
9048
9161
  const spinner = ora9("Cleaning up...").start();
@@ -9056,7 +9169,7 @@ fund.command("leave").description("Leave a fund \u2014 removes participation cro
9056
9169
  }
9057
9170
  const { resetSession } = await import("./session-XBQY7SBJ.js");
9058
9171
  resetSession(subdomain);
9059
- spinner.succeed("Left fund");
9172
+ spinner.succeed("Left vault");
9060
9173
  if (cronsRemoved) {
9061
9174
  console.log(G6(" \u2713 Participation crons removed"));
9062
9175
  }
@@ -9072,18 +9185,18 @@ fund.command("leave").description("Leave a fund \u2014 removes participation cro
9072
9185
  process.exit(1);
9073
9186
  }
9074
9187
  });
9075
- fund.command("set-primary").description("Set the active fund for CLI commands (auto-used when --subdomain is omitted)").option("--subdomain <name>", "Fund subdomain").option("--vault <address>", "Vault address").action(async (opts) => {
9188
+ vaultCmd.command("set-primary").description("Set the active vault for CLI commands (auto-used when --subdomain is omitted)").option("--subdomain <name>", "Vault subdomain").option("--vault <address>", "Vault address").action(async (opts) => {
9076
9189
  try {
9077
9190
  const chainId = getChain().id;
9078
9191
  const memberships = getFunds(chainId);
9079
9192
  if (!opts.subdomain && !opts.vault) {
9080
9193
  const primary = getPrimaryFund(chainId);
9081
9194
  if (memberships.length === 0) {
9082
- console.log(DIM6("\n No funds saved. Create or join one first.\n"));
9195
+ console.log(DIM6("\n No vaults saved. Create or join one first.\n"));
9083
9196
  return;
9084
9197
  }
9085
9198
  console.log();
9086
- console.log(LABEL5(" \u25C6 Your Funds"));
9199
+ console.log(LABEL5(" \u25C6 Your Vaults"));
9087
9200
  SEP6();
9088
9201
  for (const m of memberships) {
9089
9202
  const isPrimary = primary?.subdomain === m.subdomain;
@@ -9093,7 +9206,7 @@ fund.command("set-primary").description("Set the active fund for CLI commands (a
9093
9206
  }
9094
9207
  SEP6();
9095
9208
  if (memberships.length > 1) {
9096
- console.log(DIM6(" Switch with: sherwood fund set-primary --subdomain <name>"));
9209
+ console.log(DIM6(" Switch with: sherwood vault set-primary --subdomain <name>"));
9097
9210
  }
9098
9211
  console.log();
9099
9212
  return;
@@ -9119,19 +9232,18 @@ fund.command("set-primary").description("Set the active fund for CLI commands (a
9119
9232
  }
9120
9233
  }
9121
9234
  if (!target) {
9122
- console.error(chalk17.red(" Could not resolve fund. Pass --subdomain or --vault."));
9235
+ console.error(chalk17.red(" Could not resolve vault. Pass --subdomain or --vault."));
9123
9236
  process.exit(1);
9124
9237
  }
9125
9238
  setPrimaryFund(chainId, target);
9126
9239
  console.log(G6(`
9127
- \u2713 Primary fund set to ${target}.sherwoodagent.eth
9240
+ \u2713 Primary vault set to ${target}.sherwoodagent.eth
9128
9241
  `));
9129
9242
  } catch (err) {
9130
9243
  console.error(chalk17.red(formatContractError(err)));
9131
9244
  process.exit(1);
9132
9245
  }
9133
9246
  });
9134
- var vaultCmd = program.command("vault");
9135
9247
  vaultCmd.command("deposit").description("Deposit into a vault").option("--vault <address>", "Vault address (default: from config)").requiredOption("--amount <amount>", "Amount to deposit (in asset units)").option("--use-eth", "Auto-wrap ETH \u2192 WETH before depositing (for WETH vaults)").option("--receiver <address>", "Depositor / share receiver (required with --calldata-only)").action(async (opts) => {
9136
9248
  resolveVault(opts);
9137
9249
  const decimals = await getAssetDecimals();
@@ -9210,27 +9322,6 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
9210
9322
  process.exit(1);
9211
9323
  }
9212
9324
  });
9213
- vaultCmd.command("info").description("Display vault state").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
9214
- resolveVault(opts);
9215
- const spinner = ora9("Loading vault info...").start();
9216
- try {
9217
- const info = await getVaultInfo();
9218
- spinner.stop();
9219
- console.log();
9220
- console.log(chalk17.bold("Vault Info"));
9221
- console.log(chalk17.dim("\u2500".repeat(40)));
9222
- console.log(` Address: ${info.address}`);
9223
- console.log(` Total Assets: ${info.totalAssets}`);
9224
- console.log(` Agent Count: ${info.agentCount}`);
9225
- console.log(` Redemptions Locked: ${info.redemptionsLocked}`);
9226
- console.log(` Management Fee: ${Number(info.managementFeeBps) / 100}%`);
9227
- console.log();
9228
- } catch (err) {
9229
- spinner.fail("Failed to load vault info");
9230
- console.error(chalk17.red(formatContractError(err)));
9231
- process.exit(1);
9232
- }
9233
- });
9234
9325
  vaultCmd.command("balance").description("Show LP share balance and asset value").option("--vault <address>", "Vault address (default: from config)").option("--address <address>", "Address to check (default: your wallet)").action(async (opts) => {
9235
9326
  resolveVault(opts);
9236
9327
  const spinner = ora9("Loading balance...").start();
@@ -9346,17 +9437,17 @@ ${info.name} (${info.type})`);
9346
9437
  }
9347
9438
  });
9348
9439
  try {
9349
- const { registerChatCommands } = await import("./chat-DNWTI4CZ.js");
9440
+ const { registerChatCommands } = await import("./chat-ETZSKQDI.js");
9350
9441
  registerChatCommands(program);
9351
9442
  } catch {
9352
- program.command("chat <name> [action] [actionArgs...]").description("Fund chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
9443
+ program.command("chat <name> [action] [actionArgs...]").description("Vault chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
9353
9444
  console.error(chalk17.red("XMTP CLI not available."));
9354
9445
  console.error(chalk17.dim("Install with: npm install -g @xmtp/cli"));
9355
9446
  console.error(chalk17.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
9356
9447
  process.exit(1);
9357
9448
  });
9358
9449
  }
9359
- var { registerSessionCommands } = await import("./session-M5QB25PK.js");
9450
+ var { registerSessionCommands } = await import("./session-HVRZ6AJM.js");
9360
9451
  registerSessionCommands(program);
9361
9452
  registerVeniceCommands(program);
9362
9453
  registerAllowanceCommands(program);
@@ -9365,15 +9456,15 @@ registerProposalCommands(program);
9365
9456
  registerQueueCommands(program);
9366
9457
  registerGovernorCommands(program);
9367
9458
  registerGuardianCommands(program);
9368
- var { registerResearchCommands } = await import("./research-GZNVG3SP.js");
9459
+ var { registerResearchCommands } = await import("./research-W74PNYPO.js");
9369
9460
  registerResearchCommands(program);
9370
9461
  var { registerAgentCommands } = await import("./agent-TBLC3WNJ.js");
9371
9462
  registerAgentCommands(program);
9372
- var { registerTradeCommands } = await import("./trade-TCQ5NUNA.js");
9463
+ var { registerTradeCommands } = await import("./trade-EOQY72L7.js");
9373
9464
  registerTradeCommands(program);
9374
9465
  registerGridCommand(program);
9375
9466
  var configCmd = program.command("config");
9376
- configCmd.command("set").description("Save settings to ~/.sherwood/config.json (persists across sessions)").option("--private-key <key>", "Wallet private key (0x-prefixed)").option("--vault <address>", "Default vault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").option("--notify-to <id>", "Destination for cron summaries (Telegram chat ID, phone, etc.)").option("--uniswap-api-key <key>", "Uniswap Trading API key (from developers.uniswap.org)").option("--venice-api-key <key>", "Venice AI inference API key").option("--anthropic-api-key <key>", "Anthropic Claude API key (for LLM judge)").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a fund (e.g. my-fund:abc123)").action((opts) => {
9467
+ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (persists across sessions)").option("--private-key <key>", "Wallet private key (0x-prefixed)").option("--vault <address>", "Default vault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").option("--notify-to <id>", "Destination for cron summaries (Telegram chat ID, phone, etc.)").option("--uniswap-api-key <key>", "Uniswap Trading API key (from developers.uniswap.org)").option("--venice-api-key <key>", "Venice AI inference API key").option("--anthropic-api-key <key>", "Anthropic Claude API key (for LLM judge)").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a vault (e.g. my-vault:abc123)").action((opts) => {
9377
9468
  let saved = false;
9378
9469
  if (opts.privateKey) {
9379
9470
  setPrivateKey(opts.privateKey);