@mynthio/cli 0.0.10 → 0.0.12

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.
Files changed (2) hide show
  1. package/dist/bin.js +6 -6
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import {Command,Option,Help,InvalidArgumentError}from'commander';import*as _ from'cross-keychain';import {readFile,mkdir,writeFile,chmod,rm,stat}from'fs/promises';import {homedir}from'os';import {resolve,join,extname,basename}from'path';import {z}from'zod';import Ze from'chalk';import Bt from'ora';var f=class extends Error{_tag="MynthCliError";cause;constructor(e){super(e.message),this.name=this._tag,this.cause=e.cause;}},A=class extends Error{_tag="CliUsageError";constructor(e){super(e),this.name=this._tag;}},I=class extends Error{_tag="NotAuthenticatedError";constructor(e={}){super(e.reason??"not authenticated"),this.name=this._tag;}},v=class extends Error{_tag="CredentialsStoreError";cause;constructor(e){super(e.message),this.name=this._tag,this.cause=e.cause;}},k=class extends Error{_tag="WorkOSError";code;status;cause;constructor(e){super(e.message),this.name=this._tag,this.code=e.code,this.status=e.status,this.cause=e.cause;}},S=class extends Error{_tag="AuthorizationPendingError";slowDown;constructor(e){super("authorization pending"),this.name=this._tag,this.slowDown=e.slowDown;}},R=class extends Error{_tag="AuthorizationExpiredError";constructor(){super("authorization expired"),this.name=this._tag;}},$=class extends Error{_tag="AuthorizationDeniedError";constructor(){super("authorization denied"),this.name=this._tag;}},l=class extends Error{_tag="MynthApiError";status;code;cause;constructor(e){super(e.message),this.name=this._tag,this.status=e.status,this.code=e.code,this.cause=e.cause;}};var at=6e4,W=t=>t?{user:t}:{},ie=(t,e)=>new I({reason:e instanceof Error?`${t}: ${e.message}`:t}),q=class{constructor(e,n,s){this.config=e;this.store=n;this.workos=s;this.envApiKey=e.apiKeyEnvOverride,this.envApiKeySet=this.envApiKey!==void 0&&this.envApiKey.length>0;}envApiKeySet;envApiKey;async resolve(){if(this.envApiKeySet)return {kind:"api_key",apiKey:this.envApiKey,source:"env"};let e;try{e=await this.store.get();}catch(s){throw ie("could not read credentials",s)}if(e===void 0)throw new I({reason:"no credentials configured"});if(e.kind==="api_key")return {kind:"api_key",apiKey:e.api_key,source:"stored"};let n=await this.refreshIfNeeded(e);return {kind:"oauth",accessToken:n.access_token,...W(n.user)}}async status(){if(this.envApiKeySet)return {kind:"env",source:"MYNTH_API_KEY"};let e;try{e=await this.store.get();}catch{e=void 0;}return e===void 0?{kind:"none"}:e.kind==="api_key"?{kind:"api_key"}:{kind:"oauth",expiresAt:e.expires_at,...W(e.user)}}async setApiKey(e){await this.store.set({kind:"api_key",api_key:e});}async saveOAuth(e){await this.store.set({kind:"oauth",access_token:e.accessToken,refresh_token:e.refreshToken,expires_at:e.expiresAt,...W(e.user)});}async logout(){await this.store.clear();}async refreshIfNeeded(e){if(e.expires_at-Date.now()>at)return e;let n;try{n=await this.workos.refresh(e.refresh_token);}catch(a){throw ie("token refresh failed",a)}let s={kind:"oauth",access_token:n.token.access_token,refresh_token:n.token.refresh_token,expires_at:n.expiresAt,...W(n.token.user??e.user)};try{await this.store.set(s);}catch(a){throw ie("could not persist refreshed token",a)}return s}};var Se=()=>{let t=process.env.MYNTH_API_KEY;return {mynthApiUrl:process.env.MYNTH_API_URL??"https://api.mynth.io",...t!==void 0?{apiKeyEnvOverride:t}:{}}};var Re=z.object({id:z.string(),email:z.string(),first_name:z.string().nullable().optional(),last_name:z.string().nullable().optional()}),$e=z.object({device_code:z.string(),user_code:z.string(),verification_uri:z.string(),verification_uri_complete:z.string().optional(),expires_in:z.number(),interval:z.number().optional()}),Te=z.object({access_token:z.string(),refresh_token:z.string(),user:Re.optional(),organization_id:z.string().optional()}),Ce=z.object({error:z.string().optional(),error_description:z.string().optional(),message:z.string().optional(),code:z.string().optional()}),rt=z.object({kind:z.literal("oauth"),access_token:z.string(),refresh_token:z.string(),expires_at:z.number(),user:Re.optional()}),ot=z.object({kind:z.literal("api_key"),api_key:z.string()}),Ee=z.union([rt,ot]),H=z.lazy(()=>z.union([z.string(),z.number(),z.boolean(),z.null(),z.array(H),z.record(H)])),Pe=z.object({data:z.object({urls:z.array(z.string())})}),it=z.union([z.object({status:z.literal("success"),url:z.string(),level:z.string()}),z.object({status:z.literal("failed"),url:z.string(),error:z.object({code:z.string()})})]),Oe=z.object({data:z.object({task:z.object({id:z.string(),status:z.literal("completed"),cost:z.string()}),results:z.array(it)})}),Ie=z.object({data:z.object({taskId:z.string(),access:z.object({publicAccessToken:z.string()}).optional()})}),Me=z.object({data:z.object({status:z.union([z.literal("pending"),z.literal("completed"),z.literal("failed")])})}),lt=z.object({id:z.string(),type:z.union([z.literal("image.generate"),z.literal("image.rate")]),status:z.union([z.literal("pending"),z.literal("completed"),z.literal("failed")]),userId:z.string(),apiKeyId:z.string().nullable(),cost:z.string().nullable(),request:H,result:H,errors:z.array(z.object({code:z.string()})).nullable().optional(),createdAt:z.string(),updatedAt:z.string()}),B=z.object({data:lt}),ct=z.object({perImage:z.object({base:z.string(),"4k":z.string().optional()}),inputFee:z.string().optional()}),dt=z.object({id:z.string(),displayName:z.string().nullable(),pricing:ct.nullable()}),je=z.object({data:z.array(dt)});var le="mynth-cli",ce="default",wt="credentials.json",vt=t=>{let e=t?.name;return e==="NoKeyringError"||e==="InitError"},Y=async(t,e)=>{try{return {available:true,value:await t()}}catch(n){if(vt(n))return {available:false};throw new v({message:e,cause:n})}},Ne=t=>{let e;try{e=JSON.parse(t);}catch(s){throw new v({message:"credentials JSON parse failed",cause:s})}let n=Ee.safeParse(e);if(!n.success)throw new v({message:"credentials shape invalid",cause:n.error});return n.data},De=t=>JSON.stringify(t),kt=()=>{let t=process.env.XDG_CONFIG_HOME,e=t&&t.length>0?t:join(homedir(),".config");return join(e,"mynth")},Le=async t=>{try{return await stat(t),true}catch{return false}},G=class{filePath;dir;constructor(){this.dir=kt(),this.filePath=join(this.dir,wt);}async get(){let e=await Y(()=>_.getPassword(le,ce),"keychain get failed");if(e.available)return e.value===null?void 0:Ne(e.value);if(await Le(this.filePath))try{return Ne(await readFile(this.filePath,"utf8"))}catch(n){throw n instanceof v?n:new v({message:"read credentials file failed",cause:n})}}async set(e){if((await Y(()=>_.setPassword(le,ce,De(e)),"keychain set failed")).available){await this.deleteFileSilently();return}await mkdir(this.dir,{recursive:true}).catch(s=>{throw new v({message:"create config dir failed",cause:s})}),await writeFile(this.filePath,De(e),"utf8").catch(s=>{throw new v({message:"write credentials file failed",cause:s})}),await chmod(this.filePath,384).catch(()=>{});}async clear(){await Y(()=>_.deletePassword(le,ce),"keychain delete failed").catch(()=>{}),await this.deleteFileSilently();}async usingKeychain(){let e=await Y(()=>_.getKeyring(),"keychain probe failed");return e.available&&e.value!==null}async deleteFileSilently(){await Le(this.filePath)&&await rm(this.filePath).catch(e=>{throw new v({message:"delete credentials file failed",cause:e})});}};var At=t=>t.kind==="api_key"?t.apiKey:t.accessToken,T=async t=>{try{return await t.json()}catch(e){throw new l({message:`invalid JSON response: ${e.message}`,status:t.status,cause:e})}},C=async t=>{try{return await t.text()}catch{return ""}},V=class{constructor(e,n){this.auth=n;this.baseUrl=e.mynthApiUrl;}baseUrl;cachedAuth;async execute(e,n={}){let s=await this.attempt(e,n,false);return s.status!==401?s:this.attempt(e,n,true)}async executePublic(e,n={}){try{return await fetch(`${this.baseUrl}${e}`,n)}catch(s){throw new l({message:`request failed: ${s.message}`,status:0,cause:s})}}async attempt(e,n,s){let a=await this.getAuth(s),o=new Headers(n.headers);o.set("Authorization",`Bearer ${At(a)}`);try{return await fetch(`${this.baseUrl}${e}`,{...n,headers:o})}catch(c){throw new l({message:`request failed: ${c.message}`,status:0,cause:c})}}async getAuth(e){return e&&(this.cachedAuth=void 0),this.cachedAuth!==void 0?this.cachedAuth:(this.cachedAuth=await this.auth.resolve(),this.cachedAuth)}};var N=10,D=10,L=2,U=7,Ue=300*1e3,Ct=12e3,Et=2500,Pt=5e3,Ot={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".webp":"image/webp"},It=t=>new Promise(e=>setTimeout(e,t)),Mt=(t,e,n)=>{try{let a=new URL(t).pathname.split("/").filter(Boolean).pop();if(a&&a.length>0)return decodeURIComponent(a)}catch{}return `${e}-${n}`},jt=async t=>{let e=extname(t).toLowerCase(),n=Ot[e];if(!n)throw new l({message:`unsupported image extension "${e}" for ${t} (allowed: .jpg, .jpeg, .png, .webp)`,status:0});let s;try{s=await readFile(t);}catch(o){throw new l({message:`could not read ${t}: ${o.message}`,status:0,cause:o})}let a=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);return new File([new Uint8Array(a)],basename(t),{type:n})},M=async(t,e,n)=>{let s=e.safeParse(await T(t));if(!s.success)throw new l({message:n,status:t.status,cause:s.error});return s.data},j=async(t,e,n)=>{if(t.status>=200&&t.status<300)return;let s=await C(t);throw new l({message:`${e} failed (${t.status}): ${s||"no body"}`,status:t.status})},Nt=async(t,e,n)=>{let s=Array.from({length:t.length}),a=0,o=async()=>{for(;;){let c=a++,h=t[c];if(h===void 0)return;s[c]=await n(h,c);}};return await Promise.all(Array.from({length:Math.min(e,t.length)},o)),s},X=class{constructor(e){this.api=e;}async upload(e){if(e.length===0)throw new l({message:"no files to upload",status:0});if(e.length>N)throw new l({message:`too many files: ${e.length} (max ${N})`,status:0});let n=await Promise.all(e.map(jt)),s=new FormData;for(let c of n)s.append("images",c);let a=await this.api.execute("/image/upload",{method:"POST",body:s});await j(a,"upload");let o=await M(a,Pe,"invalid upload response");return e.map((c,h)=>({path:c,url:o.data.urls[h]}))}async rate(e){if(e.urls.length===0)throw new l({message:"no image URLs to rate",status:0});if(e.urls.length>D)throw new l({message:`too many images: ${e.urls.length} (max ${D})`,status:0});if(e.levels!==void 0&&(e.levels.length<L||e.levels.length>U))throw new l({message:`levels must have between ${L} and ${U} items (got ${e.levels.length})`,status:0});let n=e.levels!==void 0?{urls:e.urls,mode:"custom",levels:e.levels}:{urls:e.urls,mode:"nsfw_sfw"},s=await this.api.execute("/image/rate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});return await j(s,"rate"),(await M(s,Oe,"invalid rate response")).data}async generate(e){let n=e.requestPat?{...e.request,access:{...e.request.access,pat:{enabled:true}}}:e.request,s=await this.api.execute("/image/generate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});await j(s,"generate");let a=await M(s,Ie,"invalid generate response"),o=a.data.access?.publicAccessToken;return {taskId:a.data.taskId,...o!==void 0?{pat:o}:{}}}async waitForTask(e,n){let s=Date.now();for(;;){let a=Date.now()-s;if(a>=Ue)throw new l({message:`task ${e} polling timed out after ${Ue}ms`,status:0});let o=await this.getTaskStatus(e,n);if(o==="completed")return this.getTaskDetails(e);if(o==="failed")throw new l({message:`task ${e} failed during generation`,status:0});let c=a<Ct?Et:Pt;await It(c+Math.floor(Math.random()*500));}}async getTaskDetails(e){let n=await this.api.execute(`/tasks/${e}`);return await j(n,"task details"),(await M(n,B,"invalid task details response")).data}async downloadImages(e){let n=resolve(e.destinationDir);try{await mkdir(n,{recursive:true});}catch(s){throw new l({message:`could not create output directory ${n}: ${s.message}`,status:0,cause:s})}return Nt(e.urls,4,async(s,a)=>{let o;try{o=await fetch(s);}catch(g){throw new l({message:`download failed for ${s}: ${g.message}`,status:0,cause:g})}if(o.status<200||o.status>=300)throw new l({message:`download failed for ${s} (${o.status})`,status:o.status});let c;try{c=await o.arrayBuffer();}catch(g){throw new l({message:`could not read body for ${s}: ${g.message}`,status:o.status,cause:g})}let h=Mt(s,e.taskId,a),y=join(n,h);try{await writeFile(y,new Uint8Array(c));}catch(g){throw new l({message:`could not write ${y}: ${g.message}`,status:0,cause:g})}return y})}async getTaskStatus(e,n){let s=`/tasks/${e}/status`,a;if(n!==void 0)try{a=await fetch(`${this.api.baseUrl}${s}`,{headers:{Authorization:`Bearer ${n}`}});}catch(c){throw new l({message:`task status request failed: ${c.message}`,status:0,cause:c})}else a=await this.api.execute(s);return await j(a,"task status"),(await M(a,Me,"invalid task status response")).data.status}};var Q=class{constructor(e){this.api=e;}async list(){let e=await this.api.executePublic("/models");if(e.status<200||e.status>=300){let s=await C(e);throw new l({message:`models fetch failed (${e.status}): ${s||"no body"}`,status:e.status})}let n=je.safeParse(await T(e));if(!n.success)throw new l({message:"invalid models response",status:e.status,cause:n.error});return n.data.data}};var Z=class{constructor(e){this.api=e;}async getTask(e){let n=await this.api.execute(`/tasks/${e}`);if(n.status<200||n.status>=300){let a=await C(n);throw new l({message:`task fetch failed (${n.status}): ${a||"no body"}`,status:n.status})}let s=B.safeParse(await T(n));if(!s.success)throw new l({message:"invalid task response",status:n.status,cause:s.error});return s.data.data}};var ee="client_01KATK792RR5ZCHMF5YMNN1ZSE",Fe="https://api.workos.com";var Dt="urn:ietf:params:oauth:grant-type:device_code",Lt="refresh_token",Ut=t=>{try{let e=t.split(".");if(e.length<2)throw new Error("malformed jwt");let n=JSON.parse(Buffer.from(e[1],"base64url").toString("utf8"));if(typeof n.exp!="number")throw new Error("jwt missing exp claim");return n.exp*1e3}catch(e){throw new k({message:"could not decode access token",cause:e})}},ue=async t=>{try{return await t.json()}catch{return {}}},Je=async t=>Ce.catch({}).parse(await ue(t)),ze=async(t,e)=>{let n=await Je(t),s=n.error??n.code;throw new k({message:n.error_description??n.message??e,status:t.status,...s!==void 0?{code:s}:{}})},Ke=async(t,e)=>{let n=Te.safeParse(await ue(t));if(!n.success)throw new k({message:`invalid ${e} response`,status:t.status,cause:n.error});return {token:n.data,expiresAt:Ut(n.data.access_token)}},Ft=async t=>{if(t.status===200)return Ke(t,"token");let e=await Je(t),n=e.error??e.code;switch(n){case "authorization_pending":throw new S({slowDown:false});case "slow_down":throw new S({slowDown:true});case "expired_token":throw new R;case "access_denied":throw new $;default:throw new k({message:e.error_description??e.message??"WorkOS error",status:t.status,...n!==void 0?{code:n}:{}})}},te=class{baseUrl=Fe;async requestDeviceAuthorization(){let e=await this.post("/user_management/authorize/device",new URLSearchParams({client_id:ee}),"device authorize request failed");if(e.status!==200)return ze(e,"device authorize failed");let n=$e.safeParse(await ue(e));if(!n.success)throw new k({message:"invalid device authorize response",status:e.status,cause:n.error});return n.data}async exchangeDeviceCode(e){let n=await this.post("/user_management/authenticate",JSON.stringify({grant_type:Dt,client_id:ee,device_code:e}),"authenticate request failed",{"Content-Type":"application/json"});return Ft(n)}async refresh(e){let n=await this.post("/user_management/authenticate",JSON.stringify({grant_type:Lt,client_id:ee,refresh_token:e}),"refresh request failed",{"Content-Type":"application/json"});return n.status===200?Ke(n,"refresh"):ze(n,"refresh failed")}async post(e,n,s,a={}){try{return await fetch(`${this.baseUrl}${e}`,{method:"POST",body:n,headers:{Accept:"application/json",...a}})}catch(o){throw new k({message:s,cause:o})}}};var We=()=>{let t=Se(),e=new G,n=new te,s=new q(t,e,n),a=new V(t,s);return {auth:s,credentialsStore:e,images:new X(a),models:new Q(a),tasks:new Z(a),workos:n}};var i=(t="")=>{process.stdout.write(`${t}
3
- `);},ne=(t="")=>{process.stderr.write(`${t}
4
- `);};var Jt=t=>new Date(t).toISOString(),Kt=t=>new Promise(e=>setTimeout(e,t)),qe=Ze.green("\u2713"),He=(t,e)=>new f({message:e instanceof Error?`${t}: ${e.message}`:t,cause:e}),Wt=async(t,e,n,s)=>{let a=n;for(;;){if(Date.now()>=s)throw new f({message:"device code expired before approval"});try{return await t.workos.exchangeDeviceCode(e)}catch(o){if(o instanceof S){o.slowDown&&(a+=5e3),await Kt(a);continue}throw o instanceof $?new f({message:"login denied by user"}):o instanceof R?new f({message:"device code expired"}):o instanceof k?new f({message:o.message,cause:o}):o}}},me=t=>{let e=new Command("auth");return e.command("login").description("Authenticate with Mynth using OAuth device login").action(async()=>{if(t.auth.envApiKeySet)throw i(`MYNTH_API_KEY is set in your environment; that takes precedence over login.
5
- Unset it to use OAuth, or just continue using the env API key.`),new f({message:"env api key takes precedence"});let n;try{n=await t.workos.requestDeviceAuthorization();}catch(o){throw He("device authorize",o)}i(""),i(` First copy your one-time code: ${n.user_code}`),i(` Then open: ${n.verification_uri_complete??n.verification_uri}`),i(""),i("Waiting for confirmation...");let s=await Wt(t,n.device_code,(n.interval??5)*1e3,Date.now()+n.expires_in*1e3);try{await t.auth.saveOAuth({accessToken:s.token.access_token,refreshToken:s.token.refresh_token,expiresAt:s.expiresAt,...s.token.user?{user:s.token.user}:{}});}catch(o){throw He("could not save credentials",o)}let a=s.token.user?.email??s.token.user?.id??"unknown user";i(`${qe} Logged in as ${a}`);}),e.command("logout").description("Clear local Mynth credentials").action(async()=>{await t.auth.logout(),i(`${qe} Local credentials cleared`),t.auth.envApiKeySet&&i("Note: MYNTH_API_KEY is still set in your environment and will be used.");}),e.command("status").description("Show current authentication status").action(async()=>{let n=await t.auth.status(),a=await t.credentialsStore.usingKeychain()?"system keychain":`file (${t.credentialsStore.filePath})`;switch(n.kind){case "env":i("Authenticated via env: MYNTH_API_KEY");return;case "none":i("Not authenticated. Run `mynth auth login` or set an API key.");return;case "api_key":i(`Authenticated via stored API key (${a})`);return;case "oauth":{let o=n.user?.email??n.user?.id??"unknown user";i(`Authenticated via OAuth as ${o} (${a})`),i(` access token expires: ${Jt(n.expiresAt)}`);}}}),e.addCommand(se(t)),e},se=t=>new Command("whoami").description("Print the active Mynth identity").action(async()=>{let e=await t.auth.status();switch(e.kind){case "none":throw i("not authenticated"),new f({message:"not authenticated"});case "env":i("env:MYNTH_API_KEY");return;case "api_key":i("api-key");return;case "oauth":i(e.user?.email??e.user?.id??"oauth");}});var Ye=Ze.green("\u2713"),Ht=async()=>{try{let t="";process.stdin.setEncoding("utf8");for await(let e of process.stdin)t+=e;return t.trim()}catch(t){throw new f({message:"could not read stdin",cause:t})}},ge=t=>{let e=new Command("config"),n=new Command("set").description("Set local CLI configuration");n.command("api-key").description("Save a Mynth API key").argument("<value>","API key value, or `-` to read from stdin").action(async a=>{let o=a==="-"?await Ht():a;if(o.length===0)throw new f({message:"API key is empty"});try{await t.auth.setApiKey(o);}catch(c){throw new f({message:`could not save API key: ${c.message}`,cause:c})}i(`${Ye} API key saved`),t.auth.envApiKeySet&&i("Note: MYNTH_API_KEY is also set in your environment and will take precedence.");});let s=new Command("unset").description("Unset local CLI configuration");return s.command("api-key").description("Clear stored Mynth credentials").action(async()=>{await t.auth.logout(),i(`${Ye} Stored credentials cleared`);}),e.addCommand(n),e.addCommand(s),e};var Yt=["Priming the canvas","Summoning pixels","Mixing digital pigments","Whispering to the model","Dreaming up details","Sketching silhouettes","Arranging composition","Weaving light and shadow","Polishing reflections","Sculpting atmosphere","Tracing final strokes"],Gt=()=>typeof process<"u"&&process.stderr&&process.stderr.isTTY===true,Vt=t=>{let e=t.slice();for(let n=e.length-1;n>0;n--){let s=Math.floor(Math.random()*(n+1));[e[n],e[s]]=[e[s],e[n]];}return e},Ge=async(t,e={})=>{if(!Gt())return t;let n=Vt(e.messages??Yt),s=0,a=Bt({text:n[0]??"Working",stream:process.stderr}).start(),o=setInterval(()=>{s++,a.text=n[s%n.length]??"Working";},2800);try{return await t}finally{clearInterval(o),a.stop();}};var he=8,en="webp",tn=80,nn=["auto","init","reference"],b=Ze.green("\u2713"),sn=Ze.red("\u2717"),fe=()=>new Option("--json","Output machine-readable JSON instead of a human-readable summary"),an=z.array(z.object({value:z.string(),description:z.string()})),re=t=>/^https?:\/\//i.test(t),et=(t,e=[])=>[...e,t],tt=t=>{let e=Number.parseInt(t,10);if(!Number.isInteger(e)||String(e)!==t)throw new A(`invalid integer: "${t}"`);return e},rn=t=>{let e=tt(t);if(e<1||e>100)throw new A(`invalid quality: "${t}" (expected 1-100)`);return e},on=t=>{let e=t.indexOf("=");if(e<=0)throw new l({message:`invalid --level "${t}": expected "value=description"`,status:0});let n={value:t.slice(0,e).trim(),description:t.slice(e+1).trim()};if(n.value.length===0||n.description.length===0)throw new l({message:`invalid --level "${t}": value and description must be non-empty`,status:0});return n},Ve=(t,e)=>{let n;try{n=JSON.parse(t);}catch(a){throw new l({message:`invalid JSON in ${e}: ${a.message}`,status:0,cause:a})}let s=an.safeParse(n);if(!s.success)throw new l({message:`invalid levels in ${e}: expected array of { value, description }`,status:0,cause:s.error});return s.data},Xe=async t=>{let e=[t.levelPairs.length>0?"--level":null,t.levelsFile!==void 0?"--levels-file":null,t.levelsJson!==void 0?"--levels-json":null].filter(a=>a!==null);if(e.length===0)return;if(e.length>1)throw new l({message:`conflicting level options: ${e.join(", ")} - use only one`,status:0});let n;if(t.levelPairs.length>0)n=t.levelPairs.map(on);else if(t.levelsFile!==void 0){let a;try{a=await readFile(t.levelsFile,"utf8");}catch(o){throw new l({message:`could not read ${t.levelsFile}: ${o.message}`,status:0,cause:o})}n=Ve(a,t.levelsFile);}else n=Ve(t.levelsJson??"[]","--levels-json");if(n.length<L||n.length>U)throw new l({message:`levels must have between ${L} and ${U} items (got ${n.length})`,status:0});let s=new Set;for(let a of n){if(s.has(a.value))throw new l({message:`duplicate level value: "${a.value}"`,status:0});s.add(a.value);}return n},ln=t=>{let e=t.indexOf(":"),n=/^https?:/i.test(t),s="reference",a=t;if(e>0&&!n){let o=t.slice(0,e);nn.includes(o)&&(s=o,a=t.slice(e+1));}if(a.length===0)throw new l({message:`invalid --input "${t}": missing path or URL`,status:0});return {role:s,value:a,isFile:!re(a)}},cn=t=>{let e;try{e=JSON.parse(t);}catch(n){throw new l({message:`invalid --metadata JSON: ${n.message}`,status:0,cause:n})}if(e===null||typeof e!="object"||Array.isArray(e))throw new l({message:"--metadata must be a JSON object",status:0});return e},Qe=t=>t.option("-l, --level <value>",'Custom rating level as "value=description" (repeatable, 2-7 items). Example: -l safe="No explicit content" -l nsfw="Contains nudity"',et).option("--levels-file <path>",'Path to a JSON file containing an array of { "value": string, "description": string } (2-7 items). Alternative to --level when descriptions contain special characters.').option("--levels-json <json>",'Inline JSON array of { "value": string, "description": string } (2-7 items). Alternative to --level / --levels-file.'),dn=(t,e)=>{let n=t.result??{},s=n.images??[];e>0&&i(`${b} Uploaded ${e} input image${e===1?"":"s"}`);let a=s.filter(o=>o.status==="success");if(i(`${b} Generated ${a.length}/${s.length} image${s.length===1?"":"s"} (task ${t.id})`),n.model!==void 0&&i(` Model: ${n.model}`),n.size_auto?.value!==void 0&&i(` Size: ${n.size_auto.value} (auto, ${n.size_auto.source})`),n.cost?.total!==void 0&&i(` Cost: ${n.cost.total}`),n.destination?.name!==void 0&&i(` Destination: ${n.destination.name}`),n.magic_prompt?.positive!==void 0&&(i(""),i("Enhanced prompt (mynth):"),i(` ${n.magic_prompt.positive}`),n.magic_prompt.negative!==void 0&&n.magic_prompt.negative.length>0&&i(` negative: ${n.magic_prompt.negative}`)),s.length>0){i("");for(let o of s){let c=o;if(c.status==="success"){let h=c.rating,y=h?.level!==void 0?` [${h.level}]`:"",g=c.url??c.mynth_url;i(` ${b} ${g}${y}`);}else i(` ${sn} ${un(c.error)}`);}}},un=t=>{if(typeof t=="string")return t;if(t!==null&&typeof t=="object"){let e=t,n=typeof e.code=="string"?e.code:"unknown error",s=typeof e.message=="string"?e.message:void 0;return s!==void 0?`${n}: ${s}`:n}return "unknown error"},mn=t=>{let e=t.result??{},n=(e.images??[]).map(s=>{let a=s;return a.status==="success"?{status:"success",url:a.url??null,mynth_url:a.mynth_url??null,size:a.size,rating:a.rating}:{status:"failed",error:a.error,mynth_url:a.mynth_url??null}});return {taskId:t.id,status:t.status,images:n,...e.magic_prompt?{magic_prompt:e.magic_prompt}:{},...e.cost?.total!==void 0?{cost:e.cost.total}:{},...e.model!==void 0?{model:e.model}:{}}},pn=async(t,e,n)=>{let a=((e.result??{}).images??[]).map(o=>o).filter(o=>o.status==="success").map(o=>o.url??o.mynth_url).filter(o=>typeof o=="string"&&o.length>0);return a.length===0?[]:t.downloadImages({urls:a,destinationDir:n,taskId:e.id})},we=t=>{let e=new Command("image");e.command("upload").description("Upload local images to Mynth").argument("<files...>","Path to a local image file (.jpg, .jpeg, .png, .webp)").addOption(fe()).action(async(a,o)=>{if(a.length>N)throw new l({message:`too many files: ${a.length} (max ${N})`,status:0});let c=await t.images.upload(a);if(o.json){i(JSON.stringify({images:c},null,2));return}i(`${b} Uploaded ${c.length} image${c.length===1?"":"s"}`);for(let{path:h,url:y}of c)i(` ${h}`),i(` -> ${y}`);});let n=e.command("rate").description("Rate images by URL or local file").argument("<image...>","Image URL (http://, https://) or path to a local image file to upload first").addOption(fe());Qe(n),n.action(async(a,o)=>{if(a.length>D)throw new l({message:`too many images: ${a.length} (max ${D})`,status:0});let c=await Xe({levelPairs:o.level??[],levelsFile:o.levelsFile,levelsJson:o.levelsJson}),h=a.filter(re),y=a.filter(d=>!re(d)),g=y.length>0?await t.images.upload(y):[],F=new Map(g.map(d=>[d.path,d.url])),z=a.map(d=>re(d)?d:F.get(d)??d),x=await t.images.rate({urls:z,...c?{levels:c}:{}});if(o.json){i(JSON.stringify(x,null,2));return}let E=x.results.filter(d=>d.status==="success"),J=x.results.filter(d=>d.status==="failed");g.length>0&&i(`${b} Uploaded ${g.length} image${g.length===1?"":"s"}`),i(`${b} Rated ${E.length}/${x.results.length} (task ${x.task.id})`);for(let d of E)i(` ${d.level} ${d.url}`);for(let d of J)i(` ERROR ${d.error.code} ${d.url}`);if(h.length===0&&g.length>0){i(""),i("Uploaded source files:");for(let d of g)i(` ${d.path} -> ${d.url}`);}});let s=e.command("generate").description("Generate images with Mynth").addHelpText("after",`
6
- Models: mynth models list`);return s.option("-p, --prompt <text>","Text prompt describing the image to generate").option("-n, --negative <text>","Negative prompt (elements to exclude)").addOption(new Option("--enhance <mode>",'Prompt enhancement mode: "prefer_magic" (Mynth) or "none". "prefer_native" is no longer supported by the API.').choices(["prefer_magic","prefer_native","none"])).option("-m, --model <id>",'Model ID (e.g. "black-forest-labs/flux.1-dev"). Default: "auto"').option("-s, --size <size>",'Size preset or aspect ratio: "square", "portrait", "landscape", "1:1", "16:9", "16:9_4k", "auto", etc.').option("-c, --count <number>","Number of images to generate (default: 1)",tt).addOption(new Option("-f, --format <format>","Output image format (default: webp)").choices(["png","jpg","webp"])).option("-q, --quality <number>","Output quality 1-100 (default: 80)",rn).option("-i, --input <value>",`Input image as "[role:]path-or-url" (repeatable, up to ${he}). Role is one of: auto, init, reference (default: reference). Examples: -i ./img.jpg, -i reference:https://example.com/a.png, -i init:./seed.png`,et).option("-o, --output-dir <dir>","Directory to save generated images to. Created if it doesn't exist. Ignored in --async mode since the task hasn't completed yet.").option("--destination <name>","Name (slug) of a user-configured destination to deliver the result to. Falls back to MYNTH_DESTINATION env var if not set.").option("--metadata <json>","Inline JSON object of custom metadata to attach to the task (max 2KB)").option("--content-rating","Enable content rating classification using default sfw/nsfw levels. For custom levels use --level / --levels-file / --levels-json.").option("--async","Return the task ID immediately instead of polling until completion").option("--detailed","Include full task data (all fields) in the output").addOption(fe()),Qe(s),s.action(async a=>{if(a.prompt===void 0||a.prompt.length===0)throw new A("Expected to find option: '--prompt'");if(a.enhance==="prefer_native")throw new l({message:'--enhance prefer_native is no longer supported by the API; use "prefer_magic" or "none"',status:0});let o=a.input??[];if(o.length>he)throw new l({message:`too many --input values: ${o.length} (max ${he})`,status:0});let c=o.map(ln),h=a.metadata!==void 0?cn(a.metadata):void 0,y=await Xe({levelPairs:a.level??[],levelsFile:a.levelsFile,levelsJson:a.levelsJson}),g=c.filter(u=>u.isFile).map(u=>u.value),F=Array.from(new Set(g)),z=F.length>0?await t.images.upload(F):[],x=new Map(z.map(u=>[u.path,u.url])),E=c.map(u=>({type:"image",role:u.role,source:{type:"url",url:u.isFile?x.get(u.value)??u.value:u.value}})),J=a.format!==void 0||a.quality!==void 0?{format:a.format??en,quality:a.quality??tn}:void 0,d=y!==void 0?{mode:"custom",levels:y}:a.contentRating?true:void 0,w={prompt:a.prompt};if(a.model!==void 0&&(w.model=a.model),a.negative!==void 0&&(w.negative_prompt=a.negative),a.enhance==="prefer_magic"&&(w.magic_prompt=true),a.size!==void 0&&(w.size=a.size),a.count!==void 0&&(w.count=a.count),J!==void 0&&(w.output=J),E.length>0&&(w.inputs=E),a.destination!==void 0&&(w.destination=a.destination),d!==void 0&&(w.rating=d),h!==void 0&&(w.metadata=h),a.async){let u=await t.images.generate({request:w,requestPat:true}),oe={taskId:u.taskId,...u.pat!==void 0?{access:{publicAccessToken:u.pat}}:{}};if(a.json){i(JSON.stringify(oe,null,2));return}i(`${b} Task created: ${u.taskId}`),u.pat!==void 0&&i(` PAT: ${u.pat}`);return}let be=await t.images.generate({request:w,requestPat:true}),xe=t.images.waitForTask(be.taskId,be.pat),K=a.json?await xe:await Ge(xe),P=a.outputDir!==void 0?resolve(a.outputDir):void 0,O=P!==void 0?await pn(t.images,K,P):[];if(a.json){let u=a.detailed?K:mn(K),oe=P!==void 0?{...u,downloadedFiles:O}:u;i(JSON.stringify(oe,null,2));return}if(dn(K,z.length),P!==void 0&&O.length>0){i(""),i(`${b} Saved ${O.length} image${O.length===1?"":"s"} to ${P}`);for(let u of O)i(` ${u}`);}}),e};var ve=t=>t??"-",hn=t=>{if(t.length===0){i("No models available.");return}let e=t.map(s=>({id:s.id,name:s.displayName??"-",base:ve(s.pricing?.perImage.base),fourK:ve(s.pricing?.perImage["4k"]),inputFee:ve(s.pricing?.inputFee)})),n={id:Math.max(2,...e.map(s=>s.id.length)),name:Math.max(4,...e.map(s=>s.name.length)),base:Math.max(4,...e.map(s=>s.base.length)),fourK:Math.max(2,...e.map(s=>s.fourK.length)),inputFee:Math.max(9,...e.map(s=>s.inputFee.length))};i(["ID".padEnd(n.id),"Name".padEnd(n.name),"Base".padEnd(n.base),"4K".padEnd(n.fourK),"Input fee".padEnd(n.inputFee)].join(" "));for(let s of e)i([s.id.padEnd(n.id),s.name.padEnd(n.name),s.base.padEnd(n.base),s.fourK.padEnd(n.fourK),s.inputFee.padEnd(n.inputFee)].join(" "));},ke=t=>{let e=new Command("models").description("Browse the public Mynth model catalog");return e.command("list").description("List available image generation models").option("--json","Output machine-readable JSON instead of a human-readable table").action(async n=>{let s=await t.models.list();if(n.json){i(JSON.stringify(s,null,2));return}hn(s);}),e};var yn=t=>{switch(t){case "completed":return "\u2713";case "failed":return "\u2717";default:return "\u2026"}},wn=(t,e)=>{let n=" ".repeat(e);return t.split(`
2
+ import {Command,Option,Help,InvalidArgumentError}from'commander';import*as _ from'cross-keychain';import {readFile,mkdir,writeFile,chmod,rm,stat}from'fs/promises';import {homedir}from'os';import {resolve,join,extname,basename}from'path';import {z as z$1}from'zod';import tt from'chalk';import Gt from'ora';var f=class extends Error{_tag="MynthCliError";cause;constructor(e){super(e.message),this.name=this._tag,this.cause=e.cause;}},x=class extends Error{_tag="CliUsageError";constructor(e){super(e),this.name=this._tag;}},O=class extends Error{_tag="NotAuthenticatedError";constructor(e={}){super(e.reason??"not authenticated"),this.name=this._tag;}},v=class extends Error{_tag="CredentialsStoreError";cause;constructor(e){super(e.message),this.name=this._tag,this.cause=e.cause;}},k=class extends Error{_tag="WorkOSError";code;status;cause;constructor(e){super(e.message),this.name=this._tag,this.code=e.code,this.status=e.status,this.cause=e.cause;}},S=class extends Error{_tag="AuthorizationPendingError";slowDown;constructor(e){super("authorization pending"),this.name=this._tag,this.slowDown=e.slowDown;}},R=class extends Error{_tag="AuthorizationExpiredError";constructor(){super("authorization expired"),this.name=this._tag;}},$=class extends Error{_tag="AuthorizationDeniedError";constructor(){super("authorization denied"),this.name=this._tag;}},l=class extends Error{_tag="MynthApiError";status;code;cause;constructor(e){super(e.message),this.name=this._tag,this.status=e.status,this.code=e.code,this.cause=e.cause;}};var ot=6e4,z=t=>t?{user:t}:{},ie=(t,e)=>new O({reason:e instanceof Error?`${t}: ${e.message}`:t}),W=class{constructor(e,n,s){this.config=e;this.store=n;this.workos=s;this.envApiKey=e.apiKeyEnvOverride,this.envApiKeySet=this.envApiKey!==void 0&&this.envApiKey.length>0;}envApiKeySet;envApiKey;async resolve(){if(this.envApiKeySet)return {kind:"api_key",apiKey:this.envApiKey,source:"env"};let e;try{e=await this.store.get();}catch(s){throw ie("could not read credentials",s)}if(e===void 0)throw new O({reason:"no credentials configured"});if(e.kind==="api_key")return {kind:"api_key",apiKey:e.api_key,source:"stored"};let n=await this.refreshIfNeeded(e);return {kind:"oauth",accessToken:n.access_token,...z(n.user)}}async status(){if(this.envApiKeySet)return {kind:"env",source:"MYNTH_API_KEY"};let e;try{e=await this.store.get();}catch{e=void 0;}return e===void 0?{kind:"none"}:e.kind==="api_key"?{kind:"api_key"}:{kind:"oauth",expiresAt:e.expires_at,...z(e.user)}}async setApiKey(e){await this.store.set({kind:"api_key",api_key:e});}async saveOAuth(e){await this.store.set({kind:"oauth",access_token:e.accessToken,refresh_token:e.refreshToken,expires_at:e.expiresAt,...z(e.user)});}async logout(){await this.store.clear();}async refreshIfNeeded(e){if(e.expires_at-Date.now()>ot)return e;let n;try{n=await this.workos.refresh(e.refresh_token);}catch(a){throw ie("token refresh failed",a)}let s={kind:"oauth",access_token:n.token.access_token,refresh_token:n.token.refresh_token,expires_at:n.expiresAt,...z(n.token.user??e.user)};try{await this.store.set(s);}catch(a){throw ie("could not persist refreshed token",a)}return s}};var $e=()=>{let t=process.env.MYNTH_API_KEY;return {mynthApiUrl:process.env.MYNTH_API_URL??"https://api.mynth.io",...t!==void 0?{apiKeyEnvOverride:t}:{}}};var Te=z$1.object({id:z$1.string(),email:z$1.string(),first_name:z$1.string().nullable().optional(),last_name:z$1.string().nullable().optional()}),Ce=z$1.object({device_code:z$1.string(),user_code:z$1.string(),verification_uri:z$1.string(),verification_uri_complete:z$1.string().optional(),expires_in:z$1.number(),interval:z$1.number().optional()}),Ee=z$1.object({access_token:z$1.string(),refresh_token:z$1.string(),user:Te.optional(),organization_id:z$1.string().optional()}),Pe=z$1.object({error:z$1.string().optional(),error_description:z$1.string().optional(),message:z$1.string().optional(),code:z$1.string().optional()}),it=z$1.object({kind:z$1.literal("oauth"),access_token:z$1.string(),refresh_token:z$1.string(),expires_at:z$1.number(),user:Te.optional()}),lt=z$1.object({kind:z$1.literal("api_key"),api_key:z$1.string()}),Oe=z$1.union([it,lt]),q=z$1.lazy(()=>z$1.union([z$1.string(),z$1.number(),z$1.boolean(),z$1.null(),z$1.array(q),z$1.record(q)])),Ie=z$1.object({data:z$1.object({urls:z$1.array(z$1.string())})}),ct=z$1.union([z$1.object({status:z$1.literal("success"),url:z$1.string(),level:z$1.string()}),z$1.object({status:z$1.literal("failed"),url:z$1.string(),error:z$1.object({code:z$1.string()})})]),je=z$1.object({data:z$1.object({task:z$1.object({id:z$1.string(),status:z$1.literal("completed"),cost:z$1.string()}),results:z$1.array(ct)})}),Me=z$1.object({data:z$1.object({taskId:z$1.string(),access:z$1.object({publicAccessToken:z$1.string()}).optional()})}),Ne=z$1.object({data:z$1.object({status:z$1.union([z$1.literal("pending"),z$1.literal("completed"),z$1.literal("failed")])})}),dt=z$1.object({id:z$1.string(),type:z$1.union([z$1.literal("image.generate"),z$1.literal("image.rate")]),status:z$1.union([z$1.literal("pending"),z$1.literal("completed"),z$1.literal("failed")]),userId:z$1.string(),apiKeyId:z$1.string().nullable(),cost:z$1.string().nullable(),request:q,result:q,errors:z$1.array(z$1.object({code:z$1.string()})).nullable().optional(),createdAt:z$1.string(),updatedAt:z$1.string()}),H=z$1.object({data:dt}),ut=z$1.object({perImage:z$1.object({base:z$1.string(),"4k":z$1.string().optional()}),perInput:z$1.string().optional()}),pt=z$1.object({id:z$1.string(),displayName:z$1.string().nullable(),pricing:ut.nullable()}),De=z$1.object({data:z$1.array(pt)});var le="mynth-cli",ce="default",kt="credentials.json",At=t=>{let e=t?.name;return e==="NoKeyringError"||e==="InitError"},B=async(t,e)=>{try{return {available:true,value:await t()}}catch(n){if(At(n))return {available:false};throw new v({message:e,cause:n})}},Le=t=>{let e;try{e=JSON.parse(t);}catch(s){throw new v({message:"credentials JSON parse failed",cause:s})}let n=Oe.safeParse(e);if(!n.success)throw new v({message:"credentials shape invalid",cause:n.error});return n.data},Ue=t=>JSON.stringify(t),_t=()=>{let t=process.env.XDG_CONFIG_HOME,e=t&&t.length>0?t:join(homedir(),".config");return join(e,"mynth")},Fe=async t=>{try{return await stat(t),true}catch{return false}},Y=class{filePath;dir;constructor(){this.dir=_t(),this.filePath=join(this.dir,kt);}async get(){let e=await B(()=>_.getPassword(le,ce),"keychain get failed");if(e.available)return e.value===null?void 0:Le(e.value);if(await Fe(this.filePath))try{return Le(await readFile(this.filePath,"utf8"))}catch(n){throw n instanceof v?n:new v({message:"read credentials file failed",cause:n})}}async set(e){if((await B(()=>_.setPassword(le,ce,Ue(e)),"keychain set failed")).available){await this.deleteFileSilently();return}await mkdir(this.dir,{recursive:true}).catch(s=>{throw new v({message:"create config dir failed",cause:s})}),await writeFile(this.filePath,Ue(e),"utf8").catch(s=>{throw new v({message:"write credentials file failed",cause:s})}),await chmod(this.filePath,384).catch(()=>{});}async clear(){await B(()=>_.deletePassword(le,ce),"keychain delete failed").catch(()=>{}),await this.deleteFileSilently();}async usingKeychain(){let e=await B(()=>_.getKeyring(),"keychain probe failed");return e.available&&e.value!==null}async deleteFileSilently(){await Fe(this.filePath)&&await rm(this.filePath).catch(e=>{throw new v({message:"delete credentials file failed",cause:e})});}};var bt=t=>t.kind==="api_key"?t.apiKey:t.accessToken,T=async t=>{try{return await t.json()}catch(e){throw new l({message:`invalid JSON response: ${e.message}`,status:t.status,cause:e})}},C=async t=>{try{return await t.text()}catch{return ""}},G=class{constructor(e,n){this.auth=n;this.baseUrl=e.mynthApiUrl;}baseUrl;cachedAuth;async execute(e,n={}){let s=await this.attempt(e,n,false);return s.status!==401?s:this.attempt(e,n,true)}async executePublic(e,n={}){try{return await fetch(`${this.baseUrl}${e}`,n)}catch(s){throw new l({message:`request failed: ${s.message}`,status:0,cause:s})}}async attempt(e,n,s){let a=await this.getAuth(s),o=new Headers(n.headers);o.set("Authorization",`Bearer ${bt(a)}`);try{return await fetch(`${this.baseUrl}${e}`,{...n,headers:o})}catch(c){throw new l({message:`request failed: ${c.message}`,status:0,cause:c})}}async getAuth(e){return e&&(this.cachedAuth=void 0),this.cachedAuth!==void 0?this.cachedAuth:(this.cachedAuth=await this.auth.resolve(),this.cachedAuth)}};var M=10,N=10,D=2,L=7,Je=300*1e3,Pt=12e3,Ot=2500,It=5e3,jt={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".webp":"image/webp"},Mt=t=>new Promise(e=>setTimeout(e,t)),Nt=(t,e,n)=>{try{let a=new URL(t).pathname.split("/").filter(Boolean).pop();if(a&&a.length>0)return decodeURIComponent(a)}catch{}return `${e}-${n}`},Dt=async t=>{let e=extname(t).toLowerCase(),n=jt[e];if(!n)throw new l({message:`unsupported image extension "${e}" for ${t} (allowed: .jpg, .jpeg, .png, .webp)`,status:0});let s;try{s=await readFile(t);}catch(o){throw new l({message:`could not read ${t}: ${o.message}`,status:0,cause:o})}let a=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);return new File([new Uint8Array(a)],basename(t),{type:n})},I=async(t,e,n)=>{let s=e.safeParse(await T(t));if(!s.success)throw new l({message:n,status:t.status,cause:s.error});return s.data},j=async(t,e,n)=>{if(t.status>=200&&t.status<300)return;let s=await C(t);throw new l({message:`${e} failed (${t.status}): ${s||"no body"}`,status:t.status})},Lt=async(t,e,n)=>{let s=Array.from({length:t.length}),a=0,o=async()=>{for(;;){let c=a++,h=t[c];if(h===void 0)return;s[c]=await n(h,c);}};return await Promise.all(Array.from({length:Math.min(e,t.length)},o)),s},V=class{constructor(e){this.api=e;}async upload(e){if(e.length===0)throw new l({message:"no files to upload",status:0});if(e.length>M)throw new l({message:`too many files: ${e.length} (max ${M})`,status:0});let n=await Promise.all(e.map(Dt)),s=new FormData;for(let c of n)s.append("images",c);let a=await this.api.execute("/image/upload",{method:"POST",body:s});await j(a,"upload");let o=await I(a,Ie,"invalid upload response");return e.map((c,h)=>({path:c,url:o.data.urls[h]}))}async rate(e){if(e.urls.length===0)throw new l({message:"no image URLs to rate",status:0});if(e.urls.length>N)throw new l({message:`too many images: ${e.urls.length} (max ${N})`,status:0});if(e.levels!==void 0&&(e.levels.length<D||e.levels.length>L))throw new l({message:`levels must have between ${D} and ${L} items (got ${e.levels.length})`,status:0});let n=e.levels!==void 0?{urls:e.urls,mode:"custom",levels:e.levels}:{urls:e.urls,mode:"nsfw_sfw"},s=await this.api.execute("/image/rate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});return await j(s,"rate"),(await I(s,je,"invalid rate response")).data}async generate(e){let n=e.requestPat?{...e.request,access:{...e.request.access,pat:{enabled:true}}}:e.request,s=await this.api.execute("/image/generate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});await j(s,"generate");let a=await I(s,Me,"invalid generate response"),o=a.data.access?.publicAccessToken;return {taskId:a.data.taskId,...o!==void 0?{pat:o}:{}}}async waitForTask(e,n){let s=Date.now();for(;;){let a=Date.now()-s;if(a>=Je)throw new l({message:`task ${e} polling timed out after ${Je}ms`,status:0});let o=await this.getTaskStatus(e,n);if(o==="completed")return this.getTaskDetails(e);if(o==="failed")throw new l({message:`task ${e} failed during generation`,status:0});let c=a<Pt?Ot:It;await Mt(c+Math.floor(Math.random()*500));}}async getTaskDetails(e){let n=await this.api.execute(`/tasks/${e}`);return await j(n,"task details"),(await I(n,H,"invalid task details response")).data}async downloadImages(e){let n=resolve(e.destinationDir);try{await mkdir(n,{recursive:true});}catch(s){throw new l({message:`could not create output directory ${n}: ${s.message}`,status:0,cause:s})}return Lt(e.urls,4,async(s,a)=>{let o;try{o=await fetch(s);}catch(g){throw new l({message:`download failed for ${s}: ${g.message}`,status:0,cause:g})}if(o.status<200||o.status>=300)throw new l({message:`download failed for ${s} (${o.status})`,status:o.status});let c;try{c=await o.arrayBuffer();}catch(g){throw new l({message:`could not read body for ${s}: ${g.message}`,status:o.status,cause:g})}let h=Nt(s,e.taskId,a),y=join(n,h);try{await writeFile(y,new Uint8Array(c));}catch(g){throw new l({message:`could not write ${y}: ${g.message}`,status:0,cause:g})}return y})}async getTaskStatus(e,n){let s=`/tasks/${e}/status`,a;if(n!==void 0)try{a=await fetch(`${this.api.baseUrl}${s}`,{headers:{Authorization:`Bearer ${n}`}});}catch(c){throw new l({message:`task status request failed: ${c.message}`,status:0,cause:c})}else a=await this.api.execute(s);return await j(a,"task status"),(await I(a,Ne,"invalid task status response")).data.status}};var X=class{constructor(e){this.api=e;}async list(){let e=await this.api.executePublic("/models");if(e.status<200||e.status>=300){let s=await C(e);throw new l({message:`models fetch failed (${e.status}): ${s||"no body"}`,status:e.status})}let n=De.safeParse(await T(e));if(!n.success)throw new l({message:"invalid models response",status:e.status,cause:n.error});return n.data.data}};var Q=class{constructor(e){this.api=e;}async getTask(e){let n=await this.api.execute(`/tasks/${e}`);if(n.status<200||n.status>=300){let a=await C(n);throw new l({message:`task fetch failed (${n.status}): ${a||"no body"}`,status:n.status})}let s=H.safeParse(await T(n));if(!s.success)throw new l({message:"invalid task response",status:n.status,cause:s.error});return s.data.data}};var Z="client_01KATK792RR5ZCHMF5YMNN1ZSE",Ke="https://api.workos.com";var Ut="urn:ietf:params:oauth:grant-type:device_code",Ft="refresh_token",Jt=t=>{try{let e=t.split(".");if(e.length<2)throw new Error("malformed jwt");let n=JSON.parse(Buffer.from(e[1],"base64url").toString("utf8"));if(typeof n.exp!="number")throw new Error("jwt missing exp claim");return n.exp*1e3}catch(e){throw new k({message:"could not decode access token",cause:e})}},ue=async t=>{try{return await t.json()}catch{return {}}},We=async t=>Pe.catch({}).parse(await ue(t)),ze=async(t,e)=>{let n=await We(t),s=n.error??n.code;throw new k({message:n.error_description??n.message??e,status:t.status,...s!==void 0?{code:s}:{}})},qe=async(t,e)=>{let n=Ee.safeParse(await ue(t));if(!n.success)throw new k({message:`invalid ${e} response`,status:t.status,cause:n.error});return {token:n.data,expiresAt:Jt(n.data.access_token)}},Kt=async t=>{if(t.status===200)return qe(t,"token");let e=await We(t),n=e.error??e.code;switch(n){case "authorization_pending":throw new S({slowDown:false});case "slow_down":throw new S({slowDown:true});case "expired_token":throw new R;case "access_denied":throw new $;default:throw new k({message:e.error_description??e.message??"WorkOS error",status:t.status,...n!==void 0?{code:n}:{}})}},ee=class{baseUrl=Ke;async requestDeviceAuthorization(){let e=await this.post("/user_management/authorize/device",new URLSearchParams({client_id:Z}),"device authorize request failed");if(e.status!==200)return ze(e,"device authorize failed");let n=Ce.safeParse(await ue(e));if(!n.success)throw new k({message:"invalid device authorize response",status:e.status,cause:n.error});return n.data}async exchangeDeviceCode(e){let n=await this.post("/user_management/authenticate",JSON.stringify({grant_type:Ut,client_id:Z,device_code:e}),"authenticate request failed",{"Content-Type":"application/json"});return Kt(n)}async refresh(e){let n=await this.post("/user_management/authenticate",JSON.stringify({grant_type:Ft,client_id:Z,refresh_token:e}),"refresh request failed",{"Content-Type":"application/json"});return n.status===200?qe(n,"refresh"):ze(n,"refresh failed")}async post(e,n,s,a={}){try{return await fetch(`${this.baseUrl}${e}`,{method:"POST",body:n,headers:{Accept:"application/json",...a}})}catch(o){throw new k({message:s,cause:o})}}};var He=()=>{let t=$e(),e=new Y,n=new ee,s=new W(t,e,n),a=new G(t,s);return {auth:s,credentialsStore:e,images:new V(a),models:new X(a),tasks:new Q(a),workos:n}};var i=(t="")=>{process.stdout.write(`${t}
3
+ `);},te=(t="")=>{process.stderr.write(`${t}
4
+ `);};var Wt=t=>new Date(t).toISOString(),qt=t=>new Promise(e=>setTimeout(e,t)),Be=tt.green("\u2713"),Ye=(t,e)=>new f({message:e instanceof Error?`${t}: ${e.message}`:t,cause:e}),Ht=async(t,e,n,s)=>{let a=n;for(;;){if(Date.now()>=s)throw new f({message:"device code expired before approval"});try{return await t.workos.exchangeDeviceCode(e)}catch(o){if(o instanceof S){o.slowDown&&(a+=5e3),await qt(a);continue}throw o instanceof $?new f({message:"login denied by user"}):o instanceof R?new f({message:"device code expired"}):o instanceof k?new f({message:o.message,cause:o}):o}}},pe=t=>{let e=new Command("auth");return e.command("login").description("Authenticate with Mynth using OAuth device login").action(async()=>{if(t.auth.envApiKeySet)throw i(`MYNTH_API_KEY is set in your environment; that takes precedence over login.
5
+ Unset it to use OAuth, or just continue using the env API key.`),new f({message:"env api key takes precedence"});let n;try{n=await t.workos.requestDeviceAuthorization();}catch(o){throw Ye("device authorize",o)}i(""),i(` First copy your one-time code: ${n.user_code}`),i(` Then open: ${n.verification_uri_complete??n.verification_uri}`),i(""),i("Waiting for confirmation...");let s=await Ht(t,n.device_code,(n.interval??5)*1e3,Date.now()+n.expires_in*1e3);try{await t.auth.saveOAuth({accessToken:s.token.access_token,refreshToken:s.token.refresh_token,expiresAt:s.expiresAt,...s.token.user?{user:s.token.user}:{}});}catch(o){throw Ye("could not save credentials",o)}let a=s.token.user?.email??s.token.user?.id??"unknown user";i(`${Be} Logged in as ${a}`);}),e.command("logout").description("Clear local Mynth credentials").action(async()=>{await t.auth.logout(),i(`${Be} Local credentials cleared`),t.auth.envApiKeySet&&i("Note: MYNTH_API_KEY is still set in your environment and will be used.");}),e.command("status").description("Show current authentication status").action(async()=>{let n=await t.auth.status(),a=await t.credentialsStore.usingKeychain()?"system keychain":`file (${t.credentialsStore.filePath})`;switch(n.kind){case "env":i("Authenticated via env: MYNTH_API_KEY");return;case "none":i("Not authenticated. Run `mynth auth login` or set an API key.");return;case "api_key":i(`Authenticated via stored API key (${a})`);return;case "oauth":{let o=n.user?.email??n.user?.id??"unknown user";i(`Authenticated via OAuth as ${o} (${a})`),i(` access token expires: ${Wt(n.expiresAt)}`);}}}),e.addCommand(ne(t)),e},ne=t=>new Command("whoami").description("Print the active Mynth identity").action(async()=>{let e=await t.auth.status();switch(e.kind){case "none":throw i("not authenticated"),new f({message:"not authenticated"});case "env":i("env:MYNTH_API_KEY");return;case "api_key":i("api-key");return;case "oauth":i(e.user?.email??e.user?.id??"oauth");}});var Ve=tt.green("\u2713"),Yt=async()=>{try{let t="";process.stdin.setEncoding("utf8");for await(let e of process.stdin)t+=e;return t.trim()}catch(t){throw new f({message:"could not read stdin",cause:t})}},ge=t=>{let e=new Command("config"),n=new Command("set").description("Set local CLI configuration");n.command("api-key").description("Save a Mynth API key").argument("<value>","API key value, or `-` to read from stdin").action(async a=>{let o=a==="-"?await Yt():a;if(o.length===0)throw new f({message:"API key is empty"});try{await t.auth.setApiKey(o);}catch(c){throw new f({message:`could not save API key: ${c.message}`,cause:c})}i(`${Ve} API key saved`),t.auth.envApiKeySet&&i("Note: MYNTH_API_KEY is also set in your environment and will take precedence.");});let s=new Command("unset").description("Unset local CLI configuration");return s.command("api-key").description("Clear stored Mynth credentials").action(async()=>{await t.auth.logout(),i(`${Ve} Stored credentials cleared`);}),e.addCommand(n),e.addCommand(s),e};var Vt=["Priming the canvas","Summoning pixels","Mixing digital pigments","Whispering to the model","Dreaming up details","Sketching silhouettes","Arranging composition","Weaving light and shadow","Polishing reflections","Sculpting atmosphere","Tracing final strokes"],Xt=()=>typeof process<"u"&&process.stderr&&process.stderr.isTTY===true,Qt=t=>{let e=t.slice();for(let n=e.length-1;n>0;n--){let s=Math.floor(Math.random()*(n+1));[e[n],e[s]]=[e[s],e[n]];}return e},Xe=async(t,e={})=>{if(!Xt())return t;let n=Qt(e.messages??Vt),s=0,a=Gt({text:n[0]??"Working",stream:process.stderr}).start(),o=setInterval(()=>{s++,a.text=n[s%n.length]??"Working";},2800);try{return await t}finally{clearInterval(o),a.stop();}};var he=20,nn="webp",sn=80,we=["auto","person","garment","pose","style","background","product","object","character"],b=tt.green("\u2713"),an=tt.red("\u2717"),fe=()=>new Option("--json","Output machine-readable JSON instead of a human-readable summary"),rn=z$1.array(z$1.object({value:z$1.string(),description:z$1.string()})),ae=t=>/^https?:\/\//i.test(t),nt=(t,e=[])=>[...e,t],st=t=>{let e=Number.parseInt(t,10);if(!Number.isInteger(e)||String(e)!==t)throw new x(`invalid integer: "${t}"`);return e},on=t=>{let e=st(t);if(e<1||e>100)throw new x(`invalid quality: "${t}" (expected 1-100)`);return e},ln=t=>{let e=t.indexOf("=");if(e<=0)throw new l({message:`invalid --level "${t}": expected "value=description"`,status:0});let n={value:t.slice(0,e).trim(),description:t.slice(e+1).trim()};if(n.value.length===0||n.description.length===0)throw new l({message:`invalid --level "${t}": value and description must be non-empty`,status:0});return n},Qe=(t,e)=>{let n;try{n=JSON.parse(t);}catch(a){throw new l({message:`invalid JSON in ${e}: ${a.message}`,status:0,cause:a})}let s=rn.safeParse(n);if(!s.success)throw new l({message:`invalid levels in ${e}: expected array of { value, description }`,status:0,cause:s.error});return s.data},Ze=async t=>{let e=[t.levelPairs.length>0?"--level":null,t.levelsFile!==void 0?"--levels-file":null,t.levelsJson!==void 0?"--levels-json":null].filter(a=>a!==null);if(e.length===0)return;if(e.length>1)throw new l({message:`conflicting level options: ${e.join(", ")} - use only one`,status:0});let n;if(t.levelPairs.length>0)n=t.levelPairs.map(ln);else if(t.levelsFile!==void 0){let a;try{a=await readFile(t.levelsFile,"utf8");}catch(o){throw new l({message:`could not read ${t.levelsFile}: ${o.message}`,status:0,cause:o})}n=Qe(a,t.levelsFile);}else n=Qe(t.levelsJson??"[]","--levels-json");if(n.length<D||n.length>L)throw new l({message:`levels must have between ${D} and ${L} items (got ${n.length})`,status:0});let s=new Set;for(let a of n){if(s.has(a.value))throw new l({message:`duplicate level value: "${a.value}"`,status:0});s.add(a.value);}return n},cn=t=>{let e=t.indexOf(":"),n=/^https?:/i.test(t),s,a=t;if(e>0&&!n){let o=t.slice(0,e);if(!we.includes(o))throw new l({message:`invalid --input as "${o}". Expected one of: ${we.join(", ")}`,status:0});s=o,a=t.slice(e+1);}if(a.length===0)throw new l({message:`invalid --input "${t}": missing path or URL`,status:0});return {...s!==void 0?{as:s}:{},value:a,isFile:!ae(a)}},dn=t=>{let e;try{e=JSON.parse(t);}catch(n){throw new l({message:`invalid --metadata JSON: ${n.message}`,status:0,cause:n})}if(e===null||typeof e!="object"||Array.isArray(e))throw new l({message:"--metadata must be a JSON object",status:0});return e},et=t=>t.option("-l, --level <value>",'Custom rating level as "value=description" (repeatable, 2-7 items). Example: -l safe="No explicit content" -l nsfw="Contains nudity"',nt).option("--levels-file <path>",'Path to a JSON file containing an array of { "value": string, "description": string } (2-7 items). Alternative to --level when descriptions contain special characters.').option("--levels-json <json>",'Inline JSON array of { "value": string, "description": string } (2-7 items). Alternative to --level / --levels-file.'),un=(t,e)=>{let n=t.result??{},s=n.images??[];e>0&&i(`${b} Uploaded ${e} input image${e===1?"":"s"}`);let a=s.filter(o=>o.status==="success");if(i(`${b} Generated ${a.length}/${s.length} image${s.length===1?"":"s"} (task ${t.id})`),n.model!==void 0&&i(` Model: ${n.model}`),t.cost!==null&&i(` Cost: ${t.cost}`),n.magic_prompt?.positive!==void 0&&(i(""),i("Enhanced prompt (mynth):"),i(` ${n.magic_prompt.positive}`),n.magic_prompt.negative!==void 0&&n.magic_prompt.negative.length>0&&i(` negative: ${n.magic_prompt.negative}`)),s.length>0){i("");for(let o of s){let c=o;if(c.status==="success"){let h=c.rating,y=h?.level!==void 0?` [${h.level}]`:"",g=c.url??c.mynth_url;i(` ${b} ${g}${y}`);}else i(` ${an} ${pn(c.error)}`);}}},pn=t=>{if(typeof t=="string")return t;if(t!==null&&typeof t=="object"){let e=t,n=typeof e.code=="string"?e.code:"unknown error",s=typeof e.message=="string"?e.message:void 0;return s!==void 0?`${n}: ${s}`:n}return "unknown error"},mn=t=>{let e=t.result??{},n=(e.images??[]).map(s=>{let a=s;return a.status==="success"?{status:"success",url:a.url??null,mynth_url:a.mynth_url??null,size:a.size,rating:a.rating}:{status:"failed",error:a.error,mynth_url:a.mynth_url??null}});return {taskId:t.id,status:t.status,images:n,...e.magic_prompt?{magic_prompt:e.magic_prompt}:{},...t.cost!==null?{cost:t.cost}:{},...e.model!==void 0?{model:e.model}:{}}},gn=async(t,e,n)=>{let a=((e.result??{}).images??[]).map(o=>o).filter(o=>o.status==="success").map(o=>o.url??o.mynth_url).filter(o=>typeof o=="string"&&o.length>0);return a.length===0?[]:t.downloadImages({urls:a,destinationDir:n,taskId:e.id})},ve=t=>{let e=new Command("image");e.command("upload").description("Upload local images to Mynth").argument("<files...>","Path to a local image file (.jpg, .jpeg, .png, .webp)").addOption(fe()).action(async(a,o)=>{if(a.length>M)throw new l({message:`too many files: ${a.length} (max ${M})`,status:0});let c=await t.images.upload(a);if(o.json){i(JSON.stringify({images:c},null,2));return}i(`${b} Uploaded ${c.length} image${c.length===1?"":"s"}`);for(let{path:h,url:y}of c)i(` ${h}`),i(` -> ${y}`);});let n=e.command("rate").description("Rate images by URL or local file").argument("<image...>","Image URL (http://, https://) or path to a local image file to upload first").addOption(fe());et(n),n.action(async(a,o)=>{if(a.length>N)throw new l({message:`too many images: ${a.length} (max ${N})`,status:0});let c=await Ze({levelPairs:o.level??[],levelsFile:o.levelsFile,levelsJson:o.levelsJson}),h=a.filter(ae),y=a.filter(d=>!ae(d)),g=y.length>0?await t.images.upload(y):[],re=new Map(g.map(d=>[d.path,d.url])),U=a.map(d=>ae(d)?d:re.get(d)??d),A=await t.images.rate({urls:U,...c?{levels:c}:{}});if(o.json){i(JSON.stringify(A,null,2));return}let F=A.results.filter(d=>d.status==="success"),J=A.results.filter(d=>d.status==="failed");g.length>0&&i(`${b} Uploaded ${g.length} image${g.length===1?"":"s"}`),i(`${b} Rated ${F.length}/${A.results.length} (task ${A.task.id})`);for(let d of F)i(` ${d.level} ${d.url}`);for(let d of J)i(` ERROR ${d.error.code} ${d.url}`);if(h.length===0&&g.length>0){i(""),i("Uploaded source files:");for(let d of g)i(` ${d.path} -> ${d.url}`);}});let s=e.command("generate").description("Generate images with Mynth").addHelpText("after",`
6
+ Models: mynth models list`);return s.option("-p, --prompt <text>","Text prompt describing the image to generate").option("-n, --negative <text>","Negative prompt (elements to exclude)").addOption(new Option("--enhance <mode>",'Prompt enhancement mode: "prefer_magic" (Mynth) or "none". "prefer_native" is no longer supported by the API.').choices(["prefer_magic","prefer_native","none"])).option("-m, --model <id>",'Model ID (e.g. "black-forest-labs/flux.1-dev"). Default: "auto"').option("-s, --size <size>",'Size preset or aspect ratio: "square", "portrait", "landscape", "1:1", "16:9", "16:9_4k", "auto", etc.').option("-c, --count <number>","Number of images to generate (default: 1)",st).addOption(new Option("-f, --format <format>","Output image format (default: webp)").choices(["png","jpg","webp"])).option("-q, --quality <number>","Output quality 1-100 (default: 80)",on).option("-i, --input <value>",`Input image as "[as:]path-or-url" (repeatable, up to ${he}). as is optional and must be one of: ${we.join(", ")}. Examples: -i ./img.jpg, -i product:https://example.com/a.png, -i pose:./seed.png`,nt).option("-o, --output-dir <dir>","Directory to save generated images to. Created if it doesn't exist. Ignored in --async mode since the task hasn't completed yet.").option("--destination <name>","Name (slug) of a user-configured destination to deliver the result to. Falls back to MYNTH_DESTINATION env var if not set.").option("--metadata <json>","Inline JSON object of custom metadata to attach to the task (max 2KB)").option("--content-rating","Enable content rating classification using default sfw/nsfw levels. For custom levels use --level / --levels-file / --levels-json.").option("--async","Return the task ID immediately instead of polling until completion").option("--detailed","Include full task data (all fields) in the output").addOption(fe()),et(s),s.action(async a=>{let o=a.prompt??"";if(a.enhance==="prefer_native")throw new l({message:'--enhance prefer_native is no longer supported by the API; use "prefer_magic" or "none"',status:0});let c=a.input??[];if(c.length>he)throw new l({message:`too many --input values: ${c.length} (max ${he})`,status:0});let h=c.map(cn),y=a.metadata!==void 0?dn(a.metadata):void 0,g=await Ze({levelPairs:a.level??[],levelsFile:a.levelsFile,levelsJson:a.levelsJson}),re=h.filter(u=>u.isFile).map(u=>u.value),U=Array.from(new Set(re)),A=U.length>0?await t.images.upload(U):[],F=new Map(A.map(u=>[u.path,u.url])),J=h.map(u=>({type:"image",...u.as?{as:u.as}:{},source:{type:"url",url:u.isFile?F.get(u.value)??u.value:u.value}})),d=a.format!==void 0||a.quality!==void 0?{format:a.format??nn,quality:a.quality??sn}:void 0,xe=g!==void 0?{mode:"custom",levels:g}:a.contentRating?true:void 0,w={prompt:o};if(a.model!==void 0&&(w.model=a.model),a.negative!==void 0&&(w.negative_prompt=a.negative),a.enhance==="prefer_magic"&&(w.magic_prompt=true),a.size!==void 0&&(w.size=a.size),a.count!==void 0&&(w.count=a.count),d!==void 0&&(w.output=d),J.length>0&&(w.inputs=J),a.destination!==void 0&&(w.destination=a.destination),xe!==void 0&&(w.rating=xe),y!==void 0&&(w.metadata=y),a.async){let u=await t.images.generate({request:w,requestPat:true}),oe={taskId:u.taskId,...u.pat!==void 0?{access:{publicAccessToken:u.pat}}:{}};if(a.json){i(JSON.stringify(oe,null,2));return}i(`${b} Task created: ${u.taskId}`),u.pat!==void 0&&i(` PAT: ${u.pat}`);return}let Se=await t.images.generate({request:w,requestPat:true}),Re=t.images.waitForTask(Se.taskId,Se.pat),K=a.json?await Re:await Xe(Re),E=a.outputDir!==void 0?resolve(a.outputDir):void 0,P=E!==void 0?await gn(t.images,K,E):[];if(a.json){let u=a.detailed?K:mn(K),oe=E!==void 0?{...u,downloadedFiles:P}:u;i(JSON.stringify(oe,null,2));return}if(un(K,A.length),E!==void 0&&P.length>0){i(""),i(`${b} Saved ${P.length} image${P.length===1?"":"s"} to ${E}`);for(let u of P)i(` ${u}`);}}),e};var ke=t=>t??"-",fn=t=>{if(t.length===0){i("No models available.");return}let e=t.map(s=>({id:s.id,name:s.displayName??"-",base:ke(s.pricing?.perImage.base),fourK:ke(s.pricing?.perImage["4k"]),inputFee:ke(s.pricing?.perInput)})),n={id:Math.max(2,...e.map(s=>s.id.length)),name:Math.max(4,...e.map(s=>s.name.length)),base:Math.max(4,...e.map(s=>s.base.length)),fourK:Math.max(2,...e.map(s=>s.fourK.length)),inputFee:Math.max(9,...e.map(s=>s.inputFee.length))};i(["ID".padEnd(n.id),"Name".padEnd(n.name),"Base".padEnd(n.base),"4K".padEnd(n.fourK),"Input fee".padEnd(n.inputFee)].join(" "));for(let s of e)i([s.id.padEnd(n.id),s.name.padEnd(n.name),s.base.padEnd(n.base),s.fourK.padEnd(n.fourK),s.inputFee.padEnd(n.inputFee)].join(" "));},Ae=t=>{let e=new Command("models").description("Browse the public Mynth model catalog");return e.command("list").description("List available image generation models").option("--json","Output machine-readable JSON instead of a human-readable table").action(async n=>{let s=await t.models.list();if(n.json){i(JSON.stringify(s,null,2));return}fn(s);}),e};var wn=t=>{switch(t){case "completed":return "\u2713";case "failed":return "\u2717";default:return "\u2026"}},vn=(t,e)=>{let n=" ".repeat(e);return t.split(`
7
7
  `).map(s=>`${n}${s}`).join(`
