@visa/cli 4.1.0-rc.21 → 4.1.0-rc.210

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +200 -226
  2. package/dist/checkout-engine/adapters/generic.d.ts +69 -0
  3. package/dist/checkout-engine/adapters/generic.js +383 -58
  4. package/dist/checkout-engine/adapters/index.d.ts +4 -1
  5. package/dist/checkout-engine/adapters/index.js +10 -3
  6. package/dist/checkout-engine/adapters/shopify.d.ts +55 -0
  7. package/dist/checkout-engine/adapters/shopify.js +514 -0
  8. package/dist/checkout-engine/amount.d.ts +15 -0
  9. package/dist/checkout-engine/amount.js +72 -0
  10. package/dist/checkout-engine/cli-engine.d.ts +264 -4
  11. package/dist/checkout-engine/cli-engine.js +803 -43
  12. package/dist/checkout-engine/confirmed-merchants.d.ts +31 -0
  13. package/dist/checkout-engine/confirmed-merchants.js +165 -0
  14. package/dist/checkout-engine/detect.d.ts +1 -1
  15. package/dist/checkout-engine/detect.js +26 -0
  16. package/dist/checkout-engine/evidence.d.ts +4 -1
  17. package/dist/checkout-engine/evidence.js +51 -6
  18. package/dist/checkout-engine/executor.d.ts +47 -4
  19. package/dist/checkout-engine/executor.js +418 -131
  20. package/dist/checkout-engine/hosted-approval.d.ts +124 -7
  21. package/dist/checkout-engine/hosted-approval.js +381 -54
  22. package/dist/checkout-engine/index.d.ts +8 -2
  23. package/dist/checkout-engine/index.js +7 -1
  24. package/dist/checkout-engine/instrument.d.ts +7 -0
  25. package/dist/checkout-engine/instrument.js +4 -0
  26. package/dist/checkout-engine/known-merchants.d.ts +10 -0
  27. package/dist/checkout-engine/known-merchants.js +38 -0
  28. package/dist/checkout-engine/live-fill-approval.d.ts +5 -20
  29. package/dist/checkout-engine/live-fill-approval.js +20 -51
  30. package/dist/checkout-engine/mandate/card-mandate.d.ts +121 -0
  31. package/dist/checkout-engine/mandate/card-mandate.js +226 -0
  32. package/dist/checkout-engine/mandate/mandate-ledger.d.ts +174 -0
  33. package/dist/checkout-engine/mandate/mandate-ledger.js +410 -0
  34. package/dist/checkout-engine/outcome.d.ts +2 -2
  35. package/dist/checkout-engine/outcome.js +36 -1
  36. package/dist/checkout-engine/owner-only-file.d.ts +9 -0
  37. package/dist/checkout-engine/owner-only-file.js +20 -1
  38. package/dist/checkout-engine/receipt-dir.d.ts +6 -0
  39. package/dist/checkout-engine/receipt-dir.js +8 -0
  40. package/dist/checkout-engine/receipt.d.ts +42 -2
  41. package/dist/checkout-engine/receipt.js +43 -14
  42. package/dist/checkout-engine/trace-handles.d.ts +8 -0
  43. package/dist/checkout-engine/trace-handles.js +12 -0
  44. package/dist/checkout-engine/types.d.ts +28 -2
  45. package/dist/checkout-engine/unresolved-charges.d.ts +34 -0
  46. package/dist/checkout-engine/unresolved-charges.js +125 -0
  47. package/dist/checkout-engine/vgs-gateway/server-mint-client.d.ts +53 -1
  48. package/dist/checkout-engine/vgs-gateway/server-mint-client.js +78 -10
  49. package/dist/checkout-engine/vgs-live-instrument.d.ts +38 -35
  50. package/dist/checkout-engine/vgs-live-instrument.js +51 -74
  51. package/dist/checkout-engine/vic-confirmation.d.ts +18 -0
  52. package/dist/checkout-engine/vic-confirmation.js +9 -3
  53. package/dist/checkout-engine/web-bot-auth.d.ts +92 -0
  54. package/dist/checkout-engine/web-bot-auth.js +159 -0
  55. package/dist/cli.js +772 -496
  56. package/dist/mcp-apps/ucp-checkout.html +280 -0
  57. package/dist/mcp-server/index.js +637 -175
  58. package/dist/skills/pair-visa-agent/RUNTIMES.md +93 -0
  59. package/dist/skills/pair-visa-agent/SKILL.md +479 -221
  60. package/dist/subway-direct.mjs +1 -0
  61. package/install.ps1 +5 -43
  62. package/install.sh +5 -37
  63. package/native/bin/win32-x64/visa-keychain-win.exe +0 -0
  64. package/package.json +33 -27
  65. package/server.json +4 -4
  66. package/dist/checkout-engine/inline-target.d.ts +0 -13
  67. package/dist/checkout-engine/inline-target.js +0 -37
  68. package/dist/checkout-engine/pay-args.d.ts +0 -14
  69. package/dist/checkout-engine/pay-args.js +0 -44
  70. package/dist/checkout-engine/pay.d.ts +0 -1
  71. package/dist/checkout-engine/pay.js +0 -13
  72. package/dist/checkout-engine/repo-env.d.ts +0 -11
  73. package/dist/checkout-engine/repo-env.js +0 -23
  74. package/dist/checkout-engine/run-live-fill.d.ts +0 -1
  75. package/dist/checkout-engine/run-live-fill.js +0 -443
  76. package/dist/checkout-engine/vgs-gateway/fetch-credential.d.mts +0 -74
  77. package/dist/checkout-engine/vgs-gateway/fetch-credential.mjs +0 -248
