@heyamiko/amiko-cli 0.16.1 → 0.16.3

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 CHANGED
@@ -879,9 +879,9 @@ Generate a video (Create Studio)
879
879
 
880
880
  | Flag | Default | Description |
881
881
  |---|---|---|
882
- | `--model <model>` | | Video model: MiniMax-Hailuo-02 (default for prompt-only; T2V+I2V), MiniMax-Hailuo-2.3-Fast (default with --first-frame; I2V only), MiniMax-Hailuo-2.3 (T2V+I2V), MiniMax-H3 (aliases h3, hailuo-03; T2V+I2V+reference-to-video, 768P\|2K, any 4–15s, billed per second), veo-3.1[-fast\|-lite]-generate-preview (Google; durations clamp to 4/6/8s), grok-imagine-video (xAI), dreamina-seedance-* (BytePlus). ONLY these — kling and other ids are not supported |
882
+ | `--model <model>` | | Video model: MiniMax-Hailuo-02 (default for prompt-only; T2V+I2V), MiniMax-Hailuo-2.3-Fast (default with --first-frame; I2V only), MiniMax-Hailuo-2.3 (T2V+I2V), MiniMax-H3 (aliases h3, hailuo-03; T2V+I2V+reference-to-video, 768P\|2K, any 4–15s, billed per second), veo-3.1[-fast\|-lite]-generate-preview (Google; durations clamp to 4/6/8s), grok-imagine-video (xAI), dreamina-seedance-2-5-260628 (BytePlus Seedance 2.5; any whole 4–30s, billed per token so a long 1080p clip runs into dollars — quote it), other dreamina-seedance-* (BytePlus, ≤15s). ONLY these — kling and other ids are not supported |
883
883
  | `--resolution <res>` | `768P` | 512P, 720P, 768P, 1080P (MiniMax, Grok, Seedance); 720p, 1080p, 4k (Veo); 768P or 2K (MiniMax-H3) |
884
- | `--seconds <n>` | `6` | Clip length: 6 or 10 (Hailuo), 4/6/8 (Veo), 4/6/8/10 (Grok, Seedance), any whole number 4–15 (MiniMax-H3) |
884
+ | `--seconds <n>` | `6` | Clip length: 6 or 10 (Hailuo), 4/6/8 (Veo), 4/6/8/10 (Grok, Seedance 2.0), any whole number 4–15 (MiniMax-H3), any whole number 4–30 (Seedance 2.5) |
885
885
  | `--aspect <ratio>` | | Aspect ratio (provider-dependent). MiniMax-H3 text-to-video needs a concrete ratio (21:9, 16:9, 4:3, 1:1, 3:4, 9:16); defaults to 16:9 when omitted |
886
886
  | `--first-frame <file|url>` | | Image-to-video: first frame — local file path, https URL, or data URI |
887
887
  | `--last-frame <file|url>` | | First-and-last-frame video: ending frame — local file path, https URL, or data URI. MiniMax-H3, Seedance and Veo only (Seedance/Veo also need --first-frame) |
@@ -2617,6 +2617,20 @@ npm publish
2617
2617
 
2618
2618
  ## Changelog
2619
2619
 
