@heyamiko/amiko-cli 0.14.0-beta.25 → 0.14.0-beta.26

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
@@ -128,6 +128,7 @@ amiko create image "logo" --aspect 16:9 --model gpt-image-2 # widescreen, Op
128
128
  amiko create image "a sunset" --pay credits --yes # pay with Amiko account credits (unified accounts)
129
129
  amiko create video "a whale in space" --resolution 768P --seconds 6
130
130
  amiko create video "animate cover" --first-frame https://.../cover.png --yes
131
+ amiko create video "a slow pan over dunes at dusk" --model MiniMax-H3 --seconds 12 --resolution 2K --aspect 21:9 --yes
131
132
  amiko create video "dance clip" --model dreamina-seedance-2-0-fast-260128 \
132
133
  --reference-image https://.../ref1.png --reference-audio https://.../beat.mp3 --generate-audio --yes
133
134
  amiko create tts "Hello world" --voice 21m00Tcm4TlvDq8ikWAM
@@ -135,7 +136,7 @@ amiko create tts "Hello world" --provider minimax --model speech-2.8-turbo
135
136
  amiko create tts "Hello" --provider minimax --voice English_expressive_narrator --yes
136
137
  amiko voice clone ./me.mp3 --provider minimax
137
138
  amiko voice clone ./me.mp3 --provider elevenlabs
138
- amiko create music "lo-fi chill beat" --duration 30000
139
+ amiko create music "lo-fi chill beat" --duration 30 # seconds
139
140
  amiko create music --lyrics "..." --instrumental # instrumental
140
141
  amiko create sfx "thunder and heavy rain" --duration 5
141
142
  amiko create image "banner" --raw # raw JSON
@@ -163,21 +164,23 @@ Modes: `image`, `video`, `tts`, `music`, `sfx` (mirrors the platform Create Stud
163
164
 
164
165
  | Flag | Default | Description |
165
166
  |------|---------|-------------|
166
- | `--model <model>` | smart | Video model (`MiniMax-Hailuo-*`, `dreamina-seedance-2-0-fast-260128`, …). Default: `MiniMax-Hailuo-02` for prompt-only (T2V), `MiniMax-Hailuo-2.3-Fast` when `--first-frame` is given (I2V) |
167
- | `--resolution <res>` | `768P` | `512P`, `720P`, `768P`, `1080P` |
168
- | `--seconds <n>` | `6` | Clip length: `6` or `10` |
169
- | `--aspect <ratio>` | — | Aspect ratio (provider-dependent) |
167
+ | `--model <model>` | smart | Video model (`MiniMax-Hailuo-*`, `MiniMax-H3`, `dreamina-seedance-2-0-fast-260128`, …). Default: `MiniMax-Hailuo-02` for prompt-only (T2V), `MiniMax-Hailuo-2.3-Fast` when `--first-frame` is given (I2V) |
168
+ | `--resolution <res>` | `768P` | `512P`, `720P`, `768P`, `1080P`; `MiniMax-H3` only `768P` or `2K` |
169
+ | `--seconds <n>` | `6` | Clip length: `6`/`10` (Hailuo), `4`/`6`/`8` (Veo), `4`/`6`/`8`/`10` (Grok, Seedance), any whole number `4`–`15` (`MiniMax-H3`) |
170
+ | `--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`) and defaults to `16:9` when omitted |
170
171
  | `--first-frame <url>` | — | Image-to-video: first frame URL or data URI |
171
172
  | `--last-frame <url>` | — | First-and-last-frame video: ending frame URL or data URI |