8
- `)},vn=t=>{i(`${yn(t.status)} Task ${t.id}`),i(` Type: ${t.type}`),i(` Status: ${t.status}`),t.cost!==null&&i(` Cost: ${t.cost}`),i(` Created: ${t.createdAt}`),i(` Updated: ${t.updatedAt}`),t.result!==null&&t.result!==void 0&&(i(""),i("Result:"),i(wn(JSON.stringify(t.result,null,2),2)));},Ae=t=>{let e=new Command("task");return e.command("get").description("Fetch a task by ID").argument("<id>","Task ID").option("--json","Output machine-readable JSON instead of a human-readable summary").action(async(n,s)=>{let a=await t.tasks.getTask(n);if(s.json){i(JSON.stringify(a,null,2));return}vn(a);}),e};var _e=class extends Help{optionTerm(e){return `(${e.flags.replaceAll("<","").replaceAll(">","")})`}subcommandTerm(e){let n=e.registeredArguments.map(s=>s.required?`${s.name()}${s.variadic?"...":""}`:`[${s.name()}]`).join(" ");return n.length>0?`${e.name()} ${n}`:e.name()}},nt=()=>{let t=We(),e=new Command("mynth");return e.description("Official Mynth CLI").version("0.0.10"),e.addCommand(me(t)),e.addCommand(ge(t)),e.addCommand(we(t)),e.addCommand(ke(t)),e.addCommand(Ae(t)),e.addCommand(se(t)),st(e),e},st=t=>{t.configureHelp({helpWidth:100}),t.createHelp=()=>new _e;for(let e of t.commands)st(e);};var bn=process.env.MYNTH_DEBUG==="1"||process.env.MYNTH_DEBUG==="true",xn=t=>t instanceof InvalidArgumentError||t instanceof Error?t.message:String(t),Sn=async()=>{let t=nt();t.exitOverride();try{await t.parseAsync(process.argv);}catch(e){if(e.code==="commander.helpDisplayed"||e.code==="commander.version")return;let n=xn(e);ne(n),bn&&e instanceof Error&&(ne("=== MYNTH_DEBUG cause ==="),ne(JSON.stringify(e.cause??e,null,2))),process.exitCode=(1);}};await Sn();
8
+ `)},kn=t=>{i(`${wn(t.status)} Task ${t.id}`),i(` Type: ${t.type}`),i(` Status: ${t.status}`),t.cost!==null&&i(` Cost: ${t.cost}`),i(` Created: ${t.createdAt}`),i(` Updated: ${t.updatedAt}`),t.result!==null&&t.result!==void 0&&(i(""),i("Result:"),i(vn(JSON.stringify(t.result,null,2),2)));},_e=t=>{let e=new Command("task");return e.command("get").description("Fetch a task by ID").argument("<id>","Task ID").option("--json","Output machine-readable JSON instead of a human-readable summary").action(async(n,s)=>{let a=await t.tasks.getTask(n);if(s.json){i(JSON.stringify(a,null,2));return}kn(a);}),e};var be=class extends Help{optionTerm(e){return `(${e.flags.replaceAll("<","").replaceAll(">","")})`}subcommandTerm(e){let n=e.registeredArguments.map(s=>s.required?`${s.name()}${s.variadic?"...":""}`:`[${s.name()}]`).join(" ");return n.length>0?`${e.name()} ${n}`:e.name()}},at=()=>{let t=He(),e=new Command("mynth");return e.description("Official Mynth CLI").version("0.0.12"),e.addCommand(pe(t)),e.addCommand(ge(t)),e.addCommand(ve(t)),e.addCommand(Ae(t)),e.addCommand(_e(t)),e.addCommand(ne(t)),rt(e),e},rt=t=>{t.configureHelp({helpWidth:100}),t.createHelp=()=>new be;for(let e of t.commands)rt(e);};var xn=process.env.MYNTH_DEBUG==="1"||process.env.MYNTH_DEBUG==="true",Sn=t=>t instanceof InvalidArgumentError||t instanceof Error?t.message:String(t),Rn=async()=>{let t=at();t.exitOverride();try{await t.parseAsync(process.argv);}catch(e){if(e.code==="commander.helpDisplayed"||e.code==="commander.version")return;let n=Sn(e);te(n),xn&&e instanceof Error&&(te("=== MYNTH_DEBUG cause ==="),te(JSON.stringify(e.cause??e,null,2))),process.exitCode=(1);}};await Rn();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mynthio/cli",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Official Mynth CLI",
5
5
  "keywords": [
6
6
  "ai",