@haven_ai/cli 0.0.0-dev.202610141738.3a308de → 0.0.0-dev.202610142033.0d2f50f

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
@@ -166,7 +166,13 @@ never calls `activate` — that is the whole design.
166
166
  route). `--amount` is in
167
167
  whole tokens, read from your wallet's balances exactly like
168
168
  `agents connect`; `--recipient` pins the budget to one address (omit for an
169
- open budget); `--expires` takes unix seconds (default: 90 days).
169
+ open budget); `--expires` takes unix seconds (default: 90 days). A grant
170
+ adds a budget to an EMPTY (token, recipient) slot only: when the agent
171
+ already has a live budget there, the build is refused (exit 4,
172
+ `error_code: BUDGET_SLOT_OCCUPIED` with `existing_delegation_hash` under
173
+ `--json`, #3933) and the hint says to edit that budget on the agent's page,
174
+ which replaces it and stops the old one on-chain. A grant cannot replace it
175
+ — that would leave the old delegation enabled.
170
176
  - `budget revoke <agentId> <delegationHash>` prepares the sponsored
171
177
  revocation (no gas, one signature). The hash comes from
172
178
  `haven budget show <agentId> --hashes` or the dashboard. (`agents show` does
package/dist/cli.cjs CHANGED
@@ -3152,7 +3152,7 @@ async function checkTextForSecrets(text, deps) {
3152
3152
 
3153
3153
  // src/commands.ts
3154
3154
  var DEFAULT_API = "https://havenbackend-production-8a00.up.railway.app";
3155
- var CLI_VERSION = "0.0.0-dev.202610141738.3a308de";
3155
+ var CLI_VERSION = "0.0.0-dev.202610142033.0d2f50f";
3156
3156
  var CLI_CLIENT_IDENTITY = `@haven_ai/cli/${CLI_VERSION}`;
3157
3157
  function accountAddressOf(s) {
3158
3158
  return s.account_address ?? "";
@@ -3653,13 +3653,27 @@ async function cmdBudgetGrant(args, d) {
3653
3653
  }
3654
3654
  const amount = parseTokenAmount(args.flags.amount, token.decimals, token.symbol);
3655
3655
  if (!amount.ok) throw new UsageError(amount.message);
3656
- const built = await api.post(`/agents/${id}/delegations/build`, {
3657
- token_address: token.address,
3658
- recipient_address: args.flags.recipient ?? null,
3659
- budget_atomic: amount.atomic,
3660
- period_seconds: args.flags.period * 60,
3661
- ...args.flags.expires !== void 0 ? { expires_at: args.flags.expires } : {}
3662
- });
3656
+ let built;
3657
+ try {
3658
+ built = await api.post(`/agents/${id}/delegations/build`, {
3659
+ token_address: token.address,
3660
+ recipient_address: args.flags.recipient ?? null,
3661
+ budget_atomic: amount.atomic,
3662
+ period_seconds: args.flags.period * 60,
3663
+ ...args.flags.expires !== void 0 ? { expires_at: args.flags.expires } : {}
3664
+ });
3665
+ } catch (err) {
3666
+ const body = err instanceof CliApiError ? err.body : void 0;
3667
+ if (body?.error_code === "BUDGET_SLOT_OCCUPIED") {
3668
+ throw new HavenCliError(
3669
+ err instanceof Error ? err.message : "This agent already has a live budget for this token and recipient.",
3670
+ EXIT.refused,
3671
+ "Edit that budget on the agent's page in the Haven dashboard instead: editing replaces it and stops the old one on-chain. Open task and sub-budgets carved from the old budget end when it is stopped.",
3672
+ { error_code: "BUDGET_SLOT_OCCUPIED", existing_delegation_hash: body.existing_delegation_hash ?? null }
3673
+ );
3674
+ }
3675
+ throw err;
3676
+ }
3663
3677
  const emitGrant = (status) => emit(
3664
3678
  d,
3665
3679
  args.flags.json,