@conceptcraft/mindframes 0.3.22 → 0.3.24

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 (3) hide show
  1. package/README.md +6 -6
  2. package/dist/index.js +747 -673
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,18 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
3
- var f={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"CLI tool for Mindframes presentation generation",commands:["mf","mindframes"],apiUrl:"https://www.mindframes.app",docsUrl:"https://docs.mindframes.ai",packageName:"@conceptcraft/mindframes",configDir:".mindframes",apiKeyEnvVar:"MINDFRAMES_API_KEY",apiUrlEnvVar:"MINDFRAMES_API_URL",codexSelfConnectorAppId:"asdk_app_6a2b9629c1608191970dcb3ab374ac55"};import G from"chalk";import{Command as Jp}from"commander";import st from"chalk";import{Command as ed}from"commander";function Sr(e={}){let t=(d,l)=>{let y=e[d];return y&&y.trim().length>0?y.trim():l},n=t("NEXT_PUBLIC_PRODUCT_SHORT_NAME","ConceptCraft"),r=t("NEXT_PUBLIC_CLI_COMMAND","ccr"),o=t("NEXT_PUBLIC_CLI_COMMAND_FULL","conceptcraft"),i=t("NEXT_PUBLIC_CLI_CONFIG_DIR",`.${o}`),a=n.toUpperCase().replace(/[^A-Z0-9]/g,"_");return{id:o,name:i.replace(/^\./,""),displayName:n,description:`CLI tool for ${n} presentation generation`,commands:[r,o],apiUrl:t("NEXT_PUBLIC_API_URL","http://localhost:3000"),docsUrl:t("NEXT_PUBLIC_DOCS_URL",`https://docs.${n.toLowerCase()}.ai`),packageName:t("NEXT_PUBLIC_CLI_PACKAGE_NAME","@conceptcraft/cli"),configDir:i,apiKeyEnvVar:`${a}_API_KEY`,apiUrlEnvVar:`${a}_API_URL`,codexSelfConnectorAppId:e.NEXT_PUBLIC_CODEX_SELF_CONNECTOR_APP_ID?.trim()||void 0}}var m=typeof f<"u"&&f?f:Sr(process.env);import L from"chalk";import fn from"cli-table3";import bs from"conf";var $r=m.apiUrl,ws={apiKey:{type:"string"},apiUrl:{type:"string",default:$r},defaultTeamId:{type:"string"},accessToken:{type:"string"},refreshToken:{type:"string"},tokenExpiresAt:{type:"number"},clientId:{type:"string"},clientSecret:{type:"string"}},_=new bs({projectName:m.name,schema:ws});function Tr(){return{apiKey:ge(),apiUrl:B(),defaultTeamId:_.get("defaultTeamId"),accessToken:_.get("accessToken"),refreshToken:_.get("refreshToken"),tokenExpiresAt:_.get("tokenExpiresAt"),clientId:_.get("clientId"),clientSecret:_.get("clientSecret")}}function ge(){let e=process.env[m.apiKeyEnvVar]??process.env.CC_SLIDES_API_KEY;return e||_.get("apiKey")}function pn(e){_.set("apiKey",e)}function B(){let e=process.env[m.apiUrlEnvVar]??process.env.CC_SLIDES_API_URL;return e||(_.get("apiUrl")??$r)}function gn(e){_.set("apiUrl",e)}function Ct(){return _.get("defaultTeamId")}function De(e){_.set("defaultTeamId",e)}function It(){_.clear()}function ot(){return _.path}function Ne(){return!!ge()}function Er(){return _.get("accessToken")}function Ar(){return _.get("refreshToken")}function Rt(e,t,n){_.set("accessToken",e),_.set("refreshToken",t),_.set("tokenExpiresAt",Date.now()+(n-60)*1e3)}function St(){_.delete("accessToken"),_.delete("refreshToken"),_.delete("tokenExpiresAt")}function Or(){let e=_.get("tokenExpiresAt");return e?Date.now()>=e:!0}function $e(){return!!_.get("accessToken")&&!!_.get("refreshToken")}function Pr(){return _.get("clientId")}function _r(){return _.get("clientSecret")}function Lr(e,t){_.set("clientId",e),_.set("clientSecret",t)}function x(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(L.green("\u2713"),e)}function s(e,t="human"){if(t!=="quiet"){if(t==="json"){console.error(JSON.stringify({error:e}));return}console.error(L.red("\u2717"),e)}}function M(e,t="human"){t!=="quiet"&&t!=="json"&&console.warn(L.yellow("\u26A0"),e)}function Dr(e,t="human"){t==="quiet"||t==="json"||console.error(L.cyan("\u2192"),e)}function g(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(L.blue("\u2139"),e)}function qe(e,t="en"){return e?`${B()}/${t}/view/presentations/${e}`:"N/A"}function Nr(e,t={}){let{showLinks:n=!1,language:r="en"}=t,o=(d,l)=>d.length>l?`${d.slice(0,l-1)}\u2026`:d,i=d=>{try{return new Date(d).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).replace(" at ",", ")}catch{return"-"}};if(n){let d=new fn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Created"),L.cyan("URL")]});for(let l of e)d.push([o(l.slug||l.id.slice(0,8),30),o(l.title||"Untitled",22),String(l.numberOfSlides||"-"),i(l.createdAt),qe(l.slug,r)]);return d.toString()}let a=new fn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Mode"),L.cyan("Created")],colWidths:[32,28,8,11,18]});for(let d of e)a.push([d.slug||d.id.slice(0,8),d.title||"Untitled",String(d.numberOfSlides||"-"),d.mode||"-",i(d.createdAt)]);return a.toString()}function qr(e){return e.map(t=>t.slug||t.id).join(`
4
- `)}function Ur(e){let t=[...e].sort((o,i)=>{if(o.isDefault&&!i.isDefault)return-1;if(!o.isDefault&&i.isDefault)return 1;let a=o.createdAt?new Date(o.createdAt).getTime():0;return(i.createdAt?new Date(i.createdAt).getTime():0)-a}),n=o=>{if(!o)return"-";try{return new URL(o).href}catch{return o.startsWith("http")?o:`https://${o}`}},r=new fn({head:[L.cyan("Name"),L.cyan("Source"),L.cyan("Color"),L.cyan("Logo"),L.cyan("Default"),L.cyan("ID")]});for(let o of t){let i=o.primaryColor?`${L.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"-";r.push([o.name,n(o.sourceUrl),i,o.logoUrl?L.green("\u2713"):L.gray("\u2717"),o.isDefault?L.green("\u2605"):"",o.id])}return r.toString()}function hn(e){try{return new Date(e).toLocaleString()}catch{return e}}function ie(e){console.log(),console.log(L.bold(e)),console.log(L.gray("\u2500".repeat(e.length)))}function R(e,t){console.log(` ${L.gray(`${e}:`)} ${t??"-"}`)}function vs(e){return JSON.stringify(e,null,2)}function u(e){console.log(vs(e))}import{createHash as Ms,randomUUID as it}from"crypto";import{readFileSync as Fs,statSync as Vs}from"fs";import{basename as Xr}from"path";import{spawnSync as xs}from"child_process";import{existsSync as ks,mkdtempSync as Cs,rmSync as Is,writeFileSync as Rs}from"fs";import{tmpdir as Ss}from"os";import{join as jr}from"path";import yn from"ffmpeg-static";var $s=/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/;function Ts(e){let t=$s.exec(e);if(!t)return;let n=Number(t[1])*3600+Number(t[2])*60+Number(t[3]);return Number.isFinite(n)&&n>0?n:void 0}function Mr(e,t="audio"){if(e.length===0)return;let n=yn&&ks(yn)?yn:"ffmpeg",r=/^[a-z0-9]+$/i.test(t)?t:"audio",o=Cs(jr(Ss(),"mf-tts-duration-")),i=jr(o,`speech.${r}`);try{Rs(i,e);let a=xs(n,["-hide_banner","-i",i],{encoding:"utf8"});return a.error?void 0:Ts(a.stderr??"")}finally{Is(o,{force:!0,recursive:!0})}}import $t from"chalk";var c={SUCCESS:0,GENERAL_ERROR:1,AUTH_ERROR:2,NOT_FOUND:3,RATE_LIMIT:4,NETWORK_ERROR:5,INVALID_INPUT:6};async function Es(){let e=Ar(),t=Pr(),n=B();if(!e||!t)return null;try{let r=await fetch(`${n}/.well-known/oauth-authorization-server`);if(!r.ok)return null;let o=await r.json(),i=new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:t}),a=_r();a&&i.set("client_secret",a);let d=await fetch(o.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!d.ok)return St(),null;let l=await d.json();return Rt(l.access_token,l.refresh_token,l.expires_in),l.access_token}catch{return null}}async function Fr(){return $e()?Or()?Es():Er()||null:null}function fe(){return $e()||Ne()}async function O(){if(!fe()){let e=m.commands[0],t=m.apiKeyEnvVar;console.error($t.red("\u2717 Not authenticated.")),console.error(),console.error($t.bold("To authenticate, run:")),console.error($t.cyan(` ${e} login`)),console.error(),console.error($t.gray(`Or set ${t} environment variable.`)),process.exit(c.AUTH_ERROR)}}function As(e){return e.length<=14?"****":`${e.slice(0,10)}...${e.slice(-4)}`}function Vr(){let e=ge();if(e)return As(e)}function bn(e){return["cc_slides_","mcp_","cc_sk_","sk_"].some(n=>e.startsWith(n))}import{mkdirSync as Os,readFileSync as Ps,writeFileSync as _s}from"fs";import{homedir as Ls}from"os";import{join as Gr}from"path";import Ds from"ajv/dist/2020.js";var wn=new Map;function Br(){return Gr(Ls(),".conceptcraft","schemas")}function Wr(e){return Gr(Br(),`${e}.json`)}function Ns(e){try{let t=JSON.parse(Ps(Wr(e),"utf8"));return typeof t?.catalogVersion=="number"&&t.schema?t:null}catch{return null}}function qs(e,t){try{Os(Br(),{recursive:!0}),_s(Wr(e),JSON.stringify(t))}catch{}}async function Us(e){let t=wn.get(e);if(t!==void 0)return t;try{let n=await Kr(e),r={catalogVersion:n.catalogVersion,schema:n.schema};return qs(e,r),wn.set(e,r),r}catch{let n=Ns(e);return wn.set(e,n),n}}function js(e){let t=e.instancePath.replace(/^\//,"").replace(/\//g,"."),n=t.length>0?t:"(root)",r=e.keyword==="additionalProperties"?`: unknown field "${e.params.additionalProperty}"`:`: ${e.message??"invalid value"}`;return`${n}${r}`}async function Tt(e,t){let n=await Us(e);if(!n)return;let r;try{r=new Ds({allErrors:!0,strict:!1}).compile(n.schema)}catch{return}if(r(t))return;let o=(r.errors??[]).slice(0,10).map(js);throw new Error(`Request does not match the ${e} contract \u2014 ${o.join("; ")}`)}function ae(e,t){let n=e instanceof Error?e.message:"Unknown error";return!t||n.includes(t)?n:`${n} Request ID: ${t}. Resume with the matching status command; do not start a duplicate run.`}function se(e,t={}){let n=e?.code?.trim()||t.defaultCode?.trim()||"",r=e?.message?.trim()||"The run failed without a reported reason.";return n?`[${n}] ${r}`:r}function Jr(e){let t=e.projectId??"<project-id>";return/Narration is still missing for \d+ slides?\./.test(e.message)?["Narration is captured from speaker notes when the video project is prepared, so 'presentation video refresh' will not backfill it.",`Fill each empty scene with: ${e.binary} presentation video-narration ${t} --slide-id <slide-id> (scene ids: ${e.binary} presentation video inspect ${t})`].join(`
5
- `):/Every scene is excluded from the video\./.test(e.message)?`Include a scene again with: ${e.binary} presentation video edit ${t} --edit '{"type":"patch_scene","scene":1,"excluded":false}'`:null}async function he(){let e=await Fr();if(e)return{Authorization:`Bearer ${e}`};let t=ge();return t?{"x-api-key":t}:{}}var P=class extends Error{constructor(n,r,o=1,i="operation_failed",a=!1){super(n);this.statusCode=r;this.exitCode=o;this.errorCode=i;this.retryable=a;this.name="ApiError"}statusCode;exitCode;errorCode;retryable},Hr="Idempotency-Key";function Gs(e){return e&&e!=="GET"?{[Hr]:it()}:{}}async function K(e,t={}){let n=B();if(!fe()&&!t.allowUnauthenticated)throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2,"authentication_required");let r=await he(),o=`${n}${e}`,i={...r,...Gs(t.method),...t.headers};t.body&&!t.stream&&(i["Content-Type"]="application/json");let a={method:t.method??"GET",headers:i};t.body&&(a.body=JSON.stringify(t.body));let d;try{d=await fetch(o,a)}catch(y){throw new P(`Network error: ${y instanceof Error?y.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!d.ok){let y=await d.text().catch(()=>""),p=Ws(y,d.status),w=1;switch(d.status){case 401:w=2;break;case 403:w=2;break;case 404:w=3;break;case 429:w=4;break;case 500:w=1;break}let v=`[${p.code}] ${p.message}`;throw new P(v,d.status,w,p.code,p.retryable)}return t.stream?d:d.headers.get("content-type")?.includes("application/json")?d.json():d.text()}function Bs(e){switch(e){case 400:return"invalid_input";case 401:return"authentication_required";case 402:return"insufficient_credits";case 403:return"access_denied";case 404:return"not_found";case 429:return"rate_limited";case 503:return"service_unavailable";default:return"operation_failed"}}function Ws(e,t){let n=Bs(t),r=e.trim()||`HTTP ${t}: The request could not be completed.`;try{let o=JSON.parse(e),i=typeof o.error=="object"&&o.error!==null?o.error:void 0;if(o.ok===!1&&typeof i?.code=="string"&&typeof i.message=="string")return{code:i.code,message:i.message,retryable:i.retryable===!0};if(typeof o.error=="string")return{code:/^[a-z][a-z0-9_]+$/.test(o.error)?o.error:n,message:typeof o.message=="string"?o.message:o.error,retryable:t===429||t>=500}}catch{}return{code:n,message:r,retryable:t===429||t>=500}}async function Kr(e){return K(`/api/cli/tools/${encodeURIComponent(e)}/schema`)}async function Yr(){return K("/api/cli/capabilities",{allowUnauthenticated:!0})}async function T(e,t,n){let r=n?`?teamId=${encodeURIComponent(n)}`:"";return K(`/api/cli/tool-runs/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`)}async function h(e,t,n){return K(`/api/cli/tools/${encodeURIComponent(e)}`,{body:t,headers:n?{[Hr]:n}:void 0,method:"POST"})}async function Qr(e,t,n,r=120){let o=0;for(let i=0;i<r;i++){let a;try{a=await T(e,t,n),o=0}catch(d){if(d instanceof P&&d.retryable&&o<2){o+=1,await new Promise(l=>setTimeout(l,2e3));continue}throw d instanceof P?new P(`${d.message} Request ID: ${t}.`,d.statusCode,d.exitCode,d.errorCode,d.retryable):new P(`${d instanceof Error?d.message:"Unknown error"} Request ID: ${t}.`,0,5,"poll_failed",!0)}if(a.done){if(a.error)throw new P(`${se(a.error,{defaultCode:"operation_failed"})} Request ID: ${t}.`,500,1,a.error.code??"operation_failed",a.error.retryable);return a}await new Promise(d=>setTimeout(d,(a.nextPollAfterSeconds??2)*1e3))}throw new P(`[operation_timed_out] The background operation timed out. Request ID: ${t}.`,408,1,"operation_timed_out",!0)}function Et(e){return e.error||e.status==="failed"||e.status==="errored"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"?"processing":"pending"}function Ks(e){try{let n=new URL(e).pathname.split("/").pop()?.split(".").pop()?.toLowerCase();return n&&/^[a-z0-9]+$/.test(n)?n:void 0}catch{return}}function Js(e){let t=e.toLowerCase().split(".").pop();return{pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",mp4:"video/mp4",mov:"video/quicktime",mpeg:"video/mpeg",mpg:"video/mpeg",webm:"video/webm",aac:"audio/aac",m4a:"audio/mp4",mp3:"audio/mpeg",oga:"audio/ogg",ogg:"audio/ogg",wav:"audio/wav",txt:"text/plain",md:"text/markdown",csv:"text/csv",json:"application/json",html:"text/html",css:"text/css",js:"application/javascript",ts:"text/x-typescript",py:"text/x-python"}[t||""]||"application/octet-stream"}async function me(e,t={}){let n=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let r=await he(),o=Vs(e),i=Xr(e),a=Js(e),d=Fs(e),l=Ms("sha256").update(d).digest("hex"),y=await fetch(`${n}/api/cli/files/upload`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({fileMetadata:{lastModified:o.mtimeMs,name:i,type:a,size:o.size},...t.idempotencyKey?{uploadIdentity:{contentSha256:l,idempotencyKey:t.idempotencyKey}}:{}})});if(!y.ok){let E=await y.text();throw new P(E||"Failed to get upload URL",y.status,1)}let p=await y.json(),w=new FormData;for(let[E,k]of Object.entries(p.fields||{}))w.append(E,k);let v=new Blob([d],{type:a});w.append("file",v,i);let C=await fetch(p.url,{method:"POST",body:w});if(!C.ok)throw new P("Failed to upload file to storage",C.status,1);return{id:it(),name:i,url:p.fileUrl,size:o.size,type:a,selected:!0}}async function Zr(e,t){let n=[];for(let r=0;r<e.length;r++){let o=e[r],i=Xr(o);t?.(r,e.length,i);let a=await me(o);n.push(a)}return t?.(e.length,e.length,""),n}async function eo(e){let t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);let n=t.designBrandReference??t.brandId??t.brandingId;return n!==void 0&&(t.designBrandReference=n,delete t.brandId,delete t.brandingId),h("createSlides",{...t,approvalReceipt:"cli:create"})}async function to(e,t=20){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("teamId",e),(await K(`/api/cli/presentations?${n}`)).presentations}async function Ue(e,t){let n=t?.includeSlides?"?includeSlides=true":"";return K(`/api/cli/presentation/${encodeURIComponent(e)}${n}`)}async function no(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/speaker-notes`,{body:t,method:"POST"})}async function ro(e,t){return K(`/api/cli/presentation-video/${encodeURIComponent(e)}/narration`,{body:t,method:"POST"})}async function At(e){let t=B(),n=await fetch(`${t}/api/durable-runs/${encodeURIComponent(e)}/events`,{headers:await he()});if(!n.ok)throw new P(await n.text(),n.status);return n}async function oo(e){await K(`/api/cli/presentation/${encodeURIComponent(e)}`,{method:"DELETE"})}async function io(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/export`,{body:{format:t},method:"POST"})}async function ao(e){let t;try{t=await fetch(e)}catch(n){throw new P(`Network error while downloading the export: ${n instanceof Error?n.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!t.ok)throw new P(`[fetch_failed] The export download link returned ${t.status}. Signed links expire after one hour \u2014 re-run the export.`,t.status,1,"fetch_failed",!0);return t.arrayBuffer()}async function so(e,t,n={}){let r=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let o=await he(),i=new FormData,a=new Blob([e],{type:"application/zip"});i.append("file",a,t),i.append("options",JSON.stringify({dryRun:n.dryRun??!1,remapIds:!0}));let d=await fetch(`${r}/api/presentations/import`,{method:"POST",headers:o,body:i}),l=await d.json();if(!d.ok)throw new P(l.errors?.[0]?.message??"Import failed",d.status,1);return l}async function vn(){return K("/api/cli/branding")}async function co(e,t=25){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("search",e),K(`/api/cli/templates?${n}`)}async function lo(e){return K(`/api/branding/${e}`)}async function mo(e,t,n){return h("extractBranding",{approvalReceipt:n,teamId:t,url:e})}async function ye(){return K("/api/cli/whoami")}async function uo(){return K("/api/cli/features")}async function po(e,t,n={}){let r=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let o=await he(),i=await fetch(`${r}/api/presentations/${e}/generate-blog`,{method:"POST",headers:{"Content-Type":"application/json",...o},body:JSON.stringify({documentCreatedAt:t,targetWordCount:n.targetWordCount??300,tone:n.tone??"professional",language:n.language??"en",targetAudience:n.targetAudience??"General Audience",blogFormat:n.blogFormat??"narrative",customInstructions:n.customInstructions??"",includeImages:n.includeImages??!0,includeTableOfContents:n.includeTableOfContents??!1})});if(!i.ok)throw new P(await i.text(),i.status,i.status===404?3:1);return i}async function zs(e){let t=new URLSearchParams;e&&t.set("teamId",e);let n=t.toString();return K(`/api/cli/limits${n?`?${n}`:""}`)}async function go(e,t,n){let r=await zs(n);if(!r.canGenerate[e]){let o=r.remaining[e]??0,i=r.limits[e]??0;throw i===0?new P(`The "${e}" mode is not available on your ${r.planName} plan. Available modes: ${r.availableModes.join(", ")||"none"}`,403,2):new P(`You have reached your ${e} generation limit for this billing cycle (${r.usage[e]??0}/${i} used). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,4)}if(r.maxSlidesPerPresentation!==-1&&t>r.maxSlidesPerPresentation)throw new P(`Maximum ${r.maxSlidesPerPresentation} slides allowed on your ${r.planName} plan (requested: ${t}). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,6);return r}function Xs(e){return e.replace(/[\u2014\u2013]/g,"-").replace(/[\u201C\u201D]/g,'"').replace(/[\u2018\u2019]/g,"'").replace(/\u2026/g,"...").replace(/\u00A0/g," ").replace(/[\u2010-\u2015]/g,"-").replace(/[\u2032\u2033]/g,"'")}async function fo(e){let t={...e,text:Xs(e.text)};await Tt("generateSpeech",t);let n=await h("generateSpeech",{approvalReceipt:"cli:tts-generate",...t}),r=await Qr("generateSpeech",n.runId),o=r.entity?.url;if(!o)throw new P(`Speech completed without an audio URL. Request ID: ${n.runId}.`,500);let i;try{i=await fetch(o)}catch(w){throw new P(`${w instanceof Error?w.message:"Failed to download speech audio"} Request ID: ${n.runId}.`,0,5,"download_failed",!0)}if(!i.ok)throw new P(`Failed to download speech audio. Request ID: ${n.runId}.`,i.status,5,"download_failed",i.status===429||i.status>=500);let a=r.output??{},d=e.options??{},l=le(a.format)??Ks(o)??"mp3",y=Buffer.from(await i.arrayBuffer()),p=ho(a.durationSec,a.duration,a.duration_s)??Mr(y,l);if(p===void 0)throw new P(`Speech completed without a measurable duration. Request ID: ${n.runId}.`,500,1,"invalid_audio_metadata");return{audioData:y,audioUrl:o,duration:p,cost:Te(a.costUsd)??Te(a.cost)??0,provider:le(a.provider)??d.provider??"gemini",format:l,requestId:n.runId,voiceId:le(a.voice_id)??le(a.voiceId),voice:le(a.voice),model:le(a.model),speed:Te(a.speed)??d.speed,language:le(a.lang)??le(a.language)??d.language,langApplied:zr(a.langApplied)??zr(a.lang_applied),timestamps:Hs(a.timestamps),wordTimings:Ys(a.timestamps??a.timings)}}function ho(...e){for(let t of e){let n=typeof t=="number"?t:typeof t=="string"&&t.trim()?Number(t):Number.NaN;if(Number.isFinite(n)&&n>0)return n}}function Hs(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n=t.characters,r=t.characterStartTimesSeconds??t.character_start_times_seconds,o=t.characterEndTimesSeconds??t.character_end_times_seconds;if(!(!Array.isArray(n)||!Array.isArray(r)||!Array.isArray(o))&&!(n.length===0||n.length!==r.length||n.length!==o.length||!n.every(i=>typeof i=="string")||!r.every(i=>typeof i=="number"&&Number.isFinite(i))||!o.every(i=>typeof i=="number"&&Number.isFinite(i))))return{characters:n,characterStartTimesSeconds:r,characterEndTimesSeconds:o}}function Ys(e){if(!Array.isArray(e))return;let t=e.flatMap(n=>{if(!n||typeof n!="object"||Array.isArray(n))return[];let r=n,o=le(r.text)??le(r.word),i=Te(r.start),a=Te(r.end);return o&&i!==void 0&&a!==void 0&&a>=i?[{text:o,start:i,end:a}]:[]});return t.length>0?t:void 0}function le(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Te(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function zr(e){return typeof e=="boolean"?e:void 0}async function yo(e){let t=e?`/api/cli/tts?provider=${e}`:"/api/cli/tts";return K(t)}async function bo(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;return delete t.idempotency_key,await Tt("generateMusic",t),{requestId:(await h("generateMusic",{...t,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function xn(e){let t=await T("generateMusic",e);return{requestId:e,status:Et(t),audioUrl:t.entity?.url,duration:ho(t.output?.durationSec,t.output?.duration,t.output?.duration_s),cost:Te(t.output?.costUsd)??Te(t.output?.cost),error:t.error?.message}}async function wo(e){return{requestId:(await h("mixAudio",{...e,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function kn(e){let t=await T("mixAudio",e);return{requestId:e,status:Et(t),outputUrl:t.entity?.url,error:t.error?.message}}async function vo(e){return K("/api/cli/images/search",{method:"POST",body:e})}async function xo(e){return K("/api/cli/videos/search",{method:"POST",body:e})}async function te(e,t=60,n=2e3){let r=0;for(let o=0;o<t;o++){let i;try{i=await e(),r=0}catch(a){if(a instanceof P&&a.retryable&&r<2){r+=1,await new Promise(d=>setTimeout(d,n));continue}throw a}if(i.status==="completed"||i.status==="failed")return i;await new Promise(a=>setTimeout(a,n))}throw new P("Operation timed out",408,1)}async function ko(e,t,n){return h("getYoutubeTranscript",{...n?{language:n}:{},teamId:t,url:e})}async function Co(e,t){let n=await h("scrape",{teamId:t,url:e});return{data:{content:n.content,cost:n.totalCost??0,metadata:{description:"",format:"markdown",tokenUsage:Math.ceil(n.content.length/4)},title:n.title??"",url:n.url},success:!0}}async function Io(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;delete t.idempotency_key,await Tt("generateSfx",t);let r=await h("generateSfx",{...t,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function Cn(e){let t=await T("generateSfx",e);return{id:t.entity?.id??e,requestId:e,status:Et(t),audioUrl:t.entity?.url,error:t.error?.message}}async function Ro(e){return h("listPresenterOptions",{...e?{voiceLanguage:e}:{}})}async function So(e){return{requestId:(await h("generateAvatarVideo",{...e,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function In(e){let t=await T("generateAvatarVideo",e);return{durationSec:typeof t.output?.durationSec=="number"?t.output.durationSec:null,error:t.error?.message,requestId:e,status:Et(t),videoUrl:t.entity?.url}}async function $o(e){return h("lipsyncVideo",{...e,approvalReceipt:"cli:video-lipsync"})}async function To(){return(await h("listTranslationLanguages",{})).languages}async function Eo(e){return h("translateVideo",{...e,approvalReceipt:"cli:video-translate"})}async function Ao(e,t,n){return h("createVideo",{...e,approvalReceipt:t},n)}async function Oo(e){let{idempotencyKey:t,...n}=e;return h("analyzeVideoReference",n,t)}async function Po(e,t){return Qr("analyzeVideoReference",e,t)}async function _o(e){return h("listCastPresets",e)}async function Lo(e){return h("createCastPreset",e,it())}async function Do(e){return h("updateCastPreset",e,it())}async function No(e){return h("deleteCastPreset",{presetId:e},it())}var qo=[{billing:"free",category:"branding",description:"Attach a social handle to an accessible brand profile.",id:"addBrandSocialHandle",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding social add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"branding",description:"Add a competitor to an accessible brand profile.",id:"addCompetitor",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding competitor add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"delegated",category:"media",description:"Transcribe an uploaded recording and publish the transcript for generation.",id:"analyzeMediaAsset",lifecycle:{mode:"background",status:{cliCommand:"media analyze status",pollAfterSeconds:10}},milestone:"M8",name:"media analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Analyze an uploaded video before using it as a source, motion, blocking, or pacing reference in a video storyboard. The completed status output includes the analysisId required by the storyboard's source-video binding.",id:"analyzeVideoReference",lifecycle:{mode:"background",status:{cliCommand:"video reference status",pollAfterSeconds:10}},milestone:"M8",name:"video reference analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"artifacts",description:"Generate and persist an ad variation set.",id:"createAdSet",lifecycle:{mode:"background",status:{cliCommand:"ad-set status",pollAfterSeconds:10}},milestone:"M6",name:"ad-set create",operation:"generation",scopes:["ad-sets:write"],state:"available"},{billing:"free",category:"agents",description:"Create a scheduled agent from a validated configuration.",id:"createAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent create",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"media",description:"Save one way a cast member appears: a personal presenter (pp_* id), a backdrop, and optionally a voice, under a name unique to that person.",id:"createCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Save a markdown, CSV or plain-text document into the Library.",id:"createDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"fixed",category:"media",description:"Generate and persist an image.",id:"createImage",lifecycle:{mode:"background",status:{cliCommand:"image status",pollAfterSeconds:10}},milestone:"M5",name:"image generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Create a Library folder, optionally inside another.",id:"createLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"dynamic",category:"artifacts",description:"Generate and persist a microsite.",id:"createMicrosite",lifecycle:{mode:"background",status:{cliCommand:"microsite status",pollAfterSeconds:10}},milestone:"M6",name:"microsite create",operation:"generation",scopes:["microsites:write"],state:"available"},{billing:"free",category:"artifacts",description:"Create a standalone poll.",id:"createPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll create",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"delegated",category:"presentations",description:"Create an MP4 video from a finished presentation, or render an existing presentation-video project.",id:"createPresentationVideo",lifecycle:{mode:"background",status:{cliCommand:"presentation video status",pollAfterSeconds:10}},milestone:"M4",name:"presentation video",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"fixed",category:"presentations",description:"Generate a presentation and persist the resulting deck.",id:"createSlides",lifecycle:{mode:"background",status:{cliCommand:"presentation status",pollAfterSeconds:20}},milestone:"M4",name:"create",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one video from the opaque text and explicit metadata stored in a pinned storyboard revision.",id:"createVideo",lifecycle:{mode:"background",status:{cliCommand:"video status",pollAfterSeconds:20}},milestone:"M8",name:"video create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a versioned Markdown video storyboard.",id:"createVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"fixed",category:"artifacts",description:"Generate a persisted standalone visual abstract.",id:"createVisualAbstract",lifecycle:{mode:"background",status:{cliCommand:"visual-abstract status",pollAfterSeconds:10}},milestone:"M5",name:"visual-abstract create",operation:"generation",scopes:["visual-abstracts:write"],state:"available"},{billing:"free",category:"media",description:"Retire a saved cast preset. Existing videos keep working; the preset stops being offered.",id:"deleteCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset delete",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Remove a document from the Library.",id:"deleteDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"knowledge",description:"Delete a Library folder and its subfolders. Items inside are unfiled, never deleted.",id:"deleteLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"artifacts",description:"Edit a standalone poll.",id:"editPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll edit",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"free",category:"presentations",description:"Apply one atomic edit to a presentation-video draft.",id:"editPresentationVideoDraft",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video edit",operation:"mutation",scopes:["presentations:write","media:read"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate the narration a presentation-video project is still missing.",id:"ensurePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video narrate status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video narrate",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"quota",category:"branding",description:"Extract and persist a reusable brand profile from a URL.",id:"extractBranding",lifecycle:{mode:"background",status:{cliCommand:"branding status",pollAfterSeconds:10}},milestone:"M2",name:"branding extract",operation:"generation",scopes:["brands:write"],state:"available"},{billing:"dynamic",category:"research",description:"Extract normalized text from uploaded or remote content.",id:"extractContent",lifecycle:{mode:"bounded"},milestone:"M1",name:"content extract",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"File an artifact into a Library folder, or unfile it.",id:"fileArtifactIntoFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library file",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Erase every stored version of a scheduled agent's memory. Irreversible.",id:"forgetAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory forget",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one reusable avatar/presenter clip for composition into a video. Accepts a stock avatar id or a personal presenter's pp_* id (from listPresenterOptions' `personal` group) as avatarId.",id:"generateAvatarVideo",lifecycle:{mode:"background",status:{cliCommand:"avatar status",pollAfterSeconds:10}},milestone:"M8",name:"avatar generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate music from final video facts or a trusted direct prompt.",id:"generateMusic",lifecycle:{mode:"background",status:{cliCommand:"music status",pollAfterSeconds:10}},milestone:"M7",name:"music generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate an additional look for an existing personal presenter while preserving the same Cast identity.",id:"generatePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate SFX from final video facts or a trusted direct prompt.",id:"generateSfx",lifecycle:{mode:"background",status:{cliCommand:"sfx status",pollAfterSeconds:10}},milestone:"M7",name:"sfx generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate persisted speaker notes for a presentation version.",id:"generateSpeakerNotes",lifecycle:{mode:"background",status:{cliCommand:"presentation speaker-notes-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation speaker-notes",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate speech audio from text.",id:"generateSpeech",lifecycle:{mode:"background",status:{cliCommand:"tts status",pollAfterSeconds:10}},milestone:"M7",name:"tts generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Read what a scheduled agent has recorded about its own work: learned facts, standing instructions, things it never does, entities it tracks, and freeform notes.",id:"getAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory show",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"branding",description:"List competitors saved for an accessible brand profile.",id:"getBrandCompetitors",lifecycle:{mode:"bounded"},milestone:"M1",name:"branding competitor list",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"branding",description:"Read a brand's design tokens, the keys it is missing, or its design.md document.",id:"getBrandProfile",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding profile",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"knowledge",description:"Read a bounded workspace Knowledge Hub bundle.",id:"getKnowledgeBundle",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge bundle",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search recent news sources.",id:"getNews",lifecycle:{mode:"bounded"},milestone:"M1",name:"search news",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"presentations",description:"Read a presentation and its slides.",id:"getPresentation",lifecycle:{mode:"bounded"},milestone:"M1",name:"get",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"presentations",description:"Read an owned presentation-video project and its ordered scene timeline.",id:"getPresentationVideoProject",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video inspect",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"dynamic",category:"research",description:"Fetch a YouTube video's timestamped transcript with its title, channel, and duration.",id:"getYoutubeTranscript",lifecycle:{mode:"bounded"},milestone:"M1",name:"transcript",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"media",description:"Import a recording from a connected account into the media library.",id:"importConnectorRecording",lifecycle:{mode:"background",status:{cliCommand:"media import status",pollAfterSeconds:5}},milestone:"M8",name:"media import",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"presentations",description:"Import an attached PowerPoint as an auditable, review-gated Mindframes presentation.",id:"importPowerPoint",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Re-voice a ready video with new audio via provider lip-sync (one sibling re-voiced video artifact).",id:"lipsyncVideo",lifecycle:{mode:"background",status:{cliCommand:"video lipsync status",pollAfterSeconds:20}},milestone:"M8",name:"video lipsync",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"List saved ways a cast member appears \u2014 a trained presenter, a backdrop, and optionally a voice, under one name. Filtered to what the caller may actually use.",id:"listCastPresets",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset list",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace's documents, newest first.",id:"listDocuments",lifecycle:{mode:"bounded"},milestone:"M8",name:"document list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List a document's append-only version history.",id:"listDocumentVersions",lifecycle:{mode:"bounded"},milestone:"M8",name:"document versions",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace Library folder tree.",id:"listLibraryFolders",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"presentations",description:"List saved presentation-video draft versions.",id:"listPresentationVideoVersions",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video versions",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral presenter avatars, voices, and voice languages, plus the workspace's trained personal presenters (`personal` roster group, pp_* ids).",id:"listPresenterOptions",lifecycle:{mode:"bounded"},milestone:"M8",name:"avatar options",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"media",description:"List ready generated clips and uploaded MediaAssets while excluding final presentation-to-MP4 renders.",id:"listReusableVideoClips",lifecycle:{mode:"bounded"},milestone:"M8",name:"video library list",operation:"query",scopes:["media:read","presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral target languages for video translation.",id:"listTranslationLanguages",lifecycle:{mode:"bounded"},milestone:"M8",name:"video translate-languages",operation:"query",scopes:["media:read"],state:"available"},{billing:"dynamic",category:"media",description:"Mix voice, music, and sound-effect tracks.",id:"mixAudio",lifecycle:{mode:"background",status:{cliCommand:"mix status",pollAfterSeconds:10}},milestone:"M7",name:"mix create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Move a Library folder under a new parent, or to the top level.",id:"moveLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders move",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Create or reuse a presentation-video project for a finished presentation.",id:"preparePresentationVideo",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video prepare",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Read one document's full body and metadata.",id:"readDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document read",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"media",description:"Read a video storyboard and its immutable revision history.",id:"readVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard show",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"Set or clear the colour of a Library folder.",id:"recolorLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders recolor",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Create a reviewable scheduled-agent recommendation.",id:"recommendAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent recommend",operation:"generation",scopes:["agents:write"],state:"available"},{billing:"free",category:"presentations",description:"Refresh deck-backed video scenes from the latest presentation version.",id:"refreshPresentationVideoSlides",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video refresh",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Regenerate one narration override in a presentation video draft.",id:"regeneratePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video-narration-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video-narration",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Rename a Library folder.",id:"renameLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders rename",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"knowledge",description:"Restore an earlier version by appending it as the current one.",id:"restoreDocumentVersion",lifecycle:{mode:"bounded"},milestone:"M8",name:"document restore",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Restore a saved presentation-video draft version as a new version.",id:"restorePresentationVideoVersion",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video restore",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Create a new presenter Look by editing an existing Look without changing its source.",id:"revisePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look revision-status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look revise",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a new immutable revision of a Markdown video storyboard.",id:"reviseVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard revise",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"research",description:"Read and normalize content from a public URL.",id:"scrape",lifecycle:{mode:"bounded"},milestone:"M1",name:"scrape",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search licensed image providers.",id:"searchImages",lifecycle:{mode:"bounded"},milestone:"M1",name:"search images",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search the public web for current sources.",id:"searchInternet",lifecycle:{mode:"bounded"},milestone:"M1",name:"search web",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"Search workspace Knowledge Hub entries.",id:"searchKnowledge",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge search",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"media",description:"Find videos: licensed stock clips to download, or web videos to embed.",id:"searchStockVideo",lifecycle:{mode:"bounded"},milestone:"M1",name:"search video",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"branding",description:"Point a brand at an already-uploaded logo, dark-background logo variant, or favicon.",id:"setBrandLogo",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding logo set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"presentations",description:"Set one presentation-video scene to a specific avatar/look or saved preset, including the preset voice by default, or restore inheritance from the project default.",id:"setPresentationVideoScenePresenter",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video presenter",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"presentations",description:"Transform an uploaded PowerPoint source into an auditable presentation review.",id:"transformPresentationImport",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import transform",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Translate a ready video into sibling language versions (one video per target language).",id:"translateVideo",lifecycle:{mode:"background",status:{cliCommand:"video translate status",pollAfterSeconds:20}},milestone:"M8",name:"video translate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Add to or remove from what a scheduled agent remembers. Owner or workspace admin only.",id:"updateAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory set",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"branding",description:"Write a brand's design tokens from a key patch or a whole design.md document.",id:"updateBrandTokens",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"media",description:"Change a saved cast preset's name, presenter, backdrop, or voice. Sends the complete preset, not a patch.",id:"updateCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset update",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Edit a document's body, title or summary under an optimistic lock.",id:"updateDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document update",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Update avatar, voice, music, captions, format, and renderer settings for a presentation-video project.",id:"updatePresentationVideoSettings",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video settings",operation:"mutation",scopes:["presentations:write"],state:"available"}];function Ot(e){return{capabilities:qo,catalogVersion:1,reason:e,source:"snapshot"}}async function at(e=Yr){try{let{capabilities:t,catalogVersion:n}=await e();return!Array.isArray(t)||t.length===0?Ot("the live catalog returned no capabilities"):{capabilities:t,catalogVersion:n,source:"live"}}catch(t){let n=t instanceof Error?t.message:String(t);return Ot(n)}}import{InvalidArgumentError as Zs}from"commander";function b(e,t){return n=>{if(t.includes(n))return n;throw new Zs(`Expected one of: ${t.join(", ")}. Run the command with --help to see what ${e} accepts.`)}}var Uo=["presentations","media","branding","knowledge","research","artifacts","agents"],td=80,nd=30;function rd(e){return e.billing!==void 0&&e.billing!=="free"&&e.billing!=="quota"}function od(e){return e.lifecycle?.mode==="background"}function id(e,t){if(t<=0)return[e];let n=[],r="";for(let o of e.split(/\s+/).filter(Boolean))r===""?r=o:r.length+1+o.length<=t?r=`${r} ${o}`:(n.push(r),r=o);return r!==""&&n.push(r),n.length>0?n:[""]}function jo(e){let t=Uo.indexOf(e);return t===-1?Uo.length:t}function ad(e,t){let n=t.search?.trim().toLowerCase(),r=t.category?.trim().toLowerCase();return e.filter(o=>r&&(o.category??"").toLowerCase()!==r?!1:n?`${o.name} ${o.description??""}`.toLowerCase().includes(n):!0)}function sd(e){let t=new Map;for(let i of e){let a=i.category??"other",d=t.get(a);d?d.push(i):t.set(a,[i])}let n=[...t.entries()].sort(([i],[a])=>{let d=jo(i)-jo(a);return d!==0?d:i.localeCompare(a)}),r=Math.min(nd,Math.max(...e.map(i=>i.name.length))),o=[];for(let[i,a]of n){a.sort((d,l)=>d.name.localeCompare(l.name)),o.length>0&&o.push(""),o.push(st.bold(`${i} (${a.length})`));for(let d of a){let l=`${rd(d)?"$":" "}${od(d)?"*":" "}`,y=d.name.padEnd(r),p=2+r+1+l.length+1,w=Math.max(24,td-p),v=id(d.description??"",w);o.push(` ${st.cyan(y)} ${st.yellow(l)} ${v[0]??""}`.trimEnd());for(let C of v.slice(1))o.push(`${" ".repeat(p)}${C}`)}}return o}function dd(e){return e.map(t=>`${t.name} ${t.state} ${t.milestone}`)}function cd(e,t={filtered:!1}){if(e.length===0)return[t.filtered?"No capabilities match that filter.":"No capabilities available."];if(!e.some(i=>i.description||i.category))return dd(e);let r=m.commands[0],o=sd(e);return o.push(""),o.push(st.dim(`${e.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(st.dim(`Filter with: ${r} capabilities --search <query>`)),o}var Mo=new ed("capabilities").description("Index of everything this CLI can do \u2014 every command, grouped and described").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("-s, --search <query>","Only show capabilities matching a query").option("--category <name>","Only show one category").action(async e=>{try{let t=await at(),n=ad(t.capabilities,e),r=!!(e.search||e.category);if(e.format==="json"){u({capabilities:n,catalogVersion:t.catalogVersion,source:t.source,...t.reason?{sourceReason:t.reason}:{}});return}if(e.format==="quiet"){for(let o of n)console.log(o.name);return}t.source==="snapshot"&&M(`Showing the capability list baked into this CLI build (${t.reason}); the deployed catalog may have moved on.`);for(let o of cd(n,{filtered:r}))console.log(o)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdirSync as pd,writeFileSync as gd}from"fs";import{dirname as Bo,join as fd}from"path";import{Command as ve}from"commander";import dt from"chalk";import{input as hd,password as yd,confirm as Wo,select as bd}from"@inquirer/prompts";import _t from"ora";import ld from"conf";var Pt=new ld({projectName:"conceptcraft",configName:"feature-cache"}),md=3600*1e3,ud=1440*60*1e3;function Fo(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t=t&t}return t.toString(16)}function Vo(){if(!Ne())return null;let e=Pt.get("featureFlags");if(!e)return null;let t=Fo(ge());if(e.apiKeyHash&&e.apiKeyHash!==t)return Ae(),null;let n=Date.now()-e.fetchedAt;return n>ud?null:(n>md&&Rn(),e.flags)}function Rn(){Ee().catch(()=>{})}async function Ee(){let e=await uo(),t=ge();return Pt.set("featureFlags",{flags:e,fetchedAt:Date.now(),apiKeyHash:t?Fo(t):void 0}),e}function Ae(){Pt.delete("featureFlags")}function Go(){return Pt.path}var Ko=new ve("config").description("Manage CLI configuration: account settings, and the cached feature flags that decide which commands appear").addCommand(new ve("init").description("Initialize configuration interactively").action(async()=>{console.log(),console.log(dt.bold(`${m.displayName} CLI Configuration`)),console.log(dt.gray("\u2500".repeat(35))),console.log();try{let e=await yd({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":bn(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(pn(e.trim()),await Wo({message:`Use a custom API URL? (default: ${m.apiUrl.replace("https://","")})`,default:!1})){let r=await hd({message:"Enter API URL:",default:B(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});gn(r)}console.log();let n=_t("Verifying API key...").start();try{let r=await ye();if(n.succeed("API key verified!"),console.log(),g(`Logged in as: ${r.user.email}`),r.teams.length===0)M("No teams found for this user.");else if(r.teams.length===1){let o=r.teams[0];De(o.id),g(`Team: ${o.name} (${o.planName})`)}else{console.log(),g(`You have access to ${r.teams.length} teams.`);let o=await bd({message:"Select your default team:",choices:r.teams.map(a=>({name:`${a.name} (${a.planName}) - ${a.role}${a.isCurrent?" [current]":""}`,value:a.id})),default:r.currentTeam?.id});De(o);let i=r.teams.find(a=>a.id===o);x(`Selected team: ${i?.name}`)}try{await Ee()}catch{}}catch(r){n.fail("Failed to verify API key"),M(`Could not verify API key: ${r instanceof Error?r.message:String(r)}`),M(`You may need to set the team ID manually: ${m.commands[0]} config set team-id <id>`)}console.log(),x("Configuration saved!"),g(`Config file: ${ot()}`),console.log()}catch(e){if(e.name==="ExitPromptError"){console.log(),g("Configuration cancelled.");return}throw e}})).addCommand(new ve("show").description("Show current configuration").option("--verify","Verify API key and show team details").action(async e=>{let t=Tr();if(ie("Current Configuration"),console.log(),R("API Key",Vr()??dt.red("Not set")),R("API URL",t.apiUrl),R("Default Team ID",t.defaultTeamId??dt.gray("Not set")),console.log(),R("Config file",ot()),e.verify&&t.apiKey){console.log();let n=_t("Verifying...").start();try{let r=await ye();n.succeed("Verified"),console.log(),R("User",r.user.email),r.currentTeam&&R("Current Team",`${r.currentTeam.name} (${r.currentTeam.planName})`),r.teams.length>1&&R("Total Teams",String(r.teams.length))}catch(r){n.fail("Verification failed"),M(r instanceof Error?r.message:String(r))}}console.log()})).addCommand(new ve("set").description("Set a configuration value").argument("<key>","Configuration key (api-key, api-url, team-id)").argument("<value>","Value to set").action(async(e,t)=>{switch(e){case"api-key":bn(t)||(s("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),pn(t),Ae(),x("API key updated"),Ee().catch(()=>{});break;case"api-url":try{new URL(t),gn(t),x(`API URL set to: ${t}`)}catch{s("Invalid URL format"),process.exit(6)}break;case"team-id":De(t),x(`Default team ID set to: ${t}`);break;default:s(`Unknown config key: ${e}`),console.log(dt.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new ve("clear").description("Clear all configuration").action(async()=>{try{await Wo({message:"Are you sure you want to clear all configuration?",default:!1})?(It(),Ae(),x("Configuration cleared")):g("Cancelled")}catch{g("Cancelled")}})).addCommand(new ve("refresh").description("Refresh cached feature flags").action(async()=>{let e=_t("Refreshing feature flags...").start();try{await Ee(),e.succeed("Feature flags refreshed"),g(`Run '${m.commands[0]} --help' to see updated commands`)}catch(t){e.fail("Failed to refresh"),s(t instanceof Error?t.message:String(t)),process.exit(1)}})).addCommand(new ve("path").description("Show configuration file path").option("--cache","Show feature cache file path").action(e=>{e.cache?console.log(Go()):console.log(ot())})).addCommand(new ve("pull").description("Pull your account settings (memory, brand, prefs) into a local config.toml").action(async()=>{let e=_t("Pulling settings...").start();try{let t=await he(),n=await fetch(`${B()}/api/cli/settings`,{headers:t});if(!n.ok)throw new Error(`Request failed (HTTP ${n.status})`);let r=await n.text(),o=fd(Bo(ot()),"settings.toml");pd(Bo(o),{recursive:!0}),gd(o,r,"utf8"),e.succeed("Settings pulled"),g(`Written to ${o}`)}catch(t){e.fail("Failed to pull settings"),s(t instanceof Error?t.message:String(t)),process.exit(1)}}));import{Command as wd}from"commander";import{confirm as vd}from"@inquirer/prompts";var Jo=new wd("delete").description("Delete a presentation").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --force","Skip confirmation prompt").option("-q, --quiet","Suppress output").action(async(e,t)=>{if(await O(),!t.force)try{if(!await vd({message:`Are you sure you want to delete presentation "${e}"?`,default:!1})){t.quiet||M("Deletion cancelled");return}}catch{t.quiet||M("Deletion cancelled");return}try{await oo(e),t.quiet||x(`Presentation "${e}" deleted`)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as je}from"commander";import Xo from"chalk";import xd from"ora";import{createParser as Gf}from"eventsource-parser";import Wf from"chalk";import Jf from"ora";async function zo(e,t={}){let n=e.body?.getReader();if(!n)throw new Error("Response body is not readable");let r=new TextDecoder,o="",i=!1;for(;!i;){let a=await n.read();if(i=a.done,a.value){let d=r.decode(a.value,{stream:!0});o+=d,t.quiet||process.stdout.write(d)}}return t.quiet||console.log(),o}function kd(){return new je("blog").description("Generate a blog post from a presentation").argument("<slug>","Presentation slug").option("--words <count>","Target word count (50-2000)","300").option("--tone <tone>","Writing tone (professional, casual, educational)","professional").option("--audience <text>","Target audience description").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").option("--instructions <text>","Custom instructions for the blog").option("--no-images","Exclude image references").option("--toc","Include table of contents").action(async(e,t)=>{await O();let n=parseInt(t.words,10);(Number.isNaN(n)||n<50||n>2e3)&&(s("Word count must be between 50 and 2000"),process.exit(6));let r=["professional","casual","educational"];r.includes(t.tone)||(s(`Invalid tone. Valid options: ${r.join(", ")}`),process.exit(6));let o=xd("Fetching presentation...").start();try{let i=await Ue(e);o.text="Generating blog post...";let a=await po(i.id,i.documentCreatedAt||i.createdAt,{targetWordCount:n,tone:t.tone,targetAudience:t.audience??"General Audience",customInstructions:t.instructions??"",includeImages:!t.noImages,includeTableOfContents:t.toc??!1}),d=await zo(a,{quiet:!0});o.succeed("Blog generated"),t.format==="json"?console.log(JSON.stringify({presentationId:e,title:i.title,wordCount:n,tone:t.tone,content:d},null,2)):t.format==="markdown"?console.log(d):(console.log(),console.log(Xo.bold(`Blog: ${i.title}`)),console.log(Xo.gray("\u2500".repeat(40))),console.log(),console.log(d),console.log())}catch(i){o.fail("Generation failed"),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})}function Cd(){return new je("tweets").description("Generate tweets from a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of tweets to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(e,t)=>{await O(),g("Tweet generation coming soon.")})}function Id(){return new je("linkedin").description("Generate a LinkedIn carousel from a presentation").argument("<slug>","Presentation slug").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O(),g("LinkedIn carousel generation coming soon.")})}function Rd(){return new je("questions").description("Generate questions for a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of questions","10").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(e,t)=>{await O(),g("Question generation coming soon.")})}function Sd(){return new je("cheatsheet").description("Generate a presenter cheat sheet").argument("<slug>","Presentation slug").option("--mode <mode>","Cheat sheet mode (qa-prep, talking-points)","qa-prep").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").action(async(e,t)=>{await O(),g("Cheat sheet generation coming soon.")})}function Ho(){let e=new je("derive").description("Generate derivative content from a presentation"),t=Vo();return t&&(t.deckToBlog&&e.addCommand(kd()),t.deckToTweets&&e.addCommand(Cd()),t.linkedInCarousel&&e.addCommand(Id()),t.redTeamQuestions&&e.addCommand(Rd()),t.presenterCheatSheet&&e.addCommand(Sd())),e}import{Command as $d}from"commander";import Sn from"chalk";var Yo=new $d("ideas").description("Generate presentation topic ideas").option("--context <text>","Custom context for idea generation").option("--count <n>","Number of ideas to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O(),g("Idea generation is available in the web dashboard."),console.log(),console.log(Sn.gray("The CLI will support idea generation in a future release.")),console.log(),console.log("For now, try these approaches:"),console.log(Sn.gray("` 1. Visit the ${brand.displayName} dashboard and use the idea generator`")),console.log(Sn.gray(" 2. Create a presentation with a broad topic and refine it")),console.log()});import{Command as Td}from"commander";import{readFile as Ed}from"fs/promises";import{resolve as Ad,basename as Od}from"path";import Pd from"ora";var Qo=new Td("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");Qo._hidden=!0;var Zo=Qo.option("--dry-run","Validate without importing").option("--overwrite","Overwrite existing presentations").option("--remap-ids","Generate new IDs (default: true)",!0).action(async(e,t)=>{await O();try{(await ye()).user.role!=="admin"&&(s("This command is only available to administrators"),process.exit(2))}catch{s("Failed to verify permissions"),process.exit(2)}let n=Ad(e),r=Od(n);r.endsWith(".zip")||(s("File must be a ZIP archive"),process.exit(6));let o=Pd("Reading file...").start();try{let i=await Ed(n);t.dryRun?o.text="Validating...":o.text="Importing presentation...";let a=await so(i,r,{dryRun:t.dryRun});if(a.success){if(t.dryRun)o.succeed("Validation passed!"),console.log(),g("The file is valid and can be imported."),a.statistics&&(console.log(),R("Slides",String(a.statistics.slidesImported)),R("Images",String(a.statistics.imagesUploaded)));else if(o.succeed("Import complete!"),console.log(),R("Presentation ID",a.presentationId??"N/A"),R("Document ID",a.documentId??"N/A"),a.statistics&&(R("Slides imported",String(a.statistics.slidesImported)),R("Images uploaded",String(a.statistics.imagesUploaded)),R("Time",`${a.statistics.totalTimeMs}ms`)),a.presentationId){let d=B();R("View URL",`${d}/p/${a.presentationId}`)}if(a.warnings&&a.warnings.length>0){console.log();for(let d of a.warnings)M(d)}console.log()}else{if(o.fail("Import failed"),console.log(),a.errors)for(let d of a.errors)s(`${d.type}: ${d.message}`);process.exit(1)}}catch(i){o.fail("Import failed"),i.code==="ENOENT"&&(s(`File not found: ${n}`),process.exit(3)),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}});import{Command as _d}from"commander";var ei=new _d("list").description("List presentations").option("-n, --limit <count>","Number of results to return","20").option("-f, --format <format>","Output format (table, json, ids)",b("--format",["table","json","ids"]),"table").option("--sort <field>","Sort by field (created, updated, title)").option("--team-id <id>","Team ID (uses default if not specified)").option("-d, --detail","Show detailed output including URLs").option("-l, --language <lang>","Language for URLs","en").action(async e=>{await O();let t=parseInt(e.limit,10);(Number.isNaN(t)||t<1)&&(s("Invalid limit value"),process.exit(6));let n=e.teamId??Ct();n||(s("`Team ID required. Set a default with '${brand.commands[0]} config set team-id <id>' or use --team-id`"),process.exit(6));try{let r=await to(n,t);if(r.length===0){e.format==="json"?console.log(JSON.stringify([])):e.format!=="ids"&&g("No presentations found");return}switch(e.sort&&r.sort((o,i)=>{switch(e.sort){case"created":return new Date(i.createdAt).getTime()-new Date(o.createdAt).getTime();case"title":return(o.title||"").localeCompare(i.title||"");default:return 0}}),e.format){case"json":console.log(JSON.stringify(r,null,2));break;case"ids":console.log(qr(r));break;default:console.log(Nr(r,{showLinks:e.detail,language:e.language}));break}}catch(r){s(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});import{createHash as Ld,randomBytes as ri}from"crypto";import oi from"http";import ti from"chalk";import{Command as Dd}from"commander";import Nd from"open";import ni from"ora";var qd=`${m.displayName} CLI`,Ud=8765,jd=8775,Md=["presentations:read","presentations:write","media:read","media:write"];function Fd(){return ri(32).toString("base64url")}function Vd(e){return Ld("sha256").update(e).digest("base64url")}function Gd(){return ri(16).toString("hex")}async function Bd(e,t){for(let n=e;n<=t;n++)try{return await new Promise((r,o)=>{let i=oi.createServer();i.listen(n,()=>{i.close(()=>r())}),i.on("error",o)}),n}catch{}throw new Error(`No available port found between ${e} and ${t}`)}async function Wd(e){let t=await fetch(`${e}/.well-known/oauth-authorization-server`);if(!t.ok)throw new Error(`Failed to fetch OAuth metadata: ${t.status}`);return t.json()}function Kd(e){let t=e.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(t?.length?t:Md).join(" ")}async function Jd(e,t,n){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:qd,redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none",scope:n})});if(!r.ok){let o=await r.text();throw new Error(`Client registration failed: ${o}`)}return r.json()}async function zd(e,t,n,r,o){let i=new URLSearchParams({grant_type:"authorization_code",code:t,redirect_uri:r,client_id:o,code_verifier:n}),a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!a.ok){let d=await a.text();throw new Error(`Token exchange failed: ${d}`)}return a.json()}function Xd(e,t){return new Promise((n,r)=>{let o,i=!1,a=()=>{i||(i=!0,clearTimeout(o),process.off("SIGINT",d),process.off("SIGTERM",d),l.close())},d=()=>{a(),r(new Error("Login cancelled"))},l=oi.createServer((y,p)=>{let w=new URL(y.url||"",`http://localhost:${e}`);if(w.pathname!=="/callback"){p.writeHead(404),p.end("Not found");return}let v=w.searchParams.get("code"),C=w.searchParams.get("state"),E=w.searchParams.get("error"),k=w.searchParams.get("error_description");if(p.writeHead(200,{"Content-Type":"text/html"}),E){p.end(`
3
+ var g={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"CLI tool for Mindframes presentation generation",commands:["mf","mindframes"],apiUrl:"https://www.mindframes.app",docsUrl:"https://docs.mindframes.ai",packageName:"@conceptcraft/mindframes",configDir:".mindframes",apiKeyEnvVar:"MINDFRAMES_API_KEY",apiUrlEnvVar:"MINDFRAMES_API_URL",codexSelfConnectorAppId:"asdk_app_6a2b9629c1608191970dcb3ab374ac55"};import B from"chalk";import{Command as Tx}from"commander";import Kt from"chalk";import{Command as gu}from"commander";function zi(t={}){let e=(c,p)=>{let f=t[c];return f&&f.trim().length>0?f.trim():p},n=e("NEXT_PUBLIC_PRODUCT_SHORT_NAME","ConceptCraft"),r=e("NEXT_PUBLIC_CLI_COMMAND","ccr"),o=e("NEXT_PUBLIC_CLI_COMMAND_FULL","conceptcraft"),i=e("NEXT_PUBLIC_CLI_CONFIG_DIR",`.${o}`),s=n.toUpperCase().replace(/[^A-Z0-9]/g,"_");return{id:o,name:i.replace(/^\./,""),displayName:n,description:`CLI tool for ${n} presentation generation`,commands:[r,o],apiUrl:e("NEXT_PUBLIC_API_URL","http://localhost:3000"),docsUrl:e("NEXT_PUBLIC_DOCS_URL",`https://docs.${n.toLowerCase()}.ai`),packageName:e("NEXT_PUBLIC_CLI_PACKAGE_NAME","@conceptcraft/cli"),configDir:i,apiKeyEnvVar:`${s}_API_KEY`,apiUrlEnvVar:`${s}_API_URL`,codexSelfConnectorAppId:t.NEXT_PUBLIC_CODEX_SELF_CONNECTOR_APP_ID?.trim()||void 0}}var u=typeof g<"u"&&g?g:zi(process.env);import U from"chalk";import Mr from"cli-table3";import _m from"conf";import Hi from"path";var Yi=u.apiUrl,Lm={apiKey:{type:"string"},apiUrl:{type:"string",default:Yi},defaultTeamId:{type:"string"},accessToken:{type:"string"},refreshToken:{type:"string"},tokenExpiresAt:{type:"number"},clientId:{type:"string"},clientSecret:{type:"string"}};function Um(t=u.apiKeyEnvVar){return t.endsWith("_API_KEY")?`${t.slice(0,-8)}_CONFIG_DIR`:`${t}_CONFIG_DIR`}function jm(t=process.env){let e=Um(),n=t[e]?.trim()||t.CC_SLIDES_CONFIG_DIR?.trim();if(n){if(!Hi.isAbsolute(n))throw new Error(`${e} must be an absolute directory path`);return Hi.normalize(n)}}var Xi=jm(),L=new _m({projectName:u.name,schema:Lm,...Xi?{configFileMode:384,cwd:Xi}:{}});function Qi(){return{apiKey:Se(),apiUrl:W(),defaultTeamId:L.get("defaultTeamId"),accessToken:L.get("accessToken"),refreshToken:L.get("refreshToken"),tokenExpiresAt:L.get("tokenExpiresAt"),clientId:L.get("clientId"),clientSecret:L.get("clientSecret")}}function Se(){let t=process.env[u.apiKeyEnvVar]??process.env.CC_SLIDES_API_KEY;return t||L.get("apiKey")}function qr(t){L.set("apiKey",t)}function W(){let t=process.env[u.apiUrlEnvVar]??process.env.CC_SLIDES_API_URL;return t||(L.get("apiUrl")??Yi)}function Vr(t){L.set("apiUrl",t)}function ee(){return L.get("defaultTeamId")}function ot(t){L.set("defaultTeamId",t)}function kn(){L.clear()}function Ft(){return L.path}function it(){return!!Se()}function Zi(){return L.get("accessToken")}function ea(){return L.get("refreshToken")}function Rn(t,e,n){L.set("accessToken",t),L.set("refreshToken",e),L.set("tokenExpiresAt",Date.now()+(n-60)*1e3)}function Cn(){L.delete("accessToken"),L.delete("refreshToken"),L.delete("tokenExpiresAt")}function ta(){let t=L.get("tokenExpiresAt");return t?Date.now()>=t:!0}function Ke(){return!!L.get("accessToken")&&!!L.get("refreshToken")}function na(){return L.get("clientId")}function ra(){return L.get("clientSecret")}function oa(t,e){L.set("clientId",t),L.set("clientSecret",e)}function k(t,e="human"){e!=="quiet"&&e!=="json"&&console.log(U.green("\u2713"),t)}function a(t,e="human"){if(e!=="quiet"){if(e==="json"){console.error(JSON.stringify({error:t}));return}console.error(U.red("\u2717"),t)}}function _(t,e="human"){e!=="quiet"&&e!=="json"&&console.warn(U.yellow("\u26A0"),t)}function ia(t,e="human"){e==="quiet"||e==="json"||console.error(U.cyan("\u2192"),t)}function w(t,e="human"){e!=="quiet"&&e!=="json"&&console.log(U.blue("\u2139"),t)}function at(t,e="en"){return t?`${W()}/${e}/view/presentations/${t}`:"N/A"}function aa(t,e={}){let{showLinks:n=!1,language:r="en"}=e,o=(c,p)=>c.length>p?`${c.slice(0,p-1)}\u2026`:c,i=c=>{if(!c)return"-";try{return new Date(c).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).replace(" at ",", ")}catch{return"-"}};if(n){let c=new Mr({head:[U.cyan("Slug"),U.cyan("Title"),U.cyan("Slides"),U.cyan("Created"),U.cyan("URL")]});for(let p of t)c.push([o(p.slug||p.id.slice(0,8),30),o(p.title||"Untitled",22),String(p.numberOfSlides||"-"),i(p.createdAt),at(p.slug,r)]);return c.toString()}let s=new Mr({head:[U.cyan("Slug"),U.cyan("Title"),U.cyan("Slides"),U.cyan("Mode"),U.cyan("Created")],colWidths:[32,28,8,11,18]});for(let c of t)s.push([c.slug||c.id.slice(0,8),c.title||"Untitled",String(c.numberOfSlides||"-"),c.mode||"-",i(c.createdAt)]);return s.toString()}function sa(t){let e=[...t].sort((o,i)=>{if(o.isDefault&&!i.isDefault)return-1;if(!o.isDefault&&i.isDefault)return 1;let s=o.createdAt?new Date(o.createdAt).getTime():0;return(i.createdAt?new Date(i.createdAt).getTime():0)-s}),n=o=>{if(!o)return"-";try{return new URL(o).href}catch{return o.startsWith("http")?o:`https://${o}`}},r=new Mr({head:[U.cyan("Name"),U.cyan("Source"),U.cyan("Color"),U.cyan("Logo"),U.cyan("Default"),U.cyan("ID")]});for(let o of e){let i=o.primaryColor?`${U.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"-";r.push([o.name,n(o.sourceUrl),i,o.logoUrl?U.green("\u2713"):U.gray("\u2717"),o.isDefault?U.green("\u2605"):"",o.id])}return r.toString()}function Fr(t){try{return new Date(t).toLocaleString()}catch{return t}}function ge(t){console.log(),console.log(U.bold(t)),console.log(U.gray("\u2500".repeat(t.length)))}function C(t,e){console.log(` ${U.gray(`${t}:`)} ${e??"-"}`)}function qm(t){return JSON.stringify(t,null,2)}function l(t){console.log(qm(t))}import{createHash as Jr,randomUUID as st}from"crypto";import{readFileSync as ba,statSync as wa}from"fs";import{basename as Hr}from"path";import{spawnSync as Vm}from"child_process";import{existsSync as Mm,mkdtempSync as Fm,rmSync as Bm,writeFileSync as Gm}from"fs";import{tmpdir as Wm}from"os";import{join as da}from"path";import Br from"ffmpeg-static";var Km=/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/;function Jm(t){let e=Km.exec(t);if(!e)return;let n=Number(e[1])*3600+Number(e[2])*60+Number(e[3]);return Number.isFinite(n)&&n>0?n:void 0}function ca(t,e="audio"){if(t.length===0)return;let n=Br&&Mm(Br)?Br:"ffmpeg",r=/^[a-z0-9]+$/i.test(e)?e:"audio",o=Fm(da(Wm(),"mf-tts-duration-")),i=da(o,`speech.${r}`);try{Gm(i,t);let s=Vm(n,["-hide_banner","-i",i],{encoding:"utf8"});return s.error?void 0:Jm(s.stderr??"")}finally{Bm(o,{force:!0,recursive:!0})}}import Sn from"chalk";var d={SUCCESS:0,GENERAL_ERROR:1,AUTH_ERROR:2,NOT_FOUND:3,RATE_LIMIT:4,NETWORK_ERROR:5,INVALID_INPUT:6};async function zm(){let t=ea(),e=na(),n=W();if(!t||!e)return null;try{let r=await fetch(`${n}/.well-known/oauth-authorization-server`);if(!r.ok)return null;let o=await r.json(),i=new URLSearchParams({grant_type:"refresh_token",refresh_token:t,client_id:e}),s=ra();s&&i.set("client_secret",s);let c=await fetch(o.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!c.ok)return Cn(),null;let p=await c.json();return Rn(p.access_token,p.refresh_token,p.expires_in),p.access_token}catch{return null}}async function la(){return Ke()?ta()?zm():Zi()||null:null}function Ee(){return Ke()||it()}async function y(){if(!Ee()){let t=u.commands[0],e=u.apiKeyEnvVar;console.error(Sn.red("\u2717 Not authenticated.")),console.error(),console.error(Sn.bold("To authenticate, run:")),console.error(Sn.cyan(` ${t} login`)),console.error(),console.error(Sn.gray(`Or set ${e} environment variable.`)),process.exit(d.AUTH_ERROR)}}function Hm(t){return t.length<=14?"****":`${t.slice(0,10)}...${t.slice(-4)}`}function ma(){let t=Se();if(t)return Hm(t)}function Gr(t){return["cc_slides_","mcp_","cc_sk_","sk_"].some(n=>t.startsWith(n))}import{mkdirSync as Xm,readFileSync as Ym,writeFileSync as Qm}from"fs";import{homedir as Zm}from"os";import{join as ua}from"path";import eu from"ajv/dist/2020.js";var Wr=new Map;function pa(){return ua(Zm(),".conceptcraft","schemas")}function ga(t){return ua(pa(),`${t}.json`)}function tu(t){try{let e=JSON.parse(Ym(ga(t),"utf8"));return typeof e?.catalogVersion=="number"&&e.schema?e:null}catch{return null}}function nu(t,e){try{Xm(pa(),{recursive:!0}),Qm(ga(t),JSON.stringify(e))}catch{}}async function ru(t){let e=Wr.get(t);if(e!==void 0)return e;try{let n=await fa(t),r={catalogVersion:n.catalogVersion,schema:n.operationSchema??n.schema};return nu(t,r),Wr.set(t,r),r}catch{let n=tu(t);return Wr.set(t,n),n}}function ou(t){let e=t.instancePath.replace(/^\//,"").replace(/\//g,"."),n=e.length>0?e:"(root)",r=t.keyword==="additionalProperties"?`: unknown field "${t.params.additionalProperty}"`:`: ${t.message??"invalid value"}`;return`${n}${r}`}async function En(t,e){let n=await ru(t);if(!n)return;let r;try{r=new eu({allErrors:!0,strict:!1}).compile(n.schema)}catch{return}if(r(e))return;let o=(r.errors??[]).slice(0,10).map(ou);throw new Error(`Request does not match the ${t} contract \u2014 ${o.join("; ")}`)}function fe(t,e){let n=t instanceof Error?t.message:"Unknown error";return!e||n.includes(e)?n:`${n} Request ID: ${e}. Resume with the matching status command; do not start a duplicate run.`}function se(t,e={}){let n=t?.code?.trim()||e.defaultCode?.trim()||"",r=t?.message?.trim()||"The run failed without a reported reason.";return n?`[${n}] ${r}`:r}function Kr(t){let e=t.status?.trim().toLowerCase()??"";return!!t.error||e==="failed"||e==="errored"||e==="cancelled"?`${t.runId?.trim()?`Run ${t.runId.trim()}`:"Run"} ${e||"failed"}: ${se(t.error)}`:null}function ha(t){let e=t.projectId??"<project-id>";return/Narration is still missing for \d+ slides?\./.test(t.message)?["Narration is captured from speaker notes when the video project is prepared, so 'presentation video refresh' will not backfill it.",`Fill each empty scene with: ${t.binary} presentation video-narration ${e} --slide-id <slide-id> (scene ids: ${t.binary} presentation video inspect ${e})`].join(`
4
+ `):/Every scene is excluded from the video\./.test(t.message)?`Include a scene again with: ${t.binary} presentation video edit ${e} --edit '{"type":"patch_scene","scene":1,"excluded":false}'`:null}async function $e(){let t=await la();if(t)return{Authorization:`Bearer ${t}`};let e=Se();return e?{"x-api-key":e}:{}}var D=class extends Error{constructor(n,r,o=1,i="operation_failed",s=!1){super(n);this.statusCode=r;this.exitCode=o;this.errorCode=i;this.retryable=s;this.name="ApiError"}statusCode;exitCode;errorCode;retryable},Xr="Idempotency-Key";function iu(t){return t&&t!=="GET"?{[Xr]:st()}:{}}async function he(t,e={}){let n=W();if(!Ee()&&!e.allowUnauthenticated)throw new D(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2,"authentication_required");let r=await $e(),o=`${n}${t}`,i={...r,...iu(e.method),...e.headers};e.body&&!e.stream&&(i["Content-Type"]="application/json");let s={method:e.method??"GET",headers:i};e.body&&(s.body=JSON.stringify(e.body));let c;try{c=await fetch(o,s)}catch(f){throw new D(`Network error: ${f instanceof Error?f.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!c.ok){let f=await c.text().catch(()=>""),h=su(f,c.status),v=1;switch(c.status){case 401:v=2;break;case 403:v=2;break;case 404:v=3;break;case 429:v=4;break;case 500:v=1;break}let x=`[${h.code}] ${h.message}`;throw new D(x,c.status,v,h.code,h.retryable)}return e.stream?c:c.headers.get("content-type")?.includes("application/json")?c.json():c.text()}function au(t){switch(t){case 400:return"invalid_input";case 401:return"authentication_required";case 402:return"insufficient_credits";case 403:return"access_denied";case 404:return"not_found";case 429:return"rate_limited";case 503:return"service_unavailable";default:return"operation_failed"}}function su(t,e){let n=au(e),r=t.trim()||`HTTP ${e}: The request could not be completed.`;try{let o=JSON.parse(t),i=typeof o.error=="object"&&o.error!==null?o.error:void 0;if(o.ok===!1&&typeof i?.code=="string"&&typeof i.message=="string")return{code:i.code,message:i.message,retryable:i.retryable===!0};if(typeof o.error=="string")return{code:/^[a-z][a-z0-9_]+$/.test(o.error)?o.error:n,message:typeof o.message=="string"?o.message:o.error,retryable:e===429||e>=500}}catch{}return{code:n,message:r,retryable:e===429||e>=500}}async function fa(t){return he(`/api/cli/tools/${encodeURIComponent(t)}/schema`)}async function va(){return he("/api/cli/capabilities",{allowUnauthenticated:!0})}async function I(t,e,n){let r=await Yr(n),o=`?teamId=${encodeURIComponent(r)}`;return he(`/api/cli/tool-runs/${encodeURIComponent(t)}/${encodeURIComponent(e)}${o}`)}async function m(t,e,n){let r=await Yr(e.teamId);return he(`/api/cli/tools/${encodeURIComponent(t)}`,{body:{...e,teamId:r},headers:n?{[Xr]:n}:void 0,method:"POST"})}function J(t){return Yr(t)}async function Yr(t){let e=typeof t=="string"&&t.trim()?t.trim():ee()?.trim();if(e)return e;let n=await xe();if(n.currentTeam?.id)return n.currentTeam.id;throw new D("Team ID required. Select a workspace with `mf config set team-id <id>` or pass --team-id.",400,void 0,"invalid_input")}async function Ia(t){return he("/api/llm-connections/profiles",{body:t,method:"POST"})}async function Ie(t,e,n,r=120){let o=0;for(let i=0;r===null||i<r;i++){let s;try{s=await I(t,e,n),o=0}catch(c){if(c instanceof D&&c.retryable&&o<2){o+=1,await new Promise(p=>setTimeout(p,2e3));continue}throw c instanceof D?new D(`${c.message} Request ID: ${e}.`,c.statusCode,c.exitCode,c.errorCode,c.retryable):new D(`${c instanceof Error?c.message:"Unknown error"} Request ID: ${e}.`,0,5,"poll_failed",!0)}if(s.done){if(s.error)throw new D(`${se(s.error,{defaultCode:"operation_failed"})} Request ID: ${e}.`,500,1,s.error.code??"operation_failed",s.error.retryable);return s}await new Promise(c=>setTimeout(c,(s.nextPollAfterSeconds??2)*1e3))}throw new D(`[operation_timed_out] The background operation timed out. Request ID: ${e}.`,408,1,"operation_timed_out",!0)}function $n(t){return t.error||t.status==="failed"||t.status==="errored"||t.status==="cancelled"?"failed":t.done||t.status==="completed"?"completed":t.status==="in_progress"?"processing":"pending"}function du(t){try{let n=new URL(t).pathname.split("/").pop()?.split(".").pop()?.toLowerCase();return n&&/^[a-z0-9]+$/.test(n)?n:void 0}catch{return}}function Tn(t){let e=t.toLowerCase().split(".").pop();return{pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",mp4:"video/mp4",mov:"video/quicktime",mpeg:"video/mpeg",mpg:"video/mpeg",webm:"video/webm",aac:"audio/aac",m4a:"audio/mp4",mp3:"audio/mpeg",oga:"audio/ogg",ogg:"audio/ogg",wav:"audio/wav",txt:"text/plain",md:"text/markdown",csv:"text/csv",json:"application/json",html:"text/html",css:"text/css",js:"application/javascript",ts:"text/x-typescript",py:"text/x-python"}[e||""]||"application/octet-stream"}function Bt(t){let e=wa(t);return{fileName:Hr(t),fileSize:e.size,fileType:Tn(t)}}async function Gt(t,e){let n=Bt(t),r=ba(t),o=new FormData;for(let[s,c]of Object.entries(e.fields))o.append(s,c);o.append("file",new Blob([r],{type:n.fileType}),n.fileName);let i=await fetch(e.uploadUrl,{method:"POST",body:o});if(!i.ok)throw new D("Failed to upload file to storage",i.status,1);return{id:e.fileId??st(),name:n.fileName,s3Key:e.s3Key,url:e.fileUrl,size:n.fileSize,type:n.fileType,selected:!0}}async function de(t,e={}){let n=W();if(!Ee())throw new D(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let r=await $e(),o=wa(t),i=Hr(t),s=Tn(t),c=ba(t),p=Jr("sha256").update(c).digest("hex"),f=await fetch(`${n}/api/cli/files/upload`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({fileMetadata:{lastModified:o.mtimeMs,name:i,type:s,size:o.size},...e.storagePrefix?{storagePrefix:e.storagePrefix}:{},...e.idempotencyKey?{uploadIdentity:{contentSha256:p,idempotencyKey:e.idempotencyKey}}:{}})});if(!f.ok){let v=await f.text();throw new D(v||"Failed to get upload URL",f.status,1)}let h=await f.json();return Gt(t,{...e.idempotencyKey?{fileId:`file-${Jr("sha256").update(JSON.stringify({contentSha256:p,fileName:i,idempotencyKey:e.idempotencyKey})).digest("hex")}`}:{},fields:h.fields||{},fileUrl:h.fileUrl,s3Key:h.uploadKey,uploadUrl:h.url})}async function xa(t,e,n={}){let r=[];for(let o=0;o<t.length;o++){let i=t[o],s=Hr(i);e?.(o,t.length,s);let c=await de(i,{idempotencyKey:n.idempotencyKey});r.push(c)}return e?.(t.length,t.length,""),r}async function ka(t,e,n){let r={};for(let[o,i]of Object.entries(t))i!==void 0&&(r[o]=i);return r.brandingId===void 0&&typeof r.brandId=="string"&&(r.brandingId=r.brandId),delete r.brandId,m("createSlides",{...r,...n?{approvalReceipt:n}:{}},e)}async function Ra(t,e=20,n=0,r="updated"){return(await m("listPresentations",{limit:e,offset:n,sort:r,teamId:t})).presentations}async function dt(t,e){let n=e?.includeSlides!==!1,r=await m("getPresentation",{includeSlides:n,presentationId:t,teamId:e?.teamId});return n?{...r.presentation,slides:r.slides}:r.presentation}async function Ca(t,e,n,r){return he(`/api/cli/presentation/${encodeURIComponent(t)}/speaker-notes?teamId=${encodeURIComponent(r)}`,{body:e,headers:{[Xr]:n},method:"POST"})}async function An(t){let e=W(),n=await fetch(`${e}/api/durable-runs/${encodeURIComponent(t)}/events`,{headers:await $e()});if(!n.ok)throw new D(await n.text(),n.status);return n}async function Sa(t,e={}){await m("deletePresentation",{approvalReceipt:e.approvalReceipt,presentationId:t,teamId:e.teamId},e.idempotencyKey??`cli:presentation:delete:${Jr("sha256").update(JSON.stringify({slugOrId:t,teamId:e.teamId??null})).digest("hex")}`)}async function Ea(t,e){return m("updatePresentationVisibility",{presentationId:t,teamId:e.teamId,visibility:e.visibility},e.idempotencyKey??`cli:presentation:visibility:${st()}`)}async function $a(t,e,n){return m("exportPresentation",{format:e,presentationId:t,teamId:n?.teamId})}async function Ta(t){let e;try{e=await fetch(t)}catch(n){throw new D(`Network error while downloading the export: ${n instanceof Error?n.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!e.ok)throw new D(`[fetch_failed] The export download link returned ${e.status}. Signed links expire after one hour \u2014 re-run the export.`,e.status,1,"fetch_failed",!0);return e.arrayBuffer()}async function Aa(t,e,n={}){let r=W();if(!Ee())throw new D(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await $e(),i=new FormData,s=new Blob([t],{type:"application/zip"});i.append("file",s,e),i.append("options",JSON.stringify({dryRun:n.dryRun??!1,remapIds:!0}));let c=await fetch(`${r}/api/presentations/import`,{method:"POST",headers:o,body:i}),p=await c.json();if(!c.ok)throw new D(p.errors?.[0]?.message??"Import failed",c.status,1);return p}async function Pa(t,e=25){return m("listSlideTemplates",{limit:e,search:t})}async function Oa(t,e,n,r,o){return m("extractBranding",{approvalReceipt:n,skipExistingBrandingLookup:r,teamId:e,url:t},o)}async function xe(){return he("/api/cli/whoami")}async function Da(){return he("/api/cli/features")}async function Na(t,e,n={}){let r=W();if(!Ee())throw new D(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await $e(),i=await fetch(`${r}/api/presentations/${t}/generate-blog`,{method:"POST",headers:{"Content-Type":"application/json",...o},body:JSON.stringify({documentCreatedAt:e,targetWordCount:n.targetWordCount??300,tone:n.tone??"professional",language:n.language??"en",targetAudience:n.targetAudience??"General Audience",blogFormat:n.blogFormat??"narrative",customInstructions:n.customInstructions??"",includeImages:n.includeImages??!0,includeTableOfContents:n.includeTableOfContents??!1})});if(!i.ok)throw new D(await i.text(),i.status,i.status===404?3:1);return i}async function Qr(t){return m("getGenerationLimits",{teamId:t})}async function _a(t,e,n){let r=await Qr(n);if(!r.canGenerate[t]){let o=r.remaining[t]??0,i=r.limits[t]??0;throw i===0?new D(`The "${t}" mode is not available on your ${r.planName} plan. Available modes: ${r.availableModes.join(", ")||"none"}`,403,2):new D(`You have reached your ${t} generation limit for this billing cycle (${r.usage[t]??0}/${i} used). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,4)}if(r.maxSlidesPerPresentation!==-1&&e>r.maxSlidesPerPresentation)throw new D(`Maximum ${r.maxSlidesPerPresentation} slides allowed on your ${r.planName} plan (requested: ${e}). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,6);return r}function cu(t){return t.replace(/[\u2014\u2013]/g,"-").replace(/[\u201C\u201D]/g,'"').replace(/[\u2018\u2019]/g,"'").replace(/\u2026/g,"...").replace(/\u00A0/g," ").replace(/[\u2010-\u2015]/g,"-").replace(/[\u2032\u2033]/g,"'")}async function La(t){let e={...t,text:cu(t.text)};await En("generateSpeech",e);let n=await m("generateSpeech",{approvalReceipt:"cli:tts-generate",...e}),r=await Ie("generateSpeech",n.runId),o=r.entity?.url;if(!o)throw new D(`Speech completed without an audio URL. Request ID: ${n.runId}.`,500);let i;try{i=await fetch(o)}catch(v){throw new D(`${v instanceof Error?v.message:"Failed to download speech audio"} Request ID: ${n.runId}.`,0,5,"download_failed",!0)}if(!i.ok)throw new D(`Failed to download speech audio. Request ID: ${n.runId}.`,i.status,5,"download_failed",i.status===429||i.status>=500);let s=r.output??{},c=t.options??{},p=ve(s.format)??du(o)??"mp3",f=Buffer.from(await i.arrayBuffer()),h=Ua(s.durationSec,s.duration,s.duration_s)??ca(f,p);if(h===void 0)throw new D(`Speech completed without a measurable duration. Request ID: ${n.runId}.`,500,1,"invalid_audio_metadata");return{audioData:f,audioUrl:o,duration:h,provider:ve(s.provider)??c.provider??"gemini",format:p,requestId:n.runId,voiceId:ve(s.voice_id)??ve(s.voiceId),voice:ve(s.voice),model:ve(s.model),speed:zr(s.speed)??c.speed,language:ve(s.lang)??ve(s.language)??c.language,langApplied:ya(s.langApplied)??ya(s.lang_applied),timestamps:lu(s.timestamps),wordTimings:mu(s.timestamps??s.timings)}}function Ua(...t){for(let e of t){let n=typeof e=="number"?e:typeof e=="string"&&e.trim()?Number(e):Number.NaN;if(Number.isFinite(n)&&n>0)return n}}function lu(t){if(!t||typeof t!="object"||Array.isArray(t))return;let e=t,n=e.characters,r=e.characterStartTimesSeconds??e.character_start_times_seconds,o=e.characterEndTimesSeconds??e.character_end_times_seconds;if(!(!Array.isArray(n)||!Array.isArray(r)||!Array.isArray(o))&&!(n.length===0||n.length!==r.length||n.length!==o.length||!n.every(i=>typeof i=="string")||!r.every(i=>typeof i=="number"&&Number.isFinite(i))||!o.every(i=>typeof i=="number"&&Number.isFinite(i))))return{characters:n,characterStartTimesSeconds:r,characterEndTimesSeconds:o}}function mu(t){if(!Array.isArray(t))return;let e=t.flatMap(n=>{if(!n||typeof n!="object"||Array.isArray(n))return[];let r=n,o=ve(r.text)??ve(r.word),i=zr(r.start),s=zr(r.end);return o&&i!==void 0&&s!==void 0&&s>=i?[{text:o,start:i,end:s}]:[]});return e.length>0?e:void 0}function ve(t){return typeof t=="string"&&t.trim()?t.trim():void 0}function zr(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function ya(t){return typeof t=="boolean"?t:void 0}async function ja(t){let e=t?`/api/cli/tts?provider=${t}`:"/api/cli/tts";return he(e)}async function qa(t){let e={...t},n=typeof e.idempotency_key=="string"?e.idempotency_key:void 0;return delete e.idempotency_key,await En("generateMusic",e),{requestId:(await m("generateMusic",{...e,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function Zr(t){let e=await I("generateMusic",t);return{requestId:t,status:$n(e),audioUrl:e.entity?.url,duration:Ua(e.output?.durationSec,e.output?.duration,e.output?.duration_s),error:e.error?.message}}async function Va(t){return{requestId:(await m("mixAudio",{...t,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function eo(t){let e=await I("mixAudio",t);return{requestId:t,status:$n(e),outputUrl:e.entity?.url,error:e.error?.message}}async function Ma(t){return he("/api/cli/images/search",{method:"POST",body:t})}async function Fa(t){return he("/api/cli/videos/search",{method:"POST",body:t})}async function ce(t,e=60,n=2e3){let r=0;for(let o=0;o<e;o++){let i;try{i=await t(),r=0}catch(s){if(s instanceof D&&s.retryable&&r<2){r+=1,await new Promise(c=>setTimeout(c,n));continue}throw s}if(i.status==="completed"||i.status==="failed")return i;await new Promise(s=>setTimeout(s,n))}throw new D("Operation timed out",408,1)}async function Ba(t,e,n){return m("getYoutubeTranscript",{...n?{language:n}:{},teamId:e,url:t})}async function Ga(t,e){let n=await m("scrape",{teamId:e,url:t});return{data:{content:n.content,metadata:{description:"",format:"markdown",tokenUsage:Math.ceil(n.content.length/4)},title:n.title??"",url:n.url},success:!0}}async function Wa(t){let e={...t},n=typeof e.idempotency_key=="string"?e.idempotency_key:void 0;delete e.idempotency_key,await En("generateSfx",e);let r=await m("generateSfx",{...e,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function to(t){let e=await I("generateSfx",t);return{id:e.entity?.id??t,requestId:t,status:$n(e),audioUrl:e.entity?.url,error:e.error?.message}}async function Ka(t){return m("listPresenterOptions",{...t?{voiceLanguage:t}:{}})}async function Ja(t){return{requestId:(await m("generateAvatarVideo",{...t,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function no(t){let e=await I("generateAvatarVideo",t);return{durationSec:typeof e.output?.durationSec=="number"?e.output.durationSec:null,error:e.error?.message,requestId:t,status:$n(e),videoUrl:e.entity?.url}}async function za(t){return m("lipsyncVideo",{...t,approvalReceipt:"cli:video-lipsync"})}async function Ha(){return(await m("listTranslationLanguages",{})).languages}async function Xa(t){return m("translateVideo",{...t,approvalReceipt:"cli:video-translate"})}async function Ya(t,e,n){return m("createVideo",{...t,approvalReceipt:e},n)}async function Qa(t){let{idempotencyKey:e,...n}=t;return m("analyzeVideoReference",n,e)}async function Za(t,e){return Ie("analyzeVideoReference",t,e)}async function es(t,e){return Ie("selectPresentationVideoStockMusic",t,e)}async function ts(t,e){return Ie("preparePresentationVideoPreviews",t,e,null)}async function ns(t,e){return Ie("generateBrandVariations",t,e)}async function rs(t,e){return Ie("extractBrandProducts",t,e)}async function os(t,e){return Ie("buildBrandVoice",t,e)}async function is(t,e){return Ie("generateBrandGuardrails",t,e)}async function as(t,e){return Ie("repairBrandQuality",t,e)}async function ss(t,e){return Ie("syncBrandToPresentations",t,e)}async function ds(t){return m("listCastPresets",t)}async function cs(t){return m("createCastPreset",t,st())}async function ls(t){return m("updateCastPreset",t,st())}async function ms(t){return m("deleteCastPreset",{presetId:t},st())}var us=[{billing:"free",category:"branding",description:"Attach a social handle to an accessible brand profile.",id:"addBrandSocialHandle",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding social add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"branding",description:"Add a competitor to an accessible brand profile.",id:"addCompetitor",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding competitor add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"delegated",category:"media",description:"Transcribe an uploaded recording and publish the transcript for generation.",id:"analyzeMediaAsset",lifecycle:{mode:"background",status:{cliCommand:"media analyze status",pollAfterSeconds:10}},milestone:"M8",name:"media analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Analyze an uploaded video before using it as a source, motion, blocking, or pacing reference in a video storyboard. The completed status output includes the analysisId required by the storyboard's source-video binding.",id:"analyzeVideoReference",lifecycle:{mode:"background",status:{cliCommand:"video reference status",pollAfterSeconds:10}},milestone:"M8",name:"video reference analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Branch an immutable footage version into a new project.",id:"branchFootageProjectVersion",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage branch",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"artifacts",description:"Generate and persist an ad variation set.",id:"createAdSet",lifecycle:{mode:"background",status:{cliCommand:"ad-set status",pollAfterSeconds:10}},milestone:"M6",name:"ad-set create",operation:"generation",scopes:["ad-sets:write"],state:"available"},{billing:"free",category:"agents",description:"Create a scheduled agent from a validated configuration.",id:"createAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent create",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"media",description:"Save one way a cast member appears: a personal presenter (pp_* id), a backdrop, and optionally a voice, under a name unique to that person.",id:"createCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Save a markdown, CSV or plain-text document into the Library.",id:"createDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"media",description:"Create a transcript-native, versioned footage edit project.",id:"createFootageProject",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"fixed",category:"media",description:"Generate and persist an image.",id:"createImage",lifecycle:{mode:"background",status:{cliCommand:"image status",pollAfterSeconds:10}},milestone:"M5",name:"image generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Create a Library folder, optionally inside another.",id:"createLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"dynamic",category:"artifacts",description:"Generate and persist a microsite.",id:"createMicrosite",lifecycle:{mode:"background",status:{cliCommand:"microsite status",pollAfterSeconds:10}},milestone:"M6",name:"microsite create",operation:"generation",scopes:["microsites:write"],state:"available"},{billing:"free",category:"artifacts",description:"Create a standalone poll.",id:"createPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll create",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"delegated",category:"presentations",description:"Create an MP4 video from a finished presentation, or render an existing presentation-video project.",id:"createPresentationVideo",lifecycle:{mode:"background",status:{cliCommand:"presentation video status",pollAfterSeconds:10}},milestone:"M4",name:"presentation video",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"fixed",category:"presentations",description:"Generate a presentation and persist the resulting deck.",id:"createSlides",lifecycle:{mode:"background",status:{cliCommand:"presentation status",pollAfterSeconds:20}},milestone:"M4",name:"create",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one video from the opaque text and explicit metadata stored in a pinned storyboard revision.",id:"createVideo",lifecycle:{mode:"background",status:{cliCommand:"video status",pollAfterSeconds:20}},milestone:"M8",name:"video create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a versioned Markdown video storyboard.",id:"createVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"fixed",category:"artifacts",description:"Generate a persisted standalone visual abstract.",id:"createVisualAbstract",lifecycle:{mode:"background",status:{cliCommand:"visual-abstract status",pollAfterSeconds:10}},milestone:"M5",name:"visual-abstract create",operation:"generation",scopes:["visual-abstracts:write"],state:"available"},{billing:"free",category:"media",description:"Retire a saved cast preset. Existing videos keep working; the preset stops being offered.",id:"deleteCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset delete",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Remove a document from the Library.",id:"deleteDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"knowledge",description:"Delete a Library folder and its subfolders. Items inside are unfiled, never deleted.",id:"deleteLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Permanently delete an owned presentation, all of its versions, and its publications.",id:"deletePresentation",lifecycle:{mode:"bounded"},milestone:"M8",name:"presentation delete",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"artifacts",description:"Edit a standalone poll.",id:"editPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll edit",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"free",category:"presentations",description:"Apply one atomic edit to a presentation-video draft.",id:"editPresentationVideoDraft",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video edit",operation:"mutation",scopes:["presentations:write","media:read"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate the narration a presentation-video project is still missing.",id:"ensurePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video narrate status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video narrate",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"presentations",description:"Render an owned presentation to HTML/PDF/PPTX and return a short-lived signed download URL.",id:"exportPresentation",lifecycle:{mode:"bounded"},milestone:"M1",name:"export",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"quota",category:"branding",description:"Extract and persist a reusable brand profile from a URL.",id:"extractBranding",lifecycle:{mode:"background",status:{cliCommand:"branding status",pollAfterSeconds:10}},milestone:"M2",name:"branding extract",operation:"generation",scopes:["brands:write"],state:"available"},{billing:"dynamic",category:"research",description:"Extract normalized text from uploaded or remote content.",id:"extractContent",lifecycle:{mode:"bounded"},milestone:"M1",name:"content extract",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"File an artifact into a Library folder, or unfile it.",id:"fileArtifactIntoFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library file",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Erase every stored version of a scheduled agent's memory. Irreversible.",id:"forgetAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory forget",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one reusable avatar/presenter clip for composition into a video. Accepts a stock avatar id or a personal presenter's pp_* id (from listPresenterOptions' `personal` group) as avatarId.",id:"generateAvatarVideo",lifecycle:{mode:"background",status:{cliCommand:"avatar status",pollAfterSeconds:10}},milestone:"M8",name:"avatar generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate music from final video facts or a trusted direct prompt.",id:"generateMusic",lifecycle:{mode:"background",status:{cliCommand:"music status",pollAfterSeconds:10}},milestone:"M7",name:"music generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate an additional look for an existing personal presenter while preserving the same Cast identity.",id:"generatePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate SFX from final video facts or a trusted direct prompt.",id:"generateSfx",lifecycle:{mode:"background",status:{cliCommand:"sfx status",pollAfterSeconds:10}},milestone:"M7",name:"sfx generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate persisted speaker notes for a presentation version.",id:"generateSpeakerNotes",lifecycle:{mode:"background",status:{cliCommand:"presentation speaker-notes-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation speaker-notes",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate speech audio from text.",id:"generateSpeech",lifecycle:{mode:"background",status:{cliCommand:"tts status",pollAfterSeconds:10}},milestone:"M7",name:"tts generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Read what a scheduled agent has recorded about its own work: learned facts, standing instructions, things it never does, entities it tracks, and freeform notes.",id:"getAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory show",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"branding",description:"List competitors saved for an accessible brand profile.",id:"getBrandCompetitors",lifecycle:{mode:"bounded"},milestone:"M1",name:"branding competitor list",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"branding",description:"Read a brand's design tokens, the keys it is missing, or its design.md document.",id:"getBrandProfile",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding profile",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"media",description:"Read an owned footage project and its append-only versions.",id:"getFootageProject",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage show",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"Read a bounded workspace Knowledge Hub bundle.",id:"getKnowledgeBundle",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge bundle",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search recent news sources.",id:"getNews",lifecycle:{mode:"bounded"},milestone:"M1",name:"search news",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"presentations",description:"Read a presentation and its slides.",id:"getPresentation",lifecycle:{mode:"bounded"},milestone:"M1",name:"get",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"presentations",description:"Read an owned presentation-video project and its ordered scene timeline.",id:"getPresentationVideoProject",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video inspect",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"dynamic",category:"research",description:"Fetch a YouTube video's timestamped transcript with its title, channel, and duration.",id:"getYoutubeTranscript",lifecycle:{mode:"bounded"},milestone:"M1",name:"transcript",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"media",description:"Import a recording from a connected account into the media library.",id:"importConnectorRecording",lifecycle:{mode:"background",status:{cliCommand:"media import status",pollAfterSeconds:5}},milestone:"M8",name:"media import",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Import every completed provider-assisted take, preserving explicit source traceability when proven.",id:"importFootageProviderTakes",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage import-takes",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"presentations",description:"Import an attached PowerPoint as an auditable, review-gated Mindframes presentation.",id:"importPowerPoint",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"media",description:"Create proxy, filmstrip, and waveform evidence for one footage range.",id:"inspectFootageRange",lifecycle:{mode:"background",status:{cliCommand:"footage inspection-status",pollAfterSeconds:2}},milestone:"M8",name:"footage inspect",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"media",description:"Re-voice a ready video with new audio via provider lip-sync (one sibling re-voiced video artifact).",id:"lipsyncVideo",lifecycle:{mode:"background",status:{cliCommand:"video lipsync status",pollAfterSeconds:20}},milestone:"M8",name:"video lipsync",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"List the user's secret-free Claude Code or Codex connection profiles and current selection.",id:"listAiConnectionProfiles",lifecycle:{mode:"bounded"},milestone:"M8",name:"ai-connections list",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"media",description:"List saved ways a cast member appears \u2014 a trained presenter, a backdrop, and optionally a voice, under one name. Filtered to what the caller may actually use.",id:"listCastPresets",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset list",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace's documents, newest first.",id:"listDocuments",lifecycle:{mode:"bounded"},milestone:"M8",name:"document list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List a document's append-only version history.",id:"listDocumentVersions",lifecycle:{mode:"bounded"},milestone:"M8",name:"document versions",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace Library folder tree.",id:"listLibraryFolders",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"presentations",description:"List saved presentation-video draft versions.",id:"listPresentationVideoVersions",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video versions",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral presenter avatars, voices, and voice languages, plus the workspace's trained personal presenters (`personal` roster group, pp_* ids).",id:"listPresenterOptions",lifecycle:{mode:"bounded"},milestone:"M8",name:"avatar options",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"media",description:"List ready generated clips and uploaded MediaAssets while excluding final presentation-to-MP4 renders.",id:"listReusableVideoClips",lifecycle:{mode:"bounded"},milestone:"M8",name:"video library list",operation:"query",scopes:["media:read","presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral target languages for video translation.",id:"listTranslationLanguages",lifecycle:{mode:"bounded"},milestone:"M8",name:"video translate-languages",operation:"query",scopes:["media:read"],state:"available"},{billing:"dynamic",category:"media",description:"Mix voice, music, and sound-effect tracks.",id:"mixAudio",lifecycle:{mode:"background",status:{cliCommand:"mix status",pollAfterSeconds:10}},milestone:"M7",name:"mix create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Move a Library folder under a new parent, or to the top level.",id:"moveLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders move",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Create or reuse a presentation-video project for a finished presentation.",id:"preparePresentationVideo",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video prepare",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Read one document's full body and metadata.",id:"readDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document read",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"media",description:"Read a video storyboard and its immutable revision history.",id:"readVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard show",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"Set or clear the colour of a Library folder.",id:"recolorLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders recolor",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Create a reviewable scheduled-agent recommendation.",id:"recommendAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent recommend",operation:"generation",scopes:["agents:write"],state:"available"},{billing:"free",category:"presentations",description:"Refresh deck-backed video scenes from the latest presentation version.",id:"refreshPresentationVideoSlides",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video refresh",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Regenerate one narration override in a presentation video draft.",id:"regeneratePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video-narration-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video-narration",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Rename a Library folder.",id:"renameLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders rename",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"delegated",category:"media",description:"Render selected outputs from one exact, strategy-approved footage draft version.",id:"renderFootageProject",lifecycle:{mode:"background",status:{cliCommand:"footage render-status",pollAfterSeconds:5}},milestone:"M8",name:"footage render",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Restore an earlier version by appending it as the current one.",id:"restoreDocumentVersion",lifecycle:{mode:"bounded"},milestone:"M8",name:"document restore",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"media",description:"Restore an immutable footage version as a new project head.",id:"restoreFootageProjectVersion",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage restore",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"presentations",description:"Restore a saved presentation-video draft version as a new version.",id:"restorePresentationVideoVersion",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video restore",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"media",description:"Append a semantic revision to a footage edit project.",id:"reviseFootageProject",lifecycle:{mode:"bounded"},milestone:"M8",name:"footage revise",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"media",description:"Create a new presenter Look by editing an existing Look without changing its source.",id:"revisePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look revision-status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look revise",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a new immutable revision of a Markdown video storyboard.",id:"reviseVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard revise",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"research",description:"Read and normalize content from a public URL.",id:"scrape",lifecycle:{mode:"bounded"},milestone:"M1",name:"scrape",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search licensed image providers.",id:"searchImages",lifecycle:{mode:"bounded"},milestone:"M1",name:"search images",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search the public web for current sources.",id:"searchInternet",lifecycle:{mode:"bounded"},milestone:"M1",name:"search web",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"Search workspace Knowledge Hub entries.",id:"searchKnowledge",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge search",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"media",description:"Find videos: licensed stock clips to download, or web videos to embed.",id:"searchStockVideo",lifecycle:{mode:"bounded"},milestone:"M1",name:"search video",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"agents",description:"Select a Claude Code or Codex connection profile, or restore the native provider route.",id:"selectAiConnectionProfile",lifecycle:{mode:"bounded"},milestone:"M8",name:"ai-connections select",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"branding",description:"Point a brand at an already-uploaded logo, dark-background logo variant, or favicon.",id:"setBrandLogo",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding logo set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"presentations",description:"Set one presentation-video scene to a specific avatar/look or saved preset, including the preset voice by default, or restore inheritance from the project default.",id:"setPresentationVideoScenePresenter",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video presenter",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"presentations",description:"Transform an uploaded PowerPoint source into an auditable presentation review.",id:"transformPresentationImport",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import transform",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Translate a ready video into sibling language versions (one video per target language).",id:"translateVideo",lifecycle:{mode:"background",status:{cliCommand:"video translate status",pollAfterSeconds:20}},milestone:"M8",name:"video translate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Add to or remove from what a scheduled agent remembers. Owner or workspace admin only.",id:"updateAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory set",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"branding",description:"Write a brand's design tokens from a key patch or a whole design.md document.",id:"updateBrandTokens",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"media",description:"Change a saved cast preset's name, presenter, backdrop, or voice. Sends the complete preset, not a patch.",id:"updateCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset update",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Edit a document's body, title or summary under an optimistic lock.",id:"updateDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document update",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Update avatar, voice, music, captions, format, and renderer settings for a presentation-video project.",id:"updatePresentationVideoSettings",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video settings",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"agents",description:"Read one safe Agent roster card without private configuration.",id:"getRosterAgent",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent roster get",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"agents",description:"Read one owned Agent and its complete configuration.",id:"getAgent",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent get",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"agents",description:"List the caller's roster: owned Agents plus same-workspace Agents shared with the team.",id:"listAgentRoster",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent roster list",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"agents",description:"List the caller's scheduled Agents with stable cursor pagination.",id:"listAgents",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent list",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"agents",description:"Pause an owned Agent's schedule without changing its configuration.",id:"pauseAgentSchedule",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent pause",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"agents",description:"Resume an owned Agent's saved schedule without changing its configuration.",id:"resumeAgentSchedule",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent resume",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"agents",description:"Share an owned Agent with the workspace or return it to private visibility.",id:"setAgentVisibility",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent visibility set",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"agents",description:"Update an owned Agent's schedule, sources, outputs, delivery, review, runtime, or blueprint configuration.",id:"updateAgentConfiguration",lifecycle:{mode:"bounded"},milestone:"M8",name:"agent configure",operation:"mutation",scopes:["agents:write"],state:"available"}];function Pn(t){return{capabilities:us,catalogVersion:1,reason:t,source:"snapshot"}}async function Wt(t=va){try{let{capabilities:e,catalogVersion:n}=await t();return!Array.isArray(e)||e.length===0?Pn("the live catalog returned no capabilities"):{capabilities:e,catalogVersion:n,source:"live"}}catch(e){let n=e instanceof Error?e.message:String(e);return Pn(n)}}import{InvalidArgumentError as pu}from"commander";function b(t,e){return n=>{if(e.includes(n))return n;throw new pu(`Expected one of: ${e.join(", ")}. Run the command with --help to see what ${t} accepts.`)}}var ps=["presentations","media","branding","knowledge","research","artifacts","agents","support"],fu=80,hu=30;function yu(t){return t.billing!==void 0&&t.billing!=="free"&&t.billing!=="quota"}function bu(t){return t.lifecycle?.mode==="background"}function wu(t,e){if(e<=0)return[t];let n=[],r="";for(let o of t.split(/\s+/).filter(Boolean))r===""?r=o:r.length+1+o.length<=e?r=`${r} ${o}`:(n.push(r),r=o);return r!==""&&n.push(r),n.length>0?n:[""]}function gs(t){let e=ps.indexOf(t);return e===-1?ps.length:e}function vu(t,e){let n=e.search?.trim().toLowerCase(),r=e.category?.trim().toLowerCase();return t.filter(o=>r&&(o.category??"").toLowerCase()!==r?!1:n?`${o.name} ${o.description??""}`.toLowerCase().includes(n):!0)}function Iu(t){let e=new Map;for(let i of t){let s=i.category??"other",c=e.get(s);c?c.push(i):e.set(s,[i])}let n=[...e.entries()].sort(([i],[s])=>{let c=gs(i)-gs(s);return c!==0?c:i.localeCompare(s)}),r=Math.min(hu,Math.max(...t.map(i=>i.name.length))),o=[];for(let[i,s]of n){s.sort((c,p)=>c.name.localeCompare(p.name)),o.length>0&&o.push(""),o.push(Kt.bold(`${i} (${s.length})`));for(let c of s){let p=`${yu(c)?"$":" "}${bu(c)?"*":" "}`,f=c.name.padEnd(r),h=2+r+1+p.length+1,v=Math.max(24,fu-h),x=wu(c.description??"",v);o.push(` ${Kt.cyan(f)} ${Kt.yellow(p)} ${x[0]??""}`.trimEnd());for(let $ of x.slice(1))o.push(`${" ".repeat(h)}${$}`)}}return o}function xu(t){return t.map(e=>`${e.name} ${e.state} ${e.milestone}`)}function ku(t,e={filtered:!1}){if(t.length===0)return[e.filtered?"No capabilities match that filter.":"No capabilities available."];if(!t.some(i=>i.description||i.category))return xu(t);let r=u.commands[0],o=Iu(t);return o.push(""),o.push(Kt.dim(`${t.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(Kt.dim(`Filter with: ${r} capabilities --search <query>`)),o}var fs=new gu("capabilities").description("Index of everything this CLI can do \u2014 every command, grouped and described").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("-s, --search <query>","Only show capabilities matching a query").option("--category <name>","Only show one category").action(async t=>{try{let e=await Wt(),n=vu(e.capabilities,t),r=!!(t.search||t.category);if(t.format==="json"){l({capabilities:n,catalogVersion:e.catalogVersion,source:e.source,...e.reason?{sourceReason:e.reason}:{}});return}if(t.format==="quiet"){for(let o of n)console.log(o.name);return}e.source==="snapshot"&&_(`Showing the capability list baked into this CLI build (${e.reason}); the deployed catalog may have moved on.`);for(let o of ku(n,{filtered:r}))console.log(o)}catch(e){a(e instanceof Error?e.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}});import{mkdirSync as Eu,writeFileSync as $u}from"fs";import{dirname as ws,join as Tu}from"path";import{Command as De}from"commander";import Jt from"chalk";import{input as Au,password as Pu,confirm as vs,select as Ou}from"@inquirer/prompts";import Dn from"ora";import Ru from"conf";var On=new Ru({projectName:"conceptcraft",configName:"feature-cache"}),Cu=3600*1e3,Su=1440*60*1e3;function hs(t){let e=0;for(let n=0;n<t.length;n++){let r=t.charCodeAt(n);e=(e<<5)-e+r,e=e&e}return e.toString(16)}function ys(){if(!it())return null;let t=On.get("featureFlags");if(!t)return null;let e=hs(Se());if(t.apiKeyHash&&t.apiKeyHash!==e)return ze(),null;let n=Date.now()-t.fetchedAt;return n>Su?null:(n>Cu&&ro(),t.flags)}function ro(){Je().catch(()=>{})}async function Je(){let t=await Da(),e=Se();return On.set("featureFlags",{flags:t,fetchedAt:Date.now(),apiKeyHash:e?hs(e):void 0}),t}function ze(){On.delete("featureFlags")}function bs(){return On.path}var Is=new De("config").description("Manage CLI configuration: account settings, and the cached feature flags that decide which commands appear").addCommand(new De("init").description("Initialize configuration interactively").action(async()=>{console.log(),console.log(Jt.bold(`${u.displayName} CLI Configuration`)),console.log(Jt.gray("\u2500".repeat(35))),console.log();try{let t=await Pu({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":Gr(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(qr(t.trim()),await vs({message:`Use a custom API URL? (default: ${u.apiUrl.replace("https://","")})`,default:!1})){let r=await Au({message:"Enter API URL:",default:W(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});Vr(r)}console.log();let n=Dn("Verifying API key...").start();try{let r=await xe();if(n.succeed("API key verified!"),console.log(),w(`Logged in as: ${r.user.email}`),r.teams.length===0)_("No teams found for this user.");else if(r.teams.length===1){let o=r.teams[0];ot(o.id),w(`Team: ${o.name} (${o.planName})`)}else{console.log(),w(`You have access to ${r.teams.length} teams.`);let o=await Ou({message:"Select your default team:",choices:r.teams.map(s=>({name:`${s.name} (${s.planName}) - ${s.role}${s.isCurrent?" [current]":""}`,value:s.id})),default:r.currentTeam?.id});ot(o);let i=r.teams.find(s=>s.id===o);k(`Selected team: ${i?.name}`)}try{await Je()}catch{}}catch(r){n.fail("Failed to verify API key"),_(`Could not verify API key: ${r instanceof Error?r.message:String(r)}`),_(`You may need to set the team ID manually: ${u.commands[0]} config set team-id <id>`)}console.log(),k("Configuration saved!"),w(`Config file: ${Ft()}`),console.log()}catch(t){if(t.name==="ExitPromptError"){console.log(),w("Configuration cancelled.");return}throw t}})).addCommand(new De("show").description("Show current configuration").option("--verify","Verify API key and show team details").action(async t=>{let e=Qi();if(ge("Current Configuration"),console.log(),C("API Key",ma()??Jt.red("Not set")),C("API URL",e.apiUrl),C("Default Team ID",e.defaultTeamId??Jt.gray("Not set")),console.log(),C("Config file",Ft()),t.verify&&e.apiKey){console.log();let n=Dn("Verifying...").start();try{let r=await xe();n.succeed("Verified"),console.log(),C("User",r.user.email),r.currentTeam&&C("Current Team",`${r.currentTeam.name} (${r.currentTeam.planName})`),r.teams.length>1&&C("Total Teams",String(r.teams.length))}catch(r){n.fail("Verification failed"),_(r instanceof Error?r.message:String(r))}}console.log()})).addCommand(new De("set").description("Set a configuration value").argument("<key>","Configuration key (api-key, api-url, team-id)").argument("<value>","Value to set").action(async(t,e)=>{switch(t){case"api-key":Gr(e)||(a("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),qr(e),ze(),k("API key updated"),Je().catch(()=>{});break;case"api-url":try{new URL(e),Vr(e),k(`API URL set to: ${e}`)}catch{a("Invalid URL format"),process.exit(6)}break;case"team-id":ot(e),k(`Default team ID set to: ${e}`);break;default:a(`Unknown config key: ${t}`),console.log(Jt.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new De("clear").description("Clear all configuration").action(async()=>{try{await vs({message:"Are you sure you want to clear all configuration?",default:!1})?(kn(),ze(),k("Configuration cleared")):w("Cancelled")}catch{w("Cancelled")}})).addCommand(new De("refresh").description("Refresh cached feature flags").action(async()=>{let t=Dn("Refreshing feature flags...").start();try{await Je(),t.succeed("Feature flags refreshed"),w(`Run '${u.commands[0]} --help' to see updated commands`)}catch(e){t.fail("Failed to refresh"),a(e instanceof Error?e.message:String(e)),process.exit(1)}})).addCommand(new De("path").description("Show configuration file path").option("--cache","Show feature cache file path").action(t=>{t.cache?console.log(bs()):console.log(Ft())})).addCommand(new De("pull").description("Pull your account settings (memory, brand, prefs) into a local config.toml").action(async()=>{let t=Dn("Pulling settings...").start();try{let e=await $e(),n=await fetch(`${W()}/api/cli/settings`,{headers:e});if(!n.ok)throw new Error(`Request failed (HTTP ${n.status})`);let r=await n.text(),o=Tu(ws(Ft()),"settings.toml");Eu(ws(o),{recursive:!0}),$u(o,r,"utf8"),t.succeed("Settings pulled"),w(`Written to ${o}`)}catch(e){t.fail("Failed to pull settings"),a(e instanceof Error?e.message:String(e)),process.exit(1)}}));import{Command as Nu}from"commander";import{confirm as _u}from"@inquirer/prompts";import{createHash as Du}from"crypto";function z(t){let e=Du("sha256").update(JSON.stringify({command:t.command,payload:oo(t.payload),workspaceId:t.workspaceId})).digest("hex");return`cli:${t.command.trim().toLowerCase().replace(/[^a-z0-9._:-]+/g,"-").replace(/^-+|-+$/g,"")||"command"}:${e}`}function oo(t){return Array.isArray(t)?t.map(oo):!t||typeof t!="object"?t:Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>[e,oo(n)]))}var xs=new Nu("delete").description("Delete a presentation").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-y, --yes","Confirm permanent deletion without prompting").option("-f, --force","Deprecated alias for --yes").option("--team-id <id>","Workspace ID (uses configured default)").option("--idempotency-key <key>","Stable key to safely retry this deletion").option("--approval-receipt <receipt>","Browser-issued approval receipt").option("-q, --quiet","Suppress output").action(async(t,e)=>{if(await y(),!e.yes&&!e.force)try{if(!await _u({message:`Are you sure you want to delete presentation "${t}"?`,default:!1})){e.quiet||_("Deletion cancelled");return}}catch{e.quiet||_("Deletion cancelled");return}let n=e.teamId??ee(),r=e.idempotencyKey??z({command:"presentation:delete",payload:{slug:t},workspaceId:n??"configured-default"});try{await Sa(t,{approvalReceipt:e.approvalReceipt,idempotencyKey:r,teamId:n}),e.quiet||k(`Presentation "${t}" deleted`)}catch(o){o.errorCode==="approval_required"&&_(`Retry with --idempotency-key ${r}`),a(o instanceof Error?o.message:String(o)),process.exit(o.exitCode??1)}});import{Command as ct}from"commander";import Rs from"chalk";import Lu from"ora";import{createParser as AR}from"eventsource-parser";import OR from"chalk";import NR from"ora";async function ks(t,e={}){let n=t.body?.getReader();if(!n)throw new Error("Response body is not readable");let r=new TextDecoder,o="",i=!1;for(;!i;){let s=await n.read();if(i=s.done,s.value){let c=r.decode(s.value,{stream:!0});o+=c,e.quiet||process.stdout.write(c)}}return e.quiet||console.log(),o}function Uu(){return new ct("blog").description("Generate a blog post from a presentation").argument("<slug>","Presentation slug").option("--words <count>","Target word count (50-2000)","300").option("--tone <tone>","Writing tone (professional, casual, educational)","professional").option("--audience <text>","Target audience description").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").option("--instructions <text>","Custom instructions for the blog").option("--no-images","Exclude image references").option("--toc","Include table of contents").action(async(t,e)=>{await y();let n=parseInt(e.words,10);(Number.isNaN(n)||n<50||n>2e3)&&(a("Word count must be between 50 and 2000"),process.exit(6));let r=["professional","casual","educational"];r.includes(e.tone)||(a(`Invalid tone. Valid options: ${r.join(", ")}`),process.exit(6));let o=Lu("Fetching presentation...").start();try{let i=await dt(t);o.text="Generating blog post...";let s=await Na(i.id,i.documentCreatedAt||i.createdAt,{targetWordCount:n,tone:e.tone,targetAudience:e.audience??"General Audience",customInstructions:e.instructions??"",includeImages:!e.noImages,includeTableOfContents:e.toc??!1}),c=await ks(s,{quiet:!0});o.succeed("Blog generated"),e.format==="json"?console.log(JSON.stringify({presentationId:t,title:i.title,wordCount:n,tone:e.tone,content:c},null,2)):e.format==="markdown"?console.log(c):(console.log(),console.log(Rs.bold(`Blog: ${i.title}`)),console.log(Rs.gray("\u2500".repeat(40))),console.log(),console.log(c),console.log())}catch(i){o.fail("Generation failed"),a(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})}function ju(){return new ct("tweets").description("Generate tweets from a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of tweets to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(t,e)=>{await y(),w("Tweet generation coming soon.")})}function qu(){return new ct("linkedin").description("Generate a LinkedIn carousel from a presentation").argument("<slug>","Presentation slug").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async t=>{await y(),w("LinkedIn carousel generation coming soon.")})}function Vu(){return new ct("questions").description("Generate questions for a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of questions","10").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(t,e)=>{await y(),w("Question generation coming soon.")})}function Mu(){return new ct("cheatsheet").description("Generate a presenter cheat sheet").argument("<slug>","Presentation slug").option("--mode <mode>","Cheat sheet mode (qa-prep, talking-points)","qa-prep").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").action(async(t,e)=>{await y(),w("Cheat sheet generation coming soon.")})}function Cs(){let t=new ct("derive").description("Generate derivative content from a presentation"),e=ys();return e&&(e.deckToBlog&&t.addCommand(Uu()),e.deckToTweets&&t.addCommand(ju()),e.linkedInCarousel&&t.addCommand(qu()),e.redTeamQuestions&&t.addCommand(Vu()),e.presenterCheatSheet&&t.addCommand(Mu())),t}import{Command as Fu}from"commander";import io from"chalk";var Ss=new Fu("ideas").description("Generate presentation topic ideas").option("--context <text>","Custom context for idea generation").option("--count <n>","Number of ideas to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async t=>{await y(),w("Idea generation is available in the web dashboard."),console.log(),console.log(io.gray("The CLI will support idea generation in a future release.")),console.log(),console.log("For now, try these approaches:"),console.log(io.gray("` 1. Visit the ${brand.displayName} dashboard and use the idea generator`")),console.log(io.gray(" 2. Create a presentation with a broad topic and refine it")),console.log()});import{Command as Bu}from"commander";import{readFile as Gu}from"fs/promises";import{resolve as Wu,basename as Ku}from"path";import Ju from"ora";var Es=new Bu("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");Es._hidden=!0;var $s=Es.option("--dry-run","Validate without importing").option("--overwrite","Overwrite existing presentations").option("--remap-ids","Generate new IDs (default: true)",!0).action(async(t,e)=>{await y();try{(await xe()).user.role!=="admin"&&(a("This command is only available to administrators"),process.exit(2))}catch{a("Failed to verify permissions"),process.exit(2)}let n=Wu(t),r=Ku(n);r.endsWith(".zip")||(a("File must be a ZIP archive"),process.exit(6));let o=Ju("Reading file...").start();try{let i=await Gu(n);e.dryRun?o.text="Validating...":o.text="Importing presentation...";let s=await Aa(i,r,{dryRun:e.dryRun});if(s.success){if(e.dryRun)o.succeed("Validation passed!"),console.log(),w("The file is valid and can be imported."),s.statistics&&(console.log(),C("Slides",String(s.statistics.slidesImported)),C("Images",String(s.statistics.imagesUploaded)));else if(o.succeed("Import complete!"),console.log(),C("Presentation ID",s.presentationId??"N/A"),C("Document ID",s.documentId??"N/A"),s.statistics&&(C("Slides imported",String(s.statistics.slidesImported)),C("Images uploaded",String(s.statistics.imagesUploaded)),C("Time",`${s.statistics.totalTimeMs}ms`)),s.presentationId){let c=W();C("View URL",`${c}/p/${s.presentationId}`)}if(s.warnings&&s.warnings.length>0){console.log();for(let c of s.warnings)_(c)}console.log()}else{if(o.fail("Import failed"),console.log(),s.errors)for(let c of s.errors)a(`${c.type}: ${c.message}`);process.exit(1)}}catch(i){o.fail("Import failed"),i.code==="ENOENT"&&(a(`File not found: ${n}`),process.exit(3)),a(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}});import{Command as zu}from"commander";var Nn=new zu("list").description("List presentations").option("-n, --limit <count>","Number of results to return","20").option("--offset <count>","Zero-based result offset","0").option("--sort <field>","Sort by field (updated, created, title)",b("--sort",["updated","created","title"]),"updated").option("--team-id <id>","Team ID (uses default if not specified)").option("--json","Output machine-readable JSON").action(async t=>{await y();let e=parseInt(t.limit,10);(Number.isNaN(e)||e<1||e>50)&&(a("Invalid limit value (expected 1-50)"),process.exit(6));let n=parseInt(t.offset,10);(Number.isNaN(n)||n<0||n>1e4)&&(a("Invalid offset value (expected 0-10000)"),process.exit(6));let r=t.teamId??ee();r||(a("Team ID required. Set a default with 'mf config set team-id <id>' or use --team-id"),process.exit(6));try{let o=await Ra(r,e,n,t.sort);if(o.length===0){t.json?console.log(JSON.stringify([])):w("No presentations found");return}console.log(t.json?JSON.stringify(o,null,2):aa(o))}catch(o){a(o instanceof Error?o.message:String(o));let i=typeof o=="object"&&o!==null&&"exitCode"in o&&typeof o.exitCode=="number"?o.exitCode:1;process.exit(i)}});import{createHash as Hu,randomBytes as Ps}from"crypto";import Os from"http";import Ts from"chalk";import{Command as Xu}from"commander";import Yu from"open";import As from"ora";var Qu=`${u.displayName} CLI`,Zu=8765,ep=8775,tp=["presentations:read","presentations:write","brands:read","brands:write","media:read","media:write"];function np(){return Ps(32).toString("base64url")}function rp(t){return Hu("sha256").update(t).digest("base64url")}function op(){return Ps(16).toString("hex")}async function ip(t,e){for(let n=t;n<=e;n++)try{return await new Promise((r,o)=>{let i=Os.createServer();i.listen(n,()=>{i.close(()=>r())}),i.on("error",o)}),n}catch{}throw new Error(`No available port found between ${t} and ${e}`)}async function ap(t){let e=await fetch(`${t}/.well-known/oauth-authorization-server`);if(!e.ok)throw new Error(`Failed to fetch OAuth metadata: ${e.status}`);return e.json()}function sp(t){let e=t.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(e?.length?e:tp).join(" ")}function dp(t,e){if(!e?.trim())return sp(t);let n=e.split(",").map(o=>o.trim()).filter(Boolean);if(n.length===0)throw new Error("--scopes must include at least one OAuth scope");let r=t.scopes_supported?.filter(o=>typeof o=="string"&&o.trim().length>0);if(r?.length){let o=n.filter(i=>!r.includes(i));if(o.length>0)throw new Error(`Unsupported OAuth scope${o.length===1?"":"s"}: ${o.join(", ")}`)}return n.join(" ")}async function cp(t,e,n){let r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:Qu,redirect_uris:[e],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none",scope:n})});if(!r.ok){let o=await r.text();throw new Error(`Client registration failed: ${o}`)}return r.json()}async function lp(t,e,n,r,o){let i=new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:r,client_id:o,code_verifier:n}),s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!s.ok){let c=await s.text();throw new Error(`Token exchange failed: ${c}`)}return s.json()}function mp(t,e){return new Promise((n,r)=>{let o,i=!1,s=()=>{i||(i=!0,clearTimeout(o),process.off("SIGINT",c),process.off("SIGTERM",c),p.close())},c=()=>{s(),r(new Error("Login cancelled"))},p=Os.createServer((f,h)=>{let v=new URL(f.url||"",`http://localhost:${t}`);if(v.pathname!=="/callback"){h.writeHead(404),h.end("Not found");return}let x=v.searchParams.get("code"),$=v.searchParams.get("state"),A=v.searchParams.get("error"),S=v.searchParams.get("error_description");if(h.writeHead(200,{"Content-Type":"text/html"}),A){h.end(`
6
5
  <!DOCTYPE html>
7
6
  <html>
8
7
  <head><title>Login Failed</title></head>
9
8
  <body style="font-family: system-ui; text-align: center; padding: 50px;">
10
9
  <h1 style="color: #dc2626;">Login Failed</h1>
11
- <p>${k||E}</p>
10
+ <p>${S||A}</p>
12
11
  <p>You can close this window.</p>
13
12
  </body>
14
13
  </html>
15
- `),a(),r(new Error(k||E));return}if(!v||!C){p.end(`
14
+ `),s(),r(new Error(S||A));return}if(!x||!$){h.end(`
16
15
  <!DOCTYPE html>
17
16
  <html>
18
17
  <head><title>Login Failed</title></head>
@@ -22,7 +21,7 @@ var f={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"C
22
21
  <p>You can close this window.</p>
23
22
  </body>
24
23
  </html>
25
- `),a(),r(new Error("Missing authorization code or state"));return}if(C!==t){p.end(`
24
+ `),s(),r(new Error("Missing authorization code or state"));return}if($!==e){h.end(`
26
25
  <!DOCTYPE html>
27
26
  <html>
28
27
  <head><title>Login Failed</title></head>
@@ -32,7 +31,7 @@ var f={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"C
32
31
  <p>You can close this window.</p>
33
32
  </body>
34
33
  </html>
35
- `),a(),r(new Error("State mismatch"));return}p.end(`
34
+ `),s(),r(new Error("State mismatch"));return}h.end(`
36
35
  <!DOCTYPE html>
37
36
  <html>
38
37
  <head><title>Login Successful</title></head>
@@ -41,168 +40,252 @@ var f={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"C
41
40
  <p>You can close this window and return to the terminal.</p>
42
41
  </body>
43
42
  </html>
44
- `),a(),n({code:v,state:C})});l.listen(e),process.once("SIGINT",d),process.once("SIGTERM",d),o=setTimeout(()=>{a(),r(new Error("Login timed out - no callback received within 5 minutes"))},300*1e3)})}async function Hd(e,t){let n=await fetch(`${e}/api/cli/whoami`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)throw new Error(`Failed to fetch user info: ${n.status}`);return n.json()}async function Yd(e){let t=B(),n=ni("Discovering OAuth server...").start();try{let r=await Wd(t),o=Kd(r);n.succeed(`Connecting to ${t}`);let i=await Bd(Ud,jd),a=`http://localhost:${i}/callback`;console.log(`Redirect URI: ${a}`),console.log(`Authorization endpoint: ${r.authorization_endpoint}`),console.log(`Token endpoint: ${r.token_endpoint}`),console.log(`Registration endpoint: ${r.registration_endpoint}`);let d=await Jd(r.registration_endpoint,a,o),l=d.client_id;Lr(l,d.client_secret);let y=Fd(),p=Vd(y),w=Gd(),v=new URLSearchParams({client_id:l,redirect_uri:a,response_type:"code",scope:o,state:w,code_challenge:p,code_challenge_method:"S256"}),C=`${r.authorization_endpoint}?${v}`;console.log(`Authorization URL: ${C}`),e.browser?(g("Opening browser..."),await Nd(C)):(console.log(ti.bold("Open this URL in your browser:")),console.log(ti.cyan(C)));let E=Xd(i,w),{code:k}=await E;n=ni("Completing login...").start();let $=await zd(r.token_endpoint,k,y,a,l);Rt($.access_token,$.refresh_token,$.expires_in);let S=await Hd(t,$.access_token);n.succeed("Logged in!"),console.log(),R("Logged in as",S.user.email),S.currentTeam&&(De(S.currentTeam.id),R("Team",`${S.currentTeam.name} (${S.currentTeam.planName})`));try{await Ee()}catch{}console.log(),x("You're all set!"),console.log()}catch(r){throw n.fail("Login failed"),s(r instanceof Error?r.message:String(r)),r}}var ii=new Dd("login").description(`Authenticate with ${m.displayName} (opens browser)`).option("--no-browser","Print URL instead of opening browser").action(async e=>{console.log(),$e()&&(M("You are already logged in."),g(`Run '${m.commands[0]} logout' to log out first, or continue to re-authenticate.`),console.log());try{await Yd(e),process.exit(0)}catch{process.exit(1)}});import{Command as Qd}from"commander";import{confirm as Zd}from"@inquirer/prompts";var ai=new Qd("logout").description("Log out and clear authentication").option("--all","Clear all config including API key").action(async e=>{console.log();let t=$e(),n=Ne();if(!t&&!n){M("You are not logged in."),console.log();return}if(e.all)try{await Zd({message:"Clear all configuration including API key?",default:!1})?(It(),Ae(),x("All configuration cleared.")):g("Cancelled.")}catch{g("Cancelled.")}else St(),Ae(),x("Logged out successfully."),n&&g("Note: Your API key is still configured. Use --all to clear everything.");console.log()});import{homedir as Uc}from"os";import{join as jc}from"path";import de from"chalk";import{Command as Mc}from"commander";import{spawn as ec}from"child_process";import{existsSync as tc,readdirSync as nc}from"fs";import{homedir as ci}from"os";import{delimiter as si}from"path";import{query as rc}from"@anthropic-ai/claude-agent-sdk";function ne(e){if(e===void 0)return null;if(typeof e=="string")return e.length>12e3?`${e.slice(0,12e3)}\u2026`:e;try{let t=JSON.stringify(e);return t.length<=12e3?e:{preview:`${t.slice(0,12e3)}\u2026`,truncated:!0}}catch{return String(e).slice(0,12e3)}}function Lt(e){let t=typeof e=="string"?e:String(e??"");return t.length>12e3?`${t.slice(0,12e3)}\u2026`:t}function re(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function D(e){return typeof e=="string"?e:""}function di(e,t){let n=e.replace(/[/.]/g,"-");return`${ci()}/.claude/projects/${n}/${t}.jsonl`}function oc(e){try{return nc(`${e}/.nvm/versions/node`).map(t=>`${e}/.nvm/versions/node/${t}/bin`).sort().reverse()}catch{return[]}}function Dt(){let e=ci(),t=[`${e}/.local/bin`,`${e}/.claude/local`,`${e}/.bun/bin`,`${e}/bin`,"/opt/homebrew/bin","/usr/local/bin",...oc(e)],r=(process.env.PATH??"").split(si);for(let o of t)r.includes(o)||r.push(o);return r.join(si)}async function Nt(e){let t=e??"claude";return new Promise(n=>{let r=ec(t,["--version"],{env:{...process.env,PATH:Dt()},stdio:["ignore","pipe","ignore"]}),o="";r.stdout.on("data",i=>{o+=i.toString("utf8")}),r.on("error",()=>n(null)),r.on("close",i=>{if(i!==0)return n(null);let a=o.trim().split(`
45
- `)[0]??"";n(a?{bin:t,version:a}:null)})})}var ic=new Set(["","default","best"]);function $n(e){let t=e.filter(i=>i.text.trim());if(t.length===0)return"";let n=t[t.length-1],r=t.slice(0,-1);return r.length===0?n.text:`<conversation-history>
43
+ `),s(),n({code:x,state:$})});p.listen(t),process.once("SIGINT",c),process.once("SIGTERM",c),o=setTimeout(()=>{s(),r(new Error("Login timed out - no callback received within 5 minutes"))},300*1e3)})}async function up(t,e){let n=await fetch(`${t}/api/cli/whoami`,{headers:{Authorization:`Bearer ${e}`}});if(!n.ok)throw new Error(`Failed to fetch user info: ${n.status}`);return n.json()}async function pp(t){let e=W(),n=As("Discovering OAuth server...").start();try{let r=await ap(e),o=dp(r,t.scopes);n.succeed(`Connecting to ${e}`);let i=await ip(Zu,ep),s=`http://localhost:${i}/callback`;console.log(`Redirect URI: ${s}`),console.log(`Authorization endpoint: ${r.authorization_endpoint}`),console.log(`Token endpoint: ${r.token_endpoint}`),console.log(`Registration endpoint: ${r.registration_endpoint}`);let c=await cp(r.registration_endpoint,s,o),p=c.client_id;oa(p,c.client_secret);let f=np(),h=rp(f),v=op(),x=new URLSearchParams({client_id:p,redirect_uri:s,response_type:"code",scope:o,state:v,code_challenge:h,code_challenge_method:"S256"}),$=`${r.authorization_endpoint}?${x}`;console.log(`Authorization URL: ${$}`),t.browser?(w("Opening browser..."),await Yu($)):(console.log(Ts.bold("Open this URL in your browser:")),console.log(Ts.cyan($)));let A=mp(i,v),{code:S}=await A;n=As("Completing login...").start();let T=await lp(r.token_endpoint,S,f,s,p);Rn(T.access_token,T.refresh_token,T.expires_in);let E=await up(e,T.access_token);n.succeed("Logged in!"),console.log(),C("Logged in as",E.user.email),E.currentTeam&&(ot(E.currentTeam.id),C("Team",`${E.currentTeam.name} (${E.currentTeam.planName})`));try{await Je()}catch{}console.log(),k("You're all set!"),console.log()}catch(r){throw n.fail("Login failed"),a(r instanceof Error?r.message:String(r)),r}}var Ds=new Xu("login").description(`Authenticate with ${u.displayName} (opens browser)`).option("--no-browser","Print URL instead of opening browser").option("--scopes <scopes>","Comma-separated OAuth scopes to request (defaults to all server-supported scopes)").action(async t=>{console.log(),Ke()&&(_("You are already logged in."),w(`Run '${u.commands[0]} logout' to log out first, or continue to re-authenticate.`),console.log());try{await pp(t),process.exit(0)}catch{process.exit(1)}});import{Command as gp}from"commander";import{confirm as fp}from"@inquirer/prompts";var Ns=new gp("logout").description("Log out and clear authentication").option("--all","Clear all config including API key").action(async t=>{console.log();let e=Ke(),n=it();if(!e&&!n){_("You are not logged in."),console.log();return}if(t.all)try{await fp({message:"Clear all configuration including API key?",default:!1})?(kn(),ze(),k("All configuration cleared.")):w("Cancelled.")}catch{w("Cancelled.")}else Cn(),ze(),k("Logged out successfully."),n&&w("Note: Your API key is still configured. Use --all to clear everything.");console.log()});import{homedir as eg}from"os";import{join as tg}from"path";import ye from"chalk";import{Command as ng}from"commander";import{spawn as hp}from"child_process";import{existsSync as yp,readdirSync as bp}from"fs";import{homedir as Us}from"os";import{delimiter as _s}from"path";import{query as wp}from"@anthropic-ai/claude-agent-sdk";function le(t){if(t===void 0)return null;if(typeof t=="string")return t.length>12e3?`${t.slice(0,12e3)}\u2026`:t;try{let e=JSON.stringify(t);return e.length<=12e3?t:{preview:`${e.slice(0,12e3)}\u2026`,truncated:!0}}catch{return String(t).slice(0,12e3)}}function _n(t){let e=typeof t=="string"?t:String(t??"");return e.length>12e3?`${e.slice(0,12e3)}\u2026`:e}function me(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function j(t){return typeof t=="string"?t:""}function Ls(t,e){let n=t.replace(/[/.]/g,"-");return`${Us()}/.claude/projects/${n}/${e}.jsonl`}function vp(t){try{return bp(`${t}/.nvm/versions/node`).map(e=>`${t}/.nvm/versions/node/${e}/bin`).sort().reverse()}catch{return[]}}function Ln(){let t=Us(),e=[`${t}/.local/bin`,`${t}/.claude/local`,`${t}/.bun/bin`,`${t}/bin`,"/opt/homebrew/bin","/usr/local/bin",...vp(t)],r=(process.env.PATH??"").split(_s);for(let o of e)r.includes(o)||r.push(o);return r.join(_s)}async function Un(t){let e=t??"claude";return new Promise(n=>{let r=hp(e,["--version"],{env:{...process.env,PATH:Ln()},stdio:["ignore","pipe","ignore"]}),o="";r.stdout.on("data",i=>{o+=i.toString("utf8")}),r.on("error",()=>n(null)),r.on("close",i=>{if(i!==0)return n(null);let s=o.trim().split(`
44
+ `)[0]??"";n(s?{bin:e,version:s}:null)})})}var Ip=new Set(["","default","best"]);function ao(t){let e=t.filter(i=>i.text.trim());if(e.length===0)return"";let n=e[e.length-1],r=e.slice(0,-1);return r.length===0?n.text:`<conversation-history>
46
45
  ${r.map(i=>`${i.role==="assistant"?"Assistant":"User"}: ${i.text}`).join(`
47
46
 
48
47
  `)}
49
48
  </conversation-history>
50
49
 
51
- ${n.text}`}function Tn(e,t){return t?e.messages.filter(r=>r.text.trim()).at(-1)?.text??"":$n(e.messages)}function ac({abortController:e,input:t,resumeSessionId:n,workspace:r}){let o=(t.modelId??"").trim(),i=t.thinking??null,a={abortController:e,allowedTools:["WebSearch","WebFetch"],cwd:r,env:{...process.env,PATH:Dt()},includePartialMessages:!0,maxTurns:16,permissionMode:"dontAsk"};return ic.has(o)||(a.model=o),t.effort&&(a.effort=t.effort),i&&i!=="disabled"&&(a.thinking={display:"summarized",type:i==="enabled"?"enabled":"adaptive"}),n?a.resume=n:t.system?.trim()&&(a.systemPrompt=t.system),a}async function li(e){let t=Tn(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new AbortController,r=()=>n.abort();e.signal?.addEventListener("abort",r,{once:!0});let o=null,i=null,a=null,d=null,l=null,y=0,p=new Set;try{let C=rc({prompt:t,options:ac({abortController:n,input:e.input,resumeSessionId:e.resumeSessionId,workspace:e.workspace})});for await(let E of C){let k=E;if(k.type==="system"&&k.subtype==="init"){typeof k.session_id=="string"&&(i=k.session_id,e.onEvent({eventType:"chat.session",payload:{sessionId:i,sessionPath:di(e.workspace,i)}})),typeof k.model=="string"&&(o=k.model,e.onEvent({eventType:"chat.model",payload:{modelId:k.model}}));continue}if(k.type==="stream_event"){let $=k.event;if($?.type!=="content_block_delta")continue;let S=$.delta;if(!S)continue;S.type==="text_delta"&&typeof S.text=="string"?(y+=S.text.length,e.onEvent({eventType:"chat.text.delta",payload:{text:S.text}})):S.type==="thinking_delta"&&typeof S.thinking=="string"&&e.onEvent({eventType:"chat.reasoning.delta",payload:{text:S.thinking}});continue}if(k.type==="assistant"){let $=re(k.message),S=Array.isArray($.content)?$.content:[];for(let V of S){let A=re(V);if(A.type!=="tool_use")continue;let q=D(A.id),I=D(A.name);!q||!I||p.has(q)||(p.add(q),e.onEvent({eventType:"chat.tool.started",payload:{input:ne(A.input),toolCallId:q,toolName:I}}))}continue}if(k.type==="user"){let $=re(k.message),S=Array.isArray($.content)?$.content:[];for(let V of S){let A=re(V);if(A.type!=="tool_result")continue;let q=D(A.tool_use_id);q&&e.onEvent({eventType:"chat.tool.completed",payload:{...A.is_error===!0?{errorText:typeof A.content=="string"?Lt(A.content):"Claude tool call failed."}:{},output:ne(A.content),toolCallId:q}})}continue}k.type==="result"&&(typeof k.result=="string"&&(d=k.result),k.usage&&typeof k.usage=="object"&&(a=k.usage),typeof k.session_id=="string"&&(i=k.session_id),(k.is_error===!0||k.subtype!=="success")&&(l=typeof k.result=="string"&&k.result||`Claude turn failed (${String(k.subtype)}).`,e.onEvent({eventType:"chat.error",message:l,payload:{message:l}})))}}finally{e.signal?.removeEventListener("abort",r)}if(e.signal?.aborted)throw new Error("Chat turn cancelled.");if(l)throw new Error(l);let w=d??"";y===0&&w&&e.onEvent({eventType:"chat.text.delta",payload:{text:w}});let v=i?di(e.workspace,i):null;return{modelId:o,sessionId:i,sessionPath:v&&tc(v)?v:null,text:w,usage:a}}import{spawn as sc}from"child_process";import{closeSync as dc,fstatSync as cc,openSync as lc,readdirSync as mc,readSync as uc}from"fs";import{homedir as pc}from"os";import{join as mi}from"path";import{Codex as gc}from"@openai/codex-sdk";var fc=["/Applications/Codex.app/Contents/Resources/codex"];async function qt(e){let t=e?[e]:["codex",...fc];for(let n of t){let r=await hc(n);if(r)return{bin:n,version:r}}return null}function hc(e){return new Promise(t=>{let n=sc(e,["--version"],{env:{...process.env,PATH:Dt()},stdio:["ignore","pipe","ignore"]}),r="";n.stdout.on("data",o=>{r+=o.toString("utf8")}),n.on("error",()=>t(null)),n.on("close",o=>{if(o!==0)return t(null);let i=r.trim().split(`
52
- `)[0]??"";t(i||null)})})}var yc=24,bc=4*1024*1024,gi=new Set(["custom_tool_call","custom_tool_call_output","dynamic_tool_call","function_call"]);function wc(e){let t;try{t=vc(e).split(`
53
- `)}catch{return[]}let n=new Set,r=new Map,o=null;for(let i of t){if(!i.trim())continue;let a;try{a=JSON.parse(i)}catch{continue}let d=re(a.payload);if(a.type==="response_item"&&d.type==="custom_tool_call"){let l=D(d.call_id),y=D(d.input);l&&d.name==="exec"&&/\btools\.web__run\s*\(/.test(y)&&(n.add(l),o=l);continue}if(a.type==="event_msg"&&d.type==="web_search_end"){let l=D(d.call_id);if(!l||!o)continue;let y=D(d.query),p=re(d.action),v={action:{...p,...y&&!D(p.query)?{query:y}:{}},query:y,sources:ui(d.results),toolCallId:l},C=r.get(o)??[];C.push(v),r.set(o,C);continue}if(a.type==="response_item"&&d.type==="custom_tool_call_output"){let l=D(d.call_id);if(!l||!n.has(l))continue;let y=ui(d.output);for(let p of r.get(l)??[])p.sources.length===0&&(p.sources=y);o===l&&(o=null)}}return Array.from(r.values()).flat()}function vc(e){let t=lc(e,"r");try{let n=cc(t).size,r=Math.max(0,n-bc),o=Buffer.alloc(n-r);uc(t,o,0,o.length,r);let i=o.toString("utf8");if(r===0)return i;let a=i.indexOf(`
54
- `);return a===-1?"":i.slice(a+1)}finally{dc(t)}}function ui(e){let n=On(e).match(/https?:\/\/[^\s<>"'()[\]{}\\]+/g)??[],r=new Set,o=[];for(let i of n){let a=i.replace(/[.,;:!?]+$/,"");try{let d=new URL(a);if(d.protocol!=="http:"&&d.protocol!=="https:"||r.has(d.href))continue;if(r.add(d.href),o.push({type:"url",url:d.href}),o.length>=yc)break}catch{}}return o}function On(e){return typeof e=="string"?e:Array.isArray(e)?e.map(On).join(`
55
- `):e&&typeof e=="object"?Object.values(e).map(On).join(`
56
- `):""}function En(e,t){let n=re(e),r=D(n.type),o=D(n.id),i=D(n.call_id)||D(n.tool_call_id),a=gi.has(r)?i||o:o||i;if(!a)return null;if(r==="command_execution"){let d=D(n.command),l=D(n.status),y={exitCode:typeof n.exit_code=="number"?n.exit_code:null,output:ne(n.aggregated_output)};return{...t&&l==="failed"?{errorText:Lt(n.aggregated_output)||"Command failed."}:{},input:{command:d},...t?{output:y}:{},toolCallId:a,toolName:"Bash"}}if(r==="mcp_tool_call"){let d=re(n.error);return{...t&&D(d.message)?{errorText:D(d.message)}:{},input:ne(n.arguments),...t?{output:ne(n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:D(n.tool)||D(n.name)||"Codex tool"}}if(r==="web_search"){let d=D(n.query);return{input:{query:d},...t?{output:{query:d}}:{},toolCallId:a,toolName:"web_search"}}if(r==="file_change"){let d=D(n.status);return{...t&&d==="failed"?{errorText:"Codex could not apply the file changes."}:{},input:{changes:ne(n.changes)},...t?{output:{changes:ne(n.changes),status:d}}:{},toolCallId:a,toolName:"ApplyPatch"}}if(r==="custom_tool_call_output")return{input:{},...t?{output:ne(n.output)}:{},toolCallId:a,toolName:"Codex tool"};if(r==="custom_tool_call"||r==="dynamic_tool_call"||r==="function_call"){let d=D(n.name)||D(n.tool)||"Codex tool",l=n.input??n.arguments??{};return{input:d==="exec"&&typeof l=="string"?{command:l}:ne(l),...t?{output:ne(n.output??n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:d}}return null}function An(e,t=mi(pc(),".codex","sessions")){try{let r=mc(t,{recursive:!0}).find(o=>typeof o=="string"&&o.endsWith(`${e}.jsonl`));return r?mi(t,r):null}catch{return null}}function xc(e,t){return t?Tn(e,t):$n(e.messages)}function kc(e,t,n=m.codexSelfConnectorAppId){let r=t.system?.trim(),o={...r?{developer_instructions:r}:{},...n?{apps:{[n]:{enabled:!1}}}:{}};return{codexPathOverride:e,...Object.keys(o).length>0?{config:o}:{}}}var Cc=new Set(["minimal","low","medium","high","xhigh"]);function Ic(e,t){let n={networkAccessEnabled:!0,sandboxMode:"workspace-write",skipGitRepoCheck:!0,webSearchEnabled:!0,workingDirectory:t},r=(e.modelId??"").trim();return r&&r!=="default"&&(n.model=r),e.effort&&Cc.has(e.effort)&&(n.modelReasoningEffort=e.effort),n}async function fi(e){let t=xc(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new gc(kc(e.bin,e.input)),r=Ic(e.input,e.workspace),o=e.resumeSessionId?n.resumeThread(e.resumeSessionId,r):n.startThread(r),i=e.resumeSessionId??null,a=null,d=null,l=[],y=new Set,p=new Set,w=null,v=k=>{w??=An(k,e.sessionsRoot),e.onEvent({eventType:"chat.session",payload:{sessionId:k,sessionPath:w}})},C=k=>{i&&(w??=An(i,e.sessionsRoot));let $=w?wc(w):[],S=D(re(k.input).query),V=pi(S),A=$.find(q=>!y.has(q.toolCallId)&&pi(q.query)===V)??$.find(q=>!y.has(q.toolCallId));A&&y.add(A.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:{...k,output:A?{action:A.action,query:A.query,sources:A.sources}:{action:{query:S,type:"search"},sourceListUnavailable:!0,sources:[]}}})},{events:E}=await o.runStreamed(t);i&&v(i);for await(let k of E){if(e.signal?.aborted)throw await E.return?.(void 0),new Error("Chat turn cancelled.");let $=k;if($.type==="thread.started"){typeof $.thread_id=="string"&&(i=$.thread_id,v($.thread_id));continue}if($.type==="item.started"){let S=En($.item,!1);if(S){e.onEvent({eventType:"chat.tool.started",payload:S});let V=re($.item);if(gi.has(D(V.type))&&D(V.status)==="completed"){let A=En(V,!0);A&&(p.add(A.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:A}))}}continue}if($.type==="item.completed"){let S=$.item;if(!S)continue;if(S.type==="agent_message"&&typeof S.text=="string")l.push(S.text),e.onEvent({eventType:"chat.text.delta",payload:{text:S.text}});else if(S.type==="reasoning"&&typeof S.text=="string")e.onEvent({eventType:"chat.reasoning.delta",payload:{text:S.text}});else{let V=En(S,!0);V&&(S.type==="web_search"?C(V):S.type==="custom_tool_call"&&p.has(V.toolCallId)||e.onEvent({eventType:"chat.tool.completed",payload:V}))}continue}if($.type==="turn.completed"){$.usage&&typeof $.usage=="object"&&(a=$.usage);continue}if($.type==="turn.failed"){let S=$.error;d=typeof S?.message=="string"&&S.message||"Codex turn failed.",e.onEvent({eventType:"chat.error",message:d,payload:{message:d}})}}if(d)throw new Error(d);return i=o.id??i,i&&(w??=An(i,e.sessionsRoot)),{modelId:e.input.modelId??null,sessionId:i,sessionPath:w,text:l.join(`
57
-
58
- `),usage:a}}function pi(e){return e.trim().replace(/\s+/g," ").toLocaleLowerCase()}import{randomUUID as Ec}from"crypto";import{mkdir as Ac}from"fs/promises";import{hostname as jt,platform as Oc}from"os";import{join as Pc}from"path";var Me=class extends Error{constructor(n,r,o=!1){super(n);this.statusCode=r;this.reRegister=o;this.name="RunnerApiError"}statusCode;reRegister};async function Fe(e,t={}){let n=await he();t.body!==void 0&&(n["Content-Type"]="application/json");let r=new AbortController,o=setTimeout(()=>r.abort(),t.timeoutMs??3e4),i=()=>r.abort();t.signal?.addEventListener("abort",i,{once:!0});try{let a=await fetch(`${B()}${e}`,{body:t.body!==void 0?JSON.stringify(t.body):void 0,headers:n,method:t.method??"GET",signal:r.signal}),d=await a.text(),l={};try{l=d?JSON.parse(d):{}}catch{l={error:d.slice(0,300)}}if(!a.ok)throw new Me(typeof l.error=="string"?l.error:`Runner API returned ${a.status}`,a.status,l.reRegister===!0);return l}finally{clearTimeout(o),t.signal?.removeEventListener("abort",i)}}async function hi(e){await Fe("/api/runner/register",{body:e,method:"POST",timeoutMs:15e3})}async function yi(e,t){return(await Fe(`/api/runner/work?runnerId=${encodeURIComponent(e)}`,{signal:t,timeoutMs:28e3})).job??null}async function bi(e){await Fe("/api/runner/heartbeat",{body:{runnerId:e},method:"POST",timeoutMs:1e4})}async function wi(e,t){return{cancelRequested:(await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/events`,{body:{events:t},method:"POST",timeoutMs:15e3})).cancelRequested===!0}}async function Pn(e,t,n){await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/complete`,{body:{result:n,runnerId:t},method:"POST",timeoutMs:15e3})}async function Ut(e,t,n,r=!0){await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/fail`,{body:{message:n,retryable:r,runnerId:t},method:"POST",timeoutMs:15e3})}import{mkdirSync as Rc,readFileSync as Sc,writeFileSync as vi}from"fs";import{dirname as $c,join as Tc}from"path";function _n(e){return Tc(e,"sessions.json")}function Ln(e){try{let t=Sc(_n(e),"utf8"),n=JSON.parse(t);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}return{}}function xi(e,t,n){return t?Ln(e)[t]?.[n]??null:null}function ki(e,t,n,r){if(!(!t||!r))try{let o=_n(e);Rc($c(o),{recursive:!0});let i=Ln(e);i[t]={...i[t],[n]:r},vi(o,`${JSON.stringify(i,null," ")}
59
- `,"utf8")}catch{}}function Ci(e,t,n){if(t)try{let r=Ln(e);if(!r[t])return;delete r[t][n],vi(_n(e),`${JSON.stringify(r,null," ")}
60
- `,"utf8")}catch{}}var _c=300,Lc=3e4;async function Ii(e){let[t,n]=await Promise.all([Nt(e.claudeBin),qt(e.codexBin)]);if(!t&&!n)throw new Error("Neither Claude Code nor Codex was found on this machine. Install one and log in, then retry.");t?e.log(`Claude Code detected: ${t.version} (${t.bin})`):e.log("Claude Code not found \u2014 Claude turns will be declined."),n?e.log(`Codex detected: ${n.version} (${n.bin})`):e.log("Codex not found \u2014 Codex turns will be declined.");let r=[...t?["claude-code"]:[],...n?["codex"]:[]],o=`${jt().split(".")[0]}-${Ec().slice(0,8)}`,i=()=>hi({capabilities:["chat_turn","proof"],claudeCodeVersion:t?.version??null,cliVersion:e.version,codexVersion:n?.version??null,hostname:jt(),platform:Oc(),runnerId:o,runtimes:r});for(await i(),e.log(`Registered as ${o} (runtimes: ${r.join(", ")}). Waiting for work\u2026`);!e.signal?.aborted;){let a=null;try{a=await yi(o,e.signal)}catch(d){if(e.signal?.aborted)break;if(d instanceof Me&&d.reRegister){e.log("Server asked for re-registration."),await i().catch(()=>{});continue}e.log(`Work poll failed (${d instanceof Error?d.message:"unknown"}); retrying\u2026`),await qc(e.pollBackoffMs??5e3,e.signal);continue}if(!a){if(e.once)continue;continue}if(e.log(`Claimed ${a.jobType} job ${a.runId}.`),await Dc({claude:t,codex:n,job:a,options:e,runnerId:o}),e.once)break}}async function Dc({claude:e,codex:t,job:n,options:r,runnerId:o}){let i=new AbortController,a=()=>i.abort();r.signal?.addEventListener("abort",a,{once:!0});let d=setInterval(()=>{bi(o).catch(()=>{})},Lc),l=[],y=!1,p=async()=>{if(y||l.length===0)return;y=!0;let C=l.splice(0,100);try{let{cancelRequested:E}=await wi(n.runId,C);E&&i.abort()}catch(E){E instanceof Me&&E.statusCode===409&&i.abort()}finally{y=!1}},w=setInterval(()=>{p()},_c),v=C=>{l.push(C)};try{if(n.jobType==="runner.proof"){let C=typeof n.input.message=="string"?n.input.message:"proof";v({eventType:"proof.echo",payload:{message:C}}),await Dn(p,l),await Pn(n.runId,o,{echo:C}),r.log(`Proof job ${n.runId} completed.`);return}if(n.jobType==="runner.chat_turn"){let C=n.input.runtime==="codex"?"codex":"claude-code",E=C==="codex"?t&&{detection:t,run:fi}:e&&{detection:e,run:li};if(!E){await Ut(n.runId,o,C==="codex"?"Codex is not available on this machine. Install the Codex app or CLI and log in, then retry.":"Claude Code is not available on this machine. Install it and log in, then retry.",!1);return}let k=typeof n.input.chatId=="string"&&n.input.chatId?n.input.chatId:null,$=Pc(r.workspaceRoot,"chats",k??n.runId);await Ac($,{recursive:!0});let S=Nc(n.input),V=I=>v({eventType:I.eventType,message:I.message??null,payload:I.eventType==="chat.session"?{host:jt(),runtime:C,runtimeVersion:E.detection.version,...I.payload??{}}:I.payload??{}}),A=xi(r.workspaceRoot,k,C),q;try{q=await E.run({bin:E.detection.bin,input:S,onEvent:V,resumeSessionId:A,signal:i.signal,workspace:$})}catch(I){if(!A||i.signal.aborted)throw I;r.log(`Resume of ${C} session failed (${I instanceof Error?I.message:"unknown"}); retrying fresh.`),Ci(r.workspaceRoot,k,C),q=await E.run({bin:E.detection.bin,input:S,onEvent:V,resumeSessionId:null,signal:i.signal,workspace:$})}ki(r.workspaceRoot,k,C,q.sessionId),v({eventType:"chat.session",payload:{host:jt(),runtime:C,runtimeVersion:E.detection.version,sessionId:q.sessionId,sessionPath:q.sessionPath}}),await Dn(p,l),await Pn(n.runId,o,{modelId:q.modelId,runtime:C,runtimeVersion:E.detection.version,sessionId:q.sessionId,sessionPath:q.sessionPath,text:q.text,usage:q.usage??{}}),r.log(`Chat turn ${n.runId} (${C}) completed.`);return}await Ut(n.runId,o,`This runner does not support ${n.jobType} jobs. Update the desktop app / CLI.`,!1)}catch(C){let E=C instanceof Error?C.message:"Local runner job crashed.";r.log(`Job ${n.runId} failed: ${E}`),await Dn(p,l).catch(()=>{}),await Ut(n.runId,o,E).catch(()=>{})}finally{clearInterval(w),clearInterval(d),r.signal?.removeEventListener("abort",a)}}function Nc(e){let t=Array.isArray(e.messages)?e.messages.map(n=>{if(!n||typeof n!="object")return null;let r=n;return{role:typeof r.role=="string"?r.role:"user",text:typeof r.text=="string"?r.text:""}}).filter(n=>!!n):[];return{effort:typeof e.effort=="string"?e.effort:null,messages:t,modelId:typeof e.modelId=="string"?e.modelId:null,system:typeof e.system=="string"?e.system:null,thinking:typeof e.thinking=="string"?e.thinking:null}}async function Dn(e,t){for(;t.length>0;)await e(),t.length>0&&await new Promise(n=>setTimeout(n,25))}function qc(e,t){return e<=0||t?.aborted?Promise.resolve():new Promise(n=>{let r=setTimeout(o,e);function o(){clearTimeout(r),t?.removeEventListener("abort",o),n()}t?.addEventListener("abort",o,{once:!0})})}function Fc(){return jc(Uc(),`.${m.commands[0]}-runner`,"runs")}var Mt=new Mc("runner").description("Run agent work locally with your own Claude Code / Codex login (desktop lane)");Mt.command("status").description("Check local Claude Code / Codex detection and account auth").action(async()=>{let[e,t]=await Promise.all([Nt(),qt()]);if(console.log(e?de.green(`\u2713 Claude Code ${e.version}`):de.red("\u2717 Claude Code not found on PATH")),console.log(t?de.green(`\u2713 Codex ${t.version} (${t.bin})`):de.red("\u2717 Codex not found (PATH or Codex.app)")),!fe()){console.log(de.red(`\u2717 Not logged in. Run '${m.commands[0]} login' first.`)),process.exitCode=2;return}try{let n=await ye();console.log(de.green(`\u2713 Logged in as ${n.user.email}`))}catch(n){console.log(de.red(`\u2717 Auth check failed: ${n instanceof Error?n.message:"unknown"}`)),process.exitCode=2}});Mt.command("start").description("Start the local runner (register + wait for work)").option("--once","Execute a single job, then exit").option("--workspace <dir>","Workspace root for job scratch directories").option("--claude-bin <path>","Path to the claude binary").option("--codex-bin <path>","Path to the codex binary").action(async e=>{fe()||(console.error(de.red(`Not authenticated. Run '${m.commands[0]} login' first.`)),process.exit(2));let t=new AbortController,n=()=>{console.log(de.gray(`
61
- Stopping runner\u2026`)),t.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await Ii({claudeBin:e.claudeBin,codexBin:e.codexBin,log:r=>console.log(de.gray(`[runner] ${r}`)),once:e.once,signal:t.signal,version:"0.3.22",workspaceRoot:e.workspace??Fc()})}catch(r){console.error(de.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import j from"chalk";import{Command as Vp}from"commander";import{Command as Nn}from"commander";function Vc(e,t){return[...t,e]}var Gc=new Nn("create").description("Start durable ad-set generation").argument("<title>","Ad-set title").requiredOption("--brief <brief>","Campaign brief").option("--hook <text>","Opening hook (repeat)",Vc,[]).option("--style <style>","ugc, clean, cinematic, or testimonial","ugc").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve generation");try{u(await h("createAdSet",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,brief:t.brief,hooks:t.hook.length?t.hook:[t.brief],style:t.style,teamId:t.teamId,title:e}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),Bc=new Nn("status").description("Read ad-set generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createAdSet",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ri=new Nn("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(Gc).addCommand(Bc);import{randomUUID as Wc}from"crypto";import{Command as Ve}from"commander";function Si(e){return new Ve(e).description(e==="create"?"Create and activate a scheduled agent":"Create a reviewable agent recommendation").argument("<name>","Agent name").requiredOption("--instructions <markdown>","Agent instructions").option("--description <text>","Agent description","").option("--schedule <frequency>","manual, daily, weekdays, weekly, or monthly","weekly").option("--time <hh:mm>","Local run time","09:00").option("--timezone <zone>","IANA timezone","UTC").option("--output <adapter>","Output adapter","digest").option("--team-id <id>","Workspace ID").option("--yes","Approve saving the agent").action(async(t,n)=>{if(!n.yes)return s("Pass --yes to approve this operation");try{u(await h(e==="create"?"createAgent":"recommendAgent",{approvalReceipt:"cli:--yes",description:n.description,instructionsMarkdown:n.instructions,name:t,output:n.output,schedule:n.schedule,scheduleTime:n.time,teamId:n.teamId,timezone:n.timezone}))}catch(r){s(r instanceof Error?r.message:"Agent operation failed"),process.exit(c.GENERAL_ERROR)}})}function Un(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function $i(e){return`cli:agent-memory:${e}:${Wc()}`}function Kc(e,t){let n=e.indexOf("="),r=n===-1?e:e.slice(0,n),o=n===-1?"":e.slice(n+1);return[...t,{name:r.trim(),note:o.trim()}]}function qn(e,t){return[...t,e]}var Jc=new Ve("show").description("Show what a scheduled agent remembers").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("getAgentMemory",{agentId:e,teamId:t.teamId}))}catch(n){Un(n,"Could not read the agent's memory")}}),zc=new Ve("set").description("Add to or remove from what an agent remembers. Owner or workspace admin only.").argument("<agent-id>","Agent ID").option("--learned <text>","Durable fact to add (repeatable)",qn,[]).option("--always <text>","Standing instruction to add (repeatable)",qn,[]).option("--never <text>","Thing it must not do, to add (repeatable)",qn,[]).option("--track <name=note>","Entity to track, as name=note (repeatable)",Kc,[]).option("--notes <text>","Replace the freeform notes").option("--remove <field>","Remove instead of add: learned, recurringInstructions, negativePreferences, entities, or notes").option("--value <text>","Item to remove; not needed when removing notes").option("--expected-version <n>","Refuse the write unless the stored memory is still at this version").option("--team-id <id>","Workspace ID").action(async(e,t)=>{let n=typeof t.remove=="string";try{u(await h("updateAgentMemory",{agentId:e,entities:t.track.length?t.track:void 0,expectedVersion:t.expectedVersion===void 0?void 0:Number.parseInt(t.expectedVersion,10),learned:t.learned.length?t.learned:void 0,negativePreferences:t.never.length?t.never:void 0,notes:t.notes,operation:n?"remove":"add",recurringInstructions:t.always.length?t.always:void 0,removeField:t.remove,removeValue:t.value,teamId:t.teamId},$i(n?"remove":"add")))}catch(r){Un(r,"Could not update the agent's memory")}}),Xc=new Ve("forget").description("Erase every stored version of an agent's memory. This cannot be undone.").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").option("--yes","Confirm the erase").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to erase this agent's memory");try{u(await h("forgetAgentMemory",{agentId:e,teamId:t.teamId},$i("forget")))}catch(n){Un(n,"Could not erase the agent's memory")}}),Hc=new Ve("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(Jc).addCommand(zc).addCommand(Xc),Ti=new Ve("agent").description("Create scheduled agents and read, edit, or erase what they remember").addCommand(Si("create")).addCommand(Si("recommend")).addCommand(Hc);import{randomUUID as Oi}from"crypto";import{existsSync as Zc}from"fs";import{resolve as el}from"path";import ct from"chalk";import{Command as be}from"commander";import tl from"ora";import{mkdir as Yc,writeFile as Ei}from"fs/promises";import{dirname as Qc}from"path";async function Y(e,t){if(await Yc(Qc(t),{recursive:!0}),e.startsWith("data:")){let o=e.match(/^data:[^;]+;base64,(.+)$/);if(!o)throw new Error("Invalid data URL format");let i=Buffer.from(o[1],"base64");if(i.length===0)throw new Error("Downloaded media was empty");await Ei(t,i);return}let n=await fetch(e);if(!n.ok)throw new Error(`Failed to download media: ${n.status}`);let r=Buffer.from(await n.arrayBuffer());if(r.length===0)throw new Error("Downloaded media was empty");await Ei(t,r)}var nl=15e3,rl=40,Ai=3;async function Pi(e,t){if(e?.length){if(e.length>Ai)throw new Error(`A presenter Look accepts at most ${Ai} reference images`);return Promise.all(e.map(async(n,r)=>{if(Zc(n))return{url:(await me(el(n),{idempotencyKey:`${t}:reference:${r+1}`})).url};let o;try{o=new URL(n)}catch(i){throw new Error(`Reference image ${r+1} must be an existing local file or an HTTP(S) URL.`,{cause:i})}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`Reference image ${r+1} must use an HTTP(S) URL.`);return{url:o.toString()}}))}}function jn(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.durationSec!=null&&g(`Duration: ${e.durationSec}s`),e.videoUrl&&x(`Video URL: ${e.videoUrl}`),e.error&&s(`Error: ${e.error}`)}var ol=new be("options").description("List available presenter avatars and voices").option("--language <language>","Filter voices by language").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await Ro(e.language);if(e.format==="json"){u(t);return}let n=t.personal??[];if(e.format==="quiet"){for(let r of n)console.log(r.id);for(let r of t.avatars)console.log(r.id);for(let r of t.voices)console.log(r.id);return}if(n.length>0){g("Your presenters:");for(let r of n)console.log(` ${r.id} ${r.name}`)}g("Avatars:");for(let r of t.avatars){let o=r.renderTiers?.length?` [${r.renderTiers.join(", ")}]`:"";console.log(` ${r.id} ${r.name}${o}`)}g("Voices:");for(let r of t.voices)console.log(` ${r.id} ${r.name}${r.language?` (${r.language})`:""}`)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),il=new be("generate").description("Generate a reusable presenter clip").option("--avatar-id <id>","Avatar id from 'avatar options'; sandbox runs use the host presenter policy").option("--audio-url <url>","Public narration audio URL for avatar lip sync").option("--voice-id <id>","Voice id from 'avatar options'").option("--script <text>","Exact words for the presenter to speak").requiredOption("-o, --output <path>","Local output path").option("--aspect <aspect>","Aspect: 1:1, 9:16, 16:9","9:16").option("--duration <seconds>","Maximum requested duration (1-300)").option("--transparent","Render a transparent-background WebM presenter clip").option("--background-color <hex>","Solid presenter background color, for example #0F172A").option("--background-image-url <url>","Public image URL used as the presenter background").option("--fit <mode>","Background image fit: contain or cover").option("--output-format <container>","Container: mp4 (default) or webm \u2014 webm renders a transparent-background clip (single scene) for compositing").option("--render-tier <tier>","Render cost/quality: basic, standard, premium","basic").option("--title <title>","Clip title","Presenter clip").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.transparent?"webm":e.outputFormat;!!e.audioUrl==!!e.script&&(s("Provide exactly one avatar speech input: --audio-url or --script"),process.exit(c.INVALID_INPUT)),["1:1","9:16","16:9"].includes(e.aspect)||(s("Aspect must be one of 1:1, 9:16, or 16:9"),process.exit(c.INVALID_INPUT)),e.outputFormat!==void 0&&!["mp4","webm"].includes(e.outputFormat)&&(s("Output format must be mp4 or webm"),process.exit(c.INVALID_INPUT)),e.backgroundColor!==void 0&&!/^#[0-9a-fA-F]{6}$/.test(e.backgroundColor)&&(s("Background color must be a six-digit hex value"),process.exit(c.INVALID_INPUT)),e.backgroundColor&&e.backgroundImageUrl&&(s("Provide only one presenter background"),process.exit(c.INVALID_INPUT)),e.fit!==void 0&&!["contain","cover"].includes(e.fit)&&(s("Fit must be contain or cover"),process.exit(c.INVALID_INPUT)),e.fit&&!e.backgroundImageUrl&&(s("Fit requires --background-image-url"),process.exit(c.INVALID_INPUT)),e.transparent&&e.outputFormat==="mp4"&&(s("--transparent cannot be combined with --output-format mp4"),process.exit(c.INVALID_INPUT)),t==="webm"&&(e.backgroundColor||e.backgroundImageUrl)&&(s("Transparent WebM output cannot be combined with a background"),process.exit(c.INVALID_INPUT)),["basic","standard","premium"].includes(e.renderTier)||(s("Render tier must be basic, standard, or premium"),process.exit(c.INVALID_INPUT));let n=e.duration?Number.parseInt(e.duration,10):void 0;n!==void 0&&(!Number.isFinite(n)||n<1||n>300)&&(s("Duration must be between 1 and 300 seconds"),process.exit(c.INVALID_INPUT));let r=e.format==="human"?tl("Generating presenter clip...").start():null;try{let o=e.audioUrl?{audioUrl:e.audioUrl}:{script:e.script??"",...e.voiceId?{voiceId:e.voiceId}:{}},i=await So({...o,aspect:e.aspect,...e.avatarId?{avatarId:e.avatarId}:{},...e.backgroundColor?{backgroundHex:e.backgroundColor}:{},...e.backgroundImageUrl?{backgroundImageUrl:e.backgroundImageUrl}:{},...n!==void 0?{durationSec:n}:{},...e.fit?{fit:e.fit}:{},...t?{outputFormat:t}:{},renderTier:e.renderTier,title:e.title});if(!e.wait){r?.stop(),jn(i,e.format);return}let a=await te(()=>In(i.requestId),rl,nl);if(a.status==="failed")throw new Error(a.error||"Presenter generation failed");if(!a.videoUrl)throw new Error("Presenter generation completed without a video URL");r&&(r.text="Downloading presenter clip..."),await Y(a.videoUrl,e.output),r?.stop(),jn(a,e.format),e.format==="human"&&x(`Saved to: ${e.output}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),al=new be("status").description("Check a presenter clip generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{jn(await In(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),sl=new be("generate").description("Generate another look for an existing personal presenter").argument("<base-profile-id>","Base personal presenter id (pp_*)").requiredOption("--name <name>","Look name").requiredOption("--description <description>","Short look description").requiredOption("--prompt <prompt>","Exact appearance generation prompt").requiredOption("--look-id <id>","Stable template/look id").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this look request").action(async(e,t)=>{try{let n=t.idempotencyKey??Oi(),r=await Pi(t.referenceImage,n),o=await h("generatePresenterLook",{baseProfileId:e,description:t.description,id:t.lookId,prompt:t.prompt,...r?{referenceImages:r}:{},title:t.name},n);u(o)}catch(n){s(n instanceof Error?n.message:"Look generation failed"),process.exit(c.GENERAL_ERROR)}}),dl=new be("status").description("Read presenter look generation status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("generatePresenterLook",e);if(t.format==="json")return u(n);if(t.format==="quiet")return console.log(n.status);g(`Run ID: ${e}`),g(`Status: ${n.status}`),n.error?.message&&s(n.error.message)}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),cl=new be("revise").description("Create a new Look by editing an existing presenter Look").argument("<look-id>","Ready presenter Look id (pp_*)").requiredOption("--instruction <instruction>","What to add, remove, or change").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this revision").action(async(e,t)=>{try{let n=t.idempotencyKey??Oi(),r=await Pi(t.referenceImage,n),o=await h("revisePresenterLook",{instruction:t.instruction,...r?{referenceImages:r}:{},sourceLookId:e},n);u(o)}catch(n){s(n instanceof Error?n.message:"Look revision failed"),process.exit(c.GENERAL_ERROR)}}),ll=new be("revision-status").description("Read presenter Look revision status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("revisePresenterLook",e);if(t.format==="json")return u(n);if(t.format==="quiet")return console.log(n.status);g(`Run ID: ${e}`),g(`Status: ${n.status}`),n.error?.message&&s(n.error.message)}catch(n){s(n instanceof Error?n.message:"Revision status failed"),process.exit(c.GENERAL_ERROR)}}),ml=new be("look").description("Manage looks under an existing personal presenter").addCommand(sl).addCommand(cl).addCommand(ll).addCommand(dl),Mn=new be("avatar").description("Generate presenter clips and looks; avatar options lists the voices and looks used by presentation video presenter and cast preset").addCommand(ol).addCommand(il).addCommand(ml).addCommand(al);Mn.addHelpText("after",`
62
- ${ct.bold("Examples:")}
63
- ${ct.gray("# Discover the presenter avatars and voices you can use")}
64
- $ ${m.commands[0]} avatar options
65
-
66
- ${ct.bold("See also:")}
67
- ${ct.gray("# Save a presenter + backdrop + voice combination under a name")}
68
- $ ${m.commands[0]} cast preset --help
69
-
70
- ${ct.gray("# Apply an avatar, look, or preset to one presentation-video scene")}
71
- $ ${m.commands[0]} presentation video presenter <project-id>
72
- `);import{writeFile as Ui}from"fs/promises";import z from"chalk";import{Command as oe}from"commander";import Cl from"ora";import{createHash as ul}from"crypto";import{existsSync as pl}from"fs";import{basename as gl}from"path";import{Command as _i}from"commander";import fl from"ora";var Li=new _i("logo").description("Brand logo files").addCommand(new _i("set").description("Set a brand's logo, dark variant, or favicon").argument("[brand-id]","Brand ID (defaults to this workspace's default brand)").requiredOption("--file <path>","Local image file to upload and use").option("--variant <variant>","primary | dark | favicon. 'dark' is the reversed lock-up for dark backgrounds","primary").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await O();let n=t.variant??"primary";["primary","dark","favicon"].includes(n)||(s(`--variant must be primary, dark, or favicon (got "${n}")`),process.exit(c.INVALID_INPUT)),pl(t.file)||(s(`File not found: ${t.file}`),process.exit(c.INVALID_INPUT));let r=fl({text:`Uploading ${gl(t.file)}...`,stream:process.stdout}).start(),o;try{o=(await me(t.file)).url,r.succeed("Uploaded")}catch(i){r.fail("Upload failed"),s(i instanceof Error?i.message:String(i)),process.exit(c.GENERAL_ERROR)}try{u(await h("setBrandLogo",{brandId:e,fileUrl:o,teamId:t.teamId,variant:n},ul("sha256").update(`setBrandLogo:${e??"default"}:${n}:${o}`).digest("hex").slice(0,32)))}catch(i){s(i instanceof Error?i.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}));import{readFile as hl}from"fs/promises";import{randomUUID as yl}from"crypto";import{Command as Di}from"commander";var bl=["color.primary","color.background","color.text","color.secondary","color.accent","color.surface","color.link","typography.primary","typography.secondary","typography.h1","typography.h2","typography.h3","typography.h4","typography.h5","typography.h6","typography.paragraph","typography.button","typography.small","typography.label","typography.caption","asset.logo","asset.logo.dark","asset.favicon"];function wl(e){let t=e.split(".").filter(Boolean);for(let n=t.length;n>=2;n--){let r=t.slice(0,n).join(".");if(bl.includes(r))return{fieldPath:t.slice(n),nodeKey:r}}return{fieldPath:t.slice(2),nodeKey:t.slice(0,2).join(".")}}function vl(e){let t={};for(let n of e){let r=n.indexOf("=");if(r<=0)throw new Error(`"${n}" is not a token assignment. Use key=value, e.g. color.primary=#114b97`);let o=n.slice(0,r).trim(),i=n.slice(r+1);if(o.split(".").filter(Boolean).length<2)throw new Error(`"${o}" is not a brand token key. Expected something like color.primary or typography.h1.size`);let{fieldPath:d,nodeKey:l}=wl(o),y=xl(i);if(d.length===0){t[l]=y;continue}let p=t[l],w=p&&typeof p=="object"&&!Array.isArray(p)?p:{},v=w;for(let C of d.slice(0,-1)){let E=v[C],k=E&&typeof E=="object"&&!Array.isArray(E)?E:{};v[C]=k,v=k}v[d[d.length-1]]=y,t[l]=w}return t}function xl(e){return e==="true"?!0:e==="false"?!1:/^-?\d+(?:\.\d+)?$/.test(e)?Number(e):e}function kl(e,t){return e===void 0?{assignments:[...t]}:e.includes("=")?{assignments:[e,...t]}:{assignments:[...t],brandId:e}}var Ni=new Di("profile").description("Read a brand's design tokens, the keys it is missing, or its design.md").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").option("--format <format>","tokens (default) or md").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{let n=await h("getBrandProfile",{brandId:e,format:t.format,teamId:t.teamId});if(t.format==="md"&&typeof n.designMd=="string"){console.log(n.designMd);return}u(n)}catch(n){s(n instanceof Error?n.message:"Profile read failed"),process.exit(c.GENERAL_ERROR)}}),qi=new Di("set").description("Write brand design tokens (key=value pairs or a design.md)").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").argument("[tokens...]","Token assignments, e.g. color.primary=#114b97 typography.h1.size=32px").option("--design-md <path>","Apply a whole design.md file instead").option("--no-publish","Stage the change without publishing a new active brand version").option("--team-id <id>","Workspace ID").option("--yes","Confirm writing brand data").action(async(e,t,n)=>{n.yes||(s("Pass --yes to confirm writing brand tokens."),process.exit(c.INVALID_INPUT));let{assignments:r,brandId:o}=kl(e,t),i;try{i=r.length>0?vl(r):void 0}catch(d){s(d instanceof Error?d.message:"Invalid token pair"),process.exit(c.INVALID_INPUT)}let a;if(n.designMd)try{a=await hl(n.designMd,"utf8")}catch(d){s(`Could not read ${n.designMd}: ${d instanceof Error?d.message:String(d)}`),process.exit(c.INVALID_INPUT)}!i&&!a&&(s("Nothing to write. Pass token assignments (color.primary=#114b97) or --design-md <file>."),process.exit(c.INVALID_INPUT));try{u(await h("updateBrandTokens",{brandId:o,designMd:a,publish:n.publish===!1?!1:void 0,teamId:n.teamId,tokens:i},yl()))}catch(d){s(d instanceof Error?d.message:"Write failed"),process.exit(c.GENERAL_ERROR)}});var ji=new oe("branding").description("Manage brand profiles, design tokens, logos, competitors, and social handles").addCommand(Ni).addCommand(qi).addCommand(new oe("list").description("List brand profiles").option("-f, --format <format>","Output format (table, json)",b("--format",["table","json"]),"table").action(async e=>{await O();try{let t=await vn();if(t.brandings.length===0){e.format==="json"?console.log(JSON.stringify([])):(g("No brand profiles found"),console.log(),console.log(z.gray(`Create one with: ${m.commands[0]} branding extract <url>`)));return}e.format==="json"?console.log(JSON.stringify(t.brandings,null,2)):console.log(Ur(t.brandings))}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new oe("get").description("Get brand profile details").argument("<id>","Brand profile ID").option("-f, --format <format>","Output format (summary, json)",b("--format",["summary","json"]),"summary").option("-o, --output <path>","Save JSON to file").action(async(e,t)=>{await O();try{let n=await lo(e);if(t.output){await Ui(t.output,JSON.stringify(n,null,2)),x(`Brand profile saved to ${t.output}`);return}if(t.format==="json")console.log(JSON.stringify(n,null,2));else{if(ie("Brand Profile"),console.log(),R("ID",n.id),R("Name",n.name),R("Source URL",n.sourceUrl??z.gray("None")),R("Default",n.isDefault?z.green("Yes"):"No"),n.createdAt&&R("Created",new Date(n.createdAt).toLocaleString()),console.log(),n.primaryColor||n.colors.length>0){if(console.log(z.bold(" Colors")),n.primaryColor){let o=z.bgHex(n.primaryColor)(" ");console.log(` Primary: ${o} ${n.primaryColor}`)}if(n.colors.length>0){console.log(" Palette:");for(let o of n.colors.slice(0,10)){let i=z.bgHex(o.hex)(" "),a=o.role?z.gray(` (${o.role})`):"";console.log(` ${i} ${o.hex}${a}`)}}console.log()}n.logoUrl&&(console.log(z.bold(" Logo")),console.log(` ${n.logoUrl}`),console.log());let r=n.typography;r&&Object.keys(r).length>0&&(console.log(z.bold(" Typography")),(r.primary||r.headings)&&console.log(` Headings: ${r.primary||r.headings||"-"}`),(r.secondary||r.body)&&console.log(` Body: ${r.secondary||r.body||"-"}`),console.log()),(n.confidence||n.extractionMethod)&&(console.log(z.bold(" Extraction")),n.confidence&&console.log(` Confidence: ${Math.round(n.confidence*100)}%`),n.extractionMethod&&console.log(` Method: ${n.extractionMethod}`),console.log()),console.log(z.gray(" Use --format json for full details")),console.log()}}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new oe("find").description("Find existing brand profile by name or URL").argument("<query>","Brand name or website URL to search for").action(async e=>{await O();try{let t=await vn(),n=e.toLowerCase().replace(/^https?:\/\//,"").replace(/\/$/,""),r=t.brandings.filter(o=>{let i=(o.name||"").toLowerCase(),a=(o.sourceUrl||"").toLowerCase().replace(/^https?:\/\//,"").replace(/\/$/,"");return i.includes(n)||a.includes(n)||i.length>0&&n.includes(i)||a.length>0&&n.includes(a)});if(r.length===0){g(`No brand profiles matching "${e}"`),console.log(z.gray(` Extract one with: ${m.commands[0]} branding extract <url>`));return}console.log(`Found ${r.length} brand${r.length>1?"s":""}:
73
- `);for(let o of r){let i=o.primaryColor?`${z.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"";console.log(` ${z.bold(o.name)} ${z.gray(o.id)}`),o.sourceUrl&&console.log(` ${z.gray(o.sourceUrl)}`),i&&console.log(` ${i}`),console.log()}console.log(z.gray(` Export with: ${m.commands[0]} branding get <id> -o branding.json`))}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new oe("extract").description("Extract brand profile from a website").argument("<url>","Website URL to extract branding from").option("--team-id <id>","Team ID").option("--yes","Confirm starting a paid/external extraction").option("--no-save","Extract without saving").option("-o, --output <path>","Save JSON to file").action(async(e,t)=>{await O(),t.yes||(s("Pass --yes to confirm brand extraction."),process.exit(c.INVALID_INPUT));try{new URL(e.startsWith("http")?e:`https://${e}`)}catch{s("Invalid URL format"),process.exit(6)}let n=e.startsWith("http")?e:`https://${e}`,r=t.teamId??Ct(),o=Cl({text:`Extracting branding from ${n}...`,stream:process.stdout}).start();try{let i=await mo(n,r,"cli:--yes");o.succeed("Brand extraction started");let a=JSON.stringify(i,null,2);t.output?(await Ui(t.output,a),x(`Brand profile saved to ${t.output}`)):console.log(a),g(`Check progress with: ${m.commands[0]} branding status ${i.runId}`),console.log()}catch(i){o.fail("Extraction failed"),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})).addCommand(new oe("status").description("Check a brand extraction run").argument("<run-id>","Run ID returned by branding extract").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("extractBranding",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}})).addCommand(new oe("set-default").description("Set a brand profile as default").argument("<id>","Brand profile ID").action(async e=>{await O(),g(`To set brand ${e} as default, use the web dashboard.`),console.log(),console.log(z.gray("API support for setting default brand is coming soon."))})).addCommand(new oe("competitor").description("Brand competitor commands").addCommand(new oe("list").description("List competitors for a brand").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").action(async e=>{try{console.log(JSON.stringify(await h("getBrandCompetitors",{brandingId:e.brandingId,teamId:e.teamId}),null,2))}catch(t){s(t instanceof Error?t.message:"Lookup failed"),process.exit(1)}})).addCommand(new oe("add").description("Add or update a brand competitor").argument("<name>","Competitor name").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").option("--website <url>","Competitor website").option("--x-handle <handle>","Competitor X handle").option("--yes","Confirm writing brand data").action(async(e,t)=>{t.yes||(s("Pass --yes to confirm adding a competitor."),process.exit(c.INVALID_INPUT));try{u(await h("addCompetitor",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,name:e,teamId:t.teamId,website:t.website,xHandle:t.xHandle}))}catch(n){s(n instanceof Error?n.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}))).addCommand(Li).addCommand(new oe("social").description("Brand social handle commands").addCommand(new oe("add").description("Add or update a brand social handle").argument("<platform>","Social platform").argument("<handle>","Account handle").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").option("--yes","Confirm writing brand data").action(async(e,t,n)=>{n.yes||(s("Pass --yes to confirm adding a social handle."),process.exit(c.INVALID_INPUT));try{u(await h("addBrandSocialHandle",{approvalReceipt:"cli:--yes",brandingId:n.brandingId,handle:t,platform:e,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Write failed"),process.exit(c.GENERAL_ERROR)}})));import lt from"chalk";import{Command as Ge}from"commander";function Il(e){switch(e.background){case"color":{if(!e.backgroundColor)throw new Error("--background color needs --background-color <hex>, e.g. #1d4ed8");return{hex:e.backgroundColor,kind:"color"}}case"image":{if(!e.backgroundImage)throw new Error("--background image needs --background-image <url>");return{fit:e.fit,kind:"image",url:e.backgroundImage}}default:return{kind:e.background}}}function Mi(e,t){return{background:Il(t),name:e,presenterProfileId:t.presenter,...t.voiceId?{voiceId:t.voiceId}:{}}}function Ft(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.id);return}x(`${e.name} (${e.id})`),g(` Presenter: ${e.presenterProfileId}`),g(` Backdrop: ${Rl(e.background)}`),e.voiceId&&g(` Voice: ${e.voiceId}`)}function Rl(e){switch(e.kind){case"color":return`color ${e.hex}`;case"image":return`image ${e.url} (${e.fit})`;default:return e.kind}}function Fi(e){return e.requiredOption("--presenter <profileId>",`Trained personal presenter id (pp_*), from \`${m.commands[0]} avatar options\``).option("--background <kind>","Backdrop: original, transparent, color, or image","original").option("--background-color <hex>","Backdrop color, e.g. #1d4ed8").option("--background-image <url>","Backdrop image URL").option("--fit <fit>","How an image backdrop fills the frame","cover").option("--voice-id <voiceId>","Workspace voice to save with this preset").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human")}var Sl=new Ge("list").description("List saved cast presets you can use").option("--cast-member-id <castMemberId>","Only this person's presets").option("--branding-id <brandingId>","Narrow to one brand").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await _o({...e.brandingId?{brandingId:e.brandingId}:{},...e.castMemberId?{castMemberId:e.castMemberId}:{}});if(e.format==="json"){u(t);return}if(e.format==="quiet"){for(let n of t.presets)console.log(n.id);return}if(t.presets.length===0){g("No presets saved yet.");return}for(let n of t.presets)Ft(n,"human")}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(c.API_ERROR)}}),$l=Fi(new Ge("create").description("Save one way a cast member appears").argument("<name>",'What to call this preset, e.g. "In the cafe"').requiredOption("--cast-member-id <castMemberId>","The person this preset is a way of showing")).action(async(e,t)=>{try{let n=await Lo({castMemberId:t.castMemberId,...Mi(e,t)});Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Tl=Fi(new Ge("update").description("Change a saved preset (sends the complete preset)").argument("<presetId>","The preset to change").requiredOption("--name <name>","What to call it")).action(async(e,t)=>{try{let n=await Do({presetId:e,...Mi(t.name,t)});Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),El=new Ge("delete").description("Retire a saved preset. Existing videos keep working.").argument("<presetId>","The preset to retire").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await No(e);if(t.format==="human"){x(`Retired "${n.preset.name}".`);return}Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Al=new Ge("preset").description("Saved ways a cast member appears").addCommand(Sl).addCommand($l).addCommand(Tl).addCommand(El),Fn=new Ge("cast").description("The faces and voices your videos can use").addCommand(Al);Fn.addHelpText("after",`
74
- ${lt.bold("Examples:")}
75
- ${lt.gray("# List the saved presenter/backdrop/voice combinations")}
76
- $ ${m.commands[0]} cast preset list
77
-
78
- ${lt.bold("See also:")}
79
- ${lt.gray("# The presenter avatars, looks, and voices a preset is built from")}
80
- $ ${m.commands[0]} avatar options
81
-
82
- ${lt.gray("# Use a preset on one presentation-video scene")}
83
- $ ${m.commands[0]} presentation video presenter <project-id>
84
- `);import{readFile as Ol}from"fs/promises";import mt from"chalk";import{Command as Vi}from"commander";var Pl=new Vi("extract").description("Extract normalized text from a URL or local file").argument("<source>","URL, encoded source, or local file path").option("--team-id <id>","Workspace ID").option("--mime-type <type>","Source MIME type").option("--max-length <count>","Maximum output characters","30000").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=e,r;e.includes("://")||(n=await Ol(e,"utf8"),r=e);let o=await h("extractContent",{filename:r,maxLength:Number.parseInt(t.maxLength,10),mimeType:t.mimeType,source:n,teamId:t.teamId});t.format!=="quiet"&&u(o)}catch(n){s(n instanceof Error?n.message:"Extraction failed"),process.exit(c.GENERAL_ERROR)}}),Vn=new Vi("content").description("Extract normalized text from a URL, a local file, or an encoded document").addCommand(Pl);Vn.addHelpText("after",`
85
- ${mt.bold("Examples:")}
86
- ${mt.gray("# Normalized text from a local document")}
87
- $ ${m.commands[0]} content extract ./paper.pdf
88
-
89
- ${mt.bold("See also:")}
90
- ${mt.gray("# Web pages, with page metadata and cost reporting")}
91
- $ ${m.commands[0]} scrape https://example.com/post
92
-
93
- ${mt.gray("# Spoken words out of audio or video")}
94
- $ ${m.commands[0]} transcript --help
95
- `);import X from"chalk";import{Command as _l}from"commander";import{existsSync as Ll,readFileSync as Dl}from"fs";import Nl,{resolve as Gi}from"path";var Bi=new _l("create").description("Create a new presentation").argument("<topic>","The topic or title for the presentation").option("-n, --slides <count>","Number of slides (1-20)").option("-m, --mode <mode>","Generation quality (best, balanced, fast, ultrafast, instant, image-min, image, image-max) \u2014 default: fast. image-min/image/image-max render each slide as a full-bleed AI image (text not editable); slower + pricier, require image-mode access, and cap at 25 slides. image-min is cheapest (brand colors only, no exact fonts).").option("--image-tier <tier>","Embedded-image quality for HTML modes. Each tier is a per-image credit ceiling as well as its price: quick (+20/slide), smart (default, +60/slide), balanced (+250/slide), best (+500/slide, slow). Ignored for image-*/instant modes.").option("-t, --tone <tone>","Tone (creative, professional, educational, formal, casual)").option("--amount <amount>","Content density (minimal, concise, detailed, extensive)").option("--audience <text>","Target audience description").option("-l, --language <lang>","Output language").option("--branding-id <id>","Branding ID (from `ccr branding list` or `ccr branding extract`)").option("--brand-domain <url>","Brand the deck by website/domain (e.g. https://www.pfizer.com). Errors if no matching saved brand exists.").option("--template <id>","Slide template ID to style the deck after (from `ccr templates`). A default template is applied automatically when omitted.").option("-c, --context <text>","Inline text context (research notes, key facts)").option("--context-file <path>","Path to a context file (text, markdown, JSON)").option("--stdin","Read context from stdin").option("-f, --file <paths...>","Files to upload (PDF, PPTX, DOCX, images)").option("-g, --goal <type>","Goal (inform, persuade, train, learn, entertain, report)").option("--styling <mode>","Styling mode (freeform, brand-only, brand-plus-style, style-only, no-styling)").option("--reference-url <url>","Image URL to use as visual style reference").option("--thinking-depth <depth>","AI thinking depth (quick, moderate, deep, profound)").option("--theme <preset>","[instant mode only] Color theme preset (blue, violet, rose, orange, green)").option("--primary-color <hex>","[instant mode only] Primary color (e.g., #0066CC)").option("--secondary-color <hex>","[instant mode only] Secondary color").option("--accent-color <hex>","[instant mode only] Accent color").option("--background-color <hex>","[instant mode only] Background color").option("--foreground-color <hex>","[instant mode only] Foreground/text color").option("--decorations <style>","[instant mode only] Background decoration (none, waves-bottom-left, waves-top-right, blob-corners, minimal)").option("--team-id <id>","Team ID (switch teams)").option("--format <format>","Output format (human, json, quiet)",b("--format",["human","json","quiet"])).option("-o, --output <format>","Output format (human, json, quiet) \u2014 short form of --format",b("--output",["human","json","quiet"])).option("--no-stream","Wait for completion without streaming progress").option("--wait","Poll until generation completes").option("--debug","Enable debug logging").option("--open","Open in browser after creation").option("--id <uuid>","Use a specific UUID for the presentation").option("--studio","Studio mode: use current directory name as presentation ID (auto-links to Studio preview)").action(async(e,t)=>{t.output=t.format??t.output,await O();let n;t.slides!==void 0&&(n=parseInt(t.slides,10),(Number.isNaN(n)||n<1||n>20)&&(s("Slide count must be between 1 and 20"),process.exit(6)));let r=["best","balanced","fast","ultrafast","instant","image-min","image","image-max"];t.mode&&!r.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Valid: ${r.join(", ")}`),process.exit(6));let o=["smart","fast","balanced","best"];t.imageTier&&!o.includes(t.imageTier)&&(s(`Invalid image tier: ${t.imageTier}. Valid: ${o.join(", ")}`),process.exit(6));let i=["creative","professional","educational","formal","casual"];t.tone&&!i.includes(t.tone)&&(s(`Invalid tone: ${t.tone}. Valid: ${i.join(", ")}`),process.exit(6));let a=["minimal","concise","detailed","extensive"];t.amount&&!a.includes(t.amount)&&(s(`Invalid amount: ${t.amount}. Valid: ${a.join(", ")}`),process.exit(6));let d=["freeform","brand-only","brand-plus-style","style-only","no-styling"];t.styling&&!d.includes(t.styling)&&(s(`Invalid styling: ${t.styling}. Valid: ${d.join(", ")}`),process.exit(6));let l=["quick","moderate","deep","profound"];t.thinkingDepth&&!l.includes(t.thinkingDepth)&&(s(`Invalid thinking-depth: ${t.thinkingDepth}. Valid: ${l.join(", ")}`),process.exit(6));let y=["inform","persuade","train","learn","entertain","report"];t.goal&&!y.includes(t.goal)&&(s(`Invalid goal: ${t.goal}. Valid: ${y.join(", ")}`),process.exit(6));let p=["blue","violet","rose","orange","green"];t.theme&&!p.includes(t.theme)&&(s(`Invalid theme: ${t.theme}. Valid: ${p.join(", ")}`),process.exit(6));let w=["none","waves-bottom-left","waves-top-right","blob-corners","minimal"];t.decorations&&!w.includes(t.decorations)&&(s(`Invalid decorations: ${t.decorations}. Valid: ${w.join(", ")}`),process.exit(6));let v=t.theme||t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor||t.decorations;v&&t.mode&&t.mode!=="instant"&&(s("--theme, --primary-color, --decorations and other color options are only supported with --mode instant"),process.exit(6));let C=t.mode??(v?"instant":"fast"),E=/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;for(let[I,J]of[["primary-color",t.primaryColor],["secondary-color",t.secondaryColor],["accent-color",t.accentColor],["background-color",t.backgroundColor],["foreground-color",t.foregroundColor]])J&&!E.test(J)&&(s(`Invalid ${I}: ${J}. Must be hex (e.g., #0066CC)`),process.exit(6));try{t.output!=="json"&&t.output!=="quiet"&&process.stdout.write(X.gray("Checking generation limits... "));let I=await go(C,n??10,t.teamId);if(t.output!=="json"&&t.output!=="quiet"){console.log(X.green("\u2713"));let J=I.remaining[C],Z=I.limits[C],Se=J===void 0||Z===void 0?"":` | ${C}: ${J}/${Z} remaining`;console.log(X.gray(` Plan: ${I.planName}${Se}`))}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):(console.log(X.red("\u2717")),s(I instanceof Error?I.message:String(I))),process.exit(I.exitCode??1)}let k=[];if(t.file&&t.file.length>0){for(let I of t.file)Ll(Gi(I))||(s(`File not found: ${I}`),process.exit(6));t.output!=="json"&&t.output!=="quiet"&&console.log(X.gray(`
96
- Uploading ${t.file.length} file(s)...`));try{k=await Zr(t.file.map(I=>Gi(I)),(I,J,Z)=>{t.output!=="json"&&t.output!=="quiet"&&Z&&process.stdout.write(`\r ${X.cyan("\u2B06")} Uploading: ${Z} (${I+1}/${J})`)}),t.output!=="json"&&t.output!=="quiet"&&console.log(`\r ${X.green("\u2713")} Uploaded ${k.length} file(s) `)}catch(I){s(`Failed to upload files: ${I instanceof Error?I.message:String(I)}`),process.exit(1)}}let $;(t.stdin||!process.stdin.isTTY)&&($=await ql(),t.stdin&&!$&&(s("No content received from stdin"),process.exit(6)));let S=t.context;if(t.contextFile)try{S=Dl(t.contextFile,"utf-8"),S.trim()||(s(`Context file is empty: ${t.contextFile}`),process.exit(6))}catch{s(`Failed to read context file: ${t.contextFile}`),process.exit(6)}!$&&!S&&k.length===0&&(s("Context is required to create a presentation."),console.log(),console.log(X.gray(" -f, --file <paths...> Upload files (PDF, PPTX, images)")),console.log(X.gray(" -c, --context <text> Inline text context")),console.log(X.gray(" --context-file <path> Read from a file")),console.log(X.gray(` cat file | ${m.commands[0]} Pipe content`)),process.exit(6));let V=[...k];$&&V.push({id:`stdin-${Date.now()}`,content:$,title:"Piped Content",mime:"text/plain",selected:!0}),S&&V.push({id:`context-${Date.now()}`,content:S,title:"Context",mime:"text/plain",selected:!0});let A,q=t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor;(t.theme||q||t.decorations)&&(A={},t.theme&&(A.preset=t.theme),q&&(A.custom={},t.primaryColor&&(A.custom.primary=t.primaryColor),t.secondaryColor&&(A.custom.secondary=t.secondaryColor),t.accentColor&&(A.custom.accent=t.accentColor),t.backgroundColor&&(A.custom.background=t.backgroundColor),t.foregroundColor&&(A.custom.foreground=t.foregroundColor)),t.decorations&&(A.decorations=t.decorations));try{let I=await eo({topic:e,...n!==void 0&&{slideCount:n},mode:C,...t.imageTier&&{imageTier:t.imageTier},...t.tone&&{tone:t.tone},...t.amount&&{amount:t.amount},...t.audience&&{audience:t.audience},...t.language&&{language:t.language},...t.brandingId&&{brandingId:t.brandingId},...t.brandDomain&&{brandDomain:t.brandDomain},...t.template&&{templateId:t.template},...t.styling&&{stylingMode:t.styling},...t.referenceUrl&&{referenceUrl:t.referenceUrl},...t.thinkingDepth&&{thinkingDepth:t.thinkingDepth},...t.goal&&{goal:t.goal},...t.teamId&&{teamId:t.teamId},...A&&{theme:A},...t.studio?{documentId:Nl.basename(process.cwd())}:t.id?{documentId:t.id}:{},...V.length>0&&{contentSources:{uploadedFiles:V,contextFiles:[]}}});if(!t.wait){t.output==="json"?console.log(JSON.stringify({success:!0,run:I},null,2)):t.output!=="quiet"&&(x("Presentation generation queued"),R("Run ID",I.runId),R("Status",I.status),console.log(X.gray(` Check later with presentation status ${I.runId}`)));return}let J=await T("createSlides",I.runId,t.teamId);for(;!J.done;)t.output!=="json"&&t.output!=="quiet"&&console.log(X.gray(` ${J.message}`)),await new Promise(Se=>setTimeout(Se,(J.nextPollAfterSeconds??5)*1e3)),J=await T("createSlides",I.runId,t.teamId);if(J.error)throw new Error(se(J.error));let Z=J.entity?await Ue(J.entity.id):void 0;if(t.output==="json")console.log(JSON.stringify({success:!0,presentation:Z,run:J,viewUrl:Z?qe(Z.slug,t.language??"en"):void 0},null,2));else{console.log(),x("Presentation created successfully"),console.log(),R("Title",Z?.title??e),R("Slides",String(Z?.numberOfSlides??n??"\u2014")),console.log();let Se=Z?qe(Z.slug,t.language??"en"):"N/A";Se!=="N/A"&&(console.log(X.bold(" Open: ")+X.cyan.underline(Se)),t.open&&await(await import("open")).default(Se)),console.log()}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):s(I instanceof Error?I.message:String(I)),process.exit(I.exitCode??1)}});async function ql(){return new Promise(e=>{let t="";if(process.stdin.setEncoding("utf8"),process.stdin.isTTY){e("");return}process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{e(t.trim())}),setTimeout(()=>{e(t.trim())},100)})}import{randomUUID as Ul}from"crypto";import{readFile as jl}from"fs/promises";import{Command as xe}from"commander";var Gn=["text/markdown","text/csv","text/plain"];async function Wi(e){let t=e.content;if(t!==void 0&&t!=="-"&&!t.startsWith("@"))return t;if(t?.startsWith("@"))return jl(t.slice(1),"utf8");if(t==="-"||!process.stdin.isTTY)return Ml();s("No document body. Pass --content <text>, --content @<path>, or pipe it on stdin."),process.exit(c.GENERAL_ERROR)}async function Ml(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}function Vt(e){return`cli:document:${e}:${Ul()}`}function Oe(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function Fl(e){if(!e)return;let t=e.split(".").pop()?.toLowerCase();if(t==="md"||t==="markdown")return"text/markdown";if(t==="csv")return"text/csv";if(t==="txt")return"text/plain"}var Vl=new xe("create").description("Save a document into the Library").argument("<title>","Document title").option("--team-id <id>","Workspace ID").option("--content <text>","Document body: literal text, @<path> to read a file, or '-' for stdin").option("--media-type <type>",`One of ${Gn.join(", ")}; inferred from an @<path> body when omitted`).option("--summary <text>","One line for the Library card").action(async(e,t)=>{try{let n=t.mediaType??Fl(t.content?.startsWith("@")?t.content.slice(1):void 0);n||(s(`Cannot tell what this document is. Pass --media-type (${Gn.join(", ")}).`),process.exit(c.GENERAL_ERROR)),u(await h("createDocument",{content:await Wi(t),mediaType:n,summary:t.summary,teamId:t.teamId,title:e},Vt("create")))}catch(n){Oe(n,"Could not save the document")}}),Gl=new xe("list").description("List the workspace's documents, newest first").option("--team-id <id>","Workspace ID").option("--media-type <type>",`Filter to one of ${Gn.join(", ")}`).option("--limit <n>","Maximum documents to return (default 50)").action(async e=>{try{u(await h("listDocuments",{limit:e.limit?Number(e.limit):void 0,mediaType:e.mediaType,teamId:e.teamId}))}catch(t){Oe(t,"Could not list documents")}}),Bl=new xe("read").description("Print a document's body").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{let n=await h("readDocument",{documentId:e,teamId:t.teamId}),{document:r}=n;process.stderr.write(`${r.title} \xB7 ${r.mediaType} \xB7 v${r.version} \xB7 ${r.byteLength} bytes
97
- `),process.stdout.write(r.content)}catch(n){Oe(n,"Could not read the document")}}),Wl=new xe("update").description("Edit a document under an optimistic lock").argument("<document-id>","Document id").requiredOption("--expected-version <n>","The version you last read; the edit is rejected if it has moved on").option("--team-id <id>","Workspace ID").option("--content <text>","New body: literal text, @<path> to read a file, or '-' for stdin").option("--title <text>","New title").option("--summary <text>","New Library-card summary").option("--change-summary <text>","What changed, recorded on the version").action(async(e,t)=>{try{let n=t.content!==void 0;u(await h("updateDocument",{changeSummary:t.changeSummary,content:n?await Wi(t):void 0,documentId:e,expectedVersion:Number(t.expectedVersion),summary:t.summary,teamId:t.teamId,title:t.title},Vt("update")))}catch(n){Oe(n,"Could not update the document")}}),Kl=new xe("delete").description("Remove a document from the Library").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").option("--yes","Skip the confirmation prompt").action(async(e,t)=>{try{!t.yes&&process.stdin.isTTY&&(s("Refusing to delete without confirmation. Re-run with --yes to remove this document."),process.exit(c.GENERAL_ERROR)),u(await h("deleteDocument",{documentId:e,teamId:t.teamId},Vt("delete")))}catch(n){Oe(n,"Could not delete the document")}}),Jl=new xe("versions").description("List a document's version history").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("listDocumentVersions",{documentId:e,teamId:t.teamId}))}catch(n){Oe(n,"Could not list versions")}}),zl=new xe("restore").description("Restore an earlier version by appending it as the current one").argument("<document-id>","Document id").requiredOption("--version-number <n>","The historical version to restore").requiredOption("--expected-version <n>","The version you last read; the restore is rejected if it has moved on").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("restoreDocumentVersion",{documentId:e,expectedVersion:Number(t.expectedVersion),teamId:t.teamId,versionNumber:Number(t.versionNumber)},Vt("restore")))}catch(n){Oe(n,"Could not restore the version")}}),Ki=new xe("document").description("Create, read and edit Library documents").addCommand(Vl).addCommand(Gl).addCommand(Bl).addCommand(Wl).addCommand(Kl).addCommand(Jl).addCommand(zl);import ut from"chalk";import{Command as Xl}from"commander";import{writeFile as Hl}from"fs/promises";import{resolve as Ji}from"path";import Yl from"ora";var Ql=["html","pdf","pptx"],Bn=new Xl("export").description("Export a presentation to a local HTML, PDF or PPTX file").argument("<id-or-slug>","Presentation slug, presentation ID or document ID").option("-o, --output <path>","Output file path").option("-f, --format <format>","Export format: html, pdf, pptx",b("--format",Ql),"html").action(async(e,t)=>{await O();let n=Yl("Exporting presentation...").start();try{let r=await io(e,t.format),o=t.output?Ji(t.output):Ji(process.cwd(),r.fileName);n.text="Downloading...";let i=await ao(r.downloadUrl);await Hl(o,Buffer.from(i)),n.succeed("Export complete!"),console.log(),g(`File saved: ${o}`),g(`Format: ${r.format}`),g(`Slides: ${r.slideCount}`),g(`Size: ${Zl(i.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),s(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function Zl(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}Bn.addHelpText("after",`
98
- ${ut.bold("Examples:")}
99
- ${ut.gray("# Self-contained interactive HTML (default)")}
100
- $ ${m.commands[0]} export <id-or-slug> -o deck.html
101
-
102
- ${ut.gray("# PDF or PowerPoint")}
103
- $ ${m.commands[0]} export <id-or-slug> -f pdf -o deck.pdf
104
- $ ${m.commands[0]} export <id-or-slug> -f pptx -o deck.pptx
105
-
106
- ${ut.bold("See also:")}
107
- ${ut.gray("# For an MP4 instead")}
108
- $ ${m.commands[0]} presentation video <id-or-slug>
109
- `);import{Command as ce}from"commander";var em=new ce("create").description("Create a transcript-native footage edit project").requiredOption("--title <title>","Project title").requiredOption("--source <asset-ids...>","Analyzed source recording IDs").requiredOption("--strategy <json>","Editorial strategy JSON object").requiredOption("--ranges <json>","Selected ranges JSON array").requiredOption("--outputs <json>","Output variants JSON array").option("--overlays <json>","Overlay JSON array","[]").option("--music-asset-id <id>","Music media asset ID").option("--source-chat-id <id>","Source chat ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async e=>{await ke("createFootageProject",{input:{musicAssetId:e.musicAssetId??null,outputs:pt(e.outputs,"outputs"),overlays:pt(e.overlays,"overlays"),ranges:pt(e.ranges,"ranges"),sourceAssetIds:e.source,sourceChatId:e.sourceChatId,strategy:pt(e.strategy,"strategy"),teamId:e.teamId,title:e.title},idempotencyKey:e.idempotencyKey})}),tm=new ce("show").description("Read a footage project and its append-only versions").argument("<project-id>","Project ID or slug").option("--version-id <id>","Historical version ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("getFootageProject",{input:{projectId:e,teamId:t.teamId,versionId:t.versionId}})}),nm=new ce("revise").description("Append a semantic footage draft revision").argument("<project-id>","Project ID or slug").requiredOption("--base-version-id <id>","Current version ID").requiredOption("--change-summary <text>","Human-readable change summary").option("--title <title>","Replacement title").option("--strategy <json>","Replacement strategy JSON object").option("--ranges <json>","Replacement ranges JSON array").option("--outputs <json>","Replacement outputs JSON array").option("--overlays <json>","Replacement overlays JSON array").option("--music-asset-id <id-or-null>","Replacement music asset ID or null").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("reviseFootageProject",{input:Hi({baseVersionId:t.baseVersionId,changeSummary:t.changeSummary,musicAssetId:t.musicAssetId==="null"?null:t.musicAssetId,outputs:Gt(t.outputs,"outputs"),overlays:Gt(t.overlays,"overlays"),projectId:e,ranges:Gt(t.ranges,"ranges"),strategy:Gt(t.strategy,"strategy"),teamId:t.teamId,title:t.title}),idempotencyKey:t.idempotencyKey})}),rm=new ce("restore").description("Restore a historical footage version as a new head").argument("<project-id>","Project ID or slug").argument("<version-id>","Historical version ID").option("--change-summary <text>","Change summary","Restored version").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("restoreFootageProjectVersion",{input:{changeSummary:n.changeSummary,projectId:e,teamId:n.teamId,versionId:t},idempotencyKey:n.idempotencyKey})}),om=new ce("branch").description("Branch a historical footage version into a new project").argument("<project-id>","Source project ID or slug").argument("<version-id>","Historical version ID").requiredOption("--title <title>","New project title").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("branchFootageProjectVersion",{input:{projectId:e,teamId:n.teamId,title:n.title,versionId:t},idempotencyKey:n.idempotencyKey})}),im=new ce("inspect").description("Create proxy, filmstrip, and waveform evidence for one range").argument("<project-id>","Project ID or slug").argument("<range-id>","Stable range ID").requiredOption("--version-id <id>","Exact version ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("inspectFootageRange",{input:{projectId:e,rangeId:t,teamId:n.teamId,versionId:n.versionId},idempotencyKey:n.idempotencyKey})}),am=new ce("inspection-status").description("Read a footage range inspection run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("inspectFootageRange",e,t.teamId)}),sm=new ce("render").description("Render an exact approved footage draft version").argument("<project-id>","Project ID or slug").requiredOption("--version-id <id>","Exact version ID").option("--output <ids...>","Output IDs; omit to render every output").requiredOption("--approval-receipt <receipt>","Browser-issued approval receipt").requiredOption("--idempotency-key <key>","Key bound into the receipt").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("renderFootageProject",{input:Hi({approvalReceipt:t.approvalReceipt,outputIds:t.output,projectId:e,teamId:t.teamId,versionId:t.versionId}),idempotencyKey:t.idempotencyKey})}),dm=new ce("render-status").description("Read a Footage Studio render run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("renderFootageProject",e,t.teamId)}),cm=new ce("import-takes").description("Import all completed takes from a clipping invocation").argument("<project-id>","Project ID or slug").requiredOption("--invocation-id <id>","cc-services clipping invocation ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("importFootageProviderTakes",{input:{invocationId:t.invocationId,projectId:e,teamId:t.teamId}})}),zi=new ce("footage").description("Create, inspect, revise, and render transcript-native footage edits").addCommand(em).addCommand(tm).addCommand(nm).addCommand(rm).addCommand(om).addCommand(im).addCommand(am).addCommand(sm).addCommand(dm).addCommand(cm);async function ke(e,t){try{u(await h(e,t.input,t.idempotencyKey))}catch(n){s(n instanceof Error?n.message:"Footage operation failed"),process.exit(c.GENERAL_ERROR)}}async function Xi(e,t,n){try{u(await T(e,t,n))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}function pt(e,t){try{return JSON.parse(e)}catch{throw new Error(`${t} must be valid JSON.`)}}function Gt(e,t){return typeof e=="string"?pt(e,t):void 0}function Hi(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}import{Command as lm}from"commander";import Pe from"chalk";function mm(e){return new Set((e??"").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean))}function um(e){if(!e)throw new Error("Slides were requested but the server returned none. Retry, or read the deck in the browser.");ie("Slides"),console.log();for(let t of e){console.log(Pe.bold(` ${t.number}. ${t.title||"Untitled"}`));let n=t.text?.trim();console.log(n?Yi(n):Pe.gray(" (no text on this slide \u2014 image or empty)"));let r=t.speakerNotes?.trim();r&&(console.log(Pe.gray(" Narration/notes:")),console.log(Pe.gray(Yi(r)))),console.log()}}function Yi(e){return e.split(`
110
- `).map(t=>` ${t}`).join(`
111
- `)}var Qi=new lm("get").description("Get presentation details").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --format <format>","Output format (summary, full, json)",b("--format",["summary","full","json"]),"summary").option("--include <fields>","Fields to include (comma-separated: slides,styling)").option("-l, --language <lang>","Language for view URL","en").action(async(e,t)=>{await O();try{let n=mm(t.include).has("slides"),r=await Ue(e,{includeSlides:n});if(t.format==="json"){console.log(JSON.stringify(r,null,2));return}let o=qe(r.slug,t.language);ie("Presentation Details"),console.log(),R("Slug",r.slug),R("Title",r.title||"Untitled"),R("Description",r.description||Pe.gray("None")),R("Slides",String(r.numberOfSlides||"-")),R("Mode",r.mode||"-"),R("Created",hn(r.createdAt)),r.updatedAt&&R("Updated",hn(r.updatedAt)),console.log(),o!=="N/A"&&console.log(Pe.bold(" Open: ")+Pe.cyan.underline(o)),console.log(),n&&um(r.slides)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Wt}from"commander";import pm from"ora";function gm(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}function fm(e){let t=e.assetType??"image";if(t!=="image"&&t!=="icon")throw new Error("Asset type must be image or icon");let n;if(e.maxResults&&(n=Number.parseInt(e.maxResults,10),Number.isNaN(n)||n<1))throw new Error("Max results must be a positive number");return{query:t==="icon"?`${e.query.trim()} transparent icon isolated symbol`:e.query.trim(),options:{maxResults:n||10,size:e.size,safeSearch:e.safeSearch,assetType:t,sources:gm(e.source),transparentBackground:t==="icon"}}}function hm(e){let t=e.url||e.imageUrl;if(!t)throw new Error("Image search returned a result without a URL");return t}function ym(e){return e.transparent??e.isTransparent??e.metadata?.transparent??e.metadata?.isTransparent}function bm(e){let t=[],n=e.reduce((r,o)=>Math.max(r,o.length),0);for(let r=0;r<n;r+=1)for(let o of e){let i=o[r];i!==void 0&&t.push(i)}return t}function wm(e,t){let n=e.data.results.map(r=>r.results.map(o=>{let i=o,a=ym(i);if(t==="icon"&&a!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:hm(i),provider:r.providerName,assetType:t,...a!==void 0?{transparent:a}:{}}}));return bm(n)}function vm(e){return e.error||e.status==="failed"||e.status==="errored"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"?"processing":"pending"}function Bt(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function xm(e){return{requestId:e.runId,status:vm(e),...e.entity?.url?{url:e.entity.url}:{},...e.error?{error:se(e.error)}:{},...Bt(e.output?.width)!==void 0?{width:Bt(e.output?.width)}:{},...Bt(e.output?.height)!==void 0?{height:Bt(e.output?.height)}:{}}}async function Zi(e,t){return xm(await T("createImage",e,t))}function Wn(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.output??e.url??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.url&&x(`Image URL: ${e.url}`),e.output&&x(`Saved to: ${e.output}`),e.error&&s(`Error: ${e.error}`)}var km=new Wt("search").description("Search images across the web and licensed stock").requiredOption("-q, --query <query>","Search query").option("-n, --max-results <number>","Maximum number of results (default: 10)").option("-s, --size <size>","Image size: small, medium, large, any","large").option("--asset-type <type>","Asset intent: image or transparent icon","image").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--safe-search","Enable safe search (default: true)",!0).option("--no-safe-search","Disable safe search").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?pm("Searching for images...").start():null,r;try{r=fm(e)}catch(o){n?.stop(),s(o instanceof Error?o.message:"Invalid image search request"),process.exit(c.INVALID_INPUT);return}try{let o=await vo(r);n?.stop(),o.success||(s("Search failed"),process.exit(c.GENERAL_ERROR));let i=r.options?.assetType??"image",a=wm(o,i);if(t==="json"){u({success:!0,query:e.query,assetType:i,totalResults:a.length,images:a});return}if(t==="quiet"){for(let d of a)console.log(d.url);return}if(a.length===0){g("No images found");return}x(`Found ${a.length} images for "${e.query}"`),console.log();for(let d=0;d<a.length;d++){let l=a[d];console.log(`[${d+1}] ${l.title||"Untitled"}`),console.log(` URL: ${l.url}`),console.log(` Size: ${l.width}x${l.height}`),l.author&&console.log(` Author: ${l.author}`),console.log(` Provider: ${l.provider}`),console.log()}g(`Total cost: $${o.data.totalCost.toFixed(4)}`)}catch(o){n?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Cm=new Wt("generate").description("Generate an image and optionally save it locally").argument("[prompt]","Image prompt").option("-p, --prompt <text>","Image prompt (named compatibility form)").option("--provider <provider>","Provider override").option("--model <model>","Model override").option("--width <pixels>","Width").option("--height <pixels>","Height").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Local output path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("--yes","Approve generation").action(async(e,t)=>{let n,r=e??t.prompt;r?.trim()||(s("Provide an image prompt as an argument or with --prompt"),process.exit(c.INVALID_INPUT)),t.yes||(s("Pass --yes to approve image generation"),process.exit(c.INVALID_INPUT)),!t.wait&&t.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));try{let o=await h("createImage",{approvalReceipt:"cli:--yes",height:t.height?Number.parseInt(t.height,10):void 0,model:t.model,prompt:r.trim(),provider:t.provider,teamId:t.teamId,width:t.width?Number.parseInt(t.width,10):void 0});if(n=o.runId,!t.wait){Wn({requestId:o.runId,status:"pending"},t.format);return}let i=await te(()=>Zi(o.runId,t.teamId),180,2e3);if(i.status==="failed")throw new Error(i.error||"Image generation failed");if(!i.url)throw new Error("Image generation completed without an image URL");let a=t.output?{...i,output:t.output}:i;t.output&&await Y(i.url,t.output),Wn(a,t.format)}catch(o){s(ae(o,n),t.format),process.exit(c.GENERAL_ERROR)}}),Im=new Wt("status").description("Read image generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Download a completed image").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await Zi(e,t.teamId);if(t.output){if(n.status!=="completed"||!n.url)throw new Error("Image generation is not complete");await Y(n.url,t.output),n.output=t.output}Wn(n,t.format)}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ea=new Wt("image").description("Image search and generation commands").addCommand(km).addCommand(Cm).addCommand(Im);import{Command as Kn}from"commander";var Rm=new Kn("search").description("Search the workspace Knowledge Hub").argument("[query]","Optional search query").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").option("--limit <count>","Maximum results","10").action(async(e,t)=>{try{u(await h("searchKnowledge",{kind:t.kind,limit:Number.parseInt(t.limit,10),query:e,teamId:t.teamId}))}catch(n){s(n instanceof Error?n.message:"Knowledge search failed"),process.exit(c.GENERAL_ERROR)}}),Sm=new Kn("bundle").description("Read a bounded Open Knowledge Format bundle").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").action(async e=>{try{u(await h("getKnowledgeBundle",{kind:e.kind,teamId:e.teamId}))}catch(t){s(t instanceof Error?t.message:"Knowledge bundle failed"),process.exit(c.GENERAL_ERROR)}}),ta=new Kn("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(Rm).addCommand(Sm);import{randomUUID as $m}from"crypto";import Kt from"chalk";import{Command as we}from"commander";function Jn(e){if(e!==void 0)return e==="root"?null:e}function Be(e){return`cli:library:${e}:${$m()}`}function _e(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}var Tm=new we("list").description("List the Library folder tree").option("--team-id <id>","Workspace ID").option("--counts","Include how many items are in each folder").action(async e=>{try{u(await h("listLibraryFolders",{includeEntryCounts:!!e.counts,teamId:e.teamId}))}catch(t){_e(t,"Could not list folders")}}),Em=new we("create").description("Create a Library folder").argument("<name>","Folder name").option("--team-id <id>","Workspace ID").option("--parent <id>","Parent folder id; omit for a top-level folder").option("--color <color>","Colour token (slate, blue, green, amber, red, violet)").action(async(e,t)=>{try{u(await h("createLibraryFolder",{color:t.color,name:e,parentId:Jn(t.parent),teamId:t.teamId},Be("create")))}catch(n){_e(n,"Could not create the folder")}}),Am=new we("rename").description("Rename a Library folder").argument("<folder-id>","Folder id").argument("<name>","New name").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{try{u(await h("renameLibraryFolder",{folderId:e,name:t,teamId:n.teamId},Be("rename")))}catch(r){_e(r,"Could not rename the folder")}}),Om=new we("recolor").description("Set or clear a Library folder's colour").argument("<folder-id>","Folder id").requiredOption("--color <color>","Colour token (slate, blue, green, amber, red, violet), or 'none' to clear").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("recolorLibraryFolder",{color:t.color==="none"?null:t.color,folderId:e,teamId:t.teamId},Be("recolor")))}catch(n){_e(n,"Could not recolour the folder")}}),Pm=new we("move").description("Move a Library folder under a new parent").argument("<folder-id>","Folder id").requiredOption("--to <id>","New parent folder id, or 'root' for top level").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("moveLibraryFolder",{folderId:e,newParentId:Jn(t.to),teamId:t.teamId},Be("move")))}catch(n){_e(n,"Could not move the folder")}}),_m=new we("delete").description("Delete a folder and its subfolders; items inside are unfiled").argument("<folder-id>","Folder id").requiredOption("--yes","Confirm deletion").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("deleteLibraryFolder",{folderId:e,teamId:t.teamId},Be("delete")))}catch(n){_e(n,"Could not delete the folder")}}),Lm=new we("folders").description("Manage Library folders").addCommand(Tm).addCommand(Em).addCommand(Am).addCommand(Om).addCommand(Pm).addCommand(_m),Dm=new we("file").description("File an artifact into a Library folder").argument("<kind>","Artifact kind, e.g. presentation or microsite").argument("<target-id>","Id of the artifact itself").requiredOption("--folder <id>","Destination folder id, or 'root' to unfile the artifact").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{try{u(await h("fileArtifactIntoFolder",{folderId:Jn(n.folder),kind:e,targetId:t,teamId:n.teamId},Be("file")))}catch(r){_e(r,"Could not file that item")}}),zn=new we("library").description("Library folders and filing").addCommand(Lm).addCommand(Dm);zn.addHelpText("after",`
112
- ${Kt.bold("Examples:")}
113
- ${Kt.gray("# Browse the folder tree and file an artifact into a folder")}
114
- $ ${m.commands[0]} library folders list
115
- $ ${m.commands[0]} library file presentation <id> --folder <folder-id>
116
-
117
- ${Kt.bold("See also:")}
118
- ${Kt.gray("# A different thing: reusable video clips, not Library folders")}
119
- $ ${m.commands[0]} video library --help
120
- `);import{Command as gt}from"commander";function F(e,t){let n={...t},r=e.parent,o=!1;for(;r;){let i=r.opts?.();if(i){o=!0;for(let[a,d]of Object.entries(i))n[a]===void 0&&d!==void 0&&(n[a]=d)}r=r.parent}return o?n:t}var na=new gt("analyze").description("Transcribe an uploaded recording and publish it for generation").argument("<asset-id>","Recording ID").option("--language <code>","BCP-47 language hint for the spoken audio").option("--no-diarize","Skip speaker attribution (cheaper, but a multi-speaker recording becomes much weaker as generation input)").option("--team-id <id>","Workspace ID").option("--yes","Confirm the charge \u2014 billed per source-minute").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to confirm. Analysis is billed per minute of source audio.");try{u(await h("analyzeMediaAsset",{assetId:e,diarize:t.diarize,language:t.language,teamId:t.teamId}))}catch(n){s(n instanceof Error?n.message:"Analysis failed"),process.exit(c.GENERAL_ERROR)}}),Nm=new gt("status").description("Read an analysis run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{u(await T("analyzeMediaAsset",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});na.addCommand(Nm);var ra=new gt("import").description("Import a recording from a connected account").argument("<remote-file-id>","The provider's own ID for the recording").requiredOption("--provider <id>","Provider id of the connected account, e.g. google").requiredOption("--connector <id>","Connected account ID to read from").option("--title <title>","Name for the imported recording").option("--chat <id>","Chat this import was requested from").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("importConnectorRecording",{connectorId:t.connector,providerId:t.provider,remoteFileId:e,sourceChatId:t.chat,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}),qm=new gt("status").description("Read an import run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{u(await T("importConnectorRecording",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});ra.addCommand(qm);var oa=new gt("media").description("Ingest and transcribe recordings you already own").addCommand(na).addCommand(ra);import{Command as Xn}from"commander";var Um=new Xn("create").description("Start background microsite generation").argument("<title>","Microsite title").requiredOption("--description <brief>","Microsite brief").option("--audience <audience>","Target audience").option("--tone <tone>","Tone").option("--language <language>","Content language","en").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve generation");try{u(await h("createMicrosite",{approvalReceipt:"cli:--yes",audience:t.audience,brandingId:t.brandingId,description:t.description,language:t.language,teamId:t.teamId,title:e,tone:t.tone}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),jm=new Xn("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createMicrosite",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ia=new Xn("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(Um).addCommand(jm);import{Command as Qn}from"commander";import Hn from"ora";function Yn(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){e.outputUrl?console.log(e.outputUrl):console.log(e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.outputUrl&&x(`Output URL: ${e.outputUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Mm=new Qn("create").description("Mix audio tracks into a video (music will loop to match video duration)").requiredOption("--video <url>","Input video file/URL").option("--music <url>","Background music file/URL (will loop if shorter than video)").option("--voice <url>","Voiceover file/URL").option("--music-volume <percent>","Music volume 0-100 (default: 30, recommended for mix with voice)","30").option("--voice-volume <percent>","Voice volume 0-100","100").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.music&&!e.voice&&(s("At least one of --music or --voice must be provided"),process.exit(c.INVALID_INPUT));let t=parseInt(e.musicVolume,10)/100,n=parseInt(e.voiceVolume,10)/100;(Number.isNaN(t)||t<0||t>1)&&(s("Music volume must be between 0 and 100"),process.exit(c.INVALID_INPUT)),(Number.isNaN(n)||n<0||n>2)&&(s("Voice volume must be between 0 and 200"),process.exit(c.INVALID_INPUT));let r=e.format,o=r==="human"?Hn("Mixing audio...").start():null,i=[{url:e.video,role:"video"}];e.music&&i.push({url:e.music,role:"background",volume:t*5}),e.voice&&i.push({url:e.voice,role:"voice",volume:n*2});try{let a=await wo({operation:"add-to-video",inputs:i,options:{musicVolume:t,voiceVolume:n}});if(!e.wait){o?.stop(),Yn(a,r);return}o&&(o.text=`Processing (ID: ${a.requestId})...`);let d=await te(()=>kn(a.requestId),120,3e3);if(o?.stop(),d.status==="failed"&&(s(d.error||"Audio mixing failed"),process.exit(c.GENERAL_ERROR)),Yn(d,r),e.output){if(!d.outputUrl)throw new Error("Audio mix completed without an output URL");let l=r==="human"?Hn("Downloading...").start():null;await Y(d.outputUrl,e.output),l?.stop(),r==="human"&&x(`Saved to: ${e.output}`)}}catch(a){o?.stop(),s(a instanceof Error?a.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Fm=new Qn("status").description("Check status of an audio mix request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format==="human"?Hn("Checking status...").start():null;try{let r=await kn(e);n?.stop(),Yn(r,t.format)}catch(r){n?.stop(),s(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),aa=new Qn("mix").description("Audio mixing commands").addCommand(Mm).addCommand(Fm);import{Command as er}from"commander";import zm from"ora";import{readFileSync as Vm}from"fs";var sa=500,da=1e4,Jt=100,ca=1e4,la=1e3,ua=["duration_s","idempotency_key","narration","schema_version","video_description"],Gm=["end_s","id","start_s","text","words"],Bm=["end","id","start","text"],Wm=["description","end_s","id","start_s"];function pa(e){let t=fa(e);if(ha(t),ft(t,ua,""),t.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return t}function ga(e){let t=fa(e);ha(t),ft(t,[...ua,"visual_event"],"");let n=t.visual_event;if(!zt(n))throw new Error("SFX request visual_event is required");if(ft(n,Wm,"visual_event"),!Ce(n.description))throw new Error("SFX request visual_event.description is required");if(!Ce(n.id)||!Ie(n.start_s))throw new Error("SFX request visual_event requires id and start_s");if(n.end_s!==void 0&&(!Ie(n.end_s)||n.end_s<n.start_s))throw new Error("SFX request visual_event.end_s must be after start_s");return t}function fa(e){try{let t=JSON.parse(Vm(e,"utf8"));if(!zt(t))throw new Error("request must be a JSON object");return t}catch(t){throw new Error(`Cannot read audio request ${e}: ${t instanceof Error?t.message:String(t)}`)}}function ha(e){if(e.schema_version!==1)throw new Error("Audio request schema_version must be 1");if(!Ce(e.video_description))throw new Error("Audio request video_description is required");if(!Ie(e.duration_s)||e.duration_s<.5||e.duration_s>600)throw new Error("Audio request duration_s must be between 0.5 and 600");if(!Array.isArray(e.narration))throw new Error("Audio request narration must be an array");if(e.narration.length>sa)throw new Error(`Audio request narration holds at most ${sa} lines`);if(e.narration.forEach(Km),e.idempotency_key!==void 0&&!Ce(e.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function Km(e,t){let n=`narration.${t}`;if(!zt(e))throw new Error(`Audio request ${n} must be an object`);if(ft(e,Gm,n),!Ce(e.id)||e.id.length>Jt)throw new Error(`Audio request ${n}.id is required (1-${Jt} characters)`);if(!Ce(e.text)||e.text.trim().length>ca)throw new Error(`Audio request ${n}.text is required (1-${ca} characters)`);if(ma(e.start_s,`${n}.start_s`),ma(e.end_s,`${n}.end_s`),Ie(e.start_s)&&Ie(e.end_s)&&e.end_s<e.start_s)throw new Error(`Audio request ${n}.end_s must be greater than or equal to ${n}.start_s`);if(e.words!==void 0){if(!Array.isArray(e.words)||e.words.length>da)throw new Error(`Audio request ${n}.words must be an array of at most ${da} entries`);e.words.forEach((r,o)=>{Jm(r,`${n}.words.${o}`)})}}function Jm(e,t){if(!zt(e))throw new Error(`Audio request ${t} must be an object`);if(ft(e,Bm,t),!Ce(e.text)||e.text.trim().length>la)throw new Error(`Audio request ${t}.text is required (1-${la} characters)`);if(!Ie(e.start)||!Ie(e.end))throw new Error(`Audio request ${t} requires numeric start and end seconds`);if(e.end<e.start)throw new Error(`Audio request ${t}.end must be greater than or equal to ${t}.start`);if(e.id!==void 0&&(!Ce(e.id)||e.id.length>Jt))throw new Error(`Audio request ${t}.id must be 1-${Jt} characters`)}function ma(e,t){if(e!==void 0&&!Ie(e))throw new Error(`Audio request ${t} must be a non-negative number`)}function ft(e,t,n){let r=Object.keys(e).filter(i=>!t.includes(i));if(r.length===0)return;let o=n?`${n} `:"";throw new Error(`Audio request ${o}has unknown field(s): ${r.join(", ")}. Allowed: ${t.join(", ")}`)}function zt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Ce(e){return typeof e=="string"&&e.trim().length>0}function Ie(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0}function Zn(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.audioUrl&&x(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Xm=new er("generate").description("Generate music that follows a video's narration and final timing").requiredOption("--request <path>","JSON file with video description, narration, and final timing").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.wait&&e.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=pa(e.request)}catch(i){s(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?zm("Generating music for video...").start():null,o;try{let i=await bo(t);if(o=i.requestId,!e.wait){r?.stop(),Zn(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let a=i.status==="completed"||i.status==="failed"?i:await te(()=>xn(i.requestId),180,2e3);if(r?.stop(),a.status==="failed"&&(s(a.error||"Music generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!a.audioUrl)throw new Error("Music completed without an audio URL");await Y(a.audioUrl,e.output),n==="human"&&x(`Saved to: ${e.output}`),a.output=e.output}Zn(a,n)}catch(i){r?.stop(),s(ae(i,o),n),process.exit(c.GENERAL_ERROR)}}),Hm=new er("status").description("Check status of a music generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{Zn(await xn(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ya=new er("music").description("Video-aware music generation commands").addCommand(Xm).addCommand(Hm);import{Command as tr}from"commander";function ba(e,t){return[...t,e]}var Ym=new tr("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",ba,[]).option("--type <type>","single, multiple, or word-cloud","single").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve creation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve poll creation");try{u(await h("createPoll",{approvalReceipt:"cli:--yes",options:t.option.map(n=>({text:n})),pollType:t.type,question:e,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Poll creation failed"),process.exit(c.GENERAL_ERROR)}}),Qm=new tr("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",ba).option("--type <type>","single, multiple, or word-cloud").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve update").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve poll update");try{u(await h("editPoll",{approvalReceipt:"cli:--yes",options:t.option?.map(n=>({text:n})),pollId:e,pollType:t.type,question:t.question,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Poll update failed"),process.exit(c.GENERAL_ERROR)}}),wa=new tr("poll").description("Standalone poll commands").addCommand(Ym).addCommand(Qm);import{randomUUID as ir}from"crypto";import{readFile as su}from"fs/promises";import U from"chalk";import{Command as H}from"commander";import{randomUUID as rr}from"crypto";import{readFile as Zm}from"fs/promises";import{Command as Xt}from"commander";var va=new Xt("edit").description("Apply one atomic draft edit: narration, scene patch/move/remove, composition, or intro/outro card").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--edit <json-or-path>","Edit object as inline JSON or a JSON file path").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Ht("Draft edit failed",async()=>h("editPresentationVideoDraft",{edit:await eu(n.edit),projectId:e,teamId:n.teamId},n.idempotencyKey??rr()))}),xa=new Xt("versions").description("List saved presentation-video draft versions").argument("<project-id>","Presentation-video project UUID or editor slug").option("--before-version <number>","Continue below this version number",nr(1)).option("--limit <number>","Maximum versions",nr(1,100)).option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);await Ht("Version list failed",()=>h("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:e,teamId:n.teamId}))}),ka=new Xt("restore").description("Restore a saved draft version as a new version").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<version-number>","Version number",nr(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t,n){let r=F(this,n);await Ht("Version restore failed",()=>h("restorePresentationVideoVersion",{projectId:e,teamId:r.teamId,versionNumber:t},r.idempotencyKey??rr()))}),Ca=new Xt("refresh").description("Refresh deck-backed scenes from the latest presentation version").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Ht("Slide refresh failed",()=>h("refreshPresentationVideoSlides",{projectId:e,teamId:n.teamId},n.idempotencyKey??rr()))});async function eu(e){let t=e.trim(),n=t.startsWith("{")?t:await Zm(t,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--edit must contain one JSON object.");return r}function nr(e,t=Number.MAX_SAFE_INTEGER){return n=>{let r=Number(n);if(!Number.isInteger(r)||r<e||r>t)throw new Error(`Expected an integer between ${e} and ${t}.`);return r}}async function Ht(e,t){try{u(await t())}catch(n){s(n instanceof Error?n.message:e),process.exit(c.GENERAL_ERROR)}}import{randomUUID as tu}from"crypto";import{Command as nu}from"commander";var ru=["basic","standard","premium"],Ia=new nu("presenter").description("Set one scene to a different avatar/look or preset, or restore the project default").argument("<project-id>","Presentation video project ID").argument("<slide-id>","Slide or intro/outro scene ID").option("--avatar-id <id>","Exact avatar/look ID from presenter list").option("--cast-preset-id <id>","Saved cast preset ID").option("--no-apply-preset-voice","Preserve this scene's current voice instead of applying the preset voice").option("--inherit","Remove the override and inherit the project default").option("--render-tier <tier>","Avatar render tier: basic, standard, or premium").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this update").action(async function(e,t,n){let r=F(this,n);try{if(+!!r.avatarId+ +!!r.castPresetId+ +(r.inherit===!0)!==1)throw new Error("Pass exactly one of --avatar-id, --cast-preset-id, or --inherit.");if(r.renderTier&&!r.avatarId)throw new Error("--render-tier can only be used with --avatar-id.");if(r.renderTier&&!ru.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");u(await h("setPresentationVideoScenePresenter",{applyPresetVoice:r.castPresetId?r.applyPresetVoice:void 0,avatarId:r.avatarId,castPresetId:r.castPresetId,inherit:r.inherit,projectId:e,renderTier:r.renderTier,slideId:t,teamId:r.teamId},ou(r.idempotencyKey)))}catch(o){s(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(c.GENERAL_ERROR)}});function ou(e){return e||tu()}import{Command as or}from"commander";var Ra=new or("inspect").description("Read a presentation-video project and its ordered scene timeline").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await h("getPresentationVideoProject",{projectId:e,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Project read failed"),process.exit(c.GENERAL_ERROR)}}),iu=new or("list").description("List generated clips and uploaded recordings usable in a presentation video").argument("<project-id>","Target presentation-video project UUID or slug").option("--cursor <cursor>","Opaque cursor from the previous page").option("--limit <number>","Maximum clips to return",au).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await h("listReusableVideoClips",{cursor:n.cursor,limit:n.limit,projectId:e,query:n.query,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Clip list failed"),process.exit(c.GENERAL_ERROR)}}),Sa=new or("library").description("Reusable generated clips and uploaded recordings").addCommand(iu);function au(e){let t=Number(e);if(!Number.isInteger(t)||t<1||t>100)throw new Error("--limit must be an integer between 1 and 100.");return t}var du=new H("status").description("Check a presentation generation run").argument("<run-id>","Run ID returned by presentation generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("createSlides",e,t.teamId);if(t.format==="json"){u(n);return}if(t.format==="quiet"){console.log(n.status);return}g(`Status: ${n.status}`),g(n.message),n.progress!==null&&g(`Progress: ${n.progress}%`),n.error&&s(se(n.error))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),cu=new H("transform").description("Transform an uploaded PowerPoint import for review").argument("<import-id>","PowerPoint import ID returned by Mindframes").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);try{let r=await h("transformPresentationImport",{importId:e},n.idempotencyKey);u(r)}catch(r){s(r instanceof Error?r.message:"Transform failed"),process.exit(c.GENERAL_ERROR)}}),lu=new H("status").description("Read a PowerPoint import run").argument("<run-id>","Run ID returned by PowerPoint import").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("importPowerPoint",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message),n.error&&s(se(n.error)))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),$a=new H("import").description("Import a PowerPoint through the review-gated reconstruction pipeline").option("--file <path>","Path to the .pptx to import").option("--filename <name>","Override the uploaded filename").option("--mode <mode>","Import mode: preserve or rebrand","preserve").option("--branding-id <id>","Saved brand ID (required for rebrand mode)").option("--source-chat-id <id>","Associate the import with an existing chat").option("--title <title>","Presentation title").option("--idempotency-key <key>","Stable retry key").action(async e=>{if(!e.file){$a.help();return}e.file.toLowerCase().endsWith(".pptx")||(s("PowerPoint import requires a .pptx file."),process.exit(c.INVALID_INPUT));try{let t=await me(e.file),n=await h("importPowerPoint",{brandingId:e.brandingId,filename:e.filename??t.name,mode:e.mode,sourceChatId:e.sourceChatId,sourceUrl:t.url,title:e.title},e.idempotencyKey??ir());u(n)}catch(t){s(t instanceof Error?t.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(cu).addCommand(lu),mu=new H("speaker-notes-status").description("Check a speaker-notes generation run").argument("<run-id>","Run ID returned by speaker-notes generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("generateSpeakerNotes",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),uu=new H("video-narration-status").description("Check a presentation-video narration regeneration run").argument("<run-id>","Run ID returned by video-narration").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("regeneratePresentationVideoNarration",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),pu=new H("status").description("Read a presentation-video MP4 render run").argument("<run-id>","Run ID returned by presentation video").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await T("createPresentationVideo",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),gu=new H("prepare").description("Create or reuse a presentation-video project for a presentation").argument("<presentation-id>","Presentation ID, document ID, or slug").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--narrate","Also generate the narration the project is missing (costs credits; requires --yes)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this prepare request").option("--yes","Confirm the narration charge when --narrate is used").action(async function(e,t){let n=F(this,t);if(n.narrate&&!n.yes)return s("Pass --yes to confirm. --narrate generates speaker notes and costs credits.");try{u(await h("preparePresentationVideo",{forceNew:n.forceNew,narrate:n.narrate,presentationId:e,teamId:n.teamId},n.idempotencyKey??ir()))}catch(r){s(r instanceof Error?r.message:"Prepare failed"),process.exit(c.GENERAL_ERROR)}}),fu=new H("status").description("Read a presentation-video narration run").argument("<run-id>","Run ID returned by presentation video narrate").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await T("ensurePresentationVideoNarration",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),hu=new H("narrate").description("Generate the narration a presentation-video project is still missing").argument("<project-id>","Presentation video project ID").option("--no-wait","Return immediately with the durable run ID").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this narration request").option("--yes","Confirm the narration charge").action(async function(e,t){let n=F(this,t);if(!n.yes)return s("Pass --yes to confirm. Generating narration costs credits.");try{let r=await h("ensurePresentationVideoNarration",{projectId:e,teamId:n.teamId},n.idempotencyKey??ir());if(n.wait===!1||r.runStatus==="completed"){u(r);return}u(r),await ar(r.runId,"presentation video narrate status",()=>At(r.runId))}catch(r){s(r instanceof Error?r.message:"Narration failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(fu),yu=new H("settings").description("Update saved presentation-video render settings").argument("<project-id>","Presentation video project ID").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this settings update").option("--yes","Confirm updating presentation video settings").action(async function(e,t){let n=F(this,t);if(n.settings||(s("Pass --settings <json-or-path> with the patch to apply."),process.exit(c.INVALID_INPUT)),!n.yes)return s("Pass --yes to confirm updating presentation video settings.");try{u(await h("updatePresentationVideoSettings",{projectId:e,settings:await Ta(n.settings),teamId:n.teamId},n.idempotencyKey))}catch(r){s(r instanceof Error?r.message:"Settings update failed"),process.exit(c.GENERAL_ERROR)}}),bu=new H("video").description("Create an MP4 video from a presentation").argument("[presentation-id]","Presentation ID, document ID, or slug").option("--project-id <id>","Advanced: render an already-configured presentation video project").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file; only valid with presentation-id").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--force-rerender","Start a new MP4 render even when the current project fingerprint has a completed render").option("--render-engine <engine>","Renderer for this MP4 only: remotion (Standard) or hyperframes (Premium)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this render request").option("--yes","Confirm starting the MP4 render").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to confirm presentation video rendering.");try{if(!e&&!t.projectId)throw new Error("Pass a presentation id or --project-id.");if(e&&t.projectId)throw new Error("Pass either presentation id or --project-id, not both.");if(t.projectId&&(t.settings||t.forceNew))throw new Error("--settings and --force-new require a presentation id, not --project-id.");if(t.renderEngine&&t.renderEngine!=="remotion"&&t.renderEngine!=="hyperframes")throw new Error("--render-engine must be remotion or hyperframes.");u(await h("createPresentationVideo",{forceNew:t.forceNew,forceRerender:t.forceRerender,presentationId:e,projectId:t.projectId,renderEngine:t.renderEngine,settings:t.settings?await Ta(t.settings):void 0,teamId:t.teamId},t.idempotencyKey))}catch(n){let r=n instanceof Error?n.message:"Render failed";s(r);let o=Jr({binary:m.commands[0],message:r,projectId:t.projectId});o&&Dr(o),process.exit(c.GENERAL_ERROR)}}).addCommand(gu).addCommand(hu).addCommand(Ra).addCommand(va).addCommand(Ia).addCommand(Ca).addCommand(ka).addCommand(yu).addCommand(pu).addCommand(xa);async function Ta(e){let t=e.trim(),n=t.startsWith("{")?t:await su(t,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--settings must be a JSON object.");return r}function wu(e,t){return[...t,e]}var vu=new H("speaker-notes").description("Generate or regenerate persisted presentation speaker notes").argument("<presentation-id>","Presentation ID or slug").option("--mode <mode>","ensure or regenerate","ensure").option("--style <style>","concise or detailed","concise").option("--instructions <text>","Instructions for every selected slide").option("--language <language>","Output language").option("--slide-id <id>","Target one slide (repeatable)",wu,[]).option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{if(!["ensure","regenerate"].includes(t.mode))throw new Error("--mode must be ensure or regenerate");if(!["concise","detailed"].includes(t.style))throw new Error("--style must be concise or detailed");let n=await no(e,{instructions:t.instructions,language:t.language,mode:t.mode,slideIds:t.slideId.length?t.slideId:void 0,style:t.style});if(t.format==="json"||!t.follow){u(n);return}g(`Speaker notes run: ${n.runId}`),await ar(n.runId,"presentation speaker-notes-status",()=>At(n.runId))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),xu=new H("video-narration").description("Regenerate one slide narration in a presentation video draft").argument("<project-id>","Presentation video project ID").requiredOption("--slide-id <id>","Slide ID in the video draft").option("--instructions <text>","Optional regeneration instructions").option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await ro(e,{instructions:t.instructions,slideId:t.slideId});if(t.format==="json"||!t.follow){u(n);return}g(`Narration run: ${n.runId}`),await ar(n.runId,"presentation video-narration-status",()=>At(n.runId))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});async function ar(e,t,n){let r=null;try{r=await Cu(await n())}catch(o){let i=o instanceof Error&&o.message.trim()?o.message.trim():"the event stream ended unexpectedly";M(`Stopped following run ${e}: ${i}. The run is unaffected \u2014 check it with '${m.commands[0]} ${t} ${e}'.`);return}if(r)throw new Error(`Run ${e} ${r.status}: ${r.message} Inspect it with '${m.commands[0]} ${t} ${e}'.`)}function ku(e){let t=e.eventType;if(t==="run.completed"||t==="durable_run.completed")return"completed";let n=t==="run.failed"||t==="durable_run.failed"?"failed":t==="run.cancelled"||t==="durable_run.cancelled"?"cancelled":null;return n?{message:e.payload?.message?.trim()||e.message?.trim()||"the run reported no error message",status:n}:null}async function Cu(e){let t=e.body?.getReader();if(!t)throw new Error("Speaker notes event stream is unavailable");let n=new TextDecoder,r="",o=null;for(;;){let{done:i,value:a}=await t.read();r+=n.decode(a,{stream:!i});let d=r.split(`
121
-
122
- `);r=d.pop()??"";for(let l of d){let y=l.split(`
123
- `).find(v=>v.startsWith("data:"))?.slice(5).trim();if(!y)continue;let p=JSON.parse(y);p.eventType?.startsWith("slide.")&&g(`${p.eventType}${p.payload?.slideId?` \xB7 ${p.payload.slideId}`:""}`);let w=ku(p);w==="completed"?o=null:w&&(o=w)}if(i)return o}}var sr=new H("presentation").description("Create an MP4 video from a finished presentation, plus speaker notes, PowerPoint import, and run status").addCommand(du).addCommand($a).addCommand(vu).addCommand(mu).addCommand(bu).addCommand(xu).addCommand(uu);sr.addHelpText("after",`
124
- ${U.bold("Deck to MP4:")}
125
- $ ${m.commands[0]} presentation video prepare <slug> ${U.gray("# create/reuse the video project (free)")}
126
- $ ${m.commands[0]} presentation video narrate <project-id> --yes ${U.gray("# fill in missing narration")}
127
- $ ${m.commands[0]} presentation video inspect <project-id> ${U.gray("# review the scene timeline")}
128
- $ ${m.commands[0]} presentation video <slug> --yes ${U.gray("# start the MP4 render")}
129
- $ ${m.commands[0]} presentation video status <run-id> ${U.gray("# follow the render")}
130
-
131
- ${U.bold("Voice and avatar defaults:")}
132
- ${U.gray("# prepare picks the narration voice for you \u2014 the one this user last")}
133
- ${U.gray("# chose if it is still ready, otherwise the first ready voice \u2014 and")}
134
- ${U.gray("# reports it. Show which voice was selected and offer to change it")}
135
- ${U.gray("# instead of interviewing the user about voices. Every voice in")}
136
- ${U.gray("# avatar options carries a previewUrl audio sample they can hear.")}
137
- ${U.gray('# No avatar is chosen, on purpose: "slides with a voiceover" is the')}
138
- ${U.gray("# normal outcome, so presenter: null is finished, not misconfigured.")}
139
- ${U.gray("# Ask whether they want a presenter; do not assume either way.")}
140
- $ ${m.commands[0]} avatar options ${U.gray("# real voice and avatar ids + previews")}
141
- $ ${m.commands[0]} presentation video settings <project-id> --yes --settings '{"voiceId":"<id>"}'
142
- $ ${m.commands[0]} presentation video settings <project-id> --yes --settings '{"avatarId":"<id>"}'
143
-
144
- ${U.bold("Before rendering:")}
145
- ${U.gray("# Approve the content, then approve the spend \u2014 two questions. Read the")}
146
- ${U.gray("# narration back scene by scene from inspect (scenes[].narration.text)")}
147
- ${U.gray("# and get a yes on the script itself, plus the voice, the presenter (or")}
148
- ${U.gray("# none), music, format and captions, before the render. Reworking one")}
149
- ${U.gray("# scene is the cheap loop; the MP4 is not. --yes is your intent, not")}
150
- ${U.gray("# the user's consent.")}
151
- $ ${m.commands[0]} presentation video inspect <project-id> ${U.gray("# narration text + settings to show")}
152
- $ ${m.commands[0]} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"
153
-
154
- ${U.bold("See also:")}
155
- ${U.gray("# Building a video from scratch instead of from a deck")}
156
- $ ${m.commands[0]} video --help
157
- `);import{writeFile as Iu}from"fs/promises";import ht from"chalk";import{Command as Ru}from"commander";import Su from"ora";var dr=new Ru("scrape").description("Extract content from a URL").argument("<url>","URL to scrape").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Save content to file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format,r=n==="human"?Su("Scraping URL...").start():null;try{let o=await Co(e,t.teamId);r?.stop(),(!o.success||!o.data)&&(s(o.error||"Failed to scrape URL"),process.exit(c.GENERAL_ERROR));let i=o.data;if(t.output&&(await Iu(t.output,i.content,"utf-8"),n==="human"&&x(`Content saved to: ${t.output}`)),n==="json"){let{cost:a,...d}=i;u(d);return}if(n==="quiet"){console.log(i.content);return}i.title&&(console.log(),console.log(`Title: ${i.title}`)),i.metadata?.description&&console.log(`Description: ${i.metadata.description}`),console.log(`URL: ${i.url}`),console.log(`Tokens: ~${i.metadata?.tokenUsage?.toLocaleString()||"unknown"}`),i.warning&&M(i.warning),t.output||(console.log(),console.log("--- Content ---"),console.log(i.content)),i.cost&&i.cost>0&&g(`Cost: $${i.cost.toFixed(6)}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});dr.addHelpText("after",`
158
- ${ht.bold("Examples:")}
159
- ${ht.gray("# Pull the readable content of a web page")}
160
- $ ${m.commands[0]} scrape https://example.com/post
161
-
162
- ${ht.bold("See also:")}
163
- ${ht.gray("# Local files and documents, not just URLs")}
164
- $ ${m.commands[0]} content extract ./paper.pdf
165
-
166
- ${ht.gray("# Spoken words out of audio or video")}
167
- $ ${m.commands[0]} transcript --help
168
- `);import cr from"chalk";import{Command as yt}from"commander";function Yt(e,t){t!=="quiet"&&u(e)}var $u=new yt("web").description("Search current public web sources").argument("<query>","Search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","5").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchInternet",{maxResults:Number.parseInt(t.maxResults,10),query:e,teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Search failed"),process.exit(c.GENERAL_ERROR)}}),Tu=new yt("news").description("Search recent news").argument("<topic>","News topic").option("--team-id <id>","Workspace ID").option("--timeframe <value>","Timeframe hint").option("--max-results <count>","Maximum results","6").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("getNews",{maxResults:Number.parseInt(t.maxResults,10),teamId:t.teamId,timeframe:t.timeframe,topic:e});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"News search failed"),process.exit(c.GENERAL_ERROR)}});function Ea(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var Eu=new yt("images").description("Search images across the web and licensed stock").argument("<query>","Image search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--aspect <aspect>","Aspect: any, square, wide, tall","any").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchImages",{aspect:t.aspect,maxResults:Number.parseInt(t.maxResults,10),query:e,sources:Ea(t.source),teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Image search failed"),process.exit(c.GENERAL_ERROR)}}),Au=new yt("video").description("Search video across the web and licensed stock").argument("<query>","Video search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--orientation <value>","Orientation: landscape, portrait, square, any","any").option("--license <value>","License: free, premium, any","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchStockVideo",{license:t.license,maxResults:Number.parseInt(t.maxResults,10),orientation:t.orientation,query:e,sources:Ea(t.source),teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Video search failed"),process.exit(c.GENERAL_ERROR)}}),lr=new yt("search").description("Web, news, image, and stock-video search").addCommand($u).addCommand(Tu).addCommand(Eu).addCommand(Au);lr.addHelpText("after",`
169
- ${cr.bold("Examples:")}
170
- $ ${m.commands[0]} search web "state of AI video 2026"
171
- $ ${m.commands[0]} search news "vaccine approvals"
172
-
173
- ${cr.bold("See also:")}
174
- ${cr.gray("# `search images` and `search video` overlap with these")}
175
- $ ${m.commands[0]} image search --help
176
- $ ${m.commands[0]} video find --help
177
- `);import{Command as ur}from"commander";import Ou from"ora";function mr(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId??e.id);return}g(`Request ID: ${e.requestId||e.id}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.audioUrl&&x(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Pu=new ur("generate").description("Generate one SFX cue from a video's final facts and visual event").requiredOption("--request <path>","JSON file with video description, narration timings, and visual_event").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.wait&&e.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=ga(e.request)}catch(i){s(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?Ou("Generating sound effect for video...").start():null,o;try{let i=await Io(t);if(o=i.requestId||i.id,!e.wait){r?.stop(),mr(i,n);return}let a=i.requestId||i.id;r&&(r.text=`Processing (ID: ${a})...`);let d=i.status==="completed"||i.status==="failed"?i:await te(()=>Cn(a),60,2e3);if(r?.stop(),d.status==="failed"&&(s(d.error||"Sound effects generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!d.audioUrl)throw new Error("Sound effect completed without an audio URL");await Y(d.audioUrl,e.output),n==="human"&&x(`Saved to: ${e.output}`)}mr(d,n)}catch(i){r?.stop(),s(ae(i,o),n),process.exit(c.GENERAL_ERROR)}}),_u=new ur("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{mr(await Cn(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Aa=new ur("sfx").description("Video-aware sound effects generation commands").addCommand(Pu).addCommand(_u);import{writeFile as Lu}from"fs/promises";import{Command as Du}from"commander";import Nu from"ora";var Oa=new Du("transcript").description("Fetch a YouTube video's transcript").argument("<url>","YouTube URL or 11-character video id").option("--team-id <id>","Workspace ID").option("--language <codes>","Comma-separated language priority list, e.g. 'en,de' or 'asr-en'").option("--no-timestamps","Print plain text without [m:ss] prefixes").option("-o, --output <path>","Save the transcript to a file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format,r=n==="human"?Nu("Fetching transcript...").start():null;try{let o=await ko(e,t.teamId,t.language);r?.stop();let i=t.timestamps?o.cues.map(a=>`[${a.timestamp}] ${a.text}`).join(`
178
- `):o.cues.map(a=>a.text).join(`
179
- `);if(t.output&&(await Lu(t.output,i,"utf-8"),n==="human"&&x(`Transcript saved to: ${t.output}`)),n==="json"){u(o);return}if(n==="quiet"){console.log(i);return}console.log(),console.log(`Title: ${o.title}`),o.channelName&&console.log(`Channel: ${o.channelName}`),o.durationFormatted&&console.log(`Duration: ${o.durationFormatted}`),console.log(`Language: ${o.language??"unknown"}${o.isAutoGenerated?" (auto-generated)":""}`),console.log(`Words: ${o.wordCount.toLocaleString()}`),console.log(`URL: ${o.url}`),o.truncated&&M("Transcript was truncated to fit the response budget."),t.output||(console.log(),console.log("--- Transcript ---"),console.log(i)),o.totalCost&&o.totalCost>0&&g(`Cost: $${o.totalCost.toFixed(6)}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdir as qu,writeFile as Pa}from"fs/promises";import{dirname as Uu}from"path";import{Command as Qt}from"commander";import Da from"ora";var _a="en-US-Neural2-C",La="gemini",ju=new Qt("generate").description("Generate speech from text").requiredOption("-t, --text <text>","Text to convert to speech").requiredOption("-o, --output <path>","Output file path").option("--voice-id <voiceId>","Voice ID (e.g., ElevenLabs: 21m00Tcm4TlvDq8ikWAM)").option("--voice <voice>",`Voice name (default: ${_a})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${La})`).option("-m, --model <model>","Model (provider-specific)").option("-s, --speed <speed>","Speech speed 0.1-4.0 (default: 1.0)").option("-l, --lang <lang>","Language or locale hint (for example en-US)").option("--speakers <json>",`Multi-speaker (Gemini, max 2): '[{"name":"Joe","voice":"Kore"},{"name":"Jane","voice":"Puck"}]'`).option("-i, --instructions <text>","Style prompt (OpenAI gpt-4o-mini-tts): tone, accent, speed, emotion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?Da("Generating speech...").start():null,r;e.speed&&(r=parseFloat(e.speed),(Number.isNaN(r)||r<.1||r>4)&&(n?.stop(),s("Speed must be between 0.1 and 4.0"),process.exit(c.INVALID_INPUT)));let o;if(e.speakers)try{o=JSON.parse(e.speakers),(!Array.isArray(o)||o.length===0||o.length>2||o.some(a=>!a||typeof a!="object"||typeof a.name!="string"||!a.name.trim()||typeof a.voice!="string"||!a.voice.trim()))&&(n?.stop(),s("Speakers must be an array with 1-2 name/voice items"),process.exit(c.INVALID_INPUT))}catch{n?.stop(),s(`Invalid --speakers JSON. Example: '[{"name":"Joe","voice":"Kore"}]'`),process.exit(c.INVALID_INPUT)}let i;try{let a=e.voiceId,d=e.voice||_a,l=e.provider||La,y={};o&&(y.gemini={speakers:o}),e.instructions&&(y.openai={instructions:e.instructions});let p=await fo({text:e.text,options:{language:e.lang,provider:l,voiceId:a,voice:d,model:e.model,speed:r,providerOptions:Object.keys(y).length>0?y:void 0}});i=p.requestId,n?.stop();let w=e.output.endsWith(`.${p.format}`)?e.output:`${e.output}.${p.format}`;await qu(Uu(w),{recursive:!0}),await Pa(w,p.audioData);let v=w.replace(/\.[^.]+$/,".txt");if(await Pa(v,e.text,"utf-8"),t==="json"){u({status:"completed",output:w,audioUrl:p.audioUrl,duration:p.duration,provider:p.provider,format:p.format,voice_id:p.voiceId??null,voice:p.voice??d,model:p.model??e.model??null,speed:p.speed??r??1,lang:p.language??e.lang??null,langApplied:p.langApplied??!1,timestamps:p.timestamps??null,words:p.wordTimings??null});return}if(t==="quiet"){console.log(w);return}x(`Saved to: ${w}`),g(`Duration: ${p.duration.toFixed(2)}s`),g(`Provider: ${p.provider}`),g(`Cost: $${p.cost.toFixed(6)}`)}catch(a){n?.stop(),s(ae(a,i),t),process.exit(c.GENERAL_ERROR)}}),Mu=new Qt("voices").description("List available voices").option("-p, --provider <provider>","Filter by provider: gemini, elevenlabs, openai").option("-f, --format <format>","Output format: human, json",b("--format",["human","json"]),"human").action(async e=>{let t=e.format==="human"?Da("Fetching voices...").start():null;try{let n=await yo(e.provider);if(t?.stop(),e.format==="json"){u(n.voices);return}if(Array.isArray(n.voices)){let r=e.provider?.toUpperCase()||"VOICES";console.log(),console.log(`${r} Voices:`),console.log("-".repeat(50));for(let o of n.voices)console.log(` ${o.name} (${o.id})`),console.log(` ${o.description}`)}else for(let[r,o]of Object.entries(n.voices))if(!(!o||o.length===0)){console.log(),console.log(`${r.toUpperCase()} Voices:`),console.log("-".repeat(50));for(let i of o)console.log(` ${i.name} (${i.id})`),console.log(` ${i.description}`)}}catch(n){t?.stop(),s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Fu=new Qt("status").description("Read speech generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-f, --format <format>","Output format: json",b("--format",["json"]),"json").action(async(e,t)=>{try{u(await T("generateSpeech",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Na=new Qt("tts").description("Text-to-speech commands").addCommand(ju).addCommand(Mu).addCommand(Fu);import{execSync as Zt,spawnSync as rp}from"child_process";import{access as gr,readFile as op,rm as Wa}from"fs/promises";import{resolve as wt}from"path";import Q from"chalk";import{Command as ee}from"commander";import ip from"ffmpeg-static";import Ka from"ora";import{mkdir as Vu}from"fs/promises";import{join as Gu}from"path";import{Command as bt}from"commander";import Ua from"ora";var Bu=5e3,Wu=120,qa=5;function Ku(e,t){return[...t,e]}function Ju(e,t){try{let n=new URL(e);if(n.protocol!=="https:"&&n.protocol!=="http:")throw new Error;return n.toString()}catch{throw new Error(`${t} must be a public HTTP(S) URL`)}}function ja(e){if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e))throw new Error("Source video id must be a UUID");return e}function zu(e){if(e.mode&&!["speed","precision"].includes(e.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:Ju(e.audioUrl,"Audio URL"),...e.mode?{mode:e.mode}:{},sourceVideoId:ja(e.sourceVideoId)}}function Xu(e){let t=[],n=new Set;for(let o of e.targetLanguage){let i=o.trim(),a=i.toLocaleLowerCase("en-US");!i||n.has(a)||(n.add(a),t.push(i))}if(t.length===0)throw new Error("Provide at least one target language");if(t.length>qa)throw new Error(`Provide at most ${qa} target languages`);if(t.find(o=>o.length<2||o.length>40))throw new Error("Target languages must be between 2 and 40 characters");return{...e.captions?{captions:!0}:{},sourceVideoId:ja(e.sourceVideoId),targetLanguages:t}}function Hu(e){return e.error||e.status==="failed"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"||e.status==="processing"?"processing":"pending"}function pr(e){return{requestId:e.runId,status:Hu(e),...e.entity?.url?{videoUrl:e.entity.url}:{},...e.output?{output:e.output}:{},...e.error?{error:se(e.error)}:{}}}function Ma(e){return{requestId:e.runId,status:"pending"}}async function Fa(e,t){return te(async()=>pr(await T(e,t)),Wu,Bu)}function We(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.videoUrl&&x(`Video URL: ${e.videoUrl}`),e.error&&s(`Error: ${e.error}`)}function Yu(e){return Array.isArray(e?.languages)?e.languages.filter(t=>{if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t;return typeof n.language=="string"&&(n.status==="completed"||n.status==="failed")&&typeof n.videoId=="string"&&(n.videoUrl===null||typeof n.videoUrl=="string")}):[]}function Qu(e){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function Zu(e,t){let n=Qu(e);if(!t.has(n))return t.add(n),n;let r=n.slice(0,-4),o=2;for(;t.has(`${r}-${o}.mp4`);)o+=1;let i=`${r}-${o}.mp4`;return t.add(i),i}async function ep(e,t){let n=Yu(e.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await Vu(t,{recursive:!0});let r=[],o=new Set;for(let i of n){let a=Gu(t,Zu(i.language,o));await Y(i.videoUrl,a),r.push({language:i.language,path:a})}return r}var tp=new bt("status").description("Check a video lip-sync request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(e,t){let r=F(this,t).format??"human";try{We(pr(await T("lipsyncVideo",e)),r)}catch(o){s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Va=new bt("lipsync").description("Re-voice a ready workspace video with a public audio URL").requiredOption("--source-video-id <uuid>","READY workspace video UUID").requiredOption("--audio-url <url>","Public replacement voice audio URL").option("--mode <mode>","Quality mode: speed or precision","speed").requiredOption("-o, --output <path>","Local output video path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format==="human"?Ua("Starting video lip-sync...").start():null,n;try{let r=await $o(zu(e));if(n=r.runId,!e.wait){t?.stop(),We(Ma(r),e.format);return}t&&(t.text="Waiting for video lip-sync...");let o=await Fa("lipsyncVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video lip-sync failed");if(!o.videoUrl)throw new Error("Video lip-sync completed without a video URL");t&&(t.text="Downloading lip-synced video..."),await Y(o.videoUrl,e.output),t?.stop(),We(o,e.format),e.format==="human"&&x(`Saved to: ${e.output}`)}catch(r){t?.stop(),s(ae(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(tp),Ga=new bt("translate-languages").description("List supported video translation target languages").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await To();if(e.format==="json")u({languages:t});else for(let n of t)console.log(n)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),np=new bt("status").description("Check a video translation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(e,t){let r=F(this,t).format??"human";try{We(pr(await T("translateVideo",e)),r)}catch(o){s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Ba=new bt("translate").description("Translate a ready workspace video into one or more languages").requiredOption("--source-video-id <uuid>","READY workspace video UUID").option("--target-language <language>","Target language (repeatable)",Ku,[]).option("--captions","Burn provider-generated captions into translated videos").requiredOption("--output-dir <path>","Directory for translated videos").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format==="human"?Ua("Starting video translation...").start():null,n;try{let r=await Eo(Xu(e));if(n=r.runId,!e.wait){t?.stop(),We(Ma(r),e.format);return}t&&(t.text="Waiting for video translations...");let o=await Fa("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");t&&(t.text="Downloading translated videos...");let i=await ep(o,e.outputDir);if(t?.stop(),e.format==="json")u({...o,downloads:i});else if(e.format==="quiet")for(let a of i)console.log(a.path);else{We(o,e.format);for(let a of i)x(`${a.language}: ${a.path}`)}}catch(r){t?.stop(),s(ae(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(np);async function ap(){return process.stdin.isTTY?null:new Promise(e=>{let t="",n=!1;process.stdin.setEncoding("utf-8"),process.stdin.on("data",r=>{t+=r}),process.stdin.on("end",()=>{n||(n=!0,e(t.trim()||null))}),process.stdin.on("error",()=>{n||(n=!0,e(null))}),setTimeout(()=>{!n&&!t&&(n=!0,e(null))},500)})}function sp(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var dp=new ee("find").description("Find video clips across the web and licensed stock").argument("<query>","Search query").option("-n, --max-results <count>","Maximum number of results","10").option("-o, --orientation <type>","Video orientation: landscape, portrait, square, any","any").option("-l, --license <type>","License type: free, premium, any","free").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let{maxResults:n,orientation:r,license:o,format:i}=t,a=i==="human"?Ka("Finding videos...").start():null;try{let d=await xo({query:e,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:sp(t.source)}});a?.stop();let l=d.data.results.flatMap(y=>y.results);if(i==="json"){let{totalCost:y,...p}=d.data;u({...d,data:p});return}if(i==="quiet"){l.forEach(y=>{console.log(y.embedUrl||y.previewUrl||y.thumbnailUrl)});return}if(l.length===0){g("No videos found");return}x(`Found ${l.length} videos for "${e}"`),console.log(),l.forEach((y,p)=>{let w=y.kind==="embed";console.log(`[${p+1}] ${y.title}`),console.log(` ${w?"Embed":"URL"}: ${y.embedUrl||y.previewUrl||y.thumbnailUrl}`),console.log(w?` Duration: ${y.duration}s | Embed only \u2014 plays in the host player, do not download`:` Duration: ${y.duration}s | Size: ${y.width}x${y.height}`),console.log(` Provider: ${y.provider}`),console.log()}),g(`Total cost: $${d.data.totalCost.toFixed(4)}`)}catch(d){a?.stop(),s(d instanceof Error?d.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),cp=new ee("create").description("Generate one video from a pinned storyboard revision").requiredOption("--storyboard-revision <id>","Immutable storyboard revision UUID").option("--source-video <id>","Ready video from an earlier create call to use as base footage").option("--release","Render at 720p for release. Costs more; drafts are 480p by default").option("--team-id <id>","Workspace ID").option("--approval-receipt <receipt>","Receipt returned by the browser confirmation URL; omit on the first call to get that URL").requiredOption("--idempotency-key <key>","Stable invocation key bound into the approval receipt").option("--yes","Approve paid video generation").action(async e=>{if(!e.yes)return s("Pass --yes to approve video generation");try{u(await Ao({quality:e.release?"release":void 0,sourceVideoId:e.sourceVideo,storyboardRevisionId:e.storyboardRevision,teamId:e.teamId},e.approvalReceipt,e.idempotencyKey))}catch(t){s(t instanceof Error?t.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}});async function Ja(e){let t=e==="-"?await ap():await op(e,"utf-8");if(!t?.trim())throw new Error(e==="-"?"No storyboard Markdown was received on stdin":`Storyboard file is empty: ${e}`);return t}async function za(e,t={}){if(e)return e.length===1&&e[0]==="none"?[]:Promise.all(e.map(async n=>{let r;try{let v=JSON.parse(n);if(!v||typeof v!="object"||Array.isArray(v))throw new Error("Media binding must be a JSON object");r=v}catch(v){throw new Error(`Invalid --media binding. Pass one JSON object per binding, for example '{"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}'.`,{cause:v})}let o=ue(r.handle),i=ue(r.path),a=ue(r.fileUrl)??ue(r.url),d=ue(r.purpose),l=ue(r.videoRole),y=ue(r.analysisId)??ue(r.analysis);if(!o||!i&&!a||!d)throw new Error("Invalid --media binding. handle, purpose, and either path or url are required strings.");if(i&&a)throw new Error("A media binding cannot contain both path and url.");if(i&&d==="source"&&y)throw new Error("A source analysis is bound to the original uploaded URL. Reuse the url/name/mime/size binding printed by 'video reference analyze' instead of uploading path again.");if(i&&!t.uploadIdempotencyKey)throw new Error("Local storyboard media requires the command idempotency key.");let p=i?await me(wt(i),{idempotencyKey:`${t.uploadIdempotencyKey}:media:${o}`}):{name:ue(r.name),size:Number(r.size),type:ue(r.mime),url:a};if(!p.name||!p.type||!p.url||!Number.isSafeInteger(p.size)||p.size<=0)throw new Error(`URL media binding "${n}" requires name, mime, and positive integer size.`);let w=p.type.startsWith("video/")?"video":p.type.startsWith("audio/")?"audio":p.type.startsWith("image/")?"image":null;if(!w)throw new Error(`Unsupported media type for ${i??a}: ${p.type}`);if(!["source","style","identity","required"].includes(d))throw new Error(`Invalid media purpose: ${d}`);if(l&&!["reference","first-frame","last-frame"].includes(l))throw new Error(`Invalid videoRole: ${l}`);if(l&&w!=="image")throw new Error("videoRole is supported only for image bindings.");return{...y?{analysisId:y}:{},fileUrl:p.url,handle:o,kind:w,mime:p.type,name:p.name,purpose:d,size:p.size,...l?{videoRole:l}:{}}}))}function ue(e){return typeof e=="string"&&e.length>0?e:void 0}var lp=new ee("create").description("Create a versioned Markdown video storyboard").requiredOption("--file <path>","Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact create").option("--media <binding...>",'One JSON binding per asset: {"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}').option("--team-id <id>","Workspace ID").action(async e=>{try{u(await h("createVideoStoryboard",{aspectRatio:e.aspect,durationSec:Number(e.duration),mediaBindings:await za(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardMarkdown:await Ja(e.file),teamId:e.teamId,title:e.title},e.idempotencyKey))}catch(t){s(t instanceof Error?t.message:"Storyboard creation failed"),process.exit(c.GENERAL_ERROR)}}),mp=new ee("revise").description("Append an immutable revision to a video storyboard").argument("<storyboard-id>","Storyboard UUID").requiredOption("--base-revision <id>","Revision UUID that was edited").requiredOption("--file <path>","Complete Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Replacement artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact revision").option("--change-summary <text>","Short description of this revision").option("--media <binding...>",'Replace media bindings with one JSON object per asset; use the JSON printed by "video reference analyze" for analyzed source video').option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("reviseVideoStoryboard",{aspectRatio:t.aspect,baseRevisionId:t.baseRevision,changeSummary:t.changeSummary,durationSec:Number(t.duration),mediaBindings:await za(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardId:e,storyboardMarkdown:await Ja(t.file),teamId:t.teamId,title:t.title},t.idempotencyKey))}catch(n){s(n instanceof Error?n.message:"Storyboard revision failed"),process.exit(c.GENERAL_ERROR)}}),up=new ee("show").description("Read a storyboard; print Markdown unless --json is used").argument("<storyboard-id>","Storyboard UUID").option("--revision <id>","Read one immutable revision UUID").option("--team-id <id>","Workspace ID").option("--json","Print the complete structured response").action(async(e,t)=>{try{let n=await h("readVideoStoryboard",{revisionId:t.revision,storyboardId:e,teamId:t.teamId});if(t.json){u(n);return}console.error(`${n.storyboard.title} \xB7 revision ${n.storyboard.revision.versionNumber} (${n.storyboard.revision.id})`),console.log(n.storyboard.revision.storyboardMarkdown)}catch(n){s(n instanceof Error?n.message:"Storyboard read failed"),process.exit(c.GENERAL_ERROR)}}),pp=new ee("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(lp).addCommand(mp).addCommand(up),Xa=new ee("analyze").description("Upload and analyze a reference video; its analysisId is the only analysis video generation consumes").requiredOption("--file <path>","Local reference video").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact analysis").option("--user-request <text>","What the analysis should focus on").option("--team-id <id>","Workspace ID").option("--no-wait","Return the durable run immediately").option("--json","Print the complete structured result").action(async e=>{try{let t=await me(wt(e.file),{idempotencyKey:`video-reference-analysis:${e.idempotencyKey}:source`});if(!t.type.startsWith("video/"))throw new Error(`Reference analysis requires a video, got ${t.type}`);let n=await Oo({idempotencyKey:e.idempotencyKey,sourceUrl:t.url,teamId:e.teamId,userRequest:e.userRequest}),r={analysisId:n.runId,fileUrl:t.url,handle:"source-video",kind:"video",mime:t.type,name:t.name,purpose:"source",size:t.size};if(e.wait===!1){u({...n,binding:r,source:t});return}let o=await Po(n.runId,e.teamId);if(e.json){u({...o,binding:r,source:t});return}let i=o.output?.analysis??{};console.log(typeof i.promptContext=="string"?i.promptContext:JSON.stringify(o.output,null,2)),console.error(`Analysis run: ${n.runId}`),console.error(`Storyboard media JSON: ${JSON.stringify(r)}`)}catch(t){s(t instanceof Error?t.message:"Reference analysis failed"),process.exit(c.GENERAL_ERROR)}});Xa.addHelpText("after",`
180
- ${Q.gray("# Prints an analysisId plus a ready storyboard media binding. Pass that")}
181
- ${Q.gray("# binding to video storyboard create/revise --media; generation reads the")}
182
- ${Q.gray("# analysis from the analysisId, never from local files.")}
183
- `);var gp=new ee("status").description("Read a video-reference analysis run").argument("<run-id>","Analysis run UUID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("analyzeVideoReference",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status read failed"),process.exit(c.GENERAL_ERROR)}}),fp=new ee("reference").description("Upload and inspect reusable video references").addCommand(Xa).addCommand(gp),hp=new ee("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createVideo",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),yp=new ee("inject").description("Inject thumbnail into video (first frame + file icon)").requiredOption("-i, --video <path>","Input video file").requiredOption("-t, --thumbnail <path>","Thumbnail image").option("-o, --output <path>","Output video (default: video-with-thumb.mp4)").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?Ka("Injecting thumbnail...").start():null;try{let r=wt(e.video),o=wt(e.thumbnail),i=e.output?wt(e.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await gr(r),await gr(o);let a=ip;if(a)try{await gr(a)}catch{a=null}if(!a)try{a=Zt("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let d=rp(a,["-i",r],{encoding:"utf8"});if(d.error)throw new Error(`Failed to probe video: ${d.error.message}`);let l=(d.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!l)throw new Error("Could not detect video dimensions");let[,y,p]=l;n&&(n.text="Creating thumbnail frame...");let w="/tmp/cc-thumb-frame.mp4";Zt(`${a} -y -loop 1 -i "${o}" -vf "scale=${y}:${p}:force_original_aspect_ratio=decrease,pad=${y}:${p}:(ow-iw)/2:(oh-ih)/2,setsar=1" -t 0.033 -r 30 -c:v libx264 -pix_fmt yuv420p "${w}"`,{stdio:"pipe"}),n&&(n.text="Concatenating with video...");let v="/tmp/cc-concat-video.mp4";if(Zt(`${a} -y -i "${w}" -i "${r}" -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" -map "[v]" -map 1:a -c:v libx264 -preset ultrafast -crf 18 -c:a copy "${v}"`,{stdio:"pipe"}),n&&(n.text="Adding file icon thumbnail..."),Zt(`${a} -y -i "${v}" -i "${o}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await Wa(w,{force:!0}),await Wa(v,{force:!0}),n?.stop(),t==="json"){u({success:!0,output:i});return}if(t==="quiet"){console.log(i);return}x(`Thumbnail injected: ${i}`)}catch(r){n?.stop(),s(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),bp=new ee("thumbnail").description("Thumbnail operations").addCommand(yp),en=new ee("video").description("Build a video from scratch \u2014 brief or storyboard to stock and generated footage, translation, lipsync, analysis (for a finished deck, use presentation video)").addCommand(dp).addCommand(bp).addCommand(Va).addCommand(Ga).addCommand(Ba).addCommand(Sa);en.addCommand(cp).addCommand(pp).addCommand(fp).addCommand(hp);en.addHelpText("after",`
184
- ${Q.bold("Examples:")}
185
- ${Q.gray("# Storyboard-first video from a brief")}
186
- $ ${m.commands[0]} video storyboard create --file brief.md --duration 60 --aspect 16:9 --idempotency-key launch-1
187
-
188
- ${Q.gray("# Find licensed stock footage")}
189
- $ ${m.commands[0]} video find "city timelapse"
190
-
191
- ${Q.bold("Before generating:")}
192
- ${Q.gray("# Approve the content, then approve the spend \u2014 two questions. Paste the")}
193
- ${Q.gray("# storyboard text into your reply and get a yes on it BEFORE pinning a")}
194
- ${Q.gray("# revision; revising is free and append-only, a pinned revision is not.")}
195
- ${Q.gray("# The browser confirmation video create requires is about cost and")}
196
- ${Q.gray("# destination, not the user reading the script. --yes is neither.")}
197
- $ ${m.commands[0]} video storyboard show <storyboard-id>
198
- $ ${m.commands[0]} video storyboard revise <storyboard-id> --base-revision <revision-id> --file brief-v2.md --idempotency-key launch-2
199
-
200
- ${Q.bold("See also:")}
201
- ${Q.gray("# Already have a deck? Render it to MP4 (narration, avatar, captions)")}
202
- $ ${m.commands[0]} presentation video <slug>
203
- `);import{Command as fr}from"commander";var wp=new fr("create").description("Start background visual-abstract generation").argument("<brief>","Dense source brief").option("--title <title>","Artifact title").option("--aspect <ratio>","1:1, 16:9, 9:16, 4:3, or 3:4","1:1").option("--quality <tier>","fast, best, or enterprise","best").option("--preset <preset>","Output preset","executive-one-pager").option("--output <type>","raster or vector","raster").option("--branding-id <id>","Branding ID").option("--reference-url <url...>","Up to three image URLs to use as visual references").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve visual-abstract generation");try{let n=Array.isArray(t.referenceUrl)?t.referenceUrl.slice(0,3).map((r,o)=>({label:`visual-reference-${o+1}`,url:r})):void 0;u(await h("createVisualAbstract",{approvalReceipt:"cli:--yes",aspectRatio:t.aspect,brandingId:t.brandingId,brief:e,outputPreset:t.preset,outputType:t.output,qualityTier:t.quality,referenceImages:n,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),vp=new fr("status").description("Read visual-abstract generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createVisualAbstract",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ha=new fr("visual-abstract").description("Generate a one-page visual abstract graphic (raster or vector) from a dense brief").addCommand(wp).addCommand(vp);var hr=[Bi,Qi,ji,Na,ya,aa,ea,en,dr,Oa,Aa,sr,lr,Vn,ta,zn,wa,Ti,Ha,ia,Ri,Mn,oa,Fn,Ki,zi,Bn];function Ya(e){for(let t of hr)e.addCommand(t)}function Qa(e,t,n){let r=t?`${t} ${e.name()}`:e.name();n.set(r,{arguments:e.registeredArguments.filter(o=>o.required).map(o=>`<${o.name()}>`),requiredOptions:e.options.filter(o=>o.mandatory).map(o=>o.long).filter(o=>!!o)});for(let o of e.commands)Qa(o,r,n)}var tn;function xp(){if(!tn){tn=new Map;for(let e of hr)Qa(e,"",tn)}return tn}function Za(e){let t=xp().get(e);return t?[...t.arguments,...t.requiredOptions.map(n=>`${n} \u2026`)].join(" "):""}var es=["presentations","media","branding","knowledge","research","artifacts","agents"],yr={agents:"Scheduled agents and agent memory",artifacts:"Polls, microsites, ad sets and visual abstracts",branding:"Brand profiles, tokens, logos and competitors",knowledge:"Library documents, folders and the Knowledge Hub",media:"Voiceover, music, SFX, images, stock footage, avatars and video",presentations:"Decks, PowerPoint import, speaker notes and deck\u2192MP4",research:"Scraping, transcripts, web/news/image search and extraction"},kp="other";function Cp(e){let t=e.category?.trim();return t&&t.length>0?t:kp}function ts(e){let t=es.indexOf(e);return t===-1?es.length:t}function vt(e){let t=new Map;for(let n of e){let r=Cp(n),o=t.get(r);o?o.push(n):t.set(r,[n])}return[...t.entries()].sort(([n],[r])=>ts(n)-ts(r)||n.localeCompare(r)).map(([n,r])=>({capabilities:[...r].sort((o,i)=>o.name.localeCompare(i.name)),category:n}))}function br(e){return e.lifecycle?.mode==="background"}function wr(e,t){let n=e.lifecycle?.status?.cliCommand?.trim();if(!(!br(e)||!n))return`${t} ${n} <run-id>`}function Ip(e){switch(e.billing){case"free":return"free";case"quota":return"plan quota";case"fixed":return"credits (fixed)";case"dynamic":return"credits (usage-based)";case"delegated":return"credits (on completion)";default:return"unknown \u2014 check `capabilities`"}}function nn(e){return e.replace(/\|/g,"\\|").replace(/\r?\n/g," ").trim()}function Rp(e,t){let n=wr(e,t);return n?`run id \u2014 poll \`${n}\``:`immediate (${e.operation??"call"})`}function Ke(e,t){let n=["| Command | What it does | Takes | Returns | Cost | Scopes |","|---|---|---|---|---|---|"],r=e.map(o=>{let i=Za(o.name),a=o.scopes?.length?o.scopes.map(d=>`\`${d}\``).join(", "):"\u2014";return`| \`${t} ${nn(o.name)}\` | ${nn(o.description??"")} | ${i?`\`${nn(i)}\``:"\u2014"} | ${Rp(o,t)} | ${Ip(o)} | ${a} |`});return[...n,...r].join(`
204
- `)}function pe(e,t){if(e.source==="live")return`<!-- Generated from the live ${t.name} capability catalog (v${e.catalogVersion}, ${e.capabilities.length} capabilities) at install time. Re-run \`${t.cmd} skill install\` to refresh. -->`;let n=e.reason?` Reason: ${nn(e.reason).replace(/\.+$/,"")}.`:"";return`<!-- STALE-RISK: the live catalog could not be read at install time, so this was rendered from the snapshot baked into the installed CLI (v${e.catalogVersion}, ${e.capabilities.length} capabilities).${n} Run \`${t.cmd} login\` then \`${t.cmd} skill install --force\` to regenerate from the live catalog, and treat \`${t.cmd} capabilities\` as authoritative over this file. -->`}function ns(e){return e.map(t=>`- [${t}](#${t.toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/ /g,"-")})`).join(`
205
- `)}var Sp=["get","presentation video prepare","presentation video inspect","presentation video settings","presentation video edit","presentation video presenter","presentation video","presentation video versions","presentation video restore","presentation video refresh","presentation video-narration","presentation speaker-notes","video library list","avatar options"];function $p(e){let t=new Map(e.map(n=>[n.name,n]));return Sp.map(n=>t.get(n)).filter(n=>n!==void 0)}function rn(e,t){let{cmd:n}=e,r=$p(t.capabilities),o=t.capabilities.find(a=>a.name==="presentation video"),i=o?wr(o,n)??`${n} presentation video status <run-id>`:`${n} presentation video status <run-id>`;return`${pe(t,e)}
50
+ ${n.text}`}function so(t,e){return e?t.messages.filter(r=>r.text.trim()).at(-1)?.text??"":ao(t.messages)}function xp({abortController:t,input:e,resumeSessionId:n,workspace:r}){let o=(e.modelId??"").trim(),i=e.thinking??null,s={abortController:t,allowedTools:["WebSearch","WebFetch"],cwd:r,env:{...process.env,PATH:Ln()},includePartialMessages:!0,maxTurns:16,permissionMode:"dontAsk"};return Ip.has(o)||(s.model=o),e.effort&&(s.effort=e.effort),i&&i!=="disabled"&&(s.thinking={display:"summarized",type:i==="enabled"?"enabled":"adaptive"}),n?s.resume=n:e.system?.trim()&&(s.systemPrompt=e.system),s}async function js(t){let e=so(t.input,t.resumeSessionId);if(!e)throw new Error("Chat turn has no user text to send.");let n=new AbortController,r=()=>n.abort();t.signal?.addEventListener("abort",r,{once:!0});let o=null,i=null,s=null,c=null,p=null,f=0,h=new Set;try{let $=wp({prompt:e,options:xp({abortController:n,input:t.input,resumeSessionId:t.resumeSessionId,workspace:t.workspace})});for await(let A of $){let S=A;if(S.type==="system"&&S.subtype==="init"){typeof S.session_id=="string"&&(i=S.session_id,t.onEvent({eventType:"chat.session",payload:{sessionId:i,sessionPath:Ls(t.workspace,i)}})),typeof S.model=="string"&&(o=S.model,t.onEvent({eventType:"chat.model",payload:{modelId:S.model}}));continue}if(S.type==="stream_event"){let T=S.event;if(T?.type!=="content_block_delta")continue;let E=T.delta;if(!E)continue;E.type==="text_delta"&&typeof E.text=="string"?(f+=E.text.length,t.onEvent({eventType:"chat.text.delta",payload:{text:E.text}})):E.type==="thinking_delta"&&typeof E.thinking=="string"&&t.onEvent({eventType:"chat.reasoning.delta",payload:{text:E.thinking}});continue}if(S.type==="assistant"){let T=me(S.message),E=Array.isArray(T.content)?T.content:[];for(let M of E){let N=me(M);if(N.type!=="tool_use")continue;let O=j(N.id),Y=j(N.name);!O||!Y||h.has(O)||(h.add(O),t.onEvent({eventType:"chat.tool.started",payload:{input:le(N.input),toolCallId:O,toolName:Y}}))}continue}if(S.type==="user"){let T=me(S.message),E=Array.isArray(T.content)?T.content:[];for(let M of E){let N=me(M);if(N.type!=="tool_result")continue;let O=j(N.tool_use_id);O&&t.onEvent({eventType:"chat.tool.completed",payload:{...N.is_error===!0?{errorText:typeof N.content=="string"?_n(N.content):"Claude tool call failed."}:{},output:le(N.content),toolCallId:O}})}continue}S.type==="result"&&(typeof S.result=="string"&&(c=S.result),S.usage&&typeof S.usage=="object"&&(s=S.usage),typeof S.session_id=="string"&&(i=S.session_id),(S.is_error===!0||S.subtype!=="success")&&(p=typeof S.result=="string"&&S.result||`Claude turn failed (${String(S.subtype)}).`,t.onEvent({eventType:"chat.error",message:p,payload:{message:p}})))}}finally{t.signal?.removeEventListener("abort",r)}if(t.signal?.aborted)throw new Error("Chat turn cancelled.");if(p)throw new Error(p);let v=c??"";f===0&&v&&t.onEvent({eventType:"chat.text.delta",payload:{text:v}});let x=i?Ls(t.workspace,i):null;return{modelId:o,sessionId:i,sessionPath:x&&yp(x)?x:null,text:v,usage:s}}import{spawn as kp}from"child_process";import{closeSync as Rp,fstatSync as Cp,openSync as Sp,readdirSync as Ep,readSync as $p}from"fs";import{homedir as Tp}from"os";import{join as qs}from"path";import{Codex as Ap}from"@openai/codex-sdk";var Pp=["/Applications/Codex.app/Contents/Resources/codex"];async function jn(t){let e=t?[t]:["codex",...Pp];for(let n of e){let r=await Op(n);if(r)return{bin:n,version:r}}return null}function Op(t){return new Promise(e=>{let n=kp(t,["--version"],{env:{...process.env,PATH:Ln()},stdio:["ignore","pipe","ignore"]}),r="";n.stdout.on("data",o=>{r+=o.toString("utf8")}),n.on("error",()=>e(null)),n.on("close",o=>{if(o!==0)return e(null);let i=r.trim().split(`
51
+ `)[0]??"";e(i||null)})})}var Dp=24,Np=4*1024*1024,Fs=new Set(["custom_tool_call","custom_tool_call_output","dynamic_tool_call","function_call"]);function _p(t){let e;try{e=Lp(t).split(`
52
+ `)}catch{return[]}let n=new Set,r=new Map,o=null;for(let i of e){if(!i.trim())continue;let s;try{s=JSON.parse(i)}catch{continue}let c=me(s.payload);if(s.type==="response_item"&&c.type==="custom_tool_call"){let p=j(c.call_id),f=j(c.input);p&&c.name==="exec"&&/\btools\.web__run\s*\(/.test(f)&&(n.add(p),o=p);continue}if(s.type==="event_msg"&&c.type==="web_search_end"){let p=j(c.call_id);if(!p||!o)continue;let f=j(c.query),h=me(c.action),x={action:{...h,...f&&!j(h.query)?{query:f}:{}},query:f,sources:Vs(c.results),toolCallId:p},$=r.get(o)??[];$.push(x),r.set(o,$);continue}if(s.type==="response_item"&&c.type==="custom_tool_call_output"){let p=j(c.call_id);if(!p||!n.has(p))continue;let f=Vs(c.output);for(let h of r.get(p)??[])h.sources.length===0&&(h.sources=f);o===p&&(o=null)}}return Array.from(r.values()).flat()}function Lp(t){let e=Sp(t,"r");try{let n=Cp(e).size,r=Math.max(0,n-Np),o=Buffer.alloc(n-r);$p(e,o,0,o.length,r);let i=o.toString("utf8");if(r===0)return i;let s=i.indexOf(`
53
+ `);return s===-1?"":i.slice(s+1)}finally{Rp(e)}}function Vs(t){let n=mo(t).match(/https?:\/\/[^\s<>"'()[\]{}\\]+/g)??[],r=new Set,o=[];for(let i of n){let s=i.replace(/[.,;:!?]+$/,"");try{let c=new URL(s);if(c.protocol!=="http:"&&c.protocol!=="https:"||r.has(c.href))continue;if(r.add(c.href),o.push({type:"url",url:c.href}),o.length>=Dp)break}catch{}}return o}function mo(t){return typeof t=="string"?t:Array.isArray(t)?t.map(mo).join(`
54
+ `):t&&typeof t=="object"?Object.values(t).map(mo).join(`
55
+ `):""}function co(t,e){let n=me(t),r=j(n.type),o=j(n.id),i=j(n.call_id)||j(n.tool_call_id),s=Fs.has(r)?i||o:o||i;if(!s)return null;if(r==="command_execution"){let c=j(n.command),p=j(n.status),f={exitCode:typeof n.exit_code=="number"?n.exit_code:null,output:le(n.aggregated_output)};return{...e&&p==="failed"?{errorText:_n(n.aggregated_output)||"Command failed."}:{},input:{command:c},...e?{output:f}:{},toolCallId:s,toolName:"Bash"}}if(r==="mcp_tool_call"){let c=me(n.error);return{...e&&j(c.message)?{errorText:j(c.message)}:{},input:le(n.arguments),...e?{output:le(n.result??{status:n.status??"completed"})}:{},toolCallId:s,toolName:j(n.tool)||j(n.name)||"Codex tool"}}if(r==="web_search"){let c=j(n.query);return{input:{query:c},...e?{output:{query:c}}:{},toolCallId:s,toolName:"web_search"}}if(r==="file_change"){let c=j(n.status);return{...e&&c==="failed"?{errorText:"Codex could not apply the file changes."}:{},input:{changes:le(n.changes)},...e?{output:{changes:le(n.changes),status:c}}:{},toolCallId:s,toolName:"ApplyPatch"}}if(r==="custom_tool_call_output")return{input:{},...e?{output:le(n.output)}:{},toolCallId:s,toolName:"Codex tool"};if(r==="custom_tool_call"||r==="dynamic_tool_call"||r==="function_call"){let c=j(n.name)||j(n.tool)||"Codex tool",p=n.input??n.arguments??{};return{input:c==="exec"&&typeof p=="string"?{command:p}:le(p),...e?{output:le(n.output??n.result??{status:n.status??"completed"})}:{},toolCallId:s,toolName:c}}return null}function lo(t,e=qs(Tp(),".codex","sessions")){try{let r=Ep(e,{recursive:!0}).find(o=>typeof o=="string"&&o.endsWith(`${t}.jsonl`));return r?qs(e,r):null}catch{return null}}function Up(t,e){return e?so(t,e):ao(t.messages)}function jp(t,e,n=u.codexSelfConnectorAppId){let r=e.system?.trim(),o={...r?{developer_instructions:r}:{},...n?{apps:{[n]:{enabled:!1}}}:{}};return{codexPathOverride:t,...Object.keys(o).length>0?{config:o}:{}}}var qp=new Set(["minimal","low","medium","high","xhigh"]);function Vp(t,e){let n={networkAccessEnabled:!0,sandboxMode:"workspace-write",skipGitRepoCheck:!0,webSearchEnabled:!0,workingDirectory:e},r=(t.modelId??"").trim();return r&&r!=="default"&&(n.model=r),t.effort&&qp.has(t.effort)&&(n.modelReasoningEffort=t.effort),n}async function Bs(t){let e=Up(t.input,t.resumeSessionId);if(!e)throw new Error("Chat turn has no user text to send.");let n=new Ap(jp(t.bin,t.input)),r=Vp(t.input,t.workspace),o=t.resumeSessionId?n.resumeThread(t.resumeSessionId,r):n.startThread(r),i=t.resumeSessionId??null,s=null,c=null,p=[],f=new Set,h=new Set,v=null,x=S=>{v??=lo(S,t.sessionsRoot),t.onEvent({eventType:"chat.session",payload:{sessionId:S,sessionPath:v}})},$=S=>{i&&(v??=lo(i,t.sessionsRoot));let T=v?_p(v):[],E=j(me(S.input).query),M=Ms(E),N=T.find(O=>!f.has(O.toolCallId)&&Ms(O.query)===M)??T.find(O=>!f.has(O.toolCallId));N&&f.add(N.toolCallId),t.onEvent({eventType:"chat.tool.completed",payload:{...S,output:N?{action:N.action,query:N.query,sources:N.sources}:{action:{query:E,type:"search"},sourceListUnavailable:!0,sources:[]}}})},{events:A}=await o.runStreamed(e);i&&x(i);for await(let S of A){if(t.signal?.aborted)throw await A.return?.(void 0),new Error("Chat turn cancelled.");let T=S;if(T.type==="thread.started"){typeof T.thread_id=="string"&&(i=T.thread_id,x(T.thread_id));continue}if(T.type==="item.started"){let E=co(T.item,!1);if(E){t.onEvent({eventType:"chat.tool.started",payload:E});let M=me(T.item);if(Fs.has(j(M.type))&&j(M.status)==="completed"){let N=co(M,!0);N&&(h.add(N.toolCallId),t.onEvent({eventType:"chat.tool.completed",payload:N}))}}continue}if(T.type==="item.completed"){let E=T.item;if(!E)continue;if(E.type==="agent_message"&&typeof E.text=="string")p.push(E.text),t.onEvent({eventType:"chat.text.delta",payload:{text:E.text}});else if(E.type==="reasoning"&&typeof E.text=="string")t.onEvent({eventType:"chat.reasoning.delta",payload:{text:E.text}});else{let M=co(E,!0);M&&(E.type==="web_search"?$(M):E.type==="custom_tool_call"&&h.has(M.toolCallId)||t.onEvent({eventType:"chat.tool.completed",payload:M}))}continue}if(T.type==="turn.completed"){T.usage&&typeof T.usage=="object"&&(s=T.usage);continue}if(T.type==="turn.failed"){let E=T.error;c=typeof E?.message=="string"&&E.message||"Codex turn failed.",t.onEvent({eventType:"chat.error",message:c,payload:{message:c}})}}if(c)throw new Error(c);return i=o.id??i,i&&(v??=lo(i,t.sessionsRoot)),{modelId:t.input.modelId??null,sessionId:i,sessionPath:v,text:p.join(`
56
+
57
+ `),usage:s}}function Ms(t){return t.trim().replace(/\s+/g," ").toLocaleLowerCase()}import{randomUUID as Wp}from"crypto";import{mkdir as Kp}from"fs/promises";import{hostname as Vn,platform as Jp}from"os";import{join as zp}from"path";var lt=class extends Error{constructor(n,r,o=!1){super(n);this.statusCode=r;this.reRegister=o;this.name="RunnerApiError"}statusCode;reRegister};async function mt(t,e={}){let n=await $e();e.body!==void 0&&(n["Content-Type"]="application/json");let r=new AbortController,o=setTimeout(()=>r.abort(),e.timeoutMs??3e4),i=()=>r.abort();e.signal?.addEventListener("abort",i,{once:!0});try{let s=await fetch(`${W()}${t}`,{body:e.body!==void 0?JSON.stringify(e.body):void 0,headers:n,method:e.method??"GET",signal:r.signal}),c=await s.text(),p={};try{p=c?JSON.parse(c):{}}catch{p={error:c.slice(0,300)}}if(!s.ok)throw new lt(typeof p.error=="string"?p.error:`Runner API returned ${s.status}`,s.status,p.reRegister===!0);return p}finally{clearTimeout(o),e.signal?.removeEventListener("abort",i)}}async function Gs(t){await mt("/api/runner/register",{body:t,method:"POST",timeoutMs:15e3})}async function Ws(t,e){return(await mt(`/api/runner/work?runnerId=${encodeURIComponent(t)}`,{signal:e,timeoutMs:28e3})).job??null}async function Ks(t){await mt("/api/runner/heartbeat",{body:{runnerId:t},method:"POST",timeoutMs:1e4})}async function Js(t,e){return{cancelRequested:(await mt(`/api/runner/jobs/${encodeURIComponent(t)}/events`,{body:{events:e},method:"POST",timeoutMs:15e3})).cancelRequested===!0}}async function uo(t,e,n){await mt(`/api/runner/jobs/${encodeURIComponent(t)}/complete`,{body:{result:n,runnerId:e},method:"POST",timeoutMs:15e3})}async function qn(t,e,n,r=!0){await mt(`/api/runner/jobs/${encodeURIComponent(t)}/fail`,{body:{message:n,retryable:r,runnerId:e},method:"POST",timeoutMs:15e3})}import{mkdirSync as Mp,readFileSync as Fp,writeFileSync as zs}from"fs";import{dirname as Bp,join as Gp}from"path";function po(t){return Gp(t,"sessions.json")}function go(t){try{let e=Fp(po(t),"utf8"),n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}return{}}function Hs(t,e,n){return e?go(t)[e]?.[n]??null:null}function Xs(t,e,n,r){if(!(!e||!r))try{let o=po(t);Mp(Bp(o),{recursive:!0});let i=go(t);i[e]={...i[e],[n]:r},zs(o,`${JSON.stringify(i,null," ")}
58
+ `,"utf8")}catch{}}function Ys(t,e,n){if(e)try{let r=go(t);if(!r[e])return;delete r[e][n],zs(po(t),`${JSON.stringify(r,null," ")}
59
+ `,"utf8")}catch{}}var Hp=300,Xp=3e4;async function Qs(t){let[e,n]=await Promise.all([Un(t.claudeBin),jn(t.codexBin)]);if(!e&&!n)throw new Error("Neither Claude Code nor Codex was found on this machine. Install one and log in, then retry.");e?t.log(`Claude Code detected: ${e.version} (${e.bin})`):t.log("Claude Code not found \u2014 Claude turns will be declined."),n?t.log(`Codex detected: ${n.version} (${n.bin})`):t.log("Codex not found \u2014 Codex turns will be declined.");let r=[...e?["claude-code"]:[],...n?["codex"]:[]],o=`${Vn().split(".")[0]}-${Wp().slice(0,8)}`,i=()=>Gs({capabilities:["chat_turn","proof"],claudeCodeVersion:e?.version??null,cliVersion:t.version,codexVersion:n?.version??null,hostname:Vn(),platform:Jp(),runnerId:o,runtimes:r});for(await i(),t.log(`Registered as ${o} (runtimes: ${r.join(", ")}). Waiting for work\u2026`);!t.signal?.aborted;){let s=null;try{s=await Ws(o,t.signal)}catch(c){if(t.signal?.aborted)break;if(c instanceof lt&&c.reRegister){t.log("Server asked for re-registration."),await i().catch(()=>{});continue}t.log(`Work poll failed (${c instanceof Error?c.message:"unknown"}); retrying\u2026`),await Zp(t.pollBackoffMs??5e3,t.signal);continue}if(!s){if(t.once)continue;continue}if(t.log(`Claimed ${s.jobType} job ${s.runId}.`),await Yp({claude:e,codex:n,job:s,options:t,runnerId:o}),t.once)break}}async function Yp({claude:t,codex:e,job:n,options:r,runnerId:o}){let i=new AbortController,s=()=>i.abort();r.signal?.addEventListener("abort",s,{once:!0});let c=setInterval(()=>{Ks(o).catch(()=>{})},Xp),p=[],f=!1,h=async()=>{if(f||p.length===0)return;f=!0;let $=p.splice(0,100);try{let{cancelRequested:A}=await Js(n.runId,$);A&&i.abort()}catch(A){A instanceof lt&&A.statusCode===409&&i.abort()}finally{f=!1}},v=setInterval(()=>{h()},Hp),x=$=>{p.push($)};try{if(n.jobType==="runner.proof"){let $=typeof n.input.message=="string"?n.input.message:"proof";x({eventType:"proof.echo",payload:{message:$}}),await fo(h,p),await uo(n.runId,o,{echo:$}),r.log(`Proof job ${n.runId} completed.`);return}if(n.jobType==="runner.chat_turn"){let $=n.input.runtime==="codex"?"codex":"claude-code",A=$==="codex"?e&&{detection:e,run:Bs}:t&&{detection:t,run:js};if(!A){await qn(n.runId,o,$==="codex"?"Codex is not available on this machine. Install the Codex app or CLI and log in, then retry.":"Claude Code is not available on this machine. Install it and log in, then retry.",!1);return}let S=typeof n.input.chatId=="string"&&n.input.chatId?n.input.chatId:null,T=zp(r.workspaceRoot,"chats",S??n.runId);await Kp(T,{recursive:!0});let E=Qp(n.input),M=Y=>x({eventType:Y.eventType,message:Y.message??null,payload:Y.eventType==="chat.session"?{host:Vn(),runtime:$,runtimeVersion:A.detection.version,...Y.payload??{}}:Y.payload??{}}),N=Hs(r.workspaceRoot,S,$),O;try{O=await A.run({bin:A.detection.bin,input:E,onEvent:M,resumeSessionId:N,signal:i.signal,workspace:T})}catch(Y){if(!N||i.signal.aborted)throw Y;r.log(`Resume of ${$} session failed (${Y instanceof Error?Y.message:"unknown"}); retrying fresh.`),Ys(r.workspaceRoot,S,$),O=await A.run({bin:A.detection.bin,input:E,onEvent:M,resumeSessionId:null,signal:i.signal,workspace:T})}Xs(r.workspaceRoot,S,$,O.sessionId),x({eventType:"chat.session",payload:{host:Vn(),runtime:$,runtimeVersion:A.detection.version,sessionId:O.sessionId,sessionPath:O.sessionPath}}),await fo(h,p),await uo(n.runId,o,{modelId:O.modelId,runtime:$,runtimeVersion:A.detection.version,sessionId:O.sessionId,sessionPath:O.sessionPath,text:O.text,usage:O.usage??{}}),r.log(`Chat turn ${n.runId} (${$}) completed.`);return}await qn(n.runId,o,`This runner does not support ${n.jobType} jobs. Update the desktop app / CLI.`,!1)}catch($){let A=$ instanceof Error?$.message:"Local runner job crashed.";r.log(`Job ${n.runId} failed: ${A}`),await fo(h,p).catch(()=>{}),await qn(n.runId,o,A).catch(()=>{})}finally{clearInterval(v),clearInterval(c),r.signal?.removeEventListener("abort",s)}}function Qp(t){let e=Array.isArray(t.messages)?t.messages.map(n=>{if(!n||typeof n!="object")return null;let r=n;return{role:typeof r.role=="string"?r.role:"user",text:typeof r.text=="string"?r.text:""}}).filter(n=>!!n):[];return{effort:typeof t.effort=="string"?t.effort:null,messages:e,modelId:typeof t.modelId=="string"?t.modelId:null,system:typeof t.system=="string"?t.system:null,thinking:typeof t.thinking=="string"?t.thinking:null}}async function fo(t,e){for(;e.length>0;)await t(),e.length>0&&await new Promise(n=>setTimeout(n,25))}function Zp(t,e){return t<=0||e?.aborted?Promise.resolve():new Promise(n=>{let r=setTimeout(o,t);function o(){clearTimeout(r),e?.removeEventListener("abort",o),n()}e?.addEventListener("abort",o,{once:!0})})}function rg(){return tg(eg(),`.${u.commands[0]}-runner`,"runs")}var Mn=new ng("runner").description("Run agent work locally with your own Claude Code / Codex login (desktop lane)");Mn.command("status").description("Check local Claude Code / Codex detection and account auth").action(async()=>{let[t,e]=await Promise.all([Un(),jn()]);if(console.log(t?ye.green(`\u2713 Claude Code ${t.version}`):ye.red("\u2717 Claude Code not found on PATH")),console.log(e?ye.green(`\u2713 Codex ${e.version} (${e.bin})`):ye.red("\u2717 Codex not found (PATH or Codex.app)")),!Ee()){console.log(ye.red(`\u2717 Not logged in. Run '${u.commands[0]} login' first.`)),process.exitCode=2;return}try{let n=await xe();console.log(ye.green(`\u2713 Logged in as ${n.user.email}`))}catch(n){console.log(ye.red(`\u2717 Auth check failed: ${n instanceof Error?n.message:"unknown"}`)),process.exitCode=2}});Mn.command("start").description("Start the local runner (register + wait for work)").option("--once","Execute a single job, then exit").option("--workspace <dir>","Workspace root for job scratch directories").option("--claude-bin <path>","Path to the claude binary").option("--codex-bin <path>","Path to the codex binary").action(async t=>{Ee()||(console.error(ye.red(`Not authenticated. Run '${u.commands[0]} login' first.`)),process.exit(2));let e=new AbortController,n=()=>{console.log(ye.gray(`
60
+ Stopping runner\u2026`)),e.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await Qs({claudeBin:t.claudeBin,codexBin:t.codexBin,log:r=>console.log(ye.gray(`[runner] ${r}`)),once:t.once,signal:e.signal,version:"0.3.24",workspaceRoot:t.workspace??rg()})}catch(r){console.error(ye.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import Z from"chalk";import{Command as Cx}from"commander";import{Command as ho}from"commander";function og(t,e){return[...e,t]}var ig=new ho("create").description("Start durable ad-set generation").argument("<title>","Ad-set title").requiredOption("--brief <brief>","Campaign brief").option("--hook <text>","Opening hook (repeat)",og,[]).option("--style <style>","ugc, clean, cinematic, or testimonial","ugc").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to approve generation");try{l(await m("createAdSet",{approvalReceipt:"cli:--yes",brandingId:e.brandingId,brief:e.brief,hooks:e.hook.length?e.hook:[e.brief],style:e.style,teamId:e.teamId,title:t}))}catch(n){a(n instanceof Error?n.message:"Generation failed"),process.exit(d.GENERAL_ERROR)}}),ag=new ho("status").description("Read ad-set generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await I("createAdSet",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Zs=new ho("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(ig).addCommand(ag);import{randomUUID as rd}from"crypto";import{readFileSync as od}from"fs";import{readFile as mg}from"fs/promises";import{Command as be}from"commander";import{randomUUID as sg}from"crypto";function Te(t,e){a(t instanceof Error?t.message:e),process.exit(t instanceof D?t.exitCode:d.GENERAL_ERROR)}function zt(t){return`cli:agent-management:${t}:${sg()}`}function ut(t,e){let n=Number(t);if(!Number.isInteger(n)||n<=0)throw new Error(`${e} must be a positive integer`);return n}import{Command as Ht}from"commander";var dg=new Ht("list").description("List one roster page: your Agents plus teammates' team-visible Agents").option("--cursor <cursor>","Continue from a previous nextCursor").option("--page-size <n>","Roster rows to return (1-100)","50").option("--team-id <id>","Workspace ID").action(async t=>{try{l(await m("listAgentRoster",{cursor:t.cursor,pageSize:ut(t.pageSize,"--page-size"),teamId:t.teamId}))}catch(e){Te(e,"Could not list the Agent roster")}}),cg=new Ht("get").description("Read one roster-visible Agent card without private configuration").argument("<agent-id>","Roster-visible Agent UUID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("getRosterAgent",{agentId:t,teamId:e.teamId}))}catch(n){Te(n,"Could not read the roster Agent")}}),ed=new Ht("roster").description("Discover Agents shared inside the current workspace; never cross-workspace").addCommand(dg).addCommand(cg),lg=new Ht("set").description("Share an owned Agent with the workspace or make it private").argument("<agent-id>","Owned scheduled Agent UUID").argument("<visibility>","Desired visibility: private or team",b("visibility",["private","team"])).requiredOption("--expected-visibility <visibility>","Current value from agent roster get: private, team, or legacy public",b("--expected-visibility",["private","team","public"])).option("--idempotency-key <key>","Reuse only for an exact retry of this visibility change").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{try{l(await m("setAgentVisibility",{agentId:t,expectedVisibility:n.expectedVisibility,teamId:n.teamId,visibility:e},n.idempotencyKey?.trim()||zt("visibility")))}catch(r){Te(r,"Could not change Agent visibility")}}),td=new Ht("visibility").description("Control whether an owned Agent is private or team-visible").addCommand(lg);function pt(t,e){return[...e,t]}function ug(t){let e=Number(t);if(!Number.isInteger(e)||e<1)throw new Error("Expected a positive integer.");return e}async function Fn(t,e){let n=e.trim(),r=n.startsWith("{")?n:await mg(n,"utf8"),o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error(`${t} must contain one JSON object.`);return o}var pg=new be("create").description("Activate a reviewed Agent draft; get browser approval, then retry with the same key and receipt.").argument("<draft-id>","Reviewed agent draft UUID").requiredOption("--expected-version <number>","Exact draft version shown during review",ug).requiredOption("--idempotency-key <key>","Stable key bound into the approval receipt and reused on retry").option("--approval-receipt <receipt>","Receipt from the browser confirmation URL").option("--yes","Confirm activation intent; this never substitutes for the approval receipt").option("--team-id <id>","Workspace ID").action(async(t,e)=>{e.yes||(a("Pass --yes to request activation. A server-issued approval receipt is still required."),process.exit(d.INVALID_INPUT)),await id("Agent activation failed",()=>m("createAgent",{approvalReceipt:e.approvalReceipt,draftId:t,expectedVersion:e.expectedVersion,teamId:e.teamId},e.idempotencyKey))}),gg=new be("recommend").description("Save a private inactive scheduled-agent draft for review; this command never activates or runs it.").argument("<name>","Agent name").requiredOption("--instructions <markdown>","Standing agent instructions").option("--description <text>","Agent description","").option("--goal <text>","User-visible recurring objective").option("--rationale <text>","Why this draft is being recommended").option("--schedule <frequency>","manual, daily, weekdays, weekly, or monthly").option("--schedule-r-rule <rrule>","Precise recurrence rule").option("--schedule-time <hh:mm>","Local run time").option("--timezone <zone>","IANA timezone").option("--schedule-config <json-or-path>","Full schedule configuration as inline JSON or a JSON file").option("--source <connector>","Source connector (repeatable)",pt,[]).option("--x-handle-target <handle>","Target for the x_handle source").option("--x-search-target <query>","Query for the x_search source").option("--primary-output <adapter>","Legacy primary output fallback").option("--output <adapter>","Output adapter (repeatable)",pt,[]).option("--output-config <json-or-path>","Full output slot configuration (repeatable)",pt,[]).option("--delivery-adapter <adapter>","Delivery adapter").option("--delivery-config <json-or-path>","Full delivery configuration as inline JSON or a JSON file").option("--review-policy <policy>","manual_review, auto_send, or draft_only","manual_review").option("--runtime <json-or-path>","Scheduled runtime configuration as inline JSON or a JSON file").option("--sandbox-blueprint-id <id>","Sandbox blueprint UUID").option("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await id("Agent recommendation failed",async()=>m("recommendAgent",{deliveryAdapter:e.deliveryAdapter,deliveryConfig:e.deliveryConfig?await Fn("--delivery-config",e.deliveryConfig):void 0,description:e.description,goal:e.goal,instructionsMarkdown:e.instructions,name:t,outputAdapter:e.primaryOutput,outputAdapters:e.output.length?e.output:void 0,outputConfigs:e.outputConfig.length?await Promise.all(e.outputConfig.map(n=>Fn("--output-config",n))):void 0,rationale:e.rationale,reviewPolicy:e.reviewPolicy,runtime:e.runtime?await Fn("--runtime",e.runtime):void 0,sandboxBlueprintId:e.sandboxBlueprintId,schedule:e.schedule,scheduleConfig:e.scheduleConfig?await Fn("--schedule-config",e.scheduleConfig):void 0,scheduleRRule:e.scheduleRRule,scheduleTime:e.scheduleTime,sourceConnectors:e.source.length?e.source:void 0,teamId:e.teamId,timezone:e.timezone,xHandleTarget:e.xHandleTarget,xSearchTarget:e.xSearchTarget},e.idempotencyKey??rd()))});async function id(t,e){try{l(await e())}catch(n){if(n instanceof D){let r=`[${n.errorCode}] `;console.error(JSON.stringify({error:{code:n.errorCode,message:n.message.startsWith(r)?n.message.slice(r.length):n.message,retryable:n.retryable},ok:!1})),process.exit(n.exitCode)}console.error(JSON.stringify({error:{code:"operation_failed",message:n instanceof Error?n.message:t,retryable:!1},ok:!1})),process.exit(d.GENERAL_ERROR)}}function fg(t,e){return t==="none"?null:ut(t,e)}function hg(t){return t==="none"?null:t}function He(t,e){let n;try{n=od(t,"utf8")}catch(r){throw new Error(`${e} could not read ${t}: ${r instanceof Error?r.message:"unknown file error"}`)}try{return JSON.parse(n)}catch(r){throw new Error(`${e} must point to valid JSON: ${r instanceof Error?r.message:"invalid JSON"}`)}}function yg(t,e){try{return od(t,"utf8")}catch(n){throw new Error(`${e} could not read ${t}: ${n instanceof Error?n.message:"unknown file error"}`)}}var bg=new be("list").description("List all owned Agents, following cursor pages to closure").option("--cursor <cursor>","Resume from a previous nextCursor").option("--page-size <n>","Rows fetched per page","50").option("--team-id <id>","Workspace ID").action(async t=>{try{let e=[],n=t.cursor;for(;;){let r=await m("listAgents",{cursor:n,pageSize:ut(t.pageSize,"--page-size"),teamId:t.teamId});if(e.push(...r.agents),!r.hasMore||!r.nextCursor)break;n=r.nextCursor}l({agents:e,total:e.length})}catch(e){Te(e,"Could not list Agents")}}),wg=new be("get").description("Read one owned Agent and its complete configuration").argument("<agent-id>","Scheduled Agent UUID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("getAgent",{agentId:t,teamId:e.teamId}))}catch(n){Te(n,"Could not read the Agent")}}),vg=new be("configure").description("Update Agent configuration; enable automatic external delivery in the browser").argument("<agent-id>","Scheduled Agent UUID").requiredOption("--expected-version <n>","Version returned by agent get").option("--name <text>","Agent name").option("--description <text>","Agent description").option("--goal <text>","Recurring objective").option("--instructions-file <path>","UTF-8 Markdown instructions").option("--schedule-file <path>","Typed schedule JSON document").option("--sources-file <path>","Typed source array JSON document").option("--output-file <path>","Typed primary output JSON document").option("--outputs-file <path>","Typed output array JSON document").option("--delivery-file <path>","Typed delivery JSON document").option("--review-policy <policy>","manual_review, auto_send, or draft_only").option("--runtime-file <path>","Typed runtime JSON document").option("--sandbox-blueprint-id <id|none>","Subscription sandbox blueprint, or none").option("--per-run-credit-cap <credits|none>","Positive credit ceiling, or none").option("--files-file <path>","Typed attached-file array JSON document").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("updateAgentConfiguration",{additionalFiles:e.filesFile?He(e.filesFile,"--files-file"):void 0,agentId:t,delivery:e.deliveryFile?He(e.deliveryFile,"--delivery-file"):void 0,description:e.description,expectedVersion:ut(e.expectedVersion,"--expected-version"),goal:e.goal,instructionsMarkdown:e.instructionsFile?yg(e.instructionsFile,"--instructions-file"):void 0,name:e.name,output:e.outputFile?He(e.outputFile,"--output-file"):void 0,outputs:e.outputsFile?He(e.outputsFile,"--outputs-file"):void 0,perRunCreditCap:e.perRunCreditCap===void 0?void 0:fg(e.perRunCreditCap,"--per-run-credit-cap"),reviewPolicy:e.reviewPolicy,runtime:e.runtimeFile?He(e.runtimeFile,"--runtime-file"):void 0,sandboxBlueprintId:e.sandboxBlueprintId===void 0?void 0:hg(e.sandboxBlueprintId),schedule:e.scheduleFile?He(e.scheduleFile,"--schedule-file"):void 0,sources:e.sourcesFile?He(e.sourcesFile,"--sources-file"):void 0,teamId:e.teamId},zt("configure")))}catch(n){Te(n,"Could not update the Agent")}});function nd(t){return new be(t).description(`${t==="pause"?"Pause":"Resume"} an Agent schedule`).argument("<agent-id>","Scheduled Agent UUID").option("--team-id <id>","Workspace ID").action(async(e,n)=>{try{l(await m(t==="pause"?"pauseAgentSchedule":"resumeAgentSchedule",{agentId:e,teamId:n.teamId},zt(t)))}catch(r){Te(r,`Could not ${t} the Agent schedule`)}})}function yo(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}function ad(t){return`cli:agent-memory:${t}:${rd()}`}function Ig(t,e){let n=t.indexOf("="),r=n===-1?t:t.slice(0,n),o=n===-1?"":t.slice(n+1);return[...e,{name:r.trim(),note:o.trim()}]}var xg=new be("show").description("Show what a scheduled agent remembers").argument("<agent-id>","Scheduled Agent UUID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("getAgentMemory",{agentId:t,teamId:e.teamId}))}catch(n){yo(n,"Could not read the agent's memory")}}),kg=new be("set").description("Add to or remove from what an agent remembers. Owner or workspace admin only.").argument("<agent-id>","Scheduled Agent UUID").option("--learned <text>","Durable fact to add (repeatable)",pt,[]).option("--always <text>","Standing instruction to add (repeatable)",pt,[]).option("--never <text>","Thing it must not do, to add (repeatable)",pt,[]).option("--track <name=note>","Entity to track, as name=note (repeatable)",Ig,[]).option("--notes <text>","Replace the freeform notes").option("--remove <field>","Remove instead of add: learned, recurringInstructions, negativePreferences, entities, or notes").option("--value <text>","Item to remove; not needed when removing notes").option("--expected-version <n>","Refuse the write unless the stored memory is still at this version").option("--team-id <id>","Workspace ID").action(async(t,e)=>{let n=typeof e.remove=="string";try{l(await m("updateAgentMemory",{agentId:t,entities:e.track.length?e.track:void 0,expectedVersion:e.expectedVersion===void 0?void 0:Number.parseInt(e.expectedVersion,10),learned:e.learned.length?e.learned:void 0,negativePreferences:e.never.length?e.never:void 0,notes:e.notes,operation:n?"remove":"add",recurringInstructions:e.always.length?e.always:void 0,removeField:e.remove,removeValue:e.value,teamId:e.teamId},ad(n?"remove":"add")))}catch(r){yo(r,"Could not update the agent's memory")}}),Rg=new be("forget").description("Erase every stored version of an agent's memory. This cannot be undone.").argument("<agent-id>","Scheduled Agent UUID").option("--team-id <id>","Workspace ID").option("--yes","Confirm the erase").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to erase this agent's memory");try{l(await m("forgetAgentMemory",{agentId:t,teamId:e.teamId},ad("forget")))}catch(n){yo(n,"Could not erase the agent's memory")}}),Cg=new be("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(xg).addCommand(kg).addCommand(Rg),sd=new be("agent").description("Recommend, activate, configure, and manage scheduled Agents").addCommand(bg).addCommand(wg).addCommand(ed).addCommand(td).addCommand(vg).addCommand(nd("pause")).addCommand(nd("resume")).addCommand(pg).addCommand(gg).addCommand(Cg);import{Command as dd}from"commander";var bo=["article","document","microsite","presentation","presentationVideo","video"];function Sg(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}function Eg(t){if(t===void 0)return;let e=/^\s*(\d+)\s*(?:-\s*(\d+)\s*)?$/.exec(t);e||(a(`--slides expects N or N-M, got "${t}"`),process.exit(d.GENERAL_ERROR));let n=Number(e[1]),r=e[2]===void 0?n:Number(e[2]);return(n<1||r<n)&&(a(`--slides range must start at 1 and end no earlier than it starts, got "${t}"`),process.exit(d.GENERAL_ERROR)),{from:n,to:r}}var $g=new dd("read").description("Read an owned artifact's full content").argument("<kind>",`Artifact kind: ${bo.join(", ")}`).argument("<artifact-id>","Artifact id, or slug where the kind has one").option("--slides <range>","Presentations only: N or N-M. Omit to read every slide.").option("--team-id <id>","Workspace to read from").action(async(t,e,n)=>{bo.includes(t)||(a(`Unknown artifact kind "${t}". Expected one of: ${bo.join(", ")}`),process.exit(d.GENERAL_ERROR));try{let r=await m("readArtifact",{artifactId:e,kind:t,slides:Eg(n.slides),teamId:n.teamId});l(r)}catch(r){Sg(r,"Could not read the artifact")}}),cd=new dd("artifact").description("Read artifacts this workspace owns").addCommand($g);import{randomUUID as Tg}from"crypto";import{password as Ag}from"@inquirer/prompts";import{Command as Bn}from"commander";function wo(t){if(t==="claude-code"||t==="codex")return t;throw new Error("--runtime must be claude-code or codex")}function Pg(t,e){let n=t;if(e==="claude-code"&&(n==="zai-claude"||n==="anthropic-compatible")||e==="codex"&&n==="openai-responses-compatible")return n;throw new Error(e==="claude-code"?"--provider must be zai-claude or anthropic-compatible for Claude":"--provider must be openai-responses-compatible for Codex")}async function Og(){let t="";for await(let e of process.stdin)if(t+=String(e),t.length>65536)throw new Error("Credential input is too large");return t.trim()}var Dg=new Bn("add").description("Enroll a provider credential without exposing it in arguments").requiredOption("--runtime <runtime>","claude-code or codex").requiredOption("--provider <provider>","zai-claude, anthropic-compatible, or openai-responses-compatible").requiredOption("--label <name>","Profile name shown in Mindframes").requiredOption("--model <model-id>","Provider model id").option("--base-url <url>","Public HTTPS provider base URL").option("--api-key-stdin","Read the provider key from stdin instead of a hidden prompt").option("--use","Select the new profile immediately").action(async t=>{try{let e=wo(t.runtime),n=Pg(t.provider,e);if(!t.apiKeyStdin&&!process.stdin.isTTY)throw new Error("Non-interactive enrollment requires --api-key-stdin. Never pass provider keys as command arguments.");let r=t.apiKeyStdin?await Og():(await Ag({mask:"*",message:"Provider API key:"})).trim();if(!r)throw new Error("Provider API key is required");let o=await Ia({apiKey:r,...t.baseUrl?{baseUrl:t.baseUrl}:{},label:t.label,makeDefault:t.use??!1,modelId:t.model,provider:n,runtime:e});k(`Saved connection profile ${o.label} (${o.id})`)}catch(e){a(e instanceof Error?e.message:"Profile enrollment failed"),process.exit(d.GENERAL_ERROR)}}),Ng=new Bn("list").description("List secret-free Claude Code or Codex connection profiles").requiredOption("--runtime <runtime>","claude-code or codex").action(async t=>{try{let e=wo(t.runtime);l(await m("listAiConnectionProfiles",{runtime:e}))}catch(e){a(e instanceof Error?e.message:"Profile list failed"),process.exit(d.GENERAL_ERROR)}}),_g=new Bn("select").description("Select a profile UUID, or 'native' for the first-party route").requiredOption("--runtime <runtime>","claude-code or codex").requiredOption("--profile-id <id>","Profile UUID or native").option("--yes","Confirm changing the active inference route").action(async t=>{t.yes||(a("Pass --yes to confirm changing the active connection profile."),process.exit(d.INVALID_INPUT));try{let e=wo(t.runtime),n=await m("selectAiConnectionProfile",{profileId:t.profileId,runtime:e},Tg());k(n.selectedProfileId?`Selected connection profile ${n.selectedProfileId}`:"Selected the native provider route")}catch(e){a(e instanceof Error?e.message:"Profile selection failed"),process.exit(d.GENERAL_ERROR)}}),ld=new Bn("ai-connections").description("Manage Claude Code and Codex inference routes").addCommand(Dg).addCommand(Ng).addCommand(_g);import{randomUUID as pd}from"crypto";import Xt from"chalk";import{Command as Ae}from"commander";import Bg from"ora";import{existsSync as md}from"fs";import{resolve as Lg}from"path";var Ug=/^([A-Za-z][A-Za-z0-9_-]*)=(.+)$/;function jg(t){let e=t.trim();if(!e)throw new Error("A reference image value cannot be empty.");if(md(e))return{source:e};let n=Ug.exec(e);return n?{label:n[1],source:n[2]}:{source:e}}function qg(t,e,n){if(!t.startsWith("image/")&&t!=="application/octet-stream")throw new Error(`Reference image ${e} (${n}) is ${t}, not an image. A reference must be an image; pass an image file or a public image URL.`)}function Vg(t,e){let n;try{n=new URL(t)}catch(r){throw new Error(`Reference image ${e} (${t}) must be an existing local file or an HTTP(S) URL.`,{cause:r})}if(n.protocol!=="http:"&&n.protocol!=="https:")throw new Error(`Reference image ${e} (${t}) must use an HTTP(S) URL.`);return n}async function Gn(t,e){if(t?.length){if(e.maxCount!==void 0&&t.length>e.maxCount)throw new Error(`${e.maxCountSubject??"This command"} accepts at most ${e.maxCount} reference images; ${t.length} were provided.`);return Promise.all(t.map(async(n,r)=>{let o=r+1,{label:i,source:s}=jg(n);if(md(s)){let p=Lg(s),f=Tn(p);e.rejectNonImageFiles&&qg(f,o,s);let h=await de(p,{idempotencyKey:`${e.idempotencyKey}:reference:${o}`}),v=h.type||f;return{...i?{label:i}:{},...v.startsWith("image/")?{mediaType:v}:{},url:h.url}}let c=Vg(s,o);return{...i?{label:i}:{},url:c.toString()}}))}}import{mkdir as Mg,writeFile as ud}from"fs/promises";import{dirname as Fg}from"path";async function te(t,e){if(await Mg(Fg(e),{recursive:!0}),t.startsWith("data:")){let o=t.match(/^data:[^;]+;base64,(.+)$/);if(!o)throw new Error("Invalid data URL format");let i=Buffer.from(o[1],"base64");if(i.length===0)throw new Error("Downloaded media was empty");await ud(e,i);return}let n=await fetch(t);if(!n.ok)throw new Error(`Failed to download media: ${n.status}`);let r=Buffer.from(await n.arrayBuffer());if(r.length===0)throw new Error("Downloaded media was empty");await ud(e,r)}var Gg=15e3,Wg=40,Kg=3;async function gd(t,e){return(await Gn(t,{idempotencyKey:e,maxCount:Kg,maxCountSubject:"A presenter Look"}))?.map(r=>({url:r.url}))}function vo(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.videoUrl??t.requestId);return}w(`Request ID: ${t.requestId}`),w(`Status: ${t.status}`),t.durationSec!=null&&w(`Duration: ${t.durationSec}s`),t.videoUrl&&k(`Video URL: ${t.videoUrl}`),t.error&&a(`Error: ${t.error}`)}var Jg=new Ae("options").description("List available presenter avatars and voices").option("--language <language>","Filter voices by language").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{try{let e=await Ka(t.language);if(t.format==="json"){l(e);return}let n=e.personal??[];if(t.format==="quiet"){for(let r of n)console.log(r.id);for(let r of e.avatars)console.log(r.id);for(let r of e.voices)console.log(r.id);return}if(n.length>0){w("Your presenters:");for(let r of n)console.log(` ${r.id} ${r.name}`)}w("Avatars:");for(let r of e.avatars){let o=r.renderTiers?.length?` [${r.renderTiers.join(", ")}]`:"";console.log(` ${r.id} ${r.name}${o}`)}w("Voices:");for(let r of e.voices)console.log(` ${r.id} ${r.name}${r.language?` (${r.language})`:""}`)}catch(e){a(e instanceof Error?e.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),zg=new Ae("generate").description("Generate a reusable presenter clip").option("--avatar-id <id>","Avatar id from 'avatar options'; sandbox runs use the host presenter policy").option("--audio-url <url>","Public narration audio URL for avatar lip sync").option("--voice-id <id>","Voice id from 'avatar options'").option("--script <text>","Exact words for the presenter to speak").requiredOption("-o, --output <path>","Local output path").option("--aspect <aspect>","Aspect: 1:1, 9:16, 16:9","9:16").option("--duration <seconds>","Maximum requested duration (1-300)").option("--transparent","Render a transparent-background WebM presenter clip").option("--background-color <hex>","Solid presenter background color, for example #0F172A").option("--background-image-url <url>","Public image URL used as the presenter background").option("--fit <mode>","Background image fit: contain or cover").option("--output-format <container>","Container: mp4 (default) or webm \u2014 webm renders a transparent-background clip (single scene) for compositing").option("--render-tier <tier>","Render cost/quality: basic, standard, premium","basic").option("--title <title>","Clip title","Presenter clip").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.transparent?"webm":t.outputFormat;!!t.audioUrl==!!t.script&&(a("Provide exactly one avatar speech input: --audio-url or --script"),process.exit(d.INVALID_INPUT)),["1:1","9:16","16:9"].includes(t.aspect)||(a("Aspect must be one of 1:1, 9:16, or 16:9"),process.exit(d.INVALID_INPUT)),t.outputFormat!==void 0&&!["mp4","webm"].includes(t.outputFormat)&&(a("Output format must be mp4 or webm"),process.exit(d.INVALID_INPUT)),t.backgroundColor!==void 0&&!/^#[0-9a-fA-F]{6}$/.test(t.backgroundColor)&&(a("Background color must be a six-digit hex value"),process.exit(d.INVALID_INPUT)),t.backgroundColor&&t.backgroundImageUrl&&(a("Provide only one presenter background"),process.exit(d.INVALID_INPUT)),t.fit!==void 0&&!["contain","cover"].includes(t.fit)&&(a("Fit must be contain or cover"),process.exit(d.INVALID_INPUT)),t.fit&&!t.backgroundImageUrl&&(a("Fit requires --background-image-url"),process.exit(d.INVALID_INPUT)),t.transparent&&t.outputFormat==="mp4"&&(a("--transparent cannot be combined with --output-format mp4"),process.exit(d.INVALID_INPUT)),e==="webm"&&(t.backgroundColor||t.backgroundImageUrl)&&(a("Transparent WebM output cannot be combined with a background"),process.exit(d.INVALID_INPUT)),["basic","standard","premium"].includes(t.renderTier)||(a("Render tier must be basic, standard, or premium"),process.exit(d.INVALID_INPUT));let n=t.duration?Number.parseInt(t.duration,10):void 0;n!==void 0&&(!Number.isFinite(n)||n<1||n>300)&&(a("Duration must be between 1 and 300 seconds"),process.exit(d.INVALID_INPUT));let r=t.format==="human"?Bg("Generating presenter clip...").start():null;try{let o=t.audioUrl?{audioUrl:t.audioUrl}:{script:t.script??"",...t.voiceId?{voiceId:t.voiceId}:{}},i=await Ja({...o,aspect:t.aspect,...t.avatarId?{avatarId:t.avatarId}:{},...t.backgroundColor?{backgroundHex:t.backgroundColor}:{},...t.backgroundImageUrl?{backgroundImageUrl:t.backgroundImageUrl}:{},...n!==void 0?{durationSec:n}:{},...t.fit?{fit:t.fit}:{},...e?{outputFormat:e}:{},renderTier:t.renderTier,title:t.title});if(!t.wait){r?.stop(),vo(i,t.format);return}let s=await ce(()=>no(i.requestId),Wg,Gg);if(s.status==="failed")throw new Error(s.error||"Presenter generation failed");if(!s.videoUrl)throw new Error("Presenter generation completed without a video URL");r&&(r.text="Downloading presenter clip..."),await te(s.videoUrl,t.output),r?.stop(),vo(s,t.format),t.format==="human"&&k(`Saved to: ${t.output}`)}catch(o){r?.stop(),a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Hg=new Ae("status").description("Check a presenter clip generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{vo(await no(t),e.format)}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Xg=new Ae("generate").description("Generate another look for an existing personal presenter").argument("<base-profile-id>","Base personal presenter id (pp_*)").requiredOption("--name <name>","Look name").requiredOption("--description <description>","Short look description").requiredOption("--prompt <prompt>","Exact appearance generation prompt").requiredOption("--look-id <id>","Stable template/look id").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this look request").action(async(t,e)=>{try{let n=e.idempotencyKey??pd(),r=await gd(e.referenceImage,n),o=await m("generatePresenterLook",{baseProfileId:t,description:e.description,id:e.lookId,prompt:e.prompt,...r?{referenceImages:r}:{},title:e.name},n);l(o)}catch(n){a(n instanceof Error?n.message:"Look generation failed"),process.exit(d.GENERAL_ERROR)}}),Yg=new Ae("status").description("Read presenter look generation status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("generatePresenterLook",t);if(e.format==="json")return l(n);if(e.format==="quiet")return console.log(n.status);w(`Run ID: ${t}`),w(`Status: ${n.status}`),n.error?.message&&a(n.error.message)}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Qg=new Ae("revise").description("Create a new Look by editing an existing presenter Look").argument("<look-id>","Ready presenter Look id (pp_*)").requiredOption("--instruction <instruction>","What to add, remove, or change").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this revision").action(async(t,e)=>{try{let n=e.idempotencyKey??pd(),r=await gd(e.referenceImage,n),o=await m("revisePresenterLook",{instruction:e.instruction,...r?{referenceImages:r}:{},sourceLookId:t},n);l(o)}catch(n){a(n instanceof Error?n.message:"Look revision failed"),process.exit(d.GENERAL_ERROR)}}),Zg=new Ae("revision-status").description("Read presenter Look revision status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("revisePresenterLook",t);if(e.format==="json")return l(n);if(e.format==="quiet")return console.log(n.status);w(`Run ID: ${t}`),w(`Status: ${n.status}`),n.error?.message&&a(n.error.message)}catch(n){a(n instanceof Error?n.message:"Revision status failed"),process.exit(d.GENERAL_ERROR)}}),ef=new Ae("look").description("Manage looks under an existing personal presenter").addCommand(Xg).addCommand(Qg).addCommand(Zg).addCommand(Yg),Io=new Ae("avatar").description("Generate presenter clips and looks; avatar options lists the voices and looks used by presentation video presenter and cast preset").addCommand(Jg).addCommand(zg).addCommand(ef).addCommand(Hg);Io.addHelpText("after",`
61
+ ${Xt.bold("Examples:")}
62
+ ${Xt.gray("# Discover the presenter avatars and voices you can use")}
63
+ $ ${u.commands[0]} avatar options
64
+
65
+ ${Xt.bold("See also:")}
66
+ ${Xt.gray("# Save a presenter + backdrop + voice combination under a name")}
67
+ $ ${u.commands[0]} cast preset --help
68
+
69
+ ${Xt.gray("# Apply an avatar, look, or preset to one presentation-video scene")}
70
+ $ ${u.commands[0]} presentation video presenter <project-id>
71
+ `);import{randomUUID as Oy}from"crypto";import{readFileSync as Dy}from"fs";import{writeFile as Ny}from"fs/promises";import F from"chalk";import{Command as vt,InvalidArgumentError as wc}from"commander";import _y from"ora";import{createHash as bf}from"crypto";import{Command as en,InvalidArgumentError as Zt}from"commander";import{createHash as sf}from"crypto";import{existsSync as df,readFileSync as cf}from"fs";import{basename as lf}from"path";import{Command as mf,InvalidArgumentError as Yt}from"commander";import uf from"ora";import{createHash as tf}from"crypto";import{Command as nf,InvalidArgumentError as fd}from"commander";var rf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function of(t){if(!rf.test(t))throw new fd("brand-id expects a UUID from `mf branding list`.");return t}function af(t){let e=Number(t);if(!Number.isInteger(e)||e<1)throw new fd("--file-size expects the exact positive whole-number byte size.");return e}async function ko(t){let{idempotencyKey:e,...n}=t;return m("createBrandAssetUploadUrl",n,e)}function xo(t){if(t===void 0)return"";if(t===null||typeof t!="object")return JSON.stringify(t);if(Array.isArray(t))return`[${t.map(xo).join(",")}]`;let e=t;return`{${Object.keys(e).filter(n=>e[n]!==void 0).sort().map(n=>`${JSON.stringify(n)}:${xo(e[n])}`).join(",")}}`}function Ro(t){return tf("sha256").update(`createBrandAssetUploadUrl:${xo(t)}`).digest("hex").slice(0,32)}var hd=new nf("upload-url").description("Mint a short-lived brand-scoped storage POST; this does not upload bytes").argument("<brand-id>","Brand UUID you may manage",of).requiredOption("--file-name <name>","Original filename used in storage content disposition").requiredOption("--file-type <mime>","Exact MIME type that the storage POST will send").requiredOption("--file-size <bytes>","Exact byte size, 1-104857600",af).option("--idempotency-key <key>","Stable retry key; defaults to a hash of brand and complete file metadata").option("--team-id <id>","Workspace ID; defaults to the selected workspace").addHelpText("after","\nNext: POST every returned field plus the file to uploadUrl, then run `mf branding asset register` with fileUrl, MIME type, and size.\n").action(async(t,e)=>{await y();try{l(await ko({brandId:t,...e,idempotencyKey:e.idempotencyKey??Ro({brandId:t,fileName:e.fileName,fileSize:e.fileSize,fileType:e.fileType})}))}catch(n){a(n instanceof Error?n.message:"Brand asset upload URL creation failed"),process.exit(d.GENERAL_ERROR)}});var pf=["footage","image","before_after","logo","audio"],gf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function ff(t){if(!gf.test(t))throw new Yt("brand-id expects a UUID from `mf branding list`.");return t}function yd(t){return e=>{let n=Number(e);if(!Number.isInteger(n)||n<0)throw new Yt(`${t} expects a whole number of 0 or more.`);return n}}function hf(t){let e=Number(t);if(!Number.isFinite(e)||e<0)throw new Yt("--duration-sec expects a number of 0 or more.");return e}function yf(t){let e;try{e=JSON.parse(t)}catch{throw new Yt("--metadata expects valid JSON.")}if(!e||typeof e!="object"||Array.isArray(e))throw new Yt("--metadata expects a JSON object.");return e}var bd=new mf("upload").description("Upload one local file, register it on a brand, and print the asset JSON").argument("<brand-id>","Brand UUID",ff).requiredOption("--file <path>","Local file to upload through Mindframes storage").requiredOption("--kind <kind>","Asset kind: footage | image | before_after | logo | audio",b("--kind",pf)).option("--label <text>","Display label; defaults to the local filename").option("--width <px>","Image or video width in pixels",yd("--width")).option("--height <px>","Image or video height in pixels",yd("--height")).option("--duration-sec <n>","Audio or video duration in seconds",hf).option("--set-key <key>","Pair key; required when --kind before_after").option("--role <role>","Pair role: before | after; required when --kind before_after",b("--role",["before","after"])).option("--metadata <json>",'Optional metadata JSON: {"pairLabel":"Summer","source":"upload"}',yf).option("--idempotency-key <key>","Retry key; defaults to a hash of file bytes and complete registration input").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y(),df(e.file)||(a(`File not found: ${e.file}`),process.exit(d.INVALID_INPUT)),e.kind==="before_after"&&(!e.role||!e.setKey)&&(a("--kind before_after requires both --role and --set-key."),process.exit(d.INVALID_INPUT)),e.kind!=="before_after"&&(e.role||e.setKey)&&(a("--role and --set-key are only valid with --kind before_after."),process.exit(d.INVALID_INPUT));let n=sf("sha256").update(cf(e.file)).digest("hex"),r=Bt(e.file),o={brandId:t,contentHash:n,durationSec:e.durationSec,fileName:r.fileName,fileSize:r.fileSize,fileType:r.fileType,height:e.height,kind:e.kind,label:e.label===void 0?r.fileName:e.label.trim(),metadata:e.metadata,role:e.role,setKey:e.setKey,width:e.width},i=e.idempotencyKey??Ro(o),s=uf({text:`Uploading ${lf(e.file)}...`,stream:process.stderr}).start();try{let c=await ko({brandId:t,...r,idempotencyKey:i,teamId:e.teamId}),p=await Gt(e.file,c);s.succeed("Uploaded"),l(await m("registerBrandAsset",{brandId:t,durationSec:e.durationSec,height:e.height,kind:e.kind,label:o.label,metadata:e.metadata,mimeType:p.type,role:e.role,s3Key:p.s3Key,setKey:e.setKey,sizeBytes:p.size,teamId:e.teamId,url:p.url,width:e.width},i))}catch(c){s.fail("Asset upload failed"),a(c instanceof Error?c.message:"Asset upload failed"),process.exit(d.GENERAL_ERROR)}});var wd=["footage","image","before_after","logo","audio"],wf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function gt(t){return e=>{if(!wf.test(e))throw new Zt(`${t} expects a UUID from \`mf branding list\` or \`mf branding asset list\`.`);return e}}function Qt(t,e){return n=>{let r=Number(n);if(!Number.isInteger(r)||r<e)throw new Zt(`${t} expects a whole number from ${e} upward.`);return r}}function vf(t){return e=>{let n=Number(e);if(!Number.isFinite(n)||n<0)throw new Zt(`${t} expects a number of 0 or more.`);return n}}function If(t){let e;try{e=JSON.parse(t)}catch(n){throw new Zt(`--metadata expects JSON: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Zt("--metadata expects a JSON object.");return e}function Co(t){return bf("sha256").update(t).digest("hex").slice(0,32)}function Wn(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}var xf=new en("list").description("List one brand's uploaded assets and print stable asset IDs").argument("<brand-id>","Brand UUID",gt("brand-id")).option("--kind <kind>","Filter: footage | image | before_after | logo | audio",b("--kind",wd)).option("--limit <count>","Caller-selected page size; omit to return every matching asset",Qt("--limit",1)).option("--offset <count>","Matching assets to skip before returning results (default: 0)",Qt("--offset",0)).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("listBrandAssets",{brandId:t,...e.kind?{kind:e.kind}:{},...e.limit?{limit:e.limit}:{},...e.offset!==void 0?{offset:e.offset}:{},teamId:e.teamId}))}catch(n){Wn(n,"Asset list failed")}}),kf=new en("register").description("Register one app-owned upload from its exact URL, key, MIME, and metadata").argument("<brand-id>","Brand UUID",gt("brand-id")).requiredOption("--url <url>","Final app-owned file URL returned by the upload step").requiredOption("--kind <kind>","Asset kind: footage | image | before_after | logo | audio",b("--kind",wd)).option("--label <text>","Optional display label, up to 160 characters").requiredOption("--mime-type <type>","Exact MIME type returned by the upload step; verified against storage").option("--s3-key <key>","Optional storage key; when set it must match the URL and upload owner").option("--size-bytes <n>","Expected byte size; when set it must match storage",Qt("--size-bytes",0)).option("--width <px>","Image or video width in pixels",Qt("--width",0)).option("--height <px>","Image or video height in pixels",Qt("--height",0)).option("--duration-sec <n>","Audio or video duration in seconds",vf("--duration-sec")).option("--set-key <key>","Pair key; required when --kind before_after").option("--role <role>","Pair role: before | after; required when --kind before_after",b("--role",["before","after"])).option("--metadata <json>",'Optional metadata JSON: {"pairLabel":"Summer","source":"upload"}',If).option("--idempotency-key <key>","Retry key; defaults to a hash of the complete registration input").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y(),e.kind==="before_after"&&(!e.role||!e.setKey)&&(a("--kind before_after requires both --role and --set-key."),process.exit(d.INVALID_INPUT)),e.kind!=="before_after"&&(e.role||e.setKey)&&(a("--role and --set-key are only valid with --kind before_after."),process.exit(d.INVALID_INPUT));let n={brandId:t,durationSec:e.durationSec,height:e.height,kind:e.kind,label:e.label,metadata:e.metadata,mimeType:e.mimeType,role:e.role,s3Key:e.s3Key,setKey:e.setKey,sizeBytes:e.sizeBytes,teamId:e.teamId,url:e.url,width:e.width},r=e.idempotencyKey??Co(`registerBrandAsset:${JSON.stringify(n)}`);try{l(await m("registerBrandAsset",n,r))}catch(o){Wn(o,"Asset registration failed")}}),Rf=new en("rename").description("Rename one asset, then print its stored label and metadata").argument("<asset-id>","Asset UUID from `mf branding asset list`",gt("asset-id")).requiredOption("--brand <brand-id>","Owning brand UUID",gt("--brand")).requiredOption("--label <text>","New non-empty label, up to 160 characters").option("--idempotency-key <key>","Retry key; defaults to a hash of asset ID and label").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();let n=e.label.trim();n||(a("--label cannot be empty."),process.exit(d.INVALID_INPUT));try{l(await m("renameBrandAsset",{assetId:t,brandId:e.brand,label:n,teamId:e.teamId},e.idempotencyKey??Co(`renameBrandAsset:${t}:${n}`)))}catch(r){Wn(r,"Asset rename failed")}}),Cf=new en("delete").description("Remove one asset record from the brand while keeping its uploaded file").argument("<asset-id>","Asset UUID from `mf branding asset list`",gt("asset-id")).requiredOption("--brand <brand-id>","Owning brand UUID",gt("--brand")).option("--yes","Confirm removal from the brand library without an interactive prompt").option("--idempotency-key <key>","Retry key; defaults to a stable hash of the asset ID").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y(),e.yes||(a("Refusing removal from the brand library without --yes."),process.exit(d.INVALID_INPUT));try{l(await m("deleteBrandAsset",{assetId:t,brandId:e.brand,teamId:e.teamId},e.idempotencyKey??Co(`deleteBrandAsset:${t}`)))}catch(n){Wn(n,"Asset deletion failed")}}),vd=new en("asset").description("List, upload, rename, and remove a brand's private asset library").addCommand(xf).addCommand(kf).addCommand(hd).addCommand(bd).addCommand(Rf).addCommand(Cf);import{createHash as Sf}from"crypto";import{Command as Xe,InvalidArgumentError as Id}from"commander";var Ef=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Kn(t){if(!Ef.test(t))throw new Id("Expected a brand UUID from `mf branding list`.");return t}function $f(t){if(t==="true")return!0;if(t==="false")return!1;throw new Id("--show expects true or false.")}function So(t,e){return Sf("sha256").update(JSON.stringify([t,e])).digest("hex").slice(0,32)}function Jn(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}var Tf=new Xe("set").description("Create or update one custom colour role and print the committed snapshot").argument("<brand-id>","Brand UUID",Kn).argument("<role>","Custom role without the color. prefix").argument("<hex>","Three- or six-digit hex colour, for example #114b97").option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--idempotency-key <key>","Stable retry key; derived from the complete change when omitted").action(async(t,e,n,r)=>{await y();let o={brandId:t,hex:n,role:e,teamId:r.teamId};try{l(await m("setBrandCustomColor",o,r.idempotencyKey??So("setBrandCustomColor",o)))}catch(i){Jn(i,"Custom colour update failed")}}),Af=new Xe("delete").description("Remove one custom colour role and print the committed snapshot").argument("<brand-id>","Brand UUID",Kn).argument("<role>","Custom role without the color. prefix").option("--yes","Confirm removal without an interactive prompt").option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--idempotency-key <key>","Stable retry key; derived from brand and role when omitted").action(async(t,e,n)=>{await y(),n.yes||(a("Refusing to remove a custom colour without --yes."),process.exit(d.INVALID_INPUT));let r={brandId:t,role:e,teamId:n.teamId};try{l(await m("deleteBrandCustomColor",r,n.idempotencyKey??So("deleteBrandCustomColor",r)))}catch(o){Jn(o,"Custom colour removal failed")}}),xd=new Xe("foundation").description("Manage atomic Foundation settings backed by the brand DAG").addCommand(new Xe("color").description("Manage custom colour roles").addCommand(Tf).addCommand(Af)),Pf=new Xe("get").description("Read the complete current footer and its source").argument("<brand-id>","Brand UUID",Kn).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("getBrandFooter",{brandId:t,teamId:e.teamId}))}catch(n){Jn(n,"Footer read failed")}}),Of=new Xe("set").description("Patch footer text, visibility, or alignment atomically").argument("<brand-id>","Brand UUID",Kn).option("--text <text>","Complete footer text; pass an empty string to clear it").option("--show <boolean>","Whether artifacts show the footer: true | false",$f).option("--alignment <value>","Footer alignment: left | center | right",b("--alignment",["left","center","right"])).option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--idempotency-key <key>","Stable retry key; derived from the complete patch when omitted").action(async(t,e)=>{await y(),e.alignment===void 0&&e.show===void 0&&e.text===void 0&&(a("Pass at least one of --text, --show, or --alignment."),process.exit(d.INVALID_INPUT));let n={alignment:e.alignment,brandId:t,show:e.show,teamId:e.teamId,text:e.text};try{l(await m("setBrandFooter",n,e.idempotencyKey??So("setBrandFooter",n)))}catch(r){Jn(r,"Footer update failed")}}),kd=new Xe("footer").description("Read or update the brand footer").addCommand(Pf).addCommand(Of);import{createHash as Df}from"crypto";import{Command as Rd}from"commander";var Nf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function _f(t){Nf.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Lf(t){return Df("sha256").update(t).digest("hex").slice(0,32)}function Cd(t,e){try{return JSON.parse(e)}catch(n){a(`${t} is not valid JSON: ${n instanceof Error?n.message:String(n)}`),process.exit(d.INVALID_INPUT)}}function Uf(t,e){let n=Cd(t,e);return Array.isArray(n)||(a(`${t} must be a JSON array of gradients, e.g. '[{"id":"dawn","type":"linear","stops":[{"color":"#155DAC","position":0},{"color":"#0B2C52","position":100}]}]'.`),process.exit(d.INVALID_INPUT)),n}function jf(t,e){let n=Cd(t,e);return(typeof n!="object"||n===null||Array.isArray(n))&&(a(`${t} must be a JSON object.`),process.exit(d.INVALID_INPUT)),n}var qf=new Rd("set").description("Replace a brand's gradient library (whole-set: omitted gradients are deleted)").argument("<brand-id>","Brand profile ID").requiredOption("--gradients <json>",`The complete gradient list as JSON, e.g. '[{"id":"dawn","name":"Dawn","type":"linear","angle":135,"stops":[{"color":"#155DAC","position":0},{"color":"#0B2C52","position":100}]}]'. Gradients you omit are DELETED.`).option("--roles <json>",`Role pointers by gradient id, e.g. '{"primary":"dawn"}'. Omit to leave the brand's current roles alone.`).option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_f(t);let n={brandId:t,gradients:Uf("--gradients",e.gradients),teamId:e.teamId};e.roles!==void 0&&(n.gradientRoles=jf("--roles",e.roles));try{l(await m("setBrandGradients",n,Lf(`setBrandGradients:${t}:${JSON.stringify(n)}`)))}catch(r){a(r instanceof Error?r.message:"Set failed"),process.exit(d.GENERAL_ERROR)}}),Sd=new Rd("gradient").description("Brand gradient library commands").addCommand(qf);import{createHash as Vf}from"crypto";import{Command as Ye}from"commander";var Mf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function tn(t){Mf.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Ff(t,e=[]){return[...e,t]}function $o(t){return Vf("sha256").update(t).digest("hex").slice(0,32)}function Eo(t,e){if(e==="true")return!0;if(e==="false")return!1;a(`${t} must be true or false; got "${e}".`),process.exit(d.INVALID_INPUT)}function Ed(t,e){try{return JSON.parse(e)}catch{a(`${t} must be valid JSON.`),process.exit(d.INVALID_INPUT)}}var Bf=new Ye("get").description("Read a brand's guardrail rules").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),tn(t);try{l(await m("getBrandGuardrails",{brandId:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Read failed"),process.exit(d.GENERAL_ERROR)}}),Gf=new Ye("test").description("Check content against a brand's guardrail rules").argument("<brand-id>","Brand profile ID").option("--content <text>","The content to check").option("--channel <channel>","Channel the content is for, e.g. deck-16-9").option("--market <market>","Market the content is for, e.g. US").option("--artifact-type <type>","Artifact type, e.g. presentation").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),tn(t),e.content===void 0&&(a("Pass --content with the text to check."),process.exit(d.INVALID_INPUT));let n={brandId:t,content:e.content,teamId:e.teamId};e.channel!==void 0&&(n.channel=e.channel),e.market!==void 0&&(n.market=e.market),e.artifactType!==void 0&&(n.artifactType=e.artifactType);try{let r=await m("testBrandGuardrails",n);l(r),r.passed===!1&&process.exit(d.GENERAL_ERROR)}catch(r){a(r instanceof Error?r.message:"Test failed"),process.exit(d.GENERAL_ERROR)}}),Wf=new Ye("set").description("Create or update one of a brand's guardrail rules").argument("<brand-id>","Brand profile ID").option("--name <text>","Rule name").option("--category <category>","language | compliance | channel-requirements | accessibility | asset-usage").option("--severity <severity>","shadow | warn | block").option("--require <json>",`What the rule demands, as JSON, e.g. '{"component":"banned-phrase","text":"cheap"}'`).option("--conditions <json>",`When the rule applies, as JSON, e.g. '{"op":"AND","clauses":[{"field":"channel","op":"is","values":["deck-16-9"]}]}'`).option("--enabled <bool>","true or false; defaults to true").option("--node-key <key>","Existing rule node key to UPDATE, from `guardrails get`. Omit to create.").option("--notes <text>","Notes about the rule").option("--slug <slug>","Explicit kebab-case slug for a new rule").option("--publish <bool>","Publish a brand snapshot after the write; defaults to true").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),tn(t),(!e.name||!e.category||!e.severity)&&(a("Pass --name, --category and --severity."),process.exit(d.INVALID_INPUT)),e.require===void 0&&(a(`Pass --require, e.g. '{"component":"banned-phrase"}'.`),process.exit(d.INVALID_INPUT));let n={brandId:t,category:e.category,name:e.name,require:Ed("--require",e.require),severity:e.severity,teamId:e.teamId};e.conditions!==void 0&&(n.conditions=Ed("--conditions",e.conditions)),e.enabled!==void 0&&(n.enabled=Eo("--enabled",e.enabled)),e.nodeKey!==void 0&&(n.nodeKey=e.nodeKey),e.notes!==void 0&&(n.notes=e.notes),e.slug!==void 0&&(n.slug=e.slug),e.publish!==void 0&&(n.publish=Eo("--publish",e.publish));try{l(await m("setBrandGuardrail",n,$o(`setBrandGuardrail:${t}:${JSON.stringify(n)}`)))}catch(r){a(r instanceof Error?r.message:"Write failed"),process.exit(d.GENERAL_ERROR)}}),Kf=new Ye("delete").description("Remove one of a brand's guardrail rules").argument("<brand-id>","Brand profile ID").argument("<node-key>","Rule node key from `guardrails get`").option("--publish <bool>","Publish a brand snapshot after the removal; defaults to true").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{await y(),tn(t);let r={brandId:t,nodeKey:e,teamId:n.teamId};n.publish!==void 0&&(r.publish=Eo("--publish",n.publish));try{l(await m("deleteBrandGuardrail",r,$o(`deleteBrandGuardrail:${t}:${e}`)))}catch(o){a(o instanceof Error?o.message:"Delete failed"),process.exit(d.GENERAL_ERROR)}}),Jf=new Ye("generate").description("Draft guardrail rule proposals for a brand").argument("<brand-id>","Brand profile ID").option("--brand-name <name>","Brand name to draft rules for").option("--channel <channel>","Channel the brand publishes to; repeat for several. At least one is required.",Ff).option("--brand-description <text>","What the brand does").option("--brand-voice <text>","How the brand sounds").option("--industry <text>","Industry the brand operates in").option("--no-wait","Return the run id immediately instead of waiting").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),tn(t),e.brandName||(a("Pass --brand-name."),process.exit(d.INVALID_INPUT)),e.channel?.length||(a("Pass at least one --channel to scope the proposed rules."),process.exit(d.INVALID_INPUT));let n={activeChannels:e.channel,brandId:t,brandName:e.brandName,teamId:e.teamId};e.brandDescription!==void 0&&(n.brandDescription=e.brandDescription),e.brandVoice!==void 0&&(n.brandVoice=e.brandVoice),e.industry!==void 0&&(n.industry=e.industry);try{let r=await m("generateBrandGuardrails",n,$o(`generateBrandGuardrails:${JSON.stringify(n)}`));if(e.wait===!1){l(r);return}l(await is(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Generate failed"),process.exit(d.GENERAL_ERROR)}}),zf=new Ye("generate-status").description("Read a brand guardrails generation run").argument("<run-id>","Run ID from `branding guardrails generate --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("generateBrandGuardrails",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),$d=new Ye("guardrails").description("Brand guardrail rule commands").addCommand(Bf).addCommand(Gf).addCommand(Wf).addCommand(Kf).addCommand(Jf).addCommand(zf);import{randomUUID as Hf}from"crypto";import{readFile as Td}from"fs/promises";import{Command as Xf}from"commander";var Ad=new Xf("import").description("Import a workspace brand from a DESIGN.md file").argument("<design-md-file>","Path to the DESIGN.md file").option("--name <name>","Override the brand name in the document").option("--url <url>","Associate a source URL with the imported brand").option("--url-evidence <json-file>","Merge a saved raw URL-extraction JSON response").option("--team-id <id>","Workspace ID").option("--idempotency-key <key>","Stable key for retrying the same import without creating another brand").action(async(t,e)=>{await y();try{let n=await Td(t,"utf8"),r=e.urlEvidence?JSON.parse(await Td(e.urlEvidence,"utf8")):void 0,o=e.idempotencyKey??Hf();l(await m("importBrandDesignMd",{designMd:n,name:e.name,teamId:e.teamId,url:e.url,urlExtractedRaw:r},o))}catch(n){a(n instanceof Error?n.message:"Import failed"),process.exit(d.GENERAL_ERROR)}});import{createHash as Yf}from"crypto";import{Command as Ne}from"commander";var Qf=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function _e(t){Qf.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function ft(t){return Yf("sha256").update(t).digest("hex").slice(0,32)}var Pd=new Ne("create").description("Create an empty workspace brand and print its JSON").argument("<name>","Name for the new brand").option("--parent <brand-id>","File the new brand under this parent").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),e.parent&&_e(e.parent);try{l(await m("createBrand",{name:t,parentBrandingId:e.parent,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Create failed"),process.exit(d.GENERAL_ERROR)}}),Od=new Ne("star").description("Add a library star, or remove it with --off, and print the result").argument("<brand-id>","Brand profile ID").option("--off","Remove the star instead of adding it").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_e(t);let n=!e.off;try{l(await m("setBrandStar",{brandId:t,starred:n,teamId:e.teamId},ft(`setBrandStar:${t}:${n}`)))}catch(r){a(r instanceof Error?r.message:"Star failed"),process.exit(d.GENERAL_ERROR)}});async function Zf(t,e){let n=await m("getBrandProfile",{brandId:t,teamId:e.teamId});return typeof n.name=="string"?n.name:t}var Dd=new Ne("delete").description("Soft-delete a brand after confirmation and print the result").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").option("--yes","Confirm soft deletion without an interactive prompt").action(async(t,e)=>{if(await y(),_e(t),!e.yes&&process.stdin.isTTY){let n;try{n=await Zf(t,e)}catch(r){a(r instanceof Error?r.message:"Could not read the brand"),process.exit(d.GENERAL_ERROR)}a(`Refusing to delete "${n}" (${t}) without confirmation. Re-run with --yes to remove this brand from the library.`),process.exit(d.GENERAL_ERROR)}try{l(await m("deleteBrand",{brandId:t,teamId:e.teamId},ft(`deleteBrand:${t}`)))}catch(n){a(n instanceof Error?n.message:"Delete failed"),process.exit(d.GENERAL_ERROR)}}),To="none",Nd=new Ne("update").description("Rename with --name or move with --parent; print the updated JSON").argument("<brand-id>","Brand profile ID").option("--name <name>","New name for the brand").option("--parent <brand-id>",`File the brand under this parent, or "${To}" to detach it`).option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_e(t);let n=e.parent?.toLowerCase()===To;e.parent!==void 0&&!n&&_e(e.parent),e.name===void 0&&e.parent===void 0&&(a(`Nothing to update. Pass --name to rename this brand, or --parent <brand-id> to move it (--parent ${To} detaches it).`),process.exit(d.INVALID_INPUT));let r={brandId:t,teamId:e.teamId};e.name!==void 0&&(r.name=e.name),e.parent!==void 0&&(r.parentBrandingId=n?null:e.parent);try{l(await m("updateBrand",r,ft(`updateBrand:${t}:${e.name??""}:${e.parent??""}`)))}catch(o){a(o instanceof Error?o.message:"Update failed"),process.exit(d.GENERAL_ERROR)}}),_d=new Ne("set-default").description("Use this brand by default for new artifacts and print the result").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_e(t);try{l(await m("setDefaultBrand",{brandId:t,teamId:e.teamId},ft(`setDefaultBrand:${t}`)))}catch(n){a(n instanceof Error?n.message:"Set default failed"),process.exit(d.GENERAL_ERROR)}}),Ld=new Ne("approve").description("Approve a reviewed brand for use and print the persisted result").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_e(t);try{let n=await J(e.teamId);l(await m("approveBrand",{brandId:t,teamId:n},ft(`approveBrand:${n}:${t}`)))}catch(n){a(n instanceof Error?n.message:"Approve failed"),process.exit(d.GENERAL_ERROR)}}),Ud=new Ne("onboarding").description("Manage the brand onboarding review state").addCommand(new Ne("complete").description("Mark onboarding review complete without approving the brand").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),_e(t);try{let n=await J(e.teamId);l(await m("completeBrandOnboarding",{brandId:t,teamId:n},ft(`completeBrandOnboarding:${n}:${t}`)))}catch(n){a(n instanceof Error?n.message:"Complete onboarding failed"),process.exit(d.GENERAL_ERROR)}}));import{createHash as Ao}from"crypto";import{existsSync as eh,readFileSync as th}from"fs";import{basename as nh}from"path";import{Command as zn}from"commander";import rh from"ora";function oh(t,e,n){return Ao("sha256").update(JSON.stringify([t,e,n??null])).digest("hex").slice(0,32)}var jd=new zn("logo").description("Upload primary, dark-background, and favicon logo files").addCommand(new zn("list").description("List exact logo candidates and identify the active one").argument("<brand-id>","Brand UUID from `mf branding list`").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("listBrandLogos",{brandId:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Logo list failed"),process.exit(d.GENERAL_ERROR)}})).addCommand(new zn("remove").description("Remove one exact candidate URL and select its deterministic fallback").argument("<brand-id>","Brand UUID from `mf branding list`").argument("<logo-url>","Exact URL returned by `mf branding logo list`").option("--yes","Confirm exact candidate removal without an interactive prompt").option("--idempotency-key <key>","Stable retry key; derived from brand and URL when omitted").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e,n)=>{await y(),n.yes||(a("Refusing to remove a logo candidate without --yes."),process.exit(d.INVALID_INPUT));try{l(await m("removeBrandLogo",{brandId:t,logoUrl:e,teamId:n.teamId},n.idempotencyKey??oh("removeBrandLogo",t,e)))}catch(r){a(r instanceof Error?r.message:"Logo removal failed"),process.exit(d.GENERAL_ERROR)}})).addCommand(new zn("set").description("Upload one logo variant and print the updated brand JSON").argument("[brand-id]","Brand ID (defaults to this workspace's default brand)").requiredOption("--file <path>","Local image file to upload and use").option("--variant <variant>","primary | dark | favicon. 'dark' is the reversed lock-up for dark backgrounds","primary").option("--idempotency-key <key>","Stable retry key; deterministically derived from workspace, brand, variant, and file bytes when omitted").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();let n=e.variant??"primary";["primary","dark","favicon"].includes(n)||(a(`--variant must be primary, dark, or favicon (got "${n}")`),process.exit(d.INVALID_INPUT)),eh(e.file)||(a(`File not found: ${e.file}`),process.exit(d.INVALID_INPUT));let r=Ao("sha256").update(th(e.file)).digest("hex"),o=e.idempotencyKey??Ao("sha256").update(`setBrandLogo:${e.teamId??"current"}:${t??"default"}:${n}:${r}`).digest("hex").slice(0,32),i=rh({text:`Uploading ${nh(e.file)}...`,stream:process.stderr}).start(),s;try{s=(await de(e.file,{idempotencyKey:`${o}:upload`,storagePrefix:"brand-logos"})).url,i.succeed("Uploaded")}catch(c){i.fail("Upload failed"),a(c instanceof Error?c.message:String(c)),process.exit(d.GENERAL_ERROR)}try{l(await m("setBrandLogo",{brandId:t,fileUrl:s,teamId:e.teamId,variant:n},o))}catch(c){a(c instanceof Error?c.message:"Write failed"),process.exit(d.GENERAL_ERROR)}}));import{createHash as ih,randomUUID as ah}from"crypto";import{Command as ht,InvalidArgumentError as Hn}from"commander";var sh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,dh=["admin","editor","viewer"],qd=["cancelled","completed","failed","info","queued","running"],Vd=["activity","brand-extraction-request","brand-resolution","brand-sync-job"];function Qe(t){return e=>{if(!sh.test(e))throw new Hn(`${t} expects a UUID from \`mf branding list\` or the workspace member list.`);return e}}function Fd(t){let e=Number(t);if(!Number.isInteger(e)||e<1||e>200)throw new Hn("--limit expects a whole number from 1 to 200.");return e}function Md(t,e){return n=>{let r=n.split(",").map(i=>i.trim()).filter(Boolean);if(r.find(i=>!e.includes(i))||r.length===0)throw new Hn(`${t} expects comma-separated values from: ${e.join(", ")}.`);return r}}function Bd(t,e){return ih("sha256").update(JSON.stringify([t,e,ah()])).digest("hex").slice(0,32)}function nn(t,e){a(t instanceof Error?t.message:e),process.exit(typeof t=="object"&&t!==null&&"exitCode"in t&&typeof t.exitCode=="number"?t.exitCode:d.GENERAL_ERROR)}var ch=new ht("list").description("List explicit member access overrides for one team brand").argument("<brand-id>","Team brand UUID",Qe("brand-id")).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("listBrandPermissions",{brandId:t,teamId:e.teamId}))}catch(n){nn(n,"Brand permission list failed")}}),lh=new ht("candidates").description("List member IDs eligible for one team brand's access overrides").argument("<brand-id>","Team brand UUID",Qe("brand-id")).option("--query <text>","Search member name, username, or email").option("--limit <count>","Maximum members, 1-200 (default: 50)",Fd).option("--offset <count>","Members to skip (default: 0)",t=>{let e=Number(t);if(!Number.isInteger(e)||e<0)throw new Hn("--offset expects a whole number of 0 or more.");return e}).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("listBrandPermissionCandidates",{brandId:t,limit:e.limit,offset:e.offset,query:e.query,teamId:e.teamId}))}catch(n){nn(n,"Brand permission candidate list failed")}}),mh=new ht("set").description("Set one team member's explicit role for a team brand").argument("<brand-id>","Team brand UUID",Qe("brand-id")).requiredOption("--user <user-id>","Target workspace member UUID",Qe("--user")).requiredOption("--role <role>","Desired override: admin | editor | viewer",b("--role",dh)).option("--idempotency-key <key>","Explicit retry identity; otherwise a new payload-bound key is minted").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("setBrandPermission",{brandId:t,role:e.role,teamId:e.teamId,userId:e.user},e.idempotencyKey??Bd("setBrandPermission",{brandId:t,role:e.role,teamId:e.teamId??null,userId:e.user})))}catch(n){nn(n,"Brand permission update failed")}}),uh=new ht("remove").description("Remove one member override so the team role applies again").argument("<brand-id>","Team brand UUID",Qe("brand-id")).requiredOption("--user <user-id>","Target workspace member UUID",Qe("--user")).option("--yes","Confirm this access change without an interactive prompt").option("--idempotency-key <key>","Explicit retry identity; otherwise a new payload-bound key is minted").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y(),e.yes||(a("Refusing to remove a brand access override without --yes."),process.exit(d.INVALID_INPUT));try{l(await m("removeBrandPermission",{brandId:t,teamId:e.teamId,userId:e.user},e.idempotencyKey??Bd("removeBrandPermission",{brandId:t,teamId:e.teamId??null,userId:e.user})))}catch(n){nn(n,"Brand permission removal failed")}}),Gd=new ht("permission").description("Administer explicit member access overrides for a team brand").addCommand(lh).addCommand(ch).addCommand(mh).addCommand(uh),Wd=new ht("activity").description("Read a brand's filtered, cursor-paginated activity feed").argument("<brand-id>","Brand UUID",Qe("brand-id")).option("--query <text>","Search action, summary, detail, entity, and metadata").option("--status <statuses>",`Comma-separated statuses: ${qd.join(" | ")}`,Md("--status",qd)).option("--source-type <types>",`Comma-separated sources: ${Vd.join(" | ")}`,Md("--source-type",Vd)).option("--from <iso-time>","Inclusive ISO-8601 lower time bound").option("--to <iso-time>","Inclusive ISO-8601 upper time bound").option("--limit <count>","Maximum rows, 1-200 (default: 80)",Fd).option("--cursor <cursor>","Opaque nextCursor from the preceding page").option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e)=>{await y();try{l(await m("listBrandActivity",{brandId:t,cursor:e.cursor,from:e.from,limit:e.limit,query:e.query,sourceTypes:e.sourceType,statuses:e.status,teamId:e.teamId,to:e.to}))}catch(n){nn(n,"Brand activity read failed")}});import{createHash as ph}from"crypto";import{Command as yt,InvalidArgumentError as Oo}from"commander";var gh=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function Po(t,e){if(gh.test(t))return t;throw new Oo(`${e} must be a UUID.`)}function fh(t){let e=Number(t);if(Number.isInteger(e)&&e>=1&&e<=50)return e;throw new Oo("limit must be a whole number from 1 to 50.")}function hh(t){let e=Number(t);if(Number.isInteger(e)&&e>=0)return e;throw new Oo("offset must be a whole number of 0 or more.")}function yh(t){return ph("sha256").update(t).digest("hex").slice(0,32)}async function Xn(t,e){await y();try{l(await t())}catch(n){a(n instanceof Error?n.message:e),process.exit(d.GENERAL_ERROR)}}var Kd=new yt("presentations").description("Inspect presentations already linked to a brand").addCommand(new yt("list").description("List linked decks with preview, version, stale, and last-sync state").argument("<brand-id>","Brand UUID from `branding list`").option("--limit <n>","Rows to return (1-50; default 50)",fh,50).option("--offset <n>","Zero-based offset (default 0)",hh,0).option("--team-id <id>","Workspace UUID; defaults to the selected workspace").action(async(t,e)=>{let n=Po(t,"brand-id");await Xn(()=>m("listBrandPresentations",{brandId:n,limit:e.limit,offset:e.offset,teamId:e.teamId}),"Could not list linked presentations")})),Jd=new yt("presentation").description("Inspect or update one deck from its already-linked brand").addCommand(new yt("drift").description("Read current, drifted, unknown, or not-linked status and exact changes").argument("<presentation>","Presentation UUID, document UUID, or slug").option("--team-id <id>","Workspace UUID; defaults to the selected workspace").action(async(t,e)=>{await Xn(()=>m("getPresentationBrandDrift",{presentationId:t,teamId:e.teamId}),"Could not read presentation brand drift")})).addCommand(new yt("apply-changes").description("Create a new deck version using its linked brand's current colors, fonts, and logo").argument("<presentation>","Presentation UUID, document UUID, or slug").option("--team-id <id>","Workspace UUID; defaults to the selected workspace").requiredOption("--idempotency-key <key>","Stable key; reuse it for an exact retry, change it for a later brand update").action(async(t,e)=>{await Xn(()=>m("applyPresentationBrandChanges",{presentationId:t,teamId:e.teamId},e.idempotencyKey),"Could not apply linked-brand changes")})),zd=new yt("sync-cancel").description("Cancel an active bulk linked-deck sync through its durable run; retries are safe").argument("<brand-id>","Brand UUID used to start the sync").argument("<run-id>","Active run UUID from `branding sync --no-wait`").option("--team-id <id>","Workspace UUID; defaults to the selected workspace").action(async(t,e,n)=>{let r=Po(t,"brand-id"),o=Po(e,"run-id");await Xn(()=>m("cancelBrandPresentationSync",{brandId:r,runId:o,teamId:n.teamId},yh(`cancelBrandPresentationSync:${r}:${o}`)),"Could not cancel brand sync")});import{createHash as bh,randomUUID as Qd}from"crypto";import{Command as Le}from"commander";var wh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Hd=["product","service","platform","solution"],Yn=["candidate","draft","approved"],Xd=["brand-site","brand-site-scan","brand-site-extract","product-url"];function bt(t){wh.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Qn(t,e,n){if(n.includes(e))return e;a(`${t} must be one of: ${n.join(", ")}.`),process.exit(d.INVALID_INPUT)}function vh(t,e){let n=Number(e);if(Number.isInteger(n)&&n>0)return n;a(`${t} must be a whole number greater than zero.`),process.exit(d.INVALID_INPUT)}function Do(t){return bh("sha256").update(t).digest("hex").slice(0,32)}var Ih=new Le("list").description("List the products a brand sells").argument("<brand-id>","Brand profile ID").option("--status <status>",`Only products in this state. One of: ${Yn.join(", ")}. Omit for the saved catalogue.`).option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),bt(t),e.status!==void 0&&Qn("--status",e.status,Yn);let n={brandId:t,teamId:e.teamId};e.status!==void 0&&(n.status=e.status);try{l(await m("listBrandProducts",n))}catch(r){a(r instanceof Error?r.message:"List failed"),process.exit(d.GENERAL_ERROR)}}),xh=new Le("set").description("Create or update one of a brand's products").argument("<brand-id>","Brand profile ID").option("--product <id>","Existing product to update. Omit to create, or to update the product this brand already has at the same --url.").option("--name <name>","Product name (required when creating)").option("--type <type>",`One of: ${Hd.join(", ")}`).option("--description <text>","What the product is, in full").option("--summary <text>","Short form of the description").option("--url <url>","The product's page. Also its identity: a url this brand already has updates that product.").option("--status <status>",`One of: ${Yn.join(", ")}`).option("--logo-url <url>","Product logo URL").option("--inherits-brand <true|false>","Whether the product presents in the parent brand's design").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),bt(t),e.type!==void 0&&Qn("--type",e.type,Hd),e.status!==void 0&&Qn("--status",e.status,Yn),e.inheritsBrand!==void 0&&e.inheritsBrand!=="true"&&e.inheritsBrand!=="false"&&(a("--inherits-brand must be true or false."),process.exit(d.INVALID_INPUT));let n={brandId:t,teamId:e.teamId};e.product!==void 0&&(n.productId=e.product),e.name!==void 0&&(n.name=e.name),e.type!==void 0&&(n.type=e.type),e.description!==void 0&&(n.description=e.description),e.summary!==void 0&&(n.summary=e.summary),e.url!==void 0&&(n.url=e.url),e.status!==void 0&&(n.status=e.status),e.logoUrl!==void 0&&(n.logoUrl=e.logoUrl),e.inheritsBrand!==void 0&&(n.inheritsBrand=e.inheritsBrand==="true");try{l(await m("saveBrandProduct",n,Do(`saveBrandProduct:${t}:${e.product??e.url??e.name??"new"}`)))}catch(r){a(r instanceof Error?r.message:"Save failed"),process.exit(d.GENERAL_ERROR)}}),Yd=(t,e=[])=>[...e,t],kh=new Le("select").description("Atomically set approved products in a bounded product set").argument("<brand-id>","Brand profile ID").option("--product <id>","Product whose state to set; repeat for every product in the bounded set.",Yd).option("--approve <id>","Product from --product that should finish approved; repeat as needed. Others finish draft.",Yd).option("--idempotency-key <key>","Stable retry key for this selection").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),bt(t),e.product?.length||(a("Pass at least one --product <id> to set product approval."),process.exit(d.INVALID_INPUT));let n={approvedProductIds:e.approve??[],brandId:t,productIds:e.product,teamId:e.teamId};try{l(await m("setBrandProductSelection",n,e.idempotencyKey??Qd()))}catch(r){a(r instanceof Error?r.message:"Selection failed"),process.exit(d.GENERAL_ERROR)}}),Rh=new Le("duplicate").description("Create an independent draft copy of one product").argument("<brand-id>","Brand profile ID").requiredOption("--product <id>","Product ID to duplicate").option("--name <name>","Name for the copy").option("--idempotency-key <key>","Stable retry key for this duplication").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),bt(t);let n={brandId:t,productId:e.product,teamId:e.teamId};e.name!==void 0&&(n.name=e.name);try{l(await m("duplicateBrandProduct",n,e.idempotencyKey??Qd()))}catch(r){a(r instanceof Error?r.message:"Duplicate failed"),process.exit(d.GENERAL_ERROR)}}),Ch=new Le("delete").description("Remove one product from a brand").argument("<brand-id>","Brand profile ID").option("--product <id>","Product ID to remove").option("--team-id <id>","Workspace ID").option("--yes","Skip the confirmation prompt").action(async(t,e)=>{await y(),bt(t),e.product===void 0&&(a("Pass --product <id> to name the product to remove. `branding product list <brand-id>` prints the ids."),process.exit(d.INVALID_INPUT)),!e.yes&&process.stdin.isTTY&&(a(`Refusing to delete product "${e.product}" without confirmation. Re-run with --yes.`),process.exit(d.GENERAL_ERROR));try{l(await m("deleteBrandProduct",{brandId:t,productId:e.product,teamId:e.teamId},Do(`deleteBrandProduct:${t}:${e.product}`)))}catch(n){a(n instanceof Error?n.message:"Delete failed"),process.exit(d.GENERAL_ERROR)}}),Sh=new Le("extract").description("Discover a brand's products by crawling its site").argument("<brand-id>","Brand profile ID").option("--mode <mode>",`One of: ${Xd.join(", ")}`).option("--url <url>","Page to extract (product-url), or the site to scan instead of the brand's own recorded URL").option("--max-products <count>","How many pages to take from the scan (max 30)").option("--product <id>","Candidate product to extract; repeat for several. Required for brand-site-extract.",(t,e=[])=>[...e,t]).option("--no-wait","Return the run id immediately instead of waiting").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),bt(t),e.mode!==void 0&&Qn("--mode",e.mode,Xd);let n={brandId:t,teamId:e.teamId};e.mode!==void 0&&(n.mode=e.mode),e.url!==void 0&&(n.url=e.url),e.maxProducts!==void 0&&(n.maxProducts=vh("--max-products",e.maxProducts)),e.product?.length&&(n.productIds=e.product);try{let r=await m("extractBrandProducts",n,Do(`extractBrandProducts:${JSON.stringify(n)}`));if(e.wait===!1){l(r);return}l(await rs(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Extract failed"),process.exit(d.GENERAL_ERROR)}}),Eh=new Le("extract-status").description("Read a brand product extraction run").argument("<run-id>","Run ID from `branding product extract --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("extractBrandProducts",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Zd=new Le("product").description("Brand product catalogue commands").addCommand(Ih).addCommand(xh).addCommand(kh).addCommand(Rh).addCommand(Ch).addCommand(Sh).addCommand(Eh);import{createHash as $h}from"crypto";import{Command as Zn}from"commander";var Th=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function ec(t){Th.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Ah(t,e=[]){return[...e,t]}function Ph(t){return $h("sha256").update(t).digest("hex").slice(0,32)}var Oh=new Zn("get").description("Read which decks have drifted from a brand").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),ec(t);try{l(await m("getBrandQuality",{brandId:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Read failed"),process.exit(d.GENERAL_ERROR)}}),Dh=new Zn("repair").description("Repair decks that have visually drifted from a brand").argument("<brand-id>","Brand profile ID").option("--scope <scope>","selected (repair only --deck ids) or all_eligible (repair every drifted deck). Required.").option("--deck <presentation-id>","Deck to repair; repeat for several. Only used with --scope selected.",Ah).option("--confirm-partial","Also repair decks whose guidance changed too; they stay flagged as guidance-outdated afterwards.").option("--no-wait","Return the run id immediately instead of waiting").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),ec(t),e.scope!=="selected"&&e.scope!=="all_eligible"&&(a("Pass --scope selected or --scope all_eligible. There is no default: 'selected' repairs only the decks you name, 'all_eligible' repairs every drifted deck on the brand."),process.exit(d.INVALID_INPUT)),e.scope==="selected"&&!e.deck?.length&&(a("--scope selected needs at least one --deck."),process.exit(d.INVALID_INPUT));let n={brandId:t,scope:e.scope,teamId:e.teamId};e.deck?.length&&(n.presentationIds=e.deck),e.confirmPartial===!0&&(n.confirmedPartialRepair=!0);try{let r=await m("repairBrandQuality",n,Ph(`repairBrandQuality:${JSON.stringify(n)}`));if(e.wait===!1){l(r);return}l(await as(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Repair failed"),process.exit(d.GENERAL_ERROR)}}),Nh=new Zn("repair-status").description("Read a brand quality repair run").argument("<run-id>","Run ID from `branding quality repair --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("repairBrandQuality",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),tc=new Zn("quality").description("Brand deck quality commands").addCommand(Oh).addCommand(Dh).addCommand(Nh);function No(t){return Array.isArray(t.items)}function Pe(t){return typeof t=="string"&&t.length>0?t:void 0}function _o(t){return Pe(t.resolvedTokens?.logoUrl)??Pe(t.brandData?.assets?.logo)??Pe(t.brandData?.assets?.logoUrl)??Pe(t.brandData?.logoUrl)}function Lo(t){return Pe(t.resolvedTokens?.colors?.primary)??Pe(t.brandData?.colors?.primary)??Pe(t.brandData?.enhancedColors?.palette?.[0]?.hex)}function nc(t){let e=t.brandData?.enhancedColors?.palette??t.brandData?.colors?.palette;if(!Array.isArray(e))return[];let n=[];for(let r of e){if(typeof r=="string"){n.push({hex:r});continue}if(r&&typeof r=="object"&&"hex"in r){let{hex:o,role:i}=r;typeof o=="string"&&n.push({hex:o,...typeof i=="string"?{role:i}:{}})}}return n}function _h(t){return{id:t.id,isDefault:t.isDefault,name:t.name,...t.domain?{sourceUrl:t.domain}:{},...t.logoUrl?{logoUrl:t.logoUrl}:{},...t.primaryColor?{primaryColor:t.primaryColor}:{}}}function Lh(t){let e=Pe(t.extractedFrom)??Pe(t.normalizedUrl),n=_o(t),r=Lo(t);return{id:t.id,isDefault:t.isDefault,name:t.name,...e?{sourceUrl:e}:{},...n?{logoUrl:n}:{},...r?{primaryColor:r}:{},...t.createdAt?{createdAt:t.createdAt}:{}}}function rc(t){return No(t)?t.items.map(Lh):t.brandings.map(_h)}import{createHash as Uh}from"crypto";import{Command as je,InvalidArgumentError as jh}from"commander";var qh=["x","instagram","facebook","linkedin","tiktok","youtube"],Vh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ue(t){if(!Vh.test(t))throw new jh("Expected a UUID returned by the corresponding list command.");return t}function er(t,e){return Uh("sha256").update(JSON.stringify([t,...e])).digest("hex")}function wt(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}var Mh=new je("list").description("List one brand's competitors with stable IDs, websites, X accounts, and avatars").option("--branding-id <id>","Brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async t=>{await y();try{l(await m("getBrandCompetitors",{brandingId:t.brandingId,teamId:t.teamId}))}catch(e){wt(e,"Competitor list failed")}}),Fh=new je("add").description("Add or update one competitor by name and print its stable saved row").argument("<name>","Competitor company or product name").option("--branding-id <id>","Brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--website <url>","Competitor website as a full URL").option("--x-handle <handle>","Competitor X handle, with or without @").option("--x-avatar-url <url>","Avatar URL for the selected X account").option("--no-resolve-handle","Do not search X when --x-handle is omitted").action(async(t,e)=>{await y();let n={brandingId:e.brandingId,name:t,resolveHandle:e.resolveHandle,teamId:e.teamId,website:e.website,xAvatarUrl:e.xAvatarUrl,xHandle:e.xHandle};try{l(await m("addCompetitor",n,er("addCompetitor",[e.brandingId??"default",t.trim(),e.website??null,e.xHandle??null,e.xAvatarUrl??null,e.resolveHandle])))}catch(r){wt(r,"Competitor write failed")}}),Bh=new je("delete").description("Remove one competitor by the stable ID from competitor list").argument("<competitor-id>","Competitor UUID",Ue).option("--branding-id <id>","Owning brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--yes","Confirm removal without an interactive prompt").action(async(t,e)=>{await y(),e.yes||(a("Refusing to remove a competitor without --yes."),process.exit(d.INVALID_INPUT));try{l(await m("deleteBrandCompetitor",{brandingId:e.brandingId,competitorId:t,teamId:e.teamId},er("deleteBrandCompetitor",[e.brandingId??"default",t])))}catch(n){wt(n,"Competitor removal failed")}}),oc=new je("competitor").description("List, add, update, or remove a brand's competitor watch rows").addCommand(Mh).addCommand(Fh).addCommand(Bh),Gh=new je("list").description("List one brand's social accounts with stable IDs, platforms, sources, and URLs").option("--branding-id <id>","Brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async t=>{await y();try{l(await m("listBrandSocialHandles",{brandingId:t.brandingId,teamId:t.teamId}))}catch(e){wt(e,"Social-account list failed")}}),Wh=new je("add").description("Record one social account and print its stable saved row").argument("<platform>","Social network: x | instagram | facebook | linkedin | tiktok | youtube",b("platform",qh)).argument("<handle>","Account handle on that social network").option("--branding-id <id>","Brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").action(async(t,e,n)=>{await y();try{l(await m("addBrandSocialHandle",{brandingId:n.brandingId,handle:e,platform:t,teamId:n.teamId},er("addBrandSocialHandle",[n.brandingId??"default",t,e.replace(/^@/,"")])))}catch(r){wt(r,"Social-account write failed")}}),Kh=new je("delete").description("Remove one social account by the stable ID from social list").argument("<handle-id>","Social-handle UUID",Ue).option("--branding-id <id>","Owning brand UUID; defaults to the workspace brand",Ue).option("--team-id <id>","Workspace ID; defaults to the selected workspace").option("--yes","Confirm removal without an interactive prompt").action(async(t,e)=>{await y(),e.yes||(a("Refusing to remove a social account without --yes."),process.exit(d.INVALID_INPUT));try{l(await m("deleteBrandSocialHandle",{brandingId:e.brandingId,handleId:t,teamId:e.teamId},er("deleteBrandSocialHandle",[e.brandingId??"default",t])))}catch(n){wt(n,"Social-account removal failed")}}),ic=new je("social").description("List, record, or remove the social accounts owned by a brand").addCommand(Gh).addCommand(Wh).addCommand(Kh);import{createHash as Jh}from"crypto";import{Command as ac}from"commander";var zh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Hh(t){zh.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Xh(t){return Jh("sha256").update(t).digest("hex").slice(0,32)}var sc=new ac("sync").description("Update linked decks from their brand; waits by default, versions decks, and prints JSON").argument("<brand-id>","Brand profile ID").option("--no-wait","Return a run ID; resume with `branding sync-status <run-id>`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Hh(t);let n={brandId:t,teamId:e.teamId};try{let r=await m("syncBrandToPresentations",n,Xh(`syncBrandToPresentations:${t}`));if(e.wait===!1){l(r);return}l(await ss(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Sync failed"),process.exit(d.GENERAL_ERROR)}}),dc=new ac("sync-status").description("Print linked-deck sync progress, terminal result, or error").argument("<run-id>","Run ID from `branding sync --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("syncBrandToPresentations",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}});import{readFile as Yh}from"fs/promises";import{randomUUID as Qh}from"crypto";import{Command as cc}from"commander";var Zh=["color.primary","color.background","color.text","color.secondary","color.accent","color.surface","color.link","typography.primary","typography.secondary","typography.h1","typography.h2","typography.h3","typography.h4","typography.h5","typography.h6","typography.paragraph","typography.button","typography.small","typography.label","typography.caption","asset.logo","asset.logo.dark","asset.favicon"];function ey(t){let e=t.split(".").filter(Boolean);for(let n=e.length;n>=2;n--){let r=e.slice(0,n).join(".");if(Zh.includes(r))return{fieldPath:e.slice(n),nodeKey:r}}return{fieldPath:e.slice(2),nodeKey:e.slice(0,2).join(".")}}function ty(t){let e={};for(let n of t){let r=n.indexOf("=");if(r<=0)throw new Error(`"${n}" is not a token assignment. Use key=value, e.g. color.primary=#114b97`);let o=n.slice(0,r).trim(),i=n.slice(r+1);if(o.split(".").filter(Boolean).length<2)throw new Error(`"${o}" is not a brand token key. Expected something like color.primary or typography.h1.size`);let{fieldPath:c,nodeKey:p}=ey(o),f=ny(i);if(c.length===0){e[p]=f;continue}let h=e[p],v=h&&typeof h=="object"&&!Array.isArray(h)?h:{},x=v;for(let $ of c.slice(0,-1)){let A=x[$],S=A&&typeof A=="object"&&!Array.isArray(A)?A:{};x[$]=S,x=S}x[c[c.length-1]]=f,e[p]=v}return e}function ny(t){return t==="true"?!0:t==="false"?!1:/^-?\d+(?:\.\d+)?$/.test(t)?Number(t):t}function ry(t,e){return t===void 0?{assignments:[...e]}:t.includes("=")?{assignments:[t,...e]}:{assignments:[...e],brandId:t}}var lc=new cc("profile").description("Read a brand's design tokens, the keys it is missing, or its design.md").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").option("--format <format>","tokens (default) or md").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{let n=await m("getBrandProfile",{brandId:t,format:e.format,teamId:e.teamId});if(e.format==="md"&&typeof n.designMd=="string"){console.log(n.designMd);return}l(n)}catch(n){a(n instanceof Error?n.message:"Profile read failed"),process.exit(d.GENERAL_ERROR)}}),mc=new cc("set").description("Write brand design tokens (key=value pairs or a design.md)").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").argument("[tokens...]","Token assignments, e.g. color.primary=#114b97 typography.h1.size=32px").option("--design-md <path>","Apply a whole design.md file instead").option("--no-publish","Stage the change without publishing a new active brand version").option("--team-id <id>","Workspace ID").option("--yes","Confirm writing brand data").action(async(t,e,n)=>{n.yes||(a("Pass --yes to confirm writing brand tokens."),process.exit(d.INVALID_INPUT));let{assignments:r,brandId:o}=ry(t,e),i;try{i=r.length>0?ty(r):void 0}catch(c){a(c instanceof Error?c.message:"Invalid token pair"),process.exit(d.INVALID_INPUT)}let s;if(n.designMd)try{s=await Yh(n.designMd,"utf8")}catch(c){a(`Could not read ${n.designMd}: ${c instanceof Error?c.message:String(c)}`),process.exit(d.INVALID_INPUT)}!i&&!s&&(a("Nothing to write. Pass token assignments (color.primary=#114b97) or --design-md <file>."),process.exit(d.INVALID_INPUT));try{l(await m("updateBrandTokens",{brandId:o,designMd:s,publish:n.publish===!1?!1:void 0,teamId:n.teamId,tokens:i},Qh()))}catch(c){a(c instanceof Error?c.message:"Write failed"),process.exit(d.GENERAL_ERROR)}});import{createHash as oy}from"crypto";import{Command as rr}from"commander";var iy=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,nr=["deck-16-9","reel-9-16","story-9-16","walkthrough-16-9"];function jo(t){iy.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function uc(t){return oy("sha256").update(t).digest("hex").slice(0,32)}function pc(t){if(nr.includes(t))return t;a(`"${t}" is not a channel. Pass one of: ${nr.join(", ")}.`),process.exit(d.INVALID_INPUT)}function tr(t){return t===""?null:t}function Uo(t,e){if(e==="")return null;let n;try{n=JSON.parse(e)}catch(r){a(`${t} is not valid JSON: ${r instanceof Error?r.message:String(r)}`),process.exit(d.INVALID_INPUT)}return(typeof n!="object"||n===null||Array.isArray(n))&&(a(`${t} must be a JSON object.`),process.exit(d.INVALID_INPUT)),n}function ay(t,e){if(e==="true")return!0;if(e==="false")return!1;a(`${t} takes "true" or "false", not "${e}".`),process.exit(d.INVALID_INPUT)}function sy(t){if(t==="")return null;let e=Number(t);return Number.isInteger(e)||(a(`--max-seconds takes a whole number of seconds, not "${t}".`),process.exit(d.INVALID_INPUT)),e}var dy=new rr("list").description("List a brand's per-channel design variants").argument("<brand-id>","Brand profile ID").option("--channel <key>",`One of: ${nr.join(", ")}`).option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),jo(t),e.channel!==void 0&&pc(e.channel);try{l(await m("listBrandVariants",{brandId:t,channelKey:e.channel,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"List failed"),process.exit(d.GENERAL_ERROR)}}),cy=new rr("set").description("Create or update one per-channel brand design variant").argument("<brand-id>","Brand profile ID").option("--variant <slug>","Variant slug; omit to create one with a new slug").option("--channel <key>",`One of: ${nr.join(", ")}`).option("--name <name>","Display name for the variant").option("--default <true|false>","Make this the channel's default, or drop the role").option("--colors <json>",`Palette as JSON, e.g. '{"primary":"#155DAC","background":"#FFFFFF","text":"#111111"}'`).option("--logo-treatment <json>",'Logo backdrop as JSON; pass "" to clear').option("--background-gradient <json>",'Gradient document as JSON; pass "" to clear').option("--aspect <ratio>",'Aspect ratio, e.g. 16:9; pass "" to clear').option("--max-seconds <seconds>",'Longest runtime in seconds; pass "" to clear').option("--voice-tone <tone>",'Voice tone override; pass "" to clear').option("--opening-style <style>",'Opening style; pass "" to clear').option("--logo-position <position>",'Logo position; pass "" to clear').option("--constraints <text>",'Generator constraints; pass "" to clear').option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),jo(t),e.channel!==void 0&&pc(e.channel);let n={brandId:t,teamId:e.teamId};e.variant!==void 0&&(n.variantId=e.variant),e.channel!==void 0&&(n.channelKey=e.channel),e.name!==void 0&&(n.name=e.name),e.default!==void 0&&(n.isDefault=ay("--default",e.default)),e.colors!==void 0&&(n.colors=Uo("--colors",e.colors)),e.logoTreatment!==void 0&&(n.logoTreatment=Uo("--logo-treatment",e.logoTreatment)),e.backgroundGradient!==void 0&&(n.backgroundGradient=Uo("--background-gradient",e.backgroundGradient)),e.aspect!==void 0&&(n.aspect=tr(e.aspect)),e.maxSeconds!==void 0&&(n.maxSeconds=sy(e.maxSeconds)),e.voiceTone!==void 0&&(n.voiceOverride=e.voiceTone===""?null:{tone:e.voiceTone}),e.openingStyle!==void 0&&(n.openingStyle=tr(e.openingStyle)),e.logoPosition!==void 0&&(n.logoPosition=tr(e.logoPosition)),e.constraints!==void 0&&(n.constraints=tr(e.constraints));try{l(await m("setBrandVariant",n,e.variant===void 0?void 0:uc(`setBrandVariant:${t}:${e.variant}:${JSON.stringify(n)}`)))}catch(r){a(r instanceof Error?r.message:"Set failed"),process.exit(d.GENERAL_ERROR)}}),ly=new rr("delete").description("Remove one per-channel brand design variant").argument("<brand-id>","Brand profile ID").option("--variant <slug>","Variant slug to remove").option("--team-id <id>","Workspace ID").option("--yes","Skip the confirmation prompt").action(async(t,e)=>{await y(),jo(t),e.variant===void 0&&(a("Pass --variant <slug> to name the variant to remove. `branding variant list <brand-id>` prints the slugs."),process.exit(d.INVALID_INPUT)),!e.yes&&process.stdin.isTTY&&(a(`Refusing to delete variant "${e.variant}" without confirmation. This delete is permanent \u2014 re-run with --yes.`),process.exit(d.GENERAL_ERROR));try{l(await m("deleteBrandVariant",{brandId:t,teamId:e.teamId,variantId:e.variant},uc(`deleteBrandVariant:${t}:${e.variant}`)))}catch(n){a(n instanceof Error?n.message:"Delete failed"),process.exit(d.GENERAL_ERROR)}}),gc=new rr("variant").description("Per-channel brand design variant commands").addCommand(dy).addCommand(cy).addCommand(ly);import{createHash as my}from"crypto";import{Command as Vo}from"commander";var uy=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,qo=["deck-16-9","reel-9-16","story-9-16","walkthrough-16-9"];function py(t){uy.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function gy(t){if(qo.includes(t))return t;a(`"${t}" is not a channel. Pass one of: ${qo.join(", ")}.`),process.exit(d.INVALID_INPUT)}function fy(t,e){let n;try{n=JSON.parse(e)}catch(r){a(`${t} is not valid JSON: ${r instanceof Error?r.message:String(r)}`),process.exit(d.INVALID_INPUT)}return(typeof n!="object"||n===null||Array.isArray(n))&&(a(`${t} must be a JSON object.`),process.exit(d.INVALID_INPUT)),n}function hy(t){return my("sha256").update(t).digest("hex").slice(0,32)}var yy=new Vo("generate").description("Generate a brand's per-channel design variants and gradients (replaces the previously generated set for the channel)").argument("[brand-id]","Brand profile ID; omit to generate a preview that is not saved").option("--channel <key>",`One of: ${qo.join(", ")}`).option("--name <name>","Brand name to generate against").option("--description <text>","What the brand is, as generator context").option("--tone <tone>","Tone hint, e.g. 'warm, confident'").option("--style <style>","Visual style hint, e.g. 'editorial, high contrast'").option("--colors <json>",`Palette as JSON, e.g. '{"primary":"#155DAC","background":"#FFFFFF","text":"#111111"}'. Required when no brand id is given.`).option("--no-wait","Return the run id immediately instead of waiting").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),t!==void 0&&py(t),e.channel!==void 0&&gy(e.channel);let n={teamId:e.teamId};t!==void 0&&(n.brandId=t),e.channel!==void 0&&(n.channelKey=e.channel),e.name!==void 0&&(n.brandName=e.name),e.description!==void 0&&(n.brandDescription=e.description),e.tone!==void 0&&(n.brandTone=e.tone),e.style!==void 0&&(n.brandStyle=e.style),e.colors!==void 0&&(n.sourceColors=fy("--colors",e.colors));try{let r=await m("generateBrandVariations",n,hy(`generateBrandVariations:${t??"preview"}:${e.channel??"deck-16-9"}`));if(e.wait===!1){l(r);return}l(await ns(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Generate failed"),process.exit(d.GENERAL_ERROR)}}),by=new Vo("status").description("Read a brand variations generation run").argument("<run-id>","Run ID from `branding variations generate --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("generateBrandVariations",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),fc=new Vo("variations").description("Generated brand design variations").addCommand(yy).addCommand(by);import{createHash as wy}from"crypto";import{Command as or}from"commander";var Mo=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Fo(t){Mo.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function vy(t,e){if(e==="head"||Mo.test(e))return e;a(`${t} must be a version id or "head".`),process.exit(d.INVALID_INPUT)}function Iy(t,e){if(Mo.test(e))return e;a(`${t} must be a version id from \`branding version list\`.`),process.exit(d.INVALID_INPUT)}function xy(t){return wy("sha256").update(t).digest("hex").slice(0,32)}var ky=new or("list").description("List a brand's published versions, newest first").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Fo(t);try{l(await m("listBrandVersions",{brandId:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"List failed"),process.exit(d.GENERAL_ERROR)}}),Ry=new or("diff").description("Compare two points in a brand's version history").argument("<brand-id>","Brand profile ID").option("--from <version-id>","Baseline version to compare against. Defaults to the brand's live version.").option("--to <version-id|head>","Version to compare. Defaults to head, the unpublished working draft.").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Fo(t);let n={brandId:t,teamId:e.teamId};e.from!==void 0&&(n.from=Iy("--from",e.from)),e.to!==void 0&&(n.to=vy("--to",e.to));try{l(await m("diffBrandVersions",n))}catch(r){a(r instanceof Error?r.message:"Diff failed"),process.exit(d.GENERAL_ERROR)}}),Cy=new or("publish").description("Publish the brand's working draft as a new live version").argument("<brand-id>","Brand profile ID").option("--label <text>","Short name for this version, unique within the brand (max 64 characters)").option("--notes <text>","What changed. Defaults to a changelog derived from the diff.").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Fo(t);let n={brandId:t,teamId:e.teamId};e.label!==void 0&&(n.label=e.label),e.notes!==void 0&&(n.notes=e.notes);try{l(await m("publishBrandVersion",n,xy(`publishBrandVersion:${t}:${e.label??"auto"}`)))}catch(r){a(r instanceof Error?r.message:"Publish failed"),process.exit(d.GENERAL_ERROR)}}),hc=new or("version").description("Brand version history commands").addCommand(ky).addCommand(Ry).addCommand(Cy);import{createHash as Sy}from"crypto";import{Command as rn}from"commander";var Ey=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Go(t){Ey.test(t)||(a(`"${t}" is not a brand id. Pass the UUID from \`branding list\`.`),process.exit(d.INVALID_INPUT))}function Bo(t,e=[]){return[...e,t]}function yc(t){return Sy("sha256").update(t).digest("hex").slice(0,32)}var $y=new rn("get").description("Read a brand's Voice & Context document").argument("<brand-id>","Brand profile ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Go(t);try{l(await m("getBrandVoice",{brandId:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Read failed"),process.exit(d.GENERAL_ERROR)}}),Ty=new rn("set").description("Write a brand's Voice & Context document").argument("<brand-id>","Brand profile ID").option("--positioning <text>","Positioning and promise").option("--voice-tone <text>","How the brand sounds").option("--authoritative-facts <text>","Facts generated content must never contradict").option("--approved-language <text>","Wording the brand endorses").option("--guardrails <text>","What the brand must never say or do").option("--sources <json>",`Provenance as JSON, e.g. '[{"kind":"url","name":"About page"}]'. Omitting this clears the recorded provenance.`).option("--replace","Acknowledge that this replaces the WHOLE document: sections you omit are removed. Required when the payload would drop a section the brand has.").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Go(t);let n={brandId:t,teamId:e.teamId};if(e.positioning!==void 0&&(n.positioning=e.positioning),e.voiceTone!==void 0&&(n.voiceTone=e.voiceTone),e.authoritativeFacts!==void 0&&(n.authoritativeFacts=e.authoritativeFacts),e.approvedLanguage!==void 0&&(n.approvedLanguage=e.approvedLanguage),e.guardrails!==void 0&&(n.guardrails=e.guardrails),e.replace===!0&&(n.replace=!0),e.sources!==void 0)try{n.sources=JSON.parse(e.sources)}catch{a("--sources must be valid JSON (an array of source objects)."),process.exit(d.INVALID_INPUT)}try{l(await m("setBrandVoice",n,yc(`setBrandVoice:${t}:${JSON.stringify(n)}`)))}catch(r){a(r instanceof Error?r.message:"Write failed"),process.exit(d.GENERAL_ERROR)}}),Ay=new rn("build").description("Draft a brand's Voice & Context document from source material").argument("<brand-id>","Brand profile ID").option("--url <url>","Page to read; repeat for several",Bo).option("--text <text>","Pasted source material; repeat for several",Bo).option("--file <name:source>","Document to read, as name:source; repeat for several",Bo).option("--no-wait","Return the run id immediately instead of waiting").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y(),Go(t);let n={brandId:t,teamId:e.teamId};e.url?.length&&(n.urls=e.url),e.text?.length&&(n.text=e.text),e.file?.length&&(n.files=e.file.map(r=>{let o=r.indexOf(":");return(o<=0||o===r.length-1)&&(a(`--file must be name:source; got "${r}".`),process.exit(d.INVALID_INPUT)),{name:r.slice(0,o),source:r.slice(o+1)}})),!e.url?.length&&!e.text?.length&&!e.file?.length&&(a("Pass at least one --url, --text or --file to draft from."),process.exit(d.INVALID_INPUT));try{let r=await m("buildBrandVoice",n,yc(`buildBrandVoice:${JSON.stringify(n)}`));if(e.wait===!1){l(r);return}l(await os(r.runId,e.teamId))}catch(r){a(r instanceof Error?r.message:"Build failed"),process.exit(d.GENERAL_ERROR)}}),Py=new rn("build-status").description("Read a brand voice build run").argument("<run-id>","Run ID from `branding voice build --no-wait`").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{l(await I("buildBrandVoice",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),bc=new rn("voice").description("Brand voice and context commands").addCommand($y).addCommand(Ty).addCommand(Ay).addCommand(Py);function Ly(t){return e=>{let n=Number(e);if(!Number.isInteger(n)||n<0)throw new wc(`${t} expects a whole number of 0 or more.`);return n}}function Uy(t){return e=>{let n=Number(e);if(!Number.isInteger(n)||n<1)throw new wc(`${t} expects a whole number of 1+.`);return n}}var jy=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,qy=50;function Vy(t){let e=t.extractedFrom??t.normalizedUrl??null,n=Lo(t),r=nc(t),o=_o(t);if(ge("Brand Profile"),console.log(),C("ID",t.id),C("Name",t.name),C("Source URL",e??F.gray("None")),C("Default",t.isDefault?F.green("Yes"):"No"),t.createdAt&&C("Created",new Date(t.createdAt).toLocaleString()),console.log(),n||r.length>0){if(console.log(F.bold(" Colors")),n&&console.log(` Primary: ${F.bgHex(n)(" ")} ${n}`),r.length>0){console.log(" Palette:");for(let h of r.slice(0,10)){let v=h.role?F.gray(` (${h.role})`):"";console.log(` ${F.bgHex(h.hex)(" ")} ${h.hex}${v}`)}}console.log()}o&&(console.log(F.bold(" Logo")),console.log(` ${o}`),console.log());let i=t.brandData?.typography,s=t.resolvedTokens?.headingFont??i?.primary??i?.headings,c=t.resolvedTokens?.bodyFont??i?.secondary??i?.body;(s||c)&&(console.log(F.bold(" Typography")),console.log(` Headings: ${s??"-"}`),console.log(` Body: ${c??"-"}`),console.log());let p=t.brandData?.confidence,f=t.brandData?.extractionMethod;(typeof p=="number"||typeof f=="string")&&(console.log(F.bold(" Extraction")),typeof p=="number"&&console.log(` Confidence: ${Math.round(p*100)}%`),typeof f=="string"&&console.log(` Method: ${f}`),console.log()),console.log(F.gray(" Use --format json for full details")),console.log()}var vc=new vt("branding").description("Read and manage workspace brands, design rules, assets, permissions, and social presence").addCommand(lc).addCommand(mc).addCommand(vd).addCommand(Gd).addCommand(Wd).addCommand(new vt("list").description("List accessible brands as a table or paged JSON").option("--search <text>","Filter by brand name or website/domain; an exact brand id also matches").option("--filter <filter>","Which slice to return (all, mine, team)",b("--filter",["all","mine","team"])).option("--sort <sort>","Sort key (created, name, updated)",b("--sort",["created","name","updated"])).option("--shape <shape>","Result shape: list (paged rows, default) or chat (compact matches)",b("--shape",["chat","list"])).option("--limit <n>","Page size (server default: 12 for the list shape, 50 for chat)",Uy("--limit")).option("--offset <n>","Brands to skip before the page",Ly("--offset")).option("--team-id <id>","Workspace ID").option("--json","Print the complete JSON response instead of a table").action(async t=>{await y();try{let e=t.shape??"list",n=await m("listBrandings",{filter:t.filter,limit:t.limit,offset:t.offset,search:t.search,shape:e,sort:t.sort,teamId:t.teamId});if(t.json){l(n);return}let r=rc(n);if(r.length===0){w("No brand profiles found"),console.log(),console.log(F.gray(`Create one with: ${u.commands[0]} branding extract <url>`));return}console.log(sa(r));let o=t.offset??0;No(n)?n.hasMore&&console.log(F.gray(` ${o+r.length} of ${n.total}. Next page: --offset ${o+r.length}`)):r.length>=(t.limit??qy)&&console.log(F.gray(` Showing ${r.length} from --offset ${o}; there may be more. Next page: --offset ${o+r.length}`))}catch(e){a(e instanceof Error?e.message:String(e)),process.exit(e.exitCode??1)}})).addCommand(new vt("get").description("Read one brand as a summary or complete JSON").argument("<id>","Brand profile ID").option("-f, --format <format>","Output format (summary, json)",b("--format",["summary","json"]),"summary").option("-o, --output <path>","Save JSON to file").option("--team-id <id>","Workspace ID").action(async(t,e)=>{if(await y(),!jy.test(t)){a(`"${t}" is not a brand id. Pass the UUID from \`${u.commands[0]} branding list\`, or search by name with \`${u.commands[0]} branding find <query>\`.`),process.exit(d.INVALID_INPUT);return}try{let r=(await m("listBrandings",{limit:1,search:t,shape:"list",teamId:e.teamId})).items?.[0];if(!r){a(`No brand profile with id ${t} is accessible.`),process.exit(d.NOT_FOUND);return}if(e.output){await Ny(e.output,JSON.stringify(r,null,2)),k(`Brand profile saved to ${e.output}`);return}if(e.format==="json"){console.log(JSON.stringify(r,null,2));return}Vy(r)}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new vt("find").description("Print matching brand IDs for an exact name, domain, or website URL").argument("<query>","Brand name or website URL to search for").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await y();try{let r=(await m("listBrandings",{search:t,shape:"chat",teamId:e.teamId})).brandings;if(r.length===0){w(`No brand profiles matching "${t}"`),console.log(F.gray(` Extract one with: ${u.commands[0]} branding extract <url>`));return}console.log(`Found ${r.length} brand${r.length>1?"s":""}:
72
+ `);for(let o of r){let i=o.primaryColor?`${F.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"";console.log(` ${F.bold(o.name)} ${F.gray(o.id)}`),o.domain&&console.log(` ${F.gray(o.domain)}`),i&&console.log(` ${i}`),console.log()}console.log(F.gray(` Export with: ${u.commands[0]} branding get <id> -o branding.json`))}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new vt("extract").description("Start paid website extraction and print a run ID for `branding status`").argument("<url>","Website URL to extract branding from").option("--team-id <id>","Workspace ID; defaults to your configured workspace").option("--yes","Confirm you intend to start a paid extraction. Intent only: approval still requires --approval-receipt").option("--approval-receipt <receipt>","Receipt from the browser confirmation URL; omit on the first call to be given that URL").option("--approval-receipt-stdin","Read the browser-issued approval receipt from stdin so it is not exposed in process arguments").option("--idempotency-key <key>","Stable key bound into the approval receipt; pass the same one when retrying with the receipt").option("--skip-existing-lookup","Extract this exact URL even when the workspace already has related brands").action(async(t,e)=>{await y(),e.yes||(a("Pass --yes to confirm brand extraction."),process.exit(d.INVALID_INPUT));try{new URL(t.startsWith("http")?t:`https://${t}`)}catch{a("Invalid URL format"),process.exit(6)}let n=t.startsWith("http")?t:`https://${t}`,r=e.teamId??ee(),o=e.idempotencyKey??Oy();e.approvalReceipt&&e.approvalReceiptStdin&&(a("Pass only one approval receipt input mode."),process.exit(d.INVALID_INPUT));let i=e.approvalReceiptStdin?Dy(0,"utf8").trim():e.approvalReceipt;e.approvalReceiptStdin&&!i&&(a("No approval receipt was provided on stdin."),process.exit(d.INVALID_INPUT));let s=_y({text:`Extracting branding from ${n}...`,stream:process.stdout}).start(),c;try{let p=await Oa(n,r,i,e.skipExistingLookup,o);if(p.status==="needs_choice"){s.stop(),w(`This workspace already has ${p.matches.length} related brand${p.matches.length===1?"":"s"} for ${n}. Nothing was extracted and nothing was charged.`),console.log();for(let f of p.matches)console.log(` ${F.bold(f.name??"Untitled")}`),console.log(` ${F.gray(f.id)}`),f.extractedFrom&&console.log(` ${F.gray(f.extractedFrom)}`);console.log(),w(`Use one of the above, or re-run with --skip-existing-lookup to extract ${n} anyway.`),c=d.INVALID_INPUT}else s.succeed("Brand extraction started"),console.log(JSON.stringify(p,null,2)),w(`Check progress with: ${u.commands[0]} branding status ${p.runId}`),console.log()}catch(p){let f=p instanceof Error?p.message:String(p);f.includes("approval")&&(s.stop(),a(f),console.log(),w(`Retry with the receipt and the same key: --approval-receipt <receipt> --idempotency-key ${o}`),process.exit(d.INVALID_INPUT)),s.fail("Extraction failed"),a(f),process.exit(p.exitCode??1)}c!==void 0&&process.exit(c)})).addCommand(new vt("status").description("Print a brand extraction run's current state, error, or result").argument("<run-id>","Run ID returned by branding extract").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await I("extractBranding",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}})).addCommand(Pd).addCommand(Ad).addCommand(Nd).addCommand(Od).addCommand(_d).addCommand(Ld).addCommand(Ud).addCommand(Dd).addCommand(oc).addCommand(jd).addCommand(xd).addCommand(kd).addCommand(Sd).addCommand(Zd).addCommand(gc).addCommand(fc).addCommand(hc).addCommand(bc).addCommand($d).addCommand(tc).addCommand(Kd).addCommand(Jd).addCommand(sc).addCommand(dc).addCommand(zd).addCommand(ic);import on from"chalk";import{Command as It}from"commander";function My(t){switch(t.background){case"color":{if(!t.backgroundColor)throw new Error("--background color needs --background-color <hex>, e.g. #1d4ed8");return{hex:t.backgroundColor,kind:"color"}}case"image":{if(!t.backgroundImage)throw new Error("--background image needs --background-image <url>");return{fit:t.fit,kind:"image",url:t.backgroundImage}}default:return{kind:t.background}}}function Ic(t,e){return{background:My(e),name:t,presenterProfileId:e.presenter,...e.voiceId?{voiceId:e.voiceId}:{}}}function ir(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.id);return}k(`${t.name} (${t.id})`),w(` Presenter: ${t.presenterProfileId}`),w(` Backdrop: ${Fy(t.background)}`),t.voiceId&&w(` Voice: ${t.voiceId}`)}function Fy(t){switch(t.kind){case"color":return`color ${t.hex}`;case"image":return`image ${t.url} (${t.fit})`;default:return t.kind}}function xc(t){return t.requiredOption("--presenter <profileId>",`Trained personal presenter id (pp_*), from \`${u.commands[0]} avatar options\``).option("--background <kind>","Backdrop: original, transparent, color, or image","original").option("--background-color <hex>","Backdrop color, e.g. #1d4ed8").option("--background-image <url>","Backdrop image URL").option("--fit <fit>","How an image backdrop fills the frame","cover").option("--voice-id <voiceId>","Workspace voice to save with this preset").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human")}var By=new It("list").description("List saved cast presets you can use").option("--cast-member-id <castMemberId>","Only this person's presets").option("--branding-id <brandingId>","Narrow to one brand").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{try{let e=await ds({...t.brandingId?{brandingId:t.brandingId}:{},...t.castMemberId?{castMemberId:t.castMemberId}:{}});if(t.format==="json"){l(e);return}if(t.format==="quiet"){for(let n of e.presets)console.log(n.id);return}if(e.presets.length===0){w("No presets saved yet.");return}for(let n of e.presets)ir(n,"human")}catch(e){a(e instanceof Error?e.message:String(e)),process.exit(d.API_ERROR)}}),Gy=xc(new It("create").description("Save one way a cast member appears").argument("<name>",'What to call this preset, e.g. "In the cafe"').requiredOption("--cast-member-id <castMemberId>","The person this preset is a way of showing")).action(async(t,e)=>{try{let n=await cs({castMemberId:e.castMemberId,...Ic(t,e)});ir(n.preset,e.format)}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(d.API_ERROR)}}),Wy=xc(new It("update").description("Change a saved preset (sends the complete preset)").argument("<presetId>","The preset to change").requiredOption("--name <name>","What to call it")).action(async(t,e)=>{try{let n=await ls({presetId:t,...Ic(e.name,e)});ir(n.preset,e.format)}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(d.API_ERROR)}}),Ky=new It("delete").description("Retire a saved preset. Existing videos keep working.").argument("<presetId>","The preset to retire").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await ms(t);if(e.format==="human"){k(`Retired "${n.preset.name}".`);return}ir(n.preset,e.format)}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(d.API_ERROR)}}),Jy=new It("preset").description("Saved ways a cast member appears").addCommand(By).addCommand(Gy).addCommand(Wy).addCommand(Ky),Wo=new It("cast").description("The faces and voices your videos can use").addCommand(Jy);Wo.addHelpText("after",`
73
+ ${on.bold("Examples:")}
74
+ ${on.gray("# List the saved presenter/backdrop/voice combinations")}
75
+ $ ${u.commands[0]} cast preset list
76
+
77
+ ${on.bold("See also:")}
78
+ ${on.gray("# The presenter avatars, looks, and voices a preset is built from")}
79
+ $ ${u.commands[0]} avatar options
80
+
81
+ ${on.gray("# Use a preset on one presentation-video scene")}
82
+ $ ${u.commands[0]} presentation video presenter <project-id>
83
+ `);import{readFile as zy}from"fs/promises";import an from"chalk";import{Command as kc}from"commander";var Hy=new kc("extract").description("Extract normalized text from a URL or local file").argument("<source>","URL, encoded source, or local file path").option("--team-id <id>","Workspace ID").option("--mime-type <type>","Source MIME type").option("--max-length <count>","Maximum output characters","30000").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=t,r;t.includes("://")||(n=await zy(t,"utf8"),r=t);let o=await m("extractContent",{filename:r,maxLength:Number.parseInt(e.maxLength,10),mimeType:e.mimeType,source:n,teamId:e.teamId});e.format!=="quiet"&&l(o)}catch(n){a(n instanceof Error?n.message:"Extraction failed"),process.exit(d.GENERAL_ERROR)}}),Ko=new kc("content").description("Extract normalized text from a URL, a local file, or an encoded document").addCommand(Hy);Ko.addHelpText("after",`
84
+ ${an.bold("Examples:")}
85
+ ${an.gray("# Normalized text from a local document")}
86
+ $ ${u.commands[0]} content extract ./paper.pdf
87
+
88
+ ${an.bold("See also:")}
89
+ ${an.gray("# Web pages, with page metadata and cost reporting")}
90
+ $ ${u.commands[0]} scrape https://example.com/post
91
+
92
+ ${an.gray("# Spoken words out of audio or video")}
93
+ $ ${u.commands[0]} transcript --help
94
+ `);import Q from"chalk";import{Command as Xy}from"commander";import{existsSync as Yy,readFileSync as Qy}from"fs";import Zy,{resolve as Rc}from"path";function Jo(t,e){if(e)try{let n=JSON.parse(e);if(!n||typeof n!="object"||Array.isArray(n))throw new Error("expected an object");return n}catch(n){throw new Error(`${t} must be a valid JSON object.`,{cause:n})}}function eb(t,e,n){if(t!=="as-is"||e)return e;let r=n.filter(o=>o.name.toLowerCase().endsWith(".pptx"));if(r.length!==1)throw new Error("--source-mode as-is requires exactly one uploaded .pptx file (or --source-presentation JSON).");return{filename:r[0].name,sourceUrl:r[0].url}}var Cc=new Xy("create").description("Create a new presentation").argument("<topic>","The topic or title for the presentation").option("-n, --slides <count>","Number of slides (1-20)").option("-m, --mode <mode>","Generation quality (best, balanced, fast, ultrafast, instant, image-min, image, image-max) \u2014 default: fast. image-min/image/image-max render each slide as a full-bleed AI image (text not editable); slower + pricier, require image-mode access, and cap at 25 slides. image-min is cheapest (brand colors only, no exact fonts).").option("--image-tier <tier>","Embedded-image quality for HTML modes. Each tier is a per-image credit ceiling as well as its price: quick (+20/slide), smart (default, +60/slide), balanced (+250/slide), best (+500/slide, slow). Ignored for image-*/instant modes.").option("-t, --tone <tone>","Tone (creative, professional, educational, formal, casual)").option("--amount <amount>","Content density (minimal, concise, detailed, extensive)").option("--audience <text>","Target audience description").option("--additional-context <text>","Additional generation instructions").option("--conversation-context <text>","Prior conversation context").option("-l, --language <lang>","Output language").option("--branding-id <id>","Branding ID (from `ccr branding list` or `ccr branding extract`)").option("--brand-domain <url>","Brand the deck by website/domain (e.g. https://www.pfizer.com). Errors if no matching saved brand exists.").option("--brand-enforcement <json>","Brand enforcement JSON object").option("--brand-variant-id <id>","Saved brand variant ID").option("--design-brand-reference <text>","Design brand reference").option("--family <family>","Layout family (minimal, editorial, bold, dashboard)",b("--family",["minimal","editorial","bold","dashboard"])).option("--generation-request-id <id>","Generation funnel correlation ID").option("--image-policy <policy>","Image policy (auto, none)",b("--image-policy",["auto","none"])).option("--content-sources <json>","Canonical content-sources JSON object").option("--source-mode <mode>","Attached deck mode (reference, as-is)",b("--source-mode",["reference","as-is"])).option("--source-presentation <json>","Attached PowerPoint JSON object with filename and sourceUrl").option("--widget-session-id <id>","Stable widget session ID").option("--template <id>","Slide template ID to style the deck after (from `ccr templates`). A default template is applied automatically when omitted.").option("-c, --context <text>","Inline text context (research notes, key facts)").option("--context-file <path>","Path to a context file (text, markdown, JSON)").option("--stdin","Read context from stdin").option("-f, --file <paths...>","Files to upload (PDF, PPTX, DOCX, images)").option("-g, --goal <type>","Goal (inform, persuade, train, learn, entertain, report)").option("--styling <mode>","Styling mode (freeform, brand-only, brand-plus-style, style-only, no-styling)").option("--reference-url <url>","Image URL to use as visual style reference").option("--thinking-depth <depth>","AI thinking depth (quick, moderate, deep, profound)").option("--theme <preset>","[instant mode only] Color theme preset (blue, violet, rose, orange, green)").option("--primary-color <hex>","[instant mode only] Primary color (e.g., #0066CC)").option("--secondary-color <hex>","[instant mode only] Secondary color").option("--accent-color <hex>","[instant mode only] Accent color").option("--background-color <hex>","[instant mode only] Background color").option("--foreground-color <hex>","[instant mode only] Foreground/text color").option("--decorations <style>","[instant mode only] Background decoration (none, waves-bottom-left, waves-top-right, blob-corners, minimal)").option("--team-id <id>","Team ID (switch teams)").option("--format <format>","Output format (human, json, quiet)",b("--format",["human","json","quiet"])).option("-o, --output <format>","Output format (human, json, quiet) \u2014 short form of --format",b("--output",["human","json","quiet"])).option("--no-stream","Wait for completion without streaming progress").option("--wait","Poll until generation completes").option("--idempotency-key <key>","Stable retry key").option("--approval-receipt <receipt>","Server-issued approval receipt for this exact generation request").option("--debug","Enable debug logging").option("--open","Open in browser after creation").option("--id <uuid>","Use a specific UUID for the presentation").option("--studio","Studio mode: use current directory name as presentation ID (auto-links to Studio preview)").action(async(t,e)=>{e.output=e.format??e.output,await y();let n=e.idempotencyKey??z({command:"presentation:create",payload:{...e,approvalReceipt:void 0,idempotencyKey:void 0,topic:t},workspaceId:e.teamId??"configured-default"}),r;e.slides!==void 0&&(r=parseInt(e.slides,10),(Number.isNaN(r)||r<1||r>20)&&(a("Slide count must be between 1 and 20"),process.exit(6)));let o=["best","balanced","fast","ultrafast","instant","image-min","image","image-max"];e.mode&&!o.includes(e.mode)&&(a(`Invalid mode: ${e.mode}. Valid: ${o.join(", ")}`),process.exit(6));let i=["smart","fast","balanced","best"];e.imageTier&&!i.includes(e.imageTier)&&(a(`Invalid image tier: ${e.imageTier}. Valid: ${i.join(", ")}`),process.exit(6));let s=["creative","professional","educational","formal","casual"];e.tone&&!s.includes(e.tone)&&(a(`Invalid tone: ${e.tone}. Valid: ${s.join(", ")}`),process.exit(6));let c=["minimal","concise","detailed","extensive"];e.amount&&!c.includes(e.amount)&&(a(`Invalid amount: ${e.amount}. Valid: ${c.join(", ")}`),process.exit(6));let p=["freeform","brand-only","brand-plus-style","style-only","no-styling"];e.styling&&!p.includes(e.styling)&&(a(`Invalid styling: ${e.styling}. Valid: ${p.join(", ")}`),process.exit(6));let f=["quick","moderate","deep","profound"];e.thinkingDepth&&!f.includes(e.thinkingDepth)&&(a(`Invalid thinking-depth: ${e.thinkingDepth}. Valid: ${f.join(", ")}`),process.exit(6));let h=["inform","persuade","train","learn","entertain","report"];e.goal&&!h.includes(e.goal)&&(a(`Invalid goal: ${e.goal}. Valid: ${h.join(", ")}`),process.exit(6));let v=["blue","violet","rose","orange","green"];e.theme&&!v.includes(e.theme)&&(a(`Invalid theme: ${e.theme}. Valid: ${v.join(", ")}`),process.exit(6));let x=["none","waves-bottom-left","waves-top-right","blob-corners","minimal"];e.decorations&&!x.includes(e.decorations)&&(a(`Invalid decorations: ${e.decorations}. Valid: ${x.join(", ")}`),process.exit(6));let $=e.theme||e.primaryColor||e.secondaryColor||e.accentColor||e.backgroundColor||e.foregroundColor||e.decorations;$&&e.mode&&e.mode!=="instant"&&(a("--theme, --primary-color, --decorations and other color options are only supported with --mode instant"),process.exit(6));let A=e.mode??($?"instant":"fast"),S=/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;for(let[P,ue]of[["primary-color",e.primaryColor],["secondary-color",e.secondaryColor],["accent-color",e.accentColor],["background-color",e.backgroundColor],["foreground-color",e.foregroundColor]])ue&&!S.test(ue)&&(a(`Invalid ${P}: ${ue}. Must be hex (e.g., #0066CC)`),process.exit(6));try{e.output!=="json"&&e.output!=="quiet"&&process.stdout.write(Q.gray("Checking generation limits... "));let P=await _a(A,r??10,e.teamId);if(e.output!=="json"&&e.output!=="quiet"){console.log(Q.green("\u2713"));let ue=P.remaining[A],ae=P.limits[A],pe=ue===void 0||ae===void 0?"":` | ${A}: ${ue}/${ae} remaining`;console.log(Q.gray(` Plan: ${P.planName}${pe}`))}}catch(P){e.output==="json"?console.log(JSON.stringify({success:!1,error:P instanceof Error?P.message:String(P)})):(console.log(Q.red("\u2717")),a(P instanceof Error?P.message:String(P))),process.exit(P.exitCode??1)}let T=[];if(e.file&&e.file.length>0){for(let P of e.file)Yy(Rc(P))||(a(`File not found: ${P}`),process.exit(6));e.output!=="json"&&e.output!=="quiet"&&console.log(Q.gray(`
95
+ Uploading ${e.file.length} file(s)...`));try{T=await xa(e.file.map(P=>Rc(P)),(P,ue,ae)=>{e.output!=="json"&&e.output!=="quiet"&&ae&&process.stdout.write(`\r ${Q.cyan("\u2B06")} Uploading: ${ae} (${P+1}/${ue})`)},{idempotencyKey:n}),e.output!=="json"&&e.output!=="quiet"&&console.log(`\r ${Q.green("\u2713")} Uploaded ${T.length} file(s) `)}catch(P){a(`Failed to upload files: ${P instanceof Error?P.message:String(P)}`),process.exit(1)}}let E;(e.stdin||!process.stdin.isTTY)&&(E=await tb(),e.stdin&&!E&&(a("No content received from stdin"),process.exit(6)));let M=e.context;if(e.contextFile)try{M=Qy(e.contextFile,"utf-8"),M.trim()||(a(`Context file is empty: ${e.contextFile}`),process.exit(6))}catch{a(`Failed to read context file: ${e.contextFile}`),process.exit(6)}!E&&!M&&!e.additionalContext&&!e.contentSources&&!e.sourcePresentation&&T.length===0&&(a("Context is required to create a presentation."),console.log(),console.log(Q.gray(" -f, --file <paths...> Upload files (PDF, PPTX, images)")),console.log(Q.gray(" -c, --context <text> Inline text context")),console.log(Q.gray(" --context-file <path> Read from a file")),console.log(Q.gray(` cat file | ${u.commands[0]} Pipe content`)),process.exit(6));let N=[...T];E&&N.push({id:`stdin-${n}`,content:E,title:"Piped Content",mime:"text/plain",selected:!0}),M&&N.push({id:`context-${n}`,content:M,title:"Context",mime:"text/plain",selected:!0});let O,Y=e.primaryColor||e.secondaryColor||e.accentColor||e.backgroundColor||e.foregroundColor;(e.theme||Y||e.decorations)&&(O={},e.theme&&(O.preset=e.theme),Y&&(O.custom={},e.primaryColor&&(O.custom.primary=e.primaryColor),e.secondaryColor&&(O.custom.secondary=e.secondaryColor),e.accentColor&&(O.custom.accent=e.accentColor),e.backgroundColor&&(O.custom.background=e.backgroundColor),e.foregroundColor&&(O.custom.foreground=e.foregroundColor)),e.decorations&&(O.decorations=e.decorations));try{let P=Jo("--content-sources",e.contentSources),ue=eb(e.sourceMode,Jo("--source-presentation",e.sourcePresentation),T),ae=await ka({topic:t,...e.additionalContext&&{additionalContext:e.additionalContext},...r!==void 0&&{slideCount:r},mode:A,...e.imageTier&&{imageTier:e.imageTier},...e.tone&&{tone:e.tone},...e.amount&&{amount:e.amount},...e.audience&&{audience:e.audience},...e.language&&{language:e.language},...e.brandingId&&{brandingId:e.brandingId},...e.brandDomain&&{brandDomain:e.brandDomain},...e.brandEnforcement&&{brandEnforcement:Jo("--brand-enforcement",e.brandEnforcement)},...e.brandVariantId&&{brandVariantId:e.brandVariantId},...e.conversationContext&&{conversationContext:e.conversationContext},...e.designBrandReference&&{designBrandReference:e.designBrandReference},...e.family&&{family:e.family},...e.generationRequestId&&{generationRequestId:e.generationRequestId},...e.imagePolicy&&{imagePolicy:e.imagePolicy},...e.template&&{templateId:e.template},...e.styling&&{stylingMode:e.styling},...e.referenceUrl&&{referenceUrl:e.referenceUrl},...e.thinkingDepth&&{thinkingDepth:e.thinkingDepth},...e.goal&&{goal:e.goal},...e.teamId&&{teamId:e.teamId},...e.sourceMode&&{sourceMode:e.sourceMode},...ue&&{sourcePresentation:ue},...e.widgetSessionId&&{widgetSessionId:e.widgetSessionId},...O&&{theme:O},...e.studio?{documentId:Zy.basename(process.cwd())}:e.id?{documentId:e.id}:{},...P?{contentSources:P}:N.length>0&&{contentSources:{uploadedFiles:N,contextFiles:[]}}},n,e.approvalReceipt);if(!e.wait){e.output==="json"?console.log(JSON.stringify({success:!0,run:ae},null,2)):e.output!=="quiet"&&(k("Presentation generation queued"),C("Run ID",ae.runId),C("Status",ae.status),console.log(Q.gray(` Check later with presentation status ${ae.runId}`)));return}let pe=await I("createSlides",ae.runId,e.teamId);for(;!pe.done;)e.output!=="json"&&e.output!=="quiet"&&console.log(Q.gray(` ${pe.message}`)),await new Promise(Mt=>setTimeout(Mt,(pe.nextPollAfterSeconds??5)*1e3)),pe=await I("createSlides",ae.runId,e.teamId);if(pe.error)throw new Error(se(pe.error));let We=pe.entity?await dt(pe.entity.id):void 0;if(e.output==="json")console.log(JSON.stringify({success:!0,presentation:We,run:pe,viewUrl:We?at(We.slug,e.language??"en"):void 0},null,2));else{console.log(),k("Presentation created successfully"),console.log(),C("Title",We?.title??t),C("Slides",String(We?.numberOfSlides??r??"\u2014")),console.log();let Mt=We?at(We.slug,e.language??"en"):"N/A";Mt!=="N/A"&&(console.log(Q.bold(" Open: ")+Q.cyan.underline(Mt)),e.open&&await(await import("open")).default(Mt)),console.log()}}catch(P){e.output==="json"?console.log(JSON.stringify({success:!1,error:P instanceof Error?P.message:String(P),...P.errorCode==="approval_required"?{idempotencyKey:n}:{}})):(P.errorCode==="approval_required"&&C("Idempotency key",n),a(P instanceof Error?P.message:String(P))),process.exit(P.exitCode??1)}});async function tb(){return new Promise(t=>{let e="";if(process.stdin.setEncoding("utf8"),process.stdin.isTTY){t("");return}process.stdin.on("data",n=>{e+=n}),process.stdin.on("end",()=>{t(e.trim())}),setTimeout(()=>{t(e.trim())},100)})}import{Command as Ho}from"commander";function zo(t,e){let n=Number(t);return(!Number.isInteger(n)||n<0)&&(a(`${e} must be a whole number`),process.exit(d.GENERAL_ERROR)),n}var nb=new Ho("activity").description("List credit spend grouped by the artifact it was spent on").option("--limit <count>","How many groups to return (default 20)").option("--offset <count>","How many groups to skip").option("--team-id <id>","Workspace ID").action(async t=>{try{l(await m("listCreditActivity",{limit:t.limit===void 0?void 0:zo(t.limit,"--limit"),offset:t.offset===void 0?void 0:zo(t.offset,"--offset"),teamId:t.teamId}))}catch(e){a(e instanceof Error?e.message:"Reading credit activity failed"),process.exit(d.GENERAL_ERROR)}}),rb=new Ho("trace").description("List every credit charge inside one activity group").argument("[group-id]","Artifact or chat ID the group is keyed on; omit only with --group-type ungrouped").option("--group-type <type>","artifact (default), chat, or ungrouped").option("--limit <count>","How many charges to return (default 100)").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("getCreditActivityGroup",{groupId:t,groupType:e.groupType,limit:e.limit===void 0?void 0:zo(e.limit,"--limit"),teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Reading the credit activity group failed"),process.exit(d.GENERAL_ERROR)}}),Sc=new Ho("credits").description("Credit spend reporting").addCommand(nb).addCommand(rb);import{randomUUID as ob}from"crypto";import{readFile as ib}from"fs/promises";import{Command as qe}from"commander";var Xo=["text/markdown","text/csv","text/plain"];async function Ec(t){let e=t.content;if(e!==void 0&&e!=="-"&&!e.startsWith("@"))return e;if(e?.startsWith("@"))return ib(e.slice(1),"utf8");if(e==="-"||!process.stdin.isTTY)return ab();a("No document body. Pass --content <text>, --content @<path>, or pipe it on stdin."),process.exit(d.GENERAL_ERROR)}async function ab(){let t=[];for await(let e of process.stdin)t.push(Buffer.from(e));return Buffer.concat(t).toString("utf8")}function ar(t){return`cli:document:${t}:${ob()}`}function Ze(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}function sb(t){if(!t)return;let e=t.split(".").pop()?.toLowerCase();if(e==="md"||e==="markdown")return"text/markdown";if(e==="csv")return"text/csv";if(e==="txt")return"text/plain"}var db=new qe("create").description("Save a document into the Library").argument("<title>","Document title").option("--team-id <id>","Workspace ID").option("--content <text>","Document body: literal text, @<path> to read a file, or '-' for stdin").option("--media-type <type>",`One of ${Xo.join(", ")}; inferred from an @<path> body when omitted`).option("--summary <text>","One line for the Library card").action(async(t,e)=>{try{let n=e.mediaType??sb(e.content?.startsWith("@")?e.content.slice(1):void 0);n||(a(`Cannot tell what this document is. Pass --media-type (${Xo.join(", ")}).`),process.exit(d.GENERAL_ERROR)),l(await m("createDocument",{content:await Ec(e),mediaType:n,summary:e.summary,teamId:e.teamId,title:t},ar("create")))}catch(n){Ze(n,"Could not save the document")}}),cb=new qe("list").description("List the workspace's documents, newest first").option("--team-id <id>","Workspace ID").option("--media-type <type>",`Filter to one of ${Xo.join(", ")}`).option("--limit <n>","Maximum documents to return (default 50)").action(async t=>{try{l(await m("listDocuments",{limit:t.limit?Number(t.limit):void 0,mediaType:t.mediaType,teamId:t.teamId}))}catch(e){Ze(e,"Could not list documents")}}),lb=new qe("read").description("Print a document's body").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{let n=await m("readDocument",{documentId:t,teamId:e.teamId}),{document:r}=n;process.stderr.write(`${r.title} \xB7 ${r.mediaType} \xB7 v${r.version} \xB7 ${r.byteLength} bytes
96
+ `),process.stdout.write(r.content)}catch(n){Ze(n,"Could not read the document")}}),mb=new qe("update").description("Edit a document under an optimistic lock").argument("<document-id>","Document id").requiredOption("--expected-version <n>","The version you last read; the edit is rejected if it has moved on").option("--team-id <id>","Workspace ID").option("--content <text>","New body: literal text, @<path> to read a file, or '-' for stdin").option("--title <text>","New title").option("--summary <text>","New Library-card summary").option("--change-summary <text>","What changed, recorded on the version").action(async(t,e)=>{try{let n=e.content!==void 0;l(await m("updateDocument",{changeSummary:e.changeSummary,content:n?await Ec(e):void 0,documentId:t,expectedVersion:Number(e.expectedVersion),summary:e.summary,teamId:e.teamId,title:e.title},ar("update")))}catch(n){Ze(n,"Could not update the document")}}),ub=new qe("delete").description("Remove a document from the Library").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").option("--yes","Skip the confirmation prompt").action(async(t,e)=>{try{!e.yes&&process.stdin.isTTY&&(a("Refusing to delete without confirmation. Re-run with --yes to remove this document."),process.exit(d.GENERAL_ERROR)),l(await m("deleteDocument",{documentId:t,teamId:e.teamId},ar("delete")))}catch(n){Ze(n,"Could not delete the document")}}),pb=new qe("versions").description("List a document's version history").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("listDocumentVersions",{documentId:t,teamId:e.teamId}))}catch(n){Ze(n,"Could not list versions")}}),gb=new qe("restore").description("Restore an earlier version by appending it as the current one").argument("<document-id>","Document id").requiredOption("--version-number <n>","The historical version to restore").requiredOption("--expected-version <n>","The version you last read; the restore is rejected if it has moved on").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("restoreDocumentVersion",{documentId:t,expectedVersion:Number(e.expectedVersion),teamId:e.teamId,versionNumber:Number(e.versionNumber)},ar("restore")))}catch(n){Ze(n,"Could not restore the version")}}),$c=new qe("document").description("Create, read and edit Library documents").addCommand(db).addCommand(cb).addCommand(lb).addCommand(mb).addCommand(ub).addCommand(pb).addCommand(gb);import sn from"chalk";import{Command as fb}from"commander";import{writeFile as hb}from"fs/promises";import{resolve as Tc}from"path";import yb from"ora";var bb=["html","pdf","pptx"],Yo=new fb("export").description("Export a presentation to a local HTML, PDF or PPTX file").argument("<id-or-slug>","Presentation slug, presentation ID or document ID").option("-o, --output <path>","Output file path").option("-f, --format <format>","Export format: html, pdf, pptx",b("--format",bb),"html").option("--team-id <id>","Workspace ID (uses configured default)").action(async(t,e)=>{await y();let n=yb("Exporting presentation...").start();try{let r=e.teamId??ee();if(!r)throw new Error("Team ID required. Set one with 'mf config set team-id <id>' or pass --team-id.");let o=await $a(t,e.format,{teamId:r}),i=e.output?Tc(e.output):Tc(process.cwd(),o.fileName);n.text="Downloading...";let s=await Ta(o.downloadUrl);await hb(i,Buffer.from(s)),n.succeed("Export complete!"),console.log(),w(`File saved: ${i}`),w(`Format: ${o.format}`),w(`Slides: ${o.slideCount}`),w(`Size: ${wb(s.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),a(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function wb(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}Yo.addHelpText("after",`
97
+ ${sn.bold("Examples:")}
98
+ ${sn.gray("# Self-contained interactive HTML (default)")}
99
+ $ ${u.commands[0]} export <id-or-slug> -o deck.html
100
+
101
+ ${sn.gray("# PDF or PowerPoint")}
102
+ $ ${u.commands[0]} export <id-or-slug> -f pdf -o deck.pdf
103
+ $ ${u.commands[0]} export <id-or-slug> -f pptx -o deck.pptx
104
+
105
+ ${sn.bold("See also:")}
106
+ ${sn.gray("# For an MP4 instead")}
107
+ $ ${u.commands[0]} presentation video <id-or-slug>
108
+ `);import{Command as we}from"commander";var vb=new we("create").description("Create a transcript-native footage edit project").requiredOption("--title <title>","Project title").requiredOption("--source <asset-ids...>","Analyzed source recording IDs").requiredOption("--strategy <json>","Editorial strategy JSON object").requiredOption("--ranges <json>","Selected ranges JSON array").requiredOption("--outputs <json>","Output variants JSON array").option("--overlays <json>","Overlay JSON array","[]").option("--music-asset-id <id>","Music media asset ID").option("--source-chat-id <id>","Source chat ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async t=>{await Ve("createFootageProject",{input:{musicAssetId:t.musicAssetId??null,outputs:dn(t.outputs,"outputs"),overlays:dn(t.overlays,"overlays"),ranges:dn(t.ranges,"ranges"),sourceAssetIds:t.source,sourceChatId:t.sourceChatId,strategy:dn(t.strategy,"strategy"),teamId:t.teamId,title:t.title},idempotencyKey:t.idempotencyKey})}),Ib=new we("show").description("Read a footage project and its append-only versions").argument("<project-id>","Project ID or slug").option("--version-id <id>","Historical version ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Ve("getFootageProject",{input:{projectId:t,teamId:e.teamId,versionId:e.versionId}})}),xb=new we("revise").description("Append a semantic footage draft revision").argument("<project-id>","Project ID or slug").requiredOption("--base-version-id <id>","Current version ID").requiredOption("--change-summary <text>","Human-readable change summary").option("--title <title>","Replacement title").option("--strategy <json>","Replacement strategy JSON object").option("--ranges <json>","Replacement ranges JSON array").option("--outputs <json>","Replacement outputs JSON array").option("--overlays <json>","Replacement overlays JSON array").option("--music-asset-id <id-or-null>","Replacement music asset ID or null").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Ve("reviseFootageProject",{input:Oc({baseVersionId:e.baseVersionId,changeSummary:e.changeSummary,musicAssetId:e.musicAssetId==="null"?null:e.musicAssetId,outputs:sr(e.outputs,"outputs"),overlays:sr(e.overlays,"overlays"),projectId:t,ranges:sr(e.ranges,"ranges"),strategy:sr(e.strategy,"strategy"),teamId:e.teamId,title:e.title}),idempotencyKey:e.idempotencyKey})}),kb=new we("restore").description("Restore a historical footage version as a new head").argument("<project-id>","Project ID or slug").argument("<version-id>","Historical version ID").option("--change-summary <text>","Change summary","Restored version").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{await Ve("restoreFootageProjectVersion",{input:{changeSummary:n.changeSummary,projectId:t,teamId:n.teamId,versionId:e},idempotencyKey:n.idempotencyKey})}),Rb=new we("branch").description("Branch a historical footage version into a new project").argument("<project-id>","Source project ID or slug").argument("<version-id>","Historical version ID").requiredOption("--title <title>","New project title").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{await Ve("branchFootageProjectVersion",{input:{projectId:t,teamId:n.teamId,title:n.title,versionId:e},idempotencyKey:n.idempotencyKey})}),Cb=new we("inspect").description("Create proxy, filmstrip, and waveform evidence for one range").argument("<project-id>","Project ID or slug").argument("<range-id>","Stable range ID").requiredOption("--version-id <id>","Exact version ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{await Ve("inspectFootageRange",{input:{projectId:t,rangeId:e,teamId:n.teamId,versionId:n.versionId},idempotencyKey:n.idempotencyKey})}),Sb=new we("inspection-status").description("Read a footage range inspection run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Pc("inspectFootageRange",t,e.teamId)}),Eb=new we("render").description("Render an exact approved footage draft version").argument("<project-id>","Project ID or slug").requiredOption("--version-id <id>","Exact version ID").option("--output <ids...>","Output IDs; omit to render every output").requiredOption("--approval-receipt <receipt>","Browser-issued approval receipt").requiredOption("--idempotency-key <key>","Key bound into the receipt").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Ve("renderFootageProject",{input:Oc({approvalReceipt:e.approvalReceipt,outputIds:e.output,projectId:t,teamId:e.teamId,versionId:e.versionId}),idempotencyKey:e.idempotencyKey})}),$b=new we("render-status").description("Read a Footage Studio render run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Pc("renderFootageProject",t,e.teamId)}),Tb=new we("import-takes").description("Import all completed takes from a clipping invocation").argument("<project-id>","Project ID or slug").requiredOption("--invocation-id <id>","cc-services clipping invocation ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{await Ve("importFootageProviderTakes",{input:{invocationId:e.invocationId,projectId:t,teamId:e.teamId}})}),Ac=new we("footage").description("Create, inspect, revise, and render transcript-native footage edits").addCommand(vb).addCommand(Ib).addCommand(xb).addCommand(kb).addCommand(Rb).addCommand(Cb).addCommand(Sb).addCommand(Eb).addCommand($b).addCommand(Tb);async function Ve(t,e){try{l(await m(t,e.input,e.idempotencyKey))}catch(n){a(n instanceof Error?n.message:"Footage operation failed"),process.exit(d.GENERAL_ERROR)}}async function Pc(t,e,n){try{l(await I(t,e,n))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}function dn(t,e){try{return JSON.parse(t)}catch{throw new Error(`${e} must be valid JSON.`)}}function sr(t,e){return typeof t=="string"?dn(t,e):void 0}function Oc(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}import{Command as Ab}from"commander";import et from"chalk";function Pb(t){return new Set((t??"").split(",").map(e=>e.trim().toLowerCase()).filter(Boolean))}function Ob(t){if(!t)throw new Error("Slides were requested but the server returned none. Retry, or read the deck in the browser.");ge("Slides"),console.log();for(let e of t){console.log(et.bold(` ${e.number}. ${e.title||"Untitled"}`));let n=e.text?.trim();console.log(n?Dc(n):et.gray(" (no text on this slide \u2014 image or empty)"));let r=e.speakerNotes?.trim();r&&(console.log(et.gray(" Narration/notes:")),console.log(et.gray(Dc(r)))),console.log()}}function Dc(t){return t.split(`
109
+ `).map(e=>` ${e}`).join(`
110
+ `)}var Nc=new Ab("get").description("Get presentation details").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --format <format>","Output format (summary, full, json)",b("--format",["summary","full","json"]),"summary").option("--include <fields>","Legacy fields list (comma-separated: slides,styling)").option("--include-slides","Include ordered slide content",!0).option("--no-include-slides","Omit slide content for a smaller response").option("-l, --language <lang>","Language for view URL","en").option("--team-id <id>","Workspace ID (uses configured default)").action(async function(t,e){await y();try{let n=this.getOptionValueSource("includeSlides")==="cli"?e.includeSlides:this.getOptionValueSource("include")==="cli"?Pb(e.include).has("slides"):!0,r=e.teamId??ee();if(!r)throw new Error("Team ID required. Set one with 'mf config set team-id <id>' or pass --team-id.");let o=await dt(t,{includeSlides:n,teamId:r});if(e.format==="json"){console.log(JSON.stringify(o,null,2));return}let i=at(o.slug,e.language);ge("Presentation Details"),console.log(),C("Slug",o.slug),C("Title",o.title||"Untitled"),C("Description",o.description||et.gray("None")),C("Slides",String(o.numberOfSlides||"-")),C("Mode",o.mode||"-"),C("Created",Fr(o.createdAt)),o.updatedAt&&C("Updated",Fr(o.updatedAt)),console.log(),i!=="N/A"&&console.log(et.bold(" Open: ")+et.cyan.underline(i)),console.log(),n&&Ob(o.slides)}catch(n){a(n instanceof Error?n.message:String(n));let r=n&&typeof n=="object"&&"exitCode"in n&&typeof n.exitCode=="number"?n.exitCode:1;process.exit(r)}});import{randomUUID as Db}from"crypto";import{Command as cr}from"commander";import Nb from"ora";function _b(t){let e=t?.trim().toLowerCase();if(!(!e||e==="any"||e==="all"))return e==="web"||e==="stock"?[e]:void 0}function Lb(t){let e=t.assetType??"image";if(e!=="image"&&e!=="icon")throw new Error("Asset type must be image or icon");let n;if(t.maxResults&&(n=Number.parseInt(t.maxResults,10),Number.isNaN(n)||n<1))throw new Error("Max results must be a positive number");return{query:e==="icon"?`${t.query.trim()} transparent icon isolated symbol`:t.query.trim(),options:{maxResults:n||10,size:t.size,safeSearch:t.safeSearch,assetType:e,sources:_b(t.source),transparentBackground:e==="icon"}}}function Ub(t){let e=t.url||t.imageUrl;if(!e)throw new Error("Image search returned a result without a URL");return e}function jb(t){return t.transparent??t.isTransparent??t.metadata?.transparent??t.metadata?.isTransparent}function qb(t){let e=[],n=t.reduce((r,o)=>Math.max(r,o.length),0);for(let r=0;r<n;r+=1)for(let o of t){let i=o[r];i!==void 0&&e.push(i)}return e}function Vb(t,e){let n=t.data.results.map(r=>r.results.map(o=>{let i=o,s=jb(i);if(e==="icon"&&s!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:Ub(i),provider:r.providerName,assetType:e,...s!==void 0?{transparent:s}:{}}}));return qb(n)}function Mb(t){return t.error||t.status==="failed"||t.status==="errored"||t.status==="cancelled"?"failed":t.done||t.status==="completed"?"completed":t.status==="in_progress"?"processing":"pending"}function dr(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Fb(t){return{requestId:t.runId,status:Mb(t),...t.entity?.url?{url:t.entity.url}:{},...t.error?{error:se(t.error)}:{},...dr(t.output?.width)!==void 0?{width:dr(t.output?.width)}:{},...dr(t.output?.height)!==void 0?{height:dr(t.output?.height)}:{}}}async function _c(t,e){return Fb(await I("createImage",t,e))}function Qo(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.output??t.url??t.requestId);return}w(`Request ID: ${t.requestId}`),w(`Status: ${t.status}`),t.url&&k(`Image URL: ${t.url}`),t.output&&k(`Saved to: ${t.output}`),t.error&&a(`Error: ${t.error}`)}var Bb=new cr("search").description("Search images across the web and licensed stock").requiredOption("-q, --query <query>","Search query").option("-n, --max-results <number>","Maximum number of results (default: 10)").option("-s, --size <size>","Image size: small, medium, large, any","large").option("--asset-type <type>","Asset intent: image or transparent icon","image").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--safe-search","Enable safe search (default: true)",!0).option("--no-safe-search","Disable safe search").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.format,n=e==="human"?Nb("Searching for images...").start():null,r;try{r=Lb(t)}catch(o){n?.stop(),a(o instanceof Error?o.message:"Invalid image search request"),process.exit(d.INVALID_INPUT);return}try{let o=await Ma(r);n?.stop(),o.success||(a("Search failed"),process.exit(d.GENERAL_ERROR));let i=r.options?.assetType??"image",s=Vb(o,i);if(e==="json"){l({success:!0,query:t.query,assetType:i,totalResults:s.length,images:s});return}if(e==="quiet"){for(let c of s)console.log(c.url);return}if(s.length===0){w("No images found");return}k(`Found ${s.length} images for "${t.query}"`),console.log();for(let c=0;c<s.length;c++){let p=s[c];console.log(`[${c+1}] ${p.title||"Untitled"}`),console.log(` URL: ${p.url}`),console.log(` Size: ${p.width}x${p.height}`),p.author&&console.log(` Author: ${p.author}`),console.log(` Provider: ${p.provider}`),console.log()}}catch(o){n?.stop(),a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Gb=new cr("generate").description("Generate an image and optionally save it locally").argument("[prompt]","Image prompt").option("-p, --prompt <text>","Image prompt (named compatibility form)").option("--provider <provider>","Provider override").option("--model <model>","Model override").option("--purpose <purpose>","Explicit image intent: general, draft, infographic, brand-max, or vector; omitted means general",b("--purpose",["general","draft","infographic","brand-max","vector"])).option("--width <pixels>","Width").option("--height <pixels>","Height").option("--team-id <id>","Workspace ID").option("--reference-image <label=path-or-url...>","Image the generation must follow: a local file (uploaded for you, never resized) or a public HTTP(S) URL. Repeatable. Prefix an optional label, e.g. identity=./face.jpg, style=https://\u2026/mood.png. Fidelity depends on the routed model: the auto-routed one returns a similar-looking subject, while --provider google-ai --model gemini-3-pro-image returns the same person \u2014 but that pin takes effect only on workspaces holding the internal image-model-override flag").option("--idempotency-key <key>","Stable retry key for this generation and its reference uploads").option("-o, --output <path>","Local output path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("--yes","Approve generation").action(async(t,e)=>{let n,r=t??e.prompt;r?.trim()||(a("Provide an image prompt as an argument or with --prompt"),process.exit(d.INVALID_INPUT)),e.yes||(a("Pass --yes to approve image generation"),process.exit(d.INVALID_INPUT)),!e.wait&&e.output&&(a("--output requires waiting for completion; remove --no-wait"),process.exit(d.INVALID_INPUT)),(e.provider||e.model)&&_("--provider/--model are honoured only for workspaces holding the internal image-model-override flag. Without it the server drops them and routes the request itself.",e.format),e.referenceImage?.length&&!e.model&&_("Reference images without --model route to a light model that returns a similar-looking, not identical, subject. A recognisable likeness needs --provider google-ai --model gemini-3-pro-image on a workspace with the image-model-override flag.",e.format);let o=e.idempotencyKey??Db();try{let i=await Gn(e.referenceImage,{idempotencyKey:o,rejectNonImageFiles:!0}),s=await m("createImage",{approvalReceipt:"cli:--yes",height:e.height?Number.parseInt(e.height,10):void 0,model:e.model,prompt:r.trim(),provider:e.provider,...e.purpose?{purpose:e.purpose}:{},...i?{referenceImages:i}:{},teamId:e.teamId,width:e.width?Number.parseInt(e.width,10):void 0},o);if(n=s.runId,!e.wait){Qo({requestId:s.runId,status:"pending"},e.format);return}let c=await ce(()=>_c(s.runId,e.teamId),180,2e3);if(c.status==="failed")throw new Error(c.error||"Image generation failed");if(!c.url)throw new Error("Image generation completed without an image URL");let p=e.output?{...c,output:e.output}:c;e.output&&await te(c.url,e.output),Qo(p,e.format)}catch(i){a(fe(i,n),e.format),process.exit(d.GENERAL_ERROR)}}),Wb=new cr("status").description("Read image generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Download a completed image").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await _c(t,e.teamId);if(e.output){if(n.status!=="completed"||!n.url)throw new Error("Image generation is not complete");await te(n.url,e.output),n.output=e.output}Qo(n,e.format)}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Lc=new cr("image").description("Image search and generation commands").addCommand(Bb).addCommand(Gb).addCommand(Wb);import{Command as Zo}from"commander";var Kb=new Zo("search").description("Search the workspace Knowledge Hub").argument("[query]","Optional search query").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").option("--limit <count>","Maximum results","10").action(async(t,e)=>{try{l(await m("searchKnowledge",{kind:e.kind,limit:Number.parseInt(e.limit,10),query:t,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Knowledge search failed"),process.exit(d.GENERAL_ERROR)}}),Jb=new Zo("bundle").description("Read a bounded Open Knowledge Format bundle").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").action(async t=>{try{l(await m("getKnowledgeBundle",{kind:t.kind,teamId:t.teamId}))}catch(e){a(e instanceof Error?e.message:"Knowledge bundle failed"),process.exit(d.GENERAL_ERROR)}}),Uc=new Zo("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(Kb).addCommand(Jb);import{randomUUID as zb}from"crypto";import lr from"chalk";import{Command as Oe}from"commander";function ei(t){if(t!==void 0)return t==="root"?null:t}function xt(t){return`cli:library:${t}:${zb()}`}function tt(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}var Hb=new Oe("list").description("List the Library folder tree").option("--team-id <id>","Workspace ID").option("--counts","Include how many items are in each folder").action(async t=>{try{l(await m("listLibraryFolders",{includeEntryCounts:!!t.counts,teamId:t.teamId}))}catch(e){tt(e,"Could not list folders")}}),Xb=new Oe("create").description("Create a Library folder").argument("<name>","Folder name").option("--team-id <id>","Workspace ID").option("--parent <id>","Parent folder id; omit for a top-level folder").option("--color <color>","Colour token (slate, blue, green, amber, red, violet)").action(async(t,e)=>{try{l(await m("createLibraryFolder",{color:e.color,name:t,parentId:ei(e.parent),teamId:e.teamId},xt("create")))}catch(n){tt(n,"Could not create the folder")}}),Yb=new Oe("rename").description("Rename a Library folder").argument("<folder-id>","Folder id").argument("<name>","New name").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{try{l(await m("renameLibraryFolder",{folderId:t,name:e,teamId:n.teamId},xt("rename")))}catch(r){tt(r,"Could not rename the folder")}}),Qb=new Oe("recolor").description("Set or clear a Library folder's colour").argument("<folder-id>","Folder id").requiredOption("--color <color>","Colour token (slate, blue, green, amber, red, violet), or 'none' to clear").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("recolorLibraryFolder",{color:e.color==="none"?null:e.color,folderId:t,teamId:e.teamId},xt("recolor")))}catch(n){tt(n,"Could not recolour the folder")}}),Zb=new Oe("move").description("Move a Library folder under a new parent").argument("<folder-id>","Folder id").requiredOption("--to <id>","New parent folder id, or 'root' for top level").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("moveLibraryFolder",{folderId:t,newParentId:ei(e.to),teamId:e.teamId},xt("move")))}catch(n){tt(n,"Could not move the folder")}}),ew=new Oe("delete").description("Delete a folder and its subfolders; items inside are unfiled").argument("<folder-id>","Folder id").requiredOption("--yes","Confirm deletion").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("deleteLibraryFolder",{folderId:t,teamId:e.teamId},xt("delete")))}catch(n){tt(n,"Could not delete the folder")}}),tw=new Oe("folders").description("Manage Library folders").addCommand(Hb).addCommand(Xb).addCommand(Yb).addCommand(Qb).addCommand(Zb).addCommand(ew),nw=new Oe("file").description("File an artifact into a Library folder").argument("<kind>","Artifact kind, e.g. presentation or microsite").argument("<target-id>","Id of the artifact itself").requiredOption("--folder <id>","Destination folder id, or 'root' to unfile the artifact").option("--team-id <id>","Workspace ID").action(async(t,e,n)=>{try{l(await m("fileArtifactIntoFolder",{folderId:ei(n.folder),kind:t,targetId:e,teamId:n.teamId},xt("file")))}catch(r){tt(r,"Could not file that item")}}),ti=new Oe("library").description("Library folders and filing").addCommand(tw).addCommand(nw);ti.addHelpText("after",`
111
+ ${lr.bold("Examples:")}
112
+ ${lr.gray("# Browse the folder tree and file an artifact into a folder")}
113
+ $ ${u.commands[0]} library folders list
114
+ $ ${u.commands[0]} library file presentation <id> --folder <folder-id>
115
+
116
+ ${lr.bold("See also:")}
117
+ ${lr.gray("# A different thing: reusable video clips, not Library folders")}
118
+ $ ${u.commands[0]} video library --help
119
+ `);import{Command as cn}from"commander";function R(t,e){let n={...e},r=t.parent,o=!1;for(;r;){let i=r.opts?.();if(i){o=!0;for(let[s,c]of Object.entries(i))n[s]===void 0&&c!==void 0&&(n[s]=c)}r=r.parent}return o?n:e}var jc=new cn("analyze").description("Transcribe an uploaded recording and publish it for generation").argument("<asset-id>","Recording ID").option("--language <code>","BCP-47 language hint for the spoken audio").option("--no-diarize","Skip speaker attribution (cheaper, but a multi-speaker recording becomes much weaker as generation input)").option("--team-id <id>","Workspace ID").option("--yes","Confirm the charge \u2014 billed per source-minute").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to confirm. Analysis is billed per minute of source audio.");try{l(await m("analyzeMediaAsset",{assetId:t,diarize:e.diarize,language:e.language,teamId:e.teamId}))}catch(n){a(n instanceof Error?n.message:"Analysis failed"),process.exit(d.GENERAL_ERROR)}}),rw=new cn("status").description("Read an analysis run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(t,e){let n=R(this,e);try{l(await I("analyzeMediaAsset",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}});jc.addCommand(rw);var qc=new cn("import").description("Import a recording from a connected account").argument("<remote-file-id>","The provider's own ID for the recording").requiredOption("--provider <id>","Provider id of the connected account, e.g. google").requiredOption("--connector <id>","Connected account ID to read from").option("--title <title>","Name for the imported recording").option("--chat <id>","Chat this import was requested from").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("importConnectorRecording",{connectorId:e.connector,providerId:e.provider,remoteFileId:t,sourceChatId:e.chat,teamId:e.teamId,title:e.title}))}catch(n){a(n instanceof Error?n.message:"Import failed"),process.exit(d.GENERAL_ERROR)}}),ow=new cn("status").description("Read an import run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(t,e){let n=R(this,e);try{l(await I("importConnectorRecording",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}});qc.addCommand(ow);var Vc=new cn("media").description("Ingest and transcribe recordings you already own").addCommand(jc).addCommand(qc);import{Command as ni}from"commander";var iw=new ni("create").description("Start background microsite generation").argument("<title>","Microsite title").requiredOption("--description <brief>","Microsite brief").option("--audience <audience>","Target audience").option("--tone <tone>","Tone").option("--language <language>","Content language","en").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to approve generation");try{l(await m("createMicrosite",{approvalReceipt:"cli:--yes",audience:e.audience,brandingId:e.brandingId,description:e.description,language:e.language,teamId:e.teamId,title:t,tone:e.tone}))}catch(n){a(n instanceof Error?n.message:"Generation failed"),process.exit(d.GENERAL_ERROR)}}),aw=new ni("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await I("createMicrosite",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Mc=new ni("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(iw).addCommand(aw);import{Command as ii}from"commander";import ri from"ora";function oi(t,e){if(e==="json"){l(t);return}if(e==="quiet"){t.outputUrl?console.log(t.outputUrl):console.log(t.requestId);return}w(`Request ID: ${t.requestId}`),w(`Status: ${t.status}`),t.duration&&w(`Duration: ${t.duration}s`),t.outputUrl&&k(`Output URL: ${t.outputUrl}`),t.error&&a(`Error: ${t.error}`)}var sw=new ii("create").description("Mix audio tracks into a video (music will loop to match video duration)").requiredOption("--video <url>","Input video file/URL").option("--music <url>","Background music file/URL (will loop if shorter than video)").option("--voice <url>","Voiceover file/URL").option("--music-volume <percent>","Music volume 0-100 (default: 30, recommended for mix with voice)","30").option("--voice-volume <percent>","Voice volume 0-100","100").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{!t.music&&!t.voice&&(a("At least one of --music or --voice must be provided"),process.exit(d.INVALID_INPUT));let e=parseInt(t.musicVolume,10)/100,n=parseInt(t.voiceVolume,10)/100;(Number.isNaN(e)||e<0||e>1)&&(a("Music volume must be between 0 and 100"),process.exit(d.INVALID_INPUT)),(Number.isNaN(n)||n<0||n>2)&&(a("Voice volume must be between 0 and 200"),process.exit(d.INVALID_INPUT));let r=t.format,o=r==="human"?ri("Mixing audio...").start():null,i=[{url:t.video,role:"video"}];t.music&&i.push({url:t.music,role:"background",volume:e*5}),t.voice&&i.push({url:t.voice,role:"voice",volume:n*2});try{let s=await Va({operation:"add-to-video",inputs:i,options:{musicVolume:e,voiceVolume:n}});if(!t.wait){o?.stop(),oi(s,r);return}o&&(o.text=`Processing (ID: ${s.requestId})...`);let c=await ce(()=>eo(s.requestId),120,3e3);if(o?.stop(),c.status==="failed"&&(a(c.error||"Audio mixing failed"),process.exit(d.GENERAL_ERROR)),oi(c,r),t.output){if(!c.outputUrl)throw new Error("Audio mix completed without an output URL");let p=r==="human"?ri("Downloading...").start():null;await te(c.outputUrl,t.output),p?.stop(),r==="human"&&k(`Saved to: ${t.output}`)}}catch(s){o?.stop(),a(s instanceof Error?s.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),dw=new ii("status").description("Check status of an audio mix request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{let n=e.format==="human"?ri("Checking status...").start():null;try{let r=await eo(t);n?.stop(),oi(r,e.format)}catch(r){n?.stop(),a(r instanceof Error?r.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Fc=new ii("mix").description("Audio mixing commands").addCommand(sw).addCommand(dw);import{Command as si}from"commander";import fw from"ora";import{readFileSync as cw}from"fs";var Bc=500,Gc=1e4,mr=100,Wc=1e4,Kc=1e3,zc=["duration_s","idempotency_key","narration","schema_version","video_description"],lw=["end_s","id","start_s","text","words"],mw=["end","id","start","text"],uw=["description","end_s","id","start_s"];function Hc(t){let e=Yc(t);if(Qc(e),ln(e,zc,""),e.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return e}function Xc(t){let e=Yc(t);Qc(e),ln(e,[...zc,"visual_event"],"");let n=e.visual_event;if(!ur(n))throw new Error("SFX request visual_event is required");if(ln(n,uw,"visual_event"),!Me(n.description))throw new Error("SFX request visual_event.description is required");if(!Me(n.id)||!Fe(n.start_s))throw new Error("SFX request visual_event requires id and start_s");if(n.end_s!==void 0&&(!Fe(n.end_s)||n.end_s<n.start_s))throw new Error("SFX request visual_event.end_s must be after start_s");return e}function Yc(t){try{let e=JSON.parse(cw(t,"utf8"));if(!ur(e))throw new Error("request must be a JSON object");return e}catch(e){throw new Error(`Cannot read audio request ${t}: ${e instanceof Error?e.message:String(e)}`)}}function Qc(t){if(t.schema_version!==1)throw new Error("Audio request schema_version must be 1");if(!Me(t.video_description))throw new Error("Audio request video_description is required");if(!Fe(t.duration_s)||t.duration_s<.5||t.duration_s>600)throw new Error("Audio request duration_s must be between 0.5 and 600");if(!Array.isArray(t.narration))throw new Error("Audio request narration must be an array");if(t.narration.length>Bc)throw new Error(`Audio request narration holds at most ${Bc} lines`);if(t.narration.forEach(pw),t.idempotency_key!==void 0&&!Me(t.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function pw(t,e){let n=`narration.${e}`;if(!ur(t))throw new Error(`Audio request ${n} must be an object`);if(ln(t,lw,n),!Me(t.id)||t.id.length>mr)throw new Error(`Audio request ${n}.id is required (1-${mr} characters)`);if(!Me(t.text)||t.text.trim().length>Wc)throw new Error(`Audio request ${n}.text is required (1-${Wc} characters)`);if(Jc(t.start_s,`${n}.start_s`),Jc(t.end_s,`${n}.end_s`),Fe(t.start_s)&&Fe(t.end_s)&&t.end_s<t.start_s)throw new Error(`Audio request ${n}.end_s must be greater than or equal to ${n}.start_s`);if(t.words!==void 0){if(!Array.isArray(t.words)||t.words.length>Gc)throw new Error(`Audio request ${n}.words must be an array of at most ${Gc} entries`);t.words.forEach((r,o)=>{gw(r,`${n}.words.${o}`)})}}function gw(t,e){if(!ur(t))throw new Error(`Audio request ${e} must be an object`);if(ln(t,mw,e),!Me(t.text)||t.text.trim().length>Kc)throw new Error(`Audio request ${e}.text is required (1-${Kc} characters)`);if(!Fe(t.start)||!Fe(t.end))throw new Error(`Audio request ${e} requires numeric start and end seconds`);if(t.end<t.start)throw new Error(`Audio request ${e}.end must be greater than or equal to ${e}.start`);if(t.id!==void 0&&(!Me(t.id)||t.id.length>mr))throw new Error(`Audio request ${e}.id must be 1-${mr} characters`)}function Jc(t,e){if(t!==void 0&&!Fe(t))throw new Error(`Audio request ${e} must be a non-negative number`)}function ln(t,e,n){let r=Object.keys(t).filter(i=>!e.includes(i));if(r.length===0)return;let o=n?`${n} `:"";throw new Error(`Audio request ${o}has unknown field(s): ${r.join(", ")}. Allowed: ${e.join(", ")}`)}function ur(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function Me(t){return typeof t=="string"&&t.trim().length>0}function Fe(t){return typeof t=="number"&&Number.isFinite(t)&&t>=0}function ai(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.audioUrl??t.requestId);return}w(`Request ID: ${t.requestId}`),w(`Status: ${t.status}`),t.duration&&w(`Duration: ${t.duration}s`),t.audioUrl&&k(`Audio URL: ${t.audioUrl}`),t.error&&a(`Error: ${t.error}`)}var hw=new si("generate").description("Generate music that follows a video's narration and final timing").requiredOption("--request <path>","JSON file with video description, narration, and final timing").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{!t.wait&&t.output&&(a("--output requires waiting for completion; remove --no-wait"),process.exit(d.INVALID_INPUT));let e;try{e=Hc(t.request)}catch(i){a(i instanceof Error?i.message:String(i)),process.exit(d.INVALID_INPUT)}let n=t.format,r=n==="human"?fw("Generating music for video...").start():null,o;try{let i=await qa(e);if(o=i.requestId,!t.wait){r?.stop(),ai(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let s=i.status==="completed"||i.status==="failed"?i:await ce(()=>Zr(i.requestId),180,2e3);if(r?.stop(),s.status==="failed"&&(a(s.error||"Music generation failed"),process.exit(d.GENERAL_ERROR)),t.output){if(!s.audioUrl)throw new Error("Music completed without an audio URL");await te(s.audioUrl,t.output),n==="human"&&k(`Saved to: ${t.output}`),s.output=t.output}ai(s,n)}catch(i){r?.stop(),a(fe(i,o),n),process.exit(d.GENERAL_ERROR)}}),yw=new si("status").description("Check status of a music generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{ai(await Zr(t),e.format)}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Zc=new si("music").description("Video-aware music generation commands").addCommand(hw).addCommand(yw);import{Command as di}from"commander";function el(t,e){return[...e,t]}var bw=new di("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",el,[]).option("--type <type>","single, multiple, or word-cloud","single").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve creation").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to approve poll creation");try{l(await m("createPoll",{approvalReceipt:"cli:--yes",options:e.option.map(n=>({text:n})),pollType:e.type,question:t,teamId:e.teamId,title:e.title}))}catch(n){a(n instanceof Error?n.message:"Poll creation failed"),process.exit(d.GENERAL_ERROR)}}),ww=new di("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",el).option("--type <type>","single, multiple, or word-cloud").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve update").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to approve poll update");try{l(await m("editPoll",{approvalReceipt:"cli:--yes",options:e.option?.map(n=>({text:n})),pollId:t,pollType:e.type,question:e.question,teamId:e.teamId,title:e.title}))}catch(n){a(n instanceof Error?n.message:"Poll update failed"),process.exit(d.GENERAL_ERROR)}}),tl=new di("poll").description("Standalone poll commands").addCommand(bw).addCommand(ww);import{randomUUID as Ir}from"crypto";import{readFile as jl}from"fs/promises";import V from"chalk";import{Command as G,InvalidArgumentError as Ii}from"commander";import{randomUUID as li}from"crypto";import{readFile as vw}from"fs/promises";import{Command as pr}from"commander";var nl=new pr("edit").description("Apply one atomic draft edit: narration, scene patch/move/remove, composition, or intro/outro card").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--edit <json-or-path>","Edit object as inline JSON or a JSON file path").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e){let n=R(this,e);await gr("Draft edit failed",async()=>m("editPresentationVideoDraft",{edit:await Iw(n.edit),projectId:t,teamId:n.teamId},n.idempotencyKey??li()))}),rl=new pr("versions").description("List saved presentation-video draft versions").argument("<project-id>","Presentation-video project UUID or editor slug").option("--before-version <number>","Continue below this version number",ci(1)).option("--limit <number>","Maximum versions",ci(1,100)).option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await gr("Version list failed",()=>m("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:t,teamId:n.teamId}))}),ol=new pr("restore").description("Restore a saved draft version as a new version").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<version-number>","Version number",ci(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e,n){let r=R(this,n);await gr("Version restore failed",()=>m("restorePresentationVideoVersion",{projectId:t,teamId:r.teamId,versionNumber:e},r.idempotencyKey??li()))}),il=new pr("refresh").description("Refresh deck-backed scenes from the latest presentation version").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e){let n=R(this,e);await gr("Slide refresh failed",()=>m("refreshPresentationVideoSlides",{projectId:t,teamId:n.teamId},n.idempotencyKey??li()))});async function Iw(t){let e=t.trim(),n=e.startsWith("{")?e:await vw(e,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--edit must contain one JSON object.");return r}function ci(t,e=Number.MAX_SAFE_INTEGER){return n=>{let r=Number(n);if(!Number.isInteger(r)||r<t||r>e)throw new Error(`Expected an integer between ${t} and ${e}.`);return r}}async function gr(t,e){try{l(await e())}catch(n){a(n instanceof Error?n.message:t),process.exit(d.GENERAL_ERROR)}}import{createHash as xw}from"crypto";import{Command as kt,InvalidArgumentError as kw}from"commander";var al=new kt("drafts").description("List every video draft for one presentation with stage and staleness").argument("<presentation-id>","Source presentation ID, document ID, or slug").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await Rt("Draft list failed",()=>m("listPresentationVideoProjects",{presentationId:t,teamId:n.teamId}))}),sl=new kt("freshness").description("Check whether a video draft is behind its source deck without changing it").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await Rt("Freshness read failed",()=>m("getPresentationVideoFreshness",{projectId:t,teamId:n.teamId}))}),dl=new kt("version").description("Read one saved draft snapshot without restoring it").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<version-number>","Saved version number",ul(1)).option("--team-id <id>","Workspace ID override").action(async function(t,e,n){let r=R(this,n);await Rt("Version read failed",()=>m("getPresentationVideoVersion",{projectId:t,teamId:r.teamId,versionNumber:e}))}),cl=new kt("renders").description("List MP4 render attempts newest first, including failures").argument("<project-id>","Presentation-video project UUID or editor slug").option("--limit <number>","Maximum render attempts; omit to return the complete history",ul(1)).option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await Rt("Render history failed",()=>m("listPresentationVideoRenders",{limit:n.limit,projectId:t,teamId:n.teamId}))}),ll=new kt("render").description("Read one render's exact snapshot, status, progress, and MP4 URL").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<render-id>","Render attempt UUID from `presentation video renders`").option("--team-id <id>","Workspace ID override").action(async function(t,e,n){let r=R(this,n);await Rt("Render read failed",()=>m("getPresentationVideoRender",{projectId:t,renderId:e,teamId:r.teamId}))}),ml=new kt("cancel").description("Request cancellation of one in-flight MP4 DurableRun").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<render-id>","In-flight render attempt UUID").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; deterministically derived from both IDs when omitted").action(async function(t,e,n){let r=R(this,n);await Rt("Render cancellation failed",()=>m("cancelPresentationVideoRender",{projectId:t,renderId:e,teamId:r.teamId},r.idempotencyKey??Rw(t,e)))});function ul(t,e=Number.MAX_SAFE_INTEGER){return n=>{let r=Number(n);if(!Number.isInteger(r)||r<t||r>e)throw new kw(`Expected an integer between ${t} and ${e}.`);return r}}function Rw(t,e){return`presentation-video-cancel:${xw("sha256").update(`${t}\0${e}`).digest("hex")}`}async function Rt(t,e){try{l(await e())}catch(n){a(n instanceof Error?n.message:t),process.exit(d.GENERAL_ERROR)}}import{randomUUID as Sw}from"crypto";import{Command as un}from"commander";import{existsSync as Cw}from"fs";var pl=["bottom-left","bottom-right","top-left","top-right","left-half","right-half","left-overlay","right-overlay","full"];function Ct(t){let[e,n]=t.split(":");if(e==="background")return{kind:"background"};if(e==="full")return{kind:"full"};if(e==="split"){if(n!=="left"&&n!=="right")throw new Error("--placement split needs a side: split:left or split:right.");return{kind:"split",side:n}}if(e==="box"){if(!n||!pl.includes(n))throw new Error(`--placement box needs an anchor: box:${pl.join(" | box:")}.`);return{kind:"box",placement:{anchor:n}}}throw new Error("--placement must be background, split:left, split:right, full, or box:<anchor>.")}function fr(t){if(t.wholeScene&&t.duration!==void 0)throw new Error("--whole-scene and --duration ask for opposite things; pass only one.");let e=t.duration!==void 0||t.start!==void 0||t.wholeScene===!0;if(t.startWord!==void 0){if(e)throw new Error("--start-word replaces --start, --duration and --whole-scene; pass words or seconds, not both.");if(t.clearAnchor)throw new Error("--start-word and --clear-anchor ask for opposites.");if(t.endWord!==void 0&&t.endWord<t.startWord)throw new Error("--end-word must not come before --start-word.");return{anchor:{...t.endWord!==void 0?{endWord:t.endWord}:{},startWord:t.startWord}}}if(t.endWord!==void 0)throw new Error("--end-word needs --start-word.");if(!(!e&&!t.clearAnchor))return{...t.clearAnchor?{anchor:null}:{},...t.wholeScene?{durationSec:null}:t.duration!==void 0?{durationSec:t.duration}:{},...t.start!==void 0?{startSec:t.start}:{}}}function nt(t){return e=>{let n=Number(e);if(!Number.isInteger(n)||n<0)throw new Error(`${t} must be a 0-based narration word index (0, 1, 2, \u2026).`);return n}}function mn(t){let e=t.split(",").map(n=>n.trim()).filter(Boolean);if(e.length===0)throw new Error("Provide at least one scene id.");return e}function ke(t){return e=>{let n=Number(e);if(!Number.isFinite(n)||n<0)throw new Error(`${t} must be a number of seconds.`);return n}}async function hr(t,e={}){if(t.startsWith("https://"))return{url:t};if(t.startsWith("http://"))throw new Error("A layer image URL must use https.");if(Cw(t))return{uploadKey:(await de(t,{idempotencyKey:e.idempotencyKey,storagePrefix:"scene-layers"})).s3Key};if(yl(t))return{mediaAssetId:t};throw new Error("--image must be a local file path, an https image URL, or a media-library asset UUID.")}var yr=["brand","alert"],mi="::",gl=";;";function gi(t){if([t.textTitle,t.textCallout,t.textList].filter(r=>r!==void 0).length>1)throw new Error("Pass only one of --text-title, --text-callout or --text-list; each one is a whole card.");let n=pi(t.tone);if(t.textTitle!==void 0)return{heading:ui(t.textTitle,"--text-title"),tone:n,variant:"title"};if(t.textCallout!==void 0){let[r,o]=fl(t.textCallout,mi);return{...o?.trim()?{body:o.trim()}:{},heading:ui(r,"--text-callout"),tone:n,variant:"callout"}}if(t.textList!==void 0){let[r,o]=fl(t.textList,mi),i=(o??"").split(gl).map(s=>s.trim()).filter(Boolean);if(i.length===0)throw new Error(`--text-list needs a heading and its points: --text-list "Heading${mi}first${gl}second".`);return{heading:ui(r,"--text-list"),items:i,tone:n,variant:"list"}}if(t.tone!==void 0)throw new Error("--tone describes a text layer; pass it with --text-title, --text-callout or --text-list.")}function hl(t){let e=gi({...t,tone:void 0});return e?{body:e.body??null,heading:e.heading,items:e.items??null,...t.tone!==void 0?{tone:pi(t.tone)}:{},variant:e.variant}:t.tone===void 0?void 0:{tone:pi(t.tone)}}function pi(t){if(t===void 0)return"brand";if(t!=="alert"&&t!=="brand")throw new Error(`--tone must be ${yr.join(" or ")}.`);return t}function ui(t,e){let n=(t??"").trim();if(!n)throw new Error(`${e} needs the text to show.`);return n}function fl(t,e){let n=t.indexOf(e);return n<0?[t,void 0]:[t.slice(0,n),t.slice(n+e.length)]}function yl(t){return/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t)}function fi(t){try{return fr(t)}catch(e){a(e instanceof Error?e.message:"Invalid layer timing."),process.exit(d.INVALID_INPUT)}}function bl(t){try{return t()}catch(e){a(e instanceof Error?e.message:"Invalid layer text."),process.exit(d.INVALID_INPUT)}}async function br(t,e){try{l(await e())}catch(n){a(n instanceof Error?n.message:t),process.exit(d.GENERAL_ERROR)}}function wr(t,e,n){return m("editPresentationVideoDraft",{edit:n,projectId:t,teamId:e.teamId},e.idempotencyKey??Sw())}var Ew=new un("add").description("Add one timed layer to one or more scenes").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--scenes <ids>","Comma-separated composition scene ids").option("--video <id>","Reusable library video id").option("--media <id>","Media-library asset id (image or video)").option("--image <file-or-url>","Local image file to upload, or an https image URL").option("--slide <scene-id>","Reuse the image already on that deck scene").option("--text-title <line>","Words on a brand card: one loud line").option("--text-callout <heading::body>",'Words on a brand card: a heading over a paragraph, e.g. "Lockout first::Isolate the source."').option("--text-list <heading::a;;b;;c>","Words on a brand card: a heading over up to three points").option("--tone <tone>",`Text card colour: ${yr.join(" | ")}`).option("--placement <placement>","background | split:left | split:right | full | box:<anchor> (default background; required for a text layer, which cannot use background)").option("--start <seconds>","Seconds from the scene's first frame",ke("--start")).option("--duration <seconds>","Seconds shown; omit for the whole scene",ke("--duration")).option("--start-word <index>","Start on this narration word (0-based); replaces --start/--duration",nt("--start-word")).option("--end-word <index>","Last narration word shown (inclusive); omit for the whole scene",nt("--end-word")).option("--label <text>",'Studio label, e.g. "Right way"').option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e){let n=R(this,e),r=bl(()=>gi(n));[n.video,n.media,n.image,n.slide,r].filter(s=>s!==void 0).length!==1&&(a("Pass exactly one of --video, --media, --image, --slide, --text-title, --text-callout or --text-list."),process.exit(d.INVALID_INPUT)),r&&n.placement===void 0&&(a("A text layer needs --placement: split:left, split:right, full, or box:<anchor>. It cannot use background, where words paint under the scrim."),process.exit(d.INVALID_INPUT));let i=fi(n);await br("Layer add failed",async()=>{let s=r?{text:r}:n.video?{videoId:n.video}:n.media?{mediaAssetId:n.media}:n.slide?{slideId:n.slide}:await hr(n.image,{idempotencyKey:n.idempotencyKey});return wr(t,n,{...n.label?{label:n.label}:{},placement:Ct(n.placement??"background"),sceneIds:mn(n.scenes),source:s,...i?{timing:i}:{},type:"add_scene_layer"})})}),$w=new un("update").description("Move, retime, relabel or retype one layer. A picture or a clip is not editable \u2014 add a new layer instead \u2014 but a text layer's words are, because nothing was resolved to produce them").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<scene-id>","Composition scene id").argument("<layer-id>","Layer id from the project read").option("--placement <placement>","background | split:left | split:right | full | box:<anchor>").option("--start <seconds>","Seconds from the scene's first frame",ke("--start")).option("--duration <seconds>","Seconds shown",ke("--duration")).option("--start-word <index>","Start on this narration word (0-based); replaces the seconds flags",nt("--start-word")).option("--end-word <index>","Last narration word shown (inclusive)",nt("--end-word")).option("--clear-anchor","Drop the word anchor and put the layer back on seconds").option("--whole-scene","Clear the length so the layer shows until the scene ends").option("--text-title <line>","Retype a text layer as one loud line").option("--text-callout <heading::body>","Retype a text layer as a heading over a paragraph").option("--text-list <heading::a;;b;;c>","Retype a text layer as a heading over up to three points").option("--tone <tone>",`Text card colour: ${yr.join(" | ")}`).option("--label <text>","Studio label").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e,n,r){let o=R(this,r),i=fi(o),s=bl(()=>hl(o));o.placement===void 0&&i===void 0&&s===void 0&&o.label===void 0&&(a("Provide at least one of --placement, --start, --duration, --whole-scene, --start-word, --clear-anchor, --text-title, --text-callout, --text-list, --tone or --label."),process.exit(d.INVALID_INPUT)),await br("Layer update failed",()=>wr(t,o,{...o.label!==void 0?{label:o.label}:{},layerId:n,...o.placement!==void 0?{placement:Ct(o.placement)}:{},sceneId:e,...s?{text:s}:{},...i?{timing:i}:{},type:"update_scene_layer"}))}),Tw=new un("remove").description("Remove one layer from one scene").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<scene-id>","Composition scene id").argument("<layer-id>","Layer id from the project read").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e,n,r){let o=R(this,r);await br("Layer remove failed",()=>wr(t,o,{layerId:n,sceneId:e,type:"remove_scene_layer"}))}),Aw=new un("copy").description("Copy one layer onto other scenes, optionally with a different placement").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<scene-id>","Composition scene id the layer sits on").argument("<layer-id>","Layer id from the project read").requiredOption("--to <ids>","Comma-separated target scene ids").option("--placement <placement>","background | split:left | split:right | full | box:<anchor>").option("--start <seconds>","Retime the copies: seconds from each scene's first frame",ke("--start")).option("--duration <seconds>","Retime the copies: seconds shown",ke("--duration")).option("--start-word <index>","Retime the copies on each TARGET scene's narration words (0-based)",nt("--start-word")).option("--end-word <index>","Last narration word shown on each target (inclusive)",nt("--end-word")).option("--clear-anchor","Drop the source layer's word anchor on the copies").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(t,e,n,r){let o=R(this,r),i=fi(o);await br("Layer copy failed",()=>wr(t,o,{layerId:n,...o.placement!==void 0?{placement:Ct(o.placement)}:{},sceneId:e,...i?{timing:i}:{},toSceneIds:mn(o.to),type:"copy_scene_layer"}))}),wl=new un("layer").description("Add, move, remove or copy the timed layers on a scene").addCommand(Ew).addCommand($w).addCommand(Tw).addCommand(Aw).addHelpText("after",`
120
+ Examples:
121
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-1,slide-3 --image ./floor.jpg --placement background --label "Right way"
122
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-2 --video <video-id> --placement split:left --start 2 --duration 5
123
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-2 --video <video-id> --placement box:top-right --start-word 12 --end-word 18
124
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-3 --text-title "Lockout before you service it" --tone alert --placement full
125
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-2 --text-callout "Lockout/tagout::Isolate the energy source, apply your own lock, and keep the key on you." --placement split:right
126
+ ${u.commands[0]} presentation video layer add <project-id> --scenes slide-4 --text-list "Before you start::Isolate;;Lock;;Verify" --placement box:top-right --start-word 4 --end-word 11
127
+ ${u.commands[0]} presentation video layer update <project-id> slide-2 layer-abc --text-callout "Lockout/tagout::Isolate, lock, and verify before any service." --tone alert
128
+ ${u.commands[0]} presentation video layer update <project-id> slide-1 layer-abc --placement box:top-right
129
+ ${u.commands[0]} presentation video layer update <project-id> slide-1 layer-abc --whole-scene
130
+ ${u.commands[0]} presentation video layer update <project-id> slide-1 layer-abc --clear-anchor --start 2 --duration 5
131
+ ${u.commands[0]} presentation video layer copy <project-id> slide-1 layer-abc --to slide-4,slide-5 --placement full
132
+ ${u.commands[0]} presentation video layer remove <project-id> slide-1 layer-abc
133
+ `);import{randomUUID as Pw}from"crypto";import{Command as Ow}from"commander";var Dw=["basic","standard","premium"],vl=new Ow("presenter").description("Set one scene to a different avatar/look or preset, or restore the project default").argument("<project-id>","Presentation video project ID").argument("<slide-id>","Slide or intro/outro scene ID").option("--avatar-id <id>","Exact avatar/look ID from presenter list").option("--cast-preset-id <id>","Saved cast preset ID").option("--no-apply-preset-voice","Preserve this scene's current voice instead of applying the preset voice").option("--inherit","Remove the override and inherit the project default").option("--render-tier <tier>","Avatar render tier: basic, standard, or premium").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this update").action(async function(t,e,n){let r=R(this,n);try{if(+!!r.avatarId+ +!!r.castPresetId+ +(r.inherit===!0)!==1)throw new Error("Pass exactly one of --avatar-id, --cast-preset-id, or --inherit.");if(r.renderTier&&!r.avatarId)throw new Error("--render-tier can only be used with --avatar-id.");if(r.renderTier&&!Dw.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");l(await m("setPresentationVideoScenePresenter",{applyPresetVoice:r.castPresetId?r.applyPresetVoice:void 0,avatarId:r.avatarId,castPresetId:r.castPresetId,inherit:r.inherit,projectId:t,renderTier:r.renderTier,slideId:e,teamId:r.teamId},Nw(r.idempotencyKey)))}catch(o){a(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(d.GENERAL_ERROR)}});function Nw(t){return t||Pw()}import{createHash as _w}from"crypto";import{Command as pn}from"commander";var Lw=new pn("prepare").description("Start or resume free slide-preview preparation; waits by default for completion").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; generated when omitted").option("--no-wait","Return the run ID; recover with presentation video previews status <run-id>").action(async function(t,e){let n=R(this,e);await vr("Preview preparation failed",async()=>{let r=await J(n.teamId),o=await m("preparePresentationVideoPreviews",{projectId:t,teamId:r},n.idempotencyKey??xl("prepare",t,r));return n.wait===!1?o:ts(o.runId,r)})}).addHelpText("after",`
134
+ What happens:
135
+ Reuses the draft's checkpointed preview run and prepares only missing deck-slide images.
136
+ Card and reusable-video scenes report not_required. This command is free and does not render MP4.
137
+
138
+ Recovery:
139
+ $ ${u.commands[0]} presentation video previews status <run-id>
140
+ $ ${u.commands[0]} presentation video previews inspect <project-id>
141
+ $ ${u.commands[0]} presentation video previews retry <project-id> # only after failed/cancelled
142
+ `),Uw=new pn("inspect").description("Read preview run progress and horizontal/vertical image metadata for every scene").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await vr("Preview status read failed",()=>m("getPresentationVideoPreviews",{projectId:t,teamId:n.teamId}))}).addHelpText("after",`
143
+ Output:
144
+ summary.status is idle, preparing, ready, failed, or not_required.
145
+ scenes[] reports ready, missing, or not_required plus stored horizontalUrl/verticalUrl.
146
+ run contains the durable run ID, phase, progress, status, and typed public error.
147
+ `),jw=new pn("retry").description("Retry the attached failed or cancelled preview run from its saved checkpoints").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; generated when omitted").action(async function(t,e){let n=R(this,e);await vr("Preview retry failed",async()=>{let r=await J(n.teamId);return m("retryPresentationVideoPreviews",{projectId:t,teamId:r},n.idempotencyKey??xl("retry",t,r))})}).addHelpText("after",`
148
+ Rules:
149
+ Only failed or cancelled preview runs can be retried. Active and completed runs are refused.
150
+ Retry resumes unfinished scenes; it does not rebuild images already stored on the draft.
151
+
152
+ Next:
153
+ $ ${u.commands[0]} presentation video previews inspect <project-id>
154
+ `),qw=new pn("status").description("Read one preview DurableRun's progress, result, or typed error").argument("<run-id>","Run ID returned by presentation video previews prepare").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await vr("Preview run status failed",()=>I("preparePresentationVideoPreviews",t,n.teamId))}),Il=new pn("previews").description("Prepare, inspect, or retry the slide images used by presentation-to-MP4").addCommand(Lw).addCommand(Uw).addCommand(jw).addCommand(qw);function xl(t,e,n){return`presentation-video-previews:${t}:${_w("sha256").update(`${n}\0${e}`).digest("hex")}`}async function vr(t,e){try{l(await e())}catch(n){a(n instanceof Error?n.message:t),process.exit(d.GENERAL_ERROR)}}import{Command as hi}from"commander";var kl=new hi("inspect").description("Read a presentation-video project and its ordered scene timeline").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await m("getPresentationVideoProject",{projectId:t,teamId:n.teamId}))}catch(r){a(r instanceof Error?r.message:"Project read failed"),process.exit(d.GENERAL_ERROR)}}),Vw=new hi("list").description("List generated clips and uploaded recordings usable in a presentation video").argument("<project-id>","Target presentation-video project UUID or slug").option("--cursor <cursor>","Opaque cursor from the previous page").option("--limit <number>","Maximum clips to return",Mw).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await m("listReusableVideoClips",{cursor:n.cursor,limit:n.limit,projectId:t,query:n.query,teamId:n.teamId}))}catch(r){a(r instanceof Error?r.message:"Clip list failed"),process.exit(d.GENERAL_ERROR)}}),Rl=new hi("library").description("Reusable generated clips and uploaded recordings").addCommand(Vw);function Mw(t){let e=Number(t);if(!Number.isInteger(e)||e<1||e>100)throw new Error("--limit must be an integer between 1 and 100.");return e}import{randomUUID as Fw}from"crypto";import{Command as yi}from"commander";var Bw=["right-way","wrong-way"],Gw=new yi("status").description("Read a presentation-video scene clip run").argument("<run-id>","Run ID returned by presentation video scene-clip generate").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await I("generatePresentationVideoSceneClip",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Ww=new yi("generate").description("Generate a right-way or wrong-way scene clip from a picture and attach it as a layer").argument("<project-id>","Presentation video project ID or slug").requiredOption("--image <file-or-url-or-id>","Local image file to upload, an https image URL, or a media-library asset UUID").requiredOption("--scenes <ids>","Comma-separated composition scene ids the finished clip is attached to").option("--preset <preset>","right-way (correct procedure) or wrong-way (unsafe act, needs --no-real-person). Default right-way").option("--no-real-person","Declare that no real, identifiable person appears in the picture. Required by --preset wrong-way").option("--placement <placement>","background | split:left | split:right | full | box:<anchor> (default background)").option("--start <seconds>","Seconds from the scene's first frame",ke("--start")).option("--layer-duration <seconds>","Seconds the layer is on screen; omit for the whole scene",ke("--layer-duration")).option("--label <text>",'Studio label, e.g. "Right way"').option("--duration-seconds <n>","Clip length, 5 to 15 seconds (default 6)",t=>Number.parseInt(t,10)).option("--prompt <text>","Replace the derived scene description").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this clip request").option("--yes","Confirm the scene-clip charge").action(async function(t,e){let n=R(this,e);if(!n.yes)return a("Pass --yes to confirm generating a paid scene clip.");let r=n.preset??"right-way";Bw.includes(r)||(a("--preset must be right-way or wrong-way."),process.exit(d.INVALID_INPUT));let o=n.realPerson===!1;r==="wrong-way"&&!o&&(a("A wrong-way clip stages an unsafe act on whoever is in the picture, so it must never be a real person. Pass --no-real-person to declare the picture people-free."),process.exit(d.INVALID_INPUT)),r!=="wrong-way"&&o&&(a("--no-real-person only applies to --preset wrong-way."),process.exit(d.INVALID_INPUT)),n.durationSeconds!==void 0&&!Number.isInteger(n.durationSeconds)&&(a("--duration-seconds must be a whole number of seconds."),process.exit(d.INVALID_INPUT));try{let i=await hr(n.image,{idempotencyKey:n.idempotencyKey}),s=fr({duration:n.layerDuration,start:n.start});l(await m("generatePresentationVideoSceneClip",{destination:{...n.label?{label:n.label}:{},placement:Ct(n.placement??"background"),sceneIds:mn(n.scenes),...s?{timing:s}:{}},durationSeconds:n.durationSeconds,image:i,preset:r,projectId:t,prompt:n.prompt,teamId:n.teamId,...o?{wrongWay:{noRealPersonInImage:!0}}:{}},n.idempotencyKey??Fw()))}catch(i){a(i instanceof Error?i.message:"Scene clip failed"),process.exit(d.GENERAL_ERROR)}}),Cl=new yi("scene-clip").description("Generate scene-clip footage and attach it as a scene layer").addCommand(Ww).addCommand(Gw).addHelpText("after",`
155
+ A wrong-way clip is refused unless you declare the picture people-free with
156
+ --no-real-person. Layers already in the project are managed with
157
+ ${u.commands[0]} presentation video layer.
158
+
159
+ Examples:
160
+ ${u.commands[0]} presentation video scene-clip generate <project-id> --image ./lathe.jpg --scenes slide-3 --yes
161
+ ${u.commands[0]} presentation video scene-clip generate <project-id> --image ./machine.jpg --scenes slide-3,slide-4 --preset wrong-way --no-real-person --placement split:right --yes
162
+ ${u.commands[0]} presentation video scene-clip status <run-id>
163
+ `);import{randomUUID as Kw}from"crypto";import{Command as bi}from"commander";var Jw=new bi("render").description("Render one scene of a presentation video to its own MP4").argument("<project-id>","Presentation video project ID or slug").argument("<scene-id>","Composition scene ID to render").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this scene render request").option("--yes","Confirm the scene render charge").action(async function(t,e,n){let r=R(this,n);if(!r.yes)return a("Pass --yes to confirm rendering a paid scene preview. A scene already cached at its current state is free and still needs --yes only when it must be rendered.");try{l(await m("renderPresentationVideoScene",{projectId:t,sceneId:e,teamId:r.teamId},r.idempotencyKey??Kw()))}catch(o){a(o instanceof Error?o.message:"Scene render failed"),process.exit(d.GENERAL_ERROR)}}),zw=new bi("status").description("Read a presentation-video scene render run").argument("<run-id>","Run ID returned by presentation video scene render").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await I("renderPresentationVideoScene",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Sl=new bi("scene").description("Render and inspect one scene of a presentation video").addCommand(Jw).addCommand(zw).addHelpText("after",`
164
+ A scene render produces the same frames the final video uses, so rendering the
165
+ whole video afterwards is not charged for the scenes it reuses. Editing a scene
166
+ invalidates its segment; render it again to see the change.
167
+
168
+ Examples:
169
+ ${u.commands[0]} presentation video scene render <project-id> slide-3 --yes
170
+ ${u.commands[0]} presentation video scene status <run-id>
171
+ `);import{Command as Qw}from"commander";import{readFile as Hw}from"fs/promises";import{InvalidArgumentError as El}from"commander";async function Xw(t){let e=t.trim(),n=e.startsWith("{")?e:await Hw(e,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--settings must be a JSON object.");return r}async function $l(t){let e=t.settings?await Xw(t.settings):{},n=[t.captionHeight,t.captionWidth,t.captionX,t.captionY].some(i=>i!==void 0),r=[t.captionBackgroundColor,t.captionFontFamily,t.captionFontSize,t.captionHighlightColor,t.captionTextColor].some(i=>i!==void 0),o=[t.presenterAnchor,t.presenterApplyToAll,t.presenterBackground,t.presenterBackgroundFit,t.presenterBackgroundHex,t.presenterBackgroundUrl,t.presenterBorderRadius,t.presenterFramingX,t.presenterFramingY,t.presenterFramingZoom,t.presenterHeight,t.presenterOffsetX,t.presenterOffsetY,t.presenterSize,t.presenterUseDefault,t.presenterVisible,t.presenterX,t.presenterY].some(i=>i!==void 0);if(n&&e.captionPlacement!==void 0)throw new Error("Pass caption placement either as typed flags or inside --settings, not both.");if(r&&e.captionStyle!==void 0)throw new Error("Pass caption style either as typed flags or inside --settings, not both.");if(o&&e.presenter!==void 0)throw new Error("Pass presenter layout either as typed flags or as settings.presenter, not both.");return Yw({captionBackgroundColor:t.captionBackgroundColor,captionFontFamily:t.captionFontFamily,captionFontSize:t.captionFontSize,captionHeight:t.captionHeight,captionHighlightColor:t.captionHighlightColor,captionTextColor:t.captionTextColor,captionWidth:t.captionWidth,captionX:t.captionX,captionY:t.captionY,presenterAnchor:t.presenterAnchor,presenterApplyToAll:t.presenterApplyToAll||void 0,presenterBackgroundFit:t.presenterBackgroundFit,presenterBackgroundHex:t.presenterBackgroundHex,presenterBackgroundKind:t.presenterBackground,presenterBackgroundUrl:t.presenterBackgroundUrl,presenterBorderRadius:t.presenterBorderRadius,presenterFramingX:t.presenterFramingX,presenterFramingY:t.presenterFramingY,presenterFramingZoom:t.presenterFramingZoom,presenterHeight:t.presenterHeight,presenterOffsetX:t.presenterOffsetX,presenterOffsetY:t.presenterOffsetY,presenterSize:t.presenterSize,presenterSlideId:t.presenterSlideId,presenterUseDefault:t.presenterUseDefault||void 0,presenterVisible:t.presenterVisible,presenterX:t.presenterX,presenterY:t.presenterY,settings:t.settings?e:void 0})}function H(t,e,n,r=!1){return o=>{let i=Number(o);if(!Number.isFinite(i)||i<e||i>n||r&&!Number.isInteger(i))throw new El(`${t} must be ${r?"an integer":"a number"} from ${e} to ${n}.`);return i}}function Tl(t){return e=>{if(e==="true")return!0;if(e==="false")return!1;throw new El(`${t} must be true or false.`)}}function Yw(t){return Object.fromEntries(Object.entries(t).filter(e=>e[1]!==void 0))}var Al=new Qw("settings").description("Update saved presentation-video voice, presenter, caption, format, or renderer settings").argument("<project-id>","Presentation video project ID").option("--settings <json-or-path>","Advanced settings patch as JSON or a path to a JSON file").option("--caption-x <ratio>","Caption box center on the horizontal axis, from 0 to 1",H("--caption-x",0,1)).option("--caption-y <ratio>","Caption box center on the vertical axis, from 0 to 1",H("--caption-y",0,1)).option("--caption-width <ratio>","Caption box width as a frame fraction, from 0.18 to 0.95",H("--caption-width",.18,.95)).option("--caption-height <ratio>","Caption box height as a frame fraction, from 0.05 to 0.5",H("--caption-height",.05,.5)).option("--caption-font-family <css-list>","Caption CSS font-family list").option("--caption-font-size <pixels>","Caption font size in pixels, from 20 to 96",H("--caption-font-size",20,96,!0)).option("--caption-text-color <color>","Caption text color: hex, rgb, hsl, transparent, or var()").option("--caption-highlight-color <color>","Current-word highlight color: hex, rgb, hsl, transparent, or var()").option("--caption-background-color <color>","Caption box color: hex, rgb, hsl, transparent, or var()").option("--presenter-slide-id <id>","Target one scene; omit to update the project presenter default").option("--presenter-anchor <anchor>","Presenter anchor: bottom-left, bottom-right, top-left, top-right, left-half, right-half, left-overlay, right-overlay, full, or free",b("--presenter-anchor",["bottom-left","bottom-right","top-left","top-right","left-half","right-half","left-overlay","right-overlay","full","free"])).option("--presenter-size <ratio>","Presenter box width as a frame fraction, from 0.08 to 0.9",H("--presenter-size",.08,.9)).option("--presenter-height <ratio>","Explicit presenter box height as a frame fraction, from 0.05 to 1",H("--presenter-height",.05,1)).option("--presenter-x <ratio>","Horizontal center from 0 to 1; use with --presenter-anchor free",H("--presenter-x",0,1)).option("--presenter-y <ratio>","Vertical center from 0 to 1; use with --presenter-anchor free",H("--presenter-y",0,1)).option("--presenter-offset-x <ratio>","Horizontal edge offset for anchored placement, from 0 to 0.35",H("--presenter-offset-x",0,.35)).option("--presenter-offset-y <ratio>","Vertical edge offset for anchored placement, from 0 to 0.35",H("--presenter-offset-y",0,.35)).option("--presenter-border-radius <ratio>","Corner radius from 0 (square) to 0.5 (circle or pill)",H("--presenter-border-radius",0,.5)).option("--presenter-framing-x <ratio>","Horizontal crop focus inside the presenter box, from 0 to 1",H("--presenter-framing-x",0,1)).option("--presenter-framing-y <ratio>","Vertical crop focus inside the presenter box, from 0 to 1",H("--presenter-framing-y",0,1)).option("--presenter-framing-zoom <ratio>","Crop zoom inside the presenter box, from 1 to 2",H("--presenter-framing-zoom",1,2)).option("--presenter-background <kind>","Background: original, transparent, color, or image",b("--presenter-background",["original","transparent","color","image"])).option("--presenter-background-hex <hex>","Six-digit #RRGGBB value required with --presenter-background color").option("--presenter-background-url <url>","HTTP(S) image required with --presenter-background image").option("--presenter-background-fit <fit>","Image background fit: cover or contain",b("--presenter-background-fit",["cover","contain"])).option("--presenter-visible <true|false>","Show or hide the presenter on --presenter-slide-id",Tl("--presenter-visible")).option("--presenter-apply-to-all","Make the targeted scene placement the project default and clear placement overrides").option("--presenter-use-default","Remove the targeted scene placement override and use the project default").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this settings update").option("--yes","Confirm updating presentation video settings").action(async function(t,e){let n=R(this,e),r;try{r=await $l(n)}catch(o){a(o instanceof Error?o.message:"Invalid settings patch"),process.exit(d.INVALID_INPUT)}if(Object.keys(r).length===0&&(a("Pass a caption or presenter flag, or --settings <json-or-path>, with the patch to apply."),process.exit(d.INVALID_INPUT)),!n.yes)return a("Pass --yes to confirm updating presentation video settings.");try{let o=await J(n.teamId),i={projectId:t,...r,teamId:o};l(await m("updatePresentationVideoSettings",i,n.idempotencyKey??z({command:"presentation video settings",payload:i,workspaceId:o})))}catch(o){a(o instanceof Error?o.message:"Settings update failed"),process.exit(d.GENERAL_ERROR)}}).addHelpText("after",`
172
+ Caption geometry uses frame-relative values. x/y are the box center; width/height are its size.
173
+ Omitted caption fields keep their saved values. Run presentation video inspect <project-id> to verify them.
174
+ Presenter geometry also uses frame-relative values. Omit --presenter-slide-id to edit the default; pass it for one scene.
175
+ Free placement requires --presenter-anchor free plus both --presenter-x and --presenter-y.
176
+
177
+ Examples:
178
+ ${u.commands[0]} presentation video settings <project-id> --caption-y 0.82 --caption-width 0.72 --yes
179
+ ${u.commands[0]} presentation video settings <project-id> --caption-font-size 44 --caption-highlight-color '#14c8ff' --yes
180
+ ${u.commands[0]} presentation video settings <project-id> --presenter-slide-id <slide-id> --presenter-anchor free --presenter-x 0.7 --presenter-y 0.4 --presenter-size 0.28 --yes
181
+ ${u.commands[0]} presentation video settings <project-id> --presenter-slide-id <slide-id> --presenter-apply-to-all --yes
182
+ ${u.commands[0]} presentation video settings <project-id> --presenter-background color --presenter-background-hex '#14213d' --yes
183
+ `);import{Command as gn,InvalidArgumentError as ov}from"commander";import{createHash as Zw}from"crypto";import{existsSync as ev,readFileSync as tv}from"fs";import{Command as Pl,InvalidArgumentError as Ol}from"commander";function nv(t){let e=Number(t);if(!Number.isFinite(e)||e<0||e>1)throw new Ol("--volume must be a number from 0 to 1.");return e}function rv(t){let e=Number(t);if(!Number.isInteger(e)||e<1)throw new Ol("--file-size must be a positive whole number.");return e}async function Dl(t){let{idempotencyKey:e,teamId:n,...r}=t;return m("createPresentationVideoMusicUploadUrl",{...r,teamId:n},e)}var Nl=new Pl("upload-url").description("Mint a project-scoped audio storage POST; this does not upload bytes or change settings").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--file-name <name>","Original audio filename").requiredOption("--file-type <mime>","Exact audio MIME type").requiredOption("--file-size <bytes>","Exact positive byte size; maximum 104857600",rv).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; derived from workspace, project, and exact file metadata when omitted").action(async function(t,e){let n=R(this,e);await y();try{let r=await J(n.teamId),o={fileName:n.fileName,fileSize:n.fileSize,fileType:n.fileType,projectId:t};l(await Dl({...o,idempotencyKey:n.idempotencyKey??z({command:"presentation video music upload-url",payload:o,workspaceId:r}),teamId:r}))}catch(r){a(r instanceof Error?r.message:"Custom music upload URL creation failed"),process.exit(d.GENERAL_ERROR)}}),_l=new Pl("upload").description("Upload local audio, save it as this video's custom music, and verify the draft").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--file <path>","Local audio file to upload").option("--volume <level>","Saved mix level from 0 to 1; default 0.12",nv,.12).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; derived from workspace, project, exact bytes, MIME, and level when omitted").addHelpText("after",`
184
+ Postcondition: mode=upload, filename, and volume are read back from the saved project. This command never downloads an arbitrary URL.
185
+ `).action(async function(t,e){let n=R(this,e);await y(),ev(n.file)||(a(`File not found: ${n.file}`),process.exit(d.INVALID_INPUT));try{let r=await J(n.teamId),o=Bt(n.file),i=Zw("sha256").update(tv(n.file)).digest("hex"),s={contentSha256:i,...o,projectId:t,volume:n.volume},c=n.idempotencyKey??z({command:"presentation video music upload",payload:s,workspaceId:r}),p=await Dl({...o,idempotencyKey:`${c}:upload`,projectId:t,teamId:r}),f=await Gt(n.file,p),h=await m("updatePresentationVideoSettings",{projectId:p.projectId,settings:{music:{audioUrl:f.url,fileName:f.name,mode:"upload",volume:n.volume}},teamId:r},`${c}:settings`),x=(await m("getPresentationVideoProject",{projectId:p.projectId,teamId:r})).renderSettings.music;if(x.mode!=="upload"||x.uploadedFileName!==o.fileName||x.volume!==n.volume)throw new Error("Custom music upload completed but the saved project did not match it.");l({contentSha256:i,fileName:o.fileName,fileSize:o.fileSize,fileType:o.fileType,music:x,projectId:h.projectId,s3Key:p.s3Key,settings:h.settings.music})}catch(r){a(r instanceof Error?r.message:"Custom music upload failed"),process.exit(d.GENERAL_ERROR)}});function iv(t){let e=Number(t);if(!Number.isInteger(e)||e<1||e>24)throw new ov("--limit must be an integer from 1 to 24.");return e}var av=new gn("search").description("Search stock music and return preview URLs plus opaque selection tokens").argument("<query>","Mood, genre, instrument, or other search terms").option("--limit <count>","Return 1 to 24 tracks; default 12",iv).option("--token <token>","Opaque nextToken from the previous page").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await vi("Stock-music search failed",()=>m("searchPresentationVideoStockMusic",{limit:n.limit,query:t,teamId:n.teamId,token:n.token}))}).addHelpText("after",`
186
+ Output:
187
+ tracks[].previewUrl is for audition only. tracks[].selectionToken is opaque and short-lived.
188
+ To save one result, pass its id, name, and selectionToken to stock select.
189
+
190
+ Example:
191
+ $ ${u.commands[0]} presentation video music stock search "calm ambient" --limit 8
192
+ `),sv=new gn("select").description("Select one paid stock track; waits by default, saves it, and returns a recovery run ID").argument("<project-id>","Presentation-video project UUID or editor slug").option("--mode <mode>","Selection mode: manual or auto","manual").option("--selection-token <token>","Opaque selectionToken from stock search; manual mode only").option("--track-id <id>","Track id from stock search; manual mode only").option("--track-name <name>","Track name from stock search; manual mode only").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; deterministically derived from workspace and exact selection when omitted").option("--no-wait","Return the run ID; recover with presentation video music stock status <run-id>").action(async function(t,e){let n=R(this,e);if(n.mode!=="manual"&&n.mode!=="auto")return wi("--mode must be manual or auto.");if(n.mode==="manual"&&(!n.selectionToken||!n.trackId||!n.trackName))return wi("Manual mode requires --selection-token, --track-id, and --track-name from stock search.");if(n.mode==="auto"&&(n.selectionToken||n.trackId||n.trackName))return wi("Auto mode derives the choice from the saved deck; omit manual track flags.");await vi("Stock-music selection failed",async()=>{let r=await J(n.teamId),o={mode:n.mode,projectId:t,selectionToken:n.selectionToken,teamId:r,trackId:n.trackId,trackName:n.trackName},i=await m("selectPresentationVideoStockMusic",o,n.idempotencyKey??z({command:"presentation-video-stock-music-select",payload:o,workspaceId:r}));return n.wait===!1?i:es(i.runId,r)})}).addHelpText("after",`
193
+ Postcondition:
194
+ The completed run persists mode=stock, the durable audio URL, duration, track identity,
195
+ and a new project draft version. It does not render an MP4.
196
+
197
+ Manual:
198
+ $ ${u.commands[0]} presentation video music stock select <project-id> --selection-token <token> --track-id <id> --track-name "Warm Horizon"
199
+
200
+ Auto from saved slide titles and narration:
201
+ $ ${u.commands[0]} presentation video music stock select <project-id> --mode auto
202
+ `),dv=new gn("status").description("Read stock-music run status/progress, billing, persisted result, or typed failure").argument("<run-id>","Run ID returned by stock select --no-wait").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);await vi("Stock-music status failed",()=>I("selectPresentationVideoStockMusic",t,n.teamId))}),Ll=new gn("music").description("Search and select music sources for an existing video project").addCommand(_l).addCommand(Nl).addCommand(new gn("stock").description("Preview catalog tracks and save a manual or deck-aware automatic selection").addCommand(av).addCommand(sv).addCommand(dv));async function vi(t,e){try{l(await e())}catch(n){a(n instanceof Error?n.message:t),process.exit(d.GENERAL_ERROR)}}function wi(t){a(t),process.exit(d.INVALID_INPUT)}import{readFile as cv}from"fs/promises";async function Ul(t){if(!t)return;let e=t.trim().startsWith("{")?t:await cv(t,"utf8"),n=JSON.parse(e);if(!n||Array.isArray(n)||typeof n!="object")throw new Error("--slide-instructions must be a JSON object or file path");let r={};for(let[o,i]of Object.entries(n)){if(!o.trim()||typeof i!="string")throw new Error("--slide-instructions must map non-empty slide IDs to text");r[o]=i}return r}var lv=new G("status").description("Check a presentation generation run").argument("<run-id>","Run ID returned by presentation generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("createSlides",t,e.teamId);if(e.format==="json"){l(n);return}if(e.format==="quiet"){console.log(n.status);return}w(`Status: ${n.status}`),w(n.message),n.progress!==null&&w(`Progress: ${n.progress}%`),n.error&&a(se(n.error))}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),mv=new G("delete").description("Permanently delete an owned presentation and its publications").argument("<presentation-id>","Presentation id or slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").option("--approval-receipt <receipt>","Browser-issued approval receipt").option("--yes","Confirm permanent deletion").action(async(t,e)=>{e.yes||(a("Refusing to permanently delete without confirmation. Re-run with --yes."),process.exit(d.GENERAL_ERROR));let n=e.idempotencyKey??z({command:"presentation:delete",payload:{presentationId:t},workspaceId:e.teamId??"configured-default"});try{l(await m("deletePresentation",{approvalReceipt:e.approvalReceipt,presentationId:t,teamId:e.teamId},n))}catch(r){r.errorCode==="approval_required"&&_(`Retry with --idempotency-key ${n}`),a(r instanceof Error?r.message:"Could not delete the presentation"),process.exit(d.GENERAL_ERROR)}}),uv=new G("limits").description("Show the selected workspace's presentation generation limits").option("--team-id <id>","Workspace ID (uses configured default)").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{await y();let e=t.teamId??ee();e||(a("Team ID required. Set one with `mf config set team-id <id>` or pass --team-id."),process.exit(d.GENERAL_ERROR));try{let n=await Qr(e);if(t.format==="json")return l(n);if(t.format==="quiet")return console.log(n.planName);w(`Plan: ${n.planName}`),w(`Available modes: ${n.availableModes.join(", ")||"none"}`),w(`Maximum slides: ${n.maxSlidesPerPresentation}`)}catch(n){a(n instanceof Error?n.message:"Could not read generation limits"),process.exit(d.GENERAL_ERROR)}}),pv=new G("visibility").description("Set an owned presentation's visibility to private, team, or public").argument("<presentation-id>","Presentation ID or slug").argument("<visibility>","private, team, or public",b("visibility",["private","team","public"])).option("--team-id <id>","Workspace ID (uses configured default)").option("--idempotency-key <key>","Stable retry key").action(async(t,e,n)=>{await y();try{l(await Ea(t,{idempotencyKey:n.idempotencyKey,teamId:n.teamId,visibility:e}))}catch(r){a(r instanceof Error?r.message:"Could not update presentation visibility"),process.exit(d.GENERAL_ERROR)}});function ql(t){let e=Number(t);if(!Number.isInteger(e)||e<0)throw new Ii("Expected a non-negative integer.");return e}async function gv(t){let e=t.trim(),n=e.startsWith("[")?e:await jl(e,"utf-8"),r=JSON.parse(n);if(!Array.isArray(r))throw new Ii("--grants must be a JSON array.");for(let o of r)if(!o||typeof o!="object"||typeof o.userId!="string"||!["view","edit"].includes(o.permission))throw new Ii('Every grant must be {"userId":"\u2026","permission":"view|edit"}.');return r}var fv=new G("get").description("Read presentation ownership and team access").requiredOption("--document-id <id>","Presentation document ID").option("--team-id <id>","Workspace ID override").action(async t=>{try{l(await m("getPresentationSharing",{documentId:t.documentId,teamId:t.teamId}))}catch(e){a(e instanceof Error?e.message:"Could not read presentation sharing"),process.exit(d.GENERAL_ERROR)}}),hv=new G("update").description("Replace presentation collaborators and team access").requiredOption("--document-id <id>","Presentation document ID").requiredOption("--expected-revision <number>","Revision returned by presentation sharing get",ql).requiredOption("--team-access <access>","restricted, view, or edit",b("--team-access",["restricted","view","edit"])).requiredOption("--grants <json-or-path>","Complete JSON grant array; use [] to remove all collaborators").option("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID override").action(async t=>{try{let e=await J(t.teamId),n=await gv(t.grants),r=t.idempotencyKey??z({command:"presentation:sharing:update",payload:{documentId:t.documentId,expectedRevision:t.expectedRevision,grants:n,teamAccess:t.teamAccess},workspaceId:e});l(await m("updatePresentationSharing",{documentId:t.documentId,expectedRevision:t.expectedRevision,grants:n,teamAccess:t.teamAccess,teamId:e},r))}catch(e){a(e instanceof Error?e.message:"Could not update presentation sharing"),process.exit(d.GENERAL_ERROR)}}),yv=new G("sharing").description("Read or update presentation team access").addCommand(fv).addCommand(hv),bv=new G("transfer").description("Transfer a presentation and every saved version").requiredOption("--document-id <id>","Presentation document ID").requiredOption("--to-user-id <id>","Active team editor or admin").requiredOption("--expected-revision <number>","Revision returned by presentation sharing get",ql).option("--previous-owner-access <access>","Keep edit access or remove access",b("--previous-owner-access",["edit","remove"]),"edit").option("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID override").action(async t=>{try{let e=await J(t.teamId),n=t.idempotencyKey??z({command:"presentation:transfer",payload:{documentId:t.documentId,expectedRevision:t.expectedRevision,previousOwnerAccess:t.previousOwnerAccess,toUserId:t.toUserId},workspaceId:e});l(await m("transferPresentationOwnership",{documentId:t.documentId,expectedRevision:t.expectedRevision,previousOwnerAccess:t.previousOwnerAccess,teamId:e,toUserId:t.toUserId},n))}catch(e){a(e instanceof Error?e.message:"Could not transfer presentation ownership"),process.exit(d.GENERAL_ERROR)}}),wv=new G("transform").description("Transform an uploaded PowerPoint import for review").argument("<import-id>","PowerPoint import ID returned by Mindframes").option("--idempotency-key <key>","Stable retry key").action(async function(t,e){let n=R(this,e);try{let r=await m("transformPresentationImport",{importId:t},n.idempotencyKey);l(r)}catch(r){a(r instanceof Error?r.message:"Transform failed"),process.exit(d.GENERAL_ERROR)}}),vv=new G("status").description("Read a PowerPoint import run").argument("<run-id>","Run ID returned by PowerPoint import").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("importPowerPoint",t,e.teamId);e.format==="json"?l(n):e.format==="quiet"?console.log(n.status):(w(`Status: ${n.status}`),w(n.message),n.error&&a(se(n.error)))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Vl=new G("import").description("Import a PowerPoint through the review-gated reconstruction pipeline").option("--file <path>","Path to the .pptx to import").option("--filename <name>","Override the uploaded filename").option("--mode <mode>","Import mode: preserve or rebrand","preserve").option("--branding-id <id>","Saved brand ID (required for rebrand mode)").option("--source-chat-id <id>","Associate the import with an existing chat").option("--title <title>","Presentation title").option("--idempotency-key <key>","Stable retry key").action(async t=>{if(!t.file){Vl.help();return}t.file.toLowerCase().endsWith(".pptx")||(a("PowerPoint import requires a .pptx file."),process.exit(d.INVALID_INPUT));try{let e=await de(t.file),n=await m("importPowerPoint",{brandingId:t.brandingId,filename:t.filename??e.name,mode:t.mode,sourceChatId:t.sourceChatId,sourceUrl:e.url,title:t.title},t.idempotencyKey??Ir());l(n)}catch(e){a(e instanceof Error?e.message:"Import failed"),process.exit(d.GENERAL_ERROR)}}).addCommand(wv).addCommand(vv),Iv=new G("speaker-notes-status").description("Check a speaker-notes generation run").argument("<run-id>","Run ID returned by speaker-notes generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("generateSpeakerNotes",t,e.teamId);e.format==="json"?l(n):e.format==="quiet"?console.log(n.status):(w(`Status: ${n.status}`),w(n.message))}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),xv=new G("video-narration-status").description("Check a presentation-video narration regeneration run").argument("<run-id>","Run ID returned by video-narration").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await I("regeneratePresentationVideoNarration",t,e.teamId);e.format==="json"?l(n):e.format==="quiet"?console.log(n.status):(w(`Status: ${n.status}`),w(n.message))}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),kv=new G("status").description("Read a presentation-video MP4 render run").argument("<run-id>","Run ID returned by presentation video").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await I("createPresentationVideo",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Rv=new G("prepare").description("Create or reuse a presentation-video project for a presentation").argument("<presentation-id>","Presentation ID, document ID, or slug").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--narrate","Also generate the narration the project is missing (costs credits; requires --yes)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this prepare request").option("--yes","Confirm the narration charge when --narrate is used").action(async function(t,e){let n=R(this,e);if(n.narrate&&!n.yes)return a("Pass --yes to confirm. --narrate generates speaker notes and costs credits.");try{l(await m("preparePresentationVideo",{forceNew:n.forceNew,narrate:n.narrate,presentationId:t,teamId:n.teamId},n.idempotencyKey??Ir()))}catch(r){a(r instanceof Error?r.message:"Prepare failed"),process.exit(d.GENERAL_ERROR)}}),Cv=new G("status").description("Read a presentation-video narration run").argument("<run-id>","Run ID returned by presentation video narrate").option("--team-id <id>","Workspace ID override").action(async function(t,e){let n=R(this,e);try{l(await I("ensurePresentationVideoNarration",t,n.teamId))}catch(r){a(r instanceof Error?r.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Sv=new G("narrate").description("Generate the narration a presentation-video project is still missing").argument("<project-id>","Presentation video project ID").option("--no-wait","Return immediately with the durable run ID").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this narration request").option("--yes","Confirm the narration charge").action(async function(t,e){let n=R(this,e);if(!n.yes)return a("Pass --yes to confirm. Generating narration costs credits.");try{let r=await m("ensurePresentationVideoNarration",{projectId:t,teamId:n.teamId},n.idempotencyKey??Ir());if(n.wait===!1||r.runStatus==="completed"){l(r);return}l(r),await xi(r.runId,"presentation video narrate status",()=>An(r.runId))}catch(r){a(r instanceof Error?r.message:"Narration failed"),process.exit(d.GENERAL_ERROR)}}).addCommand(Cv),Ev=new G("video").description("Create an MP4 video from a presentation").argument("[presentation-id]","Presentation ID, document ID, or slug").option("--project-id <id>","Advanced: render an already-configured presentation video project").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file; only valid with presentation-id").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--force-rerender","Start a new MP4 render even when the current project fingerprint has a completed render").option("--render-engine <engine>","Renderer for this MP4 only: remotion (Standard) or hyperframes (Premium)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this render request").option("--yes","Confirm starting the MP4 render").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to confirm presentation video rendering.");try{if(!t&&!e.projectId)throw new Error("Pass a presentation id or --project-id.");if(t&&e.projectId)throw new Error("Pass either presentation id or --project-id, not both.");if(e.projectId&&(e.settings||e.forceNew))throw new Error("--settings and --force-new require a presentation id, not --project-id.");if(e.renderEngine&&e.renderEngine!=="remotion"&&e.renderEngine!=="hyperframes")throw new Error("--render-engine must be remotion or hyperframes.");l(await m("createPresentationVideo",{forceNew:e.forceNew,forceRerender:e.forceRerender,presentationId:t,projectId:e.projectId,renderEngine:e.renderEngine,settings:e.settings?await $v(e.settings):void 0,teamId:e.teamId},e.idempotencyKey))}catch(n){let r=n instanceof Error?n.message:"Render failed";a(r);let o=ha({binary:u.commands[0],message:r,projectId:e.projectId});o&&ia(o),process.exit(d.GENERAL_ERROR)}}).addCommand(Rv).addCommand(Sv).addCommand(kl).addCommand(nl).addCommand(Ll).addCommand(al).addCommand(sl).addCommand(vl).addCommand(Il).addCommand(il).addCommand(ol).addCommand(Al).addCommand(wl).addCommand(Cl).addCommand(Sl).addCommand(kv).addCommand(ll).addCommand(cl).addCommand(ml).addCommand(dl).addCommand(rl);async function $v(t){let e=t.trim(),n=e.startsWith("{")?e:await jl(e,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--settings must be a JSON object.");return r}function Tv(t,e){return[...e,t]}var Av=new G("speaker-notes").description("Generate paid speaker notes; waits by default and requires --yes").argument("<presentation-id>","Presentation ID or slug").option("--mode <mode>","ensure or regenerate","ensure").option("--style <style>","concise or detailed","concise").option("--density <density>","Narration density: brief, balanced, or deep").option("--instructions <text>","Instructions for every selected slide").option("--language <language>","Output language").option("--slide-id <id>","Target one slide (repeatable)",Tv,[]).option("--slide-instructions <json-or-path>","Per-slide instructions as a JSON object or JSON file path").option("--no-follow","Return the run ID; recover with presentation speaker-notes-status <run-id>").option("--yes","Confirm the speaker-notes generation charge").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this speaker-notes request").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{if(!e.yes)throw new Error("Pass --yes to confirm. Generating speaker notes costs credits.");if(!["ensure","regenerate"].includes(e.mode))throw new Error("--mode must be ensure or regenerate");if(!["concise","detailed"].includes(e.style))throw new Error("--style must be concise or detailed");if(e.density&&!["brief","balanced","deep"].includes(e.density))throw new Error("--density must be brief, balanced, or deep");let n=await J(e.teamId),r={density:e.density??(e.style==="detailed"?"deep":"balanced"),instructions:e.instructions,language:e.language,mode:e.mode,slideIds:e.slideId.length?e.slideId:void 0,slideInstructions:await Ul(e.slideInstructions)},o=await Ca(t,r,e.idempotencyKey??z({command:"presentation speaker-notes",payload:r,workspaceId:n}),n);if(e.format==="json"||!e.follow){l(o);return}w(`Speaker notes run: ${o.runId}`),await xi(o.runId,"presentation speaker-notes-status",()=>An(o.runId))}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Pv=new G("video-narration").description("Regenerate one slide narration in a presentation video draft").argument("<project-id>","Presentation video project ID").requiredOption("--slide-id <id>","Slide ID in the video draft").option("--instructions <text>","Optional regeneration instructions").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key; generated when omitted").option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async function(t,e){try{let n=R(this,e),r=await J(n.teamId),o={instructions:e.instructions,projectId:t,slideId:e.slideId,teamId:r},i=await m("regeneratePresentationVideoNarration",o,n.idempotencyKey??Ir());if(e.format==="json"||!e.follow){l(i);return}w(`Narration run: ${i.runId}`),await xi(i.runId,"presentation video-narration-status",()=>An(i.runId))}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}});async function xi(t,e,n){let r=null;try{r=await Dv(await n())}catch(o){let i=o instanceof Error&&o.message.trim()?o.message.trim():"the event stream ended unexpectedly";_(`Stopped following run ${t}: ${i}. The run is unaffected \u2014 check it with '${u.commands[0]} ${e} ${t}'.`);return}if(r)throw new Error(`Run ${t} ${r.status}: ${r.message} Inspect it with '${u.commands[0]} ${e} ${t}'.`)}function Ov(t){let e=t.eventType;if(e==="run.completed"||e==="durable_run.completed")return"completed";let n=e==="run.failed"||e==="durable_run.failed"?"failed":e==="run.cancelled"||e==="durable_run.cancelled"?"cancelled":null;return n?{message:t.payload?.message?.trim()||t.message?.trim()||"the run reported no error message",status:n}:null}async function Dv(t){let e=t.body?.getReader();if(!e)throw new Error("Speaker notes event stream is unavailable");let n=new TextDecoder,r="",o=null;for(;;){let{done:i,value:s}=await e.read();r+=n.decode(s,{stream:!i});let c=r.split(`
203
+
204
+ `);r=c.pop()??"";for(let p of c){let f=p.split(`
205
+ `).find(x=>x.startsWith("data:"))?.slice(5).trim();if(!f)continue;let h=JSON.parse(f);h.eventType?.startsWith("slide.")&&w(`${h.eventType}${h.payload?.slideId?` \xB7 ${h.payload.slideId}`:""}`);let v=Ov(h);v==="completed"?o=null:v&&(o=v)}if(i)return o}}var ki=new G("presentation").description("Create an MP4 video from a finished presentation, plus speaker notes, PowerPoint import, and run status").addCommand(lv).addCommand(Nn).addCommand(uv).addCommand(pv).addCommand(yv).addCommand(bv).addCommand(mv).addCommand(Vl).addCommand(Av).addCommand(Iv).addCommand(Ev).addCommand(Pv).addCommand(xv);ki.addHelpText("after",`
206
+ ${V.bold("Deck to MP4:")}
207
+ $ ${u.commands[0]} presentation video prepare <slug> ${V.gray("# create/reuse the video project (free)")}
208
+ $ ${u.commands[0]} presentation video narrate <project-id> --yes ${V.gray("# fill in missing narration")}
209
+ $ ${u.commands[0]} presentation video inspect <project-id> ${V.gray("# review the scene timeline")}
210
+ $ ${u.commands[0]} presentation video <slug> --yes ${V.gray("# start the MP4 render")}
211
+ $ ${u.commands[0]} presentation video status <run-id> ${V.gray("# follow the render")}
212
+
213
+ ${V.bold("Voice and avatar defaults:")}
214
+ ${V.gray("# prepare picks the narration voice for you \u2014 the one this user last")}
215
+ ${V.gray("# chose if it is still ready, otherwise the first ready voice \u2014 and")}
216
+ ${V.gray("# reports it. Show which voice was selected and offer to change it")}
217
+ ${V.gray("# instead of interviewing the user about voices. Every voice in")}
218
+ ${V.gray("# avatar options carries a previewUrl audio sample they can hear.")}
219
+ ${V.gray('# No avatar is chosen, on purpose: "slides with a voiceover" is the')}
220
+ ${V.gray("# normal outcome, so presenter: null is finished, not misconfigured.")}
221
+ ${V.gray("# Ask whether they want a presenter; do not assume either way.")}
222
+ $ ${u.commands[0]} avatar options ${V.gray("# real voice and avatar ids + previews")}
223
+ $ ${u.commands[0]} presentation video settings <project-id> --yes --settings '{"voiceId":"<id>"}'
224
+ $ ${u.commands[0]} presentation video settings <project-id> --yes --settings '{"avatarId":"<id>"}'
225
+
226
+ ${V.bold("Before rendering:")}
227
+ ${V.gray("# Approve the content, then approve the spend \u2014 two questions. Read the")}
228
+ ${V.gray("# narration back scene by scene from inspect (scenes[].narration.text)")}
229
+ ${V.gray("# and get a yes on the script itself, plus the voice, the presenter (or")}
230
+ ${V.gray("# none), music, format and captions, before the render. Reworking one")}
231
+ ${V.gray("# scene is the cheap loop; the MP4 is not. --yes is your intent, not")}
232
+ ${V.gray("# the user's consent.")}
233
+ $ ${u.commands[0]} presentation video inspect <project-id> ${V.gray("# narration text + settings to show")}
234
+ $ ${u.commands[0]} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"
235
+
236
+ ${V.bold("See also:")}
237
+ ${V.gray("# Building a video from scratch instead of from a deck")}
238
+ $ ${u.commands[0]} video --help
239
+ `);import{writeFile as Nv}from"fs/promises";import fn from"chalk";import{Command as _v}from"commander";import Lv from"ora";var Ri=new _v("scrape").description("Extract content from a URL").argument("<url>","URL to scrape").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Save content to file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{let n=e.format,r=n==="human"?Lv("Scraping URL...").start():null;try{let o=await Ga(t,e.teamId);r?.stop(),(!o.success||!o.data)&&(a(o.error||"Failed to scrape URL"),process.exit(d.GENERAL_ERROR));let i=o.data;if(e.output&&(await Nv(e.output,i.content,"utf-8"),n==="human"&&k(`Content saved to: ${e.output}`)),n==="json"){l(i);return}if(n==="quiet"){console.log(i.content);return}i.title&&(console.log(),console.log(`Title: ${i.title}`)),i.metadata?.description&&console.log(`Description: ${i.metadata.description}`),console.log(`URL: ${i.url}`),console.log(`Tokens: ~${i.metadata?.tokenUsage?.toLocaleString()||"unknown"}`),i.warning&&_(i.warning),e.output||(console.log(),console.log("--- Content ---"),console.log(i.content))}catch(o){r?.stop(),a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}});Ri.addHelpText("after",`
240
+ ${fn.bold("Examples:")}
241
+ ${fn.gray("# Pull the readable content of a web page")}
242
+ $ ${u.commands[0]} scrape https://example.com/post
243
+
244
+ ${fn.bold("See also:")}
245
+ ${fn.gray("# Local files and documents, not just URLs")}
246
+ $ ${u.commands[0]} content extract ./paper.pdf
247
+
248
+ ${fn.gray("# Spoken words out of audio or video")}
249
+ $ ${u.commands[0]} transcript --help
250
+ `);import Ci from"chalk";import{Command as hn}from"commander";function xr(t,e){e!=="quiet"&&l(t)}var Uv=new hn("web").description("Search current public web sources").argument("<query>","Search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","5").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await m("searchInternet",{maxResults:Number.parseInt(e.maxResults,10),query:t,teamId:e.teamId});xr(n,e.format)}catch(n){a(n instanceof Error?n.message:"Search failed"),process.exit(d.GENERAL_ERROR)}}),jv=new hn("news").description("Search recent news").argument("<topic>","News topic").option("--team-id <id>","Workspace ID").option("--timeframe <value>","Timeframe hint").option("--max-results <count>","Maximum results","6").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await m("getNews",{maxResults:Number.parseInt(e.maxResults,10),teamId:e.teamId,timeframe:e.timeframe,topic:t});xr(n,e.format)}catch(n){a(n instanceof Error?n.message:"News search failed"),process.exit(d.GENERAL_ERROR)}});function Ml(t){let e=t?.trim().toLowerCase();if(!(!e||e==="any"||e==="all"))return e==="web"||e==="stock"?[e]:void 0}var qv=new hn("images").description("Search images across the web and licensed stock").argument("<query>","Image search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--aspect <aspect>","Aspect: any, square, wide, tall","any").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await m("searchImages",{aspect:e.aspect,maxResults:Number.parseInt(e.maxResults,10),query:t,sources:Ml(e.source),teamId:e.teamId});xr(n,e.format)}catch(n){a(n instanceof Error?n.message:"Image search failed"),process.exit(d.GENERAL_ERROR)}}),Vv=new hn("video").description("Search video across the web and licensed stock").argument("<query>","Video search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--orientation <value>","Orientation: landscape, portrait, square, any","any").option("--license <value>","License: free, premium, any","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{let n=await m("searchStockVideo",{license:e.license,maxResults:Number.parseInt(e.maxResults,10),orientation:e.orientation,query:t,sources:Ml(e.source),teamId:e.teamId});xr(n,e.format)}catch(n){a(n instanceof Error?n.message:"Video search failed"),process.exit(d.GENERAL_ERROR)}}),Si=new hn("search").description("Web, news, image, and stock-video search").addCommand(Uv).addCommand(jv).addCommand(qv).addCommand(Vv);Si.addHelpText("after",`
251
+ ${Ci.bold("Examples:")}
252
+ $ ${u.commands[0]} search web "state of AI video 2026"
253
+ $ ${u.commands[0]} search news "vaccine approvals"
254
+
255
+ ${Ci.bold("See also:")}
256
+ ${Ci.gray("# `search images` and `search video` overlap with these")}
257
+ $ ${u.commands[0]} image search --help
258
+ $ ${u.commands[0]} video find --help
259
+ `);import{Command as $i}from"commander";import Mv from"ora";function Ei(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.audioUrl??t.requestId??t.id);return}w(`Request ID: ${t.requestId||t.id}`),w(`Status: ${t.status}`),t.duration&&w(`Duration: ${t.duration}s`),t.audioUrl&&k(`Audio URL: ${t.audioUrl}`),t.error&&a(`Error: ${t.error}`)}var Fv=new $i("generate").description("Generate one SFX cue from a video's final facts and visual event").requiredOption("--request <path>","JSON file with video description, narration timings, and visual_event").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{!t.wait&&t.output&&(a("--output requires waiting for completion; remove --no-wait"),process.exit(d.INVALID_INPUT));let e;try{e=Xc(t.request)}catch(i){a(i instanceof Error?i.message:String(i)),process.exit(d.INVALID_INPUT)}let n=t.format,r=n==="human"?Mv("Generating sound effect for video...").start():null,o;try{let i=await Wa(e);if(o=i.requestId||i.id,!t.wait){r?.stop(),Ei(i,n);return}let s=i.requestId||i.id;r&&(r.text=`Processing (ID: ${s})...`);let c=i.status==="completed"||i.status==="failed"?i:await ce(()=>to(s),60,2e3);if(r?.stop(),c.status==="failed"&&(a(c.error||"Sound effects generation failed"),process.exit(d.GENERAL_ERROR)),t.output){if(!c.audioUrl)throw new Error("Sound effect completed without an audio URL");await te(c.audioUrl,t.output),n==="human"&&k(`Saved to: ${t.output}`)}Ei(c,n)}catch(i){r?.stop(),a(fe(i,o),n),process.exit(d.GENERAL_ERROR)}}),Bv=new $i("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{try{Ei(await to(t),e.format)}catch(n){a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),Fl=new $i("sfx").description("Video-aware sound effects generation commands").addCommand(Fv).addCommand(Bv);import{randomUUID as Gv}from"crypto";import{readFile as Wv}from"fs/promises";import{Command as Ti}from"commander";var Kv=["received","looking_into_it","planned","in_progress","fixed_awaiting_release","shipped","not_planned","needs_input"];async function Jv(t){if(t!==void 0&&t!=="-"&&!t.startsWith("@"))return t;if(t?.startsWith("@"))return Wv(t.slice(1),"utf8");if(t==="-"||!process.stdin.isTTY)return zv();a("Nothing to report. Pass the text as an argument, @<path> to read a file, or pipe it on stdin."),process.exit(d.GENERAL_ERROR)}async function zv(){let t=[];for await(let e of process.stdin)t.push(Buffer.from(e));return Buffer.concat(t).toString("utf8")}function Hv(t){if(t===void 0)return{};let e;try{e=JSON.parse(t)}catch(n){a(`--context must be a JSON object: ${n instanceof Error?n.message:String(n)}`),process.exit(d.GENERAL_ERROR)}return(e===null||typeof e!="object"||Array.isArray(e))&&(a("--context must be a JSON object."),process.exit(d.GENERAL_ERROR)),e}function Bl(t,e){a(t instanceof Error?t.message:e),process.exit(d.GENERAL_ERROR)}var Xv=new Ti("report").description("File a bug, question, feature request or billing issue").argument("[text]","What happened, in your own words: literal text, @<path> to read a file, or '-' for stdin").option("--team-id <id>","Workspace ID").option("--screenshot-url <key>","Object key returned by the support screenshot upload (support-requests/<teamId>/<uuid>/screenshot.<ext>)").option("--source <source>","Where the report comes from; defaults to cli").option("--context <json>",`JSON object of extra context, e.g. '{"kind":"bug"}' for your own guess at bug | confusing | feature | billing | other (triage decides), route, errorReference, chatId, artifactId`).action(async(t,e)=>{try{let n=Hv(e.context);l(await m("submitSupportRequest",{context:Object.keys(n).length>0?n:void 0,screenshotUrl:e.screenshotUrl,source:e.source,teamId:e.teamId,text:await Jv(t)},`cli:support:report:${Gv()}`))}catch(n){Bl(n,"Could not file the report")}}),Yv=new Ti("list").description("List the workspace's support requests and their status, newest first").option("--team-id <id>","Workspace ID").option("--mine","Only the reports you filed yourself").option("--status <status>",`Only items in one of ${Kv.join(", ")}`).option("--limit <n>","Maximum items to return (default 50)").action(async t=>{try{l(await m("listSupportRequests",{limit:t.limit?Number(t.limit):void 0,mine:t.mine?!0:void 0,status:t.status,teamId:t.teamId}))}catch(e){Bl(e,"Could not list support requests")}}),Gl=new Ti("support").description("File a report and follow what became of it").addCommand(Xv).addCommand(Yv);import{Command as Qv}from"commander";import yn from"chalk";var Wl=new Qv("templates").description("List slide design templates (use with `create --template <id>`)").argument("[search]","Filter templates by name, description, or category").option("-f, --format <format>","Output format (table, json)",b("--format",["table","json"]),"table").option("--limit <n>","Maximum templates to list","25").action(async(t,e)=>{await y();try{let n=Number.parseInt(e.limit??"25",10),{templates:r}=await Pa(t,Number.isFinite(n)?n:25);if(r.length===0){e.format==="json"?console.log(JSON.stringify([])):w("No templates found");return}if(e.format==="json"){console.log(JSON.stringify(r,null,2));return}for(let o of r){let i=[o.isDefault?yn.green("default"):null,o.category??null,o.recommendedModes?.length?`modes: ${o.recommendedModes.join("/")}`:null].filter(Boolean).join(" \xB7 ");console.log(`${yn.bold(o.name)} ${yn.gray(o.id)}${i?`
260
+ ${yn.gray(i)}`:""}`)}console.log(),console.log(yn.gray(`Use one with: ${u.commands[0]} create "<topic>" --template <id>`))}catch(n){a(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{writeFile as Zv}from"fs/promises";import{Command as eI}from"commander";import tI from"ora";var Kl=new eI("transcript").description("Fetch a YouTube video's transcript").argument("<url>","YouTube URL or 11-character video id").option("--team-id <id>","Workspace ID").option("--language <codes>","Comma-separated language priority list, e.g. 'en,de' or 'asr-en'").option("--no-timestamps","Print plain text without [m:ss] prefixes").option("-o, --output <path>","Save the transcript to a file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{let n=e.format,r=n==="human"?tI("Fetching transcript...").start():null;try{let o=await Ba(t,e.teamId,e.language);r?.stop();let i=e.timestamps?o.cues.map(s=>`[${s.timestamp}] ${s.text}`).join(`
261
+ `):o.cues.map(s=>s.text).join(`
262
+ `);if(e.output&&(await Zv(e.output,i,"utf-8"),n==="human"&&k(`Transcript saved to: ${e.output}`)),n==="json"){l(o);return}if(n==="quiet"){console.log(i);return}console.log(),console.log(`Title: ${o.title}`),o.channelName&&console.log(`Channel: ${o.channelName}`),o.durationFormatted&&console.log(`Duration: ${o.durationFormatted}`),console.log(`Language: ${o.language??"unknown"}${o.isAutoGenerated?" (auto-generated)":""}`),console.log(`Words: ${o.wordCount.toLocaleString()}`),console.log(`URL: ${o.url}`),o.truncated&&_("Transcript was truncated to fit the response budget."),e.output||(console.log(),console.log("--- Transcript ---"),console.log(i))}catch(o){r?.stop(),a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}});import{mkdir as nI,writeFile as Jl}from"fs/promises";import{dirname as rI}from"path";import{Command as kr}from"commander";import Xl from"ora";var zl="en-US-Neural2-C",Hl="gemini",oI=new kr("generate").description("Generate speech from text").requiredOption("-t, --text <text>","Text to convert to speech").requiredOption("-o, --output <path>","Output file path").option("--voice-id <voiceId>","Voice ID (e.g., ElevenLabs: 21m00Tcm4TlvDq8ikWAM)").option("--voice <voice>",`Voice name (default: ${zl})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${Hl})`).option("-m, --model <model>","Model (provider-specific)").option("-s, --speed <speed>","Speech speed 0.1-4.0 (default: 1.0)").option("-l, --lang <lang>","Language or locale hint (for example en-US)").option("--speakers <json>",`Multi-speaker (Gemini, max 2): '[{"name":"Joe","voice":"Kore"},{"name":"Jane","voice":"Puck"}]'`).option("-i, --instructions <text>","Style prompt (OpenAI gpt-4o-mini-tts): tone, accent, speed, emotion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.format,n=e==="human"?Xl("Generating speech...").start():null,r;t.speed&&(r=parseFloat(t.speed),(Number.isNaN(r)||r<.1||r>4)&&(n?.stop(),a("Speed must be between 0.1 and 4.0"),process.exit(d.INVALID_INPUT)));let o;if(t.speakers)try{o=JSON.parse(t.speakers),(!Array.isArray(o)||o.length===0||o.length>2||o.some(s=>!s||typeof s!="object"||typeof s.name!="string"||!s.name.trim()||typeof s.voice!="string"||!s.voice.trim()))&&(n?.stop(),a("Speakers must be an array with 1-2 name/voice items"),process.exit(d.INVALID_INPUT))}catch{n?.stop(),a(`Invalid --speakers JSON. Example: '[{"name":"Joe","voice":"Kore"}]'`),process.exit(d.INVALID_INPUT)}let i;try{let s=t.voiceId,c=t.voice||zl,p=t.provider||Hl,f={};o&&(f.gemini={speakers:o}),t.instructions&&(f.openai={instructions:t.instructions});let h=await La({text:t.text,options:{language:t.lang,provider:p,voiceId:s,voice:c,model:t.model,speed:r,providerOptions:Object.keys(f).length>0?f:void 0}});i=h.requestId,n?.stop();let v=t.output.endsWith(`.${h.format}`)?t.output:`${t.output}.${h.format}`;await nI(rI(v),{recursive:!0}),await Jl(v,h.audioData);let x=v.replace(/\.[^.]+$/,".txt");if(await Jl(x,t.text,"utf-8"),e==="json"){l({status:"completed",output:v,audioUrl:h.audioUrl,duration:h.duration,provider:h.provider,format:h.format,voice_id:h.voiceId??null,voice:h.voice??c,model:h.model??t.model??null,speed:h.speed??r??1,lang:h.language??t.lang??null,langApplied:h.langApplied??!1,timestamps:h.timestamps??null,words:h.wordTimings??null});return}if(e==="quiet"){console.log(v);return}k(`Saved to: ${v}`),w(`Duration: ${h.duration.toFixed(2)}s`),w(`Provider: ${h.provider}`)}catch(s){n?.stop(),a(fe(s,i),e),process.exit(d.GENERAL_ERROR)}}),iI=new kr("voices").description("List available voices").option("-p, --provider <provider>","Filter by provider: gemini, elevenlabs, openai").option("-f, --format <format>","Output format: human, json",b("--format",["human","json"]),"human").action(async t=>{let e=t.format==="human"?Xl("Fetching voices...").start():null;try{let n=await ja(t.provider);if(e?.stop(),t.format==="json"){l(n.voices);return}if(Array.isArray(n.voices)){let r=t.provider?.toUpperCase()||"VOICES";console.log(),console.log(`${r} Voices:`),console.log("-".repeat(50));for(let o of n.voices)console.log(` ${o.name} (${o.id})`),console.log(` ${o.description}`)}else for(let[r,o]of Object.entries(n.voices))if(!(!o||o.length===0)){console.log(),console.log(`${r.toUpperCase()} Voices:`),console.log("-".repeat(50));for(let i of o)console.log(` ${i.name} (${i.id})`),console.log(` ${i.description}`)}}catch(n){e?.stop(),a(n instanceof Error?n.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),aI=new kr("status").description("Read speech generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-f, --format <format>","Output format: json",b("--format",["json"]),"json").action(async(t,e)=>{try{l(await I("generateSpeech",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),Yl=new kr("tts").description("Text-to-speech commands").addCommand(oI).addCommand(iI).addCommand(aI);import{execSync as Rr,spawnSync as xI}from"child_process";import{access as Pi,readFile as kI,rm as am}from"fs/promises";import{resolve as wn}from"path";import ne from"chalk";import{Command as ie}from"commander";import RI from"ffmpeg-static";import sm from"ora";import{mkdir as sI}from"fs/promises";import{join as dI}from"path";import{Command as bn}from"commander";import Zl from"ora";var cI=5e3,lI=120,Ql=5;function mI(t,e){return[...e,t]}function uI(t,e){try{let n=new URL(t);if(n.protocol!=="https:"&&n.protocol!=="http:")throw new Error;return n.toString()}catch{throw new Error(`${e} must be a public HTTP(S) URL`)}}function em(t){if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t))throw new Error("Source video id must be a UUID");return t}function pI(t){if(t.mode&&!["speed","precision"].includes(t.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:uI(t.audioUrl,"Audio URL"),...t.mode?{mode:t.mode}:{},sourceVideoId:em(t.sourceVideoId)}}function gI(t){let e=[],n=new Set;for(let o of t.targetLanguage){let i=o.trim(),s=i.toLocaleLowerCase("en-US");!i||n.has(s)||(n.add(s),e.push(i))}if(e.length===0)throw new Error("Provide at least one target language");if(e.length>Ql)throw new Error(`Provide at most ${Ql} target languages`);if(e.find(o=>o.length<2||o.length>40))throw new Error("Target languages must be between 2 and 40 characters");return{...t.captions?{captions:!0}:{},sourceVideoId:em(t.sourceVideoId),targetLanguages:e}}function fI(t){return t.error||t.status==="failed"||t.status==="cancelled"?"failed":t.done||t.status==="completed"?"completed":t.status==="in_progress"||t.status==="processing"?"processing":"pending"}function Ai(t){return{requestId:t.runId,status:fI(t),...t.entity?.url?{videoUrl:t.entity.url}:{},...t.output?{output:t.output}:{},...t.error?{error:se(t.error)}:{}}}function tm(t){return{requestId:t.runId,status:"pending"}}async function nm(t,e){return ce(async()=>Ai(await I(t,e)),lI,cI)}function St(t,e){if(e==="json"){l(t);return}if(e==="quiet"){console.log(t.videoUrl??t.requestId);return}w(`Request ID: ${t.requestId}`),w(`Status: ${t.status}`),t.videoUrl&&k(`Video URL: ${t.videoUrl}`),t.error&&a(`Error: ${t.error}`)}function hI(t){return Array.isArray(t?.languages)?t.languages.filter(e=>{if(!e||typeof e!="object"||Array.isArray(e))return!1;let n=e;return typeof n.language=="string"&&(n.status==="completed"||n.status==="failed")&&typeof n.videoId=="string"&&(n.videoUrl===null||typeof n.videoUrl=="string")}):[]}function yI(t){return`${t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function bI(t,e){let n=yI(t);if(!e.has(n))return e.add(n),n;let r=n.slice(0,-4),o=2;for(;e.has(`${r}-${o}.mp4`);)o+=1;let i=`${r}-${o}.mp4`;return e.add(i),i}async function wI(t,e){let n=hI(t.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await sI(e,{recursive:!0});let r=[],o=new Set;for(let i of n){let s=dI(e,bI(i.language,o));await te(i.videoUrl,s),r.push({language:i.language,path:s})}return r}var vI=new bn("status").description("Check a video lip-sync request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(t,e){let r=R(this,e).format??"human";try{St(Ai(await I("lipsyncVideo",t)),r)}catch(o){a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),rm=new bn("lipsync").description("Re-voice a ready workspace video with a public audio URL").requiredOption("--source-video-id <uuid>","READY workspace video UUID").requiredOption("--audio-url <url>","Public replacement voice audio URL").option("--mode <mode>","Quality mode: speed or precision","speed").requiredOption("-o, --output <path>","Local output video path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.format==="human"?Zl("Starting video lip-sync...").start():null,n;try{let r=await za(pI(t));if(n=r.runId,!t.wait){e?.stop(),St(tm(r),t.format);return}e&&(e.text="Waiting for video lip-sync...");let o=await nm("lipsyncVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video lip-sync failed");if(!o.videoUrl)throw new Error("Video lip-sync completed without a video URL");e&&(e.text="Downloading lip-synced video..."),await te(o.videoUrl,t.output),e?.stop(),St(o,t.format),t.format==="human"&&k(`Saved to: ${t.output}`)}catch(r){e?.stop(),a(fe(r,n),t.format),process.exit(d.GENERAL_ERROR)}}).addCommand(vI),om=new bn("translate-languages").description("List supported video translation target languages").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{try{let e=await Ha();if(t.format==="json")l({languages:e});else for(let n of e)console.log(n)}catch(e){a(e instanceof Error?e.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),II=new bn("status").description("Check a video translation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(t,e){let r=R(this,e).format??"human";try{St(Ai(await I("translateVideo",t)),r)}catch(o){a(o instanceof Error?o.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),im=new bn("translate").description("Translate a ready workspace video into one or more languages").requiredOption("--source-video-id <uuid>","READY workspace video UUID").option("--target-language <language>","Target language (repeatable)",mI,[]).option("--captions","Burn provider-generated captions into translated videos").requiredOption("--output-dir <path>","Directory for translated videos").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.format==="human"?Zl("Starting video translation...").start():null,n;try{let r=await Xa(gI(t));if(n=r.runId,!t.wait){e?.stop(),St(tm(r),t.format);return}e&&(e.text="Waiting for video translations...");let o=await nm("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");e&&(e.text="Downloading translated videos...");let i=await wI(o,t.outputDir);if(e?.stop(),t.format==="json")l({...o,downloads:i});else if(t.format==="quiet")for(let s of i)console.log(s.path);else{St(o,t.format);for(let s of i)k(`${s.language}: ${s.path}`)}}catch(r){e?.stop(),a(fe(r,n),t.format),process.exit(d.GENERAL_ERROR)}}).addCommand(II);async function CI(){return process.stdin.isTTY?null:new Promise(t=>{let e="",n=!1;process.stdin.setEncoding("utf-8"),process.stdin.on("data",r=>{e+=r}),process.stdin.on("end",()=>{n||(n=!0,t(e.trim()||null))}),process.stdin.on("error",()=>{n||(n=!0,t(null))}),setTimeout(()=>{!n&&!e&&(n=!0,t(null))},500)})}function SI(t){let e=t?.trim().toLowerCase();if(!(!e||e==="any"||e==="all"))return e==="web"||e==="stock"?[e]:void 0}var EI=new ie("find").description("Find video clips across the web and licensed stock").argument("<query>","Search query").option("-n, --max-results <count>","Maximum number of results","10").option("-o, --orientation <type>","Video orientation: landscape, portrait, square, any","any").option("-l, --license <type>","License type: free, premium, any","free").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(t,e)=>{let{maxResults:n,orientation:r,license:o,format:i}=e,s=i==="human"?sm("Finding videos...").start():null;try{let c=await Fa({query:t,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:SI(e.source)}});s?.stop();let p=c.data.results.flatMap(f=>f.results);if(i==="json"){l(c);return}if(i==="quiet"){p.forEach(f=>{console.log(f.embedUrl||f.previewUrl||f.thumbnailUrl)});return}if(p.length===0){w("No videos found");return}k(`Found ${p.length} videos for "${t}"`),console.log(),p.forEach((f,h)=>{let v=f.kind==="embed";console.log(`[${h+1}] ${f.title}`),console.log(` ${v?"Embed":"URL"}: ${f.embedUrl||f.previewUrl||f.thumbnailUrl}`),console.log(v?` Duration: ${f.duration}s | Embed only \u2014 plays in the host player, do not download`:` Duration: ${f.duration}s | Size: ${f.width}x${f.height}`),console.log(` Provider: ${f.provider}`),console.log()})}catch(c){s?.stop(),a(c instanceof Error?c.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),$I=new ie("create").description("Generate one video from a pinned storyboard revision").requiredOption("--storyboard-revision <id>","Immutable storyboard revision UUID").option("--source-video <id>","Ready video from an earlier create call to use as base footage").option("--release","Render at 720p for release. Costs more; drafts are 480p by default").option("--team-id <id>","Workspace ID").option("--approval-receipt <receipt>","Receipt returned by the browser confirmation URL; omit on the first call to get that URL").requiredOption("--idempotency-key <key>","Stable invocation key bound into the approval receipt").option("--yes","Approve paid video generation").action(async t=>{if(!t.yes)return a("Pass --yes to approve video generation");try{l(await Ya({quality:t.release?"release":void 0,sourceVideoId:t.sourceVideo,storyboardRevisionId:t.storyboardRevision,teamId:t.teamId},t.approvalReceipt,t.idempotencyKey))}catch(e){a(e instanceof Error?e.message:"Generation failed"),process.exit(d.GENERAL_ERROR)}});async function dm(t){let e=t==="-"?await CI():await kI(t,"utf-8");if(!e?.trim())throw new Error(t==="-"?"No storyboard Markdown was received on stdin":`Storyboard file is empty: ${t}`);return e}async function cm(t,e={}){if(t)return t.length===1&&t[0]==="none"?[]:Promise.all(t.map(async n=>{let r;try{let x=JSON.parse(n);if(!x||typeof x!="object"||Array.isArray(x))throw new Error("Media binding must be a JSON object");r=x}catch(x){throw new Error(`Invalid --media binding. Pass one JSON object per binding, for example '{"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}'.`,{cause:x})}let o=Re(r.handle),i=Re(r.path),s=Re(r.fileUrl)??Re(r.url),c=Re(r.purpose),p=Re(r.videoRole),f=Re(r.analysisId)??Re(r.analysis);if(!o||!i&&!s||!c)throw new Error("Invalid --media binding. handle, purpose, and either path or url are required strings.");if(i&&s)throw new Error("A media binding cannot contain both path and url.");if(i&&c==="source"&&f)throw new Error("A source analysis is bound to the original uploaded URL. Reuse the url/name/mime/size binding printed by 'video reference analyze' instead of uploading path again.");if(i&&!e.uploadIdempotencyKey)throw new Error("Local storyboard media requires the command idempotency key.");let h=i?await de(wn(i),{idempotencyKey:`${e.uploadIdempotencyKey}:media:${o}`}):{name:Re(r.name),size:Number(r.size),type:Re(r.mime),url:s};if(!h.name||!h.type||!h.url||!Number.isSafeInteger(h.size)||h.size<=0)throw new Error(`URL media binding "${n}" requires name, mime, and positive integer size.`);let v=h.type.startsWith("video/")?"video":h.type.startsWith("audio/")?"audio":h.type.startsWith("image/")?"image":null;if(!v)throw new Error(`Unsupported media type for ${i??s}: ${h.type}`);if(!["source","style","identity","required"].includes(c))throw new Error(`Invalid media purpose: ${c}`);if(p&&!["reference","first-frame","last-frame"].includes(p))throw new Error(`Invalid videoRole: ${p}`);if(p&&v!=="image")throw new Error("videoRole is supported only for image bindings.");return{...f?{analysisId:f}:{},fileUrl:h.url,handle:o,kind:v,mime:h.type,name:h.name,purpose:c,size:h.size,...p?{videoRole:p}:{}}}))}function Re(t){return typeof t=="string"&&t.length>0?t:void 0}var TI=new ie("create").description("Create a versioned Markdown video storyboard").requiredOption("--file <path>","Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact create").option("--media <binding...>",'One JSON binding per asset: {"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}').option("--team-id <id>","Workspace ID").action(async t=>{try{l(await m("createVideoStoryboard",{aspectRatio:t.aspect,durationSec:Number(t.duration),mediaBindings:await cm(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardMarkdown:await dm(t.file),teamId:t.teamId,title:t.title},t.idempotencyKey))}catch(e){a(e instanceof Error?e.message:"Storyboard creation failed"),process.exit(d.GENERAL_ERROR)}}),AI=new ie("revise").description("Append an immutable revision to a video storyboard").argument("<storyboard-id>","Storyboard UUID").requiredOption("--base-revision <id>","Revision UUID that was edited").requiredOption("--file <path>","Complete Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Replacement artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact revision").option("--change-summary <text>","Short description of this revision").option("--media <binding...>",'Replace media bindings with one JSON object per asset; use the JSON printed by "video reference analyze" for analyzed source video').option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await m("reviseVideoStoryboard",{aspectRatio:e.aspect,baseRevisionId:e.baseRevision,changeSummary:e.changeSummary,durationSec:Number(e.duration),mediaBindings:await cm(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardId:t,storyboardMarkdown:await dm(e.file),teamId:e.teamId,title:e.title},e.idempotencyKey))}catch(n){a(n instanceof Error?n.message:"Storyboard revision failed"),process.exit(d.GENERAL_ERROR)}}),PI=new ie("show").description("Read a storyboard; print Markdown unless --json is used").argument("<storyboard-id>","Storyboard UUID").option("--revision <id>","Read one immutable revision UUID").option("--team-id <id>","Workspace ID").option("--json","Print the complete structured response").action(async(t,e)=>{try{let n=await m("readVideoStoryboard",{revisionId:e.revision,storyboardId:t,teamId:e.teamId});if(e.json){l(n);return}console.error(`${n.storyboard.title} \xB7 revision ${n.storyboard.revision.versionNumber} (${n.storyboard.revision.id})`),console.log(n.storyboard.revision.storyboardMarkdown)}catch(n){a(n instanceof Error?n.message:"Storyboard read failed"),process.exit(d.GENERAL_ERROR)}}),OI=new ie("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(TI).addCommand(AI).addCommand(PI),lm=new ie("analyze").description("Upload and analyze a reference video; its analysisId is the only analysis video generation consumes").requiredOption("--file <path>","Local reference video").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact analysis").option("--user-request <text>","What the analysis should focus on").option("--team-id <id>","Workspace ID").option("--no-wait","Return the durable run immediately").option("--json","Print the complete structured result").action(async t=>{try{let e=await de(wn(t.file),{idempotencyKey:`video-reference-analysis:${t.idempotencyKey}:source`});if(!e.type.startsWith("video/"))throw new Error(`Reference analysis requires a video, got ${e.type}`);let n=await Qa({idempotencyKey:t.idempotencyKey,sourceUrl:e.url,teamId:t.teamId,userRequest:t.userRequest}),r={analysisId:n.runId,fileUrl:e.url,handle:"source-video",kind:"video",mime:e.type,name:e.name,purpose:"source",size:e.size};if(t.wait===!1){l({...n,binding:r,source:e});return}let o=await Za(n.runId,t.teamId);if(t.json){l({...o,binding:r,source:e});return}let i=o.output?.analysis??{};console.log(typeof i.promptContext=="string"?i.promptContext:JSON.stringify(o.output,null,2)),console.error(`Analysis run: ${n.runId}`),console.error(`Storyboard media JSON: ${JSON.stringify(r)}`)}catch(e){a(e instanceof Error?e.message:"Reference analysis failed"),process.exit(d.GENERAL_ERROR)}});lm.addHelpText("after",`
263
+ ${ne.gray("# Prints an analysisId plus a ready storyboard media binding. Pass that")}
264
+ ${ne.gray("# binding to video storyboard create/revise --media; generation reads the")}
265
+ ${ne.gray("# analysis from the analysisId, never from local files.")}
266
+ `);var DI=new ie("status").description("Read a video-reference analysis run").argument("<run-id>","Analysis run UUID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{let n=await I("analyzeVideoReference",t,e.teamId);l(n);let r=Kr(n);if(r)throw new Error(r)}catch(n){a(n instanceof Error?n.message:"Status read failed"),process.exit(d.GENERAL_ERROR)}}),NI=new ie("reference").description("Upload and inspect reusable video references").addCommand(lm).addCommand(DI),_I=new ie("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{let n=await I("createVideo",t,e.teamId);l(n);let r=Kr(n);if(r)throw new Error(r)}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),LI=new ie("inject").description("Inject thumbnail into video (first frame + file icon)").requiredOption("-i, --video <path>","Input video file").requiredOption("-t, --thumbnail <path>","Thumbnail image").option("-o, --output <path>","Output video (default: video-with-thumb.mp4)").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async t=>{let e=t.format,n=e==="human"?sm("Injecting thumbnail...").start():null;try{let r=wn(t.video),o=wn(t.thumbnail),i=t.output?wn(t.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await Pi(r),await Pi(o);let s=RI;if(s)try{await Pi(s)}catch{s=null}if(!s)try{s=Rr("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let c=xI(s,["-i",r],{encoding:"utf8"});if(c.error)throw new Error(`Failed to probe video: ${c.error.message}`);let p=(c.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!p)throw new Error("Could not detect video dimensions");let[,f,h]=p;n&&(n.text="Creating thumbnail frame...");let v="/tmp/cc-thumb-frame.mp4";Rr(`${s} -y -loop 1 -i "${o}" -vf "scale=${f}:${h}:force_original_aspect_ratio=decrease,pad=${f}:${h}:(ow-iw)/2:(oh-ih)/2,setsar=1" -t 0.033 -r 30 -c:v libx264 -pix_fmt yuv420p "${v}"`,{stdio:"pipe"}),n&&(n.text="Concatenating with video...");let x="/tmp/cc-concat-video.mp4";if(Rr(`${s} -y -i "${v}" -i "${r}" -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" -map "[v]" -map 1:a -c:v libx264 -preset ultrafast -crf 18 -c:a copy "${x}"`,{stdio:"pipe"}),n&&(n.text="Adding file icon thumbnail..."),Rr(`${s} -y -i "${x}" -i "${o}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await am(v,{force:!0}),await am(x,{force:!0}),n?.stop(),e==="json"){l({success:!0,output:i});return}if(e==="quiet"){console.log(i);return}k(`Thumbnail injected: ${i}`)}catch(r){n?.stop(),a(r instanceof Error?r.message:"Unknown error"),process.exit(d.GENERAL_ERROR)}}),UI=new ie("thumbnail").description("Thumbnail operations").addCommand(LI),Cr=new ie("video").description("Build a video from scratch \u2014 brief or storyboard to stock and generated footage, translation, lipsync, analysis (for a finished deck, use presentation video)").addCommand(EI).addCommand(UI).addCommand(rm).addCommand(om).addCommand(im).addCommand(Rl);Cr.addCommand($I).addCommand(OI).addCommand(NI).addCommand(_I);Cr.addHelpText("after",`
267
+ ${ne.bold("Examples:")}
268
+ ${ne.gray("# Storyboard-first video from a brief")}
269
+ $ ${u.commands[0]} video storyboard create --file brief.md --duration 60 --aspect 16:9 --idempotency-key launch-1
270
+
271
+ ${ne.gray("# Find licensed stock footage")}
272
+ $ ${u.commands[0]} video find "city timelapse"
273
+
274
+ ${ne.bold("Before generating:")}
275
+ ${ne.gray("# Approve the content, then approve the spend \u2014 two questions. Paste the")}
276
+ ${ne.gray("# storyboard text into your reply and get a yes on it BEFORE pinning a")}
277
+ ${ne.gray("# revision; revising is free and append-only, a pinned revision is not.")}
278
+ ${ne.gray("# The browser confirmation video create requires is about cost and")}
279
+ ${ne.gray("# destination, not the user reading the script. --yes is neither.")}
280
+ $ ${u.commands[0]} video storyboard show <storyboard-id>
281
+ $ ${u.commands[0]} video storyboard revise <storyboard-id> --base-revision <revision-id> --file brief-v2.md --idempotency-key launch-2
282
+
283
+ ${ne.bold("See also:")}
284
+ ${ne.gray("# Already have a deck? Render it to MP4 (narration, avatar, captions)")}
285
+ $ ${u.commands[0]} presentation video <slug>
286
+ `);import{Command as Oi}from"commander";var jI=new Oi("create").description("Start background visual-abstract generation").argument("<brief>","Dense source brief").option("--title <title>","Artifact title").option("--aspect <ratio>","1:1, 16:9, 9:16, 4:3, or 3:4","1:1").option("--quality <tier>","fast, best, or enterprise","best").option("--preset <preset>","Output preset","executive-one-pager").option("--output <type>","raster or vector","raster").option("--branding-id <id>","Branding ID").option("--reference-url <url...>","Up to three image URLs to use as visual references").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(t,e)=>{if(!e.yes)return a("Pass --yes to approve visual-abstract generation");try{let n=Array.isArray(e.referenceUrl)?e.referenceUrl.slice(0,3).map((r,o)=>({label:`visual-reference-${o+1}`,url:r})):void 0;l(await m("createVisualAbstract",{approvalReceipt:"cli:--yes",aspectRatio:e.aspect,brandingId:e.brandingId,brief:t,outputPreset:e.preset,outputType:e.output,qualityTier:e.quality,referenceImages:n,teamId:e.teamId,title:e.title}))}catch(n){a(n instanceof Error?n.message:"Generation failed"),process.exit(d.GENERAL_ERROR)}}),qI=new Oi("status").description("Read visual-abstract generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(t,e)=>{try{l(await I("createVisualAbstract",t,e.teamId))}catch(n){a(n instanceof Error?n.message:"Status failed"),process.exit(d.GENERAL_ERROR)}}),mm=new Oi("visual-abstract").description("Generate a one-page visual abstract graphic (raster or vector) from a dense brief").addCommand(jI).addCommand(qI);var Di=[Cc,Nc,cd,vc,Yl,Zc,Fc,Lc,Cr,Ri,Kl,Fl,ki,Si,Ko,Uc,ti,tl,sd,ld,mm,Mc,Zs,Io,Vc,Wo,$c,Ac,Yo,Sc,Gl,Wl];function um(t){for(let e of Di)t.addCommand(e)}function pm(t,e,n){let r=e?`${e} ${t.name()}`:t.name();n.set(r,{arguments:t.registeredArguments.filter(o=>o.required).map(o=>`<${o.name()}>`),requiredOptions:t.options.filter(o=>o.mandatory).map(o=>o.long).filter(o=>!!o)});for(let o of t.commands)pm(o,r,n)}var Sr;function VI(){if(!Sr){Sr=new Map;for(let t of Di)pm(t,"",Sr)}return Sr}function gm(t){let e=VI().get(t);return e?[...e.arguments,...e.requiredOptions.map(n=>`${n} \u2026`)].join(" "):""}var fm=["presentations","media","branding","knowledge","research","artifacts","agents","support"],Ni={agents:"Scheduled agents and agent memory",artifacts:"Polls, microsites, ad sets and visual abstracts",branding:"Brand profiles, tokens, logos and competitors",knowledge:"Library documents, folders and the Knowledge Hub",media:"Voiceover, music, SFX, images, stock footage, avatars and video",presentations:"Decks, PowerPoint import, speaker notes and deck\u2192MP4",research:"Scraping, transcripts, web/news/image search and extraction",support:"Filing and following bug reports, questions and feature requests"},MI="other";function FI(t){let e=t.category?.trim();return e&&e.length>0?e:MI}function hm(t){let e=fm.indexOf(t);return e===-1?fm.length:e}function vn(t){let e=new Map;for(let n of t){let r=FI(n),o=e.get(r);o?o.push(n):e.set(r,[n])}return[...e.entries()].sort(([n],[r])=>hm(n)-hm(r)||n.localeCompare(r)).map(([n,r])=>({capabilities:[...r].sort((o,i)=>o.name.localeCompare(i.name)),category:n}))}function _i(t){return t.lifecycle?.mode==="background"}function Li(t,e){let n=t.lifecycle?.status?.cliCommand?.trim();if(!(!_i(t)||!n))return`${e} ${n} <run-id>`}function BI(t){switch(t.billing){case"free":return"free";case"quota":return"plan quota";case"fixed":return"credits (fixed)";case"dynamic":return"credits (usage-based)";case"delegated":return"credits (on completion)";default:return"unknown \u2014 check `capabilities`"}}function Er(t){return t.replace(/\|/g,"\\|").replace(/\r?\n/g," ").trim()}function GI(t,e){let n=Li(t,e);return n?`run id \u2014 poll \`${n}\``:`immediate (${t.operation??"call"})`}function Be(t,e){let n=["| Command | What it does | Takes | Returns | Cost | Scopes |","|---|---|---|---|---|---|"],r=t.map(o=>{let i=gm(o.name),s=o.scopes?.length?o.scopes.map(c=>`\`${c}\``).join(", "):"\u2014";return`| \`${e} ${Er(o.name)}\` | ${Er(o.description??"")} | ${i?`\`${Er(i)}\``:"\u2014"} | ${GI(o,e)} | ${BI(o)} | ${s} |`});return[...n,...r].join(`
287
+ `)}function re(t,e){if(t.source==="live")return`<!-- Generated from the live ${e.name} capability catalog (v${t.catalogVersion}, ${t.capabilities.length} capabilities) at install time. Re-run \`${e.cmd} skill install\` to refresh. -->`;let n=t.reason?` Reason: ${Er(t.reason).replace(/\.+$/,"")}.`:"";return`<!-- STALE-RISK: the live catalog could not be read at install time, so this was rendered from the snapshot baked into the installed CLI (v${t.catalogVersion}, ${t.capabilities.length} capabilities).${n} Run \`${e.cmd} login\` then \`${e.cmd} skill install --force\` to regenerate from the live catalog, and treat \`${e.cmd} capabilities\` as authoritative over this file. -->`}function ym(t){return t.map(e=>`- [${e}](#${e.toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/ /g,"-")})`).join(`
288
+ `)}var WI=["get","presentation video prepare","presentation video inspect","presentation video settings","presentation video edit","presentation video presenter","presentation video","presentation video versions","presentation video restore","presentation video refresh","presentation video-narration","presentation speaker-notes","video library list","avatar options"];function KI(t){let e=new Map(t.map(n=>[n.name,n]));return WI.map(n=>e.get(n)).filter(n=>n!==void 0)}function Et(t,e){let{cmd:n}=t,r=KI(e.capabilities),o=e.capabilities.find(s=>s.name==="presentation video"),i=o?Li(o,n)??`${n} presentation video status <run-id>`:`${n} presentation video status <run-id>`;return`${re(e,t)}
206
289
 
207
290
  # Deck \u2192 MP4 (\`${n} presentation video\`)
208
291
 
@@ -437,11 +520,11 @@ not maintain a second copy.
437
520
 
438
521
  ## Every capability in this flow
439
522
 
440
- ${Ke(r,n)}
523
+ ${Be(r,n)}
441
524
 
442
525
  If something you need is not in this table, do not conclude it is missing \u2014
443
526
  run \`${n} capabilities --search video\`.
444
- `}var Tp=["video reference analyze","video storyboard create","video storyboard revise","video storyboard show","video create","search video","video translate-languages","video translate","video lipsync","media analyze","media import","video library list"];function vr(e){let t=new Map(e.map(n=>[n.name,n]));return Tp.map(n=>t.get(n)).filter(n=>n!==void 0)}function on(e,t){let{cmd:n}=e,r=vr(t.capabilities);return`${pe(t,e)}
527
+ `}var JI=["video reference analyze","video storyboard create","video storyboard revise","video storyboard show","video create","search video","video translate-languages","video translate","video lipsync","media analyze","media import","video library list"];function Ui(t){let e=new Map(t.map(n=>[n.name,n]));return JI.map(n=>e.get(n)).filter(n=>n!==void 0)}function $r(t,e){let{cmd:n}=t,r=Ui(e.capabilities);return`${re(e,t)}
445
528
 
446
529
  # Video from scratch (\`${n} video\`)
447
530
 
@@ -611,250 +694,286 @@ ${n} video library list <project-id> # reusable clips and rec
611
694
 
612
695
  ## Every capability in this flow
613
696
 
614
- ${Ke(r,n)}
697
+ ${Be(r,n)}
615
698
 
616
699
  If something you need is not in this table, do not conclude it is missing \u2014
617
700
  run \`${n} capabilities --search video\`.
618
- `}var Ep=12,Ap={media:"video.md",presentations:"deck-to-video.md"};function Op(e,t,n,r){let{cmd:o}=e,i=yr[n]??n,a=r.filter(br),d=r.filter(p=>p.billing!==void 0&&p.billing!=="free"),l=Ap[n],y=["Every capability",...a.length>0?["Background operations"]:[]];return`${pe(t,e)}
701
+ `}var zI=12,HI={media:"video.md",presentations:"deck-to-video.md"};function XI(t,e,n,r){let{cmd:o}=t,i=Ni[n]??n,s=r.filter(_i),c=r.filter(h=>h.billing!==void 0&&h.billing!=="free"),p=HI[n],f=["Every capability",...s.length>0?["Background operations"]:[]];return`${re(e,t)}
619
702
 
620
703
  # ${n} \u2014 ${i}
621
704
 
622
- ${r.length} capabilit${r.length===1?"y":"ies"} in this category${d.length>0?`, ${d.length} of which ${d.length===1?"costs":"cost"} credits or ${d.length===1?"counts":"count"} against a plan quota`:", all free"}.${l?`
705
+ ${r.length} capabilit${r.length===1?"y":"ies"} in this category${c.length>0?`, ${c.length} of which ${c.length===1?"costs":"cost"} credits or ${c.length===1?"counts":"count"} against a plan quota`:", all free"}.${p?`
623
706
 
624
- Step-by-step flow: [${l}](${l}).`:""}
625
- ${r.length>Ep?`
707
+ Step-by-step flow: [${p}](${p}).`:""}
708
+ ${r.length>zI?`
626
709
  ## Contents
627
710
 
628
- ${ns(y)}
711
+ ${ym(f)}
629
712
  `:""}
630
713
  ## Every capability
631
714
 
632
- ${Ke(r,o)}
633
- ${a.length>0?`
715
+ ${Be(r,o)}
716
+ ${s.length>0?`
634
717
  ## Background operations
635
718
 
636
719
  These return a run id immediately and keep working. Poll the status command
637
720
  until it reports done \u2014 do not assume success from the accept response.
638
721
 
639
- ${a.map(p=>`- \`${o} ${p.name}\` \u2192 \`${o} ${p.lifecycle?.status?.cliCommand??""} <run-id>\`${p.lifecycle?.status?.pollAfterSeconds?` (first poll after ~${p.lifecycle.status.pollAfterSeconds}s)`:""}`).join(`
722
+ ${s.map(h=>`- \`${o} ${h.name}\` \u2192 \`${o} ${h.lifecycle?.status?.cliCommand??""} <run-id>\`${h.lifecycle?.status?.pollAfterSeconds?` (first poll after ~${h.lifecycle.status.pollAfterSeconds}s)`:""}`).join(`
640
723
  `)}
641
724
  `:""}
642
725
  Anything missing here? Run \`${o} capabilities --category ${n}\` \u2014 the
643
726
  catalog is authoritative and always current; this file is a snapshot of it.
644
- `}function rs(e,t,n={}){let r=[{content:rn(e,t),name:"deck-to-video"},{content:on(e,t),name:"video"}];for(let{capabilities:o,category:i}of vt(t.capabilities)){let a=n[i];r.push({content:Op(e,t,i,o)+(a?`
727
+ `}function bm(t,e,n={}){let r=[{content:Et(t,e),name:"deck-to-video"},{content:$r(t,e),name:"video"}];for(let{capabilities:o,category:i}of vn(e.capabilities)){let s=n[i];r.push({content:XI(t,e,i,o)+(s?`
645
728
  ---
646
729
 
647
- ${a}`:""),name:i})}return r}function os(e){let t=[{file:"deck-to-video.md",when:"An existing deck must become an MP4 \u2014 narration, voice, avatar, music, captions."},{file:"video.md",when:"A video is being built from a brief or storyboard, with no deck involved."}];for(let{capabilities:n,category:r}of vt(e.capabilities))t.push({file:`${r}.md`,when:`${yr[r]??r} (${n.length} commands).`});return t}var Pp=[{capability:"create",intent:'"Make me a presentation / deck / slides about X"',reference:"presentations.md",suffix:' "Topic" --context "\u2026"'},{capability:"presentation video prepare",intent:'"Turn my deck into a video / MP4 / narrated video"',reference:"deck-to-video.md",suffix:" <presentation-id> --yes"},{capability:"video storyboard create",intent:'"Make me a video about X" (no deck exists)',reference:"video.md",suffix:" --file ./storyboard.md \u2026"},{capability:"presentation import",intent:'"Import this PowerPoint / .pptx"',reference:"presentations.md",suffix:" --file deck.pptx --mode preserve"},{capability:"presentation speaker-notes",intent:'"Write speaker notes for this deck"',reference:"deck-to-video.md",suffix:" <presentation-id>"},{capability:"presentation video-narration",intent:'"Rewrite the narration on one slide"',reference:"deck-to-video.md",suffix:" <project-id> --slide-id <id>"},{capability:"tts generate",intent:'"Voiceover / narration / read this aloud / TTS"',reference:"media.md",suffix:' -t "Text" -o out.mp3'},{capability:"music generate",intent:'"Background music / a soundtrack"',reference:"media.md"},{capability:"sfx generate",intent:'"Sound effects"',reference:"media.md"},{capability:"mix create",intent:'"Mix this voiceover and music into the video"',reference:"media.md"},{capability:"image generate",intent:'"Generate an image"',reference:"media.md"},{capability:"search images",intent:'"Find a stock photo"',reference:"research.md",suffix:' -q "\u2026"'},{capability:"search video",intent:'"Find stock footage / b-roll"',reference:"video.md",suffix:' "ocean waves"'},{capability:"avatar options",intent:'"Which avatars / presenters / voices can I use?"',reference:"media.md"},{capability:"avatar generate",intent:'"Make a talking-head / avatar clip"',reference:"media.md"},{capability:"video translate",intent:'"Dub / translate this video"',reference:"video.md"},{capability:"video lipsync",intent:'"Re-sync the lips to this new audio"',reference:"video.md"},{capability:"branding extract",intent:'"Match my brand" / "pull branding from this site"',reference:"branding.md",suffix:" <url>"},{capability:"scrape",intent:'"Read this web page"',reference:"research.md",suffix:" https://example.com"},{capability:"transcript",intent:'"Get the transcript of this YouTube video"',reference:"research.md",suffix:" <url>"},{capability:"search web",intent:'"Search the web / find news about X"',reference:"research.md",suffix:' "query"'},{capability:"knowledge search",intent:'"What do we already have on X?"',reference:"knowledge.md"},{capability:"document create",intent:'"Save this as a document" / library filing',reference:"knowledge.md"},{capability:"microsite create",intent:'"Build a landing page / microsite"',reference:"artifacts.md"},{capability:"poll create",intent:'"Make a poll"',reference:"artifacts.md"},{capability:"visual-abstract create",intent:'"One-page visual summary"',reference:"artifacts.md"},{capability:"ad-set create",intent:'"Ad creatives for this campaign"',reference:"artifacts.md"},{capability:"agent create",intent:'"Schedule this to run every week"',reference:"agents.md"}],_p=["capabilities","config","delete","derive","export","footage","ideas","import","list","login","logout","runner","skill","templates","whoami"];function an(e,t=Ot("rendered without a catalog fetch")){let{name:n,cmd:r,pkg:o}=e,i=n.toUpperCase().replace(/[^A-Z0-9]/g,"_"),a=new Map(t.capabilities.map(v=>[v.name,v])),d=Pp.filter(v=>a.has(v.capability)).map(v=>`| ${v.intent} | \`${r} ${v.capability}${v.suffix??""}\` | [${v.reference}](references/${v.reference}) |`).join(`
648
- `),y=vt(t.capabilities).map(({capabilities:v,category:C})=>`${C} (${v.length})`).join(", "),p=os(t).map(({file:v,when:C})=>`| [references/${v}](references/${v}) | ${C} |`).join(`
649
- `),w=[...new Set([...t.capabilities.map(v=>v.name.split(" ")[0]),..._p])].sort().map(v=>`\`${v}\``).join(", ");return`---
650
- name: ${n}
651
- description: >-
652
- Use for ANY request involving presentations, decks, slides, pitch decks, PowerPoint,
653
- speaker notes, or turning a deck into a video \u2014 plus video, MP4 export, narration,
654
- voiceover, TTS, AI music, sound effects, audio mixing, avatars and talking heads,
655
- lipsync, dubbing, stock images and stock footage, brand extraction and design tokens,
656
- microsites, polls, ad creatives, web scraping, YouTube transcripts, and the document
657
- library. Trigger it even when the user never names the product: "make me slides",
658
- "turn this into a video", "add a voiceover", "find b-roll", "match our brand".
659
- ${t.capabilities.length} CLI capabilities, listed in references/.
660
- ---
730
+ ${s}`:""),name:i})}return r}function wm(t){let e=[{file:"deck-to-video.md",when:"An existing deck must become an MP4 \u2014 narration, voice, avatar, music, captions."},{file:"video.md",when:"A video is being built from a brief or storyboard, with no deck involved."}];for(let{capabilities:n,category:r}of vn(t.capabilities))e.push({file:`${r}.md`,when:`${Ni[r]??r} (${n.length} commands).`});return e}function In(t){return[...new Set(t.flatMap(e=>[e.name,...e.lifecycle.status?.cliCommand?[e.lifecycle.status.cliCommand]:[]]))]}function oe(t,e,n,r="direct-operation-smoke"){let o=r==="ui-e2e"?"Browser/product E2E only; it does not execute the built CLI through the HTTP adapter.":"Canonical-operation smoke with adapter assertions; it does not execute a built CLI through the HTTP adapter.";return{level:"partial",boundary:r,kind:"smoke",source:`scripts/lib/deployment-smoke-catalog.ts#${e}`,case:e,run:`pnpm smoke -- run ${t} --url <non-production-deployment>`,claim:`${o} ${n}`}}function Tr(t,e,n){return{level:"partial",boundary:"mocked-adapter-integration",kind:"integration",source:t,case:e,run:`pnpm exec vitest run ${t}`,claim:`In-memory adapter integration with mocked canonical operations; no real HTTP operation or fixture postcondition is reached. ${n}`}}function ji(t,e,n){return{level:"full",boundary:"real-cli-http-journey",kind:"smoke",source:`scripts/lib/deployment-smoke-catalog.ts#${e}`,case:e,run:`pnpm smoke:${t} -- --url http://localhost:3000`,claim:`Built CLI subprocess through the real HTTP adapter, governance, and canonical operation, with a controlled fixture and independently verified postcondition. ${n}`}}var vm="tests/integration/tool-surface/presentations.integration.test.ts",YI="tests/integration/tool-surface/branding.integration.test.ts";function Im(t){switch(t){case"create":return[Tr(vm,"normalizes MCP and CLI starts into the same durable job input","MCP and CLI normalize the same generation input."),oe("presentation","presentation.create","A real deck is generated and persisted.","ui-e2e")];case"export":return[oe("presentation","presentation.export","Real PDF, PPTX, HTML, and PNG exports are validated.","ui-e2e")];case"presentation import":case"presentation import transform":return[oe("presentation-import","presentation.import-powerpoint","A PowerPoint is imported, reviewed, and reopened.","ui-e2e")];case"presentation speaker-notes":case"presentation speaker-notes-status":return[oe("presentation","presentation.speaker-notes","Persisted speaker notes are ready after reload.","ui-e2e")];default:return[]}}function QI(t){return["presentation video inspect","video library list"].includes(t)?[oe("presentation-video-agent-reads","video.presentation.agent-read-surfaces","Canonical agent surfaces share one owned project/source result.")]:["presentation video edit","presentation video refresh","presentation video restore","presentation video versions","presentation video-narration","presentation video-narration-status"].includes(t)?[oe("presentation-video-agent-edits","video.presentation.agent-edit-surfaces","Draft edits and restores persist through canonical agent operations.")]:t==="presentation video presenter"?[oe("presentation-video-scene-presenter","video.presentation.scene-presenter-agent-surfaces","A per-scene presenter override persists across agent surfaces.")]:["presentation video prepare","presentation video settings","presentation video status"].includes(t)?[Tr(vm,`generated MCP and CLI ${t}`,"The integration suite compares matching MCP and CLI adapter results.")]:t==="get"||t.startsWith("presentation speaker-notes")?Im(t):[]}function ZI(t){if(["branding list","branding profile","branding competitor list"].includes(t))return[oe("branding","branding.agent-read-surfaces","Brand reads resolve the same controlled brand across agent surfaces.")];if(t==="branding extract")return[oe("branding","branding.extraction-approval-refusal","Only the approval refusal and no-charge boundary is proven.")];if(t==="branding create")return[oe("branding","branding.create","Creation, idempotency, and plan-limit refusal reach the canonical operation.")];let e=[["branding product","branding.products","Product lifecycle behavior is exercised."],["branding variant","branding.variants","Variant lifecycle behavior is exercised."],["branding version","branding.versions","Version lifecycle behavior is exercised."],["branding voice","branding.voice","Voice document behavior is exercised."],["branding gradient","branding.gradients","Gradient replacement behavior is exercised."],["branding variations","branding.gradients","Variation generation is declared; provider-backed CLI success is not proven."],["branding guardrail","branding.guardrails","Guardrail lifecycle behavior is exercised."],["branding quality","branding.quality","Quality reads and repair refusal are exercised."],["branding sync","branding.sync","A durable linked-deck sync completes."]];for(let[n,r,o]of e)if(t.startsWith(n))return[oe("branding",r,o)];return["branding star","branding default","branding delete"].some(n=>t.startsWith(n))?[oe("branding","branding.lifecycle-pointers","Star, default, and deletion pointers reach canonical operations.")]:t==="branding update"?[oe("branding","branding.record-fields","Rename and parent moves reach updateBrand.")]:t==="branding set"?[Tr(YI,"runs the free brand write on both lanes without an approval receipt","MCP and CLI invoke the same free brand write in memory.")]:[]}function ex(t){return["agent roster list","agent roster get","agent visibility set"].includes(t)?[ji("agent-roster-visibility","agent.roster-visibility","Owner and teammate roster projections, visibility CAS, replay, conflicts, and database postconditions are verified.")]:["agent list","agent get","agent configure","agent pause","agent resume"].includes(t)?[ji("agent-management","agent.management-primitives","Owned-Agent reads, configuration CAS, schedule transitions, replay, conflicts, and database postconditions are verified.")]:[]}function tx(t,e){return t==="presentation"?Im(e):t==="presentation-video"?QI(e):t==="agents"?ex(e):ZI(e)}function qi(t,e){return In(e).map(n=>{let r=tx(t,n),o=r.length===0?"missing":r.some(i=>i.level==="full")?"full":"partial";return{command:n,evidence:r,level:o}})}function xm(t){return t==="presentation video"||t.startsWith("presentation video ")||t.startsWith("presentation video-")}function Vi(t,e){let n=new Set(e.capabilities.map(r=>r.name));return t.flow.filter(r=>n.has(r))}function nx(t,e){let n=new Set(e.capabilities.map(o=>o.name)),r=(o,i)=>n.has(o)?`- \`${t.cmd} ${o}\` \u2014 ${i}`:void 0;return`# Presentation workflow
661
731
 
662
- ${pe(t,e)}
732
+ Use this flow for decks, not MP4 production or brand-library maintenance.
663
733
 
664
- # ${n} CLI
734
+ 1. Run \`../scripts/check-auth.sh\`, then \`../scripts/check-flow.sh\`.
735
+ 2. Inspect exact flags with \`${t.cmd} <command> --help\`; never infer a flag from another surface.
736
+ 3. Gather source material before generation and pass only user-provided or verified context.
737
+ 4. If the user chose a saved brand, pass its id during creation. Do not claim a brand can be attached to an arbitrary existing deck.
738
+ 5. Retain a background run id and poll the catalog-named status command.
739
+ 6. Resolve the final deck with \`${t.cmd} get\`; export only when requested.
665
740
 
666
- **Install:** \`npm install -g ${o}\`
741
+ ## Useful operations present in this catalog
667
742
 
668
- This file routes; it does not enumerate. The per-capability detail \u2014
669
- command paths, cost, background/poll behaviour, required scopes \u2014 lives in
670
- \`references/\`, generated from the same capability catalog the CLI itself
671
- serves.
743
+ ${[r("create","create a deck from a topic and context"),r("presentation import","import a PowerPoint into a new deck"),r("get","read the resulting presentation"),r("export","export a deck to a supported format"),r("presentation delete","delete only after explicit user intent")].filter(Boolean).join(`
744
+ `)}
672
745
 
673
- ---
746
+ For narration, scenes, presenters, captions, or MP4 output, load \`${t.name}-presentation-video\`.
747
+ `}function rx(t,e){let n=Vi($t.branding,e).map(r=>`- \`${t.cmd} ${r}\``).join(`
748
+ `);return`# Branding workflow
674
749
 
675
- ## Task \u2192 command
750
+ Branding owns saved private and team brand profiles. It does not edit arbitrary deck HTML.
676
751
 
677
- | The user asks for\u2026 | Start here | Detail |
678
- |---|---|---|
679
- ${d}
752
+ 1. Run \`../scripts/check-auth.sh\`, then discover the live surface with \`../scripts/discover-capabilities.sh\`.
753
+ For least privilege, authenticate with \`${t.cmd} login --scopes brands:read,brands:write\`.
754
+ 2. Resolve the workspace or team explicitly when requested.
755
+ 3. List or inspect before mutating. Use the returned brand id; never guess from a name or URL.
756
+ 4. Select a brand during presentation creation. A later sync may propagate changed tokens only to decks already linked to that brand.
757
+ 5. Re-read the profile or sync status and verify the concrete postcondition.
680
758
 
681
- ---
759
+ ## Common flow anchors present in this catalog
682
760
 
683
- ## \`presentation video\` vs \`video\` \u2014 the one confusion that costs money
761
+ ${n||"No common anchors are present in this snapshot; run discovery before acting."}
684
762
 
685
- \`${r} presentation video\` renders an **existing deck** to MP4 (narration,
686
- voice, avatar, music, captions). \`${r} video\` builds a **new** video from a
687
- brief or storyboard and never touches a deck.
763
+ Read [commands.md](commands.md) for every available brand operation and its scopes.
764
+ `}function ox(t,e){let n=Vi($t.agents,e).map(r=>`- \`${t.cmd} ${r}\``).join(`
765
+ `);return`# Agents workflow
688
766
 
689
- They share no state, and picking the wrong one wastes a paid render. There is
690
- no \`video export\` subcommand.
767
+ This skill owns scheduled Mindframes Agents. It is not a guide for software-development agents.
691
768
 
692
- ---
769
+ 1. Run \`../scripts/check-auth.sh\`, then discover the deployed Agents surface with \`../scripts/discover-capabilities.sh\`.
770
+ Use \`${t.cmd} login --scopes agents:read,agents:write\` only when a visibility mutation is required.
771
+ 2. Use \`agent list\` and \`agent get\` for Agents owned by the caller. Use \`agent roster list\` and \`agent roster get\` for the safe team-visible roster projection.
772
+ 3. Never infer global or cross-team discovery. Legacy \`public\` visibility is readable only under the existing same-team roster policy and cannot be newly selected.
773
+ 4. Before changing visibility, read the owned Agent's current visibility. Pass it as \`--expected-visibility\` to \`agent visibility set\`; choose only \`private\` or \`team\`.
774
+ 5. Re-read the owner record and team roster to verify the exact postcondition. Treat \`version_conflict\` and \`idempotency_conflict\` as typed failures, not success.
693
775
 
694
- ## Approve the content, then approve the spend
776
+ ## Common flow anchors present in this catalog
695
777
 
696
- Two different questions, asked at two different moments. "Yes, that is the
697
- video I want" comes first; "yes, spend the credits" comes second. A
698
- confirmation that names a cost and a destination has answered the second
699
- question only \u2014 it never asked the first.
778
+ ${n||"No common anchors are present in this snapshot; run discovery before acting."}
700
779
 
701
- **Anything you authored on the user's behalf, they read before it is
702
- committed.** The storyboard text, the narration script per scene: those are the
703
- user's words, drafted for them, and they are the part most likely to be wrong.
704
- Show the text itself in your reply \u2014 a link, a project id or a file path is not
705
- the user reading it.
780
+ Read [commands.md](commands.md) for current inputs, outputs, scopes, and exact CLI help.
781
+ `}var ix=[{id:1,prompt:"Create a ten-slide investor presentation from my supplied metrics using team brand br_42, then give me the final deck link.",expected_output:"A create-and-verify plan that applies the saved brand only during deck creation.",expectations:["Runs the auth and flow checks before a product operation.","Inspects create help instead of inventing flags.","Passes the chosen brand id during presentation creation.","Polls a background run and resolves the final deck with get."]},{id:2,prompt:"Import ./board-update.pptx and export the resulting presentation as PDF.",expected_output:"An import, verification, and export flow using only real presentation commands.",expectations:["Uses presentation import and reads its help.","Does not route through standalone video or presentation-video commands.","Verifies the imported presentation before export."]},{id:3,prompt:"Turn presentation pr_123 into a narrated vertical MP4 with captions.",expected_output:"A handoff to the presentation-video skill rather than deck creation.",expectations:["Routes to the presentation-video skill.","Does not use the from-scratch video pipeline."]}],ax=[{id:1,prompt:"Make presentation pr_123 a 9:16 MP4 with concise narration and captions, and let me approve before rendering.",expected_output:"A prepare, inspect, settings, render, and status flow with a human spend gate.",expectations:["Runs auth and flow checks before product work.","Prepares and inspects before rendering.","Separates editable preparation from paid render approval.","Polls the exact render status command and verifies the MP4 result."]},{id:2,prompt:"For presentation-video project pv_9, rewrite only slide s_4 narration to be warmer and shorter, then show me the updated draft.",expected_output:"A targeted narration edit and project inspection without starting a render.",expectations:["Uses the named slide narration operation.","Does not start a paid render without a separate request and approval.","Reads the updated project after the edit completes."]},{id:3,prompt:"Create a 30-second product promo from this script; there is no presentation.",expected_output:"A handoff to the standalone video skill.",expectations:["Routes to the standalone video skill because no deck exists.","Does not create a presentation-video project."]}],sx=[{id:1,prompt:"Our team brand logo and fonts changed. Update br_42 and propagate the changes to presentations already linked to it.",expected_output:"A read, update, verify, and linked-deck sync flow over the existing brand.",expectations:["Reads br_42 before mutation.","Verifies the saved brand profile.","Uses sync semantics only for already-linked presentations.","Does not invent arbitrary brand attachment."]},{id:2,prompt:"Find our saved Acme team brand, then create a new quarterly deck using it.",expected_output:"A brand lookup followed by presentation creation with the resolved id.",expectations:["Lists or gets the brand instead of guessing an id.","Hands deck creation to the presentation skill.","Uses the brand id during deck creation."]},{id:3,prompt:"Move slide 4 after slide 7 and replace its hero image.",expected_output:"A handoff to presentation editing, not a branding mutation.",expectations:["Does not trigger brand profile writes.","Routes to presentation editing capabilities."]}],dx=[{id:1,prompt:"Share my private Agent ag_42 with this workspace, but do not make it globally public.",expected_output:"An owner read, compare-and-set visibility mutation to team, and owner plus roster verification flow.",expectations:["Reads the owned Agent before mutation and uses its returned visibility as expectedVisibility.","Selects team rather than inventing public exposure.","Verifies the owner record and team roster after the mutation."]},{id:2,prompt:"Show me the Agents my teammates have shared with our workspace.",expected_output:"A paginated roster list followed by safe roster detail reads when needed.",expectations:["Uses agent roster list rather than owner-only agent list.","Does not claim cross-team or global public search.","Does not expose instructions, credentials, or private configuration."]},{id:3,prompt:"Turn presentation pr_123 into a narrated MP4.",expected_output:"A handoff to the presentation-video skill.",expectations:["Routes to the presentation-video skill, not scheduled Agents.","Does not create or configure an Agent."]}],$t={presentation:{type:"presentation",title:"Presentation",description:t=>`Use whenever the user wants to create, import, inspect, export, organize, share, delete, or edit a ${t} presentation, deck, slides, pitch deck, or PowerPoint. Do not use for turning an existing deck into an MP4 (use ${t}-presentation-video), video from scratch (use ${t}-video), or maintaining saved brands (use ${t}-branding).`,discoveryQuery:"presentation",select:t=>t.category==="presentations"&&!xm(t.name),flow:["create","presentation status","get","export"],workflow:nx,evals:ix},"presentation-video":{type:"presentation-video",title:"Presentation to MP4",description:t=>`Use whenever an existing ${t} presentation or deck must become a narrated video or MP4, or when its narration, scenes, presenter, music, captions, draft versions, or render status must be managed. Do not use for video from a brief with no deck (use ${t}-video), ordinary slide editing (use ${t}-presentation), or brand maintenance (use ${t}-branding).`,discoveryQuery:"presentation video",select:t=>xm(t.name)||t.name==="presentation speaker-notes"||t.name==="get"||t.name==="avatar options"||t.name==="video library list",flow:["presentation video prepare","presentation video inspect","presentation video settings","presentation video","presentation video status"],workflow:Et,evals:ax},branding:{type:"branding",title:"Branding",description:t=>`Use whenever the user wants to discover, create, inspect, or maintain private or team ${t} brand profiles, tokens, logos, fonts, voice, guardrails, products, versions, quality, or linked-presentation updates. Trigger for "use our brand" when a saved brand must first be resolved. Do not use for arbitrary slide edits or presentation-to-MP4 work.`,discoveryQuery:"branding",select:t=>t.category==="branding",flow:["branding list","branding profile","branding set","branding sync"],workflow:rx,evals:sx},agents:{type:"agents",title:"Agents",description:t=>`Use for scheduled ${t} Agents: owned-Agent management, workspace roster discovery, and owner-authorized private/team visibility changes. Do not trigger for generic coding agents, presentation-to-MP4 work, or global/public Agent search.`,discoveryQuery:"agent",select:t=>t.category==="agents",flow:["agent list","agent roster list","agent roster get","agent visibility set"],workflow:ox,evals:dx}};function Ar(t,e){return e.capabilities.filter($t[t].select).sort((n,r)=>n.name.localeCompare(r.name))}function cx(t,e,n){let r=Ar(n.type,e),o=new Set(r.map(s=>s.name)),i=In(r).filter(s=>!o.has(s));return`${re(e,t)}
706
782
 
707
- **Show it before it is pinned, not after.** A storyboard revision is immutable
708
- and a render pins one; narration is what will actually be spoken. Revising is
709
- free and append-only, so the cheap moment to be wrong is before the pin.
783
+ # ${n.title} commands
710
784
 
711
- The material choices belong to the user too \u2014 voice, presenter or avatar,
712
- music, captions, aspect, duration. Offer them rather than choosing silently,
713
- and say what you would pick and why.
785
+ Generated from the capability catalog. It describes ${r.length} callable operations; run \`${t.cmd} capabilities --search "${n.discoveryQuery}"\` for the deployed surface.
714
786
 
715
- ---
787
+ ${Be(r,t.cmd)}
788
+ ${i.length?`## Recovery commands
789
+
790
+ ${i.map(s=>`- \`${t.cmd} ${s}\``).join(`
791
+ `)}
792
+ `:""}
793
+ `}function lx(t,e,n){let r=qi(n.type,Ar(n.type,e)),o=r.map(f=>{let h=f.evidence.length?f.evidence.map(x=>`**${x.kind}** ${x.source} \u2014 ${x.case}`).join("<br>"):"No non-unit evidence registered.",v=f.evidence.length?f.evidence.map(x=>x.claim).join(" "):"Do not claim integration or smoke coverage for this command.";return`| \`${t.cmd} ${f.command}\` | **${f.level.toUpperCase()}** | ${h} | ${v} |`}),i=[...new Set(r.flatMap(f=>f.evidence.map(h=>h.run)))],s=r.filter(f=>f.level==="full").length,c=r.filter(f=>f.level==="partial").length,p=r.length-s-c;return`${re(e,t)}
794
+
795
+ # ${n.title} non-unit evidence
716
796
 
717
- ## A render is a purchase
797
+ Capability registration and unit tests are not command parity evidence. **FULL** requires built CLI \u2192 real HTTP adapter \u2192 governance \u2192 canonical operation \u2192 controlled fixture/provider \u2192 independently verified postcondition. **PARTIAL** names a narrower boundary. **MISSING** has no registered non-unit evidence.
718
798
 
719
- \`${r} presentation video\` and \`${r} video create\` cost credits, take
720
- minutes, and produce the file the user will show other people. Everything
721
- before them \u2014 preparing the project, inspecting it, generating narration,
722
- revising a storyboard, changing settings \u2014 is free or cheap and undoable. So
723
- spend the cheap phase getting it right instead of rushing past it.
799
+ Summary: ${s} full, ${c} partial, ${p} missing.
724
800
 
725
- **This is the second gate, not the only one.** By the time you reach it the
726
- content should already be approved; what you are asking for here is the money
727
- and the target. Confirm what the run is pinned to and start it.
801
+ | Command | Coverage | Executable evidence | Proven claim |
802
+ |---|---|---|---|
803
+ ${o.join(`
804
+ `)}
728
805
 
729
- Where a choice comes from a list, offer the list. \`${r} avatar options\`
730
- prints the real avatar, personal-presenter and voice ids \u2014 shortlist a few and
731
- let the user pick rather than silently choosing one. "No presenter, slides
732
- only" is a common and legitimate answer, so ask instead of assuming either way.
806
+ ## Run registered evidence
807
+
808
+ Smoke runs require an approved non-production target and their catalog prerequisites.
809
+
810
+ \`\`\`bash
811
+ ${i.length?i.join(`
812
+ `):"# No non-unit evidence registered."}
813
+ \`\`\`
814
+ `}function km(t){return`'${t.replace(/'/g,`'"'"'`)}'`}function mx(t,e,n){let r=Ar(n.type,e),o=In(r),i=qi(n.type,r),s=i.filter(f=>f.level==="missing").map(f=>f.command).join(`
815
+ `),c=i.filter(f=>f.level==="partial").map(f=>f.command).join(`
816
+ `),p=km(t.cmd);return[{path:"scripts/check-auth.sh",executable:!0,content:`#!/usr/bin/env sh
817
+ set -eu
818
+ CLI=${p}
819
+ command -v "$CLI" >/dev/null 2>&1 || { echo "$CLI is not installed" >&2; exit 127; }
820
+ "$CLI" whoami
821
+ "$CLI" config refresh >/dev/null
822
+ printf '%s\\n' "Authentication and feature catalog are ready."
823
+ `},{path:"scripts/discover-capabilities.sh",executable:!0,content:`#!/usr/bin/env sh
824
+ set -eu
825
+ CLI=${p}
826
+ QUERY=\${1:-${km(n.discoveryQuery)}}
827
+ "$CLI" capabilities --search "$QUERY" --format json
828
+ `},{path:"scripts/verify-help.sh",executable:!0,content:`#!/usr/bin/env sh
829
+ set -eu
830
+ CLI=${p}
831
+ while IFS= read -r COMMAND_PATH; do
832
+ [ -z "$COMMAND_PATH" ] && continue
833
+ set -- $COMMAND_PATH
834
+ "$CLI" "$@" --help >/dev/null
835
+ done <<'COMMANDS'
836
+ ${o.join(`
837
+ `)}
838
+ COMMANDS
839
+ printf '%s\\n' "Verified help for ${o.length} ${n.type} commands."
840
+ `},{path:"scripts/check-flow.sh",executable:!0,content:`#!/usr/bin/env sh
841
+ set -eu
842
+ CLI=${p}
843
+ AVAILABLE=$("$CLI" capabilities --format quiet)
844
+ while IFS= read -r REQUIRED; do
845
+ [ -z "$REQUIRED" ] && continue
846
+ printf '%s\\n' "$AVAILABLE" | grep -Fqx "$REQUIRED" || { echo "Missing required capability: $REQUIRED" >&2; exit 1; }
847
+ done <<'COMMANDS'
848
+ ${Vi(n,e).join(`
849
+ `)}
850
+ COMMANDS
851
+ printf '%s\\n' "${n.title} flow anchors are available."
852
+ `},{path:"scripts/check-coverage.sh",executable:!0,content:`#!/usr/bin/env sh
853
+ set -eu
854
+ PARTIAL=$(cat <<'COMMANDS'
855
+ ${c}
856
+ COMMANDS
857
+ )
858
+ MISSING=$(cat <<'COMMANDS'
859
+ ${s}
860
+ COMMANDS
861
+ )
862
+ [ -z "$PARTIAL" ] || printf 'PARTIAL command evidence (not parity):\\n%s\\n' "$PARTIAL" >&2
863
+ [ -z "$MISSING" ] || printf 'MISSING command evidence:\\n%s\\n' "$MISSING" >&2
864
+ if [ -n "$PARTIAL" ] || [ -n "$MISSING" ]; then
865
+ printf '%s\\n' 'See references/coverage.md. FULL requires built CLI -> real HTTP -> governance -> operation -> controlled fixture postcondition.' >&2
866
+ exit 1
867
+ fi
868
+ printf '%s\\n' 'Every documented command has full real-CLI journey evidence.'
869
+ `}]}function ux(t,e){return{path:"evals/evals.json",content:`${JSON.stringify({skill_name:t,evals:e.map(n=>({...n,files:[],expectations:[...n.expectations,"Consults references/coverage.md and never reports PARTIAL or MISSING as full command parity."]}))},null,2)}
870
+ `}}function Ce(t,e,n){let r=$t[n],o=`${t.name}-${n}`,i=Ar(n,e).length;return`---
871
+ name: ${o}
872
+ description: >-
873
+ ${r.description(t.name)}
874
+ ---
733
875
 
734
- \`--yes\` is your statement of intent, not the user's consent. Only a person
735
- can give that.
876
+ ${re(e,t)}
736
877
 
737
- Everything free and reversible stays fluent \u2014 never ask permission to inspect a
738
- project or reread a storyboard. The gate is content you authored, and money.
878
+ # ${r.title}
739
879
 
740
- Per-pipeline detail: [deck-to-video.md](references/deck-to-video.md),
741
- [video.md](references/video.md).
880
+ Use this narrow workflow. Do not infer command names or reuse flags from UI, API, or MCP; CLI help and the capability catalog are the executable contract.
742
881
 
743
- ---
882
+ ## Start
744
883
 
745
- ## Composing commands
884
+ 1. Run \`scripts/check-auth.sh\`.
885
+ 2. Run \`scripts/check-flow.sh\` or \`scripts/discover-capabilities.sh [query]\`.
886
+ 3. Read [references/coverage.md](references/coverage.md); MISSING is not covered.
887
+ 4. Read [references/workflow.md](references/workflow.md).
888
+ 5. Read [references/commands.md](references/commands.md) only for the needed operation, then run \`${t.cmd} <command> --help\`.
889
+ 6. Verify returned state; an accepted background run is not completion.
746
890
 
747
- Every table in \`references/\` carries a **Takes** and a **Returns** column. That
748
- is enough to build a chain nobody wrote down. Derive the steps from the data:
749
-
750
- - An id one command returns is the id the next command accepts.
751
- - A **Returns** cell reading \`run id\` means the command works in the
752
- background: poll the exact status command named in that cell until it reports
753
- done, and take the resulting id from there. Never assume success from the
754
- accept response.
755
- - A **Takes** cell shows the required positionals and mandatory flags only. For
756
- the optional ones, run \`${r} <group> <sub> --help\`.
757
- - If you cannot find a step, \`${r} capabilities --search <topic>\` is
758
- authoritative \u2014 not this file.
759
- - Poll; do not wait. Options that block until a long generation finishes
760
- (\`${r} create --wait\`, the default follow mode on
761
- \`${r} presentation speaker-notes\`) stream progress to a TTY a
762
- non-interactive shell does not have, and the command routinely outlives the
763
- tool timeout. Take the run id and poll instead \u2014
764
- \`${r} presentation status <run-id>\`,
765
- \`${r} presentation speaker-notes-status <run-id>\`,
766
- \`${r} presentation video status <run-id>\`.
891
+ ## Bundled resources
767
892
 
893
+ - [references/workflow.md](references/workflow.md) \u2014 domain sequence and boundaries.
894
+ - [references/commands.md](references/commands.md) \u2014 ${i} catalog-derived commands, inputs, results, cost, and scopes.
895
+ - [references/coverage.md](references/coverage.md) \u2014 per-command non-unit evidence and explicit gaps.
896
+ - \`scripts/check-auth.sh\` \u2014 auth and feature-catalog readiness.
897
+ - \`scripts/discover-capabilities.sh\` \u2014 current server capability JSON.
898
+ - \`scripts/verify-help.sh\` \u2014 verify every documented command has CLI help.
899
+ - \`scripts/check-flow.sh\` \u2014 verify minimum flow anchors exist.
900
+ - \`scripts/check-coverage.sh\` \u2014 fail unless every documented command has full real-CLI evidence.
901
+ - \`evals/evals.json\` \u2014 realistic trigger and workflow evaluations.
902
+ `}function Tt(t,e,n){let r=$t[n];return[{name:"commands",content:cx(t,e,r)},{name:"coverage",content:lx(t,e,r)},{name:"workflow",content:r.workflow(t,e)}]}function At(t,e,n){let r=$t[n];return[...mx(t,e,r),ux(`${t.name}-${n}`,r.evals)]}var px=[{capability:"create",intent:'"Make me a presentation / deck / slides about X"',reference:"presentations.md",suffix:' "Topic" --context "\u2026"'},{capability:"presentation video prepare",intent:'"Turn my deck into a video / MP4 / narrated video"',reference:"deck-to-video.md",suffix:" <presentation-id> --yes"},{capability:"video storyboard create",intent:'"Make me a video about X" (no deck exists)',reference:"video.md",suffix:" --file ./storyboard.md \u2026"},{capability:"presentation import",intent:'"Import this PowerPoint / .pptx"',reference:"presentations.md",suffix:" --file deck.pptx --mode preserve"},{capability:"presentation speaker-notes",intent:'"Write speaker notes for this deck"',reference:"deck-to-video.md",suffix:" <presentation-id>"},{capability:"presentation video-narration",intent:'"Rewrite the narration on one slide"',reference:"deck-to-video.md",suffix:" <project-id> --slide-id <id>"},{capability:"tts generate",intent:'"Voiceover / narration / read this aloud / TTS"',reference:"media.md",suffix:' -t "Text" -o out.mp3'},{capability:"music generate",intent:'"Background music / a soundtrack"',reference:"media.md"},{capability:"sfx generate",intent:'"Sound effects"',reference:"media.md"},{capability:"mix create",intent:'"Mix this voiceover and music into the video"',reference:"media.md"},{capability:"image generate",intent:'"Generate an image"',reference:"media.md"},{capability:"image generate",intent:'"An image of this person / product / logo" (keep a real likeness)',reference:"image.md",suffix:' -p "\u2026" --reference-image identity=./photo.jpg --yes'},{capability:"search images",intent:'"Find a stock photo"',reference:"research.md",suffix:' -q "\u2026"'},{capability:"search video",intent:'"Find stock footage / b-roll"',reference:"video.md",suffix:' "ocean waves"'},{capability:"avatar options",intent:'"Which avatars / presenters / voices can I use?"',reference:"media.md"},{capability:"avatar generate",intent:'"Make a talking-head / avatar clip"',reference:"media.md"},{capability:"video translate",intent:'"Dub / translate this video"',reference:"video.md"},{capability:"video lipsync",intent:'"Re-sync the lips to this new audio"',reference:"video.md"},{capability:"branding extract",intent:'"Match my brand" / "pull branding from this site"',reference:"branding.md",suffix:" <url>"},{capability:"scrape",intent:'"Read this web page"',reference:"research.md",suffix:" https://example.com"},{capability:"transcript",intent:'"Get the transcript of this YouTube video"',reference:"research.md",suffix:" <url>"},{capability:"search web",intent:'"Search the web / find news about X"',reference:"research.md",suffix:' "query"'},{capability:"knowledge search",intent:'"What do we already have on X?"',reference:"knowledge.md"},{capability:"document create",intent:'"Save this as a document" / library filing',reference:"knowledge.md"},{capability:"microsite create",intent:'"Build a landing page / microsite"',reference:"artifacts.md"},{capability:"poll create",intent:'"Make a poll"',reference:"artifacts.md"},{capability:"visual-abstract create",intent:'"One-page visual summary"',reference:"artifacts.md"},{capability:"ad-set create",intent:'"Ad creatives for this campaign"',reference:"artifacts.md"},{capability:"agent create",intent:'"Schedule this to run every week"',reference:"agents.md"},{capability:"support report",intent:'"Something broke / how do I / I wish it could" \u2014 file it, then `support list`',reference:"support.md"}],gx=["ai-connections","capabilities","config","delete","derive","export","footage","ideas","import","list","login","logout","runner","skill","templates","whoami"];function Pr(t,e=Pn("rendered without a catalog fetch")){let{name:n,cmd:r,pkg:o}=t,i=new Map(e.capabilities.map(v=>[v.name,v])),s=px.filter(v=>i.has(v.capability)).map(v=>`| ${v.intent} | \`${r} ${v.capability}${v.suffix??""}\` | [${v.reference}](references/${v.reference}) |`).join(`
903
+ `),p=vn(e.capabilities).map(({capabilities:v,category:x})=>`${x} (${v.length})`).join(", "),f=wm(e).map(({file:v,when:x})=>`| [references/${v}](references/${v}) | ${x} |`).join(`
904
+ `),h=[...new Set([...e.capabilities.map(v=>v.name.split(" ")[0]),...gx])].sort().map(v=>`\`${v}\``).join(", ");return`---
905
+ name: ${n}
906
+ description: >-
907
+ Route any ${n} CLI task to the smallest installed domain skill. Trigger for
908
+ presentations, decks, presentation-to-MP4, video, branding, media generation,
909
+ research, knowledge, artifacts, or scheduled agents. This is an intent router;
910
+ detailed workflows live in domain skills and catalog-generated references.
768
911
  ---
769
912
 
770
- ## When you are not sure a capability exists
913
+ ${re(e,t)}
771
914
 
772
- Run this before telling the user something is unsupported:
915
+ # ${n} CLI router
773
916
 
774
- \`\`\`bash
775
- ${r} capabilities --search <topic> # search every callable capability
776
- ${r} capabilities --category media # one category at a time
777
- ${r} capabilities # all of them, with exact command paths
778
- ${r} <group> --help # flags for one group
779
- \`\`\`
917
+ Install with \`npm install -g ${o}\`. Verify authentication with \`${r} whoami\`
918
+ and refresh feature-gated commands with \`${r} config refresh\`.
780
919
 
781
- \`${r} capabilities\` reads the server's live capability catalog \u2014 the same
782
- source this skill was generated from, and the same one the API and MCP surfaces
783
- are built on. It is therefore **more current than this file can ever be**: it
784
- reflects capabilities added after this skill was installed. A capability missing
785
- from these references is not evidence that it does not exist; \`capabilities\`
786
- returning nothing is.
920
+ ## Load one domain skill
787
921
 
788
- When it cannot reach the catalog it says so and prints the list baked into the
789
- CLI build instead (\`--format json\` reports \`"source": "snapshot"\`). Treat that
790
- output as possibly behind the deployment, not as proof a capability is gone.
922
+ - Presentation create/import/read/export/edit \u2192 \`${n}-presentation\`.
923
+ - Existing presentation to narrated MP4 \u2192 \`${n}-presentation-video\`.
924
+ - Saved private/team brands and linked-deck updates \u2192 \`${n}-branding\`.
925
+ - Scheduled Agents, team roster discovery, and private/team visibility \u2192 \`${n}-agents\`.
926
+ - Video from a brief or storyboard, with no deck \u2192 \`${n}-video\`.
927
+ - Legacy Studio-only deck editing \u2192 \`${n}-presentation-edit\`.
791
928
 
792
- Two things it does not cover: commands gated behind account feature flags (the
793
- \`${r} derive\` subcommands) appear only after \`${r} login\` and
794
- \`${r} config refresh\`, and commands the CLI owns without a catalog entry are
795
- listed by \`${r} --help\`.
929
+ \`${r} presentation video\` is deck\u2192MP4; \`${r} video\` is video from scratch.
930
+ They share no state. There is no \`video export\` subcommand.
796
931
 
797
- Categories: ${y}.
932
+ Something broke, a question, or a feature request \u2192 the \`support\` group:
933
+ \`report\` files it (never gated) and \`list\` follows what became of it. Run
934
+ \`${r} capabilities --category support\` for the exact flags.
798
935
 
799
- ---
936
+ ## Task \u2192 command
800
937
 
801
- ## Which reference file
938
+ | The user asks for\u2026 | Start here | Catalog detail |
939
+ |---|---|---|
940
+ ${s}
802
941
 
803
- | File | Read it when |
804
- |---|---|
805
- ${p}
942
+ ## Composing commands
806
943
 
807
- ---
944
+ References carry **Takes** and **Returns** columns. An id one command returns is the id the next command accepts.
945
+ A run id means poll the exact status command named in that row. Read optional flags from \`${r} <group> <sub> --help\`.
808
946
 
809
- ## Authentication and feature flags
947
+ Before saying an operation is unsupported, query the deployed contract:
810
948
 
811
949
  \`\`\`bash
812
- ${r} login # opens a browser (do NOT pass --no-browser from an agent)
813
- ${r} whoami # verify
814
- ${r} config refresh
950
+ ${r} capabilities --search <topic>
951
+ ${r} capabilities --category <category>
952
+ ${r} <group> --help
815
953
  \`\`\`
816
954
 
817
- Or set \`${i}_API_KEY\` in the environment.
818
-
819
- Some command groups appear only **after** \`${r} login\` followed by
820
- \`${r} config refresh\`. If a command documented here is missing from
821
- \`--help\`, refresh before concluding it was removed.
822
-
823
- Background operations return a run id \u2014 poll the status command named in the
824
- reference file rather than assuming success.
955
+ The live catalog is authoritative; an installed skill can be older. Categories:
956
+ ${p}.
825
957
 
826
- Some commands take \`--yes\` to confirm a paid or irreversible action, and some
827
- also require \`--idempotency-key\`. Which ones is a property of the command, not
828
- of its cost: check \`${r} <command> --help\` instead of adding flags a command
829
- does not declare.
958
+ ## Reference index
830
959
 
831
- ---
960
+ | File | Read it when |
961
+ |---|---|
962
+ ${f}
832
963
 
833
964
  ## Every command group
834
965
 
835
966
  Run \`${r} <group> --help\` for any of these:
836
967
 
837
- ${w}
838
-
839
- The groups the catalog owns are documented in \`references/\`. The rest are
840
- CLI-local and never appear in \`${r} capabilities\`: auth and config
841
- (\`login\`, \`logout\`, \`whoami\`, \`config\`), the legacy direct deck commands
842
- (\`list\`, \`get\`, \`delete\`, \`export\`, \`import\`, \`templates\`, \`ideas\`),
843
- \`derive\` (needs \`config refresh\` first), plus \`runner\` and \`skill\`.
844
-
845
- ## Deeper skills
846
-
847
- - \`${r} create "Topic"\` \u2192 load the \`${n}-presentation\` skill
848
- - editing an existing deck \u2192 load the \`${n}-presentation-edit\` skill
849
- - building a video from a brief or storyboard, with no deck \u2192 load the \`${n}-video\` skill
850
- `}function sn(e){let{name:t,cmd:n}=e;return`---
851
- name: ${t}-presentation-edit
968
+ ${h}
969
+ `}function Or(t){let{name:e,cmd:n}=t;return`---
970
+ name: ${e}-presentation-edit
852
971
  description: >
853
972
  Use ONLY when editing an already-created presentation that has real slides:
854
973
  changing slide text, colors, fonts, images, charts, layout, or adding/removing slides.
855
974
  Triggers: "change", "edit", "update", "fix", "modify", "add a slide", "make it X".
856
975
  Do NOT load for creation requests \u2014 "create a presentation", "make slides",
857
- "build a deck", "3-slide pitch", "new presentation" \u2192 use ${t}-presentation.
976
+ "build a deck", "3-slide pitch", "new presentation" \u2192 use ${e}-presentation.
858
977
  ---
859
978
 
860
979
  # Presentation Editor \u2014 In-App Guide
@@ -1132,229 +1251,8 @@ Do NOT render or export the presentation \u2014 that's handled by the app.
1132
1251
  | Create brand-new presentation (5+ slides, new topic) | \`${n} create ...\` via CLI |
1133
1252
  | Redesign the whole deck | \`${n} create ...\` via CLI, then sync |
1134
1253
  | User provides a URL to base the presentation on | \`${n} scrape <url>\` \u2192 \`${n} create ...\` |
1135
- `}function dn(e){let{name:t,cmd:n}=e;return`---
1136
- name: ${t}-presentation
1137
- description: Use when user asks to create presentations, slides, decks, pitch decks.
1138
- Researches the topic, gathers context, and generates AI-powered presentations via CLI.
1139
- ---
1140
-
1141
- # ${t} Presentation CLI
1142
-
1143
- ---
1144
-
1145
- ## CRITICAL: Authentication Required
1146
-
1147
- Always verify auth before doing anything else:
1148
-
1149
- \`\`\`bash
1150
- ${n} whoami
1151
- \`\`\`
1152
-
1153
- If this fails \u2192 **STOP**. Tell the user: \`${n} login\`. Do NOT proceed without auth.
1154
-
1155
- ---
1156
-
1157
- ## Quick Reference
1158
-
1159
- | Command | Purpose |
1160
- |---------|---------|
1161
- | \`${n} create <topic>\` | Create presentation |
1162
- | \`${n} create <topic> --studio\` | Create and link to Studio preview |
1163
- | \`${n} scrape <url>\` | Scrape URL content |
1164
- | \`${n} list\` | List presentations |
1165
- | \`${n} get <id-or-slug>\` | Get details and canonical Studio/view URLs |
1166
- | \`${n} export <id-or-slug> -o deck.html\` | Export to HTML/PDF/PPTX |
1167
- | \`${n} branding find <name-or-url>\` | Search existing brands (returns IDs) |
1168
- | \`${n} branding extract <url>\` | Extract NEW brand identity |
1169
- | \`${n} branding list\` | List saved brands |
1170
- | \`${n} images search "query"\` | Stock images |
1171
-
1172
- ---
1173
-
1174
- ## Step 1: Research & Gather Context
1175
-
1176
- **Claude gathers all information first, then creates.**
1177
-
1178
- **For a company/product/URL:**
1179
- \`\`\`bash
1180
- ${n} scrape https://company.com > /tmp/context.txt
1181
- ${n} create "Company Overview" --studio --context-file /tmp/context.txt -n 10 --mode best
1182
- \`\`\`
1183
-
1184
- **For a topic (no URL):**
1185
- - Use web search to gather current facts, stats, key points
1186
- - Synthesize into text, pass via \`--context\`:
1187
- \`\`\`bash
1188
- ${n} create "AI in Healthcare" \\
1189
- --studio \\
1190
- --context "Key findings: Market size \\$45B in 2024, growing 37% CAGR. Top: diagnostics, drug discovery..." \\
1191
- -n 12 --mode best
1192
- \`\`\`
1193
-
1194
- **For user-provided files:**
1195
- \`\`\`bash
1196
- ${n} create "Q4 Review" --studio --file ./report.pdf --file ./data.xlsx -n 10
1197
- \`\`\`
1198
-
1199
- ---
1200
-
1201
- ## Step 2: Branding (optional)
1202
-
1203
- **If a brand/company is detected in the request:**
1204
-
1205
- 1. **Search existing brands first** (always before extracting):
1206
- \`\`\`bash
1207
- ${n} branding find "Company Name"
1208
- ${n} branding find company.com
1209
- \`\`\`
1210
-
1211
- 2. **If found** \u2014 use AskUserQuestion: "Found existing brand for [name]. Apply it?"
1212
- - Options: "Yes, apply" / "Skip branding"
1213
- - If yes: get the brand ID from the find results
1214
-
1215
- 3. **If not found** \u2014 extract immediately (no need to ask):
1216
- \`${n} branding extract https://company.com\`
1217
-
1218
- 4. **If extraction FAILS** (rate limit, plan limit, server error):
1219
- - **STOP immediately** \u2014 do NOT retry or manually create brand assets
1220
- - Use AskUserQuestion: "Brand extraction failed: [error]. How to proceed?"
1221
- - Options: "Continue without branding" / "Try a different URL" / "Pick from existing brands"
1222
-
1223
- 5. **If user confirms** \u2192 use brand ID in create:
1224
- \`\`\`bash
1225
- ${n} create "Topic" --branding-id <id> --styling brand-plus-style ...
1226
- \`\`\`
1227
-
1228
- **\`--reference-url\`** \u2014 only when user explicitly provides an image/URL as visual design reference:
1229
- \`\`\`bash
1230
- ${n} create "Product Demo" --reference-url https://example.com/style-screenshot.png
1231
- \`\`\`
1232
-
1233
- ---
1234
-
1235
- ## Step 3: Flag Selection Guide
1236
-
1237
- **Content (required \u2014 at least one):**
1238
- - \`--context <text>\` \u2014 inline research/facts Claude gathered
1239
- - \`--context-file <path>\` \u2014 when context is large (write to temp file first)
1240
- - \`-f, --file <paths...>\` \u2014 user's files: PDF, PPTX, DOCX, images
1241
-
1242
- **Quality** (defaults: mode=fast, thinking-depth=moderate, amount=concise):
1243
-
1244
- | Flag | Values | Pick when |
1245
- |------|--------|-----------|
1246
- | \`-n, --slides\` | 1\u201320 (default: 10) | 6\u20138 focused pitch, 12\u201315 report, 20 deep-dive |
1247
- | \`-m, --mode\` | best/balanced/**fast**/ultrafast/instant | \`best\` for client/investor decks, \`fast\` default |
1248
- | \`--amount\` | minimal/**concise**/detailed/extensive | \`detailed\` for comprehensive content |
1249
- | \`--thinking-depth\` | quick/**moderate**/deep/profound | \`deep\` for research-heavy topics |
1250
-
1251
- **Content style:**
1252
-
1253
- | Flag | Values | Pick when |
1254
- |------|--------|-----------|
1255
- | \`-t, --tone\` | professional/educational/creative/formal/casual | professional=B2B, educational=training |
1256
- | \`-g, --goal\` | inform/persuade/train/learn/entertain/report | persuade=pitch, inform=update, train=onboarding |
1257
- | \`--audience\` | text | "Series A investors", "new engineering hires", "executive team" |
1258
- | \`-l, --language\` | en/ru/etc | detect from conversation language |
1259
-
1260
- **Visual:**
1261
-
1262
- | Flag | Values | Notes |
1263
- |------|--------|-------|
1264
- | \`--branding-id\` | branding ID | DB ID from \`${n} branding list\` or returned by \`${n} branding extract\`. NOT a URL. |
1265
- | \`--styling\` | **freeform**/brand-only/brand-plus-style/style-only/no-styling | if brand \u2192 \`brand-only\` (enforces brand fonts+colors) |
1266
- | \`--reference-url\` | image url | only when user explicitly provides an image as design reference |
1267
- | \`--theme\` | blue/violet/rose/orange/green | **instant mode only** \u2014 quick color preset |
1268
- | \`--primary-color\` | #hex | **instant mode only** \u2014 custom brand color |
1269
- | \`--decorations\` | none/waves-bottom-left/.../minimal | **instant mode only** \u2014 bg decoration |
1270
-
1271
- ---
1272
-
1273
- ## Step 4: Create
1274
-
1275
- **Use \`--studio\` when running inside Studio** \u2014 links the result to the Studio preview automatically.
1276
-
1277
- Full example \u2014 research-driven:
1278
- \`\`\`bash
1279
- ${n} create "AI in Healthcare 2025" \\
1280
- --studio \\
1281
- --context-file /tmp/research.txt \\
1282
- --slides 12 \\
1283
- --mode best \\
1284
- --tone professional \\
1285
- --goal inform \\
1286
- --audience "Hospital executives and clinical directors"
1287
- \`\`\`
1288
-
1289
- Full example \u2014 company pitch deck:
1290
- \`\`\`bash
1291
- ${n} create "Acme Corp Investor Pitch" \\
1292
- --studio \\
1293
- --context "Acme Corp: B2B SaaS, \\$5M ARR, 200 customers, founded 2021..." \\
1294
- --branding-id <id-from-branding-extract> \\
1295
- --styling brand-plus-style \\
1296
- --slides 10 \\
1297
- --mode best \\
1298
- --tone professional \\
1299
- --goal persuade \\
1300
- --audience "Series A investors"
1301
- \`\`\`
1302
-
1303
- ---
1304
-
1305
- ## Export (save to file)
1306
-
1307
- \`\`\`bash
1308
- # Self-contained interactive HTML (default format)
1309
- ${n} export <id-or-slug> -o ./presentation.html
1310
-
1311
- # PDF or PowerPoint
1312
- ${n} export <id-or-slug> -f pdf -o ./presentation.pdf
1313
- ${n} export <id-or-slug> -f pptx -o ./presentation.pptx
1314
-
1315
- # Get slug from a just-created presentation
1316
- ${n} get <id-or-slug> --format json
1317
- \`\`\`
1318
-
1319
- ## Completion handoff (required)
1320
-
1321
- After a background presentation reaches 100%, do not finish with only a title
1322
- or slug. Resolve the created row and include its canonical Studio URL as a
1323
- clickable Markdown link:
1324
-
1325
- \`\`\`bash
1326
- # Find the newly created row, then use its full UUID (most reliable while a
1327
- # deployment containing slug lookup fixes may still be rolling out).
1328
- ${n} list --format json
1329
- ${n} get <presentation-uuid> --format json
1330
- \`\`\`
1331
-
1332
- Use the returned \`editUrl\` in the final response: \`[Open deck](<editUrl>)\`.
1333
- Use \`viewUrl\` only when the user asked for the viewer. If you created local
1334
- research notes, link their absolute path; the Mindframes desktop app can open
1335
- files inside its own local-runner workspace.
1336
-
1337
- ---
1338
-
1339
- ## Managing Presentations
1340
-
1341
- \`\`\`bash
1342
- ${n} list
1343
- ${n} get <id-or-slug>
1344
- ${n} export <id-or-slug> -o presentation.html
1345
- ${n} delete <id-or-slug>
1346
- ${n} import ./presentation.zip
1347
- \`\`\`
1348
-
1349
- ---
1350
-
1351
- ## Troubleshooting
1352
-
1353
- - **Auth fails** \u2192 \`${n} logout && ${n} login\` (browser required)
1354
- - **"Context required"** \u2192 add \`--context\`, \`--file\`, or \`--context-file\`
1355
- - **Rate limit (429)** \u2192 check plan with \`${n} whoami\`
1356
- `}var Lp=[{capability:"video reference analyze",when:"Optional \u2014 match the style of a reference video."},{capability:"video storyboard create",when:"Write the storyboard. Markdown in, immutable revision out."},{capability:"video storyboard revise",when:"Iterate. Each revision is appended, never rewritten."},{capability:"video create",when:"Render a pinned revision. Paid, approval-gated, background."}];function cn(e,t){let{cmd:n,name:r,pkg:o}=e,i=new Set(t.capabilities.map(l=>l.name)),a=Lp.filter(l=>i.has(l.capability)).map((l,y)=>`${y+1}. \`${n} ${l.capability}\` \u2014 ${l.when}`).join(`
1357
- `),d=vr(t.capabilities).length;return`---
1254
+ `}function Dr(t,e){return Ce(t,e,"presentation")}var fx=[{capability:"video reference analyze",when:"Optional \u2014 match the style of a reference video."},{capability:"video storyboard create",when:"Write the storyboard. Markdown in, immutable revision out."},{capability:"video storyboard revise",when:"Iterate. Each revision is appended, never rewritten."},{capability:"video create",when:"Render a pinned revision. Paid, approval-gated, background."}];function Nr(t,e){let{cmd:n,name:r,pkg:o}=t,i=new Set(e.capabilities.map(p=>p.name)),s=fx.filter(p=>i.has(p.capability)).map((p,f)=>`${f+1}. \`${n} ${p.capability}\` \u2014 ${p.when}`).join(`
1255
+ `),c=Ui(e.capabilities).length;return`---
1358
1256
  name: ${r}-video
1359
1257
  description: >-
1360
1258
  Use when a video must be built from scratch \u2014 a brief, a script, a storyboard,
@@ -1362,10 +1260,10 @@ description: >-
1362
1260
  involved. Trigger it even when the user never names the product: "make me a
1363
1261
  video about X", "turn this script into a video", "I need a 30s promo".
1364
1262
  For turning an EXISTING presentation into an MP4, use the ${r} skill's
1365
- deck\u2192MP4 flow instead. ${d} CLI capabilities, listed in references/video.md.
1263
+ deck\u2192MP4 flow instead. ${c} CLI capabilities, listed in references/video.md.
1366
1264
  ---
1367
1265
 
1368
- ${pe(t,e)}
1266
+ ${re(e,t)}
1369
1267
 
1370
1268
  # ${r} video
1371
1269
 
@@ -1379,7 +1277,7 @@ one wastes a paid render. There is no \`video export\` subcommand.
1379
1277
 
1380
1278
  ## The flow
1381
1279
 
1382
- ${a}
1280
+ ${s}
1383
1281
 
1384
1282
  Then poll \`${n} video status <run-id>\` until it reports done.
1385
1283
 
@@ -1419,17 +1317,17 @@ ${n} video <sub> --help
1419
1317
  \`\`\`
1420
1318
 
1421
1319
  The catalog is authoritative and always current; this file is a snapshot of it.
1422
- `}function is(e,t){return[{content:on(e,t),name:"video"},{content:rn(e,t),name:"deck-to-video"}]}import{existsSync as xr,mkdirSync as as,rmSync as Dp,writeFileSync as ss}from"fs";import{homedir as ls}from"os";import{basename as Np,join as Re,relative as qp,resolve as xt}from"path";var Le=[{name:"Claude Code",dir:".claude",provider:"claude"},{name:"GitHub Copilot",dir:".github",agentSuffix:".agent.md",provider:"copilot"},{name:"Cursor",dir:".cursor"},{name:"Codex",dir:".codex",agentSuffix:".toml",provider:"codex"},{name:"OpenCode",dir:".opencode"},{name:"Windsurf",dir:".windsurf"},{name:"Agent",dir:".agent"}];var Up={sonnet:"claude-sonnet-4.6",haiku:"claude-haiku-4.5",opus:"claude-opus-4.6"},jp=["permissionMode","skills","subagentType"];function Mp(e,t){if(t!=="copilot")return e;let n=e.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return ds(e);let r=n[1],o=e.slice((n.index??0)+n[0].length);r=r.replace(/^(model:\s*)(\S+)([ \t]*)$/m,(a,d,l,y)=>`${d}${Up[l]??l}${y}`);for(let a of jp)r=r.replace(new RegExp(`^${a}:[^
1320
+ `}function Rm(t,e){return[{content:$r(t,e),name:"video"},{content:Et(t,e),name:"deck-to-video"}]}import{chmodSync as hx,existsSync as Bi,mkdirSync as Mi,rmSync as yx,writeFileSync as Fi}from"fs";import{homedir as Em}from"os";import{basename as bx,dirname as wx,join as Ge,relative as vx,resolve as xn}from"path";var rt=[{name:"Claude Code",dir:".claude",provider:"claude"},{name:"GitHub Copilot",dir:".github",agentSuffix:".agent.md",provider:"copilot"},{name:"Cursor",dir:".cursor"},{name:"Codex",dir:".codex",agentSuffix:".toml",provider:"codex"},{name:"OpenCode",dir:".opencode"},{name:"Windsurf",dir:".windsurf"},{name:"Agent",dir:".agent"}];var Ix={sonnet:"claude-sonnet-4.6",haiku:"claude-haiku-4.5",opus:"claude-opus-4.6"},xx=["permissionMode","skills","subagentType"];function kx(t,e){if(e!=="copilot")return t;let n=t.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return Cm(t);let r=n[1],o=t.slice((n.index??0)+n[0].length);r=r.replace(/^(model:\s*)(\S+)([ \t]*)$/m,(s,c,p,f)=>`${c}${Ix[p]??p}${f}`);for(let s of xx)r=r.replace(new RegExp(`^${s}:[^
1423
1321
  ]*
1424
- ?`,"m"),"");r=r.replace(/\n+$/,"");let i=ds(o);return`---
1322
+ ?`,"m"),"");r=r.replace(/\n+$/,"");let i=Cm(o);return`---
1425
1323
  ${r}
1426
1324
  ---
1427
- ${i}`}function ds(e){return e.replace(/\bAskUserQuestion\b/g,"ask the user directly in your response").replace(/\*\*Construct the Task prompt:\*\*/g,"**Construct the Task prompt (must be fully self-contained \u2014 sub-agents cannot read this conversation's history):**").replace(/\*\*Wait for all agents to complete\*\*/g,"**Wait for all agents to complete** (monitor with `/tasks` in Copilot CLI)").replace("**Launch ALL scene agents in parallel**","**Launch ALL scene agents in parallel** \u2014 each agent must write to its own `Scene[NN][Name].tsx` file. Two agents writing to the same file will silently overwrite each other (no error). Verify unique filenames before spawning.")}function Fp(e,t){let n=xt(e),r=xt(e,t);if(qp(n,r).startsWith("..")||xt(r)!==r.replace(/\.\./g,""))throw new Error(`Invalid path: "${t}" would escape base directory`);return r}function cs(e,t,n,r){let o=Re(e,"SKILL.md");if(as(e,{recursive:!0}),ss(o,Mp(t,r),"utf-8"),n&&n.length>0){let i=Re(e,"references");as(i,{recursive:!0});for(let a of n){let d=Re(i,`${a.name}.md`);ss(d,a.content,"utf-8")}}}function ln(e,t,n={},r){let o={installed:[],skipped:[],errors:[]},i=n.local?process.cwd():ls();if(n.dir){let a=Np(xt(n.dir)),d=Le.find(l=>l.dir===a)?.provider;try{let l=xt(n.dir),y=Fp(l,Re("skills",e));cs(y,t,r,d),o.installed.push(n.dir)}catch(l){o.errors.push(`${n.dir}: ${l instanceof Error?l.message:String(l)}`)}}else for(let a of Le){let d=Re(i,a.dir),l=Re(d,"skills",e),y=Re(l,"SKILL.md");if(xr(d)){if(xr(y)&&!n.force){o.skipped.push(a.name);continue}try{cs(l,t,r,a.provider),o.installed.push(a.name)}catch(p){o.errors.push(`${a.name}: ${p instanceof Error?p.message:String(p)}`)}}}return o}function mn(e,t={}){let n={removed:[],errors:[]},r=t.local?process.cwd():ls();for(let o of Le){let i=Re(r,o.dir,"skills",e);if(xr(i))try{Dp(i,{recursive:!0}),n.removed.push(o.name)}catch(a){n.errors.push(`${o.name}: ${a instanceof Error?a.message:String(a)}`)}}return n}function ms(){return Le.map(e=>e.name)}function Je(e){let{name:t,cmd:n}=e;return`---
1428
- name: ${t}-tts
1325
+ ${i}`}function Cm(t){return t.replace(/\bAskUserQuestion\b/g,"ask the user directly in your response").replace(/\*\*Construct the Task prompt:\*\*/g,"**Construct the Task prompt (must be fully self-contained \u2014 sub-agents cannot read this conversation's history):**").replace(/\*\*Wait for all agents to complete\*\*/g,"**Wait for all agents to complete** (monitor with `/tasks` in Copilot CLI)").replace("**Launch ALL scene agents in parallel**","**Launch ALL scene agents in parallel** \u2014 each agent must write to its own `Scene[NN][Name].tsx` file. Two agents writing to the same file will silently overwrite each other (no error). Verify unique filenames before spawning.")}function $m(t,e){let n=xn(t),r=xn(t,e);if(vx(n,r).startsWith("..")||xn(r)!==r.replace(/\.\./g,""))throw new Error(`Invalid path: "${e}" would escape base directory`);return r}function Sm(t,e,n,r,o){let i=Ge(t,"SKILL.md");if(Mi(t,{recursive:!0}),Fi(i,kx(e,r),"utf-8"),n&&n.length>0){let s=Ge(t,"references");Mi(s,{recursive:!0});for(let c of n){let p=Ge(s,`${c.name}.md`);Fi(p,c.content,"utf-8")}}for(let s of o??[]){let c=$m(t,s.path);Mi(wx(c),{recursive:!0}),Fi(c,s.content,"utf-8"),s.executable&&hx(c,493)}}function _r(t,e,n={},r,o){let i={installed:[],skipped:[],errors:[]},s=n.local?process.cwd():Em();if(n.dir){let c=bx(xn(n.dir)),p=rt.find(f=>f.dir===c)?.provider;try{let f=xn(n.dir),h=$m(f,Ge("skills",t));Sm(h,e,r,p,o),i.installed.push(n.dir)}catch(f){i.errors.push(`${n.dir}: ${f instanceof Error?f.message:String(f)}`)}}else for(let c of rt){let p=Ge(s,c.dir),f=Ge(p,"skills",t),h=Ge(f,"SKILL.md");if(Bi(p)){if(Bi(h)&&!n.force){i.skipped.push(c.name);continue}try{Sm(f,e,r,c.provider,o),i.installed.push(c.name)}catch(v){i.errors.push(`${c.name}: ${v instanceof Error?v.message:String(v)}`)}}}return i}function Lr(t,e={}){let n={removed:[],errors:[]},r=e.local?process.cwd():Em();for(let o of rt){let i=Ge(r,o.dir,"skills",t);if(Bi(i))try{yx(i,{recursive:!0}),n.removed.push(o.name)}catch(s){n.errors.push(`${o.name}: ${s instanceof Error?s.message:String(s)}`)}}return n}function Tm(){return rt.map(t=>t.name)}function Pt(t){let{name:e,cmd:n}=t;return`---
1326
+ name: ${e}-tts
1429
1327
  description: Text-to-speech generation. Convert text to natural speech with multiple providers (Gemini, ElevenLabs, OpenAI) and voices. Use for voiceovers, narration, accessibility.
1430
1328
  ---
1431
1329
 
1432
- # ${t} TTS (Text-to-Speech)
1330
+ # ${e} TTS (Text-to-Speech)
1433
1331
 
1434
1332
  Convert text to natural speech with multiple providers and voices.
1435
1333
 
@@ -1624,12 +1522,12 @@ ${n} tts generate \\
1624
1522
  2. **Voice matching** - Match voice style to content: Puck for upbeat, Charon for serious
1625
1523
  3. **Speed adjustment** - Use 0.9-0.95 for narration, 1.0-1.1 for casual
1626
1524
  4. **Multiple voiceovers** - Run \`${n} tts generate\` once per line and poll each run with \`${n} tts status <run-id>\`
1627
- `}function ze(e){let{name:t,cmd:n}=e;return`---
1628
- name: ${t}-music
1525
+ `}function Ot(t){let{name:e,cmd:n}=t;return`---
1526
+ name: ${e}-music
1629
1527
  description: Generate music that follows a video's narration and final timing. Gemini plans the provider prompt on the backend.
1630
1528
  ---
1631
1529
 
1632
- # ${t} Video Music
1530
+ # ${e} Video Music
1633
1531
 
1634
1532
  Generate TTS first and finalize the storyboard/timeline. Then write a factual request; do not write a music prompt, music plan, style list, or provider options.
1635
1533
 
@@ -1650,12 +1548,12 @@ ${n} music status <request-id>
1650
1548
  \`\`\`
1651
1549
 
1652
1550
  The backend sends these facts to Gemini, receives the provider-ready musical direction, and makes the paid music-provider request. Retrying the same unchanged request is idempotent.
1653
- `}function Xe(e){let{name:t,cmd:n}=e;return`---
1654
- name: ${t}-sfx
1551
+ `}function Dt(t){let{name:e,cmd:n}=t;return`---
1552
+ name: ${e}-sfx
1655
1553
  description: Generate one sound effect aligned with a final visual event and narration. Gemini plans the provider prompt on the backend.
1656
1554
  ---
1657
1555
 
1658
- # ${t} Video Sound Effects
1556
+ # ${e} Video Sound Effects
1659
1557
 
1660
1558
  Generate TTS first and finalize timing. For each meaningful sound cue, send the video's facts plus exactly one factual \`visual_event\`. Include word timings when TTS provides them. Do not author an SFX prompt or provider settings.
1661
1559
 
@@ -1688,12 +1586,12 @@ ${n} sfx status <request-id>
1688
1586
  \`\`\`
1689
1587
 
1690
1588
  The backend sends these facts to Gemini, receives one provider-ready SFX description, and makes the paid SFX-provider request. Retrying the same unchanged request is idempotent.
1691
- `}function He(e){let{name:t,cmd:n}=e;return`---
1692
- name: ${t}-mix
1589
+ `}function Nt(t){let{name:e,cmd:n}=t;return`---
1590
+ name: ${e}-mix
1693
1591
  description: Audio mixing for video production. Combine video with voiceover and background music. Supports volume control, fade effects, and multiple audio tracks.
1694
1592
  ---
1695
1593
 
1696
- # ${t} Audio Mixing
1594
+ # ${e} Audio Mixing
1697
1595
 
1698
1596
  Mix video with voiceover and background music.
1699
1597
 
@@ -1838,12 +1736,12 @@ ${n} mix status <request-id>
1838
1736
  2. **Music selection** - Choose music that doesn't compete with voice frequency.
1839
1737
  3. **Consistent levels** - Keep voice at 100%, adjust music only.
1840
1738
  4. **File sizes** - Use \`--no-wait\` for large files to avoid timeout.
1841
- `}function Ye(e){let{name:t,cmd:n}=e;return`---
1842
- name: ${t}-image
1843
- description: Image search across the web and licensed stock, plus AI image generation. Find licensed photos to publish, web images for specific real-world subjects, or generate a custom image. For videos, presentations, marketing.
1739
+ `}function _t(t){let{name:e,cmd:n}=t;return`---
1740
+ name: ${e}-image
1741
+ description: Image search across the web and licensed stock, plus AI image generation with reference images. Find licensed photos to publish, web images for specific real-world subjects, generate a custom image, or generate one that keeps a real person's face, a product or a logo by passing a local photo or URL as a reference. For videos, presentations, marketing.
1844
1742
  ---
1845
1743
 
1846
- # ${t} Image Commands
1744
+ # ${e} Image Commands
1847
1745
 
1848
1746
  Search images (web + licensed stock) and generate AI images.
1849
1747
 
@@ -1858,6 +1756,13 @@ ${n} image search -q "mountain landscape" --source stock
1858
1756
 
1859
1757
  # Generate AI image
1860
1758
  ${n} image generate -p "futuristic city at sunset" -o city.png --yes
1759
+
1760
+ # Generate an image that keeps a real person's face, from a local photo
1761
+ ${n} image generate \\
1762
+ -p "The person in the identity reference, seated at a workshop bench, warm window light, shallow depth of field" \\
1763
+ --reference-image identity=./photos/founder.jpg \\
1764
+ --provider google-ai --model gemini-3-pro-image \\
1765
+ -o founder-at-bench.png --yes
1861
1766
  \`\`\`
1862
1767
 
1863
1768
  ---
@@ -1893,7 +1798,10 @@ default queries both and tags every result with its \`source\`.
1893
1798
 
1894
1799
  ### \`image generate\`
1895
1800
 
1896
- Generate an AI image from a text prompt.
1801
+ Generate an AI image from a text prompt. Use \`--purpose\` to pass explicit intent:
1802
+ \`general\`, \`draft\`, \`infographic\`, \`brand-max\`, or \`vector\`.
1803
+ Omission uses the general route. A word such as \u201Cinfographic\u201D in the prompt does
1804
+ not classify the purpose; Services owns model selection for the supplied intent.
1897
1805
 
1898
1806
  \`\`\`bash
1899
1807
  ${n} image generate <prompt> [options]
@@ -1905,13 +1813,111 @@ ${n} image generate <prompt> [options]
1905
1813
  **Options:**
1906
1814
  | Option | Description | Default |
1907
1815
  |--------|-------------|---------|
1816
+ | \`--reference-image <label=path-or-url...>\` | Images the generation must follow. Repeatable and variadic. Each value is a **local file path** (uploaded for you and turned into a public URL) or an **already-public HTTP(S) URL**. | - |
1908
1817
  | \`-o, --output <path>\` | Output file path | - |
1909
- | \`--width <pixels>\` | Image width | host default |
1910
- | \`--height <pixels>\` | Image height | host default |
1818
+ | \`--width <pixels>\` | Requested image width \u2014 see the note below | host default |
1819
+ | \`--height <pixels>\` | Requested image height \u2014 see the note below | host default |
1820
+ | \`--idempotency-key <key>\` | Stable retry key for the run and its reference uploads | new UUID per run |
1911
1821
  | \`--no-wait\` | Return the request id without downloading; cannot be combined with \`--output\` | - |
1912
1822
  | \`--yes\` | Approve generation | required |
1913
1823
  | \`-f, --format <format>\` | Output: human, json, quiet | \`human\` |
1914
1824
 
1825
+ #### Reference images \u2014 how to lock an identity
1826
+
1827
+ \`--reference-image\` is how a generated image keeps a **real** face, product or
1828
+ logo instead of inventing a lookalike. Pass a photo of the person and say in the
1829
+ prompt that the subject is the identity reference.
1830
+
1831
+ \`\`\`bash
1832
+ ${n} image generate \\
1833
+ -p "The person in the identity reference, in a navy jacket, on a bright factory floor, editorial photography" \\
1834
+ --reference-image identity=./photos/founder.jpg \\
1835
+ -o founder-on-floor.png --yes
1836
+ \`\`\`
1837
+
1838
+ **Local file or URL \u2014 both work, and you never upload by hand.**
1839
+
1840
+ - A value that resolves to an existing file is uploaded through the CLI upload
1841
+ endpoint and becomes a public URL automatically. Its \`mediaType\` is derived
1842
+ from the file (a \`.jpg\` is sent as \`image/jpeg\`) and simply omitted when the
1843
+ type is not recognised \u2014 a \`.heic\` off a phone uploads normally and declares
1844
+ no type rather than a guessed one.
1845
+ - Anything else must be an \`http://\` or \`https://\` URL and is passed straight
1846
+ through.
1847
+ - A file positively identified as something other than an image (\`.pdf\`,
1848
+ \`.mp4\`, \u2026) is refused **before** the upload and before any credits are spent,
1849
+ with an error naming the media type it found.
1850
+ A missing path or a non-HTTP scheme is refused the same way. Nothing is ever
1851
+ silently dropped \u2014 a reference either reaches the model or the command fails.
1852
+
1853
+ **Labels.** Prefix a value with \`label=\` to say what the reference is for:
1854
+ \`identity=\`, \`style=\`, \`product=\`, \`logo=\`. The label reaches the generator,
1855
+ which weighs an \`identity\` reference differently from a mood board. It is
1856
+ optional. An existing file whose own name contains \`=\` is still read as a path,
1857
+ so \`--reference-image ./style=hero.png\` uploads that file rather than parsing a
1858
+ label.
1859
+
1860
+ **Repeat it, or pass several values at once.** Both forms work and order is
1861
+ preserved:
1862
+
1863
+ \`\`\`bash
1864
+ ${n} image generate -p "The founder holding the product, studio lighting" \\
1865
+ --reference-image identity=./photos/founder.jpg \\
1866
+ --reference-image product=./photos/device.png \\
1867
+ --reference-image logo=https://cdn.example.com/logo.png \\
1868
+ --provider google-ai --model gemini-3-pro-image \\
1869
+ -o hero.png --yes
1870
+ \`\`\`
1871
+
1872
+ There is no reference count limit in this command. If the routed provider has
1873
+ one, its rejection comes back as the error \u2014 the list is never quietly
1874
+ shortened.
1875
+
1876
+ **Fidelity is a property of the model, not of the reference.** Measured against
1877
+ production with the same photo:
1878
+
1879
+ | Routing | Result |
1880
+ |---|---|
1881
+ | Auto-routed (\`gemini-3.1-flash-lite-image\`) | A person who **resembles** the reference. Usually a disappointment when a specific likeness was the point. |
1882
+ | \`google-ai\` / \`gemini-3-pro-image\` | **Recognisably the same person** \u2014 earrings, hair parting, freckles, brow shape. |
1883
+
1884
+ \u26A0\uFE0F **\`--provider\` / \`--model\` are flag-gated, and the server drops them
1885
+ silently.** \`createImageOperation\` clears both unless the workspace holds the
1886
+ internal \`image-model-override\` flag (OFF by default, IP protection). On an
1887
+ ordinary workspace the pin below has **no effect**: the request is auto-routed,
1888
+ credits are spent, and the result is the lookalike rather than the person. The
1889
+ CLI warns whenever you pass either flag, because the drop itself is silent.
1890
+
1891
+ So, on a workspace that has the flag:
1892
+
1893
+ \`\`\`bash
1894
+ ${n} image generate \\
1895
+ -p "The person in the identity reference, in a navy jacket, on a bright factory floor, editorial photography" \\
1896
+ --reference-image identity=./photos/founder.jpg \\
1897
+ --provider google-ai --model gemini-3-pro-image \\
1898
+ -o founder-on-floor.png --yes
1899
+ \`\`\`
1900
+
1901
+ Without the flag, pass the reference anyway \u2014 it is still honoured, and it is
1902
+ still far better than describing the face in prose \u2014 but tell the user the
1903
+ likeness will be close rather than exact, and do not promise otherwise.
1904
+
1905
+ **Never distort a reference before you pass it.** A face cropped to a different
1906
+ aspect ratio is reproduced as that distorted face \u2014 a photo squeezed ~30% wider
1907
+ comes back as a wider person. The CLI uploads your file byte-for-byte and never
1908
+ resizes it; if you crop first, keep the aspect ratio.
1909
+
1910
+ **\`--width\` / \`--height\` do not change the output size on this path.**
1911
+ Measured: they and \`size\` are ignored. The auto-routed model returns 1024 on the
1912
+ long side. \`resolution\` (up to 2K \u2192 2048x1152 at 16:9) IS honoured by
1913
+ \`gemini-3-pro-image\`, but \`image generate\` has no flag for it today \u2014 use
1914
+ \`visual-abstract create\` when the canvas matters, and do not promise a user an
1915
+ exact pixel size from this command.
1916
+
1917
+ **\`--provider\` takes a provider, not a model name.** \`google-ai\` is a provider;
1918
+ \`gemini-3-pro-image\` is a model. A value like \`nano-banana-pro\` is neither and
1919
+ is rejected upstream with HTTP 400.
1920
+
1915
1921
  ---
1916
1922
 
1917
1923
  ## Search Tips
@@ -1956,6 +1962,14 @@ ${n} image search -q "minimal workspace desk laptop white"
1956
1962
  ### AI Image Generation
1957
1963
 
1958
1964
  \`\`\`bash
1965
+ # Identity locked from a local photo \u2014 the reference is uploaded for you
1966
+ ${n} image generate \\
1967
+ -p "The person in the identity reference, in a navy jacket, on a bright factory floor, editorial photography" \\
1968
+ --reference-image identity=./photos/founder.jpg \\
1969
+ --provider google-ai --model gemini-3-pro-image \\
1970
+ -o founder-on-floor.png \\
1971
+ --yes
1972
+
1959
1973
  # Basic generation
1960
1974
  ${n} image generate -p "futuristic city skyline at sunset" -o city.png --yes
1961
1975
 
@@ -2008,8 +2022,7 @@ Found 10 images for "mountain landscape"
2008
2022
  }
2009
2023
  ]
2010
2024
  }
2011
- ],
2012
- "totalCost": 0.001
2025
+ ]
2013
2026
  }
2014
2027
  }
2015
2028
  \`\`\`
@@ -2028,19 +2041,100 @@ Found 10 images for "mountain landscape"
2028
2041
 
2029
2042
  ---
2030
2043
 
2044
+ ## A layout is a different command
2045
+
2046
+ A sentence is enough for one subject on one background \u2014 that is what
2047
+ \`image generate\` is for. A picture that has to carry a **layout** is a
2048
+ different job with its own canonical operation: \`${n} visual-abstract create\`.
2049
+ Reach for it whenever the output has panels, headers, labels or a page
2050
+ structure \u2014 a storyboard sheet, a spec page, a comparison board, a one-pager.
2051
+
2052
+ It takes the things a layout needs and \`image generate\` has no field for
2053
+ (references aside \u2014 \`image generate --reference-image\` covers those):
2054
+
2055
+ | Option | Why it matters here |
2056
+ |---|---|
2057
+ | \`--reference-url <url...>\` | Up to three visual references, URLs only. (\`image generate --reference-image\` also takes references, and additionally accepts local file paths.) |
2058
+ | \`--preset <preset>\` | The page archetype, rather than describing one in prose. |
2059
+ | \`--aspect <ratio>\` | \`1:1\`, \`16:9\`, \`9:16\`, \`4:3\`, \`3:4\`. |
2060
+ | \`--branding-id <id>\` | Palette and type from a stored brand instead of hand-written hex. |
2061
+ | \`--output vector\` | Vector rather than raster, when the labels must stay crisp. |
2062
+ | \`--quality <tier>\` | \`fast\`, \`best\`, \`enterprise\`. |
2063
+
2064
+ Sending a layout to \`image generate\` instead throws all of that away and hands
2065
+ the arrangement to a raster model.
2066
+
2067
+ ## Prompting a complex composition
2068
+
2069
+ Whichever of the two you are using, a picture that carries a layout needs the
2070
+ prompt written as a **specification with named sections** rather than as prose.
2071
+ Prose leaves the arrangement to the model; a spec states it.
2072
+
2073
+ The sections that carry their weight, in this order:
2074
+
2075
+ | Section | What it fixes |
2076
+ |---|---|
2077
+ | \`TITLE\` | The words that must appear as the heading |
2078
+ | \`FORMAT\` | Page shape, aspect, panel count, what the hero is |
2079
+ | \`HEADER\` | Typography, the exact information cards, palette |
2080
+ | \`CONCEPT\` | The idea in two lines \u2014 why these panels, not any panels |
2081
+ | \`STORYBOARD\` | One numbered line per panel, in order |
2082
+ | \`EVERY PANEL\` | The rows each panel repeats: number, duration, camera, action |
2083
+ | \`CAMERA\` | Shot vocabulary applied across all panels |
2084
+ | \`STYLE\` | Rendering: realism, materials, lighting, resolution |
2085
+
2086
+ \`\`\`bash
2087
+ ${n} image generate -p "$(cat ./storyboard-spec.txt)" \\
2088
+ --width 1024 --height 1536 -o ./storyboard.png --yes
2089
+ \`\`\`
2090
+
2091
+ Keep the spec in a file and pass it with \`$(cat \u2026)\`. It will run to fifty lines
2092
+ and you will revise it several times; a shell argument is the wrong place for it.
2093
+
2094
+ **Name the on-image text explicitly.** Anything you want rendered \u2014 a heading, a
2095
+ wordmark, four information cards \u2014 has to be written out in the prompt. The
2096
+ model does not infer copy. If a brand name must be legible, say so in the panel
2097
+ that shows it.
2098
+
2099
+ **One image, not a set.** A sheet like this is a single generation: the panels,
2100
+ the badges and the labels are all painted into one file at the stated aspect.
2101
+
2102
+ **A sheet's panels cannot be fed to a video model.** The numbers, timecodes and
2103
+ caption rows are part of the pixels. Bind one as a \`first-frame\` and the
2104
+ caption goes into the render with it. A sheet is for a person to approve; frames
2105
+ for video are generated separately, without any text on them.
2106
+
2107
+ **Anchor a recurring subject with a reference.** Words alone let a face, a
2108
+ product or a package drift between panels. Both image routes take references:
2109
+ \`image generate --reference-image identity=./face.jpg\` (local paths or URLs)
2110
+ and \`visual-abstract create --reference-url <url>\` (URLs, up to three). Pass
2111
+ the subject once as a reference and the likeness holds.
2112
+
2113
+ Discuss the spec with the user before spending on it, for the same reason a
2114
+ storyboard is read before it is pinned: the layout, the copy and the concept are
2115
+ things you wrote on their behalf.
2116
+
2117
+ ---
2118
+
2031
2119
  ## Tips
2032
2120
 
2033
2121
  1. **Specific queries** - "modern office workspace laptop" > "office"
2034
2122
  2. **Style keywords** - Add "minimal", "professional", "dark mode"
2035
2123
  3. **Size matters** - Use \`--size large\` for hero images
2036
2124
  4. **JSON for automation** - Parse results programmatically
2037
- 5. **Generation prompts** - Be detailed, describe style, lighting, composition
2038
- `}function Qe(e){let{name:t,cmd:n}=e;return`---
2039
- name: ${t}-video-search
2125
+ 5. **Simple generations** - one subject, one background: a sentence is enough.
2126
+ For anything carrying a layout, write a spec instead \u2014 see above.
2127
+ 6. **A real person, product or logo** - pass it as
2128
+ \`--reference-image identity=./photo.jpg\` rather than describing it. An exact
2129
+ likeness additionally needs \`--provider google-ai --model gemini-3-pro-image\`
2130
+ **and** the \`image-model-override\` flag on the workspace; without the flag
2131
+ the server drops the pin and the likeness is close, not exact.
2132
+ `}function Lt(t){let{name:e,cmd:n}=t;return`---
2133
+ name: ${e}-video-search
2040
2134
  description: Video search across the web and licensed stock. Find downloadable stock clips for b-roll and backgrounds, or web videos (YouTube, Vimeo) to embed in a slide or microsite.
2041
2135
  ---
2042
2136
 
2043
- # ${t} Video Search
2137
+ # ${e} Video Search
2044
2138
 
2045
2139
  Find video: licensed clips you can download, or web videos you can embed.
2046
2140
 
@@ -2193,8 +2287,7 @@ Found 5 videos for "ocean waves"
2193
2287
  }
2194
2288
  ]
2195
2289
  }
2196
- ],
2197
- "totalCost": 0.001
2290
+ ]
2198
2291
  }
2199
2292
  }
2200
2293
  \`\`\`
@@ -2233,12 +2326,12 @@ ${n} video find "city timelapse" --orientation landscape -n 10
2233
2326
  3. **Preview first** - Use preview URLs to check quality
2234
2327
  4. **License** - Verify license for commercial use
2235
2328
  5. **JSON export** - Save searches for batch processing
2236
- `}function Ze(e){let{name:t,cmd:n}=e;return`---
2237
- name: ${t}-scrape
2329
+ `}function Ut(t){let{name:e,cmd:n}=t;return`---
2330
+ name: ${e}-scrape
2238
2331
  description: Scrape any URL the user provides. Use when user says "check this site", "look at this URL", "use this website", "here's the link", or shares any URL for context. Supports websites, YouTube, Twitter/X.
2239
2332
  ---
2240
2333
 
2241
- # ${t} URL Scraping
2334
+ # ${e} URL Scraping
2242
2335
 
2243
2336
  Extract content from URLs for analysis and context.
2244
2337
 
@@ -2423,12 +2516,12 @@ ${n} scrape https://blog.example.com -f quiet | ${n} create "Blog Summary"
2423
2516
  3. **Use JSON** - For programmatic processing of results
2424
2517
  4. **Combine sources** - Scrape multiple URLs for comprehensive context
2425
2518
  5. **Token count** - Check token usage for large documents
2426
- `}function et(e){let{name:t,cmd:n}=e;return`---
2427
- name: ${t}-branding
2519
+ `}function Ur(t){let{name:e,cmd:n}=t;return`---
2520
+ name: ${e}-branding
2428
2521
  description: Brand profile management. Extract branding from websites, manage saved brands, apply consistent styling to presentations.
2429
2522
  ---
2430
2523
 
2431
- # ${t} Branding Management
2524
+ # ${e} Branding Management
2432
2525
 
2433
2526
  Manage brand profiles for consistent styling across presentations.
2434
2527
 
@@ -2533,12 +2626,12 @@ ${n} branding set-default abc123
2533
2626
  2. **If extraction fails** \u2014 Proceed without branding. Do not manually create brand assets.
2534
2627
  3. **Set default** \u2014 If you mostly work with one brand, set it as default.
2535
2628
  4. **Override** \u2014 Use \`--brand\` flag to override default for specific presentations.
2536
- `}function tt(e){let{name:t,cmd:n}=e,r=t.toUpperCase().replace(/[^A-Z0-9]/g,"_");return`---
2537
- name: ${t}-config
2629
+ `}function jt(t){let{name:e,cmd:n}=t,r=e.toUpperCase().replace(/[^A-Z0-9]/g,"_");return`---
2630
+ name: ${e}-config
2538
2631
  description: CLI configuration management. Set API keys, team IDs, custom API URLs. Verify authentication status.
2539
2632
  ---
2540
2633
 
2541
- # ${t} Configuration
2634
+ # ${e} Configuration
2542
2635
 
2543
2636
  Manage CLI settings and authentication.
2544
2637
 
@@ -2694,89 +2787,70 @@ ${n} config show --verify # Test API key
2694
2787
  \`\`\`bash
2695
2788
  ${n} config set team-id <correct-team-id>
2696
2789
  \`\`\`
2697
- `}var nt=["main","video","presentation","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","config"],un=["standalone","studio"],us={cmd:m.commands[0],pkg:m.packageName,url:m.apiUrl,name:m.name},rt=new Vp("skill").description(`Manage ${m.displayName} skills for AI coding assistants`).addHelpText("after",`
2698
- ${j.bold("Skill Types:")}
2699
- ${j.cyan("main")} Main CLI skill with all capabilities overview
2700
- ${j.cyan("video")} Video-from-scratch pipeline (storyboard \u2192 render)
2701
- ${j.cyan("presentation")} Detailed presentation creation workflow
2702
- ${j.cyan("presentation-edit")} In-app presentation editing (Studio)
2703
-
2704
- ${j.bold("Reference Skills:")}
2705
- ${j.cyan("tts")} Text-to-speech generation (voices, providers, options)
2706
- ${j.cyan("music")} AI music generation (prompts, styles, duration)
2707
- ${j.cyan("sfx")} Sound effects generation (categories, looping, formats)
2708
- ${j.cyan("mix")} Audio mixing (video + voice + music)
2709
- ${j.cyan("image")} Image search and AI generation
2710
- ${j.cyan("video-search")} Stock video search
2711
- ${j.cyan("scrape")} URL content extraction
2712
- ${j.cyan("branding")} Brand profile management
2713
- ${j.cyan("config")} CLI configuration management
2714
-
2715
- ${j.bold("Examples:")}
2716
- ${j.gray("# Install main CLI skill (comprehensive overview)")}
2717
- $ ${m.commands[0]} skill install main
2718
-
2719
- ${j.gray("# Install video skill")}
2720
- $ ${m.commands[0]} skill install video
2721
-
2722
- ${j.gray("# Install presentation skill")}
2723
- $ ${m.commands[0]} skill install presentation
2724
-
2725
- ${j.gray("# Install all skills")}
2726
- $ ${m.commands[0]} skill install
2727
-
2728
- ${j.gray("# Install to specific directory")}
2729
- $ ${m.commands[0]} skill install main --dir ~/.claude
2730
-
2731
- ${j.gray("# Show skill content")}
2732
- $ ${m.commands[0]} skill show main
2733
- `);rt.command("install").description(`Install ${m.displayName} skills for AI coding assistants`).argument("[type]","Skill type: main, video, presentation, or omit for all").option("-d, --dir <path>","Install to specific directory").option("-g, --global","Install globally (to home directory)",!0).option("-l, --local","Install locally (to current directory)").option("-f, --force","Overwrite existing skill files").option("-m, --mode <mode>","Skill mode: standalone (render to file) or studio (Studio Preview)","standalone").action(async(e,t)=>{t.mode&&!un.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Must be one of: ${un.join(", ")}`),process.exit(1));let n={...us,mode:t.mode},r=[];e&&!nt.includes(e)&&(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1));let o=await at();o.source==="snapshot"&&(M(`Live capability catalog unavailable (${o.reason??"unknown reason"}) \u2014 generating from the snapshot baked into this CLI.`),console.log(j.gray(` Run \`${m.commands[0]} login\` then re-run with --force to regenerate from the live catalog.`)));let i=[...rs(n,o,{branding:et(n)}),{name:"tts",content:Je(n)},{name:"music",content:ze(n)},{name:"sfx",content:Xe(n)},{name:"mix",content:He(n)},{name:"image",content:Ye(n)},{name:"video-search",content:Qe(n)},{name:"scrape",content:Ze(n)},{name:"config",content:tt(n)}];(!e||e==="main")&&r.push({name:m.name,content:an(n,o),references:i}),(!e||e==="video")&&r.push({content:cn(n,o),name:`${m.name}-video`,references:is(n,o)}),(!e||e==="presentation")&&r.push({name:`${m.name}-presentation`,content:dn(n)}),(!e||e==="presentation-edit")&&r.push({name:`${m.name}-presentation-edit`,content:sn(n)}),e==="tts"&&r.push({name:`${m.name}-tts`,content:Je(n)}),e==="music"&&r.push({name:`${m.name}-music`,content:ze(n)}),e==="sfx"&&r.push({name:`${m.name}-sfx`,content:Xe(n)}),e==="mix"&&r.push({name:`${m.name}-mix`,content:He(n)}),e==="image"&&r.push({name:`${m.name}-image`,content:Ye(n)}),e==="video-search"&&r.push({name:`${m.name}-video-search`,content:Qe(n)}),e==="scrape"&&r.push({name:`${m.name}-scrape`,content:Ze(n)}),e==="branding"&&r.push({name:`${m.name}-branding`,content:et(n)}),e==="config"&&r.push({name:`${m.name}-config`,content:tt(n)}),console.log();for(let a of r){g(`Installing ${a.name}...`);let d=ln(a.name,a.content,{dir:t.dir,local:t.local,force:t.force},a.references);if(d.installed.length>0&&(x(`${a.name} installed successfully`),R(" Installed to",d.installed.join(", "))),d.skipped.length>0&&(g(` Skipped (already exists): ${d.skipped.join(", ")}`),console.log(j.gray(" Use --force to overwrite"))),d.errors.length>0)for(let l of d.errors)s(` ${l}`);d.installed.length===0&&d.skipped.length===0&&d.errors.length===0&&(g(" No supported AI coding assistants detected"),console.log(j.gray(` Supported editors: ${ms().join(", ")}`)),console.log(j.gray(" Use --dir <path> to install to a specific directory"))),console.log()}});rt.command("show").description("Display skill content").argument("[type]","Skill type (default: main)").option("-m, --mode <mode>","Skill mode: standalone or studio","standalone").action(async(e="main",t)=>{t.mode&&!un.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Must be one of: ${un.join(", ")}`),process.exit(1));let n={...us,mode:t.mode},r=await at(),i={main:()=>an(n,r),video:()=>cn(n,r),presentation:()=>dn(n),"presentation-edit":()=>sn(n),tts:()=>Je(n),music:()=>ze(n),sfx:()=>Xe(n),mix:()=>He(n),image:()=>Ye(n),"video-search":()=>Qe(n),scrape:()=>Ze(n),branding:()=>et(n),config:()=>tt(n)}[e];i?console.log(i()):(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1))});rt.command("uninstall").description(`Remove ${m.displayName} skills from AI coding assistants`).argument("[type]","Skill type: main, video, presentation, or omit for all").option("-g, --global","Uninstall globally (from home directory)",!0).option("-l, --local","Uninstall locally (from current directory)").action(async(e,t)=>{let n=[];e&&!nt.includes(e)&&(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1)),(!e||e==="main")&&n.push(m.name),(!e||e==="video")&&n.push(`${m.name}-video`),(!e||e==="presentation")&&n.push(`${m.name}-presentation`),(!e||e==="presentation-edit")&&n.push(`${m.name}-presentation-edit`),(!e||e==="tts")&&n.push(`${m.name}-tts`),(!e||e==="music")&&n.push(`${m.name}-music`),(!e||e==="sfx")&&n.push(`${m.name}-sfx`),(!e||e==="mix")&&n.push(`${m.name}-mix`),(!e||e==="image")&&n.push(`${m.name}-image`),(!e||e==="video-search")&&n.push(`${m.name}-video-search`),(!e||e==="scrape")&&n.push(`${m.name}-scrape`),(!e||e==="branding")&&n.push(`${m.name}-branding`),(!e||e==="config")&&n.push(`${m.name}-config`),console.log();for(let r of n){let o=mn(r,{local:t.local});if(o.removed.length>0?(x(`${r} uninstalled`),R(" Removed from",o.removed.join(", "))):g(` ${r} not found`),o.errors.length>0)for(let i of o.errors)M(` Failed to remove: ${i}`)}console.log()});import{Command as Gp}from"commander";import kt from"chalk";var ps=new Gp("templates").description("List slide design templates (use with `create --template <id>`)").argument("[search]","Filter templates by name, description, or category").option("-f, --format <format>","Output format (table, json)",b("--format",["table","json"]),"table").option("--limit <n>","Maximum templates to list","25").action(async(e,t)=>{await O();try{let n=Number.parseInt(t.limit??"25",10),{templates:r}=await co(e,Number.isFinite(n)?n:25);if(r.length===0){t.format==="json"?console.log(JSON.stringify([])):g("No templates found");return}if(t.format==="json"){console.log(JSON.stringify(r,null,2));return}for(let o of r){let i=[o.isDefault?kt.green("default"):null,o.category??null,o.recommendedModes?.length?`modes: ${o.recommendedModes.join("/")}`:null].filter(Boolean).join(" \xB7 ");console.log(`${kt.bold(o.name)} ${kt.gray(o.id)}${i?`
2734
- ${kt.gray(i)}`:""}`)}console.log(),console.log(kt.gray(`Use one with: ${m.commands[0]} create "<topic>" --template <id>`))}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Bp}from"commander";import kr from"chalk";var gs=new Bp("whoami").description("Show current user and team information").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O();try{let t=await ye();if(Rn(),e.format==="json"){console.log(JSON.stringify(t,null,2));return}ie("User"),console.log(),R("Email",t.user.email),t.user.username&&R("Username",t.user.username),(t.user.firstName||t.user.lastName)&&R("Name",[t.user.firstName,t.user.lastName].filter(Boolean).join(" "));let n=t.authType==="apiKey"?"API Key":t.authType==="oauth"?"OAuth":"Session";if(R("Auth Type",n),t.currentTeam&&(console.log(),ie("Current Team"),console.log(),R("ID",t.currentTeam.id),R("Name",t.currentTeam.name),R("Plan",t.currentTeam.planName),R("Role",t.currentTeam.isOwner?"Owner":"Member")),t.teams.length>1){console.log(),ie("All Teams"),console.log();for(let r of t.teams){let o=r.isCurrent?kr.green(" (current)"):"";console.log(` ${kr.bold(r.name)}${o}`),console.log(kr.gray(` ID: ${r.id} | Plan: ${r.planName} | Role: ${r.role}`))}}console.log()}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}});function fs(e){return e[0]==="--"?e.slice(1):e}import Cr from"chalk";function Ir(e){e.configureOutput({outputError:(t,n)=>{n(Cr.red(t));let r=/unknown option '(-{1,2}[^'\s=]+)/.exec(t);if(!r)return;let o=Kp(e,r[1]);o&&n(Cr.yellow(`Did you mean '${o}'?
2735
- `)),n(Cr.gray(`Run '${Wp(e)} --help' to see the accepted options.
2736
- `))}});for(let t of e.commands)Ir(t)}function Wp(e){let t=[],n=e;for(;n;)t.unshift(n.name()),n=n.parent;return t.join(" ")}function Kp(e,t){let n,r=Number.POSITIVE_INFINITY;for(let i of e.options)if(!i.hidden)for(let a of[i.short,i.long]){if(!a)continue;let d=Rr(t,a);d<r&&(r=d,n=i.flags)}let o=t.startsWith("--")?2:1;return n!==void 0&&r<=o?n:void 0}function Rr(e,t){if(e===t)return 0;if(e.length===0)return t.length;if(t.length===0)return e.length;let n=Array.from({length:t.length+1},(r,o)=>o);for(let r=1;r<=e.length;r++){let o=[r];for(let i=1;i<=t.length;i++){let a=e[r-1]===t[i-1]?0:1;o[i]=Math.min(o[i-1]+1,n[i]+1,n[i-1]+a)}n=o}return n[t.length]}var zp="0.3.22",W=new Jp,N=m.commands[0];W.name(N).description(`${m.displayName} CLI \u2014 presentations, videos, avatars, audio, branding, media and research`).version(zp,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output");W.addCommand(Mo);Ya(W);W.addCommand(ei);W.addCommand(Zo);W.addCommand(ps);W.addCommand(Yo);W.addCommand(Jo);W.addCommand(gs);W.addCommand(ii);W.addCommand(ai);W.addCommand(Ko);W.addCommand(rt);W.addCommand(Mt);var hs=Ho();hs.commands.length>0&&W.addCommand(hs);function Xp(e){let t=e.toLowerCase(),n=t.length<=4?1:2,r,o=Number.POSITIVE_INFINITY;for(let i of W.commands)for(let a of[i.name(),...i.aliases()]){let d=Rr(t,a.toLowerCase());d<o&&(o=d,r=i.name())}return r!==void 0&&o<=n?r:void 0}W.on("command:*",e=>{let t=String(e[0]);console.error(G.red(`Error: Unknown command '${t}'`)),console.error();let n=Xp(t);n&&console.error(`Did you mean '${n}'?`),console.error(`Run '${N} --help' to see available commands.`),console.error(`Run '${N} capabilities' for the full list of callable capabilities.`),process.exit(1)});W.addHelpText("after",`
2737
- ${G.bold("Start here:")}
2738
- $ ${N} capabilities ${G.gray("# every capability + its exact command path")}
2739
- $ ${N} <group> --help ${G.gray("# drill into any command group above")}
2740
-
2741
- ${G.bold("Common tasks:")}
2742
- ${G.gray("Make a presentation")}
2743
- $ ${N} create "<topic>" --context "..."
2744
- ${G.gray("Turn a finished presentation into an MP4 (narration + avatar)")}
2745
- $ ${N} presentation video <slug>
2746
- ${G.gray("Export a presentation to HTML, PDF or PPTX")}
2747
- $ ${N} export <id-or-slug> -o deck.html
2748
- ${G.gray("Make a video from scratch (no deck)")}
2749
- $ ${N} video storyboard create ${G.gray("then")} $ ${N} video create
2750
- ${G.gray("Regenerate one slide's narration in a video draft")}
2751
- $ ${N} presentation video-narration <project-id>
2752
- ${G.gray("Generate speaker notes")}
2753
- $ ${N} presentation speaker-notes <presentation-id>
2754
- ${G.gray("Import a PowerPoint")}
2755
- $ ${N} presentation import
2756
- ${G.gray("Extract a brand identity from a URL")}
2757
- $ ${N} branding extract <url>
2758
- ${G.gray("Voiceover, music, sound effects")}
2759
- $ ${N} tts generate | ${N} music generate | ${N} sfx generate
2760
- ${G.gray("Find stock footage / images")}
2761
- $ ${N} video find | ${N} image search
2762
- ${G.gray("Read a web page or a YouTube transcript")}
2763
- $ ${N} scrape <url> | ${N} transcript <url>
2764
-
2765
- ${G.bold("Two different video pipelines:")}
2766
- '${N} presentation video ...' renders an EXISTING deck to MP4.
2767
- '${N} video ...' builds a video from a storyboard or brief with stock
2790
+ `}var Rx=["main","video","presentation","presentation-video","presentation-edit","branding","agents"];function X(t,e){return t===void 0||t==="main"?Rx.some(n=>n===e):t===e}var qt=["main","video","presentation","presentation-video","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","agents","config"],jr=["standalone","studio"],Am={cmd:u.commands[0],pkg:u.packageName,url:u.apiUrl,name:u.name},Vt=new Cx("skill").description(`Manage ${u.displayName} skills for AI coding assistants`).addHelpText("after",`
2791
+ ${Z.bold("Skill Types:")}
2792
+ ${Z.cyan("main")} Intent router and capability index
2793
+ ${Z.cyan("presentation")} Create, import, inspect, and export decks
2794
+ ${Z.cyan("presentation-video")} Turn an existing deck into an MP4
2795
+ ${Z.cyan("branding")} Manage private and team brand profiles
2796
+ ${Z.cyan("agents")} Manage scheduled Agents and team roster visibility
2797
+ ${Z.cyan("video")} Build a video from scratch (no deck)
2798
+ ${Z.cyan("presentation-edit")} Legacy Studio editing guide
2799
+
2800
+ ${Z.bold("Reference-only types:")} tts, music, sfx, mix, image, video-search, scrape, config
2801
+
2802
+ ${Z.bold("Examples:")}
2803
+ $ ${u.commands[0]} skill install ${Z.gray("# core suite")}
2804
+ $ ${u.commands[0]} skill install presentation-video
2805
+ $ ${u.commands[0]} skill install branding --dir ~/.claude
2806
+ $ ${u.commands[0]} skill install agents
2807
+ $ ${u.commands[0]} skill show presentation
2808
+ `);Vt.command("install").description(`Install ${u.displayName} skills for AI coding assistants`).argument("[type]","Skill type, or omit to install the core skill suite").option("-d, --dir <path>","Install to specific directory").option("-g, --global","Install globally (to home directory)",!0).option("-l, --local","Install locally (to current directory)").option("-f, --force","Overwrite existing skill files").option("-m, --mode <mode>","Skill mode: standalone (render to file) or studio (Studio Preview)","standalone").action(async(t,e)=>{e.mode&&!jr.includes(e.mode)&&(a(`Invalid mode: ${e.mode}. Must be one of: ${jr.join(", ")}`),process.exit(1));let n={...Am,mode:e.mode},r=[];t&&!qt.includes(t)&&(a(`Invalid skill type: ${t}. Must be one of: ${qt.join(", ")}`),process.exit(1));let o=await Wt();o.source==="snapshot"&&(_(`Live capability catalog unavailable (${o.reason??"unknown reason"}) \u2014 generating from the snapshot baked into this CLI.`),console.log(Z.gray(` Run \`${u.commands[0]} login\` then re-run with --force to regenerate from the live catalog.`)));let i=[...bm(n,o,{branding:Ur(n)}),{name:"tts",content:Pt(n)},{name:"music",content:Ot(n)},{name:"sfx",content:Dt(n)},{name:"mix",content:Nt(n)},{name:"image",content:_t(n)},{name:"video-search",content:Lt(n)},{name:"scrape",content:Ut(n)},{name:"config",content:jt(n)}];X(t,"main")&&r.push({name:u.name,content:Pr(n,o),references:i}),X(t,"video")&&r.push({content:Nr(n,o),name:`${u.name}-video`,references:Rm(n,o)}),X(t,"presentation")&&r.push({name:`${u.name}-presentation`,content:Dr(n,o),references:Tt(n,o,"presentation"),files:At(n,o,"presentation")}),X(t,"presentation-video")&&r.push({name:`${u.name}-presentation-video`,content:Ce(n,o,"presentation-video"),references:Tt(n,o,"presentation-video"),files:At(n,o,"presentation-video")}),X(t,"presentation-edit")&&r.push({name:`${u.name}-presentation-edit`,content:Or(n)}),X(t,"branding")&&r.push({name:`${u.name}-branding`,content:Ce(n,o,"branding"),references:Tt(n,o,"branding"),files:At(n,o,"branding")}),X(t,"agents")&&r.push({name:`${u.name}-agents`,content:Ce(n,o,"agents"),references:Tt(n,o,"agents"),files:At(n,o,"agents")}),X(t,"tts")&&r.push({name:`${u.name}-tts`,content:Pt(n)}),X(t,"music")&&r.push({name:`${u.name}-music`,content:Ot(n)}),X(t,"sfx")&&r.push({name:`${u.name}-sfx`,content:Dt(n)}),X(t,"mix")&&r.push({name:`${u.name}-mix`,content:Nt(n)}),X(t,"image")&&r.push({name:`${u.name}-image`,content:_t(n)}),X(t,"video-search")&&r.push({name:`${u.name}-video-search`,content:Lt(n)}),X(t,"scrape")&&r.push({name:`${u.name}-scrape`,content:Ut(n)}),X(t,"config")&&r.push({name:`${u.name}-config`,content:jt(n)}),console.log();for(let s of r){w(`Installing ${s.name}...`);let c=_r(s.name,s.content,{dir:e.dir,local:e.local,force:e.force},s.references,s.files);if(c.installed.length>0&&(k(`${s.name} installed successfully`),C(" Installed to",c.installed.join(", "))),c.skipped.length>0&&(w(` Skipped (already exists): ${c.skipped.join(", ")}`),console.log(Z.gray(" Use --force to overwrite"))),c.errors.length>0)for(let p of c.errors)a(` ${p}`);c.installed.length===0&&c.skipped.length===0&&c.errors.length===0&&(w(" No supported AI coding assistants detected"),console.log(Z.gray(` Supported editors: ${Tm().join(", ")}`)),console.log(Z.gray(" Use --dir <path> to install to a specific directory"))),console.log()}});Vt.command("show").description("Display skill content").argument("[type]","Skill type (default: main)").option("-m, --mode <mode>","Skill mode: standalone or studio","standalone").action(async(t="main",e)=>{e.mode&&!jr.includes(e.mode)&&(a(`Invalid mode: ${e.mode}. Must be one of: ${jr.join(", ")}`),process.exit(1));let n={...Am,mode:e.mode},r=await Wt(),i={main:()=>Pr(n,r),video:()=>Nr(n,r),presentation:()=>Dr(n,r),"presentation-video":()=>Ce(n,r,"presentation-video"),"presentation-edit":()=>Or(n),tts:()=>Pt(n),music:()=>Ot(n),sfx:()=>Dt(n),mix:()=>Nt(n),image:()=>_t(n),"video-search":()=>Lt(n),scrape:()=>Ut(n),branding:()=>Ce(n,r,"branding"),agents:()=>Ce(n,r,"agents"),config:()=>jt(n)}[t];i?console.log(i()):(a(`Invalid skill type: ${t}. Must be one of: ${qt.join(", ")}`),process.exit(1))});Vt.command("uninstall").description(`Remove ${u.displayName} skills from AI coding assistants`).argument("[type]","Skill type, or omit to remove installed skills").option("-g, --global","Uninstall globally (from home directory)",!0).option("-l, --local","Uninstall locally (from current directory)").action(async(t,e)=>{let n=[];t&&!qt.includes(t)&&(a(`Invalid skill type: ${t}. Must be one of: ${qt.join(", ")}`),process.exit(1)),(!t||t==="main")&&n.push(u.name),(!t||t==="video")&&n.push(`${u.name}-video`),(!t||t==="presentation")&&n.push(`${u.name}-presentation`),(!t||t==="presentation-video")&&n.push(`${u.name}-presentation-video`),(!t||t==="presentation-edit")&&n.push(`${u.name}-presentation-edit`),(!t||t==="tts")&&n.push(`${u.name}-tts`),(!t||t==="music")&&n.push(`${u.name}-music`),(!t||t==="sfx")&&n.push(`${u.name}-sfx`),(!t||t==="mix")&&n.push(`${u.name}-mix`),(!t||t==="image")&&n.push(`${u.name}-image`),(!t||t==="video-search")&&n.push(`${u.name}-video-search`),(!t||t==="scrape")&&n.push(`${u.name}-scrape`),(!t||t==="branding")&&n.push(`${u.name}-branding`),(!t||t==="agents")&&n.push(`${u.name}-agents`),(!t||t==="config")&&n.push(`${u.name}-config`),console.log();for(let r of n){let o=Lr(r,{local:e.local});if(o.removed.length>0?(k(`${r} uninstalled`),C(" Removed from",o.removed.join(", "))):w(` ${r} not found`),o.errors.length>0)for(let i of o.errors)_(` Failed to remove: ${i}`)}console.log()});import{Command as Sx}from"commander";import Gi from"chalk";var Pm=new Sx("whoami").description("Show current user and team information").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async t=>{await y();try{let e=await xe();if(ro(),t.format==="json"){console.log(JSON.stringify(e,null,2));return}ge("User"),console.log(),C("Email",e.user.email),e.user.username&&C("Username",e.user.username),(e.user.firstName||e.user.lastName)&&C("Name",[e.user.firstName,e.user.lastName].filter(Boolean).join(" "));let n=e.authType==="apiKey"?"API Key":e.authType==="oauth"?"OAuth":"Session";if(C("Auth Type",n),e.currentTeam&&(console.log(),ge("Current Team"),console.log(),C("ID",e.currentTeam.id),C("Name",e.currentTeam.name),C("Plan",e.currentTeam.planName),C("Role",e.currentTeam.isOwner?"Owner":"Member")),e.teams.length>1){console.log(),ge("All Teams"),console.log();for(let r of e.teams){let o=r.isCurrent?Gi.green(" (current)"):"";console.log(` ${Gi.bold(r.name)}${o}`),console.log(Gi.gray(` ID: ${r.id} | Plan: ${r.planName} | Role: ${r.role}`))}}console.log()}catch(e){a(e instanceof Error?e.message:String(e)),process.exit(e.exitCode??1)}});function Om(t){return t[0]==="--"?t.slice(1):t}import Wi from"chalk";function Ki(t){t.configureOutput({outputError:(e,n)=>{n(Wi.red(e));let r=/unknown option '(-{1,2}[^'\s=]+)/.exec(e);if(!r)return;let o=$x(t,r[1]);o&&n(Wi.yellow(`Did you mean '${o}'?
2809
+ `)),n(Wi.gray(`Run '${Ex(t)} --help' to see the accepted options.
2810
+ `))}});for(let e of t.commands)Ki(e)}function Ex(t){let e=[],n=t;for(;n;)e.unshift(n.name()),n=n.parent;return e.join(" ")}function $x(t,e){let n,r=Number.POSITIVE_INFINITY;for(let i of t.options)if(!i.hidden)for(let s of[i.short,i.long]){if(!s)continue;let c=Ji(e,s);c<r&&(r=c,n=i.flags)}let o=e.startsWith("--")?2:1;return n!==void 0&&r<=o?n:void 0}function Ji(t,e){if(t===e)return 0;if(t.length===0)return e.length;if(e.length===0)return t.length;let n=Array.from({length:e.length+1},(r,o)=>o);for(let r=1;r<=t.length;r++){let o=[r];for(let i=1;i<=e.length;i++){let s=t[r-1]===e[i-1]?0:1;o[i]=Math.min(o[i-1]+1,n[i]+1,n[i-1]+s)}n=o}return n[e.length]}var Ax="0.3.24",K=new Tx,q=u.commands[0];K.name(q).description(`${u.displayName} CLI \u2014 presentations, videos, avatars, audio, branding, media and research`).version(Ax,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output");K.addCommand(fs);um(K);K.addCommand(Nn);K.addCommand($s);K.addCommand(Ss);K.addCommand(xs);K.addCommand(Pm);K.addCommand(Ds);K.addCommand(Ns);K.addCommand(Is);K.addCommand(Vt);K.addCommand(Mn);var Dm=Cs();Dm.commands.length>0&&K.addCommand(Dm);function Px(t){let e=t.toLowerCase(),n=e.length<=4?1:2,r,o=Number.POSITIVE_INFINITY;for(let i of K.commands)for(let s of[i.name(),...i.aliases()]){let c=Ji(e,s.toLowerCase());c<o&&(o=c,r=i.name())}return r!==void 0&&o<=n?r:void 0}K.on("command:*",t=>{let e=String(t[0]);console.error(B.red(`Error: Unknown command '${e}'`)),console.error();let n=Px(e);n&&console.error(`Did you mean '${n}'?`),console.error(`Run '${q} --help' to see available commands.`),console.error(`Run '${q} capabilities' for the full list of callable capabilities.`),process.exit(1)});K.addHelpText("after",`
2811
+ ${B.bold("Start here:")}
2812
+ $ ${q} capabilities ${B.gray("# every capability + its exact command path")}
2813
+ $ ${q} <group> --help ${B.gray("# drill into any command group above")}
2814
+
2815
+ ${B.bold("Common tasks:")}
2816
+ ${B.gray("Make a presentation")}
2817
+ $ ${q} create "<topic>" --context "..."
2818
+ ${B.gray("Turn a finished presentation into an MP4 (narration + avatar)")}
2819
+ $ ${q} presentation video <slug>
2820
+ ${B.gray("Export a presentation to HTML, PDF or PPTX")}
2821
+ $ ${q} export <id-or-slug> -o deck.html
2822
+ ${B.gray("Make a video from scratch (no deck)")}
2823
+ $ ${q} video storyboard create ${B.gray("then")} $ ${q} video create
2824
+ ${B.gray("Regenerate one slide's narration in a video draft")}
2825
+ $ ${q} presentation video-narration <project-id>
2826
+ ${B.gray("Generate speaker notes")}
2827
+ $ ${q} presentation speaker-notes <presentation-id>
2828
+ ${B.gray("Import a PowerPoint")}
2829
+ $ ${q} presentation import
2830
+ ${B.gray("Extract a brand identity from a URL")}
2831
+ $ ${q} branding extract <url>
2832
+ ${B.gray("Voiceover, music, sound effects")}
2833
+ $ ${q} tts generate | ${q} music generate | ${q} sfx generate
2834
+ ${B.gray("Find stock footage / images")}
2835
+ $ ${q} video find | ${q} image search
2836
+ ${B.gray("Read a web page or a YouTube transcript")}
2837
+ $ ${q} scrape <url> | ${q} transcript <url>
2838
+
2839
+ ${B.bold("Two different video pipelines:")}
2840
+ '${q} presentation video ...' renders an EXISTING deck to MP4.
2841
+ '${q} video ...' builds a video from a storyboard or brief with stock
2768
2842
  and generated footage \u2014 no deck involved.
2769
2843
 
2770
- ${G.bold("Authentication:")}
2771
- Run '${N} login' to authenticate (recommended).
2844
+ ${B.bold("Authentication:")}
2845
+ Run '${q} login' to authenticate (recommended).
2772
2846
  Or set CC_SLIDES_API_KEY environment variable for API key auth.
2773
2847
 
2774
- ${G.bold("Note:")}
2848
+ ${B.bold("Note:")}
2775
2849
  The command list above is not always complete: feature-flag-gated commands
2776
- (the '${N} derive' subcommands) appear only after '${N} login'
2777
- and '${N} config refresh' have cached your feature access. Run
2778
- '${N} capabilities' for the authoritative list.
2850
+ (the '${q} derive' subcommands) appear only after '${q} login'
2851
+ and '${q} config refresh' have cached your feature access. Run
2852
+ '${q} capabilities' for the authoritative list.
2779
2853
 
2780
- ${G.bold("More Info:")}
2781
- ${G.blue(m.docsUrl)}
2782
- `);Ir(W);W.parse(fs(process.argv.slice(2)),{from:"user"});
2854
+ ${B.bold("More Info:")}
2855
+ ${B.blue(u.docsUrl)}
2856
+ `);Ki(K);K.parse(Om(process.argv.slice(2)),{from:"user"});