@aeon-ai-pay/aigateway 0.2.3 → 0.2.4
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 +20 -0
- package/docs/env-vars.md +12 -14
- package/docs/exit-codes.md +25 -15
- package/docs/ide-setup.md +2 -2
- package/docs/output-schema.md +73 -58
- package/docs/recipes/cron-issue-cards.md +34 -16
- package/docs/recipes/error-recovery.md +47 -16
- package/docs/recipes/integrate-in-agent.md +37 -16
- package/docs/recipes/merchant-integration.md +61 -32
- package/docs/troubleshooting.md +61 -13
- package/package.json +11 -5
- package/skills/aigateway/SKILL.md +5 -2
- package/src/commands/sb-invoke.mjs +13 -1
- package/src/commands/wallet-init.mjs +27 -1
- package/src/config.mjs +13 -0
- package/src/constants.mjs +3 -0
- package/src/coupon.mjs +62 -0
- package/templates/cline/.clinerules +36 -18
- package/templates/codex/AGENTS.md +48 -16
- package/templates/cursor/.cursor/rules/aigateway.mdc +27 -14
- package/templates/windsurf/.windsurfrules +24 -13
package/README.md
CHANGED
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
>
|
|
5
5
|
> **Zero API keys · Zero prepay · x402 protocol pay-per-call · Natural-language driven**
|
|
6
6
|
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚀 AEON x BNB Chain: AI Agent Campaign
|
|
10
|
+
|
|
11
|
+
> **Your AI agent is ready to work — now let it pay.**
|
|
12
|
+
|
|
13
|
+
AEON and **BNB Chain** are launching the **AI Agent Campaign**, opening up a native payment rail for autonomous AI agents on BNB Chain. With BNB assets, your agent can now call LLMs, APIs, skills, and compute resources — and settle instantly on-chain.
|
|
14
|
+
|
|
15
|
+
**How it works**
|
|
16
|
+
|
|
17
|
+
Agents pay with BNB-native assets through AEON's infrastructure. Every API call, every model inference, every skill invocation — settled seamlessly, no human in the loop.
|
|
18
|
+
|
|
19
|
+
**🎁 First 1,000 users get $5 USDT in free credits** to start using AEON Skills and experience what agentic commerce actually feels like.
|
|
20
|
+
|
|
21
|
+
Build agents that don't just think — but **transact**.
|
|
22
|
+
|
|
23
|
+
→ **[Claim your $5 free credits (Google Form)](https://docs.google.com/forms/d/e/1FAIpQLSe8WF6-Y8Sh2AEC_hEGScyl_gQRahPYWPMDewdXJlfeVENENg/viewform?usp=publish-editor)** · Deploy your agent. Let it run.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
7
27
|
`@aeon-ai-pay/aigateway` is a unified CLI + Agent Skill. Through a single session-key wallet and the [x402 protocol](https://www.x402.org/), it opens up SkillBoss's 200+ tool capabilities (image / video / audio / search / scraping / email / document / social data / UI generation, etc.) to AI Agents for pay-per-call invocation.
|
|
8
28
|
|
|
9
29
|
---
|
package/docs/env-vars.md
CHANGED
|
@@ -4,9 +4,8 @@ All environment variables that affect the `aigateway` CLI. Resolution priority f
|
|
|
4
4
|
|
|
5
5
|
| Variable | Used by | Default | Purpose |
|
|
6
6
|
| --- | --- | --- | --- |
|
|
7
|
-
| `AIGATEWAY_SERVICE_URL` | All
|
|
7
|
+
| `AIGATEWAY_SERVICE_URL` | All commands that talk to the gateway (`sb invoke`, `sb tools`, `wallet-init`, `wallet-topup`, `wallet-balance`) | `https://ai-api.aeon.xyz` | Override the x402 service base URL. Useful for staging / local backends. |
|
|
8
8
|
| `EVM_PRIVATE_KEY` | All commands needing a session key | (read from config file) | Override the saved session key. Required when running in custodial / containerised mode where you don't want a config file on disk. **Treat as a secret.** |
|
|
9
|
-
| `AICARD_LEGACY_NOOP` | — | — | Reserved. Not currently used. |
|
|
10
9
|
|
|
11
10
|
## Config file
|
|
12
11
|
|
|
@@ -26,22 +25,18 @@ All environment variables that affect the `aigateway` CLI. Resolution priority f
|
|
|
26
25
|
- `privateKey` / `address` / `mode` — written by `wallet-init` when auto-generating a session key.
|
|
27
26
|
- `mainWallet` — auto-recorded after a successful `wallet-topup` so `wallet-withdraw` can default to that address.
|
|
28
27
|
|
|
29
|
-
##
|
|
28
|
+
## Priority example
|
|
30
29
|
|
|
31
30
|
```bash
|
|
32
|
-
#
|
|
33
|
-
AIGATEWAY_SERVICE_URL=https://
|
|
34
|
-
aigateway
|
|
35
|
-
|
|
36
|
-
# Only env set
|
|
37
|
-
AIGATEWAY_SERVICE_URL=https://staging.example.com \
|
|
38
|
-
aigateway create-card --amount 5
|
|
31
|
+
# Env var wins over config file
|
|
32
|
+
AIGATEWAY_SERVICE_URL=https://staging-x402.aeon.xyz \
|
|
33
|
+
aigateway sb invoke --model <id> --inputs '<json>'
|
|
39
34
|
|
|
40
35
|
# Nothing set → built-in default https://ai-api.aeon.xyz
|
|
41
|
-
aigateway
|
|
36
|
+
aigateway sb invoke --model <id> --inputs '<json>'
|
|
42
37
|
```
|
|
43
38
|
|
|
44
|
-
|
|
39
|
+
There is no `--service-url` CLI flag — use the env var or edit the config file directly.
|
|
45
40
|
|
|
46
41
|
## Production hardening
|
|
47
42
|
|
|
@@ -60,11 +55,14 @@ aigateway wallet-init
|
|
|
60
55
|
|
|
61
56
|
# Custodial server (key from Vault, no config file)
|
|
62
57
|
EVM_PRIVATE_KEY=$(vault kv get -field=key merchants/acme-prod) \
|
|
63
|
-
aigateway
|
|
58
|
+
aigateway sb invoke \
|
|
59
|
+
--model replicate/black-forest-labs/flux-schnell \
|
|
60
|
+
--inputs '{"prompt":"a cyberpunk fox"}' \
|
|
61
|
+
--app-id MERCHANT_ACME_001
|
|
64
62
|
|
|
65
63
|
# Staging
|
|
66
64
|
AIGATEWAY_SERVICE_URL=https://staging-x402.aeon.xyz \
|
|
67
|
-
aigateway
|
|
65
|
+
aigateway sb tools --category image --app-id YOUR_TEST_APPID
|
|
68
66
|
|
|
69
67
|
# Both
|
|
70
68
|
AIGATEWAY_SERVICE_URL=https://staging-x402.aeon.xyz \
|
package/docs/exit-codes.md
CHANGED
|
@@ -6,13 +6,13 @@ The `aigateway` CLI returns a stable exit code that maps to the category of outc
|
|
|
6
6
|
| ---: | -------- | ------- |
|
|
7
7
|
| `0` | Success | Command completed and produced an `ok: true` envelope. |
|
|
8
8
|
| `1` | User error | Validation, configuration, balance, or user-side rejection. Caller should fix input and retry. |
|
|
9
|
-
| `2` | Timeout | Polling, WalletConnect, signature, or on-chain wait exceeded its limit. The underlying operation may still complete asynchronously
|
|
9
|
+
| `2` | Timeout | Polling, WalletConnect, signature, or on-chain wait exceeded its limit. The underlying operation may still complete asynchronously. |
|
|
10
10
|
| `3` | Service / network | Upstream service unavailable, network error, on-chain revert. Generally retryable after backoff. |
|
|
11
11
|
| `4` | Internal | Unexpected internal error in the CLI. Please file an issue if reproducible. |
|
|
12
12
|
|
|
13
13
|
## Error Code Reference
|
|
14
14
|
|
|
15
|
-
The full set of `error.code` values
|
|
15
|
+
The full set of `error.code` values is defined in [`src/error-codes.mjs`](../src/error-codes.mjs); the table below mirrors that file.
|
|
16
16
|
|
|
17
17
|
### Exit 1 — User Error
|
|
18
18
|
|
|
@@ -20,17 +20,25 @@ The full set of `error.code` values, grouped by exit code, is defined in [`src/e
|
|
|
20
20
|
| ---- | ---- |
|
|
21
21
|
| `WALLET_NOT_CONFIGURED` | No local wallet. Run `aigateway wallet-init`. |
|
|
22
22
|
| `SERVICE_URL_MISSING` | Service URL not configured. |
|
|
23
|
-
| `AMOUNT_INVALID` | Amount could not be parsed. |
|
|
24
|
-
| `
|
|
25
|
-
| `AMOUNT_EXCEEDS_BALANCE` | `withdraw --amount` exceeds available USDT. |
|
|
23
|
+
| `AMOUNT_INVALID` | Amount could not be parsed (e.g. `wallet-topup --amount`, `--topup-amount`). |
|
|
24
|
+
| `AMOUNT_EXCEEDS_BALANCE` | `wallet-withdraw --amount` exceeds available USDT. |
|
|
26
25
|
| `INSUFFICIENT_USDT` | USDT balance still insufficient after funding. |
|
|
27
26
|
| `INSUFFICIENT_BNB` | No BNB for approve / withdraw gas. |
|
|
28
|
-
| `NO_FUNDS` | Session wallet has zero USDT and zero BNB. |
|
|
27
|
+
| `NO_FUNDS` | Session wallet has zero USDT and zero BNB (withdraw context). |
|
|
29
28
|
| `NO_MAIN_WALLET` | `wallet-withdraw` invoked without `--to` and no `mainWallet` in config. |
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
29
|
+
| `MISSING_MODEL` | `sb invoke` invoked without `--model`. |
|
|
30
|
+
| `MISSING_INPUTS` | `sb invoke --inputs` is missing, or required fields are absent. `error.errors[]` lists which. |
|
|
31
|
+
| `INVALID_INPUTS` | Inputs failed schema validation. `error.errors[].kind ∈ {enum, type, range}`. |
|
|
32
|
+
| `INVALID_INPUTS_JSON` | `--inputs` could not be parsed as JSON. |
|
|
33
|
+
| `INPUTS_FILE_NOT_FOUND` | `--inputs @path` file does not exist. |
|
|
34
|
+
| `INVALID_MODEL_ID` | Catalog or server rejected the model id. |
|
|
35
|
+
| `CATEGORY_NOT_FOUND` | `sb tools --category` argument not in the live catalog. |
|
|
36
|
+
| `MODEL_PRICING_NOT_CONFIGURED` | Catalog lists the model but the gateway has no price entry yet. |
|
|
37
|
+
| `INVALID_BODY` | Server rejected the request body shape. |
|
|
38
|
+
| `TOPUP_REQUIRED` | Non-TTY context, USDT below the per-call minimum. Choose from `error.presets` (filtered to ≥ `error.minTopup`) and rerun the failing command with `--topup-amount <n>` (or `wallet-topup --amount <n>`). |
|
|
39
|
+
| `TOPUP_AMOUNT_TOO_SMALL` | `--topup-amount` (or `topup --amount`) below `error.minTopup`. |
|
|
33
40
|
| `PAYMENT_REJECTED` | User rejected the transaction in their wallet. |
|
|
41
|
+
| `WALLET_ERROR` | Generic wallet operation failure (treated as user-resolvable). |
|
|
34
42
|
|
|
35
43
|
### Exit 2 — Timeout
|
|
36
44
|
|
|
@@ -38,9 +46,8 @@ The full set of `error.code` values, grouped by exit code, is defined in [`src/e
|
|
|
38
46
|
| ---- | ---- |
|
|
39
47
|
| `PAYMENT_TIMEOUT` | WalletConnect / signature request timed out (5 minutes). |
|
|
40
48
|
| `WC_SESSION_EXPIRED` | WalletConnect session dropped mid-flow. |
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `UPDATE_APPLIED` | The CLI just upgraded itself synchronously to a newer version. The previous command was not executed — the caller (or the agent) must rerun it on the new version. Envelope carries `error.from` / `error.to` showing the version transition. |
|
|
49
|
+
| `TX_TIMEOUT` | On-chain receipt wait exceeded its limit. |
|
|
50
|
+
| `UPDATE_APPLIED` | The CLI just upgraded itself synchronously to a newer version. The previous command was **not executed** — the caller (or the agent) must rerun it on the new version. Envelope carries `error.from` / `error.to` showing the version transition. |
|
|
44
51
|
|
|
45
52
|
### Exit 3 — Service / Network
|
|
46
53
|
|
|
@@ -48,13 +55,15 @@ The full set of `error.code` values, grouped by exit code, is defined in [`src/e
|
|
|
48
55
|
| ---- | ---- |
|
|
49
56
|
| `SERVICE_UNAVAILABLE` | Generic upstream / network failure. |
|
|
50
57
|
| `PAYMENT_FETCH_FAILED` | First 402 request to the service failed. |
|
|
58
|
+
| `CATALOG_FETCH_FAILED` | `sb tools` could not fetch the catalog from the server. |
|
|
51
59
|
| `BALANCE_CHECK_FAILED` | RPC query to BSC failed. |
|
|
52
60
|
| `ALLOWANCE_CHECK_FAILED` | RPC `allowance()` query failed. |
|
|
53
61
|
| `TX_REVERTED` | On-chain transaction reverted. |
|
|
54
62
|
| `WITHDRAW_FAILED` | Withdraw transaction failed (revert / RPC). |
|
|
55
|
-
| `APPROVE_FAILED` | `wallet-
|
|
63
|
+
| `APPROVE_FAILED` | `wallet-topup` could not broadcast or confirm the facilitator `approve()` tx. |
|
|
56
64
|
| `FUNDING_FAILED` | WalletConnect funding flow failed (non-timeout / non-reject path). |
|
|
57
|
-
| `IMAGE_DOWNLOAD_FAILED` | Generated image URL returned a non-200 / timed out. |
|
|
65
|
+
| `IMAGE_DOWNLOAD_FAILED` | Generated image URL returned a non-200 / timed out. (Legacy alias; `sb invoke` now also emits `DOWNLOAD_FAILED` for non-image artifacts.) |
|
|
66
|
+
| `DOWNLOAD_FAILED` | `sb invoke` could not save a binary artifact (image / video / audio) to disk. The upstream URL is still available in `data.downloaded[].url`. |
|
|
58
67
|
| `INVALID_PAYMENT_AMOUNT` | Service returned a 402 with `amount === 0`. |
|
|
59
68
|
| `PAYMENT_FAILED` | Service rejected the signed payment request. |
|
|
60
69
|
|
|
@@ -63,4 +72,5 @@ The full set of `error.code` values, grouped by exit code, is defined in [`src/e
|
|
|
63
72
|
| Code | When |
|
|
64
73
|
| ---- | ---- |
|
|
65
74
|
| `INTERNAL_ERROR` | Unexpected error inside the CLI. |
|
|
66
|
-
|
|
75
|
+
|
|
76
|
+
> Note: `WALLET_ERROR` is defined alongside the timeout block in `error-codes.mjs` but its exit code is `1` (user-resolvable), so it appears under Exit 1 above.
|
package/docs/ide-setup.md
CHANGED
|
@@ -55,6 +55,6 @@ For Claude Code, OpenClaw, Gemini CLI, GitHub Copilot, and 30+ others, the [skil
|
|
|
55
55
|
|
|
56
56
|
After installation, in your IDE chat say:
|
|
57
57
|
|
|
58
|
-
>
|
|
58
|
+
> Generate me an image of a cyberpunk fox.
|
|
59
59
|
|
|
60
|
-
The agent should propose running `aigateway wallet-init` (one-time, auto-creates a wallet)
|
|
60
|
+
The agent should propose running `aigateway wallet-init` (one-time, auto-creates a wallet), then `aigateway sb tools --category image` to pick a model, then `aigateway sb invoke --model <id> --inputs '{"prompt":"cyberpunk fox"}'`. If it doesn't, the rule file isn't being picked up — check that the file path matches what your IDE expects and that the IDE has been restarted.
|
package/docs/output-schema.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Output Schema
|
|
2
2
|
|
|
3
|
-
Every `aigateway` command emits **exactly one line of JSON** to **stdout**
|
|
3
|
+
Every `aigateway` command emits **exactly one line of JSON** to **stdout** — the *envelope*. Human-readable progress logs go to **stderr** and can be safely ignored by programmatic consumers.
|
|
4
4
|
|
|
5
5
|
> Pass `--quiet` to suppress non-error stderr. Pass `--legacy-output` to fall back to the pre-envelope shape (see [Legacy mode](#legacy-mode)).
|
|
6
6
|
|
|
@@ -11,8 +11,8 @@ Every `aigateway` command emits **exactly one line of JSON** to **stdout** —
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
13
13
|
"ok": true,
|
|
14
|
-
"command": "
|
|
15
|
-
"version": "
|
|
14
|
+
"command": "sb-invoke",
|
|
15
|
+
"version": "x.y.z",
|
|
16
16
|
"data": { /* command-specific payload */ }
|
|
17
17
|
}
|
|
18
18
|
```
|
|
@@ -22,20 +22,21 @@ Every `aigateway` command emits **exactly one line of JSON** to **stdout** —
|
|
|
22
22
|
```json
|
|
23
23
|
{
|
|
24
24
|
"ok": false,
|
|
25
|
-
"command": "
|
|
26
|
-
"version": "
|
|
25
|
+
"command": "sb-invoke",
|
|
26
|
+
"version": "x.y.z",
|
|
27
27
|
"error": {
|
|
28
|
-
"code": "
|
|
29
|
-
"message": "
|
|
30
|
-
"
|
|
31
|
-
"
|
|
28
|
+
"code": "MISSING_INPUTS",
|
|
29
|
+
"message": "Inputs validation failed for ...",
|
|
30
|
+
"errors": [{ "field": "prompt", "kind": "missing", "message": "..." }],
|
|
31
|
+
"required": ["prompt"],
|
|
32
|
+
"properties": ["prompt", "aspect_ratio", "num_outputs"]
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
- `error.code` is a stable identifier from [`src/error-codes.mjs`](../src/error-codes.mjs) — see [exit-codes.md](./exit-codes.md) for the full list.
|
|
37
38
|
- `error.message` is human-readable and may change between versions; **do not** match on it for control flow.
|
|
38
|
-
- Additional fields under `error` are command-specific context (e.g. `min` / `max` / `address` / `required` / `available`).
|
|
39
|
+
- Additional fields under `error` are command-specific context (e.g. `min` / `max` / `address` / `required` / `available` / `errors[]` / `presets`).
|
|
39
40
|
|
|
40
41
|
## Per-Command `data` Payloads
|
|
41
42
|
|
|
@@ -49,8 +50,14 @@ Every `aigateway` command emits **exactly one line of JSON** to **stdout** —
|
|
|
49
50
|
"mode": "private-key",
|
|
50
51
|
"address": "0x...",
|
|
51
52
|
"mainWallet": "0x..." | null,
|
|
52
|
-
"
|
|
53
|
-
"
|
|
53
|
+
"usdt": "5.0",
|
|
54
|
+
"bnb": "0.0003",
|
|
55
|
+
"allowance": "115792...max" | "0",
|
|
56
|
+
"needsTopup": false,
|
|
57
|
+
"topupReason": null | "first_time" | "low_balance" | "no_approve" | "chain_check_failed",
|
|
58
|
+
"minTopup": 5,
|
|
59
|
+
"presets": [5, 10, 20, 50],
|
|
60
|
+
"serviceUrl": "https://..."
|
|
54
61
|
}
|
|
55
62
|
```
|
|
56
63
|
|
|
@@ -70,72 +77,80 @@ Every `aigateway` command emits **exactly one line of JSON** to **stdout** —
|
|
|
70
77
|
}
|
|
71
78
|
```
|
|
72
79
|
|
|
73
|
-
### `
|
|
80
|
+
### `sb invoke`
|
|
74
81
|
|
|
75
82
|
```json
|
|
76
83
|
{
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
84
|
+
"model": "replicate/black-forest-labs/flux-schnell",
|
|
85
|
+
"inputs": { "prompt": "...", "aspect_ratio": "1:1" },
|
|
86
|
+
"transaction": "0x..." | null,
|
|
87
|
+
"downloaded": [
|
|
88
|
+
{
|
|
89
|
+
"url": "https://...",
|
|
90
|
+
"localPath": "/home/.../aigateway-images/...png",
|
|
91
|
+
"format": "png",
|
|
92
|
+
"width": 1024,
|
|
93
|
+
"height": 1024,
|
|
94
|
+
"sizeBytes": 412345,
|
|
95
|
+
"sizeHuman": "402.7 KB"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"raw": { /* upstream vendor response, unwrapped from { payer, transaction, data } */ },
|
|
99
|
+
"paymentResponse": { "txHash": "0x...", "payer": "0x...", "...": "..." },
|
|
100
|
+
"balance": {
|
|
101
|
+
"initial": "5.0",
|
|
102
|
+
"before": "5.0",
|
|
103
|
+
"after": "4.99",
|
|
104
|
+
"charged": 0.01,
|
|
105
|
+
"topup": null | "5"
|
|
106
|
+
}
|
|
82
107
|
}
|
|
83
108
|
```
|
|
84
109
|
|
|
85
|
-
|
|
110
|
+
- **Binary outputs** (image / video / audio) populate `downloaded[]`. With `--raw` the auto-download is skipped and `downloaded[]` stays empty; the URLs live in `raw`.
|
|
111
|
+
- **JSON-only outputs** (search, scraper, social_data, email, etc.) leave `downloaded` empty; consumers read `raw`.
|
|
112
|
+
- `balance.charged` is the live USDT amount taken for this call (computed server-side as `priceUnit × inputs usage`).
|
|
113
|
+
|
|
114
|
+
Failure shapes carry extra fields per code, e.g.:
|
|
86
115
|
|
|
87
116
|
```json
|
|
88
117
|
{
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
118
|
+
"ok": false,
|
|
119
|
+
"command": "sb-invoke",
|
|
120
|
+
"error": {
|
|
121
|
+
"code": "TOPUP_REQUIRED",
|
|
122
|
+
"message": "USDT balance is below the 5 USDT minimum...",
|
|
123
|
+
"minTopup": 5,
|
|
124
|
+
"required": 0.01,
|
|
125
|
+
"currentBalance": "0",
|
|
126
|
+
"address": "0x...",
|
|
127
|
+
"presets": [5, 10, 20, 50],
|
|
128
|
+
"hint": "Rerun: aigateway wallet-topup --amount <usdt> --app-id ..."
|
|
129
|
+
}
|
|
99
130
|
}
|
|
100
131
|
```
|
|
101
132
|
|
|
102
|
-
|
|
133
|
+
### `sb tools`
|
|
103
134
|
|
|
104
|
-
|
|
105
|
-
{
|
|
106
|
-
"dryRun": true,
|
|
107
|
-
"url": "...",
|
|
108
|
-
"paymentRequirements": { "amountUsdt": 0.66, "amountWei": "660000000000000000", "asset": "0x...", "payTo": "0x...", "orderNo": "..." },
|
|
109
|
-
"wallet": { "address": "0x..." },
|
|
110
|
-
"decision": { "needTopup": true, "needGas": false, "topupAmount": "0.660000" },
|
|
111
|
-
"will": ["fund_usdt_via_walletconnect", "approve_or_skip", "sign_payment_eip712", "submit_to_facilitator", "poll_status"]
|
|
112
|
-
}
|
|
113
|
-
```
|
|
135
|
+
`data` shape depends on the filters supplied:
|
|
114
136
|
|
|
115
|
-
|
|
137
|
+
| Invocation | `data.mode` | Shape |
|
|
138
|
+
| --- | --- | --- |
|
|
139
|
+
| `sb tools` | (absent) | Full catalog: `{ categories: [{ key, agentTrigger, defaultInputsSchema, models: [...] }], version, ... }` |
|
|
140
|
+
| `sb tools --model <id>` | `"single-model"` | `{ category: "<key>", model: { id, vendor, useCase, price, priceUnit, tier, inputsOverride? }, effectiveSchema: { ... } }` |
|
|
141
|
+
| `sb tools --category <key>` | `"single-category"` | `{ category: { key, agentTrigger, defaultInputsSchema, models: [...] } }` |
|
|
142
|
+
| `sb tools --tier <t>` (alone) | `"tier-filtered"` | Full catalog with each category's `models[]` filtered to `tier === t`, plus `tier: "<t>"` |
|
|
116
143
|
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
"success": true,
|
|
120
|
-
"model": {
|
|
121
|
-
"orderNo": "...",
|
|
122
|
-
"orderStatus": "SUCCESS" | "FAIL" | "PROCESSING" | "...",
|
|
123
|
-
"channelStatus": "...",
|
|
124
|
-
"cardStatus": "ACTIVE" | "PENDING" | "...",
|
|
125
|
-
"cardScheme": "VISA" | "MASTERCARD",
|
|
126
|
-
"cardNumber": "•••• 1234",
|
|
127
|
-
"...": "(sensitive fields like CVV / expiry are stripped)"
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
144
|
+
`effectiveSchema` = `model.inputsOverride ?? category.defaultInputsSchema` — the JSON-schema-shaped object that `sb invoke` validates against client-side.
|
|
131
145
|
|
|
132
|
-
### `wallet`
|
|
146
|
+
### `wallet-balance`
|
|
133
147
|
|
|
134
148
|
```json
|
|
135
149
|
{
|
|
136
150
|
"mode": "private-key",
|
|
137
151
|
"address": "0x...",
|
|
138
152
|
"usdt": "12.34",
|
|
153
|
+
"bnb": "0.0003",
|
|
139
154
|
"network": "BSC Mainnet (Chain ID: 56)",
|
|
140
155
|
"mainWallet": { "address": "0x...", "usdt": "..." }
|
|
141
156
|
}
|
|
@@ -182,7 +197,7 @@ Every `aigateway` command emits **exactly one line of JSON** to **stdout** —
|
|
|
182
197
|
For consumers still parsing the pre-envelope JSON shape, pass `--legacy-output` to get the old format on stdout (and errors on **stderr** as before):
|
|
183
198
|
|
|
184
199
|
```bash
|
|
185
|
-
aigateway --legacy-output
|
|
200
|
+
aigateway --legacy-output wallet-balance
|
|
186
201
|
```
|
|
187
202
|
|
|
188
|
-
Legacy mode is kept
|
|
203
|
+
Legacy mode is kept as a migration aid. New integrations should use the envelope.
|
|
@@ -1,31 +1,38 @@
|
|
|
1
|
-
# Recipe — Schedule Recurring
|
|
1
|
+
# Recipe — Schedule Recurring Paid Invocations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Filename kept for backwards compatibility. The earlier "issue card" workflow has been folded into the unified `aigateway sb invoke` entry point; this recipe now covers any scheduled paid call.
|
|
4
|
+
|
|
5
|
+
Use this when an agent or automation needs to invoke a paid AI tool on a schedule — for example, "generate a marketing image every Monday at 09:00", "transcribe yesterday's recordings nightly", "run a search summarisation every hour".
|
|
4
6
|
|
|
5
7
|
## Prerequisites
|
|
6
8
|
|
|
7
9
|
1. **Pre-funded session wallet.** WalletConnect requires a browser; cron jobs run headless. Top up the local wallet manually first:
|
|
8
10
|
```bash
|
|
9
|
-
aigateway wallet-topup --amount 50 # adds USDT + a tiny amount of BNB for approve
|
|
11
|
+
aigateway wallet-topup --amount 50 # adds USDT + a tiny amount of BNB for the one-time approve
|
|
10
12
|
```
|
|
11
|
-
2. **
|
|
13
|
+
2. **Approve already broadcast.** `wallet-topup` performs the one-time `ERC20.approve(facilitator, MaxUint256)`. After it succeeds, all subsequent `sb invoke` calls are gasless EIP-712 signing — no WalletConnect needed until USDT is depleted.
|
|
14
|
+
3. **Catalog sanity-check.** Before scheduling, run `aigateway sb tools --model <id>` once to confirm the model id is valid and to learn its `effectiveSchema` (so your wrapper builds the correct `--inputs`).
|
|
12
15
|
|
|
13
16
|
## A Minimal Wrapper Script
|
|
14
17
|
|
|
15
|
-
`~/bin/
|
|
18
|
+
`~/bin/invoke-tool.sh`:
|
|
16
19
|
|
|
17
20
|
```bash
|
|
18
21
|
#!/usr/bin/env bash
|
|
19
22
|
set -euo pipefail
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
MODEL="${1:?model id required}"
|
|
25
|
+
INPUTS_FILE="${2:?path to inputs JSON required}" # e.g. ~/aigateway/jobs/daily-image.json
|
|
22
26
|
LOG_DIR="${HOME}/.aigateway/logs"
|
|
23
27
|
mkdir -p "$LOG_DIR"
|
|
24
28
|
TS=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
|
|
25
|
-
LOG="$LOG_DIR/
|
|
29
|
+
LOG="$LOG_DIR/invoke-${TS}.log"
|
|
26
30
|
|
|
27
31
|
# Capture envelope on stdout; quiet stderr noise
|
|
28
|
-
ENVELOPE=$(aigateway --quiet
|
|
32
|
+
ENVELOPE=$(aigateway --quiet sb invoke \
|
|
33
|
+
--model "$MODEL" \
|
|
34
|
+
--inputs "@${INPUTS_FILE}" \
|
|
35
|
+
2>"$LOG")
|
|
29
36
|
EXIT=$?
|
|
30
37
|
|
|
31
38
|
echo "$ENVELOPE" > "${LOG%.log}.json"
|
|
@@ -37,19 +44,26 @@ if [ "$EXIT" -ne 0 ]; then
|
|
|
37
44
|
exit "$EXIT"
|
|
38
45
|
fi
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
echo "
|
|
47
|
+
TX=$(echo "$ENVELOPE" | jq -r '.data.transaction // "—"')
|
|
48
|
+
FIRST=$(echo "$ENVELOPE" | jq -r '.data.downloaded[0].localPath // empty')
|
|
49
|
+
echo "[$(date -u)] OK tx=$TX file=${FIRST:-n/a} model=$MODEL"
|
|
42
50
|
```
|
|
43
51
|
|
|
44
52
|
```bash
|
|
45
|
-
chmod +x ~/bin/
|
|
53
|
+
chmod +x ~/bin/invoke-tool.sh
|
|
46
54
|
```
|
|
47
55
|
|
|
48
56
|
## Cron Entry
|
|
49
57
|
|
|
50
58
|
```cron
|
|
51
59
|
# minute hour dom mon dow command
|
|
52
|
-
0 9 * * 1 /Users/me/bin/
|
|
60
|
+
0 9 * * 1 /Users/me/bin/invoke-tool.sh replicate/black-forest-labs/flux-schnell /Users/me/aigateway/jobs/weekly-image.json >> /Users/me/.aigateway/logs/cron.log 2>&1
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Example `weekly-image.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{ "prompt": "neon city skyline at dusk, hyper-detailed", "aspect_ratio": "16:9" }
|
|
53
67
|
```
|
|
54
68
|
|
|
55
69
|
> ⚠️ On macOS, `cron` may lack PATH access to `aigateway`. Use an absolute path (`/Users/me/.nvm/versions/node/v25/bin/aigateway`) or source your shell rc inside the wrapper.
|
|
@@ -58,12 +72,16 @@ chmod +x ~/bin/issue-card.sh
|
|
|
58
72
|
|
|
59
73
|
| Code | Likely cause in cron context | Fix |
|
|
60
74
|
| ---- | ---------------------------- | --- |
|
|
61
|
-
| `INSUFFICIENT_USDT` | Wallet ran dry. | Top up via `aigateway wallet-
|
|
62
|
-
| `INSUFFICIENT_BNB` |
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
75
|
+
| `INSUFFICIENT_USDT` / `TOPUP_REQUIRED` | Wallet ran dry. Headless cron cannot scan a QR. | Top up via `aigateway wallet-topup --amount <n>` on a workstation. |
|
|
76
|
+
| `INSUFFICIENT_BNB` | BNB depleted (only matters for `wallet-withdraw` / re-approve). | Run `aigateway wallet-gas` interactively on a workstation. |
|
|
77
|
+
| `INVALID_MODEL_ID` | The model id was renamed or removed upstream. | Run `aigateway sb tools` and update the wrapper's `--model`. |
|
|
78
|
+
| `MISSING_INPUTS` / `INVALID_INPUTS` | Inputs file drifted from the schema (e.g. missing `duration_seconds` for video / `duration_minutes` for STT). | Re-pull `sb tools --model <id>` and fix the JSON. |
|
|
79
|
+
| `MODEL_PRICING_NOT_CONFIGURED` | Upstream removed the model from the pricing config. | Pick another model. |
|
|
80
|
+
| `SERVICE_UNAVAILABLE` / `PAYMENT_FETCH_FAILED` | Upstream outage. | Cron will retry next tick. Alert if 3+ consecutive failures. |
|
|
81
|
+
| `PAYMENT_TIMEOUT` | WalletConnect was unexpectedly triggered (should not happen once approve is on-chain). | Run an interactive `aigateway wallet-topup` once to re-fund / re-approve. |
|
|
65
82
|
|
|
66
83
|
## See Also
|
|
67
84
|
|
|
68
85
|
- [integrate-in-agent.md](./integrate-in-agent.md) — Node.js / Python subprocess wrapper.
|
|
69
86
|
- [error-recovery.md](./error-recovery.md) — Full code-by-code recovery table.
|
|
87
|
+
- [../output-schema.md](../output-schema.md) — `sb invoke` envelope fields used above (`transaction`, `downloaded[]`, `balance`).
|
|
@@ -6,25 +6,40 @@ Map each `error.code` returned by the envelope to a concrete recovery action. Us
|
|
|
6
6
|
| ------------ | :--: | -------------------- |
|
|
7
7
|
| `WALLET_NOT_CONFIGURED` | 1 | Run `aigateway wallet-init` once (auto-creates a local session wallet). |
|
|
8
8
|
| `SERVICE_URL_MISSING` | 1 | Override via env `AIGATEWAY_SERVICE_URL`. The default service URL is wired into the CLI for production; this should never trigger in normal use. |
|
|
9
|
-
| `AMOUNT_INVALID` | 1 | Caller bug — input must be a numeric string. |
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
9
|
+
| `AMOUNT_INVALID` | 1 | Caller bug — input must be a positive numeric string (used by `wallet-topup`, `wallet-gas`, `wallet-withdraw`, `--topup-amount`). |
|
|
10
|
+
| `AMOUNT_EXCEEDS_BALANCE` | 1 | `wallet-withdraw --amount` exceeded available USDT. Use the smaller of requested vs. `error.available`. |
|
|
11
|
+
| `INSUFFICIENT_USDT` | 1 | Top-up failed or the chosen `--topup-amount` was still below the call's required USDT. Surface `error.required` / `error.available`; ask the user to retry with a larger top-up. |
|
|
12
|
+
| `INSUFFICIENT_BNB` | 1 | Approve / withdraw needs BNB for gas. Run `aigateway wallet-gas` (WalletConnect, must be interactive), then retry. |
|
|
13
|
+
| `NO_FUNDS` | 1 | Nothing to withdraw. Inform the user; suggest `wallet-topup` if relevant. |
|
|
14
|
+
| `NO_MAIN_WALLET` | 1 | `wallet-withdraw` invoked with no `mainWallet` saved. Re-run with `--to <address>`. |
|
|
15
|
+
| `MISSING_MODEL` | 1 | `sb invoke --model` is required. Run `aigateway sb tools` to pick one. |
|
|
16
|
+
| `MISSING_INPUTS` | 1 | `sb invoke --inputs` is required, or the JSON is missing required fields. `error.errors[]` lists which fields are missing; `error.required[]` lists all required keys for the model. |
|
|
17
|
+
| `INVALID_INPUTS` | 1 | Inputs failed schema validation. `error.errors[]` items carry `{ field, kind, message }` where `kind ∈ {enum, type, range}`. Fix and retry. |
|
|
18
|
+
| `INVALID_INPUTS_JSON` | 1 | `--inputs` could not be parsed as JSON. Check quoting / escaping; on shells use `JSON.stringify(...)` from your wrapper. |
|
|
19
|
+
| `INPUTS_FILE_NOT_FOUND` | 1 | `--inputs @path` file does not exist. Resolve to an absolute path or correct the caller. |
|
|
20
|
+
| `INVALID_MODEL_ID` | 1 | Server / catalog rejected the model id. Run `aigateway sb tools --category <key>` to find a valid one. |
|
|
21
|
+
| `CATEGORY_NOT_FOUND` | 1 | `sb tools --category` argument is not in the live catalog. Run `aigateway sb tools` (no filter) to list categories. |
|
|
22
|
+
| `MODEL_PRICING_NOT_CONFIGURED` | 1 | The catalog lists the model but the gateway has no price entry yet. Pick another model or ask the operator to add it. |
|
|
23
|
+
| `INVALID_BODY` | 1 | Server rejected the request body shape. Usually a CLI / catalog drift; file a bug. |
|
|
24
|
+
| `TOPUP_REQUIRED` | 1 | Non-TTY context, USDT below the per-call minimum. Choose from `error.presets` (filtered to ≥ `error.minTopup`) and rerun the failing command with `--topup-amount <n>`. |
|
|
25
|
+
| `TOPUP_AMOUNT_TOO_SMALL` | 1 | `--topup-amount` (or `topup --amount`) below `error.minTopup`. Rerun with a larger value. |
|
|
16
26
|
| `PAYMENT_REJECTED` | 1 | User cancelled in their wallet. **Do not auto-retry** — ask user first. |
|
|
17
|
-
| `PAYMENT_TIMEOUT` | 2 | WalletConnect approval expired (5 min). Ask user whether to retry. **Do not auto-retry.** |
|
|
18
|
-
| `WC_SESSION_EXPIRED` | 2 |
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
27
|
+
| `PAYMENT_TIMEOUT` | 2 | WalletConnect approval window expired (5 min). Ask user whether to retry. **Do not auto-retry.** |
|
|
28
|
+
| `WC_SESSION_EXPIRED` | 2 | WalletConnect relay dropped the session. Re-run the original command. |
|
|
29
|
+
| `TX_TIMEOUT` | 2 | The on-chain transfer is likely still pending. Wait, then re-check with `wallet-balance`. |
|
|
30
|
+
| `UPDATE_APPLIED` | 2 | CLI just upgraded itself synchronously. The previous command was **not executed**. Surface `error.from` → `error.to` and **rerun the same command verbatim** on the new version. |
|
|
21
31
|
| `SERVICE_UNAVAILABLE` | 3 | Exponential backoff: 1 s → 4 s → 16 s, max 3 attempts. |
|
|
22
|
-
| `PAYMENT_FETCH_FAILED` | 3 |
|
|
32
|
+
| `PAYMENT_FETCH_FAILED` | 3 | First 402 probe failed. Backoff + retry; check network connectivity. |
|
|
33
|
+
| `CATALOG_FETCH_FAILED` | 3 | `sb tools` could not reach the server. Retry once; if it persists, `sb invoke` still runs (server-side validation is the safety net). |
|
|
23
34
|
| `BALANCE_CHECK_FAILED` | 3 | BSC RPC hiccup. Retry once after 2 s. |
|
|
35
|
+
| `ALLOWANCE_CHECK_FAILED` | 3 | BSC RPC hiccup. Retry once after 2 s. |
|
|
24
36
|
| `TX_REVERTED` | 3 | On-chain failure. Capture `error.message` for diagnosis; do not retry blindly. |
|
|
25
37
|
| `WITHDRAW_FAILED` | 3 | Withdraw transaction failed. Check `aigateway wallet-balance` and retry. |
|
|
38
|
+
| `APPROVE_FAILED` | 3 | One-time facilitator approve failed during `wallet-topup`. Inspect the tx; retry the top-up. |
|
|
26
39
|
| `INVALID_PAYMENT_AMOUNT` | 3 | Server-side issue (returned amount = 0). Retry after a short delay. |
|
|
27
|
-
| `PAYMENT_FAILED` | 3 | Service rejected the signed request. Surface `error.data` to the user / log. |
|
|
40
|
+
| `PAYMENT_FAILED` | 3 | Service rejected the signed payment request. Surface `error.data` / `error.status` to the user / log. On 5xx, retry once. |
|
|
41
|
+
| `IMAGE_DOWNLOAD_FAILED` / `DOWNLOAD_FAILED` | 3 | The paid call succeeded but the local download failed. The original URL is still in the upstream response — surface it from `data.downloaded[].url` (when available) or re-fetch via `--raw`. **Do not re-invoke the model** (you'd pay again). |
|
|
42
|
+
| `FUNDING_FAILED` | 3 | Non-timeout / non-reject failure in the WalletConnect funding flow. Re-run `wallet-topup`. |
|
|
28
43
|
| `INTERNAL_ERROR` | 4 | File a bug. Don't retry. |
|
|
29
44
|
| `WALLET_ERROR` | 1 | Generic wallet failure. Surface to user, ask whether to retry. |
|
|
30
45
|
|
|
@@ -41,13 +56,29 @@ async function withRetry(fn, { codes, attempts = 3, baseDelayMs = 1000 } = {}) {
|
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
// Only retry transient service/network errors
|
|
44
|
-
await withRetry(
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
await withRetry(
|
|
60
|
+
() => runAigateway([
|
|
61
|
+
"sb", "invoke",
|
|
62
|
+
"--model", "replicate/black-forest-labs/flux-schnell",
|
|
63
|
+
"--inputs", JSON.stringify({ prompt: "a cyberpunk fox" }),
|
|
64
|
+
]),
|
|
65
|
+
{
|
|
66
|
+
codes: [
|
|
67
|
+
"SERVICE_UNAVAILABLE",
|
|
68
|
+
"PAYMENT_FETCH_FAILED",
|
|
69
|
+
"CATALOG_FETCH_FAILED",
|
|
70
|
+
"BALANCE_CHECK_FAILED",
|
|
71
|
+
"ALLOWANCE_CHECK_FAILED",
|
|
72
|
+
"INVALID_PAYMENT_AMOUNT",
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
);
|
|
47
76
|
```
|
|
48
77
|
|
|
49
78
|
## Anti-patterns
|
|
50
79
|
|
|
51
80
|
- ❌ Don't retry `PAYMENT_REJECTED` or `PAYMENT_TIMEOUT` automatically — the user actively cancelled or walked away.
|
|
81
|
+
- ❌ Don't retry `IMAGE_DOWNLOAD_FAILED` / `DOWNLOAD_FAILED` by re-invoking the model — the paid call already settled, you'd be charged again. Re-fetch the URL or re-run with `--raw`.
|
|
52
82
|
- ❌ Don't match on `error.message` text — messages may change between versions. Match on `error.code`.
|
|
53
83
|
- ❌ Don't ignore exit code in favour of envelope. Stack-level proxies sometimes mangle stdout; the exit code is a redundant safety net.
|
|
84
|
+
- ❌ Don't paper over `UPDATE_APPLIED` by treating it as a generic timeout — it's a "new binary; rerun me" signal, not a failure.
|