repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
nushell/modules/minimax.nu
Raw# 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_<timestamp>)
# `--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_<timestamp>)
# `--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
}
}