@heyanon-arp/cli 0.0.18 → 0.0.19

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/cli.js CHANGED
@@ -617,6 +617,14 @@ var init_api = __esm({
617
617
  query
618
618
  );
619
619
  }
620
+ /**
621
+ * Signed `GET /v1/escrow/disputes/:delegationId`. The autonomous arbiter's
622
+ * verdict for a disputed delegation — winner + DID, evaluator source,
623
+ * reasoning, status, and the on-chain resolve signature. Parties only.
624
+ */
625
+ async getDisputeResolution(delegationId, signer) {
626
+ return this.signedRequest("GET", `/v1/escrow/disputes/${encodeURIComponent(delegationId)}`, null, signer);
627
+ }
620
628
  /**
621
629
  * Build the same canonical-JSON signing input the arp-server's
622
630
  * `SignedRequestGuard` recomputes (`{ method, path, query, body }`),
@@ -726,7 +734,7 @@ var import_simple_update_notifier = __toESM(require("simple-update-notifier"));
726
734
  // package.json
727
735
  var package_default = {
728
736
  name: "@heyanon-arp/cli",
729
- version: "0.0.18",
737
+ version: "0.0.19",
730
738
  description: "Command-line client for the Agent Relationship Protocol \u2014 register agents, sign envelopes, run escrowed work cycles on Solana.",
731
739
  license: "MIT",
732
740
  keywords: ["arp", "agent-relationship-protocol", "did", "solana", "escrow", "ed25519", "agents", "a2a", "cli"],
@@ -1142,26 +1150,32 @@ function warnIfForeignOwner(agent, serverUrl) {
1142
1150
  `
1143
1151
  );
1144
1152
  }
1145
- function resolveSenderAgent(cmdName, serverOverride, explicitFromDid) {
1153
+ function resolveSenderAgent(cmdName, serverOverride, explicitFromDid, explicitFromName) {
1146
1154
  const resolvedServerUrl = resolveServerUrl(serverOverride);
1155
+ if (explicitFromDid && explicitFromName) {
1156
+ throw new Error(`${cmdName}: pass either --from <name> OR --from-did <did>, not both.`);
1157
+ }
1147
1158
  if (explicitFromDid) {
1148
- if (explicitFromDid.startsWith("did:arp:")) {
1149
- const agent = loadAgentOrThrow(serverOverride, explicitFromDid);
1150
- warnIfForeignOwner(agent, resolvedServerUrl);
1151
- return agent;
1159
+ if (!explicitFromDid.startsWith("did:arp:")) {
1160
+ throw new Error(`${cmdName}: --from-did expects a did:arp:<...> DID \u2014 for an agent name use '--from ${explicitFromDid}'.`);
1152
1161
  }
1153
- const wanted = (0, import_sdk2.normalizeName)(explicitFromDid);
1162
+ const agent = loadAgentOrThrow(serverOverride, explicitFromDid);
1163
+ warnIfForeignOwner(agent, resolvedServerUrl);
1164
+ return agent;
1165
+ }
1166
+ if (explicitFromName) {
1167
+ const wanted = (0, import_sdk2.normalizeName)(explicitFromName);
1154
1168
  const named = listAgents().filter((row) => row.serverUrl === resolvedServerUrl && row.agent.name === wanted);
1155
1169
  if (named.length === 1) {
1156
1170
  warnIfForeignOwner(named[0].agent, resolvedServerUrl);
1157
1171
  return named[0].agent;
1158
1172
  }
1159
1173
  if (named.length === 0) {
1160
- throw new Error(`${cmdName}: no local agent named '${wanted}' for ${resolvedServerUrl}. Pass its did:arp: DID, or register/recover that agent locally first.`);
1174
+ throw new Error(`${cmdName}: no local agent named '${wanted}' for ${resolvedServerUrl}. Pass its --from-did <did>, or register/recover that agent locally first.`);
1161
1175
  }
1162
1176
  const dups = named.map((row) => ` ${row.agent.did}`).join("\n");
1163
1177
  throw new Error(
1164
- `${cmdName}: ${named.length} local agents share the name '${wanted}' for ${resolvedServerUrl} \u2014 ambiguous. Pass the did:arp: DID instead. Candidates:
1178
+ `${cmdName}: ${named.length} local agents share the name '${wanted}' for ${resolvedServerUrl} \u2014 ambiguous. Pass --from-did <did> instead. Candidates:
1165
1179
  ${dups}`
1166
1180
  );
1167
1181
  }
@@ -1175,7 +1189,7 @@ ${dups}`
1175
1189
  }
1176
1190
  const list = onServer.map((row) => ` ${row.agent.did}${row.agent.name ? ` (${row.agent.name})` : ""}`).join("\n");
1177
1191
  throw new Error(
1178
- `${cmdName}: ${onServer.length} agents registered for ${resolvedServerUrl} \u2014 refusing to silently sign as one of them. Pass --from-did <did> to disambiguate. Candidates:
1192
+ `${cmdName}: ${onServer.length} agents registered for ${resolvedServerUrl} \u2014 refusing to silently sign as one of them. Pass --from <name> or --from-did <did> to disambiguate. Candidates:
1179
1193
  ${list}`
1180
1194
  );
1181
1195
  }
@@ -1194,13 +1208,13 @@ function listAgents() {
1194
1208
  var import_chalk2 = __toESM(require("chalk"));
1195
1209
  init_api();
1196
1210
  function registerLifecycleCommands(root) {
1197
- root.command("update").description("Update an agent profile (description / tags). At least one flag is required. The agent name is immutable and cannot be changed.").argument("[did]", "Agent DID (did:arp:...) \u2014 optional when --from-did is given OR exactly one agent is registered for the resolved server.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Alias for the positional <did> \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--description <s>", "New description").option("--tag <s>", "Capability tag \u2014 REPLACES the existing list. Repeatable: --tag translation --tag fr", accumulate, []).option("--clear-tags", "Drop all tags (cannot be combined with --tag)", false).option("--json", "Machine-readable mode \u2014 emit the updated profile as a single JSON object on stdout (AgentPublic). Prelude moves to stderr. ", false).action(
1211
+ root.command("update").description("Update an agent profile (description / tags). At least one flag is required. The agent name is immutable and cannot be changed.").argument("[did]", "Agent DID (did:arp:...) \u2014 optional when --from-did is given OR exactly one agent is registered for the resolved server.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Alias for the positional <did> \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--description <s>", "New description").option("--tag <s>", "Capability tag \u2014 REPLACES the existing list. Repeatable: --tag translation --tag fr", accumulate, []).option("--clear-tags", "Drop all tags (cannot be combined with --tag)", false).option("--json", "Machine-readable mode \u2014 emit the updated profile as a single JSON object on stdout (AgentPublic). Prelude moves to stderr. ", false).action(
1198
1212
  async (did, opts) => {
1199
1213
  if (did !== void 0 && opts.fromDid !== void 0 && did !== opts.fromDid) {
1200
1214
  throw new Error(`update: positional <did> (${did}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
1201
1215
  }
1202
1216
  const explicitDid = did ?? opts.fromDid;
1203
- const targetDid = (explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("update", opts.server, void 0)).did;
1217
+ const targetDid = (explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("update", opts.server, void 0, opts.from)).did;
1204
1218
  const body = buildUpdateBody(opts);
1205
1219
  if (Object.keys(body).length === 0) {
1206
1220
  throw new Error("update: pass at least one of --description / --tag / --clear-tags");
@@ -1414,9 +1428,9 @@ function registerAcceptPrefsCommands(agents) {
1414
1428
  });
1415
1429
  prefs.command("show").description(
1416
1430
  "Read an agent's published accept-prefs (any DID \u2014 the read is signed with YOUR local agent key; any registered agent may read). Buyers: run this BEFORE `delegation offer` so the offer matches"
1417
- ).argument("<did>", "Agent DID to inspect (any agent, not just your own)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Emit only the AcceptPrefs JSON (or null) on stdout \u2014 jq-pipeable", false).action(async (did, _opts, cmd) => {
1431
+ ).argument("<did>", "Agent DID to inspect (any agent, not just your own)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Emit only the AcceptPrefs JSON (or null) on stdout \u2014 jq-pipeable", false).action(async (did, _opts, cmd) => {
1418
1432
  const opts = cmd.optsWithGlobals();
1419
- const sender = resolveSenderAgent("agents accept-prefs show", opts.server, opts.fromDid);
1433
+ const sender = resolveSenderAgent("agents accept-prefs show", opts.server, opts.fromDid, opts.from);
1420
1434
  const api = new ArpApiClient(opts.server);
1421
1435
  progress(opts.json, import_chalk3.default.dim(`Server: ${api.serverUrl}`));
1422
1436
  progress(opts.json, import_chalk3.default.dim(`Signer: ${sender.did}`));
@@ -1539,7 +1553,7 @@ var import_sdk5 = require("@heyanon-arp/sdk");
1539
1553
  var import_chalk5 = __toESM(require("chalk"));
1540
1554
  init_api();
1541
1555
  function resolveSigningAgent(opts) {
1542
- return opts.fromDid !== void 0 ? loadAgentOrThrow(opts.server, opts.fromDid) : resolveSenderAgent("block", opts.server, void 0);
1556
+ return opts.fromDid !== void 0 ? loadAgentOrThrow(opts.server, opts.fromDid) : resolveSenderAgent("block", opts.server, void 0, opts.from);
1543
1557
  }
1544
1558
  function formatBlockRow(b) {
1545
1559
  const scope = b.scope === import_sdk5.InboxBlockScopes.ACCOUNT ? import_chalk5.default.yellow("account") : import_chalk5.default.cyan("did");
@@ -1548,13 +1562,13 @@ function formatBlockRow(b) {
1548
1562
  }
1549
1563
  function registerBlockCommand(root) {
1550
1564
  const block = root.command("block").description("Manage your inbox blocklist \u2014 refuse inbound messages from an agent (and, by default, its whole owner account).");
1551
- block.command("add <did>").description("Block an agent. Default blocks the target\u2019s ENTIRE owner account (every sibling agent); --did-only blocks just this DID. You cannot block your own account.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent). The block applies account-wide regardless of which signs.").option("--did-only", "Block only this exact DID, not the whole owner account", false).option("--reason <text>", "Private note (max 512 chars), visible only to you").option("--json", "Machine-readable output", false).action(async (did, opts) => {
1565
+ block.command("add <did>").description("Block an agent. Default blocks the target\u2019s ENTIRE owner account (every sibling agent); --did-only blocks just this DID. You cannot block your own account.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent). The block applies account-wide regardless of which signs.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--did-only", "Block only this exact DID, not the whole owner account", false).option("--reason <text>", "Private note (max 512 chars), visible only to you").option("--json", "Machine-readable output", false).action(async (did, opts) => {
1552
1566
  await runAdd(did, opts);
1553
1567
  });
1554
- block.command("remove <did>").alias("rm").description("Remove a block. Pass the same DID (+ --did-only flag) you blocked with.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--did-only", "The original block was DID-level (didOnly)", false).option("--json", "Machine-readable output", false).action(async (did, opts) => {
1568
+ block.command("remove <did>").alias("rm").description("Remove a block. Pass the same DID (+ --did-only flag) you blocked with.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--did-only", "The original block was DID-level (didOnly)", false).option("--json", "Machine-readable output", false).action(async (did, opts) => {
1555
1569
  await runRemove(did, opts);
1556
1570
  });
1557
- block.command("list").description("List your account\u2019s blocks. Each row shows the DID you named + scope \u2014 never the resolved owner account or its other agents.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--json", "Machine-readable output \u2014 a JSON array.", false).action(async (opts) => {
1571
+ block.command("list").description("List your account\u2019s blocks. Each row shows the DID you named + scope \u2014 never the resolved owner account or its other agents.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable output \u2014 a JSON array.", false).action(async (opts) => {
1558
1572
  await runList(opts);
1559
1573
  });
1560
1574
  }
@@ -1767,7 +1781,7 @@ var UNTIL_PHASES = [
1767
1781
  var WAIT_DEFAULT_INTERVAL_SEC = 3;
1768
1782
  var WAIT_DEFAULT_TIMEOUT_SEC = 300;
1769
1783
  function registerStatusCommand(root) {
1770
- root.command("status").description("Where am I in the work cycle? FSM state + next-action hint for ONE relationship (signed reads)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable: single JSON object with the composed summary. Pipe-safe.", false).option(
1784
+ root.command("status").description("Where am I in the work cycle? FSM state + next-action hint for ONE relationship (signed reads)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable: single JSON object with the composed summary. Pipe-safe.", false).option(
1771
1785
  "--wait",
1772
1786
  `Block and poll until you can act (\`nextActionOwner === 'me'\` OR \`nextActionOwner === 'either' AND relationshipState === 'active'\`) OR the cycle terminates (COMPLETE / closed / not_found). Exits immediately if either condition is already true at first read. Default cadence ${WAIT_DEFAULT_INTERVAL_SEC}s, --wait-timeout ${WAIT_DEFAULT_TIMEOUT_SEC}s. Pairs with --json so a wrapping script can branch on the new state. Exit code 124 on timeout (unix \`timeout\` convention). Combine with --wait-verbose to see per-tick state snapshots during long waits \u2014 useful for "is it alive or stuck?" diagnosis without spawning a separate \`inbox --tail\` shell.`,
1773
1787
  false
@@ -1792,7 +1806,7 @@ function registerStatusCommand(root) {
1792
1806
  }
1793
1807
  async function runStatus(relationshipId, opts) {
1794
1808
  const api = new ArpApiClient(opts.server);
1795
- const sender = resolveSenderAgent("status", opts.server, opts.fromDid);
1809
+ const sender = resolveSenderAgent("status", opts.server, opts.fromDid, opts.from);
1796
1810
  if (!opts.json) {
1797
1811
  console.log(import_chalk8.default.dim(`Server: ${api.serverUrl}`));
1798
1812
  console.log(import_chalk8.default.dim(`Signer: ${sender.did}`));
@@ -2380,277 +2394,12 @@ function stateColor(state) {
2380
2394
  // src/commands/wallet.ts
2381
2395
  var import_sdk11 = require("@heyanon-arp/sdk");
2382
2396
  var import_utils = require("@noble/hashes/utils");
2383
- var import_web32 = require("@solana/web3.js");
2397
+ var import_web3 = require("@solana/web3.js");
2384
2398
  init_api();
2385
2399
  init_config();
2386
2400
 
2387
2401
  // src/solana/escrow-ix.ts
2388
2402
  var import_sdk9 = require("@heyanon-arp/sdk");
2389
- var import_web3 = require("@solana/web3.js");
2390
- var SPL_TOKEN_PROGRAM_ID = new import_web3.PublicKey(import_sdk9.SPL_TOKEN_PROGRAM_ID_BASE58);
2391
- var ASSOCIATED_TOKEN_PROGRAM_ID = new import_web3.PublicKey(import_sdk9.ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
2392
- var NATIVE_SOL_MINT = new import_web3.PublicKey(import_sdk9.NATIVE_SOL_MINT_BASE58);
2393
- function deriveLockPda(programId, lockId) {
2394
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.LOCK), Buffer.from(lockId)], programId)[0];
2395
- }
2396
- function deriveEscrowPda(programId, lockId) {
2397
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.ESCROW), Buffer.from(lockId)], programId)[0];
2398
- }
2399
- function deriveConfigPda(programId) {
2400
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.CONFIG)], programId)[0];
2401
- }
2402
- function deriveStakeVaultPda(programId) {
2403
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.STAKE_VAULT)], programId)[0];
2404
- }
2405
- function deriveCollateralConfigPda(programId, mint) {
2406
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.COLLATERAL), mint.toBuffer()], programId)[0];
2407
- }
2408
- function deriveDisputeResolutionPda(programId, lockId) {
2409
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.DISPUTE_RESOLUTION), Buffer.from(lockId)], programId)[0];
2410
- }
2411
- function deriveOperatorAuthPda(programId, operator) {
2412
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.OPERATOR_AUTH), operator.toBuffer()], programId)[0];
2413
- }
2414
- function deriveEventAuthorityPda(programId) {
2415
- return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk9.ESCROW_PDA_SEEDS.EVENT_AUTHORITY)], programId)[0];
2416
- }
2417
- function deriveAta(owner, mint) {
2418
- return import_web3.PublicKey.findProgramAddressSync([owner.toBuffer(), SPL_TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
2419
- }
2420
- function eventCpiTail(programId) {
2421
- return [
2422
- { pubkey: deriveEventAuthorityPda(programId), isSigner: false, isWritable: false },
2423
- { pubkey: programId, isSigner: false, isWritable: false }
2424
- ];
2425
- }
2426
- function meta(pubkey, opts = {}) {
2427
- return { pubkey, isSigner: opts.signer === true, isWritable: opts.writable === true };
2428
- }
2429
- function noArgIx(programId, name, keys) {
2430
- return new import_web3.TransactionInstruction({ programId, keys, data: Buffer.from((0, import_sdk9.buildLifecycleIxData)(name)) });
2431
- }
2432
- function buildCreateLockIx(input) {
2433
- const { programId, lockId } = input;
2434
- const native = input.mint === null;
2435
- const data = Buffer.from((0, import_sdk9.buildCreateLockIxData)({ lockId, amount: input.amount, conditionHash: input.conditionHash }, { native }));
2436
- const head = [
2437
- meta(input.payer, { signer: true, writable: true }),
2438
- meta(input.payee),
2439
- meta(deriveConfigPda(programId)),
2440
- meta(deriveLockPda(programId, lockId), { writable: true }),
2441
- meta(deriveCollateralConfigPda(programId, input.mint ?? NATIVE_SOL_MINT))
2442
- ];
2443
- const keys = native ? [...head, meta(deriveEscrowPda(programId, lockId), { writable: true }), meta(import_web3.SystemProgram.programId), ...eventCpiTail(programId)] : [
2444
- ...head,
2445
- meta(input.mint),
2446
- meta(deriveAta(input.payer, input.mint), { writable: true }),
2447
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2448
- meta(import_web3.SystemProgram.programId),
2449
- meta(SPL_TOKEN_PROGRAM_ID),
2450
- ...eventCpiTail(programId)
2451
- ];
2452
- return new import_web3.TransactionInstruction({ programId, keys, data });
2453
- }
2454
- function buildAcceptLockIx(input) {
2455
- const { programId, lockId } = input;
2456
- return noArgIx(programId, "accept_lock", [
2457
- meta(input.payee, { signer: true, writable: true }),
2458
- meta(deriveConfigPda(programId)),
2459
- meta(deriveStakeVaultPda(programId), { writable: true }),
2460
- meta(deriveLockPda(programId, lockId), { writable: true }),
2461
- meta(import_web3.SystemProgram.programId),
2462
- ...eventCpiTail(programId)
2463
- ]);
2464
- }
2465
- function buildSubmitWorkIx(input) {
2466
- const { programId, lockId } = input;
2467
- return noArgIx(programId, "submit_work", [
2468
- meta(input.payee, { signer: true }),
2469
- meta(deriveConfigPda(programId)),
2470
- meta(deriveLockPda(programId, lockId), { writable: true }),
2471
- ...eventCpiTail(programId)
2472
- ]);
2473
- }
2474
- function buildClaimWorkPaymentIx(input) {
2475
- const { programId, lockId } = input;
2476
- if (input.mint === null) {
2477
- return noArgIx(programId, "claim_work_payment_native", [
2478
- meta(input.authority, { signer: true, writable: true }),
2479
- meta(deriveStakeVaultPda(programId), { writable: true }),
2480
- meta(deriveLockPda(programId, lockId), { writable: true }),
2481
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2482
- meta(input.payer, { writable: true }),
2483
- meta(input.payee, { writable: true }),
2484
- meta(input.feeRecipient, { writable: true }),
2485
- meta(import_web3.SystemProgram.programId),
2486
- ...eventCpiTail(programId)
2487
- ]);
2488
- }
2489
- return noArgIx(programId, "claim_work_payment", [
2490
- meta(input.authority, { signer: true, writable: true }),
2491
- meta(deriveConfigPda(programId)),
2492
- meta(deriveStakeVaultPda(programId), { writable: true }),
2493
- meta(deriveLockPda(programId, lockId), { writable: true }),
2494
- meta(input.mint),
2495
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2496
- meta(input.payer, { writable: true }),
2497
- meta(input.payee, { writable: true }),
2498
- meta(deriveAta(input.payee, input.mint), { writable: true }),
2499
- meta(input.feeRecipient),
2500
- meta(deriveAta(input.feeRecipient, input.mint), { writable: true }),
2501
- meta(import_web3.SystemProgram.programId),
2502
- meta(SPL_TOKEN_PROGRAM_ID),
2503
- meta(ASSOCIATED_TOKEN_PROGRAM_ID),
2504
- ...eventCpiTail(programId)
2505
- ]);
2506
- }
2507
- function buildCancelLockIx(input) {
2508
- const { programId, lockId } = input;
2509
- if (input.mint === null) {
2510
- return noArgIx(programId, "cancel_lock_native", [
2511
- meta(input.payer, { signer: true, writable: true }),
2512
- meta(deriveLockPda(programId, lockId), { writable: true }),
2513
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2514
- meta(import_web3.SystemProgram.programId),
2515
- ...eventCpiTail(programId)
2516
- ]);
2517
- }
2518
- return noArgIx(programId, "cancel_lock", [
2519
- meta(input.payer, { signer: true, writable: true }),
2520
- meta(deriveConfigPda(programId)),
2521
- meta(deriveLockPda(programId, lockId), { writable: true }),
2522
- meta(input.mint),
2523
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2524
- meta(deriveAta(input.payer, input.mint), { writable: true }),
2525
- meta(import_web3.SystemProgram.programId),
2526
- meta(SPL_TOKEN_PROGRAM_ID),
2527
- meta(ASSOCIATED_TOKEN_PROGRAM_ID),
2528
- ...eventCpiTail(programId)
2529
- ]);
2530
- }
2531
- function buildClaimExpiredWorkIx(input) {
2532
- const { programId, lockId } = input;
2533
- if (input.mint === null) {
2534
- return noArgIx(programId, "claim_expired_work_native", [
2535
- meta(input.payer, { signer: true, writable: true }),
2536
- meta(deriveStakeVaultPda(programId), { writable: true }),
2537
- meta(deriveLockPda(programId, lockId), { writable: true }),
2538
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2539
- meta(import_web3.SystemProgram.programId),
2540
- ...eventCpiTail(programId)
2541
- ]);
2542
- }
2543
- return noArgIx(programId, "claim_expired_work", [
2544
- meta(input.payer, { signer: true, writable: true }),
2545
- meta(deriveConfigPda(programId)),
2546
- meta(deriveStakeVaultPda(programId), { writable: true }),
2547
- meta(deriveLockPda(programId, lockId), { writable: true }),
2548
- meta(input.mint),
2549
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2550
- meta(deriveAta(input.payer, input.mint), { writable: true }),
2551
- meta(import_web3.SystemProgram.programId),
2552
- meta(SPL_TOKEN_PROGRAM_ID),
2553
- meta(ASSOCIATED_TOKEN_PROGRAM_ID),
2554
- ...eventCpiTail(programId)
2555
- ]);
2556
- }
2557
- function buildOpenDisputeIx(input) {
2558
- const { programId, lockId } = input;
2559
- return noArgIx(programId, "open_dispute", [
2560
- meta(input.payer, { signer: true, writable: true }),
2561
- meta(deriveConfigPda(programId)),
2562
- meta(deriveStakeVaultPda(programId), { writable: true }),
2563
- meta(deriveLockPda(programId, lockId), { writable: true }),
2564
- meta(import_web3.SystemProgram.programId),
2565
- ...eventCpiTail(programId)
2566
- ]);
2567
- }
2568
- function buildResolveDisputeIx(input) {
2569
- const { programId, lockId } = input;
2570
- const native = input.mint === null;
2571
- const data = Buffer.from((0, import_sdk9.buildResolveDisputeIxData)(input.args, { native }));
2572
- if (native) {
2573
- return new import_web3.TransactionInstruction({
2574
- programId,
2575
- data,
2576
- keys: [
2577
- meta(input.operator, { signer: true, writable: true }),
2578
- meta(deriveOperatorAuthPda(programId, input.operator)),
2579
- meta(deriveStakeVaultPda(programId), { writable: true }),
2580
- meta(deriveLockPda(programId, lockId), { writable: true }),
2581
- meta(deriveDisputeResolutionPda(programId, lockId), { writable: true }),
2582
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2583
- meta(input.payer, { writable: true }),
2584
- meta(input.winner, { writable: true }),
2585
- meta(input.feeRecipient, { writable: true }),
2586
- meta(input.treasury, { writable: true }),
2587
- meta(import_web3.SystemProgram.programId),
2588
- ...eventCpiTail(programId)
2589
- ]
2590
- });
2591
- }
2592
- return new import_web3.TransactionInstruction({
2593
- programId,
2594
- data,
2595
- keys: [
2596
- meta(input.operator, { signer: true, writable: true }),
2597
- meta(deriveOperatorAuthPda(programId, input.operator)),
2598
- meta(deriveConfigPda(programId)),
2599
- meta(deriveStakeVaultPda(programId), { writable: true }),
2600
- meta(deriveLockPda(programId, lockId), { writable: true }),
2601
- meta(deriveDisputeResolutionPda(programId, lockId), { writable: true }),
2602
- meta(input.mint),
2603
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2604
- meta(input.payer, { writable: true }),
2605
- meta(input.winner, { writable: true }),
2606
- meta(deriveAta(input.winner, input.mint), { writable: true }),
2607
- meta(input.feeRecipient),
2608
- meta(deriveAta(input.feeRecipient, input.mint), { writable: true }),
2609
- meta(input.treasury, { writable: true }),
2610
- meta(import_web3.SystemProgram.programId),
2611
- meta(SPL_TOKEN_PROGRAM_ID),
2612
- meta(ASSOCIATED_TOKEN_PROGRAM_ID),
2613
- ...eventCpiTail(programId)
2614
- ]
2615
- });
2616
- }
2617
- function buildCloseDisputeIx(input) {
2618
- const { programId, lockId } = input;
2619
- if (input.mint === null) {
2620
- return noArgIx(programId, "close_dispute_native", [
2621
- meta(input.authority, { signer: true, writable: true }),
2622
- meta(deriveStakeVaultPda(programId), { writable: true }),
2623
- meta(deriveLockPda(programId, lockId), { writable: true }),
2624
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2625
- meta(input.payer, { writable: true }),
2626
- meta(input.payee, { writable: true }),
2627
- meta(import_web3.SystemProgram.programId),
2628
- ...eventCpiTail(programId)
2629
- ]);
2630
- }
2631
- return noArgIx(programId, "close_dispute", [
2632
- meta(input.authority, { signer: true, writable: true }),
2633
- meta(deriveConfigPda(programId)),
2634
- meta(deriveStakeVaultPda(programId), { writable: true }),
2635
- meta(deriveLockPda(programId, lockId), { writable: true }),
2636
- meta(input.mint),
2637
- meta(deriveEscrowPda(programId, lockId), { writable: true }),
2638
- meta(input.payer, { writable: true }),
2639
- meta(deriveAta(input.payer, input.mint), { writable: true }),
2640
- meta(input.payee, { writable: true }),
2641
- meta(import_web3.SystemProgram.programId),
2642
- meta(SPL_TOKEN_PROGRAM_ID),
2643
- meta(ASSOCIATED_TOKEN_PROGRAM_ID),
2644
- ...eventCpiTail(programId)
2645
- ]);
2646
- }
2647
- async function fetchLockAccount(conn, programId, delegationId) {
2648
- const lockId = (0, import_sdk9.deriveLockId)(delegationId);
2649
- const lockPda = deriveLockPda(programId, lockId);
2650
- const info = await conn.getAccountInfo(lockPda);
2651
- if (!info) return null;
2652
- return { lockId, lockPda, lock: (0, import_sdk9.decodeLockAccount)(Uint8Array.from(info.data)) };
2653
- }
2654
2403
 
2655
2404
  // src/commands/token-amount.ts
2656
2405
  var import_sdk10 = require("@heyanon-arp/sdk");
@@ -2684,8 +2433,8 @@ function normaliseDelegationId(raw) {
2684
2433
  }
2685
2434
  throw new Error(`wallet: --delegation-id must be either 'del_<uuid>' or a bare canonical-lowercase UUID (got '${raw}')`);
2686
2435
  }
2687
- var SPL_TOKEN_PROGRAM_ID2 = new import_web32.PublicKey(import_sdk11.SPL_TOKEN_PROGRAM_ID_BASE58);
2688
- var ASSOCIATED_TOKEN_PROGRAM_ID2 = new import_web32.PublicKey(import_sdk11.ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
2436
+ var SPL_TOKEN_PROGRAM_ID2 = new import_web3.PublicKey(import_sdk11.SPL_TOKEN_PROGRAM_ID_BASE58);
2437
+ var ASSOCIATED_TOKEN_PROGRAM_ID2 = new import_web3.PublicKey(import_sdk11.ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
2689
2438
  var FALLBACK_RPC_URL = "https://api.mainnet-beta.solana.com";
2690
2439
  function resolveRpcUrl(opts) {
2691
2440
  if (opts.rpcUrl !== void 0 && opts.rpcUrl !== "") return opts.rpcUrl;
@@ -2788,14 +2537,14 @@ function registerDerivePdas(cmd) {
2788
2537
  async function derivePdasHandler(opts) {
2789
2538
  const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
2790
2539
  const api = new ArpApiClient(opts.server);
2791
- const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts, "wallet derive-pdas"));
2540
+ const programId = new import_web3.PublicKey(await resolveProgramIdStrict(api, opts, "wallet derive-pdas"));
2792
2541
  const lockIdBytes = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
2793
2542
  const lockIdSeed = Buffer.from(lockIdBytes);
2794
2543
  const lockIdHex = Buffer.from(lockIdBytes).toString("hex");
2795
- const [lockPda] = import_web32.PublicKey.findProgramAddressSync([Buffer.from("lock"), lockIdSeed], programId);
2796
- const [escrowPda] = import_web32.PublicKey.findProgramAddressSync([Buffer.from("escrow"), lockIdSeed], programId);
2797
- const [configPda] = import_web32.PublicKey.findProgramAddressSync([Buffer.from("config")], programId);
2798
- const [eventAuthorityPda] = import_web32.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], programId);
2544
+ const [lockPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("lock"), lockIdSeed], programId);
2545
+ const [escrowPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("escrow"), lockIdSeed], programId);
2546
+ const [configPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("config")], programId);
2547
+ const [eventAuthorityPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], programId);
2799
2548
  return {
2800
2549
  delegation_id: normalisedDelegationId,
2801
2550
  lock_id_hex: lockIdHex,
@@ -2823,7 +2572,7 @@ function registerVerifyRelease(cmd) {
2823
2572
  ).option(
2824
2573
  "--program-id <pubkey>",
2825
2574
  "Deployed ARP escrow program id. STRICT: flag > ARP_ESCROW_PROGRAM_ID env > GET /v1/escrow/config > FAIL \u2014 a wrong-program read would silently report lock_never_created."
2826
- ).option("--from-did <did>", "Accepted for scripting symmetry with the signing commands; verify-release reads on-chain state only and needs no signer, so this is ignored.").option("--json", "Emit JSON instead of human text. jq-pipeable.", false).action(async (opts) => {
2575
+ ).option("--from-did <did>", "Accepted for scripting symmetry with the signing commands; verify-release reads on-chain state only and needs no signer, so this is ignored.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Emit JSON instead of human text. jq-pipeable.", false).action(async (opts) => {
2827
2576
  try {
2828
2577
  const out = await verifyReleaseHandler(opts);
2829
2578
  if (opts.json) {
@@ -2854,13 +2603,13 @@ function registerVerifyRelease(cmd) {
2854
2603
  async function verifyReleaseHandler(opts) {
2855
2604
  const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
2856
2605
  const api = new ArpApiClient(opts.server);
2857
- const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts));
2606
+ const programId = new import_web3.PublicKey(await resolveProgramIdStrict(api, opts));
2858
2607
  const rpcUrl = resolveRpcUrlStrict(opts);
2859
- const conn = new import_web32.Connection(rpcUrl, "confirmed");
2860
- const fetched = await fetchLockAccount(conn, programId, normalisedDelegationId);
2608
+ const conn = new import_web3.Connection(rpcUrl, "confirmed");
2609
+ const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, normalisedDelegationId);
2861
2610
  const lockId = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
2862
- const lockPda = deriveLockPda(programId, lockId);
2863
- const escrowPda = deriveEscrowPda(programId, lockId);
2611
+ const lockPda = (0, import_sdk9.deriveLockPda)(programId, lockId);
2612
+ const escrowPda = (0, import_sdk9.deriveEscrowPda)(programId, lockId);
2864
2613
  if (!fetched) {
2865
2614
  return {
2866
2615
  delegation_id: normalisedDelegationId,
@@ -2914,7 +2663,7 @@ function renderStatusLine(status) {
2914
2663
  function registerCreateLock(cmd) {
2915
2664
  cmd.command("create-lock").description(
2916
2665
  "Build + sign a create_lock Solana tx (native SOL or an SPL token); output JSON ready for attachments.escrow_lock. This command does NOT submit the tx to chain \u2014 it only signs the blob locally. Run this AFTER the worker accepts your offer; the actual on-chain submission happens inside `heyarp delegation fund <delegation-id> --escrow-lock-from-file <path>` (the server's escrow worker picks up the signed blob from the fund envelope's attachments and posts it). Watch for the `lock_id` appearing on-chain only AFTER `delegation fund` runs, not after this command."
2917
- ).option("--server <url>", "Override server URL for sender-key resolution").option("--from-did <did>", "Sender DID (= payer of the lock). Required when more than one agent on the host.").requiredOption("--delegation-id <id>", "Delegation UUID (drives the lock_id derivation)").requiredOption("--recipient-pubkey <base58>", "Payee Solana pubkey (recipient agent's settlement_pubkey)").option("--amount-lamports <int>", "NATIVE SOL: lock amount in lamports (1 SOL = 1_000_000_000). Required when --mint-pubkey is omitted; not allowed with it.").option("--mint-pubkey <base58>", "SPL token mint to lock. Omit for native SOL. Must be a legacy SPL Token mint (Token-2022 is not supported).").option("--amount-base-units <int>", "SPL: lock amount in the mint's base units (e.g. 1000000 = 1 USDC at 6 decimals). Canonical SPL amount input.").option(
2666
+ ).option("--server <url>", "Override server URL for sender-key resolution").option("--from-did <did>", "Sender DID (= payer of the lock). Required when more than one agent on the host.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").requiredOption("--delegation-id <id>", "Delegation UUID (drives the lock_id derivation)").requiredOption("--recipient-pubkey <base58>", "Payee Solana pubkey (recipient agent's settlement_pubkey)").option("--amount-lamports <int>", "NATIVE SOL: lock amount in lamports (1 SOL = 1_000_000_000). Required when --mint-pubkey is omitted; not allowed with it.").option("--mint-pubkey <base58>", "SPL token mint to lock. Omit for native SOL. Must be a legacy SPL Token mint (Token-2022 is not supported).").option("--amount-base-units <int>", "SPL: lock amount in the mint's base units (e.g. 1000000 = 1 USDC at 6 decimals). Canonical SPL amount input.").option(
2918
2667
  "--amount <decimal>",
2919
2668
  "SPL: lock amount as a human decimal (e.g. 1.5); converted using the mint's on-chain decimals. Convenience alternative to --amount-base-units."
2920
2669
  ).requiredOption("--condition-hash <hex>", "32-byte hex condition_hash from `heyarp escrow derive-condition-hash` (binds the delegation terms)").option(
@@ -3048,7 +2797,7 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
3048
2797
  if (amount === 0n) {
3049
2798
  throw new Error("wallet create-lock: lock amount must be greater than zero.");
3050
2799
  }
3051
- const [payerAta] = import_web32.PublicKey.findProgramAddressSync([payer.toBuffer(), SPL_TOKEN_PROGRAM_ID2.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID2);
2800
+ const [payerAta] = import_web3.PublicKey.findProgramAddressSync([payer.toBuffer(), SPL_TOKEN_PROGRAM_ID2.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID2);
3052
2801
  const ataInfo = await conn.getAccountInfo(payerAta);
3053
2802
  if (!ataInfo) {
3054
2803
  throw new Error(
@@ -3058,8 +2807,8 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
3058
2807
  if (ataInfo.data.length < 72) {
3059
2808
  throw new Error(`wallet create-lock: payer token account ${payerAta.toBase58()} is malformed (data length ${ataInfo.data.length} < 72).`);
3060
2809
  }
3061
- const ataMint = new import_web32.PublicKey(ataInfo.data.subarray(0, 32));
3062
- const ataOwner = new import_web32.PublicKey(ataInfo.data.subarray(32, 64));
2810
+ const ataMint = new import_web3.PublicKey(ataInfo.data.subarray(0, 32));
2811
+ const ataOwner = new import_web3.PublicKey(ataInfo.data.subarray(32, 64));
3063
2812
  if (!ataMint.equals(mint)) {
3064
2813
  throw new Error(`wallet create-lock: payer token account ${payerAta.toBase58()} is for mint ${ataMint.toBase58()}, not ${mint.toBase58()}.`);
3065
2814
  }
@@ -3080,7 +2829,7 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
3080
2829
  };
3081
2830
  }
3082
2831
  async function createLockHandler(opts) {
3083
- const agent = resolveSenderAgent("wallet create-lock", opts.server, opts.fromDid);
2832
+ const agent = resolveSenderAgent("wallet create-lock", opts.server, opts.fromDid, opts.from);
3084
2833
  const payerKp = keypairFromAgent(agent);
3085
2834
  const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
3086
2835
  const payee = parsePubkey(opts.recipientPubkey, "--recipient-pubkey");
@@ -3096,13 +2845,13 @@ async function createLockHandler(opts) {
3096
2845
  if (!offlineMode) {
3097
2846
  await preflightLockCurrency(api, agent, normalisedDelegationId, expectedLockAsset);
3098
2847
  }
3099
- const programId = new import_web32.PublicKey(await resolveProgramId(api, opts));
2848
+ const programId = new import_web3.PublicKey(await resolveProgramId(api, opts));
3100
2849
  const rpcUrl = resolveRpcUrl(opts);
3101
- const conn = new import_web32.Connection(rpcUrl, "confirmed");
2850
+ const conn = new import_web3.Connection(rpcUrl, "confirmed");
3102
2851
  const asset = await resolveCreateLockAsset(conn, opts, payerKp.publicKey, clusterCaip2);
3103
2852
  const amount = asset.amount;
3104
2853
  const lockIdBytes = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
3105
- const ix = buildCreateLockIx({
2854
+ const ix = (0, import_sdk9.buildCreateLockIx)({
3106
2855
  programId,
3107
2856
  lockId: lockIdBytes,
3108
2857
  payer: payerKp.publicKey,
@@ -3111,11 +2860,14 @@ async function createLockHandler(opts) {
3111
2860
  conditionHash,
3112
2861
  mint: asset.kind === "spl" ? asset.mint : null
3113
2862
  });
3114
- const tx = new import_web32.Transaction().add(ix);
2863
+ const tx = new import_web3.Transaction().add(ix);
3115
2864
  tx.feePayer = payerKp.publicKey;
3116
- const { blockhash } = await conn.getLatestBlockhash("confirmed");
2865
+ const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash("confirmed");
3117
2866
  tx.recentBlockhash = blockhash;
3118
2867
  tx.sign(payerKp);
2868
+ process.stderr.write(
2869
+ "\u26A0 create-lock: this signed blob is valid for only ~60-90s \u2014 run `heyarp delegation fund` NOW. If you wait, the create_lock tx is silently dropped on-chain and the delegation fails; re-run create-lock to retry.\n"
2870
+ );
3119
2871
  const blob = tx.serialize({ requireAllSignatures: true, verifySignatures: true });
3120
2872
  return {
3121
2873
  signed_tx_blob: blob.toString("base64"),
@@ -3138,22 +2890,26 @@ async function createLockHandler(opts) {
3138
2890
  // Record the program id the create_lock ix was built against.
3139
2891
  // `delegation offer` cross-checks this pre-flight so a stale
3140
2892
  // ESCRoW... fallback lock doesn't ship silently.
3141
- program_id: programId.toBase58()
2893
+ program_id: programId.toBase58(),
2894
+ // Blockhash + its expiry slot — the ~60-90s submission window for
2895
+ // this blob (see CreateLockOutput docs).
2896
+ blockhash,
2897
+ last_valid_block_height: lastValidBlockHeight
3142
2898
  };
3143
2899
  }
3144
2900
  function keypairFromAgent(agent) {
3145
2901
  const stored = base64ToBytes(agent.settlementSecretKeyB64);
3146
2902
  if (stored.length === 32) {
3147
- return import_web32.Keypair.fromSeed(stored);
2903
+ return import_web3.Keypair.fromSeed(stored);
3148
2904
  }
3149
2905
  if (stored.length === 64) {
3150
- return import_web32.Keypair.fromSecretKey(stored);
2906
+ return import_web3.Keypair.fromSecretKey(stored);
3151
2907
  }
3152
2908
  throw new Error(`agent ${agent.did}: settlementSecretKeyB64 must decode to 32 bytes (Ed25519 seed) or 64 bytes (Solana expanded form); got ${stored.length}`);
3153
2909
  }
3154
2910
  function parsePubkey(value, flag) {
3155
2911
  try {
3156
- return new import_web32.PublicKey(value);
2912
+ return new import_web3.PublicKey(value);
3157
2913
  } catch (err) {
3158
2914
  throw new Error(`${flag}: invalid base58 pubkey '${value}': ${err.message}`);
3159
2915
  }
@@ -3186,7 +2942,7 @@ function registerDelegationCommands(root) {
3186
2942
  registerCancel(cmd);
3187
2943
  }
3188
2944
  function registerOffer(parent) {
3189
- parent.command("offer").description("Open a new delegation addressed to <recipient-did> with the agreed terms INLINE (no escrow lock \u2014 fund AFTER acceptance via `delegation fund`).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--delegation-id <uuid>", "Override the auto-generated delegation id (UUID). Reuse the SAME id at `heyarp delegation fund` time. Useful for replay / scripting.").option("--title <s>", "Required: human-readable title for the offer").option("--brief <json>", "Optional structured brief (JSON object)").option("--criterion <s>", "acceptance_criteria \u2014 repeatable; pass --criterion once per bullet", collectRepeated, []).option("--deadline <rfc3339>", 'Optional RFC 3339 deadline (e.g. "2026-12-31T23:59:59Z")').option("--scope <text>", "scope_summary \u2014 short prose describing the agreed work. Required.").option("--amount <s>", 'Optional decimal-as-string amount (e.g. "10.00"). REQUIRES --currency if set.').option("--currency <s>", `Asset identifier: shorthand (${import_sdk12.WELL_KNOWN_ASSET_KEYS.join("|")}) OR raw CAIP-19 string.`).option("--currency-decimals <n>", "Decimal places for base-unit conversion (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
2945
+ parent.command("offer").description("Open a new delegation addressed to <recipient-did> with the agreed terms INLINE (no escrow lock \u2014 fund AFTER acceptance via `delegation fund`).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--delegation-id <uuid>", "Override the auto-generated delegation id (UUID). Reuse the SAME id at `heyarp delegation fund` time. Useful for replay / scripting.").option("--title <s>", "Required: human-readable title for the offer").option("--brief <json>", "Optional structured brief (JSON object)").option("--criterion <s>", "acceptance_criteria \u2014 repeatable; pass --criterion once per bullet", collectRepeated, []).option("--deadline <rfc3339>", 'Optional RFC 3339 deadline (e.g. "2026-12-31T23:59:59Z")').option("--scope <text>", "scope_summary \u2014 short prose describing the agreed work. Required.").option("--amount <s>", 'Optional decimal-as-string amount (e.g. "10.00"). REQUIRES --currency if set.').option("--currency <s>", `Asset identifier: shorthand (${import_sdk12.WELL_KNOWN_ASSET_KEYS.join("|")}) OR raw CAIP-19 string.`).option("--currency-decimals <n>", "Decimal places for base-unit conversion (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3190
2946
  "--json",
3191
2947
  'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"offer", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + the "reference this delegation" hints move to stderr; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
3192
2948
  false
@@ -3327,7 +3083,7 @@ async function runOffer(recipientDid, opts) {
3327
3083
  );
3328
3084
  }
3329
3085
  const api = new ArpApiClient(opts.server);
3330
- const sender = resolveSenderAgent("delegation offer", opts.server, opts.fromDid);
3086
+ const sender = resolveSenderAgent("delegation offer", opts.server, opts.fromDid, opts.from);
3331
3087
  const content = {
3332
3088
  action: import_sdk12.DelegationActions.OFFER,
3333
3089
  delegation_id: delegationId,
@@ -3426,7 +3182,7 @@ After the worker accepts, fund the escrow lock:`));
3426
3182
  }
3427
3183
  }
3428
3184
  function registerFund(parent) {
3429
- parent.command("fund").description("Fund an ACCEPTED delegation with the escrow lock (buyer-only). Run AFTER the worker accepts the offer.").argument("<delegation-id>", "Delegation UUID (the one you offered + the worker accepted)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3185
+ parent.command("fund").description("Fund an ACCEPTED delegation with the escrow lock (buyer-only). Run AFTER the worker accepts the offer.").argument("<delegation-id>", "Delegation UUID (the one you offered + the worker accepted)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3430
3186
  "--json",
3431
3187
  'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"fund", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude moves off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
3432
3188
  false
@@ -3467,7 +3223,7 @@ async function runFund(delegationId, opts) {
3467
3223
  );
3468
3224
  }
3469
3225
  const api = new ArpApiClient(opts.server);
3470
- const sender = resolveSenderAgent("delegation fund", opts.server, opts.fromDid);
3226
+ const sender = resolveSenderAgent("delegation fund", opts.server, opts.fromDid, opts.from);
3471
3227
  const signer = makeSigner(sender);
3472
3228
  const resolved = await resolveFundRefs("delegation fund", api, signer, { delegationId, selfDid: sender.did });
3473
3229
  if (escrowResult.lockProgramId !== void 0) {
@@ -3575,7 +3331,7 @@ async function resolveFundRefs(cmdName, api, signer, args) {
3575
3331
  );
3576
3332
  }
3577
3333
  function registerAccept(parent) {
3578
- parent.command("accept").description("Accept a PROPOSED delegation \u2014 promotes to ACCEPTED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3334
+ parent.command("accept").description("Accept a PROPOSED delegation \u2014 promotes to ACCEPTED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3579
3335
  "--json",
3580
3336
  'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"accept", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + pending-lock poll chatter move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
3581
3337
  false
@@ -3587,7 +3343,7 @@ function registerAccept(parent) {
3587
3343
  });
3588
3344
  }
3589
3345
  function registerDecline(parent) {
3590
- parent.command("decline").description("Decline a PROPOSED delegation \u2014 moves to DECLINED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").requiredOption(
3346
+ parent.command("decline").description("Decline a PROPOSED delegation \u2014 moves to DECLINED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").requiredOption(
3591
3347
  "--reason <code>",
3592
3348
  // surface the closed enum at help time so operators
3593
3349
  // don't have to read source to find acceptable values.
@@ -3604,7 +3360,7 @@ function registerDecline(parent) {
3604
3360
  });
3605
3361
  }
3606
3362
  function registerCancel(parent) {
3607
- parent.command("cancel").description("Cancel an OFFERED delegation \u2014 moves to CANCELED. Offerer-only (the OTHER side uses decline).").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3363
+ parent.command("cancel").description("Cancel an OFFERED delegation \u2014 moves to CANCELED. Offerer-only (the OTHER side uses decline).").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
3608
3364
  "--json",
3609
3365
  'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"cancel", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + pending-lock poll chatter move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
3610
3366
  false
@@ -3634,7 +3390,7 @@ async function runFollowupAction(relationshipId, delegationId, action, opts) {
3634
3390
  declinePayload = validatedDetail ? { reason, reasonDetail: validatedDetail } : { reason };
3635
3391
  }
3636
3392
  const api = new ArpApiClient(opts.server);
3637
- const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid);
3393
+ const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid, opts.from);
3638
3394
  const signer = makeSigner(sender);
3639
3395
  const resolved = await resolveDelegationRefs(cmdName, api, signer, { relationshipId, delegationId, action, selfDid: sender.did });
3640
3396
  if (resolved.state === import_sdk12.DelegationStates.PENDING_LOCK_FINALIZATION && opts.waitForLock !== false) {
@@ -4001,7 +3757,7 @@ var import_chalk10 = __toESM(require("chalk"));
4001
3757
  init_api();
4002
3758
  var ALLOWED_STATES = /* @__PURE__ */ new Set([import_sdk13.DelegationStates.OFFERED, import_sdk13.DelegationStates.ACCEPTED, import_sdk13.DelegationStates.DECLINED, import_sdk13.DelegationStates.CANCELED]);
