@haven_ai/cli 0.2.1-alpha.0 → 0.3.0-alpha.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/README.md CHANGED
@@ -210,7 +210,7 @@ Approving the budget stays with the human, in the browser, every time.
210
210
  Prints the funding instruction a human acts on: what to send (each token's
211
211
  documented minimum-useful amount), to which address, on which chain, plus the
212
212
  explorer link and a faucet link on testnets. It reads
213
- `GET /user/safes/:safeId/funding` — the same facts the dashboard's funding
213
+ `GET /user/accounts/:accountId/funding` — the same facts the dashboard's funding
214
214
  card shows — and composes nothing locally, so the printed sentence and the
215
215
  dashboard can never disagree about the amount.
216
216
 
package/dist/cli.cjs CHANGED
@@ -604,9 +604,9 @@ async function runConnector(connectorCommand, spawner, onStderr) {
604
604
 
605
605
  // src/commands.ts
606
606
  var DEFAULT_API = "https://havenbackend-production-8a00.up.railway.app";
607
- var CLI_VERSION = "0.2.1-alpha.0";
607
+ var CLI_VERSION = "0.3.0-alpha.0";
608
608
  function accountAddressOf(s) {
609
- return s.account_address ?? s.safe_address ?? "";
609
+ return s.account_address ?? "";
610
610
  }
611
611
  async function run(argv, deps = {}) {
612
612
  const out = deps.out ?? ((l) => process.stdout.write(`${l}
@@ -876,24 +876,32 @@ async function cmdWhoami(args, d) {
876
876
  );
877
877
  return EXIT.ok;
878
878
  }
879
+ function accountsEnvelope(body) {
880
+ if (!Array.isArray(body.accounts)) {
881
+ throw new Error(
882
+ "GET /user/accounts did not return an `accounts` array. This CLI needs a Haven backend from the release that carries #2914 or later; an older server returns the retired `safes` envelope. Upgrade the backend, or pin an older @haven_ai/cli."
883
+ );
884
+ }
885
+ return body.accounts;
886
+ }
879
887
  async function cmdWalletsList(args, d) {
880
888
  const { api } = await authed(args, d);
881
- const { safes } = await api.get("/user/accounts");
889
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
882
890
  emit(
883
891
  d,
884
892
  args.flags.json,
885
- safes,
886
- () => safes.length === 0 ? "No Haven wallets yet." : table(
893
+ accounts,
894
+ () => accounts.length === 0 ? "No Haven wallets yet." : table(
887
895
  ["NAME", "NETWORK", "ADDRESS", "DEFAULT"],
888
- safes.map((s) => [s.name, chainName(s.chain_id), truncateAddress(accountAddressOf(s)), s.is_default ? "\u2713" : ""])
896
+ accounts.map((s) => [s.name, chainName(s.chain_id), truncateAddress(accountAddressOf(s)), s.is_default ? "\u2713" : ""])
889
897
  )
890
898
  );
891
899
  return EXIT.ok;
892
900
  }
893
901
  async function cmdWalletsBalances(args, d) {
894
902
  const { api } = await authed(args, d);
895
- const { safes } = await api.get("/user/accounts");
896
- const safe = pickSafe(safes, args.flags.safe);
903
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
904
+ const safe = pickSafe(accounts, args.flags.safe);
897
905
  if (!safe) {
898
906
  if (args.flags.safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
899
907
  throw new CliApiError("No Haven wallet found.", 404);
@@ -904,7 +912,7 @@ async function cmdWalletsBalances(args, d) {
904
912
  emit(
905
913
  d,
906
914
  args.flags.json,
907
- { account: safe.name, safe: safe.name, chainId: safe.chain_id, balances },
915
+ { account: safe.name, chainId: safe.chain_id, balances },
908
916
  () => [
909
917
  `${safe.name} \xB7 ${chainName(safe.chain_id)} \xB7 ${truncateAddress(accountAddressOf(safe))}`,
910
918
  balances.length === 0 ? " (no balances)" : table(["TOKEN", "BALANCE"], balances.map((b) => [b.symbol, b.formatted]))
@@ -912,15 +920,15 @@ async function cmdWalletsBalances(args, d) {
912
920
  );
913
921
  return EXIT.ok;
914
922
  }
915
- function pickSafe(safes, ref) {
916
- if (!ref) return safes.find((s) => s.is_default) ?? safes[0];
923
+ function pickSafe(accounts, ref) {
924
+ if (!ref) return accounts.find((s) => s.is_default) ?? accounts[0];
917
925
  const lower = ref.toLowerCase();
918
- return safes.find((s) => s.id === ref || accountAddressOf(s).toLowerCase() === lower);
926
+ return accounts.find((s) => s.id === ref || accountAddressOf(s).toLowerCase() === lower);
919
927
  }
920
928
  async function cmdWalletsFunding(args, d) {
921
929
  const { api } = await authed(args, d);
922
- const { safes } = await api.get("/user/accounts");
923
- const safe = pickSafe(safes, args.flags.safe);
930
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
931
+ const safe = pickSafe(accounts, args.flags.safe);
924
932
  if (!safe) {
925
933
  if (args.flags.safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
926
934
  throw new CliApiError("No Haven wallet found.", 404);
@@ -1063,8 +1071,8 @@ async function cmdBudgetGrant(args, d) {
1063
1071
  EXIT.refused
1064
1072
  );
1065
1073
  }
1066
- const accountAddress = agent.account_address ?? agent.safe_address;
1067
- const accountChainId = agent.account_chain_id ?? agent.safe_chain_id;
1074
+ const accountAddress = agent.account_address;
1075
+ const accountChainId = agent.account_chain_id;
1068
1076
  if (!accountAddress || !accountChainId) {
1069
1077
  throw new HavenCliError(`Agent ${id} has no wallet assigned yet \u2014 connect it first.`, EXIT.refused);
1070
1078
  }
@@ -1239,27 +1247,24 @@ async function cmdWalletRename(args, d) {
1239
1247
  if (!id || !name) throw new UsageError("Usage: haven wallets rename <id> <name>");
1240
1248
  const { api } = await authed(args, d);
1241
1249
  await api.put(`/user/accounts/${id}`, { name });
1242
- emit(d, args.flags.json, { ok: true, account_id: id, safe_id: id, name }, () => `Wallet ${id} renamed to "${name}".`);
1250
+ emit(d, args.flags.json, { ok: true, account_id: id, name }, () => `Wallet ${id} renamed to "${name}".`);
1243
1251
  return EXIT.ok;
1244
1252
  }
1245
- async function resolveSafeId(args, api) {
1253
+ async function resolveAccountId(args, api) {
1246
1254
  if (!args.flags.safe) return void 0;
1247
- const { safes } = await api.get("/user/accounts");
1248
- const safe = pickSafe(safes, args.flags.safe);
1255
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
1256
+ const safe = pickSafe(accounts, args.flags.safe);
1249
1257
  if (!safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
1250
1258
  return safe.id;
1251
1259
  }
1252
1260
  async function cmdActivityList(args, d) {
1253
1261
  const { api } = await authed(args, d);
1254
- const safeId = await resolveSafeId(args, api);
1262
+ const accountId = await resolveAccountId(args, api);
1255
1263
  const params = new URLSearchParams({
1256
1264
  offset: String(args.flags.offset ?? 0),
1257
1265
  limit: String(args.flags.limit ?? 25)
1258
1266
  });
1259
- if (safeId) {
1260
- params.set("accountId", safeId);
1261
- params.set("safeId", safeId);
1262
- }
1267
+ if (accountId) params.set("accountId", accountId);
1263
1268
  if (args.flags.agent) params.set("agentId", args.flags.agent);
1264
1269
  const { transactions } = await api.get(`/transactions?${params.toString()}`);
1265
1270
  const visible = args.flags.direction ? transactions.filter((t) => t.direction === args.flags.direction) : transactions;
@@ -1274,7 +1279,7 @@ async function cmdActivityList(args, d) {
1274
1279
  t.direction === "in" ? "in" : "out",
1275
1280
  `${t.direction === "in" ? "+" : "-"}${t.valueFormatted} ${t.asset}`,
1276
1281
  t.source ?? "transfer",
1277
- t.safeName ?? ""
1282
+ t.accountName ?? ""
1278
1283
  ])
1279
1284
  )
1280
1285
  );
@@ -1283,15 +1288,12 @@ async function cmdActivityList(args, d) {
1283
1288
  async function cmdActivityExport(args, d) {
1284
1289
  if (args.flags.format === "sie") return exportSie(args, d);
1285
1290
  const { api } = await authed(args, d);
1286
- const safeId = await resolveSafeId(args, api);
1291
+ const accountId = await resolveAccountId(args, api);
1287
1292
  const params = new URLSearchParams({
1288
1293
  offset: String(args.flags.offset ?? 0),
1289
1294
  limit: String(args.flags.limit ?? 1e3)
1290
1295
  });
1291
- if (safeId) {
1292
- params.set("accountId", safeId);
1293
- params.set("safeId", safeId);
1294
- }
1296
+ if (accountId) params.set("accountId", accountId);
1295
1297
  if (args.flags.agent) params.set("agentId", args.flags.agent);
1296
1298
  const { transactions } = await api.get(`/transactions?${params.toString()}`);
1297
1299
  const visible = args.flags.direction ? transactions.filter((t) => t.direction === args.flags.direction) : transactions;
@@ -1304,7 +1306,6 @@ async function cmdActivityExport(args, d) {
1304
1306
  "token_symbol",
1305
1307
  "token_address",
1306
1308
  "counterparty_address",
1307
- "safe_address",
1308
1309
  "agent_name",
1309
1310
  "tx_hash",
1310
1311
  "chain_id",
@@ -1319,11 +1320,10 @@ async function cmdActivityExport(args, d) {
1319
1320
  t.tokenSymbol ?? t.asset ?? "",
1320
1321
  t.tokenAddress ?? "",
1321
1322
  (t.direction === "in" ? t.from : t.to) ?? "",
1322
- t.accountAddress ?? t.safeAddress ?? "",
1323
1323
  t.agentName ?? "",
1324
1324
  t.hash,
1325
1325
  t.chainId != null ? String(t.chainId) : "",
1326
- t.accountAddress ?? t.safeAddress ?? ""
1326
+ t.accountAddress ?? ""
1327
1327
  ]);
1328
1328
  d.o.text(toCsv(headers, rows), { format: "csv", rows: rows.length });
1329
1329
  return EXIT.ok;
@@ -1364,11 +1364,11 @@ async function cmdCatalogList(args, d) {
1364
1364
  return EXIT.ok;
1365
1365
  }
1366
1366
  async function resolveWalletAndToken(args, api, symbol) {
1367
- const { safes } = await api.get("/user/accounts");
1368
- if (safes.length === 0) {
1367
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
1368
+ if (accounts.length === 0) {
1369
1369
  throw new HavenCliError("No wallet on this account yet \u2014 finish onboarding first.", EXIT.refused);
1370
1370
  }
1371
- const safe = args.flags.safe ? safes.find((s) => s.id === args.flags.safe || accountAddressOf(s) === args.flags.safe) : safes.find((s) => s.is_default) ?? safes[0];
1371
+ const safe = args.flags.safe ? accounts.find((s) => s.id === args.flags.safe || accountAddressOf(s) === args.flags.safe) : accounts.find((s) => s.is_default) ?? accounts[0];
1372
1372
  if (!safe) throw new UsageError(`No wallet matches --safe ${args.flags.safe}`);
1373
1373
  const { balances } = await api.get(
1374
1374
  `/balances/${accountAddressOf(safe)}?chain_id=${safe.chain_id}`
@@ -1379,7 +1379,7 @@ async function resolveWalletAndToken(args, api, symbol) {
1379
1379
  const known = balances.map((b) => b.symbol).join(", ");
1380
1380
  throw new UsageError(`Unknown token ${symbol} on this wallet's chain. Available: ${known || "none"}`);
1381
1381
  }
1382
- return { safeId: safe.id, token };
1382
+ return { accountId: safe.id, token };
1383
1383
  }
1384
1384
  var SETTLED = /* @__PURE__ */ new Set(["active", "expired", "cancelled", "failed"]);
1385
1385
  async function pollSetup(api, setupId, d, wait) {
@@ -1413,16 +1413,12 @@ async function cmdAgentsConnect(args, d) {
1413
1413
  if (!args.flags.budget || !args.flags.token || args.flags.period === void 0) {
1414
1414
  throw new UsageError("--budget, --token and --period are required (period is whole minutes; 0 means one-time)");
1415
1415
  }
1416
- const { safeId, token } = await resolveWalletAndToken(args, api, args.flags.token);
1416
+ const { accountId, token } = await resolveWalletAndToken(args, api, args.flags.token);
1417
1417
  const amount = parseTokenAmount(args.flags.budget, token.decimals, token.symbol);
1418
1418
  if (!amount.ok) throw new UsageError(amount.message);
1419
1419
  const setup = await api.post("/agent-connection-setups", {
1420
1420
  name,
1421
- // #2908: both id keys for the window — `account_id` is the #2907 twin
1422
- // (landing in P0's second round), `safe_id` is what a server without it
1423
- // reads; the request works against either.
1424
- account_id: safeId,
1425
- safe_id: safeId,
1421
+ account_id: accountId,
1426
1422
  allowances: [
1427
1423
  {
1428
1424
  token_address: token.address ?? "0x0000000000000000000000000000000000000000",