@airwallex/airi-cli 0.1.0-beta.1 → 0.1.0-beta.3

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 CHANGED
@@ -1,11 +1,12 @@
1
1
  # airi-cli
2
2
 
3
- ![Version](https://img.shields.io/badge/version-0.1.0--beta.1-orange)
3
+ ![Version](https://img.shields.io/badge/version-0.1.0--beta.3-orange)
4
4
 
5
5
  Command-line tool for the Airi wallet. Authenticate with OAuth, inspect your
6
6
  session, and drive an **agentic checkout** — list payment methods, create a
7
- payment mandate, fetch the single-use checkout credential, and report the
8
- result — from your terminal or an AI agent.
7
+ payment mandate, fetch the single-use checkout credential, report the result,
8
+ and cancel a mandate — or browse mandates already in the wallet, from your
9
+ terminal or an AI agent.
9
10
 
10
11
  Results are printed to stdout as JSON, so they are easy to consume from scripts
11
12
  and agents.
@@ -13,7 +14,8 @@ and agents.
13
14
  ## Installation
14
15
 
15
16
  airi-cli is available for macOS and Linux as a single self-contained binary.
16
- Install it with npm:
17
+
18
+ ### npm
17
19
 
18
20
  ```bash
19
21
  npm install -g @airwallex/airi-cli@beta
@@ -23,17 +25,68 @@ This installs the `@airwallex/airi-cli` package, which downloads the prebuilt
23
25
  binary for your platform, verifies its SHA256 checksum, and puts `airi-cli` on
24
26
  your `PATH`.
25
27
 
26
- > **Agent skills:** deploy the bundled agent skills with `airi-cli skills install`
27
- > after installing (see [Skills](#skills)).
28
+ To run it once without installing globally, use npx:
29
+
30
+ ```bash
31
+ npx @airwallex/airi-cli@beta
32
+ ```
33
+
34
+ #### Switching from a `curl | sh` install
35
+
36
+ If you previously installed with the `install.sh` script (via `curl`), remove
37
+ that copy first — otherwise it may stay ahead of the npm one on your `PATH` and
38
+ keep shadowing it, so `airi-cli` keeps running the old binary.
39
+
40
+ Check for more than one `airi-cli` on your `PATH`:
41
+
42
+ ```bash
43
+ which -a airi-cli
44
+ ```
45
+
46
+ If an entry under `~/.local/bin` (the `install.sh` default) shows up alongside
47
+ the npm one, remove the old install:
48
+
49
+ ```bash
50
+ curl -fsSL https://raw.githubusercontent.com/airwallex/airi-cli/master/install.sh | sh -s -- uninstall
51
+ ```
52
+
53
+ Then reopen your shell and re-check with `which -a airi-cli`.
54
+
55
+ ### install.sh (fallback)
56
+
57
+ If npm is not available, install the binary directly with the install script:
58
+
59
+ ```bash
60
+ curl -fsSL https://raw.githubusercontent.com/airwallex/airi-cli/master/install.sh | sh
61
+ ```
62
+
63
+ To uninstall (removes the binary):
64
+
65
+ ```bash
66
+ curl -fsSL https://raw.githubusercontent.com/airwallex/airi-cli/master/install.sh | sh -s -- uninstall
67
+ ```
68
+
69
+ ### Install-time environment variables
28
70
 
29
- Environment variables (install time):
71
+ Both install methods honour the same variables and behave identically, except
72
+ where noted:
30
73
 
31
74
  | Variable | Description |
32
75
  |----------|-------------|
33
- | `AIRI_CLI_VERSION` | Download a specific release tag (e.g. `v0.1.0`) instead of the version bundled with the package. |
34
- | `AIRI_CLI_SKIP_DOWNLOAD` | Set to `1` to skip the binary download during install. |
76
+ | `AIRI_CLI_VERSION` | Install a specific release tag (e.g. `v0.1.0`) instead of the default. With npm the pinned checksum only matches the package's own version, so overriding it there also requires `AIRI_CLI_SKIP_CHECKSUM=1`. |
77
+ | `AIRI_CLI_INSTALL_DIR` | install.sh only: where to install (default: `$HOME/.local/bin`). npm always installs inside the package and ignores this. |
35
78
  | `AIRI_CLI_SKIP_CHECKSUM` | **Local development only.** Set to `1` to bypass SHA256 verification. Never use this in production or CI. |
36
- | `AIRI_CLI_BASE_URL` | Override the release host the binary is downloaded from (for internal mirrors). |
79
+ | `AIRI_CLI_SKIP_SKILLS` | Set to `1` to skip deploying the bundled agent skills. |
80
+
81
+ Both methods deploy the bundled agent skills at install time. You can also
82
+ deploy them to a specific project with:
83
+
84
+ ```bash
85
+ npx skills add airwallex/airi-cli
86
+ ```
87
+
88
+ or re-run deployment any time with `airi-cli skills install` (see
89
+ [Skills](#skills)).
37
90
 
38
91
  ### Checking for updates
39
92
 
@@ -151,6 +204,22 @@ after `auth login`, is:
151
204
 
152
205
  4. **Report the result** — after submitting the checkout, always report the
153
206
  outcome with `airi-cli mandate result --mandate-id <id> --result <SUCCEEDED|CANCELLED|DECLINED>`.
207
+ 5. **Cancel a mandate** — when the user asks to cancel, run
208
+ `airi-cli mandate cancel --mandate-id <id>`. The id is a flag, not a
209
+ positional argument. A cancelled mandate's status becomes `DENIED`. An
210
+ agent should cancel only when the user requests it.
211
+
212
+ ## Browsing mandates
213
+
214
+ `airi-cli mandate list` returns the user's mandates, most recent first. Page
215
+ with `--page` (0-based) and `--size` when `hasMore` is true. Filter with
216
+ repeatable `--status` (`CREATED`, `AUTHENTICATED`, `READY`, `COMPLETED`,
217
+ `FAILED`, `DENIED`) and `--created-from` / `--created-to` (full ISO-8601
218
+ timestamps, for example `2026-10-01T00:00:00Z`).
219
+
220
+ ```bash
221
+ airi-cli mandate list --status READY --size 10 --pretty
222
+ ```
154
223
 
155
224
  ## Commands
156
225
 
@@ -161,7 +230,9 @@ after `auth login`, is:
161
230
  | `airi-cli auth whoami` | Print the current sign-in status. |
162
231
  | `airi-cli auth logout` | Sign out by removing the stored session (local only). |
163
232
  | `airi-cli payment-methods list` | List payment methods available for agentic checkout. |
233
+ | `airi-cli mandate list` | List payment mandates, most recent first. |
164
234
  | `airi-cli mandate create` | Create a payment mandate for a checkout. |
235
+ | `airi-cli mandate cancel` | Cancel a payment mandate (`status` becomes `DENIED`). |
165
236
  | `airi-cli mandate get-credential` | Poll for and fetch the single-use checkout credential. |
166
237
  | `airi-cli mandate result` | Report the transaction outcome for a mandate. |
167
238
  | `airi-cli skills install` | Deploy the bundled agent skills into local AI-agent skill directories. |
@@ -186,6 +257,22 @@ Flags for `airi-cli auth whoami`:
186
257
  | --- | --- | --- |
187
258
  | `--verbose` | `false` | Include device details (name, platform, device id). |
188
259
 
260
+ Flags for `airi-cli mandate list`:
261
+
262
+ | Flag | Default | Description |
263
+ | --- | --- | --- |
264
+ | `--status` | — | Filter by mandate status (repeatable): `CREATED`, `AUTHENTICATED`, `READY`, `COMPLETED`, `FAILED`, `DENIED`. |
265
+ | `--created-from` | — | Include mandates created at or after this ISO-8601 time. |
266
+ | `--created-to` | — | Include mandates created at or before this ISO-8601 time. |
267
+ | `--page` | `0` | Zero-based page number. |
268
+ | `--size` | `10` | Mandates per page (1–100). |
269
+
270
+ Flags for `airi-cli mandate cancel`:
271
+
272
+ | Flag | Description |
273
+ | --- | --- |
274
+ | `--mandate-id` | Mandate ID (required). |
275
+
189
276
  Flags for `airi-cli mandate create` (all required):
190
277
 
191
278
  | Flag | Description |
package/checksums.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "checksums": {
3
- "linux_amd64": "b6f0ea7935b018ef1752ddbde54eee6033b754709972ddffd1be4182b527934f",
4
- "linux_arm64": "595b6f2ee28b8a254ad38d0e3db20947d06c4d0be77afa123348b2ba4bd6b8d4",
5
- "macos_x86_64": "de210b14b727cecaf8f9d2feeb228d8374b3881e4dc52f7572466c13750cc2d5",
6
- "macos_arm64": "11cfeaf377cae47048891735f616b40740b11c92f882d47739bcc035332fe4f0"
3
+ "linux_amd64": "c928039f16658358e493b27ab09710ef8d768552d4b55ffdc2a32375d7b8ce2d",
4
+ "linux_arm64": "267acceccdbecf8de21aabbdc654dc2552aa7f22da8d060a09cd33143bd5096a",
5
+ "macos_x86_64": "2fb413d8c48b0639f548e5a250bce69b95bcc0cd1267ba1758a16472e3bfda91",
6
+ "macos_arm64": "6e617b33e087a12e57e0c601d223aa55e809acbc211abbfa2f9c2ecd4510f25d"
7
7
  }
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@airwallex/airi-cli",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.3",
4
4
  "description": "Command-line tool for the Airi wallet — OAuth sign-in and agentic checkout from your terminal or an AI agent.",
5
5
  "bin": {
6
6
  "airi-cli": "bin/airi-cli.js"
@@ -17,23 +17,22 @@
17
17
  //
18
18
  // Environment variables:
19
19
  // AIRI_CLI_VERSION download this release tag instead of the package's
20
- // own version (e.g. "v0.2.0" or "0.2.0"). The pinned
21
- // digest only matches the package's own version, so
22
- // an override requires AIRI_CLI_SKIP_CHECKSUM.
23
- // AIRI_CLI_SKIP_DOWNLOAD set to "1" to skip the download entirely. Useful
24
- // for offline CI that provides the binary another
25
- // way; the CLI won't run until it is present.
20
+ // own version. The pinned digest only matches the
21
+ // package's own version, so an override also requires
22
+ // AIRI_CLI_SKIP_CHECKSUM.
26
23
  // AIRI_CLI_SKIP_CHECKSUM set to "1" to skip SHA256 verification (local-dev
27
24
  // only — never in production or CI).
28
- // AIRI_CLI_BASE_URL override the release host (internal mirror/testing).
25
+ // AIRI_CLI_SKIP_SKILLS set to "1" to skip deploying the bundled agent skills.
26
+ // AIRI_CLI_BASE_URL (internal, undocumented) override the release host.
27
+ // The e2e tests point it at a local server; kept out
28
+ // of the README so it isn't a supported user knob.
29
29
  //
30
- // The script is resilient by design: a download or verification failure prints
31
- // clear guidance but does NOT hard-fail the install, so installing a larger
32
- // dependency tree is not aborted by a transient network issue. The launcher
33
- // re-reports a missing binary with the same remediation if the CLI is run.
30
+ // A download or verification failure warns but does NOT hard-fail: a transient
31
+ // network issue must not abort a larger `npm install`. The launcher re-reports
32
+ // a missing binary with the same remediation if the CLI is run.
34
33
 
35
34
  import { createWriteStream, existsSync } from 'node:fs'
36
- import { mkdir, mkdtemp, readFile, rm, chmod, rename } from 'node:fs/promises'
35
+ import { mkdir, mkdtemp, readFile, rm, chmod, rename, copyFile } from 'node:fs/promises'
37
36
  import { createHash } from 'node:crypto'
38
37
  import { tmpdir } from 'node:os'
39
38
  import path from 'node:path'
@@ -157,12 +156,29 @@ function extract(tarball, destDir) {
157
156
  if (res.status !== 0) throw new Error(`tar exited ${res.status}`)
158
157
  }
159
158
 
160
- async function main() {
161
- if (process.env.AIRI_CLI_SKIP_DOWNLOAD === '1') {
162
- warn('AIRI_CLI_SKIP_DOWNLOAD=1 — skipping binary download.')
159
+ // Deploy the agent skills bundled in the binary, mirroring install.sh: invoke
160
+ // the freshly installed binary's `skills install`, honouring AIRI_CLI_SKIP_SKILLS.
161
+ // Best-effort — a failure warns but never fails the install (the user can
162
+ // re-run `airi-cli skills install`).
163
+ function deploySkills(bin) {
164
+ if (process.env.AIRI_CLI_SKIP_SKILLS === '1') {
165
+ warn('AIRI_CLI_SKIP_SKILLS=1 — skipping skill deployment.')
163
166
  return
164
167
  }
168
+ log('deploying agent skills')
169
+ // stdio inherited so the CLI's own output — including the target directories
170
+ // it installed into — flows through to the npm install log.
171
+ const res = spawnSync(
172
+ bin,
173
+ ['--no-telemetry', '-o', 'text', 'skills', 'install'],
174
+ { stdio: 'inherit' }
175
+ )
176
+ if (res.error || res.status !== 0) {
177
+ warn(`skill deployment failed; retry later with: ${BIN_NAME} skills install`)
178
+ }
179
+ }
165
180
 
181
+ async function main() {
166
182
  let platform
167
183
  try {
168
184
  platform = detectPlatform()
@@ -230,18 +246,19 @@ async function main() {
230
246
  throw new Error(`archive did not contain expected '${BIN_NAME}' binary`)
231
247
  }
232
248
  const finalPath = binPath()
233
- // Stage the new binary INSIDE the vendor dir (same filesystem as finalPath)
234
- // and rename it into place. Renaming within one filesystem is atomic and
235
- // avoids EXDEV (which a rename from os.tmpdir() across filesystems would
236
- // hit) — and because the staged copy is fully in place and executable
237
- // before the swap, a failure never leaves the old working binary deleted
238
- // with no replacement.
249
+ // copyFile (not rename) crosses devices without EXDEV; staging inside the
250
+ // vendor dir keeps the final swap a same-device atomic rename, so a failure
251
+ // never leaves the old working binary deleted with no replacement.
239
252
  const staged = path.join(dir, `.${BIN_NAME}.new`)
240
253
  await rm(staged, { force: true })
241
- await rename(extracted, staged)
254
+ await copyFile(extracted, staged)
242
255
  await chmod(staged, 0o755)
243
256
  await rename(staged, finalPath)
244
- log(`installed binary to ${finalPath}`)
257
+ log(`installed ${BIN_NAME} ${tag}`)
258
+
259
+ // Only after the binary is verified and in place, so skills are never
260
+ // deployed from a half-installed or unverified CLI.
261
+ deploySkills(finalPath)
245
262
  } catch (err) {
246
263
  warn(`failed to download the airi-cli binary: ${err.message}`)
247
264
  warn(