2620
+ ### 0.16.3
2621
+
2622
+ - **Seedance 2.5 (`dreamina-seedance-2-5-260628`) is a supported `create video --model`**, and it is the only model that goes past 15s — any whole `--seconds` from **4 to 30**. The 4|6|8|10 set never applied to it, and neither does H3's 4–15 range, so `--seconds 22` is now accepted rather than rejected against a table it was never subject to.
2623
+ - **Over-long durations are an error, not a silent trim.** mpp clamped anything above 15s down to 15s before submitting. On a model that accepts 30s that meant a 30s request generated a 15s clip, billed in full, and said nothing about the substitution — the owner paid for a video that was not the one they asked for. The limit is now per model and exceeding it fails before the job is created.
2624
+ - **2.5 is priced at its own rate ($0.0107/1K tokens).** It was falling through to the 2.0 Pro rate, which under-quoted it by ~31%: the number shown at approval was not the number charged. The unknown-model fallback was also inverted — it used to quote at the *cheapest* published rate, so any future model id would under-quote by default; it now quotes at the dearest known rate and logs that it did.
2625
+ - **`Expensive generation:` warning above $0.50.** Seedance 2.5 bills per token, so cost tracks duration × resolution: roughly **5s 720p ≈ $1.16**, **10s 720p ≈ $2.31**, **30s 1080p ≈ $15.60** — about 156,000 credits, more than most balances hold. `Cost:` alone reads identically at $0.09 and at $15, so anything at or above $0.50 now gets its own stderr line naming the two levers (`--seconds`, `--resolution`) that caused it. Ordinary work — an image, a short Hailuo clip — stays quiet.
2626
+ - **The reference caps stay at 9/3/3.** 2.5 advertises up to 50 multimodal references upstream, but BytePlus has not published how the ≤15s combined-reference budget changes at that ceiling, and a cap that can't be verified locally is one that fails by generating and billing. 2.5's usable win today is duration, not reference count.
2627
+
2628
+ ### 0.16.2
2629
+
2630
+ - **`--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.
2631
+ - **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.
2632
+ - **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.
2633
+
2620
2634
  ### 0.16.1
2621
2635
 
2622
2636
  - **[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}`);
@@ -29307,6 +29311,12 @@ var NON_H3_MAX_PROMPT_CHARS = 2000;
29307
29311
  var H3_MAX_REFERENCE_FILES = 12;
29308
29312
  var H3_DEFAULT_T2V_ASPECT = "16:9";
29309
29313
  var NON_H3_VIDEO_SECONDS = new Set([4, 6, 8, 10]);
29314
+ var SEEDANCE_25_MODEL = /^(dreamina-)?seedance-2-5(-|$)/i;
29315
+ var SEEDANCE_25_MIN_SECONDS = 4;
29316
+ var SEEDANCE_25_MAX_SECONDS = 30;
29317
+ function isSeedance25Model(model) {
29318
+ return SEEDANCE_25_MODEL.test(model);
29319
+ }
29310
29320
  function isH3VideoModel(model) {
29311
29321
  return H3_VIDEO_MODEL.test(model);
29312
29322
  }
@@ -29715,6 +29725,7 @@ function mediaUrls(items) {
29715
29725
  }
29716
29726
 
29717
29727
  // src/commands/create.ts
29728
+ var HIGH_COST_USD = 0.5;
29718
29729
  var MUSIC_MAX_SECONDS = 300;
29719
29730
  var ETA = {
29720
29731
  IMAGE: "~15–60s",
@@ -29799,6 +29810,8 @@ async function submitCreateJob(opts) {
29799
29810
  }
29800
29811
  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
29812
  let quotedCostAmiko;
29813
+ let quotedCostUsd;
29814
+ let quoteFailed = false;
29802
29815
  try {
29803
29816
  const q = await amikoWebFetch(auth, "/api/create/quote", {
29804
29817
  method: "POST",
@@ -29806,6 +29819,7 @@ async function submitCreateJob(opts) {
29806
29819
  timeoutMs: 15000
29807
29820
  });
29808
29821
  if (q.cost_usd != null) {
29822
+ quotedCostUsd = q.cost_usd;
29809
29823
  costLine = payCredits ? `≈ ${Math.ceil(q.cost_usd * 1e4)} Amiko credits (≈ $${q.cost_usd.toFixed(4)}) — reserved on submit, captured only on success` : `${q.cost_amiko ?? "?"} AMIKO (≈ $${q.cost_usd.toFixed(4)}) — charged only on success`;
29810
29824
  }
29811
29825
  if (typeof q.cost_amiko === "string" && q.cost_amiko.trim() !== "") {
@@ -29813,7 +29827,19 @@ async function submitCreateJob(opts) {
29813
29827
  if (Number.isFinite(n))
29814
29828
  quotedCostAmiko = n;
29815
29829
  }
29816
- } catch {}
29830
+ } catch {
29831
+ quoteFailed = true;
29832
+ }
29833
+ if (quoteFailed) {
29834
+ console.error(warn("Price quote failed — the amount below is unknown."));
29835
+ costLine = `unknown (quote failed) — ${costLine}`;
29836
+ }
29837
+ if (quotedCostUsd !== undefined && quotedCostUsd >= HIGH_COST_USD) {
29838
+ console.error("");
29839
+ console.error(warn(`Expensive generation: ≈ $${quotedCostUsd.toFixed(2)} (${Math.ceil(quotedCostUsd * 1e4).toLocaleString()} credits).`));
29840
+ console.error(dim(" Duration and resolution drive this almost linearly — halving either roughly halves the price."));
29841
+ console.error("");
29842
+ }
29817
29843
  const preferredToken = typeof jobBody.preferredToken === "string" ? jobBody.preferredToken.toUpperCase() : undefined;
29818
29844
  const chargeIsAmiko = !payCredits && (preferredToken === undefined || preferredToken === "AMIKO");
29819
29845
  const autoApprovable = payCredits || chargeIsAmiko;
@@ -29946,7 +29972,7 @@ function registerCreateCommand(create2) {
29946
29972
  }
29947
29973
  });
