@sherwoodagent/cli 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{chat-4Q7G3DFO.js → chat-UYS54RFN.js} +9 -6
  2. package/dist/{chat-4Q7G3DFO.js.map → chat-UYS54RFN.js.map} +1 -1
  3. package/dist/chunk-7CN3TSAA.js +107 -0
  4. package/dist/chunk-7CN3TSAA.js.map +1 -0
  5. package/dist/{chunk-SGYOOHML.js → chunk-7IMQTN6G.js} +65 -88
  6. package/dist/chunk-7IMQTN6G.js.map +1 -0
  7. package/dist/chunk-FWJBUK57.js +65 -0
  8. package/dist/chunk-FWJBUK57.js.map +1 -0
  9. package/dist/{chunk-3EBFJLQR.js → chunk-HFRHR4VS.js} +12 -53
  10. package/dist/chunk-HFRHR4VS.js.map +1 -0
  11. package/dist/chunk-IIDZ2TK5.js +100 -0
  12. package/dist/chunk-IIDZ2TK5.js.map +1 -0
  13. package/dist/{chunk-4MTHXGTK.js → chunk-KAZRNDZQ.js} +2 -2
  14. package/dist/{chunk-DVWORPEY.js → chunk-LEQLX7XF.js} +1 -1
  15. package/dist/chunk-LEQLX7XF.js.map +1 -0
  16. package/dist/{chunk-DTSTJUZH.js → chunk-V4S2TI6Y.js} +8 -6
  17. package/dist/{chunk-DTSTJUZH.js.map → chunk-V4S2TI6Y.js.map} +1 -1
  18. package/dist/config-U74QT4SC.js +37 -0
  19. package/dist/cron-RG46PYWA.js +203 -0
  20. package/dist/cron-RG46PYWA.js.map +1 -0
  21. package/dist/{eas-NZ7GCLPA.js → eas-TJUVEXAY.js} +6 -4
  22. package/dist/index.js +139 -151
  23. package/dist/index.js.map +1 -1
  24. package/dist/{ipfs-P3NVJQCF.js → ipfs-LUJHZGKF.js} +2 -2
  25. package/dist/network-ROF3SSAA.js +26 -0
  26. package/dist/network-ROF3SSAA.js.map +1 -0
  27. package/dist/{research-3XEIOMDP.js → research-3CTVCGEC.js} +8 -6
  28. package/dist/{research-3XEIOMDP.js.map → research-3CTVCGEC.js.map} +1 -1
  29. package/dist/research-HEZP7VPY.js +14 -0
  30. package/dist/research-HEZP7VPY.js.map +1 -0
  31. package/dist/{session-FVFIACYW.js → session-GE72NIN5.js} +48 -7
  32. package/dist/session-GE72NIN5.js.map +1 -0
  33. package/dist/{xmtp-JC5AUYRG.js → xmtp-TNWKMX6L.js} +10 -6
  34. package/dist/{xmtp-JC5AUYRG.js.map → xmtp-TNWKMX6L.js.map} +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-3EBFJLQR.js.map +0 -1
  37. package/dist/chunk-5ADWTXNT.js +0 -233
  38. package/dist/chunk-5ADWTXNT.js.map +0 -1
  39. package/dist/chunk-DVWORPEY.js.map +0 -1
  40. package/dist/chunk-SGYOOHML.js.map +0 -1
  41. package/dist/research-ZR7HXITG.js +0 -12
  42. package/dist/session-FVFIACYW.js.map +0 -1
  43. /package/dist/{chunk-4MTHXGTK.js.map → chunk-KAZRNDZQ.js.map} +0 -0
  44. /package/dist/{eas-NZ7GCLPA.js.map → config-U74QT4SC.js.map} +0 -0
  45. /package/dist/{ipfs-P3NVJQCF.js.map → eas-TJUVEXAY.js.map} +0 -0
  46. /package/dist/{research-ZR7HXITG.js.map → ipfs-LUJHZGKF.js.map} +0 -0
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  fetchMetadata,
4
4
  uploadMetadata
