@sage-protocol/cli 0.3.10 → 0.4.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 (36) hide show
  1. package/dist/cli/browser-wallet-integration.js +0 -1
  2. package/dist/cli/cast-wallet-manager.js +0 -1
  3. package/dist/cli/commands/interview.js +149 -0
  4. package/dist/cli/commands/personal.js +234 -89
  5. package/dist/cli/commands/stake-status.js +0 -2
  6. package/dist/cli/config.js +28 -8
  7. package/dist/cli/governance-manager.js +28 -19
  8. package/dist/cli/index.js +32 -8
  9. package/dist/cli/library-manager.js +16 -6
  10. package/dist/cli/mcp-server-stdio.js +549 -0
  11. package/dist/cli/mcp-server.js +4 -30
  12. package/dist/cli/mcp-setup.md +35 -34
  13. package/dist/cli/metamask-integration.js +0 -1
  14. package/dist/cli/privy-wallet-manager.js +2 -2
  15. package/dist/cli/prompt-manager.js +0 -1
  16. package/dist/cli/services/doctor/fixers.js +1 -1
  17. package/dist/cli/services/mcp/env-loader.js +2 -0
  18. package/dist/cli/services/mcp/quick-start.js +14 -15
  19. package/dist/cli/services/mcp/sage-tool-registry.js +330 -0
  20. package/dist/cli/services/mcp/tool-args-validator.js +31 -0
  21. package/dist/cli/services/metaprompt/anthropic-client.js +87 -0
  22. package/dist/cli/services/metaprompt/interview-driver.js +161 -0
  23. package/dist/cli/services/metaprompt/model-client.js +49 -0
  24. package/dist/cli/services/metaprompt/openai-client.js +67 -0
  25. package/dist/cli/services/metaprompt/persistence.js +86 -0
  26. package/dist/cli/services/metaprompt/prompt-builder.js +186 -0
  27. package/dist/cli/services/metaprompt/session.js +18 -80
  28. package/dist/cli/services/metaprompt/slot-planner.js +115 -0
  29. package/dist/cli/services/metaprompt/templates.json +130 -0
  30. package/dist/cli/subdao.js +0 -3
  31. package/dist/cli/sxxx-manager.js +0 -1
  32. package/dist/cli/utils/tx-wait.js +0 -3
  33. package/dist/cli/wallet-manager.js +18 -19
  34. package/dist/cli/walletconnect-integration.js +0 -1
  35. package/dist/cli/wizard-manager.js +0 -1
  36. package/package.json +3 -1
@@ -1,6 +1,5 @@
1
1
  const { ethers } = require('ethers');
2
2
  const { resolveArtifact } = require('./utils/artifacts');
3
- try { require('dotenv').config({ quiet: true }); } catch (_) {}
4
3
  let colors; try { colors = (require('chalk').default || require('chalk')); } catch (e) { colors = { blue: (s)=>s, green: (s)=>s, red: (s)=>s, yellow: (s)=>s, cyan: (s)=>s }; }
5
4
  const fs = require('fs');
6
5
  const path = require('path');
@@ -1284,6 +1283,8 @@ class GovernanceManager {
1284
1283
  }
1285
1284
 
