@conceptcraft/mindframes 0.3.19 → 0.3.21
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.
- package/README.md +0 -1
- package/dist/index.js +335 -281
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
3
|
-
var
|
|
4
|
-
`)}function
|
|
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 le(){let e=await Vr();if(e)return{Authorization:`Bearer ${e}`};let t=fe();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},Yr="Idempotency-Key";function Ws(e){return e&&e!=="GET"?{[Yr]:it()}:{}}async function K(e,t={}){let n=G();if(!de()&&!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 le(),o=`${n}${e}`,i={...r,...Ws(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 O(`Network error: ${f instanceof Error?f.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!s.ok){let f=await s.text().catch(()=>""),p=Js(f,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=`[${p.code}] ${p.message}`;throw new O(v,s.status,w,p.code,p.retryable)}return t.stream?s:s.headers.get("content-type")?.includes("application/json")?s.json():s.text()}function Ks(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 Js(e,t){let n=Ks(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 Jr(e){return K(`/api/cli/tools/${encodeURIComponent(e)}/schema`)}async function Qr(){return K("/api/cli/capabilities",{allowUnauthenticated:!0})}async function T(e,t,n){let r=n?`?teamId=${encodeURIComponent(n)}`:"";return K(`/api/cli/tool-runs/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`)}async function y(e,t,n){return K(`/api/cli/tools/${encodeURIComponent(e)}`,{body:t,headers:n?{[Yr]:n}:void 0,method:"POST"})}async function Zr(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(`${oe(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 O(`[operation_timed_out] The background operation timed out. Request ID: ${t}.`,408,1,"operation_timed_out",!0)}function Tt(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 zs(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 Xs(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 ue(e,t={}){let n=G();if(!de())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let r=await le(),o=Bs(e),i=Hr(e),a=Xs(e),s=Gs(e),l=Vs("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 $=await f.text();throw new O($||"Failed to get upload URL",f.status,1)}let p=await f.json(),w=new FormData;for(let[$,x]of Object.entries(p.fields||{}))w.append($,x);let v=new Blob([s],{type:a});w.append("file",v,i);let b=await fetch(p.url,{method:"POST",body:w});if(!b.ok)throw new O("Failed to upload file to storage",b.status,1);return{id:it(),name:i,url:p.fileUrl,size:o.size,type:a,selected:!0}}async function eo(e,t){let n=[];for(let r=0;r<e.length;r++){let o=e[r],i=Hr(o);t?.(r,e.length,i);let a=await ue(o);n.push(a)}return t?.(e.length,e.length,""),n}async function to(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 no(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 we(e){return K(`/api/cli/presentation/${encodeURIComponent(e)}`)}async function ro(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/speaker-notes`,{body:t,method:"POST"})}async function oo(e,t){return K(`/api/cli/presentation-video/${encodeURIComponent(e)}/narration`,{body:t,method:"POST"})}async function Et(e){let t=G(),n=await fetch(`${t}/api/durable-runs/${encodeURIComponent(e)}/events`,{headers:await le()});if(!n.ok)throw new O(await n.text(),n.status);return n}async function io(e){await K(`/api/cli/presentation/${encodeURIComponent(e)}`,{method:"DELETE"})}async function ao(e,t={}){let n=G();if(!de())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let r=await le(),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 so(e,t,n={}){let r=G();if(!de())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await le(),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 In(){return K("/api/cli/branding")}async function co(e,t=25){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("search",e),K(`/api/cli/templates?${n}`)}async function lo(e){return K(`/api/branding/${e}`)}async function uo(e,t,n){return y("extractBranding",{approvalReceipt:n,teamId:t,url:e})}async function he(){return K("/api/cli/whoami")}async function mo(){return K("/api/cli/features")}async function po(e,t,n={}){let r=G();if(!de())throw new O(`Not authenticated. Run '${u.commands[0]} login' or set ${u.apiKeyEnvVar} environment variable.`,401,2);let o=await le(),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 Hs(e){let t=new URLSearchParams;e&&t.set("teamId",e);let n=t.toString();return K(`/api/cli/limits${n?`?${n}`:""}`)}async function go(e,t,n){let r=await Hs(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 Ys(e){return e.replace(/[\u2014\u2013]/g,"-").replace(/[\u201C\u201D]/g,'"').replace(/[\u2018\u2019]/g,"'").replace(/\u2026/g,"...").replace(/\u00A0/g," ").replace(/[\u2010-\u2015]/g,"-").replace(/[\u2032\u2033]/g,"'")}async function fo(e){let t={...e,text:Ys(e.text)};await $t("generateSpeech",t);let n=await y("generateSpeech",{approvalReceipt:"cli:tts-generate",...t}),r=await Zr("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=ce(a.format)??zs(o)??"mp3",f=Buffer.from(await i.arrayBuffer()),p=ho(a.durationSec,a.duration,a.duration_s)??Fr(f,l);if(p===void 0)throw new O(`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:ce(a.provider)??s.provider??"gemini",format:l,requestId:n.runId,voiceId:ce(a.voice_id)??ce(a.voiceId),voice:ce(a.voice),model:ce(a.model),speed:Te(a.speed)??s.speed,language:ce(a.lang)??ce(a.language)??s.language,langApplied:Xr(a.langApplied)??Xr(a.lang_applied),timestamps:Qs(a.timestamps),wordTimings:Zs(a.timestamps??a.timings)}}function ho(...e){for(let t of e){let n=typeof t=="number"?t:typeof t=="string"&&t.trim()?Number(t):Number.NaN;if(Number.isFinite(n)&&n>0)return n}}function Qs(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 Zs(e){if(!Array.isArray(e))return;let t=e.flatMap(n=>{if(!n||typeof n!="object"||Array.isArray(n))return[];let r=n,o=ce(r.text)??ce(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 ce(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 Xr(e){return typeof e=="boolean"?e:void 0}async function yo(e){let t=e?`/api/cli/tts?provider=${e}`:"/api/cli/tts";return K(t)}async function bo(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;return delete t.idempotency_key,await $t("generateMusic",t),{requestId:(await y("generateMusic",{...t,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function Rn(e){let t=await T("generateMusic",e);return{requestId:e,status:Tt(t),audioUrl:t.entity?.url,duration:ho(t.output?.durationSec,t.output?.duration,t.output?.duration_s),cost:Te(t.output?.costUsd)??Te(t.output?.cost),error:t.error?.message}}async function wo(e){return{requestId:(await y("mixAudio",{...e,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function Sn(e){let t=await T("mixAudio",e);return{requestId:e,status:Tt(t),outputUrl:t.entity?.url,error:t.error?.message}}async function vo(e){return K("/api/cli/images/search",{method:"POST",body:e})}async function xo(e){return K("/api/cli/videos/search",{method:"POST",body:e})}async function Z(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 ko(e,t,n){return y("getYoutubeTranscript",{...n?{language:n}:{},teamId:t,url:e})}async function Co(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 Io(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;delete t.idempotency_key,await $t("generateSfx",t);let r=await y("generateSfx",{...t,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function $n(e){let t=await T("generateSfx",e);return{id:t.entity?.id??e,requestId:e,status:Tt(t),audioUrl:t.entity?.url,error:t.error?.message}}async function Ro(e){return y("listPresenterOptions",{...e?{voiceLanguage:e}:{}})}async function So(e){return{requestId:(await y("generateAvatarVideo",{...e,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function Tn(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:Tt(t),videoUrl:t.entity?.url}}async function $o(e){return y("lipsyncVideo",{...e,approvalReceipt:"cli:video-lipsync"})}async function To(){return(await y("listTranslationLanguages",{})).languages}async function Eo(e){return y("translateVideo",{...e,approvalReceipt:"cli:video-translate"})}async function Ao(e,t,n){return y("createVideo",{...e,approvalReceipt:t},n)}async function Oo(e){let{idempotencyKey:t,...n}=e;return y("analyzeVideoReference",n,t)}async function Po(e,t){return Zr("analyzeVideoReference",e,t)}async function _o(e){return y("listCastPresets",e)}async function Lo(e){return y("createCastPreset",e,it())}async function Do(e){return y("updateCastPreset",e,it())}async function No(e){return y("deleteCastPreset",{presetId:e},it())}var Uo=[{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 At(e){return{capabilities:Uo,catalogVersion:1,reason:e,source:"snapshot"}}async function at(e=Qr){try{let{capabilities:t,catalogVersion:n}=await e();return!Array.isArray(t)||t.length===0?At("the live catalog returned no capabilities"):{capabilities:t,catalogVersion:n,source:"live"}}catch(t){let n=t instanceof Error?t.message:String(t);return At(n)}}var qo=["presentations","media","branding","knowledge","research","artifacts","agents"],nd=80,rd=30;function od(e){return e.billing!==void 0&&e.billing!=="free"&&e.billing!=="quota"}function id(e){return e.lifecycle?.mode==="background"}function ad(e,t){if(t<=0)return[e];let n=[],r="";for(let o of e.split(/\s+/).filter(Boolean))r===""?r=o:r.length+1+o.length<=t?r=`${r} ${o}`:(n.push(r),r=o);return r!==""&&n.push(r),n.length>0?n:[""]}function jo(e){let t=qo.indexOf(e);return t===-1?qo.length:t}function sd(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 dd(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=jo(i)-jo(a);return s!==0?s:i.localeCompare(a)}),r=Math.min(rd,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(st.bold(`${i} (${a.length})`));for(let s of a){let l=`${od(s)?"$":" "}${id(s)?"*":" "}`,f=s.name.padEnd(r),p=2+r+1+l.length+1,w=Math.max(24,nd-p),v=ad(s.description??"",w);o.push(` ${st.cyan(f)} ${st.yellow(l)} ${v[0]??""}`.trimEnd());for(let b of v.slice(1))o.push(`${" ".repeat(p)}${b}`)}}return o}function cd(e){return e.map(t=>`${t.name} ${t.state} ${t.milestone}`)}function ld(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 cd(e);let r=u.commands[0],o=dd(e);return o.push(""),o.push(st.dim(`${e.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(st.dim(`Filter with: ${r} capabilities --search <query>`)),o}var Mo=new td("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 at(),n=sd(t.capabilities,e),r=!!(e.search||e.category);if(e.format==="json"){m({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"&&j(`Showing the capability list baked into this CLI build (${t.reason}); the deployed catalog may have moved on.`);for(let o of ld(n,{filtered:r}))console.log(o)}catch(t){d(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdirSync as gd,writeFileSync as fd}from"fs";import{dirname as Bo,join as hd}from"path";import{Command as ve}from"commander";import dt from"chalk";import{input as yd,password as bd,confirm as Wo,select as wd}from"@inquirer/prompts";import Pt from"ora";import ud from"conf";var Ot=new ud({projectName:"conceptcraft",configName:"feature-cache"}),md=3600*1e3,pd=1440*60*1e3;function Fo(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t=t&t}return t.toString(16)}function Vo(){if(!Ne())return null;let e=Ot.get("featureFlags");if(!e)return null;let t=Fo(fe());if(e.apiKeyHash&&e.apiKeyHash!==t)return Ae(),null;let n=Date.now()-e.fetchedAt;return n>pd?null:(n>md&&En(),e.flags)}function En(){Ee().catch(()=>{})}async function Ee(){let e=await mo(),t=fe();return Ot.set("featureFlags",{flags:e,fetchedAt:Date.now(),apiKeyHash:t?Fo(t):void 0}),e}function Ae(){Ot.delete("featureFlags")}function Go(){return Ot.path}var Ko=new ve("config").description("Manage CLI configuration: account settings, and the cached feature flags that decide which commands appear").addCommand(new ve("init").description("Initialize configuration interactively").action(async()=>{console.log(),console.log(dt.bold(`${u.displayName} CLI Configuration`)),console.log(dt.gray("\u2500".repeat(35))),console.log();try{let e=await bd({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":kn(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(yn(e.trim()),await Wo({message:`Use a custom API URL? (default: ${u.apiUrl.replace("https://","")})`,default:!1})){let r=await yd({message:"Enter API URL:",default:G(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});bn(r)}console.log();let n=Pt("Verifying API key...").start();try{let r=await he();if(n.succeed("API key verified!"),console.log(),g(`Logged in as: ${r.user.email}`),r.teams.length===0)j("No teams found for this user.");else if(r.teams.length===1){let o=r.teams[0];De(o.id),g(`Team: ${o.name} (${o.planName})`)}else{console.log(),g(`You have access to ${r.teams.length} teams.`);let o=await wd({message:"Select your default team:",choices:r.teams.map(a=>({name:`${a.name} (${a.planName}) - ${a.role}${a.isCurrent?" [current]":""}`,value:a.id})),default:r.currentTeam?.id});De(o);let i=r.teams.find(a=>a.id===o);C(`Selected team: ${i?.name}`)}try{await Ee()}catch{}}catch(r){n.fail("Failed to verify API key"),j(`Could not verify API key: ${r instanceof Error?r.message:String(r)}`),j(`You may need to set the team ID manually: ${u.commands[0]} config set team-id <id>`)}console.log(),C("Configuration saved!"),g(`Config file: ${ot()}`),console.log()}catch(e){if(e.name==="ExitPromptError"){console.log(),g("Configuration cancelled.");return}throw e}})).addCommand(new ve("show").description("Show current configuration").option("--verify","Verify API key and show team details").action(async e=>{let t=Er();if(se("Current Configuration"),console.log(),S("API Key",Gr()??dt.red("Not set")),S("API URL",t.apiUrl),S("Default Team ID",t.defaultTeamId??dt.gray("Not set")),console.log(),S("Config file",ot()),e.verify&&t.apiKey){console.log();let n=Pt("Verifying...").start();try{let r=await he();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"),j(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":kn(t)||(d("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),yn(t),Ae(),C("API key updated"),Ee().catch(()=>{});break;case"api-url":try{new URL(t),bn(t),C(`API URL set to: ${t}`)}catch{d("Invalid URL format"),process.exit(6)}break;case"team-id":De(t),C(`Default team ID set to: ${t}`);break;default:d(`Unknown config key: ${e}`),console.log(dt.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new ve("clear").description("Clear all configuration").action(async()=>{try{await Wo({message:"Are you sure you want to clear all configuration?",default:!1})?(Ct(),Ae(),C("Configuration cleared")):g("Cancelled")}catch{g("Cancelled")}})).addCommand(new ve("refresh").description("Refresh cached feature flags").action(async()=>{let e=Pt("Refreshing feature flags...").start();try{await Ee(),e.succeed("Feature flags refreshed"),g(`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 ve("path").description("Show configuration file path").option("--cache","Show feature cache file path").action(e=>{e.cache?console.log(Go()):console.log(ot())})).addCommand(new ve("pull").description("Pull your account settings (memory, brand, prefs) into a local config.toml").action(async()=>{let e=Pt("Pulling settings...").start();try{let t=await le(),n=await fetch(`${G()}/api/cli/settings`,{headers:t});if(!n.ok)throw new Error(`Request failed (HTTP ${n.status})`);let r=await n.text(),o=hd(Bo(ot()),"settings.toml");gd(Bo(o),{recursive:!0}),fd(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 vd}from"commander";import{confirm as xd}from"@inquirer/prompts";var Jo=new vd("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 xd({message:`Are you sure you want to delete presentation "${e}"?`,default:!1})){t.quiet||j("Deletion cancelled");return}}catch{t.quiet||j("Deletion cancelled");return}try{await io(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 qe}from"commander";import Xo from"chalk";import kd from"ora";import{createParser as Jf}from"eventsource-parser";import Xf from"chalk";import Yf 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 Cd(){return new qe("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=kd("Fetching presentation...").start();try{let i=await we(e);o.text="Generating blog post...";let a=await po(i.id,i.documentCreatedAt||i.createdAt,{targetWordCount:n,tone:t.tone,targetAudience:t.audience??"General Audience",customInstructions:t.instructions??"",includeImages:!t.noImages,includeTableOfContents:t.toc??!1}),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(Xo.bold(`Blog: ${i.title}`)),console.log(Xo.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 Id(){return new qe("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(),g("Tweet generation coming soon.")})}function Rd(){return new qe("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(),g("LinkedIn carousel generation coming soon.")})}function Sd(){return new qe("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(),g("Question generation coming soon.")})}function $d(){return new qe("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(),g("Cheat sheet generation coming soon.")})}function Ho(){let e=new qe("derive").description("Generate derivative content from a presentation"),t=Vo();return t&&(t.deckToBlog&&e.addCommand(Cd()),t.deckToTweets&&e.addCommand(Id()),t.linkedInCarousel&&e.addCommand(Rd()),t.redTeamQuestions&&e.addCommand(Sd()),t.presenterCheatSheet&&e.addCommand($d())),e}import _t from"chalk";import{Command as Td}from"commander";import{writeFile as Ed}from"fs/promises";import{resolve as Yo}from"path";import Ad from"ora";var An=new Td("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=Ad("Fetching presentation...").start();try{let r=await we(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`,f=t.output?Yo(t.output):Yo(process.cwd(),l);n.text=`Exporting "${o}"...`;let p=await ao(i,{includeImages:t.includeImages,includeBranding:t.includeBranding,includeExternal:!t.noExternal});n.text="Saving file...",await Ed(f,Buffer.from(p)),n.succeed("Export complete!"),console.log(),g(`File saved: ${f}`),g(`Size: ${Od(p.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),d(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function Od(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}An.addHelpText("after",`
|
|
6
|
-
${_t.bold("Examples:")}
|
|
7
|
-
${_t.gray("# HTML + assets ZIP of a deck")}
|
|
8
|
-
$ ${u.commands[0]} export <slug> -o deck.zip
|
|
9
|
-
|
|
10
|
-
${_t.bold("See also:")}
|
|
11
|
-
${_t.gray("# For an MP4 instead of a ZIP")}
|
|
12
|
-
$ ${u.commands[0]} presentation video <slug>
|
|
13
|
-
`);import{Command as Pd}from"commander";import On from"chalk";var Qo=new Pd("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(),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 _d}from"commander";import{readFile as Ld}from"fs/promises";import{resolve as Dd,basename as Nd}from"path";import Ud from"ora";var Zo=new _d("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");Zo._hidden=!0;var ei=Zo.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 he()).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=Dd(e),r=Nd(n);r.endsWith(".zip")||(d("File must be a ZIP archive"),process.exit(6));let o=Ud("Reading file...").start();try{let i=await Ld(n);t.dryRun?o.text="Validating...":o.text="Importing presentation...";let a=await so(i,r,{dryRun:t.dryRun});if(a.success){if(t.dryRun)o.succeed("Validation passed!"),console.log(),g("The file is valid and can be imported."),a.statistics&&(console.log(),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=G();S("View URL",`${s}/p/${a.presentationId}`)}if(a.warnings&&a.warnings.length>0){console.log();for(let s of a.warnings)j(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 qd}from"commander";var ti=new qd("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??kt();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 no(n,t);if(r.length===0){e.format==="json"?console.log(JSON.stringify([])):e.format!=="ids"&&g("No presentations found");return}switch(e.sort&&r.sort((o,i)=>{switch(e.sort){case"created":return new Date(i.createdAt).getTime()-new Date(o.createdAt).getTime();case"title":return(o.title||"").localeCompare(i.title||"");default:return 0}}),e.format){case"json":console.log(JSON.stringify(r,null,2));break;case"ids":console.log(qr(r));break;default:console.log(Ur(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 jd,randomBytes as oi}from"crypto";import ii from"http";import ni from"chalk";import{Command as Md}from"commander";import Fd from"open";import ri from"ora";var Vd=`${u.displayName} CLI`,Gd=8765,Bd=8775,Wd=["presentations:read","presentations:write","media:read","media:write"];function Kd(){return oi(32).toString("base64url")}function Jd(e){return jd("sha256").update(e).digest("base64url")}function zd(){return oi(16).toString("hex")}async function Xd(e,t){for(let n=e;n<=t;n++)try{return await new Promise((r,o)=>{let i=ii.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 Hd(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 Yd(e){let t=e.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(t?.length?t:Wd).join(" ")}async function Qd(e,t,n){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:Vd,redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none",scope:n})});if(!r.ok){let o=await r.text();throw new Error(`Client registration failed: ${o}`)}return r.json()}async function Zd(e,t,n,r,o){let i=new URLSearchParams({grant_type:"authorization_code",code:t,redirect_uri:r,client_id:o,code_verifier:n}),a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!a.ok){let s=await a.text();throw new Error(`Token exchange failed: ${s}`)}return a.json()}function ec(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=ii.createServer((f,p)=>{let w=new URL(f.url||"",`http://localhost:${e}`);if(w.pathname!=="/callback"){p.writeHead(404),p.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(p.writeHead(200,{"Content-Type":"text/html"}),$){p.end(`
|
|
3
|
+
var f={id:"mindframes",name:"mindframes",displayName:"Mindframes",description:"CLI tool for Mindframes presentation generation",commands:["mf","mindframes"],apiUrl:"https://www.mindframes.app",docsUrl:"https://docs.mindframes.ai",packageName:"@conceptcraft/mindframes",configDir:".mindframes",apiKeyEnvVar:"MINDFRAMES_API_KEY",apiUrlEnvVar:"MINDFRAMES_API_URL",codexSelfConnectorAppId:"asdk_app_6a2b9629c1608191970dcb3ab374ac55"};import G from"chalk";import{Command as Jp}from"commander";import st from"chalk";import{Command as ed}from"commander";function Sr(e={}){let t=(d,l)=>{let y=e[d];return y&&y.trim().length>0?y.trim():l},n=t("NEXT_PUBLIC_PRODUCT_SHORT_NAME","ConceptCraft"),r=t("NEXT_PUBLIC_CLI_COMMAND","ccr"),o=t("NEXT_PUBLIC_CLI_COMMAND_FULL","conceptcraft"),i=t("NEXT_PUBLIC_CLI_CONFIG_DIR",`.${o}`),a=n.toUpperCase().replace(/[^A-Z0-9]/g,"_");return{id:o,name:i.replace(/^\./,""),displayName:n,description:`CLI tool for ${n} presentation generation`,commands:[r,o],apiUrl:t("NEXT_PUBLIC_API_URL","http://localhost:3000"),docsUrl:t("NEXT_PUBLIC_DOCS_URL",`https://docs.${n.toLowerCase()}.ai`),packageName:t("NEXT_PUBLIC_CLI_PACKAGE_NAME","@conceptcraft/cli"),configDir:i,apiKeyEnvVar:`${a}_API_KEY`,apiUrlEnvVar:`${a}_API_URL`,codexSelfConnectorAppId:e.NEXT_PUBLIC_CODEX_SELF_CONNECTOR_APP_ID?.trim()||void 0}}var m=typeof f<"u"&&f?f:Sr(process.env);import L from"chalk";import fn from"cli-table3";import bs from"conf";var $r=m.apiUrl,ws={apiKey:{type:"string"},apiUrl:{type:"string",default:$r},defaultTeamId:{type:"string"},accessToken:{type:"string"},refreshToken:{type:"string"},tokenExpiresAt:{type:"number"},clientId:{type:"string"},clientSecret:{type:"string"}},_=new bs({projectName:m.name,schema:ws});function Tr(){return{apiKey:ge(),apiUrl:B(),defaultTeamId:_.get("defaultTeamId"),accessToken:_.get("accessToken"),refreshToken:_.get("refreshToken"),tokenExpiresAt:_.get("tokenExpiresAt"),clientId:_.get("clientId"),clientSecret:_.get("clientSecret")}}function ge(){let e=process.env[m.apiKeyEnvVar]??process.env.CC_SLIDES_API_KEY;return e||_.get("apiKey")}function pn(e){_.set("apiKey",e)}function B(){let e=process.env[m.apiUrlEnvVar]??process.env.CC_SLIDES_API_URL;return e||(_.get("apiUrl")??$r)}function gn(e){_.set("apiUrl",e)}function Ct(){return _.get("defaultTeamId")}function De(e){_.set("defaultTeamId",e)}function It(){_.clear()}function ot(){return _.path}function Ne(){return!!ge()}function Er(){return _.get("accessToken")}function Ar(){return _.get("refreshToken")}function Rt(e,t,n){_.set("accessToken",e),_.set("refreshToken",t),_.set("tokenExpiresAt",Date.now()+(n-60)*1e3)}function St(){_.delete("accessToken"),_.delete("refreshToken"),_.delete("tokenExpiresAt")}function Or(){let e=_.get("tokenExpiresAt");return e?Date.now()>=e:!0}function $e(){return!!_.get("accessToken")&&!!_.get("refreshToken")}function Pr(){return _.get("clientId")}function _r(){return _.get("clientSecret")}function Lr(e,t){_.set("clientId",e),_.set("clientSecret",t)}function x(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(L.green("\u2713"),e)}function s(e,t="human"){if(t!=="quiet"){if(t==="json"){console.error(JSON.stringify({error:e}));return}console.error(L.red("\u2717"),e)}}function M(e,t="human"){t!=="quiet"&&t!=="json"&&console.warn(L.yellow("\u26A0"),e)}function Dr(e,t="human"){t==="quiet"||t==="json"||console.error(L.cyan("\u2192"),e)}function g(e,t="human"){t!=="quiet"&&t!=="json"&&console.log(L.blue("\u2139"),e)}function qe(e,t="en"){return e?`${B()}/${t}/view/presentations/${e}`:"N/A"}function Nr(e,t={}){let{showLinks:n=!1,language:r="en"}=t,o=(d,l)=>d.length>l?`${d.slice(0,l-1)}\u2026`:d,i=d=>{try{return new Date(d).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).replace(" at ",", ")}catch{return"-"}};if(n){let d=new fn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Created"),L.cyan("URL")]});for(let l of e)d.push([o(l.slug||l.id.slice(0,8),30),o(l.title||"Untitled",22),String(l.numberOfSlides||"-"),i(l.createdAt),qe(l.slug,r)]);return d.toString()}let a=new fn({head:[L.cyan("Slug"),L.cyan("Title"),L.cyan("Slides"),L.cyan("Mode"),L.cyan("Created")],colWidths:[32,28,8,11,18]});for(let d of e)a.push([d.slug||d.id.slice(0,8),d.title||"Untitled",String(d.numberOfSlides||"-"),d.mode||"-",i(d.createdAt)]);return a.toString()}function qr(e){return e.map(t=>t.slug||t.id).join(`
|
|
4
|
+
`)}function Ur(e){let t=[...e].sort((o,i)=>{if(o.isDefault&&!i.isDefault)return-1;if(!o.isDefault&&i.isDefault)return 1;let a=o.createdAt?new Date(o.createdAt).getTime():0;return(i.createdAt?new Date(i.createdAt).getTime():0)-a}),n=o=>{if(!o)return"-";try{return new URL(o).href}catch{return o.startsWith("http")?o:`https://${o}`}},r=new fn({head:[L.cyan("Name"),L.cyan("Source"),L.cyan("Color"),L.cyan("Logo"),L.cyan("Default"),L.cyan("ID")]});for(let o of t){let i=o.primaryColor?`${L.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"-";r.push([o.name,n(o.sourceUrl),i,o.logoUrl?L.green("\u2713"):L.gray("\u2717"),o.isDefault?L.green("\u2605"):"",o.id])}return r.toString()}function hn(e){try{return new Date(e).toLocaleString()}catch{return e}}function ie(e){console.log(),console.log(L.bold(e)),console.log(L.gray("\u2500".repeat(e.length)))}function R(e,t){console.log(` ${L.gray(`${e}:`)} ${t??"-"}`)}function vs(e){return JSON.stringify(e,null,2)}function u(e){console.log(vs(e))}import{createHash as Ms,randomUUID as it}from"crypto";import{readFileSync as Fs,statSync as Vs}from"fs";import{basename as Xr}from"path";import{spawnSync as xs}from"child_process";import{existsSync as ks,mkdtempSync as Cs,rmSync as Is,writeFileSync as Rs}from"fs";import{tmpdir as Ss}from"os";import{join as jr}from"path";import yn from"ffmpeg-static";var $s=/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/;function Ts(e){let t=$s.exec(e);if(!t)return;let n=Number(t[1])*3600+Number(t[2])*60+Number(t[3]);return Number.isFinite(n)&&n>0?n:void 0}function Mr(e,t="audio"){if(e.length===0)return;let n=yn&&ks(yn)?yn:"ffmpeg",r=/^[a-z0-9]+$/i.test(t)?t:"audio",o=Cs(jr(Ss(),"mf-tts-duration-")),i=jr(o,`speech.${r}`);try{Rs(i,e);let a=xs(n,["-hide_banner","-i",i],{encoding:"utf8"});return a.error?void 0:Ts(a.stderr??"")}finally{Is(o,{force:!0,recursive:!0})}}import $t from"chalk";var c={SUCCESS:0,GENERAL_ERROR:1,AUTH_ERROR:2,NOT_FOUND:3,RATE_LIMIT:4,NETWORK_ERROR:5,INVALID_INPUT:6};async function Es(){let e=Ar(),t=Pr(),n=B();if(!e||!t)return null;try{let r=await fetch(`${n}/.well-known/oauth-authorization-server`);if(!r.ok)return null;let o=await r.json(),i=new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:t}),a=_r();a&&i.set("client_secret",a);let d=await fetch(o.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!d.ok)return St(),null;let l=await d.json();return Rt(l.access_token,l.refresh_token,l.expires_in),l.access_token}catch{return null}}async function Fr(){return $e()?Or()?Es():Er()||null:null}function fe(){return $e()||Ne()}async function O(){if(!fe()){let e=m.commands[0],t=m.apiKeyEnvVar;console.error($t.red("\u2717 Not authenticated.")),console.error(),console.error($t.bold("To authenticate, run:")),console.error($t.cyan(` ${e} login`)),console.error(),console.error($t.gray(`Or set ${t} environment variable.`)),process.exit(c.AUTH_ERROR)}}function As(e){return e.length<=14?"****":`${e.slice(0,10)}...${e.slice(-4)}`}function Vr(){let e=ge();if(e)return As(e)}function bn(e){return["cc_slides_","mcp_","cc_sk_","sk_"].some(n=>e.startsWith(n))}import{mkdirSync as Os,readFileSync as Ps,writeFileSync as _s}from"fs";import{homedir as Ls}from"os";import{join as Gr}from"path";import Ds from"ajv/dist/2020.js";var wn=new Map;function Br(){return Gr(Ls(),".conceptcraft","schemas")}function Wr(e){return Gr(Br(),`${e}.json`)}function Ns(e){try{let t=JSON.parse(Ps(Wr(e),"utf8"));return typeof t?.catalogVersion=="number"&&t.schema?t:null}catch{return null}}function qs(e,t){try{Os(Br(),{recursive:!0}),_s(Wr(e),JSON.stringify(t))}catch{}}async function Us(e){let t=wn.get(e);if(t!==void 0)return t;try{let n=await Kr(e),r={catalogVersion:n.catalogVersion,schema:n.schema};return qs(e,r),wn.set(e,r),r}catch{let n=Ns(e);return wn.set(e,n),n}}function js(e){let t=e.instancePath.replace(/^\//,"").replace(/\//g,"."),n=t.length>0?t:"(root)",r=e.keyword==="additionalProperties"?`: unknown field "${e.params.additionalProperty}"`:`: ${e.message??"invalid value"}`;return`${n}${r}`}async function Tt(e,t){let n=await Us(e);if(!n)return;let r;try{r=new Ds({allErrors:!0,strict:!1}).compile(n.schema)}catch{return}if(r(t))return;let o=(r.errors??[]).slice(0,10).map(js);throw new Error(`Request does not match the ${e} contract \u2014 ${o.join("; ")}`)}function ae(e,t){let n=e instanceof Error?e.message:"Unknown error";return!t||n.includes(t)?n:`${n} Request ID: ${t}. Resume with the matching status command; do not start a duplicate run.`}function se(e,t={}){let n=e?.code?.trim()||t.defaultCode?.trim()||"",r=e?.message?.trim()||"The run failed without a reported reason.";return n?`[${n}] ${r}`:r}function Jr(e){let t=e.projectId??"<project-id>";return/Narration is still missing for \d+ slides?\./.test(e.message)?["Narration is captured from speaker notes when the video project is prepared, so 'presentation video refresh' will not backfill it.",`Fill each empty scene with: ${e.binary} presentation video-narration ${t} --slide-id <slide-id> (scene ids: ${e.binary} presentation video inspect ${t})`].join(`
|
|
5
|
+
`):/Every scene is excluded from the video\./.test(e.message)?`Include a scene again with: ${e.binary} presentation video edit ${t} --edit '{"type":"patch_scene","scene":1,"excluded":false}'`:null}async function he(){let e=await Fr();if(e)return{Authorization:`Bearer ${e}`};let t=ge();return t?{"x-api-key":t}:{}}var P=class extends Error{constructor(n,r,o=1,i="operation_failed",a=!1){super(n);this.statusCode=r;this.exitCode=o;this.errorCode=i;this.retryable=a;this.name="ApiError"}statusCode;exitCode;errorCode;retryable},Hr="Idempotency-Key";function Gs(e){return e&&e!=="GET"?{[Hr]:it()}:{}}async function K(e,t={}){let n=B();if(!fe()&&!t.allowUnauthenticated)throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2,"authentication_required");let r=await he(),o=`${n}${e}`,i={...r,...Gs(t.method),...t.headers};t.body&&!t.stream&&(i["Content-Type"]="application/json");let a={method:t.method??"GET",headers:i};t.body&&(a.body=JSON.stringify(t.body));let d;try{d=await fetch(o,a)}catch(y){throw new P(`Network error: ${y instanceof Error?y.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!d.ok){let y=await d.text().catch(()=>""),p=Ws(y,d.status),w=1;switch(d.status){case 401:w=2;break;case 403:w=2;break;case 404:w=3;break;case 429:w=4;break;case 500:w=1;break}let v=`[${p.code}] ${p.message}`;throw new P(v,d.status,w,p.code,p.retryable)}return t.stream?d:d.headers.get("content-type")?.includes("application/json")?d.json():d.text()}function Bs(e){switch(e){case 400:return"invalid_input";case 401:return"authentication_required";case 402:return"insufficient_credits";case 403:return"access_denied";case 404:return"not_found";case 429:return"rate_limited";case 503:return"service_unavailable";default:return"operation_failed"}}function Ws(e,t){let n=Bs(t),r=e.trim()||`HTTP ${t}: The request could not be completed.`;try{let o=JSON.parse(e),i=typeof o.error=="object"&&o.error!==null?o.error:void 0;if(o.ok===!1&&typeof i?.code=="string"&&typeof i.message=="string")return{code:i.code,message:i.message,retryable:i.retryable===!0};if(typeof o.error=="string")return{code:/^[a-z][a-z0-9_]+$/.test(o.error)?o.error:n,message:typeof o.message=="string"?o.message:o.error,retryable:t===429||t>=500}}catch{}return{code:n,message:r,retryable:t===429||t>=500}}async function Kr(e){return K(`/api/cli/tools/${encodeURIComponent(e)}/schema`)}async function Yr(){return K("/api/cli/capabilities",{allowUnauthenticated:!0})}async function T(e,t,n){let r=n?`?teamId=${encodeURIComponent(n)}`:"";return K(`/api/cli/tool-runs/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`)}async function h(e,t,n){return K(`/api/cli/tools/${encodeURIComponent(e)}`,{body:t,headers:n?{[Hr]:n}:void 0,method:"POST"})}async function Qr(e,t,n,r=120){let o=0;for(let i=0;i<r;i++){let a;try{a=await T(e,t,n),o=0}catch(d){if(d instanceof P&&d.retryable&&o<2){o+=1,await new Promise(l=>setTimeout(l,2e3));continue}throw d instanceof P?new P(`${d.message} Request ID: ${t}.`,d.statusCode,d.exitCode,d.errorCode,d.retryable):new P(`${d instanceof Error?d.message:"Unknown error"} Request ID: ${t}.`,0,5,"poll_failed",!0)}if(a.done){if(a.error)throw new P(`${se(a.error,{defaultCode:"operation_failed"})} Request ID: ${t}.`,500,1,a.error.code??"operation_failed",a.error.retryable);return a}await new Promise(d=>setTimeout(d,(a.nextPollAfterSeconds??2)*1e3))}throw new P(`[operation_timed_out] The background operation timed out. Request ID: ${t}.`,408,1,"operation_timed_out",!0)}function Et(e){return e.error||e.status==="failed"||e.status==="errored"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"?"processing":"pending"}function Ks(e){try{let n=new URL(e).pathname.split("/").pop()?.split(".").pop()?.toLowerCase();return n&&/^[a-z0-9]+$/.test(n)?n:void 0}catch{return}}function Js(e){let t=e.toLowerCase().split(".").pop();return{pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",mp4:"video/mp4",mov:"video/quicktime",mpeg:"video/mpeg",mpg:"video/mpeg",webm:"video/webm",aac:"audio/aac",m4a:"audio/mp4",mp3:"audio/mpeg",oga:"audio/ogg",ogg:"audio/ogg",wav:"audio/wav",txt:"text/plain",md:"text/markdown",csv:"text/csv",json:"application/json",html:"text/html",css:"text/css",js:"application/javascript",ts:"text/x-typescript",py:"text/x-python"}[t||""]||"application/octet-stream"}async function me(e,t={}){let n=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let r=await he(),o=Vs(e),i=Xr(e),a=Js(e),d=Fs(e),l=Ms("sha256").update(d).digest("hex"),y=await fetch(`${n}/api/cli/files/upload`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({fileMetadata:{lastModified:o.mtimeMs,name:i,type:a,size:o.size},...t.idempotencyKey?{uploadIdentity:{contentSha256:l,idempotencyKey:t.idempotencyKey}}:{}})});if(!y.ok){let E=await y.text();throw new P(E||"Failed to get upload URL",y.status,1)}let p=await y.json(),w=new FormData;for(let[E,k]of Object.entries(p.fields||{}))w.append(E,k);let v=new Blob([d],{type:a});w.append("file",v,i);let C=await fetch(p.url,{method:"POST",body:w});if(!C.ok)throw new P("Failed to upload file to storage",C.status,1);return{id:it(),name:i,url:p.fileUrl,size:o.size,type:a,selected:!0}}async function Zr(e,t){let n=[];for(let r=0;r<e.length;r++){let o=e[r],i=Xr(o);t?.(r,e.length,i);let a=await me(o);n.push(a)}return t?.(e.length,e.length,""),n}async function eo(e){let t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);let n=t.designBrandReference??t.brandId??t.brandingId;return n!==void 0&&(t.designBrandReference=n,delete t.brandId,delete t.brandingId),h("createSlides",{...t,approvalReceipt:"cli:create"})}async function to(e,t=20){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("teamId",e),(await K(`/api/cli/presentations?${n}`)).presentations}async function Ue(e,t){let n=t?.includeSlides?"?includeSlides=true":"";return K(`/api/cli/presentation/${encodeURIComponent(e)}${n}`)}async function no(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/speaker-notes`,{body:t,method:"POST"})}async function ro(e,t){return K(`/api/cli/presentation-video/${encodeURIComponent(e)}/narration`,{body:t,method:"POST"})}async function At(e){let t=B(),n=await fetch(`${t}/api/durable-runs/${encodeURIComponent(e)}/events`,{headers:await he()});if(!n.ok)throw new P(await n.text(),n.status);return n}async function oo(e){await K(`/api/cli/presentation/${encodeURIComponent(e)}`,{method:"DELETE"})}async function io(e,t){return K(`/api/cli/presentation/${encodeURIComponent(e)}/export`,{body:{format:t},method:"POST"})}async function ao(e){let t;try{t=await fetch(e)}catch(n){throw new P(`Network error while downloading the export: ${n instanceof Error?n.message:"Unknown error"}`,0,5,"service_unavailable",!0)}if(!t.ok)throw new P(`[fetch_failed] The export download link returned ${t.status}. Signed links expire after one hour \u2014 re-run the export.`,t.status,1,"fetch_failed",!0);return t.arrayBuffer()}async function so(e,t,n={}){let r=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let o=await he(),i=new FormData,a=new Blob([e],{type:"application/zip"});i.append("file",a,t),i.append("options",JSON.stringify({dryRun:n.dryRun??!1,remapIds:!0}));let d=await fetch(`${r}/api/presentations/import`,{method:"POST",headers:o,body:i}),l=await d.json();if(!d.ok)throw new P(l.errors?.[0]?.message??"Import failed",d.status,1);return l}async function vn(){return K("/api/cli/branding")}async function co(e,t=25){let n=new URLSearchParams;return n.set("limit",String(t)),e&&n.set("search",e),K(`/api/cli/templates?${n}`)}async function lo(e){return K(`/api/branding/${e}`)}async function mo(e,t,n){return h("extractBranding",{approvalReceipt:n,teamId:t,url:e})}async function ye(){return K("/api/cli/whoami")}async function uo(){return K("/api/cli/features")}async function po(e,t,n={}){let r=B();if(!fe())throw new P(`Not authenticated. Run '${m.commands[0]} login' or set ${m.apiKeyEnvVar} environment variable.`,401,2);let o=await he(),i=await fetch(`${r}/api/presentations/${e}/generate-blog`,{method:"POST",headers:{"Content-Type":"application/json",...o},body:JSON.stringify({documentCreatedAt:t,targetWordCount:n.targetWordCount??300,tone:n.tone??"professional",language:n.language??"en",targetAudience:n.targetAudience??"General Audience",blogFormat:n.blogFormat??"narrative",customInstructions:n.customInstructions??"",includeImages:n.includeImages??!0,includeTableOfContents:n.includeTableOfContents??!1})});if(!i.ok)throw new P(await i.text(),i.status,i.status===404?3:1);return i}async function zs(e){let t=new URLSearchParams;e&&t.set("teamId",e);let n=t.toString();return K(`/api/cli/limits${n?`?${n}`:""}`)}async function go(e,t,n){let r=await zs(n);if(!r.canGenerate[e]){let o=r.remaining[e]??0,i=r.limits[e]??0;throw i===0?new P(`The "${e}" mode is not available on your ${r.planName} plan. Available modes: ${r.availableModes.join(", ")||"none"}`,403,2):new P(`You have reached your ${e} generation limit for this billing cycle (${r.usage[e]??0}/${i} used). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,4)}if(r.maxSlidesPerPresentation!==-1&&t>r.maxSlidesPerPresentation)throw new P(`Maximum ${r.maxSlidesPerPresentation} slides allowed on your ${r.planName} plan (requested: ${t}). Try a different mode: ${r.availableModes.join(", ")||"none available"}`,403,6);return r}function Xs(e){return e.replace(/[\u2014\u2013]/g,"-").replace(/[\u201C\u201D]/g,'"').replace(/[\u2018\u2019]/g,"'").replace(/\u2026/g,"...").replace(/\u00A0/g," ").replace(/[\u2010-\u2015]/g,"-").replace(/[\u2032\u2033]/g,"'")}async function fo(e){let t={...e,text:Xs(e.text)};await Tt("generateSpeech",t);let n=await h("generateSpeech",{approvalReceipt:"cli:tts-generate",...t}),r=await Qr("generateSpeech",n.runId),o=r.entity?.url;if(!o)throw new P(`Speech completed without an audio URL. Request ID: ${n.runId}.`,500);let i;try{i=await fetch(o)}catch(w){throw new P(`${w instanceof Error?w.message:"Failed to download speech audio"} Request ID: ${n.runId}.`,0,5,"download_failed",!0)}if(!i.ok)throw new P(`Failed to download speech audio. Request ID: ${n.runId}.`,i.status,5,"download_failed",i.status===429||i.status>=500);let a=r.output??{},d=e.options??{},l=le(a.format)??Ks(o)??"mp3",y=Buffer.from(await i.arrayBuffer()),p=ho(a.durationSec,a.duration,a.duration_s)??Mr(y,l);if(p===void 0)throw new P(`Speech completed without a measurable duration. Request ID: ${n.runId}.`,500,1,"invalid_audio_metadata");return{audioData:y,audioUrl:o,duration:p,cost:Te(a.costUsd)??Te(a.cost)??0,provider:le(a.provider)??d.provider??"gemini",format:l,requestId:n.runId,voiceId:le(a.voice_id)??le(a.voiceId),voice:le(a.voice),model:le(a.model),speed:Te(a.speed)??d.speed,language:le(a.lang)??le(a.language)??d.language,langApplied:zr(a.langApplied)??zr(a.lang_applied),timestamps:Hs(a.timestamps),wordTimings:Ys(a.timestamps??a.timings)}}function ho(...e){for(let t of e){let n=typeof t=="number"?t:typeof t=="string"&&t.trim()?Number(t):Number.NaN;if(Number.isFinite(n)&&n>0)return n}}function Hs(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n=t.characters,r=t.characterStartTimesSeconds??t.character_start_times_seconds,o=t.characterEndTimesSeconds??t.character_end_times_seconds;if(!(!Array.isArray(n)||!Array.isArray(r)||!Array.isArray(o))&&!(n.length===0||n.length!==r.length||n.length!==o.length||!n.every(i=>typeof i=="string")||!r.every(i=>typeof i=="number"&&Number.isFinite(i))||!o.every(i=>typeof i=="number"&&Number.isFinite(i))))return{characters:n,characterStartTimesSeconds:r,characterEndTimesSeconds:o}}function Ys(e){if(!Array.isArray(e))return;let t=e.flatMap(n=>{if(!n||typeof n!="object"||Array.isArray(n))return[];let r=n,o=le(r.text)??le(r.word),i=Te(r.start),a=Te(r.end);return o&&i!==void 0&&a!==void 0&&a>=i?[{text:o,start:i,end:a}]:[]});return t.length>0?t:void 0}function le(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Te(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function zr(e){return typeof e=="boolean"?e:void 0}async function yo(e){let t=e?`/api/cli/tts?provider=${e}`:"/api/cli/tts";return K(t)}async function bo(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;return delete t.idempotency_key,await Tt("generateMusic",t),{requestId:(await h("generateMusic",{...t,approvalReceipt:"cli:music-generate"},n)).runId,status:"pending"}}async function xn(e){let t=await T("generateMusic",e);return{requestId:e,status:Et(t),audioUrl:t.entity?.url,duration:ho(t.output?.durationSec,t.output?.duration,t.output?.duration_s),cost:Te(t.output?.costUsd)??Te(t.output?.cost),error:t.error?.message}}async function wo(e){return{requestId:(await h("mixAudio",{...e,approvalReceipt:"cli:mix-create"})).runId,status:"pending"}}async function kn(e){let t=await T("mixAudio",e);return{requestId:e,status:Et(t),outputUrl:t.entity?.url,error:t.error?.message}}async function vo(e){return K("/api/cli/images/search",{method:"POST",body:e})}async function xo(e){return K("/api/cli/videos/search",{method:"POST",body:e})}async function te(e,t=60,n=2e3){let r=0;for(let o=0;o<t;o++){let i;try{i=await e(),r=0}catch(a){if(a instanceof P&&a.retryable&&r<2){r+=1,await new Promise(d=>setTimeout(d,n));continue}throw a}if(i.status==="completed"||i.status==="failed")return i;await new Promise(a=>setTimeout(a,n))}throw new P("Operation timed out",408,1)}async function ko(e,t,n){return h("getYoutubeTranscript",{...n?{language:n}:{},teamId:t,url:e})}async function Co(e,t){let n=await h("scrape",{teamId:t,url:e});return{data:{content:n.content,cost:n.totalCost??0,metadata:{description:"",format:"markdown",tokenUsage:Math.ceil(n.content.length/4)},title:n.title??"",url:n.url},success:!0}}async function Io(e){let t={...e},n=typeof t.idempotency_key=="string"?t.idempotency_key:void 0;delete t.idempotency_key,await Tt("generateSfx",t);let r=await h("generateSfx",{...t,approvalReceipt:"cli:sfx-generate"},n);return{id:r.runId,requestId:r.runId,status:"pending"}}async function Cn(e){let t=await T("generateSfx",e);return{id:t.entity?.id??e,requestId:e,status:Et(t),audioUrl:t.entity?.url,error:t.error?.message}}async function Ro(e){return h("listPresenterOptions",{...e?{voiceLanguage:e}:{}})}async function So(e){return{requestId:(await h("generateAvatarVideo",{...e,approvalReceipt:"cli:avatar-generate"})).runId,status:"pending"}}async function In(e){let t=await T("generateAvatarVideo",e);return{durationSec:typeof t.output?.durationSec=="number"?t.output.durationSec:null,error:t.error?.message,requestId:e,status:Et(t),videoUrl:t.entity?.url}}async function $o(e){return h("lipsyncVideo",{...e,approvalReceipt:"cli:video-lipsync"})}async function To(){return(await h("listTranslationLanguages",{})).languages}async function Eo(e){return h("translateVideo",{...e,approvalReceipt:"cli:video-translate"})}async function Ao(e,t,n){return h("createVideo",{...e,approvalReceipt:t},n)}async function Oo(e){let{idempotencyKey:t,...n}=e;return h("analyzeVideoReference",n,t)}async function Po(e,t){return Qr("analyzeVideoReference",e,t)}async function _o(e){return h("listCastPresets",e)}async function Lo(e){return h("createCastPreset",e,it())}async function Do(e){return h("updateCastPreset",e,it())}async function No(e){return h("deleteCastPreset",{presetId:e},it())}var qo=[{billing:"free",category:"branding",description:"Attach a social handle to an accessible brand profile.",id:"addBrandSocialHandle",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding social add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"branding",description:"Add a competitor to an accessible brand profile.",id:"addCompetitor",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding competitor add",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"delegated",category:"media",description:"Transcribe an uploaded recording and publish the transcript for generation.",id:"analyzeMediaAsset",lifecycle:{mode:"background",status:{cliCommand:"media analyze status",pollAfterSeconds:10}},milestone:"M8",name:"media analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Analyze an uploaded video before using it as a source, motion, blocking, or pacing reference in a video storyboard. The completed status output includes the analysisId required by the storyboard's source-video binding.",id:"analyzeVideoReference",lifecycle:{mode:"background",status:{cliCommand:"video reference status",pollAfterSeconds:10}},milestone:"M8",name:"video reference analyze",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"artifacts",description:"Generate and persist an ad variation set.",id:"createAdSet",lifecycle:{mode:"background",status:{cliCommand:"ad-set status",pollAfterSeconds:10}},milestone:"M6",name:"ad-set create",operation:"generation",scopes:["ad-sets:write"],state:"available"},{billing:"free",category:"agents",description:"Create a scheduled agent from a validated configuration.",id:"createAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent create",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"media",description:"Save one way a cast member appears: a personal presenter (pp_* id), a backdrop, and optionally a voice, under a name unique to that person.",id:"createCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Save a markdown, CSV or plain-text document into the Library.",id:"createDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"fixed",category:"media",description:"Generate and persist an image.",id:"createImage",lifecycle:{mode:"background",status:{cliCommand:"image status",pollAfterSeconds:10}},milestone:"M5",name:"image generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Create a Library folder, optionally inside another.",id:"createLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders create",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"dynamic",category:"artifacts",description:"Generate and persist a microsite.",id:"createMicrosite",lifecycle:{mode:"background",status:{cliCommand:"microsite status",pollAfterSeconds:10}},milestone:"M6",name:"microsite create",operation:"generation",scopes:["microsites:write"],state:"available"},{billing:"free",category:"artifacts",description:"Create a standalone poll.",id:"createPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll create",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"delegated",category:"presentations",description:"Create an MP4 video from a finished presentation, or render an existing presentation-video project.",id:"createPresentationVideo",lifecycle:{mode:"background",status:{cliCommand:"presentation video status",pollAfterSeconds:10}},milestone:"M4",name:"presentation video",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"fixed",category:"presentations",description:"Generate a presentation and persist the resulting deck.",id:"createSlides",lifecycle:{mode:"background",status:{cliCommand:"presentation status",pollAfterSeconds:20}},milestone:"M4",name:"create",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one video from the opaque text and explicit metadata stored in a pinned storyboard revision.",id:"createVideo",lifecycle:{mode:"background",status:{cliCommand:"video status",pollAfterSeconds:20}},milestone:"M8",name:"video create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a versioned Markdown video storyboard.",id:"createVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard create",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"fixed",category:"artifacts",description:"Generate a persisted standalone visual abstract.",id:"createVisualAbstract",lifecycle:{mode:"background",status:{cliCommand:"visual-abstract status",pollAfterSeconds:10}},milestone:"M5",name:"visual-abstract create",operation:"generation",scopes:["visual-abstracts:write"],state:"available"},{billing:"free",category:"media",description:"Retire a saved cast preset. Existing videos keep working; the preset stops being offered.",id:"deleteCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset delete",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Remove a document from the Library.",id:"deleteDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"knowledge",description:"Delete a Library folder and its subfolders. Items inside are unfiled, never deleted.",id:"deleteLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders delete",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"artifacts",description:"Edit a standalone poll.",id:"editPoll",lifecycle:{mode:"bounded"},milestone:"M3",name:"poll edit",operation:"mutation",scopes:["polls:write"],state:"available"},{billing:"free",category:"presentations",description:"Apply one atomic edit to a presentation-video draft.",id:"editPresentationVideoDraft",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video edit",operation:"mutation",scopes:["presentations:write","media:read"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate the narration a presentation-video project is still missing.",id:"ensurePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video narrate status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video narrate",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"quota",category:"branding",description:"Extract and persist a reusable brand profile from a URL.",id:"extractBranding",lifecycle:{mode:"background",status:{cliCommand:"branding status",pollAfterSeconds:10}},milestone:"M2",name:"branding extract",operation:"generation",scopes:["brands:write"],state:"available"},{billing:"dynamic",category:"research",description:"Extract normalized text from uploaded or remote content.",id:"extractContent",lifecycle:{mode:"bounded"},milestone:"M1",name:"content extract",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"File an artifact into a Library folder, or unfile it.",id:"fileArtifactIntoFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library file",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Erase every stored version of a scheduled agent's memory. Irreversible.",id:"forgetAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory forget",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate one reusable avatar/presenter clip for composition into a video. Accepts a stock avatar id or a personal presenter's pp_* id (from listPresenterOptions' `personal` group) as avatarId.",id:"generateAvatarVideo",lifecycle:{mode:"background",status:{cliCommand:"avatar status",pollAfterSeconds:10}},milestone:"M8",name:"avatar generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate music from final video facts or a trusted direct prompt.",id:"generateMusic",lifecycle:{mode:"background",status:{cliCommand:"music status",pollAfterSeconds:10}},milestone:"M7",name:"music generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"delegated",category:"media",description:"Generate an additional look for an existing personal presenter while preserving the same Cast identity.",id:"generatePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate SFX from final video facts or a trusted direct prompt.",id:"generateSfx",lifecycle:{mode:"background",status:{cliCommand:"sfx status",pollAfterSeconds:10}},milestone:"M7",name:"sfx generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Generate persisted speaker notes for a presentation version.",id:"generateSpeakerNotes",lifecycle:{mode:"background",status:{cliCommand:"presentation speaker-notes-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation speaker-notes",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"media",description:"Generate speech audio from text.",id:"generateSpeech",lifecycle:{mode:"background",status:{cliCommand:"tts status",pollAfterSeconds:10}},milestone:"M7",name:"tts generate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Read what a scheduled agent has recorded about its own work: learned facts, standing instructions, things it never does, entities it tracks, and freeform notes.",id:"getAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory show",operation:"query",scopes:["agents:read"],state:"available"},{billing:"free",category:"branding",description:"List competitors saved for an accessible brand profile.",id:"getBrandCompetitors",lifecycle:{mode:"bounded"},milestone:"M1",name:"branding competitor list",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"branding",description:"Read a brand's design tokens, the keys it is missing, or its design.md document.",id:"getBrandProfile",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding profile",operation:"query",scopes:["brands:read"],state:"available"},{billing:"free",category:"knowledge",description:"Read a bounded workspace Knowledge Hub bundle.",id:"getKnowledgeBundle",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge bundle",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search recent news sources.",id:"getNews",lifecycle:{mode:"bounded"},milestone:"M1",name:"search news",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"presentations",description:"Read a presentation and its slides.",id:"getPresentation",lifecycle:{mode:"bounded"},milestone:"M1",name:"get",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"presentations",description:"Read an owned presentation-video project and its ordered scene timeline.",id:"getPresentationVideoProject",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video inspect",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"dynamic",category:"research",description:"Fetch a YouTube video's timestamped transcript with its title, channel, and duration.",id:"getYoutubeTranscript",lifecycle:{mode:"bounded"},milestone:"M1",name:"transcript",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"media",description:"Import a recording from a connected account into the media library.",id:"importConnectorRecording",lifecycle:{mode:"background",status:{cliCommand:"media import status",pollAfterSeconds:5}},milestone:"M8",name:"media import",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"presentations",description:"Import an attached PowerPoint as an auditable, review-gated Mindframes presentation.",id:"importPowerPoint",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Re-voice a ready video with new audio via provider lip-sync (one sibling re-voiced video artifact).",id:"lipsyncVideo",lifecycle:{mode:"background",status:{cliCommand:"video lipsync status",pollAfterSeconds:20}},milestone:"M8",name:"video lipsync",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"List saved ways a cast member appears \u2014 a trained presenter, a backdrop, and optionally a voice, under one name. Filtered to what the caller may actually use.",id:"listCastPresets",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset list",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace's documents, newest first.",id:"listDocuments",lifecycle:{mode:"bounded"},milestone:"M8",name:"document list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List a document's append-only version history.",id:"listDocumentVersions",lifecycle:{mode:"bounded"},milestone:"M8",name:"document versions",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"knowledge",description:"List the workspace Library folder tree.",id:"listLibraryFolders",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders list",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"presentations",description:"List saved presentation-video draft versions.",id:"listPresentationVideoVersions",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video versions",operation:"query",scopes:["presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral presenter avatars, voices, and voice languages, plus the workspace's trained personal presenters (`personal` roster group, pp_* ids).",id:"listPresenterOptions",lifecycle:{mode:"bounded"},milestone:"M8",name:"avatar options",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"media",description:"List ready generated clips and uploaded MediaAssets while excluding final presentation-to-MP4 renders.",id:"listReusableVideoClips",lifecycle:{mode:"bounded"},milestone:"M8",name:"video library list",operation:"query",scopes:["media:read","presentations:read"],state:"available"},{billing:"free",category:"media",description:"List provider-neutral target languages for video translation.",id:"listTranslationLanguages",lifecycle:{mode:"bounded"},milestone:"M8",name:"video translate-languages",operation:"query",scopes:["media:read"],state:"available"},{billing:"dynamic",category:"media",description:"Mix voice, music, and sound-effect tracks.",id:"mixAudio",lifecycle:{mode:"background",status:{cliCommand:"mix status",pollAfterSeconds:10}},milestone:"M7",name:"mix create",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Move a Library folder under a new parent, or to the top level.",id:"moveLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders move",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Create or reuse a presentation-video project for a finished presentation.",id:"preparePresentationVideo",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video prepare",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Read one document's full body and metadata.",id:"readDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document read",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"free",category:"media",description:"Read a video storyboard and its immutable revision history.",id:"readVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard show",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"knowledge",description:"Set or clear the colour of a Library folder.",id:"recolorLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders recolor",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"agents",description:"Create a reviewable scheduled-agent recommendation.",id:"recommendAgent",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent recommend",operation:"generation",scopes:["agents:write"],state:"available"},{billing:"free",category:"presentations",description:"Refresh deck-backed video scenes from the latest presentation version.",id:"refreshPresentationVideoSlides",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video refresh",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"dynamic",category:"presentations",description:"Regenerate one narration override in a presentation video draft.",id:"regeneratePresentationVideoNarration",lifecycle:{mode:"background",status:{cliCommand:"presentation video-narration-status",pollAfterSeconds:5}},milestone:"M4",name:"presentation video-narration",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"knowledge",description:"Rename a Library folder.",id:"renameLibraryFolder",lifecycle:{mode:"bounded"},milestone:"M1",name:"library folders rename",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"knowledge",description:"Restore an earlier version by appending it as the current one.",id:"restoreDocumentVersion",lifecycle:{mode:"bounded"},milestone:"M8",name:"document restore",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Restore a saved presentation-video draft version as a new version.",id:"restorePresentationVideoVersion",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video restore",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Create a new presenter Look by editing an existing Look without changing its source.",id:"revisePresenterLook",lifecycle:{mode:"background",status:{cliCommand:"avatar look revision-status",pollAfterSeconds:10}},milestone:"M8",name:"avatar look revise",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"media",description:"Create a new immutable revision of a Markdown video storyboard.",id:"reviseVideoStoryboard",lifecycle:{mode:"bounded"},milestone:"M8",name:"video storyboard revise",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"dynamic",category:"research",description:"Read and normalize content from a public URL.",id:"scrape",lifecycle:{mode:"bounded"},milestone:"M1",name:"scrape",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search licensed image providers.",id:"searchImages",lifecycle:{mode:"bounded"},milestone:"M1",name:"search images",operation:"query",scopes:["research:read"],state:"available"},{billing:"dynamic",category:"research",description:"Search the public web for current sources.",id:"searchInternet",lifecycle:{mode:"bounded"},milestone:"M1",name:"search web",operation:"query",scopes:["research:read"],state:"available"},{billing:"free",category:"knowledge",description:"Search workspace Knowledge Hub entries.",id:"searchKnowledge",lifecycle:{mode:"bounded"},milestone:"M1",name:"knowledge search",operation:"query",scopes:["knowledge:read"],state:"available"},{billing:"dynamic",category:"media",description:"Find videos: licensed stock clips to download, or web videos to embed.",id:"searchStockVideo",lifecycle:{mode:"bounded"},milestone:"M1",name:"search video",operation:"query",scopes:["media:read"],state:"available"},{billing:"free",category:"branding",description:"Point a brand at an already-uploaded logo, dark-background logo variant, or favicon.",id:"setBrandLogo",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding logo set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"presentations",description:"Set one presentation-video scene to a specific avatar/look or saved preset, including the preset voice by default, or restore inheritance from the project default.",id:"setPresentationVideoScenePresenter",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video presenter",operation:"mutation",scopes:["presentations:write"],state:"available"},{billing:"free",category:"presentations",description:"Transform an uploaded PowerPoint source into an auditable presentation review.",id:"transformPresentationImport",lifecycle:{mode:"background",status:{cliCommand:"presentation import status",pollAfterSeconds:5}},milestone:"M4",name:"presentation import transform",operation:"generation",scopes:["presentations:write"],state:"available"},{billing:"delegated",category:"media",description:"Translate a ready video into sibling language versions (one video per target language).",id:"translateVideo",lifecycle:{mode:"background",status:{cliCommand:"video translate status",pollAfterSeconds:20}},milestone:"M8",name:"video translate",operation:"generation",scopes:["media:write"],state:"available"},{billing:"free",category:"agents",description:"Add to or remove from what a scheduled agent remembers. Owner or workspace admin only.",id:"updateAgentMemory",lifecycle:{mode:"bounded"},milestone:"M3",name:"agent memory set",operation:"mutation",scopes:["agents:write"],state:"available"},{billing:"free",category:"branding",description:"Write a brand's design tokens from a key patch or a whole design.md document.",id:"updateBrandTokens",lifecycle:{mode:"bounded"},milestone:"M2",name:"branding set",operation:"mutation",scopes:["brands:write"],state:"available"},{billing:"free",category:"media",description:"Change a saved cast preset's name, presenter, backdrop, or voice. Sends the complete preset, not a patch.",id:"updateCastPreset",lifecycle:{mode:"bounded"},milestone:"M8",name:"cast preset update",operation:"mutation",scopes:["media:write"],state:"available"},{billing:"free",category:"knowledge",description:"Edit a document's body, title or summary under an optimistic lock.",id:"updateDocument",lifecycle:{mode:"bounded"},milestone:"M8",name:"document update",operation:"mutation",scopes:["knowledge:write"],state:"available"},{billing:"free",category:"presentations",description:"Update avatar, voice, music, captions, format, and renderer settings for a presentation-video project.",id:"updatePresentationVideoSettings",lifecycle:{mode:"bounded"},milestone:"M4",name:"presentation video settings",operation:"mutation",scopes:["presentations:write"],state:"available"}];function Ot(e){return{capabilities:qo,catalogVersion:1,reason:e,source:"snapshot"}}async function at(e=Yr){try{let{capabilities:t,catalogVersion:n}=await e();return!Array.isArray(t)||t.length===0?Ot("the live catalog returned no capabilities"):{capabilities:t,catalogVersion:n,source:"live"}}catch(t){let n=t instanceof Error?t.message:String(t);return Ot(n)}}import{InvalidArgumentError as Zs}from"commander";function b(e,t){return n=>{if(t.includes(n))return n;throw new Zs(`Expected one of: ${t.join(", ")}. Run the command with --help to see what ${e} accepts.`)}}var Uo=["presentations","media","branding","knowledge","research","artifacts","agents"],td=80,nd=30;function rd(e){return e.billing!==void 0&&e.billing!=="free"&&e.billing!=="quota"}function od(e){return e.lifecycle?.mode==="background"}function id(e,t){if(t<=0)return[e];let n=[],r="";for(let o of e.split(/\s+/).filter(Boolean))r===""?r=o:r.length+1+o.length<=t?r=`${r} ${o}`:(n.push(r),r=o);return r!==""&&n.push(r),n.length>0?n:[""]}function jo(e){let t=Uo.indexOf(e);return t===-1?Uo.length:t}function ad(e,t){let n=t.search?.trim().toLowerCase(),r=t.category?.trim().toLowerCase();return e.filter(o=>r&&(o.category??"").toLowerCase()!==r?!1:n?`${o.name} ${o.description??""}`.toLowerCase().includes(n):!0)}function sd(e){let t=new Map;for(let i of e){let a=i.category??"other",d=t.get(a);d?d.push(i):t.set(a,[i])}let n=[...t.entries()].sort(([i],[a])=>{let d=jo(i)-jo(a);return d!==0?d:i.localeCompare(a)}),r=Math.min(nd,Math.max(...e.map(i=>i.name.length))),o=[];for(let[i,a]of n){a.sort((d,l)=>d.name.localeCompare(l.name)),o.length>0&&o.push(""),o.push(st.bold(`${i} (${a.length})`));for(let d of a){let l=`${rd(d)?"$":" "}${od(d)?"*":" "}`,y=d.name.padEnd(r),p=2+r+1+l.length+1,w=Math.max(24,td-p),v=id(d.description??"",w);o.push(` ${st.cyan(y)} ${st.yellow(l)} ${v[0]??""}`.trimEnd());for(let C of v.slice(1))o.push(`${" ".repeat(p)}${C}`)}}return o}function dd(e){return e.map(t=>`${t.name} ${t.state} ${t.milestone}`)}function cd(e,t={filtered:!1}){if(e.length===0)return[t.filtered?"No capabilities match that filter.":"No capabilities available."];if(!e.some(i=>i.description||i.category))return dd(e);let r=m.commands[0],o=sd(e);return o.push(""),o.push(st.dim(`${e.length} capabilities \xB7 $ = paid \xB7 * = background (returns a run id)`)),o.push(st.dim(`Filter with: ${r} capabilities --search <query>`)),o}var Mo=new ed("capabilities").description("Index of everything this CLI can do \u2014 every command, grouped and described").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("-s, --search <query>","Only show capabilities matching a query").option("--category <name>","Only show one category").action(async e=>{try{let t=await at(),n=ad(t.capabilities,e),r=!!(e.search||e.category);if(e.format==="json"){u({capabilities:n,catalogVersion:t.catalogVersion,source:t.source,...t.reason?{sourceReason:t.reason}:{}});return}if(e.format==="quiet"){for(let o of n)console.log(o.name);return}t.source==="snapshot"&&M(`Showing the capability list baked into this CLI build (${t.reason}); the deployed catalog may have moved on.`);for(let o of cd(n,{filtered:r}))console.log(o)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdirSync as pd,writeFileSync as gd}from"fs";import{dirname as Bo,join as fd}from"path";import{Command as ve}from"commander";import dt from"chalk";import{input as hd,password as yd,confirm as Wo,select as bd}from"@inquirer/prompts";import _t from"ora";import ld from"conf";var Pt=new ld({projectName:"conceptcraft",configName:"feature-cache"}),md=3600*1e3,ud=1440*60*1e3;function Fo(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t=t&t}return t.toString(16)}function Vo(){if(!Ne())return null;let e=Pt.get("featureFlags");if(!e)return null;let t=Fo(ge());if(e.apiKeyHash&&e.apiKeyHash!==t)return Ae(),null;let n=Date.now()-e.fetchedAt;return n>ud?null:(n>md&&Rn(),e.flags)}function Rn(){Ee().catch(()=>{})}async function Ee(){let e=await uo(),t=ge();return Pt.set("featureFlags",{flags:e,fetchedAt:Date.now(),apiKeyHash:t?Fo(t):void 0}),e}function Ae(){Pt.delete("featureFlags")}function Go(){return Pt.path}var Ko=new ve("config").description("Manage CLI configuration: account settings, and the cached feature flags that decide which commands appear").addCommand(new ve("init").description("Initialize configuration interactively").action(async()=>{console.log(),console.log(dt.bold(`${m.displayName} CLI Configuration`)),console.log(dt.gray("\u2500".repeat(35))),console.log();try{let e=await yd({message:"Enter your API key:",mask:"*",validate:r=>!r||r.trim().length===0?"API key is required":bn(r.trim())?!0:"Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"});if(pn(e.trim()),await Wo({message:`Use a custom API URL? (default: ${m.apiUrl.replace("https://","")})`,default:!1})){let r=await hd({message:"Enter API URL:",default:B(),validate:o=>{try{return new URL(o),!0}catch{return"Invalid URL format"}}});gn(r)}console.log();let n=_t("Verifying API key...").start();try{let r=await ye();if(n.succeed("API key verified!"),console.log(),g(`Logged in as: ${r.user.email}`),r.teams.length===0)M("No teams found for this user.");else if(r.teams.length===1){let o=r.teams[0];De(o.id),g(`Team: ${o.name} (${o.planName})`)}else{console.log(),g(`You have access to ${r.teams.length} teams.`);let o=await bd({message:"Select your default team:",choices:r.teams.map(a=>({name:`${a.name} (${a.planName}) - ${a.role}${a.isCurrent?" [current]":""}`,value:a.id})),default:r.currentTeam?.id});De(o);let i=r.teams.find(a=>a.id===o);x(`Selected team: ${i?.name}`)}try{await Ee()}catch{}}catch(r){n.fail("Failed to verify API key"),M(`Could not verify API key: ${r instanceof Error?r.message:String(r)}`),M(`You may need to set the team ID manually: ${m.commands[0]} config set team-id <id>`)}console.log(),x("Configuration saved!"),g(`Config file: ${ot()}`),console.log()}catch(e){if(e.name==="ExitPromptError"){console.log(),g("Configuration cancelled.");return}throw e}})).addCommand(new ve("show").description("Show current configuration").option("--verify","Verify API key and show team details").action(async e=>{let t=Tr();if(ie("Current Configuration"),console.log(),R("API Key",Vr()??dt.red("Not set")),R("API URL",t.apiUrl),R("Default Team ID",t.defaultTeamId??dt.gray("Not set")),console.log(),R("Config file",ot()),e.verify&&t.apiKey){console.log();let n=_t("Verifying...").start();try{let r=await ye();n.succeed("Verified"),console.log(),R("User",r.user.email),r.currentTeam&&R("Current Team",`${r.currentTeam.name} (${r.currentTeam.planName})`),r.teams.length>1&&R("Total Teams",String(r.teams.length))}catch(r){n.fail("Verification failed"),M(r instanceof Error?r.message:String(r))}}console.log()})).addCommand(new ve("set").description("Set a configuration value").argument("<key>","Configuration key (api-key, api-url, team-id)").argument("<value>","Value to set").action(async(e,t)=>{switch(e){case"api-key":bn(t)||(s("Invalid API key format. Keys should start with 'cc_slides_' or 'mcp_'"),process.exit(6)),pn(t),Ae(),x("API key updated"),Ee().catch(()=>{});break;case"api-url":try{new URL(t),gn(t),x(`API URL set to: ${t}`)}catch{s("Invalid URL format"),process.exit(6)}break;case"team-id":De(t),x(`Default team ID set to: ${t}`);break;default:s(`Unknown config key: ${e}`),console.log(dt.gray("Valid keys: api-key, api-url, team-id")),process.exit(6)}})).addCommand(new ve("clear").description("Clear all configuration").action(async()=>{try{await Wo({message:"Are you sure you want to clear all configuration?",default:!1})?(It(),Ae(),x("Configuration cleared")):g("Cancelled")}catch{g("Cancelled")}})).addCommand(new ve("refresh").description("Refresh cached feature flags").action(async()=>{let e=_t("Refreshing feature flags...").start();try{await Ee(),e.succeed("Feature flags refreshed"),g(`Run '${m.commands[0]} --help' to see updated commands`)}catch(t){e.fail("Failed to refresh"),s(t instanceof Error?t.message:String(t)),process.exit(1)}})).addCommand(new ve("path").description("Show configuration file path").option("--cache","Show feature cache file path").action(e=>{e.cache?console.log(Go()):console.log(ot())})).addCommand(new ve("pull").description("Pull your account settings (memory, brand, prefs) into a local config.toml").action(async()=>{let e=_t("Pulling settings...").start();try{let t=await he(),n=await fetch(`${B()}/api/cli/settings`,{headers:t});if(!n.ok)throw new Error(`Request failed (HTTP ${n.status})`);let r=await n.text(),o=fd(Bo(ot()),"settings.toml");pd(Bo(o),{recursive:!0}),gd(o,r,"utf8"),e.succeed("Settings pulled"),g(`Written to ${o}`)}catch(t){e.fail("Failed to pull settings"),s(t instanceof Error?t.message:String(t)),process.exit(1)}}));import{Command as wd}from"commander";import{confirm as vd}from"@inquirer/prompts";var Jo=new wd("delete").description("Delete a presentation").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --force","Skip confirmation prompt").option("-q, --quiet","Suppress output").action(async(e,t)=>{if(await O(),!t.force)try{if(!await vd({message:`Are you sure you want to delete presentation "${e}"?`,default:!1})){t.quiet||M("Deletion cancelled");return}}catch{t.quiet||M("Deletion cancelled");return}try{await oo(e),t.quiet||x(`Presentation "${e}" deleted`)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as je}from"commander";import Xo from"chalk";import xd from"ora";import{createParser as Gf}from"eventsource-parser";import Wf from"chalk";import Jf from"ora";async function zo(e,t={}){let n=e.body?.getReader();if(!n)throw new Error("Response body is not readable");let r=new TextDecoder,o="",i=!1;for(;!i;){let a=await n.read();if(i=a.done,a.value){let d=r.decode(a.value,{stream:!0});o+=d,t.quiet||process.stdout.write(d)}}return t.quiet||console.log(),o}function kd(){return new je("blog").description("Generate a blog post from a presentation").argument("<slug>","Presentation slug").option("--words <count>","Target word count (50-2000)","300").option("--tone <tone>","Writing tone (professional, casual, educational)","professional").option("--audience <text>","Target audience description").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").option("--instructions <text>","Custom instructions for the blog").option("--no-images","Exclude image references").option("--toc","Include table of contents").action(async(e,t)=>{await O();let n=parseInt(t.words,10);(Number.isNaN(n)||n<50||n>2e3)&&(s("Word count must be between 50 and 2000"),process.exit(6));let r=["professional","casual","educational"];r.includes(t.tone)||(s(`Invalid tone. Valid options: ${r.join(", ")}`),process.exit(6));let o=xd("Fetching presentation...").start();try{let i=await Ue(e);o.text="Generating blog post...";let a=await po(i.id,i.documentCreatedAt||i.createdAt,{targetWordCount:n,tone:t.tone,targetAudience:t.audience??"General Audience",customInstructions:t.instructions??"",includeImages:!t.noImages,includeTableOfContents:t.toc??!1}),d=await zo(a,{quiet:!0});o.succeed("Blog generated"),t.format==="json"?console.log(JSON.stringify({presentationId:e,title:i.title,wordCount:n,tone:t.tone,content:d},null,2)):t.format==="markdown"?console.log(d):(console.log(),console.log(Xo.bold(`Blog: ${i.title}`)),console.log(Xo.gray("\u2500".repeat(40))),console.log(),console.log(d),console.log())}catch(i){o.fail("Generation failed"),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})}function Cd(){return new je("tweets").description("Generate tweets from a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of tweets to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(e,t)=>{await O(),g("Tweet generation coming soon.")})}function Id(){return new je("linkedin").description("Generate a LinkedIn carousel from a presentation").argument("<slug>","Presentation slug").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O(),g("LinkedIn carousel generation coming soon.")})}function Rd(){return new je("questions").description("Generate questions for a presentation").argument("<slug>","Presentation slug").option("--count <n>","Number of questions","10").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async(e,t)=>{await O(),g("Question generation coming soon.")})}function Sd(){return new je("cheatsheet").description("Generate a presenter cheat sheet").argument("<slug>","Presentation slug").option("--mode <mode>","Cheat sheet mode (qa-prep, talking-points)","qa-prep").option("-f, --format <format>","Output format (human, json, markdown)",b("--format",["human","json","markdown"]),"human").action(async(e,t)=>{await O(),g("Cheat sheet generation coming soon.")})}function Ho(){let e=new je("derive").description("Generate derivative content from a presentation"),t=Vo();return t&&(t.deckToBlog&&e.addCommand(kd()),t.deckToTweets&&e.addCommand(Cd()),t.linkedInCarousel&&e.addCommand(Id()),t.redTeamQuestions&&e.addCommand(Rd()),t.presenterCheatSheet&&e.addCommand(Sd())),e}import{Command as $d}from"commander";import Sn from"chalk";var Yo=new $d("ideas").description("Generate presentation topic ideas").option("--context <text>","Custom context for idea generation").option("--count <n>","Number of ideas to generate","5").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O(),g("Idea generation is available in the web dashboard."),console.log(),console.log(Sn.gray("The CLI will support idea generation in a future release.")),console.log(),console.log("For now, try these approaches:"),console.log(Sn.gray("` 1. Visit the ${brand.displayName} dashboard and use the idea generator`")),console.log(Sn.gray(" 2. Create a presentation with a broad topic and refine it")),console.log()});import{Command as Td}from"commander";import{readFile as Ed}from"fs/promises";import{resolve as Ad,basename as Od}from"path";import Pd from"ora";var Qo=new Td("import").description("Import a presentation from ZIP (admin only)").argument("<file>","Path to ZIP file");Qo._hidden=!0;var Zo=Qo.option("--dry-run","Validate without importing").option("--overwrite","Overwrite existing presentations").option("--remap-ids","Generate new IDs (default: true)",!0).action(async(e,t)=>{await O();try{(await ye()).user.role!=="admin"&&(s("This command is only available to administrators"),process.exit(2))}catch{s("Failed to verify permissions"),process.exit(2)}let n=Ad(e),r=Od(n);r.endsWith(".zip")||(s("File must be a ZIP archive"),process.exit(6));let o=Pd("Reading file...").start();try{let i=await Ed(n);t.dryRun?o.text="Validating...":o.text="Importing presentation...";let a=await so(i,r,{dryRun:t.dryRun});if(a.success){if(t.dryRun)o.succeed("Validation passed!"),console.log(),g("The file is valid and can be imported."),a.statistics&&(console.log(),R("Slides",String(a.statistics.slidesImported)),R("Images",String(a.statistics.imagesUploaded)));else if(o.succeed("Import complete!"),console.log(),R("Presentation ID",a.presentationId??"N/A"),R("Document ID",a.documentId??"N/A"),a.statistics&&(R("Slides imported",String(a.statistics.slidesImported)),R("Images uploaded",String(a.statistics.imagesUploaded)),R("Time",`${a.statistics.totalTimeMs}ms`)),a.presentationId){let d=B();R("View URL",`${d}/p/${a.presentationId}`)}if(a.warnings&&a.warnings.length>0){console.log();for(let d of a.warnings)M(d)}console.log()}else{if(o.fail("Import failed"),console.log(),a.errors)for(let d of a.errors)s(`${d.type}: ${d.message}`);process.exit(1)}}catch(i){o.fail("Import failed"),i.code==="ENOENT"&&(s(`File not found: ${n}`),process.exit(3)),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}});import{Command as _d}from"commander";var ei=new _d("list").description("List presentations").option("-n, --limit <count>","Number of results to return","20").option("-f, --format <format>","Output format (table, json, ids)",b("--format",["table","json","ids"]),"table").option("--sort <field>","Sort by field (created, updated, title)").option("--team-id <id>","Team ID (uses default if not specified)").option("-d, --detail","Show detailed output including URLs").option("-l, --language <lang>","Language for URLs","en").action(async e=>{await O();let t=parseInt(e.limit,10);(Number.isNaN(t)||t<1)&&(s("Invalid limit value"),process.exit(6));let n=e.teamId??Ct();n||(s("`Team ID required. Set a default with '${brand.commands[0]} config set team-id <id>' or use --team-id`"),process.exit(6));try{let r=await to(n,t);if(r.length===0){e.format==="json"?console.log(JSON.stringify([])):e.format!=="ids"&&g("No presentations found");return}switch(e.sort&&r.sort((o,i)=>{switch(e.sort){case"created":return new Date(i.createdAt).getTime()-new Date(o.createdAt).getTime();case"title":return(o.title||"").localeCompare(i.title||"");default:return 0}}),e.format){case"json":console.log(JSON.stringify(r,null,2));break;case"ids":console.log(qr(r));break;default:console.log(Nr(r,{showLinks:e.detail,language:e.language}));break}}catch(r){s(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});import{createHash as Ld,randomBytes as ri}from"crypto";import oi from"http";import ti from"chalk";import{Command as Dd}from"commander";import Nd from"open";import ni from"ora";var qd=`${m.displayName} CLI`,Ud=8765,jd=8775,Md=["presentations:read","presentations:write","media:read","media:write"];function Fd(){return ri(32).toString("base64url")}function Vd(e){return Ld("sha256").update(e).digest("base64url")}function Gd(){return ri(16).toString("hex")}async function Bd(e,t){for(let n=e;n<=t;n++)try{return await new Promise((r,o)=>{let i=oi.createServer();i.listen(n,()=>{i.close(()=>r())}),i.on("error",o)}),n}catch{}throw new Error(`No available port found between ${e} and ${t}`)}async function Wd(e){let t=await fetch(`${e}/.well-known/oauth-authorization-server`);if(!t.ok)throw new Error(`Failed to fetch OAuth metadata: ${t.status}`);return t.json()}function Kd(e){let t=e.scopes_supported?.filter(n=>typeof n=="string"&&n.trim().length>0);return(t?.length?t:Md).join(" ")}async function Jd(e,t,n){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:qd,redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none",scope:n})});if(!r.ok){let o=await r.text();throw new Error(`Client registration failed: ${o}`)}return r.json()}async function zd(e,t,n,r,o){let i=new URLSearchParams({grant_type:"authorization_code",code:t,redirect_uri:r,client_id:o,code_verifier:n}),a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()});if(!a.ok){let d=await a.text();throw new Error(`Token exchange failed: ${d}`)}return a.json()}function Xd(e,t){return new Promise((n,r)=>{let o,i=!1,a=()=>{i||(i=!0,clearTimeout(o),process.off("SIGINT",d),process.off("SIGTERM",d),l.close())},d=()=>{a(),r(new Error("Login cancelled"))},l=oi.createServer((y,p)=>{let w=new URL(y.url||"",`http://localhost:${e}`);if(w.pathname!=="/callback"){p.writeHead(404),p.end("Not found");return}let v=w.searchParams.get("code"),C=w.searchParams.get("state"),E=w.searchParams.get("error"),k=w.searchParams.get("error_description");if(p.writeHead(200,{"Content-Type":"text/html"}),E){p.end(`
|
|
14
6
|
<!DOCTYPE html>
|
|
15
7
|
<html>
|
|
16
8
|
<head><title>Login Failed</title></head>
|
|
17
9
|
<body style="font-family: system-ui; text-align: center; padding: 50px;">
|
|
18
10
|
<h1 style="color: #dc2626;">Login Failed</h1>
|
|
19
|
-
<p>${
|
|
11
|
+
<p>${k||E}</p>
|
|
20
12
|
<p>You can close this window.</p>
|
|
21
13
|
</body>
|
|
22
14
|
</html>
|
|
23
|
-
`),a(),r(new Error(
|
|
15
|
+
`),a(),r(new Error(k||E));return}if(!v||!C){p.end(`
|
|
24
16
|
<!DOCTYPE html>
|
|
25
17
|
<html>
|
|
26
18
|
<head><title>Login Failed</title></head>
|
|
@@ -30,7 +22,7 @@ ${_t.bold("See also:")}
|
|
|
30
22
|
<p>You can close this window.</p>
|
|
31
23
|
</body>
|
|
32
24
|
</html>
|
|
33
|
-
`),a(),r(new Error("Missing authorization code or state"));return}if(
|
|
25
|
+
`),a(),r(new Error("Missing authorization code or state"));return}if(C!==t){p.end(`
|
|
34
26
|
<!DOCTYPE html>
|
|
35
27
|
<html>
|
|
36
28
|
<head><title>Login Failed</title></head>
|
|
@@ -49,149 +41,168 @@ ${_t.bold("See also:")}
|
|
|
49
41
|
<p>You can close this window and return to the terminal.</p>
|
|
50
42
|
</body>
|
|
51
43
|
</html>
|
|
52
|
-
`),a(),n({code:v,state:
|
|
53
|
-
`)[0]??"";n(a?{bin:t,version:a}:null)})})}var
|
|
44
|
+
`),a(),n({code:v,state:C})});l.listen(e),process.once("SIGINT",d),process.once("SIGTERM",d),o=setTimeout(()=>{a(),r(new Error("Login timed out - no callback received within 5 minutes"))},300*1e3)})}async function Hd(e,t){let n=await fetch(`${e}/api/cli/whoami`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)throw new Error(`Failed to fetch user info: ${n.status}`);return n.json()}async function Yd(e){let t=B(),n=ni("Discovering OAuth server...").start();try{let r=await Wd(t),o=Kd(r);n.succeed(`Connecting to ${t}`);let i=await Bd(Ud,jd),a=`http://localhost:${i}/callback`;console.log(`Redirect URI: ${a}`),console.log(`Authorization endpoint: ${r.authorization_endpoint}`),console.log(`Token endpoint: ${r.token_endpoint}`),console.log(`Registration endpoint: ${r.registration_endpoint}`);let d=await Jd(r.registration_endpoint,a,o),l=d.client_id;Lr(l,d.client_secret);let y=Fd(),p=Vd(y),w=Gd(),v=new URLSearchParams({client_id:l,redirect_uri:a,response_type:"code",scope:o,state:w,code_challenge:p,code_challenge_method:"S256"}),C=`${r.authorization_endpoint}?${v}`;console.log(`Authorization URL: ${C}`),e.browser?(g("Opening browser..."),await Nd(C)):(console.log(ti.bold("Open this URL in your browser:")),console.log(ti.cyan(C)));let E=Xd(i,w),{code:k}=await E;n=ni("Completing login...").start();let $=await zd(r.token_endpoint,k,y,a,l);Rt($.access_token,$.refresh_token,$.expires_in);let S=await Hd(t,$.access_token);n.succeed("Logged in!"),console.log(),R("Logged in as",S.user.email),S.currentTeam&&(De(S.currentTeam.id),R("Team",`${S.currentTeam.name} (${S.currentTeam.planName})`));try{await Ee()}catch{}console.log(),x("You're all set!"),console.log()}catch(r){throw n.fail("Login failed"),s(r instanceof Error?r.message:String(r)),r}}var ii=new Dd("login").description(`Authenticate with ${m.displayName} (opens browser)`).option("--no-browser","Print URL instead of opening browser").action(async e=>{console.log(),$e()&&(M("You are already logged in."),g(`Run '${m.commands[0]} logout' to log out first, or continue to re-authenticate.`),console.log());try{await Yd(e),process.exit(0)}catch{process.exit(1)}});import{Command as Qd}from"commander";import{confirm as Zd}from"@inquirer/prompts";var ai=new Qd("logout").description("Log out and clear authentication").option("--all","Clear all config including API key").action(async e=>{console.log();let t=$e(),n=Ne();if(!t&&!n){M("You are not logged in."),console.log();return}if(e.all)try{await Zd({message:"Clear all configuration including API key?",default:!1})?(It(),Ae(),x("All configuration cleared.")):g("Cancelled.")}catch{g("Cancelled.")}else St(),Ae(),x("Logged out successfully."),n&&g("Note: Your API key is still configured. Use --all to clear everything.");console.log()});import{homedir as Uc}from"os";import{join as jc}from"path";import de from"chalk";import{Command as Mc}from"commander";import{spawn as ec}from"child_process";import{existsSync as tc,readdirSync as nc}from"fs";import{homedir as ci}from"os";import{delimiter as si}from"path";import{query as rc}from"@anthropic-ai/claude-agent-sdk";function ne(e){if(e===void 0)return null;if(typeof e=="string")return e.length>12e3?`${e.slice(0,12e3)}\u2026`:e;try{let t=JSON.stringify(e);return t.length<=12e3?e:{preview:`${t.slice(0,12e3)}\u2026`,truncated:!0}}catch{return String(e).slice(0,12e3)}}function Lt(e){let t=typeof e=="string"?e:String(e??"");return t.length>12e3?`${t.slice(0,12e3)}\u2026`:t}function re(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function D(e){return typeof e=="string"?e:""}function di(e,t){let n=e.replace(/[/.]/g,"-");return`${ci()}/.claude/projects/${n}/${t}.jsonl`}function oc(e){try{return nc(`${e}/.nvm/versions/node`).map(t=>`${e}/.nvm/versions/node/${t}/bin`).sort().reverse()}catch{return[]}}function Dt(){let e=ci(),t=[`${e}/.local/bin`,`${e}/.claude/local`,`${e}/.bun/bin`,`${e}/bin`,"/opt/homebrew/bin","/usr/local/bin",...oc(e)],r=(process.env.PATH??"").split(si);for(let o of t)r.includes(o)||r.push(o);return r.join(si)}async function Nt(e){let t=e??"claude";return new Promise(n=>{let r=ec(t,["--version"],{env:{...process.env,PATH:Dt()},stdio:["ignore","pipe","ignore"]}),o="";r.stdout.on("data",i=>{o+=i.toString("utf8")}),r.on("error",()=>n(null)),r.on("close",i=>{if(i!==0)return n(null);let a=o.trim().split(`
|
|
45
|
+
`)[0]??"";n(a?{bin:t,version:a}:null)})})}var ic=new Set(["","default","best"]);function $n(e){let t=e.filter(i=>i.text.trim());if(t.length===0)return"";let n=t[t.length-1],r=t.slice(0,-1);return r.length===0?n.text:`<conversation-history>
|
|
54
46
|
${r.map(i=>`${i.role==="assistant"?"Assistant":"User"}: ${i.text}`).join(`
|
|
55
47
|
|
|
56
48
|
`)}
|
|
57
49
|
</conversation-history>
|
|
58
50
|
|
|
59
|
-
${n.text}`}function
|
|
60
|
-
`)[0]??"";t(i||null)})})}var
|
|
61
|
-
`)}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
|
|
62
|
-
`);return a===-1?"":i.slice(a+1)}finally{
|
|
63
|
-
`):e&&typeof e=="object"?Object.values(e).map(
|
|
64
|
-
`):""}function
|
|
65
|
-
|
|
66
|
-
`),usage:a}}function
|
|
67
|
-
`,"utf8")}catch{}}function
|
|
68
|
-
`,"utf8")}catch{}}var
|
|
69
|
-
Stopping runner\u2026`)),t.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await Ri({claudeBin:e.claudeBin,codexBin:e.codexBin,log:r=>console.log(ie.gray(`[runner] ${r}`)),once:e.once,signal:t.signal,version:"0.3.19",workspaceRoot:e.workspace??Kc()})}catch(r){console.error(ie.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import q from"chalk";import{Command as Yp}from"commander";import{Command as Fn}from"commander";function Jc(e,t){return[...t,e]}var zc=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)",Jc,[]).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{m(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)}}),Xc=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{m(await T("createAdSet",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Si=new Fn("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(zc).addCommand(Xc);import{randomUUID as Hc}from"crypto";import{Command as Fe}from"commander";function $i(e){return new Fe(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{m(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 Ti(e){return`cli:agent-memory:${e}:${Hc()}`}function Yc(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 Qc=new Fe("show").description("Show what a scheduled agent remembers").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{m(await y("getAgentMemory",{agentId:e,teamId:t.teamId}))}catch(n){Gn(n,"Could not read the agent's memory")}}),Zc=new Fe("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)",Yc,[]).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{m(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},Ti(n?"remove":"add")))}catch(r){Gn(r,"Could not update the agent's memory")}}),el=new Fe("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{m(await y("forgetAgentMemory",{agentId:e,teamId:t.teamId},Ti("forget")))}catch(n){Gn(n,"Could not erase the agent's memory")}}),tl=new Fe("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(Qc).addCommand(Zc).addCommand(el),Ei=new Fe("agent").description("Create scheduled agents and read, edit, or erase what they remember").addCommand($i("create")).addCommand($i("recommend")).addCommand(tl);import{randomUUID as Pi}from"crypto";import{existsSync as ol}from"fs";import{resolve as il}from"path";import ct from"chalk";import{Command as ye}from"commander";import al from"ora";import{mkdir as nl,writeFile as Ai}from"fs/promises";import{dirname as rl}from"path";async function H(e,t){if(await nl(rl(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 Ai(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 Ai(t,r)}var sl=15e3,dl=40,Oi=3;async function _i(e,t){if(e?.length){if(e.length>Oi)throw new Error(`A presenter Look accepts at most ${Oi} reference images`);return Promise.all(e.map(async(n,r)=>{if(ol(n))return{url:(await ue(il(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"){m(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&&C(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}var cl=new ye("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 Ro(e.language);if(e.format==="json"){m(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)}}),ll=new ye("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"?al("Generating presenter clip...").start():null;try{let o=e.audioUrl?{audioUrl:e.audioUrl}:{script:e.script??"",...e.voiceId?{voiceId:e.voiceId}:{}},i=await So({...o,aspect:e.aspect,...e.avatarId?{avatarId:e.avatarId}:{},...e.backgroundColor?{backgroundHex:e.backgroundColor}:{},...e.backgroundImageUrl?{backgroundImageUrl:e.backgroundImageUrl}:{},...n!==void 0?{durationSec:n}:{},...e.fit?{fit:e.fit}:{},...t?{outputFormat:t}:{},renderTier:e.renderTier,title:e.title});if(!e.wait){r?.stop(),Bn(i,e.format);return}let a=await Z(()=>Tn(i.requestId),dl,sl);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 H(a.videoUrl,e.output),r?.stop(),Bn(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)}}),ul=new ye("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{Bn(await Tn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ml=new ye("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??Pi(),r=await _i(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);m(o)}catch(n){d(n instanceof Error?n.message:"Look generation failed"),process.exit(c.GENERAL_ERROR)}}),pl=new ye("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 m(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)}}),gl=new ye("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??Pi(),r=await _i(t.referenceImage,n),o=await y("revisePresenterLook",{instruction:t.instruction,...r?{referenceImages:r}:{},sourceLookId:e},n);m(o)}catch(n){d(n instanceof Error?n.message:"Look revision failed"),process.exit(c.GENERAL_ERROR)}}),fl=new ye("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 m(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)}}),hl=new ye("look").description("Manage looks under an existing personal presenter").addCommand(ml).addCommand(gl).addCommand(fl).addCommand(pl),Wn=new ye("avatar").description("Generate presenter clips and looks; avatar options lists the voices and looks used by presentation video presenter and cast preset").addCommand(cl).addCommand(ll).addCommand(hl).addCommand(ul);Wn.addHelpText("after",`
|
|
51
|
+
${n.text}`}function Tn(e,t){return t?e.messages.filter(r=>r.text.trim()).at(-1)?.text??"":$n(e.messages)}function ac({abortController:e,input:t,resumeSessionId:n,workspace:r}){let o=(t.modelId??"").trim(),i=t.thinking??null,a={abortController:e,allowedTools:["WebSearch","WebFetch"],cwd:r,env:{...process.env,PATH:Dt()},includePartialMessages:!0,maxTurns:16,permissionMode:"dontAsk"};return ic.has(o)||(a.model=o),t.effort&&(a.effort=t.effort),i&&i!=="disabled"&&(a.thinking={display:"summarized",type:i==="enabled"?"enabled":"adaptive"}),n?a.resume=n:t.system?.trim()&&(a.systemPrompt=t.system),a}async function li(e){let t=Tn(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new AbortController,r=()=>n.abort();e.signal?.addEventListener("abort",r,{once:!0});let o=null,i=null,a=null,d=null,l=null,y=0,p=new Set;try{let C=rc({prompt:t,options:ac({abortController:n,input:e.input,resumeSessionId:e.resumeSessionId,workspace:e.workspace})});for await(let E of C){let k=E;if(k.type==="system"&&k.subtype==="init"){typeof k.session_id=="string"&&(i=k.session_id,e.onEvent({eventType:"chat.session",payload:{sessionId:i,sessionPath:di(e.workspace,i)}})),typeof k.model=="string"&&(o=k.model,e.onEvent({eventType:"chat.model",payload:{modelId:k.model}}));continue}if(k.type==="stream_event"){let $=k.event;if($?.type!=="content_block_delta")continue;let S=$.delta;if(!S)continue;S.type==="text_delta"&&typeof S.text=="string"?(y+=S.text.length,e.onEvent({eventType:"chat.text.delta",payload:{text:S.text}})):S.type==="thinking_delta"&&typeof S.thinking=="string"&&e.onEvent({eventType:"chat.reasoning.delta",payload:{text:S.thinking}});continue}if(k.type==="assistant"){let $=re(k.message),S=Array.isArray($.content)?$.content:[];for(let V of S){let A=re(V);if(A.type!=="tool_use")continue;let q=D(A.id),I=D(A.name);!q||!I||p.has(q)||(p.add(q),e.onEvent({eventType:"chat.tool.started",payload:{input:ne(A.input),toolCallId:q,toolName:I}}))}continue}if(k.type==="user"){let $=re(k.message),S=Array.isArray($.content)?$.content:[];for(let V of S){let A=re(V);if(A.type!=="tool_result")continue;let q=D(A.tool_use_id);q&&e.onEvent({eventType:"chat.tool.completed",payload:{...A.is_error===!0?{errorText:typeof A.content=="string"?Lt(A.content):"Claude tool call failed."}:{},output:ne(A.content),toolCallId:q}})}continue}k.type==="result"&&(typeof k.result=="string"&&(d=k.result),k.usage&&typeof k.usage=="object"&&(a=k.usage),typeof k.session_id=="string"&&(i=k.session_id),(k.is_error===!0||k.subtype!=="success")&&(l=typeof k.result=="string"&&k.result||`Claude turn failed (${String(k.subtype)}).`,e.onEvent({eventType:"chat.error",message:l,payload:{message:l}})))}}finally{e.signal?.removeEventListener("abort",r)}if(e.signal?.aborted)throw new Error("Chat turn cancelled.");if(l)throw new Error(l);let w=d??"";y===0&&w&&e.onEvent({eventType:"chat.text.delta",payload:{text:w}});let v=i?di(e.workspace,i):null;return{modelId:o,sessionId:i,sessionPath:v&&tc(v)?v:null,text:w,usage:a}}import{spawn as sc}from"child_process";import{closeSync as dc,fstatSync as cc,openSync as lc,readdirSync as mc,readSync as uc}from"fs";import{homedir as pc}from"os";import{join as mi}from"path";import{Codex as gc}from"@openai/codex-sdk";var fc=["/Applications/Codex.app/Contents/Resources/codex"];async function qt(e){let t=e?[e]:["codex",...fc];for(let n of t){let r=await hc(n);if(r)return{bin:n,version:r}}return null}function hc(e){return new Promise(t=>{let n=sc(e,["--version"],{env:{...process.env,PATH:Dt()},stdio:["ignore","pipe","ignore"]}),r="";n.stdout.on("data",o=>{r+=o.toString("utf8")}),n.on("error",()=>t(null)),n.on("close",o=>{if(o!==0)return t(null);let i=r.trim().split(`
|
|
52
|
+
`)[0]??"";t(i||null)})})}var yc=24,bc=4*1024*1024,gi=new Set(["custom_tool_call","custom_tool_call_output","dynamic_tool_call","function_call"]);function wc(e){let t;try{t=vc(e).split(`
|
|
53
|
+
`)}catch{return[]}let n=new Set,r=new Map,o=null;for(let i of t){if(!i.trim())continue;let a;try{a=JSON.parse(i)}catch{continue}let d=re(a.payload);if(a.type==="response_item"&&d.type==="custom_tool_call"){let l=D(d.call_id),y=D(d.input);l&&d.name==="exec"&&/\btools\.web__run\s*\(/.test(y)&&(n.add(l),o=l);continue}if(a.type==="event_msg"&&d.type==="web_search_end"){let l=D(d.call_id);if(!l||!o)continue;let y=D(d.query),p=re(d.action),v={action:{...p,...y&&!D(p.query)?{query:y}:{}},query:y,sources:ui(d.results),toolCallId:l},C=r.get(o)??[];C.push(v),r.set(o,C);continue}if(a.type==="response_item"&&d.type==="custom_tool_call_output"){let l=D(d.call_id);if(!l||!n.has(l))continue;let y=ui(d.output);for(let p of r.get(l)??[])p.sources.length===0&&(p.sources=y);o===l&&(o=null)}}return Array.from(r.values()).flat()}function vc(e){let t=lc(e,"r");try{let n=cc(t).size,r=Math.max(0,n-bc),o=Buffer.alloc(n-r);uc(t,o,0,o.length,r);let i=o.toString("utf8");if(r===0)return i;let a=i.indexOf(`
|
|
54
|
+
`);return a===-1?"":i.slice(a+1)}finally{dc(t)}}function ui(e){let n=On(e).match(/https?:\/\/[^\s<>"'()[\]{}\\]+/g)??[],r=new Set,o=[];for(let i of n){let a=i.replace(/[.,;:!?]+$/,"");try{let d=new URL(a);if(d.protocol!=="http:"&&d.protocol!=="https:"||r.has(d.href))continue;if(r.add(d.href),o.push({type:"url",url:d.href}),o.length>=yc)break}catch{}}return o}function On(e){return typeof e=="string"?e:Array.isArray(e)?e.map(On).join(`
|
|
55
|
+
`):e&&typeof e=="object"?Object.values(e).map(On).join(`
|
|
56
|
+
`):""}function En(e,t){let n=re(e),r=D(n.type),o=D(n.id),i=D(n.call_id)||D(n.tool_call_id),a=gi.has(r)?i||o:o||i;if(!a)return null;if(r==="command_execution"){let d=D(n.command),l=D(n.status),y={exitCode:typeof n.exit_code=="number"?n.exit_code:null,output:ne(n.aggregated_output)};return{...t&&l==="failed"?{errorText:Lt(n.aggregated_output)||"Command failed."}:{},input:{command:d},...t?{output:y}:{},toolCallId:a,toolName:"Bash"}}if(r==="mcp_tool_call"){let d=re(n.error);return{...t&&D(d.message)?{errorText:D(d.message)}:{},input:ne(n.arguments),...t?{output:ne(n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:D(n.tool)||D(n.name)||"Codex tool"}}if(r==="web_search"){let d=D(n.query);return{input:{query:d},...t?{output:{query:d}}:{},toolCallId:a,toolName:"web_search"}}if(r==="file_change"){let d=D(n.status);return{...t&&d==="failed"?{errorText:"Codex could not apply the file changes."}:{},input:{changes:ne(n.changes)},...t?{output:{changes:ne(n.changes),status:d}}:{},toolCallId:a,toolName:"ApplyPatch"}}if(r==="custom_tool_call_output")return{input:{},...t?{output:ne(n.output)}:{},toolCallId:a,toolName:"Codex tool"};if(r==="custom_tool_call"||r==="dynamic_tool_call"||r==="function_call"){let d=D(n.name)||D(n.tool)||"Codex tool",l=n.input??n.arguments??{};return{input:d==="exec"&&typeof l=="string"?{command:l}:ne(l),...t?{output:ne(n.output??n.result??{status:n.status??"completed"})}:{},toolCallId:a,toolName:d}}return null}function An(e,t=mi(pc(),".codex","sessions")){try{let r=mc(t,{recursive:!0}).find(o=>typeof o=="string"&&o.endsWith(`${e}.jsonl`));return r?mi(t,r):null}catch{return null}}function xc(e,t){return t?Tn(e,t):$n(e.messages)}function kc(e,t,n=m.codexSelfConnectorAppId){let r=t.system?.trim(),o={...r?{developer_instructions:r}:{},...n?{apps:{[n]:{enabled:!1}}}:{}};return{codexPathOverride:e,...Object.keys(o).length>0?{config:o}:{}}}var Cc=new Set(["minimal","low","medium","high","xhigh"]);function Ic(e,t){let n={networkAccessEnabled:!0,sandboxMode:"workspace-write",skipGitRepoCheck:!0,webSearchEnabled:!0,workingDirectory:t},r=(e.modelId??"").trim();return r&&r!=="default"&&(n.model=r),e.effort&&Cc.has(e.effort)&&(n.modelReasoningEffort=e.effort),n}async function fi(e){let t=xc(e.input,e.resumeSessionId);if(!t)throw new Error("Chat turn has no user text to send.");let n=new gc(kc(e.bin,e.input)),r=Ic(e.input,e.workspace),o=e.resumeSessionId?n.resumeThread(e.resumeSessionId,r):n.startThread(r),i=e.resumeSessionId??null,a=null,d=null,l=[],y=new Set,p=new Set,w=null,v=k=>{w??=An(k,e.sessionsRoot),e.onEvent({eventType:"chat.session",payload:{sessionId:k,sessionPath:w}})},C=k=>{i&&(w??=An(i,e.sessionsRoot));let $=w?wc(w):[],S=D(re(k.input).query),V=pi(S),A=$.find(q=>!y.has(q.toolCallId)&&pi(q.query)===V)??$.find(q=>!y.has(q.toolCallId));A&&y.add(A.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:{...k,output:A?{action:A.action,query:A.query,sources:A.sources}:{action:{query:S,type:"search"},sourceListUnavailable:!0,sources:[]}}})},{events:E}=await o.runStreamed(t);i&&v(i);for await(let k of E){if(e.signal?.aborted)throw await E.return?.(void 0),new Error("Chat turn cancelled.");let $=k;if($.type==="thread.started"){typeof $.thread_id=="string"&&(i=$.thread_id,v($.thread_id));continue}if($.type==="item.started"){let S=En($.item,!1);if(S){e.onEvent({eventType:"chat.tool.started",payload:S});let V=re($.item);if(gi.has(D(V.type))&&D(V.status)==="completed"){let A=En(V,!0);A&&(p.add(A.toolCallId),e.onEvent({eventType:"chat.tool.completed",payload:A}))}}continue}if($.type==="item.completed"){let S=$.item;if(!S)continue;if(S.type==="agent_message"&&typeof S.text=="string")l.push(S.text),e.onEvent({eventType:"chat.text.delta",payload:{text:S.text}});else if(S.type==="reasoning"&&typeof S.text=="string")e.onEvent({eventType:"chat.reasoning.delta",payload:{text:S.text}});else{let V=En(S,!0);V&&(S.type==="web_search"?C(V):S.type==="custom_tool_call"&&p.has(V.toolCallId)||e.onEvent({eventType:"chat.tool.completed",payload:V}))}continue}if($.type==="turn.completed"){$.usage&&typeof $.usage=="object"&&(a=$.usage);continue}if($.type==="turn.failed"){let S=$.error;d=typeof S?.message=="string"&&S.message||"Codex turn failed.",e.onEvent({eventType:"chat.error",message:d,payload:{message:d}})}}if(d)throw new Error(d);return i=o.id??i,i&&(w??=An(i,e.sessionsRoot)),{modelId:e.input.modelId??null,sessionId:i,sessionPath:w,text:l.join(`
|
|
57
|
+
|
|
58
|
+
`),usage:a}}function pi(e){return e.trim().replace(/\s+/g," ").toLocaleLowerCase()}import{randomUUID as Ec}from"crypto";import{mkdir as Ac}from"fs/promises";import{hostname as jt,platform as Oc}from"os";import{join as Pc}from"path";var Me=class extends Error{constructor(n,r,o=!1){super(n);this.statusCode=r;this.reRegister=o;this.name="RunnerApiError"}statusCode;reRegister};async function Fe(e,t={}){let n=await he();t.body!==void 0&&(n["Content-Type"]="application/json");let r=new AbortController,o=setTimeout(()=>r.abort(),t.timeoutMs??3e4),i=()=>r.abort();t.signal?.addEventListener("abort",i,{once:!0});try{let a=await fetch(`${B()}${e}`,{body:t.body!==void 0?JSON.stringify(t.body):void 0,headers:n,method:t.method??"GET",signal:r.signal}),d=await a.text(),l={};try{l=d?JSON.parse(d):{}}catch{l={error:d.slice(0,300)}}if(!a.ok)throw new Me(typeof l.error=="string"?l.error:`Runner API returned ${a.status}`,a.status,l.reRegister===!0);return l}finally{clearTimeout(o),t.signal?.removeEventListener("abort",i)}}async function hi(e){await Fe("/api/runner/register",{body:e,method:"POST",timeoutMs:15e3})}async function yi(e,t){return(await Fe(`/api/runner/work?runnerId=${encodeURIComponent(e)}`,{signal:t,timeoutMs:28e3})).job??null}async function bi(e){await Fe("/api/runner/heartbeat",{body:{runnerId:e},method:"POST",timeoutMs:1e4})}async function wi(e,t){return{cancelRequested:(await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/events`,{body:{events:t},method:"POST",timeoutMs:15e3})).cancelRequested===!0}}async function Pn(e,t,n){await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/complete`,{body:{result:n,runnerId:t},method:"POST",timeoutMs:15e3})}async function Ut(e,t,n,r=!0){await Fe(`/api/runner/jobs/${encodeURIComponent(e)}/fail`,{body:{message:n,retryable:r,runnerId:t},method:"POST",timeoutMs:15e3})}import{mkdirSync as Rc,readFileSync as Sc,writeFileSync as vi}from"fs";import{dirname as $c,join as Tc}from"path";function _n(e){return Tc(e,"sessions.json")}function Ln(e){try{let t=Sc(_n(e),"utf8"),n=JSON.parse(t);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}return{}}function xi(e,t,n){return t?Ln(e)[t]?.[n]??null:null}function ki(e,t,n,r){if(!(!t||!r))try{let o=_n(e);Rc($c(o),{recursive:!0});let i=Ln(e);i[t]={...i[t],[n]:r},vi(o,`${JSON.stringify(i,null," ")}
|
|
59
|
+
`,"utf8")}catch{}}function Ci(e,t,n){if(t)try{let r=Ln(e);if(!r[t])return;delete r[t][n],vi(_n(e),`${JSON.stringify(r,null," ")}
|
|
60
|
+
`,"utf8")}catch{}}var _c=300,Lc=3e4;async function Ii(e){let[t,n]=await Promise.all([Nt(e.claudeBin),qt(e.codexBin)]);if(!t&&!n)throw new Error("Neither Claude Code nor Codex was found on this machine. Install one and log in, then retry.");t?e.log(`Claude Code detected: ${t.version} (${t.bin})`):e.log("Claude Code not found \u2014 Claude turns will be declined."),n?e.log(`Codex detected: ${n.version} (${n.bin})`):e.log("Codex not found \u2014 Codex turns will be declined.");let r=[...t?["claude-code"]:[],...n?["codex"]:[]],o=`${jt().split(".")[0]}-${Ec().slice(0,8)}`,i=()=>hi({capabilities:["chat_turn","proof"],claudeCodeVersion:t?.version??null,cliVersion:e.version,codexVersion:n?.version??null,hostname:jt(),platform:Oc(),runnerId:o,runtimes:r});for(await i(),e.log(`Registered as ${o} (runtimes: ${r.join(", ")}). Waiting for work\u2026`);!e.signal?.aborted;){let a=null;try{a=await yi(o,e.signal)}catch(d){if(e.signal?.aborted)break;if(d instanceof Me&&d.reRegister){e.log("Server asked for re-registration."),await i().catch(()=>{});continue}e.log(`Work poll failed (${d instanceof Error?d.message:"unknown"}); retrying\u2026`),await qc(e.pollBackoffMs??5e3,e.signal);continue}if(!a){if(e.once)continue;continue}if(e.log(`Claimed ${a.jobType} job ${a.runId}.`),await Dc({claude:t,codex:n,job:a,options:e,runnerId:o}),e.once)break}}async function Dc({claude:e,codex:t,job:n,options:r,runnerId:o}){let i=new AbortController,a=()=>i.abort();r.signal?.addEventListener("abort",a,{once:!0});let d=setInterval(()=>{bi(o).catch(()=>{})},Lc),l=[],y=!1,p=async()=>{if(y||l.length===0)return;y=!0;let C=l.splice(0,100);try{let{cancelRequested:E}=await wi(n.runId,C);E&&i.abort()}catch(E){E instanceof Me&&E.statusCode===409&&i.abort()}finally{y=!1}},w=setInterval(()=>{p()},_c),v=C=>{l.push(C)};try{if(n.jobType==="runner.proof"){let C=typeof n.input.message=="string"?n.input.message:"proof";v({eventType:"proof.echo",payload:{message:C}}),await Dn(p,l),await Pn(n.runId,o,{echo:C}),r.log(`Proof job ${n.runId} completed.`);return}if(n.jobType==="runner.chat_turn"){let C=n.input.runtime==="codex"?"codex":"claude-code",E=C==="codex"?t&&{detection:t,run:fi}:e&&{detection:e,run:li};if(!E){await Ut(n.runId,o,C==="codex"?"Codex is not available on this machine. Install the Codex app or CLI and log in, then retry.":"Claude Code is not available on this machine. Install it and log in, then retry.",!1);return}let k=typeof n.input.chatId=="string"&&n.input.chatId?n.input.chatId:null,$=Pc(r.workspaceRoot,"chats",k??n.runId);await Ac($,{recursive:!0});let S=Nc(n.input),V=I=>v({eventType:I.eventType,message:I.message??null,payload:I.eventType==="chat.session"?{host:jt(),runtime:C,runtimeVersion:E.detection.version,...I.payload??{}}:I.payload??{}}),A=xi(r.workspaceRoot,k,C),q;try{q=await E.run({bin:E.detection.bin,input:S,onEvent:V,resumeSessionId:A,signal:i.signal,workspace:$})}catch(I){if(!A||i.signal.aborted)throw I;r.log(`Resume of ${C} session failed (${I instanceof Error?I.message:"unknown"}); retrying fresh.`),Ci(r.workspaceRoot,k,C),q=await E.run({bin:E.detection.bin,input:S,onEvent:V,resumeSessionId:null,signal:i.signal,workspace:$})}ki(r.workspaceRoot,k,C,q.sessionId),v({eventType:"chat.session",payload:{host:jt(),runtime:C,runtimeVersion:E.detection.version,sessionId:q.sessionId,sessionPath:q.sessionPath}}),await Dn(p,l),await Pn(n.runId,o,{modelId:q.modelId,runtime:C,runtimeVersion:E.detection.version,sessionId:q.sessionId,sessionPath:q.sessionPath,text:q.text,usage:q.usage??{}}),r.log(`Chat turn ${n.runId} (${C}) completed.`);return}await Ut(n.runId,o,`This runner does not support ${n.jobType} jobs. Update the desktop app / CLI.`,!1)}catch(C){let E=C instanceof Error?C.message:"Local runner job crashed.";r.log(`Job ${n.runId} failed: ${E}`),await Dn(p,l).catch(()=>{}),await Ut(n.runId,o,E).catch(()=>{})}finally{clearInterval(w),clearInterval(d),r.signal?.removeEventListener("abort",a)}}function Nc(e){let t=Array.isArray(e.messages)?e.messages.map(n=>{if(!n||typeof n!="object")return null;let r=n;return{role:typeof r.role=="string"?r.role:"user",text:typeof r.text=="string"?r.text:""}}).filter(n=>!!n):[];return{effort:typeof e.effort=="string"?e.effort:null,messages:t,modelId:typeof e.modelId=="string"?e.modelId:null,system:typeof e.system=="string"?e.system:null,thinking:typeof e.thinking=="string"?e.thinking:null}}async function Dn(e,t){for(;t.length>0;)await e(),t.length>0&&await new Promise(n=>setTimeout(n,25))}function qc(e,t){return e<=0||t?.aborted?Promise.resolve():new Promise(n=>{let r=setTimeout(o,e);function o(){clearTimeout(r),t?.removeEventListener("abort",o),n()}t?.addEventListener("abort",o,{once:!0})})}function Fc(){return jc(Uc(),`.${m.commands[0]}-runner`,"runs")}var Mt=new Mc("runner").description("Run agent work locally with your own Claude Code / Codex login (desktop lane)");Mt.command("status").description("Check local Claude Code / Codex detection and account auth").action(async()=>{let[e,t]=await Promise.all([Nt(),qt()]);if(console.log(e?de.green(`\u2713 Claude Code ${e.version}`):de.red("\u2717 Claude Code not found on PATH")),console.log(t?de.green(`\u2713 Codex ${t.version} (${t.bin})`):de.red("\u2717 Codex not found (PATH or Codex.app)")),!fe()){console.log(de.red(`\u2717 Not logged in. Run '${m.commands[0]} login' first.`)),process.exitCode=2;return}try{let n=await ye();console.log(de.green(`\u2713 Logged in as ${n.user.email}`))}catch(n){console.log(de.red(`\u2717 Auth check failed: ${n instanceof Error?n.message:"unknown"}`)),process.exitCode=2}});Mt.command("start").description("Start the local runner (register + wait for work)").option("--once","Execute a single job, then exit").option("--workspace <dir>","Workspace root for job scratch directories").option("--claude-bin <path>","Path to the claude binary").option("--codex-bin <path>","Path to the codex binary").action(async e=>{fe()||(console.error(de.red(`Not authenticated. Run '${m.commands[0]} login' first.`)),process.exit(2));let t=new AbortController,n=()=>{console.log(de.gray(`
|
|
61
|
+
Stopping runner\u2026`)),t.abort()};process.on("SIGINT",n),process.on("SIGTERM",n);try{await Ii({claudeBin:e.claudeBin,codexBin:e.codexBin,log:r=>console.log(de.gray(`[runner] ${r}`)),once:e.once,signal:t.signal,version:"0.3.21",workspaceRoot:e.workspace??Fc()})}catch(r){console.error(de.red(r instanceof Error?r.message:String(r))),process.exit(1)}});import j from"chalk";import{Command as Vp}from"commander";import{Command as Nn}from"commander";function Vc(e,t){return[...t,e]}var Gc=new Nn("create").description("Start durable ad-set generation").argument("<title>","Ad-set title").requiredOption("--brief <brief>","Campaign brief").option("--hook <text>","Opening hook (repeat)",Vc,[]).option("--style <style>","ugc, clean, cinematic, or testimonial","ugc").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve generation");try{u(await h("createAdSet",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,brief:t.brief,hooks:t.hook.length?t.hook:[t.brief],style:t.style,teamId:t.teamId,title:e}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),Bc=new Nn("status").description("Read ad-set generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createAdSet",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ri=new Nn("ad-set").description("Generate a set of ad creatives (hooks, copy, visuals) from a campaign brief").addCommand(Gc).addCommand(Bc);import{randomUUID as Wc}from"crypto";import{Command as Ve}from"commander";function Si(e){return new Ve(e).description(e==="create"?"Create and activate a scheduled agent":"Create a reviewable agent recommendation").argument("<name>","Agent name").requiredOption("--instructions <markdown>","Agent instructions").option("--description <text>","Agent description","").option("--schedule <frequency>","manual, daily, weekdays, weekly, or monthly","weekly").option("--time <hh:mm>","Local run time","09:00").option("--timezone <zone>","IANA timezone","UTC").option("--output <adapter>","Output adapter","digest").option("--team-id <id>","Workspace ID").option("--yes","Approve saving the agent").action(async(t,n)=>{if(!n.yes)return s("Pass --yes to approve this operation");try{u(await h(e==="create"?"createAgent":"recommendAgent",{approvalReceipt:"cli:--yes",description:n.description,instructionsMarkdown:n.instructions,name:t,output:n.output,schedule:n.schedule,scheduleTime:n.time,teamId:n.teamId,timezone:n.timezone}))}catch(r){s(r instanceof Error?r.message:"Agent operation failed"),process.exit(c.GENERAL_ERROR)}})}function Un(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function $i(e){return`cli:agent-memory:${e}:${Wc()}`}function Kc(e,t){let n=e.indexOf("="),r=n===-1?e:e.slice(0,n),o=n===-1?"":e.slice(n+1);return[...t,{name:r.trim(),note:o.trim()}]}function qn(e,t){return[...t,e]}var Jc=new Ve("show").description("Show what a scheduled agent remembers").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("getAgentMemory",{agentId:e,teamId:t.teamId}))}catch(n){Un(n,"Could not read the agent's memory")}}),zc=new Ve("set").description("Add to or remove from what an agent remembers. Owner or workspace admin only.").argument("<agent-id>","Agent ID").option("--learned <text>","Durable fact to add (repeatable)",qn,[]).option("--always <text>","Standing instruction to add (repeatable)",qn,[]).option("--never <text>","Thing it must not do, to add (repeatable)",qn,[]).option("--track <name=note>","Entity to track, as name=note (repeatable)",Kc,[]).option("--notes <text>","Replace the freeform notes").option("--remove <field>","Remove instead of add: learned, recurringInstructions, negativePreferences, entities, or notes").option("--value <text>","Item to remove; not needed when removing notes").option("--expected-version <n>","Refuse the write unless the stored memory is still at this version").option("--team-id <id>","Workspace ID").action(async(e,t)=>{let n=typeof t.remove=="string";try{u(await h("updateAgentMemory",{agentId:e,entities:t.track.length?t.track:void 0,expectedVersion:t.expectedVersion===void 0?void 0:Number.parseInt(t.expectedVersion,10),learned:t.learned.length?t.learned:void 0,negativePreferences:t.never.length?t.never:void 0,notes:t.notes,operation:n?"remove":"add",recurringInstructions:t.always.length?t.always:void 0,removeField:t.remove,removeValue:t.value,teamId:t.teamId},$i(n?"remove":"add")))}catch(r){Un(r,"Could not update the agent's memory")}}),Xc=new Ve("forget").description("Erase every stored version of an agent's memory. This cannot be undone.").argument("<agent-id>","Agent ID").option("--team-id <id>","Workspace ID").option("--yes","Confirm the erase").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to erase this agent's memory");try{u(await h("forgetAgentMemory",{agentId:e,teamId:t.teamId},$i("forget")))}catch(n){Un(n,"Could not erase the agent's memory")}}),Hc=new Ve("memory").description("Read, edit, and erase what a scheduled agent remembers").addCommand(Jc).addCommand(zc).addCommand(Xc),Ti=new Ve("agent").description("Create scheduled agents and read, edit, or erase what they remember").addCommand(Si("create")).addCommand(Si("recommend")).addCommand(Hc);import{randomUUID as Oi}from"crypto";import{existsSync as Zc}from"fs";import{resolve as el}from"path";import ct from"chalk";import{Command as be}from"commander";import tl from"ora";import{mkdir as Yc,writeFile as Ei}from"fs/promises";import{dirname as Qc}from"path";async function Y(e,t){if(await Yc(Qc(t),{recursive:!0}),e.startsWith("data:")){let o=e.match(/^data:[^;]+;base64,(.+)$/);if(!o)throw new Error("Invalid data URL format");let i=Buffer.from(o[1],"base64");if(i.length===0)throw new Error("Downloaded media was empty");await Ei(t,i);return}let n=await fetch(e);if(!n.ok)throw new Error(`Failed to download media: ${n.status}`);let r=Buffer.from(await n.arrayBuffer());if(r.length===0)throw new Error("Downloaded media was empty");await Ei(t,r)}var nl=15e3,rl=40,Ai=3;async function Pi(e,t){if(e?.length){if(e.length>Ai)throw new Error(`A presenter Look accepts at most ${Ai} reference images`);return Promise.all(e.map(async(n,r)=>{if(Zc(n))return{url:(await me(el(n),{idempotencyKey:`${t}:reference:${r+1}`})).url};let o;try{o=new URL(n)}catch(i){throw new Error(`Reference image ${r+1} must be an existing local file or an HTTP(S) URL.`,{cause:i})}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`Reference image ${r+1} must use an HTTP(S) URL.`);return{url:o.toString()}}))}}function jn(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.durationSec!=null&&g(`Duration: ${e.durationSec}s`),e.videoUrl&&x(`Video URL: ${e.videoUrl}`),e.error&&s(`Error: ${e.error}`)}var ol=new be("options").description("List available presenter avatars and voices").option("--language <language>","Filter voices by language").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await Ro(e.language);if(e.format==="json"){u(t);return}let n=t.personal??[];if(e.format==="quiet"){for(let r of n)console.log(r.id);for(let r of t.avatars)console.log(r.id);for(let r of t.voices)console.log(r.id);return}if(n.length>0){g("Your presenters:");for(let r of n)console.log(` ${r.id} ${r.name}`)}g("Avatars:");for(let r of t.avatars){let o=r.renderTiers?.length?` [${r.renderTiers.join(", ")}]`:"";console.log(` ${r.id} ${r.name}${o}`)}g("Voices:");for(let r of t.voices)console.log(` ${r.id} ${r.name}${r.language?` (${r.language})`:""}`)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),il=new be("generate").description("Generate a reusable presenter clip").option("--avatar-id <id>","Avatar id from 'avatar options'; sandbox runs use the host presenter policy").option("--audio-url <url>","Public narration audio URL for avatar lip sync").option("--voice-id <id>","Voice id from 'avatar options'").option("--script <text>","Exact words for the presenter to speak").requiredOption("-o, --output <path>","Local output path").option("--aspect <aspect>","Aspect: 1:1, 9:16, 16:9","9:16").option("--duration <seconds>","Maximum requested duration (1-300)").option("--transparent","Render a transparent-background WebM presenter clip").option("--background-color <hex>","Solid presenter background color, for example #0F172A").option("--background-image-url <url>","Public image URL used as the presenter background").option("--fit <mode>","Background image fit: contain or cover").option("--output-format <container>","Container: mp4 (default) or webm \u2014 webm renders a transparent-background clip (single scene) for compositing").option("--render-tier <tier>","Render cost/quality: basic, standard, premium","basic").option("--title <title>","Clip title","Presenter clip").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.transparent?"webm":e.outputFormat;!!e.audioUrl==!!e.script&&(s("Provide exactly one avatar speech input: --audio-url or --script"),process.exit(c.INVALID_INPUT)),["1:1","9:16","16:9"].includes(e.aspect)||(s("Aspect must be one of 1:1, 9:16, or 16:9"),process.exit(c.INVALID_INPUT)),e.outputFormat!==void 0&&!["mp4","webm"].includes(e.outputFormat)&&(s("Output format must be mp4 or webm"),process.exit(c.INVALID_INPUT)),e.backgroundColor!==void 0&&!/^#[0-9a-fA-F]{6}$/.test(e.backgroundColor)&&(s("Background color must be a six-digit hex value"),process.exit(c.INVALID_INPUT)),e.backgroundColor&&e.backgroundImageUrl&&(s("Provide only one presenter background"),process.exit(c.INVALID_INPUT)),e.fit!==void 0&&!["contain","cover"].includes(e.fit)&&(s("Fit must be contain or cover"),process.exit(c.INVALID_INPUT)),e.fit&&!e.backgroundImageUrl&&(s("Fit requires --background-image-url"),process.exit(c.INVALID_INPUT)),e.transparent&&e.outputFormat==="mp4"&&(s("--transparent cannot be combined with --output-format mp4"),process.exit(c.INVALID_INPUT)),t==="webm"&&(e.backgroundColor||e.backgroundImageUrl)&&(s("Transparent WebM output cannot be combined with a background"),process.exit(c.INVALID_INPUT)),["basic","standard","premium"].includes(e.renderTier)||(s("Render tier must be basic, standard, or premium"),process.exit(c.INVALID_INPUT));let n=e.duration?Number.parseInt(e.duration,10):void 0;n!==void 0&&(!Number.isFinite(n)||n<1||n>300)&&(s("Duration must be between 1 and 300 seconds"),process.exit(c.INVALID_INPUT));let r=e.format==="human"?tl("Generating presenter clip...").start():null;try{let o=e.audioUrl?{audioUrl:e.audioUrl}:{script:e.script??"",...e.voiceId?{voiceId:e.voiceId}:{}},i=await So({...o,aspect:e.aspect,...e.avatarId?{avatarId:e.avatarId}:{},...e.backgroundColor?{backgroundHex:e.backgroundColor}:{},...e.backgroundImageUrl?{backgroundImageUrl:e.backgroundImageUrl}:{},...n!==void 0?{durationSec:n}:{},...e.fit?{fit:e.fit}:{},...t?{outputFormat:t}:{},renderTier:e.renderTier,title:e.title});if(!e.wait){r?.stop(),jn(i,e.format);return}let a=await te(()=>In(i.requestId),rl,nl);if(a.status==="failed")throw new Error(a.error||"Presenter generation failed");if(!a.videoUrl)throw new Error("Presenter generation completed without a video URL");r&&(r.text="Downloading presenter clip..."),await Y(a.videoUrl,e.output),r?.stop(),jn(a,e.format),e.format==="human"&&x(`Saved to: ${e.output}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),al=new be("status").description("Check a presenter clip generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{jn(await In(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),sl=new be("generate").description("Generate another look for an existing personal presenter").argument("<base-profile-id>","Base personal presenter id (pp_*)").requiredOption("--name <name>","Look name").requiredOption("--description <description>","Short look description").requiredOption("--prompt <prompt>","Exact appearance generation prompt").requiredOption("--look-id <id>","Stable template/look id").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this look request").action(async(e,t)=>{try{let n=t.idempotencyKey??Oi(),r=await Pi(t.referenceImage,n),o=await h("generatePresenterLook",{baseProfileId:e,description:t.description,id:t.lookId,prompt:t.prompt,...r?{referenceImages:r}:{},title:t.name},n);u(o)}catch(n){s(n instanceof Error?n.message:"Look generation failed"),process.exit(c.GENERAL_ERROR)}}),dl=new be("status").description("Read presenter look generation status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("generatePresenterLook",e);if(t.format==="json")return u(n);if(t.format==="quiet")return console.log(n.status);g(`Run ID: ${e}`),g(`Status: ${n.status}`),n.error?.message&&s(n.error.message)}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),cl=new be("revise").description("Create a new Look by editing an existing presenter Look").argument("<look-id>","Ready presenter Look id (pp_*)").requiredOption("--instruction <instruction>","What to add, remove, or change").option("--reference-image <path-or-url...>","Up to three local images or URLs for location, outfit, or style guidance").option("--idempotency-key <key>","Stable retry key for this revision").action(async(e,t)=>{try{let n=t.idempotencyKey??Oi(),r=await Pi(t.referenceImage,n),o=await h("revisePresenterLook",{instruction:t.instruction,...r?{referenceImages:r}:{},sourceLookId:e},n);u(o)}catch(n){s(n instanceof Error?n.message:"Look revision failed"),process.exit(c.GENERAL_ERROR)}}),ll=new be("revision-status").description("Read presenter Look revision status").argument("<run-id>","Durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("revisePresenterLook",e);if(t.format==="json")return u(n);if(t.format==="quiet")return console.log(n.status);g(`Run ID: ${e}`),g(`Status: ${n.status}`),n.error?.message&&s(n.error.message)}catch(n){s(n instanceof Error?n.message:"Revision status failed"),process.exit(c.GENERAL_ERROR)}}),ml=new be("look").description("Manage looks under an existing personal presenter").addCommand(sl).addCommand(cl).addCommand(ll).addCommand(dl),Mn=new be("avatar").description("Generate presenter clips and looks; avatar options lists the voices and looks used by presentation video presenter and cast preset").addCommand(ol).addCommand(il).addCommand(ml).addCommand(al);Mn.addHelpText("after",`
|
|
70
62
|
${ct.bold("Examples:")}
|
|
71
63
|
${ct.gray("# Discover the presenter avatars and voices you can use")}
|
|
72
|
-
$ ${
|
|
64
|
+
$ ${m.commands[0]} avatar options
|
|
73
65
|
|
|
74
66
|
${ct.bold("See also:")}
|
|
75
67
|
${ct.gray("# Save a presenter + backdrop + voice combination under a name")}
|
|
76
|
-
$ ${
|
|
68
|
+
$ ${m.commands[0]} cast preset --help
|
|
77
69
|
|
|
78
70
|
${ct.gray("# Apply an avatar, look, or preset to one presentation-video scene")}
|
|
79
|
-
$ ${
|
|
80
|
-
`);import{writeFile as
|
|
81
|
-
`);for(let o of r){let i=o.primaryColor?`${
|
|
71
|
+
$ ${m.commands[0]} presentation video presenter <project-id>
|
|
72
|
+
`);import{writeFile as Ui}from"fs/promises";import z from"chalk";import{Command as oe}from"commander";import Cl from"ora";import{createHash as ul}from"crypto";import{existsSync as pl}from"fs";import{basename as gl}from"path";import{Command as _i}from"commander";import fl from"ora";var Li=new _i("logo").description("Brand logo files").addCommand(new _i("set").description("Set a brand's logo, dark variant, or favicon").argument("[brand-id]","Brand ID (defaults to this workspace's default brand)").requiredOption("--file <path>","Local image file to upload and use").option("--variant <variant>","primary | dark | favicon. 'dark' is the reversed lock-up for dark backgrounds","primary").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await O();let n=t.variant??"primary";["primary","dark","favicon"].includes(n)||(s(`--variant must be primary, dark, or favicon (got "${n}")`),process.exit(c.INVALID_INPUT)),pl(t.file)||(s(`File not found: ${t.file}`),process.exit(c.INVALID_INPUT));let r=fl({text:`Uploading ${gl(t.file)}...`,stream:process.stdout}).start(),o;try{o=(await me(t.file)).url,r.succeed("Uploaded")}catch(i){r.fail("Upload failed"),s(i instanceof Error?i.message:String(i)),process.exit(c.GENERAL_ERROR)}try{u(await h("setBrandLogo",{brandId:e,fileUrl:o,teamId:t.teamId,variant:n},ul("sha256").update(`setBrandLogo:${e??"default"}:${n}:${o}`).digest("hex").slice(0,32)))}catch(i){s(i instanceof Error?i.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}));import{readFile as hl}from"fs/promises";import{randomUUID as yl}from"crypto";import{Command as Di}from"commander";var bl=["color.primary","color.background","color.text","color.secondary","color.accent","color.surface","color.link","typography.primary","typography.secondary","typography.h1","typography.h2","typography.h3","typography.h4","typography.h5","typography.h6","typography.paragraph","typography.button","typography.small","typography.label","typography.caption","asset.logo","asset.logo.dark","asset.favicon"];function wl(e){let t=e.split(".").filter(Boolean);for(let n=t.length;n>=2;n--){let r=t.slice(0,n).join(".");if(bl.includes(r))return{fieldPath:t.slice(n),nodeKey:r}}return{fieldPath:t.slice(2),nodeKey:t.slice(0,2).join(".")}}function vl(e){let t={};for(let n of e){let r=n.indexOf("=");if(r<=0)throw new Error(`"${n}" is not a token assignment. Use key=value, e.g. color.primary=#114b97`);let o=n.slice(0,r).trim(),i=n.slice(r+1);if(o.split(".").filter(Boolean).length<2)throw new Error(`"${o}" is not a brand token key. Expected something like color.primary or typography.h1.size`);let{fieldPath:d,nodeKey:l}=wl(o),y=xl(i);if(d.length===0){t[l]=y;continue}let p=t[l],w=p&&typeof p=="object"&&!Array.isArray(p)?p:{},v=w;for(let C of d.slice(0,-1)){let E=v[C],k=E&&typeof E=="object"&&!Array.isArray(E)?E:{};v[C]=k,v=k}v[d[d.length-1]]=y,t[l]=w}return t}function xl(e){return e==="true"?!0:e==="false"?!1:/^-?\d+(?:\.\d+)?$/.test(e)?Number(e):e}function kl(e,t){return e===void 0?{assignments:[...t]}:e.includes("=")?{assignments:[e,...t]}:{assignments:[...t],brandId:e}}var Ni=new Di("profile").description("Read a brand's design tokens, the keys it is missing, or its design.md").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").option("--format <format>","tokens (default) or md").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{let n=await h("getBrandProfile",{brandId:e,format:t.format,teamId:t.teamId});if(t.format==="md"&&typeof n.designMd=="string"){console.log(n.designMd);return}u(n)}catch(n){s(n instanceof Error?n.message:"Profile read failed"),process.exit(c.GENERAL_ERROR)}}),qi=new Di("set").description("Write brand design tokens (key=value pairs or a design.md)").argument("[brand-id]","Brand ID (defaults to this workspace's brand)").argument("[tokens...]","Token assignments, e.g. color.primary=#114b97 typography.h1.size=32px").option("--design-md <path>","Apply a whole design.md file instead").option("--no-publish","Stage the change without publishing a new active brand version").option("--team-id <id>","Workspace ID").option("--yes","Confirm writing brand data").action(async(e,t,n)=>{n.yes||(s("Pass --yes to confirm writing brand tokens."),process.exit(c.INVALID_INPUT));let{assignments:r,brandId:o}=kl(e,t),i;try{i=r.length>0?vl(r):void 0}catch(d){s(d instanceof Error?d.message:"Invalid token pair"),process.exit(c.INVALID_INPUT)}let a;if(n.designMd)try{a=await hl(n.designMd,"utf8")}catch(d){s(`Could not read ${n.designMd}: ${d instanceof Error?d.message:String(d)}`),process.exit(c.INVALID_INPUT)}!i&&!a&&(s("Nothing to write. Pass token assignments (color.primary=#114b97) or --design-md <file>."),process.exit(c.INVALID_INPUT));try{u(await h("updateBrandTokens",{brandId:o,designMd:a,publish:n.publish===!1?!1:void 0,teamId:n.teamId,tokens:i},yl()))}catch(d){s(d instanceof Error?d.message:"Write failed"),process.exit(c.GENERAL_ERROR)}});var ji=new oe("branding").description("Manage brand profiles, design tokens, logos, competitors, and social handles").addCommand(Ni).addCommand(qi).addCommand(new oe("list").description("List brand profiles").option("-f, --format <format>","Output format (table, json)",b("--format",["table","json"]),"table").action(async e=>{await O();try{let t=await vn();if(t.brandings.length===0){e.format==="json"?console.log(JSON.stringify([])):(g("No brand profiles found"),console.log(),console.log(z.gray(`Create one with: ${m.commands[0]} branding extract <url>`)));return}e.format==="json"?console.log(JSON.stringify(t.brandings,null,2)):console.log(Ur(t.brandings))}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new oe("get").description("Get brand profile details").argument("<id>","Brand profile ID").option("-f, --format <format>","Output format (summary, json)",b("--format",["summary","json"]),"summary").option("-o, --output <path>","Save JSON to file").action(async(e,t)=>{await O();try{let n=await lo(e);if(t.output){await Ui(t.output,JSON.stringify(n,null,2)),x(`Brand profile saved to ${t.output}`);return}if(t.format==="json")console.log(JSON.stringify(n,null,2));else{if(ie("Brand Profile"),console.log(),R("ID",n.id),R("Name",n.name),R("Source URL",n.sourceUrl??z.gray("None")),R("Default",n.isDefault?z.green("Yes"):"No"),n.createdAt&&R("Created",new Date(n.createdAt).toLocaleString()),console.log(),n.primaryColor||n.colors.length>0){if(console.log(z.bold(" Colors")),n.primaryColor){let o=z.bgHex(n.primaryColor)(" ");console.log(` Primary: ${o} ${n.primaryColor}`)}if(n.colors.length>0){console.log(" Palette:");for(let o of n.colors.slice(0,10)){let i=z.bgHex(o.hex)(" "),a=o.role?z.gray(` (${o.role})`):"";console.log(` ${i} ${o.hex}${a}`)}}console.log()}n.logoUrl&&(console.log(z.bold(" Logo")),console.log(` ${n.logoUrl}`),console.log());let r=n.typography;r&&Object.keys(r).length>0&&(console.log(z.bold(" Typography")),(r.primary||r.headings)&&console.log(` Headings: ${r.primary||r.headings||"-"}`),(r.secondary||r.body)&&console.log(` Body: ${r.secondary||r.body||"-"}`),console.log()),(n.confidence||n.extractionMethod)&&(console.log(z.bold(" Extraction")),n.confidence&&console.log(` Confidence: ${Math.round(n.confidence*100)}%`),n.extractionMethod&&console.log(` Method: ${n.extractionMethod}`),console.log()),console.log(z.gray(" Use --format json for full details")),console.log()}}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}})).addCommand(new oe("find").description("Find existing brand profile by name or URL").argument("<query>","Brand name or website URL to search for").action(async e=>{await O();try{let t=await vn(),n=e.toLowerCase().replace(/^https?:\/\//,"").replace(/\/$/,""),r=t.brandings.filter(o=>{let i=(o.name||"").toLowerCase(),a=(o.sourceUrl||"").toLowerCase().replace(/^https?:\/\//,"").replace(/\/$/,"");return i.includes(n)||a.includes(n)||i.length>0&&n.includes(i)||a.length>0&&n.includes(a)});if(r.length===0){g(`No brand profiles matching "${e}"`),console.log(z.gray(` Extract one with: ${m.commands[0]} branding extract <url>`));return}console.log(`Found ${r.length} brand${r.length>1?"s":""}:
|
|
73
|
+
`);for(let o of r){let i=o.primaryColor?`${z.bgHex(o.primaryColor)(" ")} ${o.primaryColor}`:"";console.log(` ${z.bold(o.name)} ${z.gray(o.id)}`),o.sourceUrl&&console.log(` ${z.gray(o.sourceUrl)}`),i&&console.log(` ${i}`),console.log()}console.log(z.gray(` Export with: ${m.commands[0]} branding get <id> -o branding.json`))}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}})).addCommand(new oe("extract").description("Extract brand profile from a website").argument("<url>","Website URL to extract branding from").option("--team-id <id>","Team ID").option("--yes","Confirm starting a paid/external extraction").option("--no-save","Extract without saving").option("-o, --output <path>","Save JSON to file").action(async(e,t)=>{await O(),t.yes||(s("Pass --yes to confirm brand extraction."),process.exit(c.INVALID_INPUT));try{new URL(e.startsWith("http")?e:`https://${e}`)}catch{s("Invalid URL format"),process.exit(6)}let n=e.startsWith("http")?e:`https://${e}`,r=t.teamId??Ct(),o=Cl({text:`Extracting branding from ${n}...`,stream:process.stdout}).start();try{let i=await mo(n,r,"cli:--yes");o.succeed("Brand extraction started");let a=JSON.stringify(i,null,2);t.output?(await Ui(t.output,a),x(`Brand profile saved to ${t.output}`)):console.log(a),g(`Check progress with: ${m.commands[0]} branding status ${i.runId}`),console.log()}catch(i){o.fail("Extraction failed"),s(i instanceof Error?i.message:String(i)),process.exit(i.exitCode??1)}})).addCommand(new oe("status").description("Check a brand extraction run").argument("<run-id>","Run ID returned by branding extract").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("extractBranding",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}})).addCommand(new oe("set-default").description("Set a brand profile as default").argument("<id>","Brand profile ID").action(async e=>{await O(),g(`To set brand ${e} as default, use the web dashboard.`),console.log(),console.log(z.gray("API support for setting default brand is coming soon."))})).addCommand(new oe("competitor").description("Brand competitor commands").addCommand(new oe("list").description("List competitors for a brand").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").action(async e=>{try{console.log(JSON.stringify(await h("getBrandCompetitors",{brandingId:e.brandingId,teamId:e.teamId}),null,2))}catch(t){s(t instanceof Error?t.message:"Lookup failed"),process.exit(1)}})).addCommand(new oe("add").description("Add or update a brand competitor").argument("<name>","Competitor name").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").option("--website <url>","Competitor website").option("--x-handle <handle>","Competitor X handle").option("--yes","Confirm writing brand data").action(async(e,t)=>{t.yes||(s("Pass --yes to confirm adding a competitor."),process.exit(c.INVALID_INPUT));try{u(await h("addCompetitor",{approvalReceipt:"cli:--yes",brandingId:t.brandingId,name:e,teamId:t.teamId,website:t.website,xHandle:t.xHandle}))}catch(n){s(n instanceof Error?n.message:"Write failed"),process.exit(c.GENERAL_ERROR)}}))).addCommand(Li).addCommand(new oe("social").description("Brand social handle commands").addCommand(new oe("add").description("Add or update a brand social handle").argument("<platform>","Social platform").argument("<handle>","Account handle").option("--branding-id <id>","Brand ID").option("--team-id <id>","Workspace ID").option("--yes","Confirm writing brand data").action(async(e,t,n)=>{n.yes||(s("Pass --yes to confirm adding a social handle."),process.exit(c.INVALID_INPUT));try{u(await h("addBrandSocialHandle",{approvalReceipt:"cli:--yes",brandingId:n.brandingId,handle:t,platform:e,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Write failed"),process.exit(c.GENERAL_ERROR)}})));import lt from"chalk";import{Command as Ge}from"commander";function Il(e){switch(e.background){case"color":{if(!e.backgroundColor)throw new Error("--background color needs --background-color <hex>, e.g. #1d4ed8");return{hex:e.backgroundColor,kind:"color"}}case"image":{if(!e.backgroundImage)throw new Error("--background image needs --background-image <url>");return{fit:e.fit,kind:"image",url:e.backgroundImage}}default:return{kind:e.background}}}function Mi(e,t){return{background:Il(t),name:e,presenterProfileId:t.presenter,...t.voiceId?{voiceId:t.voiceId}:{}}}function Ft(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.id);return}x(`${e.name} (${e.id})`),g(` Presenter: ${e.presenterProfileId}`),g(` Backdrop: ${Rl(e.background)}`),e.voiceId&&g(` Voice: ${e.voiceId}`)}function Rl(e){switch(e.kind){case"color":return`color ${e.hex}`;case"image":return`image ${e.url} (${e.fit})`;default:return e.kind}}function Fi(e){return e.requiredOption("--presenter <profileId>",`Trained personal presenter id (pp_*), from \`${m.commands[0]} avatar options\``).option("--background <kind>","Backdrop: original, transparent, color, or image","original").option("--background-color <hex>","Backdrop color, e.g. #1d4ed8").option("--background-image <url>","Backdrop image URL").option("--fit <fit>","How an image backdrop fills the frame","cover").option("--voice-id <voiceId>","Workspace voice to save with this preset").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human")}var Sl=new Ge("list").description("List saved cast presets you can use").option("--cast-member-id <castMemberId>","Only this person's presets").option("--branding-id <brandingId>","Narrow to one brand").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await _o({...e.brandingId?{brandingId:e.brandingId}:{},...e.castMemberId?{castMemberId:e.castMemberId}:{}});if(e.format==="json"){u(t);return}if(e.format==="quiet"){for(let n of t.presets)console.log(n.id);return}if(t.presets.length===0){g("No presets saved yet.");return}for(let n of t.presets)Ft(n,"human")}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(c.API_ERROR)}}),$l=Fi(new Ge("create").description("Save one way a cast member appears").argument("<name>",'What to call this preset, e.g. "In the cafe"').requiredOption("--cast-member-id <castMemberId>","The person this preset is a way of showing")).action(async(e,t)=>{try{let n=await Lo({castMemberId:t.castMemberId,...Mi(e,t)});Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Tl=Fi(new Ge("update").description("Change a saved preset (sends the complete preset)").argument("<presetId>","The preset to change").requiredOption("--name <name>","What to call it")).action(async(e,t)=>{try{let n=await Do({presetId:e,...Mi(t.name,t)});Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),El=new Ge("delete").description("Retire a saved preset. Existing videos keep working.").argument("<presetId>","The preset to retire").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await No(e);if(t.format==="human"){x(`Retired "${n.preset.name}".`);return}Ft(n.preset,t.format)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(c.API_ERROR)}}),Al=new Ge("preset").description("Saved ways a cast member appears").addCommand(Sl).addCommand($l).addCommand(Tl).addCommand(El),Fn=new Ge("cast").description("The faces and voices your videos can use").addCommand(Al);Fn.addHelpText("after",`
|
|
82
74
|
${lt.bold("Examples:")}
|
|
83
75
|
${lt.gray("# List the saved presenter/backdrop/voice combinations")}
|
|
84
|
-
$ ${
|
|
76
|
+
$ ${m.commands[0]} cast preset list
|
|
85
77
|
|
|
86
78
|
${lt.bold("See also:")}
|
|
87
79
|
${lt.gray("# The presenter avatars, looks, and voices a preset is built from")}
|
|
88
|
-
$ ${
|
|
80
|
+
$ ${m.commands[0]} avatar options
|
|
89
81
|
|
|
90
82
|
${lt.gray("# Use a preset on one presentation-video scene")}
|
|
91
|
-
$ ${
|
|
92
|
-
`);import{readFile as
|
|
83
|
+
$ ${m.commands[0]} presentation video presenter <project-id>
|
|
84
|
+
`);import{readFile as Ol}from"fs/promises";import mt from"chalk";import{Command as Vi}from"commander";var Pl=new Vi("extract").description("Extract normalized text from a URL or local file").argument("<source>","URL, encoded source, or local file path").option("--team-id <id>","Workspace ID").option("--mime-type <type>","Source MIME type").option("--max-length <count>","Maximum output characters","30000").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=e,r;e.includes("://")||(n=await Ol(e,"utf8"),r=e);let o=await h("extractContent",{filename:r,maxLength:Number.parseInt(t.maxLength,10),mimeType:t.mimeType,source:n,teamId:t.teamId});t.format!=="quiet"&&u(o)}catch(n){s(n instanceof Error?n.message:"Extraction failed"),process.exit(c.GENERAL_ERROR)}}),Vn=new Vi("content").description("Extract normalized text from a URL, a local file, or an encoded document").addCommand(Pl);Vn.addHelpText("after",`
|
|
85
|
+
${mt.bold("Examples:")}
|
|
86
|
+
${mt.gray("# Normalized text from a local document")}
|
|
87
|
+
$ ${m.commands[0]} content extract ./paper.pdf
|
|
88
|
+
|
|
89
|
+
${mt.bold("See also:")}
|
|
90
|
+
${mt.gray("# Web pages, with page metadata and cost reporting")}
|
|
91
|
+
$ ${m.commands[0]} scrape https://example.com/post
|
|
92
|
+
|
|
93
|
+
${mt.gray("# Spoken words out of audio or video")}
|
|
94
|
+
$ ${m.commands[0]} transcript --help
|
|
95
|
+
`);import X from"chalk";import{Command as _l}from"commander";import{existsSync as Ll,readFileSync as Dl}from"fs";import Nl,{resolve as Gi}from"path";var Bi=new _l("create").description("Create a new presentation").argument("<topic>","The topic or title for the presentation").option("-n, --slides <count>","Number of slides (1-20)").option("-m, --mode <mode>","Generation quality (best, balanced, fast, ultrafast, instant, image-min, image, image-max) \u2014 default: fast. image-min/image/image-max render each slide as a full-bleed AI image (text not editable); slower + pricier, require image-mode access, and cap at 25 slides. image-min is cheapest (brand colors only, no exact fonts).").option("--image-tier <tier>","Embedded-image quality for HTML modes. Each tier is a per-image credit ceiling as well as its price: quick (+20/slide), smart (default, +60/slide), balanced (+250/slide), best (+500/slide, slow). Ignored for image-*/instant modes.").option("-t, --tone <tone>","Tone (creative, professional, educational, formal, casual)").option("--amount <amount>","Content density (minimal, concise, detailed, extensive)").option("--audience <text>","Target audience description").option("-l, --language <lang>","Output language").option("--branding-id <id>","Branding ID (from `ccr branding list` or `ccr branding extract`)").option("--brand-domain <url>","Brand the deck by website/domain (e.g. https://www.pfizer.com). Errors if no matching saved brand exists.").option("--template <id>","Slide template ID to style the deck after (from `ccr templates`). A default template is applied automatically when omitted.").option("-c, --context <text>","Inline text context (research notes, key facts)").option("--context-file <path>","Path to a context file (text, markdown, JSON)").option("--stdin","Read context from stdin").option("-f, --file <paths...>","Files to upload (PDF, PPTX, DOCX, images)").option("-g, --goal <type>","Goal (inform, persuade, train, learn, entertain, report)").option("--styling <mode>","Styling mode (freeform, brand-only, brand-plus-style, style-only, no-styling)").option("--reference-url <url>","Image URL to use as visual style reference").option("--thinking-depth <depth>","AI thinking depth (quick, moderate, deep, profound)").option("--theme <preset>","[instant mode only] Color theme preset (blue, violet, rose, orange, green)").option("--primary-color <hex>","[instant mode only] Primary color (e.g., #0066CC)").option("--secondary-color <hex>","[instant mode only] Secondary color").option("--accent-color <hex>","[instant mode only] Accent color").option("--background-color <hex>","[instant mode only] Background color").option("--foreground-color <hex>","[instant mode only] Foreground/text color").option("--decorations <style>","[instant mode only] Background decoration (none, waves-bottom-left, waves-top-right, blob-corners, minimal)").option("--team-id <id>","Team ID (switch teams)").option("--format <format>","Output format (human, json, quiet)",b("--format",["human","json","quiet"])).option("-o, --output <format>","Output format (human, json, quiet) \u2014 short form of --format",b("--output",["human","json","quiet"])).option("--no-stream","Wait for completion without streaming progress").option("--wait","Poll until generation completes").option("--debug","Enable debug logging").option("--open","Open in browser after creation").option("--id <uuid>","Use a specific UUID for the presentation").option("--studio","Studio mode: use current directory name as presentation ID (auto-links to Studio preview)").action(async(e,t)=>{t.output=t.format??t.output,await O();let n;t.slides!==void 0&&(n=parseInt(t.slides,10),(Number.isNaN(n)||n<1||n>20)&&(s("Slide count must be between 1 and 20"),process.exit(6)));let r=["best","balanced","fast","ultrafast","instant","image-min","image","image-max"];t.mode&&!r.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Valid: ${r.join(", ")}`),process.exit(6));let o=["smart","fast","balanced","best"];t.imageTier&&!o.includes(t.imageTier)&&(s(`Invalid image tier: ${t.imageTier}. Valid: ${o.join(", ")}`),process.exit(6));let i=["creative","professional","educational","formal","casual"];t.tone&&!i.includes(t.tone)&&(s(`Invalid tone: ${t.tone}. Valid: ${i.join(", ")}`),process.exit(6));let a=["minimal","concise","detailed","extensive"];t.amount&&!a.includes(t.amount)&&(s(`Invalid amount: ${t.amount}. Valid: ${a.join(", ")}`),process.exit(6));let d=["freeform","brand-only","brand-plus-style","style-only","no-styling"];t.styling&&!d.includes(t.styling)&&(s(`Invalid styling: ${t.styling}. Valid: ${d.join(", ")}`),process.exit(6));let l=["quick","moderate","deep","profound"];t.thinkingDepth&&!l.includes(t.thinkingDepth)&&(s(`Invalid thinking-depth: ${t.thinkingDepth}. Valid: ${l.join(", ")}`),process.exit(6));let y=["inform","persuade","train","learn","entertain","report"];t.goal&&!y.includes(t.goal)&&(s(`Invalid goal: ${t.goal}. Valid: ${y.join(", ")}`),process.exit(6));let p=["blue","violet","rose","orange","green"];t.theme&&!p.includes(t.theme)&&(s(`Invalid theme: ${t.theme}. Valid: ${p.join(", ")}`),process.exit(6));let w=["none","waves-bottom-left","waves-top-right","blob-corners","minimal"];t.decorations&&!w.includes(t.decorations)&&(s(`Invalid decorations: ${t.decorations}. Valid: ${w.join(", ")}`),process.exit(6));let v=t.theme||t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor||t.decorations;v&&t.mode&&t.mode!=="instant"&&(s("--theme, --primary-color, --decorations and other color options are only supported with --mode instant"),process.exit(6));let C=t.mode??(v?"instant":"fast"),E=/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;for(let[I,J]of[["primary-color",t.primaryColor],["secondary-color",t.secondaryColor],["accent-color",t.accentColor],["background-color",t.backgroundColor],["foreground-color",t.foregroundColor]])J&&!E.test(J)&&(s(`Invalid ${I}: ${J}. Must be hex (e.g., #0066CC)`),process.exit(6));try{t.output!=="json"&&t.output!=="quiet"&&process.stdout.write(X.gray("Checking generation limits... "));let I=await go(C,n??10,t.teamId);if(t.output!=="json"&&t.output!=="quiet"){console.log(X.green("\u2713"));let J=I.remaining[C],Z=I.limits[C],Se=J===void 0||Z===void 0?"":` | ${C}: ${J}/${Z} remaining`;console.log(X.gray(` Plan: ${I.planName}${Se}`))}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):(console.log(X.red("\u2717")),s(I instanceof Error?I.message:String(I))),process.exit(I.exitCode??1)}let k=[];if(t.file&&t.file.length>0){for(let I of t.file)Ll(Gi(I))||(s(`File not found: ${I}`),process.exit(6));t.output!=="json"&&t.output!=="quiet"&&console.log(X.gray(`
|
|
96
|
+
Uploading ${t.file.length} file(s)...`));try{k=await Zr(t.file.map(I=>Gi(I)),(I,J,Z)=>{t.output!=="json"&&t.output!=="quiet"&&Z&&process.stdout.write(`\r ${X.cyan("\u2B06")} Uploading: ${Z} (${I+1}/${J})`)}),t.output!=="json"&&t.output!=="quiet"&&console.log(`\r ${X.green("\u2713")} Uploaded ${k.length} file(s) `)}catch(I){s(`Failed to upload files: ${I instanceof Error?I.message:String(I)}`),process.exit(1)}}let $;(t.stdin||!process.stdin.isTTY)&&($=await ql(),t.stdin&&!$&&(s("No content received from stdin"),process.exit(6)));let S=t.context;if(t.contextFile)try{S=Dl(t.contextFile,"utf-8"),S.trim()||(s(`Context file is empty: ${t.contextFile}`),process.exit(6))}catch{s(`Failed to read context file: ${t.contextFile}`),process.exit(6)}!$&&!S&&k.length===0&&(s("Context is required to create a presentation."),console.log(),console.log(X.gray(" -f, --file <paths...> Upload files (PDF, PPTX, images)")),console.log(X.gray(" -c, --context <text> Inline text context")),console.log(X.gray(" --context-file <path> Read from a file")),console.log(X.gray(` cat file | ${m.commands[0]} Pipe content`)),process.exit(6));let V=[...k];$&&V.push({id:`stdin-${Date.now()}`,content:$,title:"Piped Content",mime:"text/plain",selected:!0}),S&&V.push({id:`context-${Date.now()}`,content:S,title:"Context",mime:"text/plain",selected:!0});let A,q=t.primaryColor||t.secondaryColor||t.accentColor||t.backgroundColor||t.foregroundColor;(t.theme||q||t.decorations)&&(A={},t.theme&&(A.preset=t.theme),q&&(A.custom={},t.primaryColor&&(A.custom.primary=t.primaryColor),t.secondaryColor&&(A.custom.secondary=t.secondaryColor),t.accentColor&&(A.custom.accent=t.accentColor),t.backgroundColor&&(A.custom.background=t.backgroundColor),t.foregroundColor&&(A.custom.foreground=t.foregroundColor)),t.decorations&&(A.decorations=t.decorations));try{let I=await eo({topic:e,...n!==void 0&&{slideCount:n},mode:C,...t.imageTier&&{imageTier:t.imageTier},...t.tone&&{tone:t.tone},...t.amount&&{amount:t.amount},...t.audience&&{audience:t.audience},...t.language&&{language:t.language},...t.brandingId&&{brandingId:t.brandingId},...t.brandDomain&&{brandDomain:t.brandDomain},...t.template&&{templateId:t.template},...t.styling&&{stylingMode:t.styling},...t.referenceUrl&&{referenceUrl:t.referenceUrl},...t.thinkingDepth&&{thinkingDepth:t.thinkingDepth},...t.goal&&{goal:t.goal},...t.teamId&&{teamId:t.teamId},...A&&{theme:A},...t.studio?{documentId:Nl.basename(process.cwd())}:t.id?{documentId:t.id}:{},...V.length>0&&{contentSources:{uploadedFiles:V,contextFiles:[]}}});if(!t.wait){t.output==="json"?console.log(JSON.stringify({success:!0,run:I},null,2)):t.output!=="quiet"&&(x("Presentation generation queued"),R("Run ID",I.runId),R("Status",I.status),console.log(X.gray(` Check later with presentation status ${I.runId}`)));return}let J=await T("createSlides",I.runId,t.teamId);for(;!J.done;)t.output!=="json"&&t.output!=="quiet"&&console.log(X.gray(` ${J.message}`)),await new Promise(Se=>setTimeout(Se,(J.nextPollAfterSeconds??5)*1e3)),J=await T("createSlides",I.runId,t.teamId);if(J.error)throw new Error(se(J.error));let Z=J.entity?await Ue(J.entity.id):void 0;if(t.output==="json")console.log(JSON.stringify({success:!0,presentation:Z,run:J,viewUrl:Z?qe(Z.slug,t.language??"en"):void 0},null,2));else{console.log(),x("Presentation created successfully"),console.log(),R("Title",Z?.title??e),R("Slides",String(Z?.numberOfSlides??n??"\u2014")),console.log();let Se=Z?qe(Z.slug,t.language??"en"):"N/A";Se!=="N/A"&&(console.log(X.bold(" Open: ")+X.cyan.underline(Se)),t.open&&await(await import("open")).default(Se)),console.log()}}catch(I){t.output==="json"?console.log(JSON.stringify({success:!1,error:I instanceof Error?I.message:String(I)})):s(I instanceof Error?I.message:String(I)),process.exit(I.exitCode??1)}});async function ql(){return new Promise(e=>{let t="";if(process.stdin.setEncoding("utf8"),process.stdin.isTTY){e("");return}process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{e(t.trim())}),setTimeout(()=>{e(t.trim())},100)})}import{randomUUID as Ul}from"crypto";import{readFile as jl}from"fs/promises";import{Command as xe}from"commander";var Gn=["text/markdown","text/csv","text/plain"];async function Wi(e){let t=e.content;if(t!==void 0&&t!=="-"&&!t.startsWith("@"))return t;if(t?.startsWith("@"))return jl(t.slice(1),"utf8");if(t==="-"||!process.stdin.isTTY)return Ml();s("No document body. Pass --content <text>, --content @<path>, or pipe it on stdin."),process.exit(c.GENERAL_ERROR)}async function Ml(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}function Vt(e){return`cli:document:${e}:${Ul()}`}function Oe(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}function Fl(e){if(!e)return;let t=e.split(".").pop()?.toLowerCase();if(t==="md"||t==="markdown")return"text/markdown";if(t==="csv")return"text/csv";if(t==="txt")return"text/plain"}var Vl=new xe("create").description("Save a document into the Library").argument("<title>","Document title").option("--team-id <id>","Workspace ID").option("--content <text>","Document body: literal text, @<path> to read a file, or '-' for stdin").option("--media-type <type>",`One of ${Gn.join(", ")}; inferred from an @<path> body when omitted`).option("--summary <text>","One line for the Library card").action(async(e,t)=>{try{let n=t.mediaType??Fl(t.content?.startsWith("@")?t.content.slice(1):void 0);n||(s(`Cannot tell what this document is. Pass --media-type (${Gn.join(", ")}).`),process.exit(c.GENERAL_ERROR)),u(await h("createDocument",{content:await Wi(t),mediaType:n,summary:t.summary,teamId:t.teamId,title:e},Vt("create")))}catch(n){Oe(n,"Could not save the document")}}),Gl=new xe("list").description("List the workspace's documents, newest first").option("--team-id <id>","Workspace ID").option("--media-type <type>",`Filter to one of ${Gn.join(", ")}`).option("--limit <n>","Maximum documents to return (default 50)").action(async e=>{try{u(await h("listDocuments",{limit:e.limit?Number(e.limit):void 0,mediaType:e.mediaType,teamId:e.teamId}))}catch(t){Oe(t,"Could not list documents")}}),Bl=new xe("read").description("Print a document's body").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{let n=await h("readDocument",{documentId:e,teamId:t.teamId}),{document:r}=n;process.stderr.write(`${r.title} \xB7 ${r.mediaType} \xB7 v${r.version} \xB7 ${r.byteLength} bytes
|
|
97
|
+
`),process.stdout.write(r.content)}catch(n){Oe(n,"Could not read the document")}}),Wl=new xe("update").description("Edit a document under an optimistic lock").argument("<document-id>","Document id").requiredOption("--expected-version <n>","The version you last read; the edit is rejected if it has moved on").option("--team-id <id>","Workspace ID").option("--content <text>","New body: literal text, @<path> to read a file, or '-' for stdin").option("--title <text>","New title").option("--summary <text>","New Library-card summary").option("--change-summary <text>","What changed, recorded on the version").action(async(e,t)=>{try{let n=t.content!==void 0;u(await h("updateDocument",{changeSummary:t.changeSummary,content:n?await Wi(t):void 0,documentId:e,expectedVersion:Number(t.expectedVersion),summary:t.summary,teamId:t.teamId,title:t.title},Vt("update")))}catch(n){Oe(n,"Could not update the document")}}),Kl=new xe("delete").description("Remove a document from the Library").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").option("--yes","Skip the confirmation prompt").action(async(e,t)=>{try{!t.yes&&process.stdin.isTTY&&(s("Refusing to delete without confirmation. Re-run with --yes to remove this document."),process.exit(c.GENERAL_ERROR)),u(await h("deleteDocument",{documentId:e,teamId:t.teamId},Vt("delete")))}catch(n){Oe(n,"Could not delete the document")}}),Jl=new xe("versions").description("List a document's version history").argument("<document-id>","Document id").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("listDocumentVersions",{documentId:e,teamId:t.teamId}))}catch(n){Oe(n,"Could not list versions")}}),zl=new xe("restore").description("Restore an earlier version by appending it as the current one").argument("<document-id>","Document id").requiredOption("--version-number <n>","The historical version to restore").requiredOption("--expected-version <n>","The version you last read; the restore is rejected if it has moved on").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("restoreDocumentVersion",{documentId:e,expectedVersion:Number(t.expectedVersion),teamId:t.teamId,versionNumber:Number(t.versionNumber)},Vt("restore")))}catch(n){Oe(n,"Could not restore the version")}}),Ki=new xe("document").description("Create, read and edit Library documents").addCommand(Vl).addCommand(Gl).addCommand(Bl).addCommand(Wl).addCommand(Kl).addCommand(Jl).addCommand(zl);import ut from"chalk";import{Command as Xl}from"commander";import{writeFile as Hl}from"fs/promises";import{resolve as Ji}from"path";import Yl from"ora";var Ql=["html","pdf","pptx"],Bn=new Xl("export").description("Export a presentation to a local HTML, PDF or PPTX file").argument("<id-or-slug>","Presentation slug, presentation ID or document ID").option("-o, --output <path>","Output file path").option("-f, --format <format>","Export format: html, pdf, pptx",b("--format",Ql),"html").action(async(e,t)=>{await O();let n=Yl("Exporting presentation...").start();try{let r=await io(e,t.format),o=t.output?Ji(t.output):Ji(process.cwd(),r.fileName);n.text="Downloading...";let i=await ao(r.downloadUrl);await Hl(o,Buffer.from(i)),n.succeed("Export complete!"),console.log(),g(`File saved: ${o}`),g(`Format: ${r.format}`),g(`Slides: ${r.slideCount}`),g(`Size: ${Zl(i.byteLength)}`),console.log()}catch(r){n.fail("Export failed"),s(r instanceof Error?r.message:String(r)),process.exit(r.exitCode??1)}});function Zl(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}Bn.addHelpText("after",`
|
|
93
98
|
${ut.bold("Examples:")}
|
|
94
|
-
${ut.gray("#
|
|
95
|
-
$ ${
|
|
99
|
+
${ut.gray("# Self-contained interactive HTML (default)")}
|
|
100
|
+
$ ${m.commands[0]} export <id-or-slug> -o deck.html
|
|
101
|
+
|
|
102
|
+
${ut.gray("# PDF or PowerPoint")}
|
|
103
|
+
$ ${m.commands[0]} export <id-or-slug> -f pdf -o deck.pdf
|
|
104
|
+
$ ${m.commands[0]} export <id-or-slug> -f pptx -o deck.pptx
|
|
96
105
|
|
|
97
106
|
${ut.bold("See also:")}
|
|
98
|
-
${ut.gray("#
|
|
99
|
-
$ ${
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
$ ${u.commands[0]} transcript --help
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
`),process.stdout.write(r.content)}catch(n){Oe(n,"Could not read the document")}}),Hl=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;m(await y("updateDocument",{changeSummary:t.changeSummary,content:n?await Ki(t):void 0,documentId:e,expectedVersion:Number(t.expectedVersion),summary:t.summary,teamId:t.teamId,title:t.title},Vt("update")))}catch(n){Oe(n,"Could not update the document")}}),Yl=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)),m(await y("deleteDocument",{documentId:e,teamId:t.teamId},Vt("delete")))}catch(n){Oe(n,"Could not delete the document")}}),Ql=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{m(await y("listDocumentVersions",{documentId:e,teamId:t.teamId}))}catch(n){Oe(n,"Could not list versions")}}),Zl=new xe("restore").description("Restore an earlier version by appending it as the current one").argument("<document-id>","Document id").requiredOption("--version-number <n>","The historical version to restore").requiredOption("--expected-version <n>","The version you last read; the restore is rejected if it has moved on").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{m(await y("restoreDocumentVersion",{documentId:e,expectedVersion:Number(t.expectedVersion),teamId:t.teamId,versionNumber:Number(t.versionNumber)},Vt("restore")))}catch(n){Oe(n,"Could not restore the version")}}),Ji=new xe("document").description("Create, read and edit Library documents").addCommand(Jl).addCommand(zl).addCommand(Xl).addCommand(Hl).addCommand(Yl).addCommand(Ql).addCommand(Zl);import{Command as ae}from"commander";var eu=new ae("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:mt(e.outputs,"outputs"),overlays:mt(e.overlays,"overlays"),ranges:mt(e.ranges,"ranges"),sourceAssetIds:e.source,sourceChatId:e.sourceChatId,strategy:mt(e.strategy,"strategy"),teamId:e.teamId,title:e.title},idempotencyKey:e.idempotencyKey})}),tu=new ae("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}})}),nu=new ae("revise").description("Append a semantic footage draft revision").argument("<project-id>","Project ID or slug").requiredOption("--base-version-id <id>","Current version ID").requiredOption("--change-summary <text>","Human-readable change summary").option("--title <title>","Replacement title").option("--strategy <json>","Replacement strategy JSON object").option("--ranges <json>","Replacement ranges JSON array").option("--outputs <json>","Replacement outputs JSON array").option("--overlays <json>","Replacement overlays JSON array").option("--music-asset-id <id-or-null>","Replacement music asset ID or null").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("reviseFootageProject",{input:Hi({baseVersionId:t.baseVersionId,changeSummary:t.changeSummary,musicAssetId:t.musicAssetId==="null"?null:t.musicAssetId,outputs:Gt(t.outputs,"outputs"),overlays:Gt(t.overlays,"overlays"),projectId:e,ranges:Gt(t.ranges,"ranges"),strategy:Gt(t.strategy,"strategy"),teamId:t.teamId,title:t.title}),idempotencyKey:t.idempotencyKey})}),ru=new ae("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})}),ou=new ae("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})}),iu=new ae("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})}),au=new ae("inspection-status").description("Read a footage range inspection run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("inspectFootageRange",e,t.teamId)}),su=new ae("render").description("Render an exact approved footage draft version").argument("<project-id>","Project ID or slug").requiredOption("--version-id <id>","Exact version ID").option("--output <ids...>","Output IDs; omit to render every output").requiredOption("--approval-receipt <receipt>","Browser-issued approval receipt").requiredOption("--idempotency-key <key>","Key bound into the receipt").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("renderFootageProject",{input:Hi({approvalReceipt:t.approvalReceipt,outputIds:t.output,projectId:e,teamId:t.teamId,versionId:t.versionId}),idempotencyKey:t.idempotencyKey})}),du=new ae("render-status").description("Read a Footage Studio render run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("renderFootageProject",e,t.teamId)}),cu=new ae("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 ae("footage").description("Create, inspect, revise, and render transcript-native footage edits").addCommand(eu).addCommand(tu).addCommand(nu).addCommand(ru).addCommand(ou).addCommand(iu).addCommand(au).addCommand(su).addCommand(du).addCommand(cu);async function ke(e,t){try{m(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 Xi(e,t,n){try{m(await T(e,t,n))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}function mt(e,t){try{return JSON.parse(e)}catch{throw new Error(`${t} must be valid JSON.`)}}function Gt(e,t){return typeof e=="string"?mt(e,t):void 0}function Hi(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}import{Command as lu}from"commander";import Bt from"chalk";var Yi=new lu("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 we(e);if(t.format==="json"){console.log(JSON.stringify(n,null,2));return}let r=Ue(n.slug,t.language);se("Presentation Details"),console.log(),S("Slug",n.slug),S("Title",n.title||"Untitled"),S("Description",n.description||Bt.gray("None")),S("Slides",String(n.numberOfSlides||"-")),S("Mode",n.mode||"-"),S("Created",vn(n.createdAt)),n.updatedAt&&S("Updated",vn(n.updatedAt)),console.log(),r!=="N/A"&&console.log(Bt.bold(" Open: ")+Bt.cyan.underline(r)),console.log(),t.format==="full"&&t.include?.includes("slides")&&(console.log(Bt.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 Kt}from"commander";import uu from"ora";function mu(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}function pu(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:mu(e.source),transparentBackground:t==="icon"}}}function gu(e){let t=e.url||e.imageUrl;if(!t)throw new Error("Image search returned a result without a URL");return t}function fu(e){return e.transparent??e.isTransparent??e.metadata?.transparent??e.metadata?.isTransparent}function hu(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 yu(e,t){let n=e.data.results.map(r=>r.results.map(o=>{let i=o,a=fu(i);if(t==="icon"&&a!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:gu(i),provider:r.providerName,assetType:t,...a!==void 0?{transparent:a}:{}}}));return hu(n)}function bu(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 Wt(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function wu(e){return{requestId:e.runId,status:bu(e),...e.entity?.url?{url:e.entity.url}:{},...e.error?{error:oe(e.error)}:{},...Wt(e.output?.width)!==void 0?{width:Wt(e.output?.width)}:{},...Wt(e.output?.height)!==void 0?{height:Wt(e.output?.height)}:{}}}async function Qi(e,t){return wu(await T("createImage",e,t))}function Xn(e,t){if(t==="json"){m(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&&C(`Image URL: ${e.url}`),e.output&&C(`Saved to: ${e.output}`),e.error&&d(`Error: ${e.error}`)}var vu=new Kt("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"?uu("Searching for images...").start():null,r;try{r=pu(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 vo(r);n?.stop(),o.success||(d("Search failed"),process.exit(c.GENERAL_ERROR));let i=r.options?.assetType??"image",a=yu(o,i);if(t==="json"){m({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}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()}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)}}),xu=new Kt("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){Xn({requestId:o.runId,status:"pending"},t.format);return}let i=await Z(()=>Qi(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 H(i.url,t.output),Xn(a,t.format)}catch(o){d(re(o,n),t.format),process.exit(c.GENERAL_ERROR)}}),ku=new Kt("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 Qi(e,t.teamId);if(t.output){if(n.status!=="completed"||!n.url)throw new Error("Image generation is not complete");await H(n.url,t.output),n.output=t.output}Xn(n,t.format)}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Zi=new Kt("image").description("Image search and generation commands").addCommand(vu).addCommand(xu).addCommand(ku);import{Command as Hn}from"commander";var Cu=new Hn("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{m(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)}}),Iu=new Hn("bundle").description("Read a bounded Open Knowledge Format bundle").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").action(async e=>{try{m(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)}}),ea=new Hn("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(Cu).addCommand(Iu);import{randomUUID as Ru}from"crypto";import Jt from"chalk";import{Command as be}from"commander";function Yn(e){if(e!==void 0)return e==="root"?null:e}function Ge(e){return`cli:library:${e}:${Ru()}`}function Pe(e,t){d(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}var Su=new be("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{m(await y("listLibraryFolders",{includeEntryCounts:!!e.counts,teamId:e.teamId}))}catch(t){Pe(t,"Could not list folders")}}),$u=new be("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{m(await y("createLibraryFolder",{color:t.color,name:e,parentId:Yn(t.parent),teamId:t.teamId},Ge("create")))}catch(n){Pe(n,"Could not create the folder")}}),Tu=new be("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{m(await y("renameLibraryFolder",{folderId:e,name:t,teamId:n.teamId},Ge("rename")))}catch(r){Pe(r,"Could not rename the folder")}}),Eu=new be("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{m(await y("recolorLibraryFolder",{color:t.color==="none"?null:t.color,folderId:e,teamId:t.teamId},Ge("recolor")))}catch(n){Pe(n,"Could not recolour the folder")}}),Au=new be("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{m(await y("moveLibraryFolder",{folderId:e,newParentId:Yn(t.to),teamId:t.teamId},Ge("move")))}catch(n){Pe(n,"Could not move the folder")}}),Ou=new be("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{m(await y("deleteLibraryFolder",{folderId:e,teamId:t.teamId},Ge("delete")))}catch(n){Pe(n,"Could not delete the folder")}}),Pu=new be("folders").description("Manage Library folders").addCommand(Su).addCommand($u).addCommand(Tu).addCommand(Eu).addCommand(Au).addCommand(Ou),_u=new be("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{m(await y("fileArtifactIntoFolder",{folderId:Yn(n.folder),kind:e,targetId:t,teamId:n.teamId},Ge("file")))}catch(r){Pe(r,"Could not file that item")}}),Qn=new be("library").description("Library folders and filing").addCommand(Pu).addCommand(_u);Qn.addHelpText("after",`
|
|
106
|
-
${
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
$
|
|
110
|
-
|
|
111
|
-
${Jt.bold("See also:")}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
`);import{Command as pt}from"commander";function F(e,t){let n={...t},r=e.parent,o=!1;for(;r;){let i=r.opts?.();if(i){o=!0;for(let[a,s]of Object.entries(i))n[a]===void 0&&s!==void 0&&(n[a]=s)}r=r.parent}return o?n:t}var ta=new pt("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{m(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)}}),Lu=new pt("status").description("Read an analysis run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{m(await T("analyzeMediaAsset",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});ta.addCommand(Lu);var na=new pt("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{m(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)}}),Du=new pt("status").description("Read an import run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{m(await T("importConnectorRecording",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});na.addCommand(Du);var ra=new pt("media").description("Ingest and transcribe recordings you already own").addCommand(ta).addCommand(na);import{Command as Zn}from"commander";var Nu=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{m(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)}}),Uu=new Zn("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{m(await T("createMicrosite",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),oa=new Zn("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(Nu).addCommand(Uu);import{Command as nr}from"commander";import er from"ora";function tr(e,t){if(t==="json"){let{cost:n,...r}=e;m(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&&C(`Output URL: ${e.outputUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var qu=new nr("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"?er("Mixing audio...").start():null,i=[{url:e.video,role:"video"}];e.music&&i.push({url:e.music,role:"background",volume:t*5}),e.voice&&i.push({url:e.voice,role:"voice",volume:n*2});try{let a=await wo({operation:"add-to-video",inputs:i,options:{musicVolume:t,voiceVolume:n}});if(!e.wait){o?.stop(),tr(a,r);return}o&&(o.text=`Processing (ID: ${a.requestId})...`);let s=await Z(()=>Sn(a.requestId),120,3e3);if(o?.stop(),s.status==="failed"&&(d(s.error||"Audio mixing failed"),process.exit(c.GENERAL_ERROR)),tr(s,r),e.output){if(!s.outputUrl)throw new Error("Audio mix completed without an output URL");let l=r==="human"?er("Downloading...").start():null;await H(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)}}),ju=new nr("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"?er("Checking status...").start():null;try{let r=await Sn(e);n?.stop(),tr(r,t.format)}catch(r){n?.stop(),d(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ia=new nr("mix").description("Audio mixing commands").addCommand(qu).addCommand(ju);import{Command as or}from"commander";import Ku from"ora";import{readFileSync as Mu}from"fs";var aa=500,sa=1e4,zt=100,da=1e4,ca=1e3,ua=["duration_s","idempotency_key","narration","schema_version","video_description"],Fu=["end_s","id","start_s","text","words"],Vu=["end","id","start","text"],Gu=["description","end_s","id","start_s"];function ma(e){let t=ga(e);if(fa(t),gt(t,ua,""),t.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return t}function pa(e){let t=ga(e);fa(t),gt(t,[...ua,"visual_event"],"");let n=t.visual_event;if(!Xt(n))throw new Error("SFX request visual_event is required");if(gt(n,Gu,"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 ga(e){try{let t=JSON.parse(Mu(e,"utf8"));if(!Xt(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 fa(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>aa)throw new Error(`Audio request narration holds at most ${aa} lines`);if(e.narration.forEach(Bu),e.idempotency_key!==void 0&&!Ce(e.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function Bu(e,t){let n=`narration.${t}`;if(!Xt(e))throw new Error(`Audio request ${n} must be an object`);if(gt(e,Fu,n),!Ce(e.id)||e.id.length>zt)throw new Error(`Audio request ${n}.id is required (1-${zt} characters)`);if(!Ce(e.text)||e.text.trim().length>da)throw new Error(`Audio request ${n}.text is required (1-${da} characters)`);if(la(e.start_s,`${n}.start_s`),la(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>sa)throw new Error(`Audio request ${n}.words must be an array of at most ${sa} entries`);e.words.forEach((r,o)=>{Wu(r,`${n}.words.${o}`)})}}function Wu(e,t){if(!Xt(e))throw new Error(`Audio request ${t} must be an object`);if(gt(e,Vu,t),!Ce(e.text)||e.text.trim().length>ca)throw new Error(`Audio request ${t}.text is required (1-${ca} 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>zt))throw new Error(`Audio request ${t}.id must be 1-${zt} characters`)}function la(e,t){if(e!==void 0&&!Ie(e))throw new Error(`Audio request ${t} must be a non-negative number`)}function gt(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 Xt(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 rr(e,t){if(t==="json"){let{cost:n,...r}=e;m(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&&C(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&d(`Error: ${e.error}`)}var Ju=new or("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=ma(e.request)}catch(i){d(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?Ku("Generating music for video...").start():null,o;try{let i=await bo(t);if(o=i.requestId,!e.wait){r?.stop(),rr(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let a=i.status==="completed"||i.status==="failed"?i:await Z(()=>Rn(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 H(a.audioUrl,e.output),n==="human"&&C(`Saved to: ${e.output}`),a.output=e.output}rr(a,n)}catch(i){r?.stop(),d(re(i,o),n),process.exit(c.GENERAL_ERROR)}}),zu=new or("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{rr(await Rn(e),t.format)}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ha=new or("music").description("Video-aware music generation commands").addCommand(Ju).addCommand(zu);import{Command as ir}from"commander";function ya(e,t){return[...t,e]}var Xu=new ir("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",ya,[]).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{m(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)}}),Hu=new ir("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",ya).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{m(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)}}),ba=new ir("poll").description("Standalone poll commands").addCommand(Xu).addCommand(Hu);import{randomUUID as cr}from"crypto";import{readFile as im}from"fs/promises";import M from"chalk";import{Command as X}from"commander";import{randomUUID as sr}from"crypto";import{readFile as Yu}from"fs/promises";import{Command as Ht}from"commander";var wa=new Ht("edit").description("Apply one atomic draft edit: narration, scene patch/move/remove, composition, or intro/outro card").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--edit <json-or-path>","Edit object as inline JSON or a JSON file path").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Yt("Draft edit failed",async()=>y("editPresentationVideoDraft",{edit:await Qu(n.edit),projectId:e,teamId:n.teamId},n.idempotencyKey??sr()))}),va=new Ht("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",ar(1)).option("--limit <number>","Maximum versions",ar(1,100)).option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);await Yt("Version list failed",()=>y("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:e,teamId:n.teamId}))}),xa=new Ht("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",ar(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t,n){let r=F(this,n);await Yt("Version restore failed",()=>y("restorePresentationVideoVersion",{projectId:e,teamId:r.teamId,versionNumber:t},r.idempotencyKey??sr()))}),ka=new Ht("refresh").description("Refresh deck-backed scenes from the latest presentation version").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Yt("Slide refresh failed",()=>y("refreshPresentationVideoSlides",{projectId:e,teamId:n.teamId},n.idempotencyKey??sr()))});async function Qu(e){let t=e.trim(),n=t.startsWith("{")?t:await Yu(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 ar(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 Yt(e,t){try{m(await t())}catch(n){d(n instanceof Error?n.message:e),process.exit(c.GENERAL_ERROR)}}import{randomUUID as Zu}from"crypto";import{Command as em}from"commander";var tm=["basic","standard","premium"],Ca=new em("presenter").description("Set one scene to a different avatar/look or preset, or restore the project default").argument("<project-id>","Presentation video project ID").argument("<slide-id>","Slide or intro/outro scene ID").option("--avatar-id <id>","Exact avatar/look ID from presenter list").option("--cast-preset-id <id>","Saved cast preset ID").option("--no-apply-preset-voice","Preserve this scene's current voice instead of applying the preset voice").option("--inherit","Remove the override and inherit the project default").option("--render-tier <tier>","Avatar render tier: basic, standard, or premium").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this update").action(async function(e,t,n){let r=F(this,n);try{if(+!!r.avatarId+ +!!r.castPresetId+ +(r.inherit===!0)!==1)throw new Error("Pass exactly one of --avatar-id, --cast-preset-id, or --inherit.");if(r.renderTier&&!r.avatarId)throw new Error("--render-tier can only be used with --avatar-id.");if(r.renderTier&&!tm.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");m(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},nm(r.idempotencyKey)))}catch(o){d(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(c.GENERAL_ERROR)}});function nm(e){return e||Zu()}import{Command as dr}from"commander";var Ia=new dr("inspect").description("Read a presentation-video project and its ordered scene timeline").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{m(await y("getPresentationVideoProject",{projectId:e,teamId:n.teamId}))}catch(r){d(r instanceof Error?r.message:"Project read failed"),process.exit(c.GENERAL_ERROR)}}),rm=new dr("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",om).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{m(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)}}),Ra=new dr("library").description("Reusable generated clips and uploaded recordings").addCommand(rm);function om(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 am=new X("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"){m(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(oe(n.error))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),sm=new X("transform").description("Transform an uploaded PowerPoint import for review").argument("<import-id>","PowerPoint import ID returned by Mindframes").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);try{let r=await y("transformPresentationImport",{importId:e},n.idempotencyKey);m(r)}catch(r){d(r instanceof Error?r.message:"Transform failed"),process.exit(c.GENERAL_ERROR)}}),dm=new X("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"?m(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message),n.error&&d(oe(n.error)))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Sa=new X("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){Sa.help();return}e.file.toLowerCase().endsWith(".pptx")||(d("PowerPoint import requires a .pptx file."),process.exit(c.INVALID_INPUT));try{let t=await ue(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??cr());m(n)}catch(t){d(t instanceof Error?t.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(sm).addCommand(dm),cm=new X("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"?m(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)}}),lm=new X("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"?m(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)}}),um=new X("status").description("Read a presentation-video MP4 render run").argument("<run-id>","Run ID returned by presentation video").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{m(await T("createPresentationVideo",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),mm=new X("prepare").description("Create or reuse a presentation-video project for a presentation").argument("<presentation-id>","Presentation ID, document ID, or slug").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--narrate","Also generate the narration the project is missing (costs credits; requires --yes)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this prepare request").option("--yes","Confirm the narration charge when --narrate is used").action(async function(e,t){let n=F(this,t);if(n.narrate&&!n.yes)return d("Pass --yes to confirm. --narrate generates speaker notes and costs credits.");try{m(await y("preparePresentationVideo",{forceNew:n.forceNew,narrate:n.narrate,presentationId:e,teamId:n.teamId},n.idempotencyKey??cr()))}catch(r){d(r instanceof Error?r.message:"Prepare failed"),process.exit(c.GENERAL_ERROR)}}),pm=new X("status").description("Read a presentation-video narration run").argument("<run-id>","Run ID returned by presentation video narrate").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{m(await T("ensurePresentationVideoNarration",e,n.teamId))}catch(r){d(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),gm=new X("narrate").description("Generate the narration a presentation-video project is still missing").argument("<project-id>","Presentation video project ID").option("--no-wait","Return immediately with the durable run ID").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this narration request").option("--yes","Confirm the narration charge").action(async function(e,t){let n=F(this,t);if(!n.yes)return d("Pass --yes to confirm. Generating narration costs credits.");try{let r=await y("ensurePresentationVideoNarration",{projectId:e,teamId:n.teamId},n.idempotencyKey??cr());if(n.wait===!1||r.runStatus==="completed"){m(r);return}m(r),await lr(r.runId,"presentation video narrate status",()=>Et(r.runId))}catch(r){d(r instanceof Error?r.message:"Narration failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(pm),fm=new X("settings").description("Update saved presentation-video render settings").argument("<project-id>","Presentation video project ID").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this settings update").option("--yes","Confirm updating presentation video settings").action(async function(e,t){let n=F(this,t);if(n.settings||(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{m(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)}}),hm=new X("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.");m(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=zr({binary:u.commands[0],message:r,projectId:t.projectId});o&&Nr(o),process.exit(c.GENERAL_ERROR)}}).addCommand(mm).addCommand(gm).addCommand(Ia).addCommand(wa).addCommand(Ca).addCommand(ka).addCommand(xa).addCommand(fm).addCommand(um).addCommand(va);async function $a(e){let t=e.trim(),n=t.startsWith("{")?t:await im(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 ym(e,t){return[...t,e]}var bm=new X("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)",ym,[]).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 ro(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){m(n);return}g(`Speaker notes run: ${n.runId}`),await lr(n.runId,"presentation speaker-notes-status",()=>Et(n.runId))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),wm=new X("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 oo(e,{instructions:t.instructions,slideId:t.slideId});if(t.format==="json"||!t.follow){m(n);return}g(`Narration run: ${n.runId}`),await lr(n.runId,"presentation video-narration-status",()=>Et(n.runId))}catch(n){d(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});async function lr(e,t,n){let r=null;try{r=await xm(await n())}catch(o){let i=o instanceof Error&&o.message.trim()?o.message.trim():"the event stream ended unexpectedly";j(`Stopped following run ${e}: ${i}. The run is unaffected \u2014 check it with '${u.commands[0]} ${t} ${e}'.`);return}if(r)throw new Error(`Run ${e} ${r.status}: ${r.message} Inspect it with '${u.commands[0]} ${t} ${e}'.`)}function vm(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 xm(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(`
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
${
|
|
119
|
-
$ ${
|
|
120
|
-
$ ${
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
$
|
|
124
|
-
|
|
125
|
-
${
|
|
126
|
-
${
|
|
127
|
-
${
|
|
128
|
-
${
|
|
129
|
-
${
|
|
130
|
-
${
|
|
131
|
-
${
|
|
132
|
-
${
|
|
133
|
-
${
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
$
|
|
137
|
-
|
|
138
|
-
${
|
|
139
|
-
${
|
|
140
|
-
${
|
|
141
|
-
${
|
|
142
|
-
${
|
|
143
|
-
$ ${
|
|
144
|
-
|
|
145
|
-
${
|
|
146
|
-
${
|
|
147
|
-
$ ${
|
|
148
|
-
`);import{writeFile as
|
|
149
|
-
${
|
|
150
|
-
${
|
|
151
|
-
$ ${
|
|
152
|
-
|
|
153
|
-
${
|
|
154
|
-
${
|
|
155
|
-
$ ${
|
|
156
|
-
|
|
157
|
-
${
|
|
158
|
-
$ ${
|
|
159
|
-
`);import
|
|
160
|
-
${
|
|
161
|
-
$ ${
|
|
162
|
-
$ ${
|
|
163
|
-
|
|
164
|
-
${
|
|
165
|
-
${
|
|
166
|
-
$ ${
|
|
167
|
-
$ ${
|
|
168
|
-
`);import{Command as
|
|
107
|
+
${ut.gray("# For an MP4 instead")}
|
|
108
|
+
$ ${m.commands[0]} presentation video <id-or-slug>
|
|
109
|
+
`);import{Command as ce}from"commander";var em=new ce("create").description("Create a transcript-native footage edit project").requiredOption("--title <title>","Project title").requiredOption("--source <asset-ids...>","Analyzed source recording IDs").requiredOption("--strategy <json>","Editorial strategy JSON object").requiredOption("--ranges <json>","Selected ranges JSON array").requiredOption("--outputs <json>","Output variants JSON array").option("--overlays <json>","Overlay JSON array","[]").option("--music-asset-id <id>","Music media asset ID").option("--source-chat-id <id>","Source chat ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async e=>{await ke("createFootageProject",{input:{musicAssetId:e.musicAssetId??null,outputs:pt(e.outputs,"outputs"),overlays:pt(e.overlays,"overlays"),ranges:pt(e.ranges,"ranges"),sourceAssetIds:e.source,sourceChatId:e.sourceChatId,strategy:pt(e.strategy,"strategy"),teamId:e.teamId,title:e.title},idempotencyKey:e.idempotencyKey})}),tm=new ce("show").description("Read a footage project and its append-only versions").argument("<project-id>","Project ID or slug").option("--version-id <id>","Historical version ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("getFootageProject",{input:{projectId:e,teamId:t.teamId,versionId:t.versionId}})}),nm=new ce("revise").description("Append a semantic footage draft revision").argument("<project-id>","Project ID or slug").requiredOption("--base-version-id <id>","Current version ID").requiredOption("--change-summary <text>","Human-readable change summary").option("--title <title>","Replacement title").option("--strategy <json>","Replacement strategy JSON object").option("--ranges <json>","Replacement ranges JSON array").option("--outputs <json>","Replacement outputs JSON array").option("--overlays <json>","Replacement overlays JSON array").option("--music-asset-id <id-or-null>","Replacement music asset ID or null").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("reviseFootageProject",{input:Hi({baseVersionId:t.baseVersionId,changeSummary:t.changeSummary,musicAssetId:t.musicAssetId==="null"?null:t.musicAssetId,outputs:Gt(t.outputs,"outputs"),overlays:Gt(t.overlays,"overlays"),projectId:e,ranges:Gt(t.ranges,"ranges"),strategy:Gt(t.strategy,"strategy"),teamId:t.teamId,title:t.title}),idempotencyKey:t.idempotencyKey})}),rm=new ce("restore").description("Restore a historical footage version as a new head").argument("<project-id>","Project ID or slug").argument("<version-id>","Historical version ID").option("--change-summary <text>","Change summary","Restored version").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("restoreFootageProjectVersion",{input:{changeSummary:n.changeSummary,projectId:e,teamId:n.teamId,versionId:t},idempotencyKey:n.idempotencyKey})}),om=new ce("branch").description("Branch a historical footage version into a new project").argument("<project-id>","Source project ID or slug").argument("<version-id>","Historical version ID").requiredOption("--title <title>","New project title").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("branchFootageProjectVersion",{input:{projectId:e,teamId:n.teamId,title:n.title,versionId:t},idempotencyKey:n.idempotencyKey})}),im=new ce("inspect").description("Create proxy, filmstrip, and waveform evidence for one range").argument("<project-id>","Project ID or slug").argument("<range-id>","Stable range ID").requiredOption("--version-id <id>","Exact version ID").requiredOption("--idempotency-key <key>","Stable retry key").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{await ke("inspectFootageRange",{input:{projectId:e,rangeId:t,teamId:n.teamId,versionId:n.versionId},idempotencyKey:n.idempotencyKey})}),am=new ce("inspection-status").description("Read a footage range inspection run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("inspectFootageRange",e,t.teamId)}),sm=new ce("render").description("Render an exact approved footage draft version").argument("<project-id>","Project ID or slug").requiredOption("--version-id <id>","Exact version ID").option("--output <ids...>","Output IDs; omit to render every output").requiredOption("--approval-receipt <receipt>","Browser-issued approval receipt").requiredOption("--idempotency-key <key>","Key bound into the receipt").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("renderFootageProject",{input:Hi({approvalReceipt:t.approvalReceipt,outputIds:t.output,projectId:e,teamId:t.teamId,versionId:t.versionId}),idempotencyKey:t.idempotencyKey})}),dm=new ce("render-status").description("Read a Footage Studio render run").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await Xi("renderFootageProject",e,t.teamId)}),cm=new ce("import-takes").description("Import all completed takes from a clipping invocation").argument("<project-id>","Project ID or slug").requiredOption("--invocation-id <id>","cc-services clipping invocation ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{await ke("importFootageProviderTakes",{input:{invocationId:t.invocationId,projectId:e,teamId:t.teamId}})}),zi=new ce("footage").description("Create, inspect, revise, and render transcript-native footage edits").addCommand(em).addCommand(tm).addCommand(nm).addCommand(rm).addCommand(om).addCommand(im).addCommand(am).addCommand(sm).addCommand(dm).addCommand(cm);async function ke(e,t){try{u(await h(e,t.input,t.idempotencyKey))}catch(n){s(n instanceof Error?n.message:"Footage operation failed"),process.exit(c.GENERAL_ERROR)}}async function Xi(e,t,n){try{u(await T(e,t,n))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}function pt(e,t){try{return JSON.parse(e)}catch{throw new Error(`${t} must be valid JSON.`)}}function Gt(e,t){return typeof e=="string"?pt(e,t):void 0}function Hi(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}import{Command as lm}from"commander";import Pe from"chalk";function mm(e){return new Set((e??"").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean))}function um(e){if(!e)throw new Error("Slides were requested but the server returned none. Retry, or read the deck in the browser.");ie("Slides"),console.log();for(let t of e){console.log(Pe.bold(` ${t.number}. ${t.title||"Untitled"}`));let n=t.text?.trim();console.log(n?Yi(n):Pe.gray(" (no text on this slide \u2014 image or empty)"));let r=t.speakerNotes?.trim();r&&(console.log(Pe.gray(" Narration/notes:")),console.log(Pe.gray(Yi(r)))),console.log()}}function Yi(e){return e.split(`
|
|
110
|
+
`).map(t=>` ${t}`).join(`
|
|
111
|
+
`)}var Qi=new lm("get").description("Get presentation details").argument("<slug>","Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --format <format>","Output format (summary, full, json)",b("--format",["summary","full","json"]),"summary").option("--include <fields>","Fields to include (comma-separated: slides,styling)").option("-l, --language <lang>","Language for view URL","en").action(async(e,t)=>{await O();try{let n=mm(t.include).has("slides"),r=await Ue(e,{includeSlides:n});if(t.format==="json"){console.log(JSON.stringify(r,null,2));return}let o=qe(r.slug,t.language);ie("Presentation Details"),console.log(),R("Slug",r.slug),R("Title",r.title||"Untitled"),R("Description",r.description||Pe.gray("None")),R("Slides",String(r.numberOfSlides||"-")),R("Mode",r.mode||"-"),R("Created",hn(r.createdAt)),r.updatedAt&&R("Updated",hn(r.updatedAt)),console.log(),o!=="N/A"&&console.log(Pe.bold(" Open: ")+Pe.cyan.underline(o)),console.log(),n&&um(r.slides)}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Wt}from"commander";import pm from"ora";function gm(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}function fm(e){let t=e.assetType??"image";if(t!=="image"&&t!=="icon")throw new Error("Asset type must be image or icon");let n;if(e.maxResults&&(n=Number.parseInt(e.maxResults,10),Number.isNaN(n)||n<1))throw new Error("Max results must be a positive number");return{query:t==="icon"?`${e.query.trim()} transparent icon isolated symbol`:e.query.trim(),options:{maxResults:n||10,size:e.size,safeSearch:e.safeSearch,assetType:t,sources:gm(e.source),transparentBackground:t==="icon"}}}function hm(e){let t=e.url||e.imageUrl;if(!t)throw new Error("Image search returned a result without a URL");return t}function ym(e){return e.transparent??e.isTransparent??e.metadata?.transparent??e.metadata?.isTransparent}function bm(e){let t=[],n=e.reduce((r,o)=>Math.max(r,o.length),0);for(let r=0;r<n;r+=1)for(let o of e){let i=o[r];i!==void 0&&t.push(i)}return t}function wm(e,t){let n=e.data.results.map(r=>r.results.map(o=>{let i=o,a=ym(i);if(t==="icon"&&a!==!0)throw new Error("Icon search returned a result without a verified transparent background");return{...i,url:hm(i),provider:r.providerName,assetType:t,...a!==void 0?{transparent:a}:{}}}));return bm(n)}function vm(e){return e.error||e.status==="failed"||e.status==="errored"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"?"processing":"pending"}function Bt(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function xm(e){return{requestId:e.runId,status:vm(e),...e.entity?.url?{url:e.entity.url}:{},...e.error?{error:se(e.error)}:{},...Bt(e.output?.width)!==void 0?{width:Bt(e.output?.width)}:{},...Bt(e.output?.height)!==void 0?{height:Bt(e.output?.height)}:{}}}async function Zi(e,t){return xm(await T("createImage",e,t))}function Wn(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.output??e.url??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.url&&x(`Image URL: ${e.url}`),e.output&&x(`Saved to: ${e.output}`),e.error&&s(`Error: ${e.error}`)}var km=new Wt("search").description("Search images across the web and licensed stock").requiredOption("-q, --query <query>","Search query").option("-n, --max-results <number>","Maximum number of results (default: 10)").option("-s, --size <size>","Image size: small, medium, large, any","large").option("--asset-type <type>","Asset intent: image or transparent icon","image").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--safe-search","Enable safe search (default: true)",!0).option("--no-safe-search","Disable safe search").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?pm("Searching for images...").start():null,r;try{r=fm(e)}catch(o){n?.stop(),s(o instanceof Error?o.message:"Invalid image search request"),process.exit(c.INVALID_INPUT);return}try{let o=await vo(r);n?.stop(),o.success||(s("Search failed"),process.exit(c.GENERAL_ERROR));let i=r.options?.assetType??"image",a=wm(o,i);if(t==="json"){u({success:!0,query:e.query,assetType:i,totalResults:a.length,images:a});return}if(t==="quiet"){for(let d of a)console.log(d.url);return}if(a.length===0){g("No images found");return}x(`Found ${a.length} images for "${e.query}"`),console.log();for(let d=0;d<a.length;d++){let l=a[d];console.log(`[${d+1}] ${l.title||"Untitled"}`),console.log(` URL: ${l.url}`),console.log(` Size: ${l.width}x${l.height}`),l.author&&console.log(` Author: ${l.author}`),console.log(` Provider: ${l.provider}`),console.log()}g(`Total cost: $${o.data.totalCost.toFixed(4)}`)}catch(o){n?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Cm=new Wt("generate").description("Generate an image and optionally save it locally").argument("[prompt]","Image prompt").option("-p, --prompt <text>","Image prompt (named compatibility form)").option("--provider <provider>","Provider override").option("--model <model>","Model override").option("--width <pixels>","Width").option("--height <pixels>","Height").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Local output path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").option("--yes","Approve generation").action(async(e,t)=>{let n,r=e??t.prompt;r?.trim()||(s("Provide an image prompt as an argument or with --prompt"),process.exit(c.INVALID_INPUT)),t.yes||(s("Pass --yes to approve image generation"),process.exit(c.INVALID_INPUT)),!t.wait&&t.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));try{let o=await h("createImage",{approvalReceipt:"cli:--yes",height:t.height?Number.parseInt(t.height,10):void 0,model:t.model,prompt:r.trim(),provider:t.provider,teamId:t.teamId,width:t.width?Number.parseInt(t.width,10):void 0});if(n=o.runId,!t.wait){Wn({requestId:o.runId,status:"pending"},t.format);return}let i=await te(()=>Zi(o.runId,t.teamId),180,2e3);if(i.status==="failed")throw new Error(i.error||"Image generation failed");if(!i.url)throw new Error("Image generation completed without an image URL");let a=t.output?{...i,output:t.output}:i;t.output&&await Y(i.url,t.output),Wn(a,t.format)}catch(o){s(ae(o,n),t.format),process.exit(c.GENERAL_ERROR)}}),Im=new Wt("status").description("Read image generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Download a completed image").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await Zi(e,t.teamId);if(t.output){if(n.status!=="completed"||!n.url)throw new Error("Image generation is not complete");await Y(n.url,t.output),n.output=t.output}Wn(n,t.format)}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ea=new Wt("image").description("Image search and generation commands").addCommand(km).addCommand(Cm).addCommand(Im);import{Command as Kn}from"commander";var Rm=new Kn("search").description("Search the workspace Knowledge Hub").argument("[query]","Optional search query").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").option("--limit <count>","Maximum results","10").action(async(e,t)=>{try{u(await h("searchKnowledge",{kind:t.kind,limit:Number.parseInt(t.limit,10),query:e,teamId:t.teamId}))}catch(n){s(n instanceof Error?n.message:"Knowledge search failed"),process.exit(c.GENERAL_ERROR)}}),Sm=new Kn("bundle").description("Read a bounded Open Knowledge Format bundle").option("--team-id <id>","Workspace ID").option("--kind <kind>","Knowledge kind").action(async e=>{try{u(await h("getKnowledgeBundle",{kind:e.kind,teamId:e.teamId}))}catch(t){s(t instanceof Error?t.message:"Knowledge bundle failed"),process.exit(c.GENERAL_ERROR)}}),ta=new Kn("knowledge").description("Search the workspace Knowledge Hub and read bounded knowledge bundles").addCommand(Rm).addCommand(Sm);import{randomUUID as $m}from"crypto";import Kt from"chalk";import{Command as we}from"commander";function Jn(e){if(e!==void 0)return e==="root"?null:e}function Be(e){return`cli:library:${e}:${$m()}`}function _e(e,t){s(e instanceof Error?e.message:t),process.exit(c.GENERAL_ERROR)}var Tm=new we("list").description("List the Library folder tree").option("--team-id <id>","Workspace ID").option("--counts","Include how many items are in each folder").action(async e=>{try{u(await h("listLibraryFolders",{includeEntryCounts:!!e.counts,teamId:e.teamId}))}catch(t){_e(t,"Could not list folders")}}),Em=new we("create").description("Create a Library folder").argument("<name>","Folder name").option("--team-id <id>","Workspace ID").option("--parent <id>","Parent folder id; omit for a top-level folder").option("--color <color>","Colour token (slate, blue, green, amber, red, violet)").action(async(e,t)=>{try{u(await h("createLibraryFolder",{color:t.color,name:e,parentId:Jn(t.parent),teamId:t.teamId},Be("create")))}catch(n){_e(n,"Could not create the folder")}}),Am=new we("rename").description("Rename a Library folder").argument("<folder-id>","Folder id").argument("<name>","New name").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{try{u(await h("renameLibraryFolder",{folderId:e,name:t,teamId:n.teamId},Be("rename")))}catch(r){_e(r,"Could not rename the folder")}}),Om=new we("recolor").description("Set or clear a Library folder's colour").argument("<folder-id>","Folder id").requiredOption("--color <color>","Colour token (slate, blue, green, amber, red, violet), or 'none' to clear").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("recolorLibraryFolder",{color:t.color==="none"?null:t.color,folderId:e,teamId:t.teamId},Be("recolor")))}catch(n){_e(n,"Could not recolour the folder")}}),Pm=new we("move").description("Move a Library folder under a new parent").argument("<folder-id>","Folder id").requiredOption("--to <id>","New parent folder id, or 'root' for top level").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("moveLibraryFolder",{folderId:e,newParentId:Jn(t.to),teamId:t.teamId},Be("move")))}catch(n){_e(n,"Could not move the folder")}}),_m=new we("delete").description("Delete a folder and its subfolders; items inside are unfiled").argument("<folder-id>","Folder id").requiredOption("--yes","Confirm deletion").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("deleteLibraryFolder",{folderId:e,teamId:t.teamId},Be("delete")))}catch(n){_e(n,"Could not delete the folder")}}),Lm=new we("folders").description("Manage Library folders").addCommand(Tm).addCommand(Em).addCommand(Am).addCommand(Om).addCommand(Pm).addCommand(_m),Dm=new we("file").description("File an artifact into a Library folder").argument("<kind>","Artifact kind, e.g. presentation or microsite").argument("<target-id>","Id of the artifact itself").requiredOption("--folder <id>","Destination folder id, or 'root' to unfile the artifact").option("--team-id <id>","Workspace ID").action(async(e,t,n)=>{try{u(await h("fileArtifactIntoFolder",{folderId:Jn(n.folder),kind:e,targetId:t,teamId:n.teamId},Be("file")))}catch(r){_e(r,"Could not file that item")}}),zn=new we("library").description("Library folders and filing").addCommand(Lm).addCommand(Dm);zn.addHelpText("after",`
|
|
112
|
+
${Kt.bold("Examples:")}
|
|
113
|
+
${Kt.gray("# Browse the folder tree and file an artifact into a folder")}
|
|
114
|
+
$ ${m.commands[0]} library folders list
|
|
115
|
+
$ ${m.commands[0]} library file presentation <id> --folder <folder-id>
|
|
116
|
+
|
|
117
|
+
${Kt.bold("See also:")}
|
|
118
|
+
${Kt.gray("# A different thing: reusable video clips, not Library folders")}
|
|
119
|
+
$ ${m.commands[0]} video library --help
|
|
120
|
+
`);import{Command as gt}from"commander";function F(e,t){let n={...t},r=e.parent,o=!1;for(;r;){let i=r.opts?.();if(i){o=!0;for(let[a,d]of Object.entries(i))n[a]===void 0&&d!==void 0&&(n[a]=d)}r=r.parent}return o?n:t}var na=new gt("analyze").description("Transcribe an uploaded recording and publish it for generation").argument("<asset-id>","Recording ID").option("--language <code>","BCP-47 language hint for the spoken audio").option("--no-diarize","Skip speaker attribution (cheaper, but a multi-speaker recording becomes much weaker as generation input)").option("--team-id <id>","Workspace ID").option("--yes","Confirm the charge \u2014 billed per source-minute").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to confirm. Analysis is billed per minute of source audio.");try{u(await h("analyzeMediaAsset",{assetId:e,diarize:t.diarize,language:t.language,teamId:t.teamId}))}catch(n){s(n instanceof Error?n.message:"Analysis failed"),process.exit(c.GENERAL_ERROR)}}),Nm=new gt("status").description("Read an analysis run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{u(await T("analyzeMediaAsset",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});na.addCommand(Nm);var ra=new gt("import").description("Import a recording from a connected account").argument("<remote-file-id>","The provider's own ID for the recording").requiredOption("--provider <id>","Provider id of the connected account, e.g. google").requiredOption("--connector <id>","Connected account ID to read from").option("--title <title>","Name for the imported recording").option("--chat <id>","Chat this import was requested from").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("importConnectorRecording",{connectorId:t.connector,providerId:t.provider,remoteFileId:e,sourceChatId:t.chat,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}),qm=new gt("status").description("Read an import run's status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async function(e,t){let n=F(this,t);try{u(await T("importConnectorRecording",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}});ra.addCommand(qm);var oa=new gt("media").description("Ingest and transcribe recordings you already own").addCommand(na).addCommand(ra);import{Command as Xn}from"commander";var Um=new Xn("create").description("Start background microsite generation").argument("<title>","Microsite title").requiredOption("--description <brief>","Microsite brief").option("--audience <audience>","Target audience").option("--tone <tone>","Tone").option("--language <language>","Content language","en").option("--branding-id <id>","Branding ID").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve generation");try{u(await h("createMicrosite",{approvalReceipt:"cli:--yes",audience:t.audience,brandingId:t.brandingId,description:t.description,language:t.language,teamId:t.teamId,title:e,tone:t.tone}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),jm=new Xn("status").description("Read microsite generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createMicrosite",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),ia=new Xn("microsite").description("Generate a shareable multi-section web microsite from a brief").addCommand(Um).addCommand(jm);import{Command as Qn}from"commander";import Hn from"ora";function Yn(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){e.outputUrl?console.log(e.outputUrl):console.log(e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.outputUrl&&x(`Output URL: ${e.outputUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Mm=new Qn("create").description("Mix audio tracks into a video (music will loop to match video duration)").requiredOption("--video <url>","Input video file/URL").option("--music <url>","Background music file/URL (will loop if shorter than video)").option("--voice <url>","Voiceover file/URL").option("--music-volume <percent>","Music volume 0-100 (default: 30, recommended for mix with voice)","30").option("--voice-volume <percent>","Voice volume 0-100","100").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.music&&!e.voice&&(s("At least one of --music or --voice must be provided"),process.exit(c.INVALID_INPUT));let t=parseInt(e.musicVolume,10)/100,n=parseInt(e.voiceVolume,10)/100;(Number.isNaN(t)||t<0||t>1)&&(s("Music volume must be between 0 and 100"),process.exit(c.INVALID_INPUT)),(Number.isNaN(n)||n<0||n>2)&&(s("Voice volume must be between 0 and 200"),process.exit(c.INVALID_INPUT));let r=e.format,o=r==="human"?Hn("Mixing audio...").start():null,i=[{url:e.video,role:"video"}];e.music&&i.push({url:e.music,role:"background",volume:t*5}),e.voice&&i.push({url:e.voice,role:"voice",volume:n*2});try{let a=await wo({operation:"add-to-video",inputs:i,options:{musicVolume:t,voiceVolume:n}});if(!e.wait){o?.stop(),Yn(a,r);return}o&&(o.text=`Processing (ID: ${a.requestId})...`);let d=await te(()=>kn(a.requestId),120,3e3);if(o?.stop(),d.status==="failed"&&(s(d.error||"Audio mixing failed"),process.exit(c.GENERAL_ERROR)),Yn(d,r),e.output){if(!d.outputUrl)throw new Error("Audio mix completed without an output URL");let l=r==="human"?Hn("Downloading...").start():null;await Y(d.outputUrl,e.output),l?.stop(),r==="human"&&x(`Saved to: ${e.output}`)}}catch(a){o?.stop(),s(a instanceof Error?a.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Fm=new Qn("status").description("Check status of an audio mix request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format==="human"?Hn("Checking status...").start():null;try{let r=await kn(e);n?.stop(),Yn(r,t.format)}catch(r){n?.stop(),s(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),aa=new Qn("mix").description("Audio mixing commands").addCommand(Mm).addCommand(Fm);import{Command as er}from"commander";import zm from"ora";import{readFileSync as Vm}from"fs";var sa=500,da=1e4,Jt=100,ca=1e4,la=1e3,ua=["duration_s","idempotency_key","narration","schema_version","video_description"],Gm=["end_s","id","start_s","text","words"],Bm=["end","id","start","text"],Wm=["description","end_s","id","start_s"];function pa(e){let t=fa(e);if(ha(t),ft(t,ua,""),t.duration_s<3)throw new Error("Music request duration_s must be between 3 and 600");return t}function ga(e){let t=fa(e);ha(t),ft(t,[...ua,"visual_event"],"");let n=t.visual_event;if(!zt(n))throw new Error("SFX request visual_event is required");if(ft(n,Wm,"visual_event"),!Ce(n.description))throw new Error("SFX request visual_event.description is required");if(!Ce(n.id)||!Ie(n.start_s))throw new Error("SFX request visual_event requires id and start_s");if(n.end_s!==void 0&&(!Ie(n.end_s)||n.end_s<n.start_s))throw new Error("SFX request visual_event.end_s must be after start_s");return t}function fa(e){try{let t=JSON.parse(Vm(e,"utf8"));if(!zt(t))throw new Error("request must be a JSON object");return t}catch(t){throw new Error(`Cannot read audio request ${e}: ${t instanceof Error?t.message:String(t)}`)}}function ha(e){if(e.schema_version!==1)throw new Error("Audio request schema_version must be 1");if(!Ce(e.video_description))throw new Error("Audio request video_description is required");if(!Ie(e.duration_s)||e.duration_s<.5||e.duration_s>600)throw new Error("Audio request duration_s must be between 0.5 and 600");if(!Array.isArray(e.narration))throw new Error("Audio request narration must be an array");if(e.narration.length>sa)throw new Error(`Audio request narration holds at most ${sa} lines`);if(e.narration.forEach(Km),e.idempotency_key!==void 0&&!Ce(e.idempotency_key))throw new Error("Audio request idempotency_key must be a non-empty string")}function Km(e,t){let n=`narration.${t}`;if(!zt(e))throw new Error(`Audio request ${n} must be an object`);if(ft(e,Gm,n),!Ce(e.id)||e.id.length>Jt)throw new Error(`Audio request ${n}.id is required (1-${Jt} characters)`);if(!Ce(e.text)||e.text.trim().length>ca)throw new Error(`Audio request ${n}.text is required (1-${ca} characters)`);if(ma(e.start_s,`${n}.start_s`),ma(e.end_s,`${n}.end_s`),Ie(e.start_s)&&Ie(e.end_s)&&e.end_s<e.start_s)throw new Error(`Audio request ${n}.end_s must be greater than or equal to ${n}.start_s`);if(e.words!==void 0){if(!Array.isArray(e.words)||e.words.length>da)throw new Error(`Audio request ${n}.words must be an array of at most ${da} entries`);e.words.forEach((r,o)=>{Jm(r,`${n}.words.${o}`)})}}function Jm(e,t){if(!zt(e))throw new Error(`Audio request ${t} must be an object`);if(ft(e,Bm,t),!Ce(e.text)||e.text.trim().length>la)throw new Error(`Audio request ${t}.text is required (1-${la} characters)`);if(!Ie(e.start)||!Ie(e.end))throw new Error(`Audio request ${t} requires numeric start and end seconds`);if(e.end<e.start)throw new Error(`Audio request ${t}.end must be greater than or equal to ${t}.start`);if(e.id!==void 0&&(!Ce(e.id)||e.id.length>Jt))throw new Error(`Audio request ${t}.id must be 1-${Jt} characters`)}function ma(e,t){if(e!==void 0&&!Ie(e))throw new Error(`Audio request ${t} must be a non-negative number`)}function ft(e,t,n){let r=Object.keys(e).filter(i=>!t.includes(i));if(r.length===0)return;let o=n?`${n} `:"";throw new Error(`Audio request ${o}has unknown field(s): ${r.join(", ")}. Allowed: ${t.join(", ")}`)}function zt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Ce(e){return typeof e=="string"&&e.trim().length>0}function Ie(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0}function Zn(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.audioUrl&&x(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Xm=new er("generate").description("Generate music that follows a video's narration and final timing").requiredOption("--request <path>","JSON file with video description, narration, and final timing").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.wait&&e.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=pa(e.request)}catch(i){s(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?zm("Generating music for video...").start():null,o;try{let i=await bo(t);if(o=i.requestId,!e.wait){r?.stop(),Zn(i,n);return}r&&(r.text=`Processing (ID: ${i.requestId})...`);let a=i.status==="completed"||i.status==="failed"?i:await te(()=>xn(i.requestId),180,2e3);if(r?.stop(),a.status==="failed"&&(s(a.error||"Music generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!a.audioUrl)throw new Error("Music completed without an audio URL");await Y(a.audioUrl,e.output),n==="human"&&x(`Saved to: ${e.output}`),a.output=e.output}Zn(a,n)}catch(i){r?.stop(),s(ae(i,o),n),process.exit(c.GENERAL_ERROR)}}),Hm=new er("status").description("Check status of a music generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{Zn(await xn(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),ya=new er("music").description("Video-aware music generation commands").addCommand(Xm).addCommand(Hm);import{Command as tr}from"commander";function ba(e,t){return[...t,e]}var Ym=new tr("create").description("Create a standalone poll").argument("<question>","Poll question").option("--option <text>","Choice (repeat 2-10 times)",ba,[]).option("--type <type>","single, multiple, or word-cloud","single").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve creation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve poll creation");try{u(await h("createPoll",{approvalReceipt:"cli:--yes",options:t.option.map(n=>({text:n})),pollType:t.type,question:e,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Poll creation failed"),process.exit(c.GENERAL_ERROR)}}),Qm=new tr("edit").description("Edit a standalone poll").argument("<poll-id>","Poll UUID").option("--question <question>","New question").option("--option <text>","Replacement choice (repeat)",ba).option("--type <type>","single, multiple, or word-cloud").option("--title <title>","Poll title").option("--team-id <id>","Workspace ID").option("--yes","Approve update").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve poll update");try{u(await h("editPoll",{approvalReceipt:"cli:--yes",options:t.option?.map(n=>({text:n})),pollId:e,pollType:t.type,question:t.question,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Poll update failed"),process.exit(c.GENERAL_ERROR)}}),wa=new tr("poll").description("Standalone poll commands").addCommand(Ym).addCommand(Qm);import{randomUUID as ir}from"crypto";import{readFile as su}from"fs/promises";import U from"chalk";import{Command as H}from"commander";import{randomUUID as rr}from"crypto";import{readFile as Zm}from"fs/promises";import{Command as Xt}from"commander";var va=new Xt("edit").description("Apply one atomic draft edit: narration, scene patch/move/remove, composition, or intro/outro card").argument("<project-id>","Presentation-video project UUID or editor slug").requiredOption("--edit <json-or-path>","Edit object as inline JSON or a JSON file path").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Ht("Draft edit failed",async()=>h("editPresentationVideoDraft",{edit:await eu(n.edit),projectId:e,teamId:n.teamId},n.idempotencyKey??rr()))}),xa=new Xt("versions").description("List saved presentation-video draft versions").argument("<project-id>","Presentation-video project UUID or editor slug").option("--before-version <number>","Continue below this version number",nr(1)).option("--limit <number>","Maximum versions",nr(1,100)).option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);await Ht("Version list failed",()=>h("listPresentationVideoVersions",{beforeVersion:n.beforeVersion,limit:n.limit,projectId:e,teamId:n.teamId}))}),ka=new Xt("restore").description("Restore a saved draft version as a new version").argument("<project-id>","Presentation-video project UUID or editor slug").argument("<version-number>","Version number",nr(1)).option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t,n){let r=F(this,n);await Ht("Version restore failed",()=>h("restorePresentationVideoVersion",{projectId:e,teamId:r.teamId,versionNumber:t},r.idempotencyKey??rr()))}),Ca=new Xt("refresh").description("Refresh deck-backed scenes from the latest presentation version").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);await Ht("Slide refresh failed",()=>h("refreshPresentationVideoSlides",{projectId:e,teamId:n.teamId},n.idempotencyKey??rr()))});async function eu(e){let t=e.trim(),n=t.startsWith("{")?t:await Zm(t,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--edit must contain one JSON object.");return r}function nr(e,t=Number.MAX_SAFE_INTEGER){return n=>{let r=Number(n);if(!Number.isInteger(r)||r<e||r>t)throw new Error(`Expected an integer between ${e} and ${t}.`);return r}}async function Ht(e,t){try{u(await t())}catch(n){s(n instanceof Error?n.message:e),process.exit(c.GENERAL_ERROR)}}import{randomUUID as tu}from"crypto";import{Command as nu}from"commander";var ru=["basic","standard","premium"],Ia=new nu("presenter").description("Set one scene to a different avatar/look or preset, or restore the project default").argument("<project-id>","Presentation video project ID").argument("<slide-id>","Slide or intro/outro scene ID").option("--avatar-id <id>","Exact avatar/look ID from presenter list").option("--cast-preset-id <id>","Saved cast preset ID").option("--no-apply-preset-voice","Preserve this scene's current voice instead of applying the preset voice").option("--inherit","Remove the override and inherit the project default").option("--render-tier <tier>","Avatar render tier: basic, standard, or premium").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this update").action(async function(e,t,n){let r=F(this,n);try{if(+!!r.avatarId+ +!!r.castPresetId+ +(r.inherit===!0)!==1)throw new Error("Pass exactly one of --avatar-id, --cast-preset-id, or --inherit.");if(r.renderTier&&!r.avatarId)throw new Error("--render-tier can only be used with --avatar-id.");if(r.renderTier&&!ru.includes(r.renderTier))throw new Error("--render-tier must be basic, standard, or premium.");u(await h("setPresentationVideoScenePresenter",{applyPresetVoice:r.castPresetId?r.applyPresetVoice:void 0,avatarId:r.avatarId,castPresetId:r.castPresetId,inherit:r.inherit,projectId:e,renderTier:r.renderTier,slideId:t,teamId:r.teamId},ou(r.idempotencyKey)))}catch(o){s(o instanceof Error?o.message:"Scene presenter update failed"),process.exit(c.GENERAL_ERROR)}});function ou(e){return e||tu()}import{Command as or}from"commander";var Ra=new or("inspect").description("Read a presentation-video project and its ordered scene timeline").argument("<project-id>","Presentation-video project UUID or editor slug").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await h("getPresentationVideoProject",{projectId:e,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Project read failed"),process.exit(c.GENERAL_ERROR)}}),iu=new or("list").description("List generated clips and uploaded recordings usable in a presentation video").argument("<project-id>","Target presentation-video project UUID or slug").option("--cursor <cursor>","Opaque cursor from the previous page").option("--limit <number>","Maximum clips to return",au).option("--query <text>","Filter clips by title").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await h("listReusableVideoClips",{cursor:n.cursor,limit:n.limit,projectId:e,query:n.query,teamId:n.teamId}))}catch(r){s(r instanceof Error?r.message:"Clip list failed"),process.exit(c.GENERAL_ERROR)}}),Sa=new or("library").description("Reusable generated clips and uploaded recordings").addCommand(iu);function au(e){let t=Number(e);if(!Number.isInteger(t)||t<1||t>100)throw new Error("--limit must be an integer between 1 and 100.");return t}var du=new H("status").description("Check a presentation generation run").argument("<run-id>","Run ID returned by presentation generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("createSlides",e,t.teamId);if(t.format==="json"){u(n);return}if(t.format==="quiet"){console.log(n.status);return}g(`Status: ${n.status}`),g(n.message),n.progress!==null&&g(`Progress: ${n.progress}%`),n.error&&s(se(n.error))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),cu=new H("transform").description("Transform an uploaded PowerPoint import for review").argument("<import-id>","PowerPoint import ID returned by Mindframes").option("--idempotency-key <key>","Stable retry key").action(async function(e,t){let n=F(this,t);try{let r=await h("transformPresentationImport",{importId:e},n.idempotencyKey);u(r)}catch(r){s(r instanceof Error?r.message:"Transform failed"),process.exit(c.GENERAL_ERROR)}}),lu=new H("status").description("Read a PowerPoint import run").argument("<run-id>","Run ID returned by PowerPoint import").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("importPowerPoint",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message),n.error&&s(se(n.error)))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),$a=new H("import").description("Import a PowerPoint through the review-gated reconstruction pipeline").option("--file <path>","Path to the .pptx to import").option("--filename <name>","Override the uploaded filename").option("--mode <mode>","Import mode: preserve or rebrand","preserve").option("--branding-id <id>","Saved brand ID (required for rebrand mode)").option("--source-chat-id <id>","Associate the import with an existing chat").option("--title <title>","Presentation title").option("--idempotency-key <key>","Stable retry key").action(async e=>{if(!e.file){$a.help();return}e.file.toLowerCase().endsWith(".pptx")||(s("PowerPoint import requires a .pptx file."),process.exit(c.INVALID_INPUT));try{let t=await me(e.file),n=await h("importPowerPoint",{brandingId:e.brandingId,filename:e.filename??t.name,mode:e.mode,sourceChatId:e.sourceChatId,sourceUrl:t.url,title:e.title},e.idempotencyKey??ir());u(n)}catch(t){s(t instanceof Error?t.message:"Import failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(cu).addCommand(lu),mu=new H("speaker-notes-status").description("Check a speaker-notes generation run").argument("<run-id>","Run ID returned by speaker-notes generation").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("generateSpeakerNotes",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),uu=new H("video-narration-status").description("Check a presentation-video narration regeneration run").argument("<run-id>","Run ID returned by video-narration").option("--team-id <id>","Workspace ID override").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await T("regeneratePresentationVideoNarration",e,t.teamId);t.format==="json"?u(n):t.format==="quiet"?console.log(n.status):(g(`Status: ${n.status}`),g(n.message))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),pu=new H("status").description("Read a presentation-video MP4 render run").argument("<run-id>","Run ID returned by presentation video").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await T("createPresentationVideo",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),gu=new H("prepare").description("Create or reuse a presentation-video project for a presentation").argument("<presentation-id>","Presentation ID, document ID, or slug").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--narrate","Also generate the narration the project is missing (costs credits; requires --yes)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this prepare request").option("--yes","Confirm the narration charge when --narrate is used").action(async function(e,t){let n=F(this,t);if(n.narrate&&!n.yes)return s("Pass --yes to confirm. --narrate generates speaker notes and costs credits.");try{u(await h("preparePresentationVideo",{forceNew:n.forceNew,narrate:n.narrate,presentationId:e,teamId:n.teamId},n.idempotencyKey??ir()))}catch(r){s(r instanceof Error?r.message:"Prepare failed"),process.exit(c.GENERAL_ERROR)}}),fu=new H("status").description("Read a presentation-video narration run").argument("<run-id>","Run ID returned by presentation video narrate").option("--team-id <id>","Workspace ID override").action(async function(e,t){let n=F(this,t);try{u(await T("ensurePresentationVideoNarration",e,n.teamId))}catch(r){s(r instanceof Error?r.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),hu=new H("narrate").description("Generate the narration a presentation-video project is still missing").argument("<project-id>","Presentation video project ID").option("--no-wait","Return immediately with the durable run ID").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this narration request").option("--yes","Confirm the narration charge").action(async function(e,t){let n=F(this,t);if(!n.yes)return s("Pass --yes to confirm. Generating narration costs credits.");try{let r=await h("ensurePresentationVideoNarration",{projectId:e,teamId:n.teamId},n.idempotencyKey??ir());if(n.wait===!1||r.runStatus==="completed"){u(r);return}u(r),await ar(r.runId,"presentation video narrate status",()=>At(r.runId))}catch(r){s(r instanceof Error?r.message:"Narration failed"),process.exit(c.GENERAL_ERROR)}}).addCommand(fu),yu=new H("settings").description("Update saved presentation-video render settings").argument("<project-id>","Presentation video project ID").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this settings update").option("--yes","Confirm updating presentation video settings").action(async function(e,t){let n=F(this,t);if(n.settings||(s("Pass --settings <json-or-path> with the patch to apply."),process.exit(c.INVALID_INPUT)),!n.yes)return s("Pass --yes to confirm updating presentation video settings.");try{u(await h("updatePresentationVideoSettings",{projectId:e,settings:await Ta(n.settings),teamId:n.teamId},n.idempotencyKey))}catch(r){s(r instanceof Error?r.message:"Settings update failed"),process.exit(c.GENERAL_ERROR)}}),bu=new H("video").description("Create an MP4 video from a presentation").argument("[presentation-id]","Presentation ID, document ID, or slug").option("--project-id <id>","Advanced: render an already-configured presentation video project").option("--settings <json-or-path>","Settings patch as JSON or a path to a JSON file; only valid with presentation-id").option("--force-new","Create a fresh video project even if the current presentation version already has one").option("--force-rerender","Start a new MP4 render even when the current project fingerprint has a completed render").option("--render-engine <engine>","Renderer for this MP4 only: remotion (Standard) or hyperframes (Premium)").option("--team-id <id>","Workspace ID override").option("--idempotency-key <key>","Stable retry key for this render request").option("--yes","Confirm starting the MP4 render").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to confirm presentation video rendering.");try{if(!e&&!t.projectId)throw new Error("Pass a presentation id or --project-id.");if(e&&t.projectId)throw new Error("Pass either presentation id or --project-id, not both.");if(t.projectId&&(t.settings||t.forceNew))throw new Error("--settings and --force-new require a presentation id, not --project-id.");if(t.renderEngine&&t.renderEngine!=="remotion"&&t.renderEngine!=="hyperframes")throw new Error("--render-engine must be remotion or hyperframes.");u(await h("createPresentationVideo",{forceNew:t.forceNew,forceRerender:t.forceRerender,presentationId:e,projectId:t.projectId,renderEngine:t.renderEngine,settings:t.settings?await Ta(t.settings):void 0,teamId:t.teamId},t.idempotencyKey))}catch(n){let r=n instanceof Error?n.message:"Render failed";s(r);let o=Jr({binary:m.commands[0],message:r,projectId:t.projectId});o&&Dr(o),process.exit(c.GENERAL_ERROR)}}).addCommand(gu).addCommand(hu).addCommand(Ra).addCommand(va).addCommand(Ia).addCommand(Ca).addCommand(ka).addCommand(yu).addCommand(pu).addCommand(xa);async function Ta(e){let t=e.trim(),n=t.startsWith("{")?t:await su(t,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("--settings must be a JSON object.");return r}function wu(e,t){return[...t,e]}var vu=new H("speaker-notes").description("Generate or regenerate persisted presentation speaker notes").argument("<presentation-id>","Presentation ID or slug").option("--mode <mode>","ensure or regenerate","ensure").option("--style <style>","concise or detailed","concise").option("--instructions <text>","Instructions for every selected slide").option("--language <language>","Output language").option("--slide-id <id>","Target one slide (repeatable)",wu,[]).option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{if(!["ensure","regenerate"].includes(t.mode))throw new Error("--mode must be ensure or regenerate");if(!["concise","detailed"].includes(t.style))throw new Error("--style must be concise or detailed");let n=await no(e,{instructions:t.instructions,language:t.language,mode:t.mode,slideIds:t.slideId.length?t.slideId:void 0,style:t.style});if(t.format==="json"||!t.follow){u(n);return}g(`Speaker notes run: ${n.runId}`),await ar(n.runId,"presentation speaker-notes-status",()=>At(n.runId))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),xu=new H("video-narration").description("Regenerate one slide narration in a presentation video draft").argument("<project-id>","Presentation video project ID").requiredOption("--slide-id <id>","Slide ID in the video draft").option("--instructions <text>","Optional regeneration instructions").option("--no-follow","Return immediately with the durable run ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await ro(e,{instructions:t.instructions,slideId:t.slideId});if(t.format==="json"||!t.follow){u(n);return}g(`Narration run: ${n.runId}`),await ar(n.runId,"presentation video-narration-status",()=>At(n.runId))}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});async function ar(e,t,n){let r=null;try{r=await Cu(await n())}catch(o){let i=o instanceof Error&&o.message.trim()?o.message.trim():"the event stream ended unexpectedly";M(`Stopped following run ${e}: ${i}. The run is unaffected \u2014 check it with '${m.commands[0]} ${t} ${e}'.`);return}if(r)throw new Error(`Run ${e} ${r.status}: ${r.message} Inspect it with '${m.commands[0]} ${t} ${e}'.`)}function ku(e){let t=e.eventType;if(t==="run.completed"||t==="durable_run.completed")return"completed";let n=t==="run.failed"||t==="durable_run.failed"?"failed":t==="run.cancelled"||t==="durable_run.cancelled"?"cancelled":null;return n?{message:e.payload?.message?.trim()||e.message?.trim()||"the run reported no error message",status:n}:null}async function Cu(e){let t=e.body?.getReader();if(!t)throw new Error("Speaker notes event stream is unavailable");let n=new TextDecoder,r="",o=null;for(;;){let{done:i,value:a}=await t.read();r+=n.decode(a,{stream:!i});let d=r.split(`
|
|
121
|
+
|
|
122
|
+
`);r=d.pop()??"";for(let l of d){let y=l.split(`
|
|
123
|
+
`).find(v=>v.startsWith("data:"))?.slice(5).trim();if(!y)continue;let p=JSON.parse(y);p.eventType?.startsWith("slide.")&&g(`${p.eventType}${p.payload?.slideId?` \xB7 ${p.payload.slideId}`:""}`);let w=ku(p);w==="completed"?o=null:w&&(o=w)}if(i)return o}}var sr=new H("presentation").description("Create an MP4 video from a finished presentation, plus speaker notes, PowerPoint import, and run status").addCommand(du).addCommand($a).addCommand(vu).addCommand(mu).addCommand(bu).addCommand(xu).addCommand(uu);sr.addHelpText("after",`
|
|
124
|
+
${U.bold("Deck to MP4:")}
|
|
125
|
+
$ ${m.commands[0]} presentation video prepare <slug> ${U.gray("# create/reuse the video project (free)")}
|
|
126
|
+
$ ${m.commands[0]} presentation video narrate <project-id> --yes ${U.gray("# fill in missing narration")}
|
|
127
|
+
$ ${m.commands[0]} presentation video inspect <project-id> ${U.gray("# review the scene timeline")}
|
|
128
|
+
$ ${m.commands[0]} presentation video <slug> --yes ${U.gray("# start the MP4 render")}
|
|
129
|
+
$ ${m.commands[0]} presentation video status <run-id> ${U.gray("# follow the render")}
|
|
130
|
+
|
|
131
|
+
${U.bold("Voice and avatar defaults:")}
|
|
132
|
+
${U.gray("# prepare picks the narration voice for you \u2014 the one this user last")}
|
|
133
|
+
${U.gray("# chose if it is still ready, otherwise the first ready voice \u2014 and")}
|
|
134
|
+
${U.gray("# reports it. Show which voice was selected and offer to change it")}
|
|
135
|
+
${U.gray("# instead of interviewing the user about voices. Every voice in")}
|
|
136
|
+
${U.gray("# avatar options carries a previewUrl audio sample they can hear.")}
|
|
137
|
+
${U.gray('# No avatar is chosen, on purpose: "slides with a voiceover" is the')}
|
|
138
|
+
${U.gray("# normal outcome, so presenter: null is finished, not misconfigured.")}
|
|
139
|
+
${U.gray("# Ask whether they want a presenter; do not assume either way.")}
|
|
140
|
+
$ ${m.commands[0]} avatar options ${U.gray("# real voice and avatar ids + previews")}
|
|
141
|
+
$ ${m.commands[0]} presentation video settings <project-id> --yes --settings '{"voiceId":"<id>"}'
|
|
142
|
+
$ ${m.commands[0]} presentation video settings <project-id> --yes --settings '{"avatarId":"<id>"}'
|
|
143
|
+
|
|
144
|
+
${U.bold("Before rendering:")}
|
|
145
|
+
${U.gray("# Approve the content, then approve the spend \u2014 two questions. Read the")}
|
|
146
|
+
${U.gray("# narration back scene by scene from inspect (scenes[].narration.text)")}
|
|
147
|
+
${U.gray("# and get a yes on the script itself, plus the voice, the presenter (or")}
|
|
148
|
+
${U.gray("# none), music, format and captions, before the render. Reworking one")}
|
|
149
|
+
${U.gray("# scene is the cheap loop; the MP4 is not. --yes is your intent, not")}
|
|
150
|
+
${U.gray("# the user's consent.")}
|
|
151
|
+
$ ${m.commands[0]} presentation video inspect <project-id> ${U.gray("# narration text + settings to show")}
|
|
152
|
+
$ ${m.commands[0]} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"
|
|
153
|
+
|
|
154
|
+
${U.bold("See also:")}
|
|
155
|
+
${U.gray("# Building a video from scratch instead of from a deck")}
|
|
156
|
+
$ ${m.commands[0]} video --help
|
|
157
|
+
`);import{writeFile as Iu}from"fs/promises";import ht from"chalk";import{Command as Ru}from"commander";import Su from"ora";var dr=new Ru("scrape").description("Extract content from a URL").argument("<url>","URL to scrape").option("--team-id <id>","Workspace ID").option("-o, --output <path>","Save content to file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format,r=n==="human"?Su("Scraping URL...").start():null;try{let o=await Co(e,t.teamId);r?.stop(),(!o.success||!o.data)&&(s(o.error||"Failed to scrape URL"),process.exit(c.GENERAL_ERROR));let i=o.data;if(t.output&&(await Iu(t.output,i.content,"utf-8"),n==="human"&&x(`Content saved to: ${t.output}`)),n==="json"){let{cost:a,...d}=i;u(d);return}if(n==="quiet"){console.log(i.content);return}i.title&&(console.log(),console.log(`Title: ${i.title}`)),i.metadata?.description&&console.log(`Description: ${i.metadata.description}`),console.log(`URL: ${i.url}`),console.log(`Tokens: ~${i.metadata?.tokenUsage?.toLocaleString()||"unknown"}`),i.warning&&M(i.warning),t.output||(console.log(),console.log("--- Content ---"),console.log(i.content)),i.cost&&i.cost>0&&g(`Cost: $${i.cost.toFixed(6)}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});dr.addHelpText("after",`
|
|
158
|
+
${ht.bold("Examples:")}
|
|
159
|
+
${ht.gray("# Pull the readable content of a web page")}
|
|
160
|
+
$ ${m.commands[0]} scrape https://example.com/post
|
|
161
|
+
|
|
162
|
+
${ht.bold("See also:")}
|
|
163
|
+
${ht.gray("# Local files and documents, not just URLs")}
|
|
164
|
+
$ ${m.commands[0]} content extract ./paper.pdf
|
|
165
|
+
|
|
166
|
+
${ht.gray("# Spoken words out of audio or video")}
|
|
167
|
+
$ ${m.commands[0]} transcript --help
|
|
168
|
+
`);import cr from"chalk";import{Command as yt}from"commander";function Yt(e,t){t!=="quiet"&&u(e)}var $u=new yt("web").description("Search current public web sources").argument("<query>","Search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","5").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchInternet",{maxResults:Number.parseInt(t.maxResults,10),query:e,teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Search failed"),process.exit(c.GENERAL_ERROR)}}),Tu=new yt("news").description("Search recent news").argument("<topic>","News topic").option("--team-id <id>","Workspace ID").option("--timeframe <value>","Timeframe hint").option("--max-results <count>","Maximum results","6").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("getNews",{maxResults:Number.parseInt(t.maxResults,10),teamId:t.teamId,timeframe:t.timeframe,topic:e});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"News search failed"),process.exit(c.GENERAL_ERROR)}});function Ea(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var Eu=new yt("images").description("Search images across the web and licensed stock").argument("<query>","Image search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--aspect <aspect>","Aspect: any, square, wide, tall","any").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchImages",{aspect:t.aspect,maxResults:Number.parseInt(t.maxResults,10),query:e,sources:Ea(t.source),teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Image search failed"),process.exit(c.GENERAL_ERROR)}}),Au=new yt("video").description("Search video across the web and licensed stock").argument("<query>","Video search query").option("--team-id <id>","Workspace ID").option("--max-results <count>","Maximum results","10").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("--orientation <value>","Orientation: landscape, portrait, square, any","any").option("--license <value>","License: free, premium, any","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{let n=await h("searchStockVideo",{license:t.license,maxResults:Number.parseInt(t.maxResults,10),orientation:t.orientation,query:e,sources:Ea(t.source),teamId:t.teamId});Yt(n,t.format)}catch(n){s(n instanceof Error?n.message:"Video search failed"),process.exit(c.GENERAL_ERROR)}}),lr=new yt("search").description("Web, news, image, and stock-video search").addCommand($u).addCommand(Tu).addCommand(Eu).addCommand(Au);lr.addHelpText("after",`
|
|
169
|
+
${cr.bold("Examples:")}
|
|
170
|
+
$ ${m.commands[0]} search web "state of AI video 2026"
|
|
171
|
+
$ ${m.commands[0]} search news "vaccine approvals"
|
|
172
|
+
|
|
173
|
+
${cr.bold("See also:")}
|
|
174
|
+
${cr.gray("# `search images` and `search video` overlap with these")}
|
|
175
|
+
$ ${m.commands[0]} image search --help
|
|
176
|
+
$ ${m.commands[0]} video find --help
|
|
177
|
+
`);import{Command as ur}from"commander";import Ou from"ora";function mr(e,t){if(t==="json"){let{cost:n,...r}=e;u(r);return}if(t==="quiet"){console.log(e.audioUrl??e.requestId??e.id);return}g(`Request ID: ${e.requestId||e.id}`),g(`Status: ${e.status}`),e.duration&&g(`Duration: ${e.duration}s`),e.audioUrl&&x(`Audio URL: ${e.audioUrl}`),e.cost!==void 0&&g(`Cost: $${e.cost.toFixed(4)}`),e.error&&s(`Error: ${e.error}`)}var Pu=new ur("generate").description("Generate one SFX cue from a video's final facts and visual event").requiredOption("--request <path>","JSON file with video description, narration timings, and visual_event").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{!e.wait&&e.output&&(s("--output requires waiting for completion; remove --no-wait"),process.exit(c.INVALID_INPUT));let t;try{t=ga(e.request)}catch(i){s(i instanceof Error?i.message:String(i)),process.exit(c.INVALID_INPUT)}let n=e.format,r=n==="human"?Ou("Generating sound effect for video...").start():null,o;try{let i=await Io(t);if(o=i.requestId||i.id,!e.wait){r?.stop(),mr(i,n);return}let a=i.requestId||i.id;r&&(r.text=`Processing (ID: ${a})...`);let d=i.status==="completed"||i.status==="failed"?i:await te(()=>Cn(a),60,2e3);if(r?.stop(),d.status==="failed"&&(s(d.error||"Sound effects generation failed"),process.exit(c.GENERAL_ERROR)),e.output){if(!d.audioUrl)throw new Error("Sound effect completed without an audio URL");await Y(d.audioUrl,e.output),n==="human"&&x(`Saved to: ${e.output}`)}mr(d,n)}catch(i){r?.stop(),s(ae(i,o),n),process.exit(c.GENERAL_ERROR)}}),_u=new ur("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{try{mr(await Cn(e),t.format)}catch(n){s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Aa=new ur("sfx").description("Video-aware sound effects generation commands").addCommand(Pu).addCommand(_u);import{writeFile as Lu}from"fs/promises";import{Command as Du}from"commander";import Nu from"ora";var Oa=new Du("transcript").description("Fetch a YouTube video's transcript").argument("<url>","YouTube URL or 11-character video id").option("--team-id <id>","Workspace ID").option("--language <codes>","Comma-separated language priority list, e.g. 'en,de' or 'asr-en'").option("--no-timestamps","Print plain text without [m:ss] prefixes").option("-o, --output <path>","Save the transcript to a file").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let n=t.format,r=n==="human"?Nu("Fetching transcript...").start():null;try{let o=await ko(e,t.teamId,t.language);r?.stop();let i=t.timestamps?o.cues.map(a=>`[${a.timestamp}] ${a.text}`).join(`
|
|
169
178
|
`):o.cues.map(a=>a.text).join(`
|
|
170
|
-
`);if(t.output&&(await Pm(t.output,i,"utf-8"),n==="human"&&C(`Transcript saved to: ${t.output}`)),n==="json"){m(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&&j("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 Dm,writeFile as Oa}from"fs/promises";import{dirname as Nm}from"path";import{Command as Zt}from"commander";import La from"ora";var Pa="en-US-Neural2-C",_a="gemini",Um=new Zt("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: ${Pa})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${_a})`).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"?La("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||Pa,l=e.provider||_a,f={};o&&(f.gemini={speakers:o}),e.instructions&&(f.openai={instructions:e.instructions});let p=await fo({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 w=e.output.endsWith(`.${p.format}`)?e.output:`${e.output}.${p.format}`;await Dm(Nm(w),{recursive:!0}),await Oa(w,p.audioData);let v=w.replace(/\.[^.]+$/,".txt");if(await Oa(v,e.text,"utf-8"),t==="json"){m({status:"completed",output:w,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(w);return}C(`Saved to: ${w}`),g(`Duration: ${p.duration.toFixed(2)}s`),g(`Provider: ${p.provider}`),g(`Cost: $${p.cost.toFixed(6)}`)}catch(a){n?.stop(),d(re(a,i),t),process.exit(c.GENERAL_ERROR)}}),qm=new Zt("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"?La("Fetching voices...").start():null;try{let n=await yo(e.provider);if(t?.stop(),e.format==="json"){m(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)}}),jm=new Zt("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{m(await T("generateSpeech",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Da=new Zt("tts").description("Text-to-speech commands").addCommand(Um).addCommand(qm).addCommand(jm);import{execSync as rn,spawnSync as up}from"child_process";import{access as br,readFile as mp,rm as za}from"fs/promises";import{resolve as bt}from"path";import me from"chalk";import{Command as Q}from"commander";import pp from"ffmpeg-static";import Xa from"ora";import{Command as Mm}from"commander";import Fm from"ora";import{execSync as Vm,spawnSync as Be}from"child_process";import{mkdirSync as Na,existsSync as tn,readFileSync as qa,writeFileSync as Ua}from"fs";import{join as _e,basename as Gm}from"path";import{tmpdir as Bm}from"os";function nn(e,t){try{return Vm(t,{stdio:"ignore"}),!0}catch{return!1}}function en(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 Wm(e){let t=Be("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=Be("ffmpeg",["-i",e,"-vf",`select='gt(scene,${t})',showinfo`,"-vsync","vfr","-f","null","-"],{encoding:"utf-8",timeout:12e4}),r=[0],o=(n.stderr||"").split(`
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
Results saved to: ${r}`)}});import{mkdir as Hm}from"fs/promises";import{join as Ym}from"path";import{Command as yt}from"commander";import Fa from"ora";var Qm=5e3,Zm=120,Ma=5;function ep(e,t){return[...t,e]}function tp(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 Va(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 np(e){if(e.mode&&!["speed","precision"].includes(e.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:tp(e.audioUrl,"Audio URL"),...e.mode?{mode:e.mode}:{},sourceVideoId:Va(e.sourceVideoId)}}function rp(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>Ma)throw new Error(`Provide at most ${Ma} 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:Va(e.sourceVideoId),targetLanguages:t}}function op(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 yr(e){return{requestId:e.runId,status:op(e),...e.entity?.url?{videoUrl:e.entity.url}:{},...e.output?{output:e.output}:{},...e.error?{error:oe(e.error)}:{}}}function Ga(e){return{requestId:e.runId,status:"pending"}}async function Ba(e,t){return Z(async()=>yr(await T(e,t)),Zm,Qm)}function We(e,t){if(t==="json"){m(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.videoUrl&&C(`Video URL: ${e.videoUrl}`),e.error&&d(`Error: ${e.error}`)}function ip(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 ap(e){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function sp(e,t){let n=ap(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 dp(e,t){let n=ip(e.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await Hm(t,{recursive:!0});let r=[],o=new Set;for(let i of n){let a=Ym(t,sp(i.language,o));await H(i.videoUrl,a),r.push({language:i.language,path:a})}return r}var cp=new yt("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=F(this,t).format??"human";try{We(yr(await T("lipsyncVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Wa=new yt("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"?Fa("Starting video lip-sync...").start():null,n;try{let r=await $o(np(e));if(n=r.runId,!e.wait){t?.stop(),We(Ga(r),e.format);return}t&&(t.text="Waiting for video lip-sync...");let o=await Ba("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 H(o.videoUrl,e.output),t?.stop(),We(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(cp),Ka=new yt("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 To();if(e.format==="json")m({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)}}),lp=new yt("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=F(this,t).format??"human";try{We(yr(await T("translateVideo",e)),r)}catch(o){d(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Ja=new yt("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)",ep,[]).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"?Fa("Starting video translation...").start():null,n;try{let r=await Eo(rp(e));if(n=r.runId,!e.wait){t?.stop(),We(Ga(r),e.format);return}t&&(t.text="Waiting for video translations...");let o=await Ba("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");t&&(t.text="Downloading translated videos...");let i=await dp(o,e.outputDir);if(t?.stop(),e.format==="json")m({...o,downloads:i});else if(e.format==="quiet")for(let a of i)console.log(a.path);else{We(o,e.format);for(let a of i)C(`${a.language}: ${a.path}`)}}catch(r){t?.stop(),d(re(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(lp);async function gp(){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 fp(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var hp=new Q("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"?Xa("Finding videos...").start():null;try{let s=await xo({query:e,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:fp(t.source)}});a?.stop();let l=s.data.results.flatMap(f=>f.results);if(i==="json"){let{totalCost:f,...p}=s.data;m({...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}C(`Found ${l.length} videos for "${e}"`),console.log(),l.forEach((f,p)=>{let w=f.kind==="embed";console.log(`[${p+1}] ${f.title}`),console.log(` ${w?"Embed":"URL"}: ${f.embedUrl||f.previewUrl||f.thumbnailUrl}`),console.log(w?` 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)}}),yp=new Q("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{m(await Ao({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 Ha(e){let t=e==="-"?await gp():await mp(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 Ya(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=pe(r.handle),i=pe(r.path),a=pe(r.fileUrl)??pe(r.url),s=pe(r.purpose),l=pe(r.videoRole),f=pe(r.analysisId)??pe(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 ue(bt(i),{idempotencyKey:`${t.uploadIdempotencyKey}:media:${o}`}):{name:pe(r.name),size:Number(r.size),type:pe(r.mime),url:a};if(!p.name||!p.type||!p.url||!Number.isSafeInteger(p.size)||p.size<=0)throw new Error(`URL media binding "${n}" requires name, mime, and positive integer size.`);let w=p.type.startsWith("video/")?"video":p.type.startsWith("audio/")?"audio":p.type.startsWith("image/")?"image":null;if(!w)throw new Error(`Unsupported media type for ${i??a}: ${p.type}`);if(!["source","style","identity","required"].includes(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{...f?{analysisId:f}:{},fileUrl:p.url,handle:o,kind:w,mime:p.type,name:p.name,purpose:s,size:p.size,...l?{videoRole:l}:{}}}))}function pe(e){return typeof e=="string"&&e.length>0?e:void 0}var bp=new Q("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{m(await y("createVideoStoryboard",{aspectRatio:e.aspect,durationSec:Number(e.duration),mediaBindings:await Ya(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardMarkdown:await Ha(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)}}),wp=new Q("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{m(await y("reviseVideoStoryboard",{aspectRatio:t.aspect,baseRevisionId:t.baseRevision,changeSummary:t.changeSummary,durationSec:Number(t.duration),mediaBindings:await Ya(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardId:e,storyboardMarkdown:await Ha(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)}}),vp=new Q("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){m(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)}}),xp=new Q("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(bp).addCommand(wp).addCommand(vp),kp=new Q("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 ue(bt(e.file),{idempotencyKey:`video-reference-analysis:${e.idempotencyKey}:source`});if(!t.type.startsWith("video/"))throw new Error(`Reference analysis requires a video, got ${t.type}`);let n=await Oo({idempotencyKey:e.idempotencyKey,sourceUrl:t.url,teamId:e.teamId,userRequest:e.userRequest}),r={analysisId:n.runId,fileUrl:t.url,handle:"source-video",kind:"video",mime:t.type,name:t.name,purpose:"source",size:t.size};if(e.wait===!1){m({...n,binding:r,source:t});return}let o=await Po(n.runId,e.teamId);if(e.json){m({...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)}}),Cp=new Q("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{m(await T("analyzeVideoReference",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status read failed"),process.exit(c.GENERAL_ERROR)}}),Ip=new Q("reference").description("Upload and inspect reusable video references").addCommand(kp).addCommand(Cp),Rp=new Q("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{m(await T("createVideo",e,t.teamId))}catch(n){d(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Sp=new Q("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"?Xa("Injecting thumbnail...").start():null;try{let r=bt(e.video),o=bt(e.thumbnail),i=e.output?bt(e.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await br(r),await br(o);let a=pp;if(a)try{await br(a)}catch{a=null}if(!a)try{a=rn("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let s=up(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 w="/tmp/cc-thumb-frame.mp4";rn(`${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 "${w}"`,{stdio:"pipe"}),n&&(n.text="Concatenating with video...");let v="/tmp/cc-concat-video.mp4";if(rn(`${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..."),rn(`${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 za(w,{force:!0}),await za(v,{force:!0}),n?.stop(),t==="json"){m({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)}}),$p=new Q("thumbnail").description("Thumbnail operations").addCommand(Sp),on=new Q("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(hp).addCommand($p).addCommand(Wa).addCommand(Ka).addCommand(Ja).addCommand(Ra).addCommand(ja);on.addCommand(yp).addCommand(xp).addCommand(Ip).addCommand(Rp);on.addHelpText("after",`
|
|
174
|
-
${
|
|
175
|
-
|
|
176
|
-
$
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
$
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
${
|
|
184
|
-
${
|
|
185
|
-
${
|
|
186
|
-
$
|
|
187
|
-
$
|
|
188
|
-
|
|
189
|
-
${
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
`)}var
|
|
179
|
+
`);if(t.output&&(await Lu(t.output,i,"utf-8"),n==="human"&&x(`Transcript saved to: ${t.output}`)),n==="json"){u(o);return}if(n==="quiet"){console.log(i);return}console.log(),console.log(`Title: ${o.title}`),o.channelName&&console.log(`Channel: ${o.channelName}`),o.durationFormatted&&console.log(`Duration: ${o.durationFormatted}`),console.log(`Language: ${o.language??"unknown"}${o.isAutoGenerated?" (auto-generated)":""}`),console.log(`Words: ${o.wordCount.toLocaleString()}`),console.log(`URL: ${o.url}`),o.truncated&&M("Transcript was truncated to fit the response budget."),t.output||(console.log(),console.log("--- Transcript ---"),console.log(i)),o.totalCost&&o.totalCost>0&&g(`Cost: $${o.totalCost.toFixed(6)}`)}catch(o){r?.stop(),s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}});import{mkdir as qu,writeFile as Pa}from"fs/promises";import{dirname as Uu}from"path";import{Command as Qt}from"commander";import Da from"ora";var _a="en-US-Neural2-C",La="gemini",ju=new Qt("generate").description("Generate speech from text").requiredOption("-t, --text <text>","Text to convert to speech").requiredOption("-o, --output <path>","Output file path").option("--voice-id <voiceId>","Voice ID (e.g., ElevenLabs: 21m00Tcm4TlvDq8ikWAM)").option("--voice <voice>",`Voice name (default: ${_a})`).option("-p, --provider <provider>",`Provider: gemini, elevenlabs, openai (default: ${La})`).option("-m, --model <model>","Model (provider-specific)").option("-s, --speed <speed>","Speech speed 0.1-4.0 (default: 1.0)").option("-l, --lang <lang>","Language or locale hint (for example en-US)").option("--speakers <json>",`Multi-speaker (Gemini, max 2): '[{"name":"Joe","voice":"Kore"},{"name":"Jane","voice":"Puck"}]'`).option("-i, --instructions <text>","Style prompt (OpenAI gpt-4o-mini-tts): tone, accent, speed, emotion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?Da("Generating speech...").start():null,r;e.speed&&(r=parseFloat(e.speed),(Number.isNaN(r)||r<.1||r>4)&&(n?.stop(),s("Speed must be between 0.1 and 4.0"),process.exit(c.INVALID_INPUT)));let o;if(e.speakers)try{o=JSON.parse(e.speakers),(!Array.isArray(o)||o.length===0||o.length>2||o.some(a=>!a||typeof a!="object"||typeof a.name!="string"||!a.name.trim()||typeof a.voice!="string"||!a.voice.trim()))&&(n?.stop(),s("Speakers must be an array with 1-2 name/voice items"),process.exit(c.INVALID_INPUT))}catch{n?.stop(),s(`Invalid --speakers JSON. Example: '[{"name":"Joe","voice":"Kore"}]'`),process.exit(c.INVALID_INPUT)}let i;try{let a=e.voiceId,d=e.voice||_a,l=e.provider||La,y={};o&&(y.gemini={speakers:o}),e.instructions&&(y.openai={instructions:e.instructions});let p=await fo({text:e.text,options:{language:e.lang,provider:l,voiceId:a,voice:d,model:e.model,speed:r,providerOptions:Object.keys(y).length>0?y:void 0}});i=p.requestId,n?.stop();let w=e.output.endsWith(`.${p.format}`)?e.output:`${e.output}.${p.format}`;await qu(Uu(w),{recursive:!0}),await Pa(w,p.audioData);let v=w.replace(/\.[^.]+$/,".txt");if(await Pa(v,e.text,"utf-8"),t==="json"){u({status:"completed",output:w,audioUrl:p.audioUrl,duration:p.duration,provider:p.provider,format:p.format,voice_id:p.voiceId??null,voice:p.voice??d,model:p.model??e.model??null,speed:p.speed??r??1,lang:p.language??e.lang??null,langApplied:p.langApplied??!1,timestamps:p.timestamps??null,words:p.wordTimings??null});return}if(t==="quiet"){console.log(w);return}x(`Saved to: ${w}`),g(`Duration: ${p.duration.toFixed(2)}s`),g(`Provider: ${p.provider}`),g(`Cost: $${p.cost.toFixed(6)}`)}catch(a){n?.stop(),s(ae(a,i),t),process.exit(c.GENERAL_ERROR)}}),Mu=new Qt("voices").description("List available voices").option("-p, --provider <provider>","Filter by provider: gemini, elevenlabs, openai").option("-f, --format <format>","Output format: human, json",b("--format",["human","json"]),"human").action(async e=>{let t=e.format==="human"?Da("Fetching voices...").start():null;try{let n=await yo(e.provider);if(t?.stop(),e.format==="json"){u(n.voices);return}if(Array.isArray(n.voices)){let r=e.provider?.toUpperCase()||"VOICES";console.log(),console.log(`${r} Voices:`),console.log("-".repeat(50));for(let o of n.voices)console.log(` ${o.name} (${o.id})`),console.log(` ${o.description}`)}else for(let[r,o]of Object.entries(n.voices))if(!(!o||o.length===0)){console.log(),console.log(`${r.toUpperCase()} Voices:`),console.log("-".repeat(50));for(let i of o)console.log(` ${i.name} (${i.id})`),console.log(` ${i.description}`)}}catch(n){t?.stop(),s(n instanceof Error?n.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Fu=new Qt("status").description("Read speech generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").option("-f, --format <format>","Output format: json",b("--format",["json"]),"json").action(async(e,t)=>{try{u(await T("generateSpeech",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Na=new Qt("tts").description("Text-to-speech commands").addCommand(ju).addCommand(Mu).addCommand(Fu);import{execSync as Zt,spawnSync as rp}from"child_process";import{access as gr,readFile as op,rm as Wa}from"fs/promises";import{resolve as wt}from"path";import Q from"chalk";import{Command as ee}from"commander";import ip from"ffmpeg-static";import Ka from"ora";import{mkdir as Vu}from"fs/promises";import{join as Gu}from"path";import{Command as bt}from"commander";import Ua from"ora";var Bu=5e3,Wu=120,qa=5;function Ku(e,t){return[...t,e]}function Ju(e,t){try{let n=new URL(e);if(n.protocol!=="https:"&&n.protocol!=="http:")throw new Error;return n.toString()}catch{throw new Error(`${t} must be a public HTTP(S) URL`)}}function ja(e){if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e))throw new Error("Source video id must be a UUID");return e}function zu(e){if(e.mode&&!["speed","precision"].includes(e.mode))throw new Error("Lip-sync mode must be speed or precision");return{audioUrl:Ju(e.audioUrl,"Audio URL"),...e.mode?{mode:e.mode}:{},sourceVideoId:ja(e.sourceVideoId)}}function Xu(e){let t=[],n=new Set;for(let o of e.targetLanguage){let i=o.trim(),a=i.toLocaleLowerCase("en-US");!i||n.has(a)||(n.add(a),t.push(i))}if(t.length===0)throw new Error("Provide at least one target language");if(t.length>qa)throw new Error(`Provide at most ${qa} target languages`);if(t.find(o=>o.length<2||o.length>40))throw new Error("Target languages must be between 2 and 40 characters");return{...e.captions?{captions:!0}:{},sourceVideoId:ja(e.sourceVideoId),targetLanguages:t}}function Hu(e){return e.error||e.status==="failed"||e.status==="cancelled"?"failed":e.done||e.status==="completed"?"completed":e.status==="in_progress"||e.status==="processing"?"processing":"pending"}function pr(e){return{requestId:e.runId,status:Hu(e),...e.entity?.url?{videoUrl:e.entity.url}:{},...e.output?{output:e.output}:{},...e.error?{error:se(e.error)}:{}}}function Ma(e){return{requestId:e.runId,status:"pending"}}async function Fa(e,t){return te(async()=>pr(await T(e,t)),Wu,Bu)}function We(e,t){if(t==="json"){u(e);return}if(t==="quiet"){console.log(e.videoUrl??e.requestId);return}g(`Request ID: ${e.requestId}`),g(`Status: ${e.status}`),e.videoUrl&&x(`Video URL: ${e.videoUrl}`),e.error&&s(`Error: ${e.error}`)}function Yu(e){return Array.isArray(e?.languages)?e.languages.filter(t=>{if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t;return typeof n.language=="string"&&(n.status==="completed"||n.status==="failed")&&typeof n.videoId=="string"&&(n.videoUrl===null||typeof n.videoUrl=="string")}):[]}function Qu(e){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"translation"}.mp4`}function Zu(e,t){let n=Qu(e);if(!t.has(n))return t.add(n),n;let r=n.slice(0,-4),o=2;for(;t.has(`${r}-${o}.mp4`);)o+=1;let i=`${r}-${o}.mp4`;return t.add(i),i}async function ep(e,t){let n=Yu(e.output).filter(i=>i.status==="completed"&&!!i.videoUrl);if(n.length===0)throw new Error("Video translation completed without downloadable results");await Vu(t,{recursive:!0});let r=[],o=new Set;for(let i of n){let a=Gu(t,Zu(i.language,o));await Y(i.videoUrl,a),r.push({language:i.language,path:a})}return r}var tp=new bt("status").description("Check a video lip-sync request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(e,t){let r=F(this,t).format??"human";try{We(pr(await T("lipsyncVideo",e)),r)}catch(o){s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Va=new bt("lipsync").description("Re-voice a ready workspace video with a public audio URL").requiredOption("--source-video-id <uuid>","READY workspace video UUID").requiredOption("--audio-url <url>","Public replacement voice audio URL").option("--mode <mode>","Quality mode: speed or precision","speed").requiredOption("-o, --output <path>","Local output video path").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format==="human"?Ua("Starting video lip-sync...").start():null,n;try{let r=await $o(zu(e));if(n=r.runId,!e.wait){t?.stop(),We(Ma(r),e.format);return}t&&(t.text="Waiting for video lip-sync...");let o=await Fa("lipsyncVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video lip-sync failed");if(!o.videoUrl)throw new Error("Video lip-sync completed without a video URL");t&&(t.text="Downloading lip-synced video..."),await Y(o.videoUrl,e.output),t?.stop(),We(o,e.format),e.format==="human"&&x(`Saved to: ${e.output}`)}catch(r){t?.stop(),s(ae(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(tp),Ga=new bt("translate-languages").description("List supported video translation target languages").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{try{let t=await To();if(e.format==="json")u({languages:t});else for(let n of t)console.log(n)}catch(t){s(t instanceof Error?t.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),np=new bt("status").description("Check a video translation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"])).action(async function(e,t){let r=F(this,t).format??"human";try{We(pr(await T("translateVideo",e)),r)}catch(o){s(o instanceof Error?o.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),Ba=new bt("translate").description("Translate a ready workspace video into one or more languages").requiredOption("--source-video-id <uuid>","READY workspace video UUID").option("--target-language <language>","Target language (repeatable)",Ku,[]).option("--captions","Burn provider-generated captions into translated videos").requiredOption("--output-dir <path>","Directory for translated videos").option("--no-wait","Do not wait for completion").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format==="human"?Ua("Starting video translation...").start():null,n;try{let r=await Eo(Xu(e));if(n=r.runId,!e.wait){t?.stop(),We(Ma(r),e.format);return}t&&(t.text="Waiting for video translations...");let o=await Fa("translateVideo",r.runId);if(o.status==="failed")throw new Error(o.error??"Video translation failed");t&&(t.text="Downloading translated videos...");let i=await ep(o,e.outputDir);if(t?.stop(),e.format==="json")u({...o,downloads:i});else if(e.format==="quiet")for(let a of i)console.log(a.path);else{We(o,e.format);for(let a of i)x(`${a.language}: ${a.path}`)}}catch(r){t?.stop(),s(ae(r,n),e.format),process.exit(c.GENERAL_ERROR)}}).addCommand(np);async function ap(){return process.stdin.isTTY?null:new Promise(e=>{let t="",n=!1;process.stdin.setEncoding("utf-8"),process.stdin.on("data",r=>{t+=r}),process.stdin.on("end",()=>{n||(n=!0,e(t.trim()||null))}),process.stdin.on("error",()=>{n||(n=!0,e(null))}),setTimeout(()=>{!n&&!t&&(n=!0,e(null))},500)})}function sp(e){let t=e?.trim().toLowerCase();if(!(!t||t==="any"||t==="all"))return t==="web"||t==="stock"?[t]:void 0}var dp=new ee("find").description("Find video clips across the web and licensed stock").argument("<query>","Search query").option("-n, --max-results <count>","Maximum number of results","10").option("-o, --orientation <type>","Video orientation: landscape, portrait, square, any","any").option("-l, --license <type>","License type: free, premium, any","free").option("--source <source>","Catalog: web, stock, or any (default: any)","any").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async(e,t)=>{let{maxResults:n,orientation:r,license:o,format:i}=t,a=i==="human"?Ka("Finding videos...").start():null;try{let d=await xo({query:e,options:{maxResults:parseInt(n,10),orientation:r,license:o,sources:sp(t.source)}});a?.stop();let l=d.data.results.flatMap(y=>y.results);if(i==="json"){let{totalCost:y,...p}=d.data;u({...d,data:p});return}if(i==="quiet"){l.forEach(y=>{console.log(y.embedUrl||y.previewUrl||y.thumbnailUrl)});return}if(l.length===0){g("No videos found");return}x(`Found ${l.length} videos for "${e}"`),console.log(),l.forEach((y,p)=>{let w=y.kind==="embed";console.log(`[${p+1}] ${y.title}`),console.log(` ${w?"Embed":"URL"}: ${y.embedUrl||y.previewUrl||y.thumbnailUrl}`),console.log(w?` Duration: ${y.duration}s | Embed only \u2014 plays in the host player, do not download`:` Duration: ${y.duration}s | Size: ${y.width}x${y.height}`),console.log(` Provider: ${y.provider}`),console.log()}),g(`Total cost: $${d.data.totalCost.toFixed(4)}`)}catch(d){a?.stop(),s(d instanceof Error?d.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),cp=new ee("create").description("Generate one video from a pinned storyboard revision").requiredOption("--storyboard-revision <id>","Immutable storyboard revision UUID").option("--source-video <id>","Ready video from an earlier create call to use as base footage").option("--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 s("Pass --yes to approve video generation");try{u(await Ao({quality:e.draft?"draft":void 0,sourceVideoId:e.sourceVideo,storyboardRevisionId:e.storyboardRevision,teamId:e.teamId},e.approvalReceipt,e.idempotencyKey))}catch(t){s(t instanceof Error?t.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}});async function Ja(e){let t=e==="-"?await ap():await op(e,"utf-8");if(!t?.trim())throw new Error(e==="-"?"No storyboard Markdown was received on stdin":`Storyboard file is empty: ${e}`);return t}async function za(e,t={}){if(e)return e.length===1&&e[0]==="none"?[]:Promise.all(e.map(async n=>{let r;try{let v=JSON.parse(n);if(!v||typeof v!="object"||Array.isArray(v))throw new Error("Media binding must be a JSON object");r=v}catch(v){throw new Error(`Invalid --media binding. Pass one JSON object per binding, for example '{"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}'.`,{cause:v})}let o=ue(r.handle),i=ue(r.path),a=ue(r.fileUrl)??ue(r.url),d=ue(r.purpose),l=ue(r.videoRole),y=ue(r.analysisId)??ue(r.analysis);if(!o||!i&&!a||!d)throw new Error("Invalid --media binding. handle, purpose, and either path or url are required strings.");if(i&&a)throw new Error("A media binding cannot contain both path and url.");if(i&&d==="source"&&y)throw new Error("A source analysis is bound to the original uploaded URL. Reuse the url/name/mime/size binding printed by 'video reference analyze' instead of uploading path again.");if(i&&!t.uploadIdempotencyKey)throw new Error("Local storyboard media requires the command idempotency key.");let p=i?await me(wt(i),{idempotencyKey:`${t.uploadIdempotencyKey}:media:${o}`}):{name:ue(r.name),size:Number(r.size),type:ue(r.mime),url:a};if(!p.name||!p.type||!p.url||!Number.isSafeInteger(p.size)||p.size<=0)throw new Error(`URL media binding "${n}" requires name, mime, and positive integer size.`);let w=p.type.startsWith("video/")?"video":p.type.startsWith("audio/")?"audio":p.type.startsWith("image/")?"image":null;if(!w)throw new Error(`Unsupported media type for ${i??a}: ${p.type}`);if(!["source","style","identity","required"].includes(d))throw new Error(`Invalid media purpose: ${d}`);if(l&&!["reference","first-frame","last-frame"].includes(l))throw new Error(`Invalid videoRole: ${l}`);if(l&&w!=="image")throw new Error("videoRole is supported only for image bindings.");return{...y?{analysisId:y}:{},fileUrl:p.url,handle:o,kind:w,mime:p.type,name:p.name,purpose:d,size:p.size,...l?{videoRole:l}:{}}}))}function ue(e){return typeof e=="string"&&e.length>0?e:void 0}var lp=new ee("create").description("Create a versioned Markdown video storyboard").requiredOption("--file <path>","Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact create").option("--media <binding...>",'One JSON binding per asset: {"handle":"actress-photo","path":"./actress.jpg","purpose":"identity"}').option("--team-id <id>","Workspace ID").action(async e=>{try{u(await h("createVideoStoryboard",{aspectRatio:e.aspect,durationSec:Number(e.duration),mediaBindings:await za(e.media,{uploadIdempotencyKey:e.idempotencyKey}),storyboardMarkdown:await Ja(e.file),teamId:e.teamId,title:e.title},e.idempotencyKey))}catch(t){s(t instanceof Error?t.message:"Storyboard creation failed"),process.exit(c.GENERAL_ERROR)}}),mp=new ee("revise").description("Append an immutable revision to a video storyboard").argument("<storyboard-id>","Storyboard UUID").requiredOption("--base-revision <id>","Revision UUID that was edited").requiredOption("--file <path>","Complete Markdown file path, or - for stdin").requiredOption("--duration <seconds>","Exact total duration in seconds").requiredOption("--aspect <ratio>","Output aspect: 9:16, 16:9, or 1:1").option("--title <text>","Replacement artifact label").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact revision").option("--change-summary <text>","Short description of this revision").option("--media <binding...>",'Replace media bindings with one JSON object per asset; use the JSON printed by "video reference analyze" for analyzed source video').option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await h("reviseVideoStoryboard",{aspectRatio:t.aspect,baseRevisionId:t.baseRevision,changeSummary:t.changeSummary,durationSec:Number(t.duration),mediaBindings:await za(t.media,{uploadIdempotencyKey:t.idempotencyKey}),storyboardId:e,storyboardMarkdown:await Ja(t.file),teamId:t.teamId,title:t.title},t.idempotencyKey))}catch(n){s(n instanceof Error?n.message:"Storyboard revision failed"),process.exit(c.GENERAL_ERROR)}}),up=new ee("show").description("Read a storyboard; print Markdown unless --json is used").argument("<storyboard-id>","Storyboard UUID").option("--revision <id>","Read one immutable revision UUID").option("--team-id <id>","Workspace ID").option("--json","Print the complete structured response").action(async(e,t)=>{try{let n=await h("readVideoStoryboard",{revisionId:t.revision,storyboardId:e,teamId:t.teamId});if(t.json){u(n);return}console.error(`${n.storyboard.title} \xB7 revision ${n.storyboard.revision.versionNumber} (${n.storyboard.revision.id})`),console.log(n.storyboard.revision.storyboardMarkdown)}catch(n){s(n instanceof Error?n.message:"Storyboard read failed"),process.exit(c.GENERAL_ERROR)}}),pp=new ee("storyboard").description("Create, revise, and read Markdown video storyboards").addCommand(lp).addCommand(mp).addCommand(up),Xa=new ee("analyze").description("Upload and analyze a reference video; its analysisId is the only analysis video generation consumes").requiredOption("--file <path>","Local reference video").requiredOption("--idempotency-key <key>","Stable key to reuse when retrying this exact analysis").option("--user-request <text>","What the analysis should focus on").option("--team-id <id>","Workspace ID").option("--no-wait","Return the durable run immediately").option("--json","Print the complete structured result").action(async e=>{try{let t=await me(wt(e.file),{idempotencyKey:`video-reference-analysis:${e.idempotencyKey}:source`});if(!t.type.startsWith("video/"))throw new Error(`Reference analysis requires a video, got ${t.type}`);let n=await Oo({idempotencyKey:e.idempotencyKey,sourceUrl:t.url,teamId:e.teamId,userRequest:e.userRequest}),r={analysisId:n.runId,fileUrl:t.url,handle:"source-video",kind:"video",mime:t.type,name:t.name,purpose:"source",size:t.size};if(e.wait===!1){u({...n,binding:r,source:t});return}let o=await Po(n.runId,e.teamId);if(e.json){u({...o,binding:r,source:t});return}let i=o.output?.analysis??{};console.log(typeof i.promptContext=="string"?i.promptContext:JSON.stringify(o.output,null,2)),console.error(`Analysis run: ${n.runId}`),console.error(`Storyboard media JSON: ${JSON.stringify(r)}`)}catch(t){s(t instanceof Error?t.message:"Reference analysis failed"),process.exit(c.GENERAL_ERROR)}});Xa.addHelpText("after",`
|
|
180
|
+
${Q.gray("# Prints an analysisId plus a ready storyboard media binding. Pass that")}
|
|
181
|
+
${Q.gray("# binding to video storyboard create/revise --media; generation reads the")}
|
|
182
|
+
${Q.gray("# analysis from the analysisId, never from local files.")}
|
|
183
|
+
`);var gp=new ee("status").description("Read a video-reference analysis run").argument("<run-id>","Analysis run UUID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("analyzeVideoReference",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status read failed"),process.exit(c.GENERAL_ERROR)}}),fp=new ee("reference").description("Upload and inspect reusable video references").addCommand(Xa).addCommand(gp),hp=new ee("status").description("Read video background status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createVideo",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),yp=new ee("inject").description("Inject thumbnail into video (first frame + file icon)").requiredOption("-i, --video <path>","Input video file").requiredOption("-t, --thumbnail <path>","Thumbnail image").option("-o, --output <path>","Output video (default: video-with-thumb.mp4)").option("-f, --format <format>","Output format: human, json, quiet",b("--format",["human","json","quiet"]),"human").action(async e=>{let t=e.format,n=t==="human"?Ka("Injecting thumbnail...").start():null;try{let r=wt(e.video),o=wt(e.thumbnail),i=e.output?wt(e.output):r.replace(/\.mp4$/,"-with-thumb.mp4");await gr(r),await gr(o);let a=ip;if(a)try{await gr(a)}catch{a=null}if(!a)try{a=Zt("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let d=rp(a,["-i",r],{encoding:"utf8"});if(d.error)throw new Error(`Failed to probe video: ${d.error.message}`);let l=(d.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!l)throw new Error("Could not detect video dimensions");let[,y,p]=l;n&&(n.text="Creating thumbnail frame...");let w="/tmp/cc-thumb-frame.mp4";Zt(`${a} -y -loop 1 -i "${o}" -vf "scale=${y}:${p}:force_original_aspect_ratio=decrease,pad=${y}:${p}:(ow-iw)/2:(oh-ih)/2,setsar=1" -t 0.033 -r 30 -c:v libx264 -pix_fmt yuv420p "${w}"`,{stdio:"pipe"}),n&&(n.text="Concatenating with video...");let v="/tmp/cc-concat-video.mp4";if(Zt(`${a} -y -i "${w}" -i "${r}" -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" -map "[v]" -map 1:a -c:v libx264 -preset ultrafast -crf 18 -c:a copy "${v}"`,{stdio:"pipe"}),n&&(n.text="Adding file icon thumbnail..."),Zt(`${a} -y -i "${v}" -i "${o}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await Wa(w,{force:!0}),await Wa(v,{force:!0}),n?.stop(),t==="json"){u({success:!0,output:i});return}if(t==="quiet"){console.log(i);return}x(`Thumbnail injected: ${i}`)}catch(r){n?.stop(),s(r instanceof Error?r.message:"Unknown error"),process.exit(c.GENERAL_ERROR)}}),bp=new ee("thumbnail").description("Thumbnail operations").addCommand(yp),en=new ee("video").description("Build a video from scratch \u2014 brief or storyboard to stock and generated footage, translation, lipsync, analysis (for a finished deck, use presentation video)").addCommand(dp).addCommand(bp).addCommand(Va).addCommand(Ga).addCommand(Ba).addCommand(Sa);en.addCommand(cp).addCommand(pp).addCommand(fp).addCommand(hp);en.addHelpText("after",`
|
|
184
|
+
${Q.bold("Examples:")}
|
|
185
|
+
${Q.gray("# Storyboard-first video from a brief")}
|
|
186
|
+
$ ${m.commands[0]} video storyboard create --file brief.md --duration 60 --aspect 16:9 --idempotency-key launch-1
|
|
187
|
+
|
|
188
|
+
${Q.gray("# Find licensed stock footage")}
|
|
189
|
+
$ ${m.commands[0]} video find "city timelapse"
|
|
190
|
+
|
|
191
|
+
${Q.bold("Before generating:")}
|
|
192
|
+
${Q.gray("# Approve the content, then approve the spend \u2014 two questions. Paste the")}
|
|
193
|
+
${Q.gray("# storyboard text into your reply and get a yes on it BEFORE pinning a")}
|
|
194
|
+
${Q.gray("# revision; revising is free and append-only, a pinned revision is not.")}
|
|
195
|
+
${Q.gray("# The browser confirmation video create requires is about cost and")}
|
|
196
|
+
${Q.gray("# destination, not the user reading the script. --yes is neither.")}
|
|
197
|
+
$ ${m.commands[0]} video storyboard show <storyboard-id>
|
|
198
|
+
$ ${m.commands[0]} video storyboard revise <storyboard-id> --base-revision <revision-id> --file brief-v2.md --idempotency-key launch-2
|
|
199
|
+
|
|
200
|
+
${Q.bold("See also:")}
|
|
201
|
+
${Q.gray("# Already have a deck? Render it to MP4 (narration, avatar, captions)")}
|
|
202
|
+
$ ${m.commands[0]} presentation video <slug>
|
|
203
|
+
`);import{Command as fr}from"commander";var wp=new fr("create").description("Start background visual-abstract generation").argument("<brief>","Dense source brief").option("--title <title>","Artifact title").option("--aspect <ratio>","1:1, 16:9, 9:16, 4:3, or 3:4","1:1").option("--quality <tier>","fast, best, or enterprise","best").option("--preset <preset>","Output preset","executive-one-pager").option("--output <type>","raster or vector","raster").option("--branding-id <id>","Branding ID").option("--reference-url <url...>","Up to three image URLs to use as visual references").option("--team-id <id>","Workspace ID").option("--yes","Approve generation").action(async(e,t)=>{if(!t.yes)return s("Pass --yes to approve visual-abstract generation");try{let n=Array.isArray(t.referenceUrl)?t.referenceUrl.slice(0,3).map((r,o)=>({label:`visual-reference-${o+1}`,url:r})):void 0;u(await h("createVisualAbstract",{approvalReceipt:"cli:--yes",aspectRatio:t.aspect,brandingId:t.brandingId,brief:e,outputPreset:t.preset,outputType:t.output,qualityTier:t.quality,referenceImages:n,teamId:t.teamId,title:t.title}))}catch(n){s(n instanceof Error?n.message:"Generation failed"),process.exit(c.GENERAL_ERROR)}}),vp=new fr("status").description("Read visual-abstract generation status").argument("<run-id>","Run ID").option("--team-id <id>","Workspace ID").action(async(e,t)=>{try{u(await T("createVisualAbstract",e,t.teamId))}catch(n){s(n instanceof Error?n.message:"Status failed"),process.exit(c.GENERAL_ERROR)}}),Ha=new fr("visual-abstract").description("Generate a one-page visual abstract graphic (raster or vector) from a dense brief").addCommand(wp).addCommand(vp);var hr=[Bi,Qi,ji,Na,ya,aa,ea,en,dr,Oa,Aa,sr,lr,Vn,ta,zn,wa,Ti,Ha,ia,Ri,Mn,oa,Fn,Ki,zi,Bn];function Ya(e){for(let t of hr)e.addCommand(t)}function Qa(e,t,n){let r=t?`${t} ${e.name()}`:e.name();n.set(r,{arguments:e.registeredArguments.filter(o=>o.required).map(o=>`<${o.name()}>`),requiredOptions:e.options.filter(o=>o.mandatory).map(o=>o.long).filter(o=>!!o)});for(let o of e.commands)Qa(o,r,n)}var tn;function xp(){if(!tn){tn=new Map;for(let e of hr)Qa(e,"",tn)}return tn}function Za(e){let t=xp().get(e);return t?[...t.arguments,...t.requiredOptions.map(n=>`${n} \u2026`)].join(" "):""}var es=["presentations","media","branding","knowledge","research","artifacts","agents"],yr={agents:"Scheduled agents and agent memory",artifacts:"Polls, microsites, ad sets and visual abstracts",branding:"Brand profiles, tokens, logos and competitors",knowledge:"Library documents, folders and the Knowledge Hub",media:"Voiceover, music, SFX, images, stock footage, avatars and video",presentations:"Decks, PowerPoint import, speaker notes and deck\u2192MP4",research:"Scraping, transcripts, web/news/image search and extraction"},kp="other";function Cp(e){let t=e.category?.trim();return t&&t.length>0?t:kp}function ts(e){let t=es.indexOf(e);return t===-1?es.length:t}function vt(e){let t=new Map;for(let n of e){let r=Cp(n),o=t.get(r);o?o.push(n):t.set(r,[n])}return[...t.entries()].sort(([n],[r])=>ts(n)-ts(r)||n.localeCompare(r)).map(([n,r])=>({capabilities:[...r].sort((o,i)=>o.name.localeCompare(i.name)),category:n}))}function br(e){return e.lifecycle?.mode==="background"}function wr(e,t){let n=e.lifecycle?.status?.cliCommand?.trim();if(!(!br(e)||!n))return`${t} ${n} <run-id>`}function Ip(e){switch(e.billing){case"free":return"free";case"quota":return"plan quota";case"fixed":return"credits (fixed)";case"dynamic":return"credits (usage-based)";case"delegated":return"credits (on completion)";default:return"unknown \u2014 check `capabilities`"}}function nn(e){return e.replace(/\|/g,"\\|").replace(/\r?\n/g," ").trim()}function Rp(e,t){let n=wr(e,t);return n?`run id \u2014 poll \`${n}\``:`immediate (${e.operation??"call"})`}function Ke(e,t){let n=["| Command | What it does | Takes | Returns | Cost | Scopes |","|---|---|---|---|---|---|"],r=e.map(o=>{let i=Za(o.name),a=o.scopes?.length?o.scopes.map(d=>`\`${d}\``).join(", "):"\u2014";return`| \`${t} ${nn(o.name)}\` | ${nn(o.description??"")} | ${i?`\`${nn(i)}\``:"\u2014"} | ${Rp(o,t)} | ${Ip(o)} | ${a} |`});return[...n,...r].join(`
|
|
204
|
+
`)}function pe(e,t){if(e.source==="live")return`<!-- Generated from the live ${t.name} capability catalog (v${e.catalogVersion}, ${e.capabilities.length} capabilities) at install time. Re-run \`${t.cmd} skill install\` to refresh. -->`;let n=e.reason?` Reason: ${nn(e.reason).replace(/\.+$/,"")}.`:"";return`<!-- STALE-RISK: the live catalog could not be read at install time, so this was rendered from the snapshot baked into the installed CLI (v${e.catalogVersion}, ${e.capabilities.length} capabilities).${n} Run \`${t.cmd} login\` then \`${t.cmd} skill install --force\` to regenerate from the live catalog, and treat \`${t.cmd} capabilities\` as authoritative over this file. -->`}function ns(e){return e.map(t=>`- [${t}](#${t.toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/ /g,"-")})`).join(`
|
|
205
|
+
`)}var Sp=["get","presentation video prepare","presentation video inspect","presentation video settings","presentation video edit","presentation video presenter","presentation video","presentation video versions","presentation video restore","presentation video refresh","presentation video-narration","presentation speaker-notes","video library list","avatar options"];function $p(e){let t=new Map(e.map(n=>[n.name,n]));return Sp.map(n=>t.get(n)).filter(n=>n!==void 0)}function rn(e,t){let{cmd:n}=e,r=$p(t.capabilities),o=t.capabilities.find(a=>a.name==="presentation video"),i=o?wr(o,n)??`${n} presentation video status <run-id>`:`${n} presentation video status <run-id>`;return`${pe(t,e)}
|
|
195
206
|
|
|
196
207
|
# Deck \u2192 MP4 (\`${n} presentation video\`)
|
|
197
208
|
|
|
@@ -225,8 +236,10 @@ ${n} presentation video prepare <presentation-id> --yes
|
|
|
225
236
|
# 2) Fill in narration when prepare reported it missing (costs credits)
|
|
226
237
|
${n} presentation video narrate <project-id> --yes
|
|
227
238
|
|
|
228
|
-
# 3) Read the project back and SHOW the user what will be produced
|
|
239
|
+
# 3) Read the project back and SHOW the user what will be produced \u2014
|
|
240
|
+
# the narration here, and the deck's own slide copy alongside it.
|
|
229
241
|
${n} presentation video inspect <project-id>
|
|
242
|
+
${n} get <presentation-id> --include slides
|
|
230
243
|
|
|
231
244
|
# 4) Optional: change what they asked to change
|
|
232
245
|
${n} presentation video settings <project-id> --settings ./settings.json --yes
|
|
@@ -251,21 +264,32 @@ voice, presenter, music, captions, or the saved project setup.
|
|
|
251
264
|
## Before you render
|
|
252
265
|
|
|
253
266
|
Everything before the render is repeatable, and only narration (step 2) costs
|
|
254
|
-
anything.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
\`${n}
|
|
260
|
-
|
|
261
|
-
the
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
anything. Two approvals sit between the draft and the MP4, and they are not the
|
|
268
|
+
same approval.
|
|
269
|
+
|
|
270
|
+
Read the deck first, either way. The MP4 is this deck read aloud, so narration
|
|
271
|
+
that sounds right over a slide whose copy is wrong still renders wrong.
|
|
272
|
+
\`${n} get <presentation-id> --include slides\` returns every slide's title
|
|
273
|
+
and its body copy \u2014 the words taken from the slide's own HTML, the same text
|
|
274
|
+
the narrator was given. It is free, so there is no reason to approve a render
|
|
275
|
+
without having read what is on the slides.
|
|
276
|
+
|
|
277
|
+
**First, the script.** \`narrate\` writes the narration on the user's behalf,
|
|
278
|
+
so they read it before it is spoken.
|
|
279
|
+
\`${n} presentation video inspect <project-id>\` returns
|
|
280
|
+
\`scenes[].narration.text\` per scene \u2014 the exact words the voice will say. Put
|
|
281
|
+
those words in your reply, scene by scene; a project id is not the user reading
|
|
282
|
+
their own script. Rework one scene with
|
|
283
|
+
\`${n} presentation video-narration <project-id> --slide-id <id> --instructions "shorter, warmer"\`.
|
|
284
|
+
That loop is cheap and drafts are append-only, so this is the affordable moment
|
|
285
|
+
to be wrong.
|
|
286
|
+
|
|
287
|
+
\`inspect\` also returns per scene \`title\`, \`durationSec\`, \`presenter\`
|
|
288
|
+
(the avatar on that scene, or \`null\`), \`excluded\` and \`imageReady\`, and at
|
|
289
|
+
project level \`renderSettings\`: \`voice\`, \`presenter\`, \`music\`,
|
|
290
|
+
\`captions\`, \`format\`, \`narrationDensity\` and \`renderEngine\`. Those
|
|
291
|
+
choices are the user's too \u2014 offer them and say which you would pick.
|
|
292
|
+
\`presenter: null\` means "slides only", which is the normal answer.
|
|
269
293
|
|
|
270
294
|
### The voice is already chosen \u2014 show it, do not interview for it
|
|
271
295
|
|
|
@@ -317,9 +341,10 @@ ${n} presentation video refresh <project-id> # re-pull slid
|
|
|
317
341
|
${n} presentation video versions <project-id> # drafts are append-only; nothing is lost
|
|
318
342
|
\`\`\`
|
|
319
343
|
|
|
320
|
-
Only once the user has approved
|
|
321
|
-
\`${n} presentation video <presentation-id> --yes\`.
|
|
322
|
-
|
|
344
|
+
**Then, the spend.** Only once the user has read the script and approved the
|
|
345
|
+
settings: \`${n} presentation video <presentation-id> --yes\`. That is the
|
|
346
|
+
second question \u2014 the money \u2014 and \`--yes\` is your statement of intent; it is
|
|
347
|
+
not their consent and never replaces asking.
|
|
323
348
|
|
|
324
349
|
## Render settings
|
|
325
350
|
|
|
@@ -416,7 +441,7 @@ ${Ke(r,n)}
|
|
|
416
441
|
|
|
417
442
|
If something you need is not in this table, do not conclude it is missing \u2014
|
|
418
443
|
run \`${n} capabilities --search video\`.
|
|
419
|
-
`}var
|
|
444
|
+
`}var Tp=["video reference analyze","video storyboard create","video storyboard revise","video storyboard show","video create","search video","video translate-languages","video translate","video lipsync","media analyze","media import","video library list"];function vr(e){let t=new Map(e.map(n=>[n.name,n]));return Tp.map(n=>t.get(n)).filter(n=>n!==void 0)}function on(e,t){let{cmd:n}=e,r=vr(t.capabilities);return`${pe(t,e)}
|
|
420
445
|
|
|
421
446
|
# Video from scratch (\`${n} video\`)
|
|
422
447
|
|
|
@@ -468,25 +493,30 @@ never substitutes for one. \`--draft\` renders at 480p for a faster look;
|
|
|
468
493
|
|
|
469
494
|
## Before you generate
|
|
470
495
|
|
|
471
|
-
Steps 0-2 are cheap and repeatable.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
\`${n} video storyboard show <storyboard-id>\` prints
|
|
477
|
-
the
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
496
|
+
Steps 0-2 are cheap and repeatable. Two approvals sit between them and the MP4,
|
|
497
|
+
and they are not the same approval.
|
|
498
|
+
|
|
499
|
+
**First, the content.** The storyboard is text you wrote on the user's behalf,
|
|
500
|
+
so they read it before it is pinned.
|
|
501
|
+
\`${n} video storyboard show <storyboard-id>\` prints exactly that Markdown \u2014
|
|
502
|
+
the script, the shots, the pacing \u2014 and \`--json\` adds the structured response
|
|
503
|
+
with the revision ids. Put that text in your reply, take their edits, and fold
|
|
504
|
+
them back in with \`${n} video storyboard revise\`. Revisions are appended,
|
|
505
|
+
never overwritten, so iterating costs nothing and loses nothing; a revision is
|
|
506
|
+
immutable once \`video create\` pins it, which is why the reading happens now.
|
|
507
|
+
|
|
508
|
+
Offer the material choices instead of deciding them silently: the
|
|
509
|
+
\`--duration\` and \`--aspect\` the revision was created with, whether this is a
|
|
510
|
+
\`--draft\` look or the full-quality run, and any \`--media\` binding with
|
|
486
511
|
\`purpose\` \`identity\` \u2014 who appears in the shot is not something to guess.
|
|
512
|
+
Say what you would pick and why.
|
|
487
513
|
|
|
488
|
-
|
|
489
|
-
|
|
514
|
+
**Then, the spend.** \`video create\` costs credits, runs for minutes and
|
|
515
|
+
produces the file the user will send to other people. The browser confirmation
|
|
516
|
+
its approval receipt requires asks a person about **cost and destination**; it
|
|
517
|
+
does not show them the script, and it arrives after the revision is already
|
|
518
|
+
written. It is not the user reading the storyboard, so never let it stand in
|
|
519
|
+
for that. \`--yes\` states your intent and is neither.
|
|
490
520
|
|
|
491
521
|
## Storyboards
|
|
492
522
|
|
|
@@ -541,7 +571,6 @@ ${n} video translate-languages # supported target langu
|
|
|
541
571
|
${n} video translate \u2026 # dub a finished video
|
|
542
572
|
${n} video lipsync \u2026 # re-sync lips to new audio
|
|
543
573
|
${n} video library list <project-id> # reusable clips and recordings
|
|
544
|
-
${n} video analyze \u2026 # analyze a video you own
|
|
545
574
|
\`\`\`
|
|
546
575
|
|
|
547
576
|
\`video find\` takes \`--max-results\`, \`--orientation\`, \`--license\` and
|
|
@@ -553,17 +582,17 @@ ${Ke(r,n)}
|
|
|
553
582
|
|
|
554
583
|
If something you need is not in this table, do not conclude it is missing \u2014
|
|
555
584
|
run \`${n} capabilities --search video\`.
|
|
556
|
-
`}var
|
|
585
|
+
`}var Ep=12,Ap={media:"video.md",presentations:"deck-to-video.md"};function Op(e,t,n,r){let{cmd:o}=e,i=yr[n]??n,a=r.filter(br),d=r.filter(p=>p.billing!==void 0&&p.billing!=="free"),l=Ap[n],y=["Every capability",...a.length>0?["Background operations"]:[]];return`${pe(t,e)}
|
|
557
586
|
|
|
558
587
|
# ${n} \u2014 ${i}
|
|
559
588
|
|
|
560
|
-
${r.length} capabilit${r.length===1?"y":"ies"} in this category${
|
|
589
|
+
${r.length} capabilit${r.length===1?"y":"ies"} in this category${d.length>0?`, ${d.length} of which ${d.length===1?"costs":"cost"} credits or ${d.length===1?"counts":"count"} against a plan quota`:", all free"}.${l?`
|
|
561
590
|
|
|
562
591
|
Step-by-step flow: [${l}](${l}).`:""}
|
|
563
|
-
${r.length>
|
|
592
|
+
${r.length>Ep?`
|
|
564
593
|
## Contents
|
|
565
594
|
|
|
566
|
-
${
|
|
595
|
+
${ns(y)}
|
|
567
596
|
`:""}
|
|
568
597
|
## Every capability
|
|
569
598
|
|
|
@@ -579,12 +608,12 @@ ${a.map(p=>`- \`${o} ${p.name}\` \u2192 \`${o} ${p.lifecycle?.status?.cliCommand
|
|
|
579
608
|
`:""}
|
|
580
609
|
Anything missing here? Run \`${o} capabilities --category ${n}\` \u2014 the
|
|
581
610
|
catalog is authoritative and always current; this file is a snapshot of it.
|
|
582
|
-
`}function
|
|
611
|
+
`}function rs(e,t,n={}){let r=[{content:rn(e,t),name:"deck-to-video"},{content:on(e,t),name:"video"}];for(let{capabilities:o,category:i}of vt(t.capabilities)){let a=n[i];r.push({content:Op(e,t,i,o)+(a?`
|
|
583
612
|
---
|
|
584
613
|
|
|
585
|
-
${a}`:""),name:i})}return r}function
|
|
586
|
-
`),
|
|
587
|
-
`),w=[...new Set([...t.capabilities.map(v=>v.name.split(" ")[0]),...
|
|
614
|
+
${a}`:""),name:i})}return r}function os(e){let t=[{file:"deck-to-video.md",when:"An existing deck must become an MP4 \u2014 narration, voice, avatar, music, captions."},{file:"video.md",when:"A video is being built from a brief or storyboard, with no deck involved."}];for(let{capabilities:n,category:r}of vt(e.capabilities))t.push({file:`${r}.md`,when:`${yr[r]??r} (${n.length} commands).`});return t}var Pp=[{capability:"create",intent:'"Make me a presentation / deck / slides about X"',reference:"presentations.md",suffix:' "Topic" --context "\u2026"'},{capability:"presentation video prepare",intent:'"Turn my deck into a video / MP4 / narrated video"',reference:"deck-to-video.md",suffix:" <presentation-id> --yes"},{capability:"video storyboard create",intent:'"Make me a video about X" (no deck exists)',reference:"video.md",suffix:" --file ./storyboard.md \u2026"},{capability:"presentation import",intent:'"Import this PowerPoint / .pptx"',reference:"presentations.md",suffix:" --file deck.pptx --mode preserve"},{capability:"presentation speaker-notes",intent:'"Write speaker notes for this deck"',reference:"deck-to-video.md",suffix:" <presentation-id>"},{capability:"presentation video-narration",intent:'"Rewrite the narration on one slide"',reference:"deck-to-video.md",suffix:" <project-id> --slide-id <id>"},{capability:"tts generate",intent:'"Voiceover / narration / read this aloud / TTS"',reference:"media.md",suffix:' -t "Text" -o out.mp3'},{capability:"music generate",intent:'"Background music / a soundtrack"',reference:"media.md"},{capability:"sfx generate",intent:'"Sound effects"',reference:"media.md"},{capability:"mix create",intent:'"Mix this voiceover and music into the video"',reference:"media.md"},{capability:"image generate",intent:'"Generate an image"',reference:"media.md"},{capability:"search images",intent:'"Find a stock photo"',reference:"research.md",suffix:' -q "\u2026"'},{capability:"search video",intent:'"Find stock footage / b-roll"',reference:"video.md",suffix:' "ocean waves"'},{capability:"avatar options",intent:'"Which avatars / presenters / voices can I use?"',reference:"media.md"},{capability:"avatar generate",intent:'"Make a talking-head / avatar clip"',reference:"media.md"},{capability:"video translate",intent:'"Dub / translate this video"',reference:"video.md"},{capability:"video lipsync",intent:'"Re-sync the lips to this new audio"',reference:"video.md"},{capability:"branding extract",intent:'"Match my brand" / "pull branding from this site"',reference:"branding.md",suffix:" <url>"},{capability:"scrape",intent:'"Read this web page"',reference:"research.md",suffix:" https://example.com"},{capability:"transcript",intent:'"Get the transcript of this YouTube video"',reference:"research.md",suffix:" <url>"},{capability:"search web",intent:'"Search the web / find news about X"',reference:"research.md",suffix:' "query"'},{capability:"knowledge search",intent:'"What do we already have on X?"',reference:"knowledge.md"},{capability:"document create",intent:'"Save this as a document" / library filing',reference:"knowledge.md"},{capability:"microsite create",intent:'"Build a landing page / microsite"',reference:"artifacts.md"},{capability:"poll create",intent:'"Make a poll"',reference:"artifacts.md"},{capability:"visual-abstract create",intent:'"One-page visual summary"',reference:"artifacts.md"},{capability:"ad-set create",intent:'"Ad creatives for this campaign"',reference:"artifacts.md"},{capability:"agent create",intent:'"Schedule this to run every week"',reference:"agents.md"}],_p=["capabilities","config","delete","derive","export","footage","ideas","import","list","login","logout","runner","skill","templates","whoami"];function an(e,t=Ot("rendered without a catalog fetch")){let{name:n,cmd:r,pkg:o}=e,i=n.toUpperCase().replace(/[^A-Z0-9]/g,"_"),a=new Map(t.capabilities.map(v=>[v.name,v])),d=Pp.filter(v=>a.has(v.capability)).map(v=>`| ${v.intent} | \`${r} ${v.capability}${v.suffix??""}\` | [${v.reference}](references/${v.reference}) |`).join(`
|
|
615
|
+
`),y=vt(t.capabilities).map(({capabilities:v,category:C})=>`${C} (${v.length})`).join(", "),p=os(t).map(({file:v,when:C})=>`| [references/${v}](references/${v}) | ${C} |`).join(`
|
|
616
|
+
`),w=[...new Set([...t.capabilities.map(v=>v.name.split(" ")[0]),..._p])].sort().map(v=>`\`${v}\``).join(", ");return`---
|
|
588
617
|
name: ${n}
|
|
589
618
|
description: >-
|
|
590
619
|
Use for ANY request involving presentations, decks, slides, pitch decks, PowerPoint,
|
|
@@ -597,7 +626,7 @@ description: >-
|
|
|
597
626
|
${t.capabilities.length} CLI capabilities, listed in references/.
|
|
598
627
|
---
|
|
599
628
|
|
|
600
|
-
${
|
|
629
|
+
${pe(t,e)}
|
|
601
630
|
|
|
602
631
|
# ${n} CLI
|
|
603
632
|
|
|
@@ -614,7 +643,7 @@ serves.
|
|
|
614
643
|
|
|
615
644
|
| The user asks for\u2026 | Start here | Detail |
|
|
616
645
|
|---|---|---|
|
|
617
|
-
${
|
|
646
|
+
${d}
|
|
618
647
|
|
|
619
648
|
---
|
|
620
649
|
|
|
@@ -629,6 +658,29 @@ no \`video export\` subcommand.
|
|
|
629
658
|
|
|
630
659
|
---
|
|
631
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
|
+
|
|
632
684
|
## A render is a purchase
|
|
633
685
|
|
|
634
686
|
\`${r} presentation video\` and \`${r} video create\` cost credits, take
|
|
@@ -637,10 +689,9 @@ before them \u2014 preparing the project, inspecting it, generating narration,
|
|
|
637
689
|
revising a storyboard, changing settings \u2014 is free or cheap and undoable. So
|
|
638
690
|
spend the cheap phase getting it right instead of rushing past it.
|
|
639
691
|
|
|
640
|
-
**
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
presenter/avatar appears at all, music, format and captions.
|
|
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.
|
|
644
695
|
|
|
645
696
|
Where a choice comes from a list, offer the list. \`${r} avatar options\`
|
|
646
697
|
prints the real avatar, personal-presenter and voice ids \u2014 shortlist a few and
|
|
@@ -651,7 +702,7 @@ only" is a common and legitimate answer, so ask instead of assuming either way.
|
|
|
651
702
|
can give that.
|
|
652
703
|
|
|
653
704
|
Everything free and reversible stays fluent \u2014 never ask permission to inspect a
|
|
654
|
-
project or reread a storyboard. The gate is
|
|
705
|
+
project or reread a storyboard. The gate is content you authored, and money.
|
|
655
706
|
|
|
656
707
|
Per-pipeline detail: [deck-to-video.md](references/deck-to-video.md),
|
|
657
708
|
[video.md](references/video.md).
|
|
@@ -710,7 +761,7 @@ Two things it does not cover: commands gated behind account feature flags (the
|
|
|
710
761
|
\`${r} config refresh\`, and commands the CLI owns without a catalog entry are
|
|
711
762
|
listed by \`${r} --help\`.
|
|
712
763
|
|
|
713
|
-
Categories: ${
|
|
764
|
+
Categories: ${y}.
|
|
714
765
|
|
|
715
766
|
---
|
|
716
767
|
|
|
@@ -763,7 +814,7 @@ CLI-local and never appear in \`${r} capabilities\`: auth and config
|
|
|
763
814
|
- \`${r} create "Topic"\` \u2192 load the \`${n}-presentation\` skill
|
|
764
815
|
- editing an existing deck \u2192 load the \`${n}-presentation-edit\` skill
|
|
765
816
|
- building a video from a brief or storyboard, with no deck \u2192 load the \`${n}-video\` skill
|
|
766
|
-
`}function
|
|
817
|
+
`}function sn(e){let{name:t,cmd:n}=e;return`---
|
|
767
818
|
name: ${t}-presentation-edit
|
|
768
819
|
description: >
|
|
769
820
|
Use ONLY when editing an already-created presentation that has real slides:
|
|
@@ -1048,7 +1099,7 @@ Do NOT render or export the presentation \u2014 that's handled by the app.
|
|
|
1048
1099
|
| Create brand-new presentation (5+ slides, new topic) | \`${n} create ...\` via CLI |
|
|
1049
1100
|
| Redesign the whole deck | \`${n} create ...\` via CLI, then sync |
|
|
1050
1101
|
| User provides a URL to base the presentation on | \`${n} scrape <url>\` \u2192 \`${n} create ...\` |
|
|
1051
|
-
`}function
|
|
1102
|
+
`}function dn(e){let{name:t,cmd:n}=e;return`---
|
|
1052
1103
|
name: ${t}-presentation
|
|
1053
1104
|
description: Use when user asks to create presentations, slides, decks, pitch decks.
|
|
1054
1105
|
Researches the topic, gathers context, and generates AI-powered presentations via CLI.
|
|
@@ -1079,7 +1130,7 @@ If this fails \u2192 **STOP**. Tell the user: \`${n} login\`. Do NOT proceed wit
|
|
|
1079
1130
|
| \`${n} scrape <url>\` | Scrape URL content |
|
|
1080
1131
|
| \`${n} list\` | List presentations |
|
|
1081
1132
|
| \`${n} get <id-or-slug>\` | Get details and canonical Studio/view URLs |
|
|
1082
|
-
| \`${n} export <id> -o
|
|
1133
|
+
| \`${n} export <id-or-slug> -o deck.html\` | Export to HTML/PDF/PPTX |
|
|
1083
1134
|
| \`${n} branding find <name-or-url>\` | Search existing brands (returns IDs) |
|
|
1084
1135
|
| \`${n} branding extract <url>\` | Extract NEW brand identity |
|
|
1085
1136
|
| \`${n} branding list\` | List saved brands |
|
|
@@ -1221,11 +1272,12 @@ ${n} create "Acme Corp Investor Pitch" \\
|
|
|
1221
1272
|
## Export (save to file)
|
|
1222
1273
|
|
|
1223
1274
|
\`\`\`bash
|
|
1224
|
-
#
|
|
1225
|
-
${n} export <slug> -o ./presentation.
|
|
1275
|
+
# Self-contained interactive HTML (default format)
|
|
1276
|
+
${n} export <id-or-slug> -o ./presentation.html
|
|
1226
1277
|
|
|
1227
|
-
#
|
|
1228
|
-
${n} export <slug> -
|
|
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
|
|
1229
1281
|
|
|
1230
1282
|
# Get slug from a just-created presentation
|
|
1231
1283
|
${n} get <id-or-slug> --format json
|
|
@@ -1256,7 +1308,7 @@ files inside its own local-runner workspace.
|
|
|
1256
1308
|
\`\`\`bash
|
|
1257
1309
|
${n} list
|
|
1258
1310
|
${n} get <id-or-slug>
|
|
1259
|
-
${n} export <id-or-slug> -o presentation.
|
|
1311
|
+
${n} export <id-or-slug> -o presentation.html
|
|
1260
1312
|
${n} delete <id-or-slug>
|
|
1261
1313
|
${n} import ./presentation.zip
|
|
1262
1314
|
\`\`\`
|
|
@@ -1268,8 +1320,8 @@ ${n} import ./presentation.zip
|
|
|
1268
1320
|
- **Auth fails** \u2192 \`${n} logout && ${n} login\` (browser required)
|
|
1269
1321
|
- **"Context required"** \u2192 add \`--context\`, \`--file\`, or \`--context-file\`
|
|
1270
1322
|
- **Rate limit (429)** \u2192 check plan with \`${n} whoami\`
|
|
1271
|
-
`}var
|
|
1272
|
-
`),
|
|
1323
|
+
`}var Lp=[{capability:"video reference analyze",when:"Optional \u2014 match the style of a reference video."},{capability:"video storyboard create",when:"Write the storyboard. Markdown in, immutable revision out."},{capability:"video storyboard revise",when:"Iterate. Each revision is appended, never rewritten."},{capability:"video create",when:"Render a pinned revision. Paid, approval-gated, background."}];function cn(e,t){let{cmd:n,name:r,pkg:o}=e,i=new Set(t.capabilities.map(l=>l.name)),a=Lp.filter(l=>i.has(l.capability)).map((l,y)=>`${y+1}. \`${n} ${l.capability}\` \u2014 ${l.when}`).join(`
|
|
1324
|
+
`),d=vr(t.capabilities).length;return`---
|
|
1273
1325
|
name: ${r}-video
|
|
1274
1326
|
description: >-
|
|
1275
1327
|
Use when a video must be built from scratch \u2014 a brief, a script, a storyboard,
|
|
@@ -1277,10 +1329,10 @@ description: >-
|
|
|
1277
1329
|
involved. Trigger it even when the user never names the product: "make me a
|
|
1278
1330
|
video about X", "turn this script into a video", "I need a 30s promo".
|
|
1279
1331
|
For turning an EXISTING presentation into an MP4, use the ${r} skill's
|
|
1280
|
-
deck\u2192MP4 flow instead. ${
|
|
1332
|
+
deck\u2192MP4 flow instead. ${d} CLI capabilities, listed in references/video.md.
|
|
1281
1333
|
---
|
|
1282
1334
|
|
|
1283
|
-
${
|
|
1335
|
+
${pe(t,e)}
|
|
1284
1336
|
|
|
1285
1337
|
# ${r} video
|
|
1286
1338
|
|
|
@@ -1334,12 +1386,12 @@ ${n} video <sub> --help
|
|
|
1334
1386
|
\`\`\`
|
|
1335
1387
|
|
|
1336
1388
|
The catalog is authoritative and always current; this file is a snapshot of it.
|
|
1337
|
-
`}function
|
|
1389
|
+
`}function is(e,t){return[{content:on(e,t),name:"video"},{content:rn(e,t),name:"deck-to-video"}]}import{existsSync as xr,mkdirSync as as,rmSync as Dp,writeFileSync as ss}from"fs";import{homedir as ls}from"os";import{basename as Np,join as Re,relative as qp,resolve as xt}from"path";var Le=[{name:"Claude Code",dir:".claude",provider:"claude"},{name:"GitHub Copilot",dir:".github",agentSuffix:".agent.md",provider:"copilot"},{name:"Cursor",dir:".cursor"},{name:"Codex",dir:".codex",agentSuffix:".toml",provider:"codex"},{name:"OpenCode",dir:".opencode"},{name:"Windsurf",dir:".windsurf"},{name:"Agent",dir:".agent"}];var Up={sonnet:"claude-sonnet-4.6",haiku:"claude-haiku-4.5",opus:"claude-opus-4.6"},jp=["permissionMode","skills","subagentType"];function Mp(e,t){if(t!=="copilot")return e;let n=e.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return ds(e);let r=n[1],o=e.slice((n.index??0)+n[0].length);r=r.replace(/^(model:\s*)(\S+)([ \t]*)$/m,(a,d,l,y)=>`${d}${Up[l]??l}${y}`);for(let a of jp)r=r.replace(new RegExp(`^${a}:[^
|
|
1338
1390
|
]*
|
|
1339
|
-
?`,"m"),"");r=r.replace(/\n+$/,"");let i=
|
|
1391
|
+
?`,"m"),"");r=r.replace(/\n+$/,"");let i=ds(o);return`---
|
|
1340
1392
|
${r}
|
|
1341
1393
|
---
|
|
1342
|
-
${i}`}function
|
|
1394
|
+
${i}`}function ds(e){return e.replace(/\bAskUserQuestion\b/g,"ask the user directly in your response").replace(/\*\*Construct the Task prompt:\*\*/g,"**Construct the Task prompt (must be fully self-contained \u2014 sub-agents cannot read this conversation's history):**").replace(/\*\*Wait for all agents to complete\*\*/g,"**Wait for all agents to complete** (monitor with `/tasks` in Copilot CLI)").replace("**Launch ALL scene agents in parallel**","**Launch ALL scene agents in parallel** \u2014 each agent must write to its own `Scene[NN][Name].tsx` file. Two agents writing to the same file will silently overwrite each other (no error). Verify unique filenames before spawning.")}function Fp(e,t){let n=xt(e),r=xt(e,t);if(qp(n,r).startsWith("..")||xt(r)!==r.replace(/\.\./g,""))throw new Error(`Invalid path: "${t}" would escape base directory`);return r}function cs(e,t,n,r){let o=Re(e,"SKILL.md");if(as(e,{recursive:!0}),ss(o,Mp(t,r),"utf-8"),n&&n.length>0){let i=Re(e,"references");as(i,{recursive:!0});for(let a of n){let d=Re(i,`${a.name}.md`);ss(d,a.content,"utf-8")}}}function ln(e,t,n={},r){let o={installed:[],skipped:[],errors:[]},i=n.local?process.cwd():ls();if(n.dir){let a=Np(xt(n.dir)),d=Le.find(l=>l.dir===a)?.provider;try{let l=xt(n.dir),y=Fp(l,Re("skills",e));cs(y,t,r,d),o.installed.push(n.dir)}catch(l){o.errors.push(`${n.dir}: ${l instanceof Error?l.message:String(l)}`)}}else for(let a of Le){let d=Re(i,a.dir),l=Re(d,"skills",e),y=Re(l,"SKILL.md");if(xr(d)){if(xr(y)&&!n.force){o.skipped.push(a.name);continue}try{cs(l,t,r,a.provider),o.installed.push(a.name)}catch(p){o.errors.push(`${a.name}: ${p instanceof Error?p.message:String(p)}`)}}}return o}function mn(e,t={}){let n={removed:[],errors:[]},r=t.local?process.cwd():ls();for(let o of Le){let i=Re(r,o.dir,"skills",e);if(xr(i))try{Dp(i,{recursive:!0}),n.removed.push(o.name)}catch(a){n.errors.push(`${o.name}: ${a instanceof Error?a.message:String(a)}`)}}return n}function ms(){return Le.map(e=>e.name)}function Je(e){let{name:t,cmd:n}=e;return`---
|
|
1343
1395
|
name: ${t}-tts
|
|
1344
1396
|
description: Text-to-speech generation. Convert text to natural speech with multiple providers (Gemini, ElevenLabs, OpenAI) and voices. Use for voiceovers, narration, accessibility.
|
|
1345
1397
|
---
|
|
@@ -2609,87 +2661,89 @@ ${n} config show --verify # Test API key
|
|
|
2609
2661
|
\`\`\`bash
|
|
2610
2662
|
${n} config set team-id <correct-team-id>
|
|
2611
2663
|
\`\`\`
|
|
2612
|
-
`}var nt=["main","video","presentation","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","config"],
|
|
2613
|
-
${
|
|
2614
|
-
${
|
|
2615
|
-
${
|
|
2616
|
-
${
|
|
2617
|
-
${
|
|
2618
|
-
|
|
2619
|
-
${
|
|
2620
|
-
${
|
|
2621
|
-
${
|
|
2622
|
-
${
|
|
2623
|
-
${
|
|
2624
|
-
${
|
|
2625
|
-
${
|
|
2626
|
-
${
|
|
2627
|
-
${
|
|
2628
|
-
${
|
|
2629
|
-
|
|
2630
|
-
${
|
|
2631
|
-
${
|
|
2632
|
-
$ ${
|
|
2633
|
-
|
|
2634
|
-
${
|
|
2635
|
-
$ ${
|
|
2636
|
-
|
|
2637
|
-
${
|
|
2638
|
-
$ ${
|
|
2639
|
-
|
|
2640
|
-
${
|
|
2641
|
-
$ ${
|
|
2642
|
-
|
|
2643
|
-
${
|
|
2644
|
-
$ ${
|
|
2645
|
-
|
|
2646
|
-
${
|
|
2647
|
-
$ ${
|
|
2648
|
-
`);rt.command("install").description(`Install ${
|
|
2649
|
-
${
|
|
2650
|
-
${
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
${
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
${
|
|
2658
|
-
$ ${
|
|
2659
|
-
${
|
|
2660
|
-
$ ${
|
|
2661
|
-
${
|
|
2662
|
-
$ ${
|
|
2663
|
-
${
|
|
2664
|
-
$ ${
|
|
2665
|
-
${
|
|
2666
|
-
$ ${
|
|
2667
|
-
${
|
|
2668
|
-
$ ${
|
|
2669
|
-
${
|
|
2670
|
-
$ ${
|
|
2671
|
-
${
|
|
2672
|
-
$ ${
|
|
2673
|
-
${
|
|
2674
|
-
$ ${
|
|
2675
|
-
${
|
|
2676
|
-
$ ${
|
|
2677
|
-
|
|
2678
|
-
${
|
|
2679
|
-
|
|
2680
|
-
|
|
2664
|
+
`}var nt=["main","video","presentation","presentation-edit","tts","music","sfx","mix","image","video-search","scrape","branding","config"],un=["standalone","studio"],us={cmd:m.commands[0],pkg:m.packageName,url:m.apiUrl,name:m.name},rt=new Vp("skill").description(`Manage ${m.displayName} skills for AI coding assistants`).addHelpText("after",`
|
|
2665
|
+
${j.bold("Skill Types:")}
|
|
2666
|
+
${j.cyan("main")} Main CLI skill with all capabilities overview
|
|
2667
|
+
${j.cyan("video")} Video-from-scratch pipeline (storyboard \u2192 render)
|
|
2668
|
+
${j.cyan("presentation")} Detailed presentation creation workflow
|
|
2669
|
+
${j.cyan("presentation-edit")} In-app presentation editing (Studio)
|
|
2670
|
+
|
|
2671
|
+
${j.bold("Reference Skills:")}
|
|
2672
|
+
${j.cyan("tts")} Text-to-speech generation (voices, providers, options)
|
|
2673
|
+
${j.cyan("music")} AI music generation (prompts, styles, duration)
|
|
2674
|
+
${j.cyan("sfx")} Sound effects generation (categories, looping, formats)
|
|
2675
|
+
${j.cyan("mix")} Audio mixing (video + voice + music)
|
|
2676
|
+
${j.cyan("image")} Image search and AI generation
|
|
2677
|
+
${j.cyan("video-search")} Stock video search
|
|
2678
|
+
${j.cyan("scrape")} URL content extraction
|
|
2679
|
+
${j.cyan("branding")} Brand profile management
|
|
2680
|
+
${j.cyan("config")} CLI configuration management
|
|
2681
|
+
|
|
2682
|
+
${j.bold("Examples:")}
|
|
2683
|
+
${j.gray("# Install main CLI skill (comprehensive overview)")}
|
|
2684
|
+
$ ${m.commands[0]} skill install main
|
|
2685
|
+
|
|
2686
|
+
${j.gray("# Install video skill")}
|
|
2687
|
+
$ ${m.commands[0]} skill install video
|
|
2688
|
+
|
|
2689
|
+
${j.gray("# Install presentation skill")}
|
|
2690
|
+
$ ${m.commands[0]} skill install presentation
|
|
2691
|
+
|
|
2692
|
+
${j.gray("# Install all skills")}
|
|
2693
|
+
$ ${m.commands[0]} skill install
|
|
2694
|
+
|
|
2695
|
+
${j.gray("# Install to specific directory")}
|
|
2696
|
+
$ ${m.commands[0]} skill install main --dir ~/.claude
|
|
2697
|
+
|
|
2698
|
+
${j.gray("# Show skill content")}
|
|
2699
|
+
$ ${m.commands[0]} skill show main
|
|
2700
|
+
`);rt.command("install").description(`Install ${m.displayName} skills for AI coding assistants`).argument("[type]","Skill type: main, video, presentation, or omit for all").option("-d, --dir <path>","Install to specific directory").option("-g, --global","Install globally (to home directory)",!0).option("-l, --local","Install locally (to current directory)").option("-f, --force","Overwrite existing skill files").option("-m, --mode <mode>","Skill mode: standalone (render to file) or studio (Studio Preview)","standalone").action(async(e,t)=>{t.mode&&!un.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Must be one of: ${un.join(", ")}`),process.exit(1));let n={...us,mode:t.mode},r=[];e&&!nt.includes(e)&&(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1));let o=await at();o.source==="snapshot"&&(M(`Live capability catalog unavailable (${o.reason??"unknown reason"}) \u2014 generating from the snapshot baked into this CLI.`),console.log(j.gray(` Run \`${m.commands[0]} login\` then re-run with --force to regenerate from the live catalog.`)));let i=[...rs(n,o,{branding:et(n)}),{name:"tts",content:Je(n)},{name:"music",content:ze(n)},{name:"sfx",content:Xe(n)},{name:"mix",content:He(n)},{name:"image",content:Ye(n)},{name:"video-search",content:Qe(n)},{name:"scrape",content:Ze(n)},{name:"config",content:tt(n)}];(!e||e==="main")&&r.push({name:m.name,content:an(n,o),references:i}),(!e||e==="video")&&r.push({content:cn(n,o),name:`${m.name}-video`,references:is(n,o)}),(!e||e==="presentation")&&r.push({name:`${m.name}-presentation`,content:dn(n)}),(!e||e==="presentation-edit")&&r.push({name:`${m.name}-presentation-edit`,content:sn(n)}),e==="tts"&&r.push({name:`${m.name}-tts`,content:Je(n)}),e==="music"&&r.push({name:`${m.name}-music`,content:ze(n)}),e==="sfx"&&r.push({name:`${m.name}-sfx`,content:Xe(n)}),e==="mix"&&r.push({name:`${m.name}-mix`,content:He(n)}),e==="image"&&r.push({name:`${m.name}-image`,content:Ye(n)}),e==="video-search"&&r.push({name:`${m.name}-video-search`,content:Qe(n)}),e==="scrape"&&r.push({name:`${m.name}-scrape`,content:Ze(n)}),e==="branding"&&r.push({name:`${m.name}-branding`,content:et(n)}),e==="config"&&r.push({name:`${m.name}-config`,content:tt(n)}),console.log();for(let a of r){g(`Installing ${a.name}...`);let d=ln(a.name,a.content,{dir:t.dir,local:t.local,force:t.force},a.references);if(d.installed.length>0&&(x(`${a.name} installed successfully`),R(" Installed to",d.installed.join(", "))),d.skipped.length>0&&(g(` Skipped (already exists): ${d.skipped.join(", ")}`),console.log(j.gray(" Use --force to overwrite"))),d.errors.length>0)for(let l of d.errors)s(` ${l}`);d.installed.length===0&&d.skipped.length===0&&d.errors.length===0&&(g(" No supported AI coding assistants detected"),console.log(j.gray(` Supported editors: ${ms().join(", ")}`)),console.log(j.gray(" Use --dir <path> to install to a specific directory"))),console.log()}});rt.command("show").description("Display skill content").argument("[type]","Skill type (default: main)").option("-m, --mode <mode>","Skill mode: standalone or studio","standalone").action(async(e="main",t)=>{t.mode&&!un.includes(t.mode)&&(s(`Invalid mode: ${t.mode}. Must be one of: ${un.join(", ")}`),process.exit(1));let n={...us,mode:t.mode},r=await at(),i={main:()=>an(n,r),video:()=>cn(n,r),presentation:()=>dn(n),"presentation-edit":()=>sn(n),tts:()=>Je(n),music:()=>ze(n),sfx:()=>Xe(n),mix:()=>He(n),image:()=>Ye(n),"video-search":()=>Qe(n),scrape:()=>Ze(n),branding:()=>et(n),config:()=>tt(n)}[e];i?console.log(i()):(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1))});rt.command("uninstall").description(`Remove ${m.displayName} skills from AI coding assistants`).argument("[type]","Skill type: main, video, presentation, or omit for all").option("-g, --global","Uninstall globally (from home directory)",!0).option("-l, --local","Uninstall locally (from current directory)").action(async(e,t)=>{let n=[];e&&!nt.includes(e)&&(s(`Invalid skill type: ${e}. Must be one of: ${nt.join(", ")}`),process.exit(1)),(!e||e==="main")&&n.push(m.name),(!e||e==="video")&&n.push(`${m.name}-video`),(!e||e==="presentation")&&n.push(`${m.name}-presentation`),(!e||e==="presentation-edit")&&n.push(`${m.name}-presentation-edit`),(!e||e==="tts")&&n.push(`${m.name}-tts`),(!e||e==="music")&&n.push(`${m.name}-music`),(!e||e==="sfx")&&n.push(`${m.name}-sfx`),(!e||e==="mix")&&n.push(`${m.name}-mix`),(!e||e==="image")&&n.push(`${m.name}-image`),(!e||e==="video-search")&&n.push(`${m.name}-video-search`),(!e||e==="scrape")&&n.push(`${m.name}-scrape`),(!e||e==="branding")&&n.push(`${m.name}-branding`),(!e||e==="config")&&n.push(`${m.name}-config`),console.log();for(let r of n){let o=mn(r,{local:t.local});if(o.removed.length>0?(x(`${r} uninstalled`),R(" Removed from",o.removed.join(", "))):g(` ${r} not found`),o.errors.length>0)for(let i of o.errors)M(` Failed to remove: ${i}`)}console.log()});import{Command as Gp}from"commander";import kt from"chalk";var ps=new Gp("templates").description("List slide design templates (use with `create --template <id>`)").argument("[search]","Filter templates by name, description, or category").option("-f, --format <format>","Output format (table, json)",b("--format",["table","json"]),"table").option("--limit <n>","Maximum templates to list","25").action(async(e,t)=>{await O();try{let n=Number.parseInt(t.limit??"25",10),{templates:r}=await co(e,Number.isFinite(n)?n:25);if(r.length===0){t.format==="json"?console.log(JSON.stringify([])):g("No templates found");return}if(t.format==="json"){console.log(JSON.stringify(r,null,2));return}for(let o of r){let i=[o.isDefault?kt.green("default"):null,o.category??null,o.recommendedModes?.length?`modes: ${o.recommendedModes.join("/")}`:null].filter(Boolean).join(" \xB7 ");console.log(`${kt.bold(o.name)} ${kt.gray(o.id)}${i?`
|
|
2701
|
+
${kt.gray(i)}`:""}`)}console.log(),console.log(kt.gray(`Use one with: ${m.commands[0]} create "<topic>" --template <id>`))}catch(n){s(n instanceof Error?n.message:String(n)),process.exit(n.exitCode??1)}});import{Command as Bp}from"commander";import kr from"chalk";var gs=new Bp("whoami").description("Show current user and team information").option("-f, --format <format>","Output format (human, json)",b("--format",["human","json"]),"human").action(async e=>{await O();try{let t=await ye();if(Rn(),e.format==="json"){console.log(JSON.stringify(t,null,2));return}ie("User"),console.log(),R("Email",t.user.email),t.user.username&&R("Username",t.user.username),(t.user.firstName||t.user.lastName)&&R("Name",[t.user.firstName,t.user.lastName].filter(Boolean).join(" "));let n=t.authType==="apiKey"?"API Key":t.authType==="oauth"?"OAuth":"Session";if(R("Auth Type",n),t.currentTeam&&(console.log(),ie("Current Team"),console.log(),R("ID",t.currentTeam.id),R("Name",t.currentTeam.name),R("Plan",t.currentTeam.planName),R("Role",t.currentTeam.isOwner?"Owner":"Member")),t.teams.length>1){console.log(),ie("All Teams"),console.log();for(let r of t.teams){let o=r.isCurrent?kr.green(" (current)"):"";console.log(` ${kr.bold(r.name)}${o}`),console.log(kr.gray(` ID: ${r.id} | Plan: ${r.planName} | Role: ${r.role}`))}}console.log()}catch(t){s(t instanceof Error?t.message:String(t)),process.exit(t.exitCode??1)}});function fs(e){return e[0]==="--"?e.slice(1):e}import Cr from"chalk";function Ir(e){e.configureOutput({outputError:(t,n)=>{n(Cr.red(t));let r=/unknown option '(-{1,2}[^'\s=]+)/.exec(t);if(!r)return;let o=Kp(e,r[1]);o&&n(Cr.yellow(`Did you mean '${o}'?
|
|
2702
|
+
`)),n(Cr.gray(`Run '${Wp(e)} --help' to see the accepted options.
|
|
2703
|
+
`))}});for(let t of e.commands)Ir(t)}function Wp(e){let t=[],n=e;for(;n;)t.unshift(n.name()),n=n.parent;return t.join(" ")}function Kp(e,t){let n,r=Number.POSITIVE_INFINITY;for(let i of e.options)if(!i.hidden)for(let a of[i.short,i.long]){if(!a)continue;let d=Rr(t,a);d<r&&(r=d,n=i.flags)}let o=t.startsWith("--")?2:1;return n!==void 0&&r<=o?n:void 0}function Rr(e,t){if(e===t)return 0;if(e.length===0)return t.length;if(t.length===0)return e.length;let n=Array.from({length:t.length+1},(r,o)=>o);for(let r=1;r<=e.length;r++){let o=[r];for(let i=1;i<=t.length;i++){let a=e[r-1]===t[i-1]?0:1;o[i]=Math.min(o[i-1]+1,n[i]+1,n[i-1]+a)}n=o}return n[t.length]}var zp="0.3.21",W=new Jp,N=m.commands[0];W.name(N).description(`${m.displayName} CLI \u2014 presentations, videos, avatars, audio, branding, media and research`).version(zp,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output");W.addCommand(Mo);Ya(W);W.addCommand(ei);W.addCommand(Zo);W.addCommand(ps);W.addCommand(Yo);W.addCommand(Jo);W.addCommand(gs);W.addCommand(ii);W.addCommand(ai);W.addCommand(Ko);W.addCommand(rt);W.addCommand(Mt);var hs=Ho();hs.commands.length>0&&W.addCommand(hs);function Xp(e){let t=e.toLowerCase(),n=t.length<=4?1:2,r,o=Number.POSITIVE_INFINITY;for(let i of W.commands)for(let a of[i.name(),...i.aliases()]){let d=Rr(t,a.toLowerCase());d<o&&(o=d,r=i.name())}return r!==void 0&&o<=n?r:void 0}W.on("command:*",e=>{let t=String(e[0]);console.error(G.red(`Error: Unknown command '${t}'`)),console.error();let n=Xp(t);n&&console.error(`Did you mean '${n}'?`),console.error(`Run '${N} --help' to see available commands.`),console.error(`Run '${N} capabilities' for the full list of callable capabilities.`),process.exit(1)});W.addHelpText("after",`
|
|
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
|
|
2681
2735
|
and generated footage \u2014 no deck involved.
|
|
2682
2736
|
|
|
2683
|
-
${
|
|
2684
|
-
Run '${
|
|
2737
|
+
${G.bold("Authentication:")}
|
|
2738
|
+
Run '${N} login' to authenticate (recommended).
|
|
2685
2739
|
Or set CC_SLIDES_API_KEY environment variable for API key auth.
|
|
2686
2740
|
|
|
2687
|
-
${
|
|
2741
|
+
${G.bold("Note:")}
|
|
2688
2742
|
The command list above is not always complete: feature-flag-gated commands
|
|
2689
|
-
(the '${
|
|
2690
|
-
and '${
|
|
2691
|
-
'${
|
|
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.
|
|
2692
2746
|
|
|
2693
|
-
${
|
|
2694
|
-
${
|
|
2695
|
-
`);
|
|
2747
|
+
${G.bold("More Info:")}
|
|
2748
|
+
${G.blue(m.docsUrl)}
|
|
2749
|
+
`);Ir(W);W.parse(fs(process.argv.slice(2)),{from:"user"});
|