5
- } from "./chunk-DVWORPEY.js";
5
+ } from "./chunk-LEQLX7XF.js";
6
6
  import {
7
7
  createApproval,
8
8
  createJoinRequest,
@@ -10,7 +10,7 @@ import {
10
10
  queryApprovals,
11
11
  queryJoinRequests,
12
12
  revokeAttestation
13
- } from "./chunk-DTSTJUZH.js";
13
+ } from "./chunk-V4S2TI6Y.js";
14
14
  import {
15
15
  approveDepositor,
16
16
  deposit,
@@ -20,15 +20,13 @@ import {
20
20
  getVaultAddress,
21
21
  getVaultInfo,
22
22
  isAgent,
23
- ragequit,
24
23
  registerAgent,
25
24
  removeDepositor,
26
25
  resolveSyndicate,
27
26
  resolveVaultSyndicate,
28
27
  setTextRecord,
29
- setVaultAddress,
30
- simulateBatch
31
- } from "./chunk-3EBFJLQR.js";
28
+ setVaultAddress
29
+ } from "./chunk-HFRHR4VS.js";
32
30
  import {
33
31
  AGENT_REGISTRY,
34
32
  EAS_SCHEMAS,
@@ -44,28 +42,35 @@ import {
44
42
  UNISWAP_QUOTER_V2_ABI,
45
43
  VENICE,
46
44
  VENICE_STAKING_ABI
47
- } from "./chunk-SGYOOHML.js";
45
+ } from "./chunk-7IMQTN6G.js";
48
46
  import {
49
- VALID_NETWORKS,
50
- cacheGroupId,
51
47
  getAccount,
52
- getAgentId,
48
+ getPublicClient,
49
+ getWalletClient
50
+ } from "./chunk-FWJBUK57.js";
51
+ import {
52
+ VALID_NETWORKS,
53
53
  getChain,
54
- getChainContracts,
55
54
  getExplorerUrl,
56
55
  getNetwork,
57
- getPublicClient,
58
56
  getRpcUrl,
57
+ isTestnet,
58
+ setNetwork
59
+ } from "./chunk-7CN3TSAA.js";
60
+ import {
61
+ cacheGroupId,
62
+ getAgentId,
63
+ getChainContracts,
64
+ getNotifyTo,
59
65
  getVeniceApiKey,
60
- getWalletClient,
61
66
  loadConfig,
62
67
  setAgentId,
63
68
  setChainContract,
64
69
  setConfigRpcUrl,
65
- setNetwork,
70
+ setNotifyTo,
66
71
  setPrivateKey,
67
72
  setVeniceApiKey
68
- } from "./chunk-5ADWTXNT.js";
73
+ } from "./chunk-IIDZ2TK5.js";
69
74
 
70
75
  // src/index.ts
71
76
  import { config as loadDotenv } from "dotenv";