1286
1285
  async executeProposal(id, opts = {}) {
1286
+ const verbose = process.env.SAGE_VERBOSE === '1';
1287
+ const quietJson = String(process.env.SAGE_QUIET_JSON || '').trim() === '1';
1287
1288
  try {
1288
1289
  const { simulate } = opts;
1289
1290
  if (simulate) {
@@ -1352,19 +1353,23 @@ class GovernanceManager {
1352
1353
  throw new Error('Cached tuple has mismatched array lengths');
1353
1354
  }
1354
1355
  const descriptionHash = ethers.keccak256(ethers.toUtf8Bytes(description));
1355
- console.log('🔎 Using cached proposal tuple for execute');
1356
- console.log(' targets:', targets);
1357
- console.log(' values:', values.map(v => v.toString()));
1358
- console.log(' calldatas:', calldatas);
1359
- console.log(' descriptionHash:', descriptionHash);
1356
+ if (!quietJson) {
1357
+ console.log('🔎 Using cached proposal tuple for execute');
1358
+ if (verbose) {
1359
+ console.log(' targets:', targets);
1360
+ console.log(' values:', values.map(v => v.toString()));
1361
+ console.log(' calldatas:', calldatas);
1362
+ console.log(' descriptionHash:', descriptionHash);
1363
+ }
1364
+ }
1360
1365
  // Optional: verify readiness
1361
1366
  try {
1362
1367
  const st = await this.governor.state(this.normalizeProposalId(proposalId));
1363
1368
  const nm = this.getStateName(st);
1364
1369
  let eta = 0n;
1365
1370
  try { eta = await this.governor.proposalEta(this.normalizeProposalId(proposalId)); } catch {}
1366
- if (eta && eta > 0n) console.log(`🔍 Debug: ETA=${eta.toString()}`);
1367
- console.log(`🔍 Debug: Proposal state: ${nm} (${st})`);
1371
+ if (verbose && !quietJson && eta && eta > 0n) console.log(`🔍 Debug: ETA=${eta.toString()}`);
1372
+ if (verbose && !quietJson) console.log(`🔍 Debug: Proposal state: ${nm} (${st})`);
1368
1373
  } catch {}
1369
1374
 
1370
1375
  if (simulate) {
@@ -1447,7 +1452,9 @@ class GovernanceManager {
1447
1452
 
1448
1453
  // Fallback: if no indexed events found, try broader query
1449
1454
  if (!logs.length) {
1450
- console.log('Debug - No indexed events found, trying all ProposalCreated events...');
1455
+ if (verbose && !quietJson) {
1456
+ console.log('Debug - No indexed events found, trying all ProposalCreated events...');
1457
+ }
1451
1458
  const allLogs = await this.provider.getLogs({
1452
1459
  topics: [eventSig],
1453
1460
  address: governorAddr,
@@ -1508,26 +1515,28 @@ class GovernanceManager {
1508
1515
  // Compute descriptionHash exactly like the working script
1509
1516
  const descriptionHash = ethers.keccak256(ethers.toUtf8Bytes(description));
1510
1517
 
1511
- console.log('Governor:', governorAddr);
1512
- console.log('Executing with:');
1513
- console.log(' targets:', targets);
1514
- console.log(' values:', values.map(v => v.toString()));
1515
- console.log(' calldatas[0..]:', calldatas.length);
1516
- console.log(' descriptionHash:', descriptionHash);
1518
+ if (verbose && !quietJson) {
1519
+ console.log('Governor:', governorAddr);
1520
+ console.log('Executing with:');
1521
+ console.log(' targets:', targets);
1522
+ console.log(' values:', values.map(v => v.toString()));
1523
+ console.log(' calldatas[0..]:', calldatas.length);
1524
+ console.log(' descriptionHash:', descriptionHash);
1525
+ }
1517
1526
 
1518
1527
  // Check proposal state before executing
1519
- console.log('🔍 Debug: Checking proposal state...');
1528
+ if (verbose && !quietJson) console.log('🔍 Debug: Checking proposal state...');
1520
1529
  const state = await this.governor.state(this.normalizeProposalId(id));
1521
1530
  const stateNum = Number(state);
1522
1531
  const stateName = this.getStateName(stateNum);
1523
- console.log(`🔍 Debug: Proposal state: ${stateName} (${stateNum})`);
1532
+ if (verbose && !quietJson) console.log(`🔍 Debug: Proposal state: ${stateName} (${stateNum})`);
1524
1533
 
1525
1534
  if (stateNum !== 4) { // 4 = Succeeded
1526
1535
  console.log(`⚠️ Warning: Proposal is in state ${stateName}, not Succeeded. Execution may fail.`);
1527
1536
  }
1528
1537
 
1529
1538
  // Execute using tuple (like the working script)
1530
- console.log('🔍 Debug: Executing proposal...');
1539
+ if (verbose && !quietJson) console.log('🔍 Debug: Executing proposal...');
1531
1540
  try {
1532
1541
  const tx = await this.governor.execute(targets, values, calldatas, descriptionHash);
1533
1542
  console.log('⏳ Waiting for transaction confirmation...');
@@ -1559,7 +1568,7 @@ class GovernanceManager {
1559
1568
 
1560
1569
  // Check for LibraryUpdated events if this was a library proposal
1561
1570
  if (this.currentSubDAO) {
1562
- console.log('🔍 Debug: Checking for LibraryUpdated events...');
1571
+ if (verbose && !quietJson) console.log('🔍 Debug: Checking for LibraryUpdated events...');
1563
1572
  try {
1564
1573
  const { resolveRegistryAddress } = require('./utils/address-resolution');
1565
1574
  const registryAddress = resolveRegistryAddress().registry;
package/dist/cli/index.js CHANGED
@@ -1,7 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // Filter out deprecated Lit SDK warning immediately
4
+ const realStderrWrite = process.stderr.write.bind(process.stderr);
5
+ process.stderr.write = (chunk, encoding, callback) => {
6
+ if (chunk && chunk.toString().includes('LitErrorKind is deprecated')) {
7
+ if (typeof callback === 'function') callback();
8
+ return true;
9
+ }
10
+ return realStderrWrite(chunk, encoding, callback);
11
+ };
12
+
3
13
  const path = require('path');
4
14
  const { Command } = require('commander');
15
+
16
+ // Pre-detect JSON mode so setup logs don't pollute machine-readable output
17
+ if (process.argv.includes('--json')) {
18
+ process.env.SAGE_QUIET_JSON = process.env.SAGE_QUIET_JSON || '1';
19
+ }
20
+
5
21
  // Prefer shared config manager via workspace package; fallback to local if unavailable
6
22
  let config;
7
23
  try {
@@ -67,7 +83,6 @@ if (isVerbose) process.env.SAGE_VERBOSE = '1';
67
83
  // Global session/save-context
68
84
  if (process.argv.includes('--session')) process.env.SAGE_SESSION = '1';
69
85
  if (process.argv.includes('--save-context')) process.env.SAGE_SAVE_CONTEXT = '1';
70
- if (process.argv.includes('--verbose')) process.env.SAGE_VERBOSE = '1';
71
86
  if (process.argv.includes('--force')) process.env.SAGE_FORCE = '1';
72
87
  if (process.argv.includes('--private')) process.env.SAGE_USE_PRIVATE_TX = '1';
73
88
 
@@ -86,7 +101,7 @@ program
86
101
 
87
102
  // Reordered to highlight consolidated namespaces ('prompts' and 'gov')
88
103
  const commandGroups = [
89
- { title: 'Content (new)', modules: ['prompts', 'project', 'prompt', 'personal', 'creator', 'contributor', 'bounty'] },
104
+ { title: 'Content (new)', modules: ['prompts', 'project', 'prompt', 'personal', 'interview', 'creator', 'contributor', 'bounty'] },
90
105
  { title: 'Governance (new)', modules: ['proposals', 'governance', 'dao', 'timelock', 'roles', 'members', 'gov-config', 'stake-status'] },
91
106
  { title: 'Treasury', modules: ['treasury', 'safe', 'boost'] },
92
107
  { title: 'Ops & Utilities', modules: ['config', 'wallet', 'sxxx', 'ipfs', 'ipns', 'context', 'doctor', 'factory', 'upgrade', 'resolve', 'dry-run-queue', 'mcp', 'start', 'wizard', 'init', 'dao-config', 'pin', 'council', 'sbt', 'completion', 'help', 'hook'] },
@@ -147,7 +162,8 @@ const additionalModules = [
147
162
  'start',
148
163
  'completion',
149
164
  'help',
150
- 'hook'
165
+ 'hook',
166
+ 'interview'
151
167
  ];
152
168
  additionalModules.forEach((mod) => moduleSet.add(mod));
153
169
 
@@ -171,12 +187,19 @@ program.configureOutput({
171
187
  }
172
188
  });
173
189
 
174
- const originalStderrWrite = process.stderr.write.bind(process.stderr);
175
- aliasSupport.setStderrWriter(originalStderrWrite);
190
+ // Alias support wrapper
191
+ const currentStderrWrite = process.stderr.write.bind(process.stderr);
192
+ aliasSupport.setStderrWriter(currentStderrWrite);
176
193
  process.stderr.write = (chunk, encoding, callback) => {
194
+ // Check filter again just in case aliasSupport bypassed it (unlikely if chained correctly)
195
+ if (chunk && chunk.toString().includes('LitErrorKind is deprecated')) {
196
+ if (typeof callback === 'function') callback();
197
+ return true;
198
+ }
199
+
177
200
  const handled = aliasSupport.handleOutputError(chunk);
178
201
  if (!handled) {
179
- return originalStderrWrite(chunk, encoding, callback);
202
+ return currentStderrWrite(chunk, encoding, callback);
180
203
  }
181
204
  if (typeof callback === 'function') callback();
182
205
  return true;
@@ -194,8 +217,9 @@ program.parse(normalizedArgv);
194
217
 
195
218
  // Handle clean exit
196
219
  process.on('exit', () => {
197
- process.stderr.write = originalStderrWrite;
198
- aliasSupport.setStderrWriter(originalStderrWrite);
220
+ // Restore original writer on exit
221
+ process.stderr.write = realStderrWrite;
222
+ aliasSupport.setStderrWriter(realStderrWrite);
199
223
  if (global.walletManager) {
200
224
  global.walletManager.disconnect().catch(() => { });
201
225
  }
@@ -2,7 +2,6 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const axios = require('axios');
4
4
  const { resolveArtifact } = require('./utils/artifacts');
5
- try { require('dotenv').config({ quiet: true }); } catch (_) {}
6
5
  const { ethers } = require('ethers');
7
6
  const WalletManager = require('./wallet-manager');
8
7
  const cliConfig = require('./config');
@@ -63,6 +62,17 @@ class LibraryManager {
63
62
  return ensureLibrariesDir({ config: cliConfig });
64
63
  }
65
64
 
65
+ getManifestPath(cid) {
66
+ const dir = this.ensureLibrariesDir();
67
+ return path.join(dir, `${cid}.json`);
68
+ }
69
+
70
+ writeManifest(cid, manifest) {
71
+ const manifestPath = this.getManifestPath(cid);
72
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
73
+ return manifestPath;
74
+ }
75
+
66
76
  listPinned() {
67
77
  return listPinnedManifests({ config: cliConfig });
68
78
  }
@@ -105,8 +115,7 @@ class LibraryManager {
105
115
  prompts: [],
106
116
  };
107
117
 
108
- const manifestPath = path.join(dir, `${cid}.json`);
109
- fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
118
+ const manifestPath = this.writeManifest(cid, manifest);
110
119
 
111
120
  return { cid, path: manifestPath, manifest };
112
121
  }
@@ -152,8 +161,7 @@ class LibraryManager {
152
161
  manifest.prompts = [];
153
162
  }
154
163
 
155
- const manifestPath = path.join(dir, `${cid}.json`);
156
- fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
164
+ const manifestPath = this.writeManifest(cid, manifest);
157
165
 
158
166
  return { cid, path: manifestPath };
159
167
  }
@@ -707,7 +715,9 @@ class LibraryManager {
707
715
 
708
716
  // Resolve governor and contract
709
717
  const gov = await this.getGovernorAddress();
710
- console.log(`🔍 Debug: Executing proposal ${proposalId} on governor ${gov}`);
718
+ if (process.env.SAGE_VERBOSE === '1' && String(process.env.SAGE_QUIET_JSON || '').trim() !== '1') {
719
+ console.log(`🔍 Debug: Executing proposal ${proposalId} on governor ${gov}`);
720
+ }
711
721
  const GovABI = resolveArtifact('contracts/cloneable/PromptGovernorCloneable.sol/PromptGovernorCloneable.json').abi;
712
722
  const governorConnector = createGovernorConnector({ ethersLib: ethers });
713
723
  const governor = governorConnector.connect({ address: gov, abi: GovABI, signerOrProvider: signer });