@aeon-ai-pay/aigateway 0.1.1 → 0.1.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/CHANGELOG.md +46 -0
- package/package.json +1 -1
- package/skills/aigateway/SKILL.md +81 -18
- package/src/commands/create-card.mjs +19 -0
- package/src/commands/wallet-init.mjs +13 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.4] — 2026-05-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`create-card` envelope now carries a `balance` block** (`initial`, `before`,
|
|
14
|
+
`after`, `charged`, `topup`) parallel to `create-image`, so the agent can
|
|
15
|
+
render the same money-flow narrative for card issuance.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- **Both paid commands adopt an emoji-aligned card-style success template**
|
|
19
|
+
with explicit balance transitions (`{initial} → {before}` for top-up;
|
|
20
|
+
`{before} → {after}` for charge) on dedicated rows. The `💸 Top-up` row is
|
|
21
|
+
conditional — only rendered when `balance.topup` is non-null.
|
|
22
|
+
- `create-card`: header `✅ Card Issued`, rows for Order / Card / State /
|
|
23
|
+
Face value / Usage / Tx / (optional) Top-up / Charged.
|
|
24
|
+
- `create-image`: header `✅ Generated`, second row `🧩 Powered by Skillboss`,
|
|
25
|
+
rows for Path / Format / Dimensions / Size / Tx / (optional) Top-up /
|
|
26
|
+
Charged.
|
|
27
|
+
- SKILL.md Copy Constraints table extended with all new template rows so
|
|
28
|
+
agents must reproduce the glyphs (`→`, `−`, `+`) exactly.
|
|
29
|
+
|
|
30
|
+
## [0.1.3] — 2026-05-19
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **`wallet-init` no longer requires `mainWallet` field in config to consider the wallet "funded".**
|
|
34
|
+
Previously the decision tree was `created || !config.mainWallet ⇒ needsTopup=true`, which meant
|
|
35
|
+
a session wallet that had USDT and was already approved on-chain — but whose local config had
|
|
36
|
+
never recorded a `mainWallet` (e.g. funded by an external CEX transfer, or copied from another
|
|
37
|
+
machine without that field) — would still be flagged as needing a top-up, sending the agent
|
|
38
|
+
through a redundant `wallet-topup` flow. The decision now relies only on on-chain state
|
|
39
|
+
(USDT balance ≥ `LOW_BALANCE_THRESHOLD` and `allowance > 0`). `mainWallet` is treated purely
|
|
40
|
+
as a withdraw-default and has no effect on `needsTopup`.
|
|
41
|
+
- `topupReason` enum updated: `no_prior_funding` removed; new values are `first_time` (replaces
|
|
42
|
+
the created branch), `low_balance`, `no_approve`, and `chain_check_failed`.
|
|
43
|
+
|
|
44
|
+
## [0.1.2] — 2026-05-19
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- **SKILL.md wording discipline**: `wallet-topup` ask and `create-card` ask now have
|
|
48
|
+
enforced lexical separation. Step 2 (`wallet-topup`) explicitly says "load USDT
|
|
49
|
+
**into your session wallet**" / "往**本地钱包**充值 USDT". Step 3a (`create-card`)
|
|
50
|
+
says "card **face value**" / "**开多少美元的卡** / 卡的面额", and explicitly
|
|
51
|
+
forbids translating it as "充值". Fixes a UX confusion where a user with a
|
|
52
|
+
funded wallet would be asked "请问您想充值多少美元到虚拟卡上?" and reasonably
|
|
53
|
+
wonder if it was another wallet top-up prompt.
|
|
54
|
+
- New "Wording Discipline" section in SKILL.md `## Copy Constraints` to lock this in.
|
|
55
|
+
|
|
10
56
|
## [0.1.1] — 2026-05-19
|
|
11
57
|
|
|
12
58
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeon-ai-pay/aigateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "AI Agents discover, invoke, and settle paid LLMs, APIs, and Skills — starting with Skill Boss. No manual key setup. No prepayment. Pay-per-call via x402 or Agent Card.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@ description: >
|
|
|
16
16
|
emoji: "🛰️"
|
|
17
17
|
homepage: https://github.com/AEON-Project/aigateway
|
|
18
18
|
metadata:
|
|
19
|
-
version: "0.1.
|
|
19
|
+
version: "0.1.4"
|
|
20
20
|
author: AEON-Project
|
|
21
21
|
openclaw:
|
|
22
22
|
requires:
|
|
@@ -160,9 +160,15 @@ Trigger: `wallet-init` envelope reports `needsTopup: true` (any of `no_prior_fun
|
|
|
160
160
|
|
|
161
161
|
### Amount selection
|
|
162
162
|
|
|
163
|
+
This is a **session-wallet top-up** in USDT (NOT card face value). Make the wording unambiguously about the wallet to avoid the user confusing it with the card face value asked in Step 3a.
|
|
164
|
+
|
|
163
165
|
- Presets: **5 / 10 / 20 / 50 USDT**. Custom amounts must be ≥ 5 USDT.
|
|
164
|
-
- Ask the user **before** running the command
|
|
165
|
-
|
|
166
|
+
- Ask the user **before** running the command. **Make "wallet" / "钱包" explicit in the question:**
|
|
167
|
+
|
|
168
|
+
> How much USDT would you like to load **into your session wallet**? (presets: 5 / 10 / 20 / 50, or any custom amount ≥ 5)
|
|
169
|
+
|
|
170
|
+
(Suggested Chinese phrasing: "请问要往**本地钱包**充值多少 USDT?预设 5 / 10 / 20 / 50,或自定义 ≥ 5。")
|
|
171
|
+
|
|
166
172
|
- Once the user picks an amount, run:
|
|
167
173
|
|
|
168
174
|
```bash
|
|
@@ -205,9 +211,12 @@ Trigger: user wants to **buy / create / get a virtual card** *and* Step 1 envelo
|
|
|
205
211
|
|
|
206
212
|
### Amount confirmation
|
|
207
213
|
|
|
208
|
-
Amount must be in `amountLimits.min ~ amountLimits.max` (from Step 1; never hardcode). If user did not specify, ask once:
|
|
214
|
+
This is the **card face value** the user wants to issue (NOT a wallet top-up). Amount must be in `amountLimits.min ~ amountLimits.max` (from Step 1; never hardcode). If user did not specify, ask once — **use the word "card face value" / "面额", never "充值" / "top up"** to avoid confusing it with the `wallet-topup` step:
|
|
209
215
|
|
|
210
|
-
>
|
|
216
|
+
> What card face value would you like to issue? Allowed range: ${min}~${max} USD.
|
|
217
|
+
|
|
218
|
+
(Suggested Chinese phrasing: "请问要开多少美元的卡?允许范围 $${min} ~ $${max}。"
|
|
219
|
+
**Do not** translate this as "充值多少美元" — that wording belongs to `wallet-topup` and confuses users.)
|
|
211
220
|
|
|
212
221
|
Once specified, **execute immediately**.
|
|
213
222
|
|
|
@@ -229,16 +238,30 @@ Output template first line:
|
|
|
229
238
|
|
|
230
239
|
### Success
|
|
231
240
|
|
|
232
|
-
`envelope.data`: `{ orderNo, data, paymentResponse,
|
|
241
|
+
`envelope.data`: `{ orderNo, amount, data, paymentResponse, balance: { initial, before, after, charged, topup }, pollResult? }`.
|
|
242
|
+
|
|
243
|
+
After fetching details (may take ~30 s), display **verbatim** (emoji, spacing, glyphs `→` / `−` / `+` must match exactly):
|
|
233
244
|
|
|
234
245
|
```
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
✅ Card Issued
|
|
247
|
+
🆔 Order {orderNo}
|
|
248
|
+
💳 Card {cardScheme} •••• {last4}
|
|
249
|
+
🎯 State Active
|
|
250
|
+
💵 Face value ${amount} USD
|
|
251
|
+
🔢 Usage 0 / 1 (single-use)
|
|
252
|
+
🔗 Tx {transaction}
|
|
253
|
+
💸 Top-up {initial} → {before} USDT (+{topup})
|
|
254
|
+
💰 Charged {before} → {after} USDT (−{charged})
|
|
240
255
|
```
|
|
241
256
|
|
|
257
|
+
**Field rules:**
|
|
258
|
+
|
|
259
|
+
- `{cardScheme}` and `••••{last4}` come from `data.data.model` (already sanitized — never show full card number).
|
|
260
|
+
- `{transaction}` is `data.paymentResponse.txHash` or `data.data.transaction`. If absent, render the line as `🔗 Tx —`.
|
|
261
|
+
- The **`💸 Top-up`** row is **conditional**: render only when `data.balance.topup` is non-null and non-zero (i.e. a lazy top-up actually happened during this call). Otherwise **omit the entire `💸 Top-up` line**.
|
|
262
|
+
- The **`💰 Charged`** row is always rendered.
|
|
263
|
+
- Use the minus sign character `−` (U+2212) before `{charged}`, not the hyphen `-`. Use `→` (U+2192) for the balance transition arrow.
|
|
264
|
+
|
|
242
265
|
Always record `orderNo` — only identifier for status queries.
|
|
243
266
|
|
|
244
267
|
### Errors
|
|
@@ -275,19 +298,31 @@ Output template first line:
|
|
|
275
298
|
|
|
276
299
|
### Success
|
|
277
300
|
|
|
278
|
-
`envelope.data`: `{ prompt, transaction, images: [{ url, localPath, format, width, height, sizeHuman }], balance: { initial, before, after, charged } }`.
|
|
301
|
+
`envelope.data`: `{ prompt, transaction, images: [{ url, localPath, format, width, height, sizeHuman }], balance: { initial, before, after, charged, topup } }`.
|
|
279
302
|
|
|
280
|
-
Display **verbatim
|
|
303
|
+
Display **verbatim** (emoji, spacing, dash glyphs `→` / `−` / `+` must match exactly):
|
|
281
304
|
|
|
282
305
|
```
|
|
283
306
|
✅ Generated
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
307
|
+
🧩 Powered by Skillboss
|
|
308
|
+
📁 Path {localPath}
|
|
309
|
+
🎨 Format {FORMAT}
|
|
310
|
+
📐 Dimensions {width} × {height}
|
|
311
|
+
💾 Size {sizeHuman}
|
|
312
|
+
🔗 Tx {transaction}
|
|
313
|
+
💸 Top-up {initial} → {before} USDT (+{topup})
|
|
314
|
+
💰 Charged {before} → {after} USDT (−{charged})
|
|
289
315
|
```
|
|
290
316
|
|
|
317
|
+
**Field rules:**
|
|
318
|
+
|
|
319
|
+
- `{FORMAT}` is `data.outputFormat` uppercased (e.g. `PNG`, `JPEG`, `WEBP`).
|
|
320
|
+
- `{width}` / `{height}` / `{sizeHuman}` come from `data.images[0]` (first image only — agent does not list extras unless asked).
|
|
321
|
+
- `{transaction}` is `data.transaction` (may be `null` if the server didn't return one; in that case render the line as `🔗 Tx —`).
|
|
322
|
+
- The **`💸 Top-up`** line is **conditional**: only render it if `data.balance.topup` is not null and not "0" (i.e. a lazy top-up actually happened during this call). Otherwise **omit the entire `💸 Top-up` line**.
|
|
323
|
+
- The **`💰 Charged`** line is always rendered.
|
|
324
|
+
- Use the minus sign character `−` (U+2212) before `{charged}`, not the hyphen `-`. Use `→` (U+2192) for the balance transition arrow.
|
|
325
|
+
|
|
291
326
|
### Errors
|
|
292
327
|
|
|
293
328
|
| `error.code` | Action |
|
|
@@ -395,6 +430,15 @@ The following first-line / key-phrase strings must be **exactly reproduced** —
|
|
|
395
430
|
| Pre-check | `> Pre-check in progress...` |
|
|
396
431
|
| Top up | `> Topping up wallet...` |
|
|
397
432
|
| Create card | `> Creating Agent Card...` |
|
|
433
|
+
| Card success header | `✅ Card Issued` |
|
|
434
|
+
| Card Order row | `🆔 Order {orderNo}` |
|
|
435
|
+
| Card scheme row | `💳 Card {cardScheme} •••• {last4}` |
|
|
436
|
+
| Card State row | `🎯 State Active` |
|
|
437
|
+
| Card Face value row | `💵 Face value ${amount} USD` |
|
|
438
|
+
| Card Usage row | `🔢 Usage 0 / 1 (single-use)` |
|
|
439
|
+
| Card Tx row | `🔗 Tx {transaction}` |
|
|
440
|
+
| Card Top-up row (conditional) | `💸 Top-up {initial} → {before} USDT (+{topup})` |
|
|
441
|
+
| Card Charged row | `💰 Charged {before} → {after} USDT (−{charged})` |
|
|
398
442
|
| Create image | `> Generating image...` |
|
|
399
443
|
| Fetch details | `> Fetching card details, please wait...` |
|
|
400
444
|
| Query status | `> Fetching card status...` |
|
|
@@ -402,6 +446,25 @@ The following first-line / key-phrase strings must be **exactly reproduced** —
|
|
|
402
446
|
| Withdraw target line | `To: main wallet (0x0...{last4})` |
|
|
403
447
|
| Withdraw status line | `Status: completed` |
|
|
404
448
|
| Image success header | `✅ Generated` |
|
|
449
|
+
| Image success row 2 | `🧩 Powered by Skillboss` |
|
|
450
|
+
| Image Path row | `📁 Path {localPath}` |
|
|
451
|
+
| Image Format row | `🎨 Format {FORMAT}` |
|
|
452
|
+
| Image Dimensions row | `📐 Dimensions {width} × {height}` |
|
|
453
|
+
| Image Size row | `💾 Size {sizeHuman}` |
|
|
454
|
+
| Image Tx row | `🔗 Tx {transaction}` |
|
|
455
|
+
| Image Top-up row (conditional) | `💸 Top-up {initial} → {before} USDT (+{topup})` |
|
|
456
|
+
| Image Charged row | `💰 Charged {before} → {after} USDT (−{charged})` |
|
|
405
457
|
| Wallet prepared header | `✅ Wallet prepared` |
|
|
406
458
|
|
|
407
459
|
Address rendering: always `0x0...{last4}` (first 3 + ellipsis + last 4 chars).
|
|
460
|
+
|
|
461
|
+
### Wording Discipline: "wallet top-up" vs "card face value"
|
|
462
|
+
|
|
463
|
+
These two amounts are **different concepts** asked at **different steps**. Translators must keep them lexically distinct so users don't conflate them:
|
|
464
|
+
|
|
465
|
+
| Step | Concept | Required wording (English) | Suggested Chinese | Forbidden mix-ups |
|
|
466
|
+
| --- | --- | --- | --- | --- |
|
|
467
|
+
| Step 2 (`wallet-topup`) | USDT into the **session wallet** | "load USDT **into your session wallet**" | "往**本地钱包**充值 USDT" | Don't say "充值到卡里" / "load onto the card" — that's Step 3a |
|
|
468
|
+
| Step 3a (`create-card`) | USD **face value** loaded onto a new card | "card **face value**" / "issue a card with how much" | "**开多少美元的卡** / 卡的面额" | Don't say "充值多少" / "充值到卡" without strong "card" qualifier — confuses with Step 2 |
|
|
469
|
+
|
|
470
|
+
**Rule of thumb**: if the agent's question contains the word "充值" (top up), the noun *must* be "钱包" (wallet); if the question is about a card's amount, prefer "**面额**" or "**开多少美元的卡**", never "充值".
|
|
@@ -82,11 +82,13 @@ export async function createCard(opts) {
|
|
|
82
82
|
let sessionAddress;
|
|
83
83
|
let topupAmount = null;
|
|
84
84
|
let balanceInitialUsdt = null;
|
|
85
|
+
let balanceBeforeChargeUsdt = null;
|
|
85
86
|
|
|
86
87
|
try {
|
|
87
88
|
const { address, usdt, bnb, bnbRaw } = await getWalletBalance(privateKey);
|
|
88
89
|
sessionAddress = address;
|
|
89
90
|
balanceInitialUsdt = usdt;
|
|
91
|
+
balanceBeforeChargeUsdt = usdt;
|
|
90
92
|
const usdtNum = parseFloat(usdt);
|
|
91
93
|
logInfo(`Wallet: ${address}`);
|
|
92
94
|
logInfo(`Balance: ${usdt} USDT, ${bnb} BNB`);
|
|
@@ -210,6 +212,7 @@ export async function createCard(opts) {
|
|
|
210
212
|
logInfo("Re-checking wallet balance...");
|
|
211
213
|
try {
|
|
212
214
|
const { usdt, bnbRaw } = await getWalletBalance(privateKey);
|
|
215
|
+
balanceBeforeChargeUsdt = usdt;
|
|
213
216
|
const usdtNum = parseFloat(usdt);
|
|
214
217
|
if (needGas && bnbRaw === 0n) {
|
|
215
218
|
emitErr("create-card", "INSUFFICIENT_BNB", {
|
|
@@ -260,12 +263,28 @@ export async function createCard(opts) {
|
|
|
260
263
|
const paymentResponse = decodePaymentResponse(response.headers);
|
|
261
264
|
const orderNo = paymentReq.orderNo || response.data?.model?.orderNo || response.data?.orderNo;
|
|
262
265
|
|
|
266
|
+
let balanceAfterUsdt = null;
|
|
267
|
+
try {
|
|
268
|
+
const after = await getWalletBalance(privateKey);
|
|
269
|
+
balanceAfterUsdt = after.usdt;
|
|
270
|
+
} catch (e) {
|
|
271
|
+
logInfo(`Post-payment balance check failed: ${e.message}`);
|
|
272
|
+
}
|
|
273
|
+
|
|
263
274
|
const sanitizedData = sanitizeOutput(response.data);
|
|
264
275
|
const successData = {
|
|
265
276
|
appId,
|
|
266
277
|
orderNo,
|
|
278
|
+
amount,
|
|
267
279
|
data: sanitizedData,
|
|
268
280
|
paymentResponse,
|
|
281
|
+
balance: {
|
|
282
|
+
initial: balanceInitialUsdt,
|
|
283
|
+
before: balanceBeforeChargeUsdt,
|
|
284
|
+
after: balanceAfterUsdt,
|
|
285
|
+
charged: requiredUsdt,
|
|
286
|
+
topup: topupAmount,
|
|
287
|
+
},
|
|
269
288
|
};
|
|
270
289
|
|
|
271
290
|
function findCardStatus(obj) {
|
|
@@ -68,16 +68,24 @@ export async function initWallet(opts) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// 决策:是否需要 topup
|
|
71
|
+
// 决策:是否需要 topup —— 只看链上真实状态,不依赖 config.mainWallet 字段。
|
|
72
|
+
// 之前用 !config.mainWallet 当判断条件是错的:mainWallet 只是 withdraw 默认目标地址,
|
|
73
|
+
// 即使为 null(如用户外部转账 / 旧版本未记录),只要链上 USDT/allowance 充足就应该
|
|
74
|
+
// 直接允许付费调用,不要强制再走一次 wallet-topup。
|
|
72
75
|
let needsTopup = false;
|
|
73
76
|
let topupReason = null;
|
|
74
|
-
if (created
|
|
77
|
+
if (created) {
|
|
78
|
+
// 刚生成的 session key 必然没钱,无需查链
|
|
79
|
+
needsTopup = true;
|
|
80
|
+
topupReason = "first_time";
|
|
81
|
+
} else if (!chainCheckOk) {
|
|
82
|
+
// 链上查询失败 —— 保守标记需要 topup 由用户决定下一步
|
|
75
83
|
needsTopup = true;
|
|
76
|
-
topupReason = "
|
|
77
|
-
} else if (
|
|
84
|
+
topupReason = "chain_check_failed";
|
|
85
|
+
} else if (usdtNum < LOW_BALANCE_THRESHOLD) {
|
|
78
86
|
needsTopup = true;
|
|
79
87
|
topupReason = "low_balance";
|
|
80
|
-
} else if (
|
|
88
|
+
} else if (allowance === 0n) {
|
|
81
89
|
needsTopup = true;
|
|
82
90
|
topupReason = "no_approve";
|
|
83
91
|
}
|