use-agently 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/build/bin.js +224 -74
  2. package/package.json +2 -2
package/build/bin.js CHANGED
@@ -91828,7 +91828,7 @@ function PayTransaction(wallet) {
91828
91828
  // ../use-agently-sdk/package.json
91829
91829
  var package_default = {
91830
91830
  name: "@use-agently/sdk",
91831
- version: "0.26.0",
91831
+ version: "0.28.0",
91832
91832
  description: "Core SDK for the Agently platform — wallet management, A2A, MCP, x402 payments",
91833
91833
  homepage: "https://github.com/AgentlyHQ/use-agently/tree/main/packages/use-agently-sdk",
91834
91834
  bugs: {
@@ -96385,6 +96385,13 @@ async function getBalance2(address, options) {
96385
96385
  import { homedir } from "node:os";
96386
96386
  import { join } from "node:path";
96387
96387
  import { mkdir, rename, readFile, writeFile } from "node:fs/promises";
96388
+ function getMaxSpendPerCall(config2) {
96389
+ const spend = config2.wallet?.spend;
96390
+ if (spend && typeof spend === "object" && "max" in spend && typeof spend.max === "number") {
96391
+ return spend.max;
96392
+ }
96393
+ return 0.1;
96394
+ }
96388
96395
  function getConfigDir(scope) {
96389
96396
  return scope === "local" ? join(process.cwd(), ".use-agently") : join(homedir(), ".use-agently");
96390
96397
  }
@@ -96495,7 +96502,7 @@ var balanceCommand = new Command("balance").description("Check wallet balance on
96495
96502
  // package.json
96496
96503
  var package_default2 = {
96497
96504
  name: "use-agently",
96498
- version: "0.26.0",
96505
+ version: "0.28.0",
96499
96506
  description: "Use Agently CLI",
96500
96507
  homepage: "https://use-agently.com",
96501
96508
  bugs: "https://github.com/AgentlyHQ/use-agently/issues",
@@ -96519,7 +96526,7 @@ var package_default2 = {
96519
96526
  test: "bun test"
96520
96527
  },
96521
96528
  dependencies: {
96522
- "@use-agently/sdk": "0.26.0",
96529
+ "@use-agently/sdk": "0.28.0",
96523
96530
  boxen: "^8.0.1",
96524
96531
  "cli-table3": "^0.6.5",
96525
96532
  commander: "^14.0.3",
@@ -96564,14 +96571,75 @@ function createDryRunFetch2() {
96564
96571
  }
96565
96572
  };
96566
96573
  }
96574
+
96575
+ class SpendLimitExceeded extends Error {
96576
+ requestedAmount;
96577
+ maxSpendPerCall;
96578
+ constructor(requestedAmount, maxSpendPerCall) {
96579
+ super(`Payment of ${formatDollars(requestedAmount)} USDC exceeds your spend limit of ${formatDollars(maxSpendPerCall)} USDC per call.
96580
+ ` + `Run "use-agently wallet spend set-max" to adjust — AI agents must ask the wallet owner for approval before changing spend limits.`);
96581
+ this.name = "SpendLimitExceeded";
96582
+ this.requestedAmount = requestedAmount;
96583
+ this.maxSpendPerCall = maxSpendPerCall;
96584
+ }
96585
+ }
96586
+ function createSpendLimitedFetch(baseFetch, maxSpendPerCall) {
96587
+ return async (input, init) => {
96588
+ const response = await baseFetch(input, init);
96589
+ if (response.status === 402) {
96590
+ const header = response.headers.get("PAYMENT-REQUIRED");
96591
+ let requirements = [];
96592
+ if (header) {
96593
+ try {
96594
+ const decoded = JSON.parse(Buffer.from(header, "base64").toString("utf-8"));
96595
+ requirements = decoded.accepts ?? [];
96596
+ } catch {}
96597
+ } else {
96598
+ try {
96599
+ const body = await response.clone().json();
96600
+ if (body?.accepts) {
96601
+ requirements = body.accepts;
96602
+ }
96603
+ } catch {}
96604
+ }
96605
+ const req = requirements[0];
96606
+ if (!req) {
96607
+ throw new SpendLimitExceeded(NaN, maxSpendPerCall);
96608
+ }
96609
+ let amountInDollars;
96610
+ try {
96611
+ const { usdcDecimals } = getChainConfigByNetwork(req.network);
96612
+ amountInDollars = Number(formatUnits(BigInt(req.amount), usdcDecimals));
96613
+ } catch {
96614
+ throw new SpendLimitExceeded(NaN, maxSpendPerCall);
96615
+ }
96616
+ if (amountInDollars > maxSpendPerCall) {
96617
+ throw new SpendLimitExceeded(amountInDollars, maxSpendPerCall);
96618
+ }
96619
+ }
96620
+ return response;
96621
+ };
96622
+ }
96567
96623
  async function resolveFetch(pay) {
96568
96624
  if (pay) {
96569
96625
  const config2 = await getConfigOrThrow();
96570
96626
  const wallet = loadWallet(config2.wallet);
96571
- return createPaymentFetch(wallet, clientFetch2);
96627
+ const maxSpend = getMaxSpendPerCall(config2);
96628
+ const limitedFetch = createSpendLimitedFetch(clientFetch2, maxSpend);
96629
+ return createPaymentFetch(wallet, limitedFetch);
96572
96630
  }
96573
96631
  return createDryRunFetch2();
96574
96632
  }
96633
+ function createSpendLimitedClient(maxSpendPerCall) {
96634
+ return {
96635
+ fetch: createSpendLimitedFetch(defaultClient.fetch, maxSpendPerCall)
96636
+ };
96637
+ }
96638
+ function formatDollars(amount) {
96639
+ if (Number.isNaN(amount))
96640
+ return "$? (unknown)";
96641
+ return `$${parseFloat(amount.toFixed(6))}`;
96642
+ }
96575
96643
  function formatUsdcAmount2(req) {
96576
96644
  try {
96577
96645
  const { usdcDecimals } = getChainConfigByNetwork(req.network);
@@ -96583,20 +96651,26 @@ function formatUsdcAmount2(req) {
96583
96651
  return `${req.amount} (raw units)`;
96584
96652
  }
96585
96653
  }
96586
- function handleDryRunError(err) {
96587
- const cliErr = err instanceof DryRunPaymentRequired2 ? err : new DryRunPaymentRequired2(err.requirements);
96654
+ function handleErrorAndExit(title, message, borderColor) {
96588
96655
  if (process.stderr.isTTY) {
96589
- console.error(boxen(cliErr.message, {
96590
- title: "Payment Required",
96656
+ console.error(boxen(message, {
96657
+ title,
96591
96658
  titleAlignment: "center",
96592
- borderColor: "yellow",
96659
+ borderColor,
96593
96660
  padding: 1
96594
96661
  }));
96595
96662
  } else {
96596
- console.error(`Payment Required: ${cliErr.message}`);
96663
+ console.error(`${title}: ${message}`);
96597
96664
  }
96598
96665
  process.exit(1);
96599
96666
  }
96667
+ function handleDryRunError(err) {
96668
+ const cliErr = err instanceof DryRunPaymentRequired2 ? err : new DryRunPaymentRequired2(err.requirements);
96669
+ handleErrorAndExit("Payment Required", cliErr.message, "yellow");
96670
+ }
96671
+ function handleSpendLimitError(err) {
96672
+ handleErrorAndExit("Spend Limit Exceeded", err.message, "red");
96673
+ }
96600
96674
 
96601
96675
  // src/commands/agents.ts
96602
96676
  var agentsCommand = new Command("agents").description("List available agents on Agently").action(async (_options, command) => {
@@ -96715,9 +96789,10 @@ async function resolveTransactionMode(pay) {
96715
96789
  if (pay) {
96716
96790
  const config2 = await getConfigOrThrow();
96717
96791
  const wallet = loadWallet(config2.wallet);
96718
- return PayTransaction(wallet);
96792
+ const maxSpend = getMaxSpendPerCall(config2);
96793
+ return { client: createSpendLimitedClient(maxSpend), mode: PayTransaction(wallet) };
96719
96794
  }
96720
- return DryRunTransaction;
96795
+ return { client: defaultClient, mode: DryRunTransaction };
96721
96796
  }
96722
96797
  var a2aCommand = new Command("a2a").description("Send messages and fetch agent cards via the A2A protocol").action(function() {
96723
96798
  this.outputHelp();
@@ -96728,9 +96803,9 @@ Examples:
96728
96803
  use-agently a2a send --uri eip155:8453/erc8004:0x1234/1 -m "Hello!"
96729
96804
  use-agently a2a send --uri https://example.com/agent -m "Hello!" --pay`).action(async (options) => {
96730
96805
  const uri = options.uri;
96731
- const transaction = await resolveTransactionMode(options.pay);
96806
+ const { client, mode: mode2 } = await resolveTransactionMode(options.pay);
96732
96807
  try {
96733
- const stream = await sendMessageStream(defaultClient, uri, options.message, { mode: transaction });
96808
+ const stream = await sendMessageStream(client, uri, options.message, { mode: mode2 });
96734
96809
  let wroteText = false;
96735
96810
  let lastResult = null;
96736
96811
  for await (const event of stream) {
@@ -96748,6 +96823,8 @@ Examples:
96748
96823
  console.log(extractAgentText(lastResult));
96749
96824
  }
96750
96825
  } catch (err) {
96826
+ if (err instanceof SpendLimitExceeded)
96827
+ handleSpendLimitError(err);
96751
96828
  if (err instanceof DryRunPaymentRequired)
96752
96829
  handleDryRunError(err);
96753
96830
  throw err;
@@ -96765,13 +96842,21 @@ a2aCommand.addCommand(a2aSendCommand);
96765
96842
  a2aCommand.addCommand(a2aCardSubCommand);
96766
96843
 
96767
96844
  // src/commands/mcp.ts
96768
- async function resolveTransactionMode2(pay) {
96769
- if (pay) {
96770
- const config2 = await getConfigOrThrow();
96771
- const wallet = loadWallet(config2.wallet);
96772
- return PayTransaction(wallet);
96845
+ function checkSpendLimit(err, maxSpendPerCall) {
96846
+ const req = err.requirements[0];
96847
+ if (!req) {
96848
+ throw new SpendLimitExceeded(NaN, maxSpendPerCall);
96849
+ }
96850
+ let amountInDollars;
96851
+ try {
96852
+ const { usdcDecimals } = getChainConfigByNetwork(req.network);
96853
+ amountInDollars = Number(formatUnits(BigInt(req.amount), usdcDecimals));
96854
+ } catch {
96855
+ throw new SpendLimitExceeded(NaN, maxSpendPerCall);
96856
+ }
96857
+ if (amountInDollars > maxSpendPerCall) {
96858
+ throw new SpendLimitExceeded(amountInDollars, maxSpendPerCall);
96773
96859
  }
96774
- return DryRunTransaction;
96775
96860
  }
96776
96861
  var mcpCommand = new Command("mcp").description("Discover and call tools on MCP servers (always list tools before calling)").action(function() {
96777
96862
  this.outputHelp();
@@ -96801,70 +96886,104 @@ Examples:
96801
96886
  Expected a JSON object, e.g. --args '{"message":"hello"}'`);
96802
96887
  }
96803
96888
  }
96804
- const transaction = await resolveTransactionMode2(options.pay);
96805
- try {
96806
- const result = await callMcpTool(defaultClient, uri, tool, args, {
96807
- transaction,
96808
- clientInfo: { name: "use-agently", version: package_default2.version },
96809
- fetchImpl: clientFetch2
96810
- });
96811
- const content = result.content;
96812
- if (result.isError) {
96813
- const text = content?.find((c) => c.type === "text")?.text;
96814
- if (text) {
96815
- try {
96816
- const parsed = JSON.parse(text);
96817
- if (parsed?.error && Array.isArray(parsed?.accepts) && parsed.accepts.length > 0) {
96818
- let message;
96819
- if (parsed.error === "insufficient_funds") {
96820
- const req = parsed.accepts[0];
96821
- let amountStr = "unknown amount";
96822
- try {
96823
- const { usdcDecimals } = getChainConfigByNetwork(req.network);
96824
- const raw = formatUnits(BigInt(req.amount), usdcDecimals);
96825
- const formatted = raw.includes(".") ? raw.replace(/\.?0+$/, "") : raw;
96826
- amountStr = `$${formatted} USDC on ${req.network}`;
96827
- } catch {
96828
- amountStr = `${req.amount} (raw units)`;
96829
- }
96830
- message = `Insufficient funds to pay for this tool.
96831
- Required: ${amountStr}
96832
- Ensure your wallet has sufficient USDC balance and try again.`;
96833
- } else {
96834
- message = `Payment error: ${parsed.error}`;
96835
- }
96836
- if (process.stderr.isTTY) {
96837
- console.error(boxen(message, {
96838
- title: parsed.error === "insufficient_funds" ? "Insufficient Funds" : "Payment Error",
96839
- titleAlignment: "center",
96840
- borderColor: "red",
96841
- padding: 1
96842
- }));
96843
- } else {
96844
- const title = parsed.error === "insufficient_funds" ? "Insufficient Funds" : "Payment Error";
96845
- console.error(`${title}: ${message}`);
96846
- }
96847
- process.exit(1);
96848
- }
96849
- } catch {}
96850
- console.error(text);
96889
+ const mcpClientInfo = { name: "use-agently", version: package_default2.version };
96890
+ if (options.pay) {
96891
+ const config2 = await getConfigOrThrow();
96892
+ const wallet = loadWallet(config2.wallet);
96893
+ const maxSpend = getMaxSpendPerCall(config2);
96894
+ try {
96895
+ const result = await callMcpTool(defaultClient, uri, tool, args, {
96896
+ transaction: DryRunTransaction,
96897
+ clientInfo: mcpClientInfo,
96898
+ fetchImpl: clientFetch2
96899
+ });
96900
+ return outputMcpResult(result, command);
96901
+ } catch (err) {
96902
+ if (err instanceof DryRunPaymentRequired) {
96903
+ checkSpendLimit(err, maxSpend);
96851
96904
  } else {
96852
- console.error("Tool call returned an error with no text content.");
96905
+ throw err;
96853
96906
  }
96854
- process.exit(1);
96855
96907
  }
96856
- if (content?.every((c) => c.type === "text" && c.text)) {
96857
- const texts = content.map((c) => c.text);
96858
- output(command, texts.length === 1 ? texts[0] : texts);
96859
- } else {
96860
- output(command, result);
96908
+ try {
96909
+ const result = await callMcpTool(defaultClient, uri, tool, args, {
96910
+ transaction: PayTransaction(wallet),
96911
+ clientInfo: mcpClientInfo,
96912
+ fetchImpl: clientFetch2
96913
+ });
96914
+ return outputMcpResult(result, command);
96915
+ } catch (err) {
96916
+ if (err instanceof SpendLimitExceeded)
96917
+ handleSpendLimitError(err);
96918
+ throw err;
96861
96919
  }
96920
+ }
96921
+ try {
96922
+ const result = await callMcpTool(defaultClient, uri, tool, args, {
96923
+ transaction: DryRunTransaction,
96924
+ clientInfo: mcpClientInfo,
96925
+ fetchImpl: clientFetch2
96926
+ });
96927
+ return outputMcpResult(result, command);
96862
96928
  } catch (err) {
96863
96929
  if (err instanceof DryRunPaymentRequired)
96864
96930
  handleDryRunError(err);
96865
96931
  throw err;
96866
96932
  }
96867
96933
  });
96934
+ function outputMcpResult(result, command) {
96935
+ const content = result.content;
96936
+ if (result.isError) {
96937
+ const text = content?.find((c) => c.type === "text")?.text;
96938
+ if (text) {
96939
+ try {
96940
+ const parsed = JSON.parse(text);
96941
+ if (parsed?.error && Array.isArray(parsed?.accepts) && parsed.accepts.length > 0) {
96942
+ let message;
96943
+ if (parsed.error === "insufficient_funds") {
96944
+ const req = parsed.accepts[0];
96945
+ let amountStr = "unknown amount";
96946
+ try {
96947
+ const { usdcDecimals } = getChainConfigByNetwork(req.network);
96948
+ const raw = formatUnits(BigInt(req.amount), usdcDecimals);
96949
+ const formatted = raw.includes(".") ? raw.replace(/\.?0+$/, "") : raw;
96950
+ amountStr = `$${formatted} USDC on ${req.network}`;
96951
+ } catch {
96952
+ amountStr = `${req.amount} (raw units)`;
96953
+ }
96954
+ message = `Insufficient funds to pay for this tool.
96955
+ Required: ${amountStr}
96956
+ Ensure your wallet has sufficient USDC balance and try again.`;
96957
+ } else {
96958
+ message = `Payment error: ${parsed.error}`;
96959
+ }
96960
+ if (process.stderr.isTTY) {
96961
+ console.error(boxen(message, {
96962
+ title: parsed.error === "insufficient_funds" ? "Insufficient Funds" : "Payment Error",
96963
+ titleAlignment: "center",
96964
+ borderColor: "red",
96965
+ padding: 1
96966
+ }));
96967
+ } else {
96968
+ const title = parsed.error === "insufficient_funds" ? "Insufficient Funds" : "Payment Error";
96969
+ console.error(`${title}: ${message}`);
96970
+ }
96971
+ process.exit(1);
96972
+ }
96973
+ } catch {}
96974
+ console.error(text);
96975
+ } else {
96976
+ console.error("Tool call returned an error with no text content.");
96977
+ }
96978
+ process.exit(1);
96979
+ }
96980
+ if (content?.every((c) => c.type === "text" && c.text)) {
96981
+ const texts = content.map((c) => c.text);
96982
+ output(command, texts.length === 1 ? texts[0] : texts);
96983
+ } else {
96984
+ output(command, result);
96985
+ }
96986
+ }
96868
96987
  mcpCommand.addCommand(mcpToolsCommand);
96869
96988
  mcpCommand.addCommand(mcpCallCommand);
96870
96989
 
@@ -97073,6 +97192,9 @@ async function executeHttpRequest(method, url2, options, command) {
97073
97192
  process.exit(1);
97074
97193
  } catch (err) {
97075
97194
  clearTimeout(timer);
97195
+ if (err instanceof SpendLimitExceeded) {
97196
+ handleSpendLimitError(err);
97197
+ }
97076
97198
  if (err instanceof DryRunPaymentRequired) {
97077
97199
  handleDryRunError(err);
97078
97200
  }
@@ -97234,6 +97356,33 @@ var updateCommand = new Command("update").description("Update use-agently to the
97234
97356
  }
97235
97357
  });
97236
97358
 
97359
+ // src/commands/wallet.ts
97360
+ var walletCommand = new Command("wallet").description("Manage wallet settings (spend limits)").action(function() {
97361
+ this.outputHelp();
97362
+ });
97363
+ var spendCommand = new Command("spend").description("View or manage wallet spend limits").showHelpAfterError(true).addHelpText("after", `
97364
+ Examples:
97365
+ use-agently wallet spend
97366
+ use-agently wallet spend set-max 0.5`).action(async (_options, command) => {
97367
+ const config2 = await getConfigOrThrow();
97368
+ output(command, { max: getMaxSpendPerCall(config2) });
97369
+ });
97370
+ var setMaxCommand = new Command("set-max").description("Set the maximum USD spend per call").argument("<value>", "Max spend in USD (0–1, e.g. 0.5)").showHelpAfterError(true).addHelpText("after", `
97371
+ Examples:
97372
+ use-agently wallet spend set-max 0.5
97373
+ use-agently wallet spend set-max 1`).action(async (value, _options, command) => {
97374
+ const amount = Number(value);
97375
+ if (Number.isNaN(amount) || amount < 0 || amount > 1) {
97376
+ throw new Error(`Invalid value "${value}". Must be a number between 0 and 1 (e.g. 0.1, 0.5, 1).`);
97377
+ }
97378
+ const config2 = await getConfigOrThrow();
97379
+ config2.wallet.spend = { max: amount };
97380
+ await saveConfig(config2);
97381
+ output(command, { max: amount });
97382
+ });
97383
+ spendCommand.addCommand(setMaxCommand);
97384
+ walletCommand.addCommand(spendCommand);
97385
+
97237
97386
  // src/cli.ts
97238
97387
  var cli = new Command;
97239
97388
  cli.name("use-agently").description("Agently is the way AI coordinate and transact. All protocol interactions (A2A, MCP, Web/HTTP) go through this CLI.").version(package_default2.version).option("-o, --output <format>", "Output format (tui, json)", process.stdout.isTTY ? "tui" : "json").argument("[args...]").action((args) => {
@@ -97253,6 +97402,7 @@ cli.addCommand(a2aCommand.helpGroup("Protocols"));
97253
97402
  cli.addCommand(mcpCommand.helpGroup("Protocols"));
97254
97403
  cli.addCommand(webCommand.helpGroup("Protocols"));
97255
97404
  cli.addCommand(initCommand.helpGroup("Lifecycle"));
97405
+ cli.addCommand(walletCommand.helpGroup("Lifecycle"));
97256
97406
  cli.addCommand(updateCommand.helpGroup("Lifecycle"));
97257
97407
  function enableGlobalOptionsInHelp(cmd) {
97258
97408
  for (const sub of cmd.commands) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-agently",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Use Agently CLI",
5
5
  "homepage": "https://use-agently.com",
6
6
  "bugs": "https://github.com/AgentlyHQ/use-agently/issues",
@@ -24,7 +24,7 @@
24
24
  "test": "bun test"
25
25
  },
26
26
  "dependencies": {
27
- "@use-agently/sdk": "0.26.0",
27
+ "@use-agently/sdk": "0.28.0",
28
28
  "boxen": "^8.0.1",
29
29
  "cli-table3": "^0.6.5",
30
30
  "commander": "^14.0.3",