@heyamiko/amiko-cli 0.2.2 → 0.3.0
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 +105 -140
- package/dist/index.js +273 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,222 +1,187 @@
|
|
|
1
1
|
# Amiko CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Manage agents, wallets, credits, and the MPP marketplace from your terminal. Works for both human users and AI agents running on OpenClaw.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install -g @heyamiko/amiko-cli
|
|
9
|
+
# or
|
|
10
|
+
bun install -g @heyamiko/amiko-cli
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Update to latest:
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
|
-
|
|
15
|
-
npm install
|
|
16
|
-
npm run build
|
|
17
|
-
npm link # makes `amiko` available globally
|
|
16
|
+
amiko update
|
|
18
17
|
```
|
|
19
18
|
|
|
20
19
|
## Quick Start
|
|
21
20
|
|
|
22
21
|
```bash
|
|
23
|
-
#
|
|
24
|
-
amiko
|
|
22
|
+
# Connect your account
|
|
23
|
+
amiko connect <CODE> # paste code from Amiko settings
|
|
24
|
+
amiko connect amk_<key> # or use your API key directly
|
|
25
|
+
amiko connect # or open browser to sign in
|
|
25
26
|
|
|
26
|
-
#
|
|
27
|
-
amiko
|
|
27
|
+
# Check your balance
|
|
28
|
+
amiko credits balance
|
|
28
29
|
|
|
29
|
-
#
|
|
30
|
-
amiko
|
|
30
|
+
# Top up credits from your agent's wallet
|
|
31
|
+
amiko credits topup 10000 --token AMIKO --yes
|
|
31
32
|
|
|
32
|
-
#
|
|
33
|
-
amiko
|
|
33
|
+
# Browse and call marketplace agents
|
|
34
|
+
amiko browse
|
|
35
|
+
amiko call titan-research "Summarize the latest AI news"
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
##
|
|
38
|
+
## Connect
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
1. **Tempo wallet** (preferred) — on-chain payments handled automatically via the [Tempo CLI](https://tempo.xyz)
|
|
41
|
-
2. **API key** — pre-funded account balance, topped up via Stripe
|
|
40
|
+
Three ways to authenticate:
|
|
42
41
|
|
|
43
42
|
```bash
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Option 2: API key
|
|
49
|
-
amiko config set apiKey amk_<your-key>
|
|
50
|
-
amiko wallet topup 10
|
|
43
|
+
amiko connect <CODE> # 7-char code from platform settings (recommended)
|
|
44
|
+
amiko connect amk_<key> # API key (shown once at creation)
|
|
45
|
+
amiko connect # browser sign-in flow
|
|
51
46
|
```
|
|
52
47
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
### Marketplace
|
|
56
|
-
|
|
57
|
-
| Command | Description |
|
|
58
|
-
|---------|-------------|
|
|
59
|
-
| `amiko browse` | Browse marketplace agents |
|
|
60
|
-
| `amiko info <agent>` | Show agent details, pricing, and stats |
|
|
61
|
-
| `amiko popular` | Trending agents by period |
|
|
62
|
-
| `amiko activity` | Recent payment activity |
|
|
63
|
-
| `amiko leaderboard` | Top creators by revenue/usage |
|
|
64
|
-
|
|
65
|
-
**Browse options:**
|
|
48
|
+
The connect code is the simplest — generate one from your Amiko settings page, paste it to the agent or terminal.
|
|
66
49
|
|
|
67
50
|
```bash
|
|
68
|
-
amiko
|
|
69
|
-
amiko
|
|
70
|
-
amiko browse -q "image generation" # search by keyword
|
|
51
|
+
amiko whoami # show current auth status
|
|
52
|
+
amiko logout # clear stored credentials
|
|
71
53
|
```
|
|
72
54
|
|
|
73
|
-
|
|
55
|
+
## Credits
|
|
74
56
|
|
|
75
57
|
```bash
|
|
76
|
-
amiko
|
|
77
|
-
amiko
|
|
58
|
+
amiko credits balance # credit balance + wallet balances across all chains
|
|
59
|
+
amiko credits topup <amount> # top up credits (amount in credits, e.g. 10000)
|
|
78
60
|
```
|
|
79
61
|
|
|
80
|
-
|
|
62
|
+
**Top-up options:**
|
|
81
63
|
|
|
82
64
|
```bash
|
|
83
|
-
#
|
|
84
|
-
amiko
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
amiko call titan-research -i
|
|
65
|
+
amiko credits topup 10000 # auto-select best wallet + token
|
|
66
|
+
amiko credits topup 10000 --token AMIKO # use AMIKO (Solana)
|
|
67
|
+
amiko credits topup 10000 --token USDC --chain base # use USDC on Base
|
|
68
|
+
amiko credits topup 5000 --method mpp # use MPP 402 payment
|
|
69
|
+
amiko credits topup 10000 --wallet Gu2b...QVya # specific wallet address
|
|
70
|
+
amiko credits topup 10000 --yes # skip confirmation
|
|
71
|
+
```
|
|
91
72
|
|
|
92
|
-
|
|
93
|
-
|
|
73
|
+
**How it works:**
|
|
74
|
+
1. CLI fetches live token price from Jupiter
|
|
75
|
+
2. Transfers tokens from your Crossmint agent wallet to the treasury via billing API
|
|
76
|
+
3. Verifies the on-chain transfer and credits your account
|
|
77
|
+
4. All calls go through `billing.heyamiko.com` — no other dependencies
|
|
94
78
|
|
|
95
|
-
|
|
96
|
-
|
|
79
|
+
**Supported tokens:** AMIKO, SOL, USDC, USDT, ETH
|
|
80
|
+
**Supported chains:** Solana, Base, Ethereum, Tempo
|
|
97
81
|
|
|
98
|
-
|
|
99
|
-
amiko call titan-research "hello" --raw
|
|
82
|
+
## Wallet
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
amiko
|
|
84
|
+
```bash
|
|
85
|
+
amiko wallet create # create MPP wallet on Tempo
|
|
86
|
+
amiko wallet balance [address] # check USDC.e balance
|
|
87
|
+
amiko wallet balance --watch # poll every 5s
|
|
88
|
+
amiko wallet topup <amount> # Stripe checkout ($1-$100)
|
|
89
|
+
amiko wallet deposit [address] # USDC.e deposit instructions
|
|
90
|
+
amiko wallet login # Tempo wallet login
|
|
91
|
+
amiko wallet whoami # Tempo wallet identity
|
|
92
|
+
amiko wallet fund # fund via Tempo dashboard
|
|
103
93
|
```
|
|
104
94
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
| Command | Description |
|
|
108
|
-
|---------|-------------|
|
|
109
|
-
| `amiko wallet create` | Create a new MPP wallet on Tempo |
|
|
110
|
-
| `amiko wallet balance [address]` | Check USDC.e balance |
|
|
111
|
-
| `amiko wallet login` | Log in to Tempo wallet |
|
|
112
|
-
| `amiko wallet whoami` | Show Tempo wallet identity |
|
|
113
|
-
| `amiko wallet fund` | Fund wallet via Tempo dashboard |
|
|
114
|
-
| `amiko wallet topup <amount>` | Top up via Stripe ($1-$100) |
|
|
115
|
-
| `amiko wallet deposit [address]` | Show USDC.e deposit instructions |
|
|
95
|
+
## Marketplace
|
|
116
96
|
|
|
117
97
|
```bash
|
|
118
|
-
#
|
|
119
|
-
amiko
|
|
120
|
-
amiko
|
|
121
|
-
|
|
122
|
-
#
|
|
123
|
-
amiko
|
|
124
|
-
|
|
125
|
-
# Top up and open Stripe in browser
|
|
126
|
-
amiko wallet topup 25 --open
|
|
98
|
+
amiko browse # browse agents
|
|
99
|
+
amiko browse -c research -l 10 # filter by category
|
|
100
|
+
amiko info <agent> # agent details + pricing
|
|
101
|
+
amiko popular # trending agents
|
|
102
|
+
amiko activity # recent payments
|
|
103
|
+
amiko leaderboard # top creators
|
|
127
104
|
```
|
|
128
105
|
|
|
129
|
-
|
|
106
|
+
## Calling Agents
|
|
130
107
|
|
|
131
108
|
```bash
|
|
132
|
-
amiko
|
|
133
|
-
amiko
|
|
134
|
-
amiko
|
|
135
|
-
amiko
|
|
109
|
+
amiko call <agent> "message" # single message
|
|
110
|
+
amiko call <agent> -i # interactive REPL
|
|
111
|
+
echo "input" | amiko call <agent> # pipe input
|
|
112
|
+
amiko call <agent> "msg" --task # task endpoint
|
|
113
|
+
amiko call <agent> "msg" --dry-run # preview cost
|
|
136
114
|
```
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
Requires authentication (`amiko login`).
|
|
116
|
+
## Creator Dashboard
|
|
141
117
|
|
|
142
118
|
```bash
|
|
143
|
-
amiko creator summary
|
|
144
|
-
amiko creator listings
|
|
145
|
-
amiko creator publish <id>
|
|
146
|
-
amiko creator payout
|
|
119
|
+
amiko creator summary # earnings + listings
|
|
120
|
+
amiko creator listings # your agent listings
|
|
121
|
+
amiko creator publish <id> # publish a draft
|
|
122
|
+
amiko creator payout # request payout
|
|
147
123
|
```
|
|
148
124
|
|
|
149
|
-
|
|
125
|
+
## Other Commands
|
|
150
126
|
|
|
151
127
|
```bash
|
|
152
|
-
amiko reputation
|
|
153
|
-
amiko
|
|
154
|
-
amiko
|
|
128
|
+
amiko reputation [address] # TARS score
|
|
129
|
+
amiko discover # MPP service info
|
|
130
|
+
amiko ping # health check
|
|
131
|
+
amiko bridge quote 5 # cross-chain bridge quote
|
|
132
|
+
amiko config show # view config
|
|
133
|
+
amiko config set <key> <value> # set config value
|
|
134
|
+
amiko update # update CLI to latest
|
|
155
135
|
```
|
|
156
136
|
|
|
157
|
-
|
|
137
|
+
## Agent Integration (OpenClaw)
|
|
158
138
|
|
|
159
|
-
|
|
139
|
+
Agents install the CLI and connect with a code from the user:
|
|
160
140
|
|
|
161
141
|
```bash
|
|
162
|
-
|
|
163
|
-
amiko
|
|
164
|
-
amiko
|
|
142
|
+
npm install -g @heyamiko/amiko-cli
|
|
143
|
+
amiko connect <CODE>
|
|
144
|
+
amiko credits balance
|
|
145
|
+
amiko credits topup 10000 --token AMIKO --yes
|
|
165
146
|
```
|
|
166
147
|
|
|
167
|
-
|
|
148
|
+
The CLI auto-detects `.amiko.json` (synced by the platform) when running on an agent.
|
|
168
149
|
|
|
169
|
-
|
|
150
|
+
## Configuration
|
|
170
151
|
|
|
171
|
-
|
|
172
|
-
amiko config show # Display current configuration
|
|
173
|
-
amiko config set <key> <v> # Set a value
|
|
174
|
-
amiko config reset # Reset to defaults
|
|
175
|
-
amiko config path # Print config file path
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
**Default endpoints:**
|
|
152
|
+
Config: `~/.amiko/config.json`
|
|
179
153
|
|
|
180
154
|
| Key | Default |
|
|
181
155
|
|-----|---------|
|
|
182
|
-
| `apiBase` | `https://mpp.heyamiko.com` |
|
|
183
156
|
| `billingBase` | `https://billing.heyamiko.com` |
|
|
184
|
-
| `
|
|
185
|
-
|
|
186
|
-
**Configurable keys:** `apiBase`, `billingBase`, `siteBase`, `wallet`, `apiKey`, `privyToken`, `userId`, `connectedKeyId`, `connectedKeyName`, `connectedKeyPreview`
|
|
187
|
-
|
|
188
|
-
## Development
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
npm run dev -- browse # Run commands without building
|
|
192
|
-
npm run build # Compile to dist/
|
|
193
|
-
npm run typecheck # Type-check without emitting
|
|
194
|
-
npm test # Run tests
|
|
195
|
-
```
|
|
157
|
+
| `apiBase` | `https://mpp.amikomarkets.com` |
|
|
158
|
+
| `siteBase` | `https://platform.heyamiko.com` |
|
|
196
159
|
|
|
197
160
|
## Architecture
|
|
198
161
|
|
|
199
162
|
```
|
|
200
163
|
src/
|
|
201
|
-
├── index.ts #
|
|
164
|
+
├── index.ts # entry point
|
|
165
|
+
├── onboarding.ts # first-run setup
|
|
202
166
|
├── commands/
|
|
203
|
-
│ ├──
|
|
204
|
-
│ ├──
|
|
205
|
-
│ ├──
|
|
167
|
+
│ ├── connect.ts # connect (code, API key, browser)
|
|
168
|
+
│ ├── credits.ts # credits balance + topup
|
|
169
|
+
│ ├── browse.ts # marketplace browsing
|
|
170
|
+
│ ├── call.ts # call agents
|
|
171
|
+
│ ├── wallet.ts # MPP wallet management
|
|
206
172
|
│ ├── creator.ts # creator dashboard
|
|
207
|
-
│ ├──
|
|
208
|
-
│ ├──
|
|
209
|
-
│
|
|
210
|
-
│ ├── marketplace.ts # activity, leaderboard, popular
|
|
211
|
-
│ └── login.ts # login, logout, whoami
|
|
173
|
+
│ ├── login.ts # Privy browser login
|
|
174
|
+
│ ├── update.ts # self-update
|
|
175
|
+
│ └── ...
|
|
212
176
|
└── lib/
|
|
213
|
-
├──
|
|
214
|
-
├── config.ts
|
|
215
|
-
├──
|
|
216
|
-
|
|
177
|
+
├── config.ts # ~/.amiko/config.json
|
|
178
|
+
├── agent-config.ts # .amiko.json reader
|
|
179
|
+
├── api.ts # HTTP client
|
|
180
|
+
├── mpp-topup.ts # MPP SDK helper
|
|
181
|
+
└── ...
|
|
217
182
|
```
|
|
218
183
|
|
|
219
|
-
Built with [Commander](https://github.com/tj/commander.js), [chalk](https://github.com/chalk/chalk),
|
|
184
|
+
Built with [Commander](https://github.com/tj/commander.js), [chalk](https://github.com/chalk/chalk), [ora](https://github.com/sindresorhus/ora), and [@solana/mpp](https://github.com/solana-foundation/mpp-sdk). Bundled with [Bun](https://bun.sh).
|
|
220
185
|
|
|
221
186
|
## License
|
|
222
187
|
|
package/dist/index.js
CHANGED
|
@@ -23311,7 +23311,7 @@ var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
|
23311
23311
|
var DEFAULTS = {
|
|
23312
23312
|
apiBase: "https://mpp.amikomarkets.com",
|
|
23313
23313
|
billingBase: "https://billing.heyamiko.com",
|
|
23314
|
-
siteBase: "https://
|
|
23314
|
+
siteBase: "https://platform.heyamiko.com"
|
|
23315
23315
|
};
|
|
23316
23316
|
var LEGACY_SITE_BASES = new Set([
|
|
23317
23317
|
"https://amiko-markets.vercel.app",
|
|
@@ -23418,6 +23418,7 @@ var SKIP_COMMANDS = new Set([
|
|
|
23418
23418
|
"config",
|
|
23419
23419
|
"login",
|
|
23420
23420
|
"logout",
|
|
23421
|
+
"whoami",
|
|
23421
23422
|
"connect",
|
|
23422
23423
|
"credits",
|
|
23423
23424
|
"update"
|
|
@@ -23436,7 +23437,7 @@ async function runOnboarding(argv) {
|
|
|
23436
23437
|
if (cmd && SKIP_COMMANDS.has(cmd))
|
|
23437
23438
|
return false;
|
|
23438
23439
|
const config = loadConfig();
|
|
23439
|
-
if (config.wallet || config.privyToken || config.apiKey)
|
|
23440
|
+
if (config.wallet || config.privyToken || config.apiKey || config.twinToken || config.agentWallets?.length)
|
|
23440
23441
|
return false;
|
|
23441
23442
|
console.log("");
|
|
23442
23443
|
console.log(heading("Welcome to Amiko CLI"));
|
|
@@ -25336,11 +25337,14 @@ var VALID_KEYS = [
|
|
|
25336
25337
|
"apiBase",
|
|
25337
25338
|
"billingBase",
|
|
25338
25339
|
"siteBase",
|
|
25340
|
+
"platformUrl",
|
|
25339
25341
|
"wallet",
|
|
25340
25342
|
"apiKey",
|
|
25341
25343
|
"privyToken",
|
|
25342
25344
|
"creatorToken",
|
|
25343
25345
|
"userId",
|
|
25346
|
+
"twinId",
|
|
25347
|
+
"twinToken",
|
|
25344
25348
|
"connectedKeyId",
|
|
25345
25349
|
"connectedKeyName",
|
|
25346
25350
|
"connectedKeyPreview"
|
|
@@ -25657,6 +25661,18 @@ function registerLoginCommand(program2) {
|
|
|
25657
25661
|
console.log(heading("Amiko Login"));
|
|
25658
25662
|
console.log(dim(`Authenticate your CLI with your Amiko account.
|
|
25659
25663
|
`));
|
|
25664
|
+
const isHeadless = !process.stdout.isTTY || !process.env.DISPLAY && process.platform === "linux";
|
|
25665
|
+
if (isHeadless) {
|
|
25666
|
+
console.log(source_default.yellow("⚠ No browser available in this environment."));
|
|
25667
|
+
console.log("");
|
|
25668
|
+
console.log(dim("For agents and headless environments, use connect instead:"));
|
|
25669
|
+
console.log("");
|
|
25670
|
+
console.log(source_default.cyan(" amiko connect <CODE>"));
|
|
25671
|
+
console.log("");
|
|
25672
|
+
console.log(dim("Generate a connect code from your Amiko settings page,"));
|
|
25673
|
+
console.log(dim("then run the command above with the code."));
|
|
25674
|
+
process.exit(0);
|
|
25675
|
+
}
|
|
25660
25676
|
if (existingToken) {
|
|
25661
25677
|
console.log(dim("Already signed in."));
|
|
25662
25678
|
if (config.userId)
|
|
@@ -26386,26 +26402,91 @@ function printSuccess(data) {
|
|
|
26386
26402
|
console.log(success("Account connected. You can now run: amiko credits topup <amount>"));
|
|
26387
26403
|
}
|
|
26388
26404
|
function saveCredentials(data) {
|
|
26389
|
-
|
|
26390
|
-
|
|
26391
|
-
|
|
26392
|
-
|
|
26393
|
-
|
|
26394
|
-
|
|
26405
|
+
const update = {};
|
|
26406
|
+
if (data.userId)
|
|
26407
|
+
update.userId = data.userId;
|
|
26408
|
+
if (data.platformUrl)
|
|
26409
|
+
update.platformUrl = data.platformUrl;
|
|
26410
|
+
if (data.billingBase)
|
|
26411
|
+
update.billingBase = data.billingBase;
|
|
26412
|
+
if (data.twinId)
|
|
26413
|
+
update.twinId = data.twinId;
|
|
26414
|
+
if (data.twinToken)
|
|
26415
|
+
update.twinToken = data.twinToken;
|
|
26416
|
+
if (data.privyToken)
|
|
26417
|
+
update.privyToken = data.privyToken;
|
|
26418
|
+
if (data.connectedKeyId)
|
|
26419
|
+
update.connectedKeyId = data.connectedKeyId;
|
|
26420
|
+
if (data.connectedKeyPreview)
|
|
26421
|
+
update.connectedKeyPreview = data.connectedKeyPreview;
|
|
26422
|
+
if (data.connectedKeyName)
|
|
26423
|
+
update.connectedKeyName = data.connectedKeyName;
|
|
26424
|
+
if (data.wallets)
|
|
26425
|
+
update.agentWallets = data.wallets;
|
|
26426
|
+
saveConfig(update);
|
|
26395
26427
|
}
|
|
26396
26428
|
function registerConnectCommand(program2) {
|
|
26397
26429
|
program2.command("connect").description("Connect to an Amiko account (opens browser, or pass a connect URL)").argument("[url]", "Connect URL from Amiko settings (optional — opens browser if omitted)").option("--no-browser", "Print the connect URL instead of opening a browser").action(async (urlStr, opts) => {
|
|
26398
26430
|
if (urlStr) {
|
|
26431
|
+
const input = urlStr.trim();
|
|
26432
|
+
if (input.startsWith("amk_")) {
|
|
26433
|
+
const spinner3 = ora("Connecting with API key...").start();
|
|
26434
|
+
try {
|
|
26435
|
+
const config2 = loadConfig();
|
|
26436
|
+
const billingBase2 = config2.billingBase || "https://billing.heyamiko.com";
|
|
26437
|
+
const res = await fetch(`${billingBase2}/api/auth/bootstrap`, {
|
|
26438
|
+
headers: { Authorization: `Bearer ${input}` }
|
|
26439
|
+
});
|
|
26440
|
+
if (!res.ok) {
|
|
26441
|
+
spinner3.stop();
|
|
26442
|
+
const err = await res.json().catch(() => ({ error: "Invalid API key" }));
|
|
26443
|
+
console.error(error(err.error || `Authentication failed: ${res.status}`));
|
|
26444
|
+
process.exit(1);
|
|
26445
|
+
}
|
|
26446
|
+
const data = await res.json();
|
|
26447
|
+
spinner3.stop();
|
|
26448
|
+
saveConfig({
|
|
26449
|
+
apiKey: input,
|
|
26450
|
+
userId: data.userId,
|
|
26451
|
+
connectedKeyId: data.connectedKey?.id,
|
|
26452
|
+
connectedKeyName: data.connectedKey?.name,
|
|
26453
|
+
connectedKeyPreview: data.connectedKey?.keyPreview
|
|
26454
|
+
});
|
|
26455
|
+
console.log(heading("Connected"));
|
|
26456
|
+
console.log("");
|
|
26457
|
+
console.log(label("User", data.userId));
|
|
26458
|
+
if (data.connectedKey) {
|
|
26459
|
+
console.log(label("Key", `${data.connectedKey.name} (${data.connectedKey.keyPreview})`));
|
|
26460
|
+
}
|
|
26461
|
+
console.log(label("Credits", Number(data.credits?.balance || 0).toLocaleString()));
|
|
26462
|
+
console.log("");
|
|
26463
|
+
console.log(success("Account connected via API key."));
|
|
26464
|
+
} catch (err) {
|
|
26465
|
+
spinner3.stop();
|
|
26466
|
+
console.error(error(err instanceof Error ? err.message : "Failed to connect"));
|
|
26467
|
+
process.exit(1);
|
|
26468
|
+
}
|
|
26469
|
+
return;
|
|
26470
|
+
}
|
|
26399
26471
|
const spinner2 = ora("Connecting...").start();
|
|
26400
26472
|
try {
|
|
26401
|
-
|
|
26402
|
-
|
|
26473
|
+
let code;
|
|
26474
|
+
let redeemOrigin;
|
|
26475
|
+
try {
|
|
26476
|
+
const url = new URL(input);
|
|
26477
|
+
code = url.searchParams.get("code") || input;
|
|
26478
|
+
redeemOrigin = url.origin;
|
|
26479
|
+
} catch {
|
|
26480
|
+
code = input;
|
|
26481
|
+
const config2 = loadConfig();
|
|
26482
|
+
redeemOrigin = config2.billingBase || "https://billing.heyamiko.com";
|
|
26483
|
+
}
|
|
26403
26484
|
if (!code) {
|
|
26404
26485
|
spinner2.stop();
|
|
26405
|
-
console.error(error("Invalid
|
|
26486
|
+
console.error(error("Invalid code or URL."));
|
|
26406
26487
|
process.exit(1);
|
|
26407
26488
|
}
|
|
26408
|
-
const redeemUrl = `${
|
|
26489
|
+
const redeemUrl = `${redeemOrigin}/api/cli/connect/redeem`;
|
|
26409
26490
|
const res = await fetch(redeemUrl, {
|
|
26410
26491
|
method: "POST",
|
|
26411
26492
|
headers: { "Content-Type": "application/json" },
|
|
@@ -26430,7 +26511,7 @@ function registerConnectCommand(program2) {
|
|
|
26430
26511
|
}
|
|
26431
26512
|
const config = loadConfig();
|
|
26432
26513
|
const state = randomBytes2(16).toString("hex");
|
|
26433
|
-
const platformUrl = config.platformUrl || process.env.AMIKO_PLATFORM_URL || "https://
|
|
26514
|
+
const platformUrl = config.platformUrl || process.env.AMIKO_PLATFORM_URL || "https://platform.heyamiko.com";
|
|
26434
26515
|
console.log(heading("Amiko Connect"));
|
|
26435
26516
|
console.log(dim(`Connect your CLI to your Amiko account.
|
|
26436
26517
|
`));
|
|
@@ -26499,7 +26580,7 @@ function loadAgentConfig() {
|
|
|
26499
26580
|
return null;
|
|
26500
26581
|
}
|
|
26501
26582
|
function resolveAuth(cliConfig) {
|
|
26502
|
-
if (cliConfig.
|
|
26583
|
+
if (cliConfig.agentWallets?.length) {
|
|
26503
26584
|
return {
|
|
26504
26585
|
mode: "connected",
|
|
26505
26586
|
platformUrl: cliConfig.platformUrl,
|
|
@@ -26507,6 +26588,7 @@ function resolveAuth(cliConfig) {
|
|
|
26507
26588
|
twinId: cliConfig.twinId,
|
|
26508
26589
|
twinToken: cliConfig.twinToken,
|
|
26509
26590
|
platformKey: cliConfig.apiKey,
|
|
26591
|
+
privyToken: cliConfig.privyToken,
|
|
26510
26592
|
connectedKeyId: cliConfig.connectedKeyId,
|
|
26511
26593
|
userId: cliConfig.userId,
|
|
26512
26594
|
agentWallets: cliConfig.agentWallets
|
|
@@ -26517,6 +26599,7 @@ function resolveAuth(cliConfig) {
|
|
|
26517
26599
|
mode: "connected",
|
|
26518
26600
|
billingBase: cliConfig.billingBase,
|
|
26519
26601
|
platformKey: cliConfig.privyToken,
|
|
26602
|
+
privyToken: cliConfig.privyToken,
|
|
26520
26603
|
connectedKeyId: cliConfig.connectedKeyId,
|
|
26521
26604
|
userId: cliConfig.userId
|
|
26522
26605
|
};
|
|
@@ -26612,23 +26695,32 @@ function registerCreditsCommand(program2) {
|
|
|
26612
26695
|
spinner.stop();
|
|
26613
26696
|
console.log(heading("Credits"));
|
|
26614
26697
|
console.log("");
|
|
26615
|
-
|
|
26698
|
+
{
|
|
26616
26699
|
const spinner2 = ora("Fetching credit balance...").start();
|
|
26617
26700
|
try {
|
|
26618
|
-
|
|
26619
|
-
|
|
26620
|
-
|
|
26621
|
-
|
|
26622
|
-
|
|
26623
|
-
|
|
26624
|
-
|
|
26625
|
-
}
|
|
26626
|
-
|
|
26627
|
-
|
|
26628
|
-
|
|
26629
|
-
|
|
26630
|
-
|
|
26701
|
+
let creditsData = null;
|
|
26702
|
+
if (auth.billingBase && auth.platformKey) {
|
|
26703
|
+
const res = await fetch(`${auth.billingBase}/api/credits`, {
|
|
26704
|
+
headers: { Authorization: `Bearer ${auth.platformKey}` }
|
|
26705
|
+
});
|
|
26706
|
+
if (res.ok)
|
|
26707
|
+
creditsData = await res.json();
|
|
26708
|
+
}
|
|
26709
|
+
if (!creditsData && auth.platformUrl && auth.twinId && auth.twinToken) {
|
|
26710
|
+
const res = await fetch(`${auth.platformUrl}/api/agents/${auth.twinId}/credits/balance`, {
|
|
26711
|
+
headers: { Authorization: `Bearer ${auth.twinToken}` }
|
|
26712
|
+
});
|
|
26713
|
+
if (res.ok) {
|
|
26714
|
+
const data = await res.json();
|
|
26715
|
+
creditsData = { balance: data.balance };
|
|
26631
26716
|
}
|
|
26717
|
+
}
|
|
26718
|
+
spinner2.stop();
|
|
26719
|
+
if (creditsData) {
|
|
26720
|
+
console.log(label("Balance", source_default.bold(Number(creditsData.balance || 0).toLocaleString())));
|
|
26721
|
+
console.log("");
|
|
26722
|
+
} else {
|
|
26723
|
+
console.log(dim(" Could not fetch credit balance"));
|
|
26632
26724
|
console.log("");
|
|
26633
26725
|
}
|
|
26634
26726
|
} catch (err) {
|
|
@@ -26655,10 +26747,44 @@ function registerCreditsCommand(program2) {
|
|
|
26655
26747
|
} else {
|
|
26656
26748
|
console.log(label("Agent Wallets", ""));
|
|
26657
26749
|
for (const w of wallets) {
|
|
26658
|
-
const
|
|
26659
|
-
const
|
|
26660
|
-
const
|
|
26661
|
-
|
|
26750
|
+
const rawChain = w.chain ?? "?";
|
|
26751
|
+
const isEvm = ["base", "ethereum", "tempo"].includes(rawChain);
|
|
26752
|
+
const chainLabel = isEvm ? "EVM (Ethereum · Base · Tempo)" : rawChain.charAt(0).toUpperCase() + rawChain.slice(1);
|
|
26753
|
+
const addr = w.wallet_address || "";
|
|
26754
|
+
const shortAddr = addr ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : "";
|
|
26755
|
+
console.log(` ${source_default.bold(chainLabel)} ${dim(shortAddr)}`);
|
|
26756
|
+
let bals = w.balance && typeof w.balance === "object" ? w.balance : null;
|
|
26757
|
+
if (!bals) {
|
|
26758
|
+
try {
|
|
26759
|
+
const balRes = await fetch(`${auth.platformUrl}/api/agents/${auth.twinId}/wallets/${addr}/balance`, { headers: { Authorization: `Bearer ${auth.twinToken}` } });
|
|
26760
|
+
if (balRes.ok) {
|
|
26761
|
+
const balData = await balRes.json();
|
|
26762
|
+
if (balData.chains) {
|
|
26763
|
+
for (const [chainName, chainBals] of Object.entries(balData.chains)) {
|
|
26764
|
+
const chainLabel2 = chainName.charAt(0).toUpperCase() + chainName.slice(1);
|
|
26765
|
+
console.log(dim(` ${chainLabel2}:`));
|
|
26766
|
+
for (const [token, tData] of Object.entries(chainBals)) {
|
|
26767
|
+
const human = parseFloat(tData.amount) / Math.pow(10, tData.decimals);
|
|
26768
|
+
console.log(dim(` ${token.padEnd(8)} ${human.toFixed(6)}`));
|
|
26769
|
+
}
|
|
26770
|
+
}
|
|
26771
|
+
continue;
|
|
26772
|
+
}
|
|
26773
|
+
bals = balData.balances || {};
|
|
26774
|
+
}
|
|
26775
|
+
} catch {
|
|
26776
|
+
console.log(dim(" (balance unavailable)"));
|
|
26777
|
+
continue;
|
|
26778
|
+
}
|
|
26779
|
+
}
|
|
26780
|
+
if (bals) {
|
|
26781
|
+
for (const [token, data2] of Object.entries(bals)) {
|
|
26782
|
+
const human = parseFloat(data2.amount) / Math.pow(10, data2.decimals);
|
|
26783
|
+
if (human > 0 || ["sol", "eth", "usdc", "amiko"].includes(token.toLowerCase())) {
|
|
26784
|
+
console.log(dim(` ${token.padEnd(10)} ${human.toFixed(6)}`));
|
|
26785
|
+
}
|
|
26786
|
+
}
|
|
26787
|
+
}
|
|
26662
26788
|
}
|
|
26663
26789
|
}
|
|
26664
26790
|
console.log("");
|
|
@@ -26688,11 +26814,18 @@ function registerCreditsCommand(program2) {
|
|
|
26688
26814
|
console.error(error("Not connected"));
|
|
26689
26815
|
process.exit(1);
|
|
26690
26816
|
}
|
|
26691
|
-
if (!auth.
|
|
26817
|
+
if (!auth.billingBase) {
|
|
26818
|
+
spinner.stop();
|
|
26819
|
+
console.error(error("Billing service not configured. Run: amiko connect"));
|
|
26820
|
+
process.exit(1);
|
|
26821
|
+
}
|
|
26822
|
+
const authToken = auth.platformKey || auth.privyToken;
|
|
26823
|
+
if (!authToken) {
|
|
26692
26824
|
spinner.stop();
|
|
26693
|
-
console.error(error("
|
|
26825
|
+
console.error(error("No API key or auth token. Run: amiko connect"));
|
|
26694
26826
|
process.exit(1);
|
|
26695
26827
|
}
|
|
26828
|
+
const authHeaders2 = { Authorization: `Bearer ${authToken}`, "Content-Type": "application/json" };
|
|
26696
26829
|
spinner.stop();
|
|
26697
26830
|
if (!options2.yes) {
|
|
26698
26831
|
console.log(warn(`About to top up ${credits2} credits.`));
|
|
@@ -26700,74 +26833,132 @@ function registerCreditsCommand(program2) {
|
|
|
26700
26833
|
console.log("");
|
|
26701
26834
|
}
|
|
26702
26835
|
if (options2.method === "mpp" && auth.userId && auth.connectedKeyId) {
|
|
26703
|
-
const
|
|
26836
|
+
const spinner2 = ora("Topping up credits via MPP...").start();
|
|
26704
26837
|
const mppResult = await mppCreditsTopup({
|
|
26705
26838
|
userId: auth.userId,
|
|
26706
26839
|
keyId: auth.connectedKeyId,
|
|
26707
26840
|
amount: credits2 / 1e4
|
|
26708
26841
|
});
|
|
26709
|
-
|
|
26842
|
+
spinner2.stop();
|
|
26710
26843
|
if (!mppResult.success) {
|
|
26711
26844
|
console.error(error(mppResult.error || "MPP top-up failed"));
|
|
26712
26845
|
process.exit(1);
|
|
26713
26846
|
}
|
|
26714
|
-
console.log(heading("Top-up Complete"));
|
|
26847
|
+
console.log(heading("Top-up Complete (MPP)"));
|
|
26715
26848
|
console.log("");
|
|
26716
|
-
if (mppResult.credits?.
|
|
26717
|
-
console.log(label("
|
|
26718
|
-
|
|
26719
|
-
if (mppResult.credits?.balance !== undefined) {
|
|
26720
|
-
console.log(label("New Balance", `${mppResult.credits.balance} credits`));
|
|
26721
|
-
}
|
|
26722
|
-
console.log("");
|
|
26723
|
-
console.log(success("Credits topped up successfully via MPP."));
|
|
26849
|
+
if (mppResult.credits?.balance)
|
|
26850
|
+
console.log(label("Balance", mppResult.credits.balance));
|
|
26851
|
+
console.log(success("Credits topped up via MPP."));
|
|
26724
26852
|
return;
|
|
26725
26853
|
}
|
|
26726
|
-
const
|
|
26727
|
-
const
|
|
26728
|
-
|
|
26729
|
-
|
|
26730
|
-
if (
|
|
26731
|
-
|
|
26732
|
-
|
|
26733
|
-
|
|
26734
|
-
|
|
26735
|
-
|
|
26736
|
-
|
|
26737
|
-
|
|
26854
|
+
const agentWallet = auth.agentWallets?.find((w) => w.source === "agent");
|
|
26855
|
+
const walletAddr = options2.wallet || agentWallet?.address || auth.agentWallets?.[0]?.address;
|
|
26856
|
+
const walletChain = options2.chain || auth.agentWallets?.find((w) => w.address === walletAddr)?.chain || "solana";
|
|
26857
|
+
const token = options2.token || "AMIKO";
|
|
26858
|
+
if (!walletAddr) {
|
|
26859
|
+
console.error(error("No wallet found. Specify --wallet <address>"));
|
|
26860
|
+
process.exit(1);
|
|
26861
|
+
}
|
|
26862
|
+
const usdAmount = credits2 / 1e4;
|
|
26863
|
+
let tokenAmount;
|
|
26864
|
+
const stablecoins = ["usdc", "usdt", "usdc.e", "usdt0"];
|
|
26865
|
+
if (stablecoins.includes(token.toLowerCase())) {
|
|
26866
|
+
tokenAmount = usdAmount;
|
|
26867
|
+
} else {
|
|
26868
|
+
const spinner2 = ora(`Fetching ${token} price...`).start();
|
|
26869
|
+
try {
|
|
26870
|
+
const MINTS = {
|
|
26871
|
+
AMIKO: "AY1Ww6MxwC3cCiyrandHqLrp4FXvzgcwQTZpJ2FEpump",
|
|
26872
|
+
SOL: "So11111111111111111111111111111111111111112"
|
|
26873
|
+
};
|
|
26874
|
+
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
26875
|
+
const mint = MINTS[token.toUpperCase()];
|
|
26876
|
+
if (!mint) {
|
|
26877
|
+
spinner2.stop();
|
|
26878
|
+
console.error(error(`Unknown token: ${token}`));
|
|
26879
|
+
process.exit(1);
|
|
26880
|
+
}
|
|
26881
|
+
const decimals = token.toUpperCase() === "SOL" ? 9 : 6;
|
|
26882
|
+
const oneToken = Math.pow(10, decimals).toString();
|
|
26883
|
+
const jupRes = await fetch(`https://lite-api.jup.ag/swap/v1/quote?inputMint=${mint}&outputMint=${USDC_MINT}&amount=${oneToken}&slippageBps=100`);
|
|
26884
|
+
if (!jupRes.ok) {
|
|
26885
|
+
spinner2.stop();
|
|
26886
|
+
console.error(error("Failed to fetch token price"));
|
|
26887
|
+
process.exit(1);
|
|
26888
|
+
}
|
|
26889
|
+
const jupData = await jupRes.json();
|
|
26890
|
+
const pricePerToken = parseFloat(jupData.outAmount) / 1e6;
|
|
26891
|
+
tokenAmount = usdAmount / pricePerToken;
|
|
26892
|
+
spinner2.stop();
|
|
26893
|
+
console.log(label("Price", `1 ${token} = $${pricePerToken.toFixed(4)}`));
|
|
26894
|
+
console.log(label("Cost", `${tokenAmount.toFixed(6)} ${token} (~$${usdAmount.toFixed(2)})`));
|
|
26895
|
+
console.log("");
|
|
26896
|
+
} catch {
|
|
26897
|
+
spinner2.stop();
|
|
26898
|
+
console.error(error("Failed to fetch token price"));
|
|
26899
|
+
process.exit(1);
|
|
26900
|
+
}
|
|
26901
|
+
}
|
|
26902
|
+
const TREASURY = "FPiZAf3jEnNfCwfvbv46jdPfHbmSepD4Q6iHiLJDQXvb";
|
|
26903
|
+
const spinner3 = ora("Transferring tokens to treasury...").start();
|
|
26904
|
+
const transferRes = await fetch(`${auth.billingBase}/api/crossmint/wallets/${encodeURIComponent(walletAddr)}/transfer`, {
|
|
26738
26905
|
method: "POST",
|
|
26739
|
-
headers:
|
|
26740
|
-
|
|
26741
|
-
|
|
26742
|
-
|
|
26743
|
-
|
|
26906
|
+
headers: authHeaders2,
|
|
26907
|
+
body: JSON.stringify({
|
|
26908
|
+
to: TREASURY,
|
|
26909
|
+
amount: tokenAmount.toFixed(6),
|
|
26910
|
+
token,
|
|
26911
|
+
chain: walletChain
|
|
26912
|
+
})
|
|
26744
26913
|
});
|
|
26745
|
-
|
|
26746
|
-
|
|
26747
|
-
const err = await
|
|
26748
|
-
console.error(error(err.error || `
|
|
26914
|
+
if (!transferRes.ok) {
|
|
26915
|
+
spinner3.stop();
|
|
26916
|
+
const err = await transferRes.json().catch(() => ({ error: "Transfer failed" }));
|
|
26917
|
+
console.error(error(err.error || `Transfer failed: ${transferRes.status}`));
|
|
26749
26918
|
process.exit(1);
|
|
26750
26919
|
}
|
|
26751
|
-
const
|
|
26752
|
-
|
|
26753
|
-
|
|
26754
|
-
if (
|
|
26755
|
-
console.
|
|
26756
|
-
|
|
26757
|
-
if (data.tokenAmount !== undefined) {
|
|
26758
|
-
console.log(label("Token Amount", `${data.tokenAmount}${data.token ? ` ${data.token}` : ""}`));
|
|
26920
|
+
const transferData = await transferRes.json();
|
|
26921
|
+
const txHash = transferData.txHash;
|
|
26922
|
+
spinner3.stop();
|
|
26923
|
+
if (!txHash) {
|
|
26924
|
+
console.error(error("Transfer sent but no transaction hash returned."));
|
|
26925
|
+
process.exit(1);
|
|
26759
26926
|
}
|
|
26760
|
-
|
|
26761
|
-
|
|
26927
|
+
console.log(label("Tx Hash", dim(txHash.slice(0, 16) + "...")));
|
|
26928
|
+
const keyId = auth.connectedKeyId;
|
|
26929
|
+
if (!keyId) {
|
|
26930
|
+
console.log(warn("No connected API key — transfer sent but credits not verified."));
|
|
26931
|
+
console.log(dim(`Tx: ${txHash}`));
|
|
26932
|
+
process.exit(0);
|
|
26762
26933
|
}
|
|
26763
|
-
|
|
26764
|
-
|
|
26934
|
+
const spinner4 = ora("Verifying and crediting...").start();
|
|
26935
|
+
const verifyRes = await fetch(`${auth.billingBase}/api/user/keys/${keyId}/topup/wallet`, {
|
|
26936
|
+
method: "POST",
|
|
26937
|
+
headers: authHeaders2,
|
|
26938
|
+
body: JSON.stringify({
|
|
26939
|
+
txSignature: txHash,
|
|
26940
|
+
amount: tokenAmount,
|
|
26941
|
+
token: token.toUpperCase()
|
|
26942
|
+
})
|
|
26943
|
+
});
|
|
26944
|
+
spinner4.stop();
|
|
26945
|
+
if (!verifyRes.ok) {
|
|
26946
|
+
const err = await verifyRes.json().catch(() => ({ error: "Verify failed" }));
|
|
26947
|
+
console.error(error(err.error || "Transfer sent but credit verification failed."));
|
|
26948
|
+
console.log(dim(`Tx: ${txHash}`));
|
|
26949
|
+
process.exit(1);
|
|
26765
26950
|
}
|
|
26766
|
-
|
|
26767
|
-
|
|
26951
|
+
const verifyData = await verifyRes.json();
|
|
26952
|
+
console.log(heading("Top-up Complete"));
|
|
26953
|
+
console.log("");
|
|
26954
|
+
console.log(label("Credits", source_default.bold(credits2.toLocaleString())));
|
|
26955
|
+
console.log(label("Token", `${tokenAmount.toFixed(6)} ${token}`));
|
|
26956
|
+
console.log(label("USD", `$${usdAmount.toFixed(2)}`));
|
|
26957
|
+
if (verifyData.credits?.balance) {
|
|
26958
|
+
console.log(label("Balance", source_default.bold(Number(verifyData.credits.balance).toLocaleString())));
|
|
26768
26959
|
}
|
|
26769
26960
|
console.log("");
|
|
26770
|
-
console.log(success("Credits topped up
|
|
26961
|
+
console.log(success("Credits topped up."));
|
|
26771
26962
|
} catch (err) {
|
|
26772
26963
|
spinner.stop();
|
|
26773
26964
|
console.error(error(err instanceof Error ? err.message : "Failed to top up credits"));
|
|
@@ -26828,7 +27019,7 @@ var didOnboard = await runOnboarding(process.argv);
|
|
|
26828
27019
|
if (didOnboard)
|
|
26829
27020
|
process.exit(0);
|
|
26830
27021
|
var program2 = new Command;
|
|
26831
|
-
program2.name("amiko").description("Amiko CLI — manage agents, wallets, credits, and
|
|
27022
|
+
program2.name("amiko").description("Amiko CLI — manage agents, wallets, credits, and the MPP marketplace").version("0.3.0");
|
|
26832
27023
|
registerBrowseCommand(program2);
|
|
26833
27024
|
registerCallCommand(program2);
|
|
26834
27025
|
registerWalletCommand(program2);
|