@sherwoodagent/cli 0.14.1 → 0.14.2
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.
- package/dist/{chat-LFH2SA46.js → chat-X3IKMSNS.js} +11 -8
- package/dist/{chat-LFH2SA46.js.map → chat-X3IKMSNS.js.map} +1 -1
- package/dist/{chunk-2N7B5N7D.js → chunk-2RYZU7EP.js} +6 -4
- package/dist/chunk-2RYZU7EP.js.map +1 -0
- package/dist/chunk-4CV4JOE5.js +27 -0
- package/dist/{chunk-ADPAZUTB.js → chunk-5NA345RJ.js} +23 -10
- package/dist/chunk-5NA345RJ.js.map +1 -0
- package/dist/{chunk-IIDZ2TK5.js → chunk-BCOTZTTH.js} +39 -10
- package/dist/chunk-BCOTZTTH.js.map +1 -0
- package/dist/{chunk-7CN3TSAA.js → chunk-BGEVQQES.js} +5 -3
- package/dist/{chunk-7CN3TSAA.js.map → chunk-BGEVQQES.js.map} +1 -1
- package/dist/{chunk-FWJBUK57.js → chunk-CGSXIYYZ.js} +5 -3
- package/dist/{chunk-FWJBUK57.js.map → chunk-CGSXIYYZ.js.map} +1 -1
- package/dist/{chunk-KAZRNDZQ.js → chunk-QIOS7I7I.js} +2 -2
- package/dist/{chunk-AC4QMJKC.js → chunk-UBBR7QVJ.js} +2 -2
- package/dist/{chunk-LEQLX7XF.js → chunk-YSYX555I.js} +27 -10
- package/dist/chunk-YSYX555I.js.map +1 -0
- package/dist/{config-U74QT4SC.js → config-5C7QJMPR.js} +5 -2
- package/dist/{cron-RG46PYWA.js → cron-IKBNUL3Q.js} +3 -1
- package/dist/{cron-RG46PYWA.js.map → cron-IKBNUL3Q.js.map} +1 -1
- package/dist/{eas-XWLMRKJU.js → eas-7U7MX24T.js} +7 -6
- package/dist/index.js +74 -33
- package/dist/index.js.map +1 -1
- package/dist/ipfs-AYE4J4OX.js +13 -0
- package/dist/{network-ROF3SSAA.js → network-QU2D677V.js} +4 -3
- package/dist/research-7RI7VFPK.js +15 -0
- package/dist/research-7RI7VFPK.js.map +1 -0
- package/dist/{research-QXGYAJUL.js → research-ZDTM73C7.js} +9 -8
- package/dist/{research-QXGYAJUL.js.map → research-ZDTM73C7.js.map} +1 -1
- package/dist/{session-ECETX4MM.js → session-2VK25CSW.js} +14 -12
- package/dist/session-2VK25CSW.js.map +1 -0
- package/dist/{xmtp-EKFDS5Y3.js → xmtp-Y3LAZKOC.js} +10 -7
- package/dist/{xmtp-EKFDS5Y3.js.map → xmtp-Y3LAZKOC.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-2N7B5N7D.js.map +0 -1
- package/dist/chunk-ADPAZUTB.js.map +0 -1
- package/dist/chunk-IIDZ2TK5.js.map +0 -1
- package/dist/chunk-LEQLX7XF.js.map +0 -1
- package/dist/ipfs-LUJHZGKF.js +0 -11
- package/dist/research-HEZP7VPY.js +0 -14
- package/dist/session-ECETX4MM.js.map +0 -1
- /package/dist/{config-U74QT4SC.js.map → chunk-4CV4JOE5.js.map} +0 -0
- /package/dist/{chunk-KAZRNDZQ.js.map → chunk-QIOS7I7I.js.map} +0 -0
- /package/dist/{chunk-AC4QMJKC.js.map → chunk-UBBR7QVJ.js.map} +0 -0
- /package/dist/{eas-XWLMRKJU.js.map → config-5C7QJMPR.js.map} +0 -0
- /package/dist/{ipfs-LUJHZGKF.js.map → eas-7U7MX24T.js.map} +0 -0
- /package/dist/{network-ROF3SSAA.js.map → ipfs-AYE4J4OX.js.map} +0 -0
- /package/dist/{research-HEZP7VPY.js.map → network-QU2D677V.js.map} +0 -0
|
@@ -1,19 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
config_exports,
|
|
3
|
+
init_config
|
|
4
|
+
} from "./chunk-BCOTZTTH.js";
|
|
5
|
+
import {
|
|
6
|
+
__toCommonJS
|
|
7
|
+
} from "./chunk-4CV4JOE5.js";
|
|
8
|
+
|
|
1
9
|
// src/lib/ipfs.ts
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
var DEFAULT_PINATA_GATEWAY = "https://sherwood.mypinata.cloud";
|
|
11
|
+
function getPinataJwt() {
|
|
12
|
+
const envJwt = process.env.PINATA_JWT ?? process.env.PINATA_API_KEY;
|
|
13
|
+
if (envJwt) return envJwt;
|
|
14
|
+
try {
|
|
15
|
+
const { loadConfig } = (init_config(), __toCommonJS(config_exports));
|
|
16
|
+
const config = loadConfig();
|
|
17
|
+
if (config.pinataJwt) return config.pinataJwt;
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
throw new Error(
|
|
21
|
+
"PINATA_JWT environment variable is required for IPFS uploads. Get a free API key at https://app.pinata.cloud/developers/api-keys"
|
|
22
|
+
);
|
|
6
23
|
}
|
|
7
24
|
function getPinataGateway() {
|
|
8
|
-
return process.env.PINATA_GATEWAY ||
|
|
25
|
+
return process.env.PINATA_GATEWAY || DEFAULT_PINATA_GATEWAY;
|
|
9
26
|
}
|
|
10
27
|
async function pinJSON(content, name) {
|
|
11
|
-
const
|
|
28
|
+
const jwt = getPinataJwt();
|
|
12
29
|
const response = await fetch("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
|
|
13
30
|
method: "POST",
|
|
14
31
|
headers: {
|
|
15
32
|
"Content-Type": "application/json",
|
|
16
|
-
Authorization: `Bearer ${
|
|
33
|
+
Authorization: `Bearer ${jwt}`
|
|
17
34
|
},
|
|
18
35
|
body: JSON.stringify({
|
|
19
36
|
pinataContent: content,
|
|
@@ -28,12 +45,12 @@ async function pinJSON(content, name) {
|
|
|
28
45
|
return `ipfs://${result.IpfsHash}`;
|
|
29
46
|
}
|
|
30
47
|
async function uploadMetadata(metadata) {
|
|
31
|
-
const
|
|
48
|
+
const jwt = getPinataJwt();
|
|
32
49
|
const response = await fetch("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
|
|
33
50
|
method: "POST",
|
|
34
51
|
headers: {
|
|
35
52
|
"Content-Type": "application/json",
|
|
36
|
-
Authorization: `Bearer ${
|
|
53
|
+
Authorization: `Bearer ${jwt}`
|
|
37
54
|
},
|
|
38
55
|
body: JSON.stringify({
|
|
39
56
|
pinataContent: metadata,
|
|
@@ -72,4 +89,4 @@ export {
|
|
|
72
89
|
uploadMetadata,
|
|
73
90
|
fetchMetadata
|
|
74
91
|
};
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
92
|
+
//# sourceMappingURL=chunk-YSYX555I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ipfs.ts"],"sourcesContent":["/**\n * IPFS metadata upload/fetch via Pinata.\n *\n * Used for syndicate metadata (name, description, strategies, terms).\n * Requires PINATA_API_KEY and PINATA_GATEWAY env vars.\n */\n\nexport interface SyndicateMetadata {\n schema: string;\n name: string;\n description: string;\n logo?: string;\n chain: string;\n strategies: {\n id: string;\n name: string;\n description: string;\n protocols: string[];\n riskLevel: string;\n }[];\n terms: {\n minDeposit?: string;\n minDepositFormatted?: string;\n feeModel?: string;\n lockPeriod?: number;\n };\n links: {\n moltbook?: string;\n dashboard?: string;\n github?: string;\n };\n}\n\nconst DEFAULT_PINATA_GATEWAY = \"https://sherwood.mypinata.cloud\";\n\nfunction getPinataJwt(): string {\n const envJwt = process.env.PINATA_JWT ?? process.env.PINATA_API_KEY;\n if (envJwt) return envJwt;\n\n // Check config file\n try {\n const { loadConfig } = require(\"./config\");\n const config = loadConfig();\n if (config.pinataJwt) return config.pinataJwt;\n } catch {}\n\n throw new Error(\n \"PINATA_JWT environment variable is required for IPFS uploads. \" +\n \"Get a free API key at https://app.pinata.cloud/developers/api-keys\",\n );\n}\n\nfunction getPinataGateway(): string {\n return process.env.PINATA_GATEWAY || DEFAULT_PINATA_GATEWAY;\n}\n\n/**\n * Pin arbitrary JSON to IPFS via Pinata.\n * Used for research results and other generic JSON payloads.\n * Returns the IPFS URI (ipfs://Qm...).\n */\nexport async function pinJSON(content: Record<string, unknown>, name: string): Promise<string> {\n const jwt = getPinataJwt();\n\n const response = await fetch(\"https://api.pinata.cloud/pinning/pinJSONToIPFS\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({\n pinataContent: content,\n pinataMetadata: { name },\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Pinata upload failed (${response.status}): ${text}`);\n }\n\n const result = (await response.json()) as { IpfsHash: string };\n return `ipfs://${result.IpfsHash}`;\n}\n\n/**\n * Upload syndicate metadata to IPFS via Pinata.\n * Returns the IPFS URI (ipfs://Qm...).\n */\nexport async function uploadMetadata(metadata: SyndicateMetadata): Promise<string> {\n const jwt = getPinataJwt();\n\n const response = await fetch(\"https://api.pinata.cloud/pinning/pinJSONToIPFS\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({\n pinataContent: metadata,\n pinataMetadata: {\n name: `sherwood-syndicate-${metadata.name.toLowerCase().replace(/\\s+/g, \"-\")}`,\n },\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Pinata upload failed (${response.status}): ${text}`);\n }\n\n const result = (await response.json()) as { IpfsHash: string };\n return `ipfs://${result.IpfsHash}`;\n}\n\n/**\n * Fetch and parse metadata from an IPFS URI.\n * Supports ipfs:// protocol URIs and raw CIDs.\n */\nexport async function fetchMetadata(ipfsURI: string): Promise<SyndicateMetadata> {\n const gateway = getPinataGateway();\n let cid: string;\n\n if (ipfsURI.startsWith(\"ipfs://\")) {\n cid = ipfsURI.slice(7);\n } else if (ipfsURI.startsWith(\"Qm\") || ipfsURI.startsWith(\"bafy\")) {\n cid = ipfsURI;\n } else {\n throw new Error(`Invalid IPFS URI: ${ipfsURI}`);\n }\n\n const url = `${gateway}/ipfs/${cid}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch metadata from ${url} (${response.status})`);\n }\n\n return (await response.json()) as SyndicateMetadata;\n}\n"],"mappings":";;;;;;;;;AAiCA,IAAM,yBAAyB;AAE/B,SAAS,eAAuB;AAC9B,QAAM,SAAS,QAAQ,IAAI,cAAc,QAAQ,IAAI;AACrD,MAAI,OAAQ,QAAO;AAGnB,MAAI;AACF,UAAM,EAAE,WAAW,IAAI;AACvB,UAAM,SAAS,WAAW;AAC1B,QAAI,OAAO,UAAW,QAAO,OAAO;AAAA,EACtC,QAAQ;AAAA,EAAC;AAET,QAAM,IAAI;AAAA,IACR;AAAA,EAEF;AACF;AAEA,SAAS,mBAA2B;AAClC,SAAO,QAAQ,IAAI,kBAAkB;AACvC;AAOA,eAAsB,QAAQ,SAAkC,MAA+B;AAC7F,QAAM,MAAM,aAAa;AAEzB,QAAM,WAAW,MAAM,MAAM,kDAAkD;AAAA,IAC7E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,GAAG;AAAA,IAC9B;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,eAAe;AAAA,MACf,gBAAgB,EAAE,KAAK;AAAA,IACzB,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,IAAI,MAAM,yBAAyB,SAAS,MAAM,MAAM,IAAI,EAAE;AAAA,EACtE;AAEA,QAAM,SAAU,MAAM,SAAS,KAAK;AACpC,SAAO,UAAU,OAAO,QAAQ;AAClC;AAMA,eAAsB,eAAe,UAA8C;AACjF,QAAM,MAAM,aAAa;AAEzB,QAAM,WAAW,MAAM,MAAM,kDAAkD;AAAA,IAC7E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,GAAG;AAAA,IAC9B;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,eAAe;AAAA,MACf,gBAAgB;AAAA,QACd,MAAM,sBAAsB,SAAS,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,MAC9E;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,IAAI,MAAM,yBAAyB,SAAS,MAAM,MAAM,IAAI,EAAE;AAAA,EACtE;AAEA,QAAM,SAAU,MAAM,SAAS,KAAK;AACpC,SAAO,UAAU,OAAO,QAAQ;AAClC;AAMA,eAAsB,cAAc,SAA6C;AAC/E,QAAM,UAAU,iBAAiB;AACjC,MAAI;AAEJ,MAAI,QAAQ,WAAW,SAAS,GAAG;AACjC,UAAM,QAAQ,MAAM,CAAC;AAAA,EACvB,WAAW,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,MAAM,GAAG;AACjE,UAAM;AAAA,EACR,OAAO;AACL,UAAM,IAAI,MAAM,qBAAqB,OAAO,EAAE;AAAA,EAChD;AAEA,QAAM,MAAM,GAAG,OAAO,SAAS,GAAG;AAClC,QAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,iCAAiC,GAAG,KAAK,SAAS,MAAM,GAAG;AAAA,EAC7E;AAEA,SAAQ,MAAM,SAAS,KAAK;AAC9B;","names":[]}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
getNotifyTo,
|
|
8
8
|
getPrivateKey,
|
|
9
9
|
getVeniceApiKey,
|
|
10
|
+
init_config,
|
|
10
11
|
loadConfig,
|
|
11
12
|
saveConfig,
|
|
12
13
|
setAgentId,
|
|
@@ -15,7 +16,9 @@ import {
|
|
|
15
16
|
setNotifyTo,
|
|
16
17
|
setPrivateKey,
|
|
17
18
|
setVeniceApiKey
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BCOTZTTH.js";
|
|
20
|
+
import "./chunk-4CV4JOE5.js";
|
|
21
|
+
init_config();
|
|
19
22
|
export {
|
|
20
23
|
cacheGroupId,
|
|
21
24
|
getAgentId,
|
|
@@ -34,4 +37,4 @@ export {
|
|
|
34
37
|
setPrivateKey,
|
|
35
38
|
setVeniceApiKey
|
|
36
39
|
};
|
|
37
|
-
//# sourceMappingURL=config-
|
|
40
|
+
//# sourceMappingURL=config-5C7QJMPR.js.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "./chunk-4CV4JOE5.js";
|
|
2
|
+
|
|
1
3
|
// src/lib/cron.ts
|
|
2
4
|
import { execFileSync } from "child_process";
|
|
3
5
|
var _isOpenClaw = null;
|
|
@@ -200,4 +202,4 @@ export {
|
|
|
200
202
|
registerSyndicateCrons,
|
|
201
203
|
unregisterSyndicateCrons
|
|
202
204
|
};
|
|
203
|
-
//# sourceMappingURL=cron-
|
|
205
|
+
//# sourceMappingURL=cron-IKBNUL3Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cron.ts"],"sourcesContent":["/**\n * OpenClaw cron integration — auto-register participation crons for syndicate agents.\n *\n * When an agent creates or joins a syndicate, the CLI registers two cron jobs:\n * 1. Silent check (every 15m) — processes messages/events, responds autonomously\n * 2. Human summary (every 1h) — brief activity report delivered to the human's channel\n *\n * Non-OpenClaw agents skip silently — the caller prints guidance instead.\n */\n\nimport { execFileSync } from \"node:child_process\";\n\n// ── OpenClaw detection (cached per process) ──\n\nlet _isOpenClaw: boolean | null = null;\n\nexport function isOpenClaw(): boolean {\n if (_isOpenClaw !== null) return _isOpenClaw;\n try {\n execFileSync(\"openclaw\", [\"cron\", \"list\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n _isOpenClaw = true;\n } catch {\n _isOpenClaw = false;\n }\n return _isOpenClaw;\n}\n\n// ── Types ──\n\nexport interface CronResult {\n registered: boolean;\n isOpenClaw: boolean;\n cronNames: string[];\n}\n\nexport interface CronStatus {\n isOpenClaw: boolean;\n crons: { name: string; every: string; lastRun?: string }[];\n}\n\n// ── Cron naming ──\n\nfunction cronName(subdomain: string, testnet: boolean): string {\n return `sherwood-${subdomain}${testnet ? \"-testnet\" : \"\"}`;\n}\n\nfunction summaryCronName(subdomain: string, testnet: boolean): string {\n return `${cronName(subdomain, testnet)}-summary`;\n}\n\n// ── Prompts ──\n\nfunction silentPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n `You are a sherwood syndicate member. Your syndicate: ${subdomain}.sherwoodagent.eth`,\n \"\",\n `Step 1: Run \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"Step 2: Parse the JSON output for new messages and events\",\n \"Step 3: If new messages from OTHER agents, respond thoughtfully via:\",\n ` \\`${envPrefix}sherwood chat ${subdomain} send \"<response>\"${chainFlag}\\``,\n \"Step 4: If you responded to anything, summarize what you did (for your own session log).\",\n \" If nothing happened, reply HEARTBEAT_OK\",\n \"\",\n \"Rules:\",\n \"- Be a real syndicate member — discuss strategies, share opinions, ask questions\",\n \"- Keep responses concise and on-topic\",\n \"- Do NOT alert your human unless something requires their approval\",\n `- You can use \\`sherwood research\\` commands if you need data to back up your response`,\n ].join(\"\\n\");\n}\n\nfunction summaryPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n \"You are reporting syndicate activity to your human operator.\",\n \"\",\n `Run: \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"\",\n \"If there was activity (messages, events, proposals) since last check:\",\n \" Send a brief summary — who said what, any decisions made, any actions you took.\",\n \" Keep it to 3-5 lines max.\",\n \"\",\n \"If there was no activity:\",\n \" Reply HEARTBEAT_OK\",\n \"\",\n \"Only escalate (flag as urgent) if:\",\n \"- A proposal needs human sign-off\",\n \"- An agent left the syndicate\",\n \"- Risk alert or health factor warning\",\n \"- Human was directly asked for input\",\n ].join(\"\\n\");\n}\n\n// ── Helpers ──\n\n/** Parse `openclaw cron list --json` and return job names. */\nfunction listCronNames(): string[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string }[] = parsed.jobs || parsed || [];\n return jobs.map((j) => j.name);\n } catch {\n return [];\n }\n}\n\n/** Parse `openclaw cron list --json` with full details for status display. */\nfunction listCronDetails(): { name: string; every: string; lastRun?: string }[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string; every?: string; interval?: string; lastRun?: string }[] =\n parsed.jobs || parsed || [];\n return jobs.map((j) => ({\n name: j.name,\n every: j.every || j.interval || \"unknown\",\n lastRun: j.lastRun,\n }));\n } catch {\n return [];\n }\n}\n\n// ── Public API ──\n\nexport function registerSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n notifyTo?: string,\n): CronResult {\n if (!isOpenClaw()) {\n return { registered: false, isOpenClaw: false, cronNames: [] };\n }\n\n const checkName = cronName(subdomain, testnet);\n const summaryName = summaryCronName(subdomain, testnet);\n const existing = listCronNames();\n const created: string[] = [];\n\n // Cron 1: Silent participation check (every 15m)\n if (!existing.includes(checkName)) {\n try {\n execFileSync(\"openclaw\", [\n \"cron\", \"create\",\n \"--name\", checkName,\n \"--every\", \"15m\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"120\",\n \"--no-deliver\",\n \"--message\", silentPrompt(subdomain, testnet),\n ], {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(checkName);\n } catch (err) {\n console.warn(`Could not create silent cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Cron 2: Human summary (every 1h)\n if (!existing.includes(summaryName)) {\n try {\n const args = [\n \"cron\", \"create\",\n \"--name\", summaryName,\n \"--every\", \"1h\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"90\",\n \"--announce\",\n ];\n\n // Use explicit destination if configured, otherwise auto-route via --channel last\n if (notifyTo) {\n args.push(\"--to\", notifyTo);\n } else {\n args.push(\"--channel\", \"last\");\n }\n\n args.push(\"--message\", summaryPrompt(subdomain, testnet));\n\n execFileSync(\"openclaw\", args, {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(summaryName);\n } catch (err) {\n console.warn(`Could not create summary cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return {\n registered: created.length > 0,\n isOpenClaw: true,\n cronNames: created,\n };\n}\n\nexport function unregisterSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n): { removed: boolean; isOpenClaw: boolean } {\n if (!isOpenClaw()) {\n return { removed: false, isOpenClaw: false };\n }\n\n const names = [cronName(subdomain, testnet), summaryCronName(subdomain, testnet)];\n let removed = false;\n\n for (const name of names) {\n try {\n execFileSync(\"openclaw\", [\"cron\", \"remove\", \"--name\", name], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n removed = true;\n } catch {\n // Cron may not exist — that's fine\n }\n }\n\n return { removed, isOpenClaw: true };\n}\n\nexport function getSyndicateCronStatus(\n subdomain: string,\n testnet: boolean,\n): CronStatus {\n if (!isOpenClaw()) {\n return { isOpenClaw: false, crons: [] };\n }\n\n const prefix = cronName(subdomain, testnet);\n const all = listCronDetails();\n const matching = all.filter((c) => c.name.startsWith(prefix));\n\n return { isOpenClaw: true, crons: matching };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/cron.ts"],"sourcesContent":["/**\n * OpenClaw cron integration — auto-register participation crons for syndicate agents.\n *\n * When an agent creates or joins a syndicate, the CLI registers two cron jobs:\n * 1. Silent check (every 15m) — processes messages/events, responds autonomously\n * 2. Human summary (every 1h) — brief activity report delivered to the human's channel\n *\n * Non-OpenClaw agents skip silently — the caller prints guidance instead.\n */\n\nimport { execFileSync } from \"node:child_process\";\n\n// ── OpenClaw detection (cached per process) ──\n\nlet _isOpenClaw: boolean | null = null;\n\nexport function isOpenClaw(): boolean {\n if (_isOpenClaw !== null) return _isOpenClaw;\n try {\n execFileSync(\"openclaw\", [\"cron\", \"list\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n _isOpenClaw = true;\n } catch {\n _isOpenClaw = false;\n }\n return _isOpenClaw;\n}\n\n// ── Types ──\n\nexport interface CronResult {\n registered: boolean;\n isOpenClaw: boolean;\n cronNames: string[];\n}\n\nexport interface CronStatus {\n isOpenClaw: boolean;\n crons: { name: string; every: string; lastRun?: string }[];\n}\n\n// ── Cron naming ──\n\nfunction cronName(subdomain: string, testnet: boolean): string {\n return `sherwood-${subdomain}${testnet ? \"-testnet\" : \"\"}`;\n}\n\nfunction summaryCronName(subdomain: string, testnet: boolean): string {\n return `${cronName(subdomain, testnet)}-summary`;\n}\n\n// ── Prompts ──\n\nfunction silentPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n `You are a sherwood syndicate member. Your syndicate: ${subdomain}.sherwoodagent.eth`,\n \"\",\n `Step 1: Run \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"Step 2: Parse the JSON output for new messages and events\",\n \"Step 3: If new messages from OTHER agents, respond thoughtfully via:\",\n ` \\`${envPrefix}sherwood chat ${subdomain} send \"<response>\"${chainFlag}\\``,\n \"Step 4: If you responded to anything, summarize what you did (for your own session log).\",\n \" If nothing happened, reply HEARTBEAT_OK\",\n \"\",\n \"Rules:\",\n \"- Be a real syndicate member — discuss strategies, share opinions, ask questions\",\n \"- Keep responses concise and on-topic\",\n \"- Do NOT alert your human unless something requires their approval\",\n `- You can use \\`sherwood research\\` commands if you need data to back up your response`,\n ].join(\"\\n\");\n}\n\nfunction summaryPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n \"You are reporting syndicate activity to your human operator.\",\n \"\",\n `Run: \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"\",\n \"If there was activity (messages, events, proposals) since last check:\",\n \" Send a brief summary — who said what, any decisions made, any actions you took.\",\n \" Keep it to 3-5 lines max.\",\n \"\",\n \"If there was no activity:\",\n \" Reply HEARTBEAT_OK\",\n \"\",\n \"Only escalate (flag as urgent) if:\",\n \"- A proposal needs human sign-off\",\n \"- An agent left the syndicate\",\n \"- Risk alert or health factor warning\",\n \"- Human was directly asked for input\",\n ].join(\"\\n\");\n}\n\n// ── Helpers ──\n\n/** Parse `openclaw cron list --json` and return job names. */\nfunction listCronNames(): string[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string }[] = parsed.jobs || parsed || [];\n return jobs.map((j) => j.name);\n } catch {\n return [];\n }\n}\n\n/** Parse `openclaw cron list --json` with full details for status display. */\nfunction listCronDetails(): { name: string; every: string; lastRun?: string }[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string; every?: string; interval?: string; lastRun?: string }[] =\n parsed.jobs || parsed || [];\n return jobs.map((j) => ({\n name: j.name,\n every: j.every || j.interval || \"unknown\",\n lastRun: j.lastRun,\n }));\n } catch {\n return [];\n }\n}\n\n// ── Public API ──\n\nexport function registerSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n notifyTo?: string,\n): CronResult {\n if (!isOpenClaw()) {\n return { registered: false, isOpenClaw: false, cronNames: [] };\n }\n\n const checkName = cronName(subdomain, testnet);\n const summaryName = summaryCronName(subdomain, testnet);\n const existing = listCronNames();\n const created: string[] = [];\n\n // Cron 1: Silent participation check (every 15m)\n if (!existing.includes(checkName)) {\n try {\n execFileSync(\"openclaw\", [\n \"cron\", \"create\",\n \"--name\", checkName,\n \"--every\", \"15m\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"120\",\n \"--no-deliver\",\n \"--message\", silentPrompt(subdomain, testnet),\n ], {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(checkName);\n } catch (err) {\n console.warn(`Could not create silent cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Cron 2: Human summary (every 1h)\n if (!existing.includes(summaryName)) {\n try {\n const args = [\n \"cron\", \"create\",\n \"--name\", summaryName,\n \"--every\", \"1h\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"90\",\n \"--announce\",\n ];\n\n // Use explicit destination if configured, otherwise auto-route via --channel last\n if (notifyTo) {\n args.push(\"--to\", notifyTo);\n } else {\n args.push(\"--channel\", \"last\");\n }\n\n args.push(\"--message\", summaryPrompt(subdomain, testnet));\n\n execFileSync(\"openclaw\", args, {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(summaryName);\n } catch (err) {\n console.warn(`Could not create summary cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return {\n registered: created.length > 0,\n isOpenClaw: true,\n cronNames: created,\n };\n}\n\nexport function unregisterSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n): { removed: boolean; isOpenClaw: boolean } {\n if (!isOpenClaw()) {\n return { removed: false, isOpenClaw: false };\n }\n\n const names = [cronName(subdomain, testnet), summaryCronName(subdomain, testnet)];\n let removed = false;\n\n for (const name of names) {\n try {\n execFileSync(\"openclaw\", [\"cron\", \"remove\", \"--name\", name], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n removed = true;\n } catch {\n // Cron may not exist — that's fine\n }\n }\n\n return { removed, isOpenClaw: true };\n}\n\nexport function getSyndicateCronStatus(\n subdomain: string,\n testnet: boolean,\n): CronStatus {\n if (!isOpenClaw()) {\n return { isOpenClaw: false, crons: [] };\n }\n\n const prefix = cronName(subdomain, testnet);\n const all = listCronDetails();\n const matching = all.filter((c) => c.name.startsWith(prefix));\n\n return { isOpenClaw: true, crons: matching };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
queryApprovals,
|
|
7
7
|
queryJoinRequests,
|
|
8
8
|
revokeAttestation
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-2RYZU7EP.js";
|
|
10
|
+
import "./chunk-UBBR7QVJ.js";
|
|
11
|
+
import "./chunk-CGSXIYYZ.js";
|
|
12
|
+
import "./chunk-BGEVQQES.js";
|
|
13
|
+
import "./chunk-BCOTZTTH.js";
|
|
14
|
+
import "./chunk-4CV4JOE5.js";
|
|
14
15
|
export {
|
|
15
16
|
createApproval,
|
|
16
17
|
createJoinRequest,
|
|
@@ -20,4 +21,4 @@ export {
|
|
|
20
21
|
queryJoinRequests,
|
|
21
22
|
revokeAttestation
|
|
22
23
|
};
|
|
23
|
-
//# sourceMappingURL=eas-
|
|
24
|
+
//# sourceMappingURL=eas-7U7MX24T.js.map
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fetchMetadata,
|
|
4
4
|
uploadMetadata
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YSYX555I.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-
|
|
13
|
+
} from "./chunk-2RYZU7EP.js";
|
|
14
14
|
import {
|
|
15
15
|
approveDepositor,
|
|
16
16
|
deposit,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
resolveVaultSyndicate,
|
|
27
27
|
setTextRecord,
|
|
28
28
|
setVaultAddress
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-5NA345RJ.js";
|
|
30
30
|
import {
|
|
31
31
|
AGENT_REGISTRY,
|
|
32
32
|
EAS_SCHEMAS,
|
|
@@ -42,12 +42,12 @@ import {
|
|
|
42
42
|
UNISWAP_QUOTER_V2_ABI,
|
|
43
43
|
VENICE,
|
|
44
44
|
VENICE_STAKING_ABI
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-UBBR7QVJ.js";
|
|
46
46
|
import {
|
|
47
47
|
getAccount,
|
|
48
48
|
getPublicClient,
|
|
49
49
|
getWalletClient
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-CGSXIYYZ.js";
|
|
51
51
|
import {
|
|
52
52
|
VALID_NETWORKS,
|
|
53
53
|
getChain,
|
|
@@ -56,13 +56,14 @@ import {
|
|
|
56
56
|
getRpcUrl,
|
|
57
57
|
isTestnet,
|
|
58
58
|
setNetwork
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-BGEVQQES.js";
|
|
60
60
|
import {
|
|
61
61
|
cacheGroupId,
|
|
62
62
|
getAgentId,
|
|
63
63
|
getChainContracts,
|
|
64
64
|
getNotifyTo,
|
|
65
65
|
getVeniceApiKey,
|
|
66
|
+
init_config,
|
|
66
67
|
loadConfig,
|
|
67
68
|
setAgentId,
|
|
68
69
|
setChainContract,
|
|
@@ -70,12 +71,14 @@ import {
|
|
|
70
71
|
setNotifyTo,
|
|
71
72
|
setPrivateKey,
|
|
72
73
|
setVeniceApiKey
|
|
73
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-BCOTZTTH.js";
|
|
75
|
+
import "./chunk-4CV4JOE5.js";
|
|
74
76
|
|
|
75
77
|
// src/index.ts
|
|
76
78
|
import { config as loadDotenv } from "dotenv";
|
|
79
|
+
import { createRequire } from "module";
|
|
77
80
|
import { Command, Option } from "commander";
|
|
78
|
-
import { parseUnits as parseUnits8 } from "viem";
|
|
81
|
+
import { parseUnits as parseUnits8, isAddress as isAddress5 } from "viem";
|
|
79
82
|
import chalk7 from "chalk";
|
|
80
83
|
import ora7 from "ora";
|
|
81
84
|
import { input, confirm, select } from "@inquirer/prompts";
|
|
@@ -572,7 +575,8 @@ async function getActiveSyndicates() {
|
|
|
572
575
|
}
|
|
573
576
|
async function updateMetadata(syndicateId, metadataURI) {
|
|
574
577
|
const wallet = getWalletClient();
|
|
575
|
-
|
|
578
|
+
const client = getPublicClient();
|
|
579
|
+
const hash = await wallet.writeContract({
|
|
576
580
|
account: getAccount(),
|
|
577
581
|
chain: getChain(),
|
|
578
582
|
address: getFactoryAddress(),
|
|
@@ -580,6 +584,8 @@ async function updateMetadata(syndicateId, metadataURI) {
|
|
|
580
584
|
functionName: "updateMetadata",
|
|
581
585
|
args: [syndicateId, metadataURI]
|
|
582
586
|
});
|
|
587
|
+
await client.waitForTransactionReceipt({ hash });
|
|
588
|
+
return hash;
|
|
583
589
|
}
|
|
584
590
|
|
|
585
591
|
// src/lib/subgraph.ts
|
|
@@ -613,10 +619,27 @@ async function query(graphql, variables) {
|
|
|
613
619
|
return result.data;
|
|
614
620
|
}
|
|
615
621
|
async function getActiveSyndicates2(creator) {
|
|
616
|
-
|
|
622
|
+
if (creator) {
|
|
623
|
+
const data2 = await query(
|
|
624
|
+
`query($creator: String!) {
|
|
625
|
+
syndicates(where: { active: true, creator: $creator }, orderBy: createdAt, orderDirection: desc, first: 100) {
|
|
626
|
+
id
|
|
627
|
+
vault
|
|
628
|
+
creator
|
|
629
|
+
metadataURI
|
|
630
|
+
createdAt
|
|
631
|
+
active
|
|
632
|
+
totalDeposits
|
|
633
|
+
totalWithdrawals
|
|
634
|
+
}
|
|
635
|
+
}`,
|
|
636
|
+
{ creator: creator.toLowerCase() }
|
|
637
|
+
);
|
|
638
|
+
return data2.syndicates;
|
|
639
|
+
}
|
|
617
640
|
const data = await query(`
|
|
618
641
|
{
|
|
619
|
-
syndicates(
|
|
642
|
+
syndicates(where: { active: true }, orderBy: createdAt, orderDirection: desc, first: 100) {
|
|
620
643
|
id
|
|
621
644
|
vault
|
|
622
645
|
creator
|
|
@@ -841,6 +864,7 @@ function buildFundBatch(config, vaultAddress, agents, assetAddress, assetDecimal
|
|
|
841
864
|
}
|
|
842
865
|
|
|
843
866
|
// src/lib/venice.ts
|
|
867
|
+
init_config();
|
|
844
868
|
var VENICE_API_BASE = "https://api.venice.ai/api/v1";
|
|
845
869
|
async function provisionApiKey() {
|
|
846
870
|
const account = getAccount();
|
|
@@ -885,6 +909,7 @@ async function checkApiKeyValid() {
|
|
|
885
909
|
}
|
|
886
910
|
|
|
887
911
|
// src/commands/venice.ts
|
|
912
|
+
init_config();
|
|
888
913
|
var VALID_FEES2 = [500, 3e3, 1e4];
|
|
889
914
|
function registerVeniceCommands(program2) {
|
|
890
915
|
const venice = program2.command("venice").description("Venice private inference \u2014 stake VVV, provision API keys");
|
|
@@ -1463,6 +1488,7 @@ function registerAllowanceCommands(program2) {
|
|
|
1463
1488
|
import chalk4 from "chalk";
|
|
1464
1489
|
import ora4 from "ora";
|
|
1465
1490
|
import { SDK } from "agent0-sdk";
|
|
1491
|
+
init_config();
|
|
1466
1492
|
var IDENTITY_REGISTRY_ABI = [
|
|
1467
1493
|
{
|
|
1468
1494
|
name: "balanceOf",
|
|
@@ -1978,8 +2004,8 @@ function formatDurationLong(seconds) {
|
|
|
1978
2004
|
if (s >= 60) return `${(s / 60).toFixed(0)} min`;
|
|
1979
2005
|
return `${s}s`;
|
|
1980
2006
|
}
|
|
1981
|
-
function formatShares(raw) {
|
|
1982
|
-
const num = Number(raw) /
|
|
2007
|
+
function formatShares(raw, decimals = 6) {
|
|
2008
|
+
const num = Number(raw) / 10 ** decimals;
|
|
1983
2009
|
return num.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 2 });
|
|
1984
2010
|
}
|
|
1985
2011
|
function formatUSDC(raw) {
|
|
@@ -2401,7 +2427,7 @@ function registerGovernorCommands(program2) {
|
|
|
2401
2427
|
const spinner = ora6("Setting voting period...").start();
|
|
2402
2428
|
try {
|
|
2403
2429
|
const hash = await setVotingPeriod(parseBigIntArg(opts.seconds, "seconds"));
|
|
2404
|
-
spinner.succeed(G2(`Voting period
|
|
2430
|
+
spinner.succeed(G2(`Voting period change queued (${opts.seconds}s). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2405
2431
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2406
2432
|
} catch (err) {
|
|
2407
2433
|
spinner.fail("Failed to set voting period");
|
|
@@ -2413,7 +2439,7 @@ function registerGovernorCommands(program2) {
|
|
|
2413
2439
|
const spinner = ora6("Setting execution window...").start();
|
|
2414
2440
|
try {
|
|
2415
2441
|
const hash = await setExecutionWindow(parseBigIntArg(opts.seconds, "seconds"));
|
|
2416
|
-
spinner.succeed(G2(`Execution window
|
|
2442
|
+
spinner.succeed(G2(`Execution window change queued (${opts.seconds}s). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2417
2443
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2418
2444
|
} catch (err) {
|
|
2419
2445
|
spinner.fail("Failed to set execution window");
|
|
@@ -2425,7 +2451,7 @@ function registerGovernorCommands(program2) {
|
|
|
2425
2451
|
const spinner = ora6("Setting veto threshold...").start();
|
|
2426
2452
|
try {
|
|
2427
2453
|
const hash = await setVetoThresholdBps(parseBigIntArg(opts.bps, "bps"));
|
|
2428
|
-
spinner.succeed(G2(`Veto threshold
|
|
2454
|
+
spinner.succeed(G2(`Veto threshold change queued (${Number(opts.bps) / 100}%). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2429
2455
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2430
2456
|
} catch (err) {
|
|
2431
2457
|
spinner.fail("Failed to set veto threshold");
|
|
@@ -2437,7 +2463,7 @@ function registerGovernorCommands(program2) {
|
|
|
2437
2463
|
const spinner = ora6("Setting max fee...").start();
|
|
2438
2464
|
try {
|
|
2439
2465
|
const hash = await setMaxPerformanceFeeBps(parseBigIntArg(opts.bps, "bps"));
|
|
2440
|
-
spinner.succeed(G2(`Max performance fee
|
|
2466
|
+
spinner.succeed(G2(`Max performance fee change queued (${Number(opts.bps) / 100}%). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2441
2467
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2442
2468
|
} catch (err) {
|
|
2443
2469
|
spinner.fail("Failed to set max fee");
|
|
@@ -2449,7 +2475,7 @@ function registerGovernorCommands(program2) {
|
|
|
2449
2475
|
const spinner = ora6("Setting max duration...").start();
|
|
2450
2476
|
try {
|
|
2451
2477
|
const hash = await setMaxStrategyDuration(parseBigIntArg(opts.seconds, "seconds"));
|
|
2452
|
-
spinner.succeed(G2(`Max strategy duration
|
|
2478
|
+
spinner.succeed(G2(`Max strategy duration change queued (${opts.seconds}s). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2453
2479
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2454
2480
|
} catch (err) {
|
|
2455
2481
|
spinner.fail("Failed to set max duration");
|
|
@@ -2461,7 +2487,7 @@ function registerGovernorCommands(program2) {
|
|
|
2461
2487
|
const spinner = ora6("Setting cooldown...").start();
|
|
2462
2488
|
try {
|
|
2463
2489
|
const hash = await setCooldownPeriod(parseBigIntArg(opts.seconds, "seconds"));
|
|
2464
|
-
spinner.succeed(G2(`Cooldown period
|
|
2490
|
+
spinner.succeed(G2(`Cooldown period change queued (${opts.seconds}s). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2465
2491
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2466
2492
|
} catch (err) {
|
|
2467
2493
|
spinner.fail("Failed to set cooldown");
|
|
@@ -2473,7 +2499,7 @@ function registerGovernorCommands(program2) {
|
|
|
2473
2499
|
const spinner = ora6("Setting protocol fee...").start();
|
|
2474
2500
|
try {
|
|
2475
2501
|
const hash = await setProtocolFeeBps(parseBigIntArg(opts.bps, "bps"));
|
|
2476
|
-
spinner.succeed(G2(`Protocol fee
|
|
2502
|
+
spinner.succeed(G2(`Protocol fee change queued (${Number(opts.bps) / 100}%). Finalize after the timelock delay with \`sherwood governor finalize-param\`.`));
|
|
2477
2503
|
console.log(DIM2(` ${getExplorerUrl(hash)}`));
|
|
2478
2504
|
} catch (err) {
|
|
2479
2505
|
spinner.fail("Failed to set protocol fee");
|
|
@@ -2484,15 +2510,18 @@ function registerGovernorCommands(program2) {
|
|
|
2484
2510
|
}
|
|
2485
2511
|
|
|
2486
2512
|
// src/index.ts
|
|
2513
|
+
init_config();
|
|
2487
2514
|
try {
|
|
2488
2515
|
loadDotenv();
|
|
2489
2516
|
} catch {
|
|
2490
2517
|
}
|
|
2518
|
+
var require2 = createRequire(import.meta.url);
|
|
2519
|
+
var { version: CLI_VERSION } = require2("../package.json");
|
|
2491
2520
|
async function loadXmtp() {
|
|
2492
|
-
return import("./xmtp-
|
|
2521
|
+
return import("./xmtp-Y3LAZKOC.js");
|
|
2493
2522
|
}
|
|
2494
2523
|
async function loadCron() {
|
|
2495
|
-
return import("./cron-
|
|
2524
|
+
return import("./cron-IKBNUL3Q.js");
|
|
2496
2525
|
}
|
|
2497
2526
|
var G3 = chalk7.green;
|
|
2498
2527
|
var W3 = chalk7.white;
|
|
@@ -2500,18 +2529,26 @@ var DIM3 = chalk7.gray;
|
|
|
2500
2529
|
var BOLD3 = chalk7.white.bold;
|
|
2501
2530
|
var LABEL3 = chalk7.green.bold;
|
|
2502
2531
|
var SEP3 = () => console.log(DIM3("\u2500".repeat(60)));
|
|
2532
|
+
function validateAddress(value, name) {
|
|
2533
|
+
if (!isAddress5(value)) {
|
|
2534
|
+
console.error(chalk7.red(`Invalid ${name} address: ${value}`));
|
|
2535
|
+
process.exit(1);
|
|
2536
|
+
}
|
|
2537
|
+
return value;
|
|
2538
|
+
}
|
|
2503
2539
|
function resolveVault(opts) {
|
|
2504
2540
|
if (opts.vault) {
|
|
2505
|
-
setVaultAddress(opts.vault);
|
|
2541
|
+
setVaultAddress(validateAddress(opts.vault, "vault"));
|
|
2506
2542
|
}
|
|
2507
2543
|
}
|
|
2508
2544
|
var program = new Command();
|
|
2509
|
-
program.name("sherwood").description("CLI for agent-managed investment syndicates").version(
|
|
2545
|
+
program.name("sherwood").description("CLI for agent-managed investment syndicates").version(CLI_VERSION).addOption(
|
|
2510
2546
|
new Option("--chain <network>", "Target network").choices(VALID_NETWORKS).default("base")
|
|
2511
2547
|
).option("--testnet", "Alias for --chain base-sepolia (deprecated)", false).hook("preAction", (thisCommand) => {
|
|
2512
2548
|
const opts = thisCommand.optsWithGlobals();
|
|
2513
2549
|
let network = opts.chain;
|
|
2514
2550
|
if (opts.testnet) {
|
|
2551
|
+
process.env.ENABLE_TESTNET = "true";
|
|
2515
2552
|
if (network !== "base") {
|
|
2516
2553
|
console.warn(
|
|
2517
2554
|
chalk7.yellow("[warn] --testnet ignored, --chain takes precedence")
|
|
@@ -2826,7 +2863,8 @@ syndicate.command("approve-depositor").description("Approve an address to deposi
|
|
|
2826
2863
|
resolveVault(opts);
|
|
2827
2864
|
const spinner = ora7("Approving depositor...").start();
|
|
2828
2865
|
try {
|
|
2829
|
-
const
|
|
2866
|
+
const depositor = validateAddress(opts.depositor, "depositor");
|
|
2867
|
+
const hash = await approveDepositor(depositor);
|
|
2830
2868
|
spinner.succeed(`Depositor approved: ${hash}`);
|
|
2831
2869
|
console.log(chalk7.dim(` ${getExplorerUrl(hash)}`));
|
|
2832
2870
|
} catch (err) {
|
|
@@ -2839,7 +2877,8 @@ syndicate.command("remove-depositor").description("Remove an address from the de
|
|
|
2839
2877
|
resolveVault(opts);
|
|
2840
2878
|
const spinner = ora7("Removing depositor...").start();
|
|
2841
2879
|
try {
|
|
2842
|
-
const
|
|
2880
|
+
const depositor = validateAddress(opts.depositor, "depositor");
|
|
2881
|
+
const hash = await removeDepositor(depositor);
|
|
2843
2882
|
spinner.succeed(`Depositor removed: ${hash}`);
|
|
2844
2883
|
console.log(chalk7.dim(` ${getExplorerUrl(hash)}`));
|
|
2845
2884
|
} catch (err) {
|
|
@@ -2859,10 +2898,11 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
|
|
|
2859
2898
|
spinner.fail("Only the syndicate creator can add agents");
|
|
2860
2899
|
process.exit(1);
|
|
2861
2900
|
}
|
|
2901
|
+
const agentWallet = validateAddress(opts.wallet, "wallet");
|
|
2862
2902
|
spinner.text = "Registering agent...";
|
|
2863
2903
|
const hash = await registerAgent(
|
|
2864
2904
|
BigInt(opts.agentId),
|
|
2865
|
-
|
|
2905
|
+
agentWallet
|
|
2866
2906
|
);
|
|
2867
2907
|
spinner.succeed(`Agent registered: ${hash}`);
|
|
2868
2908
|
console.log(chalk7.dim(` ${getExplorerUrl(hash)}`));
|
|
@@ -3054,6 +3094,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
3054
3094
|
resolveVault(opts);
|
|
3055
3095
|
}
|
|
3056
3096
|
const vaultAddress = getVaultAddress();
|
|
3097
|
+
const agentWallet = validateAddress(opts.wallet, "wallet");
|
|
3057
3098
|
const { creator, subdomain, id: syndicateId } = await resolveVaultSyndicate(vaultAddress);
|
|
3058
3099
|
const callerAddress = getAccount().address.toLowerCase();
|
|
3059
3100
|
if (creator.toLowerCase() !== callerAddress) {
|
|
@@ -3065,7 +3106,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
3065
3106
|
try {
|
|
3066
3107
|
const regHash = await registerAgent(
|
|
3067
3108
|
BigInt(opts.agentId),
|
|
3068
|
-
|
|
3109
|
+
agentWallet
|
|
3069
3110
|
);
|
|
3070
3111
|
agentWasRegistered = true;
|
|
3071
3112
|
console.log(DIM3(` Agent registered: ${getExplorerUrl(regHash)}`));
|
|
@@ -3095,7 +3136,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
3095
3136
|
syndicateId,
|
|
3096
3137
|
BigInt(opts.agentId),
|
|
3097
3138
|
vaultAddress,
|
|
3098
|
-
|
|
3139
|
+
agentWallet
|
|
3099
3140
|
);
|
|
3100
3141
|
approvalUid = result.uid;
|
|
3101
3142
|
}
|
|
@@ -3278,7 +3319,7 @@ strategy.command("run").description("Execute the levered swap strategy").option(
|
|
|
3278
3319
|
await runLeveredSwap(opts);
|
|
3279
3320
|
});
|
|
3280
3321
|
program.command("providers").description("List available DeFi providers").action(async () => {
|
|
3281
|
-
const { MessariProvider, NansenProvider } = await import("./research-
|
|
3322
|
+
const { MessariProvider, NansenProvider } = await import("./research-7RI7VFPK.js");
|
|
3282
3323
|
const providers = [new MoonwellProvider(), new UniswapProvider(), new MessariProvider(), new NansenProvider()];
|
|
3283
3324
|
for (const p of providers) {
|
|
3284
3325
|
const info = p.info();
|
|
@@ -3289,7 +3330,7 @@ ${info.name} (${info.type})`);
|
|
|
3289
3330
|
}
|
|
3290
3331
|
});
|
|
3291
3332
|
try {
|
|
3292
|
-
const { registerChatCommands } = await import("./chat-
|
|
3333
|
+
const { registerChatCommands } = await import("./chat-X3IKMSNS.js");
|
|
3293
3334
|
registerChatCommands(program);
|
|
3294
3335
|
} catch {
|
|
3295
3336
|
program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
|
|
@@ -3299,14 +3340,14 @@ try {
|
|
|
3299
3340
|
process.exit(1);
|
|
3300
3341
|
});
|
|
3301
3342
|
}
|
|
3302
|
-
var { registerSessionCommands } = await import("./session-
|
|
3343
|
+
var { registerSessionCommands } = await import("./session-2VK25CSW.js");
|
|
3303
3344
|
registerSessionCommands(program);
|
|
3304
3345
|
registerVeniceCommands(program);
|
|
3305
3346
|
registerAllowanceCommands(program);
|
|
3306
3347
|
registerIdentityCommands(program);
|
|
3307
3348
|
registerProposalCommands(program);
|
|
3308
3349
|
registerGovernorCommands(program);
|
|
3309
|
-
var { registerResearchCommands } = await import("./research-
|
|
3350
|
+
var { registerResearchCommands } = await import("./research-ZDTM73C7.js");
|
|
3310
3351
|
registerResearchCommands(program);
|
|
3311
3352
|
var configCmd = program.command("config");
|
|
3312
3353
|
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) => {
|