@@ -0,0 +1 @@
1
+ import{createLibp2p as x}from"libp2p";import{tcp as A}from"@libp2p/tcp";import{noise as E}from"@chainsafe/libp2p-noise";import{yamux as U}from"@chainsafe/libp2p-yamux";import{generateKeyPairFromSeed as b}from"@libp2p/crypto/keys";import{multiaddr as q}from"@multiformats/multiaddr";import{toString as D}from"uint8arrays/to-string";var p=new TextEncoder,R=new TextDecoder;function y(e,r){let n=typeof r=="bigint"?r:BigInt(r);for(;n>0x7fn;)e.push(Number(n&0x7fn|0x80n)),n>>=7n;e.push(Number(n))}function d(e,r){let n=0n,t=0n,o=r;for(;;){let s=e[o++];if(n|=BigInt(s&127)<<t,(s&128)===0)break;t+=7n}return[n,o]}function g(e,r){return e<<3|r}function f(e,r,n){e.push(g(r,2)),y(e,n.length);for(let t of n)e.push(t)}function M(e,r,n){let t=[];return f(t,1,p.encode(e)),r&&r.length>0&&f(t,2,p.encode(r)),n&&n.length>0&&f(t,3,p.encode(n)),Uint8Array.from(t)}function O(e,r,n,t){let o=[];return n!==0n&&(o.push(g(1,0)),y(o,n)),f(o,2,M(e,r,t)),Uint8Array.from(o)}function T(e){let r=[];return f(r,1,p.encode(e)),Uint8Array.from(r)}function P(e,r){let n=[];return r!==0n&&(n.push(g(1,0)),y(n,r)),f(n,3,T(e)),Uint8Array.from(n)}var S="Name not found";function L(e){let r=0,n={success:!1,error:""};for(;r<e.length;){let[t,o]=d(e,r);r=o;let s=Number(t)>>3,i=Number(t)&7;if(s===1&&i===0){let[u,l]=d(e,r);r=l,n.success=u!==0n}else if(s===2&&i===2){let[u,l]=d(e,r),a=l,c=a+Number(u);n.error=R.decode(e.subarray(a,c)),r=c}else r=h(e,r,i)}return n}function F(e){let r=0,n={peerId:new Uint8Array(0),error:""};for(;r<e.length;){let[t,o]=d(e,r);r=o;let s=Number(t)>>3,i=Number(t)&7;if(s===1&&i===2){let[u,l]=d(e,r),a=l,c=a+Number(u);n.peerId=e.subarray(a,c),r=c}else if(s===2&&i===2){let[u,l]=d(e,r),a=l,c=a+Number(u);n.error=R.decode(e.subarray(a,c)),r=c}else r=h(e,r,i)}return n}function h(e,r,n){if(n===0)return d(e,r)[1];if(n===2){let[t,o]=d(e,r);return o+Number(t)}if(n===5)return r+4;if(n===1)return r+8;throw new Error(`unsupported wire type ${n}`)}function v(e){let r=0,n={requestId:0n};for(;r<e.length;){let[t,o]=d(e,r);r=o;let s=Number(t)>>3,i=Number(t)&7;if(s===1&&i===0){let[u,l]=d(e,r);r=l,n.requestId=u}else if(s===13&&i===2){let[u,l]=d(e,r),a=l,c=a+Number(u);n.registerNameResponse=L(e.subarray(a,c)),r=c}else if(s===14&&i===2){let[u,l]=d(e,r),a=l,c=a+Number(u);n.resolveNameResponse=F(e.subarray(a,c)),r=c}else r=h(e,r,i)}return n}function B(e){let r=new Uint8Array(4+e.length);return new DataView(r.buffer).setUint32(0,e.length,!1),r.set(e,4),r}function w(e){return new DataView(e.buffer,e.byteOffset,4).getUint32(0,!1)}function V(e){if(e.length<4)return{success:!1,error:"short reply (no length prefix)"};let r=w(e.subarray(0,4));return e.length<4+r?{success:!1,error:`truncated frame (have ${e.length-4}, need ${r})`}:v(e.subarray(4,4+r)).registerNameResponse??{success:!1,error:"reply carried no register_name_response"}}function $(e){if(e.length<4)return{peerId:new Uint8Array(0),error:"short reply (no length prefix)"};let r=w(e.subarray(0,4));return e.length<4+r?{peerId:new Uint8Array(0),error:`truncated frame (have ${e.length-4}, need ${r})`}:v(e.subarray(4,4+r)).resolveNameResponse??{peerId:new Uint8Array(0),error:"reply carried no resolve_name_response"}}var k="/subway/p2p/1.0.0",Y=15e3,z=15e3,N=1<<20;function m(e){let r=e.reduce((o,s)=>o+s.length,0),n=new Uint8Array(r),t=0;for(let o of e)n.set(o,t),t+=o.length;return n}async function K(e){let r=[],n=0,t=-1;for await(let o of e){let s=o instanceof Uint8Array?o:o.subarray();if(r.push(s),n+=s.length,n>N)throw new Error("subway: reply exceeded max size");if(t<0&&n>=4&&(t=4+w(m(r).subarray(0,4)),t>N))throw new Error("subway: declared frame exceeds max size");if(t>=0&&n>=t)return m(r).subarray(0,t)}return m(r)}async function _(e){return x({...e?{privateKey:await b("Ed25519",e)}:{},transports:[A()],connectionEncrypters:[E()],streamMuxers:[U()],connectionGater:{denyDialMultiaddr:async()=>!1}})}async function I(e,r,n){let t=await e.dialProtocol(q(r),k,{signal:AbortSignal.timeout(Y)});t.send(B(n));let o;return Promise.race([K(t),new Promise((s,i)=>{o=setTimeout(()=>i(new Error("subway: request timed out")),z)})]).finally(()=>clearTimeout(o))}async function G(e){let r=await _(e.seed);try{let n=await I(r,e.relayMultiaddr,O(e.name,e.binding,e.requestId??1n,e.runtimeCertificate)),t=V(n);return{success:t.success,error:t.error,peerId:r.peerId.toString()}}finally{await r.stop()}}async function W(e){let r=await _(e.seed);try{let n=await I(r,e.relayMultiaddr,P(e.name,e.requestId??1n)),t=$(n);if(t.peerId.length===0){let o=t.error||"name not found";return{outcome:o===S?"not_found":"lookup_failed",found:!1,peerId:"",error:o}}return{outcome:"found",found:!0,peerId:D(t.peerId,"base58btc"),error:""}}finally{await r.stop()}}export{G as registerDirect,W as resolveDirect};
package/install.ps1 CHANGED
@@ -108,8 +108,8 @@ try {
108
108
  }