@@ -451,32 +456,6 @@ async function runLeveredSwap(opts) {
451
456
  console.log(chalk.bold("Batch calls (6):"));
452
457
  console.log(formatBatch(calls));
453
458
  console.log();
454
- const simSpinner = ora("Simulating via vault...").start();
455
- try {
456
- const results = await simulateBatch(calls);
457
- const allSucceeded = results.every((r) => r.success);
458
- if (allSucceeded) {
459
- simSpinner.succeed("Simulation passed");
460
- } else {
461
- simSpinner.fail("Simulation: some calls failed");
462
- for (let i = 0; i < results.length; i++) {
463
- const status = results[i].success ? "\u2713" : "\u2717";
464
- console.log(` ${status} Call ${i + 1}`);
465
- }
466
- if (!opts.execute) {
467
- process.exit(1);
468
- }
469
- console.log(chalk.yellow("Continuing to execution despite simulation failure..."));
470
- }
471
- } catch (err) {
472
- simSpinner.fail("Simulation failed");
473
- const msg = err instanceof Error ? err.message : String(err);
474
- console.error(chalk.red(msg));
475
- if (!opts.execute) {
476
- process.exit(1);
477
- }
478
- console.log(chalk.yellow("Continuing to execution despite simulation failure..."));
479
- }
480
459
  if (!opts.execute) {
481
460
  console.log();
482
461
  console.log(chalk.yellow("Dry run complete. Add --execute to submit on-chain."));
@@ -1016,27 +995,6 @@ function registerVeniceCommands(program2) {
1016
995
  console.log(chalk2.bold(`Batch calls (${calls.length}):`));
1017
996
  console.log(formatBatch(calls));
1018
997
  console.log();
1019
- const simSpinner = ora2("Simulating via vault...").start();
1020
- try {
1021
- const results = await simulateBatch(calls);
1022
- const allSucceeded = results.every((r) => r.success);
1023
- if (allSucceeded) {
1024
- simSpinner.succeed("Simulation passed");
1025
- } else {
1026
- simSpinner.fail("Simulation: some calls failed");
1027
- for (let i = 0; i < results.length; i++) {
1028
- const status = results[i].success ? "ok" : "FAIL";
1029
- console.log(` ${status} Call ${i + 1}`);
1030
- }
1031
- if (!opts.execute) process.exit(1);
1032
- console.log(chalk2.yellow("Continuing to execution despite simulation failure..."));
1033
- }
1034
- } catch (err) {
1035
- simSpinner.fail("Simulation failed");
1036
- console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1037
- if (!opts.execute) process.exit(1);
1038
- console.log(chalk2.yellow("Continuing to execution despite simulation failure..."));
1039
- }
1040
998
  if (!opts.execute) {
1041
999
  console.log();
1042
1000
  console.log(chalk2.yellow("Dry run complete. Add --execute to submit on-chain."));
@@ -1429,27 +1387,6 @@ function registerAllowanceCommands(program2) {
1429
1387
  console.log(chalk3.bold(`Batch calls (${calls.length}):`));
1430
1388
  console.log(formatBatch(calls));
1431
1389
  console.log();
1432
- const simSpinner = ora3("Simulating via vault...").start();
1433
- try {
1434
- const results = await simulateBatch(calls);
1435
- const allSucceeded = results.every((r) => r.success);
1436
- if (allSucceeded) {
1437
- simSpinner.succeed("Simulation passed");
1438
- } else {
1439
- simSpinner.fail("Simulation: some calls failed");
1440
- for (let i = 0; i < results.length; i++) {
1441
- const status = results[i].success ? "ok" : "FAIL";
1442
- console.log(` ${status} Call ${i + 1}`);
1443
- }
1444
- if (!opts.execute) process.exit(1);
1445
- console.log(chalk3.yellow("Continuing to execution despite simulation failure..."));
1446
- }
1447
- } catch (err) {
1448
- simSpinner.fail("Simulation failed");
1449
- console.error(chalk3.red(err instanceof Error ? err.message : String(err)));
1450
- if (!opts.execute) process.exit(1);
1451
- console.log(chalk3.yellow("Continuing to execution despite simulation failure..."));
1452
- }
1453
1390
  if (!opts.execute) {
1454
1391
  console.log();
1455
1392
  console.log(chalk3.yellow("Dry run complete. Add --execute to submit on-chain."));
@@ -1786,12 +1723,22 @@ async function hasVoted(proposalId, voter) {
1786
1723
  args: [proposalId, voter]
1787
1724
  });
1788
1725
  }
1789
- async function getProposalCalls(proposalId) {
1726
+ async function getExecuteCalls(proposalId) {
1790
1727
  const client = getPublicClient();
1791
1728
  const result = await client.readContract({
1792
1729
  address: getGovernorAddress(),
1793
1730
  abi: SYNDICATE_GOVERNOR_ABI,
1794
- functionName: "getProposalCalls",
1731
+ functionName: "getExecuteCalls",
1732
+ args: [proposalId]
1733
+ });
1734
+ return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));
1735
+ }
1736
+ async function getSettlementCalls(proposalId) {
1737
+ const client = getPublicClient();
1738
+ const result = await client.readContract({
1739
+ address: getGovernorAddress(),
1740
+ abi: SYNDICATE_GOVERNOR_ABI,
1741
+ functionName: "getSettlementCalls",
1795
1742
  args: [proposalId]
1796
1743
  });
1797
1744
  return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));
@@ -1813,7 +1760,7 @@ async function getCapitalSnapshot(proposalId) {
1813
1760
  args: [proposalId]
1814
1761
  });
1815
1762
  }