29948
29974
  });
29949
- create2.command("video <prompt>").description("Generate a video (Create Studio)").option("--model <model>", "Video model: MiniMax-Hailuo-02 (default for prompt-only; T2V+I2V), MiniMax-Hailuo-2.3-Fast (default with --first-frame; I2V only), MiniMax-Hailuo-2.3 (T2V+I2V), MiniMax-H3 (aliases h3, hailuo-03; T2V+I2V+reference-to-video, 768P|2K, any 4–15s, billed per second), veo-3.1[-fast|-lite]-generate-preview (Google; durations clamp to 4/6/8s), grok-imagine-video (xAI), dreamina-seedance-* (BytePlus). ONLY these — kling and other ids are not supported").option("--resolution <res>", "512P, 720P, 768P, 1080P (MiniMax, Grok, Seedance); 720p, 1080p, 4k (Veo); 768P or 2K (MiniMax-H3)", "768P").option("--seconds <n>", "Clip length: 6 or 10 (Hailuo), 4/6/8 (Veo), 4/6/8/10 (Grok, Seedance), any whole number 4–15 (MiniMax-H3)", "6").option("--aspect <ratio>", "Aspect ratio (provider-dependent). MiniMax-H3 text-to-video needs a concrete ratio (21:9, 16:9, 4:3, 1:1, 3:4, 9:16); defaults to 16:9 when omitted").option("--first-frame <file|url>", "Image-to-video: first frame — local file path, https URL, or data URI").option("--last-frame <file|url>", "First-and-last-frame video: ending frame — local file path, https URL, or data URI. MiniMax-H3, Seedance and Veo only (Seedance/Veo also need --first-frame)").option("--reference-image <file|url>", "Reference-to-video: local file path or https URL (repeatable). MiniMax-H3 / Seedance / Grok: max 9; Veo: max 3; Hailuo v1: NOT supported — use --subject-reference", collectOption, []).option("--reference-video <file|url>", "Reference-to-video: local file path or https URL (repeatable, max 3). MiniMax-H3 and Seedance only; combined reference video+audio must be ≤15s, and H3 bills 15 input-seconds whenever any is attached", collectOption, []).option("--reference-audio <file|url>", "Reference-to-video: local file path or https URL (repeatable, max 3). MiniMax-H3 and Seedance only; needs an image or video reference alongside, H3 wants 2–15s per clip", collectOption, []).option("--subject-reference <file|url>", "MiniMax S2V / H3: subject/character reference image — local file path or https URL. Takes the place of --reference-image rather than adding to it").option("--generate-audio", "Seedance: generate audio in the output video").option("--no-generate-audio", "Seedance: output silent video").option("--watermark", "Seedance: burn in a watermark").option("--no-watermark", "Seedance: no watermark").option("--camera-fixed", "Seedance: hold the camera still").option("--no-camera-fixed", "Seedance: allow camera movement").option("--prompt-optimizer", "MiniMax (H3 and Hailuo v1): let the model rewrite the prompt before generating").option("--no-prompt-optimizer", "MiniMax: use the prompt verbatim").option("--fast-pretreatment", "MiniMax Hailuo v1: faster input pre-processing (ignored by H3, Veo, Grok and Seedance)").option("--no-fast-pretreatment", "MiniMax Hailuo v1: standard input pre-processing").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--pay <method>", "Payment method: credits (Amiko account credits, default) or wallet (twin wallet)", "credits").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (prompt, opts) => {
29975
+ create2.command("video <prompt>").description("Generate a video (Create Studio)").option("--model <model>", "Video model: MiniMax-Hailuo-02 (default for prompt-only; T2V+I2V), MiniMax-Hailuo-2.3-Fast (default with --first-frame; I2V only), MiniMax-Hailuo-2.3 (T2V+I2V), MiniMax-H3 (aliases h3, hailuo-03; T2V+I2V+reference-to-video, 768P|2K, any 4–15s, billed per second), veo-3.1[-fast|-lite]-generate-preview (Google; durations clamp to 4/6/8s), grok-imagine-video (xAI), dreamina-seedance-2-5-260628 (BytePlus Seedance 2.5; any whole 4–30s, billed per token so a long 1080p clip runs into dollars — quote it), other dreamina-seedance-* (BytePlus, ≤15s). ONLY these — kling and other ids are not supported").option("--resolution <res>", "512P, 720P, 768P, 1080P (MiniMax, Grok, Seedance); 720p, 1080p, 4k (Veo); 768P or 2K (MiniMax-H3)", "768P").option("--seconds <n>", "Clip length: 6 or 10 (Hailuo), 4/6/8 (Veo), 4/6/8/10 (Grok, Seedance 2.0), any whole number 4–15 (MiniMax-H3), any whole number 4–30 (Seedance 2.5)", "6").option("--aspect <ratio>", "Aspect ratio (provider-dependent). MiniMax-H3 text-to-video needs a concrete ratio (21:9, 16:9, 4:3, 1:1, 3:4, 9:16); defaults to 16:9 when omitted").option("--first-frame <file|url>", "Image-to-video: first frame — local file path, https URL, or data URI").option("--last-frame <file|url>", "First-and-last-frame video: ending frame — local file path, https URL, or data URI. MiniMax-H3, Seedance and Veo only (Seedance/Veo also need --first-frame)").option("--reference-image <file|url>", "Reference-to-video: local file path or https URL (repeatable). MiniMax-H3 / Seedance / Grok: max 9; Veo: max 3; Hailuo v1: NOT supported — use --subject-reference", collectOption, []).option("--reference-video <file|url>", "Reference-to-video: local file path or https URL (repeatable, max 3). MiniMax-H3 and Seedance only; combined reference video+audio must be ≤15s, and H3 bills 15 input-seconds whenever any is attached", collectOption, []).option("--reference-audio <file|url>", "Reference-to-video: local file path or https URL (repeatable, max 3). MiniMax-H3 and Seedance only; needs an image or video reference alongside, H3 wants 2–15s per clip", collectOption, []).option("--subject-reference <file|url>", "MiniMax S2V / H3: subject/character reference image — local file path or https URL. Takes the place of --reference-image rather than adding to it").option("--generate-audio", "Seedance: generate audio in the output video").option("--no-generate-audio", "Seedance: output silent video").option("--watermark", "Seedance: burn in a watermark").option("--no-watermark", "Seedance: no watermark").option("--camera-fixed", "Seedance: hold the camera still").option("--no-camera-fixed", "Seedance: allow camera movement").option("--prompt-optimizer", "MiniMax (H3 and Hailuo v1): let the model rewrite the prompt before generating").option("--no-prompt-optimizer", "MiniMax: use the prompt verbatim").option("--fast-pretreatment", "MiniMax Hailuo v1: faster input pre-processing (ignored by H3, Veo, Grok and Seedance)").option("--no-fast-pretreatment", "MiniMax Hailuo v1: standard input pre-processing").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--pay <method>", "Payment method: credits (Amiko account credits, default) or wallet (twin wallet)", "credits").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (prompt, opts) => {
29950
29976
  const model = opts.model ?? (opts.firstFrame ? "MiniMax-Hailuo-2.3-Fast" : "MiniMax-Hailuo-02");