172
- | `--reference-image <url>` | — | Seedance multimodal reference image (repeatable, max 9) |
173
- | `--reference-video <url>` | — | Seedance multimodal reference video (repeatable, max 3) |
174
- | `--reference-audio <url>` | — | Seedance multimodal reference audio (repeatable, max 3) |
175
- | `--subject-reference <url>` | — | MiniMax S2V subject/character reference image |
173
+ | `--reference-image <url>` | — | Seedance / `MiniMax-H3` reference image (repeatable, max 9; H3 surcharges images past the 5th) |
174
+ | `--reference-video <url>` | — | Seedance / `MiniMax-H3` reference video (repeatable, max 3; H3 bills the input seconds too) |
175
+ | `--reference-audio <url>` | — | Seedance / `MiniMax-H3` reference audio (repeatable, max 3; H3 needs an image or video alongside) |
176
+ | `--subject-reference <url>` | — | MiniMax S2V / H3 subject/character reference image |
176
177
  | `--generate-audio` | — | Seedance: generate audio in the output |
177
178
  | `--no-generate-audio` | — | Seedance: output silent video |
178
179
 
179
180
  Reference flags accept URLs or data URIs (not local paths). Typical I2V flow: `create image` → `create status <jobId>` for the image URL → `create video --first-frame <url>`.
180
181
 
182
+ **MiniMax-H3** (aliases `h3`, `hailuo-03`) is MiniMax's v2 video API and follows its own rules: a prompt is required in every mode (≤7000 chars), clips run any whole number of seconds from 4 to 15, only `768P` and `2K` exist, and it is billed **per second** (plus reference-video input seconds and a per-image surcharge past 5 reference images), so the quote scales with `--seconds`. It does text-to-video, first/last-frame image-to-video, and reference-to-video (`--reference-image`/`--reference-video`/`--reference-audio`), but a frame and a reference cannot be combined in one job. The CLI checks all of that before the quote and approval prompt, so a bad combination never costs a confirmation round-trip.
183
+
181
184
  **`amiko create tts <text>`**
182
185
 
183
186
  | Flag | Default | Description |
