zk-agent-cli 0.1.0-beta.7 → 0.1.0-beta.8

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.
Files changed (3) hide show
  1. package/README.md +81 -2
  2. package/dist/index.js +658 -64
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -11,7 +11,22 @@ Current strengths:
11
11
  - workflow orchestration for send, swap, bridge, deposit, and withdraw
12
12
  - machine-readable JSON output for agent callers
13
13
 
14
- ## Install
14
+ ## Public Entry Points
15
+
16
+ Choose the entrypoint that matches the environment.
17
+
18
+ If you are installing this repository into a compatible agent harness instead
19
+ of using the CLI directly, prefer the repo skill surface:
20
+
21
+ ```bash
22
+ npx skills add https://github.com/AgiWeb3/zk-agent-cli
23
+ ```
24
+
25
+ This repo currently ships a repository skill bundle for compatible harnesses.
26
+ It does not yet ship a native ChatGPT/Codex plugin bundle such as
27
+ `.codex-plugin/plugin.json`.
28
+
29
+ For direct terminal use, install the packaged CLI:
15
30
 
16
31
  One-shot execution:
17
32
 
@@ -75,6 +90,15 @@ zk-agent next
75
90
  zk-agent workflow pay --wallet main --to <address> --amount <amount>
76
91
  ```
77
92
 
93
+ If the browser is not colocated with the terminal, keep the same flow but
94
+ replace the wallet-creation step with:
95
+
96
+ ```bash
97
+ zk-agent relay inspect --relay-url <relay-url>
98
+ zk-agent wallet create --relay-url <relay-url> --wait-relay --prompt-code
99
+ zk-agent next
100
+ ```
101
+
78
102
  If a wallet already exists, inspect the blocker first. Use `wallet reapprove`
79
103
  when approval is missing or expired, then return to `zk-agent next`. Use
80
104
  `wallet signer attach` when approval is still present but the local execution
@@ -108,6 +132,58 @@ operator baseline.
108
132
  checkpoint, executes immediately when ready, reopens a missing writable session
109
133
  through the intent-scoped approval path, and defaults to the validated
110
134
  approval-based paymaster mode unless you override it.
135
+ When that approval-based path still needs a fee-token candidate, recover with
136
+ `zk-agent tokens --chain zksync-sepolia --role paymaster-fee-token` and
137
+ `zk-agent resolve-token --chain zksync-sepolia --symbol <symbol> --role paymaster-fee-token`.
138
+
139
+ ## Discovery Path
140
+
141
+ Use the discovery surfaces in this order when a workflow or direct command
142
+ needs token context:
143
+
144
+ - `zk-agent assets --wallet main` for the preferred single-chain asset view
145
+ - `zk-agent tokens --wallet main --owned` for the narrower owned ERC-20 subset
146
+ - `zk-agent tokens --chain zksync-sepolia` and
147
+ `zk-agent resolve-token --chain zksync-sepolia --symbol USDC` for
148
+ symbol-first discovery before choosing an explicit token address
149
+ - `zk-agent tokens --chain zksync-sepolia --role paymaster-fee-token` and
150
+ `zk-agent resolve-token --chain zksync-sepolia --symbol <symbol> --role paymaster-fee-token`
151
+ for approval-based paymaster fee-token discovery on the flagship pay path
152
+ - `zk-agent defaults` for the machine-readable registry/defaults catalog:
153
+ tracked token roles, paymaster metadata, source order, and validated/fallback
154
+ route metadata
155
+
156
+ ## Direct Command Escape Hatches
157
+
158
+ Use the guided workflow layer first, but the lower-level direct commands now
159
+ keep the same symbol/discovery contract:
160
+
161
+ - `zk-agent send-token --wallet main --symbol USDC --to <address> --amount <amount>`
162
+ - `zk-agent swap --wallet main --token-in-symbol USDC --token-out-symbol ETH --amount-in <amount>`
163
+ - `zk-agent fund --wallet main --symbol USDC --amount <amount>`
164
+ - `zk-agent deposit --wallet main --symbol USDC --amount <amount>`
165
+ - `zk-agent withdraw --wallet main --symbol USDC --amount <amount>`
166
+
167
+ Current direct-command behavior:
168
+
169
+ - `send-token`, `fund`, `deposit`, and `withdraw` accept symbol-first token
170
+ resolution when the local registry can resolve the active chain token
171
+ - `swap` follows the current registry-backed validated route by default when
172
+ `--protocol` is omitted
173
+ - `bridge` can reuse the tracked default destination route when one is already
174
+ known for the current wallet chain
175
+
176
+ ## Local Agent Identity
177
+
178
+ The local operator profile is optional. It helps agent harnesses and operators
179
+ persist stable metadata, but wallet approval and workflow execution do not
180
+ depend on it.
181
+
182
+ Use:
183
+
184
+ - `zk-agent agent status`
185
+ - `zk-agent agent set --name "<operator-name>" --wallet main`
186
+ - `zk-agent agent show`
111
187
 
112
188
  ## Remote Approval
113
189
 
@@ -149,7 +225,10 @@ reverse proxy, pass `--public-origin` so the emitted share/status URLs point at
149
225
  the externally reachable hosted URL instead of the local bind address. The
150
226
  published package now also ships the bundled connector UI build used by
151
227
  `relay serve`, so hosted share-link approval no longer depends on a separate
152
- source checkout just to serve the UI.
228
+ source checkout just to serve the UI. `relay inspect` now also reports
229
+ `stateBackend`, `deploymentScope`, and `sameHostRestartPersists` so the
230
+ single-host local-filesystem constraint is explicit before you rely on a hosted
231
+ URL.
153
232
 
154
233
  ## Local Storage
155
234
 
package/dist/index.js CHANGED
@@ -7722,6 +7722,10 @@ function formatHumanErrorMessage(error) {
7722
7722
  pushDetailLine(lines, "reason", details.reason);
7723
7723
  pushDetailLine(lines, "note", details.note);
7724
7724
  pushDetailLine(lines, "suggested action", details.suggestedAction);
7725
+ pushDetailLine(lines, "status command", details.statusCommand);
7726
+ pushDetailLine(lines, "approve command", details.approveCommand);
7727
+ pushDetailLine(lines, "relay inspect command", details.relayInspectCommand);
7728
+ pushDetailLine(lines, "reissue remote approval command", details.reissueRemoteApprovalCommand);
7725
7729
  pushDetailLine(lines, "validation domain", details.validationDomain);
7726
7730
  pushDetailLine(lines, "validation stage", details.validationStage);
7727
7731
  const validation = asRecord2(details.validation);
@@ -7758,6 +7762,18 @@ function buildTopLevelNextRecommendedCommand(requestId, paymasterMode) {
7758
7762
  function buildWalletCreateRecommendedCommand() {
7759
7763
  return "zk-agent wallet create --await-local";
7760
7764
  }
7765
+ function buildRelayInspectRecommendedCommand(relayUrl = "<url>") {
7766
+ return `zk-agent relay inspect --relay-url ${relayUrl}`;
7767
+ }
7768
+ function buildWalletCreateRemoteRecommendedCommand(relayUrl = "<url>", paymasterMode, walletName = "main", accountKind = "smart-account") {
7769
+ const command = [
7770
+ "zk-agent wallet create",
7771
+ walletName !== "main" ? `--name ${walletName}` : "",
7772
+ accountKind !== "smart-account" ? `--account-kind ${accountKind}` : "",
7773
+ `--relay-url ${relayUrl} --wait-relay --prompt-code`
7774
+ ].filter(Boolean).join(" ");
7775
+ return appendPaymasterMode(command, paymasterMode);
7776
+ }
7761
7777
  function buildWalletListRecommendedCommand() {
7762
7778
  return "zk-agent wallet list";
7763
7779
  }
@@ -7784,6 +7800,12 @@ function buildResolveTokenRecommendedCommand(chain, symbol, role, source) {
7784
7800
  const withRole = role ? `${command} --role ${role}` : command;
7785
7801
  return source ? `${withRole} --source ${source}` : withRole;
7786
7802
  }
7803
+ function buildPaymasterFeeTokensRecommendedCommand(chain) {
7804
+ return buildTokensRecommendedCommand(chain, void 0, "paymaster-fee-token");
7805
+ }
7806
+ function buildPaymasterFeeTokenResolveRecommendedCommand(chain, symbol) {
7807
+ return buildResolveTokenRecommendedCommand(chain, symbol, "paymaster-fee-token");
7808
+ }
7787
7809
  function buildDiscoveryRecommendedCommands(input) {
7788
7810
  return {
7789
7811
  inspectDefaults: buildDefaultsRecommendedCommand(),
@@ -7814,6 +7836,9 @@ function buildDiscoveryRecommendedCommands(input) {
7814
7836
  function buildWalletReapproveRecommendedCommand(walletName) {
7815
7837
  return `zk-agent wallet reapprove --name ${walletName} --await-local`;
7816
7838
  }
7839
+ function buildWalletReapproveRemoteRecommendedCommand(walletName, relayUrl = "<url>") {
7840
+ return `zk-agent wallet reapprove --name ${walletName} --relay-url ${relayUrl} --wait-relay --prompt-code`;
7841
+ }
7817
7842
  function buildWalletNextRecommendedCommand(walletName) {
7818
7843
  return `zk-agent wallet next --name ${walletName}`;
7819
7844
  }
@@ -8507,9 +8532,15 @@ function workflowFollowupLines(recommendedCommands) {
8507
8532
  if (recommendedCommands.discoverOwnedTokens) {
8508
8533
  lines.push(["discover owned tokens", recommendedCommands.discoverOwnedTokens]);
8509
8534
  }
8535
+ if (recommendedCommands.discoverPaymasterTokens) {
8536
+ lines.push(["discover paymaster tokens", recommendedCommands.discoverPaymasterTokens]);
8537
+ }
8510
8538
  if (recommendedCommands.discoverTokens) {
8511
8539
  lines.push(["discover tokens", recommendedCommands.discoverTokens]);
8512
8540
  }
8541
+ if (recommendedCommands.inspectPaymasterToken) {
8542
+ lines.push(["inspect paymaster token", recommendedCommands.inspectPaymasterToken]);
8543
+ }
8513
8544
  if (recommendedCommands.inspectToken) {
8514
8545
  lines.push(["inspect token", recommendedCommands.inspectToken]);
8515
8546
  }
@@ -9214,7 +9245,25 @@ function createBalancesCommand(deps) {
9214
9245
  }
9215
9246
  function createAssetsCommand(deps) {
9216
9247
  const resolvedDeps = resolveBalancesCommandDeps(deps);
9217
- return new Command("assets").description("Fetch the preferred single-chain asset view with native balance plus registry-backed ERC-20 holdings").option("--wallet <name>", "Wallet name", "main").option("--chain <chain>", "Single chain override").action(async (options) => {
9248
+ return new Command("assets").description("Fetch the preferred single-chain asset view with native balance plus registry-backed ERC-20 holdings").addHelpText(
9249
+ "after",
9250
+ [
9251
+ "",
9252
+ "Discovery asset path:",
9253
+ " Preferred single-chain asset entrypoint:",
9254
+ " zk-agent assets --wallet main",
9255
+ "",
9256
+ " Narrower owned ERC-20 registry subset:",
9257
+ " zk-agent tokens --wallet main --owned",
9258
+ "",
9259
+ " Symbol-first token lookup before a tokenized command:",
9260
+ " zk-agent tokens --chain zksync-sepolia --symbol USDC",
9261
+ " zk-agent resolve-token --chain zksync-sepolia --symbol USDC",
9262
+ "",
9263
+ " For the machine-readable registry/default catalog:",
9264
+ " zk-agent defaults"
9265
+ ].join("\n")
9266
+ ).option("--wallet <name>", "Wallet name", "main").option("--chain <chain>", "Single chain override").action(async (options) => {
9218
9267
  const walletName = options.wallet;
9219
9268
  const wallet = await resolvedDeps.loadWallet(walletName);
9220
9269
  if (!wallet) throw new Error(`Wallet not found: ${walletName}`);
@@ -9912,11 +9961,35 @@ function createPlannedCommands() {
9912
9961
 
9913
9962
  // src/commands/setup.ts
9914
9963
  import { Command as Command2 } from "commander";
9964
+ function buildSetupHelpText() {
9965
+ return [
9966
+ "",
9967
+ "What setup does:",
9968
+ " Writes the local default chain and connector URL used by the first-run path.",
9969
+ "",
9970
+ "After setup, stay on the canonical local-first path:",
9971
+ " zk-agent next",
9972
+ " zk-agent wallet create --await-local",
9973
+ " zk-agent next",
9974
+ "",
9975
+ "If the browser is not colocated with this terminal, switch at the wallet step:",
9976
+ " zk-agent relay inspect --relay-url <url>",
9977
+ " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
9978
+ " zk-agent next",
9979
+ "",
9980
+ "Environment note:",
9981
+ " No custom .env is required for setup, next, or wallet request creation.",
9982
+ " Add RPC env vars later, before live reads or broadcasts."
9983
+ ].join("\n");
9984
+ }
9915
9985
  function createInitCommand() {
9916
- return new Command2("init").alias("setup").description("Initialize local zk-agent configuration").option("--default-chain <chain>", "Default chain key", "zksync-era").option("--connector-url <url>", "Connector UI base URL", "http://localhost:4444").option("--force", "Overwrite an existing config", false).action(async (options) => {
9986
+ return new Command2("init").alias("setup").description("Initialize local zk-agent configuration for the default operator path").addHelpText("after", buildSetupHelpText()).option("--default-chain <chain>", "Default chain key", "zksync-era").option("--connector-url <url>", "Connector UI base URL", "http://localhost:4444").option("--force", "Overwrite an existing config", false).action(async (options) => {
9917
9987
  const recommendedCommands = {
9988
+ next: buildTopLevelNextRecommendedCommand(),
9918
9989
  inspectDefaults: buildDefaultsRecommendedCommand(),
9919
9990
  createWallet: buildWalletCreateRecommendedCommand(),
9991
+ relayInspect: buildRelayInspectRecommendedCommand(),
9992
+ createWalletRemote: buildWalletCreateRemoteRecommendedCommand(),
9920
9993
  afterWalletApproval: buildTopLevelNextRecommendedCommand()
9921
9994
  };
9922
9995
  const existing = await loadProjectConfig();
@@ -9926,8 +9999,11 @@ function createInitCommand() {
9926
9999
  ["status", "Config already exists. Re-run with --force to overwrite."],
9927
10000
  ["default chain", existing.defaultChain],
9928
10001
  ["connector", existing.connectorUrl],
10002
+ ["next", recommendedCommands.next],
9929
10003
  ["inspect defaults", recommendedCommands.inspectDefaults],
9930
- ["create wallet", recommendedCommands.createWallet],
10004
+ ["create wallet (local)", recommendedCommands.createWallet],
10005
+ ["relay inspect", recommendedCommands.relayInspect],
10006
+ ["create wallet (remote)", recommendedCommands.createWalletRemote],
9931
10007
  ["after approval", recommendedCommands.afterWalletApproval]
9932
10008
  ],
9933
10009
  {
@@ -9952,8 +10028,11 @@ function createInitCommand() {
9952
10028
  ["status", "Config saved"],
9953
10029
  ["default chain", config.defaultChain],
9954
10030
  ["connector", config.connectorUrl],
10031
+ ["next", recommendedCommands.next],
9955
10032
  ["inspect defaults", recommendedCommands.inspectDefaults],
9956
- ["create wallet", recommendedCommands.createWallet],
10033
+ ["create wallet (local)", recommendedCommands.createWallet],
10034
+ ["relay inspect", recommendedCommands.relayInspect],
10035
+ ["create wallet (remote)", recommendedCommands.createWalletRemote],
9957
10036
  ["after approval", recommendedCommands.afterWalletApproval]
9958
10037
  ],
9959
10038
  { ok: true, config, recommendedCommands }
@@ -10383,9 +10462,17 @@ function buildTopLevelWorkflowRecommendedCommands(input) {
10383
10462
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(input.walletName),
10384
10463
  discoverTokens: buildTokensRecommendedCommand(input.chain),
10385
10464
  inspectToken: buildResolveTokenRecommendedCommand(input.chain)
10465
+ } : {},
10466
+ ...input.paymasterMode === "approval-based" ? {
10467
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(input.chain),
10468
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(input.chain)
10386
10469
  } : {}
10387
10470
  };
10388
10471
  }
10472
+ function extractCheckpointPaymasterMode(checkpoint) {
10473
+ if (!("paymaster" in checkpoint.goal)) return void 0;
10474
+ return checkpoint.goal.paymaster?.mode;
10475
+ }
10389
10476
  function resolveNextCommandDeps(deps) {
10390
10477
  return {
10391
10478
  provider: deps?.provider ?? defaultProvider,
@@ -10415,6 +10502,11 @@ function buildNextHelpText() {
10415
10502
  " zk-agent wallet create --await-local",
10416
10503
  " zk-agent next",
10417
10504
  "",
10505
+ " If the browser is remote, switch at the wallet step instead of waiting for a local callback:",
10506
+ " zk-agent relay inspect --relay-url <url>",
10507
+ " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
10508
+ " zk-agent next",
10509
+ "",
10418
10510
  " Continue a stored workflow checkpoint:",
10419
10511
  " zk-agent next --request-id <id>",
10420
10512
  "",
@@ -10470,7 +10562,8 @@ function createNextCommand(deps) {
10470
10562
  walletName: wallet2.walletName,
10471
10563
  nextAction: nextCommand2,
10472
10564
  chain: result.plan.chain,
10473
- intent: result.intent
10565
+ intent: result.intent,
10566
+ paymasterMode: extractCheckpointPaymasterMode(updatedCheckpoint)
10474
10567
  });
10475
10568
  const workflowAgentProfile = await loadAgentIdentitySummary(wallet2.walletName);
10476
10569
  const agentFollowup2 = buildAgentFollowup(workflowAgentProfile, {
@@ -10515,6 +10608,7 @@ function createNextCommand(deps) {
10515
10608
  if (!config) {
10516
10609
  const recommendedCommands2 = {
10517
10610
  setup: buildSetupCommand(),
10611
+ afterSetup: buildTopLevelNextRecommendedCommand2(),
10518
10612
  inspectDefaults: buildDefaultsRecommendedCommand()
10519
10613
  };
10520
10614
  printResult(
@@ -10523,6 +10617,7 @@ function createNextCommand(deps) {
10523
10617
  ...agentProfileLines(agentProfile),
10524
10618
  ...agentFollowupLines(defaultAgentFollowup),
10525
10619
  ["next", recommendedCommands2.setup],
10620
+ ["after setup", recommendedCommands2.afterSetup],
10526
10621
  ["inspect defaults", recommendedCommands2.inspectDefaults]
10527
10622
  ]),
10528
10623
  {
@@ -10544,6 +10639,11 @@ function createNextCommand(deps) {
10544
10639
  buildWalletCreateRecommendedCommand(),
10545
10640
  paymasterMode
10546
10641
  ),
10642
+ relayInspect: buildRelayInspectRecommendedCommand(),
10643
+ createWalletRemote: buildWalletCreateRemoteRecommendedCommand(
10644
+ "<url>",
10645
+ paymasterMode
10646
+ ),
10547
10647
  afterApproval: appendPaymasterMode2(buildTopLevelNextRecommendedCommand2(), paymasterMode),
10548
10648
  inspectDefaults: buildDefaultsRecommendedCommand()
10549
10649
  };
@@ -10555,6 +10655,8 @@ function createNextCommand(deps) {
10555
10655
  ...agentProfileLines(agentProfile),
10556
10656
  ...agentFollowupLines(defaultAgentFollowup),
10557
10657
  ["next", recommendedCommands2.createWallet],
10658
+ ["relay inspect", recommendedCommands2.relayInspect],
10659
+ ["remote fallback", recommendedCommands2.createWalletRemote],
10558
10660
  ["after approval", recommendedCommands2.afterApproval],
10559
10661
  ["inspect defaults", recommendedCommands2.inspectDefaults]
10560
10662
  ]),
@@ -10608,6 +10710,10 @@ function createNextCommand(deps) {
10608
10710
  walletStatus: buildWalletStatusRecommendedCommand(wallet.walletName),
10609
10711
  discoverAssets: buildAssetsRecommendedCommand(wallet.walletName),
10610
10712
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(wallet.walletName),
10713
+ ...paymasterMode === "approval-based" ? {
10714
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(wallet.chain),
10715
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(wallet.chain)
10716
+ } : {},
10611
10717
  discoverTokens: buildTokensRecommendedCommand(wallet.chain),
10612
10718
  inspectToken: buildResolveTokenRecommendedCommand(wallet.chain),
10613
10719
  workflowPay,
@@ -10623,7 +10729,9 @@ function createNextCommand(deps) {
10623
10729
  ...summary.recommendedCommand ? [] : [["next", workflowPay]],
10624
10730
  ["discover assets", recommendedCommands.discoverAssets],
10625
10731
  ["discover owned tokens", recommendedCommands.discoverOwnedTokens],
10732
+ ...recommendedCommands.discoverPaymasterTokens ? [["discover paymaster tokens", recommendedCommands.discoverPaymasterTokens]] : [],
10626
10733
  ["discover tokens", recommendedCommands.discoverTokens],
10734
+ ...recommendedCommands.inspectPaymasterToken ? [["inspect paymaster token", recommendedCommands.inspectPaymasterToken]] : [],
10627
10735
  ["inspect token", recommendedCommands.inspectToken],
10628
10736
  ["inspect defaults", recommendedCommands.inspectDefaults]
10629
10737
  ]),
@@ -10740,6 +10848,21 @@ function createAgentCommand() {
10740
10848
  agent.addHelpText(
10741
10849
  "after",
10742
10850
  [
10851
+ "",
10852
+ " Agent identity path:",
10853
+ " zk-agent agent status",
10854
+ ' zk-agent agent set --name "SED Operator" --wallet main',
10855
+ " zk-agent agent show",
10856
+ "",
10857
+ " Portable local profile management:",
10858
+ " zk-agent agent export",
10859
+ " zk-agent agent import --payload @agent-profile.json --overwrite",
10860
+ "",
10861
+ " Remove the saved local profile:",
10862
+ " zk-agent agent clear",
10863
+ "",
10864
+ " This profile is optional. Wallet approval and workflow execution still work",
10865
+ " without a saved local agent profile.",
10743
10866
  "",
10744
10867
  "Examples:",
10745
10868
  " zk-agent agent status",
@@ -11386,7 +11509,24 @@ function buildDefaultsLines(input) {
11386
11509
  return lines;
11387
11510
  }
11388
11511
  function createDefaultsCommand() {
11389
- return new Command5("defaults").description("Show the machine-readable registry of supported, validated, experimental, and manually configured defaults").action(async () => {
11512
+ return new Command5("defaults").description("Show the machine-readable registry of supported, validated, experimental, and manually configured defaults").addHelpText(
11513
+ "after",
11514
+ [
11515
+ "",
11516
+ "Discovery defaults path:",
11517
+ " Use `defaults` as the machine-readable registry escape hatch for:",
11518
+ " - validated or fallback swap / bridge paths",
11519
+ " - tracked token roles and source order",
11520
+ " - paymaster defaults and supported modes",
11521
+ "",
11522
+ " For wallet-scoped asset discovery, prefer:",
11523
+ " zk-agent assets --wallet main",
11524
+ "",
11525
+ " For symbol-first token discovery, prefer:",
11526
+ " zk-agent tokens --chain zksync-sepolia",
11527
+ " zk-agent resolve-token --chain zksync-sepolia --symbol USDC"
11528
+ ].join("\n")
11529
+ ).action(async () => {
11390
11530
  const defaults = loadValidatedDefaults();
11391
11531
  const localTokenRegistry = listLocalTokenRegistryEntries();
11392
11532
  const tokenRegistrySources = describeDefaultTokenRegistrySources();
@@ -11446,7 +11586,27 @@ async function resolveActiveChain(options, deps) {
11446
11586
  }
11447
11587
  function createResolveTokenCommand(deps) {
11448
11588
  const resolvedDeps = resolveResolveTokenCommandDeps(deps);
11449
- return new Command6("resolve-token").description("Resolve a token symbol or address against the configured local-first token registry").option("--wallet <name>", "Optional stored wallet name to infer the active chain").option("--chain <chain>", "Chain key or chain id override").option("--symbol <symbol>", "Token symbol to resolve on the active chain").option("--address <address>", "Token address to inspect on the active chain").option(
11589
+ return new Command6("resolve-token").description("Resolve a token symbol or address against the configured local-first token registry").addHelpText(
11590
+ "after",
11591
+ [
11592
+ "",
11593
+ "Resolve-token path:",
11594
+ " Symbol-first resolution on one active chain:",
11595
+ " zk-agent resolve-token --chain zksync-sepolia --symbol USDC",
11596
+ "",
11597
+ " Use the stored wallet to infer the active chain:",
11598
+ " zk-agent resolve-token --wallet main --symbol USDC",
11599
+ "",
11600
+ " Use broader chain discovery before resolution when you still need the candidate set:",
11601
+ " zk-agent tokens --chain zksync-sepolia",
11602
+ "",
11603
+ " Use the wallet asset entrypoint when the real question is balances/holdings:",
11604
+ " zk-agent assets --wallet main",
11605
+ "",
11606
+ " Use the registry/default catalog when you need tracked roles or source order:",
11607
+ " zk-agent defaults"
11608
+ ].join("\n")
11609
+ ).option("--wallet <name>", "Optional stored wallet name to infer the active chain").option("--chain <chain>", "Chain key or chain id override").option("--symbol <symbol>", "Token symbol to resolve on the active chain").option("--address <address>", "Token address to inspect on the active chain").option(
11450
11610
  "--role <role>",
11451
11611
  `Optional defaults-registry role filter: ${REGISTRY_TOKEN_ROLES.join(", ")}`
11452
11612
  ).option(
@@ -11649,7 +11809,29 @@ function ownedTokenSummaryLines2(summary) {
11649
11809
  }
11650
11810
  function createTokensCommand(deps) {
11651
11811
  const resolvedDeps = resolveTokensCommandDeps(deps);
11652
- return new Command7("tokens").description("List discoverable tokens from the configured local-first token registry, or inspect the owned ERC-20 registry subset for one wallet").option("--wallet <name>", "Optional stored wallet name to infer the active chain").option("--chain <chain>", "Chain key or chain id override").option("--symbol <symbol>", "Optional exact symbol filter").option(
11812
+ return new Command7("tokens").description("List discoverable tokens from the configured local-first token registry, or inspect the owned ERC-20 registry subset for one wallet").addHelpText(
11813
+ "after",
11814
+ [
11815
+ "",
11816
+ "Discovery token path:",
11817
+ " Start with the preferred wallet asset view when you need balances plus tracked ERC-20 holdings:",
11818
+ " zk-agent assets --wallet main",
11819
+ "",
11820
+ " Use the narrower owned ERC-20 registry subset when you only want held tokens:",
11821
+ " zk-agent tokens --wallet main --owned",
11822
+ "",
11823
+ " Use chain-scoped discovery before choosing a token address:",
11824
+ " zk-agent tokens --chain zksync-sepolia",
11825
+ " zk-agent tokens --chain zksync-sepolia --symbol USDC",
11826
+ " zk-agent tokens --chain zksync-sepolia --role paymaster-fee-token",
11827
+ "",
11828
+ " For one direct token-resolution check:",
11829
+ " zk-agent resolve-token --chain zksync-sepolia --symbol USDC",
11830
+ "",
11831
+ " For the full defaults/registry catalog:",
11832
+ " zk-agent defaults"
11833
+ ].join("\n")
11834
+ ).option("--wallet <name>", "Optional stored wallet name to infer the active chain").option("--chain <chain>", "Chain key or chain id override").option("--symbol <symbol>", "Optional exact symbol filter").option(
11653
11835
  "--role <role>",
11654
11836
  `Optional defaults-registry role filter: ${REGISTRY_TOKEN_ROLES.join(", ")}`
11655
11837
  ).option(
@@ -11975,6 +12157,8 @@ var RELAY_BODY_LIMIT_BYTES = 1024 * 1024;
11975
12157
  var RELAY_SERVICE = "zk-agent-relay";
11976
12158
  var RELAY_PROTOCOL = "zk-agent-session-relay";
11977
12159
  var RELAY_SCHEMA_VERSION = 1;
12160
+ var RELAY_STATE_BACKEND = "local-filesystem";
12161
+ var RELAY_DEPLOYMENT_SCOPE = "single-host";
11978
12162
  function relayDir() {
11979
12163
  const directory = path7.join(storageDir(), "relay");
11980
12164
  if (!fs7.existsSync(directory)) {
@@ -12010,11 +12194,15 @@ function sanitizeRelayRecord(record) {
12010
12194
  }
12011
12195
  function relayStatusResponse(baseUrl, record) {
12012
12196
  const sanitized = sanitizeRelayRecord(record);
12197
+ const shareUrl = relayShareUrl(baseUrl, sanitized.request_id);
12198
+ const statusUrl = relayStatusUrl(baseUrl, sanitized.request_id);
12013
12199
  return {
12014
12200
  request_id: sanitized.request_id,
12015
12201
  status: relayStatus(record),
12016
12202
  approval_ready: Boolean(record.encrypted_payload),
12017
- approval_url: `${baseUrl}/r/${sanitized.request_id}`,
12203
+ share_url: shareUrl,
12204
+ status_url: statusUrl,
12205
+ approval_url: shareUrl,
12018
12206
  expires_at: sanitized.expires_at,
12019
12207
  request: sanitized.request,
12020
12208
  approval_submitted_at: sanitized.approval_submitted_at
@@ -12111,6 +12299,9 @@ function relayHealthResponse(bindBaseUrl, publicBaseUrl, connectorUiAvailable, p
12111
12299
  origin: normalizeRelayBaseUrl(bindBaseUrl),
12112
12300
  public_origin: normalizeRelayBaseUrl(publicBaseUrl),
12113
12301
  public_origin_source: publicOriginSource,
12302
+ state_backend: RELAY_STATE_BACKEND,
12303
+ deployment_scope: RELAY_DEPLOYMENT_SCOPE,
12304
+ same_host_restart_persists: true,
12114
12305
  connector_ui_available: connectorUiAvailable,
12115
12306
  capabilities: relayCapabilities(connectorUiAvailable)
12116
12307
  };
@@ -12357,6 +12548,12 @@ function isRelayCapability(value) {
12357
12548
  function isRelayPublicOriginSource(value) {
12358
12549
  return value === "configured" || value === "bind-origin-default";
12359
12550
  }
12551
+ function isRelayStateBackend(value) {
12552
+ return value === "local-filesystem";
12553
+ }
12554
+ function isRelayDeploymentScope(value) {
12555
+ return value === "single-host";
12556
+ }
12360
12557
  function asRelayHealthResponse(value) {
12361
12558
  if (!isRecord3(value)) return null;
12362
12559
  if (value.ok !== true) return null;
@@ -12369,6 +12566,15 @@ function asRelayHealthResponse(value) {
12369
12566
  if (typeof value.public_origin_source !== "undefined" && !isRelayPublicOriginSource(value.public_origin_source)) {
12370
12567
  return null;
12371
12568
  }
12569
+ if (typeof value.state_backend !== "undefined" && !isRelayStateBackend(value.state_backend)) {
12570
+ return null;
12571
+ }
12572
+ if (typeof value.deployment_scope !== "undefined" && !isRelayDeploymentScope(value.deployment_scope)) {
12573
+ return null;
12574
+ }
12575
+ if (typeof value.same_host_restart_persists !== "undefined" && typeof value.same_host_restart_persists !== "boolean") {
12576
+ return null;
12577
+ }
12372
12578
  if (typeof value.connector_ui_available !== "boolean") return null;
12373
12579
  if (!Array.isArray(value.capabilities) || !value.capabilities.every(isRelayCapability)) {
12374
12580
  return null;
@@ -12410,6 +12616,15 @@ function inferRelayPublicOriginSource(options) {
12410
12616
  }
12411
12617
  return normalizedOrigin === normalizedPublicOrigin ? "bind-origin-default" : "configured";
12412
12618
  }
12619
+ function inferRelayStateBackend(relayMode) {
12620
+ return relayMode === "local-file" ? "local-filesystem" : null;
12621
+ }
12622
+ function inferRelayDeploymentScope(relayMode) {
12623
+ return relayMode === "local-file" ? "single-host" : null;
12624
+ }
12625
+ function inferSameHostRestartPersists(relayMode) {
12626
+ return relayMode === "local-file" ? true : null;
12627
+ }
12413
12628
  function relayHostedReadinessNotes(options) {
12414
12629
  const notes = [];
12415
12630
  if (!options.compatible) {
@@ -12430,6 +12645,17 @@ function relayHostedReadinessNotes(options) {
12430
12645
  }
12431
12646
  return notes;
12432
12647
  }
12648
+ function relayOperationalContractNotes(options) {
12649
+ if (!options.compatible) {
12650
+ return [];
12651
+ }
12652
+ if (options.stateBackend === "local-filesystem" && options.deploymentScope === "single-host" && options.sameHostRestartPersists === true) {
12653
+ return [
12654
+ "Relay state is stored on the relay host local filesystem. Restarts on the same host keep pending approval state, but multi-instance or load-balanced deployments do not share relay state."
12655
+ ];
12656
+ }
12657
+ return [];
12658
+ }
12433
12659
  function relayOriginRelationshipNotes(options) {
12434
12660
  const notes = [];
12435
12661
  const relayUrlMatchesOrigin = relayUrlMatches(options.relayUrl, options.origin);
@@ -12454,6 +12680,9 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12454
12680
  origin: health?.origin || null,
12455
12681
  publicOrigin
12456
12682
  });
12683
+ const stateBackend = health?.state_backend || inferRelayStateBackend(health?.relay_mode || null);
12684
+ const deploymentScope = health?.deployment_scope || inferRelayDeploymentScope(health?.relay_mode || null);
12685
+ const sameHostRestartPersists = typeof health?.same_host_restart_persists === "boolean" ? health.same_host_restart_persists : inferSameHostRestartPersists(health?.relay_mode || null);
12457
12686
  const compatible = Boolean(health && hasCoreRelayCapabilities(health.capabilities));
12458
12687
  const connectorUiAvailable = health?.connector_ui_available ?? null;
12459
12688
  const relayUrlMatchesOrigin = relayUrlMatches(relayUrl, health?.origin || null);
@@ -12468,6 +12697,12 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12468
12697
  publicOriginSource,
12469
12698
  connectorUiAvailable
12470
12699
  }),
12700
+ ...relayOperationalContractNotes({
12701
+ compatible,
12702
+ stateBackend,
12703
+ deploymentScope,
12704
+ sameHostRestartPersists
12705
+ }),
12471
12706
  ...relayOriginRelationshipNotes({
12472
12707
  relayUrl,
12473
12708
  origin: health?.origin || null,
@@ -12486,6 +12721,9 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12486
12721
  origin: health?.origin || null,
12487
12722
  publicOrigin,
12488
12723
  publicOriginSource,
12724
+ stateBackend,
12725
+ deploymentScope,
12726
+ sameHostRestartPersists,
12489
12727
  shareLinkBaseUrl,
12490
12728
  statusApiBaseUrl,
12491
12729
  relayUrlMatchesOrigin,
@@ -12500,6 +12738,23 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12500
12738
  }
12501
12739
  function createRelayCommand() {
12502
12740
  const relay = new Command8("relay").description("Run the local connector relay prototype server");
12741
+ relay.addHelpText(
12742
+ "after",
12743
+ [
12744
+ "",
12745
+ " Hosted remote-approval path:",
12746
+ " zk-agent relay serve --public-origin https://relay.example.com",
12747
+ " zk-agent relay inspect --relay-url <url>",
12748
+ " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
12749
+ " zk-agent wallet reapprove --name main --relay-url <url> --wait-relay --prompt-code",
12750
+ "",
12751
+ " Keep `wallet create|reapprove --await-local` as the default baseline when",
12752
+ " the browser and terminal are colocated.",
12753
+ "",
12754
+ " Use `relay inspect` before sending operators to a hosted share link so",
12755
+ " the public origin, connector UI, and hosted-readiness contract are visible."
12756
+ ].join("\n")
12757
+ );
12503
12758
  relay.command("serve").description("Serve the local relay API and, when available, the built connector UI").option("--host <host>", "Host to bind", "127.0.0.1").option("--port <port>", "Port to bind (0 = choose a free port)", "4445").option(
12504
12759
  "--public-origin <url>",
12505
12760
  "Public base URL to advertise in share/status links when the relay is behind a tunnel or reverse proxy"
@@ -12533,6 +12788,9 @@ function createRelayCommand() {
12533
12788
  origin: server.origin,
12534
12789
  publicOrigin,
12535
12790
  publicOriginSource,
12791
+ stateBackend: "local-filesystem",
12792
+ deploymentScope: "single-host",
12793
+ sameHostRestartPersists: true,
12536
12794
  shareLinkBaseUrl,
12537
12795
  statusApiBaseUrl,
12538
12796
  publicOriginLooksLocal,
@@ -12562,6 +12820,12 @@ function createRelayCommand() {
12562
12820
  humanLine("public origin", publicOrigin);
12563
12821
  }
12564
12822
  humanLine("public origin source", publicOriginSource);
12823
+ humanLine("state backend", payload.stateBackend);
12824
+ humanLine("deployment scope", payload.deploymentScope);
12825
+ humanLine(
12826
+ "same-host restart persists",
12827
+ payload.sameHostRestartPersists ? "yes" : "no"
12828
+ );
12565
12829
  humanLine("share-link base", shareLinkBaseUrl);
12566
12830
  humanLine("status api base", statusApiBaseUrl);
12567
12831
  humanLine("health", `${server.origin}/health`);
@@ -12618,6 +12882,18 @@ function createRelayCommand() {
12618
12882
  if (payload.publicOriginSource) {
12619
12883
  humanLine("public origin source", payload.publicOriginSource);
12620
12884
  }
12885
+ if (payload.stateBackend) {
12886
+ humanLine("state backend", payload.stateBackend);
12887
+ }
12888
+ if (payload.deploymentScope) {
12889
+ humanLine("deployment scope", payload.deploymentScope);
12890
+ }
12891
+ if (payload.sameHostRestartPersists !== null) {
12892
+ humanLine(
12893
+ "same-host restart persists",
12894
+ payload.sameHostRestartPersists ? "yes" : "no"
12895
+ );
12896
+ }
12621
12897
  humanLine("share-link base", payload.shareLinkBaseUrl);
12622
12898
  humanLine("status api base", payload.statusApiBaseUrl);
12623
12899
  if (payload.relayUrlMatchesOrigin !== null) {
@@ -14527,6 +14803,165 @@ function buildPendingRequestRecommendedCommands(walletName, requestId, relayUrl,
14527
14803
  function buildPendingRequestNextAction(recommendedCommands) {
14528
14804
  return recommendedCommands.relayStatus ?? recommendedCommands.awaitLocal;
14529
14805
  }
14806
+ function buildRelayWaitGuidanceLines(options) {
14807
+ return [
14808
+ ["status", "Waiting for relay approval"],
14809
+ ["request", options.requestId],
14810
+ ["wallet", options.walletName],
14811
+ ["share url", options.relay.share_url],
14812
+ ["status url", options.relay.status_url],
14813
+ ["approval url", options.relay.approval_url],
14814
+ ["expires", options.expiresAt],
14815
+ ["browser step", "Open the share url in a browser and complete connector approval."],
14816
+ [
14817
+ "terminal step",
14818
+ options.codeEntry === "prompt" ? "After the relay is ready, enter the 6-digit approval code in this terminal." : "The CLI will finalize automatically with the provided 6-digit approval code once the relay is ready."
14819
+ ],
14820
+ ["fallback status", options.statusCommand],
14821
+ ["fallback approve", options.approveCommand]
14822
+ ];
14823
+ }
14824
+ function printRelayWaitGuidance(options) {
14825
+ if (shouldJsonOutput()) return;
14826
+ for (const [label, value] of buildRelayWaitGuidanceLines(options)) {
14827
+ humanLine(label, value);
14828
+ }
14829
+ }
14830
+ async function buildRelayStatusFollowUp(options) {
14831
+ if (options.relay.status === "expired") {
14832
+ return await buildRelayExpiredRecoveryCommands({
14833
+ walletName: options.relay.request?.walletName,
14834
+ relayUrl: options.relayUrl,
14835
+ paymasterMode: options.relay.request?.requestedPaymasterMode,
14836
+ accountKind: options.relay.request?.requestedAccountKind
14837
+ });
14838
+ }
14839
+ if (options.relay.approval_ready) {
14840
+ const approve = buildWalletRequestRelayApproveRecommendedCommand(
14841
+ options.relay.request_id,
14842
+ options.relayUrl
14843
+ );
14844
+ return {
14845
+ nextAction: approve,
14846
+ recommendedCommands: {
14847
+ status: buildWalletRequestRelayStatusRecommendedCommand(
14848
+ options.relay.request_id,
14849
+ options.relayUrl
14850
+ ),
14851
+ approve
14852
+ }
14853
+ };
14854
+ }
14855
+ return {
14856
+ nextAction: buildWalletRequestRelayStatusRecommendedCommand(
14857
+ options.relay.request_id,
14858
+ options.relayUrl
14859
+ ),
14860
+ recommendedCommands: {
14861
+ status: buildWalletRequestRelayStatusRecommendedCommand(
14862
+ options.relay.request_id,
14863
+ options.relayUrl
14864
+ )
14865
+ }
14866
+ };
14867
+ }
14868
+ async function buildRelayExpiredRecoveryCommands(options) {
14869
+ const relayInspect = buildRelayInspectRecommendedCommand(options.relayUrl);
14870
+ const walletName = options.walletName?.trim();
14871
+ if (!walletName) {
14872
+ return {
14873
+ nextAction: relayInspect,
14874
+ recommendedCommands: {
14875
+ relayInspect
14876
+ },
14877
+ note: "Relay approval expired. Inspect the hosted relay, then reissue the wallet request again."
14878
+ };
14879
+ }
14880
+ const existingWallet = await loadWalletSession(walletName);
14881
+ const reissueRemoteApproval = existingWallet ? buildWalletReapproveRemoteRecommendedCommand(walletName, options.relayUrl) : buildWalletCreateRemoteRecommendedCommand(
14882
+ options.relayUrl,
14883
+ options.paymasterMode,
14884
+ walletName,
14885
+ options.accountKind
14886
+ );
14887
+ return {
14888
+ nextAction: reissueRemoteApproval,
14889
+ recommendedCommands: {
14890
+ relayInspect,
14891
+ reissueRemoteApproval
14892
+ },
14893
+ note: "Relay approval expired. Reissue the remote request. If the original request used scoped session flags, add those same policy flags again."
14894
+ };
14895
+ }
14896
+ function buildRelayApprovalTimeoutError(options) {
14897
+ const statusCommand = buildWalletRequestRelayStatusRecommendedCommand(
14898
+ options.requestId,
14899
+ options.relayUrl
14900
+ );
14901
+ const approveCommand = buildWalletRequestRelayApproveRecommendedCommand(
14902
+ options.requestId,
14903
+ options.relayUrl
14904
+ );
14905
+ return new AgentError(
14906
+ "RELAY_APPROVAL_TIMEOUT",
14907
+ `Timed out waiting for relay approval after ${Math.ceil(options.timeoutMs / 1e3)} seconds.`,
14908
+ {
14909
+ requestId: options.requestId,
14910
+ relayUrl: options.relayUrl,
14911
+ timeoutMs: options.timeoutMs,
14912
+ intervalMs: options.intervalMs,
14913
+ retryable: true,
14914
+ statusCommand,
14915
+ approveCommand,
14916
+ suggestedAction: "Check the current relay status, then finalize the wallet approval once approval_ready=true."
14917
+ }
14918
+ );
14919
+ }
14920
+ async function buildRelayApprovalExpiredError(options) {
14921
+ const recovery = await buildRelayExpiredRecoveryCommands({
14922
+ walletName: options.walletName,
14923
+ relayUrl: options.relayUrl,
14924
+ paymasterMode: options.paymasterMode,
14925
+ accountKind: options.accountKind
14926
+ });
14927
+ return new AgentError(
14928
+ "RELAY_APPROVAL_EXPIRED",
14929
+ `Relay approval expired before the encrypted payload was ready for request ${options.requestId}.`,
14930
+ {
14931
+ requestId: options.requestId,
14932
+ relayUrl: options.relayUrl,
14933
+ retryable: true,
14934
+ note: recovery.note,
14935
+ relayInspectCommand: recovery.recommendedCommands.relayInspect,
14936
+ reissueRemoteApprovalCommand: recovery.recommendedCommands.reissueRemoteApproval,
14937
+ suggestedAction: "Inspect the hosted relay, then reissue the remote approval request."
14938
+ }
14939
+ );
14940
+ }
14941
+ function buildRelayApprovalNotReadyError(options) {
14942
+ const statusCommand = buildWalletRequestRelayStatusRecommendedCommand(
14943
+ options.requestId,
14944
+ options.relayUrl
14945
+ );
14946
+ const approveCommand = buildWalletRequestRelayApproveRecommendedCommand(
14947
+ options.requestId,
14948
+ options.relayUrl
14949
+ );
14950
+ return new AgentError(
14951
+ "RELAY_APPROVAL_NOT_READY",
14952
+ `Relay approval is not ready yet for request ${options.requestId}.`,
14953
+ {
14954
+ requestId: options.requestId,
14955
+ relayUrl: options.relayUrl,
14956
+ status: options.status,
14957
+ approvalReady: options.approvalReady,
14958
+ retryable: true,
14959
+ statusCommand,
14960
+ approveCommand,
14961
+ suggestedAction: "Check the current relay status, then retry approval once approval_ready=true."
14962
+ }
14963
+ );
14964
+ }
14530
14965
  function buildRequestListEntryRecommendedCommands(walletName, requestId, paymasterMode) {
14531
14966
  return {
14532
14967
  show: buildWalletRequestShowRecommendedCommand(requestId),
@@ -14669,25 +15104,55 @@ async function fetchEncryptedRelayApprovalPayload(relayUrl, requestId, options)
14669
15104
  intervalMs: options.intervalMs ?? 2e3
14670
15105
  });
14671
15106
  if (!relay.approval_ready) {
14672
- throw new Error(`Relay approval expired before the encrypted payload was ready for request ${requestId}.`);
15107
+ throw await buildRelayApprovalExpiredError({
15108
+ requestId,
15109
+ relayUrl
15110
+ });
14673
15111
  }
14674
15112
  }
14675
15113
  const approval = await fetchRelayApproval(relayUrl, requestId);
14676
15114
  if (!approval.approval_ready || !approval.encrypted_payload) {
14677
- throw new Error(`Relay approval is not ready yet for request ${requestId}.`);
15115
+ throw buildRelayApprovalNotReadyError({
15116
+ requestId,
15117
+ relayUrl,
15118
+ status: approval.status,
15119
+ approvalReady: approval.approval_ready
15120
+ });
14678
15121
  }
14679
15122
  return approval.encrypted_payload;
14680
15123
  }
14681
15124
  async function finalizePublishedRelayWalletRequest(options) {
14682
- const encryptedPayload = await fetchEncryptedRelayApprovalPayload(
14683
- options.relayUrl,
14684
- options.walletRequest.requestId,
14685
- {
14686
- wait: true,
14687
- timeoutMs: options.timeoutMs,
14688
- intervalMs: options.intervalMs
15125
+ let encryptedPayload;
15126
+ try {
15127
+ encryptedPayload = await fetchEncryptedRelayApprovalPayload(
15128
+ options.relayUrl,
15129
+ options.walletRequest.requestId,
15130
+ {
15131
+ wait: true,
15132
+ timeoutMs: options.timeoutMs,
15133
+ intervalMs: options.intervalMs
15134
+ }
15135
+ );
15136
+ } catch (error) {
15137
+ if (error instanceof Error && error.message.startsWith("Timed out waiting for relay approval after ")) {
15138
+ throw buildRelayApprovalTimeoutError({
15139
+ requestId: options.walletRequest.requestId,
15140
+ relayUrl: options.relayUrl,
15141
+ timeoutMs: options.timeoutMs,
15142
+ intervalMs: options.intervalMs
15143
+ });
14689
15144
  }
14690
- );
15145
+ if (error instanceof AgentError && error.code === "RELAY_APPROVAL_EXPIRED") {
15146
+ throw await buildRelayApprovalExpiredError({
15147
+ requestId: options.walletRequest.requestId,
15148
+ walletName: options.walletRequest.walletName,
15149
+ relayUrl: options.relayUrl,
15150
+ paymasterMode: options.walletRequest.requestedPaymasterMode,
15151
+ accountKind: options.walletRequest.requestedAccountKind
15152
+ });
15153
+ }
15154
+ throw error;
15155
+ }
14691
15156
  const code = options.code || (options.promptCode ? await readApprovalCodeFromStdin() : void 0);
14692
15157
  if (!code) {
14693
15158
  throw new Error("Missing relay approval code.");
@@ -15054,7 +15519,9 @@ async function printBuiltinSmartAccountProfiles() {
15054
15519
  }
15055
15520
  function createWalletCommand(deps) {
15056
15521
  const resolvedDeps = resolveWalletCommandDeps(deps);
15057
- const wallet = new Command9("wallet").description("Manage wallet sessions");
15522
+ const wallet = new Command9("wallet").description(
15523
+ "Create, inspect, and recover local-first wallet sessions"
15524
+ );
15058
15525
  const request = new Command9("request").description("Inspect and finalize pending wallet requests");
15059
15526
  const signer = new Command9("signer").description(
15060
15527
  "Inspect and manage the stored local execution signer for a wallet"
@@ -15104,7 +15571,8 @@ function createWalletCommand(deps) {
15104
15571
  " Hosted remote approval path:",
15105
15572
  " zk-agent relay inspect --relay-url <url>",
15106
15573
  " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
15107
- " zk-agent wallet reapprove --name main --relay-url <url> --wait-relay --prompt-code"
15574
+ " zk-agent wallet reapprove --name main --relay-url <url> --wait-relay --prompt-code",
15575
+ " zk-agent next"
15108
15576
  ].join("\n")
15109
15577
  );
15110
15578
  request.addHelpText(
@@ -15118,7 +15586,11 @@ function createWalletCommand(deps) {
15118
15586
  " Remote relay completion:",
15119
15587
  " zk-agent wallet request relay-publish --request-id <id> --relay-url <url>",
15120
15588
  " zk-agent wallet request relay-status --request-id <id> --relay-url <url> --wait",
15121
- " zk-agent wallet request approve --request-id <id> --relay-url <url> --code <code> --wait"
15589
+ " zk-agent wallet request approve --request-id <id> --relay-url <url> --code <code> --wait",
15590
+ "",
15591
+ " If relay-status returns status = expired:",
15592
+ " zk-agent relay inspect --relay-url <url>",
15593
+ " zk-agent wallet create|reapprove --relay-url <url> --wait-relay --prompt-code"
15122
15594
  ].join("\n")
15123
15595
  );
15124
15596
  signer.addHelpText(
@@ -15217,6 +15689,23 @@ function createWalletCommand(deps) {
15217
15689
  }
15218
15690
  const relay = options.relayUrl ? await publishWalletRequestToRelay(request2, options.relayUrl) : void 0;
15219
15691
  if (relayWaitOptions) {
15692
+ if (relay) {
15693
+ printRelayWaitGuidance({
15694
+ requestId: request2.requestId,
15695
+ walletName: request2.walletName,
15696
+ relay,
15697
+ expiresAt: request2.expiresAt,
15698
+ codeEntry: relayWaitOptions.promptCode ? "prompt" : "provided",
15699
+ statusCommand: buildWalletRequestRelayStatusRecommendedCommand(
15700
+ request2.requestId,
15701
+ relayWaitOptions.relayUrl
15702
+ ),
15703
+ approveCommand: buildWalletRequestRelayApproveRecommendedCommand(
15704
+ request2.requestId,
15705
+ relayWaitOptions.relayUrl
15706
+ )
15707
+ });
15708
+ }
15220
15709
  const { payload, walletRecord } = await finalizePublishedRelayWalletRequest({
15221
15710
  walletRequest: request2,
15222
15711
  ...relayWaitOptions
@@ -15365,6 +15854,23 @@ function createWalletCommand(deps) {
15365
15854
  }
15366
15855
  const relay = options.relayUrl ? await publishWalletRequestToRelay(request2, options.relayUrl) : void 0;
15367
15856
  if (relayWaitOptions) {
15857
+ if (relay) {
15858
+ printRelayWaitGuidance({
15859
+ requestId: request2.requestId,
15860
+ walletName: request2.walletName,
15861
+ relay,
15862
+ expiresAt: request2.expiresAt,
15863
+ codeEntry: relayWaitOptions.promptCode ? "prompt" : "provided",
15864
+ statusCommand: buildWalletRequestRelayStatusRecommendedCommand(
15865
+ request2.requestId,
15866
+ relayWaitOptions.relayUrl
15867
+ ),
15868
+ approveCommand: buildWalletRequestRelayApproveRecommendedCommand(
15869
+ request2.requestId,
15870
+ relayWaitOptions.relayUrl
15871
+ )
15872
+ });
15873
+ }
15368
15874
  const { payload, walletRecord: approvedWallet } = await finalizePublishedRelayWalletRequest({
15369
15875
  walletRequest: request2,
15370
15876
  ...relayWaitOptions
@@ -15784,40 +16290,53 @@ function createWalletCommand(deps) {
15784
16290
  );
15785
16291
  });
15786
16292
  request.command("relay-status").description("Inspect the relay status of a published wallet request, optionally waiting until approval is ready").requiredOption("--request-id <id>", "Wallet request id").requiredOption("--relay-url <url>", "Relay server base URL").option("--wait", "Poll until the encrypted relay approval is ready or the request expires").option("--timeout-seconds <seconds>", "How long to wait while polling relay status", "600").option("--interval-ms <milliseconds>", "How often to poll relay status while waiting", "2000").action(async (options) => {
15787
- const relay = options.wait ? await waitForRelayApprovalReady(options.relayUrl, options.requestId, {
15788
- timeoutMs: parsePositiveIntegerOption(options.timeoutSeconds, "--timeout-seconds", 600) * 1e3,
15789
- intervalMs: parsePositiveIntegerOption(options.intervalMs, "--interval-ms", 2e3)
15790
- }) : await fetchRelayStatus(options.relayUrl, options.requestId);
16293
+ const timeoutMs = parsePositiveIntegerOption(options.timeoutSeconds, "--timeout-seconds", 600) * 1e3;
16294
+ const intervalMs = parsePositiveIntegerOption(options.intervalMs, "--interval-ms", 2e3);
16295
+ let relay;
16296
+ try {
16297
+ relay = options.wait ? await waitForRelayApprovalReady(options.relayUrl, options.requestId, {
16298
+ timeoutMs,
16299
+ intervalMs
16300
+ }) : await fetchRelayStatus(options.relayUrl, options.requestId);
16301
+ } catch (error) {
16302
+ if (options.wait && error instanceof Error && error.message.startsWith("Timed out waiting for relay approval after ")) {
16303
+ throw buildRelayApprovalTimeoutError({
16304
+ requestId: options.requestId,
16305
+ relayUrl: options.relayUrl,
16306
+ timeoutMs,
16307
+ intervalMs
16308
+ });
16309
+ }
16310
+ throw error;
16311
+ }
16312
+ const followUp = await buildRelayStatusFollowUp({
16313
+ relay,
16314
+ relayUrl: options.relayUrl
16315
+ });
15791
16316
  printResult(
15792
16317
  [
15793
16318
  ["status", relay.status],
15794
16319
  ["request", relay.request_id],
15795
16320
  ["approval ready", relay.approval_ready ? "yes" : "no"],
15796
- ["share url", relay.approval_url],
15797
- ["share-link base", relay.approval_url.replace(/\/[^/]+$/, "")],
15798
- ["status api base", `${relay.approval_url.replace(/\/r\/[^/]+$/, "")}/api/requests`],
16321
+ ["share url", relay.share_url],
16322
+ ["status url", relay.status_url],
16323
+ ["approval url", relay.approval_url],
16324
+ ["share-link base", relay.share_url.replace(/\/[^/]+$/, "")],
16325
+ ["status api base", relay.status_url.replace(/\/[^/]+$/, "")],
15799
16326
  ["expires", relay.expires_at],
15800
- ["next status", buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl)],
15801
- ...relay.approval_ready ? [[
15802
- "next approve",
15803
- buildWalletRequestRelayApproveRecommendedCommand(relay.request_id, options.relayUrl)
15804
- ]] : []
16327
+ ...followUp.note ? [["note", followUp.note]] : [],
16328
+ ...Object.entries(followUp.recommendedCommands).map(
16329
+ ([label, command]) => [label, command]
16330
+ )
15805
16331
  ],
15806
16332
  {
15807
16333
  ok: true,
15808
16334
  walletRequestId: relay.request_id,
15809
16335
  relay,
15810
16336
  ...relayOutputAliases(relay),
15811
- nextAction: relay.approval_ready ? buildWalletRequestRelayApproveRecommendedCommand(relay.request_id, options.relayUrl) : buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl),
15812
- recommendedCommands: {
15813
- status: buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl),
15814
- ...relay.approval_ready ? {
15815
- approve: buildWalletRequestRelayApproveRecommendedCommand(
15816
- relay.request_id,
15817
- options.relayUrl
15818
- )
15819
- } : {}
15820
- }
16337
+ nextAction: followUp.nextAction,
16338
+ recommendedCommands: followUp.recommendedCommands,
16339
+ ...followUp.note ? { note: followUp.note } : {}
15821
16340
  }
15822
16341
  );
15823
16342
  });
@@ -15830,6 +16349,24 @@ function createWalletCommand(deps) {
15830
16349
  if (options.wait && !options.relayUrl) {
15831
16350
  throw new Error("--wait is only supported together with --relay-url.");
15832
16351
  }
16352
+ if (options.wait && options.relayUrl && !shouldJsonOutput()) {
16353
+ const relayStatus2 = await fetchRelayStatus(options.relayUrl, walletRequest.requestId);
16354
+ printRelayWaitGuidance({
16355
+ requestId: walletRequest.requestId,
16356
+ walletName: walletRequest.walletName,
16357
+ relay: relayStatus2,
16358
+ expiresAt: walletRequest.expiresAt,
16359
+ codeEntry: "provided",
16360
+ statusCommand: buildWalletRequestRelayStatusRecommendedCommand(
16361
+ walletRequest.requestId,
16362
+ options.relayUrl
16363
+ ),
16364
+ approveCommand: buildWalletRequestRelayApproveRecommendedCommand(
16365
+ walletRequest.requestId,
16366
+ options.relayUrl
16367
+ )
16368
+ });
16369
+ }
15833
16370
  const payload = options.payload ? parseJsonInput(options.payload) : decryptApprovedPayloadForWalletRequest(
15834
16371
  walletRequest,
15835
16372
  options.encryptedPayload ? parseJsonInput(options.encryptedPayload) : await fetchEncryptedRelayApprovalPayload(options.relayUrl, walletRequest.requestId, {
@@ -18137,7 +18674,8 @@ async function printWorkflowRunCommandResult(execution) {
18137
18674
  walletName: execution.result.walletName,
18138
18675
  nextAction: execution.result.nextCommand,
18139
18676
  chain: execution.result.plan.chain,
18140
- intent: execution.result.intent
18677
+ intent: execution.result.intent,
18678
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal)
18141
18679
  });
18142
18680
  printResult(
18143
18681
  prependWorkflowRequestId(
@@ -18178,7 +18716,8 @@ async function printWorkflowRunCommandResult(execution) {
18178
18716
  walletName: execution.status.walletName,
18179
18717
  nextAction: execution.status.recommendedCommand,
18180
18718
  chain: execution.status.plan.chain,
18181
- intent: execution.status.intent
18719
+ intent: execution.status.intent,
18720
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
18182
18721
  });
18183
18722
  printResult(
18184
18723
  prependWorkflowRequestId(
@@ -18450,6 +18989,7 @@ async function executeWorkflowAutoCommand(options, deps = resolveWorkflowCommand
18450
18989
  action: result ? result.stage : walletApproval?.stage ?? status.status,
18451
18990
  requestId: context.requestId,
18452
18991
  checkpointPersisted: Boolean(checkpoint),
18992
+ goal: context.goal,
18453
18993
  checkpoint,
18454
18994
  status,
18455
18995
  result,
@@ -18468,7 +19008,8 @@ async function printWorkflowAutoCommandResult(execution) {
18468
19008
  walletName: execution.status.walletName,
18469
19009
  nextAction,
18470
19010
  chain: execution.status.plan.chain,
18471
- intent: execution.status.intent
19011
+ intent: execution.status.intent,
19012
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal) ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
18472
19013
  });
18473
19014
  const summaryLines = [
18474
19015
  ["source", execution.source],
@@ -18530,7 +19071,21 @@ function buildWorkflowCheckpointRecommendedCommands(checkpoint) {
18530
19071
  walletStatus: buildWalletStatusRecommendedCommand(checkpoint.walletName)
18531
19072
  };
18532
19073
  }
19074
+ function extractWorkflowGoalPaymasterMode(goal) {
19075
+ if (!goal || !("paymaster" in goal)) {
19076
+ return void 0;
19077
+ }
19078
+ return goal.paymaster?.mode;
19079
+ }
19080
+ function extractPaymasterModeFromCommand(command) {
19081
+ if (!command) {
19082
+ return void 0;
19083
+ }
19084
+ const match = command.match(/--paymaster-mode (none|sponsored|approval-based)\b/);
19085
+ return match?.[1];
19086
+ }
18533
19087
  function buildWorkflowRuntimeRecommendedCommands(input) {
19088
+ const paymasterMode = extractPaymasterModeFromCommand(input.nextAction) ?? input.paymasterMode;
18534
19089
  return {
18535
19090
  inspectDefaults: "zk-agent defaults",
18536
19091
  list: buildWorkflowListRecommendedCommand(),
@@ -18554,6 +19109,10 @@ function buildWorkflowRuntimeRecommendedCommands(input) {
18554
19109
  } : {},
18555
19110
  discoverTokens: `zk-agent tokens --chain ${input.chain}`,
18556
19111
  inspectToken: `zk-agent resolve-token --chain ${input.chain} --symbol <symbol>`
19112
+ } : {},
19113
+ ...input.chain && paymasterMode === "approval-based" ? {
19114
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(input.chain),
19115
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(input.chain)
18557
19116
  } : {}
18558
19117
  };
18559
19118
  }
@@ -18571,6 +19130,10 @@ function buildWorkflowPlanRecommendedCommands(plan) {
18571
19130
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(plan.walletName),
18572
19131
  discoverTokens: buildTokensRecommendedCommand(plan.chain),
18573
19132
  inspectToken: buildResolveTokenRecommendedCommand(plan.chain)
19133
+ } : {},
19134
+ ...plan.paymasterMode === "approval-based" ? {
19135
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(plan.chain),
19136
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(plan.chain)
18574
19137
  } : {}
18575
19138
  };
18576
19139
  }
@@ -18818,6 +19381,7 @@ async function executeWorkflowRunCommand(options, deps = resolveWorkflowCommandD
18818
19381
  if (inspection.walletApproval?.stage === "request-created" || inspection.result.status === "blocked") {
18819
19382
  return {
18820
19383
  requestId: inspection.requestId,
19384
+ goal: context.goal,
18821
19385
  status: inspection.result,
18822
19386
  walletApproval: inspection.walletApproval,
18823
19387
  checkpoint: inspection.checkpoint
@@ -18855,6 +19419,7 @@ async function executeWorkflowRunCommand(options, deps = resolveWorkflowCommandD
18855
19419
  );
18856
19420
  return {
18857
19421
  requestId: context.requestId,
19422
+ goal: context.goal,
18858
19423
  result,
18859
19424
  walletApproval
18860
19425
  };
@@ -18931,14 +19496,13 @@ function assertWorkflowResumeReady(result) {
18931
19496
  }
18932
19497
  function buildWorkflowHelpText() {
18933
19498
  return [
18934
- "",
18935
- "Default workflow path:",
18936
- " Guided default:",
18937
- " zk-agent workflow auto --wallet main --intent <intent> [goal flags] --create-checkpoint --execute-when-ready",
18938
19499
  "",
18939
19500
  " Flagship native pay path:",
18940
19501
  " zk-agent workflow pay --wallet main --to <address> --amount <amount>",
18941
19502
  "",
19503
+ " Broader multi-intent guided path:",
19504
+ " zk-agent workflow auto --wallet main --intent <intent> [goal flags] --create-checkpoint --execute-when-ready",
19505
+ "",
18942
19506
  " Checkpointed execution:",
18943
19507
  " zk-agent workflow start --wallet main --intent <intent> [goal flags]",
18944
19508
  " zk-agent workflow status --request-id <id>",
@@ -18948,13 +19512,24 @@ function buildWorkflowHelpText() {
18948
19512
  " Funding-only step:",
18949
19513
  " zk-agent workflow fund --wallet main --amount <amount> --execute",
18950
19514
  "",
19515
+ " Token/discovery recovery path:",
19516
+ " zk-agent assets --wallet main",
19517
+ " zk-agent tokens --wallet main --owned",
19518
+ " zk-agent tokens --chain zksync-sepolia",
19519
+ " zk-agent resolve-token --chain zksync-sepolia --symbol USDC",
19520
+ "",
19521
+ " Approval-based paymaster fee-token recovery:",
19522
+ " zk-agent tokens --chain zksync-sepolia --role paymaster-fee-token",
19523
+ " zk-agent resolve-token --chain zksync-sepolia --symbol <symbol> --role paymaster-fee-token",
19524
+ " zk-agent defaults",
19525
+ "",
18951
19526
  " Lower-level one-shot escape hatch:",
18952
19527
  " zk-agent workflow run --wallet main --intent <intent> [goal flags]"
18953
19528
  ].join("\n");
18954
19529
  }
18955
19530
  var WORKFLOW_HELP_COMMAND_ORDER = [
18956
- "auto",
18957
19531
  "pay",
19532
+ "auto",
18958
19533
  "start",
18959
19534
  "status",
18960
19535
  "next",
@@ -18983,7 +19558,7 @@ function applyWorkflowHelpCommandOrder(workflow) {
18983
19558
  function createWorkflowCommand(deps) {
18984
19559
  const resolvedDeps = resolveWorkflowCommandDeps(deps);
18985
19560
  const workflow = new Command10("workflow").description(
18986
- "Build a higher-level CLI workflow for a stored wallet and a concrete action intent"
19561
+ "Plan, persist, and execute higher-level wallet workflows"
18987
19562
  );
18988
19563
  workflow.addHelpText("after", buildWorkflowHelpText());
18989
19564
  workflow.command("plan").description("Plan the prerequisite and execution steps for one concrete wallet workflow").requiredOption(
@@ -18995,15 +19570,19 @@ function createWorkflowCommand(deps) {
18995
19570
  ).option("--to-chain <chain>", "Optional destination chain override for bridge workflows").option("--paymaster-mode <mode>", "none, sponsored, or approval-based").option("--paymaster-address <address>", "Explicit paymaster contract address override").option("--paymaster-token <address>", "ERC-20 token address for approval-based paymaster mode").action(
18996
19571
  async (options) => {
18997
19572
  const intent = parseWorkflowIntent(options.intent);
19573
+ const paymasterInput = resolveWorkflowPaymasterInput(options);
18998
19574
  const { inspection, plan } = await loadWorkflowPlanState(
18999
19575
  options.wallet,
19000
19576
  intent,
19001
19577
  parseWorkflowSwapProtocol(options.protocol),
19002
19578
  options.toChain,
19003
- resolveWorkflowPaymasterInput(options),
19579
+ paymasterInput,
19004
19580
  resolvedDeps
19005
19581
  );
19006
- const recommendedCommands = buildWorkflowPlanRecommendedCommands(plan);
19582
+ const recommendedCommands = buildWorkflowPlanRecommendedCommands({
19583
+ ...plan,
19584
+ paymasterMode: paymasterInput?.mode
19585
+ });
19007
19586
  const agentProfile = await loadWorkflowAgentProfile(plan.walletName);
19008
19587
  const agentFollowup = buildAgentFollowup(agentProfile, {
19009
19588
  walletName: plan.walletName,
@@ -19221,7 +19800,8 @@ function createWorkflowCommand(deps) {
19221
19800
  walletName: inspection.result.walletName,
19222
19801
  nextAction: inspection.result.recommendedCommand,
19223
19802
  chain: inspection.result.plan.chain,
19224
- intent: inspection.result.intent
19803
+ intent: inspection.result.intent,
19804
+ paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal)
19225
19805
  });
19226
19806
  const agentProfile = await loadWorkflowAgentProfile(inspection.result.walletName);
19227
19807
  const agentFollowup = buildAgentFollowup(agentProfile, {
@@ -19272,7 +19852,8 @@ function createWorkflowCommand(deps) {
19272
19852
  walletName: inspection.result.walletName,
19273
19853
  nextAction: nextCommand,
19274
19854
  chain: inspection.result.plan.chain,
19275
- intent: inspection.result.intent
19855
+ intent: inspection.result.intent,
19856
+ paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal)
19276
19857
  });
19277
19858
  const agentProfile = await loadWorkflowAgentProfile(inspection.result.walletName);
19278
19859
  const agentFollowup = buildAgentFollowup(agentProfile, {
@@ -19337,7 +19918,8 @@ function createWorkflowCommand(deps) {
19337
19918
  walletName: inspection.result.walletName,
19338
19919
  nextAction: inspection.result.recommendedCommand,
19339
19920
  chain: inspection.result.plan.chain,
19340
- intent: inspection.result.intent
19921
+ intent: inspection.result.intent,
19922
+ paymasterMode: inspection.walletApproval.request.requestedPaymasterMode
19341
19923
  });
19342
19924
  const agentProfile2 = await loadWorkflowAgentProfile(inspection.result.walletName);
19343
19925
  const agentFollowup2 = buildAgentFollowup(agentProfile2, {
@@ -19388,7 +19970,8 @@ function createWorkflowCommand(deps) {
19388
19970
  walletName: execution.status.walletName,
19389
19971
  nextAction: execution.status.recommendedCommand,
19390
19972
  chain: execution.status.plan.chain,
19391
- intent: execution.status.intent
19973
+ intent: execution.status.intent,
19974
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
19392
19975
  });
19393
19976
  const agentProfile2 = await loadWorkflowAgentProfile(execution.status.walletName);
19394
19977
  const agentFollowup2 = buildAgentFollowup(agentProfile2, {
@@ -19430,7 +20013,8 @@ function createWorkflowCommand(deps) {
19430
20013
  walletName: execution.result.walletName,
19431
20014
  nextAction: execution.result.nextCommand,
19432
20015
  chain: execution.result.plan.chain,
19433
- intent: execution.result.intent
20016
+ intent: execution.result.intent,
20017
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal)
19434
20018
  });
19435
20019
  const agentProfile = await loadWorkflowAgentProfile(execution.result.walletName);
19436
20020
  const agentFollowup = buildAgentFollowup(agentProfile, {
@@ -19497,16 +20081,24 @@ function createWorkflowCommand(deps) {
19497
20081
  function buildDefaultOperatorPathHelpText() {
19498
20082
  return [
19499
20083
  "",
19500
- "Default local-first operator path:",
20084
+ "Public entrypoints:",
20085
+ " Agent harness: npx skills add https://github.com/AgiWeb3/zk-agent-cli",
20086
+ " One-shot CLI: npx zk-agent-cli --help",
20087
+ " Global CLI: npm install -g zk-agent-cli",
20088
+ "",
20089
+ "Canonical terminal path:",
19501
20090
  " zk-agent setup",
19502
20091
  " zk-agent next",
19503
20092
  " zk-agent wallet create --await-local",
19504
20093
  " zk-agent next",
19505
20094
  ` ${buildWorkflowPayRecommendedCommand("main")}`,
19506
20095
  "",
20096
+ "No custom .env is required for setup, next, or wallet create/reapprove request generation.",
20097
+ "Add RPC env vars later, before live reads or broadcasts.",
20098
+ "",
19507
20099
  "Use `zk-agent next --request-id <id>` to continue a stored workflow checkpoint.",
19508
- "Use `zk-agent relay inspect --relay-url <url>` and `zk-agent wallet --help` for the hosted remote-approval path.",
19509
- "Use `zk-agent wallet --help` for bootstrap/reapproval details and `zk-agent workflow --help` once the intent is known."
20100
+ "Use `zk-agent relay inspect --relay-url <url>` plus `zk-agent wallet create|reapprove --relay-url <url> --wait-relay --prompt-code` when the browser is not colocated.",
20101
+ "Use `zk-agent wallet --help` for wallet recovery details and `zk-agent workflow --help` when the intent is broader than the flagship native-send path."
19510
20102
  ].join("\n");
19511
20103
  }
19512
20104
  var ROOT_HELP_COMMAND_ORDER = [
@@ -19547,7 +20139,9 @@ function applyRootHelpCommandOrder(program) {
19547
20139
  program.commands = sortedCommands;
19548
20140
  }
19549
20141
  function createProgram() {
19550
- const program = new Command11().name("zk-agent").description("zkSync and ZK Stack CLI scaffold for agent workflows").showHelpAfterError().option("--json", "Force JSON output for agent harnesses", false).hook("preAction", (thisCommand) => {
20142
+ const program = new Command11().name("zk-agent").description(
20143
+ "Local-first zkSync Era CLI for wallet approval, workflow execution, and hosted relay recovery"
20144
+ ).showHelpAfterError().option("--json", "Force JSON output for agent harnesses", false).hook("preAction", (thisCommand) => {
19551
20145
  if (thisCommand.optsWithGlobals().json) process.env.ZK_AGENT_OUTPUT = "json";
19552
20146
  });
19553
20147
  program.addCommand(createInitCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zk-agent-cli",
3
- "version": "0.1.0-beta.7",
3
+ "version": "0.1.0-beta.8",
4
4
  "description": "Local-first zkSync Era and ZK Stack agent CLI with wallet session recovery, workflow orchestration, relay-backed approval, and SED smart-account support.",
5
5
  "license": "MIT",
6
6
  "type": "module",