29951
29977
  const isH3 = isH3VideoModel(model);
29952
29978
  const seconds = Number(opts.seconds);
@@ -29954,8 +29980,12 @@ function registerCreateCommand(create2) {
29954
29980
  if (!Number.isInteger(seconds) || seconds < H3_MIN_SECONDS || seconds > H3_MAX_SECONDS) {
29955
29981
  failInput(`--seconds must be a whole number from ${H3_MIN_SECONDS} to ${H3_MAX_SECONDS} for MiniMax-H3.`);
29956
29982
  }
29983
+ } else if (isSeedance25Model(model)) {
29984
+ if (!Number.isInteger(seconds) || seconds < SEEDANCE_25_MIN_SECONDS || seconds > SEEDANCE_25_MAX_SECONDS) {
29985
+ failInput(`--seconds must be a whole number from ${SEEDANCE_25_MIN_SECONDS} to ${SEEDANCE_25_MAX_SECONDS} for Seedance 2.5.`);
29986
+ }
29957
29987
  } else if (!NON_H3_VIDEO_SECONDS.has(seconds)) {
29958
- failInput("--seconds must be 4, 6, 8, or 10 (Hailuo accepts 6 or 10; use --model MiniMax-H3 for any 4–15s).");
29988
+ failInput("--seconds must be 4, 6, 8, or 10 (Hailuo accepts 6 or 10; use --model MiniMax-H3 for any 4–15s, or --model dreamina-seedance-2-5-260628 for any 4–30s).");
29959
29989
  }
