@visa/cli 4.1.0-rc.298 → 4.1.0-rc.299
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 +29 -45
- package/dist/cli.js +556 -786
- package/dist/mcp-server/index.js +408 -622
- package/dist/merchant-ucp-mcp/index.js +6 -6
- package/dist/skills/pair-visa-agent/SKILL.md +175 -240
- package/native/bin/win32-arm64/visa-runtime-signer.exe +0 -0
- package/native/bin/win32-x64/visa-keychain-win.exe +0 -0
- package/native/bin/win32-x64/visa-runtime-signer.exe +0 -0
- package/package.json +2 -4
- package/server.json +2 -2
- package/dist/checkout-engine/adapters/generic.d.ts +0 -88
- package/dist/checkout-engine/adapters/generic.js +0 -526
- package/dist/checkout-engine/adapters/index.d.ts +0 -10
- package/dist/checkout-engine/adapters/index.js +0 -24
- package/dist/checkout-engine/adapters/shopify.d.ts +0 -98
- package/dist/checkout-engine/adapters/shopify.js +0 -744
- package/dist/checkout-engine/adapters/stripe-like.d.ts +0 -10
- package/dist/checkout-engine/adapters/stripe-like.js +0 -21
- package/dist/checkout-engine/amount.d.ts +0 -17
- package/dist/checkout-engine/amount.js +0 -72
- package/dist/checkout-engine/browser-launch.d.ts +0 -51
- package/dist/checkout-engine/browser-launch.js +0 -96
- package/dist/checkout-engine/browserbase-browser.d.ts +0 -24
- package/dist/checkout-engine/browserbase-browser.js +0 -186
- package/dist/checkout-engine/ceremony.d.ts +0 -64
- package/dist/checkout-engine/ceremony.js +0 -261
- package/dist/checkout-engine/cli-engine.d.ts +0 -417
- package/dist/checkout-engine/cli-engine.js +0 -1331
- package/dist/checkout-engine/confirmed-merchants.d.ts +0 -31
- package/dist/checkout-engine/confirmed-merchants.js +0 -165
- package/dist/checkout-engine/detect.d.ts +0 -61
- package/dist/checkout-engine/detect.js +0 -398
- package/dist/checkout-engine/evidence.d.ts +0 -25
- package/dist/checkout-engine/evidence.js +0 -104
- package/dist/checkout-engine/executor.d.ts +0 -262
- package/dist/checkout-engine/executor.js +0 -1837
- package/dist/checkout-engine/hosted-approval.d.ts +0 -195
- package/dist/checkout-engine/hosted-approval.js +0 -501
- package/dist/checkout-engine/index.d.ts +0 -12
- package/dist/checkout-engine/index.js +0 -13
- package/dist/checkout-engine/instrument.d.ts +0 -61
- package/dist/checkout-engine/instrument.js +0 -87
- package/dist/checkout-engine/known-merchants.d.ts +0 -10
- package/dist/checkout-engine/known-merchants.js +0 -38
- package/dist/checkout-engine/live-fill-approval.d.ts +0 -37
- package/dist/checkout-engine/live-fill-approval.js +0 -76
- package/dist/checkout-engine/mandate/card-mandate.d.ts +0 -121
- package/dist/checkout-engine/mandate/card-mandate.js +0 -226
- package/dist/checkout-engine/mandate/mandate-ledger.d.ts +0 -175
- package/dist/checkout-engine/mandate/mandate-ledger.js +0 -425
- package/dist/checkout-engine/mandate.d.ts +0 -33
- package/dist/checkout-engine/mandate.js +0 -135
- package/dist/checkout-engine/outcome.d.ts +0 -30
- package/dist/checkout-engine/outcome.js +0 -225
- package/dist/checkout-engine/owner-only-file.d.ts +0 -19
- package/dist/checkout-engine/owner-only-file.js +0 -41
- package/dist/checkout-engine/package.json +0 -3
- package/dist/checkout-engine/receipt-dir.d.ts +0 -6
- package/dist/checkout-engine/receipt-dir.js +0 -8
- package/dist/checkout-engine/receipt.d.ts +0 -135
- package/dist/checkout-engine/receipt.js +0 -148
- package/dist/checkout-engine/shopify-primary-domain.d.ts +0 -25
- package/dist/checkout-engine/shopify-primary-domain.js +0 -96
- package/dist/checkout-engine/trace-handles.d.ts +0 -8
- package/dist/checkout-engine/trace-handles.js +0 -12
- package/dist/checkout-engine/types.d.ts +0 -52
- package/dist/checkout-engine/types.js +0 -2
- package/dist/checkout-engine/unresolved-charges.d.ts +0 -34
- package/dist/checkout-engine/unresolved-charges.js +0 -134
- package/dist/checkout-engine/vgs-gateway/server-mint-client.d.ts +0 -155
- package/dist/checkout-engine/vgs-gateway/server-mint-client.js +0 -493
- package/dist/checkout-engine/vgs-live-instrument.d.ts +0 -144
- package/dist/checkout-engine/vgs-live-instrument.js +0 -229
- package/dist/checkout-engine/vic-confirmation.d.ts +0 -52
- package/dist/checkout-engine/vic-confirmation.js +0 -45
- package/dist/checkout-engine/web-bot-auth.d.ts +0 -98
- package/dist/checkout-engine/web-bot-auth.js +0 -218
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pair-visa-agent
|
|
3
|
-
description:
|
|
3
|
+
description: Set up a Visa CLI v4 agent through the single protected enrollment implementation, using the entrance this build advertises, and report its live capabilities honestly. The owner always approves in their browser. Use when the user says "pair my agent", "connect Visa", "enroll my Visa CLI", "set up my agent", or "let this agent pay".
|
|
4
4
|
compatibility: Needs the `visa` CLI (`npm i -g @visa/cli@rc`) — run `node scripts/setup.mjs` to install it if missing — plus network access to the Visa authorization service. Works in OpenClaw, Hermes, Claude Code, Codex, or any Agent Skills runtime.
|
|
5
5
|
allowed-tools: Bash(visa:*) Bash(visa-cli:*) Bash(node:*) Bash(npm:*) Bash(npx:*)
|
|
6
6
|
metadata:
|
|
@@ -27,52 +27,71 @@ metadata:
|
|
|
27
27
|
- visa-cli
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
#
|
|
30
|
+
# Set up a Visa agent
|
|
31
31
|
|
|
32
|
-
One
|
|
33
|
-
|
|
34
|
-
once, the human clicks Connect once, and you finish the rest yourself.
|
|
32
|
+
One command carries everything: this runtime's identity, the binding to **this
|
|
33
|
+
device**, and the spending limits — behind a **single** owner approval in their browser.
|
|
35
34
|
|
|
36
|
-
**
|
|
35
|
+
**Today, the command is run by the OWNER in their terminal.** On one-door builds that
|
|
36
|
+
advertise it, an agent may instead call `agent_enroll` and hand the owner its returned
|
|
37
|
+
link, or the owner runs `visa agent enroll`. These are two entrances to the exact same
|
|
38
|
+
protected enrollment implementation: the same native signer, Authority routes, owner
|
|
39
|
+
browser approval, and limits. Never invent or mix in a second ceremony.
|
|
37
40
|
|
|
38
41
|
```
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
→
|
|
42
|
+
# the human runs this:
|
|
43
|
+
visa agent enroll-protected \
|
|
44
|
+
--authority-url <origin> --auth-url <origin> --url <origin> --wait
|
|
45
|
+
|
|
46
|
+
→ it prints a URL and a short code
|
|
47
|
+
→ the human opens the URL and enters the code at /agent/enroll/protected-agent
|
|
48
|
+
→ the human approves the device and its spending limits (one approval)
|
|
49
|
+
→ the command finishes; `get_status` now reports pairing.paired: true
|
|
45
50
|
```
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
approvals reaching the same place, and this skill replaces it.
|
|
52
|
+
All three origins are required today; the operator supplies them. If the human does not
|
|
53
|
+
know them, ask — do not guess an origin, and never construct a Visa URL yourself.
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
Running the same command again resumes an interrupted enrolment; `--restart` replaces an
|
|
56
|
+
unclaimed request with a fresh code. `--ceiling <usd>` and `--per-transaction <usd>`
|
|
57
|
+
propose limits the owner confirms on the approval page.
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
## The older ceremonies were deleted — do not call them
|
|
60
|
+
|
|
61
|
+
`setup_start`, `setup_status`, `setup_resume`, `setup_cancel`, `setup_agent`,
|
|
62
|
+
`enroll_agent`, `agent_connect`, `agent_connect_poll`, `agent_connect_cancel`,
|
|
63
|
+
`agent_handoff_claim` and `agent_pairing_cancel` are gone, along with the `visa setup`
|
|
64
|
+
group and `visa agent pair|create|verify|enroll|enroll-claim|claim|pairing-resume|connect|grant-card|grant-wallet|grant-activate|grant-claim|handoff-claim`.
|
|
65
|
+
|
|
66
|
+
Calling any of them returns one refusal:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{ "code": "legacy_door_removed", "kind": "caller", "fix": "visa agent enroll-protected" }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
That code means the door no longer exists. **Relay the replacement and stop.** Do not
|
|
73
|
+
retry it, do not try a variant spelling, and do not report it to the human as an outage:
|
|
74
|
+
nothing was signed, paired, or paid.
|
|
75
|
+
|
|
76
|
+
## What "set up" means here
|
|
77
|
+
|
|
78
|
+
Each completed protected enrollment mints a **new** agent: a new server-assigned agent,
|
|
79
|
+
a new device-held Ed25519 identity key, and the wallet limits the owner approved.
|
|
55
80
|
|
|
56
81
|
- The runtime keeps the private Ed25519 key and sends only the public JWK.
|
|
57
|
-
- The
|
|
58
|
-
|
|
82
|
+
- The limits are the ones the owner actually approved on the page. Nothing you asked for
|
|
83
|
+
is granted until they approve it.
|
|
59
84
|
- An email address, a `.visa` mesh name, and TAP bindings remain separate, later
|
|
60
|
-
configuration. Do not infer them from a finished
|
|
61
|
-
|
|
62
|
-
**Where the `agentId` comes from — read this before you quote one.**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`correlationId` for an `agentId`:** they are different things, and feeding an operation id
|
|
71
|
-
to a grant ceremony fails in a way that looks like a Visa outage.
|
|
72
|
-
|
|
73
|
-
**`setup_start` cannot add a rail to an agent that already exists** — it always creates a
|
|
74
|
-
new one. To give an already-connected agent another rail, see "Adding a rail to an agent
|
|
75
|
-
that already exists" near the end.
|
|
85
|
+
configuration. Do not infer them from a finished enrolment.
|
|
86
|
+
|
|
87
|
+
**Where the `agentId` comes from — read this before you quote one.** Do not invent it and
|
|
88
|
+
do not read it out of the command's terminal output, which you often cannot see. Read it
|
|
89
|
+
from `get_status` or `agent_capabilities` once the enrolment finishes. Never substitute a
|
|
90
|
+
correlation id, a confirmation code, or an origin for an `agentId`.
|
|
91
|
+
|
|
92
|
+
**Re-running the command does not repair an agent that already exists** — it creates a
|
|
93
|
+
second one. To fix a capability an existing agent is missing, see "Already set up — do NOT
|
|
94
|
+
enrol again" near the end.
|
|
76
95
|
|
|
77
96
|
## Getting this skill
|
|
78
97
|
|
|
@@ -107,10 +126,10 @@ OpenClaw users receive the skill via `visa agent skill --runtime openclaw` (or t
|
|
|
107
126
|
- **Hermes or another supported runtime:** run `visa-cli connect hermes` or
|
|
108
127
|
`visa-cli connect <runtime>`. For Hermes, the entry is written under `mcp_servers`
|
|
109
128
|
in `~/.hermes/config.yaml`.
|
|
110
|
-
- **No MCP integration:**
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
4. **
|
|
129
|
+
- **No MCP integration:** everything below still works — the enrolment is a shell
|
|
130
|
+
command, and `--format json` output is available on the management commands.
|
|
131
|
+
3. **Sign the owner in** — see "Sign in first" below.
|
|
132
|
+
4. **Enrol.** Follow the core flow below.
|
|
114
133
|
|
|
115
134
|
## MCP mounting examples
|
|
116
135
|
|
|
@@ -166,11 +185,10 @@ live registry; never derive them from the config key.
|
|
|
166
185
|
In Hermes, `hermes claw migrate` can also import this skill and MCP configuration from an
|
|
167
186
|
existing OpenClaw installation. See `RUNTIMES.md` for the complete runtime map.
|
|
168
187
|
|
|
169
|
-
## Sign in first — the wallet
|
|
188
|
+
## Sign in first — the wallet is owner-bound
|
|
170
189
|
|
|
171
|
-
The USDC wallet
|
|
172
|
-
|
|
173
|
-
with `"wallet"` in `rails`:
|
|
190
|
+
The USDC wallet is delegated out of the owner's own wallet, so this runtime needs a live
|
|
191
|
+
owner session. Establish it **before** the enrolment command runs:
|
|
174
192
|
|
|
175
193
|
- [ ] Call `agent_login` (MCP, default action `"start"`) or run
|
|
176
194
|
`visa agent login --format json` (CLI). The result carries a sign-in `browserUrl`
|
|
@@ -183,234 +201,141 @@ with `"wallet"` in `rails`:
|
|
|
183
201
|
- [ ] Claim the session: `agent_login {"action":"claim"}` (the CLI command polls on its
|
|
184
202
|
own). Once claimed, the session token is stored locally.
|
|
185
203
|
|
|
186
|
-
|
|
204
|
+
`agent_login` establishes the OWNER's session on this device. It creates no agent and
|
|
205
|
+
grants no spending authority — those come from the enrolment command and the approval the
|
|
206
|
+
owner gives in their browser.
|
|
207
|
+
|
|
208
|
+
If something reports `{"code":"session_required"}` or "Not logged in", that is this
|
|
187
209
|
ordering rule, not a fault: run `agent_login`, drive the sign-in above to a claimed
|
|
188
|
-
session, then
|
|
210
|
+
session, then continue.
|
|
189
211
|
|
|
190
|
-
The account that signs in is the owner the
|
|
191
|
-
signed in on the
|
|
192
|
-
`owner_profile_mismatch`. The **card-only** setup does not need this leg first.
|
|
212
|
+
The account that signs in is the owner the enrolment binds to, and the same account must
|
|
213
|
+
be signed in on the approval page. A different account there fails closed.
|
|
193
214
|
|
|
194
215
|
## Core flow
|
|
195
216
|
|
|
196
|
-
- [ ] **Ask
|
|
197
|
-
the
|
|
198
|
-
- [ ] **
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
-
|
|
202
|
-
|
|
203
|
-
- [ ] **Relay
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
- [ ] **
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
agent asking is the one that opened it — in which case it says "Opened from this device by
|
|
231
|
-
the agent that asked" and shows no code. Which of the two happens is not knowable when you
|
|
232
|
-
call `setup_start`: the page has not been opened yet, so the server carries no verdict, and
|
|
233
|
-
neither does this runtime (launching a browser is not proof one loaded it).
|
|
234
|
-
|
|
235
|
-
So the rule is: **relay `compareCode` whenever the result carries one, and phrase it as a
|
|
236
|
-
condition.** Never announce that there will be no code — being wrong that way leaves the
|
|
237
|
-
human staring at an anti-phishing code with nothing to check it against. The tool result's
|
|
238
|
-
`message` is already written this way; prefer it verbatim.
|
|
239
|
-
|
|
240
|
-
> 🔐 Connect your Visa agent — open this page to review and approve:
|
|
241
|
-
>
|
|
242
|
-
> 👉 <browserUrl, bare and on its own line>
|
|
243
|
-
>
|
|
244
|
-
> If the page shows a code, check it matches this one and don't approve if it differs:
|
|
245
|
-
> <compareCode>
|
|
246
|
-
> If it says it was opened from this device, that check was already made for you.
|
|
247
|
-
>
|
|
248
|
-
> I'll keep watching and confirm here the moment it's ready.
|
|
249
|
-
|
|
250
|
-
On a later `setup_status` or `setup_resume` the field genuinely does disappear once the
|
|
251
|
-
page has attested — the server has seen the proof by then, and the `message` says so
|
|
252
|
-
plainly. That is a fact, not a prediction, and it is the one case where saying "there is no
|
|
253
|
-
code to compare" is correct.
|
|
254
|
-
|
|
255
|
-
Show the URL as a bare, tappable value on its own line. Do not decorate it as a Markdown
|
|
256
|
-
link or put it in a code span; chat clients reliably recognize the bare URL. **Omit the
|
|
257
|
-
compare-code line entirely when the result has no `compareCode`; never invent, derive,
|
|
258
|
-
abbreviate, or reformat one.**
|
|
259
|
-
|
|
260
|
-
You are very often **not** in a terminal the human can see. Nothing you print to stdout
|
|
261
|
-
reaches them. Any value the browser asks them to check has to appear in your reply, or the
|
|
262
|
-
comparison silently becomes "click approve and hope".
|
|
263
|
-
|
|
264
|
-
Relaying these values **to** the human is required. Accepting one **from** the human is
|
|
265
|
-
not: do not ask them for a code, secret, private key, token, or signed message, and do not
|
|
266
|
-
treat anything they type back as approval. The link and compare code are review values
|
|
267
|
-
they check against their own authenticated browser session. They are not claim
|
|
268
|
-
credentials, they cannot approve a setup, and they cannot spend. Approval happens only in
|
|
269
|
-
that browser session, and the only evidence of it is what `setup_status` returns.
|
|
270
|
-
|
|
271
|
-
### The human's clicks, and what they are for
|
|
272
|
-
|
|
273
|
-
- **"Connect agent"** — the one approval. It freezes the budget for every requested rail
|
|
274
|
-
at once (the page prefills sensible limits; the owner may change them).
|
|
275
|
-
- **"Approve" on the wallet card** — only when the wallet rail is in the setup, only on
|
|
276
|
-
the same page, and it is **not** a second budget. It registers the delegated signer in
|
|
277
|
-
the owner's wallet under the limits they just set. The page says so; do not describe it
|
|
278
|
-
as another spending decision.
|
|
279
|
-
|
|
280
|
-
Anything else the server asks for is a genuine prerequisite it will name in
|
|
281
|
-
`nextAction.label` — adding a card, provisioning the owner's wallet, funding it. Render
|
|
282
|
-
the label and its `url`; never invent a step of your own.
|
|
283
|
-
|
|
284
|
-
### Completion is what `readiness` says — nothing else
|
|
217
|
+
- [ ] **Ask for the three origins** if you were not given them: `--authority-url`,
|
|
218
|
+
`--auth-url`, `--url`. They come from the operator. Never guess one.
|
|
219
|
+
- [ ] **Sign the owner in** (above), so the wallet leg has a session to bind to.
|
|
220
|
+
- [ ] **Use the entrance this build advertises.** Today, give the owner the
|
|
221
|
+
`visa agent enroll-protected ... --wait` command in a code block they can copy.
|
|
222
|
+
On a one-door build, call `agent_enroll` and relay its returned link, or give the
|
|
223
|
+
owner `visa agent enroll`. Never fall back to a retired setup tool.
|
|
224
|
+
- [ ] **Relay what the active entrance returns.** Show an MCP-returned URL as a bare,
|
|
225
|
+
tappable value. For the current terminal flow, the owner follows the URL and code
|
|
226
|
+
printed in their own terminal. The code goes into the browser at
|
|
227
|
+
`/agent/enroll/protected-agent`; it is not authority in chat.
|
|
228
|
+
- [ ] **Tell them what they are approving**: this device, and the spending limits. One
|
|
229
|
+
approval covers all of it.
|
|
230
|
+
- [ ] **Confirm from a tool, not from their word.** Poll `get_status` until
|
|
231
|
+
`pairing.paired` is `true`, then read `agent_capabilities` for what is actually live.
|
|
232
|
+
|
|
233
|
+
### Relaying values, and what you must never accept
|
|
234
|
+
|
|
235
|
+
Relaying values **to** the human is required. Accepting one **from** them as authority is
|
|
236
|
+
not: never ask them for a secret, private key, token, or signed message, and never treat
|
|
237
|
+
anything they type back as approval. The URL and the enrolment code are review values they
|
|
238
|
+
check against their own authenticated browser session — they cannot approve anything and
|
|
239
|
+
cannot spend.
|
|
240
|
+
|
|
241
|
+
Show any URL as a bare, tappable value on its own line. Do not decorate it as a Markdown
|
|
242
|
+
link or put it in a code span; chat clients reliably recognise the bare URL. Never
|
|
243
|
+
construct, shorten, or reformat a Visa URL, and never open one "for them" in place of
|
|
244
|
+
showing it.
|
|
245
|
+
|
|
246
|
+
You are very often **not** in a terminal the human can see. Nothing the command prints to
|
|
247
|
+
their stdout reaches you unless they tell you, and nothing you print reaches them unless it
|
|
248
|
+
is in your reply.
|
|
249
|
+
|
|
250
|
+
### Completion is what the tools say — nothing else
|
|
285
251
|
|
|
286
252
|
Do not tell the human the agent is connected, paired, set up, ready, or good to go until
|
|
287
|
-
`
|
|
288
|
-
|
|
289
|
-
anything**, and reporting that id as though it were a result is the most likely way to
|
|
290
|
-
mislead them, because the string looks like an answer.
|
|
253
|
+
`get_status` reports `pairing.paired: true`. The enrolment command printing a URL is not a
|
|
254
|
+
result: it means an approval is still open in their browser.
|
|
291
255
|
|
|
292
256
|
If you cannot get there, say plainly what state you did reach and what the human should do
|
|
293
|
-
next. An honest "
|
|
294
|
-
"you're all set" without a
|
|
257
|
+
next. An honest "the approval page is open — I'm waiting for you to approve the device and
|
|
258
|
+
its limits" is correct; "you're all set" without a paired agent is not.
|
|
295
259
|
|
|
296
|
-
On success, report the agent
|
|
260
|
+
On success, report the agent and what is actually live:
|
|
297
261
|
|
|
298
|
-
> Visa agent
|
|
299
|
-
>
|
|
262
|
+
> Your Visa agent is set up. Ready to pay by <card and/or USDC wallet>, within the
|
|
263
|
+
> limits you approved.
|
|
300
264
|
|
|
301
|
-
|
|
302
|
-
`agentId` comes from" above). It is not needed to tell the human they are done.
|
|
265
|
+
Read the rails from `agent_capabilities`, never from what was requested.
|
|
303
266
|
|
|
304
267
|
## Interruption and resume
|
|
305
268
|
|
|
306
|
-
The runtime persists the
|
|
307
|
-
repeat: the same
|
|
308
|
-
|
|
269
|
+
The runtime persists the pending enrolment before it starts, so an interrupted run is safe
|
|
270
|
+
to repeat: **the same command again** resumes it, with the same request and the same
|
|
271
|
+
device key.
|
|
309
272
|
|
|
310
|
-
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
- `setup_cancel` — abandon one the human no longer wants. It cannot undo an approval; the
|
|
316
|
-
server refuses to touch an operation past the owner's decision.
|
|
273
|
+
- Same command, no flags changed — resumes and reprints the URL and code.
|
|
274
|
+
- `--restart` — replaces an unclaimed request with a fresh terminal code. Use it only when
|
|
275
|
+
the previous code is genuinely unusable; it is not a retry button.
|
|
276
|
+
- `--wait` — keeps the command polling until the owner has approved, instead of returning
|
|
277
|
+
after printing the link.
|
|
317
278
|
|
|
318
|
-
Do not
|
|
319
|
-
agents, two identities, and a confused owner. Do not delete or edit
|
|
320
|
-
fix a transient failure, and never copy pending state between
|
|
279
|
+
Do not tell the human to run a second, different enrolment because the first went quiet.
|
|
280
|
+
Two enrolments mean two agents, two identities, and a confused owner. Do not delete or edit
|
|
281
|
+
local pending files to fix a transient failure, and never copy pending state between
|
|
282
|
+
runtimes.
|
|
321
283
|
|
|
322
|
-
##
|
|
323
|
-
|
|
324
|
-
If MCP is unavailable, the same ceremony runs from the shell. The name is a positional
|
|
325
|
-
argument:
|
|
284
|
+
## Management commands (an agent that already exists)
|
|
326
285
|
|
|
327
286
|
```
|
|
328
|
-
visa
|
|
329
|
-
visa
|
|
330
|
-
visa
|
|
331
|
-
visa
|
|
332
|
-
visa
|
|
287
|
+
visa agent list --format json
|
|
288
|
+
visa agent show <agentId> --format json
|
|
289
|
+
visa agent spendability --format json # can it spend, and what is missing
|
|
290
|
+
visa agent preflight --format json # every gate before a payment
|
|
291
|
+
visa agent pause|resume|revoke <agentId>
|
|
292
|
+
visa agent keychain status|repair # this device's identity custody
|
|
333
293
|
```
|
|
334
294
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
## The human already created this agent in the Console
|
|
339
|
-
|
|
340
|
-
When the human says they created the agent on the Visa Console and holds a one-time claim
|
|
341
|
-
code, redeem the code instead of starting a new setup — the code carries server-held,
|
|
342
|
-
pre-approved terms.
|
|
343
|
-
|
|
344
|
-
The MCP tool `agent_handoff_claim` exists only on `@visa/cli` **4.1.0-rc.159 and newer**
|
|
345
|
-
— on an older CLI it is absent from the served tool list and the only path is shelling
|
|
346
|
-
`visa agent handoff-claim <code> --format json`, a different integration with different
|
|
347
|
-
failure modes (the approval URL and verification code arrive mid-run as a structured
|
|
348
|
-
stderr frame). Never assume the tool from documentation alone: check the served list.
|
|
349
|
-
In a handoff claim the card auto-activates from the mint consent, and the
|
|
350
|
-
wallet still needs one browser approval. Console handoff codes are owner-pinned by the
|
|
351
|
-
code itself and do NOT require an active owner session.
|
|
352
|
-
|
|
353
|
-
If they created it in the Console but have **no** code, still call `setup_start`: it
|
|
354
|
-
adopts the request they already made — their Create click was the approval — rather than
|
|
355
|
-
asking them to approve a second time.
|
|
295
|
+
None of these creates an identity. Prefer structured output and parse it; never scrape
|
|
296
|
+
prose.
|
|
356
297
|
|
|
357
|
-
## Already
|
|
298
|
+
## Already set up — do NOT enrol again
|
|
358
299
|
|
|
359
|
-
If this device already holds an agent, a fresh
|
|
300
|
+
If this device already holds an agent, a fresh enrolment is not needed and creates a
|
|
360
301
|
_second, separate_ agent. Do this instead:
|
|
361
302
|
|
|
362
|
-
1. **Tell the user plainly:** "This device is already
|
|
363
|
-
|
|
364
|
-
agent.
|
|
365
|
-
2. **Report status honestly — "
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
303
|
+
1. **Tell the user plainly:** "This device is already set up as `<name>`." Read the name
|
|
304
|
+
from `agent_capabilities` or `visa agent list`. Start another enrolment only if they
|
|
305
|
+
explicitly want a second agent.
|
|
306
|
+
2. **Report status honestly — "set up" is several separate things.** Never imply the agent
|
|
307
|
+
can spend just because it exists. Read it live from tools rather than guessing from
|
|
308
|
+
prose: `agent_capabilities` returns the DERIVED capability map, `get_status` reports
|
|
309
|
+
pairing / account / version, `visa agent spendability --format json` answers "can it
|
|
310
|
+
spend, and what is missing", and `agent_login` establishes or confirms the account
|
|
370
311
|
session.
|
|
371
|
-
- **Identity** —
|
|
372
|
-
- **Spending** — the
|
|
373
|
-
rail
|
|
374
|
-
|
|
375
|
-
(`app.visacli.sh/agent/enroll`), never any account-settings page (that legacy surface
|
|
376
|
-
is retired). You **cannot** self-grant either, and never self-mint a wallet with
|
|
377
|
-
`wallet_init` on mainnet — it throws `WalletCredentialRequiredError` until the
|
|
378
|
-
owner's delegation lands.
|
|
312
|
+
- **Identity** — bound to _this user's_ account, on _this device_.
|
|
313
|
+
- **Spending** — the limits the owner approved in the browser. You **cannot** self-grant
|
|
314
|
+
either rail, and never self-mint a wallet with `wallet_init` on mainnet — it throws
|
|
315
|
+
`WalletCredentialRequiredError` until the owner's delegation lands.
|
|
379
316
|
- **Mesh (`.visa` messaging)** — separate; `visa register <name>` joins it.
|
|
380
317
|
- **Trusted (TAP)** — follows spend/provisioning; don't promise it before then.
|
|
381
318
|
3. **Scope everything to the user.** The identity is bound to the account they signed in
|
|
382
319
|
with; the wallet and limits are theirs. Speak in terms of "your agent / your account /
|
|
383
320
|
the limits you approved", never a shared identity.
|
|
384
321
|
|
|
385
|
-
##
|
|
386
|
-
|
|
387
|
-
`setup_start` always mints a new agent, so it is the wrong tool here. For an
|
|
388
|
-
already-connected agent that needs another rail, run the single-rail grant ceremony
|
|
389
|
-
against its **exact `agentId`** — never a name, never "the most recent one":
|
|
390
|
-
|
|
391
|
-
- [ ] **Establish the owner session** if this runtime does not have one: `agent_login`
|
|
392
|
-
(MCP) or `visa agent login` (CLI). Short-lived, established once — not a re-pair,
|
|
393
|
-
and not something the owner repeats per payment.
|
|
394
|
-
- [ ] **Initiate the grant from MCP.** `agent_connect` with the rail, caps, and the exact
|
|
395
|
-
`agentId`:
|
|
396
|
-
`{"agentId":"<agentId>","rail":"card","ceiling":"<usd>","perTransaction":"<usd>"}`
|
|
397
|
-
(or `"rail":"wallet"`). It returns `{ url, code, attachId, willGrant, expiresAt }`.
|
|
398
|
-
Present the **bare `url` and `code` exactly as returned** — never construct,
|
|
399
|
-
shorten, or guess a Visa URL, and never open it yourself.
|
|
400
|
-
- [ ] **The owner approves once** on the v4 agent dashboard, confirming the caps.
|
|
401
|
-
- [ ] **Poll to activation** with `agent_connect_poll` (`{"attachId":"<from
|
|
402
|
-
agent_connect>"}`) — one bounded poll per call, until
|
|
403
|
-
`{"ok":true,"state":"grant_activated"}`.
|
|
404
|
-
- [ ] **Confirm the rail is live.** Wallet: `wallet_status` / `visa wallet show`
|
|
405
|
-
(`agent_capabilities.wallet.available`). Card: `agent_capabilities.card.available`.
|
|
406
|
-
Only a delegated credential — not the served tool list — means the rail is usable.
|
|
407
|
-
|
|
408
|
-
Shell equivalents, which poll to activation in one call:
|
|
322
|
+
## An existing agent is missing a capability
|
|
409
323
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
324
|
+
There is no rail-add ceremony any more: `visa agent grant-card` / `grant-wallet` /
|
|
325
|
+
`grant-activate` / `grant-claim` and the `agent_connect` tools were deleted, and calling
|
|
326
|
+
one returns `legacy_door_removed`.
|
|
327
|
+
|
|
328
|
+
What to do instead:
|
|
329
|
+
|
|
330
|
+
- [ ] **Diagnose first.** `visa agent spendability --format json` and
|
|
331
|
+
`agent_capabilities` say exactly what is missing. Do not start anything before you
|
|
332
|
+
know which of identity, wallet delegation, card authority or funding is absent.
|
|
333
|
+
- [ ] **If the device's identity custody is broken**, `visa agent keychain repair` fixes
|
|
334
|
+
it without minting a new agent.
|
|
335
|
+
- [ ] **If the OWNER never approved that authority**, only they can add it. Say so, name
|
|
336
|
+
what is missing, and stop. Enrolling again mints a NEW agent — it does not upgrade
|
|
337
|
+
this one, and doing it silently leaves the owner with two agents and one funded
|
|
338
|
+
wallet.
|
|
414
339
|
|
|
415
340
|
A policy refusal or timeout means **nothing was signed**: report it and stop; do not retry
|
|
416
341
|
with a different command or a reconstructed URL. Never raise a human-approved limit
|
|
@@ -430,6 +355,13 @@ gated by the owner-approved local policy caps.
|
|
|
430
355
|
Card: `start_card_mandate`, then `pay_merchant`. The first card purchase asks the owner
|
|
431
356
|
for a spending mandate within the budget they already approved.
|
|
432
357
|
|
|
358
|
+
The current card rail uses VIC browser checkout through `pay_merchant` after
|
|
359
|
+
`start_card_mandate`; do not claim that browser checkout is unavailable before the card
|
|
360
|
+
retirement change lands. On a hosted runtime, **every payment requires the owner's browser
|
|
361
|
+
approval** until the protected no-tap executor lands. Enrollment, a session, or a spending
|
|
362
|
+
grant does not approve a later hosted payment. Relay the hosted approval URL and wait for
|
|
363
|
+
the owner's decision before reporting success or retrying.
|
|
364
|
+
|
|
433
365
|
## Optional `.visa` mesh binding (separate from setup)
|
|
434
366
|
|
|
435
367
|
Pairing does not register a `.visa` name, TAP key, or Subway peer. If the operator has
|
|
@@ -509,10 +441,13 @@ mailbox, key proof, recovery factor, or permission to spend.
|
|
|
509
441
|
- Never fetch or submit the review URL on the human's behalf. They review and approve it
|
|
510
442
|
in their own browser.
|
|
511
443
|
- Never invent a secondary path when a call fails. Preserve the local state, surface the
|
|
512
|
-
error, and resume through
|
|
444
|
+
error, and resume through the same protected entrance. On today's build, repeat the
|
|
445
|
+
same `visa agent enroll-protected ... --wait` command.
|
|
446
|
+
- Never call a retired door to "check whether it still works". `legacy_door_removed` is a
|
|
447
|
+
final answer, not a transient failure.
|
|
513
448
|
|
|
514
449
|
## Further docs
|
|
515
450
|
|
|
516
451
|
- `RUNTIMES.md` — OpenClaw, Hermes, and raw CLI setup.
|
|
517
|
-
- `docs/agents/ARCHITECTURE.md` — where
|
|
452
|
+
- `docs/agents/ARCHITECTURE.md` — where enrolment sits in the v4 request paths.
|
|
518
453
|
- `visacli.sh/agents` — product-facing agent documentation.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visa/cli",
|
|
3
|
-
"version": "4.1.0-rc.
|
|
3
|
+
"version": "4.1.0-rc.299",
|
|
4
4
|
"description": "Visa CLI runtime for stable agent identity and separately authorized payment capabilities",
|
|
5
5
|
"bin": {
|
|
6
6
|
"visa-cli": "./bin/visa-cli.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"sync:server-json": "node scripts/sync-server-json.mjs",
|
|
12
12
|
"check:server-json": "node scripts/sync-server-json.mjs --check",
|
|
13
|
-
"prebuild": "node scripts/sync-server-json.mjs && pnpm --filter @visa/shared build && pnpm --filter @visa/observability build && pnpm --filter @visa/money build && pnpm --filter @visa/crypto build && pnpm --filter subway-sdk build && pnpm --filter @visa-cli/tools build && pnpm --filter @visa/identity build && pnpm --filter @visa/wallet build && pnpm --filter @visa/agent-mail build && pnpm --filter @visa/wallet-tools build
|
|
13
|
+
"prebuild": "node scripts/sync-server-json.mjs && pnpm --filter @visa/shared build && pnpm --filter @visa/observability build && pnpm --filter @visa/money build && pnpm --filter @visa/crypto build && pnpm --filter subway-sdk build && pnpm --filter @visa-cli/tools build && pnpm --filter @visa/identity build && pnpm --filter @visa/wallet build && pnpm --filter @visa/agent-mail build && pnpm --filter @visa/wallet-tools build",
|
|
14
14
|
"build": "tsc --noEmit && node esbuild.config.js",
|
|
15
15
|
"prepack": "node scripts/sync-server-json.mjs --check",
|
|
16
16
|
"dev": "tsc --watch",
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"@libp2p/tcp": "^11.0.26",
|
|
60
60
|
"@multiformats/multiaddr": "^13.0.3",
|
|
61
61
|
"libp2p": "^3.3.9",
|
|
62
|
-
"playwright-core": "^1.62.1",
|
|
63
62
|
"uint8arrays": "^6.1.1"
|
|
64
63
|
},
|
|
65
64
|
"devDependencies": {
|
|
@@ -70,7 +69,6 @@
|
|
|
70
69
|
"@typescript-eslint/parser": "^8.68.0",
|
|
71
70
|
"@visa-cli/tools": "workspace:*",
|
|
72
71
|
"@visa/agent-mail": "workspace:*",
|
|
73
|
-
"@visa/checkout-engine": "workspace:*",
|
|
74
72
|
"@visa/crypto": "workspace:*",
|
|
75
73
|
"@visa/identity": "workspace:*",
|
|
76
74
|
"@visa/money": "workspace:*",
|
package/server.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.visa-crypto-labs/visa-cli",
|
|
4
|
-
"version": "4.1.0-rc.
|
|
4
|
+
"version": "4.1.0-rc.299",
|
|
5
5
|
"title": "Visa CLI",
|
|
6
6
|
"description": "Pair a human-approved agent identity, configure payment capabilities separately, and discover and pay x402 services from your AI coding assistant.",
|
|
7
7
|
"websiteUrl": "https://github.com/Visa-Crypto-Labs/Visa-mono/tree/main/packages/cli#readme",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"registryType": "npm",
|
|
11
11
|
"identifier": "@visa/cli",
|
|
12
|
-
"version": "4.1.0-rc.
|
|
12
|
+
"version": "4.1.0-rc.299",
|
|
13
13
|
"transport": {
|
|
14
14
|
"type": "stdio"
|
|
15
15
|
},
|