zk-agent-cli 0.1.0-beta.8 → 0.1.0-rc.0

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 +24 -3
  2. package/dist/index.js +1783 -154
  3. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command11, CommanderError } from "commander";
4
+ import { Command as Command12, CommanderError } from "commander";
5
5
  import { config as loadEnv } from "dotenv";
6
6
 
7
7
  // src/commands/operations.ts
@@ -7745,6 +7745,71 @@ function formatHumanErrorMessage(error) {
7745
7745
  return lines.join("\n");
7746
7746
  }
7747
7747
 
7748
+ // src/lib/discovery-summary.ts
7749
+ function createEmptyDiscoverySourceCounts() {
7750
+ return {
7751
+ localDeployments: 0,
7752
+ tokenDirectory: 0,
7753
+ unknown: 0
7754
+ };
7755
+ }
7756
+ function createEmptyDiscoveryRoleCounts() {
7757
+ return Object.fromEntries(
7758
+ REGISTRY_TOKEN_ROLES.map((role) => [role, 0])
7759
+ );
7760
+ }
7761
+ function summarizeDiscoveryEntrySources(entries) {
7762
+ const counts = createEmptyDiscoverySourceCounts();
7763
+ for (const entry of entries) {
7764
+ if (entry.source === "local-deployments") {
7765
+ counts.localDeployments += 1;
7766
+ continue;
7767
+ }
7768
+ if (entry.source === "token-directory") {
7769
+ counts.tokenDirectory += 1;
7770
+ continue;
7771
+ }
7772
+ counts.unknown += 1;
7773
+ }
7774
+ return counts;
7775
+ }
7776
+ function summarizeDiscoveryRoleMatches(entries) {
7777
+ const counts = createEmptyDiscoveryRoleCounts();
7778
+ for (const entry of entries) {
7779
+ for (const match of entry.defaultsRegistryMatches || []) {
7780
+ counts[match.role] += 1;
7781
+ }
7782
+ }
7783
+ return counts;
7784
+ }
7785
+ function countCurrentValidatedDefaultEntries(entries) {
7786
+ return entries.filter(
7787
+ (entry) => (entry.defaultsRegistryMatches || []).some((match) => match.isCurrentValidatedDefault)
7788
+ ).length;
7789
+ }
7790
+ function listUniqueDiscoveryChains(entries) {
7791
+ return [...new Set(
7792
+ entries.map((entry) => entry.chainKey?.trim()).filter((value) => Boolean(value))
7793
+ )];
7794
+ }
7795
+ function firstDiscoverySymbol(entries) {
7796
+ return entries.find((entry) => entry.symbol?.trim())?.symbol?.trim() || null;
7797
+ }
7798
+ function firstDiscoverySource(entries) {
7799
+ if (entries.length === 0) return null;
7800
+ return entries[0]?.source || "unknown";
7801
+ }
7802
+ function summarizeTokenRegistrySources(sources) {
7803
+ return sources.map((source) => ({
7804
+ id: source.id,
7805
+ enabled: source.enabled,
7806
+ exists: source.exists
7807
+ }));
7808
+ }
7809
+ function findNativeBalance(balances) {
7810
+ return balances.find((balance) => balance.type === "native") || null;
7811
+ }
7812
+
7748
7813
  // src/lib/recommended-commands.ts
