@bankr/cli 0.3.1 → 0.3.8

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.
@@ -1,28 +1,38 @@
1
- import { transfer, searchTokens } from "../lib/api.js";
1
+ import { transfer, resolveRecipient } from "../lib/api.js";
2
2
  import * as output from "../lib/output.js";
3
- import { NATIVE_SYMBOLS, CHAIN_IDS } from "../lib/chains.js";
3
+ import { NATIVE_SYMBOLS } from "../lib/chains.js";
4
4
  import { isAddress } from "viem";
5
- /**
6
- * Resolve a token symbol or address to a contract address.
7
- * If it's already a valid address, return as-is. Otherwise search by symbol.
8
- */
9
- async function resolveToken(tokenInput, chain) {
10
- if (isAddress(tokenInput)) {
11
- return { address: tokenInput, symbol: tokenInput };
5
+ import { ZERO_ADDRESS, resolveTokenSymbol } from "../lib/tokens.js";
6
+ function looksLikeEnsName(value) {
7
+ const v = value.trim().toLowerCase();
8
+ return v.endsWith(".eth") || v.endsWith(".cb.id");
9
+ }
10
+ async function resolveTransferRecipient(raw) {
11
+ const value = raw.trim();
12
+ if (isAddress(value)) {
13
+ return { address: value, label: value };
14
+ }
15
+ if (!looksLikeEnsName(value)) {
16
+ output.error(`Invalid recipient "${value}". Expected a 0x address or an ENS name (e.g. vitalik.eth, name.base.eth, name.cb.id).`);
17
+ process.exit(1);
12
18
  }
13
- const chainId = CHAIN_IDS[chain];
14
- const res = await searchTokens(tokenInput, chainId);
15
- // Exact symbol match (case-insensitive) to avoid resolving to wrong token
16
- const inputUpper = tokenInput.toUpperCase();
17
- const exactMatch = res.tokens.find((t) => t.symbol.toUpperCase() === inputUpper);
18
- if (!exactMatch) {
19
- const available = res.tokens
20
- .slice(0, 5)
21
- .map((t) => `${t.symbol} (${t.address})`)
22
- .join(", ");
23
- throw new Error(`No exact match for "${tokenInput}" on ${chain}. Did you mean: ${available || "no results"}`);
19
+ const spin = output.spinner(`Resolving ENS name "${value}"...`);
20
+ try {
21
+ const resolved = await resolveRecipient(value, "ens");
22
+ if (!resolved.resolved || !resolved.address) {
23
+ spin.fail(`Could not resolve "${value}": ${resolved.error ?? "unknown error"}`);
24
+ process.exit(1);
25
+ }
26
+ spin.succeed(`Resolved ${value} → ${resolved.address}`);
27
+ return {
28
+ address: resolved.address,
29
+ label: `${value} (${resolved.address})`,
30
+ };
31
+ }
32
+ catch (err) {
33
+ spin.fail(`ENS resolution failed for "${value}": ${err.message}`);
34
+ process.exit(1);
24
35
  }
25
- return { address: exactMatch.address, symbol: exactMatch.symbol };
26
36
  }
27
37
  export async function transferCommand(opts) {
28
38
  const isNative = opts.native ?? false;
@@ -31,16 +41,19 @@ export async function transferCommand(opts) {
31
41
  output.error("Token required for ERC20 transfers. Use --token <symbol or address> or --native.");
32
42
  process.exit(1);
33
43
  }
44
+ const recipient = await resolveTransferRecipient(opts.to);
45
+ const recipientAddress = recipient.address;
46
+ const recipientLabel = recipient.label;
34
47
  let tokenAddress;
35
48
  let tokenLabel;
36
49
  if (isNative) {
37
- tokenAddress = "0x0000000000000000000000000000000000000000";
50
+ tokenAddress = ZERO_ADDRESS;
38
51
  tokenLabel = NATIVE_SYMBOLS[chain] ?? "ETH";
39
52
  }
40
53
  else {
41
54
  const spin = output.spinner(`Resolving token "${opts.token}"...`);
42
55
  try {
43
- const resolved = await resolveToken(opts.token, chain);
56
+ const resolved = await resolveTokenSymbol(opts.token, chain);
44
57
  tokenAddress = resolved.address;
45
58
  tokenLabel = resolved.symbol;
46
59
  if (tokenAddress !== opts.token) {
@@ -56,11 +69,11 @@ export async function transferCommand(opts) {
56
69
  }
57
70
  }
58
71
  const chainLabel = chain !== "base" ? ` on ${chain}` : "";
59
- const spin = output.spinner(`Transferring ${opts.amount} ${tokenLabel} to ${opts.to}${chainLabel}...`);
72
+ const spin = output.spinner(`Transferring ${opts.amount} ${tokenLabel} to ${recipientLabel}${chainLabel}...`);
60
73
  try {
61
74
  const result = await transfer({
62
75
  tokenAddress,
63
- recipientAddress: opts.to,
76
+ recipientAddress,
64
77
  amount: opts.amount,
65
78
  isNativeToken: isNative,
66
79
  chain,
@@ -17,7 +17,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { join } from "node:path";
18
18
  import { confirm } from "@inquirer/prompts";
19
19
  import * as output from "../lib/output.js";
20
- import { getApiUrl, requireApiKey, readConfig, CLI_USER_AGENT, } from "../lib/config.js";
20
+ import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
21
21
  // ── Config file ─────────────────────────────────────────────────────────
22
22
  const CONFIG_FILENAME = "bankr.webhooks.json";
23
23
  const WEBHOOKS_DIR = "webhooks";
@@ -46,16 +46,11 @@ function saveConfigFile(projectRoot, config) {
46
46
  writeFileSync(join(projectRoot, CONFIG_FILENAME), JSON.stringify(config, null, 2) + "\n");
47
47
  }
48
48
  function authHeaders() {
49
- const headers = {
49
+ return {
50
50
  "X-API-Key": requireApiKey(),
51
51
  "Content-Type": "application/json",
52
52
  "User-Agent": CLI_USER_AGENT,
53
53
  };
54
- const config = readConfig();
55
- if (config.partnerKey) {
56
- headers["X-Partner-Key"] = config.partnerKey;
57
- }
58
- return headers;
59
54
  }
60
55
  async function handleResponse(res) {
61
56
  if (!res.ok) {
@@ -20,7 +20,7 @@ import { join } from "node:path";
20
20
  import chalk from "chalk";
21
21
  import { input, select, confirm } from "@inquirer/prompts";
22
22
  import * as output from "../lib/output.js";
23
- import { getApiUrl, requireApiKey, readConfig, CLI_USER_AGENT, } from "../lib/config.js";
23
+ import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
24
24
  // ── Config file helpers ─────────────────────────────────────────────────
25
25
  const CONFIG_FILENAME = "bankr.x402.json";
26
26
  function findProjectRoot() {
@@ -50,16 +50,11 @@ function saveConfigFile(projectRoot, config) {
50
50
  }
51
51
  // ── API helpers ─────────────────────────────────────────────────────────
52
52
  function authHeaders() {
53
- const headers = {
53
+ return {
54
54
  "X-API-Key": requireApiKey(),
55
55
  "Content-Type": "application/json",
56
56
  "User-Agent": CLI_USER_AGENT,
57
57
  };
58
- const config = readConfig();
59
- if (config.partnerKey) {
60
- headers["X-Partner-Key"] = config.partnerKey;
61
- }
62
- return headers;
63
58
  }
64
59
  async function handleResponse(res) {
65
60
  if (!res.ok) {
@@ -279,10 +274,7 @@ export async function x402ConfigureCommand(name) {
279
274
  const currency = "USDC";
280
275
  const network = await select({
281
276
  message: "Network:",
282
- choices: [
283
- { name: "Base", value: "base" },
284
- { name: "Base Sepolia (testnet)", value: "base-sepolia" },
285
- ],
277
+ choices: [{ name: "Base", value: "base" }],
286
278
  default: existing.network ?? "base",
287
279
  theme: output.bankrTheme,
288
280
  });
@@ -697,62 +689,78 @@ function resolveSchemas(schema) {
697
689
  const outputSchema = schema.output;
698
690
  return { input: inputSchema, output: outputSchema };
699
691
  }
700
- function printServiceFormatted(svc) {
692
+ /**
693
+ * Builds the verbose multi-line card for a service. Returns the rendered
694
+ * string. Pass `rank` and `total` to render a `#N of M` badge in the header
695
+ * (used by the search command so reading top-to-bottom shows ascending rank
696
+ * with the top match at the bottom).
697
+ */
698
+ function formatServiceCard(svc, rank, total) {
701
699
  const route = svc.routes[0];
702
700
  const methods = route?.methods?.filter((m) => m !== "*").join(", ") || "ANY";
703
701
  const url = svc.url ?? `https://x402.bankr.bot/${svc.slug}`;
704
702
  const isGet = methods === "GET";
705
- // ── Header ──
706
- console.log(` ${output.fmt.brandBold(svc.name)}`);
707
- if (svc.description) {
708
- console.log(` ${chalk.dim(svc.description)}`);
709
- }
710
- console.log("");
703
+ const lines = [];
704
+ // ── Header (with rank badge) ──
705
+ const rankBadge = rank !== undefined
706
+ ? `${chalk.bold(`#${rank}${total ? ` of ${total}` : ""}`)} `
707
+ : "";
708
+ const scoreBadge = svc.score !== undefined
709
+ ? ` ${chalk.dim(`(score ${svc.score.toFixed(2)})`)}`
710
+ : "";
711
+ lines.push(` ${rankBadge}${output.fmt.brandBold(svc.name)}${scoreBadge}`);
712
+ if (svc.description)
713
+ lines.push(` ${chalk.dim(svc.description)}`);
714
+ lines.push("");
711
715
  // ── Metadata ──
712
- console.log(` ${chalk.dim("URL")} ${url}`);
713
- console.log(` ${chalk.dim("Method")} ${chalk.bold(methods)}`);
714
- console.log(` ${chalk.dim("Price")} ${chalk.green(`$${route?.price ?? "?"} ${route?.currency ?? "USDC"}`)}`);
715
- console.log(` ${chalk.dim("Network")} ${route?.network ?? "base"}`);
716
+ lines.push(` ${chalk.dim("URL")} ${url}`);
717
+ lines.push(` ${chalk.dim("Method")} ${chalk.bold(methods)}`);
718
+ lines.push(` ${chalk.dim("Price")} ${chalk.green(`$${route?.price ?? "?"} ${route?.currency ?? "USDC"}`)}`);
719
+ lines.push(` ${chalk.dim("Network")} ${route?.network ?? "base"}`);
716
720
  // ── Schema ──
717
721
  const { input: inputSchema, output: outputSchema } = resolveSchemas(route?.schema);
718
722
  if (inputSchema || outputSchema) {
719
- console.log("");
723
+ lines.push("");
720
724
  if (inputSchema) {
721
725
  const label = isGet ? "Input (query params)" : "Input (JSON body)";
722
- console.log(` ${chalk.bold(label)}`);
726
+ lines.push(` ${chalk.bold(label)}`);
723
727
  if (isJsonSchema(inputSchema)) {
724
728
  for (const line of renderJsonSchemaProps(inputSchema)) {
725
- console.log(line);
729
+ lines.push(line);
726
730
  }
727
731
  }
728
732
  else if (typeof inputSchema === "object" && inputSchema !== null) {
729
733
  for (const line of renderLegacySchema(inputSchema)) {
730
- console.log(line);
734
+ lines.push(line);
731
735
  }
732
736
  }
733
737
  }
734
738
  if (outputSchema) {
735
- console.log("");
736
- console.log(` ${chalk.bold("Output")}`);
739
+ lines.push("");
740
+ lines.push(` ${chalk.bold("Output")}`);
737
741
  if (isJsonSchema(outputSchema)) {
738
742
  for (const line of renderJsonSchemaProps(outputSchema)) {
739
- console.log(line);
743
+ lines.push(line);
740
744
  }
741
745
  }
742
746
  else if (typeof outputSchema === "object" && outputSchema !== null) {
743
747
  for (const line of renderLegacySchema(outputSchema)) {
744
- console.log(line);
748
+ lines.push(line);
745
749
  }
746
750
  }
747
751
  }
748
752
  }
749
753
  // ── Tags ──
750
754
  if (svc.tags?.length) {
751
- console.log("");
752
- console.log(` ${svc.tags.map((t) => chalk.dim(`#${t}`)).join(" ")}`);
755
+ lines.push("");
756
+ lines.push(` ${svc.tags.map((t) => chalk.dim(`#${t}`)).join(" ")}`);
753
757
  }
754
- console.log(` ${chalk.dim("─".repeat(60))}`);
755
- console.log("");
758
+ lines.push(` ${chalk.dim("─".repeat(60))}`);
759
+ lines.push("");
760
+ return lines.join("\n");
761
+ }
762
+ function printServiceFormatted(svc, rank, total) {
763
+ console.log(formatServiceCard(svc, rank, total));
756
764
  }
757
765
  // ── Schema ────────────────────────────────────────────────────────────
758
766
  export async function x402SchemaCommand(url, opts = {}) {
@@ -1144,8 +1152,7 @@ export async function x402CallCommand(url, opts = {}) {
1144
1152
  resolvedPrice = parseFloat(schema.price);
1145
1153
  }
1146
1154
  }
1147
- // Confirm payment unless --yes
1148
- if (!opts.yes && !opts.interactive) {
1155
+ if (!opts.yes && !opts.interactive && !output.isNonInteractive()) {
1149
1156
  const priceDisplay = resolvedPrice !== null
1150
1157
  ? chalk.green(`$${resolvedPrice} USDC`)
1151
1158
  : chalk.green(`up to $${maxPaymentUsd} USDC`);
@@ -1235,7 +1242,7 @@ export async function x402SearchCommand(queryParts, opts = {}) {
1235
1242
  }
1236
1243
  const spin = output.spinner("Searching services...");
1237
1244
  try {
1238
- const params = new URLSearchParams({ q: query, limit: "10" });
1245
+ const params = new URLSearchParams({ q: query, limit: "50" });
1239
1246
  const res = await fetch(`${getApiUrl()}/x402/endpoints/discover?${params}`);
1240
1247
  const result = await handleResponse(res);
1241
1248
  spin.stop();
@@ -1246,16 +1253,25 @@ export async function x402SearchCommand(queryParts, opts = {}) {
1246
1253
  output.info(`No services found for "${query}"`);
1247
1254
  return;
1248
1255
  }
1249
- // Raw mode: dump JSON and exit
1256
+ // Raw mode: dump JSON and exit (preserves natural rank order for AI
1257
+ // agents and pipelines — most relevant first).
1250
1258
  if (opts.raw) {
1251
1259
  console.log(JSON.stringify(services, null, 2));
1252
1260
  return;
1253
1261
  }
1262
+ // Print results in REVERSE rank order so the cursor parks on the most
1263
+ // relevant result (rank #1) at the bottom of the buffer. Each card has
1264
+ // a `#N of M` badge so the rank is always visible regardless of which
1265
+ // direction you read.
1254
1266
  console.log();
1255
- console.log(` ${chalk.dim(`Found ${services.length} service(s) for`)} "${query}"`);
1267
+ console.log(` ${chalk.dim(`Found ${services.length} service(s) for`)} "${query}" ${chalk.dim("(scrolling order: lowest rank first, top match at the bottom)")}`);
1256
1268
  console.log(` ${chalk.dim("─".repeat(60))}`);
1257
- for (const svc of services) {
1258
- printServiceFormatted(svc);
1269
+ console.log();
1270
+ const total = services.length;
1271
+ // Iterate in reverse: start with the lowest-ranked result, end on rank #1.
1272
+ for (let i = total - 1; i >= 0; i--) {
1273
+ const svc = services[i];
1274
+ printServiceFormatted(svc, i + 1, total);
1259
1275
  }
1260
1276
  }
1261
1277
  catch (err) {
package/dist/lib/api.d.ts CHANGED
@@ -422,6 +422,49 @@ export interface TransferResponse {
422
422
  error?: string;
423
423
  }
424
424
  export declare function transfer(request: TransferRequest): Promise<TransferResponse>;
425
+ export interface SwapQuoteRequest {
426
+ fromChain: string;
427
+ fromToken: string;
428
+ toChain: string;
429
+ toToken: string;
430
+ amount: string;
431
+ }
432
+ export interface SwapQuoteSide {
433
+ chain: string;
434
+ token: string;
435
+ amount: string;
436
+ formattedAmount: string;
437
+ symbol: string;
438
+ decimals: number;
439
+ usdValue: string;
440
+ }
441
+ export interface SwapQuoteResponse {
442
+ from: SwapQuoteSide;
443
+ to: SwapQuoteSide;
444
+ minBuyAmount: string;
445
+ }
446
+ export interface SwapExecuteRequest extends SwapQuoteRequest {
447
+ minBuyAmount: string;
448
+ }
449
+ export interface SwapExecuteResponse {
450
+ success: boolean;
451
+ hash?: string;
452
+ error?: string;
453
+ amountReceived?: number;
454
+ amountReceivedRaw?: string;
455
+ amountSold?: number;
456
+ amountSoldRaw?: string;
457
+ }
458
+ export declare function getSwapQuote(request: SwapQuoteRequest): Promise<SwapQuoteResponse>;
459
+ export declare function executeSwap(request: SwapExecuteRequest): Promise<SwapExecuteResponse>;
460
+ export type RecipientType = "address" | "ens" | "twitter" | "farcaster";
461
+ export interface ResolveRecipientResponse {
462
+ resolved: boolean;
463
+ address?: string;
464
+ displayName?: string;
465
+ error?: string;
466
+ }
467
+ export declare function resolveRecipient(value: string, type: RecipientType): Promise<ResolveRecipientResponse>;
425
468
  export interface X402PayRequest {
426
469
  url: string;
427
470
  method?: string;
package/dist/lib/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CLI_USER_AGENT, getApiUrl, readConfig, requireApiKey, } from "./config.js";
1
+ import { CLI_USER_AGENT, getApiUrl, requireApiKey } from "./config.js";
2
2
  const TERMINAL_STATUSES = [
3
3
  "completed",
4
4
  "failed",
@@ -8,16 +8,11 @@ function isTerminalStatus(status) {
8
8
  return TERMINAL_STATUSES.includes(status);
9
9
  }
10
10
  function authHeaders() {
11
- const headers = {
11
+ return {
12
12
  "X-API-Key": requireApiKey(),
13
13
  "Content-Type": "application/json",
14
14
  "User-Agent": CLI_USER_AGENT,
15
15
  };
16
- const config = readConfig();
17
- if (config.partnerKey) {
18
- headers["X-Partner-Key"] = config.partnerKey;
19
- }
20
- return headers;
21
16
  }
22
17
  async function handleResponse(res) {
23
18
  if (!res.ok) {
@@ -321,6 +316,31 @@ export async function transfer(request) {
321
316
  });
322
317
  return handleResponse(res);
323
318
  }
319
+ export async function getSwapQuote(request) {
320
+ const res = await fetch(`${getApiUrl()}/wallet/swap-quote`, {
321
+ method: "POST",
322
+ headers: authHeaders(),
323
+ body: JSON.stringify(request),
324
+ });
325
+ return handleResponse(res);
326
+ }
327
+ export async function executeSwap(request) {
328
+ const res = await fetch(`${getApiUrl()}/wallet/swap`, {
329
+ method: "POST",
330
+ headers: authHeaders(),
331
+ body: JSON.stringify(request),
332
+ });
333
+ return handleResponse(res);
334
+ }
335
+ export async function resolveRecipient(value, type) {
336
+ const params = new URLSearchParams({ value, type });
337
+ const res = await fetch(`${getApiUrl()}/addresses/resolve?${params}`, {
338
+ headers: {
339
+ "User-Agent": CLI_USER_AGENT,
340
+ },
341
+ });
342
+ return handleResponse(res);
343
+ }
324
344
  export async function x402Pay(request) {
325
345
  const res = await fetch(`${getApiUrl()}/wallet/x402-pay`, {
326
346
  method: "POST",
@@ -5,7 +5,6 @@ export interface BankrConfig {
5
5
  llmKey?: string;
6
6
  llmUrl?: string;
7
7
  lastThreadId?: string;
8
- partnerKey?: string;
9
8
  sound?: SoundConfig;
10
9
  }
11
10
  export declare function setConfigPath(path: string): void;
@@ -44,5 +44,6 @@ export interface RemediationStep {
44
44
  * Used when the API returns a `remediation` array in error responses.
45
45
  */
46
46
  export declare function remediation(steps: RemediationStep[]): void;
47
+ export declare function isNonInteractive(): boolean;
47
48
  export declare function formatStatus(status: string): string;
48
49
  //# sourceMappingURL=output.d.ts.map
@@ -105,6 +105,9 @@ export function remediation(steps) {
105
105
  }
106
106
  console.log();
107
107
  }
108
+ export function isNonInteractive() {
109
+ return process.env.BANKR_NOT_INTERACTIVE === "1";
110
+ }
108
111
  export function formatStatus(status) {
109
112
  switch (status) {
110
113
  case "completed":
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Native-token sentinel (zero address). The API detects + sanitizes native
3
+ * tokens from this, so callers send it instead of a real contract address.
4
+ */
5
+ export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
6
+ /** Shorten an address for display, e.g. `0x8335…2913`. */
7
+ export declare function shortenAddress(address: string): string;
8
+ /**
9
+ * Resolve a token symbol or 0x address to `{ address, symbol }` on a chain:
10
+ * - a valid 0x address is used as-is (symbol shown shortened for display),
11
+ * - otherwise an exact, case-insensitive symbol match is looked up via
12
+ * `/tokens/search`, throwing a "Did you mean" suggestion list on no match.
13
+ *
14
+ * Native-token handling is caller-specific (a `--native` flag for transfer, a
15
+ * native-ticker/zero-address short-circuit for swap), so it lives in the command.
16
+ */
17
+ export declare function resolveTokenSymbol(tokenInput: string, chain: string): Promise<{
18
+ address: string;
19
+ symbol: string;
20
+ }>;
21
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { isAddress } from "viem";
2
+ import { searchTokens } from "./api.js";
3
+ import { CHAIN_IDS } from "./chains.js";
4
+ /**
5
+ * Native-token sentinel (zero address). The API detects + sanitizes native
6
+ * tokens from this, so callers send it instead of a real contract address.
7
+ */
8
+ export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
9
+ /** Shorten an address for display, e.g. `0x8335…2913`. */
10
+ export function shortenAddress(address) {
11
+ return `${address.slice(0, 6)}…${address.slice(-4)}`;
12
+ }
13
+ /**
14
+ * Resolve a token symbol or 0x address to `{ address, symbol }` on a chain:
15
+ * - a valid 0x address is used as-is (symbol shown shortened for display),
16
+ * - otherwise an exact, case-insensitive symbol match is looked up via
17
+ * `/tokens/search`, throwing a "Did you mean" suggestion list on no match.
18
+ *
19
+ * Native-token handling is caller-specific (a `--native` flag for transfer, a
20
+ * native-ticker/zero-address short-circuit for swap), so it lives in the command.
21
+ */
22
+ export async function resolveTokenSymbol(tokenInput, chain) {
23
+ const input = tokenInput.trim();
24
+ if (isAddress(input)) {
25
+ return { address: input, symbol: shortenAddress(input) };
26
+ }
27
+ const chainId = CHAIN_IDS[chain];
28
+ const res = await searchTokens(input, chainId);
29
+ const inputUpper = input.toUpperCase();
30
+ const exactMatch = res.tokens.find((t) => t.symbol.toUpperCase() === inputUpper);
31
+ if (!exactMatch) {
32
+ const available = res.tokens
33
+ .slice(0, 5)
34
+ .map((t) => `${t.symbol} (${t.address})`)
35
+ .join(", ");
36
+ throw new Error(`No exact match for "${input}" on ${chain}. Did you mean: ${available || "no results"}`);
37
+ }
38
+ return { address: exactMatch.address, symbol: exactMatch.symbol };
39
+ }
40
+ //# sourceMappingURL=tokens.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bankr/cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.8",
4
4
  "description": "Official CLI for the Bankr AI agent platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,11 +40,11 @@
40
40
  "url": "https://discord.gg/bankr"
41
41
  },
42
42
  "dependencies": {
43
- "@inquirer/prompts": "^8.2.0",
44
- "chalk": "^5.3.0",
45
- "commander": "^12.1.0",
46
- "open": "^10.1.0",
47
- "ora": "^8.1.0",
43
+ "@inquirer/prompts": "^8.4.2",
44
+ "chalk": "^5.6.2",
45
+ "commander": "^14.0.3",
46
+ "open": "^11.0.0",
47
+ "ora": "^9.4.0",
48
48
  "viem": "^2.37.2"
49
49
  }
50
50
  }