@@ -203,7 +206,7 @@ Examples: `amiko create tts "Hi" --provider minimax --yes` · `amiko create tts
203
206
  |------|---------|-------------|
204
207
  | `--model <model>` | `music-2.6` | `music_v1`, `music-2.6`, `music-cover` |
205
208
  | `--lyrics <lyrics>` | — | Lyrics (optional) |
206
- | `--duration <ms>` | — | Length in milliseconds |
209
+ | `--duration <seconds>` | — | Track length in seconds, 1–300. `music-3.0` bills per second, so this sets the price |
207
210
  | `--instrumental` | — | Instrumental (no vocals) |
208
211
 
209
212
  **`amiko create sfx <text>`**
@@ -576,7 +579,7 @@ amiko voice reset --yes
576
579
  amiko avatar update --file ./portrait.png --yes
577
580
 
578
581
  # Friends
579
- amiko friends list # list
582
+ amiko friends list # ENTIRE friend list + exact total, in one call
580
583
  amiko friends requests # pending requests (incoming + outgoing)
581
584
  amiko friends add --id <userId>
582
585
  amiko friends accept <friendshipId>
@@ -589,7 +592,8 @@ amiko friends reports list # friend matching reports
589
592
  amiko friends reports view <reportId>
590
593
 
591
594
  # Users
592
- amiko users search <query> # find users by name/handle
595
+ amiko users search <query> # find users by name/handle (one page, --limit default 10)
596
+ amiko users search <query> --all # every match, for "how many people match X"
593
597
  amiko users profile <handle> # public profile
594
598
  amiko users follow <handleOrId> # follow (one-way, no approval); unfollow to undo
595
599
  amiko users follow-status <handleOrId> # do I follow them / do they follow me
@@ -606,8 +610,10 @@ amiko post create --title "Kyoto, 6am" --media ./shot.webp # image-only note —
606
610
  amiko post create --title "Q3 report" --doc ./q3.pdf # document note — rendered as a file card
607
611
  amiko post create --content "private note" --visibility private
608
612
  amiko post create --content "look" --media https://...jpg
613
+ amiko post create --title "the track" --media drive:<docId> # media already in the Drive (id from `amiko drive list`) — works for audio/video too
609
614
  amiko post create --content "wip idea" --draft # save a draft — no share URL until published
610
615
  amiko post drafts # list draft posts (--limit/--offset/--json)
616
+ amiko post likers <postId> # who liked one of YOUR posts (403 on someone else's)
611
617
  amiko post publish <postId> # publish a draft (fresh timestamp, prints the share URL)
612
618
  amiko post comment --id <postId> --comment "great post"
613
619
  amiko post comment --id <postId> --comment "nice!" --media https://...jpg
@@ -633,6 +639,28 @@ npm publish
633
639
 
634
640
  ## Changelog
635
641
 
642
+ ### 0.14.0-beta.26 (`beta` dist-tag — `npm i -g @heyamiko/amiko-cli@beta`)
643
+
644
+ - **`amiko create video --model MiniMax-H3`** (aliases `h3`, `hailuo-03`): MiniMax's v2 video model, already live in mpp-service and amiko-web, is now reachable from the CLI. H3 breaks every local rule the video command enforced for Hailuo, so it gets its own pre-flight: `--seconds` accepts any whole number 4–15 (was hard-coded `6|10`), `--resolution` must be `768P` or `2K` (case-insensitive, canonicalized on the wire), and text-to-video needs a concrete `--aspect` — the CLI defaults it to `16:9` and prints a dim note, because the server only rejects the missing ratio *after* the owner has approved the spend. Frame/reference runs are left alone (H3 infers the ratio from the input). All checks run before the quote so an invalid job never costs an approval round-trip.
645
+ - **`--seconds` for non-H3 models widened from `6|10` to `4|6|8|10`**, matching amiko-web's own gate. The old check rejected `8`, which Veo and Seedance accept, and `4`, which Veo/Grok/Seedance accept; mpp still enforces the per-provider subset (Hailuo remains `6|10`). The error now points at `--model MiniMax-H3` for anything else.
646
+ - Reference flags (`--reference-image/video/audio`, `--subject-reference`) document that they drive H3 reference-to-video too.
647
+
648
+ ### 0.14.2
649
+
650
+ - **`--media drive:<docId>`** (new source for `post create` and `post comment`): attach a media file already in the twin's Drive — an upload, or a Create Studio generation, which `saveCreationToDrive` mirrors into the "Create Studio Files" folder. The id comes from `amiko drive list --json`. This closes the gap where the only way to post an *audio or video* file the twin already owned was to have kept the original `amiko create` URL: `--media` takes local paths for images only, and a Drive signed URL expires.
651
+ - **No amiko-web change was needed, and this is why.** A Drive doc's `file_url` is stored in *public* form (`…/storage/v1/object/public/docs/<path>`) by all three write paths (`uploadDocumentToSupabase`, `createDocSignedUpload`, `saveCreationToDrive`) even though the `docs` bucket is private. `/api/posts` accepts it (`isAllowedPostMediaUrl` checks host + `/storage/v1/object/` only), then `ensurePostMediaUrl` sees a non-`post-media` bucket and does a **service-role server-side copy into `post-media`**, returning a durable URL — so the post never links the private object and never expires. If that copy fails, the fallback reachability probe on a private-bucket URL 4xxs and the route rejects the post rather than storing a dead link. This mirrors what amiko-web's own `DriveMediaPicker` already does (it forwards the same `file_url` under the same MIME allowlist), so the CLI is matching shipped behaviour, not inventing a path.
652
+ - **The drive ref honours the command's `--twin`.** Docs are scoped by `twin_id`; `resolveMediaUrls` now takes the caller's `--twin` instead of re-resolving the default twin, so `post comment --twin <other> --media drive:<id>` no longer 404s on an id `drive list --twin <other>` had just printed.
653
+ - **Two guards on the resolved row.** A `file_url` that isn't Amiko public storage is refused locally — only `source`-tagged Doc rows are pinned to the twin's storage namespace server-side, so an ordinary row can hold any URL, and letting it through produced a `/api/posts` 400 naming neither the ref nor the doc. And the image/audio/video MIME check falls back to the **filename extension** when `file_type` is `application/octet-stream`: Create Studio stores `assetMime || "application/octet-stream"` and the job's `mime_type` is nullable, so a real mp3 can arrive typeless — refusing it with "attach it with `--doc`" would be wrong advice about an attachable file.
654
+ - **SKILL.md**: `--media` now documents its three sources (local image path / Amiko-hosted URL / `drive:<docId>`), says a Drive **signed URL** and a `/d/<slug>` share link are both rejected, and notes that a `drive:` ref pointing at a pdf belongs on `--doc`. New Examples row for "post the audio/image from my Drive".
655
+
656
+ ### 0.14.1
657
+
658
+ - **`amiko post likers <postId>`** (new): lists everyone who liked a post, paging `GET /api/posts/[id]/likes` to completeness so "who / which friends liked this" is answered from the whole set. Cross-reference the printed user ids against `amiko friends list` for the "which *friends*" variant. The route is **owner-only** (`post.user_id !== user.id` → 403), so the command says so in `--help` and turns the server's generic 403 into a message naming the rule — an agent shouldn't read it as a broken login and retry.
659
+ - **`amiko users search --all`** (new flag). Search stays a one-page lookup by default and `--limit` works again; `--all` is what pages through every match, for "how many people match X". Full paging is capped at 200 (10 requests at the server's 20-row page limit) rather than the shared 2000, because search is ranked recall — nobody needs the 2000th match, and a broad query shouldn't cost a hundred round trips.
660
+ - **`amiko friends list` reports the server's exact total.** `/api/friends` without `limit` already returns the whole list *and* an authoritative `pagination.total` in one request; the header count now comes from `total` instead of the row count. An earlier attempt to paginate this command was reverted — it added ~19 requests, capped the set at 2000, and replaced an exact server-side number with an approximation.
661
+ - **New `src/lib/paginate.ts`**: `fetchAllCursor` follows `hasMore`/`nextCursor` to completeness behind a safety cap, returning `{ items, partial }`. Exhaustion is checked *before* the cap so a set that ends exactly on the cap reports complete — flagging it `partial` would be the same lie about a count, inverted. When the cap really is hit, callers print `⚠ Partial results` and JSON carries `"partial": true` with an `N+` count.
662
+ - **SKILL.md**: new top-level **"Counts & full lists — never answer from the first page"** section (promoted out of Friends, since two of its three commands aren't friends commands) with a question → command → where-the-number-comes-from table; `post likers`'s owner-only rule; the `users search` row in the "Who should I meet?" table now notes one-page-by-default vs `--all`; Examples table gains "谁给我点赞了" and "我有多少好友".
663
+
636
664
  ### 0.14.0-beta.25
637
665
 
638
666
  - **Notes parity: `amiko post create --title` and `--doc`.** amiko-web's Notes composer (the 小红书-style card grid — same `Post` rows, new name) writes fields the CLI had no way to set. `--title <text>` sets the card heading (max 150 chars, counted in **grapheme clusters** to match the server's `Intl.Segmenter`, validated before any request; omitted from the body when unset so older amiko-web deploys still accept the payload). `--doc <pathOrUrl...>` attaches non-media documents that render as downloadable file cards: local paths upload to the public `docs` bucket via `POST /api/upload/post-doc` (≤4 MB) or presigned `POST /api/upload/post-doc/sign` + direct PUT (>4 MB, 50 MB cap — the multipart route dies at the ~4.5 MB serverless body limit), https URLs pass through, and media MIME types are refused with a pointer to `--media`. Max 8 documents — the server silently truncates past that, so the CLI errors instead. `--content` is no longer a `requiredOption`: with `--media` or `--doc` attached the body may be empty (an image-only note is normal), but a post with nothing in it — including `--title` alone — is still rejected client-side, mirroring the server's rule. `feed` and `post drafts` now render titles and a document count.