1816
- async function propose(vault, metadataURI, performanceFeeBps, strategyDuration, calls, splitIndex, coProposers = []) {
1763
+ async function propose(vault, metadataURI, performanceFeeBps, strategyDuration, executeCalls, settlementCalls, coProposers = []) {
1817
1764
  const wallet = getWalletClient();
1818
1765
  const client = getPublicClient();
1819
1766
  const hash = await wallet.writeContract({
@@ -1822,7 +1769,7 @@ async function propose(vault, metadataURI, performanceFeeBps, strategyDuration,
1822
1769
  address: getGovernorAddress(),
1823
1770
  abi: SYNDICATE_GOVERNOR_ABI,
1824
1771
  functionName: "propose",
1825
- args: [vault, metadataURI, performanceFeeBps, strategyDuration, calls, splitIndex, coProposers]
1772
+ args: [vault, metadataURI, performanceFeeBps, strategyDuration, executeCalls, settlementCalls, coProposers]
1826
1773
  });
1827
1774
  const receipt = await client.waitForTransactionReceipt({ hash });
1828
1775
  let proposalId;
@@ -1875,20 +1822,6 @@ async function settleProposal(proposalId) {
1875
1822
  const receipt = await client.waitForTransactionReceipt({ hash });
1876
1823
  return receipt.transactionHash;
1877
1824
  }
1878
- async function settleByAgent(proposalId, calls) {
1879
- const wallet = getWalletClient();
1880
- const client = getPublicClient();
1881
- const hash = await wallet.writeContract({
1882
- account: getAccount(),
1883
- chain: getChain(),
1884
- address: getGovernorAddress(),
1885
- abi: SYNDICATE_GOVERNOR_ABI,
1886
- functionName: "settleByAgent",
1887
- args: [proposalId, calls]
1888
- });
1889
- const receipt = await client.waitForTransactionReceipt({ hash });
1890
- return receipt.transactionHash;
1891
- }
1892
1825
  async function emergencySettle(proposalId, calls) {
1893
1826
  const wallet = getWalletClient();
1894
1827
  const client = getPublicClient();
@@ -1959,7 +1892,7 @@ async function setExecutionWindow(seconds) {
1959
1892
  const receipt = await client.waitForTransactionReceipt({ hash });
1960
1893
  return receipt.transactionHash;
1961
1894
  }
1962
- async function setQuorumBps(bps) {
1895
+ async function setVetoThresholdBps(bps) {
1963
1896
  const wallet = getWalletClient();
1964
1897
  const client = getPublicClient();
1965
1898
  const hash = await wallet.writeContract({
@@ -1967,7 +1900,7 @@ async function setQuorumBps(bps) {
1967
1900
  chain: getChain(),
1968
1901
  address: getGovernorAddress(),
1969
1902
  abi: SYNDICATE_GOVERNOR_ABI,
1970
- functionName: "setQuorumBps",
1903
+ functionName: "setVetoThresholdBps",
1971
1904
  args: [bps]
1972
1905
  });
1973
1906
  const receipt = await client.waitForTransactionReceipt({ hash });
@@ -2015,6 +1948,20 @@ async function setCooldownPeriod(seconds) {
2015
1948
  const receipt = await client.waitForTransactionReceipt({ hash });
2016
1949
  return receipt.transactionHash;
2017
1950
  }
1951
+ async function setProtocolFeeBps(bps) {
1952
+ const wallet = getWalletClient();
1953
+ const client = getPublicClient();
1954
+ const hash = await wallet.writeContract({
1955
+ account: getAccount(),
1956
+ chain: getChain(),
1957
+ address: getGovernorAddress(),
1958
+ abi: SYNDICATE_GOVERNOR_ABI,
1959
+ functionName: "setProtocolFeeBps",
1960
+ args: [bps]
1961
+ });
1962
+ const receipt = await client.waitForTransactionReceipt({ hash });
1963
+ return receipt.transactionHash;
1964
+ }
2018
1965
 
2019
1966
  // src/lib/format.ts
2020
1967
  function formatDurationShort(seconds) {
@@ -2068,7 +2015,7 @@ function parseCallsFile(path) {
2068
2015
  }
2069
2016
  function registerProposalCommands(program2) {
2070
2017
  const proposal = program2.command("proposal").description("Governance proposals \u2014 create, vote, execute, settle");
2071
- proposal.command("create").description("Submit a strategy proposal").requiredOption("--vault <address>", "Vault address the proposal targets").requiredOption("--name <name>", "Strategy name").requiredOption("--description <text>", "Strategy rationale and risk summary").requiredOption("--performance-fee <bps>", "Agent fee in bps (e.g. 1500 = 15%)").requiredOption("--duration <duration>", "Strategy duration (e.g. 7d, 24h, 3600)").requiredOption("--calls <path>", "Path to JSON file with Call[] array").requiredOption("--split-index <n>", "Index where execute calls end and settle calls begin").option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").action(async (opts) => {
2018
+ proposal.command("create").description("Submit a strategy proposal").requiredOption("--vault <address>", "Vault address the proposal targets").requiredOption("--name <name>", "Strategy name").requiredOption("--description <text>", "Strategy rationale and risk summary").requiredOption("--performance-fee <bps>", "Agent fee in bps (e.g. 1500 = 15%)").requiredOption("--duration <duration>", "Strategy duration (e.g. 7d, 24h, 3600)").requiredOption("--execute-calls <path>", "Path to JSON file with execute Call[] array").requiredOption("--settle-calls <path>", "Path to JSON file with settlement Call[] array").option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").action(async (opts) => {
2072
2019
  try {
2073
2020
  const vault = opts.vault;
2074
2021
  if (!isAddress4(vault)) {
@@ -2077,8 +2024,8 @@ function registerProposalCommands(program2) {
2077
2024
  }
2078
2025
  const performanceFeeBps = parseBigIntArg(opts.performanceFee, "performance-fee");
2079
2026
  const strategyDuration = parseDuration(opts.duration);
2080
- const splitIndex = parseBigIntArg(opts.splitIndex, "split-index");
2081
- const calls = parseCallsFile(opts.calls);
2027
+ const executeCalls = parseCallsFile(opts.executeCalls);
2028
+ const settleCalls = parseCallsFile(opts.settleCalls);
2082
2029
  let metadataURI = opts.metadataUri || "";
2083
2030
  if (!metadataURI) {
2084
2031
  const spinner2 = ora5({ text: W("Uploading metadata to IPFS..."), color: "green" }).start();
@@ -2090,7 +2037,7 @@ function registerProposalCommands(program2) {
2090
2037
  description: opts.description,
2091
2038
  chain: getNetwork(),
2092
2039
  strategies: [],
2093
- terms: { ragequitEnabled: true },
2040
+ terms: {},
2094
2041
  links: {}
2095
2042
  };
2096
2043
  const proposalMeta = {
@@ -2116,11 +2063,11 @@ function registerProposalCommands(program2) {
2116
2063
  console.log(W(` Vault: ${G(vault)}`));
2117
2064
  console.log(W(` Performance Fee: ${Number(performanceFeeBps) / 100}%`));
2118
2065
  console.log(W(` Duration: ${formatDurationShort(strategyDuration)}`));
2119
- console.log(W(` Calls: ${calls.length} (split at ${splitIndex})`));
2066
+ console.log(W(` Calls: ${executeCalls.length} execute + ${settleCalls.length} settle`));
2120
2067
  console.log(W(` Metadata: ${DIM(metadataURI.length > 50 ? metadataURI.slice(0, 50) + "..." : metadataURI)}`));
2121
2068
  SEP();
2122
2069
  const spinner = ora5({ text: W("Submitting proposal..."), color: "green" }).start();
2123
- const result = await propose(vault, metadataURI, performanceFeeBps, strategyDuration, calls, splitIndex);
2070
+ const result = await propose(vault, metadataURI, performanceFeeBps, strategyDuration, executeCalls, settleCalls);
2124
2071
  spinner.succeed(G("Proposal submitted"));
2125
2072
  console.log();
2126
2073
  console.log(LABEL(" \u25C6 Proposal Created"));
@@ -2195,12 +2142,11 @@ function registerProposalCommands(program2) {
2195
2142
  const id = parseBigIntArg(idStr, "proposal ID");
2196
2143
  const p = await getProposal(id);
2197
2144
  const state = await getProposalState(id);
2198
- const calls = await getProposalCalls(id);
2199
2145
  const params = await getGovernorParams();
2200
2146
  spinner.stop();
2201
2147
  const stateLabel = PROPOSAL_STATES[state] || "Unknown";
2202
2148
  const totalVotes = p.votesFor + p.votesAgainst;
2203
- const quorumNeeded = totalVotes > 0n ? `${Number(params.quorumBps) / 100}%` : "\u2014";
2149
+ const quorumNeeded = totalVotes > 0n ? `${Number(params.vetoThresholdBps) / 100}%` : "\u2014";
2204
2150
  console.log();
2205
2151
  console.log(LABEL(` \u25C6 Proposal #${p.id}`));
2206
2152
  SEP();
@@ -2231,7 +2177,7 @@ function registerProposalCommands(program2) {
2231
2177
  console.log(W(` For: ${formatShares(p.votesFor)}`));
2232
2178
  console.log(W(` Against: ${formatShares(p.votesAgainst)}`));
2233
2179
  console.log(W(` Abstain: ${formatShares(p.votesAbstain)}`));
2234
- console.log(W(` Quorum: ${quorumNeeded}`));
2180
+ console.log(W(` Veto Threshold: ${quorumNeeded}`));
2235
2181
  if (state === PROPOSAL_STATE.Executed || state === PROPOSAL_STATE.Settled) {
2236
2182
  try {
2237
2183
  const cap = await getCapitalSnapshot(id);
@@ -2241,12 +2187,18 @@ function registerProposalCommands(program2) {
2241
2187
  } catch {
2242
2188
  }
2243
2189
  }
2190
+ const execCalls = await getExecuteCalls(id);
2191
+ const settlCalls = await getSettlementCalls(id);
2244
2192
  console.log();
2245
- console.log(LABEL(` Calls (${calls.length}, split at ${p.splitIndex})`));
2246
- for (let i = 0; i < calls.length; i++) {
2247
- const phase = BigInt(i) < p.splitIndex ? "execute" : "settle";
2248
- console.log(DIM(` [${i}] (${phase}) target=${calls[i].target}`));
2249
- console.log(DIM(` data=${calls[i].data.slice(0, 20)}... value=${calls[i].value}`));
2193
+ console.log(LABEL(` Execute Calls (${execCalls.length})`));
2194
+ for (let i = 0; i < execCalls.length; i++) {
2195
+ console.log(DIM(` [${i}] target=${execCalls[i].target}`));
2196
+ console.log(DIM(` data=${execCalls[i].data.slice(0, 20)}... value=${execCalls[i].value}`));
2197
+ }
2198
+ console.log(LABEL(` Settlement Calls (${settlCalls.length})`));
2199
+ for (let i = 0; i < settlCalls.length; i++) {
2200
+ console.log(DIM(` [${i}] target=${settlCalls[i].target}`));
2201
+ console.log(DIM(` data=${settlCalls[i].data.slice(0, 20)}... value=${settlCalls[i].value}`));
2250
2202
  }
2251
2203
  SEP();
2252
2204
  console.log();
@@ -2341,11 +2293,10 @@ function registerProposalCommands(program2) {
2341
2293
  const now = BigInt(Math.floor(Date.now() / 1e3));
2342
2294
  const durationElapsed = p.executedAt > 0n && now >= p.executedAt + p.strategyDuration;
2343
2295
  let hash;
2344
- if (isProposer && opts.calls) {
2345
- spinner.text = W("Settling by agent...");
2346
- const calls = parseCallsFile(opts.calls);
2347
- hash = await settleByAgent(proposalId, calls);
2348
- spinner.succeed(G("Settled by agent"));
2296
+ if (isProposer && !durationElapsed) {
2297
+ spinner.text = W("Settling (proposer)...");
2298
+ hash = await settleProposal(proposalId);
2299
+ spinner.succeed(G("Settled by proposer"));
2349
2300
  } else if (durationElapsed && !opts.calls) {
2350
2301
  spinner.text = W("Settling (permissionless)...");
2351
2302
  hash = await settleProposal(proposalId);
@@ -2356,7 +2307,7 @@ function registerProposalCommands(program2) {
2356
2307
  hash = await emergencySettle(proposalId, calls);
2357
2308
  spinner.succeed(G("Emergency settled"));
2358
2309
  } else {
2359
- spinner.fail("Cannot settle: duration not elapsed. If you are the proposer, provide --calls.");
2310
+ spinner.fail("Cannot settle: duration not elapsed and you are not the proposer.");
2360
2311
  process.exit(1);
2361
2312
  }
2362
2313
  console.log(DIM(` ${getExplorerUrl(hash)}`));
@@ -2425,7 +2376,7 @@ function registerGovernorCommands(program2) {
2425
2376
  console.log(W2(` Address: ${G2(getGovernorAddress())}`));
2426
2377
  console.log(W2(` Voting Period: ${BOLD2(formatDurationLong(params.votingPeriod))}`));
2427
2378
  console.log(W2(` Execution Window: ${BOLD2(formatDurationLong(params.executionWindow))}`));
2428
- console.log(W2(` Quorum: ${BOLD2(`${Number(params.quorumBps) / 100}%`)}`));
2379
+ console.log(W2(` Veto Threshold: ${BOLD2(`${Number(params.vetoThresholdBps) / 100}%`)}`));
2429
2380
  console.log(W2(` Max Performance Fee: ${BOLD2(`${Number(params.maxPerformanceFeeBps) / 100}%`)}`));
2430
2381
  console.log(W2(` Max Strategy Duration:${BOLD2(` ${formatDurationLong(params.maxStrategyDuration)}`)}`));
2431
2382
  console.log(W2(` Cooldown Period: ${BOLD2(formatDurationLong(params.cooldownPeriod))}`));
@@ -2470,14 +2421,14 @@ function registerGovernorCommands(program2) {
2470
2421
  process.exit(1);
2471
2422
  }
2472
2423
  });
2473
- governor.command("set-quorum").description("Set the quorum threshold in bps (owner only)").requiredOption("--bps <n>", "New quorum in bps (e.g. 4000 = 40%)").action(async (opts) => {
2474
- const spinner = ora6("Setting quorum...").start();
2424
+ governor.command("set-veto-threshold").description("Set the veto threshold in bps (owner only)").requiredOption("--bps <n>", "New veto threshold in bps (e.g. 4000 = 40%)").action(async (opts) => {
2425
+ const spinner = ora6("Setting veto threshold...").start();
2475
2426
  try {
2476
- const hash = await setQuorumBps(parseBigIntArg(opts.bps, "bps"));
2477
- spinner.succeed(G2(`Quorum updated to ${Number(opts.bps) / 100}%`));
2427
+ const hash = await setVetoThresholdBps(parseBigIntArg(opts.bps, "bps"));
2428
+ spinner.succeed(G2(`Veto threshold updated to ${Number(opts.bps) / 100}%`));
2478
2429
  console.log(DIM2(` ${getExplorerUrl(hash)}`));
2479
2430
  } catch (err) {
2480
- spinner.fail("Failed to set quorum");
2431
+ spinner.fail("Failed to set veto threshold");
2481
2432
  console.error(chalk6.red(err instanceof Error ? err.message : String(err)));
2482
2433
  process.exit(1);
2483
2434
  }
@@ -2518,6 +2469,18 @@ function registerGovernorCommands(program2) {
2518
2469
  process.exit(1);
2519
2470
  }
2520
2471
  });
2472
+ governor.command("set-protocol-fee").description("Set the protocol fee in bps (owner only)").requiredOption("--bps <n>", "New protocol fee in bps (e.g. 500 = 5%, max 1000 = 10%)").action(async (opts) => {
2473
+ const spinner = ora6("Setting protocol fee...").start();
2474
+ try {
2475
+ const hash = await setProtocolFeeBps(parseBigIntArg(opts.bps, "bps"));
2476
+ spinner.succeed(G2(`Protocol fee updated to ${Number(opts.bps) / 100}%`));
2477
+ console.log(DIM2(` ${getExplorerUrl(hash)}`));
2478
+ } catch (err) {
2479
+ spinner.fail("Failed to set protocol fee");
2480
+ console.error(chalk6.red(err instanceof Error ? err.message : String(err)));
2481
+ process.exit(1);
2482
+ }
2483
+ });
2521
2484
  }
2522
2485
 
2523
2486
  // src/index.ts
@@ -2526,7 +2489,10 @@ try {
2526
2489
  } catch {
2527
2490
  }
2528
2491
  async function loadXmtp() {
2529
- return import("./xmtp-JC5AUYRG.js");
2492
+ return import("./xmtp-TNWKMX6L.js");
2493
+ }
2494
+ async function loadCron() {
2495
+ return import("./cron-RG46PYWA.js");
2530
2496
  }
2531
2497
  var G3 = chalk7.green;
2532
2498
  var W3 = chalk7.white;
@@ -2654,7 +2620,6 @@ syndicate.command("create").description("Create a new syndicate via the factory
2654
2620
  chain: getChain().name,
2655
2621
  strategies: [],
2656
2622
  terms: {
2657
- ragequitEnabled: true,
2658
2623
  feeModel: "none"
2659
2624
  },
2660
2625
  links: {}
@@ -2701,6 +2666,16 @@ syndicate.command("create").description("Create a new syndicate via the factory
2701
2666
  console.warn(chalk7.yellow("\n \u26A0 Could not create XMTP chat group"));
2702
2667
  console.warn(chalk7.dim(` Recover later with: sherwood chat ${subdomain} init`));
2703
2668
  }
2669
+ try {
2670
+ const cron = await loadCron();
2671
+ const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
2672
+ if (cronResult.isOpenClaw && cronResult.registered) {
2673
+ console.log(G3(" \u2713 Participation crons registered (15m check + hourly summary)"));
2674
+ } else if (!cronResult.isOpenClaw) {
2675
+ console.log(DIM3(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
2676
+ }
2677
+ } catch {
2678
+ }
2704
2679
  spinner.stop();
2705
2680
  console.log();
2706
2681
  console.log(LABEL3(" \u25C6 Syndicate Created"));
@@ -2830,7 +2805,7 @@ syndicate.command("update-metadata").description("Update syndicate metadata (cre
2830
2805
  description,
2831
2806
  chain: getChain().name,
2832
2807
  strategies: [],
2833
- terms: { ragequitEnabled: true },
2808
+ terms: {},
2834
2809
  links: {}
2835
2810
  };
2836
2811
  metadataURI = await uploadMetadata(metadata);
@@ -2934,6 +2909,16 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
2934
2909
  } catch {
2935
2910
  console.warn(chalk7.yellow(" \u26A0 Could not initialize XMTP identity"));
2936
2911
  }
2912
+ try {
2913
+ const cron = await loadCron();
2914
+ const cronResult = cron.registerSyndicateCrons(opts.subdomain, isTestnet(), getNotifyTo());
2915
+ if (cronResult.isOpenClaw && cronResult.registered) {
2916
+ console.log(chalk7.green(" \u2713 Participation crons registered"));
2917
+ } else if (!cronResult.isOpenClaw) {
2918
+ console.log(chalk7.dim(" Tip: Set up a scheduled process to run `sherwood session check " + opts.subdomain + "` periodically"));
2919
+ }
2920
+ } catch {
2921
+ }
2937
2922
  return;
2938
2923
  }
2939
2924
  spinner.text = "Checking pending requests...";
@@ -2971,6 +2956,16 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
2971
2956
  spinner.succeed("Join request created");
2972
2957
  console.warn(chalk7.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
2973
2958
  }
2959
+ try {
2960
+ const cron = await loadCron();
2961
+ const cronResult = cron.registerSyndicateCrons(opts.subdomain, isTestnet(), getNotifyTo());
2962
+ if (cronResult.isOpenClaw && cronResult.registered) {
2963
+ console.log(G3(" \u2713 Participation crons registered (will activate after approval)"));
2964
+ } else if (!cronResult.isOpenClaw) {
2965
+ console.log(DIM3(" Tip: Set up a scheduled process to run `sherwood session check " + opts.subdomain + "` periodically"));
2966
+ }
2967
+ } catch {
2968
+ }
2974
2969
  console.log();
2975
2970
  console.log(LABEL3(" \u25C6 Join Request Submitted"));
2976
2971
  SEP3();
@@ -3161,19 +3156,6 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
3161
3156
  process.exit(1);
3162
3157
  }
3163
3158
  });
3164
- vaultCmd.command("ragequit").description("Withdraw all shares from a vault").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
3165
- resolveVault(opts);
3166
- const spinner = ora7("Ragequitting...").start();
3167
- try {
3168
- const hash = await ragequit();
3169
- spinner.succeed(`Ragequit: ${hash}`);
3170
- console.log(chalk7.dim(` ${getExplorerUrl(hash)}`));
3171
- } catch (err) {
3172
- spinner.fail("Ragequit failed");
3173
- console.error(chalk7.red(err instanceof Error ? err.message : String(err)));
3174
- process.exit(1);
3175
- }
3176
- });
3177
3159
  vaultCmd.command("info").description("Display vault state").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
3178
3160
  resolveVault(opts);
3179
3161
  const spinner = ora7("Loading vault info...").start();
@@ -3290,7 +3272,7 @@ strategy.command("run").description("Execute the levered swap strategy").option(
3290
3272
  await runLeveredSwap(opts);
3291
3273
  });
3292
3274
  program.command("providers").description("List available DeFi providers").action(async () => {
3293
- const { MessariProvider, NansenProvider } = await import("./research-ZR7HXITG.js");
3275
+ const { MessariProvider, NansenProvider } = await import("./research-HEZP7VPY.js");
3294
3276
  const providers = [new MoonwellProvider(), new UniswapProvider(), new MessariProvider(), new NansenProvider()];
3295
3277
  for (const p of providers) {
3296
3278
  const info = p.info();
@@ -3301,7 +3283,7 @@ ${info.name} (${info.type})`);
3301
3283
  }
3302
3284
  });
3303
3285
  try {
3304
- const { registerChatCommands } = await import("./chat-4Q7G3DFO.js");
3286
+ const { registerChatCommands } = await import("./chat-UYS54RFN.js");
3305
3287
  registerChatCommands(program);
3306
3288
  } catch {
3307
3289
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -3311,17 +3293,17 @@ try {
3311
3293
  process.exit(1);
3312
3294
  });
3313
3295
  }
3314
- var { registerSessionCommands } = await import("./session-FVFIACYW.js");
3296
+ var { registerSessionCommands } = await import("./session-GE72NIN5.js");
3315
3297
  registerSessionCommands(program);
3316
3298
  registerVeniceCommands(program);
3317
3299
  registerAllowanceCommands(program);
3318
3300
  registerIdentityCommands(program);
3319
3301
  registerProposalCommands(program);
3320
3302
  registerGovernorCommands(program);
3321
- var { registerResearchCommands } = await import("./research-3XEIOMDP.js");
3303
+ var { registerResearchCommands } = await import("./research-3CTVCGEC.js");
3322
3304
  registerResearchCommands(program);
3323
3305
  var configCmd = program.command("config");
3324
- 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 SyndicateVault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").action((opts) => {
3306
+ 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 SyndicateVault 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.)").action((opts) => {
3325
3307
  let saved = false;
3326
3308
  if (opts.privateKey) {
3327
3309
  setPrivateKey(opts.privateKey);
@@ -3344,8 +3326,14 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
3344
3326
  console.log(chalk7.dim(` RPC: ${opts.rpc}`));
3345
3327
  saved = true;
3346
3328
  }
3329
+ if (opts.notifyTo) {
3330
+ setNotifyTo(opts.notifyTo);
3331
+ console.log(chalk7.green("Notify destination saved to ~/.sherwood/config.json"));
3332
+ console.log(chalk7.dim(` Notify to: ${opts.notifyTo}`));
3333
+ saved = true;
3334
+ }
3347
3335
  if (!saved) {
3348
- console.log(chalk7.red("Provide at least one of: --private-key, --vault, --rpc"));
3336
+ console.log(chalk7.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to"));
3349
3337
  process.exit(1);
3350
3338
  }
3351
3339
  });