7749
7814
  function appendPaymasterMode(command, paymasterMode) {
7750
7815
  if (!paymasterMode || paymasterMode === "none") {
@@ -7765,13 +7830,61 @@ function buildWalletCreateRecommendedCommand() {
7765
7830
  function buildRelayInspectRecommendedCommand(relayUrl = "<url>") {
7766
7831
  return `zk-agent relay inspect --relay-url ${relayUrl}`;
7767
7832
  }
7768
- function buildWalletCreateRemoteRecommendedCommand(relayUrl = "<url>", paymasterMode, walletName = "main", accountKind = "smart-account") {
7769
- const command = [
7833
+ function inferSessionHours(sessionPolicies, requestCreatedAt) {
7834
+ const expiresAt = sessionPolicies?.expiresAt;
7835
+ if (!expiresAt || !requestCreatedAt) return null;
7836
+ const createdAtMs = Date.parse(requestCreatedAt);
7837
+ const expiresAtMs = Date.parse(expiresAt);
7838
+ if (!Number.isFinite(createdAtMs) || !Number.isFinite(expiresAtMs) || expiresAtMs <= createdAtMs) {
7839
+ return null;
7840
+ }
7841
+ const hours = (expiresAtMs - createdAtMs) / (60 * 60 * 1e3);
7842
+ if (!Number.isFinite(hours) || hours <= 0) return null;
7843
+ const rounded = Math.round(hours * 1e3) / 1e3;
7844
+ if (Math.abs(rounded - 24) < 5e-4) {
7845
+ return null;
7846
+ }
7847
+ return Number.isInteger(rounded) ? String(rounded) : String(rounded).replace(/(?:\.0+|(\.\d*?)0+)$/, "$1");
7848
+ }
7849
+ function appendSessionPolicyFlags(commandParts, options) {
7850
+ const sessionHours = inferSessionHours(options?.sessionPolicies, options?.requestCreatedAt);
7851
+ if (sessionHours) {
7852
+ commandParts.push(`--session-hours ${sessionHours}`);
7853
+ }
7854
+ const transfers = options?.sessionPolicies?.transfers;
7855
+ if (Array.isArray(transfers)) {
7856
+ if (transfers.length === 0) {
7857
+ commandParts.push("--disallow-transfers");
7858
+ } else {
7859
+ for (const policy of transfers) {
7860
+ if (policy?.to) {
7861
+ commandParts.push(`--allow-transfer-to ${policy.to}`);
7862
+ }
7863
+ }
7864
+ }
7865
+ }
7866
+ const contractCalls = options?.sessionPolicies?.contractCalls;
7867
+ if (Array.isArray(contractCalls)) {
7868
+ if (contractCalls.length === 0) {
7869
+ commandParts.push("--disallow-contract-calls");
7870
+ } else {
7871
+ for (const policy of contractCalls) {
7872
+ if (policy?.address) {
7873
+ commandParts.push(`--allow-contract ${policy.address}`);
7874
+ }
7875
+ }
7876
+ }
7877
+ }
7878
+ }
7879
+ function buildWalletCreateRemoteRecommendedCommand(relayUrl = "<url>", paymasterMode, walletName = "main", accountKind = "smart-account", options) {
7880
+ const commandParts = [
7770
7881
  "zk-agent wallet create",
7771
7882
  walletName !== "main" ? `--name ${walletName}` : "",
7772
- accountKind !== "smart-account" ? `--account-kind ${accountKind}` : "",
7773
- `--relay-url ${relayUrl} --wait-relay --prompt-code`
7774
- ].filter(Boolean).join(" ");
7883
+ accountKind !== "smart-account" ? `--account-kind ${accountKind}` : ""
7884
+ ].filter(Boolean);
7885
+ appendSessionPolicyFlags(commandParts, options);
7886
+ commandParts.push(`--relay-url ${relayUrl} --wait-relay --prompt-code`);
7887
+ const command = commandParts.join(" ");
7775
7888
  return appendPaymasterMode(command, paymasterMode);
7776
7889
  }
7777
7890
  function buildWalletListRecommendedCommand() {
@@ -7780,6 +7893,9 @@ function buildWalletListRecommendedCommand() {
7780
7893
  function buildWalletStatusRecommendedCommand(walletName) {
7781
7894
  return `zk-agent wallet status --name ${walletName}`;
7782
7895
  }
7896
+ function buildWalletSignerShowRecommendedCommand(walletName) {
7897
+ return `zk-agent wallet signer show --name ${walletName}`;
7898
+ }
7783
7899
  function buildWalletSignerAttachRecommendedCommand(walletName, privateKeyRef = "<hex>") {
7784
7900
  return `zk-agent wallet signer attach --name ${walletName} --private-key ${privateKeyRef}`;
7785
7901
  }
@@ -7836,8 +7952,11 @@ function buildDiscoveryRecommendedCommands(input) {
7836
7952
  function buildWalletReapproveRecommendedCommand(walletName) {
7837
7953
  return `zk-agent wallet reapprove --name ${walletName} --await-local`;
7838
7954
  }
7839
- function buildWalletReapproveRemoteRecommendedCommand(walletName, relayUrl = "<url>") {
7840
- return `zk-agent wallet reapprove --name ${walletName} --relay-url ${relayUrl} --wait-relay --prompt-code`;
7955
+ function buildWalletReapproveRemoteRecommendedCommand(walletName, relayUrl = "<url>", options) {
7956
+ const commandParts = [`zk-agent wallet reapprove --name ${walletName}`];
7957
+ appendSessionPolicyFlags(commandParts, options);
7958
+ commandParts.push(`--relay-url ${relayUrl} --wait-relay --prompt-code`);
7959
+ return commandParts.join(" ");
7841
7960
  }
7842
7961
  function buildWalletNextRecommendedCommand(walletName) {
7843
7962
  return `zk-agent wallet next --name ${walletName}`;
@@ -9181,6 +9300,27 @@ function linesForMultiBalances(result) {
9181
9300
  }
9182
9301
  return lines;
9183
9302
  }
9303
+ function buildAssetsDiscoverySummary(result) {
9304
+ const nativeBalance = findNativeBalance(result.balances);
9305
+ const ownedTokenSymbols = (result.ownedTokenRegistry?.entries || []).map((entry) => entry.symbol?.trim()).filter((value) => Boolean(value));
9306
+ return {
9307
+ walletName: result.walletName,
9308
+ chain: result.chain,
9309
+ chainId: result.chainId,
9310
+ assetCount: result.balances.length,
9311
+ nativeAssetSymbol: nativeBalance?.symbol || null,
9312
+ nativeAssetBalance: nativeBalance?.balance || null,
9313
+ ownedTokenCount: result.ownedTokenRegistry?.entryCount || 0,
9314
+ primaryOwnedTokenSymbol: firstDiscoverySymbol(result.ownedTokenRegistry?.entries || []),
9315
+ ownedTokenSymbols,
9316
+ ownedTokenSourceCounts: result.ownedTokenRegistry?.summary.sourceCounts || null,
9317
+ ownedBridgeMappingCounts: result.ownedTokenRegistry?.summary.bridgeMappingCounts || null,
9318
+ ownedRegistryRoleCounts: result.ownedTokenRegistry?.summary.registryRoleCounts || null
9319
+ };
9320
+ }
9321
+ function buildBalancesDiscoverySummary(result) {
9322
+ return buildAssetsDiscoverySummary(result);
9323
+ }
9184
9324
  function withPaymasterOptions(command) {
9185
9325
  return command.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");
9186
9326
  }
@@ -9240,7 +9380,23 @@ function createBalancesCommand(deps) {
9240
9380
  provider: resolvedDeps.provider,
9241
9381
  ownedTokens: options.ownedTokens
9242
9382
  });
9243
- printResult(linesForSingleBalances(payload), { ok: true, ...payload });
9383
+ const discoverySummary = options.ownedTokens && "ownedTokenRegistry" in payload ? buildBalancesDiscoverySummary(payload) : void 0;
9384
+ const recommendedCommands = options.ownedTokens ? buildDiscoveryRecommendedCommands({
9385
+ walletName,
9386
+ chain: payload.chain
9387
+ }) : void 0;
9388
+ printResult(
9389
+ [
9390
+ ...linesForSingleBalances(payload),
9391
+ ...recommendedCommands ? workflowFollowupLines(recommendedCommands) : []
9392
+ ],
9393
+ {
9394
+ ok: true,
9395
+ ...discoverySummary ? { discoverySummary } : {},
9396
+ ...recommendedCommands ? { recommendedCommands } : {},
9397
+ ...payload
9398
+ }
9399
+ );
9244
9400
  });
9245
9401
  }
9246
9402
  function createAssetsCommand(deps) {
@@ -9279,9 +9435,12 @@ function createAssetsCommand(deps) {
9279
9435
  chain: payload.chain,
9280
9436
  includeAssets: false
9281
9437
  });
9438
+ const discoverySummary = buildAssetsDiscoverySummary(
9439
+ payload
9440
+ );
9282
9441
  printResult(
9283
9442
  [...linesForSingleBalances(payload), ...workflowFollowupLines(recommendedCommands)],
9284
- { ok: true, recommendedCommands, ...payload }
9443
+ { ok: true, discoverySummary, recommendedCommands, ...payload }
9285
9444
  );
9286
9445
  });
9287
9446
  }
@@ -9961,12 +10120,43 @@ function createPlannedCommands() {
9961
10120
 
9962
10121
  // src/commands/setup.ts
9963
10122
  import { Command as Command2 } from "commander";
10123
+
10124
+ // src/lib/onboarding-summary.ts
10125
+ function buildOnboardingSummary(input) {
10126
+ return {
10127
+ stage: input.stage,
10128
+ baseline: "local-first",
10129
+ localOnly: input.localOnly,
10130
+ configExists: input.configExists,
10131
+ walletExists: input.walletExists ?? null,
10132
+ approvalReady: input.approvalReady ?? null,
10133
+ localExecutionKeyStored: input.localExecutionKeyStored ?? null,
10134
+ defaultChain: input.defaultChain ?? null,
10135
+ connectorUrl: input.connectorUrl ?? null,
10136
+ relayUrl: input.relayUrl ?? null,
10137
+ nextAction: input.nextAction ?? null,
10138
+ notes: [...input.notes ?? []]
10139
+ };
10140
+ }
10141
+ function onboardingSummaryLines(summary) {
10142
+ return [
10143
+ ["baseline", summary.baseline],
10144
+ ["local only", summary.localOnly ? "yes" : "no"]
10145
+ ];
10146
+ }
10147
+
10148
+ // src/commands/setup.ts
9964
10149
  function buildSetupHelpText() {
9965
10150
  return [
9966
10151
  "",
9967
10152
  "What setup does:",
9968
10153
  " Writes the local default chain and connector URL used by the first-run path.",
9969
10154
  "",
10155
+ "Validated first-run baseline:",
10156
+ " Default chain: zksync-sepolia",
10157
+ " Connector URL: http://localhost:4444",
10158
+ " Override --default-chain or --connector-url only when you intentionally deviate from that path.",
10159
+ "",
9970
10160
  "After setup, stay on the canonical local-first path:",
9971
10161
  " zk-agent next",
9972
10162
  " zk-agent wallet create --await-local",
@@ -9983,7 +10173,7 @@ function buildSetupHelpText() {
9983
10173
  ].join("\n");
9984
10174
  }
9985
10175
  function createInitCommand() {
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) => {
10176
+ return new Command2("init").alias("setup").description("Initialize local zk-agent configuration for the validated first-run operator path").addHelpText("after", buildSetupHelpText()).option("--default-chain <chain>", "Default chain key", "zksync-sepolia").option("--connector-url <url>", "Connector UI base URL", "http://localhost:4444").option("--force", "Overwrite an existing config", false).action(async (options) => {
9987
10177
  const recommendedCommands = {
9988
10178
  next: buildTopLevelNextRecommendedCommand(),
9989
10179
  inspectDefaults: buildDefaultsRecommendedCommand(),
@@ -9994,9 +10184,22 @@ function createInitCommand() {
9994
10184
  };
9995
10185
  const existing = await loadProjectConfig();
9996
10186
  if (existing && !options.force) {
10187
+ const onboardingSummary2 = buildOnboardingSummary({
10188
+ stage: "wallet-bootstrap",
10189
+ localOnly: true,
10190
+ configExists: true,
10191
+ defaultChain: existing.defaultChain,
10192
+ connectorUrl: existing.connectorUrl,
10193
+ nextAction: recommendedCommands.next,
10194
+ notes: [
10195
+ "Setup did not overwrite the existing local defaults.",
10196
+ "Run zk-agent next so the CLI can choose wallet bootstrap or workflow follow-up from the current local state."
10197
+ ]
10198
+ });
9997
10199
  printResult(
9998
10200
  [
9999
10201
  ["status", "Config already exists. Re-run with --force to overwrite."],
10202
+ ...onboardingSummaryLines(onboardingSummary2),
10000
10203
  ["default chain", existing.defaultChain],
10001
10204
  ["connector", existing.connectorUrl],
10002
10205
  ["next", recommendedCommands.next],
@@ -10010,22 +10213,36 @@ function createInitCommand() {
10010
10213
  ok: true,
10011
10214
  message: "Config already exists. Re-run with --force to overwrite.",
10012
10215
  config: existing,
10216
+ onboardingSummary: onboardingSummary2,
10013
10217
  recommendedCommands
10014
10218
  }
10015
10219
  );
10016
10220
  return;
10017
10221
  }
10018
10222
  const config = {
10019
- defaultChain: options.defaultChain || "zksync-era",
10223
+ defaultChain: options.defaultChain || "zksync-sepolia",
10020
10224
  connectorUrl: options.connectorUrl || "http://localhost:4444",
10021
10225
  provider: "zksync-sso",
10022
10226
  createdAt: existing?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
10023
10227
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
10024
10228
  };
10025
10229
  await saveProjectConfig(config);
10230
+ const onboardingSummary = buildOnboardingSummary({
10231
+ stage: "wallet-bootstrap",
10232
+ localOnly: true,
10233
+ configExists: true,
10234
+ defaultChain: config.defaultChain,
10235
+ connectorUrl: config.connectorUrl,
10236
+ nextAction: recommendedCommands.next,
10237
+ notes: [
10238
+ "Setup only writes local defaults and does not inspect wallet state.",
10239
+ "Stay on zk-agent next so the product entrypoint can decide between wallet bootstrap and workflow guidance."
10240
+ ]
10241
+ });
10026
10242
  printResult(
10027
10243
  [
10028
10244
  ["status", "Config saved"],
10245
+ ...onboardingSummaryLines(onboardingSummary),
10029
10246
  ["default chain", config.defaultChain],
10030
10247
  ["connector", config.connectorUrl],
10031
10248
  ["next", recommendedCommands.next],
@@ -10035,7 +10252,7 @@ function createInitCommand() {
10035
10252
  ["create wallet (remote)", recommendedCommands.createWalletRemote],
10036
10253
  ["after approval", recommendedCommands.afterWalletApproval]
10037
10254
  ],
10038
- { ok: true, config, recommendedCommands }
10255
+ { ok: true, config, onboardingSummary, recommendedCommands }
10039
10256
  );
10040
10257
  });
10041
10258
  }
@@ -10399,16 +10616,50 @@ function agentProfileLines(summary) {
10399
10616
  }
10400
10617
 
10401
10618
  // src/lib/wallet-next.ts
10402
- function buildWalletNextRecommendedCommands(walletName, summary) {
10619
+ function buildWalletNextRecommendedCommands(walletName, summary, paymasterMode) {
10403
10620
  return {
10404
10621
  discoverAssets: buildAssetsRecommendedCommand(walletName),
10405
10622
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(walletName),
10623
+ ...paymasterMode === "approval-based" ? {
10624
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(summary.chain),
10625
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(summary.chain)
10626
+ } : {},
10406
10627
  discoverTokens: buildTokensRecommendedCommand(summary.chain),
10407
10628
  inspectToken: buildResolveTokenRecommendedCommand(summary.chain),
10408
10629
  walletStatus: buildWalletStatusRecommendedCommand(walletName),
10409
10630
  ...summary.recommendedCommand ? { nextAction: summary.recommendedCommand } : {}
10410
10631
  };
10411
10632
  }
10633
+ function workflowIntentSupportsTokenDiscovery(intent) {
10634
+ return intent === "send-token" || intent === "swap" || intent === "bridge" || intent === "deposit" || intent === "withdraw";
10635
+ }
10636
+ function buildWalletTokenDiscoverySummary(input) {
10637
+ if (!input.recommendedCommands) {
10638
+ return void 0;
10639
+ }
10640
+ const hasTokenDiscovery = Boolean(input.recommendedCommands.discoverAssets) || Boolean(input.recommendedCommands.discoverOwnedTokens) || Boolean(input.recommendedCommands.discoverTokens) || Boolean(input.recommendedCommands.inspectToken) || Boolean(input.recommendedCommands.discoverPaymasterTokens) || Boolean(input.recommendedCommands.inspectPaymasterToken);
10641
+ if (!hasTokenDiscovery) {
10642
+ return void 0;
10643
+ }
10644
+ return {
10645
+ walletName: input.walletName,
10646
+ chain: input.chain,
10647
+ intent: input.intent || null,
10648
+ nextAction: input.nextAction || null,
10649
+ paymasterMode: input.paymasterMode || null,
10650
+ tokenizedIntent: workflowIntentSupportsTokenDiscovery(input.intent),
10651
+ includesAssetDiscovery: Boolean(input.recommendedCommands.discoverAssets),
10652
+ includesOwnedTokenDiscovery: Boolean(input.recommendedCommands.discoverOwnedTokens),
10653
+ includesChainTokenDiscovery: Boolean(input.recommendedCommands.discoverTokens),
10654
+ includesDirectTokenInspection: Boolean(input.recommendedCommands.inspectToken),
10655
+ includesPaymasterTokenDiscovery: Boolean(
10656
+ input.recommendedCommands.discoverPaymasterTokens
10657
+ ),
10658
+ includesPaymasterTokenInspection: Boolean(
10659
+ input.recommendedCommands.inspectPaymasterToken
10660
+ )
10661
+ };
10662
+ }
10412
10663
  function walletNextLines(summary) {
10413
10664
  const lines = [
10414
10665
  ["wallet", summary.walletName],
@@ -10443,7 +10694,7 @@ var defaultProvider = new ZkSyncWalletProvider();
10443
10694
  var defaultDefiProvider = new ZkSyncDefiProvider({
10444
10695
  walletWriter: defaultProvider
10445
10696
  });
10446
- function workflowIntentSupportsTokenDiscovery(intent) {
10697
+ function workflowIntentSupportsTokenDiscovery2(intent) {
10447
10698
  return intent === "send-token" || intent === "swap" || intent === "bridge" || intent === "deposit" || intent === "withdraw";
10448
10699
  }
10449
10700
  function buildTopLevelWorkflowRecommendedCommands(input) {
@@ -10457,7 +10708,7 @@ function buildTopLevelWorkflowRecommendedCommands(input) {
10457
10708
  delete: buildWorkflowDeleteRecommendedCommand(input.requestId),
10458
10709
  walletStatus: buildWalletStatusRecommendedCommand(input.walletName),
10459
10710
  ...input.nextAction ? { nextAction: input.nextAction } : {},
10460
- ...workflowIntentSupportsTokenDiscovery(input.intent) ? {
10711
+ ...workflowIntentSupportsTokenDiscovery2(input.intent) ? {
10461
10712
  discoverAssets: buildAssetsRecommendedCommand(input.walletName),
10462
10713
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(input.walletName),
10463
10714
  discoverTokens: buildTokensRecommendedCommand(input.chain),
@@ -10485,17 +10736,38 @@ function buildSetupCommand() {
10485
10736
  function buildTopLevelNextRecommendedCommand2(requestId) {
10486
10737
  return requestId ? `zk-agent next --request-id ${requestId}` : "zk-agent next";
10487
10738
  }
10739
+ function buildTopLevelWorkflowSummary(result, nextCommand) {
10740
+ return {
10741
+ status: result.status,
10742
+ readyForGoal: result.readyForGoal,
10743
+ nextCommand,
10744
+ blockingActionIds: result.blockingActionIds,
10745
+ fundingProgress: result.fundingProgress ? {
10746
+ kind: result.fundingProgress.kind,
10747
+ txHash: result.fundingProgress.txHash,
10748
+ status: result.fundingProgress.status,
10749
+ terminal: result.fundingProgress.terminal,
10750
+ finalized: result.fundingProgress.finalized
10751
+ } : void 0
10752
+ };
10753
+ }
10488
10754
  function appendPaymasterMode2(command, paymasterMode) {
10489
10755
  if (!paymasterMode) return command;
10490
10756
  return `${command} --paymaster-mode ${paymasterMode}`;
10491
10757
  }
10492
- function topLevelNextLines(scope, lines) {
10493
- return [["scope", scope], ...lines];
10758
+ function topLevelNextLines(scope, lines, onboardingSummary) {
10759
+ return [
10760
+ ["scope", scope],
10761
+ ...onboardingSummary ? onboardingSummaryLines(onboardingSummary) : [],
10762
+ ...lines
10763
+ ];
10494
10764
  }
10495
10765
  function buildNextHelpText() {
10496
10766
  return [
10497
10767
  "",
10498
10768
  "Use `next` as the product entrypoint:",
10769
+ " Stay on `next` until it points you at a wallet-specific or workflow-specific blocker.",
10770
+ "",
10499
10771
  " Fresh local-first routing:",
10500
10772
  " zk-agent setup",
10501
10773
  " zk-agent next",
@@ -10507,6 +10779,8 @@ function buildNextHelpText() {
10507
10779
  " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
10508
10780
  " zk-agent next",
10509
10781
  "",
10782
+ " If setup has not run yet, `next` will send you back to `zk-agent setup` first.",
10783
+ "",
10510
10784
  " Continue a stored workflow checkpoint:",
10511
10785
  " zk-agent next --request-id <id>",
10512
10786
  "",
@@ -10516,6 +10790,9 @@ function buildNextHelpText() {
10516
10790
  " Switch to the hosted remote-approval path only when the browser is not colocated:",
10517
10791
  " zk-agent wallet --help",
10518
10792
  "",
10793
+ " Use `wallet --help` when you already know the blocker is wallet-specific:",
10794
+ " zk-agent wallet next --name main",
10795
+ "",
10519
10796
  " Stay on the workflow layer only when you already have an explicit workflow or checkpoint:",
10520
10797
  " zk-agent workflow next --request-id <id>"
10521
10798
  ].join("\n");
@@ -10565,6 +10842,14 @@ function createNextCommand(deps) {
10565
10842
  intent: result.intent,
10566
10843
  paymasterMode: extractCheckpointPaymasterMode(updatedCheckpoint)
10567
10844
  });
10845
+ const tokenDiscoverySummary2 = buildWalletTokenDiscoverySummary({
10846
+ walletName: wallet2.walletName,
10847
+ chain: result.plan.chain,
10848
+ intent: result.intent,
10849
+ nextAction: nextCommand2,
10850
+ paymasterMode: extractCheckpointPaymasterMode(updatedCheckpoint),
10851
+ recommendedCommands: recommendedCommands2
10852
+ });
10568
10853
  const workflowAgentProfile = await loadAgentIdentitySummary(wallet2.walletName);
10569
10854
  const agentFollowup2 = buildAgentFollowup(workflowAgentProfile, {
10570
10855
  walletName: wallet2.walletName,
@@ -10597,8 +10882,10 @@ function createNextCommand(deps) {
10597
10882
  nextCommand: nextCommand2,
10598
10883
  agentProfile: workflowAgentProfile,
10599
10884
  agentFollowup: agentFollowup2,
10885
+ summary: buildTopLevelWorkflowSummary(result, nextCommand2),
10600
10886
  result,
10601
10887
  checkpoint: updatedCheckpoint,
10888
+ tokenDiscoverySummary: tokenDiscoverySummary2,
10602
10889
  recommendedCommands: recommendedCommands2
10603
10890
  }
10604
10891
  );
@@ -10611,6 +10898,17 @@ function createNextCommand(deps) {
10611
10898
  afterSetup: buildTopLevelNextRecommendedCommand2(),
10612
10899
  inspectDefaults: buildDefaultsRecommendedCommand()
10613
10900
  };
10901
+ const onboardingSummary2 = buildOnboardingSummary({
10902
+ stage: "setup",
10903
+ localOnly: true,
10904
+ configExists: false,
10905
+ walletExists: false,
10906
+ nextAction: recommendedCommands2.setup,
10907
+ notes: [
10908
+ "No local config was found, so setup is still the first required onboarding step.",
10909
+ "This scope is local-only and does not require live RPC reads."
10910
+ ]
10911
+ });
10614
10912
  printResult(
10615
10913
  topLevelNextLines("setup", [
10616
10914
  ["status", "No local config found"],
@@ -10619,12 +10917,13 @@ function createNextCommand(deps) {
10619
10917
  ["next", recommendedCommands2.setup],
10620
10918
  ["after setup", recommendedCommands2.afterSetup],
10621
10919
  ["inspect defaults", recommendedCommands2.inspectDefaults]
10622
- ]),
10920
+ ], onboardingSummary2),
10623
10921
  {
10624
10922
  ok: true,
10625
10923
  scope: "setup",
10626
10924
  status: "action-required",
10627
10925
  nextCommand: recommendedCommands2.setup,
10926
+ onboardingSummary: onboardingSummary2,
10628
10927
  agentProfile,
10629
10928
  agentFollowup: defaultAgentFollowup,
10630
10929
  recommendedCommands: recommendedCommands2
@@ -10647,6 +10946,19 @@ function createNextCommand(deps) {
10647
10946
  afterApproval: appendPaymasterMode2(buildTopLevelNextRecommendedCommand2(), paymasterMode),
10648
10947
  inspectDefaults: buildDefaultsRecommendedCommand()
10649
10948
  };
10949
+ const onboardingSummary2 = buildOnboardingSummary({
10950
+ stage: "wallet-bootstrap",
10951
+ localOnly: true,
10952
+ configExists: true,
10953
+ walletExists: false,
10954
+ defaultChain: config.defaultChain,
10955
+ connectorUrl: config.connectorUrl,
10956
+ nextAction: recommendedCommands2.createWallet,
10957
+ notes: [
10958
+ "Config exists, but no saved wallet record was found for this name yet.",
10959
+ "Use the remote approval fallback only when the browser is not colocated with this terminal."
10960
+ ]
10961
+ });
10650
10962
  printResult(
10651
10963
  topLevelNextLines("wallet-bootstrap", [
10652
10964
  ["status", `Wallet not found: ${walletName}`],
@@ -10659,13 +10971,14 @@ function createNextCommand(deps) {
10659
10971
  ["remote fallback", recommendedCommands2.createWalletRemote],
10660
10972
  ["after approval", recommendedCommands2.afterApproval],
10661
10973
  ["inspect defaults", recommendedCommands2.inspectDefaults]
10662
- ]),
10974
+ ], onboardingSummary2),
10663
10975
  {
10664
10976
  ok: true,
10665
10977
  scope: "wallet-bootstrap",
10666
10978
  walletName,
10667
10979
  config,
10668
10980
  nextCommand: recommendedCommands2.createWallet,
10981
+ onboardingSummary: onboardingSummary2,
10669
10982
  agentProfile,
10670
10983
  agentFollowup: defaultAgentFollowup,
10671
10984
  recommendedCommands: recommendedCommands2
@@ -10701,6 +11014,27 @@ function createNextCommand(deps) {
10701
11014
  paymasterMode
10702
11015
  );
10703
11016
  const nextCommand = summary.recommendedCommand || workflowPay;
11017
+ const onboardingSummary = buildOnboardingSummary({
11018
+ stage: inspection.approvalReady && inspection.localExecutionKeyStored ? "wallet-ready" : "wallet-recovery",
11019
+ localOnly: false,
11020
+ configExists: true,
11021
+ walletExists: true,
11022
+ approvalReady: inspection.approvalReady,
11023
+ localExecutionKeyStored: inspection.localExecutionKeyStored,
11024
+ defaultChain: config.defaultChain,
11025
+ connectorUrl: config.connectorUrl,
11026
+ nextAction: nextCommand,
11027
+ notes: !inspection.approvalReady ? [
11028
+ "Wallet metadata exists, but approved session metadata is still missing.",
11029
+ "Top-level next returns to live workflow guidance after wallet approval is restored."
11030
+ ] : !inspection.localExecutionKeyStored ? [
11031
+ "Approved session metadata exists, but no local execution signer is stored yet.",
11032
+ "Top-level next returns to live workflow guidance after the signer is attached."
11033
+ ] : [
11034
+ "Wallet approval and local signer state are present.",
11035
+ "Top-level next also inspects live deployment and balance state before recommending the workflow step."
11036
+ ]
11037
+ });
10704
11038
  const agentFollowup = buildAgentFollowup(agentProfile, {
10705
11039
  walletName: wallet.walletName,
10706
11040
  walletExists: true
@@ -10721,6 +11055,13 @@ function createNextCommand(deps) {
10721
11055
  nextAction: nextCommand,
10722
11056
  inspectDefaults: buildDefaultsRecommendedCommand()
10723
11057
  };
11058
+ const tokenDiscoverySummary = buildWalletTokenDiscoverySummary({
11059
+ walletName: wallet.walletName,
11060
+ chain: wallet.chain,
11061
+ nextAction: nextCommand,
11062
+ paymasterMode,
11063
+ recommendedCommands
11064
+ });
10724
11065
  printResult(
10725
11066
  topLevelNextLines("wallet", [
10726
11067
  ...walletNextLines(summary),
@@ -10734,16 +11075,18 @@ function createNextCommand(deps) {
10734
11075
  ...recommendedCommands.inspectPaymasterToken ? [["inspect paymaster token", recommendedCommands.inspectPaymasterToken]] : [],
10735
11076
  ["inspect token", recommendedCommands.inspectToken],
10736
11077
  ["inspect defaults", recommendedCommands.inspectDefaults]
10737
- ]),
11078
+ ], onboardingSummary),
10738
11079
  {
10739
11080
  ok: true,
10740
11081
  scope: "wallet",
10741
11082
  walletName: wallet.walletName,
11083
+ onboardingSummary,
10742
11084
  agentProfile,
10743
11085
  agentFollowup,
10744
11086
  inspection,
10745
11087
  summary,
10746
11088
  nextCommand,
11089
+ tokenDiscoverySummary,
10747
11090
  recommendedCommands
10748
11091
  }
10749
11092
  );
@@ -10756,8 +11099,418 @@ function parsePaymasterMode(value) {
10756
11099
  throw new Error(`Unsupported paymaster mode: ${value}`);
10757
11100
  }
10758
11101
 
10759
- // src/commands/agent.ts
11102
+ // src/commands/doctor.ts
10760
11103
  import { Command as Command4 } from "commander";
11104
+ function buildDoctorHelpText() {
11105
+ return [
11106
+ "",
11107
+ "Use `doctor` when local state is unclear:",
11108
+ " zk-agent doctor",
11109
+ " zk-agent doctor --wallet main",
11110
+ " zk-agent doctor --wallet main --relay-url https://relay.example.com",
11111
+ "",
11112
+ "Default behavior:",
11113
+ " Inspects saved config, local wallet approval metadata, local signer state,",
11114
+ " and the shortest next command without requiring live RPC reads.",
11115
+ " Run this before guessing whether the blocker is setup, wallet approval, or local signer state.",
11116
+ "",
11117
+ "Remote-browser recovery path:",
11118
+ " Pass --relay-url when you want the remote approval fallback commands",
11119
+ " to use a concrete relay URL instead of a placeholder."
11120
+ ].join("\n");
11121
+ }
11122
+ function summarizeLocalWalletState(wallet) {
11123
+ const localExecutionPrivateKey = resolveLocalExecutionPrivateKey(wallet);
11124
+ return {
11125
+ exists: true,
11126
+ walletName: wallet.walletName,
11127
+ walletAddress: wallet.walletAddress,
11128
+ chain: wallet.chain,
11129
+ chainId: wallet.chainId,
11130
+ accountKind: wallet.accountKind || wallet.sessionPayload?.account?.kind || "smart-account",
11131
+ smartAccountProfileId: wallet.smartAccountProfileId || null,
11132
+ syncedAt: wallet.syncedAt || null,
11133
+ approvalReady: Boolean(wallet.sessionPayload),
11134
+ localExecutionKeyStored: Boolean(localExecutionPrivateKey),
11135
+ legacySessionKeyStored: Boolean(wallet.sessionPayload?.sessionPrivateKey),
11136
+ signerType: wallet.localExecutionAuthority?.signerType || wallet.sessionPayload?.account?.signerType || null,
11137
+ signerAddress: wallet.localExecutionAuthority?.signerAddress || deriveLocalExecutionSignerAddress(localExecutionPrivateKey) || null,
11138
+ signerSource: wallet.localExecutionAuthority?.source || (wallet.sessionPayload?.sessionPrivateKey ? "legacy-session-payload" : null)
11139
+ };
11140
+ }
11141
+ function buildSetupRecommendedCommands() {
11142
+ return {
11143
+ setup: "zk-agent setup",
11144
+ next: buildTopLevelNextRecommendedCommand(),
11145
+ inspectDefaults: buildDefaultsRecommendedCommand()
11146
+ };
11147
+ }
11148
+ function buildWalletBootstrapRecommendedCommands(walletName, relayUrl) {
11149
+ return {
11150
+ next: buildTopLevelNextRecommendedCommand(),
11151
+ inspectDefaults: buildDefaultsRecommendedCommand(),
11152
+ createWallet: buildWalletCreateRecommendedCommand(),
11153
+ relayInspect: buildRelayInspectRecommendedCommand(relayUrl),
11154
+ createWalletRemote: buildWalletCreateRemoteRecommendedCommand(relayUrl, void 0, walletName)
11155
+ };
11156
+ }
11157
+ function buildWalletRecoveryRecommendedCommands(wallet, relayUrl) {
11158
+ const shared = {
11159
+ next: buildTopLevelNextRecommendedCommand(),
11160
+ walletStatus: buildWalletStatusRecommendedCommand(wallet.walletName),
11161
+ walletNext: buildWalletNextRecommendedCommand(wallet.walletName),
11162
+ signerShow: buildWalletSignerShowRecommendedCommand(wallet.walletName),
11163
+ relayInspect: buildRelayInspectRecommendedCommand(relayUrl),
11164
+ reapproveRemote: buildWalletReapproveRemoteRecommendedCommand(wallet.walletName, relayUrl)
11165
+ };
11166
+ if (!wallet.approvalReady) {
11167
+ return {
11168
+ ...shared,
11169
+ reapprove: buildWalletReapproveRecommendedCommand(wallet.walletName)
11170
+ };
11171
+ }
11172
+ return {
11173
+ ...shared,
11174
+ attachSigner: buildWalletSignerAttachRecommendedCommand(wallet.walletName),
11175
+ reapprove: buildWalletReapproveRecommendedCommand(wallet.walletName)
11176
+ };
11177
+ }
11178
+ function buildWalletReadyRecommendedCommands(wallet) {
11179
+ return {
11180
+ next: buildTopLevelNextRecommendedCommand(),
11181
+ walletStatus: buildWalletStatusRecommendedCommand(wallet.walletName),
11182
+ walletNext: buildWalletNextRecommendedCommand(wallet.walletName),
11183
+ workflowPay: buildWorkflowPayRecommendedCommand(wallet.walletName),
11184
+ inspectDefaults: buildDefaultsRecommendedCommand()
11185
+ };
11186
+ }
11187
+ function buildDoctorResult(options) {
11188
+ if (!options.config) {
11189
+ const recommendedCommands2 = buildSetupRecommendedCommands();
11190
+ const onboardingSummary2 = buildOnboardingSummary({
11191
+ stage: "setup",
11192
+ localOnly: true,
11193
+ configExists: false,
11194
+ walletExists: Boolean(options.wallet),
11195
+ approvalReady: options.wallet?.approvalReady ?? null,
11196
+ localExecutionKeyStored: options.wallet?.localExecutionKeyStored ?? null,
11197
+ relayUrl: options.relayUrl || null,
11198
+ nextAction: recommendedCommands2.setup,
11199
+ notes: [
11200
+ "Local config is missing, so the canonical operator path should start with setup.",
11201
+ "Doctor is local-only by default and does not require live RPC reads."
11202
+ ]
11203
+ });
11204
+ return {
11205
+ scope: "setup",
11206
+ nextAction: recommendedCommands2.setup,
11207
+ onboardingSummary: onboardingSummary2,
11208
+ summary: {
11209
+ stage: "setup",
11210
+ configExists: false,
11211
+ walletExists: Boolean(options.wallet),
11212
+ approvalReady: options.wallet?.approvalReady ?? null,
11213
+ localExecutionKeyStored: options.wallet?.localExecutionKeyStored ?? null,
11214
+ relayUrl: options.relayUrl || null,
11215
+ nextAction: recommendedCommands2.setup,
11216
+ localOnly: true,
11217
+ notes: [
11218
+ "Local config is missing, so the canonical operator path should start with setup.",
11219
+ "Doctor is local-only by default and does not require live RPC reads."
11220
+ ]
11221
+ },
11222
+ recommendedCommands: recommendedCommands2
11223
+ };
11224
+ }
11225
+ if (!options.wallet) {
11226
+ const recommendedCommands2 = buildWalletBootstrapRecommendedCommands(
11227
+ options.walletName,
11228
+ options.relayUrl
11229
+ );
11230
+ const onboardingSummary2 = buildOnboardingSummary({
11231
+ stage: "wallet-bootstrap",
11232
+ localOnly: true,
11233
+ configExists: true,
11234
+ walletExists: false,
11235
+ defaultChain: options.config.defaultChain,
11236
+ connectorUrl: options.config.connectorUrl,
11237
+ relayUrl: options.relayUrl || null,
11238
+ nextAction: recommendedCommands2.createWallet,
11239
+ notes: [
11240
+ "Local config exists, but no saved wallet record was found for this name yet.",
11241
+ "Use the remote relay path only when the browser is not colocated with this terminal."
11242
+ ]
11243
+ });
11244
+ return {
11245
+ scope: "wallet-bootstrap",
11246
+ nextAction: recommendedCommands2.createWallet,
11247
+ onboardingSummary: onboardingSummary2,
11248
+ summary: {
11249
+ stage: "wallet-bootstrap",
11250
+ configExists: true,
11251
+ walletExists: false,
11252
+ approvalReady: null,
11253
+ localExecutionKeyStored: null,
11254
+ relayUrl: options.relayUrl || null,
11255
+ nextAction: recommendedCommands2.createWallet,
11256
+ localOnly: true,
11257
+ notes: [
11258
+ "Local config exists, but no saved wallet record was found for this name yet.",
11259
+ "Use the remote relay path only when the browser is not colocated with this terminal."
11260
+ ]
11261
+ },
11262
+ recommendedCommands: recommendedCommands2
11263
+ };
11264
+ }
11265
+ if (!options.wallet.approvalReady) {
11266
+ const recommendedCommands2 = buildWalletRecoveryRecommendedCommands(
11267
+ options.wallet,
11268
+ options.relayUrl
11269
+ );
11270
+ const onboardingSummary2 = buildOnboardingSummary({
11271
+ stage: "wallet-recovery",
11272
+ localOnly: true,
11273
+ configExists: true,
11274
+ walletExists: true,
11275
+ approvalReady: false,
11276
+ localExecutionKeyStored: options.wallet.localExecutionKeyStored,
11277
+ defaultChain: options.config.defaultChain,
11278
+ connectorUrl: options.config.connectorUrl,
11279
+ relayUrl: options.relayUrl || null,
11280
+ nextAction: recommendedCommands2.reapprove,
11281
+ notes: [
11282
+ "A local wallet record exists, but approved session metadata is missing.",
11283
+ "Use the remote reapproval path only when the browser cannot return directly to this terminal."
11284
+ ]
11285
+ });
11286
+ return {
11287
+ scope: "wallet-recovery",
11288
+ nextAction: recommendedCommands2.reapprove,
11289
+ onboardingSummary: onboardingSummary2,
11290
+ summary: {
11291
+ stage: "wallet-recovery",
11292
+ configExists: true,
11293
+ walletExists: true,
11294
+ approvalReady: false,
11295
+ localExecutionKeyStored: options.wallet.localExecutionKeyStored,
11296
+ relayUrl: options.relayUrl || null,
11297
+ nextAction: recommendedCommands2.reapprove,
11298
+ localOnly: true,
11299
+ notes: [
11300
+ "A local wallet record exists, but approved session metadata is missing.",
11301
+ "Use the remote reapproval path only when the browser cannot return directly to this terminal."
11302
+ ]
11303
+ },
11304
+ recommendedCommands: recommendedCommands2
11305
+ };
11306
+ }
11307
+ if (!options.wallet.localExecutionKeyStored) {
11308
+ const attachSigner = buildWalletSignerAttachRecommendedCommand(options.wallet.walletName);
11309
+ const recommendedCommands2 = {
11310
+ ...buildWalletRecoveryRecommendedCommands(options.wallet, options.relayUrl),
11311
+ attachSigner
11312
+ };
11313
+ const onboardingSummary2 = buildOnboardingSummary({
11314
+ stage: "wallet-recovery",
11315
+ localOnly: true,
11316
+ configExists: true,
11317
+ walletExists: true,
11318
+ approvalReady: true,
11319
+ localExecutionKeyStored: false,
11320
+ defaultChain: options.config.defaultChain,
11321
+ connectorUrl: options.config.connectorUrl,
11322
+ relayUrl: options.relayUrl || null,
11323
+ nextAction: attachSigner,
11324
+ notes: [
11325
+ "Approved session metadata exists, but no local execution signer is stored yet.",
11326
+ "Doctor is local-only: it confirms stored signer state, not live chain deployment or gas balance."
11327
+ ]
11328
+ });
11329
+ return {
11330
+ scope: "wallet-recovery",
11331
+ nextAction: attachSigner,
11332
+ onboardingSummary: onboardingSummary2,
11333
+ summary: {
11334
+ stage: "wallet-recovery",
11335
+ configExists: true,
11336
+ walletExists: true,
11337
+ approvalReady: true,
11338
+ localExecutionKeyStored: false,
11339
+ relayUrl: options.relayUrl || null,
11340
+ nextAction: attachSigner,
11341
+ localOnly: true,
11342
+ notes: [
11343
+ "Approved session metadata exists, but no local execution signer is stored yet.",
11344
+ "Doctor is local-only: it confirms stored signer state, not live chain deployment or gas balance."
11345
+ ]
11346
+ },
11347
+ recommendedCommands: recommendedCommands2
11348
+ };
11349
+ }
11350
+ const recommendedCommands = buildWalletReadyRecommendedCommands(options.wallet);
11351
+ const onboardingSummary = buildOnboardingSummary({
11352
+ stage: "wallet-ready",
11353
+ localOnly: true,
11354
+ configExists: true,
11355
+ walletExists: true,
11356
+ approvalReady: true,
11357
+ localExecutionKeyStored: true,
11358
+ defaultChain: options.config.defaultChain,
11359
+ connectorUrl: options.config.connectorUrl,
11360
+ relayUrl: options.relayUrl || null,
11361
+ nextAction: recommendedCommands.next,
11362
+ notes: [
11363
+ "Local config, approval metadata, and a local execution signer are all present.",
11364
+ "Run zk-agent next for the current shortest live path; doctor does not confirm RPC reachability, deployment state, or funding."
11365
+ ]
11366
+ });
11367
+ return {
11368
+ scope: "wallet-ready",
11369
+ nextAction: recommendedCommands.next,
11370
+ onboardingSummary,
11371
+ summary: {
11372
+ stage: "wallet-ready",
11373
+ configExists: true,
11374
+ walletExists: true,
11375
+ approvalReady: true,
11376
+ localExecutionKeyStored: true,
11377
+ relayUrl: options.relayUrl || null,
11378
+ nextAction: recommendedCommands.next,
11379
+ localOnly: true,
11380
+ notes: [
11381
+ "Local config, approval metadata, and a local execution signer are all present.",
11382
+ "Run zk-agent next for the current shortest live path; doctor does not confirm RPC reachability, deployment state, or funding."
11383
+ ]
11384
+ },
11385
+ recommendedCommands
11386
+ };
11387
+ }
11388
+ function buildDoctorLines(input) {
11389
+ const lines = [
11390
+ ["scope", input.scope],
11391
+ ...onboardingSummaryLines(input.onboardingSummary),
11392
+ ["config", input.config ? "present" : "missing"]
11393
+ ];
11394
+ if (input.config) {
11395
+ lines.push(["default chain", input.config.defaultChain]);
11396
+ lines.push(["connector", input.config.connectorUrl]);
11397
+ }
11398
+ lines.push(["wallet", input.walletName]);
11399
+ lines.push(["wallet record", input.wallet ? "present" : "missing"]);
11400
+ if (input.wallet) {
11401
+ lines.push(["address", input.wallet.walletAddress]);
11402
+ lines.push(["account", input.wallet.accountKind]);
11403
+ lines.push(["chain", `${input.wallet.chain} (${input.wallet.chainId})`]);
11404
+ lines.push(["approval", input.wallet.approvalReady ? "present" : "missing"]);
11405
+ lines.push(["local signer", input.wallet.localExecutionKeyStored ? "stored" : "missing"]);
11406
+ lines.push([
11407
+ "legacy payload mirror",
11408
+ input.wallet.legacySessionKeyStored ? "present" : "missing"
11409
+ ]);
11410
+ if (input.wallet.signerType) {
11411
+ lines.push(["signer type", input.wallet.signerType]);
11412
+ }
11413
+ if (input.wallet.signerAddress) {
11414
+ lines.push(["signer address", input.wallet.signerAddress]);
11415
+ }
11416
+ if (input.wallet.signerSource) {
11417
+ lines.push(["signer source", input.wallet.signerSource]);
11418
+ }
11419
+ if (input.wallet.smartAccountProfileId) {
11420
+ lines.push(["smart-account profile", input.wallet.smartAccountProfileId]);
11421
+ }
11422
+ if (input.wallet.syncedAt) {
11423
+ lines.push(["synced at", input.wallet.syncedAt]);
11424
+ }
11425
+ }
11426
+ lines.push(["next", input.nextAction]);
11427
+ if (input.recommendedCommands.createWallet) {
11428
+ lines.push(["create wallet (local)", input.recommendedCommands.createWallet]);
11429
+ }
11430
+ if (input.recommendedCommands.reapprove) {
11431
+ lines.push(["reapprove", input.recommendedCommands.reapprove]);
11432
+ }
11433
+ if (input.recommendedCommands.attachSigner) {
11434
+ lines.push(["attach signer", input.recommendedCommands.attachSigner]);
11435
+ }
11436
+ if (input.recommendedCommands.workflowPay) {
11437
+ lines.push(["workflow pay", input.recommendedCommands.workflowPay]);
11438
+ }
11439
+ if (input.recommendedCommands.relayInspect) {
11440
+ lines.push(["relay inspect", input.recommendedCommands.relayInspect]);
11441
+ }
11442
+ if (input.recommendedCommands.createWalletRemote) {
11443
+ lines.push(["create wallet (remote)", input.recommendedCommands.createWalletRemote]);
11444
+ }
11445
+ if (input.recommendedCommands.reapproveRemote) {
11446
+ lines.push(["reapprove (remote)", input.recommendedCommands.reapproveRemote]);
11447
+ }
11448
+ for (const note of input.summary.notes) {
11449
+ lines.push(["note", note]);
11450
+ }
11451
+ return lines;
11452
+ }
11453
+ function createDoctorCommand() {
11454
+ return new Command4("doctor").description("Local-only onboarding and wallet-recovery diagnostic for the default operator path").addHelpText("after", buildDoctorHelpText()).option("--wallet <name>", "Wallet name", "main").option(
11455
+ "--relay-url <url>",
11456
+ "Optional relay URL used only to make remote approval fallback commands concrete"
11457
+ ).action(async (options) => {
11458
+ const walletName = options.wallet?.trim() || "main";
11459
+ const config = await loadProjectConfig();
11460
+ const walletRecord = await loadWalletSession(walletName);
11461
+ const wallet = walletRecord ? summarizeLocalWalletState(walletRecord) : null;
11462
+ const result = buildDoctorResult({
11463
+ walletName,
11464
+ relayUrl: options.relayUrl,
11465
+ wallet,
11466
+ config
11467
+ });
11468
+ const agentProfile = await loadAgentIdentitySummary(walletName);
11469
+ const agentFollowup = buildAgentFollowup(agentProfile, {
11470
+ walletName,
11471
+ walletExists: Boolean(wallet)
11472
+ });
11473
+ printResult(
11474
+ [
11475
+ ...buildDoctorLines({
11476
+ scope: result.scope,
11477
+ walletName,
11478
+ config,
11479
+ wallet,
11480
+ onboardingSummary: result.onboardingSummary,
11481
+ summary: result.summary,
11482
+ recommendedCommands: result.recommendedCommands,
11483
+ nextAction: result.nextAction
11484
+ }),
11485
+ ...agentProfileLines(agentProfile),
11486
+ ...agentFollowupLines(agentFollowup)
11487
+ ],
11488
+ {
11489
+ ok: true,
11490
+ scope: result.scope,
11491
+ walletName,
11492
+ config: config ? {
11493
+ exists: true,
11494
+ defaultChain: config.defaultChain,
11495
+ connectorUrl: config.connectorUrl,
11496
+ provider: config.provider
11497
+ } : {
11498
+ exists: false
11499
+ },
11500
+ wallet,
11501
+ onboardingSummary: result.onboardingSummary,
11502
+ summary: result.summary,
11503
+ agentProfile,
11504
+ agentFollowup,
11505
+ nextAction: result.nextAction,
11506
+ recommendedCommands: result.recommendedCommands
11507
+ }
11508
+ );
11509
+ });
11510
+ }
11511
+
11512
+ // src/commands/agent.ts
11513
+ import { Command as Command5 } from "commander";
10761
11514
  function collectRepeatedString(value, previous) {
10762
11515
  return [...previous, value];
10763
11516
  }
@@ -10842,7 +11595,7 @@ function buildAgentSummaryLines(options) {
10842
11595
  return lines;
10843
11596
  }
10844
11597
  function createAgentCommand() {
10845
- const agent = new Command4("agent").description(
11598
+ const agent = new Command5("agent").description(
10846
11599
  "Manage local agent identity metadata without assuming a zkSync-native onchain reputation standard"
10847
11600
  );
10848
11601
  agent.addHelpText(
@@ -11035,7 +11788,81 @@ function createAgentCommand() {
11035
11788
  }
11036
11789
 
11037
11790
  // src/commands/defaults.ts
11038
- import { Command as Command5 } from "commander";
11791
+ import { Command as Command6 } from "commander";
11792
+ function inferPrimaryDiscoveryChain(defaults) {
11793
+ return defaults.defaultSelections.paymaster.validatedDefault?.chain || defaults.defaultSelections.swap.validatedDefault?.chain || defaults.defaultSelections.bridge.validatedWithdraw?.fromChain || defaults.defaultSelections.bridge.validatedDeposit?.toChain || defaults.validated.feeTokenEraVm?.chain || defaults.builtinChains.find((chain) => chain.key === "zksync-sepolia")?.key || defaults.builtinChains[0]?.key || "zksync-sepolia";
11794
+ }
11795
+ function inferExampleTokenSymbol(defaults) {
11796
+ return defaults.defaultSelections.swap.validatedDefault?.trackedTokenA.symbol || defaults.defaultSelections.paymaster.validatedApprovalBased?.feeTokenSymbol || defaults.validated.feeTokenEraVm?.symbol || defaults.registry.tokens.find((entry) => entry.symbol?.trim())?.symbol || "USDC";
11797
+ }
11798
+ function inferPaymasterFeeTokenSymbol(defaults) {
11799
+ return defaults.defaultSelections.paymaster.validatedApprovalBased?.feeTokenSymbol || defaults.validated.feeTokenEraVm?.symbol || null;
11800
+ }
11801
+ function buildDefaultsRecommendedCommands(defaults) {
11802
+ const primaryChain = inferPrimaryDiscoveryChain(defaults);
11803
+ const exampleSymbol = inferExampleTokenSymbol(defaults);
11804
+ const paymasterFeeTokenSymbol = inferPaymasterFeeTokenSymbol(defaults) || exampleSymbol;
11805
+ return {
11806
+ inspectDefaults: buildDefaultsRecommendedCommand(),
11807
+ discoverTokens: buildTokensRecommendedCommand(primaryChain),
11808
+ inspectToken: buildResolveTokenRecommendedCommand(primaryChain, exampleSymbol),
11809
+ discoverPaymasterTokens: buildPaymasterFeeTokensRecommendedCommand(primaryChain),
11810
+ inspectPaymasterToken: buildPaymasterFeeTokenResolveRecommendedCommand(
11811
+ primaryChain,
11812
+ paymasterFeeTokenSymbol
11813
+ )
11814
+ };
11815
+ }
11816
+ function buildDefaultsSummary(input) {
11817
+ const { defaults, localTokenRegistry, tokenRegistrySources, tokenDirectoryChains } = input;
11818
+ const primaryChain = inferPrimaryDiscoveryChain(defaults);
11819
+ const exampleTokenSymbol = inferExampleTokenSymbol(defaults);
11820
+ const paymasterFeeTokenSymbol = inferPaymasterFeeTokenSymbol(defaults);
11821
+ return {
11822
+ primaryDiscoveryChain: primaryChain,
11823
+ exampleTokenSymbol,
11824
+ paymasterFeeTokenSymbol,
11825
+ localTokenCount: localTokenRegistry.length,
11826
+ tokenDirectoryChainCount: tokenDirectoryChains.length,
11827
+ tokenRegistrySources: tokenRegistrySources.map((source) => ({
11828
+ id: source.id,
11829
+ enabled: source.enabled,
11830
+ exists: source.exists
11831
+ })),
11832
+ resolvedDefaults: {
11833
+ swap: defaults.defaultSelections.swap.validatedDefault ? {
11834
+ entryId: defaults.defaultSelections.swap.validatedDefault.entryId,
11835
+ chain: defaults.defaultSelections.swap.validatedDefault.chain,
11836
+ protocol: defaults.defaultSelections.swap.validatedDefault.protocol,
11837
+ status: defaults.defaultSelections.swap.validatedDefault.status
11838
+ } : null,
11839
+ bridgeDeposit: defaults.defaultSelections.bridge.validatedDeposit ? {
11840
+ entryId: defaults.defaultSelections.bridge.validatedDeposit.entryId,
11841
+ fromChain: defaults.defaultSelections.bridge.validatedDeposit.fromChain,
11842
+ toChain: defaults.defaultSelections.bridge.validatedDeposit.toChain,
11843
+ status: defaults.defaultSelections.bridge.validatedDeposit.status
11844
+ } : null,
11845
+ bridgeWithdraw: defaults.defaultSelections.bridge.validatedWithdraw ? {
11846
+ entryId: defaults.defaultSelections.bridge.validatedWithdraw.entryId,
11847
+ fromChain: defaults.defaultSelections.bridge.validatedWithdraw.fromChain,
11848
+ toChain: defaults.defaultSelections.bridge.validatedWithdraw.toChain,
11849
+ status: defaults.defaultSelections.bridge.validatedWithdraw.status,
11850
+ requiresFinalize: defaults.defaultSelections.bridge.validatedWithdraw.requiresFinalize
11851
+ } : null,
11852
+ paymasterDefault: defaults.defaultSelections.paymaster.validatedDefault ? {
11853
+ entryId: defaults.defaultSelections.paymaster.validatedDefault.entryId,
11854
+ chain: defaults.defaultSelections.paymaster.validatedDefault.chain,
11855
+ mode: defaults.defaultSelections.paymaster.validatedDefault.mode,
11856
+ status: defaults.defaultSelections.paymaster.validatedDefault.status
11857
+ } : null,
11858
+ paymasterByMode: {
11859
+ none: defaults.defaultSelections.paymaster.validatedNone?.entryId || null,
11860
+ sponsored: defaults.defaultSelections.paymaster.validatedSponsored?.entryId || null,
11861
+ approvalBased: defaults.defaultSelections.paymaster.validatedApprovalBased?.entryId || null
11862
+ }
11863
+ }
11864
+ };
11865
+ }
11039
11866
  function formatTrackedTokenSummary(token) {
11040
11867
  if (!token.address) return null;
11041
11868
  const label = token.symbol || token.address;
@@ -11509,7 +12336,7 @@ function buildDefaultsLines(input) {
11509
12336
  return lines;
11510
12337
  }
11511
12338
  function createDefaultsCommand() {
11512
- return new Command5("defaults").description("Show the machine-readable registry of supported, validated, experimental, and manually configured defaults").addHelpText(
12339
+ return new Command6("defaults").description("Show the machine-readable registry of supported, validated, experimental, and manually configured defaults").addHelpText(
11513
12340
  "after",
11514
12341
  [
11515
12342
  "",
@@ -11531,14 +12358,34 @@ function createDefaultsCommand() {
11531
12358
  const localTokenRegistry = listLocalTokenRegistryEntries();
11532
12359
  const tokenRegistrySources = describeDefaultTokenRegistrySources();
11533
12360
  const tokenDirectoryChains = await listTokenDirectoryIndexedChains();
12361
+ const recommendedCommands = buildDefaultsRecommendedCommands(defaults);
12362
+ const summary = buildDefaultsSummary({
12363
+ defaults,
12364
+ localTokenRegistry,
12365
+ tokenRegistrySources,
12366
+ tokenDirectoryChains
12367
+ });
11534
12368
  const lines = buildDefaultsLines({
11535
12369
  defaults,
11536
12370
  localTokenRegistry,
11537
12371
  tokenRegistrySources,
11538
12372
  tokenDirectoryChains
11539
12373
  });
12374
+ lines.push([
12375
+ "next discovery chain",
12376
+ summary.primaryDiscoveryChain
12377
+ ]);
12378
+ lines.push([
12379
+ "example token",
12380
+ summary.exampleTokenSymbol
12381
+ ]);
12382
+ if (summary.paymasterFeeTokenSymbol) {
12383
+ lines.push(["paymaster fee token symbol", summary.paymasterFeeTokenSymbol]);
12384
+ }
11540
12385
  printResult(lines, {
11541
12386
  ok: true,
12387
+ summary,
12388
+ recommendedCommands,
11542
12389
  defaults,
11543
12390
  localTokenRegistry,
11544
12391
  tokenRegistrySources,
@@ -11548,7 +12395,7 @@ function createDefaultsCommand() {
11548
12395
  }
11549
12396
 
11550
12397
  // src/commands/resolve-token.ts
11551
- import { Command as Command6 } from "commander";
12398
+ import { Command as Command7 } from "commander";
11552
12399
  function resolveResolveTokenCommandDeps(deps) {
11553
12400
  return {
11554
12401
  loadWallet: deps?.loadWallet ?? (async (walletName) => {
@@ -11584,9 +12431,29 @@ async function resolveActiveChain(options, deps) {
11584
12431
  }
11585
12432
  );
11586
12433
  }
12434
+ function buildResolveTokenDiscoverySummary(result) {
12435
+ return {
12436
+ chain: result.chainKey,
12437
+ chainId: result.chainId,
12438
+ queryType: result.queryType,
12439
+ query: result.queryType === "symbol" ? result.symbol || null : result.address || null,
12440
+ roleFilter: result.role || null,
12441
+ sourceFilter: result.source || null,
12442
+ matchCount: result.matchCount,
12443
+ ambiguous: result.ambiguous,
12444
+ primarySymbol: result.primaryMatch?.symbol || null,
12445
+ primaryAddress: result.primaryMatch?.address || null,
12446
+ primaryDecimals: result.primaryMatch?.decimals ?? null,
12447
+ primarySource: result.primaryMatch?.source || (result.primaryMatch ? "unknown" : null),
12448
+ sourceCounts: summarizeDiscoveryEntrySources(result.matches),
12449
+ roleMatchCounts: summarizeDiscoveryRoleMatches(result.matches),
12450
+ currentDefaultEntryCount: countCurrentValidatedDefaultEntries(result.matches),
12451
+ tokenRegistrySources: summarizeTokenRegistrySources(result.tokenRegistrySources)
12452
+ };
12453
+ }
11587
12454
  function createResolveTokenCommand(deps) {
11588
12455
  const resolvedDeps = resolveResolveTokenCommandDeps(deps);
11589
- return new Command6("resolve-token").description("Resolve a token symbol or address against the configured local-first token registry").addHelpText(
12456
+ return new Command7("resolve-token").description("Resolve a token symbol or address against the configured local-first token registry").addHelpText(
11590
12457
  "after",
11591
12458
  [
11592
12459
  "",
@@ -11688,6 +12555,7 @@ function createResolveTokenCommand(deps) {
11688
12555
  lines.push(...workflowFollowupLines(recommendedCommands));
11689
12556
  printResult(lines, {
11690
12557
  ok: true,
12558
+ discoverySummary: buildResolveTokenDiscoverySummary(result),
11691
12559
  recommendedCommands,
11692
12560
  ...result
11693
12561
  });
@@ -11719,7 +12587,7 @@ function normalizeSource(value) {
11719
12587
  }
11720
12588
 
11721
12589
  // src/commands/tokens.ts
11722
- import { Command as Command7 } from "commander";
12590
+ import { Command as Command8 } from "commander";
11723
12591
  var provider2 = new ZkSyncWalletProvider();
11724
12592
  function resolveTokensCommandDeps(deps) {
11725
12593
  return {
@@ -11807,9 +12675,49 @@ function ownedTokenSummaryLines2(summary) {
11807
12675
  }
11808
12676
  return lines;
11809
12677
  }
12678
+ function buildOwnedTokensDiscoverySummary(result) {
12679
+ return {
12680
+ mode: "owned-registry-erc20",
12681
+ walletName: result.walletName,
12682
+ chainScope: result.chainFilter.chainKey,
12683
+ chainCount: 1,
12684
+ entryCount: result.entryCount,
12685
+ symbolFilter: result.symbol || null,
12686
+ roleFilter: result.role || null,
12687
+ sourceFilter: result.source || null,
12688
+ primarySymbol: firstDiscoverySymbol(result.entries),
12689
+ primarySource: firstDiscoverySource(result.entries),
12690
+ sourceCounts: result.summary.sourceCounts,
12691
+ roleMatchCounts: result.summary.registryRoleCounts,
12692
+ currentDefaultEntryCount: countCurrentValidatedDefaultEntries(result.entries),
12693
+ probeFailureCount: result.probeFailureCount,
12694
+ bridgeMappingCounts: result.summary.bridgeMappingCounts,
12695
+ tokenRegistrySources: summarizeTokenRegistrySources(result.tokenRegistrySources)
12696
+ };
12697
+ }
12698
+ function buildTokenDiscoverySummary(result) {
12699
+ return {
12700
+ mode: "discoverable",
12701
+ walletName: null,
12702
+ chainScope: result.chainFilter?.chainKey || "all-built-in-chains",
12703
+ chainCount: result.chainFilter ? 1 : listUniqueDiscoveryChains(result.entries).length,
12704
+ entryCount: result.entryCount,
12705
+ symbolFilter: result.symbol || null,
12706
+ roleFilter: result.role || null,
12707
+ sourceFilter: result.source || null,
12708
+ primarySymbol: firstDiscoverySymbol(result.entries),
12709
+ primarySource: firstDiscoverySource(result.entries),
12710
+ sourceCounts: summarizeDiscoveryEntrySources(result.entries),
12711
+ roleMatchCounts: summarizeDiscoveryRoleMatches(result.entries),
12712
+ currentDefaultEntryCount: countCurrentValidatedDefaultEntries(result.entries),
12713
+ probeFailureCount: null,
12714
+ bridgeMappingCounts: null,
12715
+ tokenRegistrySources: summarizeTokenRegistrySources(result.tokenRegistrySources)
12716
+ };
12717
+ }
11810
12718
  function createTokensCommand(deps) {
11811
12719
  const resolvedDeps = resolveTokensCommandDeps(deps);
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(
12720
+ return new Command8("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
12721
  "after",
11814
12722
  [
11815
12723
  "",
@@ -11940,6 +12848,7 @@ function createTokensCommand(deps) {
11940
12848
  lines2.push(...workflowFollowupLines(recommendedCommands2));
11941
12849
  printResult(lines2, {
11942
12850
  ok: true,
12851
+ discoverySummary: buildOwnedTokensDiscoverySummary(result2),
11943
12852
  recommendedCommands: recommendedCommands2,
11944
12853
  ...result2
11945
12854
  });
@@ -11995,6 +12904,7 @@ function createTokensCommand(deps) {
11995
12904
  lines.push(...workflowFollowupLines(recommendedCommands));
11996
12905
  printResult(lines, {
11997
12906
  ok: true,
12907
+ discoverySummary: buildTokenDiscoverySummary(result),
11998
12908
  recommendedCommands,
11999
12909
  ...result
12000
12910
  });
@@ -12012,7 +12922,7 @@ function normalizeRole2(value) {
12012
12922
  }
12013
12923
 
12014
12924
  // src/commands/relay.ts
12015
- import { Command as Command8 } from "commander";
12925
+ import { Command as Command9 } from "commander";
12016
12926
 
12017
12927
  // src/lib/relay.ts
12018
12928
  import { createServer } from "node:http";
@@ -12520,10 +13430,52 @@ async function startRelayServer(options) {
12520
13430
  }
12521
13431
 
12522
13432
  // src/commands/relay.ts
12523
- function buildRelayServeRecommendedCommands(relayUrl) {
13433
+ function buildRelayServeRecommendedCommands(options) {
13434
+ const commands = {
13435
+ inspectRelay: `zk-agent relay inspect --relay-url ${options.relayUrl}`,
13436
+ createWallet: `zk-agent wallet create --relay-url ${options.relayUrl} --wait-relay --prompt-code`,
13437
+ reapproveWallet: `zk-agent wallet reapprove --name main --relay-url ${options.relayUrl} --wait-relay --prompt-code`
13438
+ };
13439
+ if (options.publicOriginLooksLocal) {
13440
+ return {
13441
+ ...commands,
13442
+ restartWithPublicOrigin: "zk-agent relay serve --public-origin https://relay.example.com"
13443
+ };
13444
+ }
13445
+ return commands;
13446
+ }
13447
+ function buildRelayInspectRecommendedCommands(options) {
13448
+ const commands = {};
13449
+ if (options.compatible) {
13450
+ commands.createWallet = `zk-agent wallet create --relay-url ${options.publicOrigin} --wait-relay --prompt-code`;
13451
+ commands.reapproveWallet = `zk-agent wallet reapprove --name main --relay-url ${options.publicOrigin} --wait-relay --prompt-code`;
13452
+ }
13453
+ if (options.publicOriginLooksLocal) {
13454
+ commands.restartWithPublicOrigin = "zk-agent relay serve --public-origin https://relay.example.com";
13455
+ }
13456
+ return commands;
13457
+ }
13458
+ function buildRelayHostedReadinessSummary(options) {
13459
+ let status;
13460
+ if (!options.compatible) {
13461
+ status = "incompatible";
13462
+ } else if (options.publicOriginLooksLocal && options.connectorUiAvailable !== true) {
13463
+ status = "needs-public-origin-and-ui";
13464
+ } else if (options.publicOriginLooksLocal) {
13465
+ status = "needs-public-origin";
13466
+ } else if (options.connectorUiAvailable !== true) {
13467
+ status = "needs-connector-ui";
13468
+ } else {
13469
+ status = "ready";
13470
+ }
12524
13471
  return {
12525
- createWallet: `zk-agent wallet create --relay-url ${relayUrl} --wait-relay --prompt-code`,
12526
- reapproveWallet: `zk-agent wallet reapprove --name main --relay-url ${relayUrl} --wait-relay --prompt-code`
13472
+ status,
13473
+ compatible: options.compatible,
13474
+ hostedApprovalReady: options.hostedShareRedirectReady,
13475
+ publicOriginConfigured: options.publicOriginSource === "configured",
13476
+ publicOriginLooksLocal: options.publicOriginLooksLocal,
13477
+ connectorUiAvailable: options.connectorUiAvailable,
13478
+ singleHostFileState: options.deploymentSummary.singleHostFileState
12527
13479
  };
12528
13480
  }
12529
13481
  function buildAdvertisedRelayBases(publicOrigin) {
@@ -12532,6 +13484,24 @@ function buildAdvertisedRelayBases(publicOrigin) {
12532
13484
  statusApiBaseUrl: `${publicOrigin}/api/requests`
12533
13485
  };
12534
13486
  }
13487
+ function buildRelayApprovalEndpointSummary(options) {
13488
+ let status;
13489
+ if (options.publicOriginLooksLocal) {
13490
+ status = "local-public-origin";
13491
+ } else if (options.relayUrlMatchesPublicOrigin === false) {
13492
+ status = "hosted-public-origin-via-proxy";
13493
+ } else {
13494
+ status = "hosted-public-origin";
13495
+ }
13496
+ return {
13497
+ status,
13498
+ publicOriginConfigured: options.publicOriginSource === "configured",
13499
+ publicOriginLooksLocal: options.publicOriginLooksLocal,
13500
+ relayUrlMatchesPublicOrigin: options.relayUrlMatchesPublicOrigin,
13501
+ shareLinkBaseUrl: options.shareLinkBaseUrl,
13502
+ statusApiBaseUrl: options.statusApiBaseUrl
13503
+ };
13504
+ }
12535
13505
  function isRecord3(value) {
12536
13506
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
12537
13507
  }
@@ -12672,6 +13642,20 @@ function relayOriginRelationshipNotes(options) {
12672
13642
  }
12673
13643
  return notes;
12674
13644
  }
13645
+ function buildRelayDeploymentSummary(options) {
13646
+ return {
13647
+ origin: options.origin,
13648
+ publicOrigin: options.publicOrigin,
13649
+ publicOriginSource: options.publicOriginSource,
13650
+ shareLinkBaseUrl: options.shareLinkBaseUrl,
13651
+ statusApiBaseUrl: options.statusApiBaseUrl,
13652
+ publicOriginConfigured: options.publicOriginSource === "configured",
13653
+ publicOriginLooksLocal: options.publicOriginLooksLocal,
13654
+ connectorUiAvailable: options.connectorUiAvailable,
13655
+ hostedShareRedirectReady: options.hostedShareRedirectReady,
13656
+ singleHostFileState: options.stateBackend === "local-filesystem" && options.deploymentScope === "single-host" && options.sameHostRestartPersists === true
13657
+ };
13658
+ }
12675
13659
  function buildRelayInspectPayload(relayUrl, rawHealth) {
12676
13660
  const health = asRelayHealthResponse(rawHealth);
12677
13661
  const fallbackPublicOrigin = isRecord3(rawHealth) && typeof rawHealth.public_origin === "string" ? rawHealth.public_origin : relayUrl;
@@ -12690,6 +13674,34 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12690
13674
  const publicOriginLooksLocal = relayPublicOriginLooksLocal(publicOrigin);
12691
13675
  const hostedShareRedirectReady = compatible && connectorUiAvailable === true && !publicOriginLooksLocal;
12692
13676
  const { shareLinkBaseUrl, statusApiBaseUrl } = buildAdvertisedRelayBases(publicOrigin);
13677
+ const deploymentSummary = buildRelayDeploymentSummary({
13678
+ origin: health?.origin || null,
13679
+ publicOrigin,
13680
+ publicOriginSource,
13681
+ shareLinkBaseUrl,
13682
+ statusApiBaseUrl,
13683
+ publicOriginLooksLocal,
13684
+ connectorUiAvailable,
13685
+ hostedShareRedirectReady,
13686
+ stateBackend,
13687
+ deploymentScope,
13688
+ sameHostRestartPersists
13689
+ });
13690
+ const approvalEndpointSummary = buildRelayApprovalEndpointSummary({
13691
+ publicOriginSource,
13692
+ publicOriginLooksLocal,
13693
+ relayUrlMatchesPublicOrigin,
13694
+ shareLinkBaseUrl,
13695
+ statusApiBaseUrl
13696
+ });
13697
+ const hostedReadinessSummary = buildRelayHostedReadinessSummary({
13698
+ compatible,
13699
+ publicOriginSource,
13700
+ publicOriginLooksLocal,
13701
+ connectorUiAvailable,
13702
+ hostedShareRedirectReady,
13703
+ deploymentSummary
13704
+ });
12693
13705
  const notes = [
12694
13706
  ...relayHostedReadinessNotes({
12695
13707
  compatible,
@@ -12729,15 +13741,22 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
12729
13741
  relayUrlMatchesOrigin,
12730
13742
  relayUrlMatchesPublicOrigin,
12731
13743
  publicOriginLooksLocal,
13744
+ approvalEndpointSummary,
12732
13745
  connectorUiAvailable,
12733
13746
  hostedShareRedirectReady,
13747
+ hostedReadinessSummary,
13748
+ deploymentSummary,
12734
13749
  capabilities: health?.capabilities || [],
12735
- recommendedCommands: compatible ? buildRelayServeRecommendedCommands(publicOrigin) : {},
13750
+ recommendedCommands: buildRelayInspectRecommendedCommands({
13751
+ publicOrigin,
13752
+ compatible,
13753
+ publicOriginLooksLocal
13754
+ }),
12736
13755
  notes
12737
13756
  };
12738
13757
  }
12739
13758
  function createRelayCommand() {
12740
- const relay = new Command8("relay").description("Run the local connector relay prototype server");
13759
+ const relay = new Command9("relay").description("Run the local connector relay prototype server");
12741
13760
  relay.addHelpText(
12742
13761
  "after",
12743
13762
  [
@@ -12769,13 +13788,44 @@ function createRelayCommand() {
12769
13788
  port: parsedPort,
12770
13789
  publicOrigin: options.publicOrigin?.trim()
12771
13790
  });
12772
- const publicOrigin = options.publicOrigin?.trim() || server.origin;
12773
- const publicOriginSource = options.publicOrigin?.trim() ? "configured" : "bind-origin-default";
12774
- const publicOriginLooksLocal = relayPublicOriginLooksLocal(publicOrigin);
12775
- const connectorUiAvailable = server.connectorUiAvailable;
12776
- const hostedShareRedirectReady = connectorUiAvailable && !publicOriginLooksLocal;
12777
- const { shareLinkBaseUrl, statusApiBaseUrl } = buildAdvertisedRelayBases(publicOrigin);
12778
- const recommendedCommands = buildRelayServeRecommendedCommands(publicOrigin);
13791
+ const publicOrigin = options.publicOrigin?.trim() || server.origin;
13792
+ const publicOriginSource = options.publicOrigin?.trim() ? "configured" : "bind-origin-default";
13793
+ const publicOriginLooksLocal = relayPublicOriginLooksLocal(publicOrigin);
13794
+ const connectorUiAvailable = server.connectorUiAvailable;
13795
+ const hostedShareRedirectReady = connectorUiAvailable && !publicOriginLooksLocal;
13796
+ const { shareLinkBaseUrl, statusApiBaseUrl } = buildAdvertisedRelayBases(publicOrigin);
13797
+ const recommendedCommands = buildRelayServeRecommendedCommands({
13798
+ relayUrl: publicOrigin,
13799
+ publicOriginLooksLocal
13800
+ });
13801
+ const deploymentSummary = buildRelayDeploymentSummary({
13802
+ origin: server.origin,
13803
+ publicOrigin,
13804
+ publicOriginSource,
13805
+ shareLinkBaseUrl,
13806
+ statusApiBaseUrl,
13807
+ publicOriginLooksLocal,
13808
+ connectorUiAvailable,
13809
+ hostedShareRedirectReady,
13810
+ stateBackend: "local-filesystem",
13811
+ deploymentScope: "single-host",
13812
+ sameHostRestartPersists: true
13813
+ });
13814
+ const hostedReadinessSummary = buildRelayHostedReadinessSummary({
13815
+ compatible: true,
13816
+ publicOriginSource,
13817
+ publicOriginLooksLocal,
13818
+ connectorUiAvailable,
13819
+ hostedShareRedirectReady,
13820
+ deploymentSummary
13821
+ });
13822
+ const approvalEndpointSummary = buildRelayApprovalEndpointSummary({
13823
+ publicOriginSource,
13824
+ publicOriginLooksLocal,
13825
+ relayUrlMatchesPublicOrigin: null,
13826
+ shareLinkBaseUrl,
13827
+ statusApiBaseUrl
13828
+ });
12779
13829
  const notes = relayHostedReadinessNotes({
12780
13830
  compatible: true,
12781
13831
  publicOrigin,
@@ -12794,6 +13844,9 @@ function createRelayCommand() {
12794
13844
  shareLinkBaseUrl,
12795
13845
  statusApiBaseUrl,
12796
13846
  publicOriginLooksLocal,
13847
+ approvalEndpointSummary,
13848
+ hostedReadinessSummary,
13849
+ deploymentSummary,
12797
13850
  port: server.port,
12798
13851
  healthUrl: `${server.origin}/health`,
12799
13852
  publicHealthUrl: `${publicOrigin}/health`,
@@ -12828,13 +13881,19 @@ function createRelayCommand() {
12828
13881
  );
12829
13882
  humanLine("share-link base", shareLinkBaseUrl);
12830
13883
  humanLine("status api base", statusApiBaseUrl);
13884
+ humanLine("approval endpoint", approvalEndpointSummary.status);
12831
13885
  humanLine("health", `${server.origin}/health`);
13886
+ humanLine("hosted readiness", hostedReadinessSummary.status);
12832
13887
  humanLine("hosted ready", hostedShareRedirectReady ? "yes" : "no");
12833
13888
  if (connectorUiAvailable !== null) {
12834
13889
  humanLine("connector ui", connectorUiAvailable ? "available" : "missing");
12835
13890
  }
13891
+ humanLine("inspect relay", recommendedCommands.inspectRelay);
12836
13892
  humanLine("create wallet", recommendedCommands.createWallet);
12837
13893
  humanLine("reapprove wallet", recommendedCommands.reapproveWallet);
13894
+ if (recommendedCommands.restartWithPublicOrigin) {
13895
+ humanLine("restart with public origin", recommendedCommands.restartWithPublicOrigin);
13896
+ }
12838
13897
  for (const note of notes) {
12839
13898
  humanLine("note", note);
12840
13899
  }
@@ -12896,6 +13955,8 @@ function createRelayCommand() {
12896
13955
  }
12897
13956
  humanLine("share-link base", payload.shareLinkBaseUrl);
12898
13957
  humanLine("status api base", payload.statusApiBaseUrl);
13958
+ humanLine("approval endpoint", payload.approvalEndpointSummary.status);
13959
+ humanLine("hosted readiness", payload.hostedReadinessSummary.status);
12899
13960
  if (payload.relayUrlMatchesOrigin !== null) {
12900
13961
  humanLine("relay url matches origin", payload.relayUrlMatchesOrigin ? "yes" : "no");
12901
13962
  }
@@ -12921,6 +13982,12 @@ function createRelayCommand() {
12921
13982
  humanLine("reapprove wallet", payload.recommendedCommands.reapproveWallet);
12922
13983
  }
12923
13984
  }
13985
+ if (payload.recommendedCommands.restartWithPublicOrigin) {
13986
+ humanLine(
13987
+ "restart with public origin",
13988
+ payload.recommendedCommands.restartWithPublicOrigin
13989
+ );
13990
+ }
12924
13991
  for (const note of payload.notes) {
12925
13992
  humanLine("note", note);
12926
13993
  }
@@ -12931,7 +13998,7 @@ function createRelayCommand() {
12931
13998
  // src/commands/wallet.ts
12932
13999
  import { createServer as createServer2 } from "node:http";
12933
14000
  import { createInterface } from "node:readline/promises";
12934
- import { Command as Command9 } from "commander";
14001
+ import { Command as Command10 } from "commander";
12935
14002
 
12936
14003
  // ../account-profiles/src/profiles.ts
12937
14004
  import fs8 from "node:fs";
@@ -13536,6 +14603,39 @@ function relayOutputAliases(relay) {
13536
14603
  relayStatusApiBaseUrl: statusApiBaseUrl
13537
14604
  };
13538
14605
  }
14606
+ function determineRelayRecoveryMode(options) {
14607
+ if (options.recommendedCommands.reissueRemoteApproval && options.nextAction === options.recommendedCommands.reissueRemoteApproval) {
14608
+ return "reissue-remote-approval";
14609
+ }
14610
+ if (options.recommendedCommands.relayInspect && options.nextAction === options.recommendedCommands.relayInspect) {
14611
+ return "inspect-relay";
14612
+ }
14613
+ if (options.recommendedCommands.approve && options.nextAction === options.recommendedCommands.approve) {
14614
+ return "approve";
14615
+ }
14616
+ return "status-poll";
14617
+ }
14618
+ function buildRelayRecoverySummary(options) {
14619
+ const aliases = relayOutputAliases(options.relay);
14620
+ return {
14621
+ requestId: options.requestId,
14622
+ walletName: options.walletName || null,
14623
+ relayUrl: options.relayUrl,
14624
+ relayStatus: options.relayStatus ?? options.relay?.status ?? null,
14625
+ approvalReady: typeof options.approvalReady === "boolean" ? options.approvalReady : options.relay && "approval_ready" in options.relay ? options.relay.approval_ready : null,
14626
+ nextAction: options.nextAction,
14627
+ shareLinkBaseUrl: aliases.relayShareLinkBaseUrl || null,
14628
+ statusApiBaseUrl: aliases.relayStatusApiBaseUrl || null,
14629
+ recoveryMode: determineRelayRecoveryMode({
14630
+ nextAction: options.nextAction,
14631
+ recommendedCommands: options.recommendedCommands
14632
+ }),
14633
+ includesStatusPoll: Boolean(options.recommendedCommands.status),
14634
+ includesApprove: Boolean(options.recommendedCommands.approve),
14635
+ includesRelayInspect: Boolean(options.recommendedCommands.relayInspect),
14636
+ includesRemoteReissue: Boolean(options.recommendedCommands.reissueRemoteApproval)
14637
+ };
14638
+ }
13539
14639
  function sanitizeWalletRequestRecord(request) {
13540
14640
  const { sessionSecretKey: _sessionSecretKey, ...rest } = request;
13541
14641
  return rest;
@@ -14833,7 +15933,9 @@ async function buildRelayStatusFollowUp(options) {
14833
15933
  walletName: options.relay.request?.walletName,
14834
15934
  relayUrl: options.relayUrl,
14835
15935
  paymasterMode: options.relay.request?.requestedPaymasterMode,
14836
- accountKind: options.relay.request?.requestedAccountKind
15936
+ accountKind: options.relay.request?.requestedAccountKind,
15937
+ sessionPolicies: options.relay.request?.policies,
15938
+ requestCreatedAt: options.relay.request?.createdAt
14837
15939
  });
14838
15940
  }
14839
15941
  if (options.relay.approval_ready) {
@@ -14878,11 +15980,18 @@ async function buildRelayExpiredRecoveryCommands(options) {
14878
15980
  };
14879
15981
  }
14880
15982
  const existingWallet = await loadWalletSession(walletName);
14881
- const reissueRemoteApproval = existingWallet ? buildWalletReapproveRemoteRecommendedCommand(walletName, options.relayUrl) : buildWalletCreateRemoteRecommendedCommand(
15983
+ const reissueRemoteApproval = existingWallet ? buildWalletReapproveRemoteRecommendedCommand(walletName, options.relayUrl, {
15984
+ sessionPolicies: options.sessionPolicies,
15985
+ requestCreatedAt: options.requestCreatedAt
15986
+ }) : buildWalletCreateRemoteRecommendedCommand(
14882
15987
  options.relayUrl,
14883
15988
  options.paymasterMode,
14884
15989
  walletName,
14885
- options.accountKind
15990
+ options.accountKind,
15991
+ {
15992
+ sessionPolicies: options.sessionPolicies,
15993
+ requestCreatedAt: options.requestCreatedAt
15994
+ }
14886
15995
  );
14887
15996
  return {
14888
15997
  nextAction: reissueRemoteApproval,
@@ -14890,7 +15999,7 @@ async function buildRelayExpiredRecoveryCommands(options) {
14890
15999
  relayInspect,
14891
16000
  reissueRemoteApproval
14892
16001
  },
14893
- note: "Relay approval expired. Reissue the remote request. If the original request used scoped session flags, add those same policy flags again."
16002
+ note: "Relay approval expired. Reissue the remote request. The recovery command preserves any CLI-expressible session-policy flags from the expired request."
14894
16003
  };
14895
16004
  }
14896
16005
  function buildRelayApprovalTimeoutError(options) {
@@ -14913,6 +16022,18 @@ function buildRelayApprovalTimeoutError(options) {
14913
16022
  retryable: true,
14914
16023
  statusCommand,
14915
16024
  approveCommand,
16025
+ relayRecoverySummary: buildRelayRecoverySummary({
16026
+ requestId: options.requestId,
16027
+ walletName: options.walletName,
16028
+ relayUrl: options.relayUrl,
16029
+ relayStatus: null,
16030
+ approvalReady: null,
16031
+ nextAction: statusCommand,
16032
+ recommendedCommands: {
16033
+ status: statusCommand,
16034
+ approve: approveCommand
16035
+ }
16036
+ }),
14916
16037
  suggestedAction: "Check the current relay status, then finalize the wallet approval once approval_ready=true."
14917
16038
  }
14918
16039
  );
@@ -14922,7 +16043,9 @@ async function buildRelayApprovalExpiredError(options) {
14922
16043
  walletName: options.walletName,
14923
16044
  relayUrl: options.relayUrl,
14924
16045
  paymasterMode: options.paymasterMode,
14925
- accountKind: options.accountKind
16046
+ accountKind: options.accountKind,
16047
+ sessionPolicies: options.sessionPolicies,
16048
+ requestCreatedAt: options.requestCreatedAt
14926
16049
  });
14927
16050
  return new AgentError(
14928
16051
  "RELAY_APPROVAL_EXPIRED",
@@ -14934,6 +16057,15 @@ async function buildRelayApprovalExpiredError(options) {
14934
16057
  note: recovery.note,
14935
16058
  relayInspectCommand: recovery.recommendedCommands.relayInspect,
14936
16059
  reissueRemoteApprovalCommand: recovery.recommendedCommands.reissueRemoteApproval,
16060
+ relayRecoverySummary: buildRelayRecoverySummary({
16061
+ requestId: options.requestId,
16062
+ walletName: options.walletName,
16063
+ relayUrl: options.relayUrl,
16064
+ relayStatus: "expired",
16065
+ approvalReady: false,
16066
+ nextAction: recovery.nextAction,
16067
+ recommendedCommands: recovery.recommendedCommands
16068
+ }),
14937
16069
  suggestedAction: "Inspect the hosted relay, then reissue the remote approval request."
14938
16070
  }
14939
16071
  );
@@ -14958,6 +16090,17 @@ function buildRelayApprovalNotReadyError(options) {
14958
16090
  retryable: true,
14959
16091
  statusCommand,
14960
16092
  approveCommand,
16093
+ relayRecoverySummary: buildRelayRecoverySummary({
16094
+ requestId: options.requestId,
16095
+ relayUrl: options.relayUrl,
16096
+ relayStatus: options.status,
16097
+ approvalReady: options.approvalReady,
16098
+ nextAction: statusCommand,
16099
+ recommendedCommands: {
16100
+ status: statusCommand,
16101
+ approve: approveCommand
16102
+ }
16103
+ }),
14961
16104
  suggestedAction: "Check the current relay status, then retry approval once approval_ready=true."
14962
16105
  }
14963
16106
  );
@@ -15137,6 +16280,7 @@ async function finalizePublishedRelayWalletRequest(options) {
15137
16280
  if (error instanceof Error && error.message.startsWith("Timed out waiting for relay approval after ")) {
15138
16281
  throw buildRelayApprovalTimeoutError({
15139
16282
  requestId: options.walletRequest.requestId,
16283
+ walletName: options.walletRequest.walletName,
15140
16284
  relayUrl: options.relayUrl,
15141
16285
  timeoutMs: options.timeoutMs,
15142
16286
  intervalMs: options.intervalMs
@@ -15148,7 +16292,9 @@ async function finalizePublishedRelayWalletRequest(options) {
15148
16292
  walletName: options.walletRequest.walletName,
15149
16293
  relayUrl: options.relayUrl,
15150
16294
  paymasterMode: options.walletRequest.requestedPaymasterMode,
15151
- accountKind: options.walletRequest.requestedAccountKind
16295
+ accountKind: options.walletRequest.requestedAccountKind,
16296
+ sessionPolicies: options.walletRequest.policies,
16297
+ requestCreatedAt: options.walletRequest.createdAt
15152
16298
  });
15153
16299
  }
15154
16300
  throw error;
@@ -15519,32 +16665,32 @@ async function printBuiltinSmartAccountProfiles() {
15519
16665
  }
15520
16666
  function createWalletCommand(deps) {
15521
16667
  const resolvedDeps = resolveWalletCommandDeps(deps);
15522
- const wallet = new Command9("wallet").description(
16668
+ const wallet = new Command10("wallet").description(
15523
16669
  "Create, inspect, and recover local-first wallet sessions"
15524
16670
  );
15525
- const request = new Command9("request").description("Inspect and finalize pending wallet requests");
15526
- const signer = new Command9("signer").description(
16671
+ const request = new Command10("request").description("Inspect and finalize pending wallet requests");
16672
+ const signer = new Command10("signer").description(
15527
16673
  "Inspect and manage the stored local execution signer for a wallet"
15528
16674
  );
15529
- const smartAccount = new Command9("smart-account").description(
16675
+ const smartAccount = new Command10("smart-account").description(
15530
16676
  "Predict and deploy zkSync smart-account contracts from a supplied artifact or built-in profile"
15531
16677
  );
15532
- const sedLite = new Command9("sed-lite").description(
16678
+ const sedLite = new Command10("sed-lite").description(
15533
16679
  "Inspect and manage the SED modular smart-account profile"
15534
16680
  );
15535
- const nativeCapHook = new Command9("native-cap-hook").description(
16681
+ const nativeCapHook = new Command10("native-cap-hook").description(
15536
16682
  "Inspect and manage the first SED Lite validation-hook policy: native per-transaction spend caps"
15537
16683
  );
15538
- const targetAllowlistHook = new Command9("target-allowlist-hook").description(
16684
+ const targetAllowlistHook = new Command10("target-allowlist-hook").description(
15539
16685
  "Inspect and manage the SED Lite validation-hook policy that restricts transactions to an allowlisted target set"
15540
16686
  );
15541
- const selectorAllowlistHook = new Command9("selector-allowlist-hook").description(
16687
+ const selectorAllowlistHook = new Command10("selector-allowlist-hook").description(
15542
16688
  "Inspect and manage the SED Lite validation-hook policy that restricts contract calls to allowlisted target and selector pairs"
15543
16689
  );
15544
- const dailySpendLimit = new Command9("daily-spend-limit").description(
16690
+ const dailySpendLimit = new Command10("daily-spend-limit").description(
15545
16691
  "Read and update the native-token daily spend limit used by the built-in daily-spend-limit smart-account profile"
15546
16692
  );
15547
- const paymaster = new Command9("paymaster").description(
16693
+ const paymaster = new Command10("paymaster").description(
15548
16694
  "Manage saved paymaster defaults for stored wallets"
15549
16695
  );
15550
16696
  wallet.addHelpText(
@@ -15552,6 +16698,9 @@ function createWalletCommand(deps) {
15552
16698
  [
15553
16699
  "",
15554
16700
  "Local-first wallet path:",
16701
+ " Use this layer when the blocker is specifically about wallet approval or signer state.",
16702
+ " Otherwise start with `zk-agent next` or `zk-agent doctor`.",
16703
+ "",
15555
16704
  " First bootstrap:",
15556
16705
  " zk-agent wallet create --await-local",
15557
16706
  " zk-agent next",
@@ -15572,7 +16721,8 @@ function createWalletCommand(deps) {
15572
16721
  " zk-agent relay inspect --relay-url <url>",
15573
16722
  " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
15574
16723
  " zk-agent wallet reapprove --name main --relay-url <url> --wait-relay --prompt-code",
15575
- " zk-agent next"
16724
+ " zk-agent next",
16725
+ " Use this only when the browser is not colocated with the terminal."
15576
16726
  ].join("\n")
15577
16727
  );
15578
16728
  request.addHelpText(
@@ -15643,7 +16793,28 @@ function createWalletCommand(deps) {
15643
16793
  ).option("--disallow-transfers", "Disable transfer capability for the approved session").option(
15644
16794
  "--disallow-contract-calls",
15645
16795
  "Disable contract-call capability for the approved session"
15646
- ).option("--connector-url <url>", "Connector UI base URL override").option("--relay-url <url>", "Relay server base URL for immediate remote approval publishing").option("--account-kind <kind>", "Requested account kind", "smart-account").option("--paymaster-mode <mode>", "Requested paymaster mode", "none").option("--await-local", "Immediately wait for a local connector approval callback").option("--wait-relay", "Wait for relay approval readiness and finalize from the same command (requires --relay-url and either --code or --prompt-code)").option("--code <code>", "6-digit relay approval code used together with --wait-relay").option("--prompt-code", "Read the 6-digit relay approval code from stdin after the relay approval is ready").option("--host <host>", "Loopback host to bind when using --await-local", "127.0.0.1").option("--port <port>", "Loopback port to bind when using --await-local (0 = choose a free port)", "0").option("--timeout-seconds <seconds>", "How long to wait when using --await-local or --wait-relay", "600").option("--interval-ms <milliseconds>", "How often to poll relay status while using --wait-relay", "2000").action(
16796
+ ).option("--connector-url <url>", "Connector UI base URL override").option("--relay-url <url>", "Relay server base URL for immediate remote approval publishing").option("--account-kind <kind>", "Requested account kind", "smart-account").option("--paymaster-mode <mode>", "Requested paymaster mode", "none").option("--await-local", "Immediately wait for a local connector approval callback").option("--wait-relay", "Wait for relay approval readiness and finalize from the same command (requires --relay-url and either --code or --prompt-code)").option("--code <code>", "6-digit relay approval code used together with --wait-relay").option("--prompt-code", "Read the 6-digit relay approval code from stdin after the relay approval is ready").option("--host <host>", "Loopback host to bind when using --await-local", "127.0.0.1").option("--port <port>", "Loopback port to bind when using --await-local (0 = choose a free port)", "0").option("--timeout-seconds <seconds>", "How long to wait when using --await-local or --wait-relay", "600").option("--interval-ms <milliseconds>", "How often to poll relay status while using --wait-relay", "2000").addHelpText(
16797
+ "after",
16798
+ [
16799
+ "",
16800
+ "Default wallet-create path:",
16801
+ " Keep `--await-local` as the local-first baseline when the browser and terminal are colocated.",
16802
+ "",
16803
+ " Fresh bootstrap:",
16804
+ " zk-agent next",
16805
+ " zk-agent wallet create --await-local",
16806
+ " zk-agent next",
16807
+ "",
16808
+ " Remote-browser fallback:",
16809
+ " zk-agent relay inspect --relay-url <url>",
16810
+ " zk-agent wallet create --relay-url <url> --wait-relay --prompt-code",
16811
+ " zk-agent next",
16812
+ "",
16813
+ "Environment note:",
16814
+ " No custom .env is required to create the wallet request itself.",
16815
+ " Add RPC env vars later, before live reads or broadcasts."
16816
+ ].join("\n")
16817
+ ).action(
15647
16818
  async (options) => {
15648
16819
  const config = await loadProjectConfig();
15649
16820
  const chain = options.chain || config?.defaultChain || "zksync-era";
@@ -15737,6 +16908,20 @@ function createWalletCommand(deps) {
15737
16908
  options.relayUrl,
15738
16909
  request2.requestedPaymasterMode
15739
16910
  );
16911
+ const nextAction = buildPendingRequestNextAction(recommendedCommands);
16912
+ const relayRecoverySummary = relay && recommendedCommands.relayStatus && recommendedCommands.relayApprove ? buildRelayRecoverySummary({
16913
+ requestId: request2.requestId,
16914
+ walletName: request2.walletName,
16915
+ relayUrl: options.relayUrl,
16916
+ relayStatus: relay.status,
16917
+ approvalReady: null,
16918
+ nextAction,
16919
+ recommendedCommands: {
16920
+ status: recommendedCommands.relayStatus,
16921
+ approve: recommendedCommands.relayApprove
16922
+ },
16923
+ relay
16924
+ }) : void 0;
15740
16925
  printResult(
15741
16926
  [
15742
16927
  ["wallet", request2.walletName],
@@ -15779,6 +16964,7 @@ function createWalletCommand(deps) {
15779
16964
  approvalUrl: request2.approvalUrl,
15780
16965
  relay,
15781
16966
  ...relayOutputAliases(relay),
16967
+ relayRecoverySummary,
15782
16968
  expiresAt: request2.expiresAt,
15783
16969
  chain: request2.chain,
15784
16970
  chainId: request2.chainId,
@@ -15786,7 +16972,7 @@ function createWalletCommand(deps) {
15786
16972
  paymasterMode: request2.requestedPaymasterMode,
15787
16973
  capabilities: request2.requestedCapabilities,
15788
16974
  sessionScope: request2.requestedSessionScope,
15789
- nextAction: buildPendingRequestNextAction(recommendedCommands),
16975
+ nextAction,
15790
16976
  recommendedCommands
15791
16977
  }
15792
16978
  );
@@ -15811,7 +16997,27 @@ function createWalletCommand(deps) {
15811
16997
  ).option("--disallow-transfers", "Disable transfer capability for the approved session").option(
15812
16998
  "--disallow-contract-calls",
15813
16999
  "Disable contract-call capability for the approved session"
15814
- ).option("--connector-url <url>", "Connector UI base URL override").option("--relay-url <url>", "Relay server base URL for immediate remote approval publishing").option("--await-local", "Immediately wait for a local connector approval callback").option("--wait-relay", "Wait for relay approval readiness and finalize from the same command (requires --relay-url and either --code or --prompt-code)").option("--code <code>", "6-digit relay approval code used together with --wait-relay").option("--prompt-code", "Read the 6-digit relay approval code from stdin after the relay approval is ready").option("--host <host>", "Loopback host to bind when using --await-local", "127.0.0.1").option("--port <port>", "Loopback port to bind when using --await-local (0 = choose a free port)", "0").option("--timeout-seconds <seconds>", "How long to wait when using --await-local or --wait-relay", "600").option("--interval-ms <milliseconds>", "How often to poll relay status while using --wait-relay", "2000").action(
17000
+ ).option("--connector-url <url>", "Connector UI base URL override").option("--relay-url <url>", "Relay server base URL for immediate remote approval publishing").option("--await-local", "Immediately wait for a local connector approval callback").option("--wait-relay", "Wait for relay approval readiness and finalize from the same command (requires --relay-url and either --code or --prompt-code)").option("--code <code>", "6-digit relay approval code used together with --wait-relay").option("--prompt-code", "Read the 6-digit relay approval code from stdin after the relay approval is ready").option("--host <host>", "Loopback host to bind when using --await-local", "127.0.0.1").option("--port <port>", "Loopback port to bind when using --await-local (0 = choose a free port)", "0").option("--timeout-seconds <seconds>", "How long to wait when using --await-local or --wait-relay", "600").option("--interval-ms <milliseconds>", "How often to poll relay status while using --wait-relay", "2000").addHelpText(
17001
+ "after",
17002
+ [
17003
+ "",
17004
+ "Default wallet-reapprove path:",
17005
+ " Use this when the wallet already exists locally but its approval/session must be refreshed.",
17006
+ "",
17007
+ " Colocated browser + terminal:",
17008
+ " zk-agent wallet reapprove --name main --await-local",
17009
+ " zk-agent next",
17010
+ "",
17011
+ " Remote-browser fallback:",
17012
+ " zk-agent relay inspect --relay-url <url>",
17013
+ " zk-agent wallet reapprove --name main --relay-url <url> --wait-relay --prompt-code",
17014
+ " zk-agent next",
17015
+ "",
17016
+ "Environment note:",
17017
+ " No custom .env is required to create the reapproval request itself.",
17018
+ " Add RPC env vars later, before live reads or broadcasts."
17019
+ ].join("\n")
17020
+ ).action(
15815
17021
  async (options) => {
15816
17022
  const walletRecord = await requireWalletRecord(options.name);
15817
17023
  const request2 = await createWalletReapprovalRequest({
@@ -15902,6 +17108,20 @@ function createWalletCommand(deps) {
15902
17108
  options.relayUrl,
15903
17109
  request2.requestedPaymasterMode
15904
17110
  );
17111
+ const nextAction = buildPendingRequestNextAction(recommendedCommands);
17112
+ const relayRecoverySummary = relay && recommendedCommands.relayStatus && recommendedCommands.relayApprove ? buildRelayRecoverySummary({
17113
+ requestId: request2.requestId,
17114
+ walletName: request2.walletName,
17115
+ relayUrl: options.relayUrl,
17116
+ relayStatus: relay.status,
17117
+ approvalReady: null,
17118
+ nextAction,
17119
+ recommendedCommands: {
17120
+ status: recommendedCommands.relayStatus,
17121
+ approve: recommendedCommands.relayApprove
17122
+ },
17123
+ relay
17124
+ }) : void 0;
15905
17125
  printResult(
15906
17126
  [
15907
17127
  ["wallet", request2.walletName],
@@ -15944,7 +17164,8 @@ function createWalletCommand(deps) {
15944
17164
  request: sanitizeWalletRequestRecord(request2),
15945
17165
  relay,
15946
17166
  ...relayOutputAliases(relay),
15947
- nextAction: buildPendingRequestNextAction(recommendedCommands),
17167
+ relayRecoverySummary,
17168
+ nextAction,
15948
17169
  recommendedCommands
15949
17170
  }
15950
17171
  );
@@ -16079,21 +17300,61 @@ function createWalletCommand(deps) {
16079
17300
  const walletRecord = await loadWalletSession(options.name);
16080
17301
  if (!walletRecord) throw new Error(`Wallet not found: ${options.name}`);
16081
17302
  const { inspection, summary } = await loadWalletStatusSummary(walletRecord, resolvedDeps);
16082
- printResult(walletStatusLines(inspection, summary), { ok: true, inspection, summary });
17303
+ const recommendedCommands = buildWalletNextRecommendedCommands(
17304
+ walletRecord.walletName,
17305
+ summary,
17306
+ resolveEffectivePaymasterSelection(walletRecord)?.mode
17307
+ );
17308
+ const tokenDiscoverySummary = buildWalletTokenDiscoverySummary({
17309
+ walletName: walletRecord.walletName,
17310
+ chain: summary.chain,
17311
+ nextAction: summary.recommendedCommand,
17312
+ paymasterMode: resolveEffectivePaymasterSelection(walletRecord)?.mode,
17313
+ recommendedCommands
17314
+ });
17315
+ printResult(
17316
+ [
17317
+ ...walletStatusLines(inspection, summary),
17318
+ ["discover assets", recommendedCommands.discoverAssets],
17319
+ ["discover owned tokens", recommendedCommands.discoverOwnedTokens],
17320
+ ...recommendedCommands.discoverPaymasterTokens ? [["discover paymaster tokens", recommendedCommands.discoverPaymasterTokens]] : [],
17321
+ ["discover tokens", recommendedCommands.discoverTokens],
17322
+ ...recommendedCommands.inspectPaymasterToken ? [["inspect paymaster token", recommendedCommands.inspectPaymasterToken]] : [],
17323
+ ["inspect token", recommendedCommands.inspectToken],
17324
+ ["wallet next", buildWalletNextRecommendedCommand(walletRecord.walletName)]
17325
+ ],
17326
+ {
17327
+ ok: true,
17328
+ inspection,
17329
+ summary,
17330
+ tokenDiscoverySummary,
17331
+ recommendedCommands
17332
+ }
17333
+ );
16083
17334
  });
16084
17335
  wallet.command("next").description("Explain the shortest next CLI steps to make a stored wallet operational").option("--name <name>", "Wallet name", "main").action(async (options) => {
16085
17336
  const walletRecord = await requireWalletRecord(options.name);
16086
17337
  const { inspection, summary } = await loadWalletStatusSummary(walletRecord, resolvedDeps);
16087
17338
  const recommendedCommands = buildWalletNextRecommendedCommands(
16088
17339
  walletRecord.walletName,
16089
- summary
17340
+ summary,
17341
+ resolveEffectivePaymasterSelection(walletRecord)?.mode
16090
17342
  );
17343
+ const tokenDiscoverySummary = buildWalletTokenDiscoverySummary({
17344
+ walletName: walletRecord.walletName,
17345
+ chain: summary.chain,
17346
+ nextAction: summary.recommendedCommand,
17347
+ paymasterMode: resolveEffectivePaymasterSelection(walletRecord)?.mode,
17348
+ recommendedCommands
17349
+ });
16091
17350
  printResult(
16092
17351
  [
16093
17352
  ...walletNextLines(summary),
16094
17353
  ["discover assets", recommendedCommands.discoverAssets],
16095
17354
  ["discover owned tokens", recommendedCommands.discoverOwnedTokens],
17355
+ ...recommendedCommands.discoverPaymasterTokens ? [["discover paymaster tokens", recommendedCommands.discoverPaymasterTokens]] : [],
16096
17356
  ["discover tokens", recommendedCommands.discoverTokens],
17357
+ ...recommendedCommands.inspectPaymasterToken ? [["inspect paymaster token", recommendedCommands.inspectPaymasterToken]] : [],
16097
17358
  ["inspect token", recommendedCommands.inspectToken],
16098
17359
  ["status command", recommendedCommands.walletStatus]
16099
17360
  ],
@@ -16101,6 +17362,7 @@ function createWalletCommand(deps) {
16101
17362
  ok: true,
16102
17363
  inspection,
16103
17364
  summary,
17365
+ tokenDiscoverySummary,
16104
17366
  recommendedCommands
16105
17367
  }
16106
17368
  );
@@ -16264,6 +17526,30 @@ function createWalletCommand(deps) {
16264
17526
  request.command("relay-publish").description("Publish a stored wallet request to a relay server and get a shareable approval URL").requiredOption("--request-id <id>", "Wallet request id").requiredOption("--relay-url <url>", "Relay server base URL").action(async (options) => {
16265
17527
  const walletRequest = await requireActiveWalletRequest(options.requestId);
16266
17528
  const relay = await publishWalletRequestToRelay(walletRequest, options.relayUrl);
17529
+ const nextAction = buildWalletRequestRelayStatusRecommendedCommand(
17530
+ relay.request_id,
17531
+ options.relayUrl
17532
+ );
17533
+ const recommendedCommands = {
17534
+ status: buildWalletRequestRelayStatusRecommendedCommand(
17535
+ relay.request_id,
17536
+ options.relayUrl
17537
+ ),
17538
+ approve: buildWalletRequestRelayApproveRecommendedCommand(
17539
+ relay.request_id,
17540
+ options.relayUrl
17541
+ )
17542
+ };
17543
+ const relayRecoverySummary = buildRelayRecoverySummary({
17544
+ requestId: relay.request_id,
17545
+ walletName: walletRequest.walletName,
17546
+ relayUrl: options.relayUrl,
17547
+ relayStatus: relay.status,
17548
+ approvalReady: null,
17549
+ nextAction,
17550
+ recommendedCommands,
17551
+ relay
17552
+ });
16267
17553
  printResult(
16268
17554
  [
16269
17555
  ["status", relay.status],
@@ -16272,26 +17558,25 @@ function createWalletCommand(deps) {
16272
17558
  ["status url", relay.status_url],
16273
17559
  ["share-link base", relay.share_url.replace(/\/[^/]+$/, "")],
16274
17560
  ["status api base", relay.status_url.replace(/\/[^/]+$/, "")],
16275
- ["next status", buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl)],
16276
- ["next approve", buildWalletRequestRelayApproveRecommendedCommand(relay.request_id, options.relayUrl)]
17561
+ ["next status", recommendedCommands.status],
17562
+ ["next approve", recommendedCommands.approve]
16277
17563
  ],
16278
17564
  {
16279
17565
  ok: true,
16280
17566
  walletRequestId: walletRequest.requestId,
16281
17567
  relay,
16282
17568
  ...relayOutputAliases(relay),
17569
+ relayRecoverySummary,
16283
17570
  request: sanitizeWalletRequestRecord(walletRequest),
16284
- nextAction: buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl),
16285
- recommendedCommands: {
16286
- status: buildWalletRequestRelayStatusRecommendedCommand(relay.request_id, options.relayUrl),
16287
- approve: buildWalletRequestRelayApproveRecommendedCommand(relay.request_id, options.relayUrl)
16288
- }
17571
+ nextAction,
17572
+ recommendedCommands
16289
17573
  }
16290
17574
  );
16291
17575
  });
16292
17576
  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) => {
16293
17577
  const timeoutMs = parsePositiveIntegerOption(options.timeoutSeconds, "--timeout-seconds", 600) * 1e3;
16294
17578
  const intervalMs = parsePositiveIntegerOption(options.intervalMs, "--interval-ms", 2e3);
17579
+ const walletRequest = await loadWalletRequest(options.requestId);
16295
17580
  let relay;
16296
17581
  try {
16297
17582
  relay = options.wait ? await waitForRelayApprovalReady(options.relayUrl, options.requestId, {
@@ -16302,6 +17587,7 @@ function createWalletCommand(deps) {
16302
17587
  if (options.wait && error instanceof Error && error.message.startsWith("Timed out waiting for relay approval after ")) {
16303
17588
  throw buildRelayApprovalTimeoutError({
16304
17589
  requestId: options.requestId,
17590
+ walletName: walletRequest?.walletName,
16305
17591
  relayUrl: options.relayUrl,
16306
17592
  timeoutMs,
16307
17593
  intervalMs
@@ -16313,6 +17599,16 @@ function createWalletCommand(deps) {
16313
17599
  relay,
16314
17600
  relayUrl: options.relayUrl
16315
17601
  });
17602
+ const relayRecoverySummary = buildRelayRecoverySummary({
17603
+ requestId: relay.request_id,
17604
+ walletName: relay.request?.walletName || walletRequest?.walletName,
17605
+ relayUrl: options.relayUrl,
17606
+ relayStatus: relay.status,
17607
+ approvalReady: relay.approval_ready,
17608
+ nextAction: followUp.nextAction,
17609
+ recommendedCommands: followUp.recommendedCommands,
17610
+ relay
17611
+ });
16316
17612
  printResult(
16317
17613
  [
16318
17614
  ["status", relay.status],
@@ -16334,6 +17630,7 @@ function createWalletCommand(deps) {
16334
17630
  walletRequestId: relay.request_id,
16335
17631
  relay,
16336
17632
  ...relayOutputAliases(relay),
17633
+ relayRecoverySummary,
16337
17634
  nextAction: followUp.nextAction,
16338
17635
  recommendedCommands: followUp.recommendedCommands,
16339
17636
  ...followUp.note ? { note: followUp.note } : {}
@@ -18022,7 +19319,7 @@ function createWalletCommand(deps) {
18022
19319
 
18023
19320
  // src/commands/workflow.ts
18024
19321
  import { randomBytes as randomBytes4 } from "node:crypto";
18025
- import { Command as Command10 } from "commander";
19322
+ import { Command as Command11 } from "commander";
18026
19323
  var defaultProvider2 = new ZkSyncWalletProvider();
18027
19324
  var defaultDefiProvider2 = new ZkSyncDefiProvider({
18028
19325
  walletWriter: defaultProvider2
@@ -18662,7 +19959,69 @@ function withAgentProfileLines(lines, agentProfile, agentFollowup) {
18662
19959
  ...agentFollowup ? agentFollowupLines(agentFollowup) : []
18663
19960
  ];
18664
19961
  }
18665
- async function printWorkflowRunCommandResult(execution) {
19962
+ function serializeWorkflowFundingProgress(fundingProgress) {
19963
+ return fundingProgress ? {
19964
+ kind: fundingProgress.kind,
19965
+ txHash: fundingProgress.txHash,
19966
+ status: fundingProgress.status,
19967
+ terminal: fundingProgress.terminal,
19968
+ finalized: fundingProgress.finalized
19969
+ } : void 0;
19970
+ }
19971
+ function buildWorkflowRuntimeSummary(options) {
19972
+ if (!options.status && !options.result) {
19973
+ throw new Error("Workflow runtime summary requires a workflow status or execution result.");
19974
+ }
19975
+ const nextCommand = options.nextCommand ?? options.result?.nextCommand ?? options.status?.fundingProgress?.nextCommand ?? options.status?.recommendedCommand;
19976
+ return {
19977
+ status: options.result?.stage ?? options.status?.status ?? "blocked",
19978
+ readyForGoal: options.result ? options.result.stage === "goal-executed" : Boolean(options.status?.readyForGoal),
19979
+ nextCommand,
19980
+ blockingActionIds: options.status?.blockingActionIds ?? [],
19981
+ fundingProgress: serializeWorkflowFundingProgress(options.status?.fundingProgress)
19982
+ };
19983
+ }
19984
+ function buildWorkflowEntrySummary(input) {
19985
+ if (input.plan) {
19986
+ return {
19987
+ entrypoint: "workflow",
19988
+ command: input.command,
19989
+ source: input.source || null,
19990
+ workflowRequestId: input.requestId || null,
19991
+ walletName: input.plan.walletName,
19992
+ intent: input.plan.intent,
19993
+ runtimeStatus: input.plan.status,
19994
+ readyForGoal: input.plan.readyForGoal,
19995
+ walletApprovalStatus: null,
19996
+ checkpointPersisted: typeof input.checkpointPersisted === "boolean" ? input.checkpointPersisted : null,
19997
+ nextAction: input.nextCommand || input.plan.recommendedCommand || null
19998
+ };
19999
+ }
20000
+ const runtimeSummary = buildWorkflowRuntimeSummary({
20001
+ status: input.status,
20002
+ result: input.result,
20003
+ nextCommand: input.nextCommand
20004
+ });
20005
+ const walletName = input.result?.walletName ?? input.status?.walletName;
20006
+ const intent = input.result?.intent ?? input.status?.intent;
20007
+ if (!walletName || !intent) {
20008
+ throw new Error("Workflow entry summary requires workflow status or execution metadata.");
20009
+ }
20010
+ return {
20011
+ entrypoint: "workflow",
20012
+ command: input.command,
20013
+ source: input.source || null,
20014
+ workflowRequestId: input.requestId || null,
20015
+ walletName,
20016
+ intent,
20017
+ runtimeStatus: runtimeSummary.status,
20018
+ readyForGoal: runtimeSummary.readyForGoal,
20019
+ walletApprovalStatus: buildWorkflowWalletApprovalSummary(input.walletApproval)?.status || null,
20020
+ checkpointPersisted: typeof input.checkpointPersisted === "boolean" ? input.checkpointPersisted : null,
20021
+ nextAction: runtimeSummary.nextCommand || null
20022
+ };
20023
+ }
20024
+ async function printWorkflowRunCommandResult(execution, command) {
18666
20025
  if (execution.result) {
18667
20026
  const agentProfile2 = await loadWorkflowAgentProfile(execution.result.walletName);
18668
20027
  const agentFollowup2 = buildAgentFollowup(agentProfile2, {
@@ -18677,6 +20036,29 @@ async function printWorkflowRunCommandResult(execution) {
18677
20036
  intent: execution.result.intent,
18678
20037
  paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal)
18679
20038
  });
20039
+ const tokenDiscoverySummary2 = buildWorkflowTokenDiscoverySummary({
20040
+ walletName: execution.result.walletName,
20041
+ chain: execution.result.plan.chain,
20042
+ intent: execution.result.intent,
20043
+ nextAction: execution.result.nextCommand,
20044
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal),
20045
+ recommendedCommands: recommendedCommands2
20046
+ });
20047
+ const summary2 = buildWorkflowRuntimeSummary({
20048
+ status: execution.status,
20049
+ result: execution.result,
20050
+ nextCommand: execution.result.nextCommand
20051
+ });
20052
+ const workflowEntrySummary2 = buildWorkflowEntrySummary({
20053
+ command,
20054
+ source: execution.requestId ? "checkpoint" : "input",
20055
+ requestId: execution.requestId,
20056
+ checkpointPersisted: Boolean(execution.checkpoint || execution.requestId),
20057
+ status: execution.status,
20058
+ result: execution.result,
20059
+ walletApproval: execution.walletApproval,
20060
+ nextCommand: execution.result.nextCommand
20061
+ });
18680
20062
  printResult(
18681
20063
  prependWorkflowRequestId(
18682
20064
  execution.requestId,
@@ -18693,38 +20075,62 @@ async function printWorkflowRunCommandResult(execution) {
18693
20075
  {
18694
20076
  ok: true,
18695
20077
  ...serializeWorkflowRequestMeta(execution.requestId),
20078
+ workflowEntrySummary: workflowEntrySummary2,
18696
20079
  agentProfile: agentProfile2,
18697
20080
  agentFollowup: agentFollowup2,
20081
+ summary: summary2,
18698
20082
  result: execution.result,
18699
- walletRequestId: execution.walletApproval?.request.requestId,
18700
- walletApprovalRelay: execution.walletApproval?.relay,
18701
- ...workflowWalletApprovalRelayAliases(execution.walletApproval?.relay),
18702
- walletApprovalRecommendedCommands: execution.walletApproval?.recommendedCommands,
18703
- walletApproval: serializeWalletApproval(execution.walletApproval),
20083
+ ...serializeWorkflowWalletApprovalOutput(execution.walletApproval),
20084
+ tokenDiscoverySummary: tokenDiscoverySummary2,
18704
20085
  recommendedCommands: recommendedCommands2
18705
20086
  }
18706
20087
  );
18707
20088
  return;
18708
20089
  }
18709
- const agentProfile = await loadWorkflowAgentProfile(execution.status.walletName);
20090
+ const status = execution.status;
20091
+ if (!status) {
20092
+ throw new Error("Workflow run result is missing both execution result and status.");
20093
+ }
20094
+ const agentProfile = await loadWorkflowAgentProfile(status.walletName);
18710
20095
  const agentFollowup = buildAgentFollowup(agentProfile, {
18711
- walletName: execution.status.walletName,
20096
+ walletName: status.walletName,
18712
20097
  walletExists: true
18713
20098
  });
18714
20099
  const recommendedCommands = buildWorkflowRuntimeRecommendedCommands({
18715
20100
  requestId: execution.requestId,
18716
- walletName: execution.status.walletName,
18717
- nextAction: execution.status.recommendedCommand,
18718
- chain: execution.status.plan.chain,
18719
- intent: execution.status.intent,
20101
+ walletName: status.walletName,
20102
+ nextAction: status.recommendedCommand,
20103
+ chain: status.plan.chain,
20104
+ intent: status.intent,
18720
20105
  paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
18721
20106
  });
20107
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
20108
+ walletName: status.walletName,
20109
+ chain: status.plan.chain,
20110
+ intent: status.intent,
20111
+ nextAction: status.recommendedCommand,
20112
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal),
20113
+ recommendedCommands
20114
+ });
20115
+ const summary = buildWorkflowRuntimeSummary({
20116
+ status,
20117
+ nextCommand: status.recommendedCommand
20118
+ });
20119
+ const workflowEntrySummary = buildWorkflowEntrySummary({
20120
+ command,
20121
+ source: execution.requestId ? "checkpoint" : "input",
20122
+ requestId: execution.requestId,
20123
+ checkpointPersisted: Boolean(execution.checkpoint || execution.requestId),
20124
+ status,
20125
+ walletApproval: execution.walletApproval,
20126
+ nextCommand: status.recommendedCommand
20127
+ });
18722
20128
  printResult(
18723
20129
  prependWorkflowRequestId(
18724
20130
  execution.requestId,
18725
20131
  withAgentProfileLines(
18726
20132
  [
18727
- ...workflowStatusLines(execution.status),
20133
+ ...workflowStatusLines(status),
18728
20134
  ...workflowWalletApprovalLines(execution.walletApproval),
18729
20135
  ...workflowFollowupLines(recommendedCommands)
18730
20136
  ],
@@ -18735,15 +20141,14 @@ async function printWorkflowRunCommandResult(execution) {
18735
20141
  {
18736
20142
  ok: true,
18737
20143
  ...serializeWorkflowRequestMeta(execution.requestId),
20144
+ workflowEntrySummary,
18738
20145
  agentProfile,
18739
20146
  agentFollowup,
18740
- status: execution.status,
20147
+ summary,
20148
+ status,
18741
20149
  checkpoint: execution.checkpoint,
18742
- walletRequestId: execution.walletApproval?.request.requestId,
18743
- walletApprovalRelay: execution.walletApproval?.relay,
18744
- ...workflowWalletApprovalRelayAliases(execution.walletApproval?.relay),
18745
- walletApprovalRecommendedCommands: execution.walletApproval?.recommendedCommands,
18746
- walletApproval: serializeWalletApproval(execution.walletApproval),
20150
+ ...serializeWorkflowWalletApprovalOutput(execution.walletApproval),
20151
+ tokenDiscoverySummary,
18747
20152
  recommendedCommands
18748
20153
  }
18749
20154
  );
@@ -18996,7 +20401,7 @@ async function executeWorkflowAutoCommand(options, deps = resolveWorkflowCommand
18996
20401
  walletApproval
18997
20402
  };
18998
20403
  }
18999
- async function printWorkflowAutoCommandResult(execution) {
20404
+ async function printWorkflowAutoCommandResult(execution, command) {
19000
20405
  const agentProfile = await loadWorkflowAgentProfile(execution.status.walletName);
19001
20406
  const agentFollowup = buildAgentFollowup(agentProfile, {
19002
20407
  walletName: execution.status.walletName,
@@ -19011,6 +20416,29 @@ async function printWorkflowAutoCommandResult(execution) {
19011
20416
  intent: execution.status.intent,
19012
20417
  paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal) ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
19013
20418
  });
20419
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
20420
+ walletName: execution.status.walletName,
20421
+ chain: execution.status.plan.chain,
20422
+ intent: execution.status.intent,
20423
+ nextAction,
20424
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal) ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal),
20425
+ recommendedCommands
20426
+ });
20427
+ const summary = buildWorkflowRuntimeSummary({
20428
+ status: execution.status,
20429
+ result: execution.result,
20430
+ nextCommand: nextAction
20431
+ });
20432
+ const workflowEntrySummary = buildWorkflowEntrySummary({
20433
+ command,
20434
+ source: execution.source,
20435
+ requestId: execution.requestId,
20436
+ checkpointPersisted: execution.checkpointPersisted,
20437
+ status: execution.status,
20438
+ result: execution.result,
20439
+ walletApproval: execution.walletApproval,
20440
+ nextCommand: nextAction
20441
+ });
19014
20442
  const summaryLines = [
19015
20443
  ["source", execution.source],
19016
20444
  ["action", execution.action],
@@ -19037,16 +20465,15 @@ async function printWorkflowAutoCommandResult(execution) {
19037
20465
  action: execution.action,
19038
20466
  checkpointPersisted: execution.checkpointPersisted,
19039
20467
  ...serializeWorkflowRequestMeta(execution.requestId),
20468
+ workflowEntrySummary,
19040
20469
  agentProfile,
19041
20470
  agentFollowup,
20471
+ summary,
19042
20472
  status: execution.status,
19043
20473
  result: execution.result,
19044
20474
  checkpoint: execution.checkpoint,
19045
- walletRequestId: execution.walletApproval?.request.requestId,
19046
- walletApprovalRelay: execution.walletApproval?.relay,
19047
- ...workflowWalletApprovalRelayAliases(execution.walletApproval?.relay),
19048
- walletApprovalRecommendedCommands: execution.walletApproval?.recommendedCommands,
19049
- walletApproval: serializeWalletApproval(execution.walletApproval),
20475
+ ...serializeWorkflowWalletApprovalOutput(execution.walletApproval),
20476
+ tokenDiscoverySummary,
19050
20477
  recommendedCommands
19051
20478
  }
19052
20479
  );
@@ -19102,7 +20529,7 @@ function buildWorkflowRuntimeRecommendedCommands(input) {
19102
20529
  ...input.nextAction ? {
19103
20530
  nextAction: input.nextAction
19104
20531
  } : {},
19105
- ...input.chain && input.intent && workflowIntentSupportsTokenDiscovery2(input.intent) ? {
20532
+ ...input.chain && input.intent && workflowIntentSupportsTokenDiscovery3(input.intent) ? {
19106
20533
  ...input.walletName ? {
19107
20534
  discoverAssets: `zk-agent assets --wallet ${input.walletName}`,
19108
20535
  discoverOwnedTokens: `zk-agent tokens --wallet ${input.walletName} --owned`
@@ -19116,16 +20543,54 @@ function buildWorkflowRuntimeRecommendedCommands(input) {
19116
20543
  } : {}
19117
20544
  };
19118
20545
  }
19119
- function workflowIntentSupportsTokenDiscovery2(intent) {
20546
+ function workflowIntentSupportsTokenDiscovery3(intent) {
19120
20547
  return intent === "send-token" || intent === "swap" || intent === "bridge" || intent === "deposit" || intent === "withdraw";
19121
20548
  }
20549
+ function buildWorkflowTokenDiscoverySummary(input) {
20550
+ if (!input.recommendedCommands) {
20551
+ return void 0;
20552
+ }
20553
+ const hasTokenDiscovery = Boolean(input.recommendedCommands.discoverAssets) || Boolean(input.recommendedCommands.discoverOwnedTokens) || Boolean(input.recommendedCommands.discoverTokens) || Boolean(input.recommendedCommands.inspectToken) || Boolean(input.recommendedCommands.discoverPaymasterTokens) || Boolean(input.recommendedCommands.inspectPaymasterToken);
20554
+ if (!hasTokenDiscovery) {
20555
+ return void 0;
20556
+ }
20557
+ return {
20558
+ walletName: input.walletName || null,
20559
+ chain: input.chain || null,
20560
+ intent: input.intent || null,
20561
+ nextAction: input.nextAction || null,
20562
+ paymasterMode: input.paymasterMode || null,
20563
+ tokenizedIntent: input.intent ? workflowIntentSupportsTokenDiscovery3(input.intent) : false,
20564
+ includesAssetDiscovery: Boolean(input.recommendedCommands.discoverAssets),
20565
+ includesOwnedTokenDiscovery: Boolean(input.recommendedCommands.discoverOwnedTokens),
20566
+ includesChainTokenDiscovery: Boolean(input.recommendedCommands.discoverTokens),
20567
+ includesDirectTokenInspection: Boolean(input.recommendedCommands.inspectToken),
20568
+ includesPaymasterTokenDiscovery: Boolean(
20569
+ input.recommendedCommands.discoverPaymasterTokens
20570
+ ),
20571
+ includesPaymasterTokenInspection: Boolean(
20572
+ input.recommendedCommands.inspectPaymasterToken
20573
+ )
20574
+ };
20575
+ }
20576
+ function buildWorkflowTokenInputErrorSummary(input) {
20577
+ return {
20578
+ chain: input.chain || null,
20579
+ queryType: input.tokenAddress ? "address" : input.symbol ? "symbol" : null,
20580
+ query: input.tokenAddress || input.symbol || null,
20581
+ roleFilter: input.role || null,
20582
+ includesChainTokenDiscovery: Boolean(input.recommendedCommands.discoverTokens),
20583
+ includesDirectTokenInspection: Boolean(input.recommendedCommands.inspectToken),
20584
+ workflowHelp: input.recommendedCommands.workflowHelp
20585
+ };
20586
+ }
19122
20587
  function buildWorkflowPlanRecommendedCommands(plan) {
19123
20588
  return {
19124
20589
  inspectDefaults: "zk-agent defaults",
19125
20590
  next: plan.recommendedCommand,
19126
20591
  goal: plan.goalCommand,
19127
20592
  workflowHelp: "zk-agent workflow --help",
19128
- ...workflowIntentSupportsTokenDiscovery2(plan.intent) ? {
20593
+ ...workflowIntentSupportsTokenDiscovery3(plan.intent) ? {
19129
20594
  discoverAssets: buildAssetsRecommendedCommand(plan.walletName),
19130
20595
  discoverOwnedTokens: buildOwnedTokensRecommendedCommand(plan.walletName),
19131
20596
  discoverTokens: buildTokensRecommendedCommand(plan.chain),
@@ -19169,6 +20634,13 @@ function buildWorkflowTokenErrorRecommendedCommands(error) {
19169
20634
  }
19170
20635
  function printWorkflowTokenInputError(error) {
19171
20636
  const recommendedCommands = buildWorkflowTokenErrorRecommendedCommands(error);
20637
+ const tokenDiscoverySummary = buildWorkflowTokenInputErrorSummary({
20638
+ chain: typeof error.details?.chain === "string" ? error.details.chain : void 0,
20639
+ symbol: typeof error.details?.symbol === "string" ? error.details.symbol : void 0,
20640
+ tokenAddress: typeof error.details?.tokenAddress === "string" ? error.details.tokenAddress : void 0,
20641
+ role: typeof error.details?.role === "string" ? error.details.role : void 0,
20642
+ recommendedCommands
20643
+ });
19172
20644
  const lines = [["error", error.message], ["code", error.code]];
19173
20645
  if (typeof error.details?.suggestedAction === "string" && error.details.suggestedAction.length > 0) {
19174
20646
  lines.push(["suggested action", error.details.suggestedAction]);
@@ -19176,6 +20648,7 @@ function printWorkflowTokenInputError(error) {
19176
20648
  lines.push(...workflowFollowupLines(recommendedCommands));
19177
20649
  printResult(lines, {
19178
20650
  ...formatErrorPayload(error),
20651
+ tokenDiscoverySummary,
19179
20652
  recommendedCommands
19180
20653
  });
19181
20654
  process.exitCode = 1;
@@ -19197,6 +20670,7 @@ function serializeWalletApproval(walletApproval) {
19197
20670
  if (!walletApproval) return void 0;
19198
20671
  return {
19199
20672
  ...walletApproval,
20673
+ summary: buildWorkflowWalletApprovalSummary(walletApproval),
19200
20674
  ...workflowWalletApprovalRelayAliases(walletApproval.relay, {
19201
20675
  shareLinkBaseField: "relayShareLinkBaseUrl",
19202
20676
  statusApiBaseField: "relayStatusApiBaseUrl"
@@ -19206,6 +20680,34 @@ function serializeWalletApproval(walletApproval) {
19206
20680
  wallet: walletApproval.wallet ? sanitizeWalletRecord(walletApproval.wallet) : void 0
19207
20681
  };
19208
20682
  }
20683
+ function buildWorkflowWalletApprovalSummary(walletApproval) {
20684
+ if (!walletApproval) return void 0;
20685
+ let status = "await-local";
20686
+ if (walletApproval.stage === "approved") {
20687
+ status = "approved";
20688
+ } else if (walletApproval.recommendedCommands?.relayStatus && walletApproval.nextCommand === walletApproval.recommendedCommands.relayStatus) {
20689
+ status = "relay-pending";
20690
+ }
20691
+ return {
20692
+ status,
20693
+ walletRequestId: walletApproval.request.requestId,
20694
+ reusedRequest: walletApproval.reusedRequest,
20695
+ relayPublished: Boolean(walletApproval.relay),
20696
+ nextAction: walletApproval.nextCommand,
20697
+ afterApproval: walletApproval.recommendedCommands?.afterApproval || null,
20698
+ afterApprovalStatus: walletApproval.recommendedCommands?.afterApprovalStatus || null
20699
+ };
20700
+ }
20701
+ function serializeWorkflowWalletApprovalOutput(walletApproval) {
20702
+ return {
20703
+ walletRequestId: walletApproval?.request.requestId,
20704
+ walletApprovalRelay: walletApproval?.relay,
20705
+ ...workflowWalletApprovalRelayAliases(walletApproval?.relay),
20706
+ walletApprovalRecommendedCommands: walletApproval?.recommendedCommands,
20707
+ walletApprovalSummary: buildWorkflowWalletApprovalSummary(walletApproval),
20708
+ walletApproval: serializeWalletApproval(walletApproval)
20709
+ };
20710
+ }
19209
20711
  function workflowWalletApprovalRelayAliases(relay, fieldNames = {
19210
20712
  shareLinkBaseField: "walletApprovalRelayShareLinkBaseUrl",
19211
20713
  statusApiBaseField: "walletApprovalRelayStatusApiBaseUrl"
@@ -19557,7 +21059,7 @@ function applyWorkflowHelpCommandOrder(workflow) {
19557
21059
  }
19558
21060
  function createWorkflowCommand(deps) {
19559
21061
  const resolvedDeps = resolveWorkflowCommandDeps(deps);
19560
- const workflow = new Command10("workflow").description(
21062
+ const workflow = new Command11("workflow").description(
19561
21063
  "Plan, persist, and execute higher-level wallet workflows"
19562
21064
  );
19563
21065
  workflow.addHelpText("after", buildWorkflowHelpText());
@@ -19583,11 +21085,26 @@ function createWorkflowCommand(deps) {
19583
21085
  ...plan,
19584
21086
  paymasterMode: paymasterInput?.mode
19585
21087
  });
21088
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
21089
+ walletName: plan.walletName,
21090
+ chain: plan.chain,
21091
+ intent: plan.intent,
21092
+ paymasterMode: paymasterInput?.mode,
21093
+ nextAction: plan.recommendedCommand,
21094
+ recommendedCommands
21095
+ });
19586
21096
  const agentProfile = await loadWorkflowAgentProfile(plan.walletName);
19587
21097
  const agentFollowup = buildAgentFollowup(agentProfile, {
19588
21098
  walletName: plan.walletName,
19589
21099
  walletExists: true
19590
21100
  });
21101
+ const workflowEntrySummary = buildWorkflowEntrySummary({
21102
+ command: "plan",
21103
+ source: "input",
21104
+ checkpointPersisted: false,
21105
+ plan,
21106
+ nextCommand: plan.recommendedCommand
21107
+ });
19591
21108
  printResult(
19592
21109
  withAgentProfileLines(
19593
21110
  [...workflowPlanLines(plan), ...workflowFollowupLines(recommendedCommands)],
@@ -19596,10 +21113,12 @@ function createWorkflowCommand(deps) {
19596
21113
  ),
19597
21114
  {
19598
21115
  ok: true,
21116
+ workflowEntrySummary,
19599
21117
  agentProfile,
19600
21118
  agentFollowup,
19601
21119
  inspection,
19602
21120
  plan,
21121
+ tokenDiscoverySummary,
19603
21122
  recommendedCommands
19604
21123
  }
19605
21124
  );
@@ -19736,6 +21255,14 @@ function createWorkflowCommand(deps) {
19736
21255
  {
19737
21256
  ok: true,
19738
21257
  ...serializeWorkflowRequestMeta(started.requestId),
21258
+ workflowEntrySummary: buildWorkflowEntrySummary({
21259
+ command: "start",
21260
+ source: "input",
21261
+ requestId: started.requestId,
21262
+ checkpointPersisted: true,
21263
+ status: started.status,
21264
+ nextCommand: started.status.recommendedCommand
21265
+ }),
19739
21266
  agentProfile,
19740
21267
  agentFollowup,
19741
21268
  checkpoint: started.checkpoint,
@@ -19755,7 +21282,7 @@ function createWorkflowCommand(deps) {
19755
21282
  includeLocalApproval: true
19756
21283
  }).action(withWorkflowInputErrorHandling(async (options) => {
19757
21284
  const execution = await executeWorkflowAutoCommand(options, resolvedDeps);
19758
- await printWorkflowAutoCommandResult(execution);
21285
+ await printWorkflowAutoCommandResult(execution, "auto");
19759
21286
  }));
19760
21287
  const pay = workflow.command("pay").description(
19761
21288
  "Guided flagship AA native-send path with checkpoint persistence, intent-scoped session recovery, and paymaster-aware defaults"
@@ -19772,7 +21299,7 @@ function createWorkflowCommand(deps) {
19772
21299
  applyWorkflowPayDefaults(options),
19773
21300
  resolvedDeps
19774
21301
  );
19775
- await printWorkflowAutoCommandResult(execution);
21302
+ await printWorkflowAutoCommandResult(execution, "pay");
19776
21303
  }));
19777
21304
  const run = workflow.command("run").description("Run the requested workflow, or stop on the next required prerequisite or funding step first").option(
19778
21305
  "--intent <intent>",
@@ -19784,7 +21311,7 @@ function createWorkflowCommand(deps) {
19784
21311
  includeLocalApproval: true
19785
21312
  }).action(withWorkflowInputErrorHandling(async (options) => {
19786
21313
  const execution = await executeWorkflowRunCommand(options, resolvedDeps);
19787
- await printWorkflowRunCommandResult(execution);
21314
+ await printWorkflowRunCommandResult(execution, "run");
19788
21315
  }));
19789
21316
  const status = workflow.command("status").description("Inspect whether a workflow is blocked, still waiting on funding, or ready to resume").option(
19790
21317
  "--intent <intent>",
@@ -19803,11 +21330,32 @@ function createWorkflowCommand(deps) {
19803
21330
  intent: inspection.result.intent,
19804
21331
  paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal)
19805
21332
  });
21333
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
21334
+ walletName: inspection.result.walletName,
21335
+ chain: inspection.result.plan.chain,
21336
+ intent: inspection.result.intent,
21337
+ nextAction: inspection.result.recommendedCommand,
21338
+ paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal),
21339
+ recommendedCommands
21340
+ });
19806
21341
  const agentProfile = await loadWorkflowAgentProfile(inspection.result.walletName);
19807
21342
  const agentFollowup = buildAgentFollowup(agentProfile, {
19808
21343
  walletName: inspection.result.walletName,
19809
21344
  walletExists: true
19810
21345
  });
21346
+ const summary = buildWorkflowRuntimeSummary({
21347
+ status: inspection.result,
21348
+ nextCommand: inspection.result.recommendedCommand
21349
+ });
21350
+ const workflowEntrySummary = buildWorkflowEntrySummary({
21351
+ command: "status",
21352
+ source: options.requestId?.trim() ? "checkpoint" : "input",
21353
+ requestId: inspection.requestId,
21354
+ checkpointPersisted: Boolean(inspection.checkpoint),
21355
+ status: inspection.result,
21356
+ walletApproval: inspection.walletApproval,
21357
+ nextCommand: inspection.result.recommendedCommand
21358
+ });
19811
21359
  printResult(
19812
21360
  prependWorkflowRequestId(
19813
21361
  inspection.requestId,
@@ -19824,15 +21372,14 @@ function createWorkflowCommand(deps) {
19824
21372
  {
19825
21373
  ok: true,
19826
21374
  ...serializeWorkflowRequestMeta(inspection.requestId),
21375
+ workflowEntrySummary,
19827
21376
  agentProfile,
19828
21377
  agentFollowup,
21378
+ summary,
19829
21379
  result: inspection.result,
19830
21380
  checkpoint: inspection.checkpoint,
19831
- walletRequestId: inspection.walletApproval?.request.requestId,
19832
- walletApprovalRelay: inspection.walletApproval?.relay,
19833
- ...workflowWalletApprovalRelayAliases(inspection.walletApproval?.relay),
19834
- walletApprovalRecommendedCommands: inspection.walletApproval?.recommendedCommands,
19835
- walletApproval: serializeWalletApproval(inspection.walletApproval),
21381
+ ...serializeWorkflowWalletApprovalOutput(inspection.walletApproval),
21382
+ tokenDiscoverySummary,
19836
21383
  recommendedCommands
19837
21384
  }
19838
21385
  );
@@ -19855,11 +21402,32 @@ function createWorkflowCommand(deps) {
19855
21402
  intent: inspection.result.intent,
19856
21403
  paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal)
19857
21404
  });
21405
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
21406
+ walletName: inspection.result.walletName,
21407
+ chain: inspection.result.plan.chain,
21408
+ intent: inspection.result.intent,
21409
+ nextAction: nextCommand,
21410
+ paymasterMode: inspection.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(inspection.checkpoint?.goal),
21411
+ recommendedCommands
21412
+ });
19858
21413
  const agentProfile = await loadWorkflowAgentProfile(inspection.result.walletName);
19859
21414
  const agentFollowup = buildAgentFollowup(agentProfile, {
19860
21415
  walletName: inspection.result.walletName,
19861
21416
  walletExists: true
19862
21417
  });
21418
+ const summary = buildWorkflowRuntimeSummary({
21419
+ status: inspection.result,
21420
+ nextCommand
21421
+ });
21422
+ const workflowEntrySummary = buildWorkflowEntrySummary({
21423
+ command: "next",
21424
+ source: options.requestId?.trim() ? "checkpoint" : "input",
21425
+ requestId: inspection.requestId,
21426
+ checkpointPersisted: Boolean(inspection.checkpoint),
21427
+ status: inspection.result,
21428
+ walletApproval: inspection.walletApproval,
21429
+ nextCommand
21430
+ });
19863
21431
  printResult(
19864
21432
  prependWorkflowRequestId(
19865
21433
  inspection.requestId,
@@ -19876,28 +21444,14 @@ function createWorkflowCommand(deps) {
19876
21444
  {
19877
21445
  ok: true,
19878
21446
  ...serializeWorkflowRequestMeta(inspection.requestId),
21447
+ workflowEntrySummary,
19879
21448
  agentProfile,
19880
21449
  agentFollowup,
19881
- summary: {
19882
- status: inspection.result.status,
19883
- readyForGoal: inspection.result.readyForGoal,
19884
- nextCommand,
19885
- blockingActionIds: inspection.result.blockingActionIds,
19886
- fundingProgress: inspection.result.fundingProgress ? {
19887
- kind: inspection.result.fundingProgress.kind,
19888
- txHash: inspection.result.fundingProgress.txHash,
19889
- status: inspection.result.fundingProgress.status,
19890
- terminal: inspection.result.fundingProgress.terminal,
19891
- finalized: inspection.result.fundingProgress.finalized
19892
- } : void 0
19893
- },
21450
+ summary,
19894
21451
  result: inspection.result,
19895
21452
  checkpoint: inspection.checkpoint,
19896
- walletRequestId: inspection.walletApproval?.request.requestId,
19897
- walletApprovalRelay: inspection.walletApproval?.relay,
19898
- ...workflowWalletApprovalRelayAliases(inspection.walletApproval?.relay),
19899
- walletApprovalRecommendedCommands: inspection.walletApproval?.recommendedCommands,
19900
- walletApproval: serializeWalletApproval(inspection.walletApproval),
21453
+ ...serializeWorkflowWalletApprovalOutput(inspection.walletApproval),
21454
+ tokenDiscoverySummary,
19901
21455
  recommendedCommands
19902
21456
  }
19903
21457
  );
@@ -19921,11 +21475,32 @@ function createWorkflowCommand(deps) {
19921
21475
  intent: inspection.result.intent,
19922
21476
  paymasterMode: inspection.walletApproval.request.requestedPaymasterMode
19923
21477
  });
21478
+ const tokenDiscoverySummary2 = buildWorkflowTokenDiscoverySummary({
21479
+ walletName: inspection.result.walletName,
21480
+ chain: inspection.result.plan.chain,
21481
+ intent: inspection.result.intent,
21482
+ nextAction: inspection.result.recommendedCommand,
21483
+ paymasterMode: inspection.walletApproval.request.requestedPaymasterMode,
21484
+ recommendedCommands: recommendedCommands2
21485
+ });
19924
21486
  const agentProfile2 = await loadWorkflowAgentProfile(inspection.result.walletName);
19925
21487
  const agentFollowup2 = buildAgentFollowup(agentProfile2, {
19926
21488
  walletName: inspection.result.walletName,
19927
21489
  walletExists: true
19928
21490
  });
21491
+ const summary2 = buildWorkflowRuntimeSummary({
21492
+ status: inspection.result,
21493
+ nextCommand: inspection.result.recommendedCommand
21494
+ });
21495
+ const workflowEntrySummary2 = buildWorkflowEntrySummary({
21496
+ command: "resume",
21497
+ source: options.requestId?.trim() ? "checkpoint" : "input",
21498
+ requestId: inspection.requestId,
21499
+ checkpointPersisted: Boolean(inspection.checkpoint),
21500
+ status: inspection.result,
21501
+ walletApproval: inspection.walletApproval,
21502
+ nextCommand: inspection.result.recommendedCommand
21503
+ });
19929
21504
  printResult(
19930
21505
  prependWorkflowRequestId(
19931
21506
  inspection.requestId,
@@ -19942,15 +21517,14 @@ function createWorkflowCommand(deps) {
19942
21517
  {
19943
21518
  ok: true,
19944
21519
  ...serializeWorkflowRequestMeta(inspection.requestId),
21520
+ workflowEntrySummary: workflowEntrySummary2,
19945
21521
  agentProfile: agentProfile2,
19946
21522
  agentFollowup: agentFollowup2,
21523
+ summary: summary2,
19947
21524
  status: inspection.result,
19948
21525
  checkpoint: inspection.checkpoint,
19949
- walletRequestId: inspection.walletApproval.request.requestId,
19950
- walletApprovalRelay: inspection.walletApproval.relay,
19951
- ...workflowWalletApprovalRelayAliases(inspection.walletApproval.relay),
19952
- walletApprovalRecommendedCommands: inspection.walletApproval.recommendedCommands,
19953
- walletApproval: serializeWalletApproval(inspection.walletApproval),
21526
+ ...serializeWorkflowWalletApprovalOutput(inspection.walletApproval),
21527
+ tokenDiscoverySummary: tokenDiscoverySummary2,
19954
21528
  recommendedCommands: recommendedCommands2
19955
21529
  }
19956
21530
  );
@@ -19965,25 +21539,50 @@ function createWorkflowCommand(deps) {
19965
21539
  resolvedDeps
19966
21540
  );
19967
21541
  if (!execution.result) {
21542
+ const status2 = execution.status;
21543
+ if (!status2) {
21544
+ throw new Error("Workflow resume result is missing both execution result and status.");
21545
+ }
19968
21546
  const recommendedCommands2 = buildWorkflowRuntimeRecommendedCommands({
19969
21547
  requestId: execution.requestId,
19970
- walletName: execution.status.walletName,
19971
- nextAction: execution.status.recommendedCommand,
19972
- chain: execution.status.plan.chain,
19973
- intent: execution.status.intent,
21548
+ walletName: status2.walletName,
21549
+ nextAction: status2.recommendedCommand,
21550
+ chain: status2.plan.chain,
21551
+ intent: status2.intent,
19974
21552
  paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal)
19975
21553
  });
19976
- const agentProfile2 = await loadWorkflowAgentProfile(execution.status.walletName);
21554
+ const tokenDiscoverySummary2 = buildWorkflowTokenDiscoverySummary({
21555
+ walletName: status2.walletName,
21556
+ chain: status2.plan.chain,
21557
+ intent: status2.intent,
21558
+ nextAction: status2.recommendedCommand,
21559
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.checkpoint?.goal),
21560
+ recommendedCommands: recommendedCommands2
21561
+ });
21562
+ const agentProfile2 = await loadWorkflowAgentProfile(status2.walletName);
19977
21563
  const agentFollowup2 = buildAgentFollowup(agentProfile2, {
19978
- walletName: execution.status.walletName,
21564
+ walletName: status2.walletName,
19979
21565
  walletExists: true
19980
21566
  });
21567
+ const summary2 = buildWorkflowRuntimeSummary({
21568
+ status: status2,
21569
+ nextCommand: status2.recommendedCommand
21570
+ });
21571
+ const workflowEntrySummary2 = buildWorkflowEntrySummary({
21572
+ command: "resume",
21573
+ source: options.requestId?.trim() ? "checkpoint" : "input",
21574
+ requestId: execution.requestId,
21575
+ checkpointPersisted: Boolean(execution.checkpoint || execution.requestId),
21576
+ status: status2,
21577
+ walletApproval: execution.walletApproval,
21578
+ nextCommand: status2.recommendedCommand
21579
+ });
19981
21580
  printResult(
19982
21581
  prependWorkflowRequestId(
19983
21582
  execution.requestId,
19984
21583
  withAgentProfileLines(
19985
21584
  [
19986
- ...workflowStatusLines(execution.status),
21585
+ ...workflowStatusLines(status2),
19987
21586
  ...workflowWalletApprovalLines(execution.walletApproval),
19988
21587
  ...workflowFollowupLines(recommendedCommands2)
19989
21588
  ],
@@ -19994,15 +21593,14 @@ function createWorkflowCommand(deps) {
19994
21593
  {
19995
21594
  ok: true,
19996
21595
  ...serializeWorkflowRequestMeta(execution.requestId),
21596
+ workflowEntrySummary: workflowEntrySummary2,
19997
21597
  agentProfile: agentProfile2,
19998
21598
  agentFollowup: agentFollowup2,
19999
- status: execution.status,
21599
+ summary: summary2,
21600
+ status: status2,
20000
21601
  checkpoint: execution.checkpoint,
20001
- walletRequestId: execution.walletApproval?.request.requestId,
20002
- walletApprovalRelay: execution.walletApproval?.relay,
20003
- ...workflowWalletApprovalRelayAliases(execution.walletApproval?.relay),
20004
- walletApprovalRecommendedCommands: execution.walletApproval?.recommendedCommands,
20005
- walletApproval: serializeWalletApproval(execution.walletApproval),
21602
+ ...serializeWorkflowWalletApprovalOutput(execution.walletApproval),
21603
+ tokenDiscoverySummary: tokenDiscoverySummary2,
20006
21604
  recommendedCommands: recommendedCommands2
20007
21605
  }
20008
21606
  );
@@ -20016,11 +21614,34 @@ function createWorkflowCommand(deps) {
20016
21614
  intent: execution.result.intent,
20017
21615
  paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal)
20018
21616
  });
21617
+ const tokenDiscoverySummary = buildWorkflowTokenDiscoverySummary({
21618
+ walletName: execution.result.walletName,
21619
+ chain: execution.result.plan.chain,
21620
+ intent: execution.result.intent,
21621
+ nextAction: execution.result.nextCommand,
21622
+ paymasterMode: execution.walletApproval?.request.requestedPaymasterMode ?? extractWorkflowGoalPaymasterMode(execution.goal),
21623
+ recommendedCommands
21624
+ });
20019
21625
  const agentProfile = await loadWorkflowAgentProfile(execution.result.walletName);
20020
21626
  const agentFollowup = buildAgentFollowup(agentProfile, {
20021
21627
  walletName: execution.result.walletName,
20022
21628
  walletExists: true
20023
21629
  });
21630
+ const summary = buildWorkflowRuntimeSummary({
21631
+ status: inspection.result,
21632
+ result: execution.result,
21633
+ nextCommand: execution.result.nextCommand ?? inspection.result.recommendedCommand
21634
+ });
21635
+ const workflowEntrySummary = buildWorkflowEntrySummary({
21636
+ command: "resume",
21637
+ source: options.requestId?.trim() ? "checkpoint" : "input",
21638
+ requestId: execution.requestId,
21639
+ checkpointPersisted: Boolean(execution.checkpoint || execution.requestId),
21640
+ status: inspection.result,
21641
+ result: execution.result,
21642
+ walletApproval: inspection.walletApproval,
21643
+ nextCommand: execution.result.nextCommand ?? inspection.result.recommendedCommand
21644
+ });
20024
21645
  printResult(
20025
21646
  prependWorkflowRequestId(
20026
21647
  execution.requestId,
@@ -20037,15 +21658,14 @@ function createWorkflowCommand(deps) {
20037
21658
  {
20038
21659
  ok: true,
20039
21660
  ...serializeWorkflowRequestMeta(execution.requestId),
21661
+ workflowEntrySummary,
20040
21662
  agentProfile,
20041
21663
  agentFollowup,
21664
+ summary,
20042
21665
  status: inspection.result,
20043
21666
  result: execution.result,
20044
- walletRequestId: inspection.walletApproval?.request.requestId,
20045
- walletApprovalRelay: inspection.walletApproval?.relay,
20046
- ...workflowWalletApprovalRelayAliases(inspection.walletApproval?.relay),
20047
- walletApprovalRecommendedCommands: inspection.walletApproval?.recommendedCommands,
20048
- walletApproval: serializeWalletApproval(inspection.walletApproval),
21667
+ ...serializeWorkflowWalletApprovalOutput(inspection.walletApproval),
21668
+ tokenDiscoverySummary,
20049
21669
  recommendedCommands
20050
21670
  }
20051
21671
  );
@@ -20064,7 +21684,7 @@ function createWorkflowCommand(deps) {
20064
21684
  },
20065
21685
  resolvedDeps
20066
21686
  );
20067
- await printWorkflowRunCommandResult(execution);
21687
+ await printWorkflowRunCommandResult(execution, intent);
20068
21688
  }));
20069
21689
  }
20070
21690
  workflow.addCommand(
@@ -20093,6 +21713,13 @@ function buildDefaultOperatorPathHelpText() {
20093
21713
  " zk-agent next",
20094
21714
  ` ${buildWorkflowPayRecommendedCommand("main")}`,
20095
21715
  "",
21716
+ "Validated first-run baseline:",
21717
+ " setup defaults to zksync-sepolia and the local connector at http://localhost:4444",
21718
+ " Override those only when you intentionally target a different chain or connector deployment.",
21719
+ "",
21720
+ "If local setup or wallet state is unclear:",
21721
+ " zk-agent doctor",
21722
+ "",
20096
21723
  "No custom .env is required for setup, next, or wallet create/reapprove request generation.",
20097
21724
  "Add RPC env vars later, before live reads or broadcasts.",
20098
21725
  "",
@@ -20103,6 +21730,7 @@ function buildDefaultOperatorPathHelpText() {
20103
21730
  }
20104
21731
  var ROOT_HELP_COMMAND_ORDER = [
20105
21732
  "next",
21733
+ "doctor",
20106
21734
  "init",
20107
21735
  "wallet",
20108
21736
  "workflow",
@@ -20139,13 +21767,14 @@ function applyRootHelpCommandOrder(program) {
20139
21767
  program.commands = sortedCommands;
20140
21768
  }
20141
21769
  function createProgram() {
20142
- const program = new Command11().name("zk-agent").description(
21770
+ const program = new Command12().name("zk-agent").description(
20143
21771
  "Local-first zkSync Era CLI for wallet approval, workflow execution, and hosted relay recovery"
20144
21772
  ).showHelpAfterError().option("--json", "Force JSON output for agent harnesses", false).hook("preAction", (thisCommand) => {
20145
21773
  if (thisCommand.optsWithGlobals().json) process.env.ZK_AGENT_OUTPUT = "json";
20146
21774
  });
20147
21775
  program.addCommand(createInitCommand());
20148
21776
  program.addCommand(createNextCommand());
21777
+ program.addCommand(createDoctorCommand());
20149
21778
  program.addCommand(createAgentCommand());
20150
21779
  program.addCommand(createDefaultsCommand());
20151
21780
  program.addCommand(createTokensCommand());