# MiniMax AI integration — image generation, text-to-speech, and usage. # Set MINIMAX_API_KEY in secrets.nuon (unified sk-cp- token covers all models). export def usage [] { let token = $env | get --optional MINIMAX_API_KEY if ($token | is-empty) { error make { msg: "Token for MiniMax missing in environment" label: { text: "Set MINIMAX_API_KEY in your secrets.nuon file" } } } let headers = { Authorization: $'Bearer ($token)' Content-Type: 'application/json' User-Agent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' } let response = http get --headers $headers 'https://www.minimax.io/v1/api/openplatform/coding_plan/remains' let base = $response.base_resp if ($base.status_code != 0) { error make { msg: $base.status_msg label: { text: $"MiniMax API error — check MINIMAX_API_KEY" } } } $response.model_remains | each { |row| let interval_pct = if $row.current_interval_total_count > 0 { $row.current_interval_usage_count * 100 // $row.current_interval_total_count } else { 0 } let weekly_pct = if $row.current_weekly_total_count > 0 { $row.current_weekly_usage_count * 100 // $row.current_weekly_total_count } else { 0 } let remains_h = $row.remains_time // 3600000 let remains_m = ($row.remains_time mod 3600000) // 60000 { model: $row.model_name interval: $"($row.current_interval_usage_count) / ($row.current_interval_total_count) (($interval_pct)%)" weekly: $"($row.current_weekly_usage_count) / ($row.current_weekly_total_count) (($weekly_pct)%)" resets_in: $"($remains_h)h ($remains_m)m" } } } # `minimax` — MiniMax AI: image generation, text-to-speech, voice list, and usage. # # # Subcommands # `minimax usage` — check token quota and usage # `minimax image` — generate images with image-01 model # `minimax speech` — synthesize speech with speech-2.8-hd model # `minimax voices` — list all 332 available system voices export def main [] { print "MiniMax AI integration" print " minimax usage — check token quota and usage" print " minimax image — generate images (image-01 model)" print " minimax speech — synthesize speech (speech-2.8-hd model)" print " minimax voices — list all 332 system voices" print "" print "Run a subcommand with --help for details." } # ── Private helpers ───────────────────────────────────────────────────────────── def get-token [] { let token = $env | get --optional MINIMAX_API_KEY if ($token | is-empty) { error make { msg: "MINIMAX_API_KEY is not set" label: { text: "Set MINIMAX_API_KEY in secrets.nuon" } } } $token } def check-base-resp [resp: record] { let code = $resp.base_resp.status_code if $code == 0 { return } let msg = $resp.base_resp.status_msg let human = { "1002": "Rate limit exceeded — pause before retrying" "1004": "Authentication failed — check MINIMAX_API_KEY" "1008": "Quota exhausted — check your plan limits" "1026": "Content blocked by policy — revise prompt" "2013": "Invalid parameters — check API call" "2049": "Bad API key — verify token in secrets.nuon" "2061": "Model not in plan — Plus-Highspeed includes image-01 and speech-2.8-hd" } | get --optional ($code | into string) | default $"MiniMax API error ($code): ($msg)" error make { msg: $human } } def prompt-view [path: string] { if (which wezterm | is-empty) { print $'(ansi y) wezterm not found — install it to display images inline(ansi rst)' return } print $" Display image? y/N: ($path)" let answer = input if $answer == "y" or $answer == "Y" { print $'(ansi d) Running wezterm imgcat ($path)(ansi rst)' wezterm imgcat $path } } def prompt-play [path: string] { let player = if ((which mpv | is-empty) == false) { "mpv" } else if ((which paplay | is-empty) == false) { "paplay" } else if ((which aplay | is-empty) == false) { "aplay" } else { null } if ($player | is-empty) { print $'(ansi y) No audio player found (tried mpv, paplay, aplay) — skipping playback(ansi rst)' return } print $" Play audio? y/N: ($path)" let answer = input if $answer == "y" or $answer == "Y" { print $'(ansi d) Playing with ($player) ($path)(ansi rst)' match $player { "mpv" => { mpv --no-video --quiet $path } "paplay" => { paplay $path } "aplay" => { aplay $path } } } } # ── Completions ───────────────────────────────────────────────────────────────── def parse-voice-gender [voice_name: string] { let female_markers = ["girl", "lady", "woman", "queen", "sister", "mother", "wife", "aunt", "narrator", "host", "hostess", "antie", "belle", "maiden"] let male_markers = ["man", "boy", "father", "husband", "king", "brother", "uncle", "bloke", "guy", "dude", "fellow", "lad", "gentleman"] if ($female_markers | any { |m| $voice_name | str contains --ignore-case $m }) { "Female" } else if ($male_markers | any { |m| $voice_name | str contains --ignore-case $m }) { "Male" } else { "Neutral" } } def voice-id-completions [] { [ { value: "English_Graceful_Lady", description: "Female · English · Graceful Lady" } { value: "English_expressive_narrator", description: "Female · English · Expressive Narrator" } { value: "English_CalmWoman", description: "Female · English · Calm Woman" } { value: "English_Upbeat_Woman", description: "Female · English · Upbeat Woman" } { value: "English_Trustworth_Man", description: "Male · English · Trustworthy Man" } { value: "English_Compelling_lady1", description: "Female · English · Compelling Lady" } { value: "English_captivating_female1", description: "Female · English · Captivating Female" } { value: "English_Aussie_Bloke", description: "Male · English · Aussie Bloke" } { value: "English_ConfidentWoman", description: "Female · English · Confident Woman" } { value: "English_SereneWoman", description: "Female · English · Serene Woman" } { value: "English_Soft-spokenGirl", description: "Female · English · Soft-spoken Girl" } { value: "English_PlayfulGirl", description: "Female · English · Playful Girl" } { value: "English_SentimentalLady", description: "Female · English · Sentimental Lady" } { value: "English_Wiselady", description: "Female · English · Wise Lady" } { value: "English_Kind-heartedGirl", description: "Female · English · Kind-hearted Girl" } { value: "English_LovelyGirl", description: "Female · English · Lovely Girl" } { value: "English_WhimsicalGirl", description: "Female · English · Whimsical Girl" } { value: "English_UpsetGirl", description: "Female · English · Upset Girl" } { value: "English_StressedLady", description: "Female · English · Stressed Lady" } { value: "English_AssertiveQueen", description: "Female · English · Assertive Queen" } { value: "English_magnetic_voiced_man", description: "Male · English · Magnetic-voiced Male" } { value: "English_Gentle-voiced_man", description: "Male · English · Gentle-voiced Man" } { value: "English_Diligent_Man", description: "Male · English · Diligent Man" } { value: "English_ManWithDeepVoice", description: "Male · English · Man With Deep Voice" } { value: "English_Deep-VoicedGentleman", description: "Male · English · Deep-voiced Gentleman" } { value: "English_ReservedYoungMan", description: "Male · English · Reserved Young Man" } { value: "English_DecentYoungMan", description: "Male · English · Decent Young Man" } { value: "English_PatientMan", description: "Male · English · Patient Man" } { value: "English_Jovialman", description: "Male · English · Jovial Man" } { value: "English_Strong-WilledBoy", description: "Male · English · Strong-willed Boy" } { value: "English_CaptivatingStoryteller", description: "Neutral · English · Captivating Storyteller" } { value: "English_WiseScholar", description: "Neutral · English · Wise Scholar" } { value: "English_PassionateWarrior", description: "Neutral · English · Passionate Warrior" } { value: "English_MaturePartner", description: "Neutral · English · Mature Partner" } { value: "English_FriendlyPerson", description: "Neutral · English · Friendly Guy" } { value: "English_MatureBoss", description: "Neutral · English · Bossy Lady" } { value: "English_Debator", description: "Neutral · English · Male Debater" } { value: "English_Steadymentor", description: "Neutral · English · Reliable Man" } { value: "English_ImposingManner", description: "Neutral · English · Imposing Queen" } { value: "English_SadTeen", description: "Neutral · English · Teen Boy" } { value: "English_Comedian", description: "Neutral · English · Comedian" } { value: "English_BossyLeader", description: "Neutral · English · Bossy Leader" } { value: "English_AnimeCharacter", description: "Female · English · Female Narrator" } { value: "English_radiant_girl", description: "Female · English · Radiant Girl" } { value: "Chinese (Mandarin)_News_Anchor", description: "Neutral · Chinese (Mandarin) · News Anchor" } { value: "Chinese (Mandarin)_Reliable_Executive", description: "Neutral · Chinese (Mandarin) · Reliable Executive" } { value: "Chinese (Mandarin)_Gentleman", description: "Male · Chinese (Mandarin) · Gentleman" } { value: "Chinese (Mandarin)_Sweet_Lady", description: "Female · Chinese (Mandarin) · Sweet Lady" } { value: "Chinese (Mandarin)_Mature_Woman", description: "Female · Chinese (Mandarin) · Mature Woman" } { value: "Chinese (Mandarin)_Kind-hearted_Antie", description: "Female · Chinese (Mandarin) · Kind-hearted Antie" } { value: "Chinese (Mandarin)_Warm-HeartedAunt", description: "Female · Chinese (Mandarin) · Warm-hearted Aunt" } { value: "Chinese (Mandarin)_Warm_Bestie", description: "Female · Chinese (Mandarin) · Warm Bestie" } { value: "Chinese (Mandarin)_Warm_Girl", description: "Female · Chinese (Mandarin) · Warm Girl" } { value: "Chinese (Mandarin)_Wise_Women", description: "Female · Chinese (Mandarin) · Wise Women" } { value: "Chinese (Mandarin)_Soft_Girl", description: "Female · Chinese (Mandarin) · Soft Girl" } { value: "Chinese (Mandarin)_Crisp_Girl", description: "Female · Chinese (Mandarin) · Crisp Girl" } { value: "Chinese (Mandarin)_BashfulGirl", description: "Female · Chinese (Mandarin) · Bashful Girl" } { value: "Chinese (Mandarin)_IntellectualGirl", description: "Female · Chinese (Mandarin) · Intellectual Girl" } { value: "Chinese (Mandarin)_Warm_HeartedGirl", description: "Female · Chinese (Mandarin) · Warm-hearted Girl" } { value: "Chinese (Mandarin)_Laid_BackGirl", description: "Female · Chinese (Mandarin) · Laid-back Girl" } { value: "Chinese (Mandarin)_ExplorativeGirl", description: "Female · Chinese (Mandarin) · Explorative Girl" } { value: "Chinese (Mandarin)_Arrogant_Miss", description: "Female · Chinese (Mandarin) · Arrogant Miss" } { value: "Chinese (Mandarin)_Unrestrained_Young_Man", description: "Male · Chinese (Mandarin) · Unrestrained Young Man" } { value: "Chinese (Mandarin)_Southern_Young_Man", description: "Male · Chinese (Mandarin) · Southern Young Man" } { value: "Chinese (Mandarin)_Male_Announcer", description: "Male · Chinese (Mandarin) · Male Announcer" } { value: "Chinese (Mandarin)_Straightforward_Boy", description: "Male · Chinese (Mandarin) · Straightforward Boy" } { value: "Chinese (Mandarin)_Pure-hearted_Boy", description: "Male · Chinese (Mandarin) · Pure-hearted Boy" } { value: "Chinese (Mandarin)_HK_Flight_Attendant", description: "Neutral · Chinese (Mandarin) · HK Flight Attendant" } { value: "Chinese (Mandarin)_Humorous_Elder", description: "Neutral · Chinese (Mandarin) · Humorous Elder" } { value: "Chinese (Mandarin)_Stubborn_Friend", description: "Neutral · Chinese (Mandarin) · Stubborn Friend" } { value: "Chinese (Mandarin)_Gentle_Youth", description: "Neutral · Chinese (Mandarin) · Gentle Youth" } { value: "Chinese (Mandarin)_Kind-hearted_Elder", description: "Neutral · Chinese (Mandarin) · Kind-hearted Elder" } { value: "Chinese (Mandarin)_Cute_Spirit", description: "Neutral · Chinese (Mandarin) · Cute Spirit" } { value: "Chinese (Mandarin)_Radio_Host", description: "Neutral · Chinese (Mandarin) · Radio Host" } { value: "Chinese (Mandarin)_Lyrical_Voice", description: "Neutral · Chinese (Mandarin) · Lyrical Voice" } { value: "Chinese (Mandarin)_Sincere_Adult", description: "Neutral · Chinese (Mandarin) · Sincere Adult" } { value: "Chinese (Mandarin)_Gentle_Senior", description: "Neutral · Chinese (Mandarin) · Gentle Senior" } { value: "Robot_Armor", description: "Neutral · Chinese (Mandarin) · Robot Armor" } { value: "Japanese_KindLady", description: "Female · Japanese · Kind Lady" } { value: "Japanese_CalmLady", description: "Female · Japanese · Calm Lady" } { value: "Japanese_DecisivePrincess", description: "Female · Japanese · Decisive Princess" } { value: "Japanese_DependableWoman", description: "Female · Japanese · Dependable Woman" } { value: "Japanese_GracefulMaiden", description: "Female · Japanese · Graceful Maiden" } { value: "Japanese_ColdQueen", description: "Female · Japanese · Cold Queen" } { value: "Japanese_LoyalKnight", description: "Male · Japanese · Loyal Knight" } { value: "Japanese_GentleButler", description: "Male · Japanese · Gentle Butler" } { value: "Japanese_DominantMan", description: "Male · Japanese · Dominant Man" } { value: "Japanese_InnocentBoy", description: "Male · Japanese · Innocent Boy" } { value: "Japanese_IntellectualSenior", description: "Neutral · Japanese · Intellectual Senior" } { value: "Japanese_SeriousCommander", description: "Neutral · Japanese · Serious Commander" } { value: "Japanese_OptimisticYouth", description: "Neutral · Japanese · Optimistic Youth" } { value: "Japanese_GenerousIzakayaOwner", description: "Neutral · Japanese · Generous Izakaya Owner" } { value: "Japanese_SportyStudent", description: "Neutral · Japanese · Sporty Student" } { value: "Korean_CalmLady", description: "Female · Korean · Calm Lady" } { value: "Korean_GentleWoman", description: "Female · Korean · Gentle Woman" } { value: "Korean_SoothingLady", description: "Female · Korean · Soothing Lady" } { value: "Korean_SweetGirl", description: "Female · Korean · Sweet Girl" } { value: "Korean_ShyGirl", description: "Female · Korean · Shy Girl" } { value: "Korean_SassyGirl", description: "Female · Korean · Sassy Girl" } { value: "Korean_QuirkyGirl", description: "Female · Korean · Quirky Girl" } { value: "Korean_ColdGirl", description: "Female · Korean · Cold Girl" } { value: "Korean_AirheadedGirl", description: "Female · Korean · Airheaded Girl" } { value: "Korean_AthleticGirl", description: "Female · Korean · Athletic Girl" } { value: "Korean_BraveFemaleWarrior", description: "Female · Korean · Brave Female Warrior" } { value: "Korean_CharmingElderSister", description: "Female · Korean · Charming Elder Sister" } { value: "Korean_CharmingSister", description: "Female · Korean · Charming Sister" } { value: "Korean_CheerfulLittleSister", description: "Female · Korean · Cheerful Little Sister" } { value: "Korean_ChildhoodFriendGirl", description: "Female · Korean · Childhood Friend Girl" } { value: "Korean_FriendlyBigSister", description: "Female · Korean · Friendly Big Sister" } { value: "Korean_HaughtyLady", description: "Female · Korean · Haughty Lady" } { value: "Korean_MysteriousGirl", description: "Female · Korean · Mysterious Girl" } { value: "Korean_CaringWoman", description: "Female · Korean · Caring Woman" } { value: "Korean_ThoughtfulWoman", description: "Female · Korean · Thoughtful Woman" } { value: "Korean_DecisiveQueen", description: "Female · Korean · Decisive Queen" } { value: "Korean_ElegantPrincess", description: "Female · Korean · Elegant Princess" } { value: "Korean_EncharmingSister", description: "Female · Korean · Enchanting Sister" } { value: "Korean_ReliableSister", description: "Female · Korean · Reliable Sister" } { value: "Korean_CalmGentleman", description: "Male · Korean · Calm Gentleman" } { value: "Korean_ColdYoungMan", description: "Male · Korean · Cold Young Man" } { value: "Korean_InnocentBoy", description: "Male · Korean · Innocent Boy" } { value: "Korean_IntellectualMan", description: "Male · Korean · Intellectual Man" } { value: "Korean_CockyGuy", description: "Male · Korean · Cocky Guy" } { value: "Korean_CheerfulBoyfriend", description: "Male · Korean · Cheerful Boyfriend" } { value: "Korean_PossessiveMan", description: "Male · Korean · Possessive Man" } { value: "Korean_DominantMan", description: "Male · Korean · Dominant Man" } { value: "Korean_AthleticStudent", description: "Neutral · Korean · Athletic Student" } { value: "Korean_BraveAdventurer", description: "Neutral · Korean · Brave Adventurer" } { value: "Korean_BraveYouth", description: "Neutral · Korean · Brave Youth" } { value: "Korean_CheerfulCoolJunior", description: "Neutral · Korean · Cheerful Cool Junior" } { value: "Korean_ConfidentBoss", description: "Neutral · Korean · Confident Boss" } { value: "Korean_ConsiderateSenior", description: "Neutral · Korean · Considerate Senior" } { value: "Korean_EnthusiasticTeen", description: "Neutral · Korean · Enthusiastic Teen" } { value: "Korean_GentleBoss", description: "Neutral · Korean · Gentle Boss" } { value: "Korean_IntellectualSenior", description: "Neutral · Korean · Intellectual Senior" } { value: "Korean_LonelyWarrior", description: "Neutral · Korean · Lonely Warrior" } { value: "Korean_OptimisticYouth", description: "Neutral · Korean · Optimistic Youth" } { value: "Korean_PlayboyCharmer", description: "Neutral · Korean · Playboy Charmer" } { value: "Korean_ReliableYouth", description: "Neutral · Korean · Reliable Youth" } { value: "Korean_StrictBoss", description: "Neutral · Korean · Strict Boss" } { value: "Korean_WiseElf", description: "Neutral · Korean · Wise Elf" } { value: "Korean_WiseTeacher", description: "Neutral · Korean · Wise Teacher" } { value: "Spanish_Narrator", description: "Female · Spanish · Narrator" } { value: "Spanish_SereneWoman", description: "Female · Spanish · Serene Woman" } { value: "Spanish_ConfidentWoman", description: "Female · Spanish · Confident Woman" } { value: "Spanish_Kind-heartedGirl", description: "Female · Spanish · Kind-hearted Girl" } { value: "Spanish_SophisticatedLady", description: "Female · Spanish · Sophisticated Lady" } { value: "Spanish_Wiselady", description: "Female · Spanish · Wise Lady" } { value: "Spanish_Fussyhostess", description: "Female · Spanish · Fussy Hostess" } { value: "Spanish_FrankLady", description: "Female · Spanish · Frank Lady" } { value: "Spanish_ThoughtfulLady", description: "Female · Spanish · Thoughtful Lady" } { value: "Spanish_ChattyGirl", description: "Female · Spanish · Chatty Girl" } { value: "Spanish_CompellingGirl", description: "Female · Spanish · Compelling Girl" } { value: "Spanish_CaringGirlfriend", description: "Female · Spanish · Caring Girlfriend" } { value: "Spanish_AssertiveQueen", description: "Female · Spanish · Assertive Queen" } { value: "Spanish_IntonateGirl", description: "Female · Spanish · Intonate Girl" } { value: "Spanish_WhimsicalGirl", description: "Female · Spanish · Whimsical Girl" } { value: "Spanish_ReservedYoungMan", description: "Male · Spanish · Reserved Young Man" } { value: "Spanish_ThoughtfulMan", description: "Male · Spanish · Thoughtful Man" } { value: "Spanish_Strong-WilledBoy", description: "Male · Spanish · Strong-willed Boy" } { value: "Spanish_RationalMan", description: "Male · Spanish · Rational Man" } { value: "Spanish_Deep-tonedMan", description: "Male · Spanish · Deep-toned Man" } { value: "Spanish_Jovialman", description: "Male · Spanish · Jovial Man" } { value: "Spanish_ReliableMan", description: "Male · Spanish · Reliable Man" } { value: "Spanish_AngryMan", description: "Male · Spanish · Angry Man" } { value: "Spanish_RomanticHusband", description: "Male · Spanish · Romantic Husband" } { value: "Spanish_EnergeticBoy", description: "Male · Spanish · Energetic Boy" } { value: "Spanish_SantaClaus", description: "Male · Spanish · Santa Claus" } { value: "Spanish_Rudolph", description: "Male · Spanish · Rudolph" } { value: "Spanish_Arnold", description: "Neutral · Spanish · Arnold" } { value: "Spanish_MaturePartner", description: "Neutral · Spanish · Mature Partner" } { value: "Spanish_CaptivatingStoryteller", description: "Neutral · Spanish · Captivating Storyteller" } { value: "Spanish_WiseScholar", description: "Neutral · Spanish · Wise Scholar" } { value: "Spanish_DeterminedManager", description: "Neutral · Spanish · Determined Manager" } { value: "Spanish_BossyLeader", description: "Neutral · Spanish · Bossy Leader" } { value: "Spanish_AnimeCharacter", description: "Neutral · Spanish · Anime Character" } { value: "Spanish_SincereTeen", description: "Neutral · Spanish · Sincere Teen" } { value: "Spanish_Comedian", description: "Neutral · Spanish · Comedian" } { value: "Spanish_Debator", description: "Neutral · Spanish · Debator" } { value: "Spanish_ToughBoss", description: "Neutral · Spanish · Tough Boss" } { value: "Spanish_Steadymentor", description: "Neutral · Spanish · Steady Mentor" } { value: "Spanish_Ghost", description: "Neutral · Spanish · Ghost" } { value: "Spanish_HumorousElder", description: "Neutral · Spanish · Humorous Elder" } { value: "Spanish_StrictBoss", description: "Neutral · Spanish · Strict Boss" } { value: "Spanish_SereneElder", description: "Neutral · Spanish · Serene Elder" } { value: "Spanish_PowerfulSoldier", description: "Neutral · Spanish · Powerful Soldier" } { value: "Spanish_PassionateWarrior", description: "Neutral · Spanish · Passionate Warrior" } { value: "Spanish_PowerfulVeteran", description: "Neutral · Spanish · Powerful Veteran" } { value: "Spanish_SensibleManager", description: "Neutral · Spanish · Sensible Manager" } { value: "Portuguese_Narrator", description: "Female · Portuguese · Narrator" } { value: "Portuguese_SentimentalLady", description: "Female · Portuguese · Sentimental Lady" } { value: "Portuguese_Wiselady", description: "Female · Portuguese · Wise Lady" } { value: "Portuguese_UpsetGirl", description: "Female · Portuguese · Upset Girl" } { value: "Portuguese_ConfidentWoman", description: "Female · Portuguese · Confident Woman" } { value: "Portuguese_SmartYoungGirl", description: "Female · Portuguese · Smart Young Girl" } { value: "Portuguese_Kind-heartedGirl", description: "Female · Portuguese · Kind-hearted Girl" } { value: "Portuguese_Pompouslady", description: "Female · Portuguese · Pompous Lady" } { value: "Portuguese_SweetGirl", description: "Female · Portuguese · Sweet Girl" } { value: "Portuguese_AttractiveGirl", description: "Female · Portuguese · Attractive Girl" } { value: "Portuguese_PlayfulGirl", description: "Female · Portuguese · Playful Girl" } { value: "Portuguese_GorgeousLady", description: "Female · Portuguese · Gorgeous Lady" } { value: "Portuguese_LovelyLady", description: "Female · Portuguese · Lovely Lady" } { value: "Portuguese_SereneWoman", description: "Female · Portuguese · Serene Woman" } { value: "Portuguese_NaughtySchoolgirl", description: "Female · Portuguese · Naughty Schoolgirl" } { value: "Portuguese_Fussyhostess", description: "Female · Portuguese · Fussy Hostess" } { value: "Portuguese_CharmingQueen", description: "Female · Portuguese · Charming Queen" } { value: "Portuguese_CharmingLady", description: "Female · Portuguese · Charming Lady" } { value: "Portuguese_WhimsicalGirl", description: "Female · Portuguese · Whimsical Girl" } { value: "Portuguese_StressedLady", description: "Female · Portuguese · Stressed Lady" } { value: "Portuguese_CaringGirlfriend", description: "Female · Portuguese · Caring Girlfriend" } { value: "Portuguese_InspiringLady", description: "Female · Portuguese · Inspiring Lady" } { value: "Portuguese_ElegantGirl", description: "Female · Portuguese · Elegant Girl" } { value: "Portuguese_CompellingGirl", description: "Female · Portuguese · Compelling Girl" } { value: "Portuguese_ThoughtfulLady", description: "Female · Portuguese · Thoughtful Lady" } { value: "Portuguese_FrankLady", description: "Female · Portuguese · Frank Lady" } { value: "Portuguese_Strong-WilledBoy", description: "Male · Portuguese · Strong-willed Boy" } { value: "Portuguese_Deep-VoicedGentleman", description: "Male · Portuguese · Deep-voiced Gentleman" } { value: "Portuguese_AngryMan", description: "Male · Portuguese · Angry Man" } { value: "Portuguese_Godfather", description: "Male · Portuguese · Godfather" } { value: "Portuguese_ReservedYoungMan", description: "Male · Portuguese · Reserved Young Man" } { value: "Portuguese_ThoughtfulMan", description: "Male · Portuguese · Thoughtful Man" } { value: "Portuguese_Jovialman", description: "Male · Portuguese · Jovial Man" } { value: "Portuguese_Grinch", description: "Male · Portuguese · Grinch" } { value: "Portuguese_EnergeticBoy", description: "Male · Portuguese · Energetic Boy" } { value: "Portuguese_ReliableMan", description: "Male · Portuguese · Reliable Man" } { value: "Portuguese_SantaClaus", description: "Male · Portuguese · Santa Claus" } { value: "Portuguese_Rudolph", description: "Male · Portuguese · Rudolph" } { value: "Portuguese_Arnold", description: "Neutral · Portuguese · Arnold" } { value: "Portuguese_CharmingSanta", description: "Male · Portuguese · Charming Santa" } { value: "Portuguese_FascinatingBoy", description: "Male · Portuguese · Fascinating Boy" } { value: "Portuguese_RomanticHusband", description: "Male · Portuguese · Romantic Husband" } { value: "Portuguese_FragileBoy", description: "Male · Portuguese · Fragile Boy" } { value: "Portuguese_RationalMan", description: "Male · Portuguese · Rational Man" } { value: "Portuguese_TheatricalActor", description: "Male · Portuguese · Theatrical Actor" } { value: "Portuguese_PassionateWarrior", description: "Neutral · Portuguese · Passionate Warrior" } { value: "Portuguese_AnimeCharacter", description: "Neutral · Portuguese · Anime Character" } { value: "Portuguese_CaptivatingStoryteller", description: "Neutral · Portuguese · Captivating Storyteller" } { value: "Portuguese_BossyLeader", description: "Neutral · Portuguese · Bossy Leader" } { value: "Portuguese_SadTeen", description: "Neutral · Portuguese · Sad Teen" } { value: "Portuguese_MaturePartner", description: "Neutral · Portuguese · Mature Partner" } { value: "Portuguese_Comedian", description: "Neutral · Portuguese · Comedian" } { value: "Portuguese_ToughBoss", description: "Neutral · Portuguese · Tough Boss" } { value: "Portuguese_Dramatist", description: "Neutral · Portuguese · Dramatist" } { value: "Portuguese_Steadymentor", description: "Neutral · Portuguese · Steady Mentor" } { value: "Portuguese_Ghost", description: "Neutral · Portuguese · Ghost" } { value: "Portuguese_HumorousElder", description: "Neutral · Portuguese · Humorous Elder" } { value: "Portuguese_CalmLeader", description: "Neutral · Portuguese · Calm Leader" } { value: "Portuguese_GentleTeacher", description: "Neutral · Portuguese · Gentle Teacher" } { value: "Portuguese_SereneElder", description: "Neutral · Portuguese · Serene Elder" } { value: "Portuguese_GrimReaper", description: "Neutral · Portuguese · Grim Reaper" } { value: "Portuguese_FriendlyNeighbor", description: "Neutral · Portuguese · Friendly Neighbor" } { value: "Portuguese_PowerfulSoldier", description: "Neutral · Portuguese · Powerful Soldier" } { value: "Portuguese_StrictBoss", description: "Neutral · Portuguese · Strict Boss" } { value: "Portuguese_PlayfulSpirit", description: "Neutral · Portuguese · Playful Spirit" } { value: "Portuguese_PowerfulVeteran", description: "Neutral · Portuguese · Powerful Veteran" } { value: "Portuguese_SensibleManager", description: "Neutral · Portuguese · Sensible Manager" } { value: "Portuguese_Debator", description: "Neutral · Portuguese · Debator" } { value: "Portuguese_Conscientiousinstructor", description: "Neutral · Portuguese · Conscientious Instructor" } { value: "Portuguese_WiseScholar", description: "Neutral · Portuguese · Wise Scholar" } { value: "Portuguese_DeterminedManager", description: "Neutral · Portuguese · Determined Manager" } { value: "French_Female_News_Anchor", description: "Female · French · Patient Female Presenter" } { value: "French_MovieLeadFemale", description: "Female · French · Movie Lead Female" } { value: "French_FemaleAnchor", description: "Female · French · Female Anchor" } { value: "French_Male_Speech_New", description: "Male · French · Level-headed Man" } { value: "French_CasualMan", description: "Male · French · Casual Man" } { value: "French_MaleNarrator", description: "Male · French · Male Narrator" } { value: "Indonesian_CalmWoman", description: "Female · Indonesian · Calm Woman" } { value: "Indonesian_SweetGirl", description: "Female · Indonesian · Sweet Girl" } { value: "Indonesian_CharmingGirl", description: "Female · Indonesian · Charming Girl" } { value: "Indonesian_ConfidentWoman", description: "Female · Indonesian · Confident Woman" } { value: "Indonesian_GentleGirl", description: "Female · Indonesian · Gentle Girl" } { value: "Indonesian_ReservedYoungMan", description: "Male · Indonesian · Reserved Young Man" } { value: "Indonesian_CaringMan", description: "Male · Indonesian · Caring Man" } { value: "Indonesian_DeterminedBoy", description: "Male · Indonesian · Determined Boy" } { value: "Indonesian_BossyLeader", description: "Neutral · Indonesian · Bossy Leader" } { value: "German_SweetLady", description: "Female · German · Sweet Lady" } { value: "German_FriendlyMan", description: "Male · German · Friendly Man" } { value: "German_PlayfulMan", description: "Male · German · Playful Man" } { value: "Russian_AmbitiousWoman", description: "Female · Russian · Ambitious Woman" } { value: "Russian_CrazyQueen", description: "Female · Russian · Crazy Girl" } { value: "Russian_PessimisticGirl", description: "Female · Russian · Pessimistic Girl" } { value: "Russian_ReliableMan", description: "Male · Russian · Reliable Man" } { value: "Russian_AttractiveGuy", description: "Male · Russian · Attractive Guy" } { value: "Russian_Bad-temperedBoy", description: "Male · Russian · Bad-tempered Boy" } { value: "Russian_HandsomeChildhoodFriend", description: "Neutral · Russian · Handsome Childhood Friend" } { value: "Russian_BrightHeroine", description: "Female · Russian · Bright Queen" } { value: "Italian_BraveHeroine", description: "Female · Italian · Brave Heroine" } { value: "Italian_WanderingSorcerer", description: "Male · Italian · Wandering Sorcerer" } { value: "Italian_Narrator", description: "Neutral · Italian · Narrator" } { value: "Italian_DiligentLeader", description: "Neutral · Italian · Diligent Leader" } { value: "Dutch_kindhearted_girl", description: "Female · Dutch · Kind-hearted Girl" } { value: "Dutch_bossy_leader", description: "Neutral · Dutch · Bossy Leader" } { value: "Vietnamese_kindhearted_girl", description: "Female · Vietnamese · Kind-hearted Girl" } { value: "Arabic_CalmWoman", description: "Female · Arabic · Calm Woman" } { value: "Arabic_FriendlyGuy", description: "Male · Arabic · Friendly Guy" } { value: "Turkish_CalmWoman", description: "Female · Turkish · Calm Woman" } { value: "Turkish_Trustworthyman", description: "Male · Turkish · Trustworthy Man" } { value: "Ukrainian_CalmWoman", description: "Female · Ukrainian · Calm Woman" } { value: "Ukrainian_WiseScholar", description: "Neutral · Ukrainian · Wise Scholar" } { value: "Thai_female_1_sample1", description: "Female · Thai · Confident Woman" } { value: "Thai_female_2_sample2", description: "Female · Thai · Energetic Woman" } { value: "Thai_male_1_sample8", description: "Male · Thai · Serene Man" } { value: "Thai_male_2_sample2", description: "Male · Thai · Friendly Man" } { value: "Polish_female_1_sample1", description: "Female · Polish · Calm Woman" } { value: "Polish_female_2_sample3", description: "Female · Polish · Casual Woman" } { value: "Polish_male_1_sample4", description: "Male · Polish · Male Narrator" } { value: "Polish_male_2_sample3", description: "Male · Polish · Male Anchor" } { value: "Romanian_female_1_sample4", description: "Female · Romanian · Optimistic Youth" } { value: "Romanian_female_2_sample1", description: "Female · Romanian · Gentle Woman" } { value: "Romanian_male_1_sample2", description: "Male · Romanian · Reliable Man" } { value: "Romanian_male_2_sample1", description: "Neutral · Romanian · Energetic Youth" } { value: "Greek_female_1_sample1", description: "Female · Greek · Gentle Lady" } { value: "Greek_female_2_sample3", description: "Female · Greek · Girl Next Door" } { value: "Greek_male_1a_v1", description: "Male · Greek · Thoughtful Mentor" } { value: "czech_female_5_v7", description: "Female · Czech · Steadfast Narrator" } { value: "czech_female_2_v2", description: "Female · Czech · Elegant Lady" } { value: "czech_male_1_v1", description: "Male · Czech · Assured Presenter" } { value: "finnish_female_4_v1", description: "Female · Finnish · Assertive Woman" } { value: "finnish_male_1_v2", description: "Male · Finnish · Friendly Boy" } { value: "finnish_male_3_v1", description: "Male · Finnish · Upbeat Man" } { value: "hindi_female_1_v2", description: "Female · Hindi · News Anchor" } { value: "hindi_female_2_v1", description: "Female · Hindi · Tranquil Woman" } { value: "hindi_male_1_v2", description: "Male · Hindi · Trustworthy Advisor" } { value: "Cantonese_GentleLady", description: "Female · Cantonese · Gentle Lady" } { value: "Cantonese_CuteGirl", description: "Female · Cantonese · Cute Girl" } { value: "Cantonese_KindWoman", description: "Female · Cantonese · Kind Woman" } { value: "Cantonese_PlayfulMan", description: "Male · Cantonese · Playful Man" } { value: "Cantonese_ProfessionalHost", description: "Neutral · Cantonese · Professional Host" } ] } def aspect-ratio-completions [] { [ { value: "1:1", description: "Square (1:1) — 1024×1024" } { value: "16:9", description: "Landscape (16:9) — 1024×576" } { value: "9:16", description: "Portrait (9:16) — 576×1024" } { value: "4:3", description: "Standard (4:3) — 1024×768" } { value: "3:2", description: "Classic photo (3:2) — 1024×682" } { value: "2:3", description: "Portrait photo (2:3) — 682×1024" } ] } def speech-model-completions [] { [ { value: "speech-2.8-hd", description: "2.8-hd — High quality, natural expressiveness (recommended)" } { value: "speech-2.8-turbo", description: "2.8-turbo — Faster synthesis, slightly lower quality" } { value: "speech-2.6-hd", description: "2.6-hd — Legacy HD model (may not be in plan)" } { value: "speech-2.6-turbo", description: "2.6-turbo — Legacy fast model (may not be in plan)" } { value: "speech-02-hd", description: "02-hd — Older HD model (may not be in plan)" } { value: "speech-01-turbo", description: "01-turbo — Older fast model (may not be in plan)" } ] } # ── Subcommands ───────────────────────────────────────────────────────────────── # `minimax voices` — list all available MiniMax TTS system voices. # # Voices are grouped by language. Each voice has a unique ID (use with --voice), # plus gender and description. # # # Example # minimax voices # list all voices # minimax speech --voice male-qn-johnny "Hello" # use a specific voice export def voices [] { let voices = voice-id-completions let by_lang = $voices | group-by { |v| let parsed = ($v.description | parse "{gender} · {lang} ·{rest}") if ($parsed | is-empty) { "Other" } else { $parsed | get 0 | get --optional lang | default "Other" } } print "MiniMax system voices — 332 voices across 15 languages" print "" for lang_name in ["Chinese (Mandarin)", "Cantonese", "English", "Japanese", "Korean", "Spanish", "Portuguese", "French", "Indonesian", "German", "Russian", "Italian", "Dutch", "Vietnamese", "Arabic", "Turkish", "Ukrainian", "Thai", "Polish", "Romanian", "Greek", "Czech", "Finnish", "Hindi", "Other"] { if ($by_lang | get --optional $lang_name | is-empty) { continue } let lang_voices = $by_lang | get $lang_name let count = ($lang_voices | length) print $'(ansi cb)◆ ($lang_name)(ansi rst) — ($count) voices' $lang_voices | each { |v| print $' (ansi d)($v.value)(ansi rst) ($v.description)' } print "" } } # `minimax image` — generate an image with MiniMax image-01 model. # # # Parameters # `prompt` # The text description of the image to generate (required, non-empty) # `--aspect` # Aspect ratio: 1:1 (default), 16:9, 9:16, 4:3, 3:2, 2:3 # `--model` # Model to use: image-01 (default) or image-01-pro # `--seed` # Random seed for reproducible results (optional) # `--n` # Number of images to generate (1-4, default 1) # `--name` # Output filename without extension (default: minimax_) # `--dir` # Output directory (default: current directory) # `--no-view` # Skip the terminal display prompt (image is still saved) export def image [ # The text description of the image to generate. prompt: string # Aspect ratio of the output image. --aspect (-a): string@aspect-ratio-completions = "1:1" # Image model to use. --model (-m): string = "image-01" # Random seed for reproducible results (0 = random). --seed (-s): int = 0 # Number of images to generate (1–4). --n (-n): int = 1 # Output filename without extension (timestamp is added). --name (-N): string = "" # Output directory. --dir (-d): string = "." # Skip the terminal display prompt. --no-view (-V) ] { if ($prompt | str trim | is-empty) { error make { msg: "Prompt cannot be empty" label: { text: "Provide a non-empty prompt string" } } } if $n < 1 or $n > 4 { error make { msg: $"n must be 1–4, got ($n)" label: { text: "Use --n with a value between 1 and 4" } } } let token = get-token let out_dir = if ($dir | path expand) == "." { $env.PWD } else { $dir | path expand } if not (($out_dir | path type) == "dir") { error make { msg: $"Output directory does not exist: ($out_dir)" label: { text: "Use an existing directory, or omit --dir" } } } let timestamp = (date now | format date "%Y%m%d_%H%M%S") let base_name = if $name == "" { $"minimax_($timestamp)" } else { $name } let seed_val = if $seed == 0 { null } else { $seed } let payload = { model: $model prompt: $prompt aspect_ratio: $aspect } let payload = if $seed != 0 { $payload | merge { seed: $seed } } else { $payload } let payload = $payload | merge { n: $n } let headers = { Authorization: $'Bearer ($token)' Content-Type: "application/json" } print $'(ansi d)Generating ($n) images with ($model) at ($aspect)…(ansi rst)' let resp = http post --headers $headers $"https://api.minimax.io/v1/image_generation" ($payload | to json) if ($resp.base_resp.status_code != 0) { check-base-resp $resp } if not ($resp.data | columns | any { |c| $c == "image_urls" }) { error make { msg: "No image URLs in API response — content may have been blocked" label: { text: "Try a different prompt; NSFW content is not allowed" } } } let image_urls = $resp.data.image_urls let items = $image_urls | enumerate | each { |pair| let idx = $pair.index let img_url = $pair.item let parsed_ext = ($img_url | parse --regex "\\.(\\w+)\\?") let ext = if ($parsed_ext | is-empty) { "png" } else { ($parsed_ext | get 0 | get capture0) } let filename = if $n > 1 { $"($base_name)_($idx).($ext)" } else { $"($base_name).($ext)" } let out_path = $out_dir | path join $filename print $'(ansi d)Downloading ($filename)…(ansi rst)' let download_err = (try { curl -L -s -o $out_path $img_url null } catch { |e| $e.raw }) if $download_err != null { error make { msg: $"Failed to download image: ($download_err)" label: { text: "Check network and image URL" } } } { index: $idx filename: $filename path: $out_path url: $img_url } } print "" print $'(ansi gb)◆ Images saved(ansi rst)' $items | table -e if not $no_view { for item in $items { prompt-view $item.path } } } # `minimax speech` — synthesize text to speech with MiniMax speech-2.8-hd model. # # # Parameters # `text` # The text to synthesize (required, non-empty) # `--voice` # Voice ID from `minimax voices` (default: English_Graceful_Lady) # `--model` # Speech model: speech-2.8-hd (default, recommended) or speech-2.8-turbo # `--speed` # Speech speed as a multiplier (0.5–2.0, default 1.0) # `--vol` # Volume as a multiplier (0.5–2.0, default 1.0) # `--pitch` # Pitch adjustment in semitones (-12 to 12, default 0) # `--name` # Output filename without extension (default: minimax_) # `--dir` # Output directory (default: current directory) # `--no-play` # Skip the audio playback prompt (file is still saved) export def speech [ # The text to synthesize into speech. text: string # Voice ID — run `minimax voices` for the full list. --voice (-v): string@voice-id-completions = "English_Graceful_Lady" # Speech synthesis model. --model (-m): string@speech-model-completions = "speech-2.8-hd" # Speech speed as a multiplier (0.5–2.0). --speed: float = 1.0 # Volume as a multiplier (0.5–2.0). --vol: float = 1.0 # Pitch adjustment in semitones (-12 to 12). --pitch: int = 0 # Output filename without extension (timestamp is added). --name (-N): string = "" # Output directory. --dir (-d): string = "." # Skip the audio playback prompt. --no-play (-P) ] { if ($text | str trim | is-empty) { error make { msg: "Text to synthesize cannot be empty" label: { text: "Provide a non-empty text string" } } } if $speed < 0.5 or $speed > 2.0 { error make { msg: $"speed must be 0.5–2.0, got ($speed)" label: { text: "Use --speed with a value between 0.5 and 2.0" } } } if $vol < 0.5 or $vol > 2.0 { error make { msg: $"vol must be 0.5–2.0, got ($vol)" label: { text: "Use --vol with a value between 0.5 and 2.0" } } } if $pitch < -12 or $pitch > 12 { error make { msg: $"pitch must be -12 to 12, got ($pitch)" label: { text: "Use --pitch with a value between -12 and 12" } } } let token = get-token let out_dir = if ($dir | path expand) == "." { $env.PWD } else { $dir | path expand } if not (($out_dir | path type) == "dir") { error make { msg: $"Output directory does not exist: ($out_dir)" label: { text: "Use an existing directory, or omit --dir" } } } let timestamp = (date now | format date "%Y%m%d_%H%M%S") let base_name = if $name == "" { $"minimax_($timestamp)" } else { $name } let filename = $"($base_name).mp3" let out_path = $out_dir | path join $filename let payload = { model: $model text: $text voice_setting: { voice_id: $voice } audio_setting: { sample_rate: 32000 speed: $speed vol: $vol pitch: $pitch } } let headers = { Authorization: $'Bearer ($token)' Content-Type: "application/json" } print $'(ansi d)Synthesizing speech with ($voice) at ($model)…(ansi rst)' let resp = http post --headers $headers $"https://api.minimax.io/v1/t2a_v2" ($payload | to json) if ($resp.base_resp.status_code != 0) { check-base-resp $resp } let audio_hex = $resp.data.audio if ($audio_hex | is-empty) { error make { msg: "No audio data in API response" label: { text: "Check API response or try again" } } } print $'(ansi d)Decoding and saving audio…(ansi rst)' let decode_err = (try { $audio_hex | decode hex | save -f $out_path null } catch { |e| $e.raw }) if $decode_err != null { error make { msg: $"Failed to decode and save audio: ($decode_err)" label: { text: "Check audio data integrity" } } } let chars = $resp.extra_info.usage_characters print "" print $'(ansi gb)? Audio saved(ansi rst)' print $'(ansi d) File: ($out_path)(ansi rst)' if not ($chars | is-empty) { print $'(ansi d) Characters synthesised: ($chars)(ansi rst)' } if not $no_play { prompt-play $out_path } }