@haven_ai/cli 0.2.1-alpha.0 → 0.4.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/dist/index.js CHANGED
@@ -600,9 +600,9 @@ async function runConnector(connectorCommand, spawner, onStderr) {
600
600
 
601
601
  // src/commands.ts
602
602
  var DEFAULT_API = "https://havenbackend-production-8a00.up.railway.app";
603
- var CLI_VERSION = "0.2.1-alpha.0";
603
+ var CLI_VERSION = "0.4.0-alpha.0";
604
604
  function accountAddressOf(s) {
605
- return s.account_address ?? s.safe_address ?? "";
605
+ return s.account_address ?? "";
606
606
  }
607
607
  async function run(argv, deps = {}) {
608
608
  const out = deps.out ?? ((l) => process.stdout.write(`${l}
@@ -872,24 +872,32 @@ async function cmdWhoami(args, d) {
872
872
  );
873
873
  return EXIT.ok;
874
874
  }
875
+ function accountsEnvelope(body) {
876
+ if (!Array.isArray(body.accounts)) {
877
+ throw new Error(
878
+ "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."
879
+ );
880
+ }
881
+ return body.accounts;
882
+ }
875
883
  async function cmdWalletsList(args, d) {
876
884
  const { api } = await authed(args, d);
877
- const { safes } = await api.get("/user/accounts");
885
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
878
886
  emit(
879
887
  d,
880
888
  args.flags.json,
881
- safes,
882
- () => safes.length === 0 ? "No Haven wallets yet." : table(
889
+ accounts,
890
+ () => accounts.length === 0 ? "No Haven wallets yet." : table(
883
891
  ["NAME", "NETWORK", "ADDRESS", "DEFAULT"],
884
- safes.map((s) => [s.name, chainName(s.chain_id), truncateAddress(accountAddressOf(s)), s.is_default ? "\u2713" : ""])
892
+ accounts.map((s) => [s.name, chainName(s.chain_id), truncateAddress(accountAddressOf(s)), s.is_default ? "\u2713" : ""])
885
893
  )
886
894
  );
887
895
  return EXIT.ok;
888
896
  }
889
897
  async function cmdWalletsBalances(args, d) {
890
898
  const { api } = await authed(args, d);
891
- const { safes } = await api.get("/user/accounts");
892
- const safe = pickSafe(safes, args.flags.safe);
899
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
900
+ const safe = pickSafe(accounts, args.flags.safe);
893
901
  if (!safe) {
894
902
  if (args.flags.safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
895
903
  throw new CliApiError("No Haven wallet found.", 404);
@@ -900,7 +908,7 @@ async function cmdWalletsBalances(args, d) {
900
908
  emit(
901
909
  d,
902
910
  args.flags.json,
903
- { account: safe.name, safe: safe.name, chainId: safe.chain_id, balances },
911
+ { account: safe.name, chainId: safe.chain_id, balances },
904
912
  () => [
905
913
  `${safe.name} \xB7 ${chainName(safe.chain_id)} \xB7 ${truncateAddress(accountAddressOf(safe))}`,
906
914
  balances.length === 0 ? " (no balances)" : table(["TOKEN", "BALANCE"], balances.map((b) => [b.symbol, b.formatted]))
@@ -908,15 +916,15 @@ async function cmdWalletsBalances(args, d) {
908
916
  );
909
917
  return EXIT.ok;
910
918
  }
911
- function pickSafe(safes, ref) {
912
- if (!ref) return safes.find((s) => s.is_default) ?? safes[0];
919
+ function pickSafe(accounts, ref) {
920
+ if (!ref) return accounts.find((s) => s.is_default) ?? accounts[0];
913
921
  const lower = ref.toLowerCase();
914
- return safes.find((s) => s.id === ref || accountAddressOf(s).toLowerCase() === lower);
922
+ return accounts.find((s) => s.id === ref || accountAddressOf(s).toLowerCase() === lower);
915
923
  }
916
924
  async function cmdWalletsFunding(args, d) {
917
925
  const { api } = await authed(args, d);
918
- const { safes } = await api.get("/user/accounts");
919
- const safe = pickSafe(safes, args.flags.safe);
926
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
927
+ const safe = pickSafe(accounts, args.flags.safe);
920
928
  if (!safe) {
921
929
  if (args.flags.safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
922
930
  throw new CliApiError("No Haven wallet found.", 404);
@@ -1059,8 +1067,8 @@ async function cmdBudgetGrant(args, d) {
1059
1067
  EXIT.refused
1060
1068
  );
1061
1069
  }
1062
- const accountAddress = agent.account_address ?? agent.safe_address;
1063
- const accountChainId = agent.account_chain_id ?? agent.safe_chain_id;
1070
+ const accountAddress = agent.account_address;
1071
+ const accountChainId = agent.account_chain_id;
1064
1072
  if (!accountAddress || !accountChainId) {
1065
1073
  throw new HavenCliError(`Agent ${id} has no wallet assigned yet \u2014 connect it first.`, EXIT.refused);
1066
1074
  }
@@ -1235,27 +1243,24 @@ async function cmdWalletRename(args, d) {
1235
1243
  if (!id || !name) throw new UsageError("Usage: haven wallets rename <id> <name>");
1236
1244
  const { api } = await authed(args, d);
1237
1245
  await api.put(`/user/accounts/${id}`, { name });
1238
- emit(d, args.flags.json, { ok: true, account_id: id, safe_id: id, name }, () => `Wallet ${id} renamed to "${name}".`);
1246
+ emit(d, args.flags.json, { ok: true, account_id: id, name }, () => `Wallet ${id} renamed to "${name}".`);
1239
1247
  return EXIT.ok;
1240
1248
  }
1241
- async function resolveSafeId(args, api) {
1249
+ async function resolveAccountId(args, api) {
1242
1250
  if (!args.flags.safe) return void 0;
1243
- const { safes } = await api.get("/user/accounts");
1244
- const safe = pickSafe(safes, args.flags.safe);
1251
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
1252
+ const safe = pickSafe(accounts, args.flags.safe);
1245
1253
  if (!safe) throw new UsageError(`No wallet matches "${args.flags.safe}".`);
1246
1254
  return safe.id;
1247
1255
  }
1248
1256
  async function cmdActivityList(args, d) {
1249
1257
  const { api } = await authed(args, d);
1250
- const safeId = await resolveSafeId(args, api);
1258
+ const accountId = await resolveAccountId(args, api);
1251
1259
  const params = new URLSearchParams({
1252
1260
  offset: String(args.flags.offset ?? 0),
1253
1261
  limit: String(args.flags.limit ?? 25)
1254
1262
  });
1255
- if (safeId) {
1256
- params.set("accountId", safeId);
1257
- params.set("safeId", safeId);
1258
- }
1263
+ if (accountId) params.set("accountId", accountId);
1259
1264
  if (args.flags.agent) params.set("agentId", args.flags.agent);
1260
1265
  const { transactions } = await api.get(`/transactions?${params.toString()}`);
1261
1266
  const visible = args.flags.direction ? transactions.filter((t) => t.direction === args.flags.direction) : transactions;
@@ -1270,7 +1275,7 @@ async function cmdActivityList(args, d) {
1270
1275
  t.direction === "in" ? "in" : "out",
1271
1276
  `${t.direction === "in" ? "+" : "-"}${t.valueFormatted} ${t.asset}`,
1272
1277
  t.source ?? "transfer",
1273
- t.safeName ?? ""
1278
+ t.accountName ?? ""
1274
1279
  ])
1275
1280
  )
1276
1281
  );
@@ -1279,15 +1284,12 @@ async function cmdActivityList(args, d) {
1279
1284
  async function cmdActivityExport(args, d) {
1280
1285
  if (args.flags.format === "sie") return exportSie(args, d);
1281
1286
  const { api } = await authed(args, d);
1282
- const safeId = await resolveSafeId(args, api);
1287
+ const accountId = await resolveAccountId(args, api);
1283
1288
  const params = new URLSearchParams({
1284
1289
  offset: String(args.flags.offset ?? 0),
1285
1290
  limit: String(args.flags.limit ?? 1e3)
1286
1291
  });
1287
- if (safeId) {
1288
- params.set("accountId", safeId);
1289
- params.set("safeId", safeId);
1290
- }
1292
+ if (accountId) params.set("accountId", accountId);
1291
1293
  if (args.flags.agent) params.set("agentId", args.flags.agent);
1292
1294
  const { transactions } = await api.get(`/transactions?${params.toString()}`);
1293
1295
  const visible = args.flags.direction ? transactions.filter((t) => t.direction === args.flags.direction) : transactions;
@@ -1300,7 +1302,6 @@ async function cmdActivityExport(args, d) {
1300
1302
  "token_symbol",
1301
1303
  "token_address",
1302
1304
  "counterparty_address",
1303
- "safe_address",
1304
1305
  "agent_name",
1305
1306
  "tx_hash",
1306
1307
  "chain_id",
@@ -1315,11 +1316,10 @@ async function cmdActivityExport(args, d) {
1315
1316
  t.tokenSymbol ?? t.asset ?? "",
1316
1317
  t.tokenAddress ?? "",
1317
1318
  (t.direction === "in" ? t.from : t.to) ?? "",
1318
- t.accountAddress ?? t.safeAddress ?? "",
1319
1319
  t.agentName ?? "",
1320
1320
  t.hash,
1321
1321
  t.chainId != null ? String(t.chainId) : "",
1322
- t.accountAddress ?? t.safeAddress ?? ""
1322
+ t.accountAddress ?? ""
1323
1323
  ]);
1324
1324
  d.o.text(toCsv(headers, rows), { format: "csv", rows: rows.length });
1325
1325
  return EXIT.ok;
@@ -1360,11 +1360,11 @@ async function cmdCatalogList(args, d) {
1360
1360
  return EXIT.ok;
1361
1361
  }
1362
1362
  async function resolveWalletAndToken(args, api, symbol) {
1363
- const { safes } = await api.get("/user/accounts");
1364
- if (safes.length === 0) {
1363
+ const accounts = accountsEnvelope(await api.get("/user/accounts"));
1364
+ if (accounts.length === 0) {
1365
1365
  throw new HavenCliError("No wallet on this account yet \u2014 finish onboarding first.", EXIT.refused);
1366
1366
  }
1367
- 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];
1367
+ 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];
1368
1368
  if (!safe) throw new UsageError(`No wallet matches --safe ${args.flags.safe}`);
1369
1369
  const { balances } = await api.get(
1370
1370
  `/balances/${accountAddressOf(safe)}?chain_id=${safe.chain_id}`
@@ -1375,7 +1375,7 @@ async function resolveWalletAndToken(args, api, symbol) {
1375
1375
  const known = balances.map((b) => b.symbol).join(", ");
1376
1376
  throw new UsageError(`Unknown token ${symbol} on this wallet's chain. Available: ${known || "none"}`);
1377
1377
  }
1378
- return { safeId: safe.id, token };
1378
+ return { accountId: safe.id, token };
1379
1379
  }
1380
1380
  var SETTLED = /* @__PURE__ */ new Set(["active", "expired", "cancelled", "failed"]);
1381
1381
  async function pollSetup(api, setupId, d, wait) {
@@ -1409,16 +1409,12 @@ async function cmdAgentsConnect(args, d) {
1409
1409
  if (!args.flags.budget || !args.flags.token || args.flags.period === void 0) {
1410
1410
  throw new UsageError("--budget, --token and --period are required (period is whole minutes; 0 means one-time)");
1411
1411
  }
1412
- const { safeId, token } = await resolveWalletAndToken(args, api, args.flags.token);
1412
+ const { accountId, token } = await resolveWalletAndToken(args, api, args.flags.token);
1413
1413
  const amount = parseTokenAmount(args.flags.budget, token.decimals, token.symbol);
1414
1414
  if (!amount.ok) throw new UsageError(amount.message);
1415
1415
  const setup = await api.post("/agent-connection-setups", {
1416
1416
  name,
1417
- // #2908: both id keys for the window — `account_id` is the #2907 twin
1418
- // (landing in P0's second round), `safe_id` is what a server without it
1419
- // reads; the request works against either.
1420
- account_id: safeId,
1421
- safe_id: safeId,
1417
+ account_id: accountId,
1422
1418
  allowances: [
1423
1419
  {
1424
1420
  token_address: token.address ?? "0x0000000000000000000000000000000000000000",