@t2000/cli 0.10.4 → 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.
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-D4HDZEJT.js";
2
3
 
3
4
  // src/program.ts
4
5
  import { Command } from "commander";
@@ -790,8 +791,10 @@ function registerFundStatus(program2) {
790
791
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
791
792
  import { join } from "path";
792
793
  import { homedir as homedir3 } from "os";
794
+ import { SafeguardEnforcer } from "@t2000/sdk";
793
795
  var CONFIG_DIR = join(homedir3(), ".t2000");
794
796
  var CONFIG_PATH = join(CONFIG_DIR, "config.json");
797
+ var SAFEGUARD_KEYS = /* @__PURE__ */ new Set(["locked", "maxPerTx", "maxDailySend", "dailyUsed", "dailyResetDate", "alertThreshold"]);
795
798
  function loadConfig() {
796
799
  try {
797
800
  return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
@@ -805,8 +808,35 @@ function saveConfig(config) {
805
808
  }
806
809
  writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
807
810
  }
811
+ function formatUsd11(amount) {
812
+ return `$${amount.toFixed(2)}`;
813
+ }
808
814
  function registerConfig(program2) {
809
815
  const configCmd = program2.command("config").description("Show or set configuration");
816
+ configCmd.command("show").description("Show safeguard settings").action(() => {
817
+ try {
818
+ const enforcer = new SafeguardEnforcer(CONFIG_DIR);
819
+ enforcer.load();
820
+ const config = enforcer.getConfig();
821
+ if (isJsonMode()) {
822
+ printJson({
823
+ locked: config.locked,
824
+ maxPerTx: config.maxPerTx,
825
+ maxDailySend: config.maxDailySend,
826
+ dailyUsed: config.dailyUsed
827
+ });
828
+ return;
829
+ }
830
+ printHeader("Agent Safeguards");
831
+ printDivider();
832
+ printKeyValue("Locked", config.locked ? "Yes" : "No");
833
+ printKeyValue("Per-transaction", config.maxPerTx > 0 ? formatUsd11(config.maxPerTx) : "Unlimited");
834
+ printKeyValue("Daily send limit", config.maxDailySend > 0 ? `${formatUsd11(config.maxDailySend)} (${formatUsd11(config.dailyUsed)} used today)` : "Unlimited");
835
+ printBlank();
836
+ } catch (error) {
837
+ handleError(error);
838
+ }
839
+ });
810
840
  configCmd.command("get").argument("[key]", "Config key to get (omit for all)").action((key) => {
811
841
  try {
812
842
  const config = loadConfig();
@@ -833,6 +863,23 @@ function registerConfig(program2) {
833
863
  });
834
864
  configCmd.command("set").argument("<key>", "Config key").argument("<value>", "Config value").action((key, value) => {
835
865
  try {
866
+ if (SAFEGUARD_KEYS.has(key)) {
867
+ const enforcer = new SafeguardEnforcer(CONFIG_DIR);
868
+ enforcer.load();
869
+ let parsed2 = value;
870
+ if (value === "true") parsed2 = true;
871
+ else if (value === "false") parsed2 = false;
872
+ else if (!isNaN(Number(value)) && value.trim() !== "") parsed2 = Number(value);
873
+ enforcer.set(key, parsed2);
874
+ if (isJsonMode()) {
875
+ printJson({ [key]: parsed2 });
876
+ return;
877
+ }
878
+ printBlank();
879
+ printSuccess(`Set ${key} = ${String(parsed2)}`);
880
+ printBlank();
881
+ return;
882
+ }
836
883
  const config = loadConfig();
837
884
  let parsed = value;
838
885
  if (value === "true") parsed = true;
@@ -1189,6 +1236,7 @@ function registerPay(program2) {
1189
1236
  try {
1190
1237
  const pin = await resolvePin();
1191
1238
  const agent = await T200019.create({ pin, keyPath: opts.key });
1239
+ agent.enforcer.check({ operation: "pay", amount: parseFloat(opts.maxPrice) });
1192
1240
  const wallet = createX402Wallet(agent);
1193
1241
  const client = new x402Client(wallet);
1194
1242
  const startTime = Date.now();
@@ -1246,12 +1294,53 @@ function collectHeaders(value, previous) {
1246
1294
  }
1247
1295
 
1248
1296
  // src/commands/lock.ts
1297
+ import { join as join3 } from "path";
1298
+ import { homedir as homedir5 } from "os";
1299
+ import { SafeguardEnforcer as SafeguardEnforcer2 } from "@t2000/sdk";
1300
+ var CONFIG_DIR3 = join3(homedir5(), ".t2000");
1249
1301
  function registerLock(program2) {
1250
- program2.command("lock").description("Clear saved session (require PIN on next command)").action(async () => {
1302
+ program2.command("lock").description("Lock agent \u2014 freeze all operations").action(async () => {
1251
1303
  try {
1304
+ const enforcer = new SafeguardEnforcer2(CONFIG_DIR3);
1305
+ enforcer.load();
1306
+ enforcer.lock();
1252
1307
  await clearSession();
1308
+ if (isJsonMode()) {
1309
+ printJson({ locked: true });
1310
+ return;
1311
+ }
1312
+ printBlank();
1313
+ printSuccess("Agent locked. All operations frozen.");
1314
+ printInfo("Run: t2000 unlock (requires PIN)");
1315
+ printBlank();
1316
+ } catch (error) {
1317
+ handleError(error);
1318
+ }
1319
+ });
1320
+ program2.command("unlock").description("Unlock agent \u2014 resume operations").action(async () => {
1321
+ try {
1322
+ const pin = await resolvePin();
1323
+ if (!pin) {
1324
+ throw new Error("PIN required to unlock agent");
1325
+ }
1326
+ const { T2000: T200024 } = await import("@t2000/sdk");
1327
+ await T200024.create({ pin });
1328
+ const enforcer = new SafeguardEnforcer2(CONFIG_DIR3);
1329
+ enforcer.load();
1330
+ enforcer.unlock();
1331
+ if (isJsonMode()) {
1332
+ printJson({ locked: false });
1333
+ return;
1334
+ }
1335
+ const config = enforcer.getConfig();
1253
1336
  printBlank();
1254
- printSuccess("Session cleared \u2014 PIN required on next command");
1337
+ printSuccess("Agent unlocked. Operations resumed.");
1338
+ if (config.maxPerTx > 0 || config.maxDailySend > 0) {
1339
+ const limits = [];
1340
+ if (config.maxPerTx > 0) limits.push(`maxPerTx=$${config.maxPerTx}`);
1341
+ if (config.maxDailySend > 0) limits.push(`maxDailySend=$${config.maxDailySend}`);
1342
+ printInfo(`Active safeguards: ${limits.join(", ")}`);
1343
+ }
1255
1344
  printBlank();
1256
1345
  } catch (error) {
1257
1346
  handleError(error);
@@ -1379,7 +1468,7 @@ function registerSentinel(program2) {
1379
1468
  }
1380
1469
 
1381
1470
  // src/commands/earn.ts
1382
- import { T2000 as T200021, MIST_PER_SUI as MIST_PER_SUI2, listSentinels, formatUsd as formatUsd11 } from "@t2000/sdk";
1471
+ import { T2000 as T200021, MIST_PER_SUI as MIST_PER_SUI2, listSentinels, formatUsd as formatUsd12 } from "@t2000/sdk";
1383
1472
  import pc11 from "picocolors";
1384
1473
  function mistToSui(mist) {
1385
1474
  return Number(mist) / Number(MIST_PER_SUI2);
@@ -1439,16 +1528,16 @@ function registerEarn(program2) {
1439
1528
  if (savePositions.length > 0) {
1440
1529
  for (const pos of savePositions) {
1441
1530
  const dailyYield = pos.amount * pos.apy / 100 / 365;
1442
- printKeyValue(pos.protocol, `${formatUsd11(pos.amount)} ${pos.asset} @ ${pos.apy.toFixed(2)}% APY`);
1531
+ printKeyValue(pos.protocol, `${formatUsd12(pos.amount)} ${pos.asset} @ ${pos.apy.toFixed(2)}% APY`);
1443
1532
  if (dailyYield > 1e-4) {
1444
- const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd11(dailyYield);
1445
- const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd11(dailyYield * 30);
1533
+ const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd12(dailyYield);
1534
+ const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd12(dailyYield * 30);
1446
1535
  printLine(pc11.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
1447
1536
  }
1448
1537
  }
1449
1538
  if (savePositions.length > 1) {
1450
1539
  printBlank();
1451
- printKeyValue("Total Saved", formatUsd11(totalSaved));
1540
+ printKeyValue("Total Saved", formatUsd12(totalSaved));
1452
1541
  }
1453
1542
  } else if (posData) {
1454
1543
  printInfo("No savings yet \u2014 run `t2000 save <amount>` to start earning yield");
@@ -1489,7 +1578,7 @@ function registerEarn(program2) {
1489
1578
 
1490
1579
  // src/commands/rebalance.ts
1491
1580
  import pc12 from "picocolors";
1492
- import { T2000 as T200022, formatUsd as formatUsd12, SUPPORTED_ASSETS as SUPPORTED_ASSETS2 } from "@t2000/sdk";
1581
+ import { T2000 as T200022, formatUsd as formatUsd13, SUPPORTED_ASSETS as SUPPORTED_ASSETS2 } from "@t2000/sdk";
1493
1582
  function registerRebalance(program2) {
1494
1583
  program2.command("rebalance").description("Optimize yield \u2014 move savings to the best rate across protocols and stablecoins").option("--key <path>", "Key file path").option("--dry-run", "Show what would happen without executing").option("--min-diff <pct>", "Minimum APY difference to trigger (default: 0.5)", "0.5").option("--max-break-even <days>", "Max break-even days for cross-asset moves (default: 30)", "30").action(async (opts) => {
1495
1584
  try {
@@ -1531,14 +1620,14 @@ function registerRebalance(program2) {
1531
1620
  printDivider();
1532
1621
  printKeyValue("From", `${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}% APY)`);
1533
1622
  printKeyValue("To", `${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}% APY)`);
1534
- printKeyValue("Amount", formatUsd12(plan.amount));
1623
+ printKeyValue("Amount", formatUsd13(plan.amount));
1535
1624
  printBlank();
1536
1625
  printLine(pc12.bold("Economics"));
1537
1626
  printDivider();
1538
1627
  printKeyValue("APY Gain", `+${(plan.newApy - plan.currentApy).toFixed(2)}%`);
1539
- printKeyValue("Annual Gain", `${formatUsd12(plan.annualGain)}/year`);
1628
+ printKeyValue("Annual Gain", `${formatUsd13(plan.annualGain)}/year`);
1540
1629
  if (plan.estimatedSwapCost > 0) {
1541
- printKeyValue("Swap Cost", `~${formatUsd12(plan.estimatedSwapCost)}`);
1630
+ printKeyValue("Swap Cost", `~${formatUsd13(plan.estimatedSwapCost)}`);
1542
1631
  printKeyValue("Break-even", `${plan.breakEvenDays} days`);
1543
1632
  }
1544
1633
  printBlank();
@@ -1549,11 +1638,11 @@ function registerRebalance(program2) {
1549
1638
  const step = plan.steps[i];
1550
1639
  const num = `${i + 1}.`;
1551
1640
  if (step.action === "withdraw") {
1552
- printLine(` ${num} Withdraw ${formatUsd12(step.amount)} ${displayAsset(step.fromAsset ?? "")} from ${step.protocol}`);
1641
+ printLine(` ${num} Withdraw ${formatUsd13(step.amount)} ${displayAsset(step.fromAsset ?? "")} from ${step.protocol}`);
1553
1642
  } else if (step.action === "swap") {
1554
- printLine(` ${num} Swap ${displayAsset(step.fromAsset ?? "")} \u2192 ${displayAsset(step.toAsset ?? "")} (~${formatUsd12(step.estimatedOutput ?? 0)})`);
1643
+ printLine(` ${num} Swap ${displayAsset(step.fromAsset ?? "")} \u2192 ${displayAsset(step.toAsset ?? "")} (~${formatUsd13(step.estimatedOutput ?? 0)})`);
1555
1644
  } else if (step.action === "deposit") {
1556
- printLine(` ${num} Deposit ${formatUsd12(step.amount)} ${displayAsset(step.toAsset ?? "")} into ${step.protocol}`);
1645
+ printLine(` ${num} Deposit ${formatUsd13(step.amount)} ${displayAsset(step.toAsset ?? "")} into ${step.protocol}`);
1557
1646
  }
1558
1647
  }
1559
1648
  printBlank();
@@ -1566,7 +1655,7 @@ function registerRebalance(program2) {
1566
1655
  }
1567
1656
  const result = await agent.rebalance({ dryRun: false, minYieldDiff, maxBreakEven });
1568
1657
  if (result.executed) {
1569
- printSuccess(`Rebalanced ${formatUsd12(result.amount)} \u2192 ${result.newApy.toFixed(2)}% APY`);
1658
+ printSuccess(`Rebalanced ${formatUsd13(result.amount)} \u2192 ${result.newApy.toFixed(2)}% APY`);
1570
1659
  for (const digest of result.txDigests) {
1571
1660
  printKeyValue("Tx", explorerUrl(digest));
1572
1661
  }
@@ -1583,7 +1672,7 @@ function displayAsset(asset) {
1583
1672
  }
1584
1673
 
1585
1674
  // src/commands/exchange.ts
1586
- import { T2000 as T200023, formatUsd as formatUsd13, SUPPORTED_ASSETS as SUPPORTED_ASSETS3 } from "@t2000/sdk";
1675
+ import { T2000 as T200023, formatUsd as formatUsd14, SUPPORTED_ASSETS as SUPPORTED_ASSETS3 } from "@t2000/sdk";
1587
1676
  function registerExchange(program2) {
1588
1677
  program2.command("exchange <amount> <from> <to>").description("Exchange between tokens (e.g. USDC \u21CC SUI) via Cetus DEX").option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percentage (default: 3)", "3").action(async (amount, from, to, opts) => {
1589
1678
  try {
@@ -1609,7 +1698,7 @@ function registerExchange(program2) {
1609
1698
  const toDisplay = SUPPORTED_ASSETS3[toAsset]?.displayName ?? toAsset;
1610
1699
  const toDecimals = toAsset === "SUI" ? 4 : 2;
1611
1700
  printBlank();
1612
- const fromStr = ["USDC", "USDT", "USDE"].includes(fromAsset) ? formatUsd13(parsedAmount) : parsedAmount.toFixed(4);
1701
+ const fromStr = ["USDC", "USDT", "USDE"].includes(fromAsset) ? formatUsd14(parsedAmount) : parsedAmount.toFixed(4);
1613
1702
  printSuccess(`Exchanged ${fromStr} ${fromDisplay} \u2192 ${result.toAmount.toFixed(toDecimals)} ${toDisplay}`);
1614
1703
  printKeyValue("Tx", explorerUrl(result.tx));
1615
1704
  printKeyValue("Gas", `${result.gasCost.toFixed(4)} SUI (${result.gasMethod})`);
@@ -1620,6 +1709,14 @@ function registerExchange(program2) {
1620
1709
  });
1621
1710
  }
1622
1711
 
1712
+ // src/commands/mcp.ts
1713
+ function registerMcp(program2) {
1714
+ program2.command("mcp").description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
1715
+ const { startMcpServer } = await import("./dist-QVEFT4TY.js");
1716
+ await startMcpServer({ keyPath: opts.key });
1717
+ });
1718
+ }
1719
+
1623
1720
  // src/program.ts
1624
1721
  var require2 = createRequire(import.meta.url);
1625
1722
  var { version: CLI_VERSION } = require2("../package.json");
@@ -1654,6 +1751,7 @@ function createProgram() {
1654
1751
  registerEarn(program2);
1655
1752
  registerRebalance(program2);
1656
1753
  registerExchange(program2);
1754
+ registerMcp(program2);
1657
1755
  return program2;
1658
1756
  }
1659
1757