29960
29990
  let resolution = opts.resolution;
29961
29991
  if (isH3) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.16.1",
3
+ "version": "0.16.3",
4
4
  "description": "Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace agents",
5
5
  "type": "module",
6
6
  "bin": {
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" | shell → `amiko create image "a whale in space" --yes` (quote cost first) |
26
- | "animate my cover art / album visual" | shell → `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" | shell → `amiko create music "lo-fi chill beat" --yes` (quote cost first) |
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
- ### Quoting cost before running
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,13 +207,17 @@ 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)
173
215
 
174
216
  - **HTTP 202 / `status: PENDING` / `PROCESSING` = success so far, NOT failure.** MPP logs like `POST /internal/create/video 202` mean the async job was **accepted and queued**. A single immediate `GET /internal/create/jobs/… 200` only means the job record exists — video still needs **~2–9 minutes**. **Never** tell the owner the render "failed" or "stalled" just because you saw 202 or polled once while still `PROCESSING`.
175
217
  - **Only call it failed when** `amiko create status <jobId>` returns `FAILED` (or the CLI exits non-zero with an error), **or** after the ETA you check again and it's still not `COMPLETED` **and** mpp logs show `[internal-create/video]` with an error.
176
- - **Do NOT invent video models.** `kling-v1.6`, `kling-*`, and other non-platform ids are **not supported** and will error. Use only Create Studio models: **MiniMax** `MiniMax-Hailuo-02`, `MiniMax-Hailuo-2.3`, `MiniMax-Hailuo-2.3-Fast`, `MiniMax-H3` (aliases `h3`, `hailuo-03` — v2 API: T2V + I2V + reference-to-video, `768P`|`2K`, any whole `--seconds` 4–15, **billed per second** so longer clips cost more; text-to-video needs a concrete `--aspect`, defaulting to `16:9`); **Google Veo** `veo-3.1-generate-preview`, `veo-3.1-fast-generate-preview`, `veo-3.1-lite-generate-preview` (durations clamp to 4/6/8s; lite is prompt-only/T2V, no first frame); **xAI** `grok-imagine-video`; **BytePlus Seedance** `dreamina-seedance-*` / `seedance-*`. Run `amiko create video --help` — do **not** bypass with `markets service call` to `/internal/create/video`.
218
+ - **Do NOT invent video models.** `kling-v1.6`, `kling-*`, and other non-platform ids are **not supported** and will error. Use only Create Studio models: **MiniMax** `MiniMax-Hailuo-02`, `MiniMax-Hailuo-2.3`, `MiniMax-Hailuo-2.3-Fast`, `MiniMax-H3` (aliases `h3`, `hailuo-03` — v2 API: T2V + I2V + reference-to-video, `768P`|`2K`, any whole `--seconds` 4–15, **billed per second** so longer clips cost more; text-to-video needs a concrete `--aspect`, defaulting to `16:9`); **Google Veo** `veo-3.1-generate-preview`, `veo-3.1-fast-generate-preview`, `veo-3.1-lite-generate-preview` (durations clamp to 4/6/8s; lite is prompt-only/T2V, no first frame); **xAI** `grok-imagine-video`; **BytePlus Seedance** `dreamina-seedance-2-5-260628` (2.5 — any whole `--seconds` **4–30**, the only model that goes past 15s) and the 2.0 family `dreamina-seedance-2-0-260128` / `-2-0-fast-260128` (≤15s). Run `amiko create video --help` — do **not** bypass with `markets service call` to `/internal/create/video`.
219
+
220
+ - **Seedance 2.5 is the expensive one — never submit it without quoting.** It bills per token, so cost scales with duration × resolution and runs roughly: **5s 720p ≈ $1.16**, **10s 720p ≈ $2.31**, **30s 1080p ≈ $15.60**. That last one is ~156,000 credits — more than most owners hold. Treat every 2.5 job as a job that needs the full propose → quote → generate flow, and say the dollar figure out loud, not just the credit count: "≈ $15.60" lands where "156,000 credits" does not. The CLI prints its own `Expensive generation:` warning above $0.50, which is every 2.5 clip — pass that warning on to the owner rather than swallowing it. If they want something cheaper, the levers are `--seconds` and `--resolution`, roughly linear in both.
177
221
  - **Cover art → motion (I2V):** pass the cover's Amiko URL as `--first-frame <url>` (from `amiko create status` on the image job or `amiko create media`). The default model is now **input-aware**: prompt-only video defaults to `MiniMax-Hailuo-02` (T2V), and `--first-frame` runs default to `MiniMax-Hailuo-2.3-Fast` (I2V) — so omitting `--model` is safe in both shapes. Explicit `--model` always wins; Fast alone still rejects prompt-only (it needs a reference image).
178
222
  - **Before giving up on video**, you must have: (1) submitted with `amiko create video … --yes`, (2) waited through the ETA, (3) run `amiko create status <jobId>` **or** `amiko create media --service video`. If `COMPLETED` + `assetUrl`, report success with the URL. If still `PROCESSING`, say it's still rendering — don't claim the pipeline is broken.
179
223
 
@@ -201,6 +245,8 @@ This twin has **two** optional TTS ids. They are **not** the same:
201
245
  | **Grok** | 9 | — | — | `--first-frame` only | |
202
246
  | **Hailuo v1** (02 / 2.3 / 2.3-Fast) | — | — | — | `--first-frame` only | `--reference-image` is silently dropped — use `--subject-reference`, which Hailuo does read |
203
247
 
248
+ Seedance 2.5 advertises up to **50** multimodal references upstream, but the CLI, the studio and mpp all still cap it at 9/3/3 with the ≤15s reference budget — BytePlus has not published what the longer-reference rules become at that ceiling, and a cap we can't verify is one that fails by generating and billing. Don't promise the owner 50; 2.5's usable win today is **duration** (30s vs 15s), not reference count.
249
+
204
250
  `--subject-reference` **replaces** a reference-image slot rather than adding one (except on Hailuo v1, where it's a separate field). The ≤15s combined budget and H3's 2–15s per-clip audio window are checked from the **local file's bytes** — so they're verified for `.wav` / `.mp4` / `.mov` paths and skipped (allowed through) for https URLs and `.mp3`, where the server has the last word.
205
251
 
206
252
  **Provider toggles** (each has a `--no-…` form): `--generate-audio`, `--watermark`, `--camera-fixed` (Seedance); `--prompt-optimizer` (MiniMax H3 + Hailuo v1); `--fast-pretreatment` (Hailuo v1). Passing one to a model that ignores it is harmless — the server drops it.