4003
3759
  function registerDelegationsCommand(root) {
4004
- root.command("delegations").description("List delegations for a relationship (one row per delegationId, oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (offered|accepted|declined|canceled)").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
3760
+ root.command("delegations").description("List delegations for a relationship (one row per delegationId, oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (offered|accepted|declined|canceled)").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
4005
3761
  "--verbose",
4006
3762
  'After the one-line summaries, print a framed "Full delegation payloads (N rows)" block \u2014 each row labelled with full delegationId (`delegation accept` / `delegation decline` / `work request` need it) and dumped as JSON. Mutually exclusive with --json.',
4007
3763
  false
@@ -4018,7 +3774,7 @@ async function runDelegations(relationshipId, opts) {
4018
3774
  const limit = parseLimit2(opts.limit);
4019
3775
  const state = parseState(opts.state);
4020
3776
  const api = new ArpApiClient(opts.server);
4021
- const sender = resolveSenderAgent("delegations", opts.server, opts.fromDid);
3777
+ const sender = resolveSenderAgent("delegations", opts.server, opts.fromDid, opts.from);
4022
3778
  progress(opts.json, import_chalk10.default.dim(`Server: ${api.serverUrl}`));
4023
3779
  progress(opts.json, import_chalk10.default.dim(`Signer: ${sender.did}`));
4024
3780
  progress(opts.json, import_chalk10.default.dim(`Relationship: ${relationshipId}`));
@@ -4396,13 +4152,13 @@ function formatDoctorReport(r) {
4396
4152
  var import_chalk12 = __toESM(require("chalk"));
4397
4153
  init_api();
4398
4154
  function registerEnvelopeCommand(root) {
4399
- root.command("envelope").description("Fetch one canonical envelope by eventId \u2014 full body for inspection (signed read)").argument("<event-id>", "Event UUID \u2014 copy from `heyarp inbox`, `heyarp events`, or a counterparty citation").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable: emit only the envelope JSON object on stdout (no prelude, no chalk). Pipe-safe.", false).action(async (eventId, opts) => {
4155
+ root.command("envelope").description("Fetch one canonical envelope by eventId \u2014 full body for inspection (signed read)").argument("<event-id>", "Event UUID \u2014 copy from `heyarp inbox`, `heyarp events`, or a counterparty citation").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable: emit only the envelope JSON object on stdout (no prelude, no chalk). Pipe-safe.", false).action(async (eventId, opts) => {
4400
4156
  await runEnvelope(eventId, opts);
4401
4157
  });
4402
4158
  }
4403
4159
  async function runEnvelope(eventId, opts) {
4404
4160
  const api = new ArpApiClient(opts.server);
4405
- const sender = resolveSenderAgent("envelope", opts.server, opts.fromDid);
4161
+ const sender = resolveSenderAgent("envelope", opts.server, opts.fromDid, opts.from);
4406
4162
  if (!opts.json) {
4407
4163
  console.log(import_chalk12.default.dim(`Server: ${api.serverUrl}`));
4408
4164
  console.log(import_chalk12.default.dim(`Signer: ${sender.did}`));
@@ -4438,20 +4194,20 @@ init_api();
4438
4194
  // src/commands/escrow-actions.ts
4439
4195
  var import_node_crypto = require("crypto");
4440
4196
  var import_sdk16 = require("@heyanon-arp/sdk");
4441
- var import_web33 = require("@solana/web3.js");
4197
+ var import_web32 = require("@solana/web3.js");
4442
4198
  init_api();
4443
4199
  var FEE_BUFFER_LAMPORTS = 10000000n;
4444
4200
  async function setup(cmd, delegationIdArg, opts) {
4445
- const agent = resolveSenderAgent(cmd, opts.server, opts.fromDid);
4201
+ const agent = resolveSenderAgent(cmd, opts.server, opts.fromDid, opts.from);
4446
4202
  const keypair = keypairFromAgent(agent);
4447
4203
  const api = new ArpApiClient(opts.server);
4448
- const programId = new import_web33.PublicKey(await resolveProgramIdStrict(api, opts, cmd));
4204
+ const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts, cmd));
4449
4205
  const rpcUrl = resolveRpcUrlStrict(opts, cmd);
4450
- const conn = new import_web33.Connection(rpcUrl, "confirmed");
4206
+ const conn = new import_web32.Connection(rpcUrl, "confirmed");
4451
4207
  const delegationId = normaliseDelegationId(delegationIdArg);
4452
- const fetched = await fetchLockAccount(conn, programId, delegationId);
4208
+ const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, delegationId);
4453
4209
  if (!fetched) {
4454
- const lockPda = deriveLockPda(programId, (0, import_sdk16.deriveLockId)(delegationId)).toBase58();
4210
+ const lockPda = (0, import_sdk9.deriveLockPda)(programId, (0, import_sdk16.deriveLockId)(delegationId)).toBase58();
4455
4211
  throw new Error(
4456
4212
  `${cmd}: no on-chain Lock for delegation ${delegationId} (PDA ${lockPda} not found on ${rpcUrl}). Either the buyer hasn't funded yet (delegation fund \u2192 server relays create_lock), or you're pointing at the wrong cluster/program.`
4457
4213
  );
@@ -4478,8 +4234,8 @@ function deadlinePassed(ctx) {
4478
4234
  }
4479
4235
  var SYSTEM_PROGRAM_B58 = import_sdk16.SYSTEM_PROGRAM_ID_BASE58;
4480
4236
  function effectiveFeeRecipient(lock) {
4481
- if (lock.feeRecipientAtLock !== SYSTEM_PROGRAM_B58) return new import_web33.PublicKey(lock.feeRecipientAtLock);
4482
- if (lock.treasuryAtLock && lock.treasuryAtLock !== SYSTEM_PROGRAM_B58) return new import_web33.PublicKey(lock.treasuryAtLock);
4237
+ if (lock.feeRecipientAtLock !== SYSTEM_PROGRAM_B58) return new import_web32.PublicKey(lock.feeRecipientAtLock);
4238
+ if (lock.treasuryAtLock && lock.treasuryAtLock !== SYSTEM_PROGRAM_B58) return new import_web32.PublicKey(lock.treasuryAtLock);
4483
4239
  throw new Error(
4484
4240
  "escrow: this lock snapshots the system program as BOTH fee_recipient and treasury \u2014 no writable fee account exists; the on-chain Config was initialized inconsistently."
4485
4241
  );
@@ -4497,7 +4253,7 @@ async function preflightLamports(ctx, stake, what) {
4497
4253
  }
4498
4254
  }
4499
4255
  async function sendIx(ctx, ix) {
4500
- const tx = new import_web33.Transaction().add(ix);
4256
+ const tx = new import_web32.Transaction().add(ix);
4501
4257
  tx.feePayer = ctx.keypair.publicKey;
4502
4258
  const { blockhash, lastValidBlockHeight } = await ctx.conn.getLatestBlockhash("confirmed");
4503
4259
  tx.recentBlockhash = blockhash;
@@ -4543,7 +4299,7 @@ async function acceptHandler(delegationId, opts) {
4543
4299
  const stake = ctx.lock.workerStakeAtLock;
4544
4300
  await preflightLamports(ctx, stake, `the worker stake (${stake} lamports, returned when the lock settles in your favour)`);
4545
4301
  progress(ctx.opts.json, `accepting lock ${ctx.lock.lockId.slice(0, 16)}\u2026 \u2014 staking ${stake} lamports from ${ctx.keypair.publicKey.toBase58()}`);
4546
- const sig = await sendIx(ctx, buildAcceptLockIx({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
4302
+ const sig = await sendIx(ctx, (0, import_sdk9.buildAcceptLockIx)({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
4547
4303
  emit(ctx, "accept", sig, { worker_stake: stake.toString() });
4548
4304
  }
4549
4305
  async function submitWorkHandler(delegationId, opts) {
@@ -4555,10 +4311,10 @@ async function submitWorkHandler(delegationId, opts) {
4555
4311
  `escrow submit-work: the work window expired at ${expiryIso(ctx)} \u2014 the chain will reject submit_work and the buyer can claim the escrow back (claim_expired_work). Nothing to salvage on-chain.`
4556
4312
  );
4557
4313
  }
4558
- const sig = await sendIx(ctx, buildSubmitWorkIx({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
4314
+ const sig = await sendIx(ctx, (0, import_sdk9.buildSubmitWorkIx)({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
4559
4315
  let reviewDeadline = null;
4560
4316
  try {
4561
- const fresh = await fetchLockAccount(ctx.conn, ctx.programId, ctx.delegationId);
4317
+ const fresh = await (0, import_sdk9.fetchLockAccount)(ctx.conn, ctx.programId, ctx.delegationId);
4562
4318
  if (fresh && fresh.lock.state === import_sdk16.LockStates.SUBMITTED && fresh.lock.expiry > 0n) {
4563
4319
  reviewDeadline = new Date(Number(fresh.lock.expiry) * 1e3).toISOString();
4564
4320
  }
@@ -4593,13 +4349,13 @@ async function claimHandler(delegationId, opts) {
4593
4349
  );
4594
4350
  const sig = await sendIx(
4595
4351
  ctx,
4596
- buildClaimWorkPaymentIx({
4352
+ (0, import_sdk9.buildClaimWorkPaymentIx)({
4597
4353
  programId: ctx.programId,
4598
4354
  lockId: ctx.lockId,
4599
4355
  authority: ctx.keypair.publicKey,
4600
- payer: new import_web33.PublicKey(ctx.lock.payer),
4601
- payee: new import_web33.PublicKey(ctx.lock.payee),
4602
- mint: ctx.lock.isNative ? null : new import_web33.PublicKey(ctx.lock.mint),
4356
+ payer: new import_web32.PublicKey(ctx.lock.payer),
4357
+ payee: new import_web32.PublicKey(ctx.lock.payee),
4358
+ mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint),
4603
4359
  feeRecipient: effectiveFeeRecipient(ctx.lock)
4604
4360
  })
4605
4361
  );
@@ -4611,11 +4367,11 @@ async function cancelHandler(delegationId, opts) {
4611
4367
  requireSigner(ctx, "payer", ctx.lock.payer);
4612
4368
  const sig = await sendIx(
4613
4369
  ctx,
4614
- buildCancelLockIx({
4370
+ (0, import_sdk9.buildCancelLockIx)({
4615
4371
  programId: ctx.programId,
4616
4372
  lockId: ctx.lockId,
4617
4373
  payer: ctx.keypair.publicKey,
4618
- mint: ctx.lock.isNative ? null : new import_web33.PublicKey(ctx.lock.mint)
4374
+ mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
4619
4375
  })
4620
4376
  );
4621
4377
  emit(ctx, "cancel", sig, { refunded_amount: ctx.lock.amount.toString() });
@@ -4629,11 +4385,11 @@ async function claimExpiredHandler(delegationId, opts) {
4629
4385
  }
4630
4386
  const sig = await sendIx(
4631
4387
  ctx,
4632
- buildClaimExpiredWorkIx({
4388
+ (0, import_sdk9.buildClaimExpiredWorkIx)({
4633
4389
  programId: ctx.programId,
4634
4390
  lockId: ctx.lockId,
4635
4391
  payer: ctx.keypair.publicKey,
4636
- mint: ctx.lock.isNative ? null : new import_web33.PublicKey(ctx.lock.mint)
4392
+ mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
4637
4393
  })
4638
4394
  );
4639
4395
  emit(ctx, "claim-expired", sig, { refunded_amount: ctx.lock.amount.toString(), worker_stake_forfeited: ctx.lock.workerStakeAtLock.toString() });
@@ -4650,7 +4406,7 @@ async function disputeOpenHandler(delegationId, opts) {
4650
4406
  const stake = ctx.lock.workerStakeAtLock;
4651
4407
  await preflightLamports(ctx, stake, `the dispute stake (${stake} lamports \u2014 returned if the operator rules for you or the dispute times out)`);
4652
4408
  progress(ctx.opts.json, `opening dispute \u2014 staking ${stake} lamports; the operator has the dispute window to rule, after that either party can close`);
4653
- const sig = await sendIx(ctx, buildOpenDisputeIx({ programId: ctx.programId, lockId: ctx.lockId, payer: ctx.keypair.publicKey }));
4409
+ const sig = await sendIx(ctx, (0, import_sdk9.buildOpenDisputeIx)({ programId: ctx.programId, lockId: ctx.lockId, payer: ctx.keypair.publicKey }));
4654
4410
  emit(ctx, "dispute-open", sig, { buyer_stake: stake.toString() });
4655
4411
  }
4656
4412
  async function disputeCloseHandler(delegationId, opts) {
@@ -4667,13 +4423,13 @@ async function disputeCloseHandler(delegationId, opts) {
4667
4423
  }
4668
4424
  const sig = await sendIx(
4669
4425
  ctx,
4670
- buildCloseDisputeIx({
4426
+ (0, import_sdk9.buildCloseDisputeIx)({
4671
4427
  programId: ctx.programId,
4672
4428
  lockId: ctx.lockId,
4673
4429
  authority: ctx.keypair.publicKey,
4674
- payer: new import_web33.PublicKey(ctx.lock.payer),
4675
- payee: new import_web33.PublicKey(ctx.lock.payee),
4676
- mint: ctx.lock.isNative ? null : new import_web33.PublicKey(ctx.lock.mint)
4430
+ payer: new import_web32.PublicKey(ctx.lock.payer),
4431
+ payee: new import_web32.PublicKey(ctx.lock.payee),
4432
+ mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
4677
4433
  })
4678
4434
  );
4679
4435
  emit(ctx, "dispute-close", sig, {});
@@ -4699,15 +4455,15 @@ async function disputeResolveHandler(delegationId, opts) {
4699
4455
  const disputeId = Uint8Array.from(Buffer.from(disputeUuid.replace(/-/g, ""), "hex"));
4700
4456
  const sig = await sendIx(
4701
4457
  ctx,
4702
- buildResolveDisputeIx({
4458
+ (0, import_sdk9.buildResolveDisputeIx)({
4703
4459
  programId: ctx.programId,
4704
4460
  lockId: ctx.lockId,
4705
4461
  operator: ctx.keypair.publicKey,
4706
- payer: new import_web33.PublicKey(ctx.lock.payer),
4707
- winner: new import_web33.PublicKey(winner),
4462
+ payer: new import_web32.PublicKey(ctx.lock.payer),
4463
+ winner: new import_web32.PublicKey(winner),
4708
4464
  feeRecipient: effectiveFeeRecipient(ctx.lock),
4709
- treasury: new import_web33.PublicKey(ctx.lock.treasuryAtLock),
4710
- mint: ctx.lock.isNative ? null : new import_web33.PublicKey(ctx.lock.mint),
4465
+ treasury: new import_web32.PublicKey(ctx.lock.treasuryAtLock),
4466
+ mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint),
4711
4467
  args: { isPayerWinner, reasonHash, disputeId }
4712
4468
  })
4713
4469
  );
@@ -4715,16 +4471,16 @@ async function disputeResolveHandler(delegationId, opts) {
4715
4471
  }
4716
4472
  async function showHandler(delegationId, opts) {
4717
4473
  const api = new ArpApiClient(opts.server);
4718
- const programId = new import_web33.PublicKey(await resolveProgramIdStrict(api, opts, "escrow show"));
4474
+ const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts, "escrow show"));
4719
4475
  const rpcUrl = resolveRpcUrlStrict(opts, "escrow show");
4720
- const conn = new import_web33.Connection(rpcUrl, "confirmed");
4476
+ const conn = new import_web32.Connection(rpcUrl, "confirmed");
4721
4477
  const normalised = normaliseDelegationId(delegationId);
4722
- const fetched = await fetchLockAccount(conn, programId, normalised);
4478
+ const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, normalised);
4723
4479
  if (!fetched) {
4724
4480
  jsonOut({
4725
4481
  delegation_id: normalised.slice("del_".length),
4726
4482
  lock_exists: false,
4727
- lock_pda: deriveLockPda(programId, (0, import_sdk16.deriveLockId)(normalised)).toBase58(),
4483
+ lock_pda: (0, import_sdk9.deriveLockPda)(programId, (0, import_sdk16.deriveLockId)(normalised)).toBase58(),
4728
4484
  rpc_url: redactRpcUrl(rpcUrl)
4729
4485
  });
4730
4486
  return;
@@ -4749,7 +4505,34 @@ async function showHandler(delegationId, opts) {
4749
4505
  });
4750
4506
  }
4751
4507
  function sharedFlags(cmd) {
4752
- return cmd.option("--server <url>", "Override ARP server base URL (program-id discovery)").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--rpc-url <url>", "Solana RPC URL (STRICT: flag > ARP_ESCROW_RPC_URL env > `heyarp config rpcUrl`; no public fallback for state-changing txs)").option("--program-id <pubkey>", "Escrow program id (STRICT: flag > env > server discovery; no hardcoded fallback)").option("--json", "Machine-readable JSON output", false);
4508
+ return cmd.option("--server <url>", "Override ARP server base URL (program-id discovery)").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--rpc-url <url>", "Solana RPC URL (STRICT: flag > ARP_ESCROW_RPC_URL env > `heyarp config rpcUrl`; no public fallback for state-changing txs)").option("--program-id <pubkey>", "Escrow program id (STRICT: flag > env > server discovery; no hardcoded fallback)").option("--json", "Machine-readable JSON output", false);
4509
+ }
4510
+ async function disputeShowHandler(delegationId, opts) {
4511
+ const delId = delegationId.replace(/^del_/, "");
4512
+ const api = new ArpApiClient(opts.server);
4513
+ const sender = resolveSenderAgent("escrow dispute show", opts.server, opts.fromDid, opts.from);
4514
+ const row = await api.getDisputeResolution(delId, makeSigner(sender));
4515
+ progress(opts.json, `Server: ${api.serverUrl}`);
4516
+ progress(opts.json, `Signer: ${sender.did}`);
4517
+ if (opts.json) {
4518
+ jsonOut(row);
4519
+ return;
4520
+ }
4521
+ const winner = row.winnerRole === "payer" ? "BUYER (payer)" : row.winnerRole === "payee" ? "WORKER (payee)" : "(undecided)";
4522
+ console.log("");
4523
+ console.log(`Dispute resolution \u2014 delegation ${row.delegationId}`);
4524
+ console.log(` status: ${row.status}`);
4525
+ console.log(` winner: ${winner}${row.winnerDid ? ` ${row.winnerDid}` : ""}`);
4526
+ console.log(` is_payer_winner: ${row.isPayerWinner}`);
4527
+ console.log(` source: ${row.verdictSource ?? "(none)"} policy: ${row.policyId ?? "(none)"}`);
4528
+ console.log(` snapshot_hash: ${row.snapshotHash ?? "(none)"}`);
4529
+ console.log(` reason_hash: ${row.reasonHashHex ?? "(none)"}`);
4530
+ console.log(` resolve tx: ${row.solanaSignature ?? "(none)"}`);
4531
+ console.log(` attempts: ${row.attempts}${row.lastError ? ` last_error: ${row.lastError}` : ""}`);
4532
+ console.log("\n reasoning:");
4533
+ console.log(
4534
+ (row.reasoning ?? "(none)").split("\n").map((l) => ` ${l}`).join("\n")
4535
+ );
4753
4536
  }
4754
4537
  function registerEscrowActionCommands(escrow) {
4755
4538
  sharedFlags(
@@ -4785,6 +4568,9 @@ function registerEscrowActionCommands(escrow) {
4785
4568
  "OPERATOR: rule the dispute (winner takes the escrow; stakes split per config). Requires the on-chain-registered operator key. Disputing \u2192 DisputeResolved."
4786
4569
  ).option("--payer-wins", "Rule for the buyer").option("--payee-wins", "Rule for the worker").option("--reason <text>", "Resolution reasoning \u2014 sha256 recorded on-chain as reason_hash")
4787
4570
  ).action(disputeResolveHandler);
4571
+ dispute.command("show <delegation-id>").description(
4572
+ "Read the arbiter's verdict for a disputed delegation \u2014 winner + DID, source (llm | objective_fallback), reasoning, status, resolve tx. Signed server read; parties only."
4573
+ ).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable JSON output", false).action(disputeShowHandler);
4788
4574
  sharedFlags(escrow.command("show <delegation-id>").description("Decode + print the on-chain Lock account (state, parties, amounts, rolling deadline). Read-only.")).action(
4789
4575
  showHandler
4790
4576
  );
@@ -4802,12 +4588,12 @@ function registerEscrowCommands(root) {
4802
4588
  ).requiredOption("--delegation-id <id>", "Delegation UUID this lock binds (drives the on-chain lock_id + the condition_hash identity binding)").requiredOption("--scope <text>", "scope_summary \u2014 short prose describing the agreed work").option(
4803
4589
  "--currency <s>",
4804
4590
  `Asset identifier bound into the hash: shorthand (${import_sdk17.WELL_KNOWN_ASSET_KEYS.join("|")}) OR raw CAIP-19 string. Optional but must match the offer's --currency.`
4805
- ).option("--currency-decimals <n>", "Decimal places (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable JSON: {delegation_id, condition_hash_hex, projected_subset}", false).action(async (opts) => {
4591
+ ).option("--currency-decimals <n>", "Decimal places (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable JSON: {delegation_id, condition_hash_hex, projected_subset}", false).action(async (opts) => {
4806
4592
  await runDeriveConditionHash(opts);
4807
4593
  });
4808
4594
  cmd.command("recover-sequence").description(
4809
4595
  "Repair a desynced local `lastSenderSequence` after a post-commit failure the CLI couldn't auto-classify (e.g. `INTERNAL_SERVER_ERROR` from the global Internal filter \u2014 pre-/post-commit origin is ambiguous, so auto-advance is unsafe). Queries the server's owner-only `/sender-sequence` endpoint and compares; with --apply, updates local agent state to match. Default is dry-run \u2014 prints the diff and exits 0 if in-sync, 1 if drift detected."
4810
- ).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--apply", "Apply the fix (write the server-known value to local state). Default: dry-run.", false).option("--json", "Machine-readable JSON: {local, server, drift, applied}", false).action(async (opts) => {
4596
+ ).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--apply", "Apply the fix (write the server-known value to local state). Default: dry-run.", false).option("--json", "Machine-readable JSON: {local, server, drift, applied}", false).action(async (opts) => {
4811
4597
  await runRecoverSequence(opts);
4812
4598
  });
4813
4599
  }
@@ -4876,7 +4662,7 @@ async function runDeriveConditionHash(opts) {
4876
4662
  throw new Error(`${cmdName}: --scope is required (binds scope_summary into the condition_hash)`);
4877
4663
  }
4878
4664
  const api = new ArpApiClient(opts.server);
4879
- const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid);
4665
+ const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid, opts.from);
4880
4666
  progress(opts.json, import_chalk13.default.dim(`Server: ${api.serverUrl}`));
4881
4667
  progress(opts.json, import_chalk13.default.dim(`Signer: ${sender.did}`));
4882
4668
  const subset = projectDelegationForHash(cmdName, opts, delegationId);
@@ -4905,7 +4691,7 @@ function classifyRecoverOutcome(local, server) {
4905
4691
  return { kind: "ahead", local, server, drift: local - server };
4906
4692
  }
4907
4693
  async function runRecoverSequence(opts) {
4908
- const sender = resolveSenderAgent("escrow recover-sequence", opts.server, opts.fromDid);
4694
+ const sender = resolveSenderAgent("escrow recover-sequence", opts.server, opts.fromDid, opts.from);
4909
4695
  const signer = makeSigner(sender);
4910
4696
  const api = new ArpApiClient(opts.server);
4911
4697
  const local = sender.lastSenderSequence ?? 0;
@@ -4966,7 +4752,7 @@ var import_sdk18 = require("@heyanon-arp/sdk");
4966
4752
  var import_chalk14 = __toESM(require("chalk"));
4967
4753
  init_api();
4968
4754
  function registerEventsCommand(root) {
4969
- root.command("events").description("List events for a relationship (chain order, ascending index)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--since <n>", "Cursor: only events with relationshipEventIndex >= since").option("--limit <n>", "Max events to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
4755
+ root.command("events").description("List events for a relationship (chain order, ascending index)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--since <n>", "Cursor: only events with relationshipEventIndex >= since").option("--limit <n>", "Max events to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
4970
4756
  "--verbose",
4971
4757
  'After the summary table, print a framed "Full event payloads (N rows)" block \u2014 each event labelled with full eventId + serverEventHash and dumped as JSON. Mutually exclusive with --json.',
4972
4758
  false
@@ -5005,7 +4791,7 @@ async function runEvents(relationshipId, opts) {
5005
4791
  const limit = parseLimit3(opts.limit);
5006
4792
  const since = parseSince(opts.since);
5007
4793
  const api = new ArpApiClient(opts.server);
5008
- const sender = resolveSenderAgent("events", opts.server, opts.fromDid);
4794
+ const sender = resolveSenderAgent("events", opts.server, opts.fromDid, opts.from);
5009
4795
  if (!opts.json) {
5010
4796
  console.log(import_chalk14.default.dim(`Server: ${api.serverUrl}`));
5011
4797
  console.log(import_chalk14.default.dim(`Signer: ${sender.did}`));
@@ -6045,7 +5831,7 @@ function registerInboxCommand(root) {
6045
5831
  ).argument("[did]", "Recipient DID (did:arp:...) \u2014 must have local state. Optional when --from-did is given OR exactly one agent is registered for the resolved server.").option("--server <url>", "Override ARP server base URL").option("--limit <n>", "Max events to return (1..100)", "20").option("--before <iso>", "Cursor: only events strictly OLDER than this RFC 3339 timestamp").option("--before-event-id <id>", "Tiebreaker for --before \u2014 pass the previous page's last eventId").option(
6046
5832
  "--since <iso>",
6047
5833
  "Forward cursor: only events strictly NEWER than this RFC 3339 timestamp. Polling workers persist this between iterations to skip already-handled envelopes (fixes the double-fire pattern of re-reading from the same head). Pages are returned OLDEST-FIRST when --since is used alone (so a poller can advance its watermark to the page tail without losing backlogged events); combine with --before for a newest-first range query."
6048
- ).option("--since-event-id <id>", "Tiebreaker for --since \u2014 pass the previous tick's last handled eventId. Combine with --since for same-millisecond stability.").option("--verbose", "After the table, print the full JSON envelope for each event with a per-row label that includes the full serverEventHash + eventId", false).option("--json", "Machine-readable mode \u2014 emit a single JSON array of events, no human-format summary, no chalk colors. Pipe-safe.", false).option("--full-ids", "Print sender DID and full serverEventHash in the table (no truncation). Use when you need to copy-paste either value into another command.", false).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option(
5834
+ ).option("--since-event-id <id>", "Tiebreaker for --since \u2014 pass the previous tick's last handled eventId. Combine with --since for same-millisecond stability.").option("--verbose", "After the table, print the full JSON envelope for each event with a per-row label that includes the full serverEventHash + eventId", false).option("--json", "Machine-readable mode \u2014 emit a single JSON array of events, no human-format summary, no chalk colors. Pipe-safe.", false).option("--full-ids", "Print sender DID and full serverEventHash in the table (no truncation). Use when you need to copy-paste either value into another command.", false).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
6049
5835
  "--tail",
6050
5836
  // The polling output (`heyarp inbox --json`) emits raw
6051
5837
  // `EventPublic[]` rows with `.body` at the top level, but
@@ -6066,7 +5852,7 @@ async function runInbox(positionalDid, opts) {
6066
5852
  throw new Error(`inbox: positional <did> (${positionalDid}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
6067
5853
  }
6068
5854
  const explicitDid = positionalDid ?? opts.fromDid;
6069
- const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("inbox", opts.server, void 0);
5855
+ const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("inbox", opts.server, void 0, opts.from);
6070
5856
  const did = local.did;
6071
5857
  if (opts.tail) {
6072
5858
  await runInboxTail(did, local, opts);
@@ -6544,7 +6330,7 @@ function registerReceiptCommands(root) {
6544
6330
  registerPropose(cmd);
6545
6331
  }
6546
6332
  function registerPropose(parent) {
6547
- parent.command("propose").description("Send a receipt envelope as the PAYEE. Row lands PROPOSED; the buyer approves payment on-chain via claim_work_payment.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (= caller / offerer of the parent delegation)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").argument("[request-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_request payload being settled. Omit when --auto-hashes is set.").argument("[response-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_response payload being settled. Omit when --auto-hashes is set.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--verdict <s>", "verdict_proposed (accepted | accepted_with_notes | rejected)", "accepted").option("--notes-hash <sha256>", "Optional sha256:<64 hex> notes hash").option("--deliverable-hash <sha256>", "Optional sha256:<64 hex> deliverable hash").option("--input-tokens <n>", "Optional usage.input_tokens").option("--output-tokens <n>", "Optional usage.output_tokens").option("--latency-ms <n>", "Optional usage.latency_ms").option("--model <name>", "Optional usage.model").option("--computed-amount <s>", "Optional usage.computed_amount").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option(
6333
+ parent.command("propose").description("Send a receipt envelope as the PAYEE. Row lands PROPOSED; the buyer approves payment on-chain via claim_work_payment.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (= caller / offerer of the parent delegation)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").argument("[request-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_request payload being settled. Omit when --auto-hashes is set.").argument("[response-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_response payload being settled. Omit when --auto-hashes is set.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--verdict <s>", "verdict_proposed (accepted | accepted_with_notes | rejected)", "accepted").option("--notes-hash <sha256>", "Optional sha256:<64 hex> notes hash").option("--deliverable-hash <sha256>", "Optional sha256:<64 hex> deliverable hash").option("--input-tokens <n>", "Optional usage.input_tokens").option("--output-tokens <n>", "Optional usage.output_tokens").option("--latency-ms <n>", "Optional usage.latency_ms").option("--model <name>", "Optional usage.model").option("--computed-amount <s>", "Optional usage.computed_amount").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option(
6548
6334
  "--auto-hashes",
6549
6335
  "Compute request_hash + response_hash automatically from the work-log row at (--rel-id, <delegation-id>, --request-id). Positional <request-hash>/<response-hash> become optional; if supplied they must match the computed values (consistency check). --rel-id and --request-id auto-resolve from local state when unambiguous \u2014 pass them explicitly only if the lookup finds multiple candidates.",
6550
6336
  false
@@ -6585,7 +6371,7 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
6585
6371
  if (opts.deliverableHash) requireSha256("receipt propose", opts.deliverableHash, "--deliverable-hash");
6586
6372
  const usage = parseUsage("receipt propose", opts);
6587
6373
  const api = new ArpApiClient(opts.server);
6588
- const sender = resolveSenderAgent("receipt propose", opts.server, opts.fromDid);
6374
+ const sender = resolveSenderAgent("receipt propose", opts.server, opts.fromDid, opts.from);
6589
6375
  if (!opts.relId && opts.autoHashes) {
6590
6376
  opts.relId = await resolveAutoRelId(api, sender, delegationId);
6591
6377
  progress(
@@ -6859,7 +6645,7 @@ init_api();
6859
6645
  function registerReceiptsCommand(root) {
6860
6646
  root.command("receipts").description(
6861
6647
  "List receipts for a relationship (one row per (delegationId, requestHash, responseHash), oldest-first). Receipt rows expose the chain hash as `receiptEventHash` (NOT `serverEventHash` \u2014 that field is the wider envelope identifier on `heyarp events` rows). Scripts using `--json | jq .receiptEventHash` get the value; `jq .serverEventHash` silently returns null because the row doesn't carry that key."
6862
- ).argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--delegation-id <uuid>", "Narrow to receipts under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
6648
+ ).argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--delegation-id <uuid>", "Narrow to receipts under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
6863
6649
  "--verbose",
6864
6650
  'After the one-line summaries, print a framed "Full receipt payloads (N rows)" block \u2014 each row labelled with full delegationId + requestHash + responseHash and dumped as JSON. Mutually exclusive with --json.',
6865
6651
  false
@@ -6875,7 +6661,7 @@ async function runReceipts(relationshipId, opts) {
6875
6661
  }
6876
6662
  const limit = parseLimit5(opts.limit);
6877
6663
  const api = new ArpApiClient(opts.server);
6878
- const sender = resolveSenderAgent("receipts", opts.server, opts.fromDid);
6664
+ const sender = resolveSenderAgent("receipts", opts.server, opts.fromDid, opts.from);
6879
6665
  if (!opts.json) {
6880
6666
  console.log(import_chalk25.default.dim(`Server: ${api.serverUrl}`));
6881
6667
  console.log(import_chalk25.default.dim(`Signer: ${sender.did}`));
@@ -7407,7 +7193,7 @@ function registerRelationshipsCommand(root) {
7407
7193
  "--json",
7408
7194
  "Machine-readable mode \u2014 emit the relationships as a single JSON array on stdout (RelationshipPublic[]). Prelude + table move to stderr. Mutually exclusive with --verbose.",
7409
7195
  false
7410
- ).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").action(async (did, opts) => {
7196
+ ).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").action(async (did, opts) => {
7411
7197
  await runRelationships(did, opts);
7412
7198
  });
7413
7199
  }
@@ -7423,7 +7209,7 @@ async function runRelationships(positionalDid, opts) {
7423
7209
  throw new Error(`relationships: positional <did> (${positionalDid}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
7424
7210
  }
7425
7211
  const explicitDid = positionalDid ?? opts.fromDid;
7426
- const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("relationships", opts.server, void 0);
7212
+ const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("relationships", opts.server, void 0, opts.from);
7427
7213
  const did = local.did;
7428
7214
  const api = new ArpApiClient(opts.server);
7429
7215
  progress(opts.json, import_chalk28.default.dim(`Server: ${api.serverUrl}`));
@@ -7531,7 +7317,7 @@ var import_sdk28 = require("@heyanon-arp/sdk");
7531
7317
  var import_chalk30 = __toESM(require("chalk"));
7532
7318
  init_api();
7533
7319
  function registerSendHandshakeCommand(root) {
7534
- root.command("send-handshake").description("Send a handshake envelope to a recipient (agent name or DID). Server creates the relationship row on first contact.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--greeting <s>", "Optional greeting text included in body.content").option("--intent <s>", "Optional intent text included in body.content").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk28.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
7320
+ root.command("send-handshake").description("Send a handshake envelope to a recipient (agent name or DID). Server creates the relationship row on first contact.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--greeting <s>", "Optional greeting text included in body.content").option("--intent <s>", "Optional intent text included in body.content").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk28.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
7535
7321
  "--json",
7536
7322
  "Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, eventId, relationshipId, relationshipEventIndex, serverTimestamp, signedMessageHash, serverEventHash, prevServerEventHash, senderSequence}). The Server/Sender/Recipient prelude moves to stderr so `--json | jq` stays byte-pure. Mutually exclusive with --verbose.",
7537
7323
  false
@@ -7549,7 +7335,7 @@ async function runSendHandshake(recipientDid, opts) {
7549
7335
  const ttlSeconds = parseTtl3(opts.ttl);
7550
7336
  const api = new ArpApiClient(opts.server);
7551
7337
  progress(opts.json, import_chalk30.default.dim(`Server: ${api.serverUrl}`));
7552
- const sender = resolveSenderAgent("send-handshake", opts.server, opts.fromDid);
7338
+ const sender = resolveSenderAgent("send-handshake", opts.server, opts.fromDid, opts.from);
7553
7339
  progress(opts.json, import_chalk30.default.dim(`Sender: ${sender.did}`));
7554
7340
  progress(opts.json, import_chalk30.default.dim(`Recipient: ${recipientDid}`));
7555
7341
  const content = {};
@@ -7631,7 +7417,7 @@ var import_chalk31 = __toESM(require("chalk"));
7631
7417
  init_api();
7632
7418
  var ALLOWED_DECISIONS = new Set(import_sdk29.HANDSHAKE_DECISIONS);
7633
7419
  function registerSendHandshakeResponseCommand(root) {
7634
- root.command("send-handshake-response").description("Accept or decline an inbound handshake from <recipient-did>. Server reuses the existing relationship row.").argument("<recipient-did>", "Recipient agent DID (did:arp:...) \u2014 the original handshake sender").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--decision <s>", "REQUIRED: accept or decline").option("--notes <s>", "Optional notes included in body.content").option(
7420
+ root.command("send-handshake-response").description("Accept or decline an inbound handshake from <recipient-did>. Server reuses the existing relationship row.").argument("<recipient-did>", "Recipient agent DID (did:arp:...) \u2014 the original handshake sender").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--decision <s>", "REQUIRED: accept or decline").option("--notes <s>", "Optional notes included in body.content").option(
7635
7421
  "--reason <code>",
7636
7422
  // REQUIRED when --decision=decline. Optional otherwise.
7637
7423
  // We don't use commander's requiredOption because it
@@ -7669,7 +7455,7 @@ async function runSendHandshakeResponse(recipientDid, opts) {
7669
7455
  }
7670
7456
  const api = new ArpApiClient(opts.server);
7671
7457
  progress(opts.json, import_chalk31.default.dim(`Server: ${api.serverUrl}`));
7672
- const sender = resolveSenderAgent("send-handshake-response", opts.server, opts.fromDid);
7458
+ const sender = resolveSenderAgent("send-handshake-response", opts.server, opts.fromDid, opts.from);
7673
7459
  progress(opts.json, import_chalk31.default.dim(`Sender: ${sender.did}`));
7674
7460
  progress(opts.json, import_chalk31.default.dim(`Recipient: ${recipientDid}`));
7675
7461
  progress(opts.json, import_chalk31.default.dim(`Decision: ${decision}`));
@@ -7840,12 +7626,12 @@ async function findExistingRelationship(api, signer, senderDid, recipientDid) {
7840
7626
  var import_chalk32 = __toESM(require("chalk"));
7841
7627
  init_api();
7842
7628
  function registerWatchCommand(root) {
7843
- root.command("watch").description("Live tail filtered to a single relationship (SSE). Server-side $match; only envelopes belonging to <rel-id> are streamed.").argument("<relationship-id>", "Relationship UUID to watch").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--verbose", "After each envelope, print the full JSON with a per-row label including eventId + serverEventHash", false).option("--json", "Machine-readable: one NDJSON object per line. Pipe-safe into `jq -c`.", false).option("--full-ids", "Print DIDs + serverEventHash in full (no truncation).", false).action(async (relationshipId, opts) => {
7629
+ root.command("watch").description("Live tail filtered to a single relationship (SSE). Server-side $match; only envelopes belonging to <rel-id> are streamed.").argument("<relationship-id>", "Relationship UUID to watch").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--verbose", "After each envelope, print the full JSON with a per-row label including eventId + serverEventHash", false).option("--json", "Machine-readable: one NDJSON object per line. Pipe-safe into `jq -c`.", false).option("--full-ids", "Print DIDs + serverEventHash in full (no truncation).", false).action(async (relationshipId, opts) => {
7844
7630
  await runWatch(relationshipId, opts);
7845
7631
  });
7846
7632
  }
7847
7633
  async function runWatch(relationshipId, opts) {
7848
- const local = resolveSenderAgent("watch", opts.server, opts.fromDid);
7634
+ const local = resolveSenderAgent("watch", opts.server, opts.fromDid, opts.from);
7849
7635
  const api = new ArpApiClient(opts.server);
7850
7636
  if (!opts.json) {
7851
7637
  console.log(import_chalk32.default.dim(`Server: ${api.serverUrl}`));
@@ -7936,7 +7722,7 @@ init_api();
7936
7722
  function registerWhoamiCommand(root) {
7937
7723
  root.command("whoami").description(
7938
7724
  "Identify the local agent: print DID + settlement pubkey + identity pubkey (with --local), and/or fetch the server profile via signed GET /agents/:did. When <did> is omitted, uses the same sole-agent resolution as other signed commands."
7939
- ).argument("[did]", "Agent DID (did:arp:...) \u2014 omit when there is exactly ONE local agent (sole-agent fallback)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Explicit sender DID \u2014 same precedence as the positional arg, surfaced for symmetry with other commands").option(
7725
+ ).argument("[did]", "Agent DID (did:arp:...) \u2014 omit when there is exactly ONE local agent (sole-agent fallback)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Explicit sender DID \u2014 same precedence as the positional arg, surfaced for symmetry with other commands").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
7940
7726
  "--local",
7941
7727
  // Persona scripts want the local settlement pubkey for
7942
7728
  // `--payer-settlement-pubkey` / on-chain ops without a
@@ -7948,7 +7734,8 @@ function registerWhoamiCommand(root) {
7948
7734
  ).option("--json", "JSON output (jq-pipeable). Combines local + server data when --local is unset, or just local when --local is set.", false).action(async (didArg, opts, cmd) => {
7949
7735
  try {
7950
7736
  const explicitDid = didArg ?? opts.fromDid;
7951
- const local = resolveSenderAgent("whoami", opts.server, explicitDid);
7737
+ const explicitFrom = opts.from;
7738
+ const local = resolveSenderAgent("whoami", opts.server, explicitDid, explicitFrom);
7952
7739
  const api = new ArpApiClient(opts.server);
7953
7740
  const credential = readCredential(api.serverUrl);
7954
7741
  const localJson = {
@@ -8056,7 +7843,7 @@ function registerWorkCommands(root) {
8056
7843
  registerRespond(cmd);
8057
7844
  }
8058
7845
  function registerRequest(parent) {
8059
- parent.command("request").description("Send a work_request to <recipient-did> under <delegation-id> (must be ACCEPTED).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (the payee \u2014 the OTHER side of the delegation pair)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--request-id <id>", "Override the auto-generated request id (must be unique within the delegation)").option(
7846
+ parent.command("request").description("Send a work_request to <recipient-did> under <delegation-id> (must be ACCEPTED).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (the payee \u2014 the OTHER side of the delegation pair)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--request-id <id>", "Override the auto-generated request id (must be unique within the delegation)").option(
8060
7847
  "--params <json>",
8061
7848
  "JSON object payload as a literal string. Defaults to {}. Mutually exclusive with --params-file. Brittle against shell quoting \u2014 prefer --params-file for non-trivial bodies."
8062
7849
  ).option(
@@ -8082,7 +7869,7 @@ async function runRequest(recipientDid, delegationId, opts) {
8082
7869
  const params = parseParamsInput("work request", opts);
8083
7870
  const requestId = parseRequestId("work request", opts.requestId);
8084
7871
  const api = new ArpApiClient(opts.server);
8085
- const sender = resolveSenderAgent("work request", opts.server, opts.fromDid);
7872
+ const sender = resolveSenderAgent("work request", opts.server, opts.fromDid, opts.from);
8086
7873
  const content = {
8087
7874
  delegation_id: delegationId,
8088
7875
  request_id: requestId,
@@ -8117,7 +7904,7 @@ The payee can reply with:`));
8117
7904
  }
8118
7905
  }
8119
7906
  function registerRespond(parent) {
8120
- parent.command("respond").description("Send a work_response under <relationship-id> for <delegation-id> / <request-id>. Payee-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Parent delegation id (UUID)").argument("<request-id>", "Request id supplied on the work_request").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--output <json>", "Success payload as a JSON object literal. Mutually exclusive with --error and --output-file.").option(
7907
+ parent.command("respond").description("Send a work_response under <relationship-id> for <delegation-id> / <request-id>. Payee-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Parent delegation id (UUID)").argument("<request-id>", "Request id supplied on the work_request").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--output <json>", "Success payload as a JSON object literal. Mutually exclusive with --error and --output-file.").option(
8121
7908
  "--output-file <path>",
8122
7909
  "Read the success payload from a file. Mutually exclusive with --output and --error. Use this for any payload large or quote-heavy enough to fight your shell."
8123
7910
  ).option("--error <code:message>", "Failure payload as `CODE:message`. Mutually exclusive with --output / --output-file.").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
@@ -8139,7 +7926,7 @@ async function runRespond(relationshipId, delegationId, requestId, opts) {
8139
7926
  const ttlSeconds = parseTtl5("work respond", opts.ttl);
8140
7927
  const responsePayload = parseResponsePayload("work respond", opts);
8141
7928
  const api = new ArpApiClient(opts.server);
8142
- const sender = resolveSenderAgent("work respond", opts.server, opts.fromDid);
7929
+ const sender = resolveSenderAgent("work respond", opts.server, opts.fromDid, opts.from);
8143
7930
  const signer = makeSigner(sender);
8144
7931
  const recipientDid = await resolveResponseRecipient("work respond", api, signer, { relationshipId, delegationId, requestId, selfDid: sender.did });
8145
7932
  const content = {
@@ -8353,7 +8140,7 @@ var import_chalk36 = __toESM(require("chalk"));
8353
8140
  init_api();
8354
8141
  var ALLOWED_STATES3 = new Set(import_sdk32.WORK_LOG_STATES);
8355
8142
  function registerWorkListCommand(root) {
8356
- root.command("work-list").description("List work-log rows for a relationship (one row per (delegationId, requestId), oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (requested|responded)").option("--delegation-id <uuid>", "Narrow to work-logs operating under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
8143
+ root.command("work-list").description("List work-log rows for a relationship (one row per (delegationId, requestId), oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (requested|responded)").option("--delegation-id <uuid>", "Narrow to work-logs operating under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
8357
8144
  "--verbose",
8358
8145
  'After the summary, print a framed "Full work-log payloads (N rows)" block \u2014 each row labelled with full delegationId + requestId and dumped as JSON, including `requestParams` (the work_request payload the worker was asked) and `responseOutput` / `responseError`. Mutually exclusive with --json.',
8359
8146
  false
@@ -8374,7 +8161,7 @@ async function runWorkList(relationshipId, opts) {
8374
8161
  const limit = parseLimit7(opts.limit);
8375
8162
  const state = parseState3(opts.state);
8376
8163
  const api = new ArpApiClient(opts.server);
8377
- const sender = resolveSenderAgent("work-list", opts.server, opts.fromDid);
8164
+ const sender = resolveSenderAgent("work-list", opts.server, opts.fromDid, opts.from);
8378
8165
  if (!opts.json) {
8379
8166
  console.log(import_chalk36.default.dim(`Server: ${api.serverUrl}`));
8380
8167
  console.log(import_chalk36.default.dim(`Signer: ${sender.did}`));