@conceptcraft/mindframes 0.3.18 → 0.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +476 -241
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,25 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
3
- var h={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 F from"chalk";import{Command as Ap}from"commander";import rt from"chalk";import{Command as Bs}from"commander";function vr(e={}){let t=(s,l)=>{let g=e[s];return g&&g.trim().length>0?g.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 u=typeof h<"u"&&h?h:vr(process.env);import N from"chalk";import pn from"cli-table3";import cs from"conf";var xr=u.apiUrl,ls={apiKey:{type:"string"},apiUrl:{type:"string",default:xr},defaultTeamId:{type:"string"},accessToken:{type:"string"},refreshToken:{type:"string"},tokenExpiresAt:{type:"number"},clientId:{type:"string"},clientSecret:{type:"string"}},P=new cs({projectName:u.name,schema:ls});function kr(){return{apiKey:ue(),apiUrl:V(),defaultTeamId:P.get("defaultTeamId"),accessToken:P.get("accessToken"),refreshToken:P.get("refreshToken"),tokenExpiresAt:P.get("tokenExpiresAt"),clientId:P.get("clientId"),clientSecret:P.get("clientSecret")}}function ue(){let e=process.env[u.apiKeyEnvVar]??process.env.CC_SLIDES_API_KEY;return e||P.get("apiKey")}function un(e){P.set("apiKey",e)}function V(){let e=process.env[u.apiUrlEnvVar]??process.env.CC_SLIDES_API_URL;return e||(P.get("apiUrl")??xr)}function mn(e){P.set("apiUrl",e)}function bt(){return P.get("defaultTeamId")}function Oe(e){P.set("defaultTeamId",e)}function wt(){P.clear()}function et(){return P.path}function Pe(){return!!ue()}function Cr(){return P.get("accessToken")}function Ir(){return P.get("refreshToken")}function vt(e,t,n){P.set("accessToken",e),P.set("refreshToken",t),P.set("tokenExpiresAt",Date.now()+(n-60)*1e3)}function xt(){P.delete("accessToken"),P.delete("refreshToken"),P.delete("tokenExpiresAt")}function Rr(){let e=P.get("tokenExpiresAt");return e?Date.now()>=e:!0}function ke(){return!!P.get("accessToken")&&!!P.get("refreshToken")}function Sr(){return P.get("clientId")}function $r(){return P.get("clientSecret")}function Tr(e,t){P.set("clientId",e),P.set("clientSecret",t)}function C(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(N.green("\u2713"),e)}function d(e,t="human"){if(t!=="quiet"){if(t==="json"){console.error(JSON.stringify({error:e}));return}console.error(N.red("\u2717"),e)}}function M(e,t="human"){t!=="quiet"&&t!=="json"&&console.warn(N.yellow("\u26A0"),e)}function f(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(N.blue("\u2139"),e)}function _e(e,t="en"){return e?`${V()}/${t}/view/presentations/${e}`:"N/A"}function Er(e,t={}){let{showLinks:n=!1,language:r="en"}=t,o=(s,l)=>s.length>l?`${s.slice(0,l-1)}\u2026`:s,i=s=>{try{return new Date(s).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).replace(" at ",", ")}catch{return"-"}};if(n){let s=new pn({head:[N.cyan("Slug"),N.cyan("Title"),N.cyan("Slides"),N.cyan("Created"),N.cyan("URL")]});for(let l of e)s.push([o(l.slug||l.id.slice(0,8),30),o(l.title||"Untitled",22),String(l.numberOfSlides||"-"),i(l.createdAt),_e(l.slug,r)]);return s.toString()}let a=new pn({head:[N.cyan("Slug"),N.cyan("Title"),N.cyan("Slides"),N.cyan("Mode"),N.cyan("Created")],colWidths:[32,28,8,11,18]});for(let s of e)a.push([s.slug||s.id.slice(0,8),s.title||"Untitled",String(s.numberOfSlides||"-"),s.mode||"-",i(s.createdAt)]);return a.toString()}function Ar(e){return e.map(t=>t.slug||t.id).join(`
4
- `)}function Or(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 pn({head:[N.cyan("Name"),N.cyan("Source"),N.cyan("Color"),N.cyan("Logo"),N.cyan("Default"),N.cyan("ID")]});for(let o of t){let i=o.primaryColor?`${N.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"-";r.push([o.name,n(o.sourceUrl),i,o.logoUrl?N.green("\u2713"):N.gray("\u2717"),o.isDefault?N.green("\u2605"):"",o.id])}return r.toString()}function gn(e){try{return new Date(e).toLocaleString()}catch{return e}}function oe(e){console.log(),console.log(N.bold(e)),console.log(N.gray("\u2500".repeat(e.length)))}function S(e,t){console.log(` ${N.gray(`${e}:`)} ${t??"-"}`)}function us(e){return JSON.stringify(e,null,2)}function p(e){console.log(us(e))}import{createHash as Os,randomUUID as tt}from"crypto";import{readFileSync as Ps,statSync as _s}from"fs";import{basename as Vr}from"path";import{spawnSync as ms}from"child_process";import{existsSync as ps,mkdtempSync as gs,rmSync as fs,writeFileSync as hs}from"fs";import{tmpdir as ys}from"os";import{join as Pr}from"path";import fn from"ffmpeg-static";var bs=/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/;function ws(e){let t=bs.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 _r(e,t="audio"){if(e.length===0)return;let n=fn&&ps(fn)?fn:"ffmpeg",r=/^[a-z0-9]+$/i.test(t)?t:"audio",o=gs(Pr(ys(),"mf-tts-duration-")),i=Pr(o,`speech.${r}`);try{hs(i,e);let a=ms(n,["-hide_banner","-i",i],{encoding:"utf8"});return a.error?void 0:ws(a.stderr??"")}finally{fs(o,{force:!0,recursive:!0})}}import kt 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 vs(){let e=Ir(),t=Sr(),n=V();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 s=await fetch(o.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!s.ok)return xt(),null;let l=await s.json();return vt(l.access_token,l.refresh_token,l.expires_in),l.access_token}catch{return null}}async function Lr(){return ke()?Rr()?vs():Cr()||null:null}function ie(){return ke()||Pe()}async function A(){if(!ie()){let e=u.commands[0],t=u.apiKeyEnvVar;console.error(kt.red("\u2717 Not authenticated.")),console.error(),console.error(kt.bold("To authenticate, run:")),console.error(kt.cyan(` ${e} login`)),console.error(),console.error(kt.gray(`Or set ${t} environment variable.`)),process.exit(c.AUTH_ERROR)}}function xs(e){return e.length<=14?"****":`${e.slice(0,10)}...${e.slice(-4)}`}function Dr(){let e=ue();if(e)return xs(e)}function hn(e){return["cc_slides_","mcp_","cc_sk_","sk_"].some(n=>e.startsWith(n))}import{mkdirSync as ks,readFileSync as Cs,writeFileSync as Is}from"fs";import{homedir as Rs}from"os";import{join as Nr}from"path";import Ss from"ajv/dist/2020.js";var yn=new Map;function Ur(){return Nr(Rs(),".conceptcraft","schemas")}function qr(e){return Nr(Ur(),`${e}.json`)}function $s(e){try{let t=JSON.parse(Cs(qr(e),"utf8"));return typeof t?.catalogVersion=="number"&&t.schema?t:null}catch{return null}}function Ts(e,t){try{ks(Ur(),{recursive:!0}),Is(qr(e),JSON.stringify(t))}catch{}}async function Es(e){let t=yn.get(e);if(t!==void 0)return t;try{let n=await Mr(e),r={catalogVersion:n.catalogVersion,schema:n.schema};return Ts(e,r),yn.set(e,r),r}catch{let n=$s(e);return yn.set(e,n),n}}function As(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 Ct(e,t){let n=await Es(e);if(!n)return;let r;try{r=new Ss({allErrors:!0,strict:!1}).compile(n.schema)}catch{return}if(r(t))return;let o=(r.errors??[]).slice(0,10).map(As);throw new Error(`Request does not match the ${e} contract \u2014 ${o.join("; ")}`)}async function se(){let e=await Lr();if(e)return{Authorization:`Bearer ${e}`};let t=ue();return t?{"x-api-key":t}:{}}var O=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},jr="Idempotency-Key";function Ls(e){return e&&e!=="GET"?{[jr]:tt()}:{}}async function W(e,t={}){let n=V();if(!ie()&&!t.allowUnauthenticated)throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2,"authentication_required");let r=await se(),o=`${n}${e}`,i={...r,...Ls(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 s;try{s=await fetch(o,a)}catch(g){throw new O(`Network error: ${g instanceof Error?g.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!s.ok){let g=await s.text().catch(()=>""),m=Ns(g,s.status),w=1;switch(s.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=`[${m.code}] ${m.message}`;throw new O(v,s.status,w,m.code,m.retryable)}return t.stream?s:s.headers.get("content-type")?.includes("application/json")?s.json():s.text()}function Ds(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 Ns(e,t){let n=Ds(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 Mr(e){return W(`/api/cli/tools/${encodeURIComponent(e)}/schema`)}async function Gr(){return W("/api/cli/capabilities",{allowUnauthenticated:!0})}async function T(e,t,n){let r=n?`?teamId=${encodeURIComponent(n)}`:"";return W(`/api/cli/tool-runs/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`)}async function y(e,t,n){return W(`/api/cli/tools/${encodeURIComponent(e)}`,{body:t,headers:n?{[jr]:n}:void 0,method:"POST"})}async function Br(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(s){if(s instanceof O&&s.retryable&&o<2){o+=1,await new Promise(l=>setTimeout(l,2e3));continue}throw s instanceof O?new O(`${s.message} Request ID: ${t}.`,s.statusCode,s.exitCode,s.errorCode,s.retryable):new O(`${s instanceof Error?s.message:"Unknown error"} Request ID: ${t}.`,0,5,"poll_failed",!0)}if(a.done){if(a.error)throw new O(`[${a.error.code??"operation_failed"}] ${a.error.message} Request ID: ${t}.`,500,1,a.error.code??"operation_failed",a.error.retryable);return a}await new Promise(s=>setTimeout(s,(a.nextPollAfterSeconds??2)*1e3))}throw new O(`[operation_timed_out] The background operation timed out. Request ID: ${t}.`,408,1,"operation_timed_out",!0)}function It(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 Us(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 qs(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 de(e,t={}){let n=V();if(!ie())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let r=await se(),o=_s(e),i=Vr(e),a=qs(e),s=Ps(e),l=Os("sha256").update(s).digest("hex"),g=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(!g.ok){let $=await g.text();throw new O($||"Failed to get upload URL",g.status,1)}let m=await g.json(),w=new FormData;for(let[$,x]of Object.entries(m.fields||{}))w.append($,x);let v=new Blob([s],{type:a});w.append("file",v,i);let b=await fetch(m.url,{method:"POST",body:w});if(!b.ok)throw new O("Failed to upload file to storage",b.status,1);return{id:tt(),name:i,url:m.fileUrl,size:o.size,type:a,selected:!0}}async function Wr(e,t){let n=[];for(let r=0;r<e.length;r++){let o=e[r],i=Vr(o);t?.(r,e.length,i);let a=await de(o);n.push(a)}return t?.(e.length,e.length,""),n}async function Kr(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),y("createSlides",{...t,approvalReceipt:"cli:create"})}async function Jr(e,t=20){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("teamId",e),(await W(`/api/cli/presentations?${n}`)).presentations}async function fe(e){return W(`/api/cli/presentation/${encodeURIComponent(e)}`)}async function zr(e,t){return W(`/api/cli/presentation/${encodeURIComponent(e)}/speaker-notes`,{body:t,method:"POST"})}async function Xr(e,t){return W(`/api/cli/presentation-video/${encodeURIComponent(e)}/narration`,{body:t,method:"POST"})}async function bn(e){let t=V(),n=await fetch(`${t}/api/durable-runs/${encodeURIComponent(e)}/events`,{headers:await se()});if(!n.ok)throw new O(await n.text(),n.status);return n}async function Hr(e){await W(`/api/cli/presentation/${encodeURIComponent(e)}`,{method:"DELETE"})}async function Yr(e,t={}){let n=V();if(!ie())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let r=await se(),o=await fetch(`${n}/api/presentations/export`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({presentationId:e,options:{includeImages:t.includeImages??!0,includeBranding:t.includeBranding??!0,downloadExternalImages:t.includeExternal??!0}})});if(!o.ok)throw new O(await o.text(),o.status,o.status===404?3:1);return o.arrayBuffer()}async function Qr(e,t,n={}){let r=V();if(!ie())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await se(),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 s=await fetch(`${r}/api/presentations/import`,{method:"POST",headers:o,body:i}),l=await s.json();if(!s.ok)throw new O(l.errors?.[0]?.message??"Import failed",s.status,1);return l}async function wn(){return W("/api/cli/branding")}async function Zr(e,t=25){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("search",e),W(`/api/cli/templates?${n}`)}async function eo(e){return W(`/api/branding/${e}`)}async function to(e,t,n){return y("extractBranding",{approvalReceipt:n,teamId:t,url:e})}async function me(){return W("/api/cli/whoami")}async function no(){return W("/api/cli/features")}async function ro(e,t,n={}){let r=V();if(!ie())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await se(),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 O(await i.text(),i.status,i.status===404?3:1);return i}async function Ms(e){let t=new URLSearchParams;e&&t.set("teamId",e);let n=t.toString();return W(`/api/cli/limits${n?`?${n}`:""}`)}async function oo(e,t,n){let r=await Ms(n);if(!r.canGenerate[e]){let o=r.remaining[e]??0,i=r.limits[e]??0;throw i===0?new O(`The "${e}" mode is not available on your ${r.planName} plan. Available modes: ${r.availableModes.join(", ")||"none"}`,403,2):new O(`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 O(`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 Fs(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 io(e){let t={...e,text:Fs(e.text)};await Ct("generateSpeech",t);let n=await y("generateSpeech",{approvalReceipt:"cli:tts-generate",...t}),r=await Br("generateSpeech",n.runId),o=r.entity?.url;if(!o)throw new O(`Speech completed without an audio URL. Request ID: ${n.runId}.`,500);let i;try{i=await fetch(o)}catch(w){throw new O(`${w instanceof Error?w.message:"Failed to download speech audio"} Request ID: ${n.runId}.`,0,5,"download_failed",!0)}if(!i.ok)throw new O(`Failed to download speech audio. Request ID: ${n.runId}.`,i.status,5,"download_failed",i.status===429||i.status>=500);let a=r.output??{},s=e.options??{},l=ae(a.format)??Us(o)??"mp3",g=Buffer.from(await i.arrayBuffer()),m=ao(a.durationSec,a.duration,a.duration_s)??_r(g,l);if(m===void 0)throw new O(`Speech completed without a measurable duration. Request ID: ${n.runId}.`,500,1,"invalid_audio_metadata");return{audioData:g,audioUrl:o,duration:m,cost:Ce(a.costUsd)??Ce(a.cost)??0,provider:ae(a.provider)??s.provider??"gemini",format:l,requestId:n.runId,voiceId:ae(a.voice_id)??ae(a.voiceId),voice:ae(a.voice),model:ae(a.model),speed:Ce(a.speed)??s.speed,language:ae(a.lang)??ae(a.language)??s.language,langApplied:Fr(a.langApplied)??Fr(a.lang_applied),timestamps:Vs(a.timestamps),wordTimings:js(a.timestamps??a.timings)}}function ao(...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 Vs(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 js(e){if(!Array.isArray(e))return;let t=e.flatMap(n=>{if(!n||typeof n!="object"||Array.isArray(n))return[];let r=n,o=ae(r.text)??ae(r.word),i=Ce(r.start),a=Ce(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 ae(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Ce(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Fr(e){return typeof e=="boolean"?e:void 0}async function so(e){let t=e?`/api/cli/tts?provider=${e}`:"/api/cli/tts";return W(t)}async function co(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;return delete t.idempotency_key,await Ct("generateMusic",t),{requestId:(await y("generateMusic",{...t,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function vn(e){let t=await T("generateMusic",e);return{requestId:e,status:It(t),audioUrl:t.entity?.url,duration:ao(t.output?.durationSec,t.output?.duration,t.output?.duration_s),cost:Ce(t.output?.costUsd)??Ce(t.output?.cost),error:t.error?.message}}async function lo(e){return{requestId:(await y("mixAudio",{...e,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function xn(e){let t=await T("mixAudio",e);return{requestId:e,status:It(t),outputUrl:t.entity?.url,error:t.error?.message}}async function uo(e){return W("/api/cli/images/search",{method:"POST",body:e})}async function mo(e){return W("/api/cli/videos/search",{method:"POST",body:e})}async function Q(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 O&&a.retryable&&r<2){r+=1,await new Promise(s=>setTimeout(s,n));continue}throw a}if(i.status==="completed"||i.status==="failed")return i;await new Promise(a=>setTimeout(a,n))}throw new O("Operation timed out",408,1)}async function po(e,t,n){return y("getYoutubeTranscript",{...n?{language:n}:{},teamId:t,url:e})}async function go(e,t){let n=await y("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 fo(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;delete t.idempotency_key,await Ct("generateSfx",t);let r=await y("generateSfx",{...t,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function kn(e){let t=await T("generateSfx",e);return{id:t.entity?.id??e,requestId:e,status:It(t),audioUrl:t.entity?.url,error:t.error?.message}}async function ho(e){return y("listPresenterOptions",{...e?{voiceLanguage:e}:{}})}async function yo(e){return{requestId:(await y("generateAvatarVideo",{...e,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function Cn(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:It(t),videoUrl:t.entity?.url}}async function bo(e){return y("lipsyncVideo",{...e,approvalReceipt:"cli:video-lipsync"})}async function wo(){return(await y("listTranslationLanguages",{})).languages}async function vo(e){return y("translateVideo",{...e,approvalReceipt:"cli:video-translate"})}async function xo(e,t,n){return y("createVideo",{...e,approvalReceipt:t},n)}async function ko(e){let{idempotencyKey:t,...n}=e;return y("analyzeVideoReference",n,t)}async function Co(e,t){return Br("analyzeVideoReference",e,t)}async function Io(e){return y("listCastPresets",e)}async function Ro(e){return y("createCastPreset",e,tt())}async function So(e){return y("updateCastPreset",e,tt())}async function $o(e){return y("deleteCastPreset",{presetId:e},tt())}var To=[{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:"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 Rt(e){return{capabilities:To,catalogVersion:1,reason:e,source:"snapshot"}}async function nt(e=Gr){try{let{capabilities:t,catalogVersion:n}=await e();return!Array.isArray(t)||t.length===0?Rt("the live catalog returned no capabilities"):{capabilities:t,catalogVersion:n,source:"live"}}catch(t){let n=t instanceof Error?t.message:String(t);return Rt(n)}}var Eo=["presentations","media","branding","knowledge","research","artifacts","agents"],Ws=80,Ks=30;function Js(e){return e.billing!==void 0&&e.billing!=="free"&&e.billing!=="quota"}function zs(e){return e.lifecycle?.mode==="background"}function Xs(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 Ao(e){let t=Eo.indexOf(e);return t===-1?Eo.length:t}function Hs(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 Ys(e){let t=new Map;for(let i of e){let a=i.category??"other",s=t.get(a);s?s.push(i):t.set(a,[i])}let n=[...t.entries()].sort(([i],[a])=>{let s=Ao(i)-Ao(a);return s!==0?s:i.localeCompare(a)}),r=Math.min(Ks,Math.max(...e.map(i=>i.name.length))),o=[];for(let[i,a]of n){a.sort((s,l)=>s.name.localeCompare(l.name)),o.length>0&&o.push(""),o.push(rt.bold(`${i} (${a.length})`));for(let s of a){let l=`${Js(s)?"$":" "}${zs(s)?"*":" "}`,g=s.name.padEnd(r),m=2+r+1+l.length+1,w=Math.max(24,Ws-m),v=Xs(s.description??"",w);o.push(` ${rt.cyan(g)} ${rt.yellow(l)} ${v[0]??""}`.trimEnd());for(let b of v.slice(1))o.push(`${" ".repeat(m)}${b}`)}}return o}function Qs(e){return e.map(t=>`${t.name} ${t.state} ${t.milestone}`)}function Zs(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 Qs(e);let r=u.commands[0],o=Ys(e);return o.push(""),o.push(rt.dim(`${e.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(rt.dim(`Filter with: ${r} capabilities --search <query>`)),o}var Oo=new Bs("capabilities").description("Index of everything this CLI can do \u2014 every command, grouped and described").option("-f, --format <format>","Output 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 nt(),n=Hs(t.capabilities,e),r=!!(e.search||e.category);if(e.format==="json"){p({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 Zs(n,{filtered:r}))console.log(o)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdirSync as rd,writeFileSync as od}from"fs";import{dirname as Do,join as id}from"path";import{Command as he}from"commander";import ot from"chalk";import{input as ad,password as sd,confirm as No,select as dd}from"@inquirer/prompts";import $t from"ora";import ed from"conf";var St=new ed({projectName:"conceptcraft",configName:"feature-cache"}),td=3600*1e3,nd=1440*60*1e3;function Po(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 _o(){if(!Pe())return null;let e=St.get("featureFlags");if(!e)return null;let t=Po(ue());if(e.apiKeyHash&&e.apiKeyHash!==t)return Re(),null;let n=Date.now()-e.fetchedAt;return n>nd?null:(n>td&&In(),e.flags)}function In(){Ie().catch(()=>{})}async function Ie(){let e=await no(),t=ue();return St.set("featureFlags",{flags:e,fetchedAt:Date.now(),apiKeyHash:t?Po(t):void 0}),e}function Re(){St.delete("featureFlags")}function Lo(){return St.path}var Uo=new he("config").description("Manage CLI configuration: account settings, and the cached feature flags that decide which commands appear").addCommand(new he("init").description("Initialize configuration interactively").action(async()=>{console.log(),console.log(ot.bold(`${u.displayName} CLI Configuration`)),console.log(ot.gray("\u2500".repeat(35))),console.log();try{let e=await sd({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":hn(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(un(e.trim()),await No({message:`Use a custom API URL? (default: ${u.apiUrl.replace("https://","")})`,default:!1})){let r=await ad({message:"Enter API URL:",default:V(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});mn(r)}console.log();let n=$t("Verifying API key...").start();try{let r=await me();if(n.succeed("API key verified!"),console.log(),f(`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];Oe(o.id),f(`Team: ${o.name} (${o.planName})`)}else{console.log(),f(`You have access to ${r.teams.length} teams.`);let o=await dd({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});Oe(o);let i=r.teams.find(a=>a.id===o);C(`Selected team: ${i?.name}`)}try{await Ie()}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: ${u.commands[0]} config set team-id <id>`)}console.log(),C("Configuration saved!"),f(`Config file: ${et()}`),console.log()}catch(e){if(e.name==="ExitPromptError"){console.log(),f("Configuration cancelled.");return}throw e}})).addCommand(new he("show").description("Show current configuration").option("--verify","Verify API key and show team details").action(async e=>{let t=kr();if(oe("Current Configuration"),console.log(),S("API Key",Dr()??ot.red("Not set")),S("API URL",t.apiUrl),S("Default Team ID",t.defaultTeamId??ot.gray("Not set")),console.log(),S("Config file",et()),e.verify&&t.apiKey){console.log();let n=$t("Verifying...").start();try{let r=await me();n.succeed("Verified"),console.log(),S("User",r.user.email),r.currentTeam&&S("Current Team",`${r.currentTeam.name} (${r.currentTeam.planName})`),r.teams.length>1&&S("Total Teams",String(r.teams.length))}catch(r){n.fail("Verification failed"),M(r instanceof Error?r.message:String(r))}}console.log()})).addCommand(new he("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":hn(t)||(d("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),un(t),Re(),C("API key updated"),Ie().catch(()=>{});break;case"api-url":try{new URL(t),mn(t),C(`API URL set to: ${t}`)}catch{d("Invalid URL format"),process.exit(6)}break;case"team-id":Oe(t),C(`Default team ID set to: ${t}`);break;default:d(`Unknown config key: ${e}`),console.log(ot.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new he("clear").description("Clear all configuration").action(async()=>{try{await No({message:"Are you sure you want to clear all configuration?",default:!1})?(wt(),Re(),C("Configuration cleared")):f("Cancelled")}catch{f("Cancelled")}})).addCommand(new he("refresh").description("Refresh cached feature flags").action(async()=>{let e=$t("Refreshing feature flags...").start();try{await Ie(),e.succeed("Feature flags refreshed"),f(`Run '${u.commands[0]} --help' to see updated commands`)}catch(t){e.fail("Failed to refresh"),d(t instanceof Error?t.message:String(t)),process.exit(1)}})).addCommand(new he("path").description("Show configuration file path").option("--cache","Show feature cache file path").action(e=>{e.cache?console.log(Lo()):console.log(et())})).addCommand(new he("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 se(),n=await fetch(`${V()}/api/cli/settings`,{headers:t});if(!n.ok)throw new Error(`Request failed (HTTP ${n.status})`);let r=await n.text(),o=id(Do(et()),"settings.toml");rd(Do(o),{recursive:!0}),od(o,r,"utf8"),e.succeed("Settings pulled"),f(`Written to ${o}`)}catch(t){e.fail("Failed to pull settings"),d(t instanceof Error?t.message:String(t)),process.exit(1)}}));import{Command as cd}from"commander";import{confirm as ld}from"@inquirer/prompts";var qo=new cd("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 A(),!t.force)try{if(!await ld({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 Hr(e),t.quiet||C(`Presentation "${e}" deleted`)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Le}from"commander";import Fo from"chalk";import ud from"ora";import{createParser as vf}from"eventsource-parser";import kf from"chalk";import If from"ora";async function Mo(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 s=r.decode(a.value,{stream:!0});o+=s,t.quiet||process.stdout.write(s)}}return t.quiet||console.log(),o}function md(){return new Le("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)","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 A();let n=parseInt(t.words,10);(Number.isNaN(n)||n<50||n>2e3)&&(d("Word count must be between 50 and 2000"),process.exit(6));let r=["professional","casual","educational"];r.includes(t.tone)||(d(`Invalid tone. Valid options: ${r.join(", ")}`),process.exit(6));let o=ud("Fetching presentation...").start();try{let i=await fe(e);o.text="Generating blog post...";let a=await ro(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}),s=await Mo(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:s},null,2)):t.format==="markdown"?console.log(s):(console.log(),console.log(Fo.bold(`Blog: ${i.title}`)),console.log(Fo.gray("\u2500".repeat(40))),console.log(),console.log(s),console.log())}catch(i){o.fail("Generation failed"),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})}function pd(){return new Le("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)","human").action(async(e,t)=>{await A(),f("Tweet generation coming soon.")})}function gd(){return new Le("linkedin").description("Generate a LinkedIn carousel from a presentation").argument("<slug>","Presentation slug").option("-f, --format <format>","Output format (human, json)","human").action(async e=>{await A(),f("LinkedIn carousel generation coming soon.")})}function fd(){return new Le("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)","human").action(async(e,t)=>{await A(),f("Question generation coming soon.")})}function hd(){return new Le("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)","human").action(async(e,t)=>{await A(),f("Cheat sheet generation coming soon.")})}function Vo(){let e=new Le("derive").description("Generate derivative content from a presentation"),t=_o();return t&&(t.deckToBlog&&e.addCommand(md()),t.deckToTweets&&e.addCommand(pd()),t.linkedInCarousel&&e.addCommand(gd()),t.redTeamQuestions&&e.addCommand(fd()),t.presenterCheatSheet&&e.addCommand(hd())),e}import Tt from"chalk";import{Command as yd}from"commander";import{writeFile as bd}from"fs/promises";import{resolve as jo}from"path";import wd from"ora";var Rn=new yd("export").description("Export a presentation to a ZIP of HTML and its assets").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-o, --output <path>","Output file path").option("--include-images","Include images (default: true)",!0).option("--include-branding","Include branding (default: true)",!0).option("--no-external","Skip external image downloads").action(async(e,t)=>{await A();let n=wd("Fetching presentation...").start();try{let r=await fe(e),o=r.title||e,i=r.id,a=e.replace(/[^a-z0-9-]/gi,"_").toLowerCase().substring(0,50),s=new Date().toISOString().split("T")[0],l=`${a}_${s}.zip`,g=t.output?jo(t.output):jo(process.cwd(),l);n.text=`Exporting "${o}"...`;let m=await Yr(i,{includeImages:t.includeImages,includeBranding:t.includeBranding,includeExternal:!t.noExternal});n.text="Saving file...",await bd(g,Buffer.from(m)),n.succeed("Export complete!"),console.log(),f(`File saved: ${g}`),f(`Size: ${vd(m.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),d(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function vd(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}Rn.addHelpText("after",`
5
- ${Tt.bold("Examples:")}
6
- ${Tt.gray("# HTML + assets ZIP of a deck")}
7
- $ ${u.commands[0]} export <slug> -o deck.zip
8
-
9
- ${Tt.bold("See also:")}
10
- ${Tt.gray("# For an MP4 instead of a ZIP")}
11
- $ ${u.commands[0]} presentation video <slug>
12
- `);import{Command as xd}from"commander";import Sn from"chalk";var Go=new xd("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)","human").action(async e=>{await A(),f("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 kd}from"commander";import{readFile as Cd}from"fs/promises";import{resolve as Id,basename as Rd}from"path";import Sd from"ora";var Bo=new kd("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");Bo._hidden=!0;var Wo=Bo.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 A();try{(await me()).user.role!=="admin"&&(d("This command is only available to administrators"),process.exit(2))}catch{d("Failed to verify permissions"),process.exit(2)}let n=Id(e),r=Rd(n);r.endsWith(".zip")||(d("File must be a ZIP archive"),process.exit(6));let o=Sd("Reading file...").start();try{let i=await Cd(n);t.dryRun?o.text="Validating...":o.text="Importing presentation...";let a=await Qr(i,r,{dryRun:t.dryRun});if(a.success){if(t.dryRun)o.succeed("Validation passed!"),console.log(),f("The file is valid and can be imported."),a.statistics&&(console.log(),S("Slides",String(a.statistics.slidesImported)),S("Images",String(a.statistics.imagesUploaded)));else if(o.succeed("Import complete!"),console.log(),S("Presentation ID",a.presentationId??"N/A"),S("Document ID",a.documentId??"N/A"),a.statistics&&(S("Slides imported",String(a.statistics.slidesImported)),S("Images uploaded",String(a.statistics.imagesUploaded)),S("Time",`${a.statistics.totalTimeMs}ms`)),a.presentationId){let s=V();S("View URL",`${s}/p/${a.presentationId}`)}if(a.warnings&&a.warnings.length>0){console.log();for(let s of a.warnings)M(s)}console.log()}else{if(o.fail("Import failed"),console.log(),a.errors)for(let s of a.errors)d(`${s.type}: ${s.message}`);process.exit(1)}}catch(i){o.fail("Import failed"),i.code==="ENOENT"&&(d(`File not found: ${n}`),process.exit(3)),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}});import{Command as $d}from"commander";var Ko=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)","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 A();let t=parseInt(e.limit,10);(Number.isNaN(t)||t<1)&&(d("Invalid limit value"),process.exit(6));let n=e.teamId??bt();n||(d("`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 Jr(n,t);if(r.length===0){e.format==="json"?console.log(JSON.stringify([])):e.format!=="ids"&&f("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(Ar(r));break;default:console.log(Er(r,{showLinks:e.detail,language:e.language}));break}}catch(r){d(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});import{createHash as Td,randomBytes as Xo}from"crypto";import Ho from"http";import Jo from"chalk";import{Command as Ed}from"commander";import Ad from"open";import zo from"ora";var Od=`${u.displayName} CLI`,Pd=8765,_d=8775,Ld=["presentations:read","presentations:write","media:read","media:write"];function Dd(){return Xo(32).toString("base64url")}function Nd(e){return Td("sha256").update(e).digest("base64url")}function Ud(){return Xo(16).toString("hex")}async function qd(e,t){for(let n=e;n<=t;n++)try{return await new Promise((r,o)=>{let i=Ho.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 Md(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 Fd(e){let t=e.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(t?.length?t:Ld).join(" ")}async function Vd(e,t,n){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:Od,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 jd(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 s=await a.text();throw new Error(`Token exchange failed: ${s}`)}return a.json()}function Gd(e,t){return new Promise((n,r)=>{let o,i=!1,a=()=>{i||(i=!0,clearTimeout(o),process.off("SIGINT",s),process.off("SIGTERM",s),l.close())},s=()=>{a(),r(new Error("Login cancelled"))},l=Ho.createServer((g,m)=>{let w=new URL(g.url||"",`http://localhost:${e}`);if(w.pathname!=="/callback"){m.writeHead(404),m.end("Not found");return}let v=w.searchParams.get("code"),b=w.searchParams.get("state"),$=w.searchParams.get("error"),x=w.searchParams.get("error_description");if(m.writeHead(200,{"Content-Type":"text/html"}),$){m.end(`
3
+ var h={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 ug}from"commander";import ct from"chalk";import{Command as dd}from"commander";function Or(e={}){let t=(s,l)=>{let f=e[s];return f&&f.trim().length>0?f.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 h<"u"&&h?h:Or(process.env);import L from"chalk";import vn from"cli-table3";import Ss from"conf";var Pr=m.apiUrl,$s={apiKey:{type:"string"},apiUrl:{type:"string",default:Pr},defaultTeamId:{type:"string"},accessToken:{type:"string"},refreshToken:{type:"string"},tokenExpiresAt:{type:"number"},clientId:{type:"string"},clientSecret:{type:"string"}},_=new Ss({projectName:m.name,schema:$s});function _r(){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 bn(e){_.set("apiKey",e)}function B(){let e=process.env[m.apiUrlEnvVar]??process.env.CC_SLIDES_API_URL;return e||(_.get("apiUrl")??Pr)}function wn(e){_.set("apiUrl",e)}function Rt(){return _.get("defaultTeamId")}function Ne(e){_.set("defaultTeamId",e)}function St(){_.clear()}function at(){return _.path}function qe(){return!!ge()}function Lr(){return _.get("accessToken")}function Dr(){return _.get("refreshToken")}function $t(e,t,n){_.set("accessToken",e),_.set("refreshToken",t),_.set("tokenExpiresAt",Date.now()+(n-60)*1e3)}function Tt(){_.delete("accessToken"),_.delete("refreshToken"),_.delete("tokenExpiresAt")}function Nr(){let e=_.get("tokenExpiresAt");return e?Date.now()>=e:!0}function $e(){return!!_.get("accessToken")&&!!_.get("refreshToken")}function qr(){return _.get("clientId")}function Ur(){return _.get("clientSecret")}function jr(e,t){_.set("clientId",e),_.set("clientSecret",t)}function I(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(L.green("\u2713"),e)}function d(e,t="human"){if(t!=="quiet"){if(t==="json"){console.error(JSON.stringify({error:e}));return}console.error(L.red("\u2717"),e)}}function F(e,t="human"){t!=="quiet"&&t!=="json"&&console.warn(L.yellow("\u26A0"),e)}function Mr(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 Ue(e,t="en"){return e?`${B()}/${t}/view/presentations/${e}`:"N/A"}function Fr(e,t={}){let{showLinks:n=!1,language:r="en"}=t,o=(s,l)=>s.length>l?`${s.slice(0,l-1)}\u2026`:s,i=s=>{try{return new Date(s).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).replace(" at ",", ")}catch{return"-"}};if(n){let s=new vn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Created"),L.cyan("URL")]});for(let l of e)s.push([o(l.slug||l.id.slice(0,8),30),o(l.title||"Untitled",22),String(l.numberOfSlides||"-"),i(l.createdAt),Ue(l.slug,r)]);return s.toString()}let a=new vn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Mode"),L.cyan("Created")],colWidths:[32,28,8,11,18]});for(let s of e)a.push([s.slug||s.id.slice(0,8),s.title||"Untitled",String(s.numberOfSlides||"-"),s.mode||"-",i(s.createdAt)]);return a.toString()}function Vr(e){return e.map(t=>t.slug||t.id).join(`
4
+ `)}function Gr(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 vn({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 xn(e){try{return new Date(e).toLocaleString()}catch{return e}}function oe(e){console.log(),console.log(L.bold(e)),console.log(L.gray("\u2500".repeat(e.length)))}function $(e,t){console.log(` ${L.gray(`${e}:`)} ${t??"-"}`)}function Ts(e){return JSON.stringify(e,null,2)}function u(e){console.log(Ts(e))}import{createHash as zs,randomUUID as st}from"crypto";import{readFileSync as Xs,statSync as Hs}from"fs";import{basename as eo}from"path";import{spawnSync as Es}from"child_process";import{existsSync as As,mkdtempSync as Os,rmSync as Ps,writeFileSync as _s}from"fs";import{tmpdir as Ls}from"os";import{join as Br}from"path";import kn from"ffmpeg-static";var Ds=/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/;function Ns(e){let t=Ds.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 Wr(e,t="audio"){if(e.length===0)return;let n=kn&&As(kn)?kn:"ffmpeg",r=/^[a-z0-9]+$/i.test(t)?t:"audio",o=Os(Br(Ls(),"mf-tts-duration-")),i=Br(o,`speech.${r}`);try{_s(i,e);let a=Es(n,["-hide_banner","-i",i],{encoding:"utf8"});return a.error?void 0:Ns(a.stderr??"")}finally{Ps(o,{force:!0,recursive:!0})}}import Et 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 qs(){let e=Dr(),t=qr(),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=Ur();a&&i.set("client_secret",a);let s=await fetch(o.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!s.ok)return Tt(),null;let l=await s.json();return $t(l.access_token,l.refresh_token,l.expires_in),l.access_token}catch{return null}}async function Kr(){return $e()?Nr()?qs():Lr()||null:null}function fe(){return $e()||qe()}async function O(){if(!fe()){let e=m.commands[0],t=m.apiKeyEnvVar;console.error(Et.red("\u2717 Not authenticated.")),console.error(),console.error(Et.bold("To authenticate, run:")),console.error(Et.cyan(` ${e} login`)),console.error(),console.error(Et.gray(`Or set ${t} environment variable.`)),process.exit(c.AUTH_ERROR)}}function Us(e){return e.length<=14?"****":`${e.slice(0,10)}...${e.slice(-4)}`}function Jr(){let e=ge();if(e)return Us(e)}function Cn(e){return["cc_slides_","mcp_","cc_sk_","sk_"].some(n=>e.startsWith(n))}import{mkdirSync as js,readFileSync as Ms,writeFileSync as Fs}from"fs";import{homedir as Vs}from"os";import{join as zr}from"path";import Gs from"ajv/dist/2020.js";var In=new Map;function Xr(){return zr(Vs(),".conceptcraft","schemas")}function Hr(e){return zr(Xr(),`${e}.json`)}function Bs(e){try{let t=JSON.parse(Ms(Hr(e),"utf8"));return typeof t?.catalogVersion=="number"&&t.schema?t:null}catch{return null}}function Ws(e,t){try{js(Xr(),{recursive:!0}),Fs(Hr(e),JSON.stringify(t))}catch{}}async function Ks(e){let t=In.get(e);if(t!==void 0)return t;try{let n=await Yr(e),r={catalogVersion:n.catalogVersion,schema:n.schema};return Ws(e,r),In.set(e,r),r}catch{let n=Bs(e);return In.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 At(e,t){let n=await Ks(e);if(!n)return;let r;try{r=new Gs({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 ie(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 ae(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 Qr(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 Kr();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},to="Idempotency-Key";function Ys(e){return e&&e!=="GET"?{[to]:st()}:{}}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,...Ys(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 s;try{s=await fetch(o,a)}catch(f){throw new P(`Network error: ${f instanceof Error?f.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!s.ok){let f=await s.text().catch(()=>""),p=Zs(f,s.status),v=1;switch(s.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=`[${p.code}] ${p.message}`;throw new P(x,s.status,v,p.code,p.retryable)}return t.stream?s:s.headers.get("content-type")?.includes("application/json")?s.json():s.text()}function Qs(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 Zs(e,t){let n=Qs(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 Yr(e){return K(`/api/cli/tools/${encodeURIComponent(e)}/schema`)}async function no(){return K("/api/cli/capabilities",{allowUnauthenticated:!0})}async function E(e,t,n){let r=n?`?teamId=${encodeURIComponent(n)}`:"";return K(`/api/cli/tool-runs/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`)}async function y(e,t,n){return K(`/api/cli/tools/${encodeURIComponent(e)}`,{body:t,headers:n?{[to]:n}:void 0,method:"POST"})}async function ro(e,t,n,r=120){let o=0;for(let i=0;i<r;i++){let a;try{a=await E(e,t,n),o=0}catch(s){if(s instanceof P&&s.retryable&&o<2){o+=1,await new Promise(l=>setTimeout(l,2e3));continue}throw s instanceof P?new P(`${s.message} Request ID: ${t}.`,s.statusCode,s.exitCode,s.errorCode,s.retryable):new P(`${s instanceof Error?s.message:"Unknown error"} Request ID: ${t}.`,0,5,"poll_failed",!0)}if(a.done){if(a.error)throw new P(`${ae(a.error,{defaultCode:"operation_failed"})} Request ID: ${t}.`,500,1,a.error.code??"operation_failed",a.error.retryable);return a}await new Promise(s=>setTimeout(s,(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 Ot(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 ed(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 td(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=Hs(e),i=eo(e),a=td(e),s=Xs(e),l=zs("sha256").update(s).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:a,size:o.size},...t.idempotencyKey?{uploadIdentity:{contentSha256:l,idempotencyKey:t.idempotencyKey}}:{}})});if(!f.ok){let T=await f.text();throw new P(T||"Failed to get upload URL",f.status,1)}let p=await f.json(),v=new FormData;for(let[T,k]of Object.entries(p.fields||{}))v.append(T,k);let x=new Blob([s],{type:a});v.append("file",x,i);let w=await fetch(p.url,{method:"POST",body:v});if(!w.ok)throw new P("Failed to upload file to storage",w.status,1);return{id:st(),name:i,url:p.fileUrl,size:o.size,type:a,selected:!0}}async function oo(e,t){let n=[];for(let r=0;r<e.length;r++){let o=e[r],i=eo(o);t?.(r,e.length,i);let a=await me(o);n.push(a)}return t?.(e.length,e.length,""),n}async function io(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),y("createSlides",{...t,approvalReceipt:"cli:create"})}async function ao(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 je(e,t){let n=t?.includeSlides?"?includeSlides=true":"";return K(`/api/cli/presentation/${encodeURIComponent(e)}${n}`)}async function so(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/speaker-notes`,{body:t,method:"POST"})}async function co(e,t){return K(`/api/cli/presentation-video/${encodeURIComponent(e)}/narration`,{body:t,method:"POST"})}async function Pt(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 lo(e){await K(`/api/cli/presentation/${encodeURIComponent(e)}`,{method:"DELETE"})}async function mo(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/export`,{body:{format:t},method:"POST"})}async function uo(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 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=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 s=await fetch(`${r}/api/presentations/import`,{method:"POST",headers:o,body:i}),l=await s.json();if(!s.ok)throw new P(l.errors?.[0]?.message??"Import failed",s.status,1);return l}async function Rn(){return K("/api/cli/branding")}async function go(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 fo(e){return K(`/api/branding/${e}`)}async function ho(e,t,n){return y("extractBranding",{approvalReceipt:n,teamId:t,url:e})}async function ye(){return K("/api/cli/whoami")}async function yo(){return K("/api/cli/features")}async function bo(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 nd(e){let t=new URLSearchParams;e&&t.set("teamId",e);let n=t.toString();return K(`/api/cli/limits${n?`?${n}`:""}`)}async function wo(e,t,n){let r=await nd(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 rd(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 vo(e){let t={...e,text:rd(e.text)};await At("generateSpeech",t);let n=await y("generateSpeech",{approvalReceipt:"cli:tts-generate",...t}),r=await ro("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(v){throw new P(`${v instanceof Error?v.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??{},s=e.options??{},l=le(a.format)??ed(o)??"mp3",f=Buffer.from(await i.arrayBuffer()),p=xo(a.durationSec,a.duration,a.duration_s)??Wr(f,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:f,audioUrl:o,duration:p,cost:Te(a.costUsd)??Te(a.cost)??0,provider:le(a.provider)??s.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)??s.speed,language:le(a.lang)??le(a.language)??s.language,langApplied:Zr(a.langApplied)??Zr(a.lang_applied),timestamps:od(a.timestamps),wordTimings:id(a.timestamps??a.timings)}}function xo(...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 od(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 id(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 ko(e){let t=e?`/api/cli/tts?provider=${e}`:"/api/cli/tts";return K(t)}async function Co(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;return delete t.idempotency_key,await At("generateMusic",t),{requestId:(await y("generateMusic",{...t,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function Sn(e){let t=await E("generateMusic",e);return{requestId:e,status:Ot(t),audioUrl:t.entity?.url,duration:xo(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 Io(e){return{requestId:(await y("mixAudio",{...e,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function $n(e){let t=await E("mixAudio",e);return{requestId:e,status:Ot(t),outputUrl:t.entity?.url,error:t.error?.message}}async function Ro(e){return K("/api/cli/images/search",{method:"POST",body:e})}async function So(e){return K("/api/cli/videos/search",{method:"POST",body:e})}async function ee(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(s=>setTimeout(s,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 $o(e,t,n){return y("getYoutubeTranscript",{...n?{language:n}:{},teamId:t,url:e})}async function To(e,t){let n=await y("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 Eo(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;delete t.idempotency_key,await At("generateSfx",t);let r=await y("generateSfx",{...t,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function Tn(e){let t=await E("generateSfx",e);return{id:t.entity?.id??e,requestId:e,status:Ot(t),audioUrl:t.entity?.url,error:t.error?.message}}async function Ao(e){return y("listPresenterOptions",{...e?{voiceLanguage:e}:{}})}async function Oo(e){return{requestId:(await y("generateAvatarVideo",{...e,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function En(e){let t=await E("generateAvatarVideo",e);return{durationSec:typeof t.output?.durationSec=="number"?t.output.durationSec:null,error:t.error?.message,requestId:e,status:Ot(t),videoUrl:t.entity?.url}}async function Po(e){return y("lipsyncVideo",{...e,approvalReceipt:"cli:video-lipsync"})}async function _o(){return(await y("listTranslationLanguages",{})).languages}async function Lo(e){return y("translateVideo",{...e,approvalReceipt:"cli:video-translate"})}async function Do(e,t,n){return y("createVideo",{...e,approvalReceipt:t},n)}async function No(e){let{idempotencyKey:t,...n}=e;return y("analyzeVideoReference",n,t)}async function qo(e,t){return ro("analyzeVideoReference",e,t)}async function Uo(e){return y("listCastPresets",e)}async function jo(e){return y("createCastPreset",e,st())}async function Mo(e){return y("updateCastPreset",e,st())}async function Fo(e){return y("deleteCastPreset",{presetId:e},st())}var Vo=[{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 _t(e){return{capabilities:Vo,catalogVersion:1,reason:e,source:"snapshot"}}async function dt(e=no){try{let{capabilities:t,catalogVersion:n}=await e();return!Array.isArray(t)||t.length===0?_t("the live catalog returned no capabilities"):{capabilities:t,catalogVersion:n,source:"live"}}catch(t){let n=t instanceof Error?t.message:String(t);return _t(n)}}import{InvalidArgumentError as sd}from"commander";function b(e,t){return n=>{if(t.includes(n))return n;throw new sd(`Expected one of: ${t.join(", ")}. Run the command with --help to see what ${e} accepts.`)}}var Go=["presentations","media","branding","knowledge","research","artifacts","agents"],cd=80,ld=30;function md(e){return e.billing!==void 0&&e.billing!=="free"&&e.billing!=="quota"}function ud(e){return e.lifecycle?.mode==="background"}function pd(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 Bo(e){let t=Go.indexOf(e);return t===-1?Go.length:t}function gd(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 fd(e){let t=new Map;for(let i of e){let a=i.category??"other",s=t.get(a);s?s.push(i):t.set(a,[i])}let n=[...t.entries()].sort(([i],[a])=>{let s=Bo(i)-Bo(a);return s!==0?s:i.localeCompare(a)}),r=Math.min(ld,Math.max(...e.map(i=>i.name.length))),o=[];for(let[i,a]of n){a.sort((s,l)=>s.name.localeCompare(l.name)),o.length>0&&o.push(""),o.push(ct.bold(`${i} (${a.length})`));for(let s of a){let l=`${md(s)?"$":" "}${ud(s)?"*":" "}`,f=s.name.padEnd(r),p=2+r+1+l.length+1,v=Math.max(24,cd-p),x=pd(s.description??"",v);o.push(` ${ct.cyan(f)} ${ct.yellow(l)} ${x[0]??""}`.trimEnd());for(let w of x.slice(1))o.push(`${" ".repeat(p)}${w}`)}}return o}function hd(e){return e.map(t=>`${t.name} ${t.state} ${t.milestone}`)}function yd(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 hd(e);let r=m.commands[0],o=fd(e);return o.push(""),o.push(ct.dim(`${e.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(ct.dim(`Filter with: ${r} capabilities --search <query>`)),o}var Wo=new dd("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 dt(),n=gd(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"&&F(`Showing the capability list baked into this CLI build (${t.reason}); the deployed catalog may have moved on.`);for(let o of yd(n,{filtered:r}))console.log(o)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdirSync as xd,writeFileSync as kd}from"fs";import{dirname as Xo,join as Cd}from"path";import{Command as ve}from"commander";import lt from"chalk";import{input as Id,password as Rd,confirm as Ho,select as Sd}from"@inquirer/prompts";import Dt from"ora";import bd from"conf";var Lt=new bd({projectName:"conceptcraft",configName:"feature-cache"}),wd=3600*1e3,vd=1440*60*1e3;function Ko(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 Jo(){if(!qe())return null;let e=Lt.get("featureFlags");if(!e)return null;let t=Ko(ge());if(e.apiKeyHash&&e.apiKeyHash!==t)return Ae(),null;let n=Date.now()-e.fetchedAt;return n>vd?null:(n>wd&&An(),e.flags)}function An(){Ee().catch(()=>{})}async function Ee(){let e=await yo(),t=ge();return Lt.set("featureFlags",{flags:e,fetchedAt:Date.now(),apiKeyHash:t?Ko(t):void 0}),e}function Ae(){Lt.delete("featureFlags")}function zo(){return Lt.path}var Yo=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(lt.bold(`${m.displayName} CLI Configuration`)),console.log(lt.gray("\u2500".repeat(35))),console.log();try{let e=await Rd({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":Cn(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(bn(e.trim()),await Ho({message:`Use a custom API URL? (default: ${m.apiUrl.replace("https://","")})`,default:!1})){let r=await Id({message:"Enter API URL:",default:B(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});wn(r)}console.log();let n=Dt("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)F("No teams found for this user.");else if(r.teams.length===1){let o=r.teams[0];Ne(o.id),g(`Team: ${o.name} (${o.planName})`)}else{console.log(),g(`You have access to ${r.teams.length} teams.`);let o=await Sd({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});Ne(o);let i=r.teams.find(a=>a.id===o);I(`Selected team: ${i?.name}`)}try{await Ee()}catch{}}catch(r){n.fail("Failed to verify API key"),F(`Could not verify API key: ${r instanceof Error?r.message:String(r)}`),F(`You may need to set the team ID manually: ${m.commands[0]} config set team-id <id>`)}console.log(),I("Configuration saved!"),g(`Config file: ${at()}`),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=_r();if(oe("Current Configuration"),console.log(),$("API Key",Jr()??lt.red("Not set")),$("API URL",t.apiUrl),$("Default Team ID",t.defaultTeamId??lt.gray("Not set")),console.log(),$("Config file",at()),e.verify&&t.apiKey){console.log();let n=Dt("Verifying...").start();try{let r=await ye();n.succeed("Verified"),console.log(),$("User",r.user.email),r.currentTeam&&$("Current Team",`${r.currentTeam.name} (${r.currentTeam.planName})`),r.teams.length>1&&$("Total Teams",String(r.teams.length))}catch(r){n.fail("Verification failed"),F(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":Cn(t)||(d("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),bn(t),Ae(),I("API key updated"),Ee().catch(()=>{});break;case"api-url":try{new URL(t),wn(t),I(`API URL set to: ${t}`)}catch{d("Invalid URL format"),process.exit(6)}break;case"team-id":Ne(t),I(`Default team ID set to: ${t}`);break;default:d(`Unknown config key: ${e}`),console.log(lt.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new ve("clear").description("Clear all configuration").action(async()=>{try{await Ho({message:"Are you sure you want to clear all configuration?",default:!1})?(St(),Ae(),I("Configuration cleared")):g("Cancelled")}catch{g("Cancelled")}})).addCommand(new ve("refresh").description("Refresh cached feature flags").action(async()=>{let e=Dt("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"),d(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(zo()):console.log(at())})).addCommand(new ve("pull").description("Pull your account settings (memory, brand, prefs) into a local config.toml").action(async()=>{let e=Dt("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=Cd(Xo(at()),"settings.toml");xd(Xo(o),{recursive:!0}),kd(o,r,"utf8"),e.succeed("Settings pulled"),g(`Written to ${o}`)}catch(t){e.fail("Failed to pull settings"),d(t instanceof Error?t.message:String(t)),process.exit(1)}}));import{Command as $d}from"commander";import{confirm as Td}from"@inquirer/prompts";var Qo=new $d("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 Td({message:`Are you sure you want to delete presentation "${e}"?`,default:!1})){t.quiet||F("Deletion cancelled");return}}catch{t.quiet||F("Deletion cancelled");return}try{await lo(e),t.quiet||I(`Presentation "${e}" deleted`)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Me}from"commander";import ei from"chalk";import Ed from"ora";import{createParser as dh}from"eventsource-parser";import lh from"chalk";import uh 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 s=r.decode(a.value,{stream:!0});o+=s,t.quiet||process.stdout.write(s)}}return t.quiet||console.log(),o}function Ad(){return new Me("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)&&(d("Word count must be between 50 and 2000"),process.exit(6));let r=["professional","casual","educational"];r.includes(t.tone)||(d(`Invalid tone. Valid options: ${r.join(", ")}`),process.exit(6));let o=Ed("Fetching presentation...").start();try{let i=await je(e);o.text="Generating blog post...";let a=await bo(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}),s=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:s},null,2)):t.format==="markdown"?console.log(s):(console.log(),console.log(ei.bold(`Blog: ${i.title}`)),console.log(ei.gray("\u2500".repeat(40))),console.log(),console.log(s),console.log())}catch(i){o.fail("Generation failed"),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})}function Od(){return new Me("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 Pd(){return new Me("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 _d(){return new Me("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 Ld(){return new Me("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 ti(){let e=new Me("derive").description("Generate derivative content from a presentation"),t=Jo();return t&&(t.deckToBlog&&e.addCommand(Ad()),t.deckToTweets&&e.addCommand(Od()),t.linkedInCarousel&&e.addCommand(Pd()),t.redTeamQuestions&&e.addCommand(_d()),t.presenterCheatSheet&&e.addCommand(Ld())),e}import{Command as Dd}from"commander";import On from"chalk";var ni=new Dd("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(On.gray("The CLI will support idea generation in a future release.")),console.log(),console.log("For now, try these approaches:"),console.log(On.gray("` 1. Visit the ${brand.displayName} dashboard and use the idea generator`")),console.log(On.gray(" 2. Create a presentation with a broad topic and refine it")),console.log()});import{Command as Nd}from"commander";import{readFile as qd}from"fs/promises";import{resolve as Ud,basename as jd}from"path";import Md from"ora";var ri=new Nd("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");ri._hidden=!0;var oi=ri.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"&&(d("This command is only available to administrators"),process.exit(2))}catch{d("Failed to verify permissions"),process.exit(2)}let n=Ud(e),r=jd(n);r.endsWith(".zip")||(d("File must be a ZIP archive"),process.exit(6));let o=Md("Reading file...").start();try{let i=await qd(n);t.dryRun?o.text="Validating...":o.text="Importing presentation...";let a=await po(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(),$("Slides",String(a.statistics.slidesImported)),$("Images",String(a.statistics.imagesUploaded)));else if(o.succeed("Import complete!"),console.log(),$("Presentation ID",a.presentationId??"N/A"),$("Document ID",a.documentId??"N/A"),a.statistics&&($("Slides imported",String(a.statistics.slidesImported)),$("Images uploaded",String(a.statistics.imagesUploaded)),$("Time",`${a.statistics.totalTimeMs}ms`)),a.presentationId){let s=B();$("View URL",`${s}/p/${a.presentationId}`)}if(a.warnings&&a.warnings.length>0){console.log();for(let s of a.warnings)F(s)}console.log()}else{if(o.fail("Import failed"),console.log(),a.errors)for(let s of a.errors)d(`${s.type}: ${s.message}`);process.exit(1)}}catch(i){o.fail("Import failed"),i.code==="ENOENT"&&(d(`File not found: ${n}`),process.exit(3)),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}});import{Command as Fd}from"commander";var ii=new Fd("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)&&(d("Invalid limit value"),process.exit(6));let n=e.teamId??Rt();n||(d("`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 ao(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(Vr(r));break;default:console.log(Fr(r,{showLinks:e.detail,language:e.language}));break}}catch(r){d(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});import{createHash as Vd,randomBytes as di}from"crypto";import ci from"http";import ai from"chalk";import{Command as Gd}from"commander";import Bd from"open";import si from"ora";var Wd=`${m.displayName} CLI`,Kd=8765,Jd=8775,zd=["presentations:read","presentations:write","media:read","media:write"];function Xd(){return di(32).toString("base64url")}function Hd(e){return Vd("sha256").update(e).digest("base64url")}function Yd(){return di(16).toString("hex")}async function Qd(e,t){for(let n=e;n<=t;n++)try{return await new Promise((r,o)=>{let i=ci.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 Zd(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 ec(e){let t=e.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(t?.length?t:zd).join(" ")}async function tc(e,t,n){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:Wd,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 nc(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 s=await a.text();throw new Error(`Token exchange failed: ${s}`)}return a.json()}function rc(e,t){return new Promise((n,r)=>{let o,i=!1,a=()=>{i||(i=!0,clearTimeout(o),process.off("SIGINT",s),process.off("SIGTERM",s),l.close())},s=()=>{a(),r(new Error("Login cancelled"))},l=ci.createServer((f,p)=>{let v=new URL(f.url||"",`http://localhost:${e}`);if(v.pathname!=="/callback"){p.writeHead(404),p.end("Not found");return}let x=v.searchParams.get("code"),w=v.searchParams.get("state"),T=v.searchParams.get("error"),k=v.searchParams.get("error_description");if(p.writeHead(200,{"Content-Type":"text/html"}),T){p.end(`
13
6
  <!DOCTYPE html>
14
7
  <html>
15
8
  <head><title>Login Failed</title></head>
16
9
  <body style="font-family: system-ui; text-align: center; padding: 50px;">
17
10
  <h1 style="color: #dc2626;">Login Failed</h1>
18
- <p>${x||$}</p>
11
+ <p>${k||T}</p>
19
12
  <p>You can close this window.</p>
20
13
  </body>
21
14
  </html>
22
- `),a(),r(new Error(x||$));return}if(!v||!b){m.end(`
15
+ `),a(),r(new Error(k||T));return}if(!x||!w){p.end(`
23
16
  <!DOCTYPE html>
24
17
  <html>
25
18
  <head><title>Login Failed</title></head>
@@ -29,7 +22,7 @@ ${Tt.bold("See also:")}
29
22
  <p>You can close this window.</p>
30
23
  </body>
31
24
  </html>
32
- `),a(),r(new Error("Missing authorization code or state"));return}if(b!==t){m.end(`
25
+ `),a(),r(new Error("Missing authorization code or state"));return}if(w!==t){p.end(`
33
26
  <!DOCTYPE html>
34
27
  <html>
35
28
  <head><title>Login Failed</title></head>
@@ -39,7 +32,7 @@ ${Tt.bold("See also:")}
39
32
  <p>You can close this window.</p>
40
33
  </body>
41
34
  </html>
42
- `),a(),r(new Error("State mismatch"));return}m.end(`
35
+ `),a(),r(new Error("State mismatch"));return}p.end(`
43
36
  <!DOCTYPE html>
44
37
  <html>
45
38
  <head><title>Login Successful</title></head>
@@ -48,120 +41,167 @@ ${Tt.bold("See also:")}
48
41
  <p>You can close this window and return to the terminal.</p>
49
42
  </body>
50
43
  </html>
51
- `),a(),n({code:v,state:b})});l.listen(e),process.once("SIGINT",s),process.once("SIGTERM",s),o=setTimeout(()=>{a(),r(new Error("Login timed out - no callback received within 5 minutes"))},300*1e3)})}async function Bd(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 Wd(e){let t=V(),n=zo("Discovering OAuth server...").start();try{let r=await Md(t),o=Fd(r);n.succeed(`Connecting to ${t}`);let i=await qd(Pd,_d),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 s=await Vd(r.registration_endpoint,a,o),l=s.client_id;Tr(l,s.client_secret);let g=Dd(),m=Nd(g),w=Ud(),v=new URLSearchParams({client_id:l,redirect_uri:a,response_type:"code",scope:o,state:w,code_challenge:m,code_challenge_method:"S256"}),b=`${r.authorization_endpoint}?${v}`;console.log(`Authorization URL: ${b}`),e.browser?(f("Opening browser..."),await Ad(b)):(console.log(Jo.bold("Open this URL in your browser:")),console.log(Jo.cyan(b)));let $=Gd(i,w),{code:x}=await $;n=zo("Completing login...").start();let k=await jd(r.token_endpoint,x,g,a,l);vt(k.access_token,k.refresh_token,k.expires_in);let R=await Bd(t,k.access_token);n.succeed("Logged in!"),console.log(),S("Logged in as",R.user.email),R.currentTeam&&(Oe(R.currentTeam.id),S("Team",`${R.currentTeam.name} (${R.currentTeam.planName})`));try{await Ie()}catch{}console.log(),C("You're all set!"),console.log()}catch(r){throw n.fail("Login failed"),d(r instanceof Error?r.message:String(r)),r}}var Yo=new Ed("login").description(`Authenticate with ${u.displayName} (opens browser)`).option("--no-browser","Print URL instead of opening browser").action(async e=>{console.log(),ke()&&(M("You are already logged in."),f(`Run '${u.commands[0]} logout' to log out first, or continue to re-authenticate.`),console.log());try{await Wd(e),process.exit(0)}catch{process.exit(1)}});import{Command as Kd}from"commander";import{confirm as Jd}from"@inquirer/prompts";var Qo=new Kd("logout").description("Log out and clear authentication").option("--all","Clear all config including API key").action(async e=>{console.log();let t=ke(),n=Pe();if(!t&&!n){M("You are not logged in."),console.log();return}if(e.all)try{await Jd({message:"Clear all configuration including API key?",default:!1})?(wt(),Re(),C("All configuration cleared.")):f("Cancelled.")}catch{f("Cancelled.")}else xt(),Re(),C("Logged out successfully."),n&&f("Note: Your API key is still configured. Use --all to clear everything.");console.log()});import{homedir as Pc}from"os";import{join as _c}from"path";import ne from"chalk";import{Command as Lc}from"commander";import{spawn as zd}from"child_process";import{existsSync as Xd,readdirSync as Hd}from"fs";import{homedir as ti}from"os";import{delimiter as Zo}from"path";import{query as Yd}from"@anthropic-ai/claude-agent-sdk";function Z(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 Et(e){let t=typeof e=="string"?e:String(e??"");return t.length>12e3?`${t.slice(0,12e3)}\u2026`:t}function ee(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function _(e){return typeof e=="string"?e:""}function ei(e,t){let n=e.replace(/[/.]/g,"-");return`${ti()}/.claude/projects/${n}/${t}.jsonl`}function Qd(e){try{return Hd(`${e}/.nvm/versions/node`).map(t=>`${e}/.nvm/versions/node/${t}/bin`).sort().reverse()}catch{return[]}}function At(){let e=ti(),t=[`${e}/.local/bin`,`${e}/.claude/local`,`${e}/.bun/bin`,`${e}/bin`,"/opt/homebrew/bin","/usr/local/bin",...Qd(e)],r=(process.env.PATH??"").split(Zo);for(let o of t)r.includes(o)||r.push(o);return r.join(Zo)}async function Ot(e){let t=e??"claude";return new Promise(n=>{let r=zd(t,["--version"],{env:{...process.env,PATH:At()},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(`
52
- `)[0]??"";n(a?{bin:t,version:a}:null)})})}var Zd=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>
44
+ `),a(),n({code:x,state:w})});l.listen(e),process.once("SIGINT",s),process.once("SIGTERM",s),o=setTimeout(()=>{a(),r(new Error("Login timed out - no callback received within 5 minutes"))},300*1e3)})}async function oc(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 ic(e){let t=B(),n=si("Discovering OAuth server...").start();try{let r=await Zd(t),o=ec(r);n.succeed(`Connecting to ${t}`);let i=await Qd(Kd,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 s=await tc(r.registration_endpoint,a,o),l=s.client_id;jr(l,s.client_secret);let f=Xd(),p=Hd(f),v=Yd(),x=new URLSearchParams({client_id:l,redirect_uri:a,response_type:"code",scope:o,state:v,code_challenge:p,code_challenge_method:"S256"}),w=`${r.authorization_endpoint}?${x}`;console.log(`Authorization URL: ${w}`),e.browser?(g("Opening browser..."),await Bd(w)):(console.log(ai.bold("Open this URL in your browser:")),console.log(ai.cyan(w)));let T=rc(i,v),{code:k}=await T;n=si("Completing login...").start();let C=await nc(r.token_endpoint,k,f,a,l);$t(C.access_token,C.refresh_token,C.expires_in);let S=await oc(t,C.access_token);n.succeed("Logged in!"),console.log(),$("Logged in as",S.user.email),S.currentTeam&&(Ne(S.currentTeam.id),$("Team",`${S.currentTeam.name} (${S.currentTeam.planName})`));try{await Ee()}catch{}console.log(),I("You're all set!"),console.log()}catch(r){throw n.fail("Login failed"),d(r instanceof Error?r.message:String(r)),r}}var li=new Gd("login").description(`Authenticate with ${m.displayName} (opens browser)`).option("--no-browser","Print URL instead of opening browser").action(async e=>{console.log(),$e()&&(F("You are already logged in."),g(`Run '${m.commands[0]} logout' to log out first, or continue to re-authenticate.`),console.log());try{await ic(e),process.exit(0)}catch{process.exit(1)}});import{Command as ac}from"commander";import{confirm as sc}from"@inquirer/prompts";var mi=new ac("logout").description("Log out and clear authentication").option("--all","Clear all config including API key").action(async e=>{console.log();let t=$e(),n=qe();if(!t&&!n){F("You are not logged in."),console.log();return}if(e.all)try{await sc({message:"Clear all configuration including API key?",default:!1})?(St(),Ae(),I("All configuration cleared.")):g("Cancelled.")}catch{g("Cancelled.")}else Tt(),Ae(),I("Logged out successfully."),n&&g("Note: Your API key is still configured. Use --all to clear everything.");console.log()});import{homedir as Kc}from"os";import{join as Jc}from"path";import se from"chalk";import{Command as zc}from"commander";import{spawn as dc}from"child_process";import{existsSync as cc,readdirSync as lc}from"fs";import{homedir as gi}from"os";import{delimiter as ui}from"path";import{query as mc}from"@anthropic-ai/claude-agent-sdk";function te(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 Nt(e){let t=typeof e=="string"?e:String(e??"");return t.length>12e3?`${t.slice(0,12e3)}\u2026`:t}function ne(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function D(e){return typeof e=="string"?e:""}function pi(e,t){let n=e.replace(/[/.]/g,"-");return`${gi()}/.claude/projects/${n}/${t}.jsonl`}function uc(e){try{return lc(`${e}/.nvm/versions/node`).map(t=>`${e}/.nvm/versions/node/${t}/bin`).sort().reverse()}catch{return[]}}function qt(){let e=gi(),t=[`${e}/.local/bin`,`${e}/.claude/local`,`${e}/.bun/bin`,`${e}/bin`,"/opt/homebrew/bin","/usr/local/bin",...uc(e)],r=(process.env.PATH??"").split(ui);for(let o of t)r.includes(o)||r.push(o);return r.join(ui)}async function Ut(e){let t=e??"claude";return new Promise(n=>{let r=dc(t,["--version"],{env:{...process.env,PATH:qt()},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 pc=new Set(["","default","best"]);function Pn(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>
53
46
  ${r.map(i=>`${i.role==="assistant"?"Assistant":"User"}: ${i.text}`).join(`
54
47
 
55
48
  `)}
56
49
  </conversation-history>
57
50
 
58
- ${n.text}`}function Tn(e,t){return t?e.messages.filter(r=>r.text.trim()).at(-1)?.text??"":$n(e.messages)}function ec({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:At()},includePartialMessages:!0,maxTurns:16,permissionMode:"dontAsk"};return Zd.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 ni(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,s=null,l=null,g=0,m=new Set;try{let b=Yd({prompt:t,options:ec({abortController:n,input:e.input,resumeSessionId:e.resumeSessionId,workspace:e.workspace})});for await(let $ of b){let x=$;if(x.type==="system"&&x.subtype==="init"){typeof x.session_id=="string"&&(i=x.session_id,e.onEvent({eventType:"chat.session",payload:{sessionId:i,sessionPath:ei(e.workspace,i)}})),typeof x.model=="string"&&(o=x.model,e.onEvent({eventType:"chat.model",payload:{modelId:x.model}}));continue}if(x.type==="stream_event"){let k=x.event;if(k?.type!=="content_block_delta")continue;let R=k.delta;if(!R)continue;R.type==="text_delta"&&typeof R.text=="string"?(g+=R.text.length,e.onEvent({eventType:"chat.text.delta",payload:{text:R.text}})):R.type==="thinking_delta"&&typeof R.thinking=="string"&&e.onEvent({eventType:"chat.reasoning.delta",payload:{text:R.thinking}});continue}if(x.type==="assistant"){let k=ee(x.message),R=Array.isArray(k.content)?k.content:[];for(let D of R){let E=ee(D);if(E.type!=="tool_use")continue;let U=_(E.id),I=_(E.name);!U||!I||m.has(U)||(m.add(U),e.onEvent({eventType:"chat.tool.started",payload:{input:Z(E.input),toolCallId:U,toolName:I}}))}continue}if(x.type==="user"){let k=ee(x.message),R=Array.isArray(k.content)?k.content:[];for(let D of R){let E=ee(D);if(E.type!=="tool_result")continue;let U=_(E.tool_use_id);U&&e.onEvent({eventType:"chat.tool.completed",payload:{...E.is_error===!0?{errorText:typeof E.content=="string"?Et(E.content):"Claude tool call failed."}:{},output:Z(E.content),toolCallId:U}})}continue}x.type==="result"&&(typeof x.result=="string"&&(s=x.result),x.usage&&typeof x.usage=="object"&&(a=x.usage),typeof x.session_id=="string"&&(i=x.session_id),(x.is_error===!0||x.subtype!=="success")&&(l=typeof x.result=="string"&&x.result||`Claude turn failed (${String(x.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=s??"";g===0&&w&&e.onEvent({eventType:"chat.text.delta",payload:{text:w}});let v=i?ei(e.workspace,i):null;return{modelId:o,sessionId:i,sessionPath:v&&Xd(v)?v:null,text:w,usage:a}}import{spawn as tc}from"child_process";import{closeSync as nc,fstatSync as rc,openSync as oc,readdirSync as ic,readSync as ac}from"fs";import{homedir as sc}from"os";import{join as ri}from"path";import{Codex as dc}from"@openai/codex-sdk";var cc=["/Applications/Codex.app/Contents/Resources/codex"];async function Pt(e){let t=e?[e]:["codex",...cc];for(let n of t){let r=await lc(n);if(r)return{bin:n,version:r}}return null}function lc(e){return new Promise(t=>{let n=tc(e,["--version"],{env:{...process.env,PATH:At()},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(`
59
- `)[0]??"";t(i||null)})})}var uc=24,mc=4*1024*1024,ai=new Set(["custom_tool_call","custom_tool_call_output","dynamic_tool_call","function_call"]);function pc(e){let t;try{t=gc(e).split(`
60
- `)}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 s=ee(a.payload);if(a.type==="response_item"&&s.type==="custom_tool_call"){let l=_(s.call_id),g=_(s.input);l&&s.name==="exec"&&/\btools\.web__run\s*\(/.test(g)&&(n.add(l),o=l);continue}if(a.type==="event_msg"&&s.type==="web_search_end"){let l=_(s.call_id);if(!l||!o)continue;let g=_(s.query),m=ee(s.action),v={action:{...m,...g&&!_(m.query)?{query:g}:{}},query:g,sources:oi(s.results),toolCallId:l},b=r.get(o)??[];b.push(v),r.set(o,b);continue}if(a.type==="response_item"&&s.type==="custom_tool_call_output"){let l=_(s.call_id);if(!l||!n.has(l))continue;let g=oi(s.output);for(let m of r.get(l)??[])m.sources.length===0&&(m.sources=g);o===l&&(o=null)}}return Array.from(r.values()).flat()}function gc(e){let t=oc(e,"r");try{let n=rc(t).size,r=Math.max(0,n-mc),o=Buffer.alloc(n-r);ac(t,o,0,o.length,r);let i=o.toString("utf8");if(r===0)return i;let a=i.indexOf(`
61
- `);return a===-1?"":i.slice(a+1)}finally{nc(t)}}function oi(e){let n=On(e).match(/https?:\/\/[^\s<>"'()[\]{}\\]+/g)??[],r=new Set,o=[];for(let i of n){let a=i.replace(/[.,;:!?]+$/,"");try{let s=new URL(a);if(s.protocol!=="http:"&&s.protocol!=="https:"||r.has(s.href))continue;if(r.add(s.href),o.push({type:"url",url:s.href}),o.length>=uc)break}catch{}}return o}function On(e){return typeof e=="string"?e:Array.isArray(e)?e.map(On).join(`
62
- `):e&&typeof e=="object"?Object.values(e).map(On).join(`
63
- `):""}function En(e,t){let n=ee(e),r=_(n.type),o=_(n.id),i=_(n.call_id)||_(n.tool_call_id),a=ai.has(r)?i||o:o||i;if(!a)return null;if(r==="command_execution"){let s=_(n.command),l=_(n.status),g={exitCode:typeof n.exit_code=="number"?n.exit_code:null,output:Z(n.aggregated_output)};return{...t&&l==="failed"?{errorText:Et(n.aggregated_output)||"Command failed."}:{},input:{command:s},...t?{output:g}:{},toolCallId:a,toolName:"Bash"}}if(r==="mcp_tool_call"){let s=ee(n.error);return{...t&&_(s.message)?{errorText:_(s.message)}:{},input:Z(n.arguments),...t?{output:Z(n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:_(n.tool)||_(n.name)||"Codex tool"}}if(r==="web_search"){let s=_(n.query);return{input:{query:s},...t?{output:{query:s}}:{},toolCallId:a,toolName:"web_search"}}if(r==="file_change"){let s=_(n.status);return{...t&&s==="failed"?{errorText:"Codex could not apply the file changes."}:{},input:{changes:Z(n.changes)},...t?{output:{changes:Z(n.changes),status:s}}:{},toolCallId:a,toolName:"ApplyPatch"}}if(r==="custom_tool_call_output")return{input:{},...t?{output:Z(n.output)}:{},toolCallId:a,toolName:"Codex tool"};if(r==="custom_tool_call"||r==="dynamic_tool_call"||r==="function_call"){let s=_(n.name)||_(n.tool)||"Codex tool",l=n.input??n.arguments??{};return{input:s==="exec"&&typeof l=="string"?{command:l}:Z(l),...t?{output:Z(n.output??n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:s}}return null}function An(e,t=ri(sc(),".codex","sessions")){try{let r=ic(t,{recursive:!0}).find(o=>typeof o=="string"&&o.endsWith(`${e}.jsonl`));return r?ri(t,r):null}catch{return null}}function fc(e,t){return t?Tn(e,t):$n(e.messages)}function hc(e,t,n=u.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 yc=new Set(["minimal","low","medium","high","xhigh"]);function bc(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&&yc.has(e.effort)&&(n.modelReasoningEffort=e.effort),n}async function si(e){let t=fc(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new dc(hc(e.bin,e.input)),r=bc(e.input,e.workspace),o=e.resumeSessionId?n.resumeThread(e.resumeSessionId,r):n.startThread(r),i=e.resumeSessionId??null,a=null,s=null,l=[],g=new Set,m=new Set,w=null,v=x=>{w??=An(x,e.sessionsRoot),e.onEvent({eventType:"chat.session",payload:{sessionId:x,sessionPath:w}})},b=x=>{i&&(w??=An(i,e.sessionsRoot));let k=w?pc(w):[],R=_(ee(x.input).query),D=ii(R),E=k.find(U=>!g.has(U.toolCallId)&&ii(U.query)===D)??k.find(U=>!g.has(U.toolCallId));E&&g.add(E.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:{...x,output:E?{action:E.action,query:E.query,sources:E.sources}:{action:{query:R,type:"search"},sourceListUnavailable:!0,sources:[]}}})},{events:$}=await o.runStreamed(t);i&&v(i);for await(let x of $){if(e.signal?.aborted)throw await $.return?.(void 0),new Error("Chat turn cancelled.");let k=x;if(k.type==="thread.started"){typeof k.thread_id=="string"&&(i=k.thread_id,v(k.thread_id));continue}if(k.type==="item.started"){let R=En(k.item,!1);if(R){e.onEvent({eventType:"chat.tool.started",payload:R});let D=ee(k.item);if(ai.has(_(D.type))&&_(D.status)==="completed"){let E=En(D,!0);E&&(m.add(E.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:E}))}}continue}if(k.type==="item.completed"){let R=k.item;if(!R)continue;if(R.type==="agent_message"&&typeof R.text=="string")l.push(R.text),e.onEvent({eventType:"chat.text.delta",payload:{text:R.text}});else if(R.type==="reasoning"&&typeof R.text=="string")e.onEvent({eventType:"chat.reasoning.delta",payload:{text:R.text}});else{let D=En(R,!0);D&&(R.type==="web_search"?b(D):R.type==="custom_tool_call"&&m.has(D.toolCallId)||e.onEvent({eventType:"chat.tool.completed",payload:D}))}continue}if(k.type==="turn.completed"){k.usage&&typeof k.usage=="object"&&(a=k.usage);continue}if(k.type==="turn.failed"){let R=k.error;s=typeof R?.message=="string"&&R.message||"Codex turn failed.",e.onEvent({eventType:"chat.error",message:s,payload:{message:s}})}}if(s)throw new Error(s);return i=o.id??i,i&&(w??=An(i,e.sessionsRoot)),{modelId:e.input.modelId??null,sessionId:i,sessionPath:w,text:l.join(`
64
-
65
- `),usage:a}}function ii(e){return e.trim().replace(/\s+/g," ").toLocaleLowerCase()}import{randomUUID as Cc}from"crypto";import{mkdir as Ic}from"fs/promises";import{hostname as Lt,platform as Rc}from"os";import{join as Sc}from"path";var De=class extends Error{constructor(n,r,o=!1){super(n);this.statusCode=r;this.reRegister=o;this.name="RunnerApiError"}statusCode;reRegister};async function Ne(e,t={}){let n=await se();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(`${V()}${e}`,{body:t.body!==void 0?JSON.stringify(t.body):void 0,headers:n,method:t.method??"GET",signal:r.signal}),s=await a.text(),l={};try{l=s?JSON.parse(s):{}}catch{l={error:s.slice(0,300)}}if(!a.ok)throw new De(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 di(e){await Ne("/api/runner/register",{body:e,method:"POST",timeoutMs:15e3})}async function ci(e,t){return(await Ne(`/api/runner/work?runnerId=${encodeURIComponent(e)}`,{signal:t,timeoutMs:28e3})).job??null}async function li(e){await Ne("/api/runner/heartbeat",{body:{runnerId:e},method:"POST",timeoutMs:1e4})}async function ui(e,t){return{cancelRequested:(await Ne(`/api/runner/jobs/${encodeURIComponent(e)}/events`,{body:{events:t},method:"POST",timeoutMs:15e3})).cancelRequested===!0}}async function Pn(e,t,n){await Ne(`/api/runner/jobs/${encodeURIComponent(e)}/complete`,{body:{result:n,runnerId:t},method:"POST",timeoutMs:15e3})}async function _t(e,t,n,r=!0){await Ne(`/api/runner/jobs/${encodeURIComponent(e)}/fail`,{body:{message:n,retryable:r,runnerId:t},method:"POST",timeoutMs:15e3})}import{mkdirSync as wc,readFileSync as vc,writeFileSync as mi}from"fs";import{dirname as xc,join as kc}from"path";function _n(e){return kc(e,"sessions.json")}function Ln(e){try{let t=vc(_n(e),"utf8"),n=JSON.parse(t);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}return{}}function pi(e,t,n){return t?Ln(e)[t]?.[n]??null:null}function gi(e,t,n,r){if(!(!t||!r))try{let o=_n(e);wc(xc(o),{recursive:!0});let i=Ln(e);i[t]={...i[t],[n]:r},mi(o,`${JSON.stringify(i,null," ")}
66
- `,"utf8")}catch{}}function fi(e,t,n){if(t)try{let r=Ln(e);if(!r[t])return;delete r[t][n],mi(_n(e),`${JSON.stringify(r,null," ")}
67
- `,"utf8")}catch{}}var $c=300,Tc=3e4;async function hi(e){let[t,n]=await Promise.all([Ot(e.claudeBin),Pt(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=`${Lt().split(".")[0]}-${Cc().slice(0,8)}`,i=()=>di({capabilities:["chat_turn","proof"],claudeCodeVersion:t?.version??null,cliVersion:e.version,codexVersion:n?.version??null,hostname:Lt(),platform:Rc(),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 ci(o,e.signal)}catch(s){if(e.signal?.aborted)break;if(s instanceof De&&s.reRegister){e.log("Server asked for re-registration."),await i().catch(()=>{});continue}e.log(`Work poll failed (${s instanceof Error?s.message:"unknown"}); retrying\u2026`),await Oc(e.pollBackoffMs??5e3,e.signal);continue}if(!a){if(e.once)continue;continue}if(e.log(`Claimed ${a.jobType} job ${a.runId}.`),await Ec({claude:t,codex:n,job:a,options:e,runnerId:o}),e.once)break}}async function Ec({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 s=setInterval(()=>{li(o).catch(()=>{})},Tc),l=[],g=!1,m=async()=>{if(g||l.length===0)return;g=!0;let b=l.splice(0,100);try{let{cancelRequested:$}=await ui(n.runId,b);$&&i.abort()}catch($){$ instanceof De&&$.statusCode===409&&i.abort()}finally{g=!1}},w=setInterval(()=>{m()},$c),v=b=>{l.push(b)};try{if(n.jobType==="runner.proof"){let b=typeof n.input.message=="string"?n.input.message:"proof";v({eventType:"proof.echo",payload:{message:b}}),await Dn(m,l),await Pn(n.runId,o,{echo:b}),r.log(`Proof job ${n.runId} completed.`);return}if(n.jobType==="runner.chat_turn"){let b=n.input.runtime==="codex"?"codex":"claude-code",$=b==="codex"?t&&{detection:t,run:si}:e&&{detection:e,run:ni};if(!$){await _t(n.runId,o,b==="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 x=typeof n.input.chatId=="string"&&n.input.chatId?n.input.chatId:null,k=Sc(r.workspaceRoot,"chats",x??n.runId);await Ic(k,{recursive:!0});let R=Ac(n.input),D=I=>v({eventType:I.eventType,message:I.message??null,payload:I.eventType==="chat.session"?{host:Lt(),runtime:b,runtimeVersion:$.detection.version,...I.payload??{}}:I.payload??{}}),E=pi(r.workspaceRoot,x,b),U;try{U=await $.run({bin:$.detection.bin,input:R,onEvent:D,resumeSessionId:E,signal:i.signal,workspace:k})}catch(I){if(!E||i.signal.aborted)throw I;r.log(`Resume of ${b} session failed (${I instanceof Error?I.message:"unknown"}); retrying fresh.`),fi(r.workspaceRoot,x,b),U=await $.run({bin:$.detection.bin,input:R,onEvent:D,resumeSessionId:null,signal:i.signal,workspace:k})}gi(r.workspaceRoot,x,b,U.sessionId),v({eventType:"chat.session",payload:{host:Lt(),runtime:b,runtimeVersion:$.detection.version,sessionId:U.sessionId,sessionPath:U.sessionPath}}),await Dn(m,l),await Pn(n.runId,o,{modelId:U.modelId,runtime:b,runtimeVersion:$.detection.version,sessionId:U.sessionId,sessionPath:U.sessionPath,text:U.text,usage:U.usage??{}}),r.log(`Chat turn ${n.runId} (${b}) completed.`);return}await _t(n.runId,o,`This runner does not support ${n.jobType} jobs. Update the desktop app / CLI.`,!1)}catch(b){let $=b instanceof Error?b.message:"Local runner job crashed.";r.log(`Job ${n.runId} failed: ${$}`),await Dn(m,l).catch(()=>{}),await _t(n.runId,o,$).catch(()=>{})}finally{clearInterval(w),clearInterval(s),r.signal?.removeEventListener("abort",a)}}function Ac(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 Oc(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 Dc(){return _c(Pc(),`.${u.commands[0]}-runner`,"runs")}var Dt=new Lc("runner").description("Run agent work locally with your own Claude Code / Codex login (desktop lane)");Dt.command("status").description("Check local Claude Code / Codex detection and account auth").action(async()=>{let[e,t]=await Promise.all([Ot(),Pt()]);if(console.log(e?ne.green(`\u2713 Claude Code ${e.version}`):ne.red("\u2717 Claude Code not found on PATH")),console.log(t?ne.green(`\u2713 Codex ${t.version} (${t.bin})`):ne.red("\u2717 Codex not found (PATH or Codex.app)")),!ie()){console.log(ne.red(`\u2717 Not logged in. Run '${u.commands[0]} login' first.`)),process.exitCode=2;return}try{let n=await me();console.log(ne.green(`\u2713 Logged in as ${n.user.email}`))}catch(n){console.log(ne.red(`\u2717 Auth check failed: ${n instanceof Error?n.message:"unknown"}`)),process.exitCode=2}});Dt.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=>{ie()||(console.error(ne.red(`Not authenticated. Run '${u.commands[0]} login' first.`)),process.exit(2));let t=new AbortController,n=()=>{console.log(ne.gray(`
68
- Stopping runner\u2026`)),t.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await hi({claudeBin:e.claudeBin,codexBin:e.codexBin,log:r=>console.log(ne.gray(`[runner] ${r}`)),once:e.once,signal:t.signal,version:"0.3.18",workspaceRoot:e.workspace??Dc()})}catch(r){console.error(ne.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import q from"chalk";import{Command as $p}from"commander";import{Command as Nn}from"commander";function Nc(e,t){return[...t,e]}var Uc=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)",Nc,[]).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 d("Pass --yes to approve generation");try{p(await y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),qc=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{p(await T("createAdSet",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),yi=new Nn("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(Uc).addCommand(qc);import{randomUUID as Mc}from"crypto";import{Command as Ue}from"commander";function bi(e){return new Ue(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 d("Pass --yes to approve this operation");try{p(await y(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){d(r instanceof Error?r.message:"Agent operation failed"),process.exit(c.GENERAL_ERROR)}})}function qn(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function wi(e){return`cli:agent-memory:${e}:${Mc()}`}function Fc(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 Un(e,t){return[...t,e]}var Vc=new Ue("show").description("Show what a scheduled agent remembers").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{p(await y("getAgentMemory",{agentId:e,teamId:t.teamId}))}catch(n){qn(n,"Could not read the agent's memory")}}),jc=new Ue("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)",Un,[]).option("--always <text>","Standing instruction to add (repeatable)",Un,[]).option("--never <text>","Thing it must not do, to add (repeatable)",Un,[]).option("--track <name=note>","Entity to track, as name=note (repeatable)",Fc,[]).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{p(await y("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},wi(n?"remove":"add")))}catch(r){qn(r,"Could not update the agent's memory")}}),Gc=new Ue("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 d("Pass --yes to erase this agent's memory");try{p(await y("forgetAgentMemory",{agentId:e,teamId:t.teamId},wi("forget")))}catch(n){qn(n,"Could not erase the agent's memory")}}),Bc=new Ue("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(Vc).addCommand(jc).addCommand(Gc),vi=new Ue("agent").description("Create scheduled agents and read, edit, or erase what they remember").addCommand(bi("create")).addCommand(bi("recommend")).addCommand(Bc);import{randomUUID as Ci}from"crypto";import{existsSync as Jc}from"fs";import{resolve as zc}from"path";import it from"chalk";import{Command as pe}from"commander";import Xc from"ora";import{mkdir as Wc,writeFile as xi}from"fs/promises";import{dirname as Kc}from"path";async function z(e,t){if(await Wc(Kc(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 xi(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 xi(t,r)}var Hc=15e3,Yc=40,ki=3;async function Ii(e,t){if(e?.length){if(e.length>ki)throw new Error(`A presenter Look accepts at most ${ki} reference images`);return Promise.all(e.map(async(n,r)=>{if(Jc(n))return{url:(await de(zc(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 Mn(e,t){if(t==="json"){p(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}f(`Request ID: ${e.requestId}`),f(`Status: ${e.status}`),e.durationSec!=null&&f(`Duration: ${e.durationSec}s`),e.videoUrl&&C(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}var Qc=new pe("options").description("List available presenter avatars and voices").option("--language <language>","Filter voices by language").option("-f, --format <format>","Output format: human, json, quiet","human").action(async e=>{try{let t=await ho(e.language);if(e.format==="json"){p(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){f("Your presenters:");for(let r of n)console.log(` ${r.id} ${r.name}`)}f("Avatars:");for(let r of t.avatars){let o=r.renderTiers?.length?` [${r.renderTiers.join(", ")}]`:"";console.log(` ${r.id} ${r.name}${o}`)}f("Voices:");for(let r of t.voices)console.log(` ${r.id} ${r.name}${r.language?` (${r.language})`:""}`)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Zc=new pe("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","human").action(async e=>{let t=e.transparent?"webm":e.outputFormat;!!e.audioUrl==!!e.script&&(d("Provide exactly one avatar speech input: --audio-url or --script"),process.exit(c.INVALID_INPUT)),["1:1","9:16","16:9"].includes(e.aspect)||(d("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)&&(d("Output format must be mp4 or webm"),process.exit(c.INVALID_INPUT)),e.backgroundColor!==void 0&&!/^#[0-9a-fA-F]{6}$/.test(e.backgroundColor)&&(d("Background color must be a six-digit hex value"),process.exit(c.INVALID_INPUT)),e.backgroundColor&&e.backgroundImageUrl&&(d("Provide only one presenter background"),process.exit(c.INVALID_INPUT)),e.fit!==void 0&&!["contain","cover"].includes(e.fit)&&(d("Fit must be contain or cover"),process.exit(c.INVALID_INPUT)),e.fit&&!e.backgroundImageUrl&&(d("Fit requires --background-image-url"),process.exit(c.INVALID_INPUT)),e.transparent&&e.outputFormat==="mp4"&&(d("--transparent cannot be combined with --output-format mp4"),process.exit(c.INVALID_INPUT)),t==="webm"&&(e.backgroundColor||e.backgroundImageUrl)&&(d("Transparent WebM output cannot be combined with a background"),process.exit(c.INVALID_INPUT)),["basic","standard","premium"].includes(e.renderTier)||(d("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)&&(d("Duration must be between 1 and 300 seconds"),process.exit(c.INVALID_INPUT));let r=e.format==="human"?Xc("Generating presenter clip...").start():null;try{let o=e.audioUrl?{audioUrl:e.audioUrl}:{script:e.script??"",...e.voiceId?{voiceId:e.voiceId}:{}},i=await yo({...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(),Mn(i,e.format);return}let a=await Q(()=>Cn(i.requestId),Yc,Hc);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 z(a.videoUrl,e.output),r?.stop(),Mn(a,e.format),e.format==="human"&&C(`Saved to: ${e.output}`)}catch(o){r?.stop(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),el=new pe("status").description("Check a presenter clip generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{try{Mn(await Cn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),tl=new pe("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??Ci(),r=await Ii(t.referenceImage,n),o=await y("generatePresenterLook",{baseProfileId:e,description:t.description,id:t.lookId,prompt:t.prompt,...r?{referenceImages:r}:{},title:t.name},n);p(o)}catch(n){d(n instanceof Error?n.message:"Look generation failed"),process.exit(c.GENERAL_ERROR)}}),nl=new pe("status").description("Read presenter look generation status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{try{let n=await T("generatePresenterLook",e);if(t.format==="json")return p(n);if(t.format==="quiet")return console.log(n.status);f(`Run ID: ${e}`),f(`Status: ${n.status}`),n.error?.message&&d(n.error.message)}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),rl=new pe("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??Ci(),r=await Ii(t.referenceImage,n),o=await y("revisePresenterLook",{instruction:t.instruction,...r?{referenceImages:r}:{},sourceLookId:e},n);p(o)}catch(n){d(n instanceof Error?n.message:"Look revision failed"),process.exit(c.GENERAL_ERROR)}}),ol=new pe("revision-status").description("Read presenter Look revision status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{try{let n=await T("revisePresenterLook",e);if(t.format==="json")return p(n);if(t.format==="quiet")return console.log(n.status);f(`Run ID: ${e}`),f(`Status: ${n.status}`),n.error?.message&&d(n.error.message)}catch(n){d(n instanceof Error?n.message:"Revision status failed"),process.exit(c.GENERAL_ERROR)}}),il=new pe("look").description("Manage looks under an existing personal presenter").addCommand(tl).addCommand(rl).addCommand(ol).addCommand(nl),Fn=new pe("avatar").description("Generate presenter clips and looks; avatar options lists the voices and looks used by presentation video presenter and cast preset").addCommand(Qc).addCommand(Zc).addCommand(il).addCommand(el);Fn.addHelpText("after",`
69
- ${it.bold("Examples:")}
70
- ${it.gray("# Discover the presenter avatars and voices you can use")}
71
- $ ${u.commands[0]} avatar options
72
-
73
- ${it.bold("See also:")}
74
- ${it.gray("# Save a presenter + backdrop + voice combination under a name")}
75
- $ ${u.commands[0]} cast preset --help
76
-
77
- ${it.gray("# Apply an avatar, look, or preset to one presentation-video scene")}
78
- $ ${u.commands[0]} presentation video presenter <project-id>
79
- `);import{writeFile as Ai}from"fs/promises";import K from"chalk";import{Command as te}from"commander";import yl from"ora";import{createHash as al}from"crypto";import{existsSync as sl}from"fs";import{basename as dl}from"path";import{Command as Ri}from"commander";import cl from"ora";var Si=new Ri("logo").description("Brand logo files").addCommand(new Ri("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 A();let n=t.variant??"primary";["primary","dark","favicon"].includes(n)||(d(`--variant must be primary, dark, or favicon (got "${n}")`),process.exit(c.INVALID_INPUT)),sl(t.file)||(d(`File not found: ${t.file}`),process.exit(c.INVALID_INPUT));let r=cl({text:`Uploading ${dl(t.file)}...`,stream:process.stdout}).start(),o;try{o=(await de(t.file)).url,r.succeed("Uploaded")}catch(i){r.fail("Upload failed"),d(i instanceof Error?i.message:String(i)),process.exit(c.GENERAL_ERROR)}try{p(await y("setBrandLogo",{brandId:e,fileUrl:o,teamId:t.teamId,variant:n},al("sha256").update(`setBrandLogo:${e??"default"}:${n}:${o}`).digest("hex").slice(0,32)))}catch(i){d(i instanceof Error?i.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}));import{readFile as ll}from"fs/promises";import{randomUUID as ul}from"crypto";import{Command as $i}from"commander";var ml=["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 pl(e){let t=e.split(".").filter(Boolean);for(let n=t.length;n>=2;n--){let r=t.slice(0,n).join(".");if(ml.includes(r))return{fieldPath:t.slice(n),nodeKey:r}}return{fieldPath:t.slice(2),nodeKey:t.slice(0,2).join(".")}}function gl(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:s,nodeKey:l}=pl(o),g=fl(i);if(s.length===0){t[l]=g;continue}let m=t[l],w=m&&typeof m=="object"&&!Array.isArray(m)?m:{},v=w;for(let b of s.slice(0,-1)){let $=v[b],x=$&&typeof $=="object"&&!Array.isArray($)?$:{};v[b]=x,v=x}v[s[s.length-1]]=g,t[l]=w}return t}function fl(e){return e==="true"?!0:e==="false"?!1:/^-?\d+(?:\.\d+)?$/.test(e)?Number(e):e}function hl(e,t){return e===void 0?{assignments:[...t]}:e.includes("=")?{assignments:[e,...t]}:{assignments:[...t],brandId:e}}var Ti=new $i("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 y("getBrandProfile",{brandId:e,format:t.format,teamId:t.teamId});if(t.format==="md"&&typeof n.designMd=="string"){console.log(n.designMd);return}p(n)}catch(n){d(n instanceof Error?n.message:"Profile read failed"),process.exit(c.GENERAL_ERROR)}}),Ei=new $i("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||(d("Pass --yes to confirm writing brand tokens."),process.exit(c.INVALID_INPUT));let{assignments:r,brandId:o}=hl(e,t),i;try{i=r.length>0?gl(r):void 0}catch(s){d(s instanceof Error?s.message:"Invalid token pair"),process.exit(c.INVALID_INPUT)}let a;if(n.designMd)try{a=await ll(n.designMd,"utf8")}catch(s){d(`Could not read ${n.designMd}: ${s instanceof Error?s.message:String(s)}`),process.exit(c.INVALID_INPUT)}!i&&!a&&(d("Nothing to write. Pass token assignments (color.primary=#114b97) or --design-md <file>."),process.exit(c.INVALID_INPUT));try{p(await y("updateBrandTokens",{brandId:o,designMd:a,publish:n.publish===!1?!1:void 0,teamId:n.teamId,tokens:i},ul()))}catch(s){d(s instanceof Error?s.message:"Write failed"),process.exit(c.GENERAL_ERROR)}});var Oi=new te("branding").description("Manage brand profiles, design tokens, logos, competitors, and social handles").addCommand(Ti).addCommand(Ei).addCommand(new te("list").description("List brand profiles").option("-f, --format <format>","Output format (table, json)","table").action(async e=>{await A();try{let t=await wn();if(t.brandings.length===0){e.format==="json"?console.log(JSON.stringify([])):(f("No brand profiles found"),console.log(),console.log(K.gray(`Create one with: ${u.commands[0]} branding extract <url>`)));return}e.format==="json"?console.log(JSON.stringify(t.brandings,null,2)):console.log(Or(t.brandings))}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new te("get").description("Get brand profile details").argument("<id>","Brand profile ID").option("-f, --format <format>","Output format (summary, json)","summary").option("-o, --output <path>","Save JSON to file").action(async(e,t)=>{await A();try{let n=await eo(e);if(t.output){await Ai(t.output,JSON.stringify(n,null,2)),C(`Brand profile saved to ${t.output}`);return}if(t.format==="json")console.log(JSON.stringify(n,null,2));else{if(oe("Brand Profile"),console.log(),S("ID",n.id),S("Name",n.name),S("Source URL",n.sourceUrl??K.gray("None")),S("Default",n.isDefault?K.green("Yes"):"No"),n.createdAt&&S("Created",new Date(n.createdAt).toLocaleString()),console.log(),n.primaryColor||n.colors.length>0){if(console.log(K.bold(" Colors")),n.primaryColor){let o=K.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=K.bgHex(o.hex)(" "),a=o.role?K.gray(` (${o.role})`):"";console.log(` ${i} ${o.hex}${a}`)}}console.log()}n.logoUrl&&(console.log(K.bold(" Logo")),console.log(` ${n.logoUrl}`),console.log());let r=n.typography;r&&Object.keys(r).length>0&&(console.log(K.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(K.bold(" Extraction")),n.confidence&&console.log(` Confidence: ${Math.round(n.confidence*100)}%`),n.extractionMethod&&console.log(` Method: ${n.extractionMethod}`),console.log()),console.log(K.gray(" Use --format json for full details")),console.log()}}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new te("find").description("Find existing brand profile by name or URL").argument("<query>","Brand name or website URL to search for").action(async e=>{await A();try{let t=await wn(),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){f(`No brand profiles matching "${e}"`),console.log(K.gray(` Extract one with: ${u.commands[0]} branding extract <url>`));return}console.log(`Found ${r.length} brand${r.length>1?"s":""}:
80
- `);for(let o of r){let i=o.primaryColor?`${K.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"";console.log(` ${K.bold(o.name)} ${K.gray(o.id)}`),o.sourceUrl&&console.log(` ${K.gray(o.sourceUrl)}`),i&&console.log(` ${i}`),console.log()}console.log(K.gray(` Export with: ${u.commands[0]} branding get <id> -o branding.json`))}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new te("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 A(),t.yes||(d("Pass --yes to confirm brand extraction."),process.exit(c.INVALID_INPUT));try{new URL(e.startsWith("http")?e:`https://${e}`)}catch{d("Invalid URL format"),process.exit(6)}let n=e.startsWith("http")?e:`https://${e}`,r=t.teamId??bt(),o=yl({text:`Extracting branding from ${n}...`,stream:process.stdout}).start();try{let i=await to(n,r,"cli:--yes");o.succeed("Brand extraction started");let a=JSON.stringify(i,null,2);t.output?(await Ai(t.output,a),C(`Brand profile saved to ${t.output}`)):console.log(a),f(`Check progress with: ${u.commands[0]} branding status ${i.runId}`),console.log()}catch(i){o.fail("Extraction failed"),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})).addCommand(new te("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{p(await T("extractBranding",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}})).addCommand(new te("set-default").description("Set a brand profile as default").argument("<id>","Brand profile ID").action(async e=>{await A(),f(`To set brand ${e} as default, use the web dashboard.`),console.log(),console.log(K.gray("API support for setting default brand is coming soon."))})).addCommand(new te("competitor").description("Brand competitor commands").addCommand(new te("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 y("getBrandCompetitors",{brandingId:e.brandingId,teamId:e.teamId}),null,2))}catch(t){d(t instanceof Error?t.message:"Lookup failed"),process.exit(1)}})).addCommand(new te("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||(d("Pass --yes to confirm adding a competitor."),process.exit(c.INVALID_INPUT));try{p(await y("addCompetitor",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,name:e,teamId:t.teamId,website:t.website,xHandle:t.xHandle}))}catch(n){d(n instanceof Error?n.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}))).addCommand(Si).addCommand(new te("social").description("Brand social handle commands").addCommand(new te("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||(d("Pass --yes to confirm adding a social handle."),process.exit(c.INVALID_INPUT));try{p(await y("addBrandSocialHandle",{approvalReceipt:"cli:--yes",brandingId:n.brandingId,handle:t,platform:e,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Write failed"),process.exit(c.GENERAL_ERROR)}})));import at from"chalk";import{Command as qe}from"commander";function bl(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 Pi(e,t){return{background:bl(t),name:e,presenterProfileId:t.presenter,...t.voiceId?{voiceId:t.voiceId}:{}}}function Nt(e,t){if(t==="json"){p(e);return}if(t==="quiet"){console.log(e.id);return}C(`${e.name} (${e.id})`),f(` Presenter: ${e.presenterProfileId}`),f(` Backdrop: ${wl(e.background)}`),e.voiceId&&f(` Voice: ${e.voiceId}`)}function wl(e){switch(e.kind){case"color":return`color ${e.hex}`;case"image":return`image ${e.url} (${e.fit})`;default:return e.kind}}function _i(e){return e.requiredOption("--presenter <profileId>","Trained personal presenter id (pp_*), from `mf 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","human")}var vl=new qe("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","human").action(async e=>{try{let t=await Io({...e.brandingId?{brandingId:e.brandingId}:{},...e.castMemberId?{castMemberId:e.castMemberId}:{}});if(e.format==="json"){p(t);return}if(e.format==="quiet"){for(let n of t.presets)console.log(n.id);return}if(t.presets.length===0){f("No presets saved yet.");return}for(let n of t.presets)Nt(n,"human")}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(c.API_ERROR)}}),xl=_i(new qe("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 Ro({castMemberId:t.castMemberId,...Pi(e,t)});Nt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),kl=_i(new qe("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 So({presetId:e,...Pi(t.name,t)});Nt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Cl=new qe("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","human").action(async(e,t)=>{try{let n=await $o(e);if(t.format==="human"){C(`Retired "${n.preset.name}".`);return}Nt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Il=new qe("preset").description("Saved ways a cast member appears").addCommand(vl).addCommand(xl).addCommand(kl).addCommand(Cl),Vn=new qe("cast").description("The faces and voices your videos can use").addCommand(Il);Vn.addHelpText("after",`
81
- ${at.bold("Examples:")}
82
- ${at.gray("# List the saved presenter/backdrop/voice combinations")}
83
- $ ${u.commands[0]} cast preset list
84
-
85
- ${at.bold("See also:")}
86
- ${at.gray("# The presenter avatars, looks, and voices a preset is built from")}
87
- $ ${u.commands[0]} avatar options
88
-
89
- ${at.gray("# Use a preset on one presentation-video scene")}
90
- $ ${u.commands[0]} presentation video presenter <project-id>
91
- `);import{readFile as Rl}from"fs/promises";import st from"chalk";import{Command as Li}from"commander";var Sl=new Li("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","human").action(async(e,t)=>{try{let n=e,r;e.includes("://")||(n=await Rl(e,"utf8"),r=e);let o=await y("extractContent",{filename:r,maxLength:Number.parseInt(t.maxLength,10),mimeType:t.mimeType,source:n,teamId:t.teamId});t.format!=="quiet"&&p(o)}catch(n){d(n instanceof Error?n.message:"Extraction failed"),process.exit(c.GENERAL_ERROR)}}),jn=new Li("content").description("Extract normalized text from a URL, a local file, or an encoded document").addCommand(Sl);jn.addHelpText("after",`
92
- ${st.bold("Examples:")}
93
- ${st.gray("# Normalized text from a local document")}
94
- $ ${u.commands[0]} content extract ./paper.pdf
95
-
96
- ${st.bold("See also:")}
97
- ${st.gray("# Web pages, with page metadata and cost reporting")}
98
- $ ${u.commands[0]} scrape https://example.com/post
99
-
100
- ${st.gray("# Spoken words out of audio or video")}
101
- $ ${u.commands[0]} transcript --help
102
- `);import J from"chalk";import{Command as $l}from"commander";import{existsSync as Tl,readFileSync as El}from"fs";import Al,{resolve as Di}from"path";var Ni=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("-o, --output <format>","Output format (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)=>{await A();let n;t.slides!==void 0&&(n=parseInt(t.slides,10),(Number.isNaN(n)||n<1||n>20)&&(d("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)&&(d(`Invalid mode: ${t.mode}. Valid: ${r.join(", ")}`),process.exit(6));let o=["smart","fast","balanced","best"];t.imageTier&&!o.includes(t.imageTier)&&(d(`Invalid image tier: ${t.imageTier}. Valid: ${o.join(", ")}`),process.exit(6));let i=["creative","professional","educational","formal","casual"];t.tone&&!i.includes(t.tone)&&(d(`Invalid tone: ${t.tone}. Valid: ${i.join(", ")}`),process.exit(6));let a=["minimal","concise","detailed","extensive"];t.amount&&!a.includes(t.amount)&&(d(`Invalid amount: ${t.amount}. Valid: ${a.join(", ")}`),process.exit(6));let s=["freeform","brand-only","brand-plus-style","style-only","no-styling"];t.styling&&!s.includes(t.styling)&&(d(`Invalid styling: ${t.styling}. Valid: ${s.join(", ")}`),process.exit(6));let l=["quick","moderate","deep","profound"];t.thinkingDepth&&!l.includes(t.thinkingDepth)&&(d(`Invalid thinking-depth: ${t.thinkingDepth}. Valid: ${l.join(", ")}`),process.exit(6));let g=["inform","persuade","train","learn","entertain","report"];t.goal&&!g.includes(t.goal)&&(d(`Invalid goal: ${t.goal}. Valid: ${g.join(", ")}`),process.exit(6));let m=["blue","violet","rose","orange","green"];t.theme&&!m.includes(t.theme)&&(d(`Invalid theme: ${t.theme}. Valid: ${m.join(", ")}`),process.exit(6));let w=["none","waves-bottom-left","waves-top-right","blob-corners","minimal"];t.decorations&&!w.includes(t.decorations)&&(d(`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"&&(d("--theme, --primary-color, --decorations and other color options are only supported with --mode instant"),process.exit(6));let b=t.mode??(v?"instant":"fast"),$=/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;for(let[I,B]of[["primary-color",t.primaryColor],["secondary-color",t.secondaryColor],["accent-color",t.accentColor],["background-color",t.backgroundColor],["foreground-color",t.foregroundColor]])B&&!$.test(B)&&(d(`Invalid ${I}: ${B}. Must be hex (e.g., #0066CC)`),process.exit(6));try{t.output!=="json"&&t.output!=="quiet"&&process.stdout.write(J.gray("Checking generation limits... "));let I=await oo(b,n??10,t.teamId);if(t.output!=="json"&&t.output!=="quiet"){console.log(J.green("\u2713"));let B=I.remaining[b],X=I.limits[b],xe=B===void 0||X===void 0?"":` | ${b}: ${B}/${X} remaining`;console.log(J.gray(` Plan: ${I.planName}${xe}`))}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):(console.log(J.red("\u2717")),d(I instanceof Error?I.message:String(I))),process.exit(I.exitCode??1)}let x=[];if(t.file&&t.file.length>0){for(let I of t.file)Tl(Di(I))||(d(`File not found: ${I}`),process.exit(6));t.output!=="json"&&t.output!=="quiet"&&console.log(J.gray(`
103
- Uploading ${t.file.length} file(s)...`));try{x=await Wr(t.file.map(I=>Di(I)),(I,B,X)=>{t.output!=="json"&&t.output!=="quiet"&&X&&process.stdout.write(`\r ${J.cyan("\u2B06")} Uploading: ${X} (${I+1}/${B})`)}),t.output!=="json"&&t.output!=="quiet"&&console.log(`\r ${J.green("\u2713")} Uploaded ${x.length} file(s) `)}catch(I){d(`Failed to upload files: ${I instanceof Error?I.message:String(I)}`),process.exit(1)}}let k;(t.stdin||!process.stdin.isTTY)&&(k=await Ol(),t.stdin&&!k&&(d("No content received from stdin"),process.exit(6)));let R=t.context;if(t.contextFile)try{R=El(t.contextFile,"utf-8"),R.trim()||(d(`Context file is empty: ${t.contextFile}`),process.exit(6))}catch{d(`Failed to read context file: ${t.contextFile}`),process.exit(6)}!k&&!R&&x.length===0&&(d("Context is required to create a presentation."),console.log(),console.log(J.gray(" -f, --file <paths...> Upload files (PDF, PPTX, images)")),console.log(J.gray(" -c, --context <text> Inline text context")),console.log(J.gray(" --context-file <path> Read from a file")),console.log(J.gray(` cat file | ${u.commands[0]} Pipe content`)),process.exit(6));let D=[...x];k&&D.push({id:`stdin-${Date.now()}`,content:k,title:"Piped Content",mime:"text/plain",selected:!0}),R&&D.push({id:`context-${Date.now()}`,content:R,title:"Context",mime:"text/plain",selected:!0});let E,U=t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor;(t.theme||U||t.decorations)&&(E={},t.theme&&(E.preset=t.theme),U&&(E.custom={},t.primaryColor&&(E.custom.primary=t.primaryColor),t.secondaryColor&&(E.custom.secondary=t.secondaryColor),t.accentColor&&(E.custom.accent=t.accentColor),t.backgroundColor&&(E.custom.background=t.backgroundColor),t.foregroundColor&&(E.custom.foreground=t.foregroundColor)),t.decorations&&(E.decorations=t.decorations));try{let I=await Kr({topic:e,...n!==void 0&&{slideCount:n},mode:b,...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},...E&&{theme:E},...t.studio?{documentId:Al.basename(process.cwd())}:t.id?{documentId:t.id}:{},...D.length>0&&{contentSources:{uploadedFiles:D,contextFiles:[]}}});if(!t.wait){t.output==="json"?console.log(JSON.stringify({success:!0,run:I},null,2)):t.output!=="quiet"&&(C("Presentation generation queued"),S("Run ID",I.runId),S("Status",I.status),console.log(J.gray(` Check later with presentation status ${I.runId}`)));return}let B=await T("createSlides",I.runId,t.teamId);for(;!B.done;)t.output!=="json"&&t.output!=="quiet"&&console.log(J.gray(` ${B.message}`)),await new Promise(xe=>setTimeout(xe,(B.nextPollAfterSeconds??5)*1e3)),B=await T("createSlides",I.runId,t.teamId);if(B.error)throw new Error(B.error.message);let X=B.entity?await fe(B.entity.id):void 0;if(t.output==="json")console.log(JSON.stringify({success:!0,presentation:X,run:B,viewUrl:X?_e(X.slug,t.language??"en"):void 0},null,2));else{console.log(),C("Presentation created successfully"),console.log(),S("Title",X?.title??e),S("Slides",String(X?.numberOfSlides??n??"\u2014")),console.log();let xe=X?_e(X.slug,t.language??"en"):"N/A";xe!=="N/A"&&(console.log(J.bold(" Open: ")+J.cyan.underline(xe)),t.open&&await(await import("open")).default(xe)),console.log()}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):d(I instanceof Error?I.message:String(I)),process.exit(I.exitCode??1)}});async function Ol(){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 Pl}from"crypto";import{readFile as _l}from"fs/promises";import{Command as ye}from"commander";var Gn=["text/markdown","text/csv","text/plain"];async function Ui(e){let t=e.content;if(t!==void 0&&t!=="-"&&!t.startsWith("@"))return t;if(t?.startsWith("@"))return _l(t.slice(1),"utf8");if(t==="-"||!process.stdin.isTTY)return Ll();d("No document body. Pass --content <text>, --content @<path>, or pipe it on stdin."),process.exit(c.GENERAL_ERROR)}async function Ll(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}function Ut(e){return`cli:document:${e}:${Pl()}`}function Se(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function Dl(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 Nl=new ye("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??Dl(t.content?.startsWith("@")?t.content.slice(1):void 0);n||(d(`Cannot tell what this document is. Pass --media-type (${Gn.join(", ")}).`),process.exit(c.GENERAL_ERROR)),p(await y("createDocument",{content:await Ui(t),mediaType:n,summary:t.summary,teamId:t.teamId,title:e},Ut("create")))}catch(n){Se(n,"Could not save the document")}}),Ul=new ye("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{p(await y("listDocuments",{limit:e.limit?Number(e.limit):void 0,mediaType:e.mediaType,teamId:e.teamId}))}catch(t){Se(t,"Could not list documents")}}),ql=new ye("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 y("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
104
- `),process.stdout.write(r.content)}catch(n){Se(n,"Could not read the document")}}),Ml=new ye("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;p(await y("updateDocument",{changeSummary:t.changeSummary,content:n?await Ui(t):void 0,documentId:e,expectedVersion:Number(t.expectedVersion),summary:t.summary,teamId:t.teamId,title:t.title},Ut("update")))}catch(n){Se(n,"Could not update the document")}}),Fl=new ye("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&&(d("Refusing to delete without confirmation. Re-run with --yes to remove this document."),process.exit(c.GENERAL_ERROR)),p(await y("deleteDocument",{documentId:e,teamId:t.teamId},Ut("delete")))}catch(n){Se(n,"Could not delete the document")}}),Vl=new ye("versions").description("List a document's version history").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{p(await y("listDocumentVersions",{documentId:e,teamId:t.teamId}))}catch(n){Se(n,"Could not list versions")}}),jl=new ye("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{p(await y("restoreDocumentVersion",{documentId:e,expectedVersion:Number(t.expectedVersion),teamId:t.teamId,versionNumber:Number(t.versionNumber)},Ut("restore")))}catch(n){Se(n,"Could not restore the version")}}),qi=new ye("document").description("Create, read and edit Library documents").addCommand(Nl).addCommand(Ul).addCommand(ql).addCommand(Ml).addCommand(Fl).addCommand(Vl).addCommand(jl);import{Command as Gl}from"commander";import qt from"chalk";var Mi=new Gl("get").description("Get presentation details").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --format <format>","Output 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 A();try{let n=await fe(e);if(t.format==="json"){console.log(JSON.stringify(n,null,2));return}let r=_e(n.slug,t.language);oe("Presentation Details"),console.log(),S("Slug",n.slug),S("Title",n.title||"Untitled"),S("Description",n.description||qt.gray("None")),S("Slides",String(n.numberOfSlides||"-")),S("Mode",n.mode||"-"),S("Created",gn(n.createdAt)),n.updatedAt&&S("Updated",gn(n.updatedAt)),console.log(),r!=="N/A"&&console.log(qt.bold(" Open: ")+qt.cyan.underline(r)),console.log(),t.format==="full"&&t.include?.includes("slides")&&(console.log(qt.gray("(Full slide content available in JSON format)")),console.log())}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Ft}from"commander";import Bl from"ora";function re(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 Wl(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}function Kl(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:Wl(e.source),transparentBackground:t==="icon"}}}function Jl(e){let t=e.url||e.imageUrl;if(!t)throw new Error("Image search returned a result without a URL");return t}function zl(e){return e.transparent??e.isTransparent??e.metadata?.transparent??e.metadata?.isTransparent}function Xl(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 Hl(e,t){let n=e.data.results.map(r=>r.results.map(o=>{let i=o,a=zl(i);if(t==="icon"&&a!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:Jl(i),provider:r.providerName,assetType:t,...a!==void 0?{transparent:a}:{}}}));return Xl(n)}function Yl(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 Mt(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Ql(e){return{requestId:e.runId,status:Yl(e),...e.entity?.url?{url:e.entity.url}:{},...e.error?.message?{error:e.error.message}:{},...Mt(e.output?.width)!==void 0?{width:Mt(e.output?.width)}:{},...Mt(e.output?.height)!==void 0?{height:Mt(e.output?.height)}:{}}}async function Fi(e,t){return Ql(await T("createImage",e,t))}function Bn(e,t){if(t==="json"){p(e);return}if(t==="quiet"){console.log(e.output??e.url??e.requestId);return}f(`Request ID: ${e.requestId}`),f(`Status: ${e.status}`),e.url&&C(`Image URL: ${e.url}`),e.output&&C(`Saved to: ${e.output}`),e.error&&d(`Error: ${e.error}`)}var Zl=new Ft("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","human").action(async e=>{let t=e.format,n=t==="human"?Bl("Searching for images...").start():null,r;try{r=Kl(e)}catch(o){n?.stop(),d(o instanceof Error?o.message:"Invalid image search request"),process.exit(c.INVALID_INPUT);return}try{let o=await uo(r);n?.stop(),o.success||(d("Search failed"),process.exit(c.GENERAL_ERROR));let i=r.options?.assetType??"image",a=Hl(o,i);if(t==="json"){p({success:!0,query:e.query,assetType:i,totalResults:a.length,images:a});return}if(t==="quiet"){for(let s of a)console.log(s.url);return}if(a.length===0){f("No images found");return}C(`Found ${a.length} images for "${e.query}"`),console.log();for(let s=0;s<a.length;s++){let l=a[s];console.log(`[${s+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()}f(`Total cost: $${o.data.totalCost.toFixed(4)}`)}catch(o){n?.stop(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),eu=new Ft("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","human").option("--yes","Approve generation").action(async(e,t)=>{let n,r=e??t.prompt;r?.trim()||(d("Provide an image prompt as an argument or with --prompt"),process.exit(c.INVALID_INPUT)),t.yes||(d("Pass --yes to approve image generation"),process.exit(c.INVALID_INPUT)),!t.wait&&t.output&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));try{let o=await y("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){Bn({requestId:o.runId,status:"pending"},t.format);return}let i=await Q(()=>Fi(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 z(i.url,t.output),Bn(a,t.format)}catch(o){d(re(o,n),t.format),process.exit(c.GENERAL_ERROR)}}),tu=new Ft("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","human").action(async(e,t)=>{try{let n=await Fi(e,t.teamId);if(t.output){if(n.status!=="completed"||!n.url)throw new Error("Image generation is not complete");await z(n.url,t.output),n.output=t.output}Bn(n,t.format)}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Vi=new Ft("image").description("Image search and generation commands").addCommand(Zl).addCommand(eu).addCommand(tu);import{Command as Wn}from"commander";var nu=new Wn("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{p(await y("searchKnowledge",{kind:t.kind,limit:Number.parseInt(t.limit,10),query:e,teamId:t.teamId}))}catch(n){d(n instanceof Error?n.message:"Knowledge search failed"),process.exit(c.GENERAL_ERROR)}}),ru=new Wn("bundle").description("Read a bounded Open Knowledge Format bundle").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").action(async e=>{try{p(await y("getKnowledgeBundle",{kind:e.kind,teamId:e.teamId}))}catch(t){d(t instanceof Error?t.message:"Knowledge bundle failed"),process.exit(c.GENERAL_ERROR)}}),ji=new Wn("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(nu).addCommand(ru);import{randomUUID as ou}from"crypto";import Vt from"chalk";import{Command as ge}from"commander";function Kn(e){if(e!==void 0)return e==="root"?null:e}function Me(e){return`cli:library:${e}:${ou()}`}function $e(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}var iu=new ge("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{p(await y("listLibraryFolders",{includeEntryCounts:!!e.counts,teamId:e.teamId}))}catch(t){$e(t,"Could not list folders")}}),au=new ge("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{p(await y("createLibraryFolder",{color:t.color,name:e,parentId:Kn(t.parent),teamId:t.teamId},Me("create")))}catch(n){$e(n,"Could not create the folder")}}),su=new ge("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{p(await y("renameLibraryFolder",{folderId:e,name:t,teamId:n.teamId},Me("rename")))}catch(r){$e(r,"Could not rename the folder")}}),du=new ge("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{p(await y("recolorLibraryFolder",{color:t.color==="none"?null:t.color,folderId:e,teamId:t.teamId},Me("recolor")))}catch(n){$e(n,"Could not recolour the folder")}}),cu=new ge("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{p(await y("moveLibraryFolder",{folderId:e,newParentId:Kn(t.to),teamId:t.teamId},Me("move")))}catch(n){$e(n,"Could not move the folder")}}),lu=new ge("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{p(await y("deleteLibraryFolder",{folderId:e,teamId:t.teamId},Me("delete")))}catch(n){$e(n,"Could not delete the folder")}}),uu=new ge("folders").description("Manage Library folders").addCommand(iu).addCommand(au).addCommand(su).addCommand(du).addCommand(cu).addCommand(lu),mu=new ge("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{p(await y("fileArtifactIntoFolder",{folderId:Kn(n.folder),kind:e,targetId:t,teamId:n.teamId},Me("file")))}catch(r){$e(r,"Could not file that item")}}),Jn=new ge("library").description("Library folders and filing").addCommand(uu).addCommand(mu);Jn.addHelpText("after",`
105
- ${Vt.bold("Examples:")}
106
- ${Vt.gray("# Browse the folder tree and file an artifact into a folder")}
107
- $ ${u.commands[0]} library folders list
108
- $ ${u.commands[0]} library file presentation <id> --folder <folder-id>
109
-
110
- ${Vt.bold("See also:")}
111
- ${Vt.gray("# A different thing: reusable video clips, not Library folders")}
112
- $ ${u.commands[0]} video library --help
113
- `);import{Command as dt}from"commander";function j(e,t){let n=e.parent?.opts?.();if(!n)return t;let r={...t};for(let[o,i]of Object.entries(n))r[o]===void 0&&i!==void 0&&(r[o]=i);return r}var Gi=new dt("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 d("Pass --yes to confirm. Analysis is billed per minute of source audio.");try{p(await y("analyzeMediaAsset",{assetId:e,diarize:t.diarize,language:t.language,teamId:t.teamId}))}catch(n){d(n instanceof Error?n.message:"Analysis failed"),process.exit(c.GENERAL_ERROR)}}),pu=new dt("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=j(this,t);try{p(await T("analyzeMediaAsset",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});Gi.addCommand(pu);var Bi=new dt("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{p(await y("importConnectorRecording",{connectorId:t.connector,providerId:t.provider,remoteFileId:e,sourceChatId:t.chat,teamId:t.teamId,title:t.title}))}catch(n){d(n instanceof Error?n.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}),gu=new dt("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=j(this,t);try{p(await T("importConnectorRecording",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});Bi.addCommand(gu);var Wi=new dt("media").description("Ingest and transcribe recordings you already own").addCommand(Gi).addCommand(Bi);import{Command as zn}from"commander";var fu=new zn("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 d("Pass --yes to approve generation");try{p(await y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),hu=new zn("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{p(await T("createMicrosite",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ki=new zn("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(fu).addCommand(hu);import{Command as Yn}from"commander";import Xn from"ora";function Hn(e,t){if(t==="json"){let{cost:n,...r}=e;p(r);return}if(t==="quiet"){e.outputUrl?console.log(e.outputUrl):console.log(e.requestId);return}f(`Request ID: ${e.requestId}`),f(`Status: ${e.status}`),e.duration&&f(`Duration: ${e.duration}s`),e.outputUrl&&C(`Output URL: ${e.outputUrl}`),e.cost!==void 0&&f(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var yu=new Yn("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","human").action(async e=>{!e.music&&!e.voice&&(d("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)&&(d("Music volume must be between 0 and 100"),process.exit(c.INVALID_INPUT)),(Number.isNaN(n)||n<0||n>2)&&(d("Voice volume must be between 0 and 200"),process.exit(c.INVALID_INPUT));let r=e.format,o=r==="human"?Xn("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 lo({operation:"add-to-video",inputs:i,options:{musicVolume:t,voiceVolume:n}});if(!e.wait){o?.stop(),Hn(a,r);return}o&&(o.text=`Processing (ID: ${a.requestId})...`);let s=await Q(()=>xn(a.requestId),120,3e3);if(o?.stop(),s.status==="failed"&&(d(s.error||"Audio mixing failed"),process.exit(c.GENERAL_ERROR)),Hn(s,r),e.output){if(!s.outputUrl)throw new Error("Audio mix completed without an output URL");let l=r==="human"?Xn("Downloading...").start():null;await z(s.outputUrl,e.output),l?.stop(),r==="human"&&C(`Saved to: ${e.output}`)}}catch(a){o?.stop(),d(a instanceof Error?a.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),bu=new Yn("status").description("Check status of an audio mix request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{let n=t.format==="human"?Xn("Checking status...").start():null;try{let r=await xn(e);n?.stop(),Hn(r,t.format)}catch(r){n?.stop(),d(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Ji=new Yn("mix").description("Audio mixing commands").addCommand(yu).addCommand(bu);import{Command as Zn}from"commander";import Ru from"ora";import{readFileSync as wu}from"fs";var zi=500,Xi=1e4,jt=100,Hi=1e4,Yi=1e3,Zi=["duration_s","idempotency_key","narration","schema_version","video_description"],vu=["end_s","id","start_s","text","words"],xu=["end","id","start","text"],ku=["description","end_s","id","start_s"];function ea(e){let t=na(e);if(ra(t),ct(t,Zi,""),t.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return t}function ta(e){let t=na(e);ra(t),ct(t,[...Zi,"visual_event"],"");let n=t.visual_event;if(!Gt(n))throw new Error("SFX request visual_event is required");if(ct(n,ku,"visual_event"),!be(n.description))throw new Error("SFX request visual_event.description is required");if(!be(n.id)||!we(n.start_s))throw new Error("SFX request visual_event requires id and start_s");if(n.end_s!==void 0&&(!we(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 na(e){try{let t=JSON.parse(wu(e,"utf8"));if(!Gt(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 ra(e){if(e.schema_version!==1)throw new Error("Audio request schema_version must be 1");if(!be(e.video_description))throw new Error("Audio request video_description is required");if(!we(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>zi)throw new Error(`Audio request narration holds at most ${zi} lines`);if(e.narration.forEach(Cu),e.idempotency_key!==void 0&&!be(e.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function Cu(e,t){let n=`narration.${t}`;if(!Gt(e))throw new Error(`Audio request ${n} must be an object`);if(ct(e,vu,n),!be(e.id)||e.id.length>jt)throw new Error(`Audio request ${n}.id is required (1-${jt} characters)`);if(!be(e.text)||e.text.trim().length>Hi)throw new Error(`Audio request ${n}.text is required (1-${Hi} characters)`);if(Qi(e.start_s,`${n}.start_s`),Qi(e.end_s,`${n}.end_s`),we(e.start_s)&&we(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>Xi)throw new Error(`Audio request ${n}.words must be an array of at most ${Xi} entries`);e.words.forEach((r,o)=>{Iu(r,`${n}.words.${o}`)})}}function Iu(e,t){if(!Gt(e))throw new Error(`Audio request ${t} must be an object`);if(ct(e,xu,t),!be(e.text)||e.text.trim().length>Yi)throw new Error(`Audio request ${t}.text is required (1-${Yi} characters)`);if(!we(e.start)||!we(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&&(!be(e.id)||e.id.length>jt))throw new Error(`Audio request ${t}.id must be 1-${jt} characters`)}function Qi(e,t){if(e!==void 0&&!we(e))throw new Error(`Audio request ${t} must be a non-negative number`)}function ct(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 Gt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function be(e){return typeof e=="string"&&e.trim().length>0}function we(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0}function Qn(e,t){if(t==="json"){let{cost:n,...r}=e;p(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId);return}f(`Request ID: ${e.requestId}`),f(`Status: ${e.status}`),e.duration&&f(`Duration: ${e.duration}s`),e.audioUrl&&C(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&f(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var Su=new Zn("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","human").action(async e=>{!e.wait&&e.output&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=ea(e.request)}catch(i){d(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?Ru("Generating music for video...").start():null,o;try{let i=await co(t);if(o=i.requestId,!e.wait){r?.stop(),Qn(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let a=i.status==="completed"||i.status==="failed"?i:await Q(()=>vn(i.requestId),180,2e3);if(r?.stop(),a.status==="failed"&&(d(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 z(a.audioUrl,e.output),n==="human"&&C(`Saved to: ${e.output}`),a.output=e.output}Qn(a,n)}catch(i){r?.stop(),d(re(i,o),n),process.exit(c.GENERAL_ERROR)}}),$u=new Zn("status").description("Check status of a music generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{try{Qn(await vn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),oa=new Zn("music").description("Video-aware music generation commands").addCommand(Su).addCommand($u);import{Command as er}from"commander";function ia(e,t){return[...t,e]}var Tu=new er("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",ia,[]).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 d("Pass --yes to approve poll creation");try{p(await y("createPoll",{approvalReceipt:"cli:--yes",options:t.option.map(n=>({text:n})),pollType:t.type,question:e,teamId:t.teamId,title:t.title}))}catch(n){d(n instanceof Error?n.message:"Poll creation failed"),process.exit(c.GENERAL_ERROR)}}),Eu=new er("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",ia).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 d("Pass --yes to approve poll update");try{p(await y("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){d(n instanceof Error?n.message:"Poll update failed"),process.exit(c.GENERAL_ERROR)}}),aa=new er("poll").description("Standalone poll commands").addCommand(Tu).addCommand(Eu);import{randomUUID as qu}from"crypto";import{readFile as Mu}from"fs/promises";import Te from"chalk";import{Command as H}from"commander";import{randomUUID as nr}from"crypto";import{readFile as Au}from"fs/promises";import{Command as Bt}from"commander";var sa=new Bt("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=j(this,t);await Wt("Draft edit failed",async()=>y("editPresentationVideoDraft",{edit:await Ou(n.edit),projectId:e,teamId:n.teamId},n.idempotencyKey??nr()))}),da=new Bt("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",tr(1)).option("--limit <number>","Maximum versions",tr(1,100)).option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=j(this,t);await Wt("Version list failed",()=>y("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:e,teamId:n.teamId}))}),ca=new Bt("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",tr(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t,n){let r=j(this,n);await Wt("Version restore failed",()=>y("restorePresentationVideoVersion",{projectId:e,teamId:r.teamId,versionNumber:t},r.idempotencyKey??nr()))}),la=new Bt("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=j(this,t);await Wt("Slide refresh failed",()=>y("refreshPresentationVideoSlides",{projectId:e,teamId:n.teamId},n.idempotencyKey??nr()))});async function Ou(e){let t=e.trim(),n=t.startsWith("{")?t:await Au(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 tr(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 Wt(e,t){try{p(await t())}catch(n){d(n instanceof Error?n.message:e),process.exit(c.GENERAL_ERROR)}}import{randomUUID as Pu}from"crypto";import{Command as _u}from"commander";var Lu=["basic","standard","premium"],ua=new _u("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=j(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&&!Lu.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");p(await y("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},Du(r.idempotencyKey)))}catch(o){d(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(c.GENERAL_ERROR)}});function Du(e){return e||Pu()}import{Command as rr}from"commander";var ma=new rr("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=j(this,t);try{p(await y("getPresentationVideoProject",{projectId:e,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Project read failed"),process.exit(c.GENERAL_ERROR)}}),Nu=new rr("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",Uu).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=j(this,t);try{p(await y("listReusableVideoClips",{cursor:n.cursor,limit:n.limit,projectId:e,query:n.query,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Clip list failed"),process.exit(c.GENERAL_ERROR)}}),pa=new rr("library").description("Reusable generated clips and uploaded recordings").addCommand(Nu);function Uu(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 Fu=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","human").action(async(e,t)=>{try{let n=await T("createSlides",e,t.teamId);if(t.format==="json"){p(n);return}if(t.format==="quiet"){console.log(n.status);return}f(`Status: ${n.status}`),f(n.message),n.progress!==null&&f(`Progress: ${n.progress}%`),n.error&&d(n.error.message)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Vu=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=j(this,t);try{let r=await y("transformPresentationImport",{importId:e},n.idempotencyKey);p(r)}catch(r){d(r instanceof Error?r.message:"Transform failed"),process.exit(c.GENERAL_ERROR)}}),ju=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","human").action(async(e,t)=>{try{let n=await T("importPowerPoint",e,t.teamId);t.format==="json"?p(n):t.format==="quiet"?console.log(n.status):(f(`Status: ${n.status}`),f(n.message),n.error&&d(n.error.message))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ga=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){ga.help();return}e.file.toLowerCase().endsWith(".pptx")||(d("PowerPoint import requires a .pptx file."),process.exit(c.INVALID_INPUT));try{let t=await de(e.file),n=await y("importPowerPoint",{brandingId:e.brandingId,filename:e.filename??t.name,mode:e.mode,sourceChatId:e.sourceChatId,sourceUrl:t.url,title:e.title},e.idempotencyKey??qu());p(n)}catch(t){d(t instanceof Error?t.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(Vu).addCommand(ju),Gu=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","human").action(async(e,t)=>{try{let n=await T("generateSpeakerNotes",e,t.teamId);t.format==="json"?p(n):t.format==="quiet"?console.log(n.status):(f(`Status: ${n.status}`),f(n.message))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Bu=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","human").action(async(e,t)=>{try{let n=await T("regeneratePresentationVideoNarration",e,t.teamId);t.format==="json"?p(n):t.format==="quiet"?console.log(n.status):(f(`Status: ${n.status}`),f(n.message))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Wu=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=j(this,t);try{p(await T("createPresentationVideo",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ku=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("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this prepare request").option("--yes","Confirm creating or reusing the presentation video project").action(async function(e,t){let n=j(this,t);if(!n.yes)return d("Pass --yes to confirm preparing a presentation video.");try{p(await y("preparePresentationVideo",{forceNew:n.forceNew,presentationId:e,teamId:n.teamId},n.idempotencyKey))}catch(r){d(r instanceof Error?r.message:"Prepare failed"),process.exit(c.GENERAL_ERROR)}}),Ju=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=j(this,t);if(n.settings||(d("Pass --settings <json-or-path> with the patch to apply."),process.exit(c.INVALID_INPUT)),!n.yes)return d("Pass --yes to confirm updating presentation video settings.");try{p(await y("updatePresentationVideoSettings",{projectId:e,settings:await fa(n.settings),teamId:n.teamId},n.idempotencyKey))}catch(r){d(r instanceof Error?r.message:"Settings update failed"),process.exit(c.GENERAL_ERROR)}}),zu=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 d("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.");p(await y("createPresentationVideo",{forceNew:t.forceNew,forceRerender:t.forceRerender,presentationId:e,projectId:t.projectId,renderEngine:t.renderEngine,settings:t.settings?await fa(t.settings):void 0,teamId:t.teamId},t.idempotencyKey))}catch(n){d(n instanceof Error?n.message:"Render failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(Ku).addCommand(ma).addCommand(sa).addCommand(ua).addCommand(la).addCommand(ca).addCommand(Ju).addCommand(Wu).addCommand(da);async function fa(e){let t=e.trim(),n=t.startsWith("{")?t:await Mu(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 Xu(e,t){return[...t,e]}var Hu=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)",Xu,[]).option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output 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 zr(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){p(n);return}f(`Speaker notes run: ${n.runId}`);let r=await bn(n.runId);await ha(r)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Yu=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","human").action(async(e,t)=>{try{let n=await Xr(e,{instructions:t.instructions,slideId:t.slideId});if(t.format==="json"||!t.follow){p(n);return}f(`Narration run: ${n.runId}`),await ha(await bn(n.runId))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});async function ha(e){let t=e.body?.getReader();if(!t)throw new Error("Speaker notes event stream is unavailable");let n=new TextDecoder,r="";for(;;){let{done:o,value:i}=await t.read();r+=n.decode(i,{stream:!o});let a=r.split(`
114
-
115
- `);r=a.pop()??"";for(let s of a){let l=s.split(`
116
- `).find(m=>m.startsWith("data:"))?.slice(5).trim();if(!l)continue;let g=JSON.parse(l);g.eventType?.startsWith("slide.")&&f(`${g.eventType}${g.payload?.slideId?` \xB7 ${g.payload.slideId}`:""}`)}if(o)return}}var or=new H("presentation").description("Create an MP4 video from a finished presentation, plus speaker notes, PowerPoint import, and run status").addCommand(Fu).addCommand(ga).addCommand(Hu).addCommand(Gu).addCommand(zu).addCommand(Yu).addCommand(Bu);or.addHelpText("after",`
117
- ${Te.bold("Deck to MP4:")}
118
- $ ${u.commands[0]} presentation video prepare <slug> ${Te.gray("# create/reuse the video project")}
119
- $ ${u.commands[0]} presentation video inspect <project-id> ${Te.gray("# review the scene timeline")}
120
- $ ${u.commands[0]} presentation video <slug> --yes ${Te.gray("# start the MP4 render")}
121
- $ ${u.commands[0]} presentation video status <run-id> ${Te.gray("# follow the render")}
122
-
123
- ${Te.bold("See also:")}
124
- ${Te.gray("# Building a video from scratch instead of from a deck")}
125
- $ ${u.commands[0]} video --help
126
- `);import{writeFile as Qu}from"fs/promises";import lt from"chalk";import{Command as Zu}from"commander";import em from"ora";var ir=new Zu("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","human").action(async(e,t)=>{let n=t.format,r=n==="human"?em("Scraping URL...").start():null;try{let o=await go(e,t.teamId);r?.stop(),(!o.success||!o.data)&&(d(o.error||"Failed to scrape URL"),process.exit(c.GENERAL_ERROR));let i=o.data;if(t.output&&(await Qu(t.output,i.content,"utf-8"),n==="human"&&C(`Content saved to: ${t.output}`)),n==="json"){let{cost:a,...s}=i;p(s);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&&f(`Cost: $${i.cost.toFixed(6)}`)}catch(o){r?.stop(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});ir.addHelpText("after",`
127
- ${lt.bold("Examples:")}
128
- ${lt.gray("# Pull the readable content of a web page")}
129
- $ ${u.commands[0]} scrape https://example.com/post
130
-
131
- ${lt.bold("See also:")}
132
- ${lt.gray("# Local files and documents, not just URLs")}
133
- $ ${u.commands[0]} content extract ./paper.pdf
134
-
135
- ${lt.gray("# Spoken words out of audio or video")}
136
- $ ${u.commands[0]} transcript --help
137
- `);import ar from"chalk";import{Command as ut}from"commander";function Kt(e,t){t!=="quiet"&&p(e)}var tm=new ut("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","human").action(async(e,t)=>{try{let n=await y("searchInternet",{maxResults:Number.parseInt(t.maxResults,10),query:e,teamId:t.teamId});Kt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Search failed"),process.exit(c.GENERAL_ERROR)}}),nm=new ut("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","human").action(async(e,t)=>{try{let n=await y("getNews",{maxResults:Number.parseInt(t.maxResults,10),teamId:t.teamId,timeframe:t.timeframe,topic:e});Kt(n,t.format)}catch(n){d(n instanceof Error?n.message:"News search failed"),process.exit(c.GENERAL_ERROR)}});function ya(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var rm=new ut("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","human").action(async(e,t)=>{try{let n=await y("searchImages",{aspect:t.aspect,maxResults:Number.parseInt(t.maxResults,10),query:e,sources:ya(t.source),teamId:t.teamId});Kt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Image search failed"),process.exit(c.GENERAL_ERROR)}}),om=new ut("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","human").action(async(e,t)=>{try{let n=await y("searchStockVideo",{license:t.license,maxResults:Number.parseInt(t.maxResults,10),orientation:t.orientation,query:e,sources:ya(t.source),teamId:t.teamId});Kt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Video search failed"),process.exit(c.GENERAL_ERROR)}}),sr=new ut("search").description("Web, news, image, and stock-video search").addCommand(tm).addCommand(nm).addCommand(rm).addCommand(om);sr.addHelpText("after",`
138
- ${ar.bold("Examples:")}
139
- $ ${u.commands[0]} search web "state of AI video 2026"
140
- $ ${u.commands[0]} search news "vaccine approvals"
141
-
142
- ${ar.bold("See also:")}
143
- ${ar.gray("# `search images` and `search video` overlap with these")}
144
- $ ${u.commands[0]} image search --help
145
- $ ${u.commands[0]} video find --help
146
- `);import{Command as cr}from"commander";import im from"ora";function dr(e,t){if(t==="json"){let{cost:n,...r}=e;p(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId??e.id);return}f(`Request ID: ${e.requestId||e.id}`),f(`Status: ${e.status}`),e.duration&&f(`Duration: ${e.duration}s`),e.audioUrl&&C(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&f(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var am=new cr("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","human").action(async e=>{!e.wait&&e.output&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=ta(e.request)}catch(i){d(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?im("Generating sound effect for video...").start():null,o;try{let i=await fo(t);if(o=i.requestId||i.id,!e.wait){r?.stop(),dr(i,n);return}let a=i.requestId||i.id;r&&(r.text=`Processing (ID: ${a})...`);let s=i.status==="completed"||i.status==="failed"?i:await Q(()=>kn(a),60,2e3);if(r?.stop(),s.status==="failed"&&(d(s.error||"Sound effects generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!s.audioUrl)throw new Error("Sound effect completed without an audio URL");await z(s.audioUrl,e.output),n==="human"&&C(`Saved to: ${e.output}`)}dr(s,n)}catch(i){r?.stop(),d(re(i,o),n),process.exit(c.GENERAL_ERROR)}}),sm=new cr("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(e,t)=>{try{dr(await kn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ba=new cr("sfx").description("Video-aware sound effects generation commands").addCommand(am).addCommand(sm);import{writeFile as dm}from"fs/promises";import{Command as cm}from"commander";import lm from"ora";var wa=new cm("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","human").action(async(e,t)=>{let n=t.format,r=n==="human"?lm("Fetching transcript...").start():null;try{let o=await po(e,t.teamId,t.language);r?.stop();let i=t.timestamps?o.cues.map(a=>`[${a.timestamp}] ${a.text}`).join(`
147
- `):o.cues.map(a=>a.text).join(`
148
- `);if(t.output&&(await dm(t.output,i,"utf-8"),n==="human"&&C(`Transcript saved to: ${t.output}`)),n==="json"){p(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&&f(`Cost: $${o.totalCost.toFixed(6)}`)}catch(o){r?.stop(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdir as um,writeFile as va}from"fs/promises";import{dirname as mm}from"path";import{Command as Jt}from"commander";import Ca from"ora";var xa="en-US-Neural2-C",ka="gemini",pm=new Jt("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: ${xa})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${ka})`).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","human").action(async e=>{let t=e.format,n=t==="human"?Ca("Generating speech...").start():null,r;e.speed&&(r=parseFloat(e.speed),(Number.isNaN(r)||r<.1||r>4)&&(n?.stop(),d("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(),d("Speakers must be an array with 1-2 name/voice items"),process.exit(c.INVALID_INPUT))}catch{n?.stop(),d(`Invalid --speakers JSON. Example: '[{"name":"Joe","voice":"Kore"}]'`),process.exit(c.INVALID_INPUT)}let i;try{let a=e.voiceId,s=e.voice||xa,l=e.provider||ka,g={};o&&(g.gemini={speakers:o}),e.instructions&&(g.openai={instructions:e.instructions});let m=await io({text:e.text,options:{language:e.lang,provider:l,voiceId:a,voice:s,model:e.model,speed:r,providerOptions:Object.keys(g).length>0?g:void 0}});i=m.requestId,n?.stop();let w=e.output.endsWith(`.${m.format}`)?e.output:`${e.output}.${m.format}`;await um(mm(w),{recursive:!0}),await va(w,m.audioData);let v=w.replace(/\.[^.]+$/,".txt");if(await va(v,e.text,"utf-8"),t==="json"){p({status:"completed",output:w,audioUrl:m.audioUrl,duration:m.duration,provider:m.provider,format:m.format,voice_id:m.voiceId??null,voice:m.voice??s,model:m.model??e.model??null,speed:m.speed??r??1,lang:m.language??e.lang??null,langApplied:m.langApplied??!1,timestamps:m.timestamps??null,words:m.wordTimings??null});return}if(t==="quiet"){console.log(w);return}C(`Saved to: ${w}`),f(`Duration: ${m.duration.toFixed(2)}s`),f(`Provider: ${m.provider}`),f(`Cost: $${m.cost.toFixed(6)}`)}catch(a){n?.stop(),d(re(a,i),t),process.exit(c.GENERAL_ERROR)}}),gm=new Jt("voices").description("List available voices").option("-p, --provider <provider>","Filter by provider: gemini, elevenlabs, openai").option("-f, --format <format>","Output format: human, json","human").action(async e=>{let t=e.format==="human"?Ca("Fetching voices...").start():null;try{let n=await so(e.provider);if(t?.stop(),e.format==="json"){p(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(),d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),fm=new Jt("status").description("Read speech generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-f, --format <format>","Output format: json","json").action(async(e,t)=>{try{p(await T("generateSpeech",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ia=new Jt("tts").description("Text-to-speech commands").addCommand(pm).addCommand(gm).addCommand(fm);import{execSync as Yt,spawnSync as Vm}from"child_process";import{access as ur,readFile as jm,rm as Ua}from"fs/promises";import{resolve as gt}from"path";import pt from"chalk";import{Command as Y}from"commander";import Gm from"ffmpeg-static";import qa from"ora";import{Command as hm}from"commander";import ym from"ora";import{execSync as bm,spawnSync as Fe}from"child_process";import{mkdirSync as Ra,existsSync as Xt,readFileSync as $a,writeFileSync as Sa}from"fs";import{join as Ee,basename as wm}from"path";import{tmpdir as vm}from"os";function Ht(e,t){try{return bm(t,{stdio:"ignore"}),!0}catch{return!1}}function zt(e){let t=Math.floor(e/60),n=Math.floor(e%60),r=Math.round(e%1*10);return`${t}:${String(n).padStart(2,"0")}.${r}`}function xm(e){let t=Fe("ffprobe",["-v","error","-show_entries","format=duration","-of","default=noprint_wrappers=1:nokey=1",e],{encoding:"utf-8"});return parseFloat(t.stdout.trim())}function km(e,t){let n=Fe("ffmpeg",["-i",e,"-vf",`select='gt(scene,${t})',showinfo`,"-vsync","vfr","-f","null","-"],{encoding:"utf-8",timeout:12e4}),r=[0],o=(n.stderr||"").split(`
149
- `);for(let i of o){let a=i.match(/pts_time:([\d.]+)/);if(a){let s=parseFloat(a[1]);s-r[r.length-1]>=1.5&&r.push(s)}}return r}function Cm(e,t,n){let r=[];for(let o=0;o<t.length;o++){let i=t[o]+.5,a=Ee(n,`scene_${String(o+1).padStart(2,"0")}.jpg`);Fe("ffmpeg",["-ss",String(i),"-i",e,"-vframes","1","-q:v","2","-y",a],{stdio:"ignore",timeout:3e4}),r.push(a)}return r}function Im(e,t){let n=Ee(t,"audio.wav");if(Fe("ffmpeg",["-i",e,"-vn","-acodec","pcm_s16le","-ar","16000","-ac","1","-y",n],{stdio:"ignore",timeout:6e4}),!Xt(n)||!Ht("whisper","which whisper")&&!Ht("whisper-cpp","which whisper-cpp"))return null;let o=Fe("whisper",[n,"--model","base","--output_format","json","--output_dir",t,"--language","en"],{encoding:"utf-8",timeout:3e5}),i=Ee(t,"audio.json");if(!Xt(i))return null;try{let a=JSON.parse($a(i,"utf-8"));return{text:a.text||"",segments:(a.segments||[]).map(s=>({start:s.start,end:s.end,text:s.text?.trim()||""}))}}catch{return null}}function Rm(e,t){let n=$a(e).toString("base64"),r=JSON.stringify({model:t,prompt:"Describe this image in one short sentence (max 15 words). Focus on: what is shown, the setting, key objects or people.",images:[n],stream:!1}),o=Fe("curl",["-s","-X","POST","http://localhost:11434/api/generate","-H","Content-Type: application/json","-d",r],{encoding:"utf-8",timeout:6e4});try{return(JSON.parse(o.stdout).response||"").replace(/!!!IMAGE!!!/gi,"").replace(/\[image[^\]]*\]/gi,"").trim()||"Unable to describe frame"}catch{return"Unable to describe frame"}}var Ta=new hm("analyze").description("Analyze a video file: detect scenes, transcribe audio, describe frames").argument("<file>","Path to video file").option("-o, --output <path>","Output directory for analysis results").option("-t, --threshold <number>","Scene detection threshold (0-1, lower = more scenes)","0.3").option("-m, --model <name>","Ollama vision model","moondream").option("--no-vision","Skip frame description (faster)").option("--no-transcribe","Skip audio transcription").option("-f, --output-format <format>","Output format: human, json","human").action(async(e,t)=>{let n=ym();Xt(e)||(console.error(`File not found: ${e}`),process.exit(1)),Ht("ffmpeg","which ffmpeg")||(console.error("ffmpeg is required. Install: brew install ffmpeg"),process.exit(1)),t.vision!==!1&&!Ht("ollama","which ollama")&&(console.error("ollama is required for vision. Install: brew install ollama"),process.exit(1));let r=t.output||Ee(vm(),`video-analyze-${Date.now()}`);Ra(r,{recursive:!0});let o=Ee(r,"frames");Ra(o,{recursive:!0});let i=parseFloat(t.threshold),a=t.model;n.start("Reading video metadata...");let s=xm(e);n.succeed(`Video: ${zt(s)} (${s.toFixed(1)}s)`),n.start("Detecting scenes...");let l=km(e,i);n.succeed(`Detected ${l.length} scenes`),n.start("Extracting key frames...");let g=Cm(e,l,o);n.succeed(`Extracted ${g.length} key frames`);let m=null;t.transcribe!==!1&&(n.start("Transcribing audio..."),m=Im(e,r),m?n.succeed(`Transcribed: ${m.segments.length} segments`):n.warn("Transcription skipped (whisper not installed: pip install openai-whisper)"));let w=[];for(let b=0;b<l.length;b++){let $=l[b],x=b<l.length-1?l[b+1]:s,k="";t.vision!==!1&&Xt(g[b])&&(n.start(`Describing scene ${b+1}/${l.length}...`),k=Rm(g[b],a),n.succeed(`Scene ${b+1}: ${k}`)),w.push({id:b+1,startTime:$,endTime:x,duration:x-$,framePath:g[b],description:k})}let v={source:e,duration:s,scenes:w,transcript:m};if(t.outputFormat==="json"){let b=JSON.stringify(v,null,2),$=Ee(r,"analysis.json");Sa($,b),console.log(b)}else{let b=["# Video Analysis","",`**Source:** ${wm(e)}`,`**Duration:** ${zt(s)} (${s.toFixed(1)}s)`,`**Scenes:** ${w.length}`,"","## Scenes",""];for(let k of w){if(b.push(`### Scene ${k.id} (${zt(k.startTime)} - ${zt(k.endTime)}) [${k.duration.toFixed(1)}s]`),k.description&&b.push(`**Visual:** ${k.description}`),m?.segments){let R=m.segments.filter(D=>D.end>k.startTime&&D.start<k.endTime);R.length>0&&b.push(`**Audio:** ${R.map(D=>D.text).join(" ").trim()}`)}b.push(`**Frame:** ${k.framePath}`),b.push("")}m?.text&&(b.push("## Full Transcript"),b.push(""),b.push(m.text.trim()),b.push(""));let $=b.join(`
150
- `),x=Ee(r,"analysis.md");Sa(x,$),console.log($),console.log(`
151
- Results saved to: ${r}`)}});import{mkdir as Sm}from"fs/promises";import{join as $m}from"path";import{Command as mt}from"commander";import Aa from"ora";var Tm=5e3,Em=120,Ea=5;function Am(e,t){return[...t,e]}function Om(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 Oa(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 Pm(e){if(e.mode&&!["speed","precision"].includes(e.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:Om(e.audioUrl,"Audio URL"),...e.mode?{mode:e.mode}:{},sourceVideoId:Oa(e.sourceVideoId)}}function _m(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>Ea)throw new Error(`Provide at most ${Ea} 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:Oa(e.sourceVideoId),targetLanguages:t}}function Lm(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 lr(e){return{requestId:e.runId,status:Lm(e),...e.entity?.url?{videoUrl:e.entity.url}:{},...e.output?{output:e.output}:{},...e.error?.message?{error:e.error.message}:{}}}function Pa(e){return{requestId:e.runId,status:"pending"}}async function _a(e,t){return Q(async()=>lr(await T(e,t)),Em,Tm)}function Ve(e,t){if(t==="json"){p(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}f(`Request ID: ${e.requestId}`),f(`Status: ${e.status}`),e.videoUrl&&C(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}function Dm(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 Nm(e){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function Um(e,t){let n=Nm(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 qm(e,t){let n=Dm(e.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await Sm(t,{recursive:!0});let r=[],o=new Set;for(let i of n){let a=$m(t,Um(i.language,o));await z(i.videoUrl,a),r.push({language:i.language,path:a})}return r}var Mm=new mt("status").description("Check a video lip-sync request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet").action(async function(e,t){let r=j(this,t).format??"human";try{Ve(lr(await T("lipsyncVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),La=new mt("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","human").action(async e=>{let t=e.format==="human"?Aa("Starting video lip-sync...").start():null,n;try{let r=await bo(Pm(e));if(n=r.runId,!e.wait){t?.stop(),Ve(Pa(r),e.format);return}t&&(t.text="Waiting for video lip-sync...");let o=await _a("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 z(o.videoUrl,e.output),t?.stop(),Ve(o,e.format),e.format==="human"&&C(`Saved to: ${e.output}`)}catch(r){t?.stop(),d(re(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(Mm),Da=new mt("translate-languages").description("List supported video translation target languages").option("-f, --format <format>","Output format: human, json, quiet","human").action(async e=>{try{let t=await wo();if(e.format==="json")p({languages:t});else for(let n of t)console.log(n)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Fm=new mt("status").description("Check a video translation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet").action(async function(e,t){let r=j(this,t).format??"human";try{Ve(lr(await T("translateVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Na=new mt("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)",Am,[]).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","human").action(async e=>{let t=e.format==="human"?Aa("Starting video translation...").start():null,n;try{let r=await vo(_m(e));if(n=r.runId,!e.wait){t?.stop(),Ve(Pa(r),e.format);return}t&&(t.text="Waiting for video translations...");let o=await _a("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");t&&(t.text="Downloading translated videos...");let i=await qm(o,e.outputDir);if(t?.stop(),e.format==="json")p({...o,downloads:i});else if(e.format==="quiet")for(let a of i)console.log(a.path);else{Ve(o,e.format);for(let a of i)C(`${a.language}: ${a.path}`)}}catch(r){t?.stop(),d(re(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(Fm);async function Bm(){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 Wm(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var Km=new Y("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","human").action(async(e,t)=>{let{maxResults:n,orientation:r,license:o,format:i}=t,a=i==="human"?qa("Finding videos...").start():null;try{let s=await mo({query:e,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:Wm(t.source)}});a?.stop();let l=s.data.results.flatMap(g=>g.results);if(i==="json"){let{totalCost:g,...m}=s.data;p({...s,data:m});return}if(i==="quiet"){l.forEach(g=>{console.log(g.embedUrl||g.previewUrl||g.thumbnailUrl)});return}if(l.length===0){f("No videos found");return}C(`Found ${l.length} videos for "${e}"`),console.log(),l.forEach((g,m)=>{let w=g.kind==="embed";console.log(`[${m+1}] ${g.title}`),console.log(` ${w?"Embed":"URL"}: ${g.embedUrl||g.previewUrl||g.thumbnailUrl}`),console.log(w?` Duration: ${g.duration}s | Embed only \u2014 plays in the host player, do not download`:` Duration: ${g.duration}s | Size: ${g.width}x${g.height}`),console.log(` Provider: ${g.provider}`),console.log()}),f(`Total cost: $${s.data.totalCost.toFixed(4)}`)}catch(s){a?.stop(),d(s instanceof Error?s.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Jm=new Y("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("--draft","Generate at 480p for a faster draft").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 d("Pass --yes to approve video generation");try{p(await xo({quality:e.draft?"draft":void 0,sourceVideoId:e.sourceVideo,storyboardRevisionId:e.storyboardRevision,teamId:e.teamId},e.approvalReceipt,e.idempotencyKey))}catch(t){d(t instanceof Error?t.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}});async function Ma(e){let t=e==="-"?await Bm():await jm(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 Fa(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=ce(r.handle),i=ce(r.path),a=ce(r.fileUrl)??ce(r.url),s=ce(r.purpose),l=ce(r.videoRole),g=ce(r.analysisId)??ce(r.analysis);if(!o||!i&&!a||!s)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&&s==="source"&&g)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 m=i?await de(gt(i),{idempotencyKey:`${t.uploadIdempotencyKey}:media:${o}`}):{name:ce(r.name),size:Number(r.size),type:ce(r.mime),url:a};if(!m.name||!m.type||!m.url||!Number.isSafeInteger(m.size)||m.size<=0)throw new Error(`URL media binding "${n}" requires name, mime, and positive integer size.`);let w=m.type.startsWith("video/")?"video":m.type.startsWith("audio/")?"audio":m.type.startsWith("image/")?"image":null;if(!w)throw new Error(`Unsupported media type for ${i??a}: ${m.type}`);if(!["source","style","identity","required"].includes(s))throw new Error(`Invalid media purpose: ${s}`);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{...g?{analysisId:g}:{},fileUrl:m.url,handle:o,kind:w,mime:m.type,name:m.name,purpose:s,size:m.size,...l?{videoRole:l}:{}}}))}function ce(e){return typeof e=="string"&&e.length>0?e:void 0}var zm=new Y("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{p(await y("createVideoStoryboard",{aspectRatio:e.aspect,durationSec:Number(e.duration),mediaBindings:await Fa(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardMarkdown:await Ma(e.file),teamId:e.teamId,title:e.title},e.idempotencyKey))}catch(t){d(t instanceof Error?t.message:"Storyboard creation failed"),process.exit(c.GENERAL_ERROR)}}),Xm=new Y("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{p(await y("reviseVideoStoryboard",{aspectRatio:t.aspect,baseRevisionId:t.baseRevision,changeSummary:t.changeSummary,durationSec:Number(t.duration),mediaBindings:await Fa(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardId:e,storyboardMarkdown:await Ma(t.file),teamId:t.teamId,title:t.title},t.idempotencyKey))}catch(n){d(n instanceof Error?n.message:"Storyboard revision failed"),process.exit(c.GENERAL_ERROR)}}),Hm=new Y("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 y("readVideoStoryboard",{revisionId:t.revision,storyboardId:e,teamId:t.teamId});if(t.json){p(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){d(n instanceof Error?n.message:"Storyboard read failed"),process.exit(c.GENERAL_ERROR)}}),Ym=new Y("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(zm).addCommand(Xm).addCommand(Hm),Qm=new Y("analyze").description("Upload and analyze a reference video").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 de(gt(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 ko({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){p({...n,binding:r,source:t});return}let o=await Co(n.runId,e.teamId);if(e.json){p({...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){d(t instanceof Error?t.message:"Reference analysis failed"),process.exit(c.GENERAL_ERROR)}}),Zm=new Y("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{p(await T("analyzeVideoReference",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status read failed"),process.exit(c.GENERAL_ERROR)}}),ep=new Y("reference").description("Upload and inspect reusable video references").addCommand(Qm).addCommand(Zm),tp=new Y("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{p(await T("createVideo",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),np=new Y("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","human").action(async e=>{let t=e.format,n=t==="human"?qa("Injecting thumbnail...").start():null;try{let r=gt(e.video),o=gt(e.thumbnail),i=e.output?gt(e.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await ur(r),await ur(o);let a=Gm;if(a)try{await ur(a)}catch{a=null}if(!a)try{a=Yt("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let s=Vm(a,["-i",r],{encoding:"utf8"});if(s.error)throw new Error(`Failed to probe video: ${s.error.message}`);let l=(s.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!l)throw new Error("Could not detect video dimensions");let[,g,m]=l;n&&(n.text="Creating thumbnail frame...");let w="/tmp/cc-thumb-frame.mp4";Yt(`${a} -y -loop 1 -i "${o}" -vf "scale=${g}:${m}:force_original_aspect_ratio=decrease,pad=${g}:${m}:(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(Yt(`${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..."),Yt(`${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 Ua(w,{force:!0}),await Ua(v,{force:!0}),n?.stop(),t==="json"){p({success:!0,output:i});return}if(t==="quiet"){console.log(i);return}C(`Thumbnail injected: ${i}`)}catch(r){n?.stop(),d(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),rp=new Y("thumbnail").description("Thumbnail operations").addCommand(np),Qt=new Y("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(Km).addCommand(rp).addCommand(La).addCommand(Da).addCommand(Na).addCommand(pa).addCommand(Ta);Qt.addCommand(Jm).addCommand(Ym).addCommand(ep).addCommand(tp);Qt.addHelpText("after",`
51
+ ${n.text}`}function _n(e,t){return t?e.messages.filter(r=>r.text.trim()).at(-1)?.text??"":Pn(e.messages)}function gc({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:qt()},includePartialMessages:!0,maxTurns:16,permissionMode:"dontAsk"};return pc.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 fi(e){let t=_n(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,s=null,l=null,f=0,p=new Set;try{let w=mc({prompt:t,options:gc({abortController:n,input:e.input,resumeSessionId:e.resumeSessionId,workspace:e.workspace})});for await(let T of w){let k=T;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:pi(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 C=k.event;if(C?.type!=="content_block_delta")continue;let S=C.delta;if(!S)continue;S.type==="text_delta"&&typeof S.text=="string"?(f+=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 C=ne(k.message),S=Array.isArray(C.content)?C.content:[];for(let q of S){let A=ne(q);if(A.type!=="tool_use")continue;let U=D(A.id),R=D(A.name);!U||!R||p.has(U)||(p.add(U),e.onEvent({eventType:"chat.tool.started",payload:{input:te(A.input),toolCallId:U,toolName:R}}))}continue}if(k.type==="user"){let C=ne(k.message),S=Array.isArray(C.content)?C.content:[];for(let q of S){let A=ne(q);if(A.type!=="tool_result")continue;let U=D(A.tool_use_id);U&&e.onEvent({eventType:"chat.tool.completed",payload:{...A.is_error===!0?{errorText:typeof A.content=="string"?Nt(A.content):"Claude tool call failed."}:{},output:te(A.content),toolCallId:U}})}continue}k.type==="result"&&(typeof k.result=="string"&&(s=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 v=s??"";f===0&&v&&e.onEvent({eventType:"chat.text.delta",payload:{text:v}});let x=i?pi(e.workspace,i):null;return{modelId:o,sessionId:i,sessionPath:x&&cc(x)?x:null,text:v,usage:a}}import{spawn as fc}from"child_process";import{closeSync as hc,fstatSync as yc,openSync as bc,readdirSync as wc,readSync as vc}from"fs";import{homedir as xc}from"os";import{join as hi}from"path";import{Codex as kc}from"@openai/codex-sdk";var Cc=["/Applications/Codex.app/Contents/Resources/codex"];async function jt(e){let t=e?[e]:["codex",...Cc];for(let n of t){let r=await Ic(n);if(r)return{bin:n,version:r}}return null}function Ic(e){return new Promise(t=>{let n=fc(e,["--version"],{env:{...process.env,PATH:qt()},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 Rc=24,Sc=4*1024*1024,wi=new Set(["custom_tool_call","custom_tool_call_output","dynamic_tool_call","function_call"]);function $c(e){let t;try{t=Tc(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 s=ne(a.payload);if(a.type==="response_item"&&s.type==="custom_tool_call"){let l=D(s.call_id),f=D(s.input);l&&s.name==="exec"&&/\btools\.web__run\s*\(/.test(f)&&(n.add(l),o=l);continue}if(a.type==="event_msg"&&s.type==="web_search_end"){let l=D(s.call_id);if(!l||!o)continue;let f=D(s.query),p=ne(s.action),x={action:{...p,...f&&!D(p.query)?{query:f}:{}},query:f,sources:yi(s.results),toolCallId:l},w=r.get(o)??[];w.push(x),r.set(o,w);continue}if(a.type==="response_item"&&s.type==="custom_tool_call_output"){let l=D(s.call_id);if(!l||!n.has(l))continue;let f=yi(s.output);for(let p of r.get(l)??[])p.sources.length===0&&(p.sources=f);o===l&&(o=null)}}return Array.from(r.values()).flat()}function Tc(e){let t=bc(e,"r");try{let n=yc(t).size,r=Math.max(0,n-Sc),o=Buffer.alloc(n-r);vc(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{hc(t)}}function yi(e){let n=Nn(e).match(/https?:\/\/[^\s<>"'()[\]{}\\]+/g)??[],r=new Set,o=[];for(let i of n){let a=i.replace(/[.,;:!?]+$/,"");try{let s=new URL(a);if(s.protocol!=="http:"&&s.protocol!=="https:"||r.has(s.href))continue;if(r.add(s.href),o.push({type:"url",url:s.href}),o.length>=Rc)break}catch{}}return o}function Nn(e){return typeof e=="string"?e:Array.isArray(e)?e.map(Nn).join(`
55
+ `):e&&typeof e=="object"?Object.values(e).map(Nn).join(`
56
+ `):""}function Ln(e,t){let n=ne(e),r=D(n.type),o=D(n.id),i=D(n.call_id)||D(n.tool_call_id),a=wi.has(r)?i||o:o||i;if(!a)return null;if(r==="command_execution"){let s=D(n.command),l=D(n.status),f={exitCode:typeof n.exit_code=="number"?n.exit_code:null,output:te(n.aggregated_output)};return{...t&&l==="failed"?{errorText:Nt(n.aggregated_output)||"Command failed."}:{},input:{command:s},...t?{output:f}:{},toolCallId:a,toolName:"Bash"}}if(r==="mcp_tool_call"){let s=ne(n.error);return{...t&&D(s.message)?{errorText:D(s.message)}:{},input:te(n.arguments),...t?{output:te(n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:D(n.tool)||D(n.name)||"Codex tool"}}if(r==="web_search"){let s=D(n.query);return{input:{query:s},...t?{output:{query:s}}:{},toolCallId:a,toolName:"web_search"}}if(r==="file_change"){let s=D(n.status);return{...t&&s==="failed"?{errorText:"Codex could not apply the file changes."}:{},input:{changes:te(n.changes)},...t?{output:{changes:te(n.changes),status:s}}:{},toolCallId:a,toolName:"ApplyPatch"}}if(r==="custom_tool_call_output")return{input:{},...t?{output:te(n.output)}:{},toolCallId:a,toolName:"Codex tool"};if(r==="custom_tool_call"||r==="dynamic_tool_call"||r==="function_call"){let s=D(n.name)||D(n.tool)||"Codex tool",l=n.input??n.arguments??{};return{input:s==="exec"&&typeof l=="string"?{command:l}:te(l),...t?{output:te(n.output??n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:s}}return null}function Dn(e,t=hi(xc(),".codex","sessions")){try{let r=wc(t,{recursive:!0}).find(o=>typeof o=="string"&&o.endsWith(`${e}.jsonl`));return r?hi(t,r):null}catch{return null}}function Ec(e,t){return t?_n(e,t):Pn(e.messages)}function Ac(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 Oc=new Set(["minimal","low","medium","high","xhigh"]);function Pc(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&&Oc.has(e.effort)&&(n.modelReasoningEffort=e.effort),n}async function vi(e){let t=Ec(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new kc(Ac(e.bin,e.input)),r=Pc(e.input,e.workspace),o=e.resumeSessionId?n.resumeThread(e.resumeSessionId,r):n.startThread(r),i=e.resumeSessionId??null,a=null,s=null,l=[],f=new Set,p=new Set,v=null,x=k=>{v??=Dn(k,e.sessionsRoot),e.onEvent({eventType:"chat.session",payload:{sessionId:k,sessionPath:v}})},w=k=>{i&&(v??=Dn(i,e.sessionsRoot));let C=v?$c(v):[],S=D(ne(k.input).query),q=bi(S),A=C.find(U=>!f.has(U.toolCallId)&&bi(U.query)===q)??C.find(U=>!f.has(U.toolCallId));A&&f.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:T}=await o.runStreamed(t);i&&x(i);for await(let k of T){if(e.signal?.aborted)throw await T.return?.(void 0),new Error("Chat turn cancelled.");let C=k;if(C.type==="thread.started"){typeof C.thread_id=="string"&&(i=C.thread_id,x(C.thread_id));continue}if(C.type==="item.started"){let S=Ln(C.item,!1);if(S){e.onEvent({eventType:"chat.tool.started",payload:S});let q=ne(C.item);if(wi.has(D(q.type))&&D(q.status)==="completed"){let A=Ln(q,!0);A&&(p.add(A.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:A}))}}continue}if(C.type==="item.completed"){let S=C.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 q=Ln(S,!0);q&&(S.type==="web_search"?w(q):S.type==="custom_tool_call"&&p.has(q.toolCallId)||e.onEvent({eventType:"chat.tool.completed",payload:q}))}continue}if(C.type==="turn.completed"){C.usage&&typeof C.usage=="object"&&(a=C.usage);continue}if(C.type==="turn.failed"){let S=C.error;s=typeof S?.message=="string"&&S.message||"Codex turn failed.",e.onEvent({eventType:"chat.error",message:s,payload:{message:s}})}}if(s)throw new Error(s);return i=o.id??i,i&&(v??=Dn(i,e.sessionsRoot)),{modelId:e.input.modelId??null,sessionId:i,sessionPath:v,text:l.join(`
57
+
58
+ `),usage:a}}function bi(e){return e.trim().replace(/\s+/g," ").toLocaleLowerCase()}import{randomUUID as qc}from"crypto";import{mkdir as Uc}from"fs/promises";import{hostname as Ft,platform as jc}from"os";import{join as Mc}from"path";var Fe=class extends Error{constructor(n,r,o=!1){super(n);this.statusCode=r;this.reRegister=o;this.name="RunnerApiError"}statusCode;reRegister};async function Ve(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}),s=await a.text(),l={};try{l=s?JSON.parse(s):{}}catch{l={error:s.slice(0,300)}}if(!a.ok)throw new Fe(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 xi(e){await Ve("/api/runner/register",{body:e,method:"POST",timeoutMs:15e3})}async function ki(e,t){return(await Ve(`/api/runner/work?runnerId=${encodeURIComponent(e)}`,{signal:t,timeoutMs:28e3})).job??null}async function Ci(e){await Ve("/api/runner/heartbeat",{body:{runnerId:e},method:"POST",timeoutMs:1e4})}async function Ii(e,t){return{cancelRequested:(await Ve(`/api/runner/jobs/${encodeURIComponent(e)}/events`,{body:{events:t},method:"POST",timeoutMs:15e3})).cancelRequested===!0}}async function qn(e,t,n){await Ve(`/api/runner/jobs/${encodeURIComponent(e)}/complete`,{body:{result:n,runnerId:t},method:"POST",timeoutMs:15e3})}async function Mt(e,t,n,r=!0){await Ve(`/api/runner/jobs/${encodeURIComponent(e)}/fail`,{body:{message:n,retryable:r,runnerId:t},method:"POST",timeoutMs:15e3})}import{mkdirSync as _c,readFileSync as Lc,writeFileSync as Ri}from"fs";import{dirname as Dc,join as Nc}from"path";function Un(e){return Nc(e,"sessions.json")}function jn(e){try{let t=Lc(Un(e),"utf8"),n=JSON.parse(t);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}return{}}function Si(e,t,n){return t?jn(e)[t]?.[n]??null:null}function $i(e,t,n,r){if(!(!t||!r))try{let o=Un(e);_c(Dc(o),{recursive:!0});let i=jn(e);i[t]={...i[t],[n]:r},Ri(o,`${JSON.stringify(i,null," ")}
59
+ `,"utf8")}catch{}}function Ti(e,t,n){if(t)try{let r=jn(e);if(!r[t])return;delete r[t][n],Ri(Un(e),`${JSON.stringify(r,null," ")}
60
+ `,"utf8")}catch{}}var Fc=300,Vc=3e4;async function Ei(e){let[t,n]=await Promise.all([Ut(e.claudeBin),jt(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=`${Ft().split(".")[0]}-${qc().slice(0,8)}`,i=()=>xi({capabilities:["chat_turn","proof"],claudeCodeVersion:t?.version??null,cliVersion:e.version,codexVersion:n?.version??null,hostname:Ft(),platform:jc(),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 ki(o,e.signal)}catch(s){if(e.signal?.aborted)break;if(s instanceof Fe&&s.reRegister){e.log("Server asked for re-registration."),await i().catch(()=>{});continue}e.log(`Work poll failed (${s instanceof Error?s.message:"unknown"}); retrying\u2026`),await Wc(e.pollBackoffMs??5e3,e.signal);continue}if(!a){if(e.once)continue;continue}if(e.log(`Claimed ${a.jobType} job ${a.runId}.`),await Gc({claude:t,codex:n,job:a,options:e,runnerId:o}),e.once)break}}async function Gc({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 s=setInterval(()=>{Ci(o).catch(()=>{})},Vc),l=[],f=!1,p=async()=>{if(f||l.length===0)return;f=!0;let w=l.splice(0,100);try{let{cancelRequested:T}=await Ii(n.runId,w);T&&i.abort()}catch(T){T instanceof Fe&&T.statusCode===409&&i.abort()}finally{f=!1}},v=setInterval(()=>{p()},Fc),x=w=>{l.push(w)};try{if(n.jobType==="runner.proof"){let w=typeof n.input.message=="string"?n.input.message:"proof";x({eventType:"proof.echo",payload:{message:w}}),await Mn(p,l),await qn(n.runId,o,{echo:w}),r.log(`Proof job ${n.runId} completed.`);return}if(n.jobType==="runner.chat_turn"){let w=n.input.runtime==="codex"?"codex":"claude-code",T=w==="codex"?t&&{detection:t,run:vi}:e&&{detection:e,run:fi};if(!T){await Mt(n.runId,o,w==="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,C=Mc(r.workspaceRoot,"chats",k??n.runId);await Uc(C,{recursive:!0});let S=Bc(n.input),q=R=>x({eventType:R.eventType,message:R.message??null,payload:R.eventType==="chat.session"?{host:Ft(),runtime:w,runtimeVersion:T.detection.version,...R.payload??{}}:R.payload??{}}),A=Si(r.workspaceRoot,k,w),U;try{U=await T.run({bin:T.detection.bin,input:S,onEvent:q,resumeSessionId:A,signal:i.signal,workspace:C})}catch(R){if(!A||i.signal.aborted)throw R;r.log(`Resume of ${w} session failed (${R instanceof Error?R.message:"unknown"}); retrying fresh.`),Ti(r.workspaceRoot,k,w),U=await T.run({bin:T.detection.bin,input:S,onEvent:q,resumeSessionId:null,signal:i.signal,workspace:C})}$i(r.workspaceRoot,k,w,U.sessionId),x({eventType:"chat.session",payload:{host:Ft(),runtime:w,runtimeVersion:T.detection.version,sessionId:U.sessionId,sessionPath:U.sessionPath}}),await Mn(p,l),await qn(n.runId,o,{modelId:U.modelId,runtime:w,runtimeVersion:T.detection.version,sessionId:U.sessionId,sessionPath:U.sessionPath,text:U.text,usage:U.usage??{}}),r.log(`Chat turn ${n.runId} (${w}) completed.`);return}await Mt(n.runId,o,`This runner does not support ${n.jobType} jobs. Update the desktop app / CLI.`,!1)}catch(w){let T=w instanceof Error?w.message:"Local runner job crashed.";r.log(`Job ${n.runId} failed: ${T}`),await Mn(p,l).catch(()=>{}),await Mt(n.runId,o,T).catch(()=>{})}finally{clearInterval(v),clearInterval(s),r.signal?.removeEventListener("abort",a)}}function Bc(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 Mn(e,t){for(;t.length>0;)await e(),t.length>0&&await new Promise(n=>setTimeout(n,25))}function Wc(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 Xc(){return Jc(Kc(),`.${m.commands[0]}-runner`,"runs")}var Vt=new zc("runner").description("Run agent work locally with your own Claude Code / Codex login (desktop lane)");Vt.command("status").description("Check local Claude Code / Codex detection and account auth").action(async()=>{let[e,t]=await Promise.all([Ut(),jt()]);if(console.log(e?se.green(`\u2713 Claude Code ${e.version}`):se.red("\u2717 Claude Code not found on PATH")),console.log(t?se.green(`\u2713 Codex ${t.version} (${t.bin})`):se.red("\u2717 Codex not found (PATH or Codex.app)")),!fe()){console.log(se.red(`\u2717 Not logged in. Run '${m.commands[0]} login' first.`)),process.exitCode=2;return}try{let n=await ye();console.log(se.green(`\u2713 Logged in as ${n.user.email}`))}catch(n){console.log(se.red(`\u2717 Auth check failed: ${n instanceof Error?n.message:"unknown"}`)),process.exitCode=2}});Vt.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(se.red(`Not authenticated. Run '${m.commands[0]} login' first.`)),process.exit(2));let t=new AbortController,n=()=>{console.log(se.gray(`
61
+ Stopping runner\u2026`)),t.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await Ei({claudeBin:e.claudeBin,codexBin:e.codexBin,log:r=>console.log(se.gray(`[runner] ${r}`)),once:e.once,signal:t.signal,version:"0.3.20",workspaceRoot:e.workspace??Xc()})}catch(r){console.error(se.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import M from"chalk";import{Command as sg}from"commander";import{Command as Fn}from"commander";function Hc(e,t){return[...t,e]}var Yc=new Fn("create").description("Start durable ad-set generation").argument("<title>","Ad-set title").requiredOption("--brief <brief>","Campaign brief").option("--hook <text>","Opening hook (repeat)",Hc,[]).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 d("Pass --yes to approve generation");try{u(await y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),Qc=new Fn("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 E("createAdSet",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ai=new Fn("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(Yc).addCommand(Qc);import{randomUUID as Zc}from"crypto";import{Command as Ge}from"commander";function Oi(e){return new Ge(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 d("Pass --yes to approve this operation");try{u(await y(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){d(r instanceof Error?r.message:"Agent operation failed"),process.exit(c.GENERAL_ERROR)}})}function Gn(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function Pi(e){return`cli:agent-memory:${e}:${Zc()}`}function el(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 Vn(e,t){return[...t,e]}var tl=new Ge("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 y("getAgentMemory",{agentId:e,teamId:t.teamId}))}catch(n){Gn(n,"Could not read the agent's memory")}}),nl=new Ge("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)",Vn,[]).option("--always <text>","Standing instruction to add (repeatable)",Vn,[]).option("--never <text>","Thing it must not do, to add (repeatable)",Vn,[]).option("--track <name=note>","Entity to track, as name=note (repeatable)",el,[]).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 y("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},Pi(n?"remove":"add")))}catch(r){Gn(r,"Could not update the agent's memory")}}),rl=new Ge("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 d("Pass --yes to erase this agent's memory");try{u(await y("forgetAgentMemory",{agentId:e,teamId:t.teamId},Pi("forget")))}catch(n){Gn(n,"Could not erase the agent's memory")}}),ol=new Ge("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(tl).addCommand(nl).addCommand(rl),_i=new Ge("agent").description("Create scheduled agents and read, edit, or erase what they remember").addCommand(Oi("create")).addCommand(Oi("recommend")).addCommand(ol);import{randomUUID as Ni}from"crypto";import{existsSync as sl}from"fs";import{resolve as dl}from"path";import mt from"chalk";import{Command as be}from"commander";import cl from"ora";import{mkdir as il,writeFile as Li}from"fs/promises";import{dirname as al}from"path";async function Y(e,t){if(await il(al(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 Li(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 Li(t,r)}var ll=15e3,ml=40,Di=3;async function qi(e,t){if(e?.length){if(e.length>Di)throw new Error(`A presenter Look accepts at most ${Di} reference images`);return Promise.all(e.map(async(n,r)=>{if(sl(n))return{url:(await me(dl(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 Bn(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&&I(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}var ul=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 Ao(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){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),pl=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&&(d("Provide exactly one avatar speech input: --audio-url or --script"),process.exit(c.INVALID_INPUT)),["1:1","9:16","16:9"].includes(e.aspect)||(d("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)&&(d("Output format must be mp4 or webm"),process.exit(c.INVALID_INPUT)),e.backgroundColor!==void 0&&!/^#[0-9a-fA-F]{6}$/.test(e.backgroundColor)&&(d("Background color must be a six-digit hex value"),process.exit(c.INVALID_INPUT)),e.backgroundColor&&e.backgroundImageUrl&&(d("Provide only one presenter background"),process.exit(c.INVALID_INPUT)),e.fit!==void 0&&!["contain","cover"].includes(e.fit)&&(d("Fit must be contain or cover"),process.exit(c.INVALID_INPUT)),e.fit&&!e.backgroundImageUrl&&(d("Fit requires --background-image-url"),process.exit(c.INVALID_INPUT)),e.transparent&&e.outputFormat==="mp4"&&(d("--transparent cannot be combined with --output-format mp4"),process.exit(c.INVALID_INPUT)),t==="webm"&&(e.backgroundColor||e.backgroundImageUrl)&&(d("Transparent WebM output cannot be combined with a background"),process.exit(c.INVALID_INPUT)),["basic","standard","premium"].includes(e.renderTier)||(d("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)&&(d("Duration must be between 1 and 300 seconds"),process.exit(c.INVALID_INPUT));let r=e.format==="human"?cl("Generating presenter clip...").start():null;try{let o=e.audioUrl?{audioUrl:e.audioUrl}:{script:e.script??"",...e.voiceId?{voiceId:e.voiceId}:{}},i=await Oo({...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(),Bn(i,e.format);return}let a=await ee(()=>En(i.requestId),ml,ll);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(),Bn(a,e.format),e.format==="human"&&I(`Saved to: ${e.output}`)}catch(o){r?.stop(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),gl=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{Bn(await En(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),fl=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??Ni(),r=await qi(t.referenceImage,n),o=await y("generatePresenterLook",{baseProfileId:e,description:t.description,id:t.lookId,prompt:t.prompt,...r?{referenceImages:r}:{},title:t.name},n);u(o)}catch(n){d(n instanceof Error?n.message:"Look generation failed"),process.exit(c.GENERAL_ERROR)}}),hl=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 E("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&&d(n.error.message)}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),yl=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??Ni(),r=await qi(t.referenceImage,n),o=await y("revisePresenterLook",{instruction:t.instruction,...r?{referenceImages:r}:{},sourceLookId:e},n);u(o)}catch(n){d(n instanceof Error?n.message:"Look revision failed"),process.exit(c.GENERAL_ERROR)}}),bl=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 E("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&&d(n.error.message)}catch(n){d(n instanceof Error?n.message:"Revision status failed"),process.exit(c.GENERAL_ERROR)}}),wl=new be("look").description("Manage looks under an existing personal presenter").addCommand(fl).addCommand(yl).addCommand(bl).addCommand(hl),Wn=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(ul).addCommand(pl).addCommand(wl).addCommand(gl);Wn.addHelpText("after",`
62
+ ${mt.bold("Examples:")}
63
+ ${mt.gray("# Discover the presenter avatars and voices you can use")}
64
+ $ ${m.commands[0]} avatar options
65
+
66
+ ${mt.bold("See also:")}
67
+ ${mt.gray("# Save a presenter + backdrop + voice combination under a name")}
68
+ $ ${m.commands[0]} cast preset --help
69
+
70
+ ${mt.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 Gi}from"fs/promises";import z from"chalk";import{Command as re}from"commander";import Ol from"ora";import{createHash as vl}from"crypto";import{existsSync as xl}from"fs";import{basename as kl}from"path";import{Command as Ui}from"commander";import Cl from"ora";var ji=new Ui("logo").description("Brand logo files").addCommand(new Ui("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)||(d(`--variant must be primary, dark, or favicon (got "${n}")`),process.exit(c.INVALID_INPUT)),xl(t.file)||(d(`File not found: ${t.file}`),process.exit(c.INVALID_INPUT));let r=Cl({text:`Uploading ${kl(t.file)}...`,stream:process.stdout}).start(),o;try{o=(await me(t.file)).url,r.succeed("Uploaded")}catch(i){r.fail("Upload failed"),d(i instanceof Error?i.message:String(i)),process.exit(c.GENERAL_ERROR)}try{u(await y("setBrandLogo",{brandId:e,fileUrl:o,teamId:t.teamId,variant:n},vl("sha256").update(`setBrandLogo:${e??"default"}:${n}:${o}`).digest("hex").slice(0,32)))}catch(i){d(i instanceof Error?i.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}));import{readFile as Il}from"fs/promises";import{randomUUID as Rl}from"crypto";import{Command as Mi}from"commander";var Sl=["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 $l(e){let t=e.split(".").filter(Boolean);for(let n=t.length;n>=2;n--){let r=t.slice(0,n).join(".");if(Sl.includes(r))return{fieldPath:t.slice(n),nodeKey:r}}return{fieldPath:t.slice(2),nodeKey:t.slice(0,2).join(".")}}function Tl(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:s,nodeKey:l}=$l(o),f=El(i);if(s.length===0){t[l]=f;continue}let p=t[l],v=p&&typeof p=="object"&&!Array.isArray(p)?p:{},x=v;for(let w of s.slice(0,-1)){let T=x[w],k=T&&typeof T=="object"&&!Array.isArray(T)?T:{};x[w]=k,x=k}x[s[s.length-1]]=f,t[l]=v}return t}function El(e){return e==="true"?!0:e==="false"?!1:/^-?\d+(?:\.\d+)?$/.test(e)?Number(e):e}function Al(e,t){return e===void 0?{assignments:[...t]}:e.includes("=")?{assignments:[e,...t]}:{assignments:[...t],brandId:e}}var Fi=new Mi("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 y("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){d(n instanceof Error?n.message:"Profile read failed"),process.exit(c.GENERAL_ERROR)}}),Vi=new Mi("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||(d("Pass --yes to confirm writing brand tokens."),process.exit(c.INVALID_INPUT));let{assignments:r,brandId:o}=Al(e,t),i;try{i=r.length>0?Tl(r):void 0}catch(s){d(s instanceof Error?s.message:"Invalid token pair"),process.exit(c.INVALID_INPUT)}let a;if(n.designMd)try{a=await Il(n.designMd,"utf8")}catch(s){d(`Could not read ${n.designMd}: ${s instanceof Error?s.message:String(s)}`),process.exit(c.INVALID_INPUT)}!i&&!a&&(d("Nothing to write. Pass token assignments (color.primary=#114b97) or --design-md <file>."),process.exit(c.INVALID_INPUT));try{u(await y("updateBrandTokens",{brandId:o,designMd:a,publish:n.publish===!1?!1:void 0,teamId:n.teamId,tokens:i},Rl()))}catch(s){d(s instanceof Error?s.message:"Write failed"),process.exit(c.GENERAL_ERROR)}});var Bi=new re("branding").description("Manage brand profiles, design tokens, logos, competitors, and social handles").addCommand(Fi).addCommand(Vi).addCommand(new re("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 Rn();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(Gr(t.brandings))}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new re("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 fo(e);if(t.output){await Gi(t.output,JSON.stringify(n,null,2)),I(`Brand profile saved to ${t.output}`);return}if(t.format==="json")console.log(JSON.stringify(n,null,2));else{if(oe("Brand Profile"),console.log(),$("ID",n.id),$("Name",n.name),$("Source URL",n.sourceUrl??z.gray("None")),$("Default",n.isDefault?z.green("Yes"):"No"),n.createdAt&&$("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){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new re("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 Rn(),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){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new re("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||(d("Pass --yes to confirm brand extraction."),process.exit(c.INVALID_INPUT));try{new URL(e.startsWith("http")?e:`https://${e}`)}catch{d("Invalid URL format"),process.exit(6)}let n=e.startsWith("http")?e:`https://${e}`,r=t.teamId??Rt(),o=Ol({text:`Extracting branding from ${n}...`,stream:process.stdout}).start();try{let i=await ho(n,r,"cli:--yes");o.succeed("Brand extraction started");let a=JSON.stringify(i,null,2);t.output?(await Gi(t.output,a),I(`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"),d(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})).addCommand(new re("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 E("extractBranding",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}})).addCommand(new re("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 re("competitor").description("Brand competitor commands").addCommand(new re("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 y("getBrandCompetitors",{brandingId:e.brandingId,teamId:e.teamId}),null,2))}catch(t){d(t instanceof Error?t.message:"Lookup failed"),process.exit(1)}})).addCommand(new re("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||(d("Pass --yes to confirm adding a competitor."),process.exit(c.INVALID_INPUT));try{u(await y("addCompetitor",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,name:e,teamId:t.teamId,website:t.website,xHandle:t.xHandle}))}catch(n){d(n instanceof Error?n.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}))).addCommand(ji).addCommand(new re("social").description("Brand social handle commands").addCommand(new re("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||(d("Pass --yes to confirm adding a social handle."),process.exit(c.INVALID_INPUT));try{u(await y("addBrandSocialHandle",{approvalReceipt:"cli:--yes",brandingId:n.brandingId,handle:t,platform:e,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Write failed"),process.exit(c.GENERAL_ERROR)}})));import ut from"chalk";import{Command as Be}from"commander";function Pl(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 Wi(e,t){return{background:Pl(t),name:e,presenterProfileId:t.presenter,...t.voiceId?{voiceId:t.voiceId}:{}}}function Gt(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.id);return}I(`${e.name} (${e.id})`),g(` Presenter: ${e.presenterProfileId}`),g(` Backdrop: ${_l(e.background)}`),e.voiceId&&g(` Voice: ${e.voiceId}`)}function _l(e){switch(e.kind){case"color":return`color ${e.hex}`;case"image":return`image ${e.url} (${e.fit})`;default:return e.kind}}function Ki(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 Ll=new Be("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 Uo({...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)Gt(n,"human")}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(c.API_ERROR)}}),Dl=Ki(new Be("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 jo({castMemberId:t.castMemberId,...Wi(e,t)});Gt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Nl=Ki(new Be("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 Mo({presetId:e,...Wi(t.name,t)});Gt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),ql=new Be("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 Fo(e);if(t.format==="human"){I(`Retired "${n.preset.name}".`);return}Gt(n.preset,t.format)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Ul=new Be("preset").description("Saved ways a cast member appears").addCommand(Ll).addCommand(Dl).addCommand(Nl).addCommand(ql),Kn=new Be("cast").description("The faces and voices your videos can use").addCommand(Ul);Kn.addHelpText("after",`
74
+ ${ut.bold("Examples:")}
75
+ ${ut.gray("# List the saved presenter/backdrop/voice combinations")}
76
+ $ ${m.commands[0]} cast preset list
77
+
78
+ ${ut.bold("See also:")}
79
+ ${ut.gray("# The presenter avatars, looks, and voices a preset is built from")}
80
+ $ ${m.commands[0]} avatar options
81
+
82
+ ${ut.gray("# Use a preset on one presentation-video scene")}
83
+ $ ${m.commands[0]} presentation video presenter <project-id>
84
+ `);import{readFile as jl}from"fs/promises";import pt from"chalk";import{Command as Ji}from"commander";var Ml=new Ji("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 jl(e,"utf8"),r=e);let o=await y("extractContent",{filename:r,maxLength:Number.parseInt(t.maxLength,10),mimeType:t.mimeType,source:n,teamId:t.teamId});t.format!=="quiet"&&u(o)}catch(n){d(n instanceof Error?n.message:"Extraction failed"),process.exit(c.GENERAL_ERROR)}}),Jn=new Ji("content").description("Extract normalized text from a URL, a local file, or an encoded document").addCommand(Ml);Jn.addHelpText("after",`
152
85
  ${pt.bold("Examples:")}
153
- ${pt.gray("# Storyboard-first video from a brief")}
154
- $ ${u.commands[0]} video storyboard create --file brief.md --duration 60 --aspect 16:9 --idempotency-key launch-1
155
-
156
- ${pt.gray("# Find licensed stock footage")}
157
- $ ${u.commands[0]} video find "city timelapse"
86
+ ${pt.gray("# Normalized text from a local document")}
87
+ $ ${m.commands[0]} content extract ./paper.pdf
158
88
 
159
89
  ${pt.bold("See also:")}
160
- ${pt.gray("# Already have a deck? Render it to MP4 (narration, avatar, captions)")}
161
- $ ${u.commands[0]} presentation video <slug>
162
- `);import{Command as mr}from"commander";var op=new mr("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 d("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;p(await y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),ip=new mr("status").description("Read visual-abstract generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{p(await T("createVisualAbstract",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Va=new mr("visual-abstract").description("Generate a one-page visual abstract graphic (raster or vector) from a dense brief").addCommand(op).addCommand(ip);var pr=[Ni,Mi,Oi,Ia,oa,Ji,Vi,Qt,ir,wa,ba,or,sr,jn,ji,Jn,aa,vi,Va,Ki,yi,Fn,Wi,Vn,qi];function ja(e){for(let t of pr)e.addCommand(t)}function Ga(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)Ga(o,r,n)}var Zt;function ap(){if(!Zt){Zt=new Map;for(let e of pr)Ga(e,"",Zt)}return Zt}function Ba(e){let t=ap().get(e);return t?[...t.arguments,...t.requiredOptions.map(n=>`${n} \u2026`)].join(" "):""}var Wa=["presentations","media","branding","knowledge","research","artifacts","agents"],gr={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"},sp="other";function dp(e){let t=e.category?.trim();return t&&t.length>0?t:sp}function Ka(e){let t=Wa.indexOf(e);return t===-1?Wa.length:t}function ft(e){let t=new Map;for(let n of e){let r=dp(n),o=t.get(r);o?o.push(n):t.set(r,[n])}return[...t.entries()].sort(([n],[r])=>Ka(n)-Ka(r)||n.localeCompare(r)).map(([n,r])=>({capabilities:[...r].sort((o,i)=>o.name.localeCompare(i.name)),category:n}))}function fr(e){return e.lifecycle?.mode==="background"}function hr(e,t){let n=e.lifecycle?.status?.cliCommand?.trim();if(!(!fr(e)||!n))return`${t} ${n} <run-id>`}function cp(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 en(e){return e.replace(/\|/g,"\\|").replace(/\r?\n/g," ").trim()}function lp(e,t){let n=hr(e,t);return n?`run id \u2014 poll \`${n}\``:`immediate (${e.operation??"call"})`}function je(e,t){let n=["| Command | What it does | Takes | Returns | Cost | Scopes |","|---|---|---|---|---|---|"],r=e.map(o=>{let i=Ba(o.name),a=o.scopes?.length?o.scopes.map(s=>`\`${s}\``).join(", "):"\u2014";return`| \`${t} ${en(o.name)}\` | ${en(o.description??"")} | ${i?`\`${en(i)}\``:"\u2014"} | ${lp(o,t)} | ${cp(o)} | ${a} |`});return[...n,...r].join(`
163
- `)}function le(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: ${en(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 Ja(e){return e.map(t=>`- [${t}](#${t.toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/ /g,"-")})`).join(`
164
- `)}var up=["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 mp(e){let t=new Map(e.map(n=>[n.name,n]));return up.map(n=>t.get(n)).filter(n=>n!==void 0)}function tn(e,t){let{cmd:n}=e,r=mp(t.capabilities),o=t.capabilities.find(a=>a.name==="presentation video"),i=o?hr(o,n)??`${n} presentation video status <run-id>`:`${n} presentation video status <run-id>`;return`${le(t,e)}
90
+ ${pt.gray("# Web pages, with page metadata and cost reporting")}
91
+ $ ${m.commands[0]} scrape https://example.com/post
92
+
93
+ ${pt.gray("# Spoken words out of audio or video")}
94
+ $ ${m.commands[0]} transcript --help
95
+ `);import X from"chalk";import{Command as Fl}from"commander";import{existsSync as Vl,readFileSync as Gl}from"fs";import Bl,{resolve as zi}from"path";var Xi=new Fl("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)&&(d("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)&&(d(`Invalid mode: ${t.mode}. Valid: ${r.join(", ")}`),process.exit(6));let o=["smart","fast","balanced","best"];t.imageTier&&!o.includes(t.imageTier)&&(d(`Invalid image tier: ${t.imageTier}. Valid: ${o.join(", ")}`),process.exit(6));let i=["creative","professional","educational","formal","casual"];t.tone&&!i.includes(t.tone)&&(d(`Invalid tone: ${t.tone}. Valid: ${i.join(", ")}`),process.exit(6));let a=["minimal","concise","detailed","extensive"];t.amount&&!a.includes(t.amount)&&(d(`Invalid amount: ${t.amount}. Valid: ${a.join(", ")}`),process.exit(6));let s=["freeform","brand-only","brand-plus-style","style-only","no-styling"];t.styling&&!s.includes(t.styling)&&(d(`Invalid styling: ${t.styling}. Valid: ${s.join(", ")}`),process.exit(6));let l=["quick","moderate","deep","profound"];t.thinkingDepth&&!l.includes(t.thinkingDepth)&&(d(`Invalid thinking-depth: ${t.thinkingDepth}. Valid: ${l.join(", ")}`),process.exit(6));let f=["inform","persuade","train","learn","entertain","report"];t.goal&&!f.includes(t.goal)&&(d(`Invalid goal: ${t.goal}. Valid: ${f.join(", ")}`),process.exit(6));let p=["blue","violet","rose","orange","green"];t.theme&&!p.includes(t.theme)&&(d(`Invalid theme: ${t.theme}. Valid: ${p.join(", ")}`),process.exit(6));let v=["none","waves-bottom-left","waves-top-right","blob-corners","minimal"];t.decorations&&!v.includes(t.decorations)&&(d(`Invalid decorations: ${t.decorations}. Valid: ${v.join(", ")}`),process.exit(6));let x=t.theme||t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor||t.decorations;x&&t.mode&&t.mode!=="instant"&&(d("--theme, --primary-color, --decorations and other color options are only supported with --mode instant"),process.exit(6));let w=t.mode??(x?"instant":"fast"),T=/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;for(let[R,J]of[["primary-color",t.primaryColor],["secondary-color",t.secondaryColor],["accent-color",t.accentColor],["background-color",t.backgroundColor],["foreground-color",t.foregroundColor]])J&&!T.test(J)&&(d(`Invalid ${R}: ${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 R=await wo(w,n??10,t.teamId);if(t.output!=="json"&&t.output!=="quiet"){console.log(X.green("\u2713"));let J=R.remaining[w],Q=R.limits[w],Se=J===void 0||Q===void 0?"":` | ${w}: ${J}/${Q} remaining`;console.log(X.gray(` Plan: ${R.planName}${Se}`))}}catch(R){t.output==="json"?console.log(JSON.stringify({success:!1,error:R instanceof Error?R.message:String(R)})):(console.log(X.red("\u2717")),d(R instanceof Error?R.message:String(R))),process.exit(R.exitCode??1)}let k=[];if(t.file&&t.file.length>0){for(let R of t.file)Vl(zi(R))||(d(`File not found: ${R}`),process.exit(6));t.output!=="json"&&t.output!=="quiet"&&console.log(X.gray(`
96
+ Uploading ${t.file.length} file(s)...`));try{k=await oo(t.file.map(R=>zi(R)),(R,J,Q)=>{t.output!=="json"&&t.output!=="quiet"&&Q&&process.stdout.write(`\r ${X.cyan("\u2B06")} Uploading: ${Q} (${R+1}/${J})`)}),t.output!=="json"&&t.output!=="quiet"&&console.log(`\r ${X.green("\u2713")} Uploaded ${k.length} file(s) `)}catch(R){d(`Failed to upload files: ${R instanceof Error?R.message:String(R)}`),process.exit(1)}}let C;(t.stdin||!process.stdin.isTTY)&&(C=await Wl(),t.stdin&&!C&&(d("No content received from stdin"),process.exit(6)));let S=t.context;if(t.contextFile)try{S=Gl(t.contextFile,"utf-8"),S.trim()||(d(`Context file is empty: ${t.contextFile}`),process.exit(6))}catch{d(`Failed to read context file: ${t.contextFile}`),process.exit(6)}!C&&!S&&k.length===0&&(d("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 q=[...k];C&&q.push({id:`stdin-${Date.now()}`,content:C,title:"Piped Content",mime:"text/plain",selected:!0}),S&&q.push({id:`context-${Date.now()}`,content:S,title:"Context",mime:"text/plain",selected:!0});let A,U=t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor;(t.theme||U||t.decorations)&&(A={},t.theme&&(A.preset=t.theme),U&&(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 R=await io({topic:e,...n!==void 0&&{slideCount:n},mode:w,...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:Bl.basename(process.cwd())}:t.id?{documentId:t.id}:{},...q.length>0&&{contentSources:{uploadedFiles:q,contextFiles:[]}}});if(!t.wait){t.output==="json"?console.log(JSON.stringify({success:!0,run:R},null,2)):t.output!=="quiet"&&(I("Presentation generation queued"),$("Run ID",R.runId),$("Status",R.status),console.log(X.gray(` Check later with presentation status ${R.runId}`)));return}let J=await E("createSlides",R.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 E("createSlides",R.runId,t.teamId);if(J.error)throw new Error(ae(J.error));let Q=J.entity?await je(J.entity.id):void 0;if(t.output==="json")console.log(JSON.stringify({success:!0,presentation:Q,run:J,viewUrl:Q?Ue(Q.slug,t.language??"en"):void 0},null,2));else{console.log(),I("Presentation created successfully"),console.log(),$("Title",Q?.title??e),$("Slides",String(Q?.numberOfSlides??n??"\u2014")),console.log();let Se=Q?Ue(Q.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(R){t.output==="json"?console.log(JSON.stringify({success:!1,error:R instanceof Error?R.message:String(R)})):d(R instanceof Error?R.message:String(R)),process.exit(R.exitCode??1)}});async function Wl(){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 Kl}from"crypto";import{readFile as Jl}from"fs/promises";import{Command as xe}from"commander";var zn=["text/markdown","text/csv","text/plain"];async function Hi(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 zl();d("No document body. Pass --content <text>, --content @<path>, or pipe it on stdin."),process.exit(c.GENERAL_ERROR)}async function zl(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}function Bt(e){return`cli:document:${e}:${Kl()}`}function Oe(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function Xl(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 Hl=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 ${zn.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??Xl(t.content?.startsWith("@")?t.content.slice(1):void 0);n||(d(`Cannot tell what this document is. Pass --media-type (${zn.join(", ")}).`),process.exit(c.GENERAL_ERROR)),u(await y("createDocument",{content:await Hi(t),mediaType:n,summary:t.summary,teamId:t.teamId,title:e},Bt("create")))}catch(n){Oe(n,"Could not save the document")}}),Yl=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 ${zn.join(", ")}`).option("--limit <n>","Maximum documents to return (default 50)").action(async e=>{try{u(await y("listDocuments",{limit:e.limit?Number(e.limit):void 0,mediaType:e.mediaType,teamId:e.teamId}))}catch(t){Oe(t,"Could not list documents")}}),Ql=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 y("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")}}),Zl=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 y("updateDocument",{changeSummary:t.changeSummary,content:n?await Hi(t):void 0,documentId:e,expectedVersion:Number(t.expectedVersion),summary:t.summary,teamId:t.teamId,title:t.title},Bt("update")))}catch(n){Oe(n,"Could not update the document")}}),em=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&&(d("Refusing to delete without confirmation. Re-run with --yes to remove this document."),process.exit(c.GENERAL_ERROR)),u(await y("deleteDocument",{documentId:e,teamId:t.teamId},Bt("delete")))}catch(n){Oe(n,"Could not delete the document")}}),tm=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 y("listDocumentVersions",{documentId:e,teamId:t.teamId}))}catch(n){Oe(n,"Could not list versions")}}),nm=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 y("restoreDocumentVersion",{documentId:e,expectedVersion:Number(t.expectedVersion),teamId:t.teamId,versionNumber:Number(t.versionNumber)},Bt("restore")))}catch(n){Oe(n,"Could not restore the version")}}),Yi=new xe("document").description("Create, read and edit Library documents").addCommand(Hl).addCommand(Yl).addCommand(Ql).addCommand(Zl).addCommand(em).addCommand(tm).addCommand(nm);import gt from"chalk";import{Command as rm}from"commander";import{writeFile as om}from"fs/promises";import{resolve as Qi}from"path";import im from"ora";var am=["html","pdf","pptx"],Xn=new rm("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",am),"html").action(async(e,t)=>{await O();let n=im("Exporting presentation...").start();try{let r=await mo(e,t.format),o=t.output?Qi(t.output):Qi(process.cwd(),r.fileName);n.text="Downloading...";let i=await uo(r.downloadUrl);await om(o,Buffer.from(i)),n.succeed("Export complete!"),console.log(),g(`File saved: ${o}`),g(`Format: ${r.format}`),g(`Slides: ${r.slideCount}`),g(`Size: ${sm(i.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),d(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function sm(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}Xn.addHelpText("after",`
98
+ ${gt.bold("Examples:")}
99
+ ${gt.gray("# Self-contained interactive HTML (default)")}
100
+ $ ${m.commands[0]} export <id-or-slug> -o deck.html
101
+
102
+ ${gt.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
+ ${gt.bold("See also:")}
107
+ ${gt.gray("# For an MP4 instead")}
108
+ $ ${m.commands[0]} presentation video <id-or-slug>
109
+ `);import{Command as de}from"commander";var dm=new de("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:ft(e.outputs,"outputs"),overlays:ft(e.overlays,"overlays"),ranges:ft(e.ranges,"ranges"),sourceAssetIds:e.source,sourceChatId:e.sourceChatId,strategy:ft(e.strategy,"strategy"),teamId:e.teamId,title:e.title},idempotencyKey:e.idempotencyKey})}),cm=new de("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}})}),lm=new de("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:ta({baseVersionId:t.baseVersionId,changeSummary:t.changeSummary,musicAssetId:t.musicAssetId==="null"?null:t.musicAssetId,outputs:Wt(t.outputs,"outputs"),overlays:Wt(t.overlays,"overlays"),projectId:e,ranges:Wt(t.ranges,"ranges"),strategy:Wt(t.strategy,"strategy"),teamId:t.teamId,title:t.title}),idempotencyKey:t.idempotencyKey})}),mm=new de("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})}),um=new de("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})}),pm=new de("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})}),gm=new de("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 ea("inspectFootageRange",e,t.teamId)}),fm=new de("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:ta({approvalReceipt:t.approvalReceipt,outputIds:t.output,projectId:e,teamId:t.teamId,versionId:t.versionId}),idempotencyKey:t.idempotencyKey})}),hm=new de("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 ea("renderFootageProject",e,t.teamId)}),ym=new de("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 de("footage").description("Create, inspect, revise, and render transcript-native footage edits").addCommand(dm).addCommand(cm).addCommand(lm).addCommand(mm).addCommand(um).addCommand(pm).addCommand(gm).addCommand(fm).addCommand(hm).addCommand(ym);async function ke(e,t){try{u(await y(e,t.input,t.idempotencyKey))}catch(n){d(n instanceof Error?n.message:"Footage operation failed"),process.exit(c.GENERAL_ERROR)}}async function ea(e,t,n){try{u(await E(e,t,n))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}function ft(e,t){try{return JSON.parse(e)}catch{throw new Error(`${t} must be valid JSON.`)}}function Wt(e,t){return typeof e=="string"?ft(e,t):void 0}function ta(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}import{Command as bm}from"commander";import Pe from"chalk";function wm(e){return new Set((e??"").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean))}function vm(e){if(!e)throw new Error("Slides were requested but the server returned none. Retry, or read the deck in the browser.");oe("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?na(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(na(r)))),console.log()}}function na(e){return e.split(`
110
+ `).map(t=>` ${t}`).join(`
111
+ `)}var ra=new bm("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=wm(t.include).has("slides"),r=await je(e,{includeSlides:n});if(t.format==="json"){console.log(JSON.stringify(r,null,2));return}let o=Ue(r.slug,t.language);oe("Presentation Details"),console.log(),$("Slug",r.slug),$("Title",r.title||"Untitled"),$("Description",r.description||Pe.gray("None")),$("Slides",String(r.numberOfSlides||"-")),$("Mode",r.mode||"-"),$("Created",xn(r.createdAt)),r.updatedAt&&$("Updated",xn(r.updatedAt)),console.log(),o!=="N/A"&&console.log(Pe.bold(" Open: ")+Pe.cyan.underline(o)),console.log(),n&&vm(r.slides)}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Jt}from"commander";import xm from"ora";function km(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}function Cm(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:km(e.source),transparentBackground:t==="icon"}}}function Im(e){let t=e.url||e.imageUrl;if(!t)throw new Error("Image search returned a result without a URL");return t}function Rm(e){return e.transparent??e.isTransparent??e.metadata?.transparent??e.metadata?.isTransparent}function Sm(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 $m(e,t){let n=e.data.results.map(r=>r.results.map(o=>{let i=o,a=Rm(i);if(t==="icon"&&a!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:Im(i),provider:r.providerName,assetType:t,...a!==void 0?{transparent:a}:{}}}));return Sm(n)}function Tm(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 Kt(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Em(e){return{requestId:e.runId,status:Tm(e),...e.entity?.url?{url:e.entity.url}:{},...e.error?{error:ae(e.error)}:{},...Kt(e.output?.width)!==void 0?{width:Kt(e.output?.width)}:{},...Kt(e.output?.height)!==void 0?{height:Kt(e.output?.height)}:{}}}async function oa(e,t){return Em(await E("createImage",e,t))}function Hn(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&&I(`Image URL: ${e.url}`),e.output&&I(`Saved to: ${e.output}`),e.error&&d(`Error: ${e.error}`)}var Am=new Jt("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"?xm("Searching for images...").start():null,r;try{r=Cm(e)}catch(o){n?.stop(),d(o instanceof Error?o.message:"Invalid image search request"),process.exit(c.INVALID_INPUT);return}try{let o=await Ro(r);n?.stop(),o.success||(d("Search failed"),process.exit(c.GENERAL_ERROR));let i=r.options?.assetType??"image",a=$m(o,i);if(t==="json"){u({success:!0,query:e.query,assetType:i,totalResults:a.length,images:a});return}if(t==="quiet"){for(let s of a)console.log(s.url);return}if(a.length===0){g("No images found");return}I(`Found ${a.length} images for "${e.query}"`),console.log();for(let s=0;s<a.length;s++){let l=a[s];console.log(`[${s+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(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Om=new Jt("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()||(d("Provide an image prompt as an argument or with --prompt"),process.exit(c.INVALID_INPUT)),t.yes||(d("Pass --yes to approve image generation"),process.exit(c.INVALID_INPUT)),!t.wait&&t.output&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));try{let o=await y("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){Hn({requestId:o.runId,status:"pending"},t.format);return}let i=await ee(()=>oa(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),Hn(a,t.format)}catch(o){d(ie(o,n),t.format),process.exit(c.GENERAL_ERROR)}}),Pm=new Jt("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 oa(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}Hn(n,t.format)}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ia=new Jt("image").description("Image search and generation commands").addCommand(Am).addCommand(Om).addCommand(Pm);import{Command as Yn}from"commander";var _m=new Yn("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 y("searchKnowledge",{kind:t.kind,limit:Number.parseInt(t.limit,10),query:e,teamId:t.teamId}))}catch(n){d(n instanceof Error?n.message:"Knowledge search failed"),process.exit(c.GENERAL_ERROR)}}),Lm=new Yn("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 y("getKnowledgeBundle",{kind:e.kind,teamId:e.teamId}))}catch(t){d(t instanceof Error?t.message:"Knowledge bundle failed"),process.exit(c.GENERAL_ERROR)}}),aa=new Yn("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(_m).addCommand(Lm);import{randomUUID as Dm}from"crypto";import zt from"chalk";import{Command as we}from"commander";function Qn(e){if(e!==void 0)return e==="root"?null:e}function We(e){return`cli:library:${e}:${Dm()}`}function _e(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}var Nm=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 y("listLibraryFolders",{includeEntryCounts:!!e.counts,teamId:e.teamId}))}catch(t){_e(t,"Could not list folders")}}),qm=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 y("createLibraryFolder",{color:t.color,name:e,parentId:Qn(t.parent),teamId:t.teamId},We("create")))}catch(n){_e(n,"Could not create the folder")}}),Um=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 y("renameLibraryFolder",{folderId:e,name:t,teamId:n.teamId},We("rename")))}catch(r){_e(r,"Could not rename the folder")}}),jm=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 y("recolorLibraryFolder",{color:t.color==="none"?null:t.color,folderId:e,teamId:t.teamId},We("recolor")))}catch(n){_e(n,"Could not recolour the folder")}}),Mm=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 y("moveLibraryFolder",{folderId:e,newParentId:Qn(t.to),teamId:t.teamId},We("move")))}catch(n){_e(n,"Could not move the folder")}}),Fm=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 y("deleteLibraryFolder",{folderId:e,teamId:t.teamId},We("delete")))}catch(n){_e(n,"Could not delete the folder")}}),Vm=new we("folders").description("Manage Library folders").addCommand(Nm).addCommand(qm).addCommand(Um).addCommand(jm).addCommand(Mm).addCommand(Fm),Gm=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 y("fileArtifactIntoFolder",{folderId:Qn(n.folder),kind:e,targetId:t,teamId:n.teamId},We("file")))}catch(r){_e(r,"Could not file that item")}}),Zn=new we("library").description("Library folders and filing").addCommand(Vm).addCommand(Gm);Zn.addHelpText("after",`
112
+ ${zt.bold("Examples:")}
113
+ ${zt.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
+ ${zt.bold("See also:")}
118
+ ${zt.gray("# A different thing: reusable video clips, not Library folders")}
119
+ $ ${m.commands[0]} video library --help
120
+ `);import{Command as ht}from"commander";function V(e,t){let n={...t},r=e.parent,o=!1;for(;r;){let i=r.opts?.();if(i){o=!0;for(let[a,s]of Object.entries(i))n[a]===void 0&&s!==void 0&&(n[a]=s)}r=r.parent}return o?n:t}var sa=new ht("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 d("Pass --yes to confirm. Analysis is billed per minute of source audio.");try{u(await y("analyzeMediaAsset",{assetId:e,diarize:t.diarize,language:t.language,teamId:t.teamId}))}catch(n){d(n instanceof Error?n.message:"Analysis failed"),process.exit(c.GENERAL_ERROR)}}),Bm=new ht("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=V(this,t);try{u(await E("analyzeMediaAsset",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});sa.addCommand(Bm);var da=new ht("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 y("importConnectorRecording",{connectorId:t.connector,providerId:t.provider,remoteFileId:e,sourceChatId:t.chat,teamId:t.teamId,title:t.title}))}catch(n){d(n instanceof Error?n.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}),Wm=new ht("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=V(this,t);try{u(await E("importConnectorRecording",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});da.addCommand(Wm);var ca=new ht("media").description("Ingest and transcribe recordings you already own").addCommand(sa).addCommand(da);import{Command as er}from"commander";var Km=new er("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 d("Pass --yes to approve generation");try{u(await y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),Jm=new er("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await E("createMicrosite",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),la=new er("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(Km).addCommand(Jm);import{Command as rr}from"commander";import tr from"ora";function nr(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&&I(`Output URL: ${e.outputUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var zm=new rr("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&&(d("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)&&(d("Music volume must be between 0 and 100"),process.exit(c.INVALID_INPUT)),(Number.isNaN(n)||n<0||n>2)&&(d("Voice volume must be between 0 and 200"),process.exit(c.INVALID_INPUT));let r=e.format,o=r==="human"?tr("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 Io({operation:"add-to-video",inputs:i,options:{musicVolume:t,voiceVolume:n}});if(!e.wait){o?.stop(),nr(a,r);return}o&&(o.text=`Processing (ID: ${a.requestId})...`);let s=await ee(()=>$n(a.requestId),120,3e3);if(o?.stop(),s.status==="failed"&&(d(s.error||"Audio mixing failed"),process.exit(c.GENERAL_ERROR)),nr(s,r),e.output){if(!s.outputUrl)throw new Error("Audio mix completed without an output URL");let l=r==="human"?tr("Downloading...").start():null;await Y(s.outputUrl,e.output),l?.stop(),r==="human"&&I(`Saved to: ${e.output}`)}}catch(a){o?.stop(),d(a instanceof Error?a.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Xm=new rr("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"?tr("Checking status...").start():null;try{let r=await $n(e);n?.stop(),nr(r,t.format)}catch(r){n?.stop(),d(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ma=new rr("mix").description("Audio mixing commands").addCommand(zm).addCommand(Xm);import{Command as ir}from"commander";import nu from"ora";import{readFileSync as Hm}from"fs";var ua=500,pa=1e4,Xt=100,ga=1e4,fa=1e3,ya=["duration_s","idempotency_key","narration","schema_version","video_description"],Ym=["end_s","id","start_s","text","words"],Qm=["end","id","start","text"],Zm=["description","end_s","id","start_s"];function ba(e){let t=va(e);if(xa(t),yt(t,ya,""),t.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return t}function wa(e){let t=va(e);xa(t),yt(t,[...ya,"visual_event"],"");let n=t.visual_event;if(!Ht(n))throw new Error("SFX request visual_event is required");if(yt(n,Zm,"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 va(e){try{let t=JSON.parse(Hm(e,"utf8"));if(!Ht(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 xa(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>ua)throw new Error(`Audio request narration holds at most ${ua} lines`);if(e.narration.forEach(eu),e.idempotency_key!==void 0&&!Ce(e.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function eu(e,t){let n=`narration.${t}`;if(!Ht(e))throw new Error(`Audio request ${n} must be an object`);if(yt(e,Ym,n),!Ce(e.id)||e.id.length>Xt)throw new Error(`Audio request ${n}.id is required (1-${Xt} characters)`);if(!Ce(e.text)||e.text.trim().length>ga)throw new Error(`Audio request ${n}.text is required (1-${ga} characters)`);if(ha(e.start_s,`${n}.start_s`),ha(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>pa)throw new Error(`Audio request ${n}.words must be an array of at most ${pa} entries`);e.words.forEach((r,o)=>{tu(r,`${n}.words.${o}`)})}}function tu(e,t){if(!Ht(e))throw new Error(`Audio request ${t} must be an object`);if(yt(e,Qm,t),!Ce(e.text)||e.text.trim().length>fa)throw new Error(`Audio request ${t}.text is required (1-${fa} 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>Xt))throw new Error(`Audio request ${t}.id must be 1-${Xt} characters`)}function ha(e,t){if(e!==void 0&&!Ie(e))throw new Error(`Audio request ${t} must be a non-negative number`)}function yt(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 Ht(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 or(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&&I(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var ru=new ir("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&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=ba(e.request)}catch(i){d(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?nu("Generating music for video...").start():null,o;try{let i=await Co(t);if(o=i.requestId,!e.wait){r?.stop(),or(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let a=i.status==="completed"||i.status==="failed"?i:await ee(()=>Sn(i.requestId),180,2e3);if(r?.stop(),a.status==="failed"&&(d(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"&&I(`Saved to: ${e.output}`),a.output=e.output}or(a,n)}catch(i){r?.stop(),d(ie(i,o),n),process.exit(c.GENERAL_ERROR)}}),ou=new ir("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{or(await Sn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ka=new ir("music").description("Video-aware music generation commands").addCommand(ru).addCommand(ou);import{Command as ar}from"commander";function Ca(e,t){return[...t,e]}var iu=new ar("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",Ca,[]).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 d("Pass --yes to approve poll creation");try{u(await y("createPoll",{approvalReceipt:"cli:--yes",options:t.option.map(n=>({text:n})),pollType:t.type,question:e,teamId:t.teamId,title:t.title}))}catch(n){d(n instanceof Error?n.message:"Poll creation failed"),process.exit(c.GENERAL_ERROR)}}),au=new ar("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",Ca).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 d("Pass --yes to approve poll update");try{u(await y("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){d(n instanceof Error?n.message:"Poll update failed"),process.exit(c.GENERAL_ERROR)}}),Ia=new ar("poll").description("Standalone poll commands").addCommand(iu).addCommand(au);import{randomUUID as lr}from"crypto";import{readFile as fu}from"fs/promises";import j from"chalk";import{Command as H}from"commander";import{randomUUID as dr}from"crypto";import{readFile as su}from"fs/promises";import{Command as Yt}from"commander";var Ra=new Yt("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=V(this,t);await Qt("Draft edit failed",async()=>y("editPresentationVideoDraft",{edit:await du(n.edit),projectId:e,teamId:n.teamId},n.idempotencyKey??dr()))}),Sa=new Yt("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",sr(1)).option("--limit <number>","Maximum versions",sr(1,100)).option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=V(this,t);await Qt("Version list failed",()=>y("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:e,teamId:n.teamId}))}),$a=new Yt("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",sr(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t,n){let r=V(this,n);await Qt("Version restore failed",()=>y("restorePresentationVideoVersion",{projectId:e,teamId:r.teamId,versionNumber:t},r.idempotencyKey??dr()))}),Ta=new Yt("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=V(this,t);await Qt("Slide refresh failed",()=>y("refreshPresentationVideoSlides",{projectId:e,teamId:n.teamId},n.idempotencyKey??dr()))});async function du(e){let t=e.trim(),n=t.startsWith("{")?t:await su(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 sr(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 Qt(e,t){try{u(await t())}catch(n){d(n instanceof Error?n.message:e),process.exit(c.GENERAL_ERROR)}}import{randomUUID as cu}from"crypto";import{Command as lu}from"commander";var mu=["basic","standard","premium"],Ea=new lu("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=V(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&&!mu.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");u(await y("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},uu(r.idempotencyKey)))}catch(o){d(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(c.GENERAL_ERROR)}});function uu(e){return e||cu()}import{Command as cr}from"commander";var Aa=new cr("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=V(this,t);try{u(await y("getPresentationVideoProject",{projectId:e,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Project read failed"),process.exit(c.GENERAL_ERROR)}}),pu=new cr("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",gu).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=V(this,t);try{u(await y("listReusableVideoClips",{cursor:n.cursor,limit:n.limit,projectId:e,query:n.query,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Clip list failed"),process.exit(c.GENERAL_ERROR)}}),Oa=new cr("library").description("Reusable generated clips and uploaded recordings").addCommand(pu);function gu(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 hu=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 E("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&&d(ae(n.error))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),yu=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=V(this,t);try{let r=await y("transformPresentationImport",{importId:e},n.idempotencyKey);u(r)}catch(r){d(r instanceof Error?r.message:"Transform failed"),process.exit(c.GENERAL_ERROR)}}),bu=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 E("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&&d(ae(n.error)))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Pa=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){Pa.help();return}e.file.toLowerCase().endsWith(".pptx")||(d("PowerPoint import requires a .pptx file."),process.exit(c.INVALID_INPUT));try{let t=await me(e.file),n=await y("importPowerPoint",{brandingId:e.brandingId,filename:e.filename??t.name,mode:e.mode,sourceChatId:e.sourceChatId,sourceUrl:t.url,title:e.title},e.idempotencyKey??lr());u(n)}catch(t){d(t instanceof Error?t.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(yu).addCommand(bu),wu=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 E("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){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),vu=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 E("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){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),xu=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=V(this,t);try{u(await E("createPresentationVideo",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ku=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=V(this,t);if(n.narrate&&!n.yes)return d("Pass --yes to confirm. --narrate generates speaker notes and costs credits.");try{u(await y("preparePresentationVideo",{forceNew:n.forceNew,narrate:n.narrate,presentationId:e,teamId:n.teamId},n.idempotencyKey??lr()))}catch(r){d(r instanceof Error?r.message:"Prepare failed"),process.exit(c.GENERAL_ERROR)}}),Cu=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=V(this,t);try{u(await E("ensurePresentationVideoNarration",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Iu=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=V(this,t);if(!n.yes)return d("Pass --yes to confirm. Generating narration costs credits.");try{let r=await y("ensurePresentationVideoNarration",{projectId:e,teamId:n.teamId},n.idempotencyKey??lr());if(n.wait===!1||r.runStatus==="completed"){u(r);return}u(r),await mr(r.runId,"presentation video narrate status",()=>Pt(r.runId))}catch(r){d(r instanceof Error?r.message:"Narration failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(Cu),Ru=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=V(this,t);if(n.settings||(d("Pass --settings <json-or-path> with the patch to apply."),process.exit(c.INVALID_INPUT)),!n.yes)return d("Pass --yes to confirm updating presentation video settings.");try{u(await y("updatePresentationVideoSettings",{projectId:e,settings:await _a(n.settings),teamId:n.teamId},n.idempotencyKey))}catch(r){d(r instanceof Error?r.message:"Settings update failed"),process.exit(c.GENERAL_ERROR)}}),Su=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 d("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 y("createPresentationVideo",{forceNew:t.forceNew,forceRerender:t.forceRerender,presentationId:e,projectId:t.projectId,renderEngine:t.renderEngine,settings:t.settings?await _a(t.settings):void 0,teamId:t.teamId},t.idempotencyKey))}catch(n){let r=n instanceof Error?n.message:"Render failed";d(r);let o=Qr({binary:m.commands[0],message:r,projectId:t.projectId});o&&Mr(o),process.exit(c.GENERAL_ERROR)}}).addCommand(ku).addCommand(Iu).addCommand(Aa).addCommand(Ra).addCommand(Ea).addCommand(Ta).addCommand($a).addCommand(Ru).addCommand(xu).addCommand(Sa);async function _a(e){let t=e.trim(),n=t.startsWith("{")?t:await fu(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 $u(e,t){return[...t,e]}var Tu=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)",$u,[]).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 so(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 mr(n.runId,"presentation speaker-notes-status",()=>Pt(n.runId))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Eu=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 co(e,{instructions:t.instructions,slideId:t.slideId});if(t.format==="json"||!t.follow){u(n);return}g(`Narration run: ${n.runId}`),await mr(n.runId,"presentation video-narration-status",()=>Pt(n.runId))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});async function mr(e,t,n){let r=null;try{r=await Ou(await n())}catch(o){let i=o instanceof Error&&o.message.trim()?o.message.trim():"the event stream ended unexpectedly";F(`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 Au(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 Ou(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 s=r.split(`
121
+
122
+ `);r=s.pop()??"";for(let l of s){let f=l.split(`
123
+ `).find(x=>x.startsWith("data:"))?.slice(5).trim();if(!f)continue;let p=JSON.parse(f);p.eventType?.startsWith("slide.")&&g(`${p.eventType}${p.payload?.slideId?` \xB7 ${p.payload.slideId}`:""}`);let v=Au(p);v==="completed"?o=null:v&&(o=v)}if(i)return o}}var ur=new H("presentation").description("Create an MP4 video from a finished presentation, plus speaker notes, PowerPoint import, and run status").addCommand(hu).addCommand(Pa).addCommand(Tu).addCommand(wu).addCommand(Su).addCommand(Eu).addCommand(vu);ur.addHelpText("after",`
124
+ ${j.bold("Deck to MP4:")}
125
+ $ ${m.commands[0]} presentation video prepare <slug> ${j.gray("# create/reuse the video project (free)")}
126
+ $ ${m.commands[0]} presentation video narrate <project-id> --yes ${j.gray("# fill in missing narration")}
127
+ $ ${m.commands[0]} presentation video inspect <project-id> ${j.gray("# review the scene timeline")}
128
+ $ ${m.commands[0]} presentation video <slug> --yes ${j.gray("# start the MP4 render")}
129
+ $ ${m.commands[0]} presentation video status <run-id> ${j.gray("# follow the render")}
130
+
131
+ ${j.bold("Voice and avatar defaults:")}
132
+ ${j.gray("# prepare picks the narration voice for you \u2014 the one this user last")}
133
+ ${j.gray("# chose if it is still ready, otherwise the first ready voice \u2014 and")}
134
+ ${j.gray("# reports it. Show which voice was selected and offer to change it")}
135
+ ${j.gray("# instead of interviewing the user about voices. Every voice in")}
136
+ ${j.gray("# avatar options carries a previewUrl audio sample they can hear.")}
137
+ ${j.gray('# No avatar is chosen, on purpose: "slides with a voiceover" is the')}
138
+ ${j.gray("# normal outcome, so presenter: null is finished, not misconfigured.")}
139
+ ${j.gray("# Ask whether they want a presenter; do not assume either way.")}
140
+ $ ${m.commands[0]} avatar options ${j.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
+ ${j.bold("Before rendering:")}
145
+ ${j.gray("# Approve the content, then approve the spend \u2014 two questions. Read the")}
146
+ ${j.gray("# narration back scene by scene from inspect (scenes[].narration.text)")}
147
+ ${j.gray("# and get a yes on the script itself, plus the voice, the presenter (or")}
148
+ ${j.gray("# none), music, format and captions, before the render. Reworking one")}
149
+ ${j.gray("# scene is the cheap loop; the MP4 is not. --yes is your intent, not")}
150
+ ${j.gray("# the user's consent.")}
151
+ $ ${m.commands[0]} presentation video inspect <project-id> ${j.gray("# narration text + settings to show")}
152
+ $ ${m.commands[0]} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"
153
+
154
+ ${j.bold("See also:")}
155
+ ${j.gray("# Building a video from scratch instead of from a deck")}
156
+ $ ${m.commands[0]} video --help
157
+ `);import{writeFile as Pu}from"fs/promises";import bt from"chalk";import{Command as _u}from"commander";import Lu from"ora";var pr=new _u("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"?Lu("Scraping URL...").start():null;try{let o=await To(e,t.teamId);r?.stop(),(!o.success||!o.data)&&(d(o.error||"Failed to scrape URL"),process.exit(c.GENERAL_ERROR));let i=o.data;if(t.output&&(await Pu(t.output,i.content,"utf-8"),n==="human"&&I(`Content saved to: ${t.output}`)),n==="json"){let{cost:a,...s}=i;u(s);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&&F(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(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});pr.addHelpText("after",`
158
+ ${bt.bold("Examples:")}
159
+ ${bt.gray("# Pull the readable content of a web page")}
160
+ $ ${m.commands[0]} scrape https://example.com/post
161
+
162
+ ${bt.bold("See also:")}
163
+ ${bt.gray("# Local files and documents, not just URLs")}
164
+ $ ${m.commands[0]} content extract ./paper.pdf
165
+
166
+ ${bt.gray("# Spoken words out of audio or video")}
167
+ $ ${m.commands[0]} transcript --help
168
+ `);import gr from"chalk";import{Command as wt}from"commander";function Zt(e,t){t!=="quiet"&&u(e)}var Du=new wt("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 y("searchInternet",{maxResults:Number.parseInt(t.maxResults,10),query:e,teamId:t.teamId});Zt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Search failed"),process.exit(c.GENERAL_ERROR)}}),Nu=new wt("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 y("getNews",{maxResults:Number.parseInt(t.maxResults,10),teamId:t.teamId,timeframe:t.timeframe,topic:e});Zt(n,t.format)}catch(n){d(n instanceof Error?n.message:"News search failed"),process.exit(c.GENERAL_ERROR)}});function La(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var qu=new wt("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 y("searchImages",{aspect:t.aspect,maxResults:Number.parseInt(t.maxResults,10),query:e,sources:La(t.source),teamId:t.teamId});Zt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Image search failed"),process.exit(c.GENERAL_ERROR)}}),Uu=new wt("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 y("searchStockVideo",{license:t.license,maxResults:Number.parseInt(t.maxResults,10),orientation:t.orientation,query:e,sources:La(t.source),teamId:t.teamId});Zt(n,t.format)}catch(n){d(n instanceof Error?n.message:"Video search failed"),process.exit(c.GENERAL_ERROR)}}),fr=new wt("search").description("Web, news, image, and stock-video search").addCommand(Du).addCommand(Nu).addCommand(qu).addCommand(Uu);fr.addHelpText("after",`
169
+ ${gr.bold("Examples:")}
170
+ $ ${m.commands[0]} search web "state of AI video 2026"
171
+ $ ${m.commands[0]} search news "vaccine approvals"
172
+
173
+ ${gr.bold("See also:")}
174
+ ${gr.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 yr}from"commander";import ju from"ora";function hr(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&&I(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var Mu=new yr("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&&(d("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=wa(e.request)}catch(i){d(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?ju("Generating sound effect for video...").start():null,o;try{let i=await Eo(t);if(o=i.requestId||i.id,!e.wait){r?.stop(),hr(i,n);return}let a=i.requestId||i.id;r&&(r.text=`Processing (ID: ${a})...`);let s=i.status==="completed"||i.status==="failed"?i:await ee(()=>Tn(a),60,2e3);if(r?.stop(),s.status==="failed"&&(d(s.error||"Sound effects generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!s.audioUrl)throw new Error("Sound effect completed without an audio URL");await Y(s.audioUrl,e.output),n==="human"&&I(`Saved to: ${e.output}`)}hr(s,n)}catch(i){r?.stop(),d(ie(i,o),n),process.exit(c.GENERAL_ERROR)}}),Fu=new yr("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{hr(await Tn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Da=new yr("sfx").description("Video-aware sound effects generation commands").addCommand(Mu).addCommand(Fu);import{writeFile as Vu}from"fs/promises";import{Command as Gu}from"commander";import Bu from"ora";var Na=new Gu("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"?Bu("Fetching transcript...").start():null;try{let o=await $o(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 Vu(t.output,i,"utf-8"),n==="human"&&I(`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&&F("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(),d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdir as Wu,writeFile as qa}from"fs/promises";import{dirname as Ku}from"path";import{Command as en}from"commander";import Ma from"ora";var Ua="en-US-Neural2-C",ja="gemini",Ju=new en("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: ${Ua})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${ja})`).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"?Ma("Generating speech...").start():null,r;e.speed&&(r=parseFloat(e.speed),(Number.isNaN(r)||r<.1||r>4)&&(n?.stop(),d("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(),d("Speakers must be an array with 1-2 name/voice items"),process.exit(c.INVALID_INPUT))}catch{n?.stop(),d(`Invalid --speakers JSON. Example: '[{"name":"Joe","voice":"Kore"}]'`),process.exit(c.INVALID_INPUT)}let i;try{let a=e.voiceId,s=e.voice||Ua,l=e.provider||ja,f={};o&&(f.gemini={speakers:o}),e.instructions&&(f.openai={instructions:e.instructions});let p=await vo({text:e.text,options:{language:e.lang,provider:l,voiceId:a,voice:s,model:e.model,speed:r,providerOptions:Object.keys(f).length>0?f:void 0}});i=p.requestId,n?.stop();let v=e.output.endsWith(`.${p.format}`)?e.output:`${e.output}.${p.format}`;await Wu(Ku(v),{recursive:!0}),await qa(v,p.audioData);let x=v.replace(/\.[^.]+$/,".txt");if(await qa(x,e.text,"utf-8"),t==="json"){u({status:"completed",output:v,audioUrl:p.audioUrl,duration:p.duration,provider:p.provider,format:p.format,voice_id:p.voiceId??null,voice:p.voice??s,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(v);return}I(`Saved to: ${v}`),g(`Duration: ${p.duration.toFixed(2)}s`),g(`Provider: ${p.provider}`),g(`Cost: $${p.cost.toFixed(6)}`)}catch(a){n?.stop(),d(ie(a,i),t),process.exit(c.GENERAL_ERROR)}}),zu=new en("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"?Ma("Fetching voices...").start():null;try{let n=await ko(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(),d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Xu=new en("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 E("generateSpeech",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Fa=new en("tts").description("Text-to-speech commands").addCommand(Ju).addCommand(zu).addCommand(Xu);import{execSync as on,spawnSync as xp}from"child_process";import{access as wr,readFile as kp,rm as es}from"fs/promises";import{resolve as xt}from"path";import ce from"chalk";import{Command as Z}from"commander";import Cp from"ffmpeg-static";import ts from"ora";import{Command as Hu}from"commander";import Yu from"ora";import{execSync as Qu,spawnSync as Ke}from"child_process";import{mkdirSync as Va,existsSync as nn,readFileSync as Ba,writeFileSync as Ga}from"fs";import{join as Le,basename as Zu}from"path";import{tmpdir as ep}from"os";function rn(e,t){try{return Qu(t,{stdio:"ignore"}),!0}catch{return!1}}function tn(e){let t=Math.floor(e/60),n=Math.floor(e%60),r=Math.round(e%1*10);return`${t}:${String(n).padStart(2,"0")}.${r}`}function tp(e){let t=Ke("ffprobe",["-v","error","-show_entries","format=duration","-of","default=noprint_wrappers=1:nokey=1",e],{encoding:"utf-8"});return parseFloat(t.stdout.trim())}function np(e,t){let n=Ke("ffmpeg",["-i",e,"-vf",`select='gt(scene,${t})',showinfo`,"-vsync","vfr","-f","null","-"],{encoding:"utf-8",timeout:12e4}),r=[0],o=(n.stderr||"").split(`
180
+ `);for(let i of o){let a=i.match(/pts_time:([\d.]+)/);if(a){let s=parseFloat(a[1]);s-r[r.length-1]>=1.5&&r.push(s)}}return r}function rp(e,t,n){let r=[];for(let o=0;o<t.length;o++){let i=t[o]+.5,a=Le(n,`scene_${String(o+1).padStart(2,"0")}.jpg`);Ke("ffmpeg",["-ss",String(i),"-i",e,"-vframes","1","-q:v","2","-y",a],{stdio:"ignore",timeout:3e4}),r.push(a)}return r}function op(e,t){let n=Le(t,"audio.wav");if(Ke("ffmpeg",["-i",e,"-vn","-acodec","pcm_s16le","-ar","16000","-ac","1","-y",n],{stdio:"ignore",timeout:6e4}),!nn(n)||!rn("whisper","which whisper")&&!rn("whisper-cpp","which whisper-cpp"))return null;let o=Ke("whisper",[n,"--model","base","--output_format","json","--output_dir",t,"--language","en"],{encoding:"utf-8",timeout:3e5}),i=Le(t,"audio.json");if(!nn(i))return null;try{let a=JSON.parse(Ba(i,"utf-8"));return{text:a.text||"",segments:(a.segments||[]).map(s=>({start:s.start,end:s.end,text:s.text?.trim()||""}))}}catch{return null}}function ip(e,t){let n=Ba(e).toString("base64"),r=JSON.stringify({model:t,prompt:"Describe this image in one short sentence (max 15 words). Focus on: what is shown, the setting, key objects or people.",images:[n],stream:!1}),o=Ke("curl",["-s","-X","POST","http://localhost:11434/api/generate","-H","Content-Type: application/json","-d",r],{encoding:"utf-8",timeout:6e4});try{return(JSON.parse(o.stdout).response||"").replace(/!!!IMAGE!!!/gi,"").replace(/\[image[^\]]*\]/gi,"").trim()||"Unable to describe frame"}catch{return"Unable to describe frame"}}var Wa=new Hu("analyze").description("Analyze a video file: detect scenes, transcribe audio, describe frames").argument("<file>","Path to video file").option("-o, --output <path>","Output directory for analysis results").option("-t, --threshold <number>","Scene detection threshold (0-1, lower = more scenes)","0.3").option("-m, --model <name>","Ollama vision model","moondream").option("--no-vision","Skip frame description (faster)").option("--no-transcribe","Skip audio transcription").option("-f, --output-format <format>","Output format: human, json","human").action(async(e,t)=>{let n=Yu();nn(e)||(console.error(`File not found: ${e}`),process.exit(1)),rn("ffmpeg","which ffmpeg")||(console.error("ffmpeg is required. Install: brew install ffmpeg"),process.exit(1)),t.vision!==!1&&!rn("ollama","which ollama")&&(console.error("ollama is required for vision. Install: brew install ollama"),process.exit(1));let r=t.output||Le(ep(),`video-analyze-${Date.now()}`);Va(r,{recursive:!0});let o=Le(r,"frames");Va(o,{recursive:!0});let i=parseFloat(t.threshold),a=t.model;n.start("Reading video metadata...");let s=tp(e);n.succeed(`Video: ${tn(s)} (${s.toFixed(1)}s)`),n.start("Detecting scenes...");let l=np(e,i);n.succeed(`Detected ${l.length} scenes`),n.start("Extracting key frames...");let f=rp(e,l,o);n.succeed(`Extracted ${f.length} key frames`);let p=null;t.transcribe!==!1&&(n.start("Transcribing audio..."),p=op(e,r),p?n.succeed(`Transcribed: ${p.segments.length} segments`):n.warn("Transcription skipped (whisper not installed: pip install openai-whisper)"));let v=[];for(let w=0;w<l.length;w++){let T=l[w],k=w<l.length-1?l[w+1]:s,C="";t.vision!==!1&&nn(f[w])&&(n.start(`Describing scene ${w+1}/${l.length}...`),C=ip(f[w],a),n.succeed(`Scene ${w+1}: ${C}`)),v.push({id:w+1,startTime:T,endTime:k,duration:k-T,framePath:f[w],description:C})}let x={source:e,duration:s,scenes:v,transcript:p};if(t.outputFormat==="json"){let w=JSON.stringify(x,null,2),T=Le(r,"analysis.json");Ga(T,w),console.log(w)}else{let w=["# Video Analysis","",`**Source:** ${Zu(e)}`,`**Duration:** ${tn(s)} (${s.toFixed(1)}s)`,`**Scenes:** ${v.length}`,"","## Scenes",""];for(let C of v){if(w.push(`### Scene ${C.id} (${tn(C.startTime)} - ${tn(C.endTime)}) [${C.duration.toFixed(1)}s]`),C.description&&w.push(`**Visual:** ${C.description}`),p?.segments){let S=p.segments.filter(q=>q.end>C.startTime&&q.start<C.endTime);S.length>0&&w.push(`**Audio:** ${S.map(q=>q.text).join(" ").trim()}`)}w.push(`**Frame:** ${C.framePath}`),w.push("")}p?.text&&(w.push("## Full Transcript"),w.push(""),w.push(p.text.trim()),w.push(""));let T=w.join(`
181
+ `),k=Le(r,"analysis.md");Ga(k,T),console.log(T),console.log(`
182
+ Results saved to: ${r}`)}});import{mkdir as ap}from"fs/promises";import{join as sp}from"path";import{Command as vt}from"commander";import Ja from"ora";var dp=5e3,cp=120,Ka=5;function lp(e,t){return[...t,e]}function mp(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 za(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 up(e){if(e.mode&&!["speed","precision"].includes(e.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:mp(e.audioUrl,"Audio URL"),...e.mode?{mode:e.mode}:{},sourceVideoId:za(e.sourceVideoId)}}function pp(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>Ka)throw new Error(`Provide at most ${Ka} 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:za(e.sourceVideoId),targetLanguages:t}}function gp(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 br(e){return{requestId:e.runId,status:gp(e),...e.entity?.url?{videoUrl:e.entity.url}:{},...e.output?{output:e.output}:{},...e.error?{error:ae(e.error)}:{}}}function Xa(e){return{requestId:e.runId,status:"pending"}}async function Ha(e,t){return ee(async()=>br(await E(e,t)),cp,dp)}function Je(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&&I(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}function fp(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 hp(e){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function yp(e,t){let n=hp(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 bp(e,t){let n=fp(e.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await ap(t,{recursive:!0});let r=[],o=new Set;for(let i of n){let a=sp(t,yp(i.language,o));await Y(i.videoUrl,a),r.push({language:i.language,path:a})}return r}var wp=new vt("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=V(this,t).format??"human";try{Je(br(await E("lipsyncVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Ya=new vt("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"?Ja("Starting video lip-sync...").start():null,n;try{let r=await Po(up(e));if(n=r.runId,!e.wait){t?.stop(),Je(Xa(r),e.format);return}t&&(t.text="Waiting for video lip-sync...");let o=await Ha("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(),Je(o,e.format),e.format==="human"&&I(`Saved to: ${e.output}`)}catch(r){t?.stop(),d(ie(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(wp),Qa=new vt("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 _o();if(e.format==="json")u({languages:t});else for(let n of t)console.log(n)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),vp=new vt("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=V(this,t).format??"human";try{Je(br(await E("translateVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Za=new vt("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)",lp,[]).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"?Ja("Starting video translation...").start():null,n;try{let r=await Lo(pp(e));if(n=r.runId,!e.wait){t?.stop(),Je(Xa(r),e.format);return}t&&(t.text="Waiting for video translations...");let o=await Ha("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");t&&(t.text="Downloading translated videos...");let i=await bp(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{Je(o,e.format);for(let a of i)I(`${a.language}: ${a.path}`)}}catch(r){t?.stop(),d(ie(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(vp);async function Ip(){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 Rp(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var Sp=new Z("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"?ts("Finding videos...").start():null;try{let s=await So({query:e,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:Rp(t.source)}});a?.stop();let l=s.data.results.flatMap(f=>f.results);if(i==="json"){let{totalCost:f,...p}=s.data;u({...s,data:p});return}if(i==="quiet"){l.forEach(f=>{console.log(f.embedUrl||f.previewUrl||f.thumbnailUrl)});return}if(l.length===0){g("No videos found");return}I(`Found ${l.length} videos for "${e}"`),console.log(),l.forEach((f,p)=>{let v=f.kind==="embed";console.log(`[${p+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()}),g(`Total cost: $${s.data.totalCost.toFixed(4)}`)}catch(s){a?.stop(),d(s instanceof Error?s.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),$p=new Z("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("--draft","Generate at 480p for a faster draft").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 d("Pass --yes to approve video generation");try{u(await Do({quality:e.draft?"draft":void 0,sourceVideoId:e.sourceVideo,storyboardRevisionId:e.storyboardRevision,teamId:e.teamId},e.approvalReceipt,e.idempotencyKey))}catch(t){d(t instanceof Error?t.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}});async function ns(e){let t=e==="-"?await Ip():await kp(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 rs(e,t={}){if(e)return e.length===1&&e[0]==="none"?[]:Promise.all(e.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=ue(r.handle),i=ue(r.path),a=ue(r.fileUrl)??ue(r.url),s=ue(r.purpose),l=ue(r.videoRole),f=ue(r.analysisId)??ue(r.analysis);if(!o||!i&&!a||!s)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&&s==="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&&!t.uploadIdempotencyKey)throw new Error("Local storyboard media requires the command idempotency key.");let p=i?await me(xt(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 v=p.type.startsWith("video/")?"video":p.type.startsWith("audio/")?"audio":p.type.startsWith("image/")?"image":null;if(!v)throw new Error(`Unsupported media type for ${i??a}: ${p.type}`);if(!["source","style","identity","required"].includes(s))throw new Error(`Invalid media purpose: ${s}`);if(l&&!["reference","first-frame","last-frame"].includes(l))throw new Error(`Invalid videoRole: ${l}`);if(l&&v!=="image")throw new Error("videoRole is supported only for image bindings.");return{...f?{analysisId:f}:{},fileUrl:p.url,handle:o,kind:v,mime:p.type,name:p.name,purpose:s,size:p.size,...l?{videoRole:l}:{}}}))}function ue(e){return typeof e=="string"&&e.length>0?e:void 0}var Tp=new Z("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 y("createVideoStoryboard",{aspectRatio:e.aspect,durationSec:Number(e.duration),mediaBindings:await rs(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardMarkdown:await ns(e.file),teamId:e.teamId,title:e.title},e.idempotencyKey))}catch(t){d(t instanceof Error?t.message:"Storyboard creation failed"),process.exit(c.GENERAL_ERROR)}}),Ep=new Z("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 y("reviseVideoStoryboard",{aspectRatio:t.aspect,baseRevisionId:t.baseRevision,changeSummary:t.changeSummary,durationSec:Number(t.duration),mediaBindings:await rs(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardId:e,storyboardMarkdown:await ns(t.file),teamId:t.teamId,title:t.title},t.idempotencyKey))}catch(n){d(n instanceof Error?n.message:"Storyboard revision failed"),process.exit(c.GENERAL_ERROR)}}),Ap=new Z("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 y("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){d(n instanceof Error?n.message:"Storyboard read failed"),process.exit(c.GENERAL_ERROR)}}),Op=new Z("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(Tp).addCommand(Ep).addCommand(Ap),Pp=new Z("analyze").description("Upload and analyze a reference video").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(xt(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 No({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 qo(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){d(t instanceof Error?t.message:"Reference analysis failed"),process.exit(c.GENERAL_ERROR)}}),_p=new Z("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 E("analyzeVideoReference",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status read failed"),process.exit(c.GENERAL_ERROR)}}),Lp=new Z("reference").description("Upload and inspect reusable video references").addCommand(Pp).addCommand(_p),Dp=new Z("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await E("createVideo",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Np=new Z("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"?ts("Injecting thumbnail...").start():null;try{let r=xt(e.video),o=xt(e.thumbnail),i=e.output?xt(e.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await wr(r),await wr(o);let a=Cp;if(a)try{await wr(a)}catch{a=null}if(!a)try{a=on("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let s=xp(a,["-i",r],{encoding:"utf8"});if(s.error)throw new Error(`Failed to probe video: ${s.error.message}`);let l=(s.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!l)throw new Error("Could not detect video dimensions");let[,f,p]=l;n&&(n.text="Creating thumbnail frame...");let v="/tmp/cc-thumb-frame.mp4";on(`${a} -y -loop 1 -i "${o}" -vf "scale=${f}:${p}:force_original_aspect_ratio=decrease,pad=${f}:${p}:(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(on(`${a} -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..."),on(`${a} -y -i "${x}" -i "${o}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await es(v,{force:!0}),await es(x,{force:!0}),n?.stop(),t==="json"){u({success:!0,output:i});return}if(t==="quiet"){console.log(i);return}I(`Thumbnail injected: ${i}`)}catch(r){n?.stop(),d(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),qp=new Z("thumbnail").description("Thumbnail operations").addCommand(Np),an=new Z("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(Sp).addCommand(qp).addCommand(Ya).addCommand(Qa).addCommand(Za).addCommand(Oa).addCommand(Wa);an.addCommand($p).addCommand(Op).addCommand(Lp).addCommand(Dp);an.addHelpText("after",`
183
+ ${ce.bold("Examples:")}
184
+ ${ce.gray("# Storyboard-first video from a brief")}
185
+ $ ${m.commands[0]} video storyboard create --file brief.md --duration 60 --aspect 16:9 --idempotency-key launch-1
186
+
187
+ ${ce.gray("# Find licensed stock footage")}
188
+ $ ${m.commands[0]} video find "city timelapse"
189
+
190
+ ${ce.bold("Before generating:")}
191
+ ${ce.gray("# Approve the content, then approve the spend \u2014 two questions. Paste the")}
192
+ ${ce.gray("# storyboard text into your reply and get a yes on it BEFORE pinning a")}
193
+ ${ce.gray("# revision; revising is free and append-only, a pinned revision is not.")}
194
+ ${ce.gray("# The browser confirmation video create requires is about cost and")}
195
+ ${ce.gray("# destination, not the user reading the script. --yes is neither.")}
196
+ $ ${m.commands[0]} video storyboard show <storyboard-id>
197
+ $ ${m.commands[0]} video storyboard revise <storyboard-id> --base-revision <revision-id> --file brief-v2.md --idempotency-key launch-2
198
+
199
+ ${ce.bold("See also:")}
200
+ ${ce.gray("# Already have a deck? Render it to MP4 (narration, avatar, captions)")}
201
+ $ ${m.commands[0]} presentation video <slug>
202
+ `);import{Command as vr}from"commander";var Up=new vr("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 d("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 y("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){d(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),jp=new vr("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 E("createVisualAbstract",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),os=new vr("visual-abstract").description("Generate a one-page visual abstract graphic (raster or vector) from a dense brief").addCommand(Up).addCommand(jp);var xr=[Xi,ra,Bi,Fa,ka,ma,ia,an,pr,Na,Da,ur,fr,Jn,aa,Zn,Ia,_i,os,la,Ai,Wn,ca,Kn,Yi,Zi,Xn];function is(e){for(let t of xr)e.addCommand(t)}function as(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)as(o,r,n)}var sn;function Mp(){if(!sn){sn=new Map;for(let e of xr)as(e,"",sn)}return sn}function ss(e){let t=Mp().get(e);return t?[...t.arguments,...t.requiredOptions.map(n=>`${n} \u2026`)].join(" "):""}var ds=["presentations","media","branding","knowledge","research","artifacts","agents"],kr={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"},Fp="other";function Vp(e){let t=e.category?.trim();return t&&t.length>0?t:Fp}function cs(e){let t=ds.indexOf(e);return t===-1?ds.length:t}function kt(e){let t=new Map;for(let n of e){let r=Vp(n),o=t.get(r);o?o.push(n):t.set(r,[n])}return[...t.entries()].sort(([n],[r])=>cs(n)-cs(r)||n.localeCompare(r)).map(([n,r])=>({capabilities:[...r].sort((o,i)=>o.name.localeCompare(i.name)),category:n}))}function Cr(e){return e.lifecycle?.mode==="background"}function Ir(e,t){let n=e.lifecycle?.status?.cliCommand?.trim();if(!(!Cr(e)||!n))return`${t} ${n} <run-id>`}function Gp(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 dn(e){return e.replace(/\|/g,"\\|").replace(/\r?\n/g," ").trim()}function Bp(e,t){let n=Ir(e,t);return n?`run id \u2014 poll \`${n}\``:`immediate (${e.operation??"call"})`}function ze(e,t){let n=["| Command | What it does | Takes | Returns | Cost | Scopes |","|---|---|---|---|---|---|"],r=e.map(o=>{let i=ss(o.name),a=o.scopes?.length?o.scopes.map(s=>`\`${s}\``).join(", "):"\u2014";return`| \`${t} ${dn(o.name)}\` | ${dn(o.description??"")} | ${i?`\`${dn(i)}\``:"\u2014"} | ${Bp(o,t)} | ${Gp(o)} | ${a} |`});return[...n,...r].join(`
203
+ `)}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: ${dn(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 ls(e){return e.map(t=>`- [${t}](#${t.toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/ /g,"-")})`).join(`
204
+ `)}var Wp=["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 Kp(e){let t=new Map(e.map(n=>[n.name,n]));return Wp.map(n=>t.get(n)).filter(n=>n!==void 0)}function cn(e,t){let{cmd:n}=e,r=Kp(t.capabilities),o=t.capabilities.find(a=>a.name==="presentation video"),i=o?Ir(o,n)??`${n} presentation video status <run-id>`:`${n} presentation video status <run-id>`;return`${pe(t,e)}
165
205
 
166
206
  # Deck \u2192 MP4 (\`${n} presentation video\`)
167
207
 
@@ -175,6 +215,7 @@ For a video that is not built from a deck, read
175
215
  ## Contents
176
216
 
177
217
  - [The lifecycle](#the-lifecycle)
218
+ - [Before you render](#before-you-render)
178
219
  - [Render settings](#render-settings)
179
220
  - [Draft editing, versions and presenters](#draft-editing-versions-and-presenters)
180
221
  - [Narration and speaker notes](#narration-and-speaker-notes)
@@ -183,19 +224,29 @@ For a video that is not built from a deck, read
183
224
  ## The lifecycle
184
225
 
185
226
  \`\`\`bash
186
- # 1) Create or reuse the version-pinned video project for a deck
227
+ # 0) No deck yet? Make one first.
228
+ ${n} create "\u2026"
229
+
230
+ # 1) Create or reuse the version-pinned video project for the deck.
231
+ # Picks the narration voice for you and reports it, plus the narration
232
+ # state. No presenter is chosen \u2014 that is the default, not a gap.
187
233
  ${n} presentation video prepare <presentation-id> --yes
188
234
 
189
- # 2) Read the project and its ordered scene timeline (slide ids live here)
235
+ # 2) Fill in narration when prepare reported it missing (costs credits)
236
+ ${n} presentation video narrate <project-id> --yes
237
+
238
+ # 3) Read the project back and SHOW the user what will be produced \u2014
239
+ # the narration here, and the deck's own slide copy alongside it.
190
240
  ${n} presentation video inspect <project-id>
241
+ ${n} get <presentation-id> --include slides
191
242
 
192
- # 3) Optional: persist render settings on the project
243
+ # 4) Optional: change what they asked to change
193
244
  ${n} presentation video settings <project-id> --settings ./settings.json --yes
194
245
 
195
- # 4) Render the MP4 \u2014 paid, background, requires --yes
246
+ # 5) Only after they say yes: render the MP4 \u2014 paid, background, requires --yes
196
247
  ${n} presentation video <presentation-id> --render-engine remotion --yes
197
248
 
198
- # 5) Poll until done
249
+ # 6) Poll until done
199
250
  ${i}
200
251
  \`\`\`
201
252
 
@@ -209,6 +260,91 @@ The render takes **either** a \`<presentation-id>\` argument **or**
209
260
  \`--render-engine\` applies to that one run only. It does not change narration,
210
261
  voice, presenter, music, captions, or the saved project setup.
211
262
 
263
+ ## Before you render
264
+
265
+ Everything before the render is repeatable, and only narration (step 2) costs
266
+ anything. Two approvals sit between the draft and the MP4, and they are not the
267
+ same approval.
268
+
269
+ Read the deck first, either way. The MP4 is this deck read aloud, so narration
270
+ that sounds right over a slide whose copy is wrong still renders wrong.
271
+ \`${n} get <presentation-id> --include slides\` returns every slide's title
272
+ and its body copy \u2014 the words taken from the slide's own HTML, the same text
273
+ the narrator was given. It is free, so there is no reason to approve a render
274
+ without having read what is on the slides.
275
+
276
+ **First, the script.** \`narrate\` writes the narration on the user's behalf,
277
+ so they read it before it is spoken.
278
+ \`${n} presentation video inspect <project-id>\` returns
279
+ \`scenes[].narration.text\` per scene \u2014 the exact words the voice will say. Put
280
+ those words in your reply, scene by scene; a project id is not the user reading
281
+ their own script. Rework one scene with
282
+ \`${n} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"\`.
283
+ That loop is cheap and drafts are append-only, so this is the affordable moment
284
+ to be wrong.
285
+
286
+ \`inspect\` also returns per scene \`title\`, \`durationSec\`, \`presenter\`
287
+ (the avatar on that scene, or \`null\`), \`excluded\` and \`imageReady\`, and at
288
+ project level \`renderSettings\`: \`voice\`, \`presenter\`, \`music\`,
289
+ \`captions\`, \`format\`, \`narrationDensity\` and \`renderEngine\`. Those
290
+ choices are the user's too \u2014 offer them and say which you would pick.
291
+ \`presenter: null\` means "slides only", which is the normal answer.
292
+
293
+ ### The voice is already chosen \u2014 show it, do not interview for it
294
+
295
+ \`prepare\` picks the narration voice the way the studio does: the voice this
296
+ user last chose if it is still ready, otherwise the workspace's first ready
297
+ voice. It reports the choice as \`voice\`:
298
+
299
+ \`\`\`json
300
+ { "voice": { "status": "selected", "source": "preference",
301
+ "voice": { "id": "\u2026", "label": "Ava" } } }
302
+ \`\`\`
303
+
304
+ So do not open with "which voice would you like?" \u2014 say which voice was
305
+ selected and offer to change it. \`status: "unavailable"\` is the only case
306
+ that needs a question: it means the workspace has no ready voice, or the voice
307
+ catalog is down, and the render will refuse until one is set.
308
+
309
+ To change it, \`${n} avatar options\` lists the real ids: stock avatars (with
310
+ render tiers), the workspace's own trained \`pp_*\` presenters, and the voices
311
+ (\`--language <lang>\` filters them; \`--format json\` adds gender and avatar
312
+ preview images). Every voice carries a \`previewUrl\` \u2014 an audio sample, so the
313
+ user can HEAR a shortlist instead of choosing a name blind. Then:
314
+
315
+ \`\`\`bash
316
+ ${n} presentation video settings <project-id> --yes --settings '{"voiceId":"<id>"}'
317
+ \`\`\`
318
+
319
+ ### No avatar is the default, on purpose
320
+
321
+ "Slides with a voiceover" is the normal product outcome, so \`presenter: null\`
322
+ is a finished setup, not a missing setting. Ask whether they want a presenter
323
+ on screen; never treat its absence as a misconfiguration to repair. If they do
324
+ want one:
325
+
326
+ \`\`\`bash
327
+ ${n} presentation video settings <project-id> --yes --settings '{"avatarId":"<id>"}'
328
+ ${n} presentation video presenter <project-id> <slide-id> --avatar-id <id> # one scene only
329
+ \`\`\`
330
+
331
+ To take the presenter back off, \`--settings '{"presenter":null}'\`.
332
+
333
+ Iterating is the cheap part, so iterate:
334
+
335
+ \`\`\`bash
336
+ ${n} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"
337
+ ${n} presentation video edit <project-id> --edit ./edit.json # patch, move or remove a scene
338
+ ${n} presentation video settings <project-id> --settings \u2026 --yes # voice, presenter, music, format, captions
339
+ ${n} presentation video refresh <project-id> # re-pull slides after the deck changed
340
+ ${n} presentation video versions <project-id> # drafts are append-only; nothing is lost
341
+ \`\`\`
342
+
343
+ **Then, the spend.** Only once the user has read the script and approved the
344
+ settings: \`${n} presentation video <presentation-id> --yes\`. That is the
345
+ second question \u2014 the money \u2014 and \`--yes\` is your statement of intent; it is
346
+ not their consent and never replaces asking.
347
+
212
348
  ## Render settings
213
349
 
214
350
  Both \`presentation video settings --settings\` and the render's own
@@ -222,8 +358,11 @@ file. At least one key is required.
222
358
  | \`music\` | object (see below) | Background music settings to merge into the saved project. |
223
359
  | \`narrationDensity\` | \`brief\` \\| \`balanced\` \\| \`deep\` | How much narration to generate per slide. |
224
360
  | \`presenter\` | object or \`null\` | Selected avatar/presenter, or null to remove it. |
361
+ | \`avatarId\` | string | Avatar/look id from \`avatar options\`; the server resolves the presenter identity. Alternative to \`presenter\`. |
362
+ | \`renderTier\` | \`basic\` \\| \`standard\` \\| \`premium\` | Render tier for \`avatarId\`. Only valid with \`avatarId\`. |
225
363
  | \`renderEngine\` | \`remotion\` \\| \`hyperframes\` | Terminal renderer for the MP4. |
226
364
  | \`voice\` | object or \`null\` | Selected narration voice, or null to clear it. |
365
+ | \`voiceId\` | string | Voice id from \`avatar options\`; the server resolves its label. Alternative to \`voice\`. |
227
366
 
228
367
  \`music\` keys: \`mode\` (\`basic\` \\| \`standard\` \\| \`stock\` \\| \`upload\` \\| \`off\`,
229
368
  default \`basic\`), \`volume\` (0\u20131), \`prompt\`, \`audioUrl\`, \`fileName\`,
@@ -236,6 +375,12 @@ default \`basic\`), \`volume\` (0\u20131), \`prompt\`, \`audioUrl\`, \`fileName\
236
375
  \`previewImageUrl\`, \`source\`) plus \`perSlideEnabled\` / \`perSlidePlacements\`
237
376
  maps keyed by slide id. Get real ids from \`${n} avatar options\`.
238
377
 
378
+ Because that roster reports ids, not those objects, \`voiceId\` and
379
+ \`avatarId\` accept what you can actually list and the server resolves the
380
+ rest. Passing both forms of one setting (\`voice\` and \`voiceId\`, or
381
+ \`presenter\` and \`avatarId\`) is refused rather than silently ranked;
382
+ \`presenter: null\` remains how a presenter is removed.
383
+
239
384
  Example:
240
385
 
241
386
  \`\`\`bash
@@ -291,11 +436,11 @@ not maintain a second copy.
291
436
 
292
437
  ## Every capability in this flow
293
438
 
294
- ${je(r,n)}
439
+ ${ze(r,n)}
295
440
 
296
441
  If something you need is not in this table, do not conclude it is missing \u2014
297
442
  run \`${n} capabilities --search video\`.
298
- `}var pp=["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 yr(e){let t=new Map(e.map(n=>[n.name,n]));return pp.map(n=>t.get(n)).filter(n=>n!==void 0)}function nn(e,t){let{cmd:n}=e,r=yr(t.capabilities);return`${le(t,e)}
443
+ `}var Jp=["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 Rr(e){let t=new Map(e.map(n=>[n.name,n]));return Jp.map(n=>t.get(n)).filter(n=>n!==void 0)}function ln(e,t){let{cmd:n}=e,r=Rr(t.capabilities);return`${pe(t,e)}
299
444
 
300
445
  # Video from scratch (\`${n} video\`)
301
446
 
@@ -309,6 +454,7 @@ There is no \`video export\` subcommand.
309
454
  ## Contents
310
455
 
311
456
  - [The hosted pipeline](#the-hosted-pipeline)
457
+ - [Before you generate](#before-you-generate)
312
458
  - [Storyboards](#storyboards)
313
459
  - [Other video operations](#other-video-operations)
314
460
  - [Every capability in this flow](#every-capability-in-this-flow)
@@ -344,6 +490,33 @@ browser confirmation URL, then repeat the **exact** invocation with
344
490
  never substitutes for one. \`--draft\` renders at 480p for a faster look;
345
491
  \`--source-video <id>\` reuses a finished video as base footage.
346
492
 
493
+ ## Before you generate
494
+
495
+ Steps 0-2 are cheap and repeatable. Two approvals sit between them and the MP4,
496
+ and they are not the same approval.
497
+
498
+ **First, the content.** The storyboard is text you wrote on the user's behalf,
499
+ so they read it before it is pinned.
500
+ \`${n} video storyboard show <storyboard-id>\` prints exactly that Markdown \u2014
501
+ the script, the shots, the pacing \u2014 and \`--json\` adds the structured response
502
+ with the revision ids. Put that text in your reply, take their edits, and fold
503
+ them back in with \`${n} video storyboard revise\`. Revisions are appended,
504
+ never overwritten, so iterating costs nothing and loses nothing; a revision is
505
+ immutable once \`video create\` pins it, which is why the reading happens now.
506
+
507
+ Offer the material choices instead of deciding them silently: the
508
+ \`--duration\` and \`--aspect\` the revision was created with, whether this is a
509
+ \`--draft\` look or the full-quality run, and any \`--media\` binding with
510
+ \`purpose\` \`identity\` \u2014 who appears in the shot is not something to guess.
511
+ Say what you would pick and why.
512
+
513
+ **Then, the spend.** \`video create\` costs credits, runs for minutes and
514
+ produces the file the user will send to other people. The browser confirmation
515
+ its approval receipt requires asks a person about **cost and destination**; it
516
+ does not show them the script, and it arrives after the revision is already
517
+ written. It is not the user reading the storyboard, so never let it stand in
518
+ for that. \`--yes\` states your intent and is neither.
519
+
347
520
  ## Storyboards
348
521
 
349
522
  \`storyboard create\` requires \`--file <path|->\`, \`--duration <seconds>\`,
@@ -405,42 +578,42 @@ ${n} video analyze \u2026 # analyze a video y
405
578
 
406
579
  ## Every capability in this flow
407
580
 
408
- ${je(r,n)}
581
+ ${ze(r,n)}
409
582
 
410
583
  If something you need is not in this table, do not conclude it is missing \u2014
411
584
  run \`${n} capabilities --search video\`.
412
- `}var gp=12,fp={media:"video.md",presentations:"deck-to-video.md"};function hp(e,t,n,r){let{cmd:o}=e,i=gr[n]??n,a=r.filter(fr),s=r.filter(m=>m.billing!==void 0&&m.billing!=="free"),l=fp[n],g=["Every capability",...a.length>0?["Background operations"]:[]];return`${le(t,e)}
585
+ `}var zp=12,Xp={media:"video.md",presentations:"deck-to-video.md"};function Hp(e,t,n,r){let{cmd:o}=e,i=kr[n]??n,a=r.filter(Cr),s=r.filter(p=>p.billing!==void 0&&p.billing!=="free"),l=Xp[n],f=["Every capability",...a.length>0?["Background operations"]:[]];return`${pe(t,e)}
413
586
 
414
587
  # ${n} \u2014 ${i}
415
588
 
416
589
  ${r.length} capabilit${r.length===1?"y":"ies"} in this category${s.length>0?`, ${s.length} of which ${s.length===1?"costs":"cost"} credits or ${s.length===1?"counts":"count"} against a plan quota`:", all free"}.${l?`
417
590
 
418
591
  Step-by-step flow: [${l}](${l}).`:""}
419
- ${r.length>gp?`
592
+ ${r.length>zp?`
420
593
  ## Contents
421
594
 
422
- ${Ja(g)}
595
+ ${ls(f)}
423
596
  `:""}
424
597
  ## Every capability
425
598
 
426
- ${je(r,o)}
599
+ ${ze(r,o)}
427
600
  ${a.length>0?`
428
601
  ## Background operations
429
602
 
430
603
  These return a run id immediately and keep working. Poll the status command
431
604
  until it reports done \u2014 do not assume success from the accept response.
432
605
 
433
- ${a.map(m=>`- \`${o} ${m.name}\` \u2192 \`${o} ${m.lifecycle?.status?.cliCommand??""} <run-id>\`${m.lifecycle?.status?.pollAfterSeconds?` (first poll after ~${m.lifecycle.status.pollAfterSeconds}s)`:""}`).join(`
606
+ ${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(`
434
607
  `)}
435
608
  `:""}
436
609
  Anything missing here? Run \`${o} capabilities --category ${n}\` \u2014 the
437
610
  catalog is authoritative and always current; this file is a snapshot of it.
438
- `}function za(e,t,n={}){let r=[{content:tn(e,t),name:"deck-to-video"},{content:nn(e,t),name:"video"}];for(let{capabilities:o,category:i}of ft(t.capabilities)){let a=n[i];r.push({content:hp(e,t,i,o)+(a?`
611
+ `}function ms(e,t,n={}){let r=[{content:cn(e,t),name:"deck-to-video"},{content:ln(e,t),name:"video"}];for(let{capabilities:o,category:i}of kt(t.capabilities)){let a=n[i];r.push({content:Hp(e,t,i,o)+(a?`
439
612
  ---
440
613
 
441
- ${a}`:""),name:i})}return r}function Xa(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 ft(e.capabilities))t.push({file:`${r}.md`,when:`${gr[r]??r} (${n.length} commands).`});return t}var yp=[{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"}],bp=["capabilities","config","delete","derive","export","ideas","import","list","login","logout","runner","skill","templates","whoami"];function rn(e,t=Rt("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])),s=yp.filter(v=>a.has(v.capability)).map(v=>`| ${v.intent} | \`${r} ${v.capability}${v.suffix??""}\` | [${v.reference}](references/${v.reference}) |`).join(`
442
- `),g=ft(t.capabilities).map(({capabilities:v,category:b})=>`${b} (${v.length})`).join(", "),m=Xa(t).map(({file:v,when:b})=>`| [references/${v}](references/${v}) | ${b} |`).join(`
443
- `),w=[...new Set([...t.capabilities.map(v=>v.name.split(" ")[0]),...bp])].sort().map(v=>`\`${v}\``).join(", ");return`---
614
+ ${a}`:""),name:i})}return r}function us(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 kt(e.capabilities))t.push({file:`${r}.md`,when:`${kr[r]??r} (${n.length} commands).`});return t}var Yp=[{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"}],Qp=["capabilities","config","delete","derive","export","footage","ideas","import","list","login","logout","runner","skill","templates","whoami"];function mn(e,t=_t("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(x=>[x.name,x])),s=Yp.filter(x=>a.has(x.capability)).map(x=>`| ${x.intent} | \`${r} ${x.capability}${x.suffix??""}\` | [${x.reference}](references/${x.reference}) |`).join(`
615
+ `),f=kt(t.capabilities).map(({capabilities:x,category:w})=>`${w} (${x.length})`).join(", "),p=us(t).map(({file:x,when:w})=>`| [references/${x}](references/${x}) | ${w} |`).join(`
616
+ `),v=[...new Set([...t.capabilities.map(x=>x.name.split(" ")[0]),...Qp])].sort().map(x=>`\`${x}\``).join(", ");return`---
444
617
  name: ${n}
445
618
  description: >-
446
619
  Use for ANY request involving presentations, decks, slides, pitch decks, PowerPoint,
@@ -453,7 +626,7 @@ description: >-
453
626
  ${t.capabilities.length} CLI capabilities, listed in references/.
454
627
  ---
455
628
 
456
- ${le(t,e)}
629
+ ${pe(t,e)}
457
630
 
458
631
  # ${n} CLI
459
632
 
@@ -485,6 +658,57 @@ no \`video export\` subcommand.
485
658
 
486
659
  ---
487
660
 
661
+ ## Approve the content, then approve the spend
662
+
663
+ Two different questions, asked at two different moments. "Yes, that is the
664
+ video I want" comes first; "yes, spend the credits" comes second. A
665
+ confirmation that names a cost and a destination has answered the second
666
+ question only \u2014 it never asked the first.
667
+
668
+ **Anything you authored on the user's behalf, they read before it is
669
+ committed.** The storyboard text, the narration script per scene: those are the
670
+ user's words, drafted for them, and they are the part most likely to be wrong.
671
+ Show the text itself in your reply \u2014 a link, a project id or a file path is not
672
+ the user reading it.
673
+
674
+ **Show it before it is pinned, not after.** A storyboard revision is immutable
675
+ and a render pins one; narration is what will actually be spoken. Revising is
676
+ free and append-only, so the cheap moment to be wrong is before the pin.
677
+
678
+ The material choices belong to the user too \u2014 voice, presenter or avatar,
679
+ music, captions, aspect, duration. Offer them rather than choosing silently,
680
+ and say what you would pick and why.
681
+
682
+ ---
683
+
684
+ ## A render is a purchase
685
+
686
+ \`${r} presentation video\` and \`${r} video create\` cost credits, take
687
+ minutes, and produce the file the user will show other people. Everything
688
+ before them \u2014 preparing the project, inspecting it, generating narration,
689
+ revising a storyboard, changing settings \u2014 is free or cheap and undoable. So
690
+ spend the cheap phase getting it right instead of rushing past it.
691
+
692
+ **This is the second gate, not the only one.** By the time you reach it the
693
+ content should already be approved; what you are asking for here is the money
694
+ and the target. Confirm what the run is pinned to and start it.
695
+
696
+ Where a choice comes from a list, offer the list. \`${r} avatar options\`
697
+ prints the real avatar, personal-presenter and voice ids \u2014 shortlist a few and
698
+ let the user pick rather than silently choosing one. "No presenter, slides
699
+ only" is a common and legitimate answer, so ask instead of assuming either way.
700
+
701
+ \`--yes\` is your statement of intent, not the user's consent. Only a person
702
+ can give that.
703
+
704
+ Everything free and reversible stays fluent \u2014 never ask permission to inspect a
705
+ project or reread a storyboard. The gate is content you authored, and money.
706
+
707
+ Per-pipeline detail: [deck-to-video.md](references/deck-to-video.md),
708
+ [video.md](references/video.md).
709
+
710
+ ---
711
+
488
712
  ## Composing commands
489
713
 
490
714
  Every table in \`references/\` carries a **Takes** and a **Returns** column. That
@@ -499,6 +723,14 @@ is enough to build a chain nobody wrote down. Derive the steps from the data:
499
723
  the optional ones, run \`${r} <group> <sub> --help\`.
500
724
  - If you cannot find a step, \`${r} capabilities --search <topic>\` is
501
725
  authoritative \u2014 not this file.
726
+ - Poll; do not wait. Options that block until a long generation finishes
727
+ (\`${r} create --wait\`, the default follow mode on
728
+ \`${r} presentation speaker-notes\`) stream progress to a TTY a
729
+ non-interactive shell does not have, and the command routinely outlives the
730
+ tool timeout. Take the run id and poll instead \u2014
731
+ \`${r} presentation status <run-id>\`,
732
+ \`${r} presentation speaker-notes-status <run-id>\`,
733
+ \`${r} presentation video status <run-id>\`.
502
734
 
503
735
  ---
504
736
 
@@ -529,7 +761,7 @@ Two things it does not cover: commands gated behind account feature flags (the
529
761
  \`${r} config refresh\`, and commands the CLI owns without a catalog entry are
530
762
  listed by \`${r} --help\`.
531
763
 
532
- Categories: ${g}.
764
+ Categories: ${f}.
533
765
 
534
766
  ---
535
767
 
@@ -537,7 +769,7 @@ Categories: ${g}.
537
769
 
538
770
  | File | Read it when |
539
771
  |---|---|
540
- ${m}
772
+ ${p}
541
773
 
542
774
  ---
543
775
 
@@ -569,7 +801,7 @@ does not declare.
569
801
 
570
802
  Run \`${r} <group> --help\` for any of these:
571
803
 
572
- ${w}
804
+ ${v}
573
805
 
574
806
  The groups the catalog owns are documented in \`references/\`. The rest are
575
807
  CLI-local and never appear in \`${r} capabilities\`: auth and config
@@ -582,7 +814,7 @@ CLI-local and never appear in \`${r} capabilities\`: auth and config
582
814
  - \`${r} create "Topic"\` \u2192 load the \`${n}-presentation\` skill
583
815
  - editing an existing deck \u2192 load the \`${n}-presentation-edit\` skill
584
816
  - building a video from a brief or storyboard, with no deck \u2192 load the \`${n}-video\` skill
585
- `}function on(e){let{name:t,cmd:n}=e;return`---
817
+ `}function un(e){let{name:t,cmd:n}=e;return`---
586
818
  name: ${t}-presentation-edit
587
819
  description: >
588
820
  Use ONLY when editing an already-created presentation that has real slides:
@@ -867,7 +1099,7 @@ Do NOT render or export the presentation \u2014 that's handled by the app.
867
1099
  | Create brand-new presentation (5+ slides, new topic) | \`${n} create ...\` via CLI |
868
1100
  | Redesign the whole deck | \`${n} create ...\` via CLI, then sync |
869
1101
  | User provides a URL to base the presentation on | \`${n} scrape <url>\` \u2192 \`${n} create ...\` |
870
- `}function an(e){let{name:t,cmd:n}=e;return`---
1102
+ `}function pn(e){let{name:t,cmd:n}=e;return`---
871
1103
  name: ${t}-presentation
872
1104
  description: Use when user asks to create presentations, slides, decks, pitch decks.
873
1105
  Researches the topic, gathers context, and generates AI-powered presentations via CLI.
@@ -898,7 +1130,7 @@ If this fails \u2192 **STOP**. Tell the user: \`${n} login\`. Do NOT proceed wit
898
1130
  | \`${n} scrape <url>\` | Scrape URL content |
899
1131
  | \`${n} list\` | List presentations |
900
1132
  | \`${n} get <id-or-slug>\` | Get details and canonical Studio/view URLs |
901
- | \`${n} export <id> -o file.zip\` | Export |
1133
+ | \`${n} export <id-or-slug> -o deck.html\` | Export to HTML/PDF/PPTX |
902
1134
  | \`${n} branding find <name-or-url>\` | Search existing brands (returns IDs) |
903
1135
  | \`${n} branding extract <url>\` | Extract NEW brand identity |
904
1136
  | \`${n} branding list\` | List saved brands |
@@ -1040,11 +1272,12 @@ ${n} create "Acme Corp Investor Pitch" \\
1040
1272
  ## Export (save to file)
1041
1273
 
1042
1274
  \`\`\`bash
1043
- # Export to ZIP (HTML + all assets)
1044
- ${n} export <slug> -o ./presentation.zip
1275
+ # Self-contained interactive HTML (default format)
1276
+ ${n} export <id-or-slug> -o ./presentation.html
1045
1277
 
1046
- # Export and unzip to folder
1047
- ${n} export <slug> -o ./presentation.zip && unzip -o ./presentation.zip -d ./presentation/
1278
+ # PDF or PowerPoint
1279
+ ${n} export <id-or-slug> -f pdf -o ./presentation.pdf
1280
+ ${n} export <id-or-slug> -f pptx -o ./presentation.pptx
1048
1281
 
1049
1282
  # Get slug from a just-created presentation
1050
1283
  ${n} get <id-or-slug> --format json
@@ -1075,7 +1308,7 @@ files inside its own local-runner workspace.
1075
1308
  \`\`\`bash
1076
1309
  ${n} list
1077
1310
  ${n} get <id-or-slug>
1078
- ${n} export <id-or-slug> -o presentation.zip
1311
+ ${n} export <id-or-slug> -o presentation.html
1079
1312
  ${n} delete <id-or-slug>
1080
1313
  ${n} import ./presentation.zip
1081
1314
  \`\`\`
@@ -1087,8 +1320,8 @@ ${n} import ./presentation.zip
1087
1320
  - **Auth fails** \u2192 \`${n} logout && ${n} login\` (browser required)
1088
1321
  - **"Context required"** \u2192 add \`--context\`, \`--file\`, or \`--context-file\`
1089
1322
  - **Rate limit (429)** \u2192 check plan with \`${n} whoami\`
1090
- `}var wp=[{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 sn(e,t){let{cmd:n,name:r,pkg:o}=e,i=new Set(t.capabilities.map(l=>l.name)),a=wp.filter(l=>i.has(l.capability)).map((l,g)=>`${g+1}. \`${n} ${l.capability}\` \u2014 ${l.when}`).join(`
1091
- `),s=yr(t.capabilities).length;return`---
1323
+ `}var Zp=[{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 gn(e,t){let{cmd:n,name:r,pkg:o}=e,i=new Set(t.capabilities.map(l=>l.name)),a=Zp.filter(l=>i.has(l.capability)).map((l,f)=>`${f+1}. \`${n} ${l.capability}\` \u2014 ${l.when}`).join(`
1324
+ `),s=Rr(t.capabilities).length;return`---
1092
1325
  name: ${r}-video
1093
1326
  description: >-
1094
1327
  Use when a video must be built from scratch \u2014 a brief, a script, a storyboard,
@@ -1099,7 +1332,7 @@ description: >-
1099
1332
  deck\u2192MP4 flow instead. ${s} CLI capabilities, listed in references/video.md.
1100
1333
  ---
1101
1334
 
1102
- ${le(t,e)}
1335
+ ${pe(t,e)}
1103
1336
 
1104
1337
  # ${r} video
1105
1338
 
@@ -1153,12 +1386,12 @@ ${n} video <sub> --help
1153
1386
  \`\`\`
1154
1387
 
1155
1388
  The catalog is authoritative and always current; this file is a snapshot of it.
1156
- `}function Ha(e,t){return[{content:nn(e,t),name:"video"},{content:tn(e,t),name:"deck-to-video"}]}import{existsSync as br,mkdirSync as Ya,rmSync as vp,writeFileSync as Qa}from"fs";import{homedir as ts}from"os";import{basename as xp,join as ve,relative as kp,resolve as ht}from"path";var Ae=[{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 Cp={sonnet:"claude-sonnet-4.6",haiku:"claude-haiku-4.5",opus:"claude-opus-4.6"},Ip=["permissionMode","skills","subagentType"];function Rp(e,t){if(t!=="copilot")return e;let n=e.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return Za(e);let r=n[1],o=e.slice((n.index??0)+n[0].length);r=r.replace(/^(model:\s*)(\S+)([ \t]*)$/m,(a,s,l,g)=>`${s}${Cp[l]??l}${g}`);for(let a of Ip)r=r.replace(new RegExp(`^${a}:[^
1389
+ `}function ps(e,t){return[{content:ln(e,t),name:"video"},{content:cn(e,t),name:"deck-to-video"}]}import{existsSync as Sr,mkdirSync as gs,rmSync as eg,writeFileSync as fs}from"fs";import{homedir as bs}from"os";import{basename as tg,join as Re,relative as ng,resolve as Ct}from"path";var De=[{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 rg={sonnet:"claude-sonnet-4.6",haiku:"claude-haiku-4.5",opus:"claude-opus-4.6"},og=["permissionMode","skills","subagentType"];function ig(e,t){if(t!=="copilot")return e;let n=e.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return hs(e);let r=n[1],o=e.slice((n.index??0)+n[0].length);r=r.replace(/^(model:\s*)(\S+)([ \t]*)$/m,(a,s,l,f)=>`${s}${rg[l]??l}${f}`);for(let a of og)r=r.replace(new RegExp(`^${a}:[^
1157
1390
  ]*
1158
- ?`,"m"),"");r=r.replace(/\n+$/,"");let i=Za(o);return`---
1391
+ ?`,"m"),"");r=r.replace(/\n+$/,"");let i=hs(o);return`---
1159
1392
  ${r}
1160
1393
  ---
1161
- ${i}`}function Za(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 Sp(e,t){let n=ht(e),r=ht(e,t);if(kp(n,r).startsWith("..")||ht(r)!==r.replace(/\.\./g,""))throw new Error(`Invalid path: "${t}" would escape base directory`);return r}function es(e,t,n,r){let o=ve(e,"SKILL.md");if(Ya(e,{recursive:!0}),Qa(o,Rp(t,r),"utf-8"),n&&n.length>0){let i=ve(e,"references");Ya(i,{recursive:!0});for(let a of n){let s=ve(i,`${a.name}.md`);Qa(s,a.content,"utf-8")}}}function dn(e,t,n={},r){let o={installed:[],skipped:[],errors:[]},i=n.local?process.cwd():ts();if(n.dir){let a=xp(ht(n.dir)),s=Ae.find(l=>l.dir===a)?.provider;try{let l=ht(n.dir),g=Sp(l,ve("skills",e));es(g,t,r,s),o.installed.push(n.dir)}catch(l){o.errors.push(`${n.dir}: ${l instanceof Error?l.message:String(l)}`)}}else for(let a of Ae){let s=ve(i,a.dir),l=ve(s,"skills",e),g=ve(l,"SKILL.md");if(br(s)){if(br(g)&&!n.force){o.skipped.push(a.name);continue}try{es(l,t,r,a.provider),o.installed.push(a.name)}catch(m){o.errors.push(`${a.name}: ${m instanceof Error?m.message:String(m)}`)}}}return o}function cn(e,t={}){let n={removed:[],errors:[]},r=t.local?process.cwd():ts();for(let o of Ae){let i=ve(r,o.dir,"skills",e);if(br(i))try{vp(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 ns(){return Ae.map(e=>e.name)}function Ge(e){let{name:t,cmd:n}=e;return`---
1394
+ ${i}`}function hs(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 ag(e,t){let n=Ct(e),r=Ct(e,t);if(ng(n,r).startsWith("..")||Ct(r)!==r.replace(/\.\./g,""))throw new Error(`Invalid path: "${t}" would escape base directory`);return r}function ys(e,t,n,r){let o=Re(e,"SKILL.md");if(gs(e,{recursive:!0}),fs(o,ig(t,r),"utf-8"),n&&n.length>0){let i=Re(e,"references");gs(i,{recursive:!0});for(let a of n){let s=Re(i,`${a.name}.md`);fs(s,a.content,"utf-8")}}}function fn(e,t,n={},r){let o={installed:[],skipped:[],errors:[]},i=n.local?process.cwd():bs();if(n.dir){let a=tg(Ct(n.dir)),s=De.find(l=>l.dir===a)?.provider;try{let l=Ct(n.dir),f=ag(l,Re("skills",e));ys(f,t,r,s),o.installed.push(n.dir)}catch(l){o.errors.push(`${n.dir}: ${l instanceof Error?l.message:String(l)}`)}}else for(let a of De){let s=Re(i,a.dir),l=Re(s,"skills",e),f=Re(l,"SKILL.md");if(Sr(s)){if(Sr(f)&&!n.force){o.skipped.push(a.name);continue}try{ys(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 hn(e,t={}){let n={removed:[],errors:[]},r=t.local?process.cwd():bs();for(let o of De){let i=Re(r,o.dir,"skills",e);if(Sr(i))try{eg(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 ws(){return De.map(e=>e.name)}function Xe(e){let{name:t,cmd:n}=e;return`---
1162
1395
  name: ${t}-tts
1163
1396
  description: Text-to-speech generation. Convert text to natural speech with multiple providers (Gemini, ElevenLabs, OpenAI) and voices. Use for voiceovers, narration, accessibility.
1164
1397
  ---
@@ -1358,7 +1591,7 @@ ${n} tts generate \\
1358
1591
  2. **Voice matching** - Match voice style to content: Puck for upbeat, Charon for serious
1359
1592
  3. **Speed adjustment** - Use 0.9-0.95 for narration, 1.0-1.1 for casual
1360
1593
  4. **Multiple voiceovers** - Run \`${n} tts generate\` once per line and poll each run with \`${n} tts status <run-id>\`
1361
- `}function Be(e){let{name:t,cmd:n}=e;return`---
1594
+ `}function He(e){let{name:t,cmd:n}=e;return`---
1362
1595
  name: ${t}-music
1363
1596
  description: Generate music that follows a video's narration and final timing. Gemini plans the provider prompt on the backend.
1364
1597
  ---
@@ -1384,7 +1617,7 @@ ${n} music status <request-id>
1384
1617
  \`\`\`
1385
1618
 
1386
1619
  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.
1387
- `}function We(e){let{name:t,cmd:n}=e;return`---
1620
+ `}function Ye(e){let{name:t,cmd:n}=e;return`---
1388
1621
  name: ${t}-sfx
1389
1622
  description: Generate one sound effect aligned with a final visual event and narration. Gemini plans the provider prompt on the backend.
1390
1623
  ---
@@ -1422,7 +1655,7 @@ ${n} sfx status <request-id>
1422
1655
  \`\`\`
1423
1656
 
1424
1657
  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.
1425
- `}function Ke(e){let{name:t,cmd:n}=e;return`---
1658
+ `}function Qe(e){let{name:t,cmd:n}=e;return`---
1426
1659
  name: ${t}-mix
1427
1660
  description: Audio mixing for video production. Combine video with voiceover and background music. Supports volume control, fade effects, and multiple audio tracks.
1428
1661
  ---
@@ -1572,7 +1805,7 @@ ${n} mix status <request-id>
1572
1805
  2. **Music selection** - Choose music that doesn't compete with voice frequency.
1573
1806
  3. **Consistent levels** - Keep voice at 100%, adjust music only.
1574
1807
  4. **File sizes** - Use \`--no-wait\` for large files to avoid timeout.
1575
- `}function Je(e){let{name:t,cmd:n}=e;return`---
1808
+ `}function Ze(e){let{name:t,cmd:n}=e;return`---
1576
1809
  name: ${t}-image
1577
1810
  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.
1578
1811
  ---
@@ -1769,7 +2002,7 @@ Found 10 images for "mountain landscape"
1769
2002
  3. **Size matters** - Use \`--size large\` for hero images
1770
2003
  4. **JSON for automation** - Parse results programmatically
1771
2004
  5. **Generation prompts** - Be detailed, describe style, lighting, composition
1772
- `}function ze(e){let{name:t,cmd:n}=e;return`---
2005
+ `}function et(e){let{name:t,cmd:n}=e;return`---
1773
2006
  name: ${t}-video-search
1774
2007
  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.
1775
2008
  ---
@@ -1967,7 +2200,7 @@ ${n} video find "city timelapse" --orientation landscape -n 10
1967
2200
  3. **Preview first** - Use preview URLs to check quality
1968
2201
  4. **License** - Verify license for commercial use
1969
2202
  5. **JSON export** - Save searches for batch processing
1970
- `}function Xe(e){let{name:t,cmd:n}=e;return`---
2203
+ `}function tt(e){let{name:t,cmd:n}=e;return`---
1971
2204
  name: ${t}-scrape
1972
2205
  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.
1973
2206
  ---
@@ -2157,7 +2390,7 @@ ${n} scrape https://blog.example.com -f quiet | ${n} create "Blog Summary"
2157
2390
  3. **Use JSON** - For programmatic processing of results
2158
2391
  4. **Combine sources** - Scrape multiple URLs for comprehensive context
2159
2392
  5. **Token count** - Check token usage for large documents
2160
- `}function He(e){let{name:t,cmd:n}=e;return`---
2393
+ `}function nt(e){let{name:t,cmd:n}=e;return`---
2161
2394
  name: ${t}-branding
2162
2395
  description: Brand profile management. Extract branding from websites, manage saved brands, apply consistent styling to presentations.
2163
2396
  ---
@@ -2267,7 +2500,7 @@ ${n} branding set-default abc123
2267
2500
  2. **If extraction fails** \u2014 Proceed without branding. Do not manually create brand assets.
2268
2501
  3. **Set default** \u2014 If you mostly work with one brand, set it as default.
2269
2502
  4. **Override** \u2014 Use \`--brand\` flag to override default for specific presentations.
2270
- `}function Ye(e){let{name:t,cmd:n}=e,r=t.toUpperCase().replace(/[^A-Z0-9]/g,"_");return`---
2503
+ `}function rt(e){let{name:t,cmd:n}=e,r=t.toUpperCase().replace(/[^A-Z0-9]/g,"_");return`---
2271
2504
  name: ${t}-config
2272
2505
  description: CLI configuration management. Set API keys, team IDs, custom API URLs. Verify authentication status.
2273
2506
  ---
@@ -2428,87 +2661,89 @@ ${n} config show --verify # Test API key
2428
2661
  \`\`\`bash
2429
2662
  ${n} config set team-id <correct-team-id>
2430
2663
  \`\`\`
2431
- `}var Qe=["main","video","presentation","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","config"],ln=["standalone","studio"],rs={cmd:u.commands[0],pkg:u.packageName,url:u.apiUrl,name:u.name},Ze=new $p("skill").description(`Manage ${u.displayName} skills for AI coding assistants`).addHelpText("after",`
2432
- ${q.bold("Skill Types:")}
2433
- ${q.cyan("main")} Main CLI skill with all capabilities overview
2434
- ${q.cyan("video")} Video-from-scratch pipeline (storyboard \u2192 render)
2435
- ${q.cyan("presentation")} Detailed presentation creation workflow
2436
- ${q.cyan("presentation-edit")} In-app presentation editing (Studio)
2437
-
2438
- ${q.bold("Reference Skills:")}
2439
- ${q.cyan("tts")} Text-to-speech generation (voices, providers, options)
2440
- ${q.cyan("music")} AI music generation (prompts, styles, duration)
2441
- ${q.cyan("sfx")} Sound effects generation (categories, looping, formats)
2442
- ${q.cyan("mix")} Audio mixing (video + voice + music)
2443
- ${q.cyan("image")} Image search and AI generation
2444
- ${q.cyan("video-search")} Stock video search
2445
- ${q.cyan("scrape")} URL content extraction
2446
- ${q.cyan("branding")} Brand profile management
2447
- ${q.cyan("config")} CLI configuration management
2448
-
2449
- ${q.bold("Examples:")}
2450
- ${q.gray("# Install main CLI skill (comprehensive overview)")}
2451
- $ ${u.commands[0]} skill install main
2452
-
2453
- ${q.gray("# Install video skill")}
2454
- $ ${u.commands[0]} skill install video
2455
-
2456
- ${q.gray("# Install presentation skill")}
2457
- $ ${u.commands[0]} skill install presentation
2458
-
2459
- ${q.gray("# Install all skills")}
2460
- $ ${u.commands[0]} skill install
2461
-
2462
- ${q.gray("# Install to specific directory")}
2463
- $ ${u.commands[0]} skill install main --dir ~/.claude
2464
-
2465
- ${q.gray("# Show skill content")}
2466
- $ ${u.commands[0]} skill show main
2467
- `);Ze.command("install").description(`Install ${u.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&&!ln.includes(t.mode)&&(d(`Invalid mode: ${t.mode}. Must be one of: ${ln.join(", ")}`),process.exit(1));let n={...rs,mode:t.mode},r=[];e&&!Qe.includes(e)&&(d(`Invalid skill type: ${e}. Must be one of: ${Qe.join(", ")}`),process.exit(1));let o=await nt();o.source==="snapshot"&&(M(`Live capability catalog unavailable (${o.reason??"unknown reason"}) \u2014 generating from the snapshot baked into this CLI.`),console.log(q.gray(` Run \`${u.commands[0]} login\` then re-run with --force to regenerate from the live catalog.`)));let i=[...za(n,o,{branding:He(n)}),{name:"tts",content:Ge(n)},{name:"music",content:Be(n)},{name:"sfx",content:We(n)},{name:"mix",content:Ke(n)},{name:"image",content:Je(n)},{name:"video-search",content:ze(n)},{name:"scrape",content:Xe(n)},{name:"config",content:Ye(n)}];(!e||e==="main")&&r.push({name:u.name,content:rn(n,o),references:i}),(!e||e==="video")&&r.push({content:sn(n,o),name:`${u.name}-video`,references:Ha(n,o)}),(!e||e==="presentation")&&r.push({name:`${u.name}-presentation`,content:an(n)}),(!e||e==="presentation-edit")&&r.push({name:`${u.name}-presentation-edit`,content:on(n)}),e==="tts"&&r.push({name:`${u.name}-tts`,content:Ge(n)}),e==="music"&&r.push({name:`${u.name}-music`,content:Be(n)}),e==="sfx"&&r.push({name:`${u.name}-sfx`,content:We(n)}),e==="mix"&&r.push({name:`${u.name}-mix`,content:Ke(n)}),e==="image"&&r.push({name:`${u.name}-image`,content:Je(n)}),e==="video-search"&&r.push({name:`${u.name}-video-search`,content:ze(n)}),e==="scrape"&&r.push({name:`${u.name}-scrape`,content:Xe(n)}),e==="branding"&&r.push({name:`${u.name}-branding`,content:He(n)}),e==="config"&&r.push({name:`${u.name}-config`,content:Ye(n)}),console.log();for(let a of r){f(`Installing ${a.name}...`);let s=dn(a.name,a.content,{dir:t.dir,local:t.local,force:t.force},a.references);if(s.installed.length>0&&(C(`${a.name} installed successfully`),S(" Installed to",s.installed.join(", "))),s.skipped.length>0&&(f(` Skipped (already exists): ${s.skipped.join(", ")}`),console.log(q.gray(" Use --force to overwrite"))),s.errors.length>0)for(let l of s.errors)d(` ${l}`);s.installed.length===0&&s.skipped.length===0&&s.errors.length===0&&(f(" No supported AI coding assistants detected"),console.log(q.gray(` Supported editors: ${ns().join(", ")}`)),console.log(q.gray(" Use --dir <path> to install to a specific directory"))),console.log()}});Ze.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&&!ln.includes(t.mode)&&(d(`Invalid mode: ${t.mode}. Must be one of: ${ln.join(", ")}`),process.exit(1));let n={...rs,mode:t.mode},r=await nt(),i={main:()=>rn(n,r),video:()=>sn(n,r),presentation:()=>an(n),"presentation-edit":()=>on(n),tts:()=>Ge(n),music:()=>Be(n),sfx:()=>We(n),mix:()=>Ke(n),image:()=>Je(n),"video-search":()=>ze(n),scrape:()=>Xe(n),branding:()=>He(n),config:()=>Ye(n)}[e];i?console.log(i()):(d(`Invalid skill type: ${e}. Must be one of: ${Qe.join(", ")}`),process.exit(1))});Ze.command("uninstall").description(`Remove ${u.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&&!Qe.includes(e)&&(d(`Invalid skill type: ${e}. Must be one of: ${Qe.join(", ")}`),process.exit(1)),(!e||e==="main")&&n.push(u.name),(!e||e==="video")&&n.push(`${u.name}-video`),(!e||e==="presentation")&&n.push(`${u.name}-presentation`),(!e||e==="presentation-edit")&&n.push(`${u.name}-presentation-edit`),(!e||e==="tts")&&n.push(`${u.name}-tts`),(!e||e==="music")&&n.push(`${u.name}-music`),(!e||e==="sfx")&&n.push(`${u.name}-sfx`),(!e||e==="mix")&&n.push(`${u.name}-mix`),(!e||e==="image")&&n.push(`${u.name}-image`),(!e||e==="video-search")&&n.push(`${u.name}-video-search`),(!e||e==="scrape")&&n.push(`${u.name}-scrape`),(!e||e==="branding")&&n.push(`${u.name}-branding`),(!e||e==="config")&&n.push(`${u.name}-config`),console.log();for(let r of n){let o=cn(r,{local:t.local});if(o.removed.length>0?(C(`${r} uninstalled`),S(" Removed from",o.removed.join(", "))):f(` ${r} not found`),o.errors.length>0)for(let i of o.errors)M(` Failed to remove: ${i}`)}console.log()});import{Command as Tp}from"commander";import yt from"chalk";var os=new Tp("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)","table").option("--limit <n>","Maximum templates to list","25").action(async(e,t)=>{await A();try{let n=Number.parseInt(t.limit??"25",10),{templates:r}=await Zr(e,Number.isFinite(n)?n:25);if(r.length===0){t.format==="json"?console.log(JSON.stringify([])):f("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?yt.green("default"):null,o.category??null,o.recommendedModes?.length?`modes: ${o.recommendedModes.join("/")}`:null].filter(Boolean).join(" \xB7 ");console.log(`${yt.bold(o.name)} ${yt.gray(o.id)}${i?`
2468
- ${yt.gray(i)}`:""}`)}console.log(),console.log(yt.gray(`Use one with: ${u.commands[0]} create "<topic>" --template <id>`))}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Ep}from"commander";import wr from"chalk";var is=new Ep("whoami").description("Show current user and team information").option("-f, --format <format>","Output format (human, json)","human").action(async e=>{await A();try{let t=await me();if(In(),e.format==="json"){console.log(JSON.stringify(t,null,2));return}oe("User"),console.log(),S("Email",t.user.email),t.user.username&&S("Username",t.user.username),(t.user.firstName||t.user.lastName)&&S("Name",[t.user.firstName,t.user.lastName].filter(Boolean).join(" "));let n=t.authType==="apiKey"?"API Key":t.authType==="oauth"?"OAuth":"Session";if(S("Auth Type",n),t.currentTeam&&(console.log(),oe("Current Team"),console.log(),S("ID",t.currentTeam.id),S("Name",t.currentTeam.name),S("Plan",t.currentTeam.planName),S("Role",t.currentTeam.isOwner?"Owner":"Member")),t.teams.length>1){console.log(),oe("All Teams"),console.log();for(let r of t.teams){let o=r.isCurrent?wr.green(" (current)"):"";console.log(` ${wr.bold(r.name)}${o}`),console.log(wr.gray(` ID: ${r.id} | Plan: ${r.planName} | Role: ${r.role}`))}}console.log()}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}});function as(e){return e[0]==="--"?e.slice(1):e}var Op="0.3.18",G=new Ap,L=u.commands[0];G.name(L).description(`${u.displayName} CLI \u2014 presentations, videos, avatars, audio, branding, media and research`).version(Op,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output").configureOutput({outputError:(e,t)=>{t(F.red(e))}});G.addCommand(Oo);ja(G);G.addCommand(Ko);G.addCommand(Rn);G.addCommand(Wo);G.addCommand(os);G.addCommand(Go);G.addCommand(qo);G.addCommand(is);G.addCommand(Yo);G.addCommand(Qo);G.addCommand(Uo);G.addCommand(Ze);G.addCommand(Dt);var ss=Vo();ss.commands.length>0&&G.addCommand(ss);function Pp(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]}function _p(e){let t=e.toLowerCase(),n=t.length<=4?1:2,r,o=Number.POSITIVE_INFINITY;for(let i of G.commands)for(let a of[i.name(),...i.aliases()]){let s=Pp(t,a.toLowerCase());s<o&&(o=s,r=i.name())}return r!==void 0&&o<=n?r:void 0}G.on("command:*",e=>{let t=String(e[0]);console.error(F.red(`Error: Unknown command '${t}'`)),console.error();let n=_p(t);n&&console.error(`Did you mean '${n}'?`),console.error(`Run '${L} --help' to see available commands.`),console.error(`Run '${L} capabilities' for the full list of callable capabilities.`),process.exit(1)});G.addHelpText("after",`
2469
- ${F.bold("Start here:")}
2470
- $ ${L} capabilities ${F.gray("# every capability + its exact command path")}
2471
- $ ${L} <group> --help ${F.gray("# drill into any command group above")}
2472
-
2473
- ${F.bold("Common tasks:")}
2474
- ${F.gray("Make a presentation")}
2475
- $ ${L} create "<topic>" --context "..."
2476
- ${F.gray("Turn a finished presentation into an MP4 (narration + avatar)")}
2477
- $ ${L} presentation video <slug>
2478
- ${F.gray("Export a presentation as a ZIP of HTML + assets")}
2479
- $ ${L} export <slug> -o deck.zip
2480
- ${F.gray("Make a video from scratch (no deck)")}
2481
- $ ${L} video storyboard create ${F.gray("then")} $ ${L} video create
2482
- ${F.gray("Regenerate one slide's narration in a video draft")}
2483
- $ ${L} presentation video-narration <project-id>
2484
- ${F.gray("Generate speaker notes")}
2485
- $ ${L} presentation speaker-notes <presentation-id>
2486
- ${F.gray("Import a PowerPoint")}
2487
- $ ${L} presentation import
2488
- ${F.gray("Extract a brand identity from a URL")}
2489
- $ ${L} branding extract <url>
2490
- ${F.gray("Voiceover, music, sound effects")}
2491
- $ ${L} tts generate | ${L} music generate | ${L} sfx generate
2492
- ${F.gray("Find stock footage / images")}
2493
- $ ${L} video find | ${L} image search
2494
- ${F.gray("Read a web page or a YouTube transcript")}
2495
- $ ${L} scrape <url> | ${L} transcript <url>
2496
-
2497
- ${F.bold("Two different video pipelines:")}
2498
- '${L} presentation video ...' renders an EXISTING deck to MP4.
2499
- '${L} video ...' builds a video from a storyboard or brief with stock
2664
+ `}var ot=["main","video","presentation","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","config"],yn=["standalone","studio"],vs={cmd:m.commands[0],pkg:m.packageName,url:m.apiUrl,name:m.name},it=new sg("skill").description(`Manage ${m.displayName} skills for AI coding assistants`).addHelpText("after",`
2665
+ ${M.bold("Skill Types:")}
2666
+ ${M.cyan("main")} Main CLI skill with all capabilities overview
2667
+ ${M.cyan("video")} Video-from-scratch pipeline (storyboard \u2192 render)
2668
+ ${M.cyan("presentation")} Detailed presentation creation workflow
2669
+ ${M.cyan("presentation-edit")} In-app presentation editing (Studio)
2670
+
2671
+ ${M.bold("Reference Skills:")}
2672
+ ${M.cyan("tts")} Text-to-speech generation (voices, providers, options)
2673
+ ${M.cyan("music")} AI music generation (prompts, styles, duration)
2674
+ ${M.cyan("sfx")} Sound effects generation (categories, looping, formats)
2675
+ ${M.cyan("mix")} Audio mixing (video + voice + music)
2676
+ ${M.cyan("image")} Image search and AI generation
2677
+ ${M.cyan("video-search")} Stock video search
2678
+ ${M.cyan("scrape")} URL content extraction
2679
+ ${M.cyan("branding")} Brand profile management
2680
+ ${M.cyan("config")} CLI configuration management
2681
+
2682
+ ${M.bold("Examples:")}
2683
+ ${M.gray("# Install main CLI skill (comprehensive overview)")}
2684
+ $ ${m.commands[0]} skill install main
2685
+
2686
+ ${M.gray("# Install video skill")}
2687
+ $ ${m.commands[0]} skill install video
2688
+
2689
+ ${M.gray("# Install presentation skill")}
2690
+ $ ${m.commands[0]} skill install presentation
2691
+
2692
+ ${M.gray("# Install all skills")}
2693
+ $ ${m.commands[0]} skill install
2694
+
2695
+ ${M.gray("# Install to specific directory")}
2696
+ $ ${m.commands[0]} skill install main --dir ~/.claude
2697
+
2698
+ ${M.gray("# Show skill content")}
2699
+ $ ${m.commands[0]} skill show main
2700
+ `);it.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&&!yn.includes(t.mode)&&(d(`Invalid mode: ${t.mode}. Must be one of: ${yn.join(", ")}`),process.exit(1));let n={...vs,mode:t.mode},r=[];e&&!ot.includes(e)&&(d(`Invalid skill type: ${e}. Must be one of: ${ot.join(", ")}`),process.exit(1));let o=await dt();o.source==="snapshot"&&(F(`Live capability catalog unavailable (${o.reason??"unknown reason"}) \u2014 generating from the snapshot baked into this CLI.`),console.log(M.gray(` Run \`${m.commands[0]} login\` then re-run with --force to regenerate from the live catalog.`)));let i=[...ms(n,o,{branding:nt(n)}),{name:"tts",content:Xe(n)},{name:"music",content:He(n)},{name:"sfx",content:Ye(n)},{name:"mix",content:Qe(n)},{name:"image",content:Ze(n)},{name:"video-search",content:et(n)},{name:"scrape",content:tt(n)},{name:"config",content:rt(n)}];(!e||e==="main")&&r.push({name:m.name,content:mn(n,o),references:i}),(!e||e==="video")&&r.push({content:gn(n,o),name:`${m.name}-video`,references:ps(n,o)}),(!e||e==="presentation")&&r.push({name:`${m.name}-presentation`,content:pn(n)}),(!e||e==="presentation-edit")&&r.push({name:`${m.name}-presentation-edit`,content:un(n)}),e==="tts"&&r.push({name:`${m.name}-tts`,content:Xe(n)}),e==="music"&&r.push({name:`${m.name}-music`,content:He(n)}),e==="sfx"&&r.push({name:`${m.name}-sfx`,content:Ye(n)}),e==="mix"&&r.push({name:`${m.name}-mix`,content:Qe(n)}),e==="image"&&r.push({name:`${m.name}-image`,content:Ze(n)}),e==="video-search"&&r.push({name:`${m.name}-video-search`,content:et(n)}),e==="scrape"&&r.push({name:`${m.name}-scrape`,content:tt(n)}),e==="branding"&&r.push({name:`${m.name}-branding`,content:nt(n)}),e==="config"&&r.push({name:`${m.name}-config`,content:rt(n)}),console.log();for(let a of r){g(`Installing ${a.name}...`);let s=fn(a.name,a.content,{dir:t.dir,local:t.local,force:t.force},a.references);if(s.installed.length>0&&(I(`${a.name} installed successfully`),$(" Installed to",s.installed.join(", "))),s.skipped.length>0&&(g(` Skipped (already exists): ${s.skipped.join(", ")}`),console.log(M.gray(" Use --force to overwrite"))),s.errors.length>0)for(let l of s.errors)d(` ${l}`);s.installed.length===0&&s.skipped.length===0&&s.errors.length===0&&(g(" No supported AI coding assistants detected"),console.log(M.gray(` Supported editors: ${ws().join(", ")}`)),console.log(M.gray(" Use --dir <path> to install to a specific directory"))),console.log()}});it.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&&!yn.includes(t.mode)&&(d(`Invalid mode: ${t.mode}. Must be one of: ${yn.join(", ")}`),process.exit(1));let n={...vs,mode:t.mode},r=await dt(),i={main:()=>mn(n,r),video:()=>gn(n,r),presentation:()=>pn(n),"presentation-edit":()=>un(n),tts:()=>Xe(n),music:()=>He(n),sfx:()=>Ye(n),mix:()=>Qe(n),image:()=>Ze(n),"video-search":()=>et(n),scrape:()=>tt(n),branding:()=>nt(n),config:()=>rt(n)}[e];i?console.log(i()):(d(`Invalid skill type: ${e}. Must be one of: ${ot.join(", ")}`),process.exit(1))});it.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&&!ot.includes(e)&&(d(`Invalid skill type: ${e}. Must be one of: ${ot.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=hn(r,{local:t.local});if(o.removed.length>0?(I(`${r} uninstalled`),$(" Removed from",o.removed.join(", "))):g(` ${r} not found`),o.errors.length>0)for(let i of o.errors)F(` Failed to remove: ${i}`)}console.log()});import{Command as dg}from"commander";import It from"chalk";var xs=new dg("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 go(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?It.green("default"):null,o.category??null,o.recommendedModes?.length?`modes: ${o.recommendedModes.join("/")}`:null].filter(Boolean).join(" \xB7 ");console.log(`${It.bold(o.name)} ${It.gray(o.id)}${i?`
2701
+ ${It.gray(i)}`:""}`)}console.log(),console.log(It.gray(`Use one with: ${m.commands[0]} create "<topic>" --template <id>`))}catch(n){d(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as cg}from"commander";import $r from"chalk";var ks=new cg("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(An(),e.format==="json"){console.log(JSON.stringify(t,null,2));return}oe("User"),console.log(),$("Email",t.user.email),t.user.username&&$("Username",t.user.username),(t.user.firstName||t.user.lastName)&&$("Name",[t.user.firstName,t.user.lastName].filter(Boolean).join(" "));let n=t.authType==="apiKey"?"API Key":t.authType==="oauth"?"OAuth":"Session";if($("Auth Type",n),t.currentTeam&&(console.log(),oe("Current Team"),console.log(),$("ID",t.currentTeam.id),$("Name",t.currentTeam.name),$("Plan",t.currentTeam.planName),$("Role",t.currentTeam.isOwner?"Owner":"Member")),t.teams.length>1){console.log(),oe("All Teams"),console.log();for(let r of t.teams){let o=r.isCurrent?$r.green(" (current)"):"";console.log(` ${$r.bold(r.name)}${o}`),console.log($r.gray(` ID: ${r.id} | Plan: ${r.planName} | Role: ${r.role}`))}}console.log()}catch(t){d(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}});function Cs(e){return e[0]==="--"?e.slice(1):e}import Tr from"chalk";function Er(e){e.configureOutput({outputError:(t,n)=>{n(Tr.red(t));let r=/unknown option '(-{1,2}[^'\s=]+)/.exec(t);if(!r)return;let o=mg(e,r[1]);o&&n(Tr.yellow(`Did you mean '${o}'?
2702
+ `)),n(Tr.gray(`Run '${lg(e)} --help' to see the accepted options.
2703
+ `))}});for(let t of e.commands)Er(t)}function lg(e){let t=[],n=e;for(;n;)t.unshift(n.name()),n=n.parent;return t.join(" ")}function mg(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 s=Ar(t,a);s<r&&(r=s,n=i.flags)}let o=t.startsWith("--")?2:1;return n!==void 0&&r<=o?n:void 0}function Ar(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 pg="0.3.20",W=new ug,N=m.commands[0];W.name(N).description(`${m.displayName} CLI \u2014 presentations, videos, avatars, audio, branding, media and research`).version(pg,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output");W.addCommand(Wo);is(W);W.addCommand(ii);W.addCommand(oi);W.addCommand(xs);W.addCommand(ni);W.addCommand(Qo);W.addCommand(ks);W.addCommand(li);W.addCommand(mi);W.addCommand(Yo);W.addCommand(it);W.addCommand(Vt);var Is=ti();Is.commands.length>0&&W.addCommand(Is);function gg(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 s=Ar(t,a.toLowerCase());s<o&&(o=s,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=gg(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",`
2704
+ ${G.bold("Start here:")}
2705
+ $ ${N} capabilities ${G.gray("# every capability + its exact command path")}
2706
+ $ ${N} <group> --help ${G.gray("# drill into any command group above")}
2707
+
2708
+ ${G.bold("Common tasks:")}
2709
+ ${G.gray("Make a presentation")}
2710
+ $ ${N} create "<topic>" --context "..."
2711
+ ${G.gray("Turn a finished presentation into an MP4 (narration + avatar)")}
2712
+ $ ${N} presentation video <slug>
2713
+ ${G.gray("Export a presentation to HTML, PDF or PPTX")}
2714
+ $ ${N} export <id-or-slug> -o deck.html
2715
+ ${G.gray("Make a video from scratch (no deck)")}
2716
+ $ ${N} video storyboard create ${G.gray("then")} $ ${N} video create
2717
+ ${G.gray("Regenerate one slide's narration in a video draft")}
2718
+ $ ${N} presentation video-narration <project-id>
2719
+ ${G.gray("Generate speaker notes")}
2720
+ $ ${N} presentation speaker-notes <presentation-id>
2721
+ ${G.gray("Import a PowerPoint")}
2722
+ $ ${N} presentation import
2723
+ ${G.gray("Extract a brand identity from a URL")}
2724
+ $ ${N} branding extract <url>
2725
+ ${G.gray("Voiceover, music, sound effects")}
2726
+ $ ${N} tts generate | ${N} music generate | ${N} sfx generate
2727
+ ${G.gray("Find stock footage / images")}
2728
+ $ ${N} video find | ${N} image search
2729
+ ${G.gray("Read a web page or a YouTube transcript")}
2730
+ $ ${N} scrape <url> | ${N} transcript <url>
2731
+
2732
+ ${G.bold("Two different video pipelines:")}
2733
+ '${N} presentation video ...' renders an EXISTING deck to MP4.
2734
+ '${N} video ...' builds a video from a storyboard or brief with stock
2500
2735
  and generated footage \u2014 no deck involved.
2501
2736
 
2502
- ${F.bold("Authentication:")}
2503
- Run '${L} login' to authenticate (recommended).
2737
+ ${G.bold("Authentication:")}
2738
+ Run '${N} login' to authenticate (recommended).
2504
2739
  Or set CC_SLIDES_API_KEY environment variable for API key auth.
2505
2740
 
2506
- ${F.bold("Note:")}
2741
+ ${G.bold("Note:")}
2507
2742
  The command list above is not always complete: feature-flag-gated commands
2508
- (the '${L} derive' subcommands) appear only after '${L} login'
2509
- and '${L} config refresh' have cached your feature access. Run
2510
- '${L} capabilities' for the authoritative list.
2743
+ (the '${N} derive' subcommands) appear only after '${N} login'
2744
+ and '${N} config refresh' have cached your feature access. Run
2745
+ '${N} capabilities' for the authoritative list.
2511
2746
 
2512
- ${F.bold("More Info:")}
2513
- ${F.blue(u.docsUrl)}
2514
- `);G.parse(as(process.argv.slice(2)),{from:"user"});
2747
+ ${G.bold("More Info:")}
2748
+ ${G.blue(m.docsUrl)}
2749
+ `);Er(W);W.parse(Cs(process.argv.slice(2)),{from:"user"});