@heyamiko/amiko-cli 0.16.1 → 0.16.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 +6 -0
- package/dist/index.js +13 -2
- package/package.json +1 -1
- package/skills/SKILL.md +47 -5
package/README.md
CHANGED
|
@@ -2617,6 +2617,12 @@ npm publish
|
|
|
2617
2617
|
|
|
2618
2618
|
## Changelog
|
|
2619
2619
|
|
|
2620
|
+
### 0.16.2
|
|
2621
|
+
|
|
2622
|
+
- **`--yes` now discloses the cost instead of hiding it.** The approval gate treated `--yes` as permission to skip the *prompt* and the *disclosure* together, so an agent that passed it generated media with the amount appearing nowhere in the output — the one path where money moves was the one path that said nothing about it. The quote has already been fetched by then, so `Cost: …` now prints on every approved paid run. It goes to **stderr**, because job ids and `--raw` JSON go to stdout and callers parse them; free outward actions (a chat message, a follow) still print nothing, so nothing reintroduces "the cost is 0" for an action that has no price.
|
|
2623
|
+
- **A failed price quote says so.** `create` swallowed a quote failure to avoid blocking a job that the server charges for anyway — but that made "we couldn't get a price" indistinguishable from "this one is free", and the fallback note then read as the price. It now prints `Price quote failed — the amount below is unknown` and labels the figure accordingly.
|
|
2624
|
+
- **SKILL.md: a three-step flow for generation, replacing an empty section.** `### Quoting cost before running` was a heading with no body. Agents were picking the model, duration, aspect ratio and resolution on the owner's behalf and spending on the result, because a request like "make me a video of my cat" contains none of them. The rule is now: **propose** (model and why, mode, the parameters the owner didn't think to give, a price band flagged as rough) → **quote** (run without `--yes`, show the CLI's exact number) → **generate** (`--yes`, nothing else changed). Steps 1 and 2 may share a turn when the owner was already specific; step 3 is always separately approved.
|
|
2625
|
+
|
|
2620
2626
|
### 0.16.1
|
|
2621
2627
|
|
|
2622
2628
|
- **[Command Reference](#command-reference) in the README** — every group, subcommand, argument and flag the CLI accepts, with defaults. It is generated from the same commander tree `--help` renders (`bun run gen:reference`), and `bun test` fails if it drifts, so the README can't go stale behind a newly added flag.
|
package/dist/index.js
CHANGED
|
@@ -27057,8 +27057,12 @@ async function requireApproval(args) {
|
|
|
27057
27057
|
if (args.cost === undefined === (args.free === undefined)) {
|
|
27058
27058
|
throw new Error("requireApproval: set exactly one of `cost` or `free`.");
|
|
27059
27059
|
}
|
|
27060
|
-
if (args.yes)
|
|
27060
|
+
if (args.yes) {
|
|
27061
|
+
if (args.cost !== undefined) {
|
|
27062
|
+
console.error(dim(`Cost: ${args.cost}`));
|
|
27063
|
+
}
|
|
27061
27064
|
return;
|
|
27065
|
+
}
|
|
27062
27066
|
if (process.stdin.isTTY) {
|
|
27063
27067
|
console.log("");
|
|
27064
27068
|
console.log(`About to run: ${args.summary}`);
|
|
@@ -29799,6 +29803,7 @@ async function submitCreateJob(opts) {
|
|
|
29799
29803
|
}
|
|
29800
29804
|
let costLine = payCredits ? "reserved from your Amiko account credits, captured on success (released on failure)" : "charged from your twin wallet on success (nothing on failure)";
|
|
29801
29805
|
let quotedCostAmiko;
|
|
29806
|
+
let quoteFailed = false;
|
|
29802
29807
|
try {
|
|
29803
29808
|
const q = await amikoWebFetch(auth, "/api/create/quote", {
|
|
29804
29809
|
method: "POST",
|
|
@@ -29813,7 +29818,13 @@ async function submitCreateJob(opts) {
|
|
|
29813
29818
|
if (Number.isFinite(n))
|
|
29814
29819
|
quotedCostAmiko = n;
|
|
29815
29820
|
}
|
|
29816
|
-
} catch {
|
|
29821
|
+
} catch {
|
|
29822
|
+
quoteFailed = true;
|
|
29823
|
+
}
|
|
29824
|
+
if (quoteFailed) {
|
|
29825
|
+
console.error(warn("Price quote failed — the amount below is unknown."));
|
|
29826
|
+
costLine = `unknown (quote failed) — ${costLine}`;
|
|
29827
|
+
}
|
|
29817
29828
|
const preferredToken = typeof jobBody.preferredToken === "string" ? jobBody.preferredToken.toUpperCase() : undefined;
|
|
29818
29829
|
const chargeIsAmiko = !payCredits && (preferredToken === undefined || preferredToken === "AMIKO");
|
|
29819
29830
|
const autoApprovable = payCredits || chargeIsAmiko;
|
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -22,9 +22,9 @@ Call your shell tool (your runtime calls it `bash`, `shell`, `run`, or similar)
|
|
|
22
22
|
| "swap 1 SOL to USDC" | shell → `amiko wallets swap quote 1 SOL USDC` (then send with `--yes` after approval) |
|
|
23
23
|
| "any notifications?" | shell → `amiko notifications list --unread` |
|
|
24
24
|
| "any new posts I haven't seen?" | shell → `amiko feed --unread` |
|
|
25
|
-
| "make an image of a whale in space" |
|
|
26
|
-
| "animate my cover art / album visual" |
|
|
27
|
-
| "generate a lo-fi track" |
|
|
25
|
+
| "make an image of a whale in space" | propose model + settings → quote (run without `--yes`) → on approval `amiko create image "a whale in space" --yes` |
|
|
26
|
+
| "animate my cover art / album visual" | propose + quote first → `amiko create video "subtle motion…" --first-frame <cover-url> --model MiniMax-Hailuo-02 --yes` → wait ~2–9 min → `amiko create status <jobId>` |
|
|
27
|
+
| "generate a lo-fi track" | propose model + `--duration` → quote → on approval `amiko create music "lo-fi chill beat" --yes` |
|
|
28
28
|
| "show my recent creations" | shell → `amiko create media` |
|
|
29
29
|
| "did my video finish?" | shell → `amiko create status <jobId>` or `amiko create media --service video --limit 5` |
|
|
30
30
|
| "upload report.pdf to my drive" | shell → `amiko drive upload ./report.pdf` |
|
|
@@ -72,7 +72,7 @@ Discover everything via `amiko --help` (or `amiko <group> --help` / `amiko <grou
|
|
|
72
72
|
|
|
73
73
|
## Critical Rules
|
|
74
74
|
|
|
75
|
-
1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI refuses to run `search *`, `markets *`, `create *`, `card mint`, `credits topup`, `wallets swap send`, `wallets bridge send`, `wallets transfer` unless `--yes` is passed. The refusal prints the cost and the re-run command. **Quote the cost, get explicit approval, THEN append `--yes`.** The same `--yes` gate also covers **free outward social actions** — `chat send`, `chat pin` (the whole chat sees a pinned-message announcement), `chat group create`, `chat group add` (real people see them, so get the owner's explicit approval for the action itself) — and **destructive ops** like `chat unpin` (removes the pin for everyone), `chat mark-read --all` (irreversibly marks every conversation read — senders see read ticks), `chat group remove/leave/rename/promote/mention-all`, `chat lists create/rename/add/remove/delete` (private to the owner, but they reshape the owner's chat UI), `friends nickname set/remove` (private to the owner, but it changes how that friend is displayed everywhere in the owner's apps), `twin update --public`, `drive delete`, `drive share` / `drive folder share` (exposes the file — or the folder's ENTIRE subtree — to anyone with the link), `friends remove`, `friends reports request`, `avatar update`, `voice reset`, `review reject`. **For these free actions never mention cost, never say "the cost is 0", and never call it a paid operation** — ask for plain confirmation of the action itself (e.g. "Send "hi" to Mars — go ahead?").
|
|
75
|
+
1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI refuses to run `search *`, `markets *`, `create *`, `card mint`, `credits topup`, `wallets swap send`, `wallets bridge send`, `wallets transfer` unless `--yes` is passed. The refusal prints the cost and the re-run command. **Quote the cost, get explicit approval, THEN append `--yes`.** For `create *` there is a step before that — propose the model and settings and get the owner's sign-off on the *plan* first; see **Proposing, then quoting, before you generate**. The same `--yes` gate also covers **free outward social actions** — `chat send`, `chat pin` (the whole chat sees a pinned-message announcement), `chat group create`, `chat group add` (real people see them, so get the owner's explicit approval for the action itself) — and **destructive ops** like `chat unpin` (removes the pin for everyone), `chat mark-read --all` (irreversibly marks every conversation read — senders see read ticks), `chat group remove/leave/rename/promote/mention-all`, `chat lists create/rename/add/remove/delete` (private to the owner, but they reshape the owner's chat UI), `friends nickname set/remove` (private to the owner, but it changes how that friend is displayed everywhere in the owner's apps), `twin update --public`, `drive delete`, `drive share` / `drive folder share` (exposes the file — or the folder's ENTIRE subtree — to anyone with the link), `friends remove`, `friends reports request`, `avatar update`, `voice reset`, `review reject`. **For these free actions never mention cost, never say "the cost is 0", and never call it a paid operation** — ask for plain confirmation of the action itself (e.g. "Send "hi" to Mars — go ahead?").
|
|
76
76
|
2. **After every paid command, report the remaining balance.** The CLI prints a `Balance: N credits` line — include that figure in your reply.
|
|
77
77
|
3. **Never retry a failed command.** Report and stop. Every paid call costs tokens even on failure.
|
|
78
78
|
4. **Auth is automatic.** Never suggest `amiko login` / `amiko connect`. Run from the agent's workspace folder; if anything looks off, `amiko accounts` shows the resolved `userId` / `twinId`.
|
|
@@ -91,7 +91,47 @@ Discover everything via `amiko --help` (or `amiko <group> --help` / `amiko <grou
|
|
|
91
91
|
|
|
92
92
|
`post likers` and `users search --all` stop at a safety cap. When one does, the human output prints `⚠ Partial results: …`, JSON sets `"partial": true`, and the count renders as `N+`. **If you see that, tell the owner it is a partial set (the first N), not the total** — never present a capped number as exact.
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
## Proposing, then quoting, before you generate
|
|
95
|
+
|
|
96
|
+
**Never send a generation with `--yes` on the first turn.** `--yes` means "a human already approved this". Passing it on the turn the owner asked for the media makes that a lie — they approved the *idea*, not the model, the settings, or the price you chose on their behalf.
|
|
97
|
+
|
|
98
|
+
Owners ask vaguely: *"make me a video of my cat"*. That request does not contain a model, a duration, an aspect ratio, a resolution, or a budget — **you** are about to pick all five and spend their money on the result. So the flow is three steps, and the first one is a conversation, not a command.
|
|
99
|
+
|
|
100
|
+
**Step 1 — propose.** Before touching the CLI, tell the owner what you'd do and why, and name every choice you're making for them:
|
|
101
|
+
|
|
102
|
+
- **Model + why** — "`MiniMax-Hailuo-02` — good motion on live subjects and cheaper than H3; if you want 2K or a clip longer than 10s I'd switch to `MiniMax-H3`, which bills per second."
|
|
103
|
+
- **Mode** — text-to-video, image-to-video (`--first-frame`), first+last frame, reference-to-video, subject reference. If they sent you a photo, say you'll use it and how.
|
|
104
|
+
- **The parameters they didn't think to give you** — duration (`--seconds`), aspect ratio (`--aspect`), resolution (`--resolution`), audio (`--generate-audio`). Say the value **and** that it's your default, so they know it's theirs to change: "6 seconds, 16:9, 1080P — say the word if you want vertical for stories."
|
|
105
|
+
- **A rough price band, flagged as rough** — "somewhere around $0.10; I'll get you the exact number before anything runs."
|
|
106
|
+
|
|
107
|
+
Then ask: *"Want me to go with that, or change something?"*
|
|
108
|
+
|
|
109
|
+
**Step 2 — quote.** Once they've agreed to the shape of the job, **run the command WITHOUT `--yes`.** In your shell it refuses (exit 2) and prints the exact cost, the model, and what it's about to do. Nothing is spent. This is a *quote*, not a failure — don't report it to the owner as an error, and don't retry it with `--yes` to "get past" it.
|
|
110
|
+
|
|
111
|
+
Put the result in front of them — every row, every time:
|
|
112
|
+
|
|
113
|
+
| | Example |
|
|
114
|
+
|---|---|
|
|
115
|
+
| **What** | "a 6-second video of your cat on the windowsill, 16:9, 1080P" |
|
|
116
|
+
| **Model** | `MiniMax-Hailuo-02` (say it even when you let it default — the default was your choice, not theirs) |
|
|
117
|
+
| **Cost** | `≈ 871 Amiko credits (≈ $0.0871)` — the number the CLI printed, never one you estimated |
|
|
118
|
+
| **Attached media** | "using the photo you sent as the first frame" — if you're attaching files, name them |
|
|
119
|
+
| **Billing rail** | account credits (default) or twin wallet (`--pay wallet`) |
|
|
120
|
+
|
|
121
|
+
Then ask plainly: *"Generate this for ≈871 credits?"*
|
|
122
|
+
|
|
123
|
+
**Step 3 — generate.** On an explicit yes, re-run with `--yes` appended and **nothing else changed**.
|
|
124
|
+
|
|
125
|
+
Rules that follow from this:
|
|
126
|
+
|
|
127
|
+
- **Steps 1 and 2 can share a turn when the owner was already specific.** "Generate a 6s 16:9 clip of my cat with Hailuo-02" has made every choice itself — go straight to the quote. What you may never collapse is step 3: the price is approved separately, always.
|
|
128
|
+
- **Quote the CLI's number, not your own.** Prices change per model, resolution, duration and reference count. A figure you worked out from a price table you remember is a guess; the `Cost:` line the CLI printed is the real quote. The rough band in step 1 is explicitly a band — don't let it stand in for the quote.
|
|
129
|
+
- **If the CLI prints `Price quote failed — the amount below is unknown`, say exactly that** and ask whether to proceed blind. Do not substitute an estimate, and do not stay quiet about it.
|
|
130
|
+
- **With `--yes`, the cost line still prints** (to stderr, as `Cost: …`). Read it and include the figure when you report back — that is the record of what was actually spent.
|
|
131
|
+
- **Changing anything re-opens approval.** A different model, longer duration, higher resolution, or added reference files is a different price — go back to the quote, don't reuse the earlier yes.
|
|
132
|
+
- **One approval, one generation.** "Make me three variations" needs the cost of all three quoted up front, or one approval per run.
|
|
133
|
+
- **A failed job is not a free retry.** Generations are charged on success, but a retry is a new spend — re-propose (the failure usually means a parameter should change) and re-quote.
|
|
134
|
+
- **`AMIKO_AUTO_APPROVE_LIMIT`** may auto-approve cheap jobs without a prompt; the CLI prints `Auto-approved (cost N ≤ limit M AMIKO)`. It waives step 3, not steps 1 and 2 — still report what was spent.
|
|
95
135
|
|
|
96
136
|
## Search — `amiko search <vertical> <query>`
|
|
97
137
|
|
|
@@ -167,6 +207,8 @@ This twin has **two** optional TTS ids. They are **not** the same:
|
|
|
167
207
|
|
|
168
208
|
## Create Studio — behavior notes
|
|
169
209
|
|
|
210
|
+
**Nothing here runs before the owner has approved a plan and a price** — see **Proposing, then quoting, before you generate**. The models, durations and resolutions below are the menu you propose *from*, not defaults to spend on unasked.
|
|
211
|
+
|
|
170
212
|
`amiko create <image|video|tts|music|sfx>` is the CLI half of the platform Create Studio. It generates through Amiko's own authenticated endpoints (not raw MPP), runs **async**, and is **charged on success** from the twin's custodial wallet — a failed or timed-out generation is **never billed**, and there is no pre-pay. **The command returns immediately** with a `jobId` and `status: PENDING` — it does NOT block for the whole generation (so you're not held for 60s–9min). It prints how to check + a rough ETA. **Do NOT sit in a tight polling loop** (it burns turns/tokens). After submitting, **tell the user roughly how long to wait and stop** — image ~15–60s, video ~2–9min, music ~30–120s, tts/sfx ~5–20s (e.g. "your video's generating — check back in a few minutes"). Then retrieve it **once** later — when the user next asks, or after the ETA — with `amiko create status <jobId>` (re-query that job, ~24h) or `amiko create media` (list recent generations; `--service`/`--limit`/`--raw`). Result is a permanent Supabase Storage URL. **Every successful generation is also auto-saved to the drive** (folder "Create Studio Files", with the prompt as title/description) — so `amiko drive search "<prompt words>"` finds past creations, and `drive share <docId>` can hand out a link; no manual re-upload. **Do NOT use `--wait`** — there's no such option; `create` is always non-blocking, so submit then check later with `amiko create status <jobId>`. `--token <AMIKO|USDC|USDT|SOL>` selects the charge token (default auto, AMIKO-first). `--pay credits` pays from the owner's **Amiko account credits** instead of the twin wallet (unified-billing accounts only — reserved at submit, captured only on success, released on failure; the server rejects it for legacy accounts, so fall back to the default `--pay wallet` if it errors). Prefer `create` over `markets image` for media generation — it doesn't lose money on timeouts. `markets image` remains the raw MPP pre-pay path. For **music**, a plain prompt is enough — `create music "a triumphant orchestral ballad"` sings from the prompt (lyrics auto-written); add `--lyrics "…"` to set exact words, or `--instrumental` for no vocals. Don't paste long lyrics into the prompt itself. **Track length is `--duration <seconds>`** (1–300, same unit as `sfx --duration` and `video --seconds`) — e.g. a 3.5-minute track is `--duration 210`. On `music-3.0` this is the **price input**: it bills per second, so `--duration 210` costs 210× the per-second rate. Omit it for the 60s default; never put the length in the prompt text instead (the model can't act on it). **Image models** (`--model`): `nano-banana-2` (default), `nano-banana`, `nano-banana-lite`, `nano-banana-pro` (Google Gemini — when the owner says "nano banana", pass it verbatim; `-pro` is the premium/priciest tier at ~$0.17); `gpt-image-2` and `gpt-image-1.5/-1/-1-mini` (OpenAI); `grok-imagine-image-quality` (xAI); `image-01` (MiniMax). Images also take `--reference-image <file|url>` for image-to-image — see "Reference limits" below.
|
|
171
213
|
|
|
172
214
|
### Video — critical agent rules (read before claiming failure)
|