@heyanon-arp/cli 0.0.19 → 0.0.20

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
@@ -734,7 +734,7 @@ var import_simple_update_notifier = __toESM(require("simple-update-notifier"));
734
734
  // package.json
735
735
  var package_default = {
736
736
  name: "@heyanon-arp/cli",
737
- version: "0.0.19",
737
+ version: "0.0.20",
738
738
  description: "Command-line client for the Agent Relationship Protocol \u2014 register agents, sign envelopes, run escrowed work cycles on Solana.",
739
739
  license: "MIT",
740
740
  keywords: ["arp", "agent-relationship-protocol", "did", "solana", "escrow", "ed25519", "agents", "a2a", "cli"],
@@ -1780,6 +1780,9 @@ var UNTIL_PHASES = [
1780
1780
  ];
1781
1781
  var WAIT_DEFAULT_INTERVAL_SEC = 3;
1782
1782
  var WAIT_DEFAULT_TIMEOUT_SEC = 300;
1783
+ var WAIT_ABS_MAX_SEC = 86400;
1784
+ var WAIT_CONTRACT_LAG_MARGIN_SEC = 300;
1785
+ var WAIT_CONTRACT_CAP_FALLBACK_SEC = 3600;
1783
1786
  function registerStatusCommand(root) {
1784
1787
  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(
1785
1788
  "--wait",
@@ -1787,7 +1790,7 @@ function registerStatusCommand(root) {
1787
1790
  false
1788
1791
  ).option(
1789
1792
  "--wait-timeout <seconds>",
1790
- `Max wall-clock seconds to wait when --wait is set (default ${WAIT_DEFAULT_TIMEOUT_SEC}). Process exits code 124 on timeout, matching the unix \`timeout\` convention.`,
1793
+ `Max wall-clock seconds to wait when --wait is set (default ${WAIT_DEFAULT_TIMEOUT_SEC}; with --until it defaults to the live on-chain budget = work+review+dispute windows + margin, read from the contract). Capped at that same on-chain budget. Process exits code 124 on timeout (unix \`timeout\` convention).`,
1791
1794
  String(WAIT_DEFAULT_TIMEOUT_SEC)
1792
1795
  ).option(
1793
1796
  "--wait-interval <seconds>",
@@ -1823,9 +1826,9 @@ async function runStatus(relationshipId, opts) {
1823
1826
  console.log(formatStatusReport(summary));
1824
1827
  return;
1825
1828
  }
1826
- const waitTimeout = parseWaitTimeout(opts.waitTimeout);
1827
- const waitInterval = parseWaitInterval(opts.waitInterval);
1828
1829
  const until = parseUntilPhase(opts.until);
1830
+ const waitInterval = parseWaitInterval(opts.waitInterval);
1831
+ const waitTimeout = await resolveWaitTimeoutSec(api, opts.waitTimeout, { hasUntil: !!until });
1829
1832
  const outcome = await runWaitLoop({
1830
1833
  fetchSummary: () => composeStatus(api, sender.did, relationshipId, signer),
1831
1834
  waitIntervalSec: waitInterval,
@@ -1986,8 +1989,31 @@ function parseWaitTimeout(raw) {
1986
1989
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
1987
1990
  throw new Error(`status: --wait-timeout must be a positive integer number of seconds (got '${raw}')`);
1988
1991
  }
1989
- if (n > 3600) {
1990
- throw new Error(`status: --wait-timeout must be <= 3600 seconds (1h). Got ${n}; if you really need to wait longer, script a loop around \`heyarp status\`.`);
1992
+ if (n > WAIT_ABS_MAX_SEC) {
1993
+ throw new Error(`status: --wait-timeout must be <= ${WAIT_ABS_MAX_SEC} seconds (24h, the max envelope TTL). Got ${n}.`);
1994
+ }
1995
+ return n;
1996
+ }
1997
+ function contractWaitCapSec(cfg) {
1998
+ const w = Number(cfg?.workWindowSecs);
1999
+ const r = Number(cfg?.reviewWindowSecs);
2000
+ const d = Number(cfg?.disputeWindowSecs);
2001
+ if (![w, r, d].every((n) => Number.isFinite(n) && n > 0)) return WAIT_CONTRACT_CAP_FALLBACK_SEC;
2002
+ return Math.min(WAIT_ABS_MAX_SEC, w + r + d + WAIT_CONTRACT_LAG_MARGIN_SEC);
2003
+ }
2004
+ async function resolveWaitTimeoutSec(api, raw, opts) {
2005
+ let cap;
2006
+ try {
2007
+ cap = contractWaitCapSec(await api.getEscrowConfig());
2008
+ } catch {
2009
+ cap = WAIT_CONTRACT_CAP_FALLBACK_SEC;
2010
+ }
2011
+ if (raw === void 0) return opts.hasUntil ? cap : WAIT_DEFAULT_TIMEOUT_SEC;
2012
+ const n = parseWaitTimeout(raw);
2013
+ if (n > cap) {
2014
+ throw new Error(
2015
+ `status: --wait-timeout ${n}s exceeds the live on-chain budget of ${cap}s (work+review+dispute windows + ${WAIT_CONTRACT_LAG_MARGIN_SEC}s lag, read from the contract). Nothing stays pending longer; lower it or script a loop around \`heyarp status\`.`
2016
+ );
1991
2017
  }
1992
2018
  return n;
1993
2019
  }
@@ -2949,7 +2975,10 @@ function registerOffer(parent) {
2949
2975
  ).option(
2950
2976
  "--wait-until <phase>",
2951
2977
  'Block after delivery until the named FSM phase is reached (e.g. delegation.accepted). One of the UNTIL_PHASES from `heyarp status --help`. Exit code 124 on --wait-timeout. Recovers the "sub-agent exits before counterparty accepts" antipattern.'
2952
- ).option("--wait-timeout <seconds>", "When --wait-until is set: max wall-clock wait (default 300). Exit code 124 on timeout.").option("--wait-interval <seconds>", "When --wait-until is set: poll cadence (default 3, bound [1, 60]).").option(
2978
+ ).option(
2979
+ "--wait-timeout <seconds>",
2980
+ "When --wait-until is set: max wall-clock wait. Omitted \u2192 auto-sized to the live on-chain budget (work+review+dispute windows + margin, read from the contract); explicit values are capped at that budget. Exit code 124 on timeout."
2981
+ ).option("--wait-interval <seconds>", "When --wait-until is set: poll cadence (default 3, bound [1, 60]).").option(
2953
2982
  "--wait-verbose",
2954
2983
  'When --wait-until is set: emit one dim line per poll tick showing the current FSM state. Useful for "is it alive or stuck?" diagnosis on long blocks.',
2955
2984
  false
@@ -3174,7 +3203,8 @@ After the worker accepts, fund the escrow lock:`));
3174
3203
  relationshipId: result.relationshipId,
3175
3204
  untilPhase,
3176
3205
  waitIntervalSec: parseWaitInterval(opts.waitInterval),
3177
- waitTimeoutSec: parseWaitTimeout(opts.waitTimeout),
3206
+ // Cap/default the wait against the live on-chain windows (work+review+dispute).
3207
+ waitTimeoutSec: await resolveWaitTimeoutSec(api, opts.waitTimeout, { hasUntil: true }),
3178
3208
  waitVerbose: !!opts.waitVerbose,
3179
3209
  json: false
3180
3210
  // delegation offer is a human-text command (printIngestResult is human-text); JSON mode would be a follow-up.
@@ -3198,7 +3228,10 @@ function registerFund(parent) {
3198
3228
  ).option(
3199
3229
  "--wait-until <phase>",
3200
3230
  "Block after delivery until the named FSM phase is reached (typically delegation.locked \u2014 resolves once the escrow lock confirms on chain). One of the UNTIL_PHASES from `heyarp status --help`. Exit code 124 on --wait-timeout."
3201
- ).option("--wait-timeout <seconds>", "When --wait-until is set: max wall-clock wait (default 300). Exit code 124 on timeout.").option("--wait-interval <seconds>", "When --wait-until is set: poll cadence (default 3, bound [1, 60]).").option("--wait-verbose", "When --wait-until is set: emit one dim line per poll tick showing the current FSM state.", false).action(async (delegationId, opts) => {
3231
+ ).option(
3232
+ "--wait-timeout <seconds>",
3233
+ "When --wait-until is set: max wall-clock wait. Omitted \u2192 auto-sized to the live on-chain budget (work+review+dispute windows + margin, read from the contract); explicit values are capped at that budget. Exit code 124 on timeout."
3234
+ ).option("--wait-interval <seconds>", "When --wait-until is set: poll cadence (default 3, bound [1, 60]).").option("--wait-verbose", "When --wait-until is set: emit one dim line per poll tick showing the current FSM state.", false).action(async (delegationId, opts) => {
3202
3235
  await runFund(delegationId, opts);
3203
3236
  });
3204
3237
  }
@@ -3296,11 +3329,11 @@ async function runFund(delegationId, opts) {
3296
3329
  relationshipId: result.relationshipId,
3297
3330
  untilPhase,
3298
3331
  waitIntervalSec: parseWaitInterval(opts.waitInterval),
3299
- // Lock finalization on devnet routinely takes 5–12 min
3300
- // (submit confirm indexer projection), so fund gets a
3301
- // larger default than the generic 300s a timeout here is
3302
- // almost never a failure, just a slow chain.
3303
- waitTimeoutSec: parseWaitTimeout(opts.waitTimeout ?? "1200"),
3332
+ // Lock finalization (submit confirm indexer projection) is
3333
+ // slow, so an omitted timeout auto-sizes to the live on-chain
3334
+ // budget (work+review+dispute + margin)generous by design;
3335
+ // a timeout here is almost never a failure, just a slow chain.
3336
+ waitTimeoutSec: await resolveWaitTimeoutSec(api, opts.waitTimeout, { hasUntil: true }),
3304
3337
  waitVerbose: !!opts.waitVerbose,
3305
3338
  json: false
3306
3339
  });