@heyamiko/amiko-cli 0.14.0-beta.13 → 0.14.0-beta.14
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 +5 -1
- package/dist/index.js +56 -5
- package/package.json +1 -1
- package/skills/SKILL.md +17 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @heyamiko/amiko-cli (v0.14.0-beta.
|
|
1
|
+
# @heyamiko/amiko-cli (v0.14.0-beta.14)
|
|
2
2
|
|
|
3
3
|
Manage wallets, credits, swaps, MPP marketplace services, and your Amiko twin (identity, documents, voice, avatar, friends, feed) from the terminal. Works for both human users and AI agents running on OpenClaw.
|
|
4
4
|
|
|
@@ -583,6 +583,10 @@ npm publish
|
|
|
583
583
|
|
|
584
584
|
## Changelog
|
|
585
585
|
|
|
586
|
+
### 0.14.0-beta.14
|
|
587
|
+
|
|
588
|
+
- `credits balance` prefers `AMIKO_API_KEY` (`amk_`) → `billing.heyamiko.com/api/credits` directly; falls back to twin-token platform proxy. Override base with `AMIKO_BILLING_URL`.
|
|
589
|
+
|
|
586
590
|
### 0.14.0-beta.13
|
|
587
591
|
|
|
588
592
|
- **Create Studio TTS + voice clone: MiniMax.** `amiko create tts` accepts `--provider minimax|elevenlabs` (infers from `speech-*` / `eleven_*` models when omitted), with provider-specific defaults (`speech-2.8-turbo` + `English_expressive_narrator` vs `eleven_multilingual_v2` + Rachel). Quote body includes `voiceId`. Cloned-voice examples require `--provider minimax` when using a MiniMax `voice_id`.
|
package/dist/index.js
CHANGED
|
@@ -23655,7 +23655,9 @@ function readFromFile(path) {
|
|
|
23655
23655
|
twinId: asString(parsed.amikoTwinId) ?? asString(parsed.AMIKO_TWIN_ID),
|
|
23656
23656
|
userId: asString(parsed.amikoUserId) ?? asString(parsed.AMIKO_USER_ID),
|
|
23657
23657
|
platformUrl: asString(parsed.amikoPlatformUrl) ?? asString(parsed.AMIKO_PLATFORM_URL),
|
|
23658
|
-
apiBase: asString(parsed.amikoApiBase) ?? asString(parsed.AMIKO_API_BASE) ?? asString(parsed.apiBase)
|
|
23658
|
+
apiBase: asString(parsed.amikoApiBase) ?? asString(parsed.AMIKO_API_BASE) ?? asString(parsed.apiBase),
|
|
23659
|
+
billingApiKey: asString(parsed.amikoApiKey) ?? asString(parsed.AMIKO_API_KEY) ?? asString(parsed.billingApiKey),
|
|
23660
|
+
billingUrl: asString(parsed.amikoBillingUrl) ?? asString(parsed.AMIKO_BILLING_URL) ?? asString(parsed.billingUrl)
|
|
23659
23661
|
};
|
|
23660
23662
|
} catch {
|
|
23661
23663
|
return null;
|
|
@@ -23674,6 +23676,8 @@ function readFromEnv() {
|
|
|
23674
23676
|
userId: asString(process.env.AMIKO_USER_ID),
|
|
23675
23677
|
platformUrl: asString(process.env.AMIKO_PLATFORM_URL),
|
|
23676
23678
|
apiBase: asString(process.env.AMIKO_API_BASE),
|
|
23679
|
+
billingApiKey: asString(process.env.AMIKO_API_KEY),
|
|
23680
|
+
billingUrl: asString(process.env.AMIKO_BILLING_URL),
|
|
23677
23681
|
...readRoutingIdsFromEnv()
|
|
23678
23682
|
};
|
|
23679
23683
|
}
|
|
@@ -23681,7 +23685,13 @@ function resolveFileAuth(path) {
|
|
|
23681
23685
|
const fromFile = readFromFile(path);
|
|
23682
23686
|
if (!fromFile)
|
|
23683
23687
|
return null;
|
|
23684
|
-
|
|
23688
|
+
const fromEnv = readFromEnv();
|
|
23689
|
+
return {
|
|
23690
|
+
...fromFile,
|
|
23691
|
+
...readRoutingIdsFromEnv(),
|
|
23692
|
+
billingApiKey: fromEnv.billingApiKey ?? fromFile.billingApiKey,
|
|
23693
|
+
billingUrl: fromEnv.billingUrl ?? fromFile.billingUrl
|
|
23694
|
+
};
|
|
23685
23695
|
}
|
|
23686
23696
|
function resolveAuth() {
|
|
23687
23697
|
const filePath = findAmikoJsonPath();
|
|
@@ -25418,7 +25428,31 @@ function registerBridgeCommand(program2) {
|
|
|
25418
25428
|
import readline2 from "node:readline";
|
|
25419
25429
|
|
|
25420
25430
|
// src/lib/balance.ts
|
|
25421
|
-
|
|
25431
|
+
var DEFAULT_BILLING_URL = "https://billing.heyamiko.com";
|
|
25432
|
+
function billingBase(auth) {
|
|
25433
|
+
const url = auth.billingUrl || DEFAULT_BILLING_URL;
|
|
25434
|
+
return url.replace(/\/$/, "");
|
|
25435
|
+
}
|
|
25436
|
+
async function fetchCreditsBalanceViaAmk(auth) {
|
|
25437
|
+
const apiKey = auth.billingApiKey;
|
|
25438
|
+
if (!apiKey || !apiKey.startsWith("amk_"))
|
|
25439
|
+
return null;
|
|
25440
|
+
try {
|
|
25441
|
+
const res = await fetch(`${billingBase(auth)}/api/credits`, {
|
|
25442
|
+
method: "GET",
|
|
25443
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
25444
|
+
signal: AbortSignal.timeout(15000)
|
|
25445
|
+
});
|
|
25446
|
+
if (!res.ok)
|
|
25447
|
+
return null;
|
|
25448
|
+
const data = await res.json();
|
|
25449
|
+
const raw = data.displayBalance;
|
|
25450
|
+
return typeof raw === "number" && isFinite(raw) ? Math.round(raw) : null;
|
|
25451
|
+
} catch {
|
|
25452
|
+
return null;
|
|
25453
|
+
}
|
|
25454
|
+
}
|
|
25455
|
+
async function fetchCreditsBalanceViaPlatformProxy(auth) {
|
|
25422
25456
|
if (!auth.twinToken)
|
|
25423
25457
|
return null;
|
|
25424
25458
|
try {
|
|
@@ -25429,6 +25463,12 @@ async function fetchCreditsBalance(auth) {
|
|
|
25429
25463
|
return null;
|
|
25430
25464
|
}
|
|
25431
25465
|
}
|
|
25466
|
+
async function fetchCreditsBalance(auth) {
|
|
25467
|
+
const viaAmk = await fetchCreditsBalanceViaAmk(auth);
|
|
25468
|
+
if (viaAmk != null)
|
|
25469
|
+
return viaAmk;
|
|
25470
|
+
return fetchCreditsBalanceViaPlatformProxy(auth);
|
|
25471
|
+
}
|
|
25432
25472
|
async function printBalanceRemaining(auth) {
|
|
25433
25473
|
const balance = await fetchCreditsBalance(auth);
|
|
25434
25474
|
if (balance == null) {
|
|
@@ -28639,7 +28679,7 @@ function registerAccountsCommand(program2) {
|
|
|
28639
28679
|
}
|
|
28640
28680
|
}, { json: opts.json });
|
|
28641
28681
|
});
|
|
28642
|
-
program2.command("info").description("Get twin info (name, description, voice, avatar)").option("--twin <idOrName>", "Target twin id or name").option("--json", "Output as JSON").action(async (opts) => {
|
|
28682
|
+
program2.command("info").description("Get twin info (name, description, voice ids, avatar)").option("--twin <idOrName>", "Target twin id or name").option("--json", "Output as JSON").action(async (opts) => {
|
|
28643
28683
|
const config2 = loadConfig();
|
|
28644
28684
|
const auth = resolveAuth();
|
|
28645
28685
|
let twinId;
|
|
@@ -28663,13 +28703,24 @@ function registerAccountsCommand(program2) {
|
|
|
28663
28703
|
console.log(label("Description", t.description));
|
|
28664
28704
|
console.log(label("Public", t.is_public ? "yes" : "no"));
|
|
28665
28705
|
if (t.voice_status)
|
|
28666
|
-
console.log(label("Voice", t.voice_status));
|
|
28706
|
+
console.log(label("Voice status", t.voice_status));
|
|
28707
|
+
if (t.voice_id)
|
|
28708
|
+
console.log(label("ElevenLabs voice_id", t.voice_id));
|
|
28709
|
+
else
|
|
28710
|
+
console.log(label("ElevenLabs voice_id", dim("(none)")));
|
|
28711
|
+
if (t.minimax_voice_id)
|
|
28712
|
+
console.log(label("MiniMax voice_id", t.minimax_voice_id));
|
|
28713
|
+
else
|
|
28714
|
+
console.log(label("MiniMax voice_id", dim("(none — clone with amiko voice clone)")));
|
|
28667
28715
|
if (t.avatar_url)
|
|
28668
28716
|
console.log(label("Avatar", t.avatar_url));
|
|
28669
28717
|
if (t.shipped_at)
|
|
28670
28718
|
console.log(label("Shipped", t.shipped_at));
|
|
28671
28719
|
if (t.updated_at)
|
|
28672
28720
|
console.log(dim(`Updated ${t.updated_at}`));
|
|
28721
|
+
console.log("");
|
|
28722
|
+
console.log(dim('MiniMax TTS: amiko create tts "…" --provider minimax --voice <MiniMax voice_id> --yes'));
|
|
28723
|
+
console.log(dim('ElevenLabs TTS: amiko create tts "…" --provider elevenlabs --voice <ElevenLabs voice_id> --yes'));
|
|
28673
28724
|
}, { json: opts.json });
|
|
28674
28725
|
} catch (e5) {
|
|
28675
28726
|
spinner?.stop();
|
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -35,6 +35,8 @@ Call your shell tool (your runtime calls it `bash`, `shell`, `run`, or similar)
|
|
|
35
35
|
| "share the group's invite link" (asked by an admin) | shell → `amiko chat group info "<group>"` (confirm they're admin) → `amiko chat group invite "<group>"` |
|
|
36
36
|
| "react to the latest message from Ava about the team with a heart" | shell → `amiko chat read "Ava"` (find that message, copy its `id`) → `amiko chat react <messageId> ❤️ --yes` |
|
|
37
37
|
| "what can amiko do?" | shell → `amiko --help` |
|
|
38
|
+
| "what's my MiniMax / ElevenLabs voice id?" | shell → `amiko info` |
|
|
39
|
+
| "speak with my cloned MiniMax voice" | shell → `amiko info`, quote the cost, obtain explicit approval, then run `amiko create tts "…" --provider minimax --voice <minimax_voice_id> --yes` |
|
|
38
40
|
|
|
39
41
|
The CLI is installed globally and is pre-authenticated when you're inside your workspace folder. Never suggest `amiko login` or `amiko connect` — they don't exist.
|
|
40
42
|
|
|
@@ -96,6 +98,21 @@ All paid markets commands auto-select the twin's active Solana wallet (see `--wa
|
|
|
96
98
|
|
|
97
99
|
**Prefer `amiko create` for anything it supports.** For media generation — image, video, speech (TTS), music, SFX — use `amiko create` (async, charge-on-success, never loses money on a timeout), NOT `markets`. Reach for `markets` **only for what `create` does not cover**: X/Twitter search, Amazon, AI chat, speech-to-text/transcription, and arbitrary MPP endpoints via `markets service call`.
|
|
98
100
|
|
|
101
|
+
### Voice IDs — never guess
|
|
102
|
+
|
|
103
|
+
This twin has **two** optional TTS ids. They are **not** the same:
|
|
104
|
+
|
|
105
|
+
| Field | Provider | How to get it | How to use |
|
|
106
|
+
|---|---|---|---|
|
|
107
|
+
| `voice_id` | ElevenLabs | shown by `amiko info` | quote cost + approval, then `amiko create tts "…" --provider elevenlabs --voice <voice_id> --yes` |
|
|
108
|
+
| `minimax_voice_id` | MiniMax | shown by `amiko info` | quote cost + approval, then `amiko create tts "…" --provider minimax --voice <minimax_voice_id> --yes` |
|
|
109
|
+
|
|
110
|
+
- **Before any TTS or clone follow-up**, run `amiko info` (or `amiko info --json`) and read the printed ids. Do **not** invent a `voice_id`, ask the owner to paste one you already have on the twin, or claim MiniMax TTS is blocked because you "don't know" the id.
|
|
111
|
+
- Paid voice ops still need the Critical Rules gate: quote live cost, get explicit approval, only then append `--yes`.
|
|
112
|
+
- If MiniMax voice_id is `(none)`, quote the clone cost, obtain explicit approval, then run `amiko voice clone <audio> --provider minimax --yes` and `amiko info` again.
|
|
113
|
+
- System MiniMax voices (no clone) also work: e.g. `--voice English_expressive_narrator --provider minimax` (same approval gate before `--yes`).
|
|
114
|
+
- `markets service tts <voiceId> "…" --provider minimax --yes` needs the same MiniMax id and approval gate.
|
|
115
|
+
|
|
99
116
|
**Payment token:** `markets search`, `markets image`, and `markets amazon search` accept `--token <AMIKO|USDC|USDT>` (default AMIKO); `markets service call` uses `--usdc`/`--usdt` (pass `auto` to price from USD). Stables are pinned at $1.00 — the amount equals the endpoint's USD price — so there is no forced swap through AMIKO. When the owner asks to pay in USDT/USDC, pass the flag; do NOT swap first.
|
|
100
117
|
|
|
101
118
|
## Create Studio — behavior notes
|