@haven_ai/cli 0.0.0-dev.202610061536.ad3de49 → 0.0.0-dev.202610071154.39eddce

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
@@ -126,7 +126,9 @@ haven feedback submit "<text>" # several unquoted words are joined int
126
126
 
127
127
  # manage (backend-only — no on-chain signing)
128
128
  haven agents pause <id> | resume <id>
129
- haven agents revoke <id> --yes # terminal; needs explicit --yes
129
+ haven agents revoke <id> [--keep-budget] --yes # terminal; needs explicit --yes; refuses
130
+ # while a budget is still live on-chain
131
+ # unless --keep-budget
130
132
  haven agents rotate-key <id> # new API key, shown once
131
133
  haven agents rename <id> <name>
132
134
  haven wallets rename <id> <name>
package/dist/cli.cjs CHANGED
@@ -41,7 +41,8 @@ function parseArgs(argv) {
41
41
  noWait: false,
42
42
  run: false,
43
43
  wait: false,
44
- hashes: false
44
+ hashes: false,
45
+ keepBudget: false
45
46
  };
46
47
  for (let i = 0; i < argv.length; i += 1) {
47
48
  const arg = argv[i];
@@ -49,6 +50,7 @@ function parseArgs(argv) {
49
50
  else if (arg === "--help" || arg === "-h") flags.help = true;
50
51
  else if (arg === "--version" || arg === "-v") flags.version = true;
51
52
  else if (arg === "--yes" || arg === "-y") flags.yes = true;
53
+ else if (arg === "--keep-budget") flags.keepBudget = true;
52
54
  else if (arg === "--no-wait") flags.noWait = true;
53
55
  else if (arg === "--run") flags.run = true;
54
56
  else if (arg === "--wait") flags.wait = true;
@@ -159,7 +161,8 @@ function helpText() {
159
161
  "Manage (backend-only \u2014 no on-chain signing):",
160
162
  " agents pause <id> Stop the agent spending; keeps its budget",
161
163
  " agents resume <id> Let it spend again",
162
- " agents revoke <id> --yes Permanently revoke an agent",
164
+ " agents revoke <id> --yes Permanently revoke an agent. Refuses while a",
165
+ " budget is still live on-chain unless --keep-budget",
163
166
  " agents rotate-key <id> Issue a new API key (shown once)",
164
167
  " agents rename <id> <name>",
165
168
  " wallets rename <id> <name>",
@@ -3147,7 +3150,7 @@ async function checkTextForSecrets(text, deps) {
3147
3150
 
3148
3151
  // src/commands.ts
3149
3152
  var DEFAULT_API = "https://havenbackend-production-8a00.up.railway.app";
3150
- var CLI_VERSION = "0.0.0-dev.202610061536.ad3de49";
3153
+ var CLI_VERSION = "0.0.0-dev.202610071154.39eddce";
3151
3154
  var CLI_CLIENT_IDENTITY = `@haven_ai/cli/${CLI_VERSION}`;
3152
3155
  function accountAddressOf(s) {
3153
3156
  return s.account_address ?? "";
@@ -3701,12 +3704,6 @@ async function cmdBudgetRevoke(args, d) {
3701
3704
  if (row.status === "revoked") {
3702
3705
  throw new HavenCliError(`Delegation ${hash} is already revoked.`, EXIT.refused);
3703
3706
  }
3704
- if (row.status === "replaced") {
3705
- throw new HavenCliError(
3706
- `Delegation ${hash} was already replaced by a newer grant \u2014 nothing to revoke.`,
3707
- EXIT.refused
3708
- );
3709
- }
3710
3707
  const prepared = await api.post(`/agents/${id}/delegations/${hash}/revoke`, {});
3711
3708
  const revokeUrl = prepared.revocation_url;
3712
3709
  if (!revokeUrl) {
@@ -3762,7 +3759,7 @@ async function cmdAgentLifecycle(args, d, action) {
3762
3759
  }
3763
3760
  async function cmdAgentRevoke(args, d) {
3764
3761
  const id = args.positionals[0];
3765
- if (!id) throw new UsageError("Usage: haven agents revoke <id> --yes");
3762
+ if (!id) throw new UsageError("Usage: haven agents revoke <id> [--keep-budget] --yes");
3766
3763
  if (!args.flags.yes) {
3767
3764
  throw new UsageError(
3768
3765
  `This permanently revokes agent ${id}.`,
@@ -3770,12 +3767,45 @@ async function cmdAgentRevoke(args, d) {
3770
3767
  );
3771
3768
  }
3772
3769
  const { api } = await authed(args, d);
3770
+ let live = [];
3771
+ try {
3772
+ const agent = await api.get(`/agents/${id}`);
3773
+ if ((agent.live_delegation_count ?? 0) > 0) {
3774
+ const { delegations } = await api.get(`/agents/${id}/delegations`);
3775
+ live = delegations.filter((r) => r.status === "pending" || r.status === "active" || r.status === "replaced");
3776
+ }
3777
+ } catch (err) {
3778
+ d.o.note(`Couldn't check budgets for agent ${id}, so the revocation was not attempted.`);
3779
+ throw err;
3780
+ }
3781
+ if (live.length > 0 && !args.flags.keepBudget) {
3782
+ throw new HavenCliError(
3783
+ `Agent ${id} still has a live on-chain budget. Revoking now would leave it redeemable by the delegate key.`,
3784
+ EXIT.refused,
3785
+ [
3786
+ ...live.map((r) => `haven budget revoke ${id} ${r.delegation_hash} # ${r.status}`),
3787
+ "Remove agent\u2026 in the dashboard ends every live budget with one signature, before revoking.",
3788
+ "To revoke the agent anyway and leave the budget live on-chain, re-run with --keep-budget."
3789
+ ].join("\n"),
3790
+ // The machine branch: a script skips the prose and reads the rows.
3791
+ { live_delegations: live.map(({ delegation_hash, status }) => ({ delegation_hash, status })) }
3792
+ );
3793
+ }
3773
3794
  await api.post(`/agents/${id}/revoke`);
3774
3795
  emit(
3775
3796
  d,
3776
3797
  args.flags.json,
3777
- { ok: true, agent_id: id, status: "revoked" },
3778
- () => `Agent ${id} revoked. To also remove its on-chain allowance, use the dashboard.`
3798
+ live.length > 0 ? {
3799
+ ok: true,
3800
+ agent_id: id,
3801
+ status: "revoked",
3802
+ live_delegations: live.map(({ delegation_hash, status }) => ({ delegation_hash, status }))
3803
+ } : { ok: true, agent_id: id, status: "revoked" },
3804
+ () => live.length > 0 ? [
3805
+ `Agent ${id} revoked.`,
3806
+ `Its budget is still live on-chain: the delegate key can keep spending until each delegation is revoked.`,
3807
+ ...live.map((r) => `haven budget revoke ${id} ${r.delegation_hash} # ${r.status}`)
3808
+ ].join("\n") : `Agent ${id} revoked. To also remove its on-chain allowance, use the dashboard.`
3779
3809
  );
3780
3810
  return EXIT.ok;
3781
3811
  }