@agentis-hq/cli 0.3.2 → 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 (2) hide show
  1. package/dist/index.js +306 -12
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -97,7 +97,9 @@ var SCOPES = [
97
97
  "privacy:read",
98
98
  "privacy:write",
99
99
  "earn:read",
100
- "earn:write"
100
+ "earn:write",
101
+ "jupiter:read",
102
+ "jupiter:write"
101
103
  ];
102
104
  function base64url(bytes) {
103
105
  return Buffer.from(bytes).toString("base64url");
@@ -131,8 +133,8 @@ async function login() {
131
133
  const server = Bun.serve({
132
134
  hostname: "127.0.0.1",
133
135
  port: 0,
134
- fetch(request) {
135
- const url = new URL(request.url);
136
+ fetch(request2) {
137
+ const url = new URL(request2.url);
136
138
  if (url.pathname !== "/callback") return new Response("Not found", { status: 404 });
137
139
  if (!handled) {
138
140
  handled = true;
@@ -285,6 +287,9 @@ var DEFAULT_LOCAL_POLICY = {
285
287
  maxBudget: null,
286
288
  maxPerTx: null,
287
289
  allowedDomains: [],
290
+ allowedMints: [],
291
+ maxSlippageBps: null,
292
+ maxDailySwapVolume: null,
288
293
  killSwitch: false
289
294
  };
290
295
  function ensureVaultDir() {
@@ -837,6 +842,9 @@ Policy for ${name} (${scope}):`);
837
842
  console.log(` Monthly limit: ${p.monthlyLimit !== null ? `$${p.monthlyLimit}` : "unlimited"}`);
838
843
  console.log(` Total budget: ${p.maxBudget !== null ? `$${p.maxBudget}` : "unlimited"}`);
839
844
  console.log(` Allowed domains: ${p.allowedDomains?.length > 0 ? p.allowedDomains.join(", ") : "all"}`);
845
+ console.log(` Allowed mints: ${p.allowedMints?.length > 0 ? p.allowedMints.join(", ") : "all"}`);
846
+ console.log(` Max slippage: ${p.maxSlippageBps !== null && p.maxSlippageBps !== void 0 ? `${p.maxSlippageBps} bps` : "unlimited"}`);
847
+ console.log(` Daily swaps: ${p.maxDailySwapVolume !== null && p.maxDailySwapVolume !== void 0 ? `$${p.maxDailySwapVolume}` : "unlimited"}`);
840
848
  console.log();
841
849
  }
842
850
  function applyPolicyFlags(existingPolicy, args2) {
@@ -852,6 +860,8 @@ function applyPolicyFlags(existingPolicy, args2) {
852
860
  if (get("--daily") !== void 0) policy.dailyLimit = parseFloat(get("--daily"));
853
861
  if (get("--monthly") !== void 0) policy.monthlyLimit = parseFloat(get("--monthly"));
854
862
  if (get("--budget") !== void 0) policy.maxBudget = parseFloat(get("--budget"));
863
+ if (get("--max-slippage-bps") !== void 0) policy.maxSlippageBps = parseInt(get("--max-slippage-bps"), 10);
864
+ if (get("--daily-swap-volume") !== void 0) policy.maxDailySwapVolume = parseFloat(get("--daily-swap-volume"));
855
865
  if (get("--allow")) {
856
866
  const domain = get("--allow").replace(/^https?:\/\//, "").toLowerCase();
857
867
  policy.allowedDomains = [.../* @__PURE__ */ new Set([...policy.allowedDomains ?? [], domain])];
@@ -860,6 +870,14 @@ function applyPolicyFlags(existingPolicy, args2) {
860
870
  const domain = get("--disallow").replace(/^https?:\/\//, "").toLowerCase();
861
871
  policy.allowedDomains = (policy.allowedDomains ?? []).filter((d) => d !== domain);
862
872
  }
873
+ if (get("--allow-mint")) {
874
+ const mint = get("--allow-mint");
875
+ policy.allowedMints = [.../* @__PURE__ */ new Set([...policy.allowedMints ?? [], mint])];
876
+ }
877
+ if (get("--disallow-mint")) {
878
+ const mint = get("--disallow-mint");
879
+ policy.allowedMints = (policy.allowedMints ?? []).filter((candidate) => candidate !== mint);
880
+ }
863
881
  return policy;
864
882
  }
865
883
  async function policyGet(nameOrId) {
@@ -1559,6 +1577,236 @@ async function earnSweep(args2) {
1559
1577
  await executeSweep(token, plan);
1560
1578
  }
1561
1579
 
1580
+ // src/commands/jupiter.ts
1581
+ function getFlag4(args2, flag2) {
1582
+ const index = args2.indexOf(flag2);
1583
+ return index === -1 ? void 0 : args2[index + 1];
1584
+ }
1585
+ function hasFlag3(args2, flag2) {
1586
+ return args2.includes(flag2);
1587
+ }
1588
+ async function auth() {
1589
+ const token = await getToken();
1590
+ if (!token) {
1591
+ console.error("Not logged in. Run `agentis login` first.");
1592
+ process.exit(1);
1593
+ }
1594
+ return token;
1595
+ }
1596
+ async function request(path, token, init = {}) {
1597
+ const response = await apiFetch(path, init, token);
1598
+ const body = await response.json().catch(() => ({}));
1599
+ if (!response.ok) throw new Error(body.error ?? `Agentis API failed (${response.status})`);
1600
+ return body;
1601
+ }
1602
+ function tradeBody(args2) {
1603
+ const input = getFlag4(args2, "--from");
1604
+ const output = getFlag4(args2, "--to");
1605
+ const amount = getFlag4(args2, "--amount");
1606
+ const slippage = getFlag4(args2, "--slippage-bps");
1607
+ if (!input || !output || !amount) {
1608
+ throw new Error("--from, --to, and --amount are required");
1609
+ }
1610
+ return {
1611
+ input,
1612
+ output,
1613
+ amount,
1614
+ ...slippage ? { slippageBps: Number(slippage) } : {}
1615
+ };
1616
+ }
1617
+ function printToken(token) {
1618
+ const trust = token.audit?.isSus ? "suspicious" : token.isVerified ? "verified" : "unverified";
1619
+ console.log(` ${(token.symbol ?? "?").padEnd(10)} ${token.name ?? ""}`);
1620
+ console.log(` ${token.id}`);
1621
+ console.log(` ${trust} \xB7 decimals=${token.decimals} \xB7 organic=${token.organicScoreLabel ?? "unknown"}`);
1622
+ }
1623
+ async function financialCommand(args2) {
1624
+ const area = args2[0];
1625
+ const action = args2[1];
1626
+ const token = await auth();
1627
+ if (area === "tokens" && action === "search") {
1628
+ const query = args2.slice(2).filter((value) => !value.startsWith("--")).join(" ").trim();
1629
+ if (!query) throw new Error("Usage: agentis tokens search <query>");
1630
+ const data = await request(`/agents/jupiter/tokens?query=${encodeURIComponent(query)}`, token);
1631
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1632
+ console.log(`
1633
+ Jupiter tokens matching "${query}"
1634
+ `);
1635
+ const matches = data.tokens ?? [];
1636
+ for (const item of matches.slice(0, 20)) printToken(item);
1637
+ if (matches.length > 20) console.log(` ...and ${matches.length - 20} more. Use --json for the full result.`);
1638
+ console.log();
1639
+ return;
1640
+ }
1641
+ if (area === "swap" && (action === "quote" || action === "execute")) {
1642
+ const agentName = args2[2];
1643
+ if (!agentName) throw new Error(`Usage: agentis swap ${action} <agent> --from SOL --to USDC --amount 0.1`);
1644
+ const agent = await resolveAccountAgent(agentName, token);
1645
+ const data = await request(
1646
+ `/agents/${agent.id}/jupiter/swap${action === "quote" ? "/quote" : ""}`,
1647
+ token,
1648
+ { method: "POST", body: JSON.stringify(tradeBody(args2.slice(3))) }
1649
+ );
1650
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1651
+ const quote = data.quote ?? data.order ?? {};
1652
+ console.log(`
1653
+ Jupiter swap ${action === "quote" ? "quote" : "executed"} for ${agent.name}`);
1654
+ console.log(` ${data.amountUi} ${data.inputToken?.symbol ?? data.inputToken?.id} -> ${data.outputToken?.symbol ?? data.outputToken?.id}`);
1655
+ console.log(` Expected out: ${quote.outAmount ?? data.result?.outputAmountResult ?? "unknown"} atomic`);
1656
+ console.log(` Router: ${quote.router ?? "unknown"}`);
1657
+ if (data.result?.signature) console.log(` Signature: ${data.result.signature}`);
1658
+ console.log();
1659
+ return;
1660
+ }
1661
+ if (area === "portfolio") {
1662
+ const agentName = args2[1];
1663
+ if (!agentName) throw new Error("Usage: agentis portfolio <agent> [--json]");
1664
+ const agent = await resolveAccountAgent(agentName, token);
1665
+ const data = await request(`/agents/${agent.id}/jupiter/portfolio`, token);
1666
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1667
+ const elements = data.portfolio?.elements ?? [];
1668
+ console.log(`
1669
+ Jupiter portfolio for ${agent.name}`);
1670
+ console.log(` Positions: ${elements.length}`);
1671
+ for (const item of elements.slice(0, 20)) {
1672
+ console.log(` ${(item.label ?? item.type ?? "position").padEnd(18)} $${Number(item.value ?? 0).toFixed(2)} \xB7 ${item.platformId ?? "jupiter"}`);
1673
+ }
1674
+ console.log();
1675
+ return;
1676
+ }
1677
+ if (area === "recurring" && action === "list") {
1678
+ const agentName = args2[2];
1679
+ if (!agentName) throw new Error("Usage: agentis recurring list <agent> [--history] [--json]");
1680
+ const agent = await resolveAccountAgent(agentName, token);
1681
+ const status = hasFlag3(args2, "--history") ? "history" : "active";
1682
+ const data = await request(`/agents/${agent.id}/jupiter/recurring?status=${status}`, token);
1683
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1684
+ const orders = Array.isArray(data.orders) ? data.orders : data.orders?.orders ?? [];
1685
+ console.log(`
1686
+ ${status} Jupiter recurring orders for ${agent.name}`);
1687
+ if (!orders.length) console.log(" None.");
1688
+ for (const order of orders) {
1689
+ console.log(` ${order.orderKey ?? order.publicKey ?? order.id ?? "unknown"} \xB7 ${order.status ?? status}`);
1690
+ }
1691
+ console.log();
1692
+ return;
1693
+ }
1694
+ if (area === "recurring" && action === "create") {
1695
+ const agentName = args2[2];
1696
+ if (!agentName) throw new Error("Usage: agentis recurring create <agent> --from USDC --to SOL --amount 100 --orders 2 --interval 86400");
1697
+ const agent = await resolveAccountAgent(agentName, token);
1698
+ const numberOfOrders = Number(getFlag4(args2, "--orders"));
1699
+ const intervalSeconds = Number(getFlag4(args2, "--interval"));
1700
+ const data = await request(`/agents/${agent.id}/jupiter/recurring`, token, {
1701
+ method: "POST",
1702
+ body: JSON.stringify({
1703
+ ...tradeBody(args2.slice(3)),
1704
+ numberOfOrders,
1705
+ intervalSeconds,
1706
+ startAt: getFlag4(args2, "--start-at") ? Number(getFlag4(args2, "--start-at")) : void 0
1707
+ })
1708
+ });
1709
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1710
+ console.log(`
1711
+ Recurring order created for ${agent.name}`);
1712
+ console.log(` Order: ${data.result?.order ?? "submitted"}`);
1713
+ console.log(` Signature: ${data.result?.signature ?? "unknown"}
1714
+ `);
1715
+ return;
1716
+ }
1717
+ if (area === "recurring" && action === "cancel") {
1718
+ const agentName = args2[2];
1719
+ const order = args2[3];
1720
+ if (!agentName || !order) throw new Error("Usage: agentis recurring cancel <agent> <order>");
1721
+ const agent = await resolveAccountAgent(agentName, token);
1722
+ const data = await request(`/agents/${agent.id}/jupiter/recurring/${encodeURIComponent(order)}/cancel`, token, { method: "POST" });
1723
+ if (hasFlag3(args2, "--json")) return console.log(JSON.stringify(data, null, 2));
1724
+ console.log(`
1725
+ Recurring order cancelled for ${agent.name}`);
1726
+ console.log(` Signature: ${data.result?.signature ?? "unknown"}
1727
+ `);
1728
+ return;
1729
+ }
1730
+ console.log("Usage: agentis <tokens|swap|portfolio|recurring> ...");
1731
+ }
1732
+
1733
+ // src/lib/command-validation.ts
1734
+ var commandTree = {
1735
+ login: null,
1736
+ logout: null,
1737
+ whoami: null,
1738
+ version: null,
1739
+ wallet: ["create", "list"],
1740
+ agent: ["create", "send", "balance"],
1741
+ fetch: null,
1742
+ earn: ["deposit", "withdraw", "positions", "sweep"],
1743
+ tokens: ["search"],
1744
+ swap: ["quote", "execute"],
1745
+ portfolio: null,
1746
+ recurring: ["list", "create", "cancel"],
1747
+ facilitator: ["create", "list", "publish"],
1748
+ privacy: ["status", "register", "balance", "deposit", "withdraw", "create-utxo", "scan", "claim-latest"],
1749
+ policy: ["get", "set", "init-onchain"]
1750
+ };
1751
+ var CliCommandError = class extends Error {
1752
+ constructor(message, helpCommand = "agentis --help") {
1753
+ super(message);
1754
+ this.helpCommand = helpCommand;
1755
+ this.name = "CliCommandError";
1756
+ }
1757
+ helpCommand;
1758
+ };
1759
+ function editDistance(left, right) {
1760
+ const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
1761
+ for (let i = 1; i <= left.length; i++) {
1762
+ const current = [i];
1763
+ for (let j = 1; j <= right.length; j++) {
1764
+ current[j] = Math.min(
1765
+ current[j - 1] + 1,
1766
+ previous[j] + 1,
1767
+ previous[j - 1] + (left[i - 1] === right[j - 1] ? 0 : 1)
1768
+ );
1769
+ }
1770
+ previous.splice(0, previous.length, ...current);
1771
+ }
1772
+ return previous[right.length];
1773
+ }
1774
+ function closestMatch(value, choices) {
1775
+ const ranked = choices.map((choice) => ({ choice, distance: editDistance(value, choice) })).sort((a, b) => a.distance - b.distance);
1776
+ const best = ranked[0];
1777
+ if (!best) return null;
1778
+ const threshold = Math.max(1, Math.floor(Math.max(value.length, best.choice.length) / 3));
1779
+ return best.distance <= threshold ? best.choice : null;
1780
+ }
1781
+ function unknownMessage(kind, value, suggestion, parent) {
1782
+ const context = kind === "subcommand" ? ` for "${parent}"` : "";
1783
+ return `Unknown ${kind} "${value}"${context}.${suggestion ? ` Did you mean "${suggestion}"?` : ""}`;
1784
+ }
1785
+ function validateCommand(args2) {
1786
+ const command = args2[0];
1787
+ if (!command || command === "--version" || command === "-v" || command === "--help" || command === "-h") return;
1788
+ const subcommands = commandTree[command];
1789
+ if (subcommands === void 0) {
1790
+ throw new CliCommandError(
1791
+ unknownMessage("command", command, closestMatch(command, Object.keys(commandTree)))
1792
+ );
1793
+ }
1794
+ if (!subcommands) return;
1795
+ const subcommand = args2[1];
1796
+ const hasHelp = args2.includes("--help") || args2.includes("-h");
1797
+ if (!subcommand) {
1798
+ if (hasHelp) return;
1799
+ throw new CliCommandError(`Missing command for "${command}".`, `agentis ${command} --help`);
1800
+ }
1801
+ if (subcommand.startsWith("-") && hasHelp) return;
1802
+ if (!subcommands.includes(subcommand)) {
1803
+ throw new CliCommandError(
1804
+ unknownMessage("subcommand", subcommand, closestMatch(subcommand, subcommands), command),
1805
+ `agentis ${command} --help`
1806
+ );
1807
+ }
1808
+ }
1809
+
1562
1810
  // src/index.ts
1563
1811
  var args = process.argv.slice(2);
1564
1812
  var cmd = args[0];
@@ -1670,6 +1918,31 @@ var helpSpecs = {
1670
1918
  ["sweep [--dry-run|--no-dry-run]", "sweep all hosted agents mainnet USDC into Jupiter Earn"]
1671
1919
  ]
1672
1920
  },
1921
+ swap: {
1922
+ usage: "agentis swap <quote|execute> <agent> --from <token> --to <token> --amount <ui>",
1923
+ description: "Quote or execute policy-controlled swaps through Jupiter.",
1924
+ commands: [
1925
+ ["quote <agent> --from <token> --to <token> --amount <ui>", "get a policy-checked quote"],
1926
+ ["execute <agent> --from <token> --to <token> --amount <ui>", "execute the swap"]
1927
+ ]
1928
+ },
1929
+ tokens: {
1930
+ usage: "agentis tokens search <query> [--json]",
1931
+ description: "Search Jupiter token metadata and safety signals."
1932
+ },
1933
+ portfolio: {
1934
+ usage: "agentis portfolio <agent> [--json]",
1935
+ description: "Show mainnet Jupiter portfolio positions."
1936
+ },
1937
+ recurring: {
1938
+ usage: "agentis recurring <list|create|cancel> ...",
1939
+ description: "Manage Jupiter time-based recurring swaps.",
1940
+ commands: [
1941
+ ["list <agent> [--history] [--json]", "list active or historical orders"],
1942
+ ["create <agent> --from <token> --to <token> --amount <ui> --orders <n> --interval <seconds>", "create an order"],
1943
+ ["cancel <agent> <order>", "cancel an active order"]
1944
+ ]
1945
+ },
1673
1946
  "earn deposit": {
1674
1947
  usage: "agentis earn deposit <agent> --asset USDC --amount <amount> --mainnet",
1675
1948
  description: "Deposit mainnet USDC from a hosted agent wallet into Jupiter Earn.",
@@ -1829,6 +2102,10 @@ var helpSpecs = {
1829
2102
  ["--budget <usd>", "total lifetime budget cap"],
1830
2103
  ["--allow <domain>", "add domain to whitelist"],
1831
2104
  ["--disallow <domain>", "remove domain from whitelist"],
2105
+ ["--allow-mint <mint>", "add token mint to Jupiter allowlist"],
2106
+ ["--disallow-mint <mint>", "remove token mint from Jupiter allowlist"],
2107
+ ["--max-slippage-bps <bps>", "maximum Jupiter swap slippage"],
2108
+ ["--daily-swap-volume <usd>", "maximum Jupiter volume per 24 hours"],
1832
2109
  ["-h, --help", "display help for command"]
1833
2110
  ]
1834
2111
  },
@@ -1878,6 +2155,14 @@ ${green2}${bold}Commands:${reset2}
1878
2155
  earn positions <agent> --mainnet show Jupiter Earn positions
1879
2156
  earn sweep [--dry-run|--no-dry-run] sweep all agents' mainnet USDC into Earn
1880
2157
 
2158
+ tokens search <query> search token metadata and safety
2159
+ swap quote <agent> quote a mainnet Jupiter swap
2160
+ swap execute <agent> execute a policy-checked swap
2161
+ portfolio <agent> show Jupiter portfolio positions
2162
+ recurring list <agent> list active or historical DCA orders
2163
+ recurring create <agent> create a time-based DCA order
2164
+ recurring cancel <agent> <order> cancel a DCA order
2165
+
1881
2166
  facilitator create <name> scaffold a Kora-backed x402 facilitator
1882
2167
  --dir <path> output directory
1883
2168
  --fee-bps <bps> prepaid seller fee rate (default 500)
@@ -1909,6 +2194,10 @@ ${green2}${bold}Commands:${reset2}
1909
2194
  --budget <usd> total lifetime budget cap
1910
2195
  --allow <domain> add domain to whitelist
1911
2196
  --disallow <domain> remove domain from whitelist
2197
+ --allow-mint <mint> add token mint to Jupiter allowlist
2198
+ --disallow-mint <mint> remove token mint from Jupiter allowlist
2199
+ --max-slippage-bps <bps> maximum Jupiter swap slippage
2200
+ --daily-swap-volume <usd> maximum Jupiter volume per 24 hours
1912
2201
  `);
1913
2202
  }
1914
2203
  function hasHelpFlag(values) {
@@ -1943,6 +2232,7 @@ function showCommandHelp(path) {
1943
2232
  console.log();
1944
2233
  }
1945
2234
  async function main() {
2235
+ validateCommand(args);
1946
2236
  if (cmd === "--version" || cmd === "-v" || cmd === "version") {
1947
2237
  console.log(version);
1948
2238
  return;
@@ -1969,8 +2259,6 @@ async function main() {
1969
2259
  case "list":
1970
2260
  await walletList(args.slice(2));
1971
2261
  break;
1972
- default:
1973
- console.log("Usage: agentis wallet <create|list>");
1974
2262
  }
1975
2263
  break;
1976
2264
  case "agent":
@@ -1984,8 +2272,6 @@ async function main() {
1984
2272
  case "balance":
1985
2273
  await agentBalance(args[2]);
1986
2274
  break;
1987
- default:
1988
- console.log("Usage: agentis agent <create|send|balance>");
1989
2275
  }
1990
2276
  break;
1991
2277
  case "policy":
@@ -1999,8 +2285,6 @@ async function main() {
1999
2285
  case "init-onchain":
2000
2286
  await policyInitOnchain(args[2]);
2001
2287
  break;
2002
- default:
2003
- console.log("Usage: agentis policy <get|set|init-onchain>");
2004
2288
  }
2005
2289
  break;
2006
2290
  case "fetch":
@@ -2015,11 +2299,21 @@ async function main() {
2015
2299
  case "earn":
2016
2300
  await earnCommand(args.slice(1));
2017
2301
  break;
2018
- default:
2019
- showHelp();
2302
+ case "tokens":
2303
+ case "swap":
2304
+ case "portfolio":
2305
+ case "recurring":
2306
+ await financialCommand(args);
2307
+ break;
2020
2308
  }
2021
2309
  }
2022
2310
  main().catch((err) => {
2023
- console.error("Error:", err.message);
2311
+ if (err instanceof CliCommandError) {
2312
+ console.error(`Error: ${err.message}
2313
+
2314
+ Run \`${err.helpCommand}\` for usage.`);
2315
+ } else {
2316
+ console.error("Error:", err instanceof Error ? err.message : String(err));
2317
+ }
2024
2318
  process.exit(1);
2025
2319
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentis-hq/cli",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "agentis": "dist/index.js"
@@ -41,8 +41,8 @@
41
41
  "check": "bun --check src/index.ts"
42
42
  },
43
43
  "dependencies": {
44
- "@agentis-hq/core": "^0.1.0",
45
- "@agentis-hq/sdk": "^0.1.0",
44
+ "@agentis-hq/core": "^0.2.0",
45
+ "@agentis-hq/sdk": "^0.2.0",
46
46
  "@napi-rs/keyring": "^1.2.0",
47
47
  "@noble/ciphers": "^2.2.0",
48
48
  "@noble/curves": "^2.2.0",