@layers/amba 1.0.1 → 4.0.2
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 +45 -22
- package/dist/api-client.d.ts +49 -29
- package/dist/auth.d.ts +8 -0
- package/dist/bundle.d.ts +23 -9
- package/dist/commands/billing.d.ts +34 -0
- package/dist/commands/claim.d.ts +41 -0
- package/dist/commands/functions.d.ts +28 -3
- package/dist/commands/init.d.ts +69 -0
- package/dist/commands/projects.d.ts +8 -0
- package/dist/credentials.d.ts +259 -0
- package/dist/index.js +3657 -425
- package/dist/project-config.d.ts +11 -0
- package/dist/sandbox.d.ts +309 -0
- package/dist/skill-installer.d.ts +95 -0
- package/dist/skills/presets.d.ts +146 -0
- package/dist/skills.d.ts +266 -0
- package/package.json +7 -2
- package/skill-bundle/SKILL.md +324 -0
- package/skill-bundle/references/economy.md +331 -0
- package/skill-bundle/references/engagement.md +400 -0
- package/skill-bundle/references/gamification.md +316 -0
- package/skill-bundle/references/identity.md +395 -0
- package/skill-bundle/references/infrastructure.md +348 -0
- package/skill-bundle/references/social.md +366 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# Economy
|
|
2
|
+
|
|
3
|
+
Virtual currencies, the catalog of things they buy, stores (curated catalog subsets, possibly segment-gated), and the per-user inventory. Currencies come in two flavors: **soft** (earned in-app, e.g. `gold` / `coins` / `gems`) and **premium** (bought with real money via App Store / Play / Stripe / RevenueCat). Both flow through the same APIs; the difference is whether real money or a tracked event is the input.
|
|
4
|
+
|
|
5
|
+
Pattern:
|
|
6
|
+
|
|
7
|
+
1. Agent (MCP): create a currency, create catalog items, set prices, group items into one or more stores.
|
|
8
|
+
2. Client SDK: read the catalog, read the store, show the offer, call `Amba.stores.purchase(...)` (real money) or `Amba.inventory.purchase(...)` (soft currency). The server debits the currency / records the IAP receipt and grants the item.
|
|
9
|
+
|
|
10
|
+
Real-money purchases need a billing integration configured separately — see `references/infrastructure.md` for `amba_integrations_configure` with RevenueCat. Without RevenueCat, premium currencies still work (you grant them manually) but `Amba.stores.purchase(...)` for IAP-backed items won't validate.
|
|
11
|
+
|
|
12
|
+
## MCP tools
|
|
13
|
+
|
|
14
|
+
### Currencies
|
|
15
|
+
|
|
16
|
+
| Tool | Purpose | Example args |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `amba_currencies_create` / `amba_create_currency` | Define a currency. Soft or premium, with optional auto-recharge (hearts / energy mechanics). | `{ project_id, code: "gems", name: "Gems", is_premium: false, initial_balance: 0, max_balance: null }` |
|
|
19
|
+
| `amba_currencies_list` / `amba_list_currencies` | List currencies. | `{ project_id }` |
|
|
20
|
+
| `amba_currencies_update` / `amba_update_currency` | Edit a currency (rename, change caps, change auto-recharge). | `{ project_id, currency_id, max_balance: 10000 }` |
|
|
21
|
+
| `amba_currencies_delete` / `amba_delete_currency` | Delete a currency (irreversible — users lose their balance). | `{ project_id, currency_id }` |
|
|
22
|
+
| `amba_currencies_grant` / `amba_grant_currency` | Grant currency to a specific user (rewards, refunds, admin adjustments). | `{ project_id, app_user_id, currency_code: "gems", amount: 100, reason: "welcome_bonus" }` |
|
|
23
|
+
| `amba_currencies_get_transactions` / `amba_get_currency_transactions` | Per-user transaction ledger. | `{ project_id, user_id, currency_code: "gems", limit: 100 }` |
|
|
24
|
+
|
|
25
|
+
#### Currency grant rules (auto-grants)
|
|
26
|
+
|
|
27
|
+
| Tool | Purpose | Example args |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `amba_currency_grant_rules_create` | Auto-grant currency on an event (e.g. 10 gems per `workout_completed`). | `{ project_id, currency_code: "gems", event_name: "workout_completed", amount: 10, max_per_day: 5 }` |
|
|
30
|
+
| `amba_currency_grant_rules_list` | List grant rules. | `{ project_id, currency_code }` |
|
|
31
|
+
| `amba_currency_grant_rules_delete` | Delete a grant rule. | `{ project_id, rule_id }` |
|
|
32
|
+
|
|
33
|
+
#### Hearts / energy (auto-recharge)
|
|
34
|
+
|
|
35
|
+
Set `auto_recharge_amount` + `auto_recharge_interval_hours` when creating the currency:
|
|
36
|
+
|
|
37
|
+
```jsonc
|
|
38
|
+
{
|
|
39
|
+
"project_id": "...",
|
|
40
|
+
"code": "hearts",
|
|
41
|
+
"name": "Hearts",
|
|
42
|
+
"is_premium": false,
|
|
43
|
+
"initial_balance": 5,
|
|
44
|
+
"max_balance": 5,
|
|
45
|
+
"auto_recharge_amount": 1,
|
|
46
|
+
"auto_recharge_interval_hours": 4
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This is the Duolingo pattern: spend a heart on failure, regenerate 1 heart every 4 hours, capped at 5.
|
|
51
|
+
|
|
52
|
+
### Catalog
|
|
53
|
+
|
|
54
|
+
| Tool | Purpose | Example args |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `amba_catalog_items_create` / `amba_create_catalog_item` | Create a catalog item. | `{ project_id, key: "premium_theme", name: "Dark Pro Theme", item_type: "durable", description: "Pitch-black UI with magenta accents", icon_url: "https://...", category: "themes" }` |
|
|
57
|
+
| `amba_catalog_list` / `amba_list_catalog` | List the catalog. | `{ project_id }` |
|
|
58
|
+
| `amba_catalog_items_get` / `amba_get_catalog_item` | Read one item. | `{ project_id, item_id }` |
|
|
59
|
+
| `amba_catalog_items_update` / `amba_update_catalog_item` | Edit an item. | `{ project_id, item_id, name: "..." }` |
|
|
60
|
+
| `amba_catalog_items_delete` / `amba_delete_catalog_item` | Delete an item. | `{ project_id, item_id }` |
|
|
61
|
+
| `amba_catalog_items_set_price` / `amba_set_item_price` | Set or update a price (per currency, or in-app product id for real money). | `{ project_id, item_id, currency_code: "gems", amount: 200 }` or `{ project_id, item_id, iap_product_id: "com.example.premium_theme" }` |
|
|
62
|
+
| `amba_catalog_items_delete_price` / `amba_delete_catalog_price` | Delete a price (e.g. you no longer accept gems for this item). | `{ project_id, item_id, price_id }` |
|
|
63
|
+
| `amba_catalog_bundles_add_item` / `amba_add_catalog_bundle_item` | Add an item to a bundle (a bundle is itself a catalog item with `item_type: "bundle"`). | `{ project_id, bundle_item_id, child_item_id, quantity: 1 }` |
|
|
64
|
+
| `amba_catalog_bundles_remove_item` / `amba_remove_catalog_bundle_item` | Remove an item from a bundle. | `{ project_id, bundle_item_id, child_item_id }` |
|
|
65
|
+
|
|
66
|
+
Item types:
|
|
67
|
+
- `durable` — owned forever (themes, character skins, ad removal).
|
|
68
|
+
- `consumable` — used up (extra lives, hint packs, energy refills).
|
|
69
|
+
- `bundle` — contains other items (starter pack with 100 gems + 5 hints + 1 theme).
|
|
70
|
+
|
|
71
|
+
### Stores
|
|
72
|
+
|
|
73
|
+
| Tool | Purpose | Example args |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `amba_stores_create` / `amba_create_store` | Create a store (curated catalog subset). Optionally segment-gated. | `{ project_id, name: "Main Shop", description: "Tap to spend gems" }` |
|
|
76
|
+
| `amba_stores_list` | List stores. | `{ project_id }` |
|
|
77
|
+
| `amba_stores_patch` | Edit a store. | `{ project_id, store_id, name: "..." }` |
|
|
78
|
+
| `amba_stores_delete` | Delete a store. | `{ project_id, store_id }` |
|
|
79
|
+
| `amba_stores_add_listing` / `amba_add_store_listing` | Add an item to a store. | `{ project_id, store_id, item_id, sort_order: 1, featured: true }` |
|
|
80
|
+
| `amba_stores_list_listings` | List items in a store. | `{ project_id, store_id }` |
|
|
81
|
+
| `amba_stores_patch_listing` | Edit a listing (re-order, mark featured). | `{ project_id, store_id, listing_id, featured: true }` |
|
|
82
|
+
| `amba_stores_delete_listing` | Remove an item from a store. | `{ project_id, store_id, listing_id }` |
|
|
83
|
+
|
|
84
|
+
A segment-gated store: pass `segment_id` to `amba_stores_create` — only users in that segment see it via `Amba.stores.list()`.
|
|
85
|
+
|
|
86
|
+
### Inventory (admin-side grants)
|
|
87
|
+
|
|
88
|
+
| Tool | Purpose | Example args |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| `amba_inventory_grant_item` / `amba_grant_item` | Grant an item to a user without payment (rewards, admin adjustments). | `{ project_id, app_user_id, item_key: "premium_theme", quantity: 1 }` |
|
|
91
|
+
| `amba_users_get_inventory` / `amba_get_user_inventory` | Read a user's inventory. | `{ project_id, user_id }` |
|
|
92
|
+
|
|
93
|
+
## SDK init per stack
|
|
94
|
+
|
|
95
|
+
The SDK side is mostly read + purchase. `Amba.configure(...)` runs first.
|
|
96
|
+
|
|
97
|
+
### Expo
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { Amba } from '@layers/amba-expo';
|
|
101
|
+
|
|
102
|
+
// Read the user's currency balance
|
|
103
|
+
const balances = await Amba.currencies.getBalance();
|
|
104
|
+
// [{ code: "gems", amount: 150 }, { code: "hearts", amount: 4 }]
|
|
105
|
+
|
|
106
|
+
// Read the catalog
|
|
107
|
+
const items = await Amba.catalog.list();
|
|
108
|
+
|
|
109
|
+
// Read a store (a curated catalog subset)
|
|
110
|
+
const stores = await Amba.stores.list();
|
|
111
|
+
const offers = await Amba.stores.getPurchaseOptions(stores[0].key);
|
|
112
|
+
|
|
113
|
+
// Soft-currency purchase (deducts from currency balance)
|
|
114
|
+
await Amba.inventory.purchase({
|
|
115
|
+
item_key: 'premium_theme',
|
|
116
|
+
currency_code: 'gems',
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Consume a consumable item
|
|
120
|
+
await Amba.inventory.consume({ item_key: 'hint_pack', quantity: 1 });
|
|
121
|
+
|
|
122
|
+
// Read the user's inventory
|
|
123
|
+
const inv = await Amba.inventory.getItems();
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### React Native (bare)
|
|
127
|
+
|
|
128
|
+
Identical surface — only the package name changes:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { Amba } from '@layers/amba-react-native';
|
|
132
|
+
|
|
133
|
+
const balances = await Amba.currencies.getBalance();
|
|
134
|
+
const items = await Amba.catalog.list();
|
|
135
|
+
const stores = await Amba.stores.list();
|
|
136
|
+
const offers = await Amba.stores.getPurchaseOptions(stores[0].key);
|
|
137
|
+
await Amba.inventory.purchase({ item_key: 'premium_theme', currency_code: 'gems' });
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
For real-money IAP, you typically combine Amba with RevenueCat or `react-native-iap`:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import Purchases from 'react-native-purchases';
|
|
144
|
+
|
|
145
|
+
// Trigger the OS purchase sheet via RevenueCat
|
|
146
|
+
const offerings = await Purchases.getOfferings();
|
|
147
|
+
const product = offerings.current?.availablePackages[0];
|
|
148
|
+
const { customerInfo, transaction } = await Purchases.purchasePackage(product!);
|
|
149
|
+
|
|
150
|
+
// Forward the receipt to Amba's stores API — server validates with the store
|
|
151
|
+
await Amba.stores.purchase(
|
|
152
|
+
'main_shop',
|
|
153
|
+
product!.identifier,
|
|
154
|
+
{ receipt: transaction.transactionReceipt, platform: 'ios' },
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Web
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { Amba } from '@layers/amba-web';
|
|
162
|
+
|
|
163
|
+
const balances = await Amba.currencies.getBalance();
|
|
164
|
+
const items = await Amba.catalog.list();
|
|
165
|
+
const stores = await Amba.stores.list();
|
|
166
|
+
await Amba.inventory.purchase({ item_key: 'pro_plan', currency_code: 'credits' });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Real-money web flow — typically Stripe Checkout:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
// Server-side: create a Stripe Checkout Session, redirect.
|
|
173
|
+
// Client-side: on return, Amba's webhook (`/webhooks/stripe` if configured)
|
|
174
|
+
// fulfils via `amba_grant_item`. No SDK call required.
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### iOS (Swift)
|
|
178
|
+
|
|
179
|
+
```swift
|
|
180
|
+
import Amba
|
|
181
|
+
|
|
182
|
+
let balances = try await Amba.currencies.getBalance()
|
|
183
|
+
let items = try await Amba.catalog.list()
|
|
184
|
+
let stores = try await Amba.stores.list()
|
|
185
|
+
let offers = try await Amba.stores.getPurchaseOptions(storeKey: stores[0].key)
|
|
186
|
+
|
|
187
|
+
// Soft-currency purchase
|
|
188
|
+
_ = try await Amba.inventory.purchase(PurchaseRequest(
|
|
189
|
+
itemKey: "premium_theme",
|
|
190
|
+
currencyCode: "gems"
|
|
191
|
+
))
|
|
192
|
+
|
|
193
|
+
// Consumable
|
|
194
|
+
_ = try await Amba.inventory.consume(ConsumeRequest(itemKey: "hint_pack", quantity: 1))
|
|
195
|
+
|
|
196
|
+
// Real-money via StoreKit 2
|
|
197
|
+
import StoreKit
|
|
198
|
+
|
|
199
|
+
let products = try await Product.products(for: ["com.example.premium_theme"])
|
|
200
|
+
let result = try await products[0].purchase()
|
|
201
|
+
if case .success(.verified(let transaction)) = result {
|
|
202
|
+
_ = try await Amba.stores.purchase(
|
|
203
|
+
storeKey: "main_shop",
|
|
204
|
+
purchaseOptionId: products[0].id,
|
|
205
|
+
receipt: ["jws_representation": transaction.jsonRepresentation]
|
|
206
|
+
)
|
|
207
|
+
await transaction.finish()
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Android (Kotlin)
|
|
212
|
+
|
|
213
|
+
```kotlin
|
|
214
|
+
val balances = Amba.currencies.getBalance()
|
|
215
|
+
val items = Amba.catalog.list()
|
|
216
|
+
val stores = Amba.stores.list()
|
|
217
|
+
|
|
218
|
+
Amba.inventory.purchase(
|
|
219
|
+
PurchaseRequest(itemKey = "premium_theme", currencyCode = "gems")
|
|
220
|
+
)
|
|
221
|
+
Amba.inventory.consume(ConsumeRequest(itemKey = "hint_pack", quantity = 1))
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Real-money via Google Play Billing — capture the `purchaseToken` then:
|
|
225
|
+
|
|
226
|
+
```kotlin
|
|
227
|
+
Amba.stores.purchase(
|
|
228
|
+
storeKey = "main_shop",
|
|
229
|
+
purchaseOptionId = sku,
|
|
230
|
+
receipt = mapOf(
|
|
231
|
+
"purchase_token" to purchaseToken,
|
|
232
|
+
"package_name" to context.packageName,
|
|
233
|
+
"product_id" to sku
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Flutter
|
|
239
|
+
|
|
240
|
+
```dart
|
|
241
|
+
import 'package:amba/amba.dart';
|
|
242
|
+
|
|
243
|
+
final balances = await Amba.currencies.getBalance();
|
|
244
|
+
final items = await Amba.catalog.list();
|
|
245
|
+
final stores = await Amba.stores.list();
|
|
246
|
+
|
|
247
|
+
await Amba.inventory.purchase(
|
|
248
|
+
PurchaseRequest(itemKey: 'premium_theme', currencyCode: 'gems'),
|
|
249
|
+
);
|
|
250
|
+
await Amba.inventory.consume(
|
|
251
|
+
ConsumeRequest(itemKey: 'hint_pack', quantity: 1),
|
|
252
|
+
);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
For IAP, the `in_app_purchase` Flutter plugin gives you the receipt; pass it to `Amba.stores.purchase(...)` with the same shape as Swift/Kotlin.
|
|
256
|
+
|
|
257
|
+
## Common follow-ups
|
|
258
|
+
|
|
259
|
+
Batch.
|
|
260
|
+
|
|
261
|
+
1. **Virtual currency: what's it called?**
|
|
262
|
+
- `gems` (recommended — neutral, premium feel)
|
|
263
|
+
- `coins`
|
|
264
|
+
- `gold`
|
|
265
|
+
- `credits` (recommended for ai_chatbot)
|
|
266
|
+
- `points`
|
|
267
|
+
- Custom — I'll provide
|
|
268
|
+
- None — no soft currency for now
|
|
269
|
+
|
|
270
|
+
2. **Add a "hearts" / energy mechanic?** (only ask for fitness / game / education)
|
|
271
|
+
- Yes — 5 hearts max, +1 every 4 hours (Duolingo style)
|
|
272
|
+
- Yes but custom (ask for cap and recharge rate)
|
|
273
|
+
- No
|
|
274
|
+
|
|
275
|
+
3. **Premium currency too?** (real-money purchases of a tradeable virtual currency)
|
|
276
|
+
- Yes — `gems` (premium) — pairs with App Store / Play / Stripe billing
|
|
277
|
+
- No — only soft currency
|
|
278
|
+
|
|
279
|
+
4. **Seed a starter catalog?**
|
|
280
|
+
- Yes — 3 cosmetics + 1 consumable + 1 starter bundle (uses the chosen currency)
|
|
281
|
+
- Yes but seed it empty — I'll add items myself
|
|
282
|
+
- No
|
|
283
|
+
|
|
284
|
+
5. **Stores: one store or segmented stores?**
|
|
285
|
+
- One "Main Shop" — recommended for v1
|
|
286
|
+
- Multiple — main + a "Trial Users" segment-gated store
|
|
287
|
+
- I'll wire stores myself
|
|
288
|
+
|
|
289
|
+
6. **Auto-grant rules:** earn currency on the gamification event?
|
|
290
|
+
- Yes — grant 10 of `<currency>` per `<event>` (same event as XP rule), cap at 5/day
|
|
291
|
+
- No — currency is granted only through achievement rewards / IAP
|
|
292
|
+
|
|
293
|
+
7. **Real-money integration:** which provider?
|
|
294
|
+
- RevenueCat (recommended for mobile — handles iOS + Android in one SDK; configure with `amba_integrations_configure`)
|
|
295
|
+
- Native StoreKit / Play Billing only (no aggregator)
|
|
296
|
+
- Stripe (web)
|
|
297
|
+
- None yet — I'll add later
|
|
298
|
+
|
|
299
|
+
## Re-run behavior
|
|
300
|
+
|
|
301
|
+
1. `.amba/wired.json`:
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"surfaces": {
|
|
306
|
+
"economy": {
|
|
307
|
+
"currencies": ["gems", "hearts"],
|
|
308
|
+
"catalog_items": ["premium_theme", "hint_pack", "starter_bundle"],
|
|
309
|
+
"stores": ["Main Shop"],
|
|
310
|
+
"grant_rules": [{ "currency": "gems", "event": "workout_completed" }],
|
|
311
|
+
"integrations": ["revenuecat"]
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
2. Before creating anything:
|
|
318
|
+
- `amba_currencies_list` — match on `code`. Codes are unique per project. Collision → ask to update instead.
|
|
319
|
+
- `amba_catalog_list` — match on `key`. Same.
|
|
320
|
+
- `amba_stores_list` — match on `name`. Same.
|
|
321
|
+
|
|
322
|
+
3. **Never delete a currency or item without explicit confirmation** — users have balances and inventory tied to them. Suggest renaming + updating instead. If they insist on delete, surface what gets lost (number of users with non-zero balances / inventory).
|
|
323
|
+
|
|
324
|
+
4. If adding a new currency to an existing project, ask whether to:
|
|
325
|
+
- Add a grant rule for it on the existing gamification event
|
|
326
|
+
- Set up auto-recharge (hearts pattern)
|
|
327
|
+
- Just create it without rules — manual grant only
|
|
328
|
+
|
|
329
|
+
5. For real-money integrations, treat as orthogonal: `amba_integrations_list` shows what's wired. Don't duplicate. RevenueCat needs webhook URL + secret on the RevenueCat dashboard side; the configure tool prints the URL, but the user has to paste it into RevenueCat themselves — surface that as a "needs your input" line in Step 4.
|
|
330
|
+
|
|
331
|
+
6. Update `wired.json` to append.
|