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