109
109
 
110
110
  $major = [int]$nodeMatch.Groups['major'].Value
111
- if ($major -lt 18) {
112
- Write-Host " Node.js $nodeVersion is too old. Version 18+ required." -ForegroundColor Red
111
+ if ($major -lt 20) {
112
+ Write-Host " Node.js $nodeVersion is too old. Version 20+ required." -ForegroundColor Red
113
113
  Write-Host " Install from https://nodejs.org/ and try again." -ForegroundColor Yellow
114
114
  Wait-BeforeExit
115
115
  exit 1
@@ -168,7 +168,6 @@ if ($npmExitCode -ne 0) {
168
168
  # Verify
169
169
  $cliCommandNames = Get-InstalledCliCommands
170
170
  $verifiedCommand = $null
171
- $verifiedCommandPath = $null
172
171
  $visaVersion = $null
173
172
 
174
173
  foreach ($commandName in $cliCommandNames) {
@@ -177,12 +176,9 @@ foreach ($commandName in $cliCommandNames) {
177
176
  continue
178
177
  }
179
178
 
180
- # Capture the resolved executable path so the setup hand-off below runs
181
- # exactly the binary verified here, not a fresh PATH lookup.
182
179
  $versionOutput = (& $commandInfo.Source --version 2>$null | Select-Object -First 1)
183
180
  if ($LASTEXITCODE -eq 0 -and $versionOutput) {
184
181
  $verifiedCommand = $commandName
185
- $verifiedCommandPath = $commandInfo.Source
186
182
  $visaVersion = $versionOutput.Trim()
187
183
  break
188
184
  }
@@ -191,46 +187,12 @@ foreach ($commandName in $cliCommandNames) {
191
187
  Write-Host ""
192
188
  if ($verifiedCommand) {
193
189
  Write-Host " Visa CLI $visaVersion installed." -ForegroundColor Green
194
-
195
- # Hand off straight into setup so install -> setup -> signed-in is one
196
- # uninterrupted flow. Hardening:
197
- # * Auto-launch only on an interactive console with input/output/error
198
- # all attached - setup must prompt and open a browser. Redirected
199
- # streams and CI fall back to printing the next step.
200
- # * Invoke $verifiedCommandPath (the path verified just above), not a
201
- # bare command name re-resolved through PATH.
202
- # * Pass only the literal "setup" argument - nothing caller-controlled.
203
- if ($Host.Name -eq 'ConsoleHost' -and -not [Console]::IsInputRedirected -and -not [Console]::IsOutputRedirected -and -not [Console]::IsErrorRedirected -and -not $env:CI) {
204
- Write-Host ""
205
- Write-Host " Continuing to setup..." -ForegroundColor Cyan
206
- Write-Host ""
207
- try {
208
- $setupProcess = Start-Process -FilePath $verifiedCommandPath -ArgumentList @('setup') -Wait -NoNewWindow -PassThru -ErrorAction Stop
209
- } catch {
210
- Write-Host ""
211
- Write-Host " Setup could not start. Visa CLI is installed." -ForegroundColor Yellow
212
- Write-Host " PowerShell error: $($_.Exception.Message)" -ForegroundColor Yellow
213
- Write-Host " run '$verifiedCommand setup' when you're ready to finish." -ForegroundColor Yellow
214
- Wait-BeforeExit
215
- exit 1
216
- }
217
- if ($setupProcess.ExitCode -ne 0) {
218
- Write-Host ""
219
- Write-Host " Setup exited before completion. Visa CLI is installed." -ForegroundColor Yellow
220
- Write-Host " run '$verifiedCommand setup' when you're ready to finish." -ForegroundColor Yellow
221
- Wait-BeforeExit
222
- exit 1
223
- }
224
- exit 0
225
- } else {
226
- Write-Host " Run '$verifiedCommand setup' to get started." -ForegroundColor Cyan
227
- Write-Host " After setup, run /mcp inside Claude Code, not PowerShell, if Claude Code was already open." -ForegroundColor Cyan
228
- }
190
+ Write-Host " Connect an AI client with: $verifiedCommand connect <client>" -ForegroundColor Cyan
191
+ Write-Host " Then ask your agent to call enroll_agent." -ForegroundColor Cyan
229
192
  Write-Host ""
230
193
  } else {
231
194
  $primaryCommand = $cliCommandNames | Select-Object -First 1
232
195
  Write-Host " Installed but '$primaryCommand' was not runnable from PATH yet." -ForegroundColor Yellow
233
- Write-Host " Close and reopen PowerShell, then run: $primaryCommand setup" -ForegroundColor Yellow
234
- Write-Host " Run /mcp inside Claude Code after setup if you need to reconnect the MCP server." -ForegroundColor Yellow
196
+ Write-Host " Close and reopen PowerShell, then run: $primaryCommand connect <client>" -ForegroundColor Yellow
235
197
  Write-Host ""
236
198
  }
package/install.sh CHANGED
@@ -10,8 +10,8 @@
10
10
  _visa_install() {
11
11
  set -euo pipefail
12
12
 
13
- REQUIRED_NODE_MAJOR=18
14
- PACKAGE="@visa/cli"
13
+ REQUIRED_NODE_MAJOR=20
14
+ PACKAGE="@visa/cli@rc"
15
15
 
16
16
  # ── colours (disabled when piped) ─────────────────────────────────────────────
17
17
  if [ -t 1 ]; then
@@ -99,9 +99,6 @@ fi
99
99
  echo "$NPM_OUTPUT"
100
100
 
101
101
  # ── verify ────────────────────────────────────────────────────────────────────
102
- # Capture the absolute path resolved here so the setup hand-off below invokes
103
- # exactly the binary we just verified, instead of re-resolving "visa-cli"
104
- # through $PATH a second time.
105
102
  VISA_BIN=""
106
103
  VISA_VERSION=""
107
104
  if VISA_BIN="$(command -v visa-cli 2>/dev/null)"; then
@@ -111,40 +108,11 @@ fi
111
108
  echo ""
112
109
  if [ -n "$VISA_VERSION" ]; then
113
110
  ok "Visa CLI ${VISA_VERSION} installed."
114
- # Hand off straight into setup so install -> setup -> signed-in is one
115
- # uninterrupted flow. Hardening:
116
- # * Auto-launch only when output streams are real terminals and setup can
117
- # read from either stdin or /dev/tty. That keeps `curl ... | bash` usable:
118
- # the script arrives on stdin, while setup prompts still read from the
119
- # user's terminal. CI and redirected output print the next step instead.
120
- # * Invoke "$VISA_BIN" (the path verified just above), never a bare
121
- # "visa-cli" re-resolved through $PATH at call time.
122
- # * Pass only the literal "setup" argument — "$@" is never forwarded — so
123
- # nothing the script's caller controls reaches the installed binary.
124
- if [ -t 1 ] && [ -t 2 ] && { [ -t 0 ] || [ -r /dev/tty ]; }; then
125
- echo ""
126
- info "Continuing to setup..."
127
- echo ""
128
- SETUP_EXIT=0
129
- if [ -t 0 ]; then
130
- "$VISA_BIN" setup || SETUP_EXIT=$?
131
- else
132
- "$VISA_BIN" setup </dev/tty || SETUP_EXIT=$?
133
- fi
134
- if [ "$SETUP_EXIT" -ne 0 ]; then
135
- echo ""
136
- warn "Setup exited before completion. Visa CLI is installed."
137
- warn "run 'visa-cli setup' when you're ready to finish."
138
- exit 1
139
- fi
140
- exit 0
141
- else
142
- info "Run 'visa-cli setup' to get started."
143
- info "After setup, run /mcp inside Claude Code, not Terminal, if Claude Code was already open."
144
- fi
111
+ info "Connect an AI client with: visa-cli connect <client>"
112
+ info "Then ask your agent to call enroll_agent."
145
113
  else
146
114
  warn "Installed, but 'visa-cli' was not found on PATH."
147
- warn "You may need to restart your shell, then run: visa-cli setup"
115
+ warn "Restart your shell, then run: visa-cli connect <client>"
148
116
  fi
149
117
  echo ""
150
118
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@visa/cli",
3
- "version": "4.1.0-rc.21",
4
- "description": "AI-powered payments for Claude Code",
3
+ "version": "4.1.0-rc.210",
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",
7
7
  "visa": "./bin/visa-cli.js"
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "sync:server-json": "node scripts/sync-server-json.mjs",
11
11
  "check:server-json": "node scripts/sync-server-json.mjs --check",
12
- "prebuild": "node scripts/sync-server-json.mjs && 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/wallet-tools build && pnpm --filter @visa/checkout-engine build",
12
+ "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 && pnpm --filter @visa/checkout-engine build",
13
13
  "build": "tsc --noEmit && node esbuild.config.js",
14
14
  "prepack": "node scripts/sync-server-json.mjs --check",
15
15
  "dev": "tsc --watch",
@@ -20,9 +20,9 @@
20
20
  "test:unit:watch": "jest --config jest.config.js --watch",
21
21
  "test:unit:coverage": "jest --config jest.config.js --coverage",
22
22
  "test:smoke": "VISA_AUTH_URL=https://auth.visacli.sh jest --config jest.smoke.config.js",
23
+ "test:packed": "node scripts/packed-cli-smoke.mjs",
23
24
  "test:integration": "jest --config jest.integration.config.js",
24
25
  "test:e2e": "jest --config jest.e2e.config.js",
25
- "test:catalog-e2e": "jest --config jest.catalog-e2e.config.js",
26
26
  "test:all": "npm run test:unit && npm run test:integration && npm run test:e2e",
27
27
  "prepublishOnly": "npm run build && npm test",
28
28
  "lint": "eslint src/**/*.ts",
@@ -42,47 +42,54 @@
42
42
  "author": "Visa Crypto Labs",
43
43
  "license": "SEE LICENSE IN LICENSE",
44
44
  "dependencies": {
45
- "@modelcontextprotocol/sdk": "^1.0.0",
45
+ "@modelcontextprotocol/core": "2.0.0",
46
+ "@modelcontextprotocol/ext-apps": "1.7.5",
47
+ "@modelcontextprotocol/server": "2.0.0",
48
+ "@ucp-js/sdk": "0.4.4",
46
49
  "commander": "^12.1.0",
47
- "zod": "^3.23.0"
50
+ "punycode": "^2.3.1",
51
+ "zod": "^3.25.76"
48
52
  },
49
53
  "optionalDependencies": {
50
- "libp2p": "^3.3.4",
51
- "@libp2p/tcp": "^11.0.22",
52
- "@libp2p/crypto": "^5.1.20",
53
54
  "@chainsafe/libp2p-noise": "^17.0.0",
54
55
  "@chainsafe/libp2p-yamux": "^8.0.1",
56
+ "@libp2p/crypto": "^5.1.22",
57
+ "@libp2p/tcp": "^11.0.26",
55
58
  "@multiformats/multiaddr": "^13.0.3",
56
- "uint8arrays": "^6.1.1",
57
- "playwright-core": "^1.48.2"
59
+ "libp2p": "^3.3.8",
60
+ "playwright-core": "^1.48.2",
61
+ "uint8arrays": "^6.1.1"
58
62
  },
59
63
  "devDependencies": {
64
+ "@changesets/changelog-git": "^0.2.1",
65
+ "@types/express": "^5.0.0",
66
+ "@changesets/cli": "^2.31.1",
67
+ "@types/jest": "^30.0.0",
68
+ "@types/node": "^26.1.0",
69
+ "@typescript-eslint/eslint-plugin": "^8.65.0",
70
+ "@typescript-eslint/parser": "^8.65.0",
71
+ "@visa-cli/tools": "workspace:*",
72
+ "@visa/agent-mail": "workspace:*",
60
73
  "@visa/checkout-engine": "workspace:*",
61
74
  "@visa/crypto": "workspace:*",
62
- "subway-sdk": "workspace:*",
75
+ "@visa/identity": "workspace:*",
63
76
  "@visa/money": "workspace:*",
77
+ "@visa/observability": "workspace:*",
78
+ "@visa/shared": "workspace:*",
64
79
  "@visa/wallet": "workspace:*",
65
80
  "@visa/wallet-tools": "workspace:*",
66
- "@visa/observability": "workspace:*",
67
- "@visa-cli/tools": "workspace:*",
68
- "@changesets/changelog-git": "^0.2.1",
69
- "@changesets/cli": "^2.31.0",
70
- "@types/jest": "^30.0.0",
71
- "@types/node": "^26.1.0",
72
- "@typescript-eslint/eslint-plugin": "^8.63.0",
73
- "@typescript-eslint/parser": "^8.63.0",
74
- "@types/express": "^5.0.0",
75
81
  "esbuild": "^0.28.1",
76
- "express": "^4.21.0",
77
82
  "eslint": "^10.0.2",
78
83
  "eslint-config-prettier": "^10.1.8",
84
+ "express": "^4.21.0",
79
85
  "jest": "^29.7.0",
80
- "prettier": "^3.9.4",
81
- "ts-jest": "^29.4.11",
86
+ "prettier": "^3.9.6",
87
+ "subway-sdk": "workspace:*",
88
+ "ts-jest": "^29.4.12",
82
89
  "typescript": "^5.7.0"
83
90
  },
84
91
  "engines": {
85
- "node": ">=18.0.0"
92
+ "node": ">=20.0.0"
86
93
  },
87
94
  "mcpName": "io.github.visa-crypto-labs/visa-cli",
88
95
  "files": [
@@ -95,7 +102,6 @@
95
102
  "native/build-win.bat",
96
103
  "native/bin/win32-x64/visa-keychain-win.exe",
97
104
  "server.json",
98
- "README.md",
99
- "LICENSE"
105
+ "README.md"
100
106
  ]
101
107
  }
package/server.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
- "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
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.21",
4
+ "version": "4.1.0-rc.210",
5
5
  "title": "Visa CLI",
6
- "description": "AI-powered payments and creative tools for coding agents. Generate images, music, video, query crypto prices, and make purchases all from your AI coding assistant.",
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",
8
8
  "packages": [
9
9
  {
10
10
  "registryType": "npm",
11
11
  "identifier": "@visa/cli",
12
- "version": "4.1.0-rc.21",
12
+ "version": "4.1.0-rc.210",
13
13
  "transport": {
14
14
  "type": "stdio"
15
15
  },
@@ -1,13 +0,0 @@
1
- import type { VgsCheckoutTarget } from './vgs-live-instrument.js';
2
- /**
3
- * Build a checkout target from inline CLI flags (`--merchant-url` +
4
- * `--amount`, with optional `--merchant-name` / `--country` / `--currency`)
5
- * so any merchant can be paid without authoring a checkout JSON file first.
6
- *
7
- * Returns null when neither driving flag is present (file mode). Shape-only:
8
- * the returned target flows through run-live-fill's existing validation block
9
- * (positive-decimal amount, ISO codes, HTTPS), which stays the single source
10
- * of truth — nothing is double-validated here except the URL parse, which
11
- * must happen early because the merchant-name default derives from it.
12
- */
13
- export declare function inlineTargetFromFlags(input: Map<string, string>): VgsCheckoutTarget | null;
@@ -1,37 +0,0 @@
1
- /**
2
- * Build a checkout target from inline CLI flags (`--merchant-url` +
3
- * `--amount`, with optional `--merchant-name` / `--country` / `--currency`)
4
- * so any merchant can be paid without authoring a checkout JSON file first.
5
- *
6
- * Returns null when neither driving flag is present (file mode). Shape-only:
7
- * the returned target flows through run-live-fill's existing validation block
8
- * (positive-decimal amount, ISO codes, HTTPS), which stays the single source
9
- * of truth — nothing is double-validated here except the URL parse, which
10
- * must happen early because the merchant-name default derives from it.
11
- */
12
- export function inlineTargetFromFlags(input) {
13
- const merchantUrl = input.get('--merchant-url');
14
- const amount = input.get('--amount');
15
- if (merchantUrl === undefined && amount === undefined)
16
- return null;
17
- if (!merchantUrl || !amount) {
18
- throw new Error('inline checkout needs both --merchant-url and --amount');
19
- }
20
- let host;
21
- try {
22
- host = new URL(merchantUrl).hostname;
23
- }
24
- catch {
25
- throw new Error('--merchant-url must be a valid URL');
26
- }
27
- if (!host) {
28
- throw new Error('--merchant-url must have a hostname');
29
- }
30
- return {
31
- merchantName: input.get('--merchant-name') ?? host,
32
- merchantUrl,
33
- merchantCountryCode: input.get('--country') ?? 'US',
34
- transactionAmount: amount,
35
- transactionCurrencyCode: input.get('--currency') ?? 'USD',
36
- };
37
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Argv rewriter for the `pnpm pay` positional entry point, extracted pure so
3
- * it is unit-testable (the pay.ts script executes on import). Maps
4
- * `<checkout-url> <amount> [flags]` onto run-live-fill's inline flags.
5
- *
6
- * Strict by design — this drives a real-money run:
7
- * - `--merchant-url`/`--amount` are REJECTED as passthrough flags: the
8
- * runner's arg map lets a later flag win, so a stray duplicate would
9
- * silently retarget the purchase away from the typed positionals.
10
- * - Every flag must carry a value (same grammar as run-live-fill's args()),
11
- * so a trailing bare flag fails HERE with pay's usage, not downstream with
12
- * fill:live's.
13
- */
14
- export declare function rewritePayArgs(argv: string[]): string[];
@@ -1,44 +0,0 @@
1
- /**
2
- * Argv rewriter for the `pnpm pay` positional entry point, extracted pure so
3
- * it is unit-testable (the pay.ts script executes on import). Maps
4
- * `<checkout-url> <amount> [flags]` onto run-live-fill's inline flags.
5
- *
6
- * Strict by design — this drives a real-money run:
7
- * - `--merchant-url`/`--amount` are REJECTED as passthrough flags: the
8
- * runner's arg map lets a later flag win, so a stray duplicate would
9
- * silently retarget the purchase away from the typed positionals.
10
- * - Every flag must carry a value (same grammar as run-live-fill's args()),
11
- * so a trailing bare flag fails HERE with pay's usage, not downstream with
12
- * fill:live's.
13
- */
14
- const USAGE = 'usage: pnpm pay -- <checkout-url> <amount> [--merchant-name <name>] ' +
15
- '[--country <CC>] [--currency <ISO>] [--mode dry-run|submit] [--contact-file <path>] ' +
16
- '[--agent-credential-file <path>] [--approval-base-url <url>]';
17
- const RESERVED_FLAGS = ['--merchant-url', '--amount'];
18
- export function rewritePayArgs(argv) {
19
- // pnpm forwards the literal `--` separator; drop it like run-live-fill does.
20
- const tokens = argv.filter((a) => a !== '--');
21
- const positionals = [];
22
- const flags = [];
23
- for (let i = 0; i < tokens.length; i++) {
24
- const token = tokens[i];
25
- if (token.startsWith('--')) {
26
- if (RESERVED_FLAGS.includes(token)) {
27
- throw new Error(`${token} is derived from the positionals — pass the url and amount ` +
28
- `positionally instead of as flags\n${USAGE}`);
29
- }
30
- const value = tokens[i + 1];
31
- if (value === undefined || value.startsWith('--')) {
32
- throw new Error(`flag ${token} needs a value\n${USAGE}`);
33
- }
34
- flags.push(token, value);
35
- i++;
36
- }
37
- else {
38
- positionals.push(token);
39
- }
40
- }
41
- if (positionals.length !== 2)
42
- throw new Error(USAGE);
43
- return ['--merchant-url', positionals[0], '--amount', positionals[1], ...flags];
44
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,13 +0,0 @@
1
- /**
2
- * Positional sugar over run-live-fill's inline any-merchant mode:
3
- *
4
- * pnpm pay -- <checkout-url> <amount> [--mode submit] [--merchant-name "X"] [...]
5
- *
6
- * Rewrites the two positionals into --merchant-url/--amount (pay-args.ts,
7
- * strict) and re-enters the runner, so every guardrail (typed PAY approval,
8
- * CHECKOUT_AGENT_ALLOW_SUBMIT, hosted/loopback ceremony, receipts) is exactly
9
- * the fill:live path — this file must never grow logic of its own.
10
- */
11
- import { rewritePayArgs } from './pay-args.js';
12
- process.argv = [process.argv[0], process.argv[1], ...rewritePayArgs(process.argv.slice(2))];
13
- await import('./run-live-fill.js');
@@ -1,11 +0,0 @@
1
- /**
2
- * Load the monorepo root `.env` as DEFAULTS for the runner, so stable
3
- * per-machine config (VGS credentials, CHECKOUT_APPROVAL_BASE_URL,
4
- * CHECKOUT_AGENT_ALLOW_SUBMIT, CHECKOUT_AGENT_MODE) is set once instead of
5
- * retyped on every invocation. `process.loadEnvFile` never overrides
6
- * variables already present in the environment (verified: shell always wins),
7
- * so an explicit `FOO=x pnpm pay …` still beats the file. A missing file is
8
- * fine — the runner then relies on the ambient environment exactly as before.
9
- */
10
- export declare function defaultRepoEnvPath(): string;
11
- export declare function loadRepoEnvDefaults(path?: string, log?: (line: string) => void): boolean;
@@ -1,23 +0,0 @@
1
- import { fileURLToPath } from 'node:url';
2
- /**
3
- * Load the monorepo root `.env` as DEFAULTS for the runner, so stable
4
- * per-machine config (VGS credentials, CHECKOUT_APPROVAL_BASE_URL,
5
- * CHECKOUT_AGENT_ALLOW_SUBMIT, CHECKOUT_AGENT_MODE) is set once instead of
6
- * retyped on every invocation. `process.loadEnvFile` never overrides
7
- * variables already present in the environment (verified: shell always wins),
8
- * so an explicit `FOO=x pnpm pay …` still beats the file. A missing file is
9
- * fine — the runner then relies on the ambient environment exactly as before.
10
- */
11
- export function defaultRepoEnvPath() {
12
- return fileURLToPath(new URL('../../../.env', import.meta.url));
13
- }
14
- export function loadRepoEnvDefaults(path = defaultRepoEnvPath(), log = (line) => process.stdout.write(`${line}\n`)) {
15
- try {
16
- process.loadEnvFile(path);
17
- }
18
- catch {
19
- return false;
20
- }
21
- log(`loaded env defaults from ${path} (already-set variables win)`);
22
- return true;
23
- }
@@ -1 +0,0 @@
1
- export {};