videobook 0.2.2 → 0.2.3
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/CHANGELOG.md +25 -0
- package/README.md +7 -8
- package/dist/book-manager.js +40 -2
- package/dist/env-secrets.js +1 -0
- package/dist/image-edit-models.js +1 -0
- package/dist/media/catalog.js +13 -0
- package/dist/media/cost.js +79 -6
- package/dist/media/json-schema.js +7 -0
- package/dist/media/ref-fields.js +11 -3
- package/dist/media/request.js +49 -0
- package/dist/provider-usage.js +19 -7
- package/dist/tools/estimate-cost.js +4 -4
- package/dist/tools/provider-key-status.js +2 -0
- package/package.json +13 -13
- package/ui/assets/{alive-captions-C48o6dfv.js → alive-captions-4QySEGdt.js} +1 -1
- package/ui/assets/confirm-bodies-Bw818V9J.js +1 -0
- package/ui/assets/{fullscreen-4m0qtZ7w.js → fullscreen-CzTnPPG5.js} +1 -1
- package/ui/assets/{goal-ui-2pUWP_B2.js → goal-ui-CosrK_ko.js} +1 -1
- package/ui/assets/index-C9xjFEGL.js +37 -0
- package/ui/assets/{inspector-CnKySYc5.js → inspector-BN2fezh4.js} +1 -1
- package/ui/assets/{jobs-ui-lRoS1MbL.js → jobs-ui-C4Wgy6I1.js} +1 -1
- package/ui/assets/{music-video-BQnnPp-X.js → music-video-BSj8SgbQ.js} +1 -1
- package/ui/assets/{ui-OHFUngrc.js → ui-Cpr6zMTA.js} +1 -1
- package/ui/assets/{videobook-DZ58pKW5.js → videobook-B5G0jMoi.js} +13 -13
- package/ui/index.html +8 -8
- package/ui/assets/confirm-bodies-aq6Az8Md.js +0 -1
- package/ui/assets/index-DmDH4gYr.js +0 -37
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/confirm-bodies-Bw818V9J.js","assets/vendor-react-Dj7D1fD4.js","assets/videobook-B5G0jMoi.js","assets/vendor-yctIZ9Dz.js","assets/vendor-mcp-DQ7EusT9.js","assets/vendor-D2rfiZ5j.css","assets/vendor-remotion-CH1HXrlc.js","assets/ui-Cpr6zMTA.js","assets/vendor-icons-CGqhCIXV.js","assets/vendor-flow-zBavaNEW.js","assets/vendor-flow-BnuhLJ6X.css","assets/ui-Oirr9VOf.css","assets/confirm-bodies-DrMhaXC6.css","assets/music-video-BSj8SgbQ.js","assets/music-video-DPaiKKEq.css","assets/alive-captions-4QySEGdt.js","assets/alive-captions-BWb5nLKj.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{a as f,j as C,d as af}from"./vendor-react-Dj7D1fD4.js";import{i as lf,S as cf,b as Pi,c as df}from"./vendor-flow-zBavaNEW.js";import{g as Os}from"./vendor-mcp-DQ7EusT9.js";import{y as ct,z as dt,E as uf,q as Mi,F as ff,H as mf,J as pf,K as gf,L as kf,T as bf,O as wf,Q as hf,U as vf,n as yf,W as If,o as Cf,l as Sf,m as xf,X as Ef,Y as _f,Z as Af,_ as Rf,$ as Pf,a0 as Mf,a1 as Tf,a2 as Ti,p as jf,a3 as $f,a4 as qf,a5 as Nf}from"./ui-Cpr6zMTA.js";import{es as Lf,et as Ff,eu as ji,ev as $i,ew as bs,ex as Df,cB as Xn,ey as Of,ez as Vf,eA as Gf,eB as Wf,eC as Uf,eD as Bf,eE as Hf,bG as A,bS as ae,eF as zf,eG as qi,eH as eo,eI as Kf,cI as Ni,eJ as Li,eK as Xf,dl as Jf,dp as Qf,eL as Fi,eM as Yf,eN as Zf,eO as em,eP as tm,eQ as Di,eR as om,eS as nm,eT as rm,a as sm,eU as am,eV as im,eW as lm,eX as cm,eY as dm,bI as D,co as Oi,eZ as um,e_ as fm,e$ as mm,f0 as pm,f1 as Nt,f2 as gm,f3 as km,f4 as bm,f5 as Vi,f6 as ut,f7 as O,f8 as M,f9 as ws,fa as Gi,fb as wm,fc as hm,fd as vm,fe as pe,ff as to,fg as Wi,fh as ym,fi as Im,fj as Cm,fk as Lt,fl as Sm,fm as xm,bz as Ft,fn as Em,fo as Ui,fp as Jn,fq as _m,fr as Am,fs as Bi,ft as Rm,fu as Pm,fv as Mm,fw as Hi,fx as Tm,fy as jm,fz as $m,fA as dn,fB as qm,fC as zi,fD as Nm,dy as Lm,fE as Qn,dz as Fm,dA as Dm,fF as Ki,fG as Om,fH as hs,fI as Vm,fJ as Gm,fK as Wm,fL as Um,db as Bm,bQ as Hm,fM as It,a8 as un,fN as zm,de as Xi,fO as Km,fP as Xm,fQ as vs,fR as Ji,fS as Qi,fT as Ke,fU as Jm,fV as Qm,O as Ym,fW as Zm,fX as ep,fY as tp,fZ as Yi,f_ as ys,f$ as Zi,g0 as Is,g1 as Cs,g2 as op,g3 as np,g4 as rp,g5 as sp,g6 as ap,g7 as el,g8 as ip,g9 as lp,dL as Yn,bB as cp,bA as dp,dx as up,ga as fp,gb as mp,gc as pp,gd as tl,ge as gp,gf as kp,gg as bp,cl as wp,cm as hp,am as vp,cj as ol,gh as nl,c0 as yp,cp as Ip,gi as Cp,gj as Sp,gk as Ss,gl as xp,gm as Ep,b7 as rl,gn as xs,go as Mo,bJ as Es,bE as oo,a9 as _p,gp as sl,gq as Ap,gr as _s,gs as Rp,gt as no,gu as Pp,gv as Mp,gw as Tp,gx as jp,gy as $p,gz as qp,gA as Bl,gB as As,gC as Np,gD as Lp,gE as Fp,c5 as Rs,gF as al,gG as Dp,gH as Op,gI as Vp,gJ as Gp,gK as Wp,gL as Up,gM as Bp,gN as Hp,gO as il,bX as Dt,gP as zp,gQ as Kp,gR as ll,aa as cl,b1 as Xp,gS as Jp,br as Qp,gT as Yp,dd as Zp,gU as eg,gV as tg,gW as og,gX as dl,gY as ng,gZ as rg,g_ as sg,g$ as Zn,h0 as ag,h1 as Ps,h2 as ig,aL as lg,h3 as cg,aJ as dg,h4 as ug,h5 as fg,h6 as Ms,h7 as mg,h8 as pg,h9 as ul,ha as gg,hb as fl,d3 as kg,hc as ml,hd as bg,he as Ts,hf as wg,hg as er,hh as hg,hi as vg,hj as yg,hk as Ig,hl as Cg,hm as Sg,hn as xg,b0 as Eg,aH as _g,ho as Ag,hp as Rg,hq as Pg,hr as Mg,hs as pl,ht as fn,hu as js,hv as Tg,hw as jg,hx as $g,hy as qg,hz as Ng,hA as Lg,hB as Fg,hC as Dg,hD as Og,hE as Vg,hF as gl,hG as Gg,hH as kl,hI as Wg,hJ as Ug,hK as tr,hL as Bg,hM as Hg,hN as zg,hO as Kg,hP as Xg,hQ as Jg,hR as bl,hS as Qg,hT as Yg,hU as Zg,hV as wl,hW as ek,hX as hl,hY as tk,hZ as vl,h_ as ok,h$ as yl,i0 as or,i1 as Il,i2 as nr,i3 as Cl,d4 as nk,i4 as rk,N as sk,D as ak,i5 as ik,i6 as $s,i7 as lk,i8 as ck,i9 as dk,ia as uk,ib as fk,ic as mk,id as pk,ie as gk,ig as kk,ih as bk,ii as Sl,ij as wk,ik as hk,il as vk,im as yk,io as Ik,ip as Ck,iq as xl,ir as Po,is as Sk,it as xk,Y as Ek,iu as _k,iv as Ak,iw as Rk,ix as Pk,iy as Mk,iz as Tk,iA as jk,iB as $k}from"./videobook-B5G0jMoi.js";import{a as qk,G as Nk,P as Lk,C as Fk,S as Dk,b as Ok,R as El,N as Vk}from"./confirm-bodies-Bw818V9J.js";import{i as Gk,A as Hl,n as Se,b as U,m as _l,v as Al,x as rr,y as Ct,Y as Wk,f as lr,s as Uk}from"./vendor-yctIZ9Dz.js";import{J as Bk}from"./jobs-ui-C4Wgy6I1.js";import{N as Hk}from"./inspector-BN2fezh4.js";import{N as zk}from"./fullscreen-CzTnPPG5.js";import{G as Kk,a as Xk,b as Jk,c as Qk}from"./goal-ui-CosrK_ko.js";import{ar as Yk,z as Rl,H as Zk,B as eb,at as tb,a8 as ob,b as nb,au as rb}from"./vendor-icons-CGqhCIXV.js";import"./vendor-remotion-CH1HXrlc.js";(function(){const g=document.createElement("link").relList;if(g&&g.supports&&g.supports("modulepreload"))return;for(const I of document.querySelectorAll('link[rel="modulepreload"]'))k(I);new MutationObserver(I=>{for(const x of I)if(x.type==="childList")for(const j of x.addedNodes)j.tagName==="LINK"&&j.rel==="modulepreload"&&k(j)}).observe(document,{childList:!0,subtree:!0});function p(I){const x={};return I.integrity&&(x.integrity=I.integrity),I.referrerPolicy&&(x.referrerPolicy=I.referrerPolicy),I.crossOrigin==="use-credentials"?x.credentials="include":I.crossOrigin==="anonymous"?x.credentials="omit":x.credentials="same-origin",x}function k(I){if(I.ep)return;I.ep=!0;const x=p(I);fetch(I.href,x)}})();const we=d=>d.startsWith("@")?d.slice(1):d;function cr(d){const g=d.trim();if(g.length<2)return g;const p=g[0],k=g[g.length-1];return(p==='"'||p==="'")&&p===k?g.slice(1,-1).trim():g}const sb=/^[a-z0-9][a-z0-9-]*$/i;function ab(d){const g=d.asset_id;if(typeof g!="string"||!g.trim())throw new Error("/keywords requires a video cell or asset");const p=we(g.trim()),k=d.inputs;if(k===void 0)return{asset_id:p};if(!Array.isArray(k)||!k.every(j=>typeof j=="string"))throw new Error("/keywords inputs must be words");const I=k.map(j=>j.trim()).filter(Boolean);if(I.length===0)return{asset_id:p};const x=ib(I);return x?{asset_id:p,...x}:{asset_id:p,keywords:I}}function ib(d){const g=d[0]?.toLowerCase()??"",p=d.slice(1);if(["off","false","no","0"].includes(g))return p.length===0?{enabled:!1}:null;if(!["on","true","yes","1"].includes(g)||p.length>2)return null;if(p.length===0)return{enabled:!0};const k=Number(p[0]);if(!Number.isInteger(k)||k<1||k>20)return null;if(p.length===1)return{enabled:!0,max_keywords:k};const I=Number(p[1]);return!Number.isFinite(I)||I<.8||I>5?null:{enabled:!0,max_keywords:k,linger_seconds:I}}function lb(d){const g=d.toLowerCase();return g==="16:9"||g==="landscape"?"16:9":g==="9:16"||g==="portrait"?"9:16":g==="1:1"||g==="square"?"1:1":null}function cb(d){const g=d.map(we),p=[];let k;for(const I of g){const x=lb(I);if(x){if(k)throw new Error("/outroqr accepts only one aspect ratio");k=x;continue}if(!sb.test(I))throw new Error(`Unrecognized /outroqr input: ${I}`);if(p.push(I),p.length>4)throw new Error("/outroqr accepts at most 4 QR images")}if(p.length===0)throw new Error("/outroqr requires at least one QR image cell or asset");return{qr_image_refs:p,...k?{aspect_ratio:k}:{}}}function db(d){const g=d.asset_id,p=d.timestamp,k=d.type,I=d.description;if(typeof g!="string"||!g.trim())throw new Error("/apply-sfx requires a video cell or asset");const x=we(g.trim());if(typeof p!="string"&&typeof p!="number")throw new Error("/apply-sfx requires a timestamp");const j=typeof p=="number"?p:nt(p,"/apply-sfx");if(!Number.isFinite(j)||j<0)throw new Error("/apply-sfx timestamp must be 0 or later");if(typeof k!="string"||!k.trim())throw new Error("/apply-sfx requires an effect type");if(typeof I!="string"||!I.trim())throw new Error("/apply-sfx requires an effect description");return{asset_id:x,sfx:[{timestamp:j,type:k.trim(),description:I.trim()}]}}function nt(d,g){const k=d.trim().replace(/s$/i,"").split(":");if(k.length===1){const x=Number(k[0]);if(Number.isFinite(x)&&x>=0)return x;throw new Error(`Invalid ${g} timestamp: ${d}`)}if(k.length!==2&&k.length!==3)throw new Error(`Invalid ${g} timestamp: ${d}`);if(!k.every(x=>/^\d+(?:\.\d+)?$/.test(x)))throw new Error(`Invalid ${g} timestamp: ${d}`);const I=k.map(Number);return k.length===2?I[0]*60+I[1]:I[0]*3600+I[1]*60+I[2]}function ub(d){const g=d.asset_id,p=d.range,k=d.factor;if(typeof g!="string"||!g.trim())throw new Error("/timewarp requires a video cell or asset");const I=we(g.trim());if(typeof p!="string")throw new Error("/timewarp requires a <start>-<end> range");const x=/^(.+)-(.+)$/.exec(p.trim());if(!x)throw new Error("/timewarp requires a <start>-<end> range");const j=nt(x[1],"/timewarp"),i=nt(x[2],"/timewarp");if(j>=i)throw new Error("/timewarp start must be before end");if(typeof k!="string"&&typeof k!="number")throw new Error("/timewarp requires a stretch factor");const K=String(k).trim();if(!/^\d+(?:\.\d+)?x?$/i.test(K))throw new Error(`Invalid /timewarp stretch factor: ${K}`);const c=Number(K.replace(/x$/i,""));if(!Number.isFinite(c)||c<.25||c>4)throw new Error("/timewarp stretch factor must be between 0.25x and 4x");if(c===1)throw new Error("/timewarp stretch factor 1x is a no-op");return{asset_id:I,start_seconds:j,end_seconds:i,stretch_factor:c}}function fb(d){const g=d.trim(),p=g[0],k=g[g.length-1],I=p==='"'||p==="'";if(I||(k==='"'||k==="'")){if(!I||p!==k||g.length<2)throw new Error(`/sync-audio has mismatched quotes: ${d}`);return g.slice(1,-1).trim()}return g}function mb(d){const p=d.trim().replace(/s$/i,"").split(":");return p.length<1||p.length>3?!1:p.every(k=>/^\d+(?:\.\d+)?$/.test(k))}function pb(d){const g=d.trim(),p=g.startsWith('"')||g.startsWith("'"),k=fb(d);if(!k)throw new Error("/sync-audio anchor target cannot be empty");return!p&&mb(k)?{audio_seconds:nt(k,"/sync-audio")}:{audio_cue:k}}function gb(d){const g=d.asset_id,p=d.mappings;if(typeof g!="string"||!g.trim())throw new Error("/sync-audio requires a video cell or asset");const k=we(g.trim());if(typeof p!="string"||!p.trim())throw new Error("/sync-audio requires at least one video-time=audio-target mapping");const I=p.split(";"),x=[];for(const j of I){const i=j.indexOf("=");if(i<=0||i!==j.lastIndexOf("="))throw new Error(`Invalid /sync-audio mapping: ${j.trim()}`);const K=j.slice(0,i).trim(),c=j.slice(i+1).trim();if(!K||!c)throw new Error(`Invalid /sync-audio mapping: ${j.trim()}`);const xe=nt(K,"/sync-audio"),z=x[x.length-1];if(z&&xe<=z.video_seconds)throw new Error("/sync-audio video timestamps must be strictly increasing");x.push({video_seconds:xe,...pb(c)})}return{asset_id:k,anchors:x}}function kb(d){const g=d.asset_id;if(typeof g!="string"||!g.trim())throw new Error("Trim command requires an asset ID");const p=we(g.trim());let k,I,x,j;const i=d.trim_start!==void 0?d.trim_start:d.start;i!=null&&i!==""&&(typeof i=="number"?k=i:typeof i=="string"&&(k=nt(i,"/trim")));const K=d.trim_end!==void 0?d.trim_end:d.end;if(K!=null&&K!==""&&(typeof K=="number"?I=K:typeof K=="string"&&(I=nt(K,"/trim"))),d.cut_start!==void 0&&d.cut_start!==null&&d.cut_start!==""&&(typeof d.cut_start=="number"?x=d.cut_start:typeof d.cut_start=="string"&&(x=nt(d.cut_start,"/trim"))),d.cut_end!==void 0&&d.cut_end!==null&&d.cut_end!==""&&(typeof d.cut_end=="number"?j=d.cut_end:typeof d.cut_end=="string"&&(j=nt(d.cut_end,"/trim"))),k!==void 0&&(!Number.isFinite(k)||k<0))throw new Error("trim_start must be >= 0");if(I!==void 0&&(!Number.isFinite(I)||I<0))throw new Error("trim_end must be >= 0");if(k!==void 0&&I!==void 0&&k>=I)throw new Error("trim_start must be less than trim_end");if(x!==void 0&&(!Number.isFinite(x)||x<0))throw new Error("cut_start must be >= 0");if(j!==void 0&&(!Number.isFinite(j)||j<0))throw new Error("cut_end must be >= 0");if(x!==void 0&&j!==void 0&&x>=j)throw new Error("cut_start must be less than cut_end");return{asset_id:p,...k!==void 0&&{trim_start:k},...I!==void 0&&{trim_end:I},...x!==void 0&&{cut_start:x},...j!==void 0&&{cut_end:j}}}function bb(d){const g=d.asset_id;if(typeof g!="string"||!g.trim())throw new Error("/apply-cuts requires a video cell or asset");const p=we(g.trim()),k=d.cuts;if(!k)throw new Error("/apply-cuts requires at least one cut range");const I=Array.isArray(k)?k:[k];if(I.length===0)throw new Error("/apply-cuts requires at least one cut range");const x=[];for(const j of I){if(typeof j=="object"&&j!==null&&"cut_start"in j&&"cut_end"in j){const X=Number(j.cut_start),Ee=Number(j.cut_end);if(!Number.isFinite(X)||!Number.isFinite(Ee)||X>=Ee||X<0)throw new Error(`Invalid cut range object: ${JSON.stringify(j)}`);x.push({cut_start:X,cut_end:Ee});continue}if(typeof j!="string")throw new Error(`/apply-cuts range must be string or object, got: ${typeof j}`);const i=j.trim(),K=i.indexOf("-");if(K<=0||K===i.length-1)throw new Error(`Invalid /apply-cuts range format: ${i}. Expected <start>-<end>`);const c=i.slice(0,K),xe=i.slice(K+1),z=nt(c,"/apply-cuts"),Xe=nt(xe,"/apply-cuts");if(z>=Xe)throw new Error(`/apply-cuts start (${c}) must be before end (${xe})`);x.push({cut_start:z,cut_end:Xe})}return{asset_id:p,cuts:x}}function wb(d){const g=d.asset_id;if(typeof g!="string"||!g.trim())throw new Error("/translate-subs requires an asset ID");const p=we(g.trim()),k=d.language!==void 0?d.language:d.target_language;if(typeof k!="string"||!k.trim())throw new Error("/translate-subs requires a target language code");const I=k.trim().toLowerCase();if(!/^[a-z]{2}$/.test(I))throw new Error("/translate-subs target language must be a two-letter ISO code (e.g. es, fr, de)");return{asset_id:p,language:I}}const Pl=new RegExp(`^@?${Hl}$`,"iu"),hb=new Set(["ig","tiktok","youtube"]),Ml=new Set(["normal","line","dsj","bubble","func"]),vb=new Set(["landscape","portrait","square"]),yb=/^(?:vid|img|aud|asset|final|script)-[a-z0-9-]+$/i,Ib=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Cb(d){const g={...d},p=typeof d.platform=="string"?d.platform.trim():"",k=typeof d.custom_prompt=="string"?d.custom_prompt.trim():"",I=p.toLowerCase();if(I&&hb.has(I))return g.platform=I,k?g.custom_prompt=k:delete g.custom_prompt,g;delete g.platform;const x=[p,k].filter(Boolean).join(" ");return x?g.custom_prompt=x:delete g.custom_prompt,g}function Sb(d){const g={...d},p=typeof d.value=="string"?d.value.trim():"",k=typeof d.style=="string"?d.style.trim():"";if(!p&&!k)return g;const I=k.split(/\s+/).filter(Boolean),x=I[I.length-1]?.toLowerCase()??"";return I.length===1&&Ml.has(x)?(g.style=x,p&&(g.value=p),g):I.length>1&&Ml.has(x)?(g.style=x,g.value=[p,I.slice(0,-1).join(" ")].filter(Boolean).join(" "),g):(delete g.style,g.value=[p,k].filter(Boolean).join(" "),g)}function xb(d){const g=we(d);return d.startsWith("@")||Gk(g)||Ib.test(g)||yb.test(g)}function Eb(d){const g=d.trim().split(/\s+/).filter(Boolean);if(g.length===0)return{};const[p,...k]=g;return p&&xb(p)?{asset_ref:we(p),...k.length>0?{text:k.join(" ")}:{}}:{text:g.join(" ")}}const _b={qr_outro:d=>{const g=d.inputs;if(!Array.isArray(g)||!g.every(k=>typeof k=="string"))throw new Error("/outroqr inputs are required");const p={...d};return delete p.inputs,{...p,...cb(g)}},keywords:d=>{const g=ab(d),p={...d};return delete p.inputs,{...p,...g}},change_speed:d=>{const g={...d};if(!("speed"in g))return g;const p=g.speed;delete g.speed;const k=typeof p=="number"?String(p):typeof p=="string"?p.trim():"",I="Usage: /speed @asset <0.25-4 or 8.32s>";if(!k)throw new Error(I);if(/s$/i.test(k)){const j=Number(k.slice(0,-1));if(!Number.isFinite(j)||j<=0)throw new Error(I);return g.target_duration_seconds=j,g}const x=Number(k.replace(/x$/i,""));if(!Number.isFinite(x))throw new Error(I);return g.speed=x,g},duplicate:d=>{const g={...d},p=typeof d.new_name=="string"?d.new_name.trim():"",k=typeof d.destination=="string"?d.destination.trim():"";if(delete g.new_name,delete g.destination,Pl.test(k))return g.destination=we(k).toLowerCase(),p&&(g.new_name=cr(p)),g;const I=[...p.split(/\s+/),k].filter(Boolean),x=I.filter(j=>Pl.test(j));if(x.length>1)throw new Error("Usage: /duplicate @asset [@cell] [name]");if(x.length===1){g.destination=we(x[0]).toLowerCase();const j=I.filter(i=>i!==x[0]).join(" ");return j&&(g.new_name=cr(j)),g}return I.length>0&&(g.new_name=cr(I.join(" "))),g},timewarp:d=>{const g=ub(d),p={...d};return delete p.range,delete p.factor,{...p,...g}},sync_audio:d=>{const g=gb(d),p={...d};return delete p.mappings,{...p,...g}},apply_sfx:d=>{const g=db(d),p={...d};return delete p.timestamp,delete p.type,delete p.description,{...p,...g}},rewrite_script:d=>Cb(d),qrbtf:d=>Sb(d),trim:d=>{const g=kb(d),p={...d};return delete p.start,delete p.end,{...p,...g}},apply_cuts:d=>{const g=bb(d),p={...d};return delete p.cuts,{...p,...g}},translate_subtitles:d=>{const g=wb(d),p={...d};return delete p.target_language,{...p,...g}}};function Tl(d){const g=d.orientation;if(typeof g!="string")return d;const p=g.trim().toLowerCase();if(!p){const k={...d};return delete k.orientation,k}if(!vb.has(p))throw new Error("Orientation must be landscape, portrait, or square");return g===p?d:{...d,orientation:p}}function Ab(d,g){if(!d)return Tl(g);const p=_b[d];if(!p)throw new Error(`Unknown command adapter: ${d}`);return Tl(p(g))}const Rb=new Set(["target_duration_seconds","transition_seconds","overlap","timestamp","start","duration"]);function Pb(d,g){const p=we(d),I=(Rb.has(g)?/^(\d+(?:\.\d+)?)(?:s|sec|secs|second|seconds)$/i.exec(p):null)??(g==="boost"?/^(\d+(?:\.\d+)?)x$/i.exec(p):null)??(g==="volume"?/^(\d+(?:\.\d+)?)%$/i.exec(p):null),x=Number(I?.[1]??p);return Number.isFinite(x)?x:p}function zl(d){const g=we(d).toLowerCase();return["true","1","yes","y","on"].includes(g)?!0:["false","0","no","n","off"].includes(g)?!1:we(d)}function Mb(d,g){if(g.type==="number")return Pb(d,g.name);if(g.type==="boolean"){const p=zl(d);if(typeof p!="boolean")throw new Error(`${g.name} must be on or off`);return p}return we(d)}function jl(d,g){if(g.type!=="boolean")return null;const p=we(d).toLowerCase();return p===g.name.toLowerCase()||["true","yes","y","on"].includes(p)?!0:["false","no","n","off"].includes(p)?!1:null}function St(d,g){if(!d||g.length===0)return{};const p=d.split(/\s+/).filter(i=>i.length>0),k={},I=[];for(const i of p){const K=g.find(c=>c.type==="boolean"&&!(c.name in k)&&jl(i,c)!==null);if(K){k[K.name]=jl(i,K);continue}I.push(i)}const x=g[g.length-1];let j=I.length;if(x?.type==="boolean"&&I.length>1&&I.length<g.length){const i=zl(I[I.length-1]);typeof i=="boolean"&&(k[x.name]=i,j-=1)}for(let i=0;i<g.length&&!(i>=j);i++){const K=g[i];if(K.name in k)continue;const c=i===g.length-1;if(c&&K.type==="string[]")k[K.name]=I.slice(i,j).map(we);else if((c||K.consumeRest)&&K.type==="string"){let xe=I.slice(i,j);if(K.name==="new_name"&&xe.length>1&&xe[0]==="to"&&(xe=xe.slice(1)),k[K.name]=cr(we(xe.join(" "))),K.consumeRest)break}else k[K.name]=Mb(I[i],K)}return k}function $l(d,g,p){const k=g.toLowerCase(),I=d.filter(c=>c.command.toLowerCase()===k),x=I.length>0?I:d.filter(c=>c.aliases?.some(xe=>xe.toLowerCase()===k));if(x.length<=1)return x[0];const j=p.split(/\s+/).find(Boolean)??"",i=c=>c.params[0]?.name??"",K=c=>/asset|ref|source/.test(i(c));return j.startsWith("@")?x.find(K)??x[0]:x.find(c=>!K(c))??x[0]}const Tb=f.lazy(async()=>({default:(await Os(()=>import("./confirm-bodies-Bw818V9J.js").then(g=>g.W),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]))).WatermarkBody})),ql=f.lazy(async()=>({default:(await Os(()=>import("./music-video-BSj8SgbQ.js"),__vite__mapDeps([13,1,2,3,4,5,6,7,8,9,10,11,14]))).MusicVideoEditor})),jb=f.lazy(async()=>({default:(await Os(()=>import("./alive-captions-4QySEGdt.js"),__vite__mapDeps([15,1,6,2,3,4,5,8,16]))).AliveCaptionsStudio}));function $b(d){return{mode:d.mode,reference:d.reference,referenceStartSeconds:d.startSeconds,referenceDurationSeconds:d.durationSeconds}}const Nl="videobook.cloud-generation-consent";function sr(d){return window.localStorage.getItem(Nl)==="accepted"?!0:window.confirm(`Cloud generation disclosure
|
|
3
|
+
|
|
4
|
+
Provider/model: ${d.provider??"unknown"} · ${d.model??d.tool}
|
|
5
|
+
Payload class: prompt text and connected media references.
|
|
6
|
+
Your local source files are sent only when required by the selected model.
|
|
7
|
+
|
|
8
|
+
Continue and remember this choice on this device?`)?(window.localStorage.setItem(Nl,"accepted"),!0):!1}const qb=typeof window>"u"?"http://localhost/mcp":new URL("/mcp",window.location.origin).toString(),mn=500,pn=5*6e4,ar=10,Nb=5,Lb=1e3,Fb=2e3,Db=45*6e4,Ll=5e3,Ob=3e3,Vb=20*6e4,Fl=750,Gb=20,Dl=45*6e4,Wb=new Set(["queued","running","completing"]),Ub=[];function ot(d){return new Promise(g=>window.setTimeout(g,d))}const Bb=[{id:"jobs",label:"Jobs",icon:nb},{id:"settings",label:"Settings",icon:rb}];function Ol(d,g){return!!(g==="transcript"?d?.transcript:d?.visionAnalysis)}function Hb(d){return $p(d)}function Ds(d){return d==="generate_audio"?"audio":d==="generate_image"?"image":"video"}function Vl(d){const g=d.document.cells.find(p=>p.id===d.sourceCellId);if(!g)throw new Error("The source asset cell is no longer available");return Bl({actions:d.actions,cellId:d.cellId,command:{cellType:d.cellType,mediaKind:Ds(d.cellType),prompt:"",sourceReferences:[U(g.slot)]},document:d.document,fallbackSlot:Mo(d.cellType,d.document.cells,d.lastWorkSlot),lastWorkSlot:d.lastWorkSlot})}function ft(d){return{ok:!0,message:d,nextInput:"/apply",selectInput:!0}}function zb(d){return{ok:!0,message:d,nextInput:"/apply ",selectInput:!1}}function Gl(d){return d.match(/https?:\/\/[^\s]+/u)?.[0]??d}function gn(d){return{ok:!1,error:d instanceof Error?d.message:String(d)}}function qs(d,g){const p=qp(g);if(p.artifactId&&p.artifactId!==d.asset.artifactId)throw new Error("The subject map belongs to another image artifact");if(p.objectHash&&p.objectHash!==d.asset.objectHash)throw new Error("The image changed before subject analysis finished");return{...p,artifactId:p.artifactId??d.asset.artifactId,objectHash:p.objectHash??d.asset.objectHash??null,width:p.width??d.asset.width,height:p.height??d.asset.height}}function Ns(d,g,p=d.subjectMap){return{status:"failed",artifactId:d.asset.artifactId,objectHash:d.asset.objectHash??null,width:d.asset.width,height:d.asset.height,baseUrl:p?.baseUrl??null,jobId:p?.jobId??null,startedAt:p?.startedAt??null,error:g instanceof Error?g.message:String(g),subjects:p?.subjects??[]}}function Kb(d,g){if(!d||!g)return null;const p=lr(g),k=d.tracks.filter(I=>I.trackId.toLowerCase().startsWith(p)||I.name.toLowerCase()===p);return k.length===1?k[0]:null}function Kl(d,g){const p=d.tracks.filter(I=>I.kind==="audio"&&I.enabled&&!I.locked&&!I.muted);return p.find(I=>{const x=d.clips.filter(j=>j.trackId===I.trackId);return x.length===1&&x[0]?.timelineStartFrame===0&&x[0].source.kind==="timed"&&x[0].source.artifactId===g})??p.find(I=>!d.clips.some(x=>x.trackId===I.trackId))??null}function Xb(d,g,p){const k=Kl(d,g);if(!k)return!1;const I=d.clips.filter(j=>j.trackId===k.trackId),x=I[0];return I.length===1&&x!==void 0&&x.timelineStartFrame===0&&x.durationFrames===p&&x.source.kind==="timed"&&x.source.artifactId===g}function Jb(d,g,p){const k=d.stages.find(i=>i.kind==="edit"),I=k?.intent.operations.find(i=>i.kind==="insert-clip"&&i.placement.source.artifactId===p);if(I?.kind==="insert-clip")return I.placement.durationFrames;const x=g.clips.find(i=>i.timelineStartFrame===0&&i.source.kind==="timed"&&i.source.artifactId===p),j=k?.intent.operations.find(i=>i.kind==="trim-clip"&&i.clipId===x?.clipId);if(j?.kind==="trim-clip")return j.durationFrames;if(x)return x.durationFrames;throw new Error("The soundtrack setup plan has no duration boundary")}function Qb(d){const g=d.stages.flatMap(I=>I.kind==="edit"?I.intent.operations:[]),p=g.filter(I=>I.kind==="insert-clip").length,k=g.filter(I=>I.kind==="set-clip-audio"?I.audio.muted:I.kind==="set-clip-speed"&&I.audioPolicy==="mute").length;return`${p>0?"Place":"Normalize"} master soundtrack · mute ${k} other ${k===1?"clip":"clips"}`}function Wl(d){return d.valid?null:d.conflicts.map(p=>p.message).join(" · ")||"The canonical edit preview is invalid"}function Yb(d){const p=d.find(k=>k.kind==="edit")?.intent.operations.map(k=>{if(k.kind==="insert-clip")return{kind:"insert",mode:k.mode,artifact_id:k.placement.source.artifactId,track_id:k.placement.trackId,timeline_start_frame:k.placement.timelineStartFrame,duration_frames:k.placement.durationFrames,...k.placement.source.kind==="timed"?{source_start_tick:k.placement.source.range.startTick,source_duration_ticks:k.placement.source.range.durationTicks}:{}};if(k.kind==="trim-clip")return{kind:"trim",clip_id:k.clipId,timeline_start_frame:k.timelineStartFrame,duration_frames:k.durationFrames};if(k.kind==="set-clip-audio")return{kind:"volume",clip_id:k.clipId,gain_db:k.audio.gainDb,muted:k.audio.muted,fade_in_frames:k.audio.fadeInFrames,fade_out_frames:k.audio.fadeOutFrames};if(k.kind==="move-clip")return{kind:"move",clip_id:k.clipId,track_id:k.trackId,timeline_start_frame:k.timelineStartFrame};if(k.kind==="split-clip")return{kind:"split",clip_id:k.clipId,split_frame:k.splitFrame};if(k.kind==="set-clip-transform")return{kind:"transform",clip_id:k.clipId,fit:k.transform.fit,position_x:k.transform.positionX,position_y:k.transform.positionY,scale_x:k.transform.scaleX,scale_y:k.transform.scaleY,rotation_degrees:k.transform.rotationDegrees,opacity:k.transform.opacity,crop_top:k.transform.cropTop,crop_right:k.transform.cropRight,crop_bottom:k.transform.cropBottom,crop_left:k.transform.cropLeft};if(k.kind==="set-clip-speed")return{kind:"speed",clip_id:k.clipId,numerator:k.speed.numerator,denominator:k.speed.denominator,reverse:k.reverse,audio_policy:k.audioPolicy};if(k.kind==="set-transition")return{kind:"transition",outgoing_clip_id:k.outgoingClipId,incoming_clip_id:k.incomingClipId,transition_kind:k.transition?.kind??null,...k.transition?{duration_frames:k.transition.durationFrames,alignment:k.transition.alignment}:{}};if(k.kind==="upsert-caption-cue")return{kind:"caption",cue_id:k.cue.cueId,track_id:k.cue.trackId,timeline_start_frame:k.cue.timelineStartFrame,duration_frames:k.cue.durationFrames,text:k.cue.text,style_id:k.cue.styleId,...k.cue.speaker?{speaker:k.cue.speaker}:{}};throw new Error(`The edit cannot be replanned: ${k.kind}`)})??[];if(p.length===0)throw new Error("The plan has no editable operation");return p.length===1?p[0]:p}function kn(d){try{return window.localStorage.getItem(d)??""}catch{return""}}function Ot(d,g){try{window.localStorage.setItem(d,g)}catch{return}}const ir={offset:0,limit:24,total:0,hasMore:!1};function Ls(d){return d==="final"?"video":d==="audio"||d==="image"||d==="video"?d:null}function Zb(d){return d==="all"?["audio","image","video","final"]:d==="video"?["video","final"]:[d]}function Fs(d,g){return Zb(d).includes(g)}async function Ul(d){const g=await window.crypto.subtle.digest("SHA-256",await d.arrayBuffer());return[...new Uint8Array(g)].map(p=>p.toString(16).padStart(2,"0")).join("")}function ew(d){return`slot-context-menu-${d.row}-${d.column}`}const tw={cell:Rf,timeline:Af,goal:Jk},ow={busRiver:_f},nw={hideAttribution:!0},rw={selectable:!1},sw=["Shift","Control","Meta"],aw=[];function iw({initialWorkspace:d}){const g=f.useMemo(()=>Lf(d),[d]),p=Ff({url:qb,clientName:"videobook",reconnectDelayMs:3e3}),[k,I]=f.useState(()=>ji(window.location.pathname)),[x,j]=f.useState(()=>g?.books??[]),[i,K]=f.useState(()=>g?.bookId??kn("videobook.active-book")),[c,xe]=f.useState(()=>g?.notebook??null),[z,Xe]=f.useState(()=>g?.assets??[]),[X,Ee]=f.useState(()=>g?.sequence??null),[De,Vs]=f.useState(()=>g?.jobs??[]),[Xl,Gs]=f.useState(()=>Date.now()),[bn,Jl]=f.useState(()=>g?.commands??[]),[xt,dr]=f.useState([]),[ur,fr]=f.useState({loading:!1,error:null}),[$e,Qe]=f.useState(null),mt=f.useRef(0),[mr,Et]=f.useState(null),[wn,Vt]=f.useState(null),[Ql,Yl]=f.useState(null),[Zl,ec]=f.useState(null),[Oe,To]=f.useState(null),Ws=f.useRef(null),[pr,tc]=f.useState(()=>g?.chatModelCatalog??$i),[Us,Bs]=f.useState(()=>bs(g?.chatModelCatalog??$i,kn("videobook.chat-model"))),[Je,Hs]=f.useState(()=>g?.generationActions??[]),oc=f.useMemo(()=>new Map(Je.map(e=>[e.model,e.title])),[Je]),[nc,rc]=f.useState([]),[jo,ro]=f.useState(Df),hn=Xn(jo.status),[sc,gr]=f.useState(null),[ac,zs]=f.useState(!1),[ic,Ks]=f.useState(null),[lc,Xs]=f.useState(!1),Js=f.useRef(0),{lastWorkSlot:Ve,rememberLastWorkSlot:_e}=Of(i,c?.id??null),[Me,$o]=f.useState(null),[vn,cc]=f.useState(()=>new Set),[Ye,yn]=f.useState(null),[In,Qs]=f.useState(()=>new Set),[kr,br]=f.useState(()=>new Set),[wr,Ys]=f.useState(()=>new Set),[hr,Zs]=f.useState({}),[vr,dc]=f.useState({}),[so,ea]=f.useState({}),[B,ge]=f.useState(null),ue=Vf(),[he,qe]=f.useState(null),[te,qo]=f.useState(null),ta=f.useRef(new Map),[ve,Ge]=f.useState(null),[rt,yr]=f.useState(null),[uc,Ir]=f.useState(null),[oa,Cr]=f.useState(!1),[No,Gt]=f.useState(null),[na,Lo]=f.useState(!1),[fc,mc]=f.useState(null),{scrollRef:Wt,surface:_t,zoom:Te,revealCell:ao}=Gf(i,c?.id,k==="notebook"),[ra,pc]=f.useState(58),[sa,gc]=f.useState(58),kc=f.useMemo(()=>({"--notebook-command-row-height":`${ra}px`,"--notebook-composer-height":`${sa}px`}),[ra,sa]),[Sr,ke]=f.useState(!1),[Ut,Ne]=f.useState(null),[Bt,pt]=f.useState(null),[io,Cn]=f.useState(null),[bc,xr]=f.useState(!1),[wc,Er]=f.useState(!1),[hc,_r]=f.useState(null),[vc,aa]=f.useState(!1),[ce,de]=f.useState(null),[_,V]=f.useState(null),Ar=f.useRef(null),ia=f.useRef(null),Rr=f.useRef(!1),[Pr,lo]=f.useState(""),[G,T]=f.useState(!1),{turns:la,begin:ca,observe:Sn,cancelReview:da,claimVoice:ua}=Wf(i,c?.id??null),fa=f.useRef(void 0),[yc,Ic]=f.useState(null),[Cc,Mr]=f.useState(Uf),[Sc,ma]=f.useState(null),[At,xc]=f.useState(()=>window.navigator.onLine),[Ht,Fo]=f.useState({text:"Connect to the server, then load your books.",tone:"info"}),h=f.useCallback((e,t="info")=>{Fo({text:e,tone:t})},[]),Do=f.useRef(null),Oo=f.useRef(0),Ae=f.useRef(0),We=f.useRef(0),Tr=f.useRef(0),jr=f.useRef(null),Ze=f.useRef(new Map),Vo=f.useRef(new Map),$r=f.useRef(0),xn=f.useRef(new Map),st=f.useRef(new Set),Q=f.useRef({bookId:i,notebookId:c?.id??null,assets:z}),Pe=f.useRef(async()=>{throw new Error("MCP call is not ready")}),ye=f.useRef(0),qr=f.useRef(De),pa=f.useRef(k),ne=f.useCallback((e,t)=>{ea(o=>{if(t===null){if(!(e in o))return o;const n={...o};return delete n[e],n}return o[e]===t?o:{...o,[e]:t}})},[]);f.useEffect(()=>{if(!Ht||Ht.tone!=="info")return;const e=Ht,t=window.setTimeout(()=>{Fo(o=>o===e?null:o)},6e3);return()=>window.clearTimeout(t)},[Ht]);const co=f.useMemo(()=>x.find(e=>e.bookId===i)??null,[i,x]),re=f.useMemo(()=>new Map(z.map(e=>[e.artifactId,e])),[z]),fe=f.useMemo(()=>Bf(c?.cells??[],z),[z,c]),Nr=f.useMemo(()=>Hf(c?.cells??[],z),[z,c]),En=f.useMemo(()=>[...Nr.values()].flatMap(e=>e.asset?[{...e.asset,cellAddress:e.token.slice(1)}]:[]),[Nr]),W=_?.kind==="generation"?_.draft:null,ga=f.useMemo(()=>{if(_?.kind!=="routed")return null;const e=_.plan;if(e.routedTool!=="change_video_speed")return null;const t=A(e.params.asset_id),o=t?fe.find(w=>w.artifactId===t):void 0,n=t?re.get(t):void 0,r=ae(n?.duration)??ae(o?.duration),s=ae(e.params.speed),a=ae(e.params.target_duration_seconds),l=s??(r&&a&&a>0?r/a:null),m=n?.mediaUrl??null,u=n?.type??o?.type??null;return{mediaUrl:m,thumbnailUrl:n?.thumbnailUrl??null,unavailableReason:u!==null&&u!=="video"?"the selected source is not a video":m===null?"the source media is not loaded yet":null,sourceDurationSeconds:r&&r>0?r:null,effectiveSpeed:l&&l>0?l:null}},[re,fe,_]),Ec=_?.kind==="routed"?zf({input:_.plan.prompt,params:_.plan.params,tool:_.plan.routedTool,sourceDurationSeconds:ga?.sourceDurationSeconds??null}):null,uo=f.useMemo(()=>{if(_?.kind!=="routed")return null;const e=_.plan;if(e.tool!=="post"&&e.routedTool!=="post")return null;const t=A(e.params.asset_id)?.trim()??"",o=t.replace(/^@/,""),n=fe.find(m=>m.artifactId===o||m.cellAddress.toLowerCase()===o.toLowerCase()),r=re.get(n?.artifactId??o)??n??null,s=qi(e.params),a=_.xPostReview,l=a?.options.enabled&&eo(a).length===0?{blocking:Ni,notice:null}:Kf(s,void 0,hn);return{asset:r,draft:s,error:Li(s,void 0,hn),validation:l,sourceLabel:n?`@${n.cellAddress}`:t.startsWith("@")?t:o?`@${o}`:"Selected media"}},[re,fe,_,hn]),gt=f.useMemo(()=>W&&c?Xf(W,c):[],[c,W]),Go=f.useMemo(()=>W?Jf(Je,W.cell.type,gt):[],[Je,gt,W]),_c=f.useMemo(()=>W?Qf(W.action,gt):[],[gt,W]),Wo=f.useMemo(()=>W&&c?W.sourceCellIds.flatMap(e=>{const t=c.cells.find(o=>o.id===e);return t?[{cellId:e,address:Se(t.slot),type:t.type,asset:t.outputArtifactId?re.get(t.outputArtifactId)??null:null}]:[]}):[],[re,c,W]),Uo=f.useMemo(()=>{if(!_)return Fi;if(_.kind==="generation"&&W)return{target:Se(W.cell.slot),sources:Wo.map(e=>e.address)};if(_.kind==="frame"||_.kind==="split")return{target:null,sources:_.expectations.map(e=>e.address)};if(_.kind==="notebook"){const[e,...t]=_.plan.expectations.map(o=>o.address);return{target:e??null,sources:t}}return Fi},[_,W,Wo]),Lr=f.useMemo(()=>Yf(Uo),[Uo]),Ac=f.useMemo(()=>W&&c?Zf(c,W.sourceCellIds,W.cell.id).map(({cell:e})=>({cellId:e.id,address:Se(e.slot),type:e.type,asset:e.outputArtifactId?re.get(e.outputArtifactId)??null:null})):[],[re,c,W]),Fr=f.useMemo(()=>em(c?.generationPlans),[c]),b=f.useCallback(async(e,t,o)=>{if(p.state!=="ready")throw new Error("MCP server is not ready");if(o?.chat&&!o.chat.isInScope())throw new Error("Workspace changed. Repeat the command in the current workspace.");if(o?.background||!tm(e)){const l=Di(await p.callTool(e,t));return o?.chat?.accept(e,t,l),l}const n=Mp(),r=performance.now();Vo.current.set(n,{tool:e,startedAt:r}),Mr(l=>om(l,{id:n,turnId:o?.chat?.visible===!1?void 0:o?.chat?.id,tool:e,args:nm(t)}));let s="done",a="";try{const l=Di(await p.callTool(e,t));return a=rm(l),o?.chat?.accept(e,t,l),l}catch(l){throw s="failed",a=l instanceof Error?l.message:String(l),l}finally{Vo.current.delete(n);const l=performance.now()-r,m=()=>{xn.current.delete(n),Mr(w=>jp(w,n,{phase:s,elapsedMs:l,detail:a})),!(Vo.current.size>0)&&(window.clearTimeout($r.current),ma(s==="failed"?"error":"success"),$r.current=window.setTimeout(()=>ma(null),s==="failed"?1100:620))},u=Math.max(0,Tp-l);u===0?m():xn.current.set(n,window.setTimeout(m,u))}},[p]),_n=_?.kind==="post-delivery"?_.review:null;sm(!!(_n?.receipt&&_n.destination==="icloud"),p.state==="ready"?b:void 0,_n?.bookId??"",_n?.postId??"",e=>V(t=>t?.kind==="post-delivery"?{...t,review:{...t.review,sync:e}}:t));const Bo=f.useMemo(()=>i&&c?{bookId:i,notebookId:c.id}:null,[i,c]),{goals:Dr,events:Rc,accept:Pc,refresh:ka,act:ba}=am(b,Bo),Or=f.useMemo(()=>new Set((c?.cells??[]).filter(e=>e.type==="goal").map(e=>e.id)),[c]),Ho=f.useMemo(()=>Dr.filter(e=>Or.has(e.cellId)),[Or,Dr]),wa=f.useMemo(()=>new Map(Ho.map(e=>[e.cellId,e])),[Ho]),Mc=f.useMemo(()=>im(Ho),[Ho]),fo=lm(Ho),zo=cm({callTool:b,ready:p.state==="ready"}),Vr=dm({bookId:i,ready:p.state==="ready",call:b}),Tc=f.useCallback(async e=>{try{const t=D(await b("estimate_cost",{calls:[{tool_name:"edit_image_subjects",input:{model:e}}]})),o=D(t?.estimate),n=Array.isArray(o?.warnings)?o.warnings.filter(l=>typeof l=="string"):[],r=typeof o?.usd=="number"?o.usd:null,s=Oi(n);if(r===null||r<=0||n.length>0&&!s)return null;const a=`$${r.toFixed(r<.01?4:2)}`;return s?`${a} · historical average`:a}catch{return null}},[b]),[Ko,An]=f.useState(null),et=um({bookId:i,ready:p.state==="ready"&&!G,sequence:X,call:b,parseSequence:Ke,parseAssets:Lt,onSequence:e=>{ye.current=performance.now(),Ee(e)},onAssets:e=>Xe(t=>{const o=new Map(t.map(n=>[n.artifactId,n]));for(const n of e)o.set(n.artifactId,n);return[...o.values()]})}),kt=fm({bookId:i,ready:p.state==="ready",sequence:X,call:b,onSequence:e=>{const t=Ke(e);t&&(ye.current=performance.now(),Ee(t))}}),Rn=Ko?.bookId===i?c?.cells.find(e=>e.id===Ko.cellId&&e.type==="timeline"):void 0,Xo=!!(Rn&&X&&k==="notebook"),{preview:ha,select:Jo}=mm({bookId:i,notebook:c,ready:p.state==="ready",call:b}),jc=f.useCallback(e=>{Mr(t=>pm(t,e))},[]);f.useEffect(()=>()=>{window.clearTimeout($r.current);for(const e of xn.current.values())window.clearTimeout(e);xn.current.clear()},[]),f.useEffect(()=>{Pe.current=b},[b]),f.useEffect(()=>{Q.current={bookId:i,notebookId:c?.id??null,assets:z}},[z,i,c?.id]),f.useEffect(()=>{qr.current=De},[De]),f.useEffect(()=>{pa.current=k},[k]);const at=f.useCallback(e=>{Sn(Q.current.bookId??"",e);const t=!Nt(qr.current,e);t&&(qr.current=e,Vs(e));const o=pa.current==="jobs"&&e.some(n=>Wb.has(n.state));(t||o)&&Gs(Date.now())},[Sn]),Rt=f.useCallback((e,t,o=null)=>{Zs(n=>({...n,[e]:{operation:t,error:o}}))},[]),Qo=f.useCallback((e,t)=>{Rt(e,null,t)},[Rt]),oe=f.useCallback((e,t)=>{Qs(o=>{const n=new Set(o);return t?n.add(e):n.delete(e),n.size===o.size?o:n})},[]),Yo=f.useCallback(e=>{br(t=>new Set([...t,...e])),window.setTimeout(()=>{br(t=>{const o=new Set(t);for(const n of e)o.delete(n);return o.size===t.size?t:o})},900)},[]),[Gr,va]=f.useState(()=>new Set),mo=f.useRef(null);f.useEffect(()=>()=>{mo.current!==null&&window.clearTimeout(mo.current)},[]);const po=f.useCallback((e,t={})=>{va(o=>gm(o,e)),mo.current!==null&&window.clearTimeout(mo.current),mo.current=window.setTimeout(()=>{mo.current=null,va(o=>km(o,e))},bm),t.scroll&&window.requestAnimationFrame(()=>{if(t.scroll==="offscreen"&&Do.current?.getNodes().some(n=>n.dragging))return;const o=window.matchMedia("(prefers-reduced-motion: reduce)").matches;for(const n of e){const r=document.querySelector(`[data-id="${n}"]`);if(r){if(t.scroll==="offscreen"){const s=r.getBoundingClientRect();if(s.top>=0&&s.left>=0&&s.bottom<=window.innerHeight&&s.right<=window.innerWidth)continue}r.scrollIntoView({block:"center",behavior:o?"auto":"smooth"})}}})},[]),go=f.useCallback(()=>{Vi(()=>document.querySelector('.command-composer [aria-label="Videobook command input"]'))},[]);f.useEffect(()=>{const e=()=>xc(window.navigator.onLine);return window.addEventListener("online",e),window.addEventListener("offline",e),()=>{window.removeEventListener("online",e),window.removeEventListener("offline",e)}},[]);const ko=f.useCallback(async(e,t,o)=>{if(!i||!c)throw new Error("Load a notebook first.");return ut(await b("plan_notebook_generation",{book_id:i,notebook_id:c.id,cell_id:e,source_surface:t,actor:"videobook-user",timeline_start_frame:0},{chat:o}))},[i,b,c]),Wr=f.useCallback(async(e,t,o)=>{const n=await ko(e,t,o);return O(o,!1,()=>V(null)),O(o,!0,()=>de({plan:n,previews:{}})),M(o,()=>go()),ft("Generation plan ready for review")},[ko,go]),[Ue,bt]=f.useState(()=>g?.notebook?ws(g.notebook,g.assets,g.jobs):[]),[ya,Pn]=f.useState(()=>g?.notebook?Gi(g.notebook):[]),bo=f.useCallback(e=>{e.size>0&&ge(o=>o?.cellId===null?null:o);const t=st.current;t.size===e.size&&[...e].every(o=>t.has(o))||(st.current=e,cc(e))},[]),Y=f.useCallback((e,t,o)=>{if(t&&!t.isCurrent()||(Ic(e?t?.id??null:null),$o(e),Jo(e,o),bo(e?new Set([e]):new Set),!e))return;const n=c?.cells.find(s=>s.id===e);if(n){_e(n.slot);return}const r=Ue.find(s=>s.id===e);r&&_e(r.data.slot)},[Jo,c,Ue,_e,bo]),wo=f.useCallback(()=>{yn(null)},[]),Ia=f.useCallback((e,t,o)=>{Y(e),yn({target:{kind:"cell",cellId:e},position:t,returnFocus:o})},[Y]),$c=f.useCallback((e,t,o)=>{yn({target:{kind:"slot",slot:e},position:t,returnFocus:o})},[]),zt=Ye?.target.kind==="cell"?Ye.target.cellId:null,qc=f.useMemo(()=>({openCellId:zt,open:Ia}),[zt,Ia]),Ie=f.useCallback((e,t,o,n=i)=>{Sn(n,o,e,t),ye.current=performance.now(),xe(s=>Nt(s,e)?s:e);const r=new Set(e.cells.map(s=>s.id));Qs(s=>{const a=new Set([...s].filter(l=>r.has(l)));return a.size===s.size?s:a}),br(s=>{const a=new Set([...s].filter(l=>r.has(l)));return a.size===s.size?s:a}),Zs(s=>Object.keys(s).every(a=>r.has(a))?s:Object.fromEntries(Object.entries(s).filter(([a])=>r.has(a)))),ea(s=>Object.keys(s).every(a=>r.has(a))?s:Object.fromEntries(Object.entries(s).filter(([a])=>r.has(a)))),bo(new Set([...st.current].filter(s=>r.has(s)))),ge(s=>s&&s.bookId===n&&s.notebookId===e.id&&(s.cellId===null||r.has(s.cellId))?s:null),yn(s=>!s||s.target.kind==="slot"||r.has(s.target.cellId)?s:null),bt(s=>wm(s,ws(e,t,o))),Pn(s=>hm(s,Gi(e))),$o(s=>s&&e.cells.some(a=>a.id===s)?s:null),Ne(s=>s&&r.has(s)?s:null)},[i,Sn,bo]);vm({bookId:i,notebookId:c?.id??null,enabled:p.state==="ready"&&k==="notebook"&&!G&&!et.busy&&!Ue.some(e=>e.dragging),refresh:async e=>{if(p.state!=="ready"||!c||Vo.current.size>0)return;const t=performance.now(),o=Or.size>0||Dr.length>0,[n,r,s,a,l]=await Promise.allSettled([b("get_notebook",{book_id:i,notebook_id:c.id},{background:!0}),b("list_assets",{book_id:i,sort:"newest",limit:200,include_referenced:!0},{background:!0}),b("list_jobs",{book_id:i,limit:200},{background:!0}),c.cells.some(v=>v.type==="timeline")?b("get_primary_sequence",{book_id:i},{background:!0}):Promise.resolve(null),o?b("video_goal",{book_id:i,notebook_id:c.id,action:"list"},{background:!0}):Promise.resolve(null)]);if(!e()||Vo.current.size>0||(l.status==="fulfilled"&&l.value&&Pc({bookId:i,notebookId:c.id},l.value),t<ye.current)||n.status!=="fulfilled"||r.status!=="fulfilled"||s.status!=="fulfilled")return;const m=pe(n.value);if(!m)return;const u=Lt(r.value),w=to(s.value);if(Xe(v=>Nt(v,u)?v:u),a.status==="fulfilled"&&a.value){const v=Ke(a.value);v&&Ee(S=>Nt(S,v)?S:v)}at(w),Ie(m,u,w)}});const Pt=f.useCallback(async e=>{Ze.current.set(e.cellId,e.runId);let t=!1,o=0;const n=Date.now()+e.timeoutMs,r=()=>{const l=Q.current;return l.bookId===e.bookId&&l.notebookId===e.notebookId},s=async()=>{const l=performance.now(),[m,u,w]=await Promise.all([Pe.current("get_notebook",{book_id:e.bookId,notebook_id:e.notebookId},{background:!0}),Pe.current("list_assets",{book_id:e.bookId,sort:"newest",limit:200,include_referenced:!0},{background:!0}),Pe.current("list_jobs",{book_id:e.bookId,limit:200},{background:!0})]);if(!r())return;const v=pe(m);if(!v)return;const S=Lt(u),E=to(w);l<ye.current||(ye.current=l,Xe(y=>Nt(y,S)?y:S),at(E),Ie(v,S,E))},a=async()=>{for(let l=0;l<Nb;l+=1){if(!r())return;try{await s();return}catch{await ot(Lb)}}};try{for(;Date.now()<n;){if(Ze.current.get(e.cellId)!==e.runId)return{kind:"superseded"};const l=Q.current;if(l.bookId!==e.bookId||l.notebookId!==e.notebookId)return{kind:"superseded"};try{const m=performance.now(),[u,w]=await Promise.all([Pe.current("get_notebook",{book_id:e.bookId,notebook_id:e.notebookId},{background:!0}),Pe.current("list_jobs",{book_id:e.bookId,limit:200},{background:!0})]);o=0;const v=Q.current;if(v.bookId!==e.bookId||v.notebookId!==e.notebookId||Ze.current.get(e.cellId)!==e.runId)return{kind:"superseded"};const S=pe(u);if(!S)throw new Error("The server returned an invalid notebook");const E=to(w),y=m>=ye.current;y&&(ye.current=m,at(E));const R=E.map(Wi),$=ym({jobs:R,cellId:e.cellId,runId:e.runId,jobOperationId:e.jobOperationId}),F=Im(S,e.cellId,e.runId);F.state!=="pending"&&oe(e.cellId,!1),y&&Ie(S,v.assets,E);const J=Cm({observation:F,job:$,address:e.address,sawRun:t});if(J.kind==="continue"){t=J.sawRun,await ot(e.intervalMs);continue}return J.kind==="completed"?(await a(),ne(e.cellId,null),{kind:"completed"}):J.kind==="failed"?{kind:"failed",message:J.message}:{kind:"superseded"}}catch(m){if(o+=1,o>=e.maxPollFailures){const u=m instanceof Error?m.message:String(m);return await a(),{kind:"failed",message:`Lost contact with the server while watching @${e.address}: ${u}`}}await ot(e.intervalMs)}}return await a(),{kind:"timeout"}}finally{Ze.current.get(e.cellId)===e.runId&&Ze.current.delete(e.cellId)}},[at,Ie,oe,ne]),Zo=f.useCallback(async(e,t)=>{try{const o=await Pt({...e,intervalMs:Fb,timeoutMs:Db,maxPollFailures:10});if(o.kind==="completed"){M(t,()=>{h(`@${e.address} generated`),po([e.cellId],{scroll:"offscreen"})}),ne(e.cellId,null);return}if(o.kind==="failed"){const n=o.message??`@${e.address} failed`;ne(e.cellId,n),M(t,()=>h(n,"error"));return}o.kind==="timeout"&&M(t,()=>h(`@${e.address} is still running — check the Jobs screen`))}catch(o){const n=o instanceof Error?o.message:String(o);ne(e.cellId,n),M(t,()=>h(n,"error"))}finally{oe(e.cellId,!1)}},[po,oe,ne,h,Pt]),Mn=f.useCallback(async e=>{const t=e.intervalMs??Ll,o=`${e.tokenPrefix??"media"}:${e.artifactId}`;Ze.current.set(e.cellId,o);let n=e.artifactId,r=0;const s=Date.now()+Dl;try{for(;Date.now()<s;){const a=Q.current;if(Ze.current.get(e.cellId)!==o||a.bookId!==e.bookId||a.notebookId!==e.notebookId)return;try{const l=performance.now(),[m,u,w]=await Promise.all([Pe.current("get_notebook",{book_id:e.bookId,notebook_id:e.notebookId},{background:!0}),Pe.current("list_assets",{book_id:e.bookId,sort:"newest",limit:200,include_referenced:!0},{background:!0}),Pe.current("list_jobs",{book_id:e.bookId,limit:200},{background:!0})]);r=0;const v=Q.current;if(Ze.current.get(e.cellId)!==o||v.bookId!==e.bookId||v.notebookId!==e.notebookId)return;const S=pe(m);if(!S)throw new Error("The server returned an invalid notebook");const E=S.cells.find(F=>F.id===e.cellId);if(!E||E.outputArtifactId!==n)return;const y=Lt(u),R=to(w);l>=ye.current&&(ye.current=l,Xe(F=>Nt(F,y)?F:y),at(R),Ie(S,y,R));const $=Sm(n,y.find(F=>F.artifactId===n),R,xm(S,e.cellId));if($.kind==="redirected"){const F=y.find(P=>P.artifactId===$.artifactId),J=F?Ls(F.type):null;if(!F||!J){await ot(t);continue}await Pe.current("update_notebook_cell",{book_id:e.bookId,notebook_id:e.notebookId,cell_id:e.cellId,cell:{type:J,output_artifact_id:F.artifactId}},{background:!0}),n=F.artifactId,ne(e.cellId,null);continue}if($.kind==="completed"){ne(e.cellId,null),e.completedNotice&&h(e.completedNotice);return}if($.kind==="failed"){ne(e.cellId,$.message),h($.message,"error");return}await ot(t)}catch(l){if(r+=1,r>=10){const m=l instanceof Error?l.message:String(l);h(`Stopped watching @${e.address}: ${m}. Check the Jobs screen.`,"error");return}await ot(t)}}h(e.stillWorkingNotice??`@${e.address} is still processing — check the Jobs screen`)}finally{Ze.current.get(e.cellId)===o&&Ze.current.delete(e.cellId)}},[at,Ie,ne,h]),Nc=f.useCallback(async e=>{await Mn({...e,tokenPrefix:"download",intervalMs:Ll,completedNotice:`@${e.address} downloaded`,stillWorkingNotice:`@${e.address} is still downloading — check the Jobs screen`})},[Mn]),Tn=f.useCallback(async e=>{await Mn({...e,tokenPrefix:"process",intervalMs:Fl,stillWorkingNotice:`@${e.address} is still processing — check the Jobs screen`})},[Mn]),jn=f.useCallback((e,t,o)=>{const n=new Map(o.map(r=>[r.artifactId,r]));for(const r of t.cells){if(!Ft(r.type)||!r.outputArtifactId)continue;const s=n.get(r.outputArtifactId);!s||s.status==="ready"||s.status==="error"||Ze.current.has(r.id)||Tn({bookId:e,notebookId:t.id,cellId:r.id,address:Se(r.slot),artifactId:r.outputArtifactId})}},[Tn]),Ca=f.useRef(!1);f.useEffect(()=>{Ca.current||!i||!c||(Ca.current=!0,jn(i,c,z))},[z,i,c,jn]);const se=f.useCallback(e=>{const t=Q.current;t.bookId!==i||t.notebookId!==c?.id||Rr.current||M(e,()=>ke(!1))},[i,c?.id]),en=f.useCallback(async(e,t,o,n)=>{if(!i||!c)return;let r=!1;T(!0),ne(e,null);try{const s=t??pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(!s)throw new Error("The server returned an invalid notebook");const a=s.cells.find(S=>S.id===e);if(!a||!Hb(a))throw new Error("Configure this cell before running it");const l=Em(a);if(l&&!At)throw new Error("Offline: cloud generation is unavailable. Local search, editing, playback, and export remain available.");if(l){if(Ui(a)){const E=await ko(e,"ui",o),y=E.stages.find(le=>le.kind==="queued"&&le.jobType==="generation"&&le.tool==="run_notebook_cell"&&le.input.cell_id===e);if(y?.kind!=="queued")throw new Error("The generation plan is missing its notebook cell");const R=A(y.input.notebook_id);if(R!==s.id)throw new Error("The generation plan belongs to another notebook");if(!sr(y))throw new Error("Cloud generation cancelled before sending data");O(o,!1,()=>V(null)),O(o,!1,()=>de(null));const $=await Jn({start:()=>b("run_notebook_cell",{book_id:i,notebook_id:R,cell_id:e,plan:E,...n?{retry_failed_cell_id:n}:{},actor:"videobook-user"},{chat:o}),onStarting:()=>oe(e,!0),onAccepted:()=>oe(e,!1),onRejected:()=>oe(e,!1)}),F=D($),J=A(F?.run_id),P=A(F?.job_id),L=A(F?.output_cell_id);if(!J||!P)throw oe(e,!1),new Error("The server did not return a notebook run");r=!0,L&&se(o);const H=L??e;let ee=Se(a.slot);if(L){const le=await b("get_notebook",{book_id:i,notebook_id:R},{background:!0,chat:o}),me=pe(le);if(me){Ie(me,z,De);const ze=me.cells.find(be=>be.id===L);ze&&(ee=Se(ze.slot))}M(o,()=>Yo([L])),ne(L,null),oe(L,!0),st.current.has(e)&&(Y(null,o),M(o,()=>po([L],{scroll:"center"})))}return M(o,()=>h(`${U(a.slot)} queued`)),Zo({bookId:i,notebookId:R,cellId:H,address:ee,runId:J,jobOperationId:P},o),{ok:!0,message:`${U(a.slot)} queued`}}const S=await Wr(e,"ui",o);return M(o,()=>h(S.message,S.ok?"info":"error")),S}const m=await Jn({start:()=>b("run_notebook_cell",{book_id:i,notebook_id:s.id,cell_id:e,actor:"videobook-user",...s.revision?{expected_revision:s.revision}:{}},{chat:o}),onStarting:()=>oe(e,!0),onRejected:()=>oe(e,!1)}),u=A(D(m)?.run_id),w=A(D(m)?.job_id);if(!u||!w)throw new Error("The server did not return a notebook run");M(o,()=>h(`${U(a.slot)} queued`));const v=await Pt({bookId:i,notebookId:s.id,cellId:e,address:Se(a.slot),runId:u,jobOperationId:w,intervalMs:mn,timeoutMs:pn,maxPollFailures:ar});if(v.kind==="failed")throw new Error(v.message??`${U(a.slot)} failed`);if(v.kind==="timeout")throw new Error("Notebook run did not finish within five minutes");return v.kind==="completed"&&M(o,()=>h(`${U(a.slot)} updated`)),{ok:!0,message:`${U(a.slot)} run accepted`}}catch(s){const a=s instanceof Error?s.message:String(s);return ne(e,a),M(o,()=>h(a,"error")),{ok:!1,message:a}}finally{r||oe(e,!1),T(!1)}},[Ie,z,i,b,se,ko,po,De,c,At,Wr,Yo,Y,oe,ne,h,Zo,Pt]),Mt=f.useMemo(()=>{let e=Ue;for(const t of In)e=_m(e,t,"queued");return kr.size>0&&(e=e.map(t=>kr.has(t.id)?{...t,data:{...t.data,revealing:!0}}:t)),Gr.size>0&&(e=e.map(t=>Gr.has(t.id)?{...t,data:{...t.data,highlighted:!0}}:t)),Object.keys(so).length===0?e:e.map(t=>{const o=so[t.id];return o?{...t,data:{...t.data,status:"error",statusError:o}}:t})},[so,Gr,Ue,In,kr]),Lc=f.useMemo(()=>Mt.map(e=>{const t=vn.has(e.id),o=Lr.get(Se(e.data.slot)),n=o?`notebook-review-${o}`:void 0;return e.selected===t&&e.className===n?e:{...e,selected:t,className:n}}),[Lr,Mt,vn]),Fc=f.useMemo(()=>Am(ya,Me),[ya,Me]),wt=f.useMemo(()=>Ue.flatMap(e=>_l({type:e.data.kind,slot:e.data.slot})),[Ue]),Sa=f.useMemo(()=>Ue.map(e=>({type:e.data.kind,slot:e.data.slot})),[Ue]),Ur=f.useMemo(()=>Bi(wt,{viewportWidth:_t.width,viewportHeight:_t.height,zoom:Te}),[wt,_t.height,_t.width,Te]),Tt=f.useMemo(()=>No?Bi(wt,{preview:No,viewportWidth:_t.width,viewportHeight:_t.height,zoom:Te}):Ur,[wt,Ur,_t.height,_t.width,Te,No]),$n=f.useMemo(()=>Rm(Tt,Te),[Tt,Te]),Dc=f.useMemo(()=>Pm(Mm(Sa,Tt.rowCount)),[Sa,Tt.rowCount]),Oc=f.useMemo(()=>({"--notebook-detail-scale":Hi(Te),width:$n.width,height:$n.height}),[$n.height,$n.width,Te]),Vc=f.useMemo(()=>Tm(Tt,Te),[Tt,Te]),Gc=f.useCallback(()=>{k==="notebook"&&jm(()=>Wt.current)},[Wt,k]),Be=f.useCallback(()=>{if(da(),Ar.current?.({status:"cancelled",message:"Pending action cancelled on screen."}),_?.kind==="chain-step"&&i){const e=_.chainId;Ot("videobook.active-chain",""),b("chain",{action:"cancel",book_id:i,chain_id:e}).catch(()=>{})}de(null),V(null),qe(null),go()},[i,b,da,go,_]),Wc=f.useCallback(e=>{V(t=>t?.kind!=="routed"||t.plan.tool!=="post"&&t.plan.routedTool!=="post"?t:{...t,plan:{...t.plan,params:$m(t.plan.params,e)}})},[]),Uc=f.useCallback(e=>{V(t=>{if(t?.kind!=="routed"||!t.xPostReview)return t;const o={...t.xPostReview,options:{...t.xPostReview.options,...e}};return{...t,xPostReview:o,plan:{...t.plan,params:dn(t.plan.params,eo(o))}}})},[]),xa=f.useCallback(e=>{V(t=>{if(t?.kind!=="routed"||!t.xPostReview)return t;const o=qm(t.xPostReview,e);return o===t.xPostReview?t:{...t,xPostReview:o,plan:{...t.plan,params:dn(t.plan.params,eo(o))}}})},[]),Bc=f.useCallback((e,t)=>{V(o=>{if(o?.kind!=="routed"||!o.xPostReview)return o;const n={...o.xPostReview,promptOverrides:{...o.xPostReview.promptOverrides,[e]:t}};return{...o,xPostReview:n,plan:{...o.plan,params:dn(o.plan.params,eo(n))}}})},[]),Hc=f.useCallback(e=>{V(t=>{if(t?.kind!=="routed"||!t.xPostReview)return t;const o={...t.xPostReview,creditsOverride:e};return{...t,xPostReview:o,plan:{...t.plan,params:dn(t.plan.params,eo(o))}}})},[]),zc=f.useCallback(e=>{V(t=>{if(t?.kind!=="split")return t;const o=t.expectations[0]?.address??"video",n={...t.command,cutPointsSeconds:e.cutPointsSeconds,outputMode:e.outputMode,selectedChunkIndexes:[e.selectedIndex]};return{...t,command:n,summary:zi({cutPointsSeconds:n.cutPointsSeconds,outputMode:n.outputMode,selectedChunkIndexes:n.selectedChunkIndexes,sourceAddress:o,sourceDurationSeconds:t.sourceDurationSeconds})}})},[]),Br=f.useCallback(async(e,t,o)=>{if(!i)throw new Error("Open a book before previewing generation.");return await b("preview_notebook_generation",{book_id:i,notebook_id:t.id,cell_id:e.cell.id,draft:{type:e.cell.type,...e.cell.label===void 0?{}:{label:e.cell.label},slot:e.cell.slot,prompt:Nm(e,t),provider:e.cell.provider??e.action.provider,model:e.cell.model??e.action.model,operation:e.cell.operation??e.action.operation,tool:e.cell.tool??e.action.tool,inputs:e.cell.inputs??{}},connections:e.connections.map(n=>({source_cell_id:n.sourceCellId,target_input:n.targetInput}))},{chat:o,background:!0})},[i,b]),ho=f.useRef(0);f.useEffect(()=>()=>{ho.current+=1},[i,c?.id]);const jt=f.useCallback((e,t,o)=>{const n=++ho.current,r=JSON.stringify({id:e.cell.id,prompt:e.cell.prompt,action:e.action.id,inputs:e.cell.inputs,connections:e.connections});M(o,()=>V(s=>s?.kind==="generation"&&s.draft.cell.id===e.cell.id?{...s,previewError:null,previewLoading:!0,previewStale:!0}:s)),Br(e,t,o).then(s=>{ho.current===n&&M(o,()=>V(a=>a?.kind!=="generation"?a:JSON.stringify({id:a.draft.cell.id,prompt:a.draft.cell.prompt,action:a.draft.action.id,inputs:a.draft.cell.inputs,connections:a.draft.connections})===r?{...a,preview:s,previewError:null,previewLoading:!1,previewStale:!1}:a))}).catch(s=>{ho.current===n&&M(o,()=>V(a=>a?.kind!=="generation"?a:JSON.stringify({id:a.draft.cell.id,prompt:a.draft.cell.prompt,action:a.draft.action.id,inputs:a.draft.cell.inputs,connections:a.draft.connections})===r?{...a,previewError:s instanceof Error?s.message:String(s),previewLoading:!1,previewStale:!1}:a))})},[Br]),$t=Lm(jt,`${i}:${c?.id}:${W?.cell.id}`),ht=f.useCallback((e,t)=>{ho.current+=1,$t.cancel(),V(o=>o?.kind==="generation"&&o.draft.cell.id===e.cell.id?{...o,draft:e,previewError:null,previewLoading:!1,previewStale:!0}:o),c&&(t?jt(e,c):$t.schedule(e,c))},[c,$t,jt]),Ea=f.useCallback(e=>{W&&ht(Qn(W,e),!1)},[W,ht]),Kc=Fm({call:p.state==="ready"?b:void 0,bookId:i??"",surface:W?Dm(W.cell.type):null,prompt:W?.cell.prompt??"",onApply:Ea}),Xc=f.useCallback(e=>{if(!W)return;const t=Go.find(o=>o.id===e);t&&ht(Ki(W,t,gt),!0)},[Go,gt,W,ht]),Jc=f.useCallback(e=>{W&&ht(Om(W,e,gt),!0)},[gt,W,ht]),Qc=f.useCallback((e,t)=>{W&&ht(hs(W,e,t),!0)},[W,ht]),Yc=f.useCallback(()=>{!W||!c||($t.cancel(),jt(W,c))},[c,W,$t,jt]),Zc=f.useCallback(e=>{Y(e),no("selection")&&ke(!0)},[Y]),qn=f.useCallback(e=>{if(!W||!c)return;let t;try{t=Vm({actions:Je,draft:W,document:c,sourceCellIds:e})}catch(r){h(r instanceof Error?r.message:String(r),"error");return}const o=[...t.sourceCellIds.flatMap(r=>{const s=c.cells.find(a=>a.id===r);return s?[{address:U(s.slot),cellId:s.id}]:[]}),{address:U(t.cell.slot),cellId:null}],n=t.sourceAddresses.length>0?` from ${t.sourceAddresses.join(", ")}`:"";V(r=>r?.kind==="generation"&&r.draft.cell.id===t.cell.id?{...r,draft:t,expectations:o,previewError:null,previewLoading:!1,previewStale:!0,summary:`Generate ${Ds(t.cell.type)} as ${U(t.cell.slot)}${n}`}:r),$t.cancel(),jt(t,c)},[Je,c,W,$t,jt,h]),ed=f.useCallback(e=>{W&&qn([...W.sourceCellIds,e])},[W,qn]),td=f.useCallback(e=>{W&&qn(W.sourceCellIds.filter(t=>t!==e))},[W,qn]),Hr=f.useMemo(()=>{const e=Uo.target??Uo.sources[0]??null;return e?Al(e)?.row??null:null},[Uo]);f.useEffect(()=>{k!=="notebook"||Hr===null||Gm(()=>Wt.current,{row:Hr,zoom:Te},{reducedMotion:typeof window<"u"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches})},[Wt,Te,Hr,k]);const ie=f.useMemo(()=>Mt.find(e=>e.id===Me)??null,[Mt,Me]),q=f.useMemo(()=>c?.cells.find(e=>e.id===Me)??null,[c,Me]),vt=f.useMemo(()=>(c?.cells??[]).filter(e=>vn.has(e.id)).sort((e,t)=>e.slot.row-t.slot.row||e.slot.column-t.slot.column),[c,vn]),tn=f.useMemo(()=>new Map((c?.cells??[]).flatMap(e=>{const t=Wm(re,e.outputArtifactId);return t?[[e.id,t]]:[]})),[re,c]),od=f.useMemo(()=>new Set([...tn].flatMap(([e,t])=>t.type==="video"||t.type==="final"?[e]:[])),[tn]),_a=f.useMemo(()=>new Set([...tn].flatMap(([e,t])=>t.type==="image"?[e]:[])),[tn]),Aa=c&&q?Um(c,q.id).error??so[q.id]??null:null,Ra=f.useMemo(()=>De.map(Wi),[De]),zr=q?Bm({cell:q,cells:c?.cells??[],edges:c?.edges??[],queuedCellIds:In,runErrors:so,error:Aa,jobs:Ra}):null,nd=f.useMemo(()=>!q||q.type!=="audio"&&q.type!=="image"&&q.type!=="video"&&q.type!=="analysis"?[]:Hm(q.inputs,q.outputArtifactId).flatMap(e=>{const t=re.get(e);return t?[t]:[]}),[re,q]),rd=f.useMemo(()=>{if(!c||!q)return null;try{const e=It(c,q.id),t=rr(c,e),o=t?re.get(t):void 0,n=o?.duration??ae(e.inputs?.durationSeconds);return!o?.mediaUrl||!n||n<1?null:{source:e,asset:o,duration:n}}catch{return null}},[re,c,q]),Pa=f.useMemo(()=>{if(!c||_?.kind!=="split")return null;try{const e=It(c,_.command.sourceReference),t=rr(c,e),o=t?re.get(t):void 0,n=o?.duration??ae(e.inputs?.durationSeconds);if(!o?.mediaUrl||!n||n<1)return null;const r=un.maximumRowCount*un.columnCount;return{availableEmptyCells:Math.max(0,r-c.cells.length),cutPointsSeconds:_.command.cutPointsSeconds,mediaUrl:o.mediaUrl,outputMode:_.command.outputMode??"all",selectedIndex:_.command.selectedChunkIndexes?.[0]??0,sourceDurationSeconds:n,sourceFps:o.fps,sourceLabel:U(e.slot)}}catch{return null}},[re,c,_]),sd=q?hr[q.id]:void 0,ad=f.useCallback(async(e,t)=>{if(!i||!c)throw new Error("Notebook is not ready");return await b("preview_notebook_generation",{book_id:i,notebook_id:c.id,cell_id:e,draft:t},{background:!0})},[i,b,c]),id=f.useCallback(async e=>{if(!i)throw new Error("Book is not ready");const o=await b("inspect_generation_request",{book_id:i,asset_id:e},{background:!0});if(o.payload==null)throw new Error("No generation payload recorded for this attempt");return o.payload},[i,b]),ld=f.useCallback(async e=>{if(!i)throw new Error("Book is not ready");const t=await b("inspect_generation_request",{book_id:i,asset_id:e},{background:!0});return zm(t)},[i,b]),Nn=f.useCallback((e,t)=>{dc(o=>({...o,[e]:{...o[e]??Xi,...t}}))},[]),Ma=f.useCallback(async e=>{const t=Date.now()+Vb;for(;Date.now()<t;){await ot(Ob);const o=Q.current;if(o.bookId!==e.bookId||o.notebookId!==e.notebookId)return{kind:"continue"};const n=performance.now(),[r,s,a]=await Promise.all([Pe.current("get_notebook",{book_id:e.bookId,notebook_id:e.notebookId},{background:!0}),Pe.current("list_assets",{book_id:e.bookId,sort:"newest",limit:200,include_referenced:!0},{background:!0}),Pe.current("list_jobs",{book_id:e.bookId,limit:200},{background:!0})]),l=pe(r),m=Lt(s),u=to(a);l&&n>=ye.current&&(ye.current=n,Xe(S=>Nt(S,m)?S:m),at(u),Ie(l,m,u));const w=m.find(S=>S.artifactId===e.artifactId),v=Km({insight:e.insight,artifactId:e.artifactId,since:e.since,hasInsight:Ol(w,e.insight),hadInsight:e.hadInsight,jobs:u});if(v.kind!=="continue")return v}return{kind:"failed",message:e.insight==="transcript"?"Transcription did not finish in time. Check the jobs screen.":"Video analysis did not finish in time. Check the jobs screen."}},[at,Ie]),Ta=f.useCallback(async(e,t)=>{const o=c?.id;if(!i||!o)return;const n=vr[e]??Xi;if(Xm(n,t))return;const r=Ol(Q.current.assets.find(a=>a.artifactId===e),t),s=Date.now();Nn(e,{...vs(t,!0),error:null});try{await b(t==="transcript"?"transcribe":"analyze_video",t==="transcript"?{book_id:i,asset_id:e}:{book_id:i,asset_id:e,force:r},{background:!0});const a=await Ma({bookId:i,notebookId:o,artifactId:e,insight:t,since:s,hadInsight:r});Nn(e,{...vs(t,!1),error:a.kind==="failed"?a.message:null})}catch(a){Nn(e,{...vs(t,!1),error:a instanceof Error?a.message:String(a)})}},[i,b,vr,c,Nn,Ma]),cd=f.useCallback(e=>{Ta(e,"transcript")},[Ta]),dd=f.useCallback(async(e,t)=>{if(!i)throw new Error("Book is not ready");const o=await b("read_transcript",{book_id:i,asset_id:e,raw:!0,source:t},{background:!0}),n=D(o),r=typeof n?.text=="string"?n.text:null,s=A(n?.file);if(!r||!s)throw new Error("No transcript sidecar for this asset");return{text:r,file:s}},[i,b]),ud=f.useCallback(e=>{i&&b("export_transcript_srt",{book_id:i,asset_id:e}).then(t=>{const o=D(t),n=A(o?.path);h(n?`Saved ${n}`:"Saved SRT to Downloads")}).catch(t=>{h(t instanceof Error?t.message:String(t),"error")})},[i,b,h]),je=f.useCallback(async(e,t,o)=>{const n=await b("get_notebook",{book_id:e,notebook_id:t},{background:!0,chat:o}),r=pe(n);if(!r)throw new Error("The server returned an invalid notebook");if(o&&!o.isInScope())throw new Error("Workspace changed while refreshing the notebook.");return Ie(r,z,De,e),r},[Ie,z,b,De]),N=f.useCallback(async(e,t,o,n)=>{if(o?.()===!1||n&&!n.isInScope())return;const r=Tr.current+1;Tr.current=r;const s=await Ji(async()=>await Promise.all([b("list_notebooks",{book_id:e},{background:!0,chat:n}),b("list_assets",{book_id:e,sort:"newest",limit:200,include_referenced:!0},{background:!0,chat:n}),b("get_primary_sequence",{book_id:e},{background:!0,chat:n}),b("list_jobs",{book_id:e,limit:200},{background:!0,chat:n}),b("list_notebook_actions",{book_id:e},{background:!0,chat:n})]),()=>Tr.current===r&&o?.()!==!1&&(!n||n.isInScope()));if(s.kind==="stale")return;if(s.kind==="error")throw s.error;const[a,l,m,u,w]=s.value,v=Qi(a),S=Lt(l),E=to(u),y=kn(`videobook.active-notebook:${e}`),R=v.find($=>$.id===t)??v.find($=>$.id===y)??v[0]??null;if(K(e),Ot("videobook.active-book",e),Xe(S),Ee(Ke(m)),Vs(E),Hs(Jm(w)),Gs(Date.now()),!R){xe(null),bt([]),Pn([]);return}return Ot(`videobook.active-notebook:${e}`,R.id),Ie(R,S,E,e),jn(e,R,S),R.cells.some($=>$.type==="goal")&&ka({bookId:e,notebookId:R.id}).catch(()=>{}),R},[Ie,b,ka,jn]),Kr=e=>{tt("notebook"),Qt(e),ao(e)},fd=async(e="",t)=>{if(!i||!c)return{ok:!1,message:"Open a notebook first."};if(!e)return fo?(Kr(fo.cellId),{ok:!0,message:`Opened goal ${fo.address??""}`.trim()}):{ok:!1,message:"Mention the reference images or videos, for example /goal @a1 @a2 as a short clip."};if(Uk(e).length===0)return{ok:!1,message:"Mention the reference images or videos, for example /goal @a1 @a2 as a short clip"};const o={bookId:i,notebookId:c.id},n=await ba(o,{action:"create",brief:e,request_id:Ct()},t);return Q.current.bookId!==o.bookId||Q.current.notebookId!==o.notebookId||t?.isCurrent()===!1?{ok:!0,message:"Goal saved in its notebook."}:(await N(o.bookId,o.notebookId,void 0,t),ao(n.cellId),se(t),Kr(n.cellId),{ok:!0,message:`Planning your video goal in ${n.address??"a new tile"}`})},md=async e=>{if(!Bo)throw new Error("Open the goal notebook first.");const t=Bo,o=await ba(t,e);return e.action==="combine"?(await N(t.bookId,t.notebookId),o):(e.action!=="approve"&&e.action!=="regenerate"&&e.action!=="revise"&&e.action!=="retry"||(Q.current.bookId===t.bookId&&Q.current.notebookId===t.notebookId&&se(),await N(t.bookId,t.notebookId)),o)},pd=async e=>{if(!Bo)return;const t=Bo,n=(await N(t.bookId,t.notebookId,()=>Q.current.bookId===t.bookId&&Q.current.notebookId===t.notebookId))?.cells.find(r=>r.type==="timeline");if(!n)throw new Error("Add a timeline cell to preview the assembled sequence.");fs(n.id,e)},it=f.useCallback((e,t,o=!1)=>{qo(n=>n?.key===e?{...n,subjectMap:t,subjectMapLoading:o}:n)},[]),Ln=f.useCallback(async(e,t,o)=>{const n=await Qm({initialMap:o,read:async()=>qs(e,await b("get_image_subject_map",{book_id:e.bookId,artifact_id:e.asset.artifactId,object_hash:e.asset.objectHash},{background:!0})),publish:r=>it(e.key,r),isCurrent:()=>We.current===t});n.kind==="stale"||n.kind==="terminal"||We.current!==t||it(e.key,Ns(e,n.kind==="timeout"?new Error("Subject analysis did not finish within 27 minutes. Retry to check or restart it."):n.error,n.map))},[b,it]),Fn=f.useCallback((e,t,o,n="view")=>{if(!i||!c)return;const r={mode:n,initialInstruction:ta.current.get(i)??kn(`videobook.image-edit-instruction:${i}`),key:[i,c.id,e.id,t.artifactId,t.objectHash].join(":"),bookId:i,notebookId:c.id,cellId:e.id,address:Se(e.slot),asset:t,returnFocus:o??(document.activeElement instanceof HTMLElement?document.activeElement:null),subjectMap:null,subjectMapLoading:t.type==="image"&&!!t.objectHash};Ym(document.querySelector(".command-composer")),mt.current+=1,Et(null),Vt(null);const s=We.current+1;We.current=s,Ir(null),Cr(!1),qo(r),ke(!0),t.type==="image"&&zo.ensureLoaded(i),!(t.type!=="image"||!t.objectHash)&&b("get_image_subject_map",{book_id:i,artifact_id:t.artifactId,object_hash:t.objectHash},{background:!0}).then(a=>{if(We.current!==s)return;const l=qs(r,a);it(r.key,l),l.status==="analyzing"&&Ln(r,s,l)}).catch(a=>{We.current===s&&it(r.key,Ns(r,a))})},[i,b,zo,c,it,Ln]),Kt=f.useCallback(()=>{mt.current+=1,Et(null),Vt(null),We.current+=1,Ir(null),Cr(!1),qo(null)},[]),gd=async(e,t)=>{const o=D(await b("extract_notebook_frame",{book_id:e.bookId,notebook_id:e.notebookId,source_cell_id:e.cellId,frame_mode:"time",timestamp_seconds:Math.round(t*1e3)/1e3})),n=A(o?.cell_id),r=A(o?.address),s=A(o?.run_id),a=A(o?.job_id);if(!n||!r||!s||!a)throw new Error("The server did not return the frame extraction cell");return se(),ne(n,null),oe(n,!0),Pt({bookId:e.bookId,notebookId:e.notebookId,cellId:n,address:r.replace(/^@/,""),runId:s,jobOperationId:a,intervalMs:mn,timeoutMs:pn,maxPollFailures:ar}).then(l=>{if(l.kind==="failed"||l.kind==="timeout"){const m=l.message??`Frame extraction into ${r} failed`;ne(n,m),h(m,"error")}}).finally(()=>{oe(n,!1)}),r},kd=f.useCallback(async(e,t=!1)=>{if(!e.asset.objectHash)throw new Error("This image does not expose an immutable object hash");if(!sr({provider:"kie",model:"seedream/5-pro-layer-decomposition",tool:"analyze_image_subjects"}))return;const o=We.current+1;We.current=o,it(e.key,{status:"analyzing",artifactId:e.asset.artifactId,objectHash:e.asset.objectHash,width:e.asset.width,height:e.asset.height,baseUrl:e.subjectMap?.baseUrl??null,jobId:null,startedAt:new Date().toISOString(),error:null,subjects:e.subjectMap?.subjects??[]},!0);try{const n=await b("analyze_image_subjects",{book_id:e.bookId,artifact_id:e.asset.artifactId,object_hash:e.asset.objectHash,...t?{force:!0}:{}});if(We.current!==o)return;const r=qs(e,n);it(e.key,r),r.status==="analyzing"&&Ln(e,o,r)}catch(n){throw We.current===o&&it(e.key,Ns(e,n)),n}},[b,it,Ln]),Dn=f.useCallback(async(e,t,o)=>{if(!e.asset.objectHash)throw new Error("This image does not expose an immutable object hash");if(i!==e.bookId)throw new Error("The active book changed while the image editor was open");if(Q.current.notebookId!==e.notebookId)throw new Error("The active notebook changed while the image editor was open");const n=t.model??Zm,r=n.startsWith("fal-ai/")||n.startsWith("alibaba/")?"fal":"kie";if((t.operation!=="remove"||(t.editRegions?.length??0)>0)&&!sr({provider:r,model:n,tool:"edit_image_subjects"}))return!1;const s=We.current,a=()=>{const v=Q.current;return We.current===s&&v.bookId===e.bookId&&v.notebookId===e.notebookId},l=await Ji(async()=>await b("edit_image_subjects",{book_id:e.bookId,notebook_id:e.notebookId,source_cell_id:e.cellId,artifact_id:e.asset.artifactId,object_hash:e.asset.objectHash,...t.subjectIds.length>0?{subject_ids:t.subjectIds}:{},operation:t.operation,...t.model?{model:t.model}:{},...t.prompt?{prompt:t.prompt}:{},...t.editRegions?.length?{edit_regions:t.editRegions}:{},...t.regions&&t.regions.length>0?{regions:t.regions.map(v=>({replacement_artifact_id:v.replacementArtifactId,...v.box?{box:v.box}:{},...v.subjectId?{subject_id:v.subjectId}:{},...v.note?{note:v.note}:{}}))}:{}},{chat:o}),a);if(l.kind==="stale")return!1;if(l.kind==="error")throw l.error;const m=l.value,u=A(D(m)?.status)??"queued";M(o,()=>h(t.operation==="remove"?`${t.editRegions?.length?"Region":"Subject"} removal ${u}`:t.operation==="replace"?`Region replacement ${u}`:t.operation==="whole_image"?`Whole-image edit ${u}`:`${t.editRegions?.length?"Region":"Subject"} edit ${u}`)),await N(e.bookId,e.notebookId,a,o).catch(()=>{});const w=A(D(m)?.producer_cell_id);return w&&a()&&M(o,()=>{Kt(),Y(w,o),Ne(null),pt(null),se(o),ao(w)}),!0},[i,b,Kt,se,N,ao,Y,h]),vo=f.useCallback(async()=>{const e=await b("list_books",{sort:"newest"}),t=ep(e);return j(t),t},[b]),bd=f.useCallback(async(e,t=!1)=>{const o=`@${e.id}`;if(e.owningBookId!==i)return h(`Open ${e.owningBookName} to forget ${o}`,"error"),{ok:!1,message:`Open ${e.owningBookName} first`};if(!t&&!window.confirm(tp(o)))return{ok:!1,message:"Forget cancelled"};T(!0);try{let n=Yi(await b("delete_asset",{book_id:i,asset_id:e.artifactId,forget:!0}));if(n.status==="in_use"){if(!window.confirm(ys(o,n.references)))return{ok:!1,message:"Forget cancelled; media is still in use"};n=Yi(await b("delete_asset",{book_id:i,asset_id:e.artifactId,forget:!0,clear_references:!0}))}return n.status==="in_use"?(h(ys(o,n.references).split(`
|
|
9
|
+
`)[0],"error"),{ok:!1,message:ys(o,n.references).split(`
|
|
10
|
+
`)[0]}):(h(Zi(o,n)),await N(i,c?.id),await vo(),{ok:!0,message:Zi(o,n)})}catch(n){return h(n instanceof Error?n.message:String(n),"error"),{ok:!1,message:n instanceof Error?n.message:String(n)}}finally{T(!1)}},[i,b,c?.id,N,vo,h]),yo=f.useCallback(async()=>{const[e,t]=await Promise.all([b("slash_commands",{detail:"full"}),b("list_workspace_actions",{detail:"full"})]),o=Is(t);dr(o.actions),Jl(Cs(o.actions,op(e)))},[b]),Ce=async(e,t,o,n,r)=>{if(p.state!=="ready")return;ke(!0);const s=document.activeElement instanceof HTMLElement?document.activeElement:null,a=n??$e?.opener??(s===document.body||s?.closest(".command-composer")?document.querySelector('[aria-label="Videobook command input"]'):s),l=typeof t?.book_id=="string"?t.book_id:i,m=++mt.current;if(e)Et(null),Qe({key:m,actionId:e,values:t,query:o,opener:a});else{const u=l===i&&te?.asset.type==="image"?`image-edit:${te.key}`:`chat:${l}`;Qe(null),Et({key:m,query:o??"",values:t,bookId:l,session:u}),Vt({bookId:l,session:u,opener:a})}fr({loading:!0,error:null});try{const u=e&&xt.length?{actions:xt}:Is(await b("list_workspace_actions",{detail:"full"},{chat:r}));if(m!==mt.current||r&&!r.isCurrent())return;dr(u.actions);const w=u.actions.find(v=>v.id===e);if(w){const v=t?.asset_id??t?.artifact_id,S={...Xp(w,{...ln,assetId:typeof v=="string"?v:ln.assetId}),...t};w.handler.kind==="tool"&&w.handler.tool==="create_notebook_cell"&&t?.slot&&(S.cell={...D(S.cell),slot:t.slot});const E=await Jp(w,S,($,F)=>b($,{book_id:S.book_id??i,...F},{chat:r}));if(m!==mt.current||r&&!r.isCurrent())return;const R=w.handler.kind==="tool"&&["list_notebooks","list_entities","list_book_actions","search_archive"].includes(w.handler.tool)&&w.handler.kind==="tool"?{message:`${w.title} loaded`,value:await b(w.handler.tool,S,{chat:r})}:void 0;if(m!==mt.current||r&&!r.isCurrent())return;Qe($=>$?.key===m?{...$,values:{...S,...E.values},resources:E,result:R}:$)}fr({loading:!1,error:null})}catch(u){if(m!==mt.current||r&&!r.isCurrent())return;fr({loading:!1,error:u instanceof Error?u.message:String(u)})}},ja=()=>{mt.current+=1;const e=wn?.opener;Et(null),Vt(null),Vi(()=>e?.isConnected?e:null)},On=f.useCallback(async()=>{const e=np(await b("list_chat_models",{})),t=kn("videobook.chat-model");tc(e),Bs(o=>{const n=bs(e,t||o);return Ot("videobook.chat-model",n),n})},[b]),wd=f.useCallback(async()=>{await Promise.all([yo(),On()])},[yo,On]),hd=f.useCallback(e=>{const t=bs(pr,e);Bs(t),Ot("videobook.chat-model",t)},[pr]),Io=f.useCallback(async()=>{try{return await yo(),null}catch(e){return e instanceof Error?e.message:String(e)}},[yo]),vd=f.useCallback(async e=>{T(!0);try{const[t]=await Promise.all([vo(),yo(),On()]),o=rp(t,e??i);o?(await N(o.bookId),h(`Loaded ${o.name}`)):(K(""),xe(null),Xe([]),Hs([]),Ee(null),bt([]),Pn([]),h("No videobook projects are available."))}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}},[i,yo,N,vo,On,h]),Co=f.useCallback(async()=>{const e=Oo.current+1;Oo.current=e,xr(!0),Er(!0),_r(null);try{return await vo(),{ok:!0}}catch(t){const o=gn(t);return Oo.current===e&&_r(o.error),h(o.error,"error"),o}finally{Oo.current===e&&Er(!1)}},[vo,h]),Xt=f.useCallback(e=>{if(e){Co();return}Oo.current+=1,xr(!1),Er(!1),_r(null)},[Co]),yd=f.useCallback(()=>{Co()},[Co]),tt=f.useCallback(e=>{I(e);const t=sp(e);window.location.pathname!==t&&window.history.pushState({},"",t)},[]);f.useEffect(()=>{document.title=ap(k)},[k]),f.useEffect(()=>{const e=()=>{const t=ji(window.location.pathname);I(t)};return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)},[]);const $a=f.useCallback(async e=>{T(!0);try{await N(e);const t=x.find(o=>o.bookId===e);return h(t?`Opened ${t.name}`:"Book opened"),tt("notebook"),Xt(!1),{ok:!0}}catch(t){const o=gn(t);return h(o.error,"error"),o}finally{T(!1)}},[x,Xt,N,h,tt]),qa=f.useCallback(async e=>{T(!0);try{const t=el(await b("create_book",{name:e}));if(!t)throw new Error("The server returned an invalid project");j(n=>[t,...n.filter(r=>r.bookId!==t.bookId)]),await N(t.bookId);const o=await Io();return tt("notebook"),Xt(!1),h(o?`Created ${t.name}; commands could not refresh: ${o}`:`Created ${t.name}`),{ok:!0}}catch(t){const o=gn(t);return h(o.error,"error"),o}finally{T(!1)}},[b,Xt,Io,N,h,tt]),Na=f.useCallback(async(e,t)=>{T(!0);try{const o=el(await b("rename_book",{book_id:e,name:t}));if(!o)throw new Error("The server returned an invalid project");j(r=>r.map(s=>s.bookId===e?o:s));const n=await Io();return h(n?`Renamed to ${o.name}; commands could not refresh: ${n}`:`Renamed to ${o.name}`),{ok:!0}}catch(o){const n=gn(o);return h(n.error,"error"),n}finally{T(!1)}},[b,Io,h]),La=f.useCallback(async(e,t)=>{if(x.length<2)return{ok:!1,error:"Create another project before deleting this one"};const o=x.find(r=>r.bookId===e),n=x.find(r=>r.bookId!==e);if(!o||!n)return{ok:!1,error:"The selected project is no longer available"};T(!0);try{await b("delete_book",{book_id:e,confirm_name:t}),j(s=>s.filter(a=>a.bookId!==e)),e===i&&(await N(n.bookId),tt("notebook"),Xt(!1));const r=await Io();return h(r?`Deleted ${o.name}; commands could not refresh: ${r}`:`Deleted ${o.name}`),{ok:!0}}catch(r){const s=gn(r);return h(s.error,"error"),s}finally{T(!1)}},[i,x,b,Xt,Io,N,h,tt]),on=c?.posts?.find(e=>e.id===Me),Fa=async e=>{if(!(!i||!c||p.state!=="ready")){T(!0);try{const t=await b("create_post",{book_id:i,notebook_id:c.id,...e?{source_cell_id:e}:{}});await N(i,c.id),Qt(t.id),h(`Created Post ${t.address}`)}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Xr=async(e,t)=>{if(!i||!c)return;if(e==="post"){const r=c.cells.find(s=>s.id===Me&&s.type!=="post"&&s.outputArtifactId&&["image","video","generate_image","generate_video","concat","splice","split_video"].includes(s.type));await Fa(r?.id);return}const o=e==="timeline"?c.cells.find(r=>r.type==="timeline"):null;if(o){Y(o.id),ke(!0),document.querySelector(`[data-id="${o.id}"]`)?.scrollIntoView({block:"nearest",inline:"nearest"});return}let n;try{n=t?ll(t,Ur):Mo(e,c.cells,Ve),e==="timeline"&&(n={row:n.row,column:0});const r=new Set(_l({type:e,slot:n}).map(cl));if(wt.some(s=>r.has(cl(s)))){h(e==="timeline"?"Choose a completely empty row for Timeline":"Choose an empty grid square for the new cell","error");return}}catch(r){h(r instanceof Error?r.message:String(r),"error");return}T(!0);try{const r=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:{type:e,slot:n,...e==="prompt"||e==="analyze"||oo(e)?{prompt:""}:{}}})),s=await N(i,c.id);_e(n),e==="timeline"&&typeof r?.id=="string"&&(Y(r.id),requestAnimationFrame(()=>document.querySelector(`[data-id="${r.id}"]`)?.scrollIntoView({block:"nearest",inline:"nearest"}))),Ft(e)&&typeof r?.id=="string"?xo(r.id,s):se(),h(`Added ${U(n)} cell`)}catch(r){h(r instanceof Error?r.message:String(r),"error")}finally{T(!1)}},Id=async e=>{if(!i||!c||!ie)return!1;T(!0);try{return await b("update_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:ie.id,cell:e}),await je(i,c.id),_e(ie.data.slot),h("Cell saved"),!0}catch(t){return h(t instanceof Error?t.message:String(t),"error"),!1}finally{T(!1)}},Cd=async(e,t)=>{if(!i||!c||!q)return;const o=c.edges.some(n=>n.target===q.id&&n.targetInput===e);T(!0);try{await b("set_notebook_cell_input",{book_id:i,notebook_id:c.id,target_cell_id:q.id,target_input:e,source_cell_id:t}),await je(i,c.id),h(t?o?"Input source replaced":"Input source attached":"Input source cleared")}catch(n){h(n instanceof Error?n.message:String(n),"error")}finally{T(!1)}},So=async(e,t)=>{if(!i||!c||e.length===0)return;const o=[...new Map(e.map(w=>[w.id,w])).values()],n=new Set(o.map(w=>w.id)),r=o.map(w=>U(w.slot)),s=o.length,a=new Set(Mt.filter(w=>w.data.status==="error").map(w=>w.id));if((t?.confirm??o.some(w=>!a.has(w.id)))&&!window.confirm(s===1?`Delete ${r[0]}?
|
|
11
|
+
|
|
12
|
+
This removes the cell and its connections. This cannot be undone.`:`Delete ${s} selected cells?
|
|
13
|
+
|
|
14
|
+
${r.join(", ")}
|
|
15
|
+
|
|
16
|
+
This removes the cells and their connections. This cannot be undone.`))return;const m=new Set,u=()=>{const w=vt.map(v=>v.id).filter(v=>!m.has(v)).at(-1)??null;bo(new Set([...st.current].filter(v=>!m.has(v)))),$o(v=>v&&!m.has(v)?v:w),Ne(v=>v&&m.has(v)?null:v)};Ys(n),bt(w=>w.map(v=>n.has(v.id)?{...v,data:{...v.data,deleting:!0}}:v)),T(!0);try{await ot(180);for(const w of o)await b("delete_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:w.id}),m.add(w.id);te&&m.has(te.cellId)&&Kt(),await N(i,c.id),u(),h(s===1?`${r[0]} deleted`:`${s} cells deleted`)}catch(w){te&&m.has(te.cellId)&&Kt(),await N(i,c.id).catch(()=>{}),u();const v=w instanceof Error?w.message:String(w);h(m.size>0?`Deleted ${m.size} of ${s} cells. ${v}`:v,"error")}finally{bt(w=>w.map(v=>n.has(v.id)?{...v,data:{...v.data,deleting:!1}}:v)),Ys(new Set),T(!1)}},Sd=async()=>{q&&await So([q])},Da=async()=>{await So(vt)},xd=e=>{if(e.key!=="Backspace"&&e.key!=="Delete")return;const t=e.target;t instanceof HTMLElement&&t.closest('input, textarea, select, button, a, [contenteditable="true"]')||G||vt.length===0||(e.preventDefault(),e.stopPropagation(),Da())},Ed=async e=>{if(!(!i||!c))try{await b("move_notebook_cells",{book_id:i,notebook_id:c.id,slots:e.map(t=>({id:t.id,row:t.data.slot.row,column:t.data.slot.column}))}),await je(i,c.id)}catch(t){const o=t instanceof Error?t.message:String(t);await je(i,c.id).catch(()=>{}),h(o,"error")}},_d=async()=>{if(!(!i||!c||c.cells.length===0)){T(!0);try{const e=pe(await b("get_notebook",{book_id:i,notebook_id:c.id}));if(!e)throw new Error("Unable to read the notebook before arranging");if(Q.current.bookId!==i||Q.current.notebookId!==c.id)return;const t=zp(e);if(!t.ok)throw new Error(t.message);const o=new Map(e.cells.map(a=>[a.id,a.slot])),n=t.slots.some(a=>{const l=o.get(a.id);return l?.row!==a.row||l?.column!==a.column}),r=()=>Kp(()=>Wt.current);if(!n){await je(i,c.id),h("Notebook is already auto-arranged"),r();return}await b("move_notebook_cells",{book_id:i,notebook_id:c.id,...e.revision?{expected_revision:e.revision}:{},slots:t.slots}),await je(i,c.id);const s=Me?t.slots.find(a=>a.id===Me):void 0;s&&_e({row:s.row,column:s.column}),h(`Auto-arranged ${t.slots.length} ${t.slots.length===1?"tile":"tiles"}`),r()}catch(e){await je(i,c.id).catch(()=>{}),h(e instanceof Error?e.message:String(e),"error")}finally{T(!1)}}},Ad=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"No notebook is open"};const n=Sk(c,od,t,e);if(!n.ok)return M(o,()=>h(n.message,"error")),{ok:!1,message:n.message};const r=e==="column"?`column ${t.column+1}`:`row ${String.fromCharCode(97+t.row)}`;if(n.movedCount===0){const a=`Videos are already arranged in ${r}`;return M(o,()=>h(a)),{ok:!0,message:a}}const s=A(D(c)?.revision);T(!0);try{await b("move_notebook_cells",{book_id:i,notebook_id:c.id,...s?{expected_revision:s}:{},slots:n.slots},{chat:o}),await je(i,c.id,o),_e({row:t.row,column:t.column});const a=n.slots.length-n.displacedCount,l=`Arranged ${a} ${a===1?"video":"videos"} in ${r}`;return M(o,()=>h(l)),{ok:!0,message:l}}catch(a){await je(i,c.id,o).catch(()=>{});const l=a instanceof Error?a.message:String(a);return M(o,()=>h(l,"error")),{ok:!1,message:l}}finally{T(!1)}},Oa=async(e,t)=>{if(!i||!c)return{ok:!1,message:"No notebook is open"};const o=Ug(c,_a,e);if(!o.ok)return M(t,()=>h(o.message,"error")),{ok:!1,message:o.message};const n=U(e);if(o.movedCount===0){const s=`Images are already grouped from ${n}`;return M(t,()=>h(s)),{ok:!0,message:s}}const r=A(D(c)?.revision);T(!0);try{await b("move_notebook_cells",{book_id:i,notebook_id:c.id,...r?{expected_revision:r}:{},slots:o.slots},{chat:t}),await je(i,c.id,t),_e({row:e.row,column:e.column});const s=o.slots.length-o.displacedCount,a=`Grouped ${s} ${s===1?"image":"images"} from ${n}`;return M(t,()=>h(a)),{ok:!0,message:a}}catch(s){await je(i,c.id,t).catch(()=>{});const a=s instanceof Error?s.message:String(s);return M(t,()=>h(a,"error")),{ok:!1,message:a}}finally{T(!1)}},Rd=async e=>{if(!(!i||!c||!e.source||!e.target)){if(!sl(c.edges,e,c.cells)){const t=c.cells.find(n=>n.id===e.source),o=c.cells.find(n=>n.id===e.target);h(t&&o?`Connecting ${U(t.slot)} to ${U(o.slot)} would create a cycle`:"That connection would create a cycle","error");return}T(!0);try{await b("connect_notebook_cells",{book_id:i,notebook_id:c.id,source_cell_id:e.source,target_cell_id:e.target,target_input:dl(c,e)}),await je(i,c.id),h("Cells connected")}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Pd=async e=>{if(!(!i||!c||e.length===0))try{await Promise.all(e.map(t=>b("disconnect_notebook_cells",{book_id:i,notebook_id:c.id,edge_id:t}))),await je(i,c.id),h("Connection removed")}catch(t){h(t instanceof Error?t.message:String(t),"error")}},Va=async(e,t)=>{if(!i)throw new Error("Choose a book before uploading media");const o=await Ul(e),n=D(await b("check_duplicate_bytes",{book_id:i,object_hash:o})),s=(Array.isArray(n?.matches)?n.matches:[]).map(w=>D(w)).find(w=>{const v=w&&A(w.kind);return v!==null&&Fs(t,v)}),a=s&&A(s.artifact_id);if(a)return{artifactRef:a,reusedExisting:!0};const l=await fetch(`/api/books/${encodeURIComponent(i)}/upload?filename=${encodeURIComponent(e.name)}`,{method:"POST",body:e}),m=D(await l.json());if(!l.ok)throw new Error(A(m?.error)??`Upload failed: ${e.name}`);const u=A(m?.assetId);if(!u)throw new Error("Upload did not return an asset id");return{artifactRef:u,reusedExisting:!1}},Ga=async(e,t)=>{if(!i||!c||p.state!=="ready")return;const o=Yn(),n=c.cells.find(a=>a.id===e),r=n&&Ft(n.type);if(!n||!r)return;if(n.outputArtifactId||c.edges.some(a=>a.target===e)){Qo(e,"This media slot already contains media.");return}if(xs(t)!==r){Qo(e,`Choose one ${r} file for this slot.`);return}Rt(e,"upload");try{const{artifactRef:a,reusedExisting:l}=await Va(t,r);await b("set_notebook_media_slot",{book_id:i,notebook_id:c.id,cell_id:e,artifact_ref:a}),await N(i,c.id),Rt(e,null),h(l?`Reused @${a} in media slot`:`Uploaded and attached @${a}`),Tn({bookId:i,notebookId:c.id,cellId:e,address:Se(n.slot),artifactId:a})}catch(a){const l=a instanceof Error?a.message:String(a);Qo(e,l),h(l,"error")}finally{o()}},Jr=async(e,t)=>{if(!i||!c)return;const o=Yn();if(G){h("Wait for the current operation to finish","error");return}const n=xs(t);if(!n){h("Drop an image, video, or audio file on an open square","error");return}if(wt.some(l=>l.row===e.row&&l.column===e.column)){h("Choose an empty grid square for the media file","error");return}const r=U(e);let s=null,a=!1;T(!0);try{const{artifactRef:l,reusedExisting:m}=await Va(t,n),u=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:{type:n,slot:e}}));if(s=u&&A(u.id),!s)throw new Error("The server did not return the new media cell");await b("set_notebook_media_slot",{book_id:i,notebook_id:c.id,cell_id:s,artifact_ref:l}),a=!0,B?.cellId===null&&Vn(),se(),_e(e),await N(i,c.id),h(m?`Reused @${l} at ${r}`:`Uploaded and attached @${l} at ${r}`),Tn({bookId:i,notebookId:c.id,cellId:s,address:Se(e),artifactId:l})}catch(l){let m=l instanceof Error?l.message:String(l);if(s&&!a)try{await b("delete_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:s})}catch(u){const w=u instanceof Error?u.message:String(u);m=`${m}. The empty ${r} cell could not be removed: ${w}`}await N(i,c.id).catch(()=>{}),h(m,"error")}finally{T(!1),o()}},Vn=()=>{const e=Eg(jr.current);Ae.current+=1,ue.lifecycle.close(),ge(null),jr.current=null,e()},yt=async(e,t,o,n,r,s,a)=>{const l=c?.cells.find(S=>S.id===e),m=a??(e===null?"all":l&&Ft(l.type));if(!m)return;const u=r??(B?.cellId===e?$b(ue.state):{mode:"text",reference:null,referenceStartSeconds:"0",referenceDurationSeconds:""}),w=s??(B?.cellId===e?B.tagFilters:[]),v=Ae.current+1;Ae.current=v,ge(S=>!S||S.cellId!==e?S:{...S,query:t,tagFilters:[...w],assets:n?S.assets:[],page:n?S.page:ir,booksWithErrors:n?S.booksWithErrors:[],preparingIndex:!1,loading:!n,loadingMore:n,error:null});try{let S;try{S=u.mode==="video-reverse"&&u.reference?Ig(u.referenceStartSeconds,u.referenceDurationSeconds,u.reference):void 0}catch($){const F=ue.lifecycle.getState().reference===u.reference?ue.lifecycle.resetInvalidRange($):$ instanceof Error?$.message:String($);throw new Error(F)}const E=()=>Ae.current!==v,y=await Cg({search:()=>b("search_library_assets",{...u.mode==="text"&&t.trim()?{query:t.trim()}:{},...u.mode!=="text"&&u.reference?{reference_id:u.reference.referenceId}:{},...S?{reference_range:S}:{},kinds:m==="all"?["audio","image","video"]:[m],...Sg(w),limit:ir.limit,offset:o}),listJobs:($,F)=>b("list_jobs",{book_id:$,job_ids:F},{background:!0}),onPreparing:$=>{E()||ge(F=>F&&F.cellId===e?{...F,preparingIndex:$}:F)},isCancelled:E});if(E())return;const R=xg(y);ge($=>{if(!$||$.cellId!==e)return $;const F=R.assets.filter(L=>Fs(m,L.type)),J=n?[...$.assets,...F]:F,P=new Map(J.map(L=>[`${L.owningBookId}:${L.artifactId}`,L]));return{...$,assets:[...P.values()],page:R.page,booksWithErrors:R.booksWithErrors,unindexedVisualAssets:R.unindexedVisualAssets,loading:!1,loadingMore:!1}})}catch(S){if(Ae.current!==v)return;const E=S instanceof Error?S.message:String(S);ge(y=>y&&y.cellId===e?{...y,loading:!1,loadingMore:!1,error:E}:y),h(E,"error")}},Wa=(e,t=c)=>{const o=t?.cells.find(r=>r.id===e),n=o?Ft(o.type):null;return!o||!n||o.outputArtifactId||t?.edges.some(r=>r.target===e)?null:n},xo=(e,t=c,o)=>{if(!t||p.state!=="ready")return;const n=e===null?"all":Wa(e,t);n&&((e===null||st.current.size!==1||!st.current.has(e))&&Y(e),Ne(null),pt(null),ke(!0),jr.current=document.activeElement instanceof HTMLElement?document.activeElement:null,ue.lifecycle.close(),e&&Rt(e,null),ge({unindexedVisualAssets:0,preparingIndex:!1,bookId:i,notebookId:t.id,cellId:e,slot:o,query:"",draftQuery:"",assets:[],page:ir,booksWithErrors:[],loading:!0,loadingMore:!1,error:null,activeArtifactId:null,tagFilters:[],tagSuggestions:[]}),yt(e,"",0,!1,{mode:"text",reference:null,referenceStartSeconds:"0",referenceDurationSeconds:""},[],n))},Md=()=>{Vn(),ke(!1)},Qr=e=>{_o("notebook"),xo(null,c,e)},Td=async e=>{if(!i||!c||!B||p.state!=="ready"||G)return;const t=B,o=Ae.current,n=()=>Ae.current===o&&Q.current.bookId===t.bookId&&Q.current.notebookId===t.notebookId;let r=t.cellId;const s=c.cells.find(u=>u.id===r),a=r===null?Ls(e.type):s&&Ft(s.type);if(!a||!Fs(a,e.type))return;r&&Rt(r,"attach"),ge(u=>u===t?{...u,activeArtifactId:e.artifactId,error:null}:u);let l=null,m=!1;T(!0);try{if(r===null){const u=t.slot??Mo(a,c.cells,Ve),w=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:{type:a,slot:u}}));if(l=w&&A(w.id),!l)throw new Error("The server did not return the new media cell");r=l,_e(u)}if(e.owningBookId===i?await b("set_notebook_media_slot",{book_id:i,notebook_id:c.id,cell_id:r,artifact_ref:e.artifactId}):await b("attach_library_asset",{source_book_id:e.owningBookId,source_artifact_id:e.artifactId,target_book_id:i,notebook_id:c.id,cell_id:r,expected_output_artifact_id:s?.outputArtifactId??null}),m=!0,!n()||(await N(i,c.id),!n()))return;Rt(r,null),h(e.owningBookId===i?`Attached @${e.id}`:`Copied and attached @${e.id} from ${e.owningBookName}`),(t.cellId!==null||st.current.size===0)&&(Vn(),l&&se())}catch(u){let w=u instanceof Error?u.message:String(u);if(l&&!m)try{await b("delete_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:l})}catch(v){w+=`. The empty cell could not be removed: ${v instanceof Error?v.message:String(v)}`}if(!n())return;t.cellId&&Qo(t.cellId,w),ge(v=>v&&v.cellId===t.cellId?{...v,activeArtifactId:null,error:w}:v),h(w,"error")}finally{!n()&&t.cellId&&Q.current.bookId===t.bookId&&Rt(t.cellId,null),T(!1)}},Gn=ip({callTool:b,ready:p.state==="ready"}),jd=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before speaking."};let n=null,r=!1;try{if(!At)throw new Error("Offline: cloud generation is unavailable. Local search, editing, playback, and export remain available.");const s=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(!s)throw new Error("The server returned an invalid notebook");const a=await xk({bookId:i,callTool:(y,R)=>b(y,R,{chat:o}),document:s,lastWorkSlot:Ve,text:e,voiceId:t,...s.revision?{expectedRevision:s.revision}:{}});n=a;const l=Al(a.cellAddress);l&&_e(l);const m=await ko(a.cellId,"slash",o),u=m.stages.find(y=>y.kind==="queued"&&y.jobType==="generation"&&y.tool==="run_notebook_cell"&&y.input.cell_id===a.cellId);if(u?.kind!=="queued")throw new Error("The generation plan is missing its notebook cell");const w=A(u.input.notebook_id);if(w!==s.id)throw new Error("The generation plan belongs to another notebook");if(!sr(u))throw new Error("Cloud generation cancelled before sending data");O(o,!1,()=>V(null)),O(o,!1,()=>de(null));const v=await Jn({start:()=>b("run_notebook_cell",{book_id:i,notebook_id:w,cell_id:a.cellId,plan:m,actor:"videobook-user"},{chat:o}),onStarting:()=>oe(a.cellId,!0),onRejected:()=>oe(a.cellId,!1)}),S=A(D(v)?.run_id),E=A(D(v)?.job_id);if(!S||!E)throw oe(a.cellId,!1),new Error("The server did not return a notebook run");return r=!0,Ek(t),se(o),M(o,()=>h(`${a.cellAddress} queued`)),Zo({bookId:i,notebookId:w,cellId:a.cellId,address:a.cellAddress.replace(/^@/,""),runId:S,jobOperationId:E},o),await N(i,c.id,void 0,o).catch(()=>{}),{ok:!0,message:`${a.cellAddress} queued`}}catch(s){const a=s instanceof Error?s.message:String(s);return n&&!r?(await b("delete_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:n.cellId},{chat:o}).catch(()=>{}),await b("delete_notebook_cell",{book_id:i,notebook_id:c.id,cell_id:n.outputCellId},{chat:o}).catch(()=>{}),{ok:!1,message:a}):r?(M(o,()=>h(a,"error")),{ok:!1,message:a}):{ok:!1,message:a}}},Ua=(e,t,o={},n)=>{const r=z.find(a=>a.artifactId===e),s=Zg(wl(i),o,r?.duration??null);O(n,!1,()=>de(null)),O(n,!1,()=>V(null)),O(n,!0,()=>{tl(i,s.platform,o),qe({assetId:e,targetLabel:t,mediaUrl:r?.mediaUrl??null,thumbnailUrl:r?.thumbnailUrl??null,width:r?.width??null,height:r?.height??null,durationSeconds:r?.duration??null,platform:s.platform,identities:{x:{handle:s.handles?.x??"",recent:[]},tiktok:{handle:s.handles?.tiktok??"",recent:[]}},url:s.url??"",includeQr:s.includeQr??!0,includeHandle:s.includeHandle??!0,position:s.position??"auto",handleVerticalPercent:s.handleVerticalPercent===void 0?ok:Cl(s.handleVerticalPercent),handlePlacement:s.handlePlacement??"center",includePlatformIcon:s.includePlatformIcon??!0,includeHandleBorder:s.includeHandleBorder??!0,handlePadding:s.handlePadding===void 0?vl:nr(s.handlePadding),handlePaddingY:s.handlePaddingY===void 0?vl:nr(s.handlePaddingY),handleRounding:s.handleRounding===void 0?tk:Il(s.handleRounding),qrOpacity:s.qrOpacity===void 0?hl:or(s.qrOpacity),handleOpacity:s.handleOpacity===void 0?hl:or(s.handleOpacity),qrStartSeconds:s.qrStartSeconds??0,qrEndSeconds:s.qrEndSeconds??null,handleStartSeconds:s.handleStartSeconds??0,handleEndSeconds:s.handleEndSeconds??null,fadeSeconds:s.fadeSeconds===void 0?ek:yl(s.fadeSeconds),saveDefault:s.saveDefault??!1,loadingConfig:!0,error:null})}),Promise.allSettled(nk.map(async a=>{const l=D(await b("get_watermark_config",{book_id:i,platform:a},{background:!0,chat:n})),m=A(l?.savedHandle),u=A(l?.authenticatedHandle),w=Array.isArray(l?.recent)?l.recent.filter(R=>typeof R=="string"):[],v=D(l?.profile),S=A(v?.handle),E=A(v?.profileUrl),y=wl(i).handles?.[a];M(n,()=>qe(R=>R&&R.assetId===e?{...R,url:R.url||(a===R.platform?E??"":R.url),identities:{...R.identities,[a]:{handle:y??(R.identities[a].handle||(m??u??w[0]??S??"")),recent:w}}}:R))})).then(()=>{M(n,()=>qe(a=>a&&a.assetId===e?{...a,loadingConfig:!1}:a))})},$d=async e=>{if(!i||!he)return{ok:!1,message:"There is no pending watermark to apply."};const{assetId:t,targetLabel:o,platform:n,identities:r,url:s,includeQr:a,includeHandle:l,position:m,handleVerticalPercent:u,handlePlacement:w,includePlatformIcon:v,includeHandleBorder:S,handlePadding:E,handlePaddingY:y,handleRounding:R,qrOpacity:$,handleOpacity:F,qrStartSeconds:J,qrEndSeconds:P,handleStartSeconds:L,handleEndSeconds:H,fadeSeconds:ee,saveDefault:le}=he,me=r[n].handle.trim().replace(/^@/,"").trim(),ze=s.trim();if(!a&&!l)return{ok:!1,message:"Include a QR code, a handle, or both before applying the watermark.",nextInput:"/apply",selectInput:!1};if(l&&!me)return{ok:!1,message:"Enter a handle before applying the watermark.",nextInput:"/apply",selectInput:!1};if(a&&!ze&&!me)return{ok:!1,message:"Enter a QR link before applying the watermark.",nextInput:"/apply",selectInput:!1};M(e,()=>qe(be=>be&&be.assetId===t?{...be,error:null}:be)),T(!0);try{const be=D(await b("apply_watermark",{book_id:i,asset_id:t,platform:n,...me&&(l||!ze)?{handle:me}:{},include_qr:a,include_handle:l,position:m,...l?{handle_vertical_percent:u}:{},...l&&a&&w!=="center"?{handle_position:w}:{},...l?{include_platform_icon:v}:{},...l?{include_handle_border:S}:{},...l?{handle_padding:E}:{},...l?{handle_padding_y:y}:{},...l?{handle_rounding:R}:{},...l?{handle_opacity:F}:{},...a&&ze?{url:ze}:{},...a?{qr_opacity:$}:{},...a&&J>0?{qr_start_seconds:J}:{},...a&&P!==null?{qr_end_seconds:P}:{},...l&&L>0?{handle_start_seconds:L}:{},...l&&H!==null?{handle_end_seconds:H}:{},fade_seconds:ee,...l&&le?{save_default:!0}:{},wait:!1},{chat:e})),Fe={includeQr:a,includeHandle:l,handle:me,handlePlacement:w,handleVerticalPercent:u,handleOpacity:F,qrOpacity:$,requestedPosition:m},Zt=ae(be?.job_id);if(A(be?.status)==="accepted"&&Zt!==null){const Ai=bk(a,l,me,o);return M(e,()=>h(Ai)),O(e,!1,()=>qe(null)),Ld({bookId:i,artifactId:t,jobId:Zt,targetLabel:o,describe:Ri=>Sl({...Fe,corner:A(Ri?.corner),placementSource:A(Ri?.placementSource)})},e),{ok:!0,message:Ai}}await N(i,c?.id,void 0,e);const _i=Sl({...Fe,corner:A(be?.position),placementSource:A(be?.placement_source)});return M(e,()=>h(_i)),O(e,!1,()=>qe(null)),{ok:!0,message:_i}}catch(be){const Fe=be instanceof Error?be.message:String(be);return M(e,()=>qe(Zt=>Zt&&Zt.assetId===t?{...Zt,error:Fe}:Zt)),M(e,()=>h(Fe,"error")),{ok:!1,message:Fe,nextInput:"/apply",selectInput:!1}}finally{T(!1)}},qd=async e=>{if(!(e.length===0||!i)){if(vc){h("Wait for the current import to finish");return}aa(!0);try{let t=0,o=0;for(const r of e){const s=await Ul(r),a=D(await b("check_duplicate_bytes",{book_id:i,object_hash:s})),l=Array.isArray(a?.matches)?a.matches:[];if(l.length>0){const w=D(l[0]),v=A(w?.label)??A(w?.artifact_id)??"existing source";if(!window.confirm(`${r.name} has the same bytes as ${v}.
|
|
17
|
+
|
|
18
|
+
Choose OK to import another copy, or Cancel to reuse the existing source.`)){o+=1;continue}}const m=await fetch(`/api/books/${encodeURIComponent(i)}/upload?filename=${encodeURIComponent(r.name)}`,{method:"POST",body:r}),u=await m.json();if(!m.ok)throw new Error(u.error??`Upload failed: ${r.name}`);t+=1}const n=await N(i,c?.id);tr(c,n)&&se(),h([t>0?`Imported ${t}`:"",o>0?`reused ${o} existing`:""].filter(Boolean).join(" · ")||"No files imported")}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{aa(!1)}}},Nd=e=>{const t=[...e.target.files??[]];e.target.value="",qd(t)},Ld=f.useCallback(async(e,t)=>{const o=Date.now()+Dl;let n=0,r=0;const s=async(a,l="info")=>{try{await N(e.bookId,Q.current.notebookId??void 0,void 0,t)}catch{}M(t,()=>h(a,l))};for(;Date.now()<o;){const a=Q.current;if(a.bookId!==e.bookId)return;try{const l=performance.now(),m=a.notebookId,[u,w,v]=await Promise.all([Pe.current("list_assets",{book_id:e.bookId,sort:"newest",limit:200,include_referenced:!0},{background:!0}),Pe.current("list_jobs",{book_id:e.bookId,limit:200},{background:!0}),m?Pe.current("get_notebook",{book_id:e.bookId,notebook_id:m},{background:!0}):Promise.resolve(null)]);n=0;const S=Q.current;if(S.bookId!==e.bookId)return;const E=Lt(u),y=to(w),R=m&&S.notebookId===m?pe(v):null;l>=ye.current&&(ye.current=l,Xe(F=>Nt(F,E)?F:E),at(y),R&&Ie(R,E,y));const $=lp(e.artifactId,e.jobId,E.find(F=>F.artifactId===e.artifactId),y);if($.kind==="completed"){await s(e.describe($.result));return}if($.kind==="failed"){await s($.message,"error");return}if(r=$.kind==="missing"?r+1:0,r>=Gb){M(t,()=>h(`Lost track of the ${e.targetLabel} watermark job — check the Jobs screen`,"error"));return}}catch(l){if(n+=1,n>=10){const m=l instanceof Error?l.message:String(l);M(t,()=>h(`Stopped watching the ${e.targetLabel} watermark: ${m}. Check the Jobs screen.`,"error"));return}}await ot(Fl)}M(t,()=>h(`${e.targetLabel} watermark is still processing — check the Jobs screen`))},[at,Ie,N,h]),Ba=async e=>{if(i){T(!0);try{await b("cancel_job",{book_id:i,job_id:e}),await N(i,c?.id),h(`Job ${e} cancelled`)}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Fd=async e=>{if(i){T(!0);try{await b("retry_job",{book_id:i,job_id:e}),await N(i,c?.id),h(`Job ${e} retry queued`)}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Dd=async(e,t)=>{if(!i||!c)return;const o=e.plan.stages.find(r=>r.kind==="queued"&&r.jobType==="generation"),n=t==="switch"?window.prompt("Generation model",o?.kind==="queued"?o.tool:"")?.trim():void 0;if(!(t==="switch"&&!n)){T(!0);try{const r=await b("revise_notebook_generation_plan",{book_id:i,notebook_id:c.id,plan_id:e.planId,action:t,...n?{model:n}:{},source_surface:"ui",actor:"videobook-user"});t==="omit"?(await N(i,c.id),h("Generation output omitted; the preserved failure remains available")):(V(null),de({plan:ut(r),previews:{}}),h(t==="retry"?"Retry plan ready for review":"Provider/model switch ready for review"))}catch(r){h(r instanceof Error?r.message:String(r),"error")}finally{T(!1)}}},Od=async e=>{if(!(!i||!c)){T(!0);try{const t=await b("continue_notebook_generation",{book_id:i,notebook_id:c.id,plan_id:e.planId,actor:"videobook-user"}),o=D(t);if(o?.kind==="stale-continuation"){h(A(o.message)??"The sequence changed; review a new destination","error"),await N(i,c.id);return}const n=await Jt(ut(t));h(n.message,n.ok?"info":"error")}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Ha=async(e={})=>{try{const t=await Og(b,e);return ro(o=>({...o,status:t,error:null})),xa(Xn(t)),t}catch(t){return ro(o=>({...o,error:t instanceof Error?t.message:String(t)})),null}},Yr=async()=>{if(jo.connecting)return{ok:!1,message:"X authorization is already waiting for approval."};ro(e=>({...e,connecting:!0,authorizeUrl:null,error:null}));try{const e=await Dp(b);ro(n=>({...n,authorizeUrl:e})),window.open(e,"_blank","noopener,noreferrer");const t=await Op(b,{sleep:ot}),o=Vp(t);return ro({status:t,connecting:!1,authorizeUrl:null,error:o.ok||t.error?null:o.message}),xa(Xn(t)),h(o.message,o.ok?"info":"error"),o}catch(e){const t=e instanceof Error?e.message:String(e);return ro(o=>({...o,connecting:!1,authorizeUrl:null,error:t})),h(t,"error"),{ok:!1,message:t}}},nn=async()=>{if(p.state!=="ready")return;const e=++Js.current,t=i;zs(!0),Ks(null),Fo(null),Xs(!1),gr(t?{bookId:t,status:"loading"}:null);const[o,n,r]=await Promise.allSettled([b("provider_key_status",{}),t?b("storage_status",{book_id:t}):Promise.resolve(null),Ha({refreshAccount:!0})]);if(e!==Js.current)return;let s=!0;try{if(o.status==="rejected")throw o.reason;rc(rg(o.value))}catch(a){s=!1,Ks(a instanceof Error?a.message:String(a))}if(t)try{if(n.status==="rejected")throw n.reason;gr({bookId:t,status:"ready",value:sg(n.value)})}catch(a){s=!1,gr({bookId:t,status:"error",error:a instanceof Error?a.message:String(a)})}Xs(s&&r.status==="fulfilled"&&r.value!==null),zs(!1)},Vd=async(e,t)=>{if(p.state!=="ready")throw new Error("Connect to save settings");if(!t.trim())throw new Error("Enter a value to save");T(!0);try{await b("set_env_secret",{key:e,value:t}),await nn()}finally{T(!1)}},Jt=async(e,t)=>{try{const o=e.stages.filter(a=>a.kind==="edit"),n=await Promise.all(o.map(async a=>[a.stageId,await b("preview_edit_intent",{book_id:i,intent:a.intent},{chat:t})])),r=Object.fromEntries(n);O(t,!1,()=>V(null)),O(t,!0,()=>de({plan:e,previews:r}));const s=Object.values(r).reduce((a,l)=>a+l.conflicts.length,0);return s>0?{ok:!1,message:`Plan requires review: ${s} conflicts`}:ft("Plan preview ready")}catch(o){return{ok:!1,message:o instanceof Error?o.message:String(o)}}},Gd=async e=>{if(!ce?.plan.suggestions)return;const t=ce.plan.suggestions.map(s=>s.suggestionId===e?{...s,included:!s.included}:s),o=t.filter(s=>s.included).map(s=>s.operation),n={...ce.plan,suggestions:t,stages:ce.plan.stages.map(s=>s.kind==="edit"?{...s,intent:{...s.intent,operations:o}}:s)};if(o.length===0){de({plan:n,previews:{}});return}const r=await Jt(n);h(r.message,r.ok?"info":"error")},za=async(e,t,o)=>{if(!i)return{ok:!1,message:"Load or create a book first."};try{const n=ut(await b("plan_sequence_edit",{book_id:i,source_surface:t,actor:"videobook-user",edits:Array.isArray(e)?e:[e]},{chat:o}));return await Jt(n,o)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},Wd=async e=>{if(!i||!ce)return{ok:!1,message:"There is no pending command plan."};const t=ce;T(!0);try{const o=t.plan.stages.find(a=>a.kind==="queued"&&a.input.workbook_run===!0);if(o?.kind==="queued"){const a=t.plan.stages.some(S=>S.kind==="queued"&&S.jobType==="generation");if(a&&!At)throw new Error("Offline: cloud generation is unavailable. The workbook plan remains preserved.");const l="videobook.cloud-generation-consent";if(a&&window.localStorage.getItem(l)!=="accepted"){if(!window.confirm(`Cloud generation disclosure
|
|
19
|
+
|
|
20
|
+
Payload class: rewritten prompts, extracted first and last frames, and connected media references.
|
|
21
|
+
The four scene audio assets remain local and replace generated sound after animation.
|
|
22
|
+
|
|
23
|
+
Continue and remember this choice on this device?`))throw new Error("Workbook generation cancelled before sending data");window.localStorage.setItem(l,"accepted")}const m=A(o.input.notebook_id)??c?.id;if(!m)throw new Error("The workbook plan is missing its notebook");const u=D(await b("enqueue_notebook_run",{book_id:i,notebook_id:m,plan_id:t.plan.planId,actor:"videobook-user",confirm_unpriced:!0},{chat:e}));O(e,!1,()=>de(null));const w=await N(i,m,void 0,e).catch(()=>{});tr(c,w)&&se(e);const v=A(u?.status)==="completed"?"Workbook is already current":"Workbook run accepted and queued";return M(e,()=>h(v)),{ok:!0,message:v}}let n="",r=0;for(const a of t.plan.stages){if(a.kind==="edit"){const l=ce.previews[a.stageId];if(!l?.valid)throw new Error("The plan has conflicts and cannot be applied");const m=D(await b("commit_edit_intent",{book_id:i,intent:a.intent,preview_hash:l.previewHash},{chat:e}));n=A(m?.actionId)??n;continue}if(a.kind==="queued"&&a.jobType==="export"&&a.tool==="export_sequence"){const l=Ke(await b("get_primary_sequence",{book_id:i},{chat:e}));if(!l)throw new Error("The sequence is no longer available.");const m=a.input.sequence_content_revision;if(typeof m=="string"&&await Zn(l)!==m)throw new Error("The sequence changed after review. Review the current cut before exporting.");const u=D(await b("enqueue_sequence_export",{book_id:i,confirm:!0,sequence_revision:typeof m=="string"?l.revision:a.input.sequence_revision,orientation:a.input.orientation,captions:a.input.captions},{chat:e}));if(u?.kind==="invalid-export"){const w=D(u.validation),v=Array.isArray(w?.errors)?w.errors.map(S=>A(D(S)?.message)).filter(Boolean):[];throw new Error(v.join(" · ")||"Export validation failed. Review the current sequence again.")}r+=1;continue}if(a.kind==="queued"&&a.jobType==="generation"&&a.tool==="run_notebook_cell"){if(!At)throw new Error("Offline: cloud generation is unavailable. The plan remains preserved.");const l="videobook.cloud-generation-consent";if(window.localStorage.getItem(l)!=="accepted"){if(!window.confirm(`Cloud generation disclosure
|
|
24
|
+
|
|
25
|
+
Provider/model: ${a.provider??"unknown"} · ${a.model??a.tool}
|
|
26
|
+
Payload class: prompt text and connected media references.
|
|
27
|
+
Your local source files are sent only when required by the selected model.
|
|
28
|
+
|
|
29
|
+
Continue and remember this choice on this device?`))throw new Error("Cloud generation cancelled before sending data");window.localStorage.setItem(l,"accepted")}const m=A(a.input.notebook_id),u=A(a.input.cell_id);if(!m||!u)throw new Error("The generation plan is missing its notebook cell");ne(u,null);const w=await Jn({start:()=>b("run_notebook_cell",{book_id:i,notebook_id:m,cell_id:u,plan:t.plan,actor:"videobook-user"},{chat:e}),onStarting:()=>oe(u,!0),onAccepted:()=>oe(u,!1),onRejected:()=>oe(u,!1)}),v=D(w),S=A(v?.run_id),E=A(v?.job_id),y=A(v?.output_cell_id);if(!S||!E)throw oe(u,!1),new Error("The server did not return a notebook run");y&&se(e);const R=y??u,$=c?.cells.find(J=>J.id===u);let F=$?Se($.slot):u.slice(0,8);if(y){const J=await b("get_notebook",{book_id:i,notebook_id:m},{background:!0,chat:e}),P=pe(J);if(P){Ie(P,z,De);const L=P.cells.find(H=>H.id===y);L&&(F=Se(L.slot))}M(e,()=>Yo([y])),ne(y,null),oe(y,!0)}Zo({bookId:i,notebookId:m,cellId:R,address:F,runId:S,jobOperationId:E},e),r+=1;continue}if(a.kind==="queued")throw new Error(`Queued ${a.jobType} execution is not available from this plan yet`)}O(e,!1,()=>de(null)),lo(n),await N(i,c?.id,void 0,e).catch(()=>{});const s=r>0?`CommandPlan accepted · ${r} queued job`:"CommandPlan committed to a new sequence revision";return M(e,()=>h(s)),{ok:!0,message:s}}catch(o){let n=o instanceof Error?o.message:String(o);M(e,()=>h(n,"error"));const r=t.plan.stages.some(a=>a.kind==="queued"&&a.jobType==="generation"),s=t.plan.stages.some(a=>a.kind==="export");if(!r&&!s)try{const a=await za(Yb(t.plan.stages),t.plan.sourceSurface==="system"?"ui":t.plan.sourceSurface,e);a.ok||(n=a.message,M(e,()=>h(n,"error")))}catch{O(e,!1,()=>de(null)),n="The sequence changed. Recreate this plan against the current cut.",M(e,()=>h(n,"error"))}return{ok:!1,message:n,...r?{nextInput:"/apply",selectInput:!0}:{}}}finally{T(!1),M(e,()=>go())}},Ud=async()=>{if(!(!i||!Pr||!window.confirm(`Restore the sequence state before the last applied plan?
|
|
30
|
+
|
|
31
|
+
This creates a new forward revision.`))){T(!0);try{const t=D(await b("get_edit_action",{book_id:i,action_id:Pr})),o=A(t?.baseRevision);if(!o)throw new Error("The edit audit has no base revision");const n=D(await b("restore_edit_action",{book_id:i,target_revision:o,base_revision:X?.revision??A(t?.committedRevision)??"",actor:"videobook-user",source_surface:"ui"}));lo(A(n?.actionId)??""),await N(i,c?.id),h("Restored the previous sequence state as a forward revision")}catch(t){h(t instanceof Error?t.message:String(t),"error")}finally{T(!1)}}},Bd=async(e,t)=>{if(!i||!c||!X)return{ok:!1,message:"Open a notebook sequence first."};const o=X.captions.slice(0,20).map(n=>({beat_id:n.cueId,text:n.text,timeline_start_frame:n.timelineStartFrame,duration_frames:n.durationFrames}));if(o.length===0)return{ok:!1,message:"Add captions first so narration beats have exact timing."};try{const n=await b("plan_notebook_rough_cut",{book_id:i,notebook_id:c.id,source_surface:e,actor:"videobook-user",beats:o,min_shot_frames:30,max_shot_frames:120,max_repeats_per_artifact:1},{chat:t}),r=D(n);return r?.kind==="rough-cut-uncovered"?{ok:!1,message:`No existing indexed coverage for ${Array.isArray(r.uncoveredBeats)?r.uncoveredBeats.length:o.length} narration beats.`}:await Jt(ut(n),t)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},Hd=async(e,t)=>{if(!i||!X)return{ok:!1,message:"Open a sequence first."};const o=X.captions.slice(0,20).map(n=>({beat_id:n.cueId,text:n.text,timeline_start_frame:n.timelineStartFrame,duration_frames:n.durationFrames}));if(o.length===0)return{ok:!1,message:"Add captions first so sound suggestions have exact timing."};try{const n=await b("plan_sequence_sound_effects",{book_id:i,source_surface:e,actor:"videobook-user",moments:o,max_repeats_per_artifact:1},{chat:t});return D(n)?.kind==="sound-effects-uncovered"?{ok:!1,message:"No existing indexed sound effects cover these beats. Generation is available as a fallback."}:await Jt(ut(n),t)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},zd=async(e,t,o)=>{if(!i)return{ok:!1,message:"Load or create a book first."};try{const n=Ke(await b("add_sequence_track",{book_id:i,kind:e,...t?.trim()?{name:t.trim()}:{}},{chat:o}));if(!n)throw new Error("The server returned an invalid sequence");return Ee(n),{ok:!0,message:`Added ${e} track`}}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},Kd=async(e,t)=>{if(!i)return{ok:!1,message:"Load or create a book first."};try{const o=Ke(await b("remove_sequence_track",{book_id:i,track_id:e},{chat:t}));if(!o)throw new Error("The server returned an invalid sequence");return Ee(o),{ok:!0,message:"Removed empty track"}}catch(o){return{ok:!1,message:o instanceof Error?o.message:String(o)}}},Ka=async(e,t,o,n)=>{if(!i){Ge(s=>s?.key===e?{...s,setup:{status:"error",message:"Load or create a book first."}}:s);return}Ge(s=>s?.key===e?{...s,setup:{status:"loading"}}:s);const r=Kl(o,t);if(!r){Ge(s=>s?.key===e?{...s,setup:{status:"needs-audio-track",message:"Create an empty, enabled soundtrack track before reviewing setup."}}:s);return}try{const s=ut(await b("plan_sequence_edit",{book_id:i,source_surface:"ui",actor:"videobook-user",expected_revision:await Zn(o),edits:[{kind:"music_video_setup",audio_artifact_id:t,audio_track_id:r.trackId}]},{chat:n})),a=s.stages.find(v=>v.kind==="edit");if(!a)throw new Error("The soundtrack setup plan has no edit stage");const l=await b("preview_edit_intent",{book_id:i,intent:a.intent},{chat:n}),m=Wl(l);if(m)throw new Error(m);const u=Jb(s,o,t);if(Xb(o,t,u)){Ge(v=>v?.key===e?{...v,setup:{status:"applied",audioTrackId:r.trackId,timelineLimitFrame:u}}:v);return}const w={status:"ready",audioTrackId:r.trackId,timelineLimitFrame:u,operationCount:a.intent.operations.length,summary:Qb(s),warnings:l.warnings.map(v=>v.message),plan:s,preview:l};Ge(v=>v?.key===e?{...v,setup:w}:v)}catch(s){const a=s instanceof Error?s.message:String(s);Ge(l=>l?.key===e?{...l,setup:{status:"error",message:a}}:l)}},Xa=async()=>{if(!i||!ve||ve.setup.status!=="ready")throw new Error("Review the soundtrack setup before applying it");const e=ve.key,t=ve.setup,o=t.plan.stages.find(n=>n.kind==="edit");if(!o)throw new Error("The soundtrack setup plan has no edit stage");Ge(n=>n?.key===e?{...n,setup:{status:"applying",audioTrackId:t.audioTrackId,timelineLimitFrame:t.timelineLimitFrame,operationCount:t.operationCount,summary:t.summary,warnings:t.warnings}}:n);try{const n=D(await b("commit_edit_intent",{book_id:i,intent:o.intent,preview_hash:t.preview.previewHash})),r=Ke(n?.sequence),s=A(n?.actionId);if(!r||!s)throw new Error("The server returned an invalid soundtrack commit");Ee(r),lo(s);const a=r.clips.find(l=>l.trackId===t.audioTrackId&&l.source.artifactId===ve.audioArtifactId);return a&&await kt.save({masterClipId:a.clipId,correction:null},r),Ge(l=>l?.key===e?{...l,setup:{status:"applied",audioTrackId:t.audioTrackId,timelineLimitFrame:t.timelineLimitFrame}}:l),{sequence:r,actionId:s,beforeRevision:o.intent.baseRevision}}catch(n){const r=n instanceof Error?n.message:String(n);throw Ge(s=>s?.key===e?{...s,setup:{status:"error",message:r}}:s),n}},Ja=async(e,t)=>{if(!i)throw new Error("Load or create a book first.");const n=ut(await b("plan_sequence_edit",{book_id:i,source_surface:"ui",actor:"videobook-user",expected_revision:await Zn(t),edits:[e]})).stages.find(u=>u.kind==="edit");if(!n)throw new Error("The music-video plan has no edit stage");const r=await b("preview_edit_intent",{book_id:i,intent:n.intent}),s=Wl(r);if(s)throw new Error(s);const a=D(await b("commit_edit_intent",{book_id:i,intent:n.intent,preview_hash:r.previewHash})),l=Ke(a?.sequence),m=A(a?.actionId);if(!l||!m)throw new Error("The server returned an invalid music-video edit commit");return ye.current=performance.now(),Ee(l),lo(m),{sequence:l,actionId:m,beforeRevision:n.intent.baseRevision}},Qa=async(e,t)=>await b("plan_music_video",{book_id:i,expected_revision:await Zn(t),rhythm_revision:kt.rhythm.revision,options:e,source_surface:"ui",actor:"videobook-user"}),Ya=async e=>{const t=e.plan.stages[0]?.intent;if(!t||e.uncovered.length)throw new Error("Review a complete draft before applying it");const o=D(await b("commit_music_video",{book_id:i,intent:t,preview_hash:e.preview.previewHash,rhythm_revision:e.rhythmRevision,sequence_content_revision:e.sequenceContentRevision})),n=Ke(o?.sequence),r=A(o?.actionId);if(!n||!r)throw new Error("The server returned an invalid draft commit");return ye.current=performance.now(),Ee(n),lo(r),{sequence:n,actionId:r,beforeRevision:t.baseRevision}},Za=async(e,t)=>{if(!i)throw new Error("Load or create a book first.");const o=D(await b("restore_edit_action",{book_id:i,target_revision:e,base_revision:t,actor:"videobook-user",source_surface:"ui"})),n=Ke(o?.sequence),r=A(o?.actionId);if(!n||!r)throw new Error("The server returned an invalid sequence restore");return ye.current=performance.now(),Ee(n),lo(r),{sequence:n,actionId:r,beforeRevision:t}},ei=async e=>{if(!i)throw new Error("Load or create a book first.");const t=Ke(await b("add_sequence_track",{book_id:i,kind:e,name:e==="audio"?"Master Soundtrack":"Music Video"}));if(!t)throw new Error("The server returned an invalid sequence");return ye.current=performance.now(),Ee(t),t},ti=f.useCallback(()=>{const e=Yn();Ge(null),e()},[]),Xd=f.useCallback(()=>{const e=Yn();yr(null),e()},[]),oi=(e,t)=>{yr(o=>o?.key===e?{...o,state:t}:o)},ni=async(e,t,o,n)=>{try{const r=await b("alive_captions",{book_id:i,asset_id:t,reanalyze:o},{chat:n});oi(e,{status:"ready",data:ag(r)})}catch(r){if(o)throw new Error(Ps(r),{cause:r});oi(e,{status:"error",message:Ps(r)})}},ri=async(e,t)=>{try{await b("set_alive_captions",{book_id:i,asset_id:e,...ig(t)})}catch(o){throw new Error(Ps(o),{cause:o})}},Jd=async(e,t,o)=>{await ri(e,t),await b("render_video",{book_id:i,asset_id:e,orientation:o,subtitles_enabled:!0,highlight_style:"alive"})},Wn=async(e,t,o,n,r)=>{if(!c)return await N(i,void 0,o,n),{ok:!0,message:fn(e,"Download queued")};const s=Dg(e,t,r??Mo("video",c.cells,Ve));let a;try{const l=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:s},{chat:n})),m=A(l?.id);if(!m)throw new Error("The server did not return the new notebook cell");if(a=m,o?.()===!1)return{ok:!0,message:"Download queued in the previous workspace."};Y(m,n),se(n)}catch(l){return await N(i,c.id,o,n),{ok:!1,message:`Download queued in Library, but board placement failed: ${l instanceof Error?l.message:String(l)}`}}return await N(i,c.id,o,n),Nc({bookId:i,notebookId:c.id,cellId:a,address:Se(s.slot),artifactId:s.output_artifact_id}),{ok:!0,message:fn(e,`Download queued as ${U(s.slot)}`)}},Qd=async(e,t)=>{if(!(!i||!c))try{const o=await b("download_video",{book_id:i,url:e}),n=await Wn(o,e,void 0,void 0,t);h(n.message,n.ok?"info":"error")}catch(o){h(o instanceof Error?o.message:String(o),"error")}},Yd=async(e,t)=>{let o;try{o=await Pt({bookId:e.bookId,notebookId:e.notebookId,cellId:e.run.actionCellId,address:e.actionAddress.slice(1),runId:e.run.runId,jobOperationId:e.run.jobId,intervalMs:mn,timeoutMs:pn,maxPollFailures:10}),o.kind==="failed"&&ne(e.run.actionCellId,o.message??`${e.actionAddress} failed`)}catch(n){const r=n instanceof Error?n.message:String(n);ne(e.run.actionCellId,r),o={kind:"failed",message:r}}finally{oe(e.run.actionCellId,!1)}if(o.kind==="failed"){M(t,()=>h(o.message??`${e.actionAddress} failed`,"error"));return}if(o.kind==="timeout"){M(t,()=>h(`${e.sourceAddress} is still splitting — check the Jobs screen`));return}o.kind!=="superseded"&&(Y(e.run.outputs.at(-1)?.outputCellId??null,t),M(t,()=>h(`Split ${e.sourceAddress} into ${e.outputAddresses.join(" and ")}`)))},Zd=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before splitting a video."};let n=null;T(!0);try{const r=await b("list_assets",{book_id:i,sort:"newest",limit:200,include_referenced:!0},{chat:o}),s=Lt(r),a=It(t,e.sourceReference),l=U(a.slot),m=rr(t,a),u=s.find(y=>y.artifactId===m)?.duration??ae(a.inputs?.durationSeconds),w=Pk({command:e,document:t,sourceDurationSeconds:u??Number.NaN}),v=U(w.actionCell.slot),S=w.outputs.map(y=>U(y.outputCell.slot));n=w.actionCell.id,Xe(s),Ie(w.document,s,De),M(o,()=>Yo(w.createdCellIds)),ne(n,null),oe(n,!0),Y(w.outputs[0].outputCell.id,o),M(o,()=>h(`Splitting ${l} into ${w.outputs.length} chunks`));const E=await Mk({actor:"videobook-user",bookId:i,callTool:(y,R)=>b(y,R,{chat:o}),draft:w,...t.revision?{expectedRevision:t.revision}:{}});return se(o),await N(i,t.id,void 0,o).catch(()=>{}),Yd({actionAddress:v,bookId:i,notebookId:t.id,outputAddresses:S,run:E,sourceAddress:l},o),{ok:!0,message:`Splitting ${l} into ${S.join(", ")}`}}catch(r){const s=r instanceof Error?r.message:String(r);return n&&oe(n,!1),await N(i,c.id,void 0,o).catch(()=>{}),M(o,()=>h(s,"error")),{ok:!1,message:s}}finally{T(!1)}},si=async(e,t,o,n)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before extracting a frame."};let r=null;T(!0);try{const s=It(t,e.sourceReference),a=U(s.slot),l=await Ak({actor:"videobook-user",bookId:i,callTool:(w,v)=>b(w,v,{chat:n}),command:e,document:t,...t.revision?{expectedRevision:t.revision}:{}});if(r=l.actionCellId,o?.()===!1)return{ok:!0,message:"Frame extraction queued in the previous workspace."};se(n),ne(r,null),oe(r,!0),Y(l.outputCellId??r,n),M(n,()=>h(`Frame extraction queued for ${a}`));const m=await Pt({bookId:i,notebookId:t.id,cellId:r,address:Se(s.slot),runId:l.runId,jobOperationId:l.jobId,intervalMs:mn,timeoutMs:pn,maxPollFailures:ar});if(o?.()===!1)return{ok:!0,message:"Check the previous workspace for the accepted frame extraction."};if(m.kind==="failed")throw new Error(m.message??`Frame extraction for ${a} failed`);if(m.kind==="timeout")throw new Error("Frame extraction did not finish within five minutes");if(m.kind==="superseded")throw new Error(`Frame extraction for ${a} was superseded by a newer run`);return Y(l.outputCellId??r,n),{ok:!0,message:e.frameMode==="time"?`Extracted the frame at ${e.timestampSeconds??0}s of ${a}`:`Extracted the ${e.frameMode} frame of ${a}`}}catch(s){const a=s instanceof Error?s.message:String(s);return o?.()!==!1&&(r&&ne(r,a),M(n,()=>h(a,"error"))),{ok:!1,message:a}}finally{r&&o?.()!==!1&&oe(r,!1),T(!1)}},eu=async(e,t,o,n)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before extracting audio."};let r=null;T(!0);try{const s=It(t,e.sourceReference),a=U(s.slot),l=await _k({actor:"videobook-user",bookId:i,callTool:(u,w)=>b(u,w,{chat:n}),command:e,document:t,...t.revision?{expectedRevision:t.revision}:{}});if(r=l.actionCellId,o?.()===!1)return{ok:!0,message:"Audio extraction queued in the previous workspace."};se(n),ne(r,null),oe(r,!0),Y(l.outputCellId??r,n),M(n,()=>h(`Audio extraction queued for ${a}`));const m=await Pt({bookId:i,notebookId:t.id,cellId:r,address:Se(s.slot),runId:l.runId,jobOperationId:l.jobId,intervalMs:mn,timeoutMs:pn,maxPollFailures:ar});if(o?.()===!1)return{ok:!0,message:"Check the previous workspace for the accepted audio extraction."};if(m.kind==="failed")throw new Error(m.message??`Audio extraction for ${a} failed`);if(m.kind==="timeout")throw new Error("Audio extraction did not finish within five minutes");if(m.kind==="superseded")throw new Error(`Audio extraction for ${a} was superseded by a newer run`);return Y(l.outputCellId??r,n),{ok:!0,message:`Extracted audio from ${a}`}}catch(s){const a=s instanceof Error?s.message:String(s);return o?.()!==!1&&(r&&ne(r,a),M(n,()=>h(a,"error"))),{ok:!1,message:a}}finally{r&&o?.()!==!1&&oe(r,!1),T(!1)}},ai=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before extracting audio."};try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(t?.()===!1)return{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."};if(!n)throw new Error("The server returned an invalid notebook");return It(n,e.sourceReference),O(o,!1,()=>de(null)),O(o,!1,()=>V(null)),await eu(e,n,t,o)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},ii=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before extracting a frame."};try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(t?.()===!1)return{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."};if(!n)throw new Error("The server returned an invalid notebook");return It(n,e.sourceReference),O(o,!1,()=>de(null)),O(o,!1,()=>V(null)),await si(e,n,t,o)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},li=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before extracting a frame."};try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(t?.()===!1)return{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."};if(!n)throw new Error("The server returned an invalid notebook");const r=It(n,e.sourceReference),s=e.frameMode==="time"?`Extract the frame at ${e.timestampSeconds??0}s from ${U(r.slot)}`:`Extract the ${e.frameMode} frame from ${U(r.slot)}`;return O(o,!1,()=>de(null)),O(o,!0,()=>V({kind:"frame",command:e,expectations:[{address:U(r.slot),cellId:r.id}],notebookId:n.id,reason:"This request extracts a frame into a new image cell",summary:s})),ft("Frame extraction ready to apply")}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},rn=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before splitting a video."};try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(t?.()===!1)return{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."};if(!n)throw new Error("The server returned an invalid notebook");const r=It(n,e.sourceReference),s=rr(n,r),a=s?re.get(s):void 0,l=a?.duration??ae(r.inputs?.durationSeconds);if(!a?.mediaUrl)throw new Error(`${U(r.slot)} does not have playable video yet`);const m=un.maximumRowCount*un.columnCount,u=e.outputMode??"all",w=e.cutPointsSeconds.filter(R=>l===null||Math.abs(R-l)>.001),v=u==="all"?Gg({cutPointsSeconds:w,sourceDurationSeconds:l??Number.NaN}):kl({cutPointsSeconds:w,sourceDurationSeconds:l??Number.NaN}).slice(0,-1).map(R=>R.endSeconds),S={...e,cutPointsSeconds:v,outputMode:u,selectedChunkIndexes:e.selectedChunkIndexes??(u==="all"?[0]:e.selectedChunkIndexes??[0])},E=kl({cutPointsSeconds:v,sourceDurationSeconds:l??Number.NaN}).length,y=Wg(u,E);if(m-n.cells.length<y)throw new Error(`The notebook needs ${y} empty cells to split a video`);return O(o,!1,()=>de(null)),O(o,!0,()=>V({kind:"split",command:S,expectations:[{address:U(r.slot),cellId:r.id}],notebookId:n.id,reason:"This request creates and runs a Split Video workflow",sourceDurationSeconds:l??Number.NaN,summary:zi({cutPointsSeconds:v,outputMode:u,selectedChunkIndexes:S.selectedChunkIndexes,sourceAddress:U(r.slot),sourceDurationSeconds:l??Number.NaN})})),ft("Video split ready to apply")}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},tu=async(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a notebook before generating media."};try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:c.id},{chat:o}));if(t?.isCurrent?.()===!1)return{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."};if(!n)throw new Error("The server returned an invalid notebook");let r=Bl({actions:Je,cellId:Ct(),command:e,document:n,fallbackSlot:Mo(e.cellType,n.cells,Ve),lastWorkSlot:Ve,...t?.preferredModel?{preferredModel:t.preferredModel}:{},...t?.routedParams?{routedParams:t.routedParams}:{}});const s=r.sourceCellIds.flatMap(l=>{const m=n.cells.find(u=>u.id===l);return m?[m]:[]});if(r=Qn(r,rk(e.prompt,fe,s)),r.cell.type==="generate_audio"&&r.action.controls.some(l=>l.name==="voice_id")&&typeof ol(r).voice_id!="string"){const l=sk(Gn.voices,ak());l&&(r=hs(r,"voice_id",l))}ik(r,n);const a=r.sourceCellIds.length>0?` from ${r.sourceCellIds.flatMap(l=>{const m=n.cells.find(u=>u.id===l);return m?[U(m.slot)]:[]}).join(", ")}`:"";return O(o,!1,()=>de(null)),O(o,!0,()=>V({kind:"generation",draft:r,notebookId:n.id,preview:null,previewError:null,previewLoading:!0,previewStale:!1,expectations:[...r.sourceCellIds.flatMap(l=>{const m=n.cells.find(u=>u.id===l);return m?[{address:U(m.slot),cellId:m.id}]:[]}),{address:U(r.cell.slot),cellId:null}],reason:t?.reason??"Generation can incur provider spend and sends the prompt and required references",summary:`Generate ${e.mediaKind} as ${U(r.cell.slot)}${a}`})),jt(r,n,o),zb(`Generation ready to apply as ${U(r.cell.slot)}`)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},Zr=e=>e==="completed"||e==="failed"||e==="cancelled"||e==="interrupted"||e==="awaiting-approval",ci=async(e,t,o,n)=>{Ot("videobook.active-chain",JSON.stringify({bookId:e,chainId:t.chainId}));const r=Date.now()+5*6e4;let s=t;for(;Date.now()<r;){const a=$s(await b("chain",{action:"status",book_id:e,chain_id:t.chainId},{background:!0,chat:n}));if(o?.()===!1)throw new Error("Workspace changed. Check the previous project for the accepted action.");if(!a)break;s=a;const l=a.steps.find(m=>m.status==="running");if(l&&M(n,()=>h(`${l.tool.replaceAll("_"," ")}…`)),Zr(a.status))return a.status!=="awaiting-approval"&&Ot("videobook.active-chain",""),a;await new Promise(m=>window.setTimeout(m,250))}throw new Error(s.error??"Chain timed out")},di=(e,t)=>{const n=e.steps.find(s=>s.id===e.awaitingStepId)?.review;if(!n)return{ok:!1,message:"The chain is waiting for approval but sent no review."};const r=e.steps.filter(s=>s.status==="pending").length;return O(t,!0,()=>V({kind:"chain-step",chainId:e.chainId,review:n,remaining:r})),M(t,()=>h(n.reason)),{ok:!0,message:n.reason,nextInput:"/apply",selectInput:!1}},ou=async(e,t)=>{if(!i)return{ok:!1,message:"Load or create a book first."};O(t,!1,()=>V(null)),T(!0);try{const o=$s(await b("chain",{action:"approve",book_id:i,chain_id:e.chainId,step_id:e.review.stepId,actor:"chat"},{chat:t}));if(!o)throw new Error("The server did not return the chain run");const n=Zr(o.status)?o:await ci(i,o,void 0,t);if(n.status==="awaiting-approval")return di(n,t);if(await N(i,c?.id,void 0,t),n.status!=="completed")throw new Error(n.error??`Chain ${n.status}`);const r="Chain complete";return M(t,()=>h(r)),{ok:!0,message:r}}catch(o){const n=o instanceof Error?o.message:String(o);return M(t,()=>h(n,"error")),{ok:!1,message:n}}finally{T(!1)}},ui=async(e,t,o)=>{if(!i)return{ok:!1,message:"Load or create a book first."};O(o,!1,()=>de(null)),T(!0);let n=!1;try{const r=await b("chat",{book_id:i,action_plan:e},{chat:o});if(n=!0,t?.()===!1)return{ok:!1,message:"Workspace changed. Check the previous project for the accepted action."};O(o,!1,()=>V(null));const s=$s(r),a=s&&!Zr(s.status)?await ci(i,s,t,o):s;if(a?.status==="awaiting-approval")return di(a,o);const l=a;if(a&&a.status!=="completed")throw new Error(a.error??`Chain ${a.status}`);if(t?.()===!1)return{ok:!0,message:"Action accepted in the previous workspace."};if(pl(r)){const E=await Wn(r,Gl(e.prompt),t,o);return t?.()===!1?E:(M(o,()=>h(E.message,E.ok?"info":"error")),E.ok?E:{...E,nextInput:"",selectInput:!1})}const m=c?bl(e.tool,r,c.cells,Ve):[];if(c&&m.length>0){const E=[];let y=null;for(const $ of m){if(t?.()===!1)return{ok:!0,message:"Action accepted in the previous workspace."};const F=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:$},{chat:o})),J=A(F?.id);if(!J)throw new Error("The server did not return the new notebook cell");y??=J,E.push(U($.slot))}if(t?.()===!1)return{ok:!0,message:"Action accepted in the previous workspace."};Y(y,o),await N(i,c.id,t,o),se(o);const R=`Created ${E.join(" and ")}`;return t?.()!==!1&&M(o,()=>h(R)),{ok:!0,message:R}}const u=D(r),w=A(u?.cell_id),v=await N(i,c?.id,t,o);if(t?.()===!1)return{ok:!0,message:"Action accepted in the previous workspace."};w&&Y(w,o),tr(c,v)&&se(o);const S=l?e.message||"Chain complete":fn(r,e.message||"Action applied");return M(o,()=>h(S)),{ok:!0,message:S}}catch(r){const s=r instanceof Error?r.message:String(r);if(t?.()===!1)return{ok:!1,message:s};const a=n?`Action completed, but its notebook result could not be shown: ${s}`:s;return n&&await N(i,c?.id,t,o).catch(()=>{}),M(o,()=>h(a,"error")),{ok:!1,message:a,nextInput:n?"":"/apply",selectInput:!n}}finally{T(!1)}},nu=async(e,t,o)=>{if(!i||!c||e.tool!=="post"&&e.routedTool!=="post")return null;const r=(A(e.params.asset_id)?.trim()??"").replace(/^@/,""),s=fe.find(y=>y.artifactId===r||y.cellAddress.toLowerCase()===r.toLowerCase()),a=s?.artifactId??r,l=re.get(a)??s;if(!a||l?.type!=="video"&&l?.type!=="final")return null;const m=c.posts?.find(y=>y.id===e.params.post_cell_id),u=lk(c,m?.definition.source?.artifactId??a),w=[...z.map(y=>({reference:y.artifactId,type:y.type})),...fe.map(y=>({reference:y.cellAddress,type:y.type}))],v=await Promise.all(u.steps.map(async y=>{const R=await b("list_cell_generations",{book_id:i,notebook_id:c.id,cell_id:y.outputCellId??y.producerCellId,limit:20},{background:!0,chat:o}).catch(()=>null),$=D(R)?.attempts,F=Array.isArray($)?$:[],J=ck(dk({attempts:F,outputArtifactId:y.outputArtifactId,outputAssetPrompt:y.outputArtifactId?re.get(y.outputArtifactId)?.prompt??null:null,producerResolvedPrompt:y.producerResolvedPrompt,producerPrompt:y.producerPrompt}),w),P=y.sourceArtifactIds.flatMap(H=>{const ee=re.get(H);if(ee?.type!=="image")return[];const le=fe.find(me=>me.artifactId===H);return[{assetId:H,label:le?`@${le.cellAddress}`:ee.id,mediaUrl:ee.mediaUrl,thumbnailUrl:ee.thumbnailUrl}]}),L=uk({attempts:F,outputArtifactId:y.outputArtifactId,producerTool:y.producerTool,producerModel:y.producerModel,producerProvider:y.producerProvider,actions:Je});return{id:y.id,prompt:J,model:L,images:P}})),S=await Promise.all(u.upstreamArtifactIds.filter(y=>{const R=re.get(y);return R?.origin==="download"&&(R.type==="video"||R.type==="final")}).map(async y=>{const R=await b("read_asset_metadata",{asset_id:y,name:"original",book_id:i},{background:!0,chat:o}).catch(()=>null),$=D(R);return $?fk(y,$):null})),E=mk(S.filter(y=>y!==null));return pk({steps:v,credits:E},t)},ru=async e=>{const t=e.definition.source?.snapshotArtifactId;if(!t)return;const o={kind:"chat-action-plan",planId:Ct(),bookId:i,prompt:`Post ${e.address} to X`,routedTool:"post",tool:"post",params:{book_id:i,asset_id:t,post_cell_id:e.id,platform:"x",text:e.definition.caption},message:"Review your X publication",summary:"Publish the saved clip to X",effect:"mutation",confirmation:{required:!0,reason:"Publishes this clip to X"}};await Un(o,o.prompt),ke(!0)},es=(e,t)=>{if(p.state!=="ready"||!i||!c)return{ok:!1,message:"Open a connected notebook before making a cold open."};const o=e?.replace(/^@/,""),n=o?fe.find(l=>l.artifactId===o||l.cellAddress.toLowerCase()===o.toLowerCase()):null,r=n?.artifactId??o??q?.outputArtifactId,s=r?re.get(r):null;if(!s||!["video","final"].includes(s.type)||!s.mediaUrl)return{ok:!1,message:"Select a playable video or use /edit-cold-open @a1."};const a=s.mediaUrl;return O(t,!1,()=>de(null)),O(t,!1,()=>qe(null)),O(t,!0,()=>V({kind:"cold-open",review:{bookId:i,notebookId:c.id,assetId:s.artifactId,label:n?`@${n.cellAddress}`:s.label??s.id,mediaUrl:a,requestId:Ct(),suggestion:null}})),ke(!0),ft("Cold-open review opened")},sn=c?.posts??[],ts=(e,t)=>b(e,t,{background:!0}),lt=e=>V(t=>t?.kind==="post-delivery"?{...t,review:{...t.review,...e}}:t),os=async()=>{try{lt({connection:await Np(ts)})}catch(e){lt({connection:{connected:!1,pending:!1,hasCredentials:!0,error:e instanceof Error?e.message:String(e)}})}},su=async()=>{try{const e=await gk(ts);V(t=>t?.kind==="post-delivery"?{...t,review:kk(t.review,e)}:t)}catch(e){lt({icloud:{available:!1,root:"",shared:null,role:null,reason:e instanceof Error?e.message:String(e)}})}},au=async()=>{const e=window.open("about:blank","_blank");lt({connecting:!0});try{const t=await Lp(b);e?e.location.href=t:window.open(t,"_blank","noopener,noreferrer");const o=Q.current.bookId,n=await Fp(ts,ot,()=>Q.current.bookId===o);lt({connection:n,connecting:!1})}catch(t){e?.close(),lt({connecting:!1,connection:{connected:!1,pending:!1,hasCredentials:!0,error:t instanceof Error?t.message:String(t)}})}},ns=(e,t,o)=>{if(p.state!=="ready"||!i||!c)return{ok:!1,message:"Open a connected notebook before delivering a Post."};const n=il(sn,c.cells,e,q?.id??null),r=t==="dropbox"?"/upload-post-to-dropbox @b1":"/save-post-to-icloud @b1";return n?as(n,t,o):{ok:!1,message:e?.trim()?`${e.trim()} is not a Post or a clip. Select one or use ${r}.`:`Select a Post cell or use ${r}.`}},rs=async(e,t,o)=>{const n=e?.trim(),r=n&&p.state==="ready"&&i&&c&&!il(sn,c.cells,n,null)?Qg(c.cells,n):null;if(!r||!i||!c)return ns(e,t,o);const s=Yg(sn,r.id);if(s)return as(s,t,o);try{const a=await b("create_post",{book_id:i,notebook_id:c.id,source_cell_id:r.id});return await N(i,c.id),as(a,t,o)}catch(a){return{ok:!1,message:a instanceof Error?a.message:String(a)}}},ss=async(e,t,o,n,r)=>{const s=Ct(),a=l=>l?.kind==="post-delivery"&&l.review.postId===t&&l.review.copy.drafting?.requestId===s;V(l=>l?.kind==="post-delivery"&&l.review.postId===t?{...l,review:{...l.review,copy:{...l.review.copy,drafting:{requestId:s,language:n},error:null}}}:l);try{const l=hg(await b("draft_post_copy",vg(e,t,o,n,r)));V(m=>a(m)&&m?.kind==="post-delivery"?{...m,review:{...m.review,copy:yg(m.review.copy,n,l,r)}}:m)}catch(l){const m=l instanceof Error?l.message:String(l);V(u=>a(u)&&u?.kind==="post-delivery"?{...u,review:{...u.review,copy:{...u.review.copy,drafting:null,error:m}}}:u)}},iu=(e,t,o)=>{const n={...t.copy,language:o};lt({copy:n}),al(n,o,Rs(e))&&ss(t.bookId,e.id,n,o,null)},lu=(e,t)=>{Rs(e)||t.copy.drafting||ss(t.bookId,e.id,t.copy,t.copy.language,t.copy.prompt.trim()||null)},as=(e,t,o)=>{if(!i||!c)return{ok:!1,message:"Open a connected notebook before delivering a Post."};const n=co?.name??"book",r=Rg(e);return O(o,!1,()=>de(null)),O(o,!1,()=>qe(null)),O(o,!0,()=>V({kind:"post-delivery",review:{bookId:i,notebookId:c.id,postId:e.id,entry:t,destination:t,pinnedDestination:!1,copy:r,icloudFolder:Mg(e,n),dropboxFolder:Pg(e,n),connection:null,connecting:!1,icloud:null,receipt:null,sync:null}})),ke(!0),su(),t==="dropbox"&&os(),al(r,r.language,Rs(e))&&ss(i,e.id,r,r.language,null),ft(t==="dropbox"?"Dropbox upload review opened":"Save to iPhone review opened")},cu=e=>{lt({destination:e,pinnedDestination:!0}),e==="dropbox"&&os()},Un=async(e,t,o,n)=>{const r=u=>{const w=A(u);return w?er(Ts(w.startsWith("@")?w:`@${w}`,fe))[0]??null:null};if(e.tool==="prepare_cold_open"||e.tool==="edit_cold_open")return es(A(e.params.asset_id)??void 0,n);if(e.tool==="upload_post_to_dropbox"||e.tool==="save_post_to_icloud")return rs(A(e.params.post_cell_id)??void 0,e.tool==="upload_post_to_dropbox"?"dropbox":"icloud",n);if(e.tool==="show_media_fullscreen"){const u=gg(e.params,c?.cells??[],z);return u.ok?o?.()===!1||n?.isCurrent()===!1?{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."}:(O(n,!1,()=>V(null)),O(n,!1,()=>de(null)),Fn(u.cell,u.asset),{ok:!0,message:`Opened ${u.address} fullscreen`}):u}if(e.tool==="apply_watermark"||e.routedTool==="apply_watermark"){const u=A(e.params.asset_id)?.replace(/^@/,""),v=(u?fe.find(Fe=>Fe.artifactId===u||Fe.cellAddress.toLowerCase()===u.toLowerCase()):void 0)?.artifactId??u,S=fl(v,q,z,new Map(fe.map(Fe=>[Fe.artifactId,Fe.cellAddress])));if(!S.ok)return{ok:!1,message:S.message};const E=ae(e.params.qr_start_seconds),y=ae(e.params.qr_end_seconds),R=ae(e.params.handle_start_seconds),$=ae(e.params.handle_end_seconds),F=ae(e.params.qr_opacity),J=ae(e.params.handle_opacity),P=ae(e.params.handle_vertical_percent),L=ae(e.params.handle_padding),H=ae(e.params.handle_padding_y),ee=ae(e.params.handle_rounding),le=ae(e.params.fade_seconds),me=e.params.position,ze=e.params.handle_position,be=e.params.include_platform_icon;return Ua(S.artifactId,S.label,{...kg(e.params.platform)?{platform:e.params.platform}:{},...A(e.params.handle)?{handle:A(e.params.handle)??void 0}:{},...A(e.params.url)?{url:A(e.params.url)??void 0}:{},...typeof e.params.include_qr=="boolean"?{includeQr:e.params.include_qr}:{},...typeof e.params.include_handle=="boolean"?{includeHandle:e.params.include_handle}:{},...jk(me)?{position:me}:{},...P!==null?{handleVerticalPercent:Cl(P)}:{},...Tk(ze)?{handlePlacement:ze}:{},...typeof be=="boolean"?{includePlatformIcon:be}:{},...typeof e.params.include_handle_border=="boolean"?{includeHandleBorder:e.params.include_handle_border}:{},...L!==null?{handlePadding:nr(L)}:{},...H!==null?{handlePaddingY:nr(H)}:{},...ee!==null?{handleRounding:Il(ee)}:{},...F!==null?{qrOpacity:or(F)}:{},...J!==null?{handleOpacity:or(J)}:{},...E!==null&&E>=0?{qrStartSeconds:E}:{},...y!==null&&y>=0?{qrEndSeconds:y}:{},...R!==null&&R>=0?{handleStartSeconds:R}:{},...$!==null&&$>=0?{handleEndSeconds:$}:{},...le!==null?{fadeSeconds:yl(le)}:{},...typeof e.params.save_default=="boolean"?{saveDefault:e.params.save_default}:{}},n),ft(`Watermark review ready for ${S.label}`)}if(e.tool==="extract_audio"){const u=r(e.params.asset_id);return u?await ai({sourceReference:u},o,n):{ok:!1,message:"The chat model did not select a video source."}}if(e.tool==="extract_frame"&&(e.params.frame==="first"||e.params.frame==="last")){const u=r(e.params.asset_id);if(!u)return{ok:!1,message:"The chat model did not select a video source."};const w={frameMode:e.params.frame,sourceReference:u};return e.confirmation.required===!1?await ii(w,o,n):await li(w,o,n)}if(e.tool==="extract_frame"){const u=r(e.params.asset_id),w=ae(e.params.timestamp);if(!u||w===null||w<0)return{ok:!1,message:"The chat model did not select a valid video source and timestamp."};const v={frameMode:"time",sourceReference:u,timestampSeconds:w};return e.confirmation.required===!1?await ii(v,o,n):await li(v,o,n)}if(e.tool==="split_video"){const u=r(e.params.asset_id),w=ae(e.params.chunk_a_end);return!u||!w||w<=0?{ok:!1,message:"The chat model did not select a valid split source and time."}:await rn({sourceReference:u,cutPointsSeconds:[w]},o,n)}if(e.tool==="split_video_by_durations"&&e.params.destination===void 0){const u=r(e.params.asset_id),v=(Array.isArray(e.params.target_secs)?e.params.target_secs:[7]).map(ae);if(v.some(S=>S===null||S<=0))return{ok:!1,message:"The chat model did not select valid split durations."};if(u)return await rn({sourceReference:u,cutPointsSeconds:ml(v)},o,n)}if(e.effect==="generation"){const u=bg(e.tool,e.routedTool,Je),w=A(e.params.prompt)??t,v=Ts(w,fe),S=wg(e.params).map($=>Ts(`@${$}`,fe)).join(" "),E=er(S),y=er(v),R={cellType:u,mediaKind:Ds(u),prompt:w,sourceReferences:E.length>0?E:y.length>0?y:er(t)};return await tu(R,{isCurrent:o,...A(e.params.model)?{preferredModel:A(e.params.model)}:{},reason:e.confirmation.reason,routedParams:e.params},n)}if(e.confirmation.required===!1)return await ui(e,o,n);const a=e.tool==="post"||e.routedTool==="post"?await Ha():null,l=await nu(e,Xn(a??jo.status),n),m=l?{...e,params:dn(e.params,eo(l))}:e;return o?.()===!1?{ok:!1,message:"Workspace changed. Repeat the command in the current workspace."}:(O(n,!1,()=>de(null)),O(n,!0,()=>V({kind:"routed",plan:m,xPostReview:l})),ft("Action preview ready"))},du=(e,t)=>{const o=ws({...t,cells:[e.cell],edges:[]},z,De)[0];if(!o)return;const n=new Date().toISOString();bt(r=>r.some(s=>s.id===o.id)?r.map(s=>s.id===o.id?{...o,data:{...o.data,status:"queued",statusStartedAt:n}}:s):[...r,{...o,data:{...o.data,status:"queued",statusStartedAt:n}}])},uu=async(e,t=null,o)=>{const n=t?{...e,draft:Qn(e.draft,t)}:e,r=t?`/apply ${t}`:"/apply ";if(!n.draft.cell.prompt?.trim())return{ok:!1,message:"Enter a generation prompt before applying.",nextInput:r,selectInput:!1};if(!i||!c||c.id!==n.notebookId)return{ok:!1,message:"The generation draft belongs to another notebook."};let s;try{const E=pe(await b("get_notebook",{book_id:i,notebook_id:n.notebookId},{chat:o}));if(!E)throw new Error("The server returned an invalid notebook");s=E}catch(E){return{ok:!1,message:E instanceof Error?E.message:String(E),nextInput:r,selectInput:!1}}if(xl(s,n.expectations))return O(o,!1,()=>V(null)),{ok:!1,message:"Notebook changed since this preview; prepare the action again."};if(!At)return{ok:!1,message:"Offline: cloud generation is unavailable.",nextInput:r,selectInput:!1};M(o,()=>V(E=>E?.kind==="generation"&&E.draft.cell.id===n.draft.cell.id?{...E,draft:n.draft,previewError:null,previewLoading:!0,previewStale:!1}:E));let a;try{$t.cancel(),ho.current+=1,a=await Br(n.draft,s,o)}catch(E){const y=E instanceof Error?E.message:String(E);return M(o,()=>V(R=>R?.kind==="generation"&&R.draft.cell.id===n.draft.cell.id?{...R,draft:n.draft,previewError:y,previewLoading:!1,previewStale:!1}:R)),{ok:!1,message:y,nextInput:r,selectInput:!1}}M(o,()=>V(E=>E?.kind==="generation"&&E.draft.cell.id===n.draft.cell.id?{...E,draft:n.draft,preview:a,previewError:null,previewLoading:!1,previewStale:!1}:E));const l=Rk(a);if(l)return{ok:!1,message:l,nextInput:r,selectInput:!1};const m="videobook.cloud-generation-consent";if(window.localStorage.getItem(m)!=="accepted"){if(!window.confirm(`Cloud generation disclosure
|
|
32
|
+
|
|
33
|
+
Provider/model: ${n.draft.action.provider} · ${n.draft.action.model}
|
|
34
|
+
Payload class: prompt text and connected media references.
|
|
35
|
+
Your local source files are sent only when required by the selected model.
|
|
36
|
+
|
|
37
|
+
Continue and remember this choice on this device?`))return{ok:!1,message:"Cloud generation cancelled before sending data",nextInput:r,selectInput:!1};window.localStorage.setItem(m,"accepted")}const u=n.draft.cell.id,w=U(n.draft.cell.slot);let v=!1,S=!1;T(!0),ne(u,null),oe(u,!0),_e(n.draft.cell.slot),Y(u,o,a),du(n.draft,s);try{await gl({bookId:i,callTool:(H,ee)=>b(H,ee,{chat:o}),document:s,draft:n.draft,...s.revision?{expectedRevision:s.revision}:{}}),v=!0;const E=await ko(u,"chat",o),y=await b("run_notebook_cell",{book_id:i,notebook_id:s.id,cell_id:u,plan:E,actor:"videobook-user"},{chat:o});S=!0;const R=D(y);se(o);const $=A(R?.run_id),F=A(R?.job_id),J=A(R?.output_cell_id);if(O(o,!1,()=>V(null)),Rr.current||go(),oe(u,!1),!$||!F)return await N(i,s.id,void 0,o).catch(()=>{}),{ok:!0,message:`${w} was accepted; follow its status in Jobs`};M(o,()=>h(`${w} queued`));const P=J??u;let L=Se(n.draft.cell.slot);if(J){const H=await je(i,s.id,o).catch(()=>null);M(o,()=>{Yo([J]),po([J],{scroll:"center"})}),ne(J,null),oe(J,!0);const ee=H?.cells.find(le=>le.id===J);ee&&(L=Se(ee.slot))}else po([u],{scroll:"center"});return Zo({bookId:i,notebookId:s.id,cellId:P,address:L,runId:$,jobOperationId:F},o),await N(i,s.id,void 0,o).catch(()=>{}),{ok:!0,message:`${w} queued`}}catch(E){const y=E instanceof Error?E.message:String(E),R=y.startsWith("Stale notebook revision:");return v&&!S&&await b("delete_notebook_cell",{book_id:i,notebook_id:s.id,cell_id:u},{chat:o}).catch(()=>{}),S||(bt($=>$.filter(F=>F.id!==u)),oe(u,!1)),ne(u,y),await N(i,s.id,void 0,o).catch(()=>{}),R?(O(o,!1,()=>V(null)),M(o,()=>h("Notebook changed since this preview; prepare the action again.","error")),{ok:!1,message:"Notebook changed since this preview; prepare the action again."}):(M(o,()=>h(y,"error")),{ok:!1,message:y,nextInput:r,selectInput:!1})}finally{T(!1)}},fu=async(e=null,t)=>{if(!_||!i)return{ok:!1,message:"There is no pending chat action."};if(_.kind==="cold-open"){const o=_.review,n=()=>Q.current.bookId===o.bookId&&Q.current.notebookId===o.notebookId&&(t?.isCurrent()??!0),r=(a,l,m)=>b(a,l,{...m,chat:t});if(!o.suggestion){const a=await wk(r,o,n);return O(t,!0,()=>V({kind:"cold-open",review:a})),ft("Adjust the highlight, then create the copy")}const s=await hk(r,o,n);return await N(o.bookId,o.notebookId,n,t),n()?(O(t,!1,()=>V(null)),Y(s.cellId),se(t),{ok:!0,message:`Cold-open copy created as ${s.address}`}):{ok:!0,message:`Cold-open copy created as ${s.address}`}}if(_.kind==="post-delivery"){const o=_.review,n=sn.find(u=>u.id===o.postId)??null,r=nl(n,o);if(!n||r.blocking)return{ok:!1,message:r.blocking??"This Post is no longer on the canvas."};const s=()=>Q.current.bookId===o.bookId&&Q.current.notebookId===o.notebookId&&(t?.isCurrent()??!0),a=vk(n,o);a&&await b("update_post",a,{chat:t});const l=await b(yk(o.destination),Ik(n,o),{chat:t});await N(o.bookId,o.notebookId,s,t);const m=Ck(l,o.destination);return s()&&O(t,!0,()=>V({kind:"post-delivery",review:{...o,icloudFolder:l.runtime.icloud?.folder??o.icloudFolder,dropboxFolder:l.runtime.dropbox?.folder??o.dropboxFolder,receipt:m,sync:null}})),{ok:!0,message:m}}if(_.kind==="generation")return await uu(_,e,t);if(_.kind==="routed"&&(_.plan.tool==="post"||_.plan.routedTool==="post")){const o=Li(qi(_.plan.params),void 0,hn),n=_.xPostReview?.options.enabled&&eo(_.xPostReview).length===0?Ni:null;if(o||n)return{ok:!1,message:o??n??"The post is not ready.",nextInput:"/apply",selectInput:!1}}if(_.kind==="frame"||_.kind==="split"||_.kind==="notebook"){const o=pe(await b("get_notebook",{book_id:i,notebook_id:_.notebookId},{chat:t}));if(!o)return{ok:!1,message:"The server returned an invalid notebook"};const n=_.kind==="notebook"?_.plan.expectations:_.expectations;if(xl(o,n))return O(t,!1,()=>V(null)),{ok:!1,message:"Notebook changed since this preview; prepare the action again."};if(_.kind==="frame"){const s=await si(_.command,o,void 0,t);if(s.ok)O(t,!1,()=>V(null));else if(s.message.startsWith("Stale notebook revision:"))return O(t,!1,()=>V(null)),{ok:!1,message:"Notebook changed since this preview; prepare the action again."};return s}if(_.kind==="split"){const s=await Zd(_.command,o,t);if(s.ok)O(t,!1,()=>V(null));else if(s.message.startsWith("Stale notebook revision:"))return O(t,!1,()=>V(null)),{ok:!1,message:"Notebook changed since this preview; prepare the action again."};return s}const r=_.plan.action;if(r.kind==="run"){const s=Po(o,r.source),a=await en(s.id,o,t);return a?.ok?(O(t,!1,()=>V(null)),{ok:!0,message:`Run requested for ${U(s.slot)}`}):a?.message.startsWith("Stale notebook revision:")?(O(t,!1,()=>V(null)),{ok:!1,message:"Notebook changed since this preview; prepare the action again."}):a??{ok:!1,message:`Could not run ${U(s.slot)}`}}T(!0);try{const s=o.revision?{expected_revision:o.revision}:{};if(r.kind==="create"){const a=r.destination,l=D(await b("create_notebook_cell",{book_id:i,notebook_id:o.id,...s,cell:{type:r.cellType,slot:a,...r.cellType==="prompt"||r.cellType==="analyze"||oo(r.cellType)?{prompt:""}:{}}},{chat:t})),m=A(l?.id);m&&Y(m,t)}else if(r.kind==="move"){const a=Po(o,r.source),l=Po(o,r.destination);await b("move_notebook_cells",{book_id:i,notebook_id:o.id,...s,slots:[{id:a.id,row:r.destination.row,column:r.destination.column},...l?[{id:l.id,row:r.source.row,column:r.source.column}]:[]]},{chat:t})}else if(r.kind==="delete"){const a=Po(o,r.source);await b("delete_notebook_cell",{book_id:i,notebook_id:o.id,cell_id:a.id,...s},{chat:t})}else if(r.kind==="connect"){const a=Po(o,r.source),l=Po(o,r.target),m=r.targetInput??dl(o,{source:a.id,target:l.id,targetHandle:null});await b("set_notebook_cell_input",{book_id:i,notebook_id:o.id,source_cell_id:a.id,target_cell_id:l.id,target_input:m,...s},{chat:t})}else throw new Error("Unsupported notebook action");return O(t,!1,()=>V(null)),await N(i,o.id,void 0,t),r.kind==="create"&&se(t),M(t,()=>h(_.plan.summary)),{ok:!0,message:_.plan.summary}}catch(s){const a=s instanceof Error?s.message:String(s);return a.startsWith("Stale notebook revision:")?(O(t,!1,()=>V(null)),M(t,()=>h("Notebook changed since this preview; prepare the action again.","error")),{ok:!1,message:"Notebook changed since this preview; prepare the action again."}):(M(t,()=>h(a,"error")),{ok:!1,message:a,nextInput:"/apply",selectInput:!0})}finally{T(!1)}}return _.kind==="chain-step"?await ou(_,t):await ui(_.plan,void 0,t)},fi=async(e,t,o,n,r)=>{if(e==="download_video"&&c)return await Wn(t,A(o.url)??"",void 0,r);const s=c?bl(e,t,c.cells,Ve):[];if(c&&s.length>0){const a=[];let l=null;for(const u of s){const w=D(await b("create_notebook_cell",{book_id:i,notebook_id:c.id,cell:u},{chat:r})),v=A(w?.id);if(!v)throw new Error("The server did not return the new notebook cell");l??=v,a.push(U(u.slot))}Q.current.bookId===i&&(Y(l,r),await N(i,c.id,void 0,r));const m=`Created ${a.join(" and ")}`;return se(r),M(r,()=>h(m)),{ok:!0,message:m}}if(Q.current.bookId===i){const a=await N(i,c?.id,void 0,r);tr(c,a)&&se(r)}if(e==="rename_asset"){const a=D(t),l=A(a?.label);return{ok:!0,message:l?`Renamed asset to ${l}`:"Asset renamed"}}return{ok:!0,message:fn(t,`${n} complete`)}},mi=async(e,t,o,n)=>{const r=i,s=D(await b("asset_manifest",{book_id:r,asset_id:e.artifactId},{chat:n}));if(Q.current.bookId!==r)return;const a=(Array.isArray(s?.files)?s.files:[]).flatMap(u=>{const w=A(D(u)?.name);return w?[{name:w,url:`/files/${encodeURIComponent(r)}/${encodeURIComponent(e.artifactId)}/${w.split("/").map(encodeURIComponent).join("/")}`}]:[]}),l=t==="original"?a.find(u=>u.name.startsWith("original.")):t?a.find(u=>u.name.startsWith(`${t}.`)):o?a[o-1]:void 0;if((t||o)&&!l)throw new Error(t?`No ${t} file exists yet. Use render video to create it.`:"That file position does not exist.");const m=document.activeElement instanceof HTMLElement?document.activeElement:null;M(n,()=>To({media:{label:e.label,assetId:e.artifactId,type:e.type,url:e.mediaUrl,thumbnailUrl:e.thumbnailUrl,files:a,initialFile:l?.name,opener:m},opener:m,turnId:n?.id}))},pi=async(e,t,o)=>{if(e.handler.kind!=="ui")return null;const n=e.handler.action,r=Bg[n];if(r.kind==="existing")return null;if(r.kind==="library")return Qr(),{ok:!0,message:"Library opened"};if(r.kind==="screen")return _o(r.screen),{ok:!0,message:`${r.screen==="jobs"?"Jobs":"Settings"} opened`};const s=A(t.asset_id??t.asset_ref??t.artifact_id)??Oe?.media?.assetId??te?.asset.artifactId??q?.outputArtifactId,a=z.find(l=>l.artifactId===s)??z.find(l=>fe.some(m=>m.artifactId===l.artifactId&&m.cellAddress.toLowerCase()===s?.replace(/^@/u,"").toLowerCase()));if(r.kind==="search")return await Ce(void 0,void 0,r.query,void 0,o),{ok:!0,message:"Actions opened"};if(r.kind==="form"){const l=e.command==="/storage"?"storage_status":r.tool,m=X?X.frameRate.numerator/X.frameRate.denominator:30,u=Hg(n,t,m);if(a&&(u.asset_id=a.artifactId),n.startsWith("timeline_audio_")&&n!=="timeline_audio_add"&&t.audio_ref){const w=zg(String(t.audio_ref),X,z,fe);if(!w.ok)return w;u.audio_id=w.clipId}return n==="viewer_focus_file"&&a?await mi(a,void 0,Kg(t.position),o):await Ce(`tool.${l}`,u,void 0,void 0,o),{ok:!0,message:`${e.title} options opened`}}if(r.action==="upload")return Ws.current?.click(),{ok:!0,message:"Choose files to import"};if(r.action==="notebook"){const l=A(t.name)?.trim();if(l){const u=Qi(await b("list_notebooks",{book_id:i},{chat:o})).find(w=>w.name===l||w.id===l);if(!u)return await Ce("tool.create_notebook",{name:l},void 0,void 0,o),{ok:!0,message:"Create notebook options opened"};await N(i,u.id,void 0,o)}else if(!c)return await Ce("tool.create_notebook",{name:"scratch"},void 0,void 0,o),{ok:!0,message:"Create notebook options opened"};return _o("notebook"),{ok:!0,message:"Notebook opened"}}if(r.action==="save"){if(!c)throw new Error("Open a notebook first.");return await je(i,c.id,o),{ok:!0,message:"Notebook changes are saved automatically. Saved state verified."}}if(r.action==="collapse"||r.action==="expand"){const l=r.action==="expand",m=Xg(A(t.side));return m!=="left"&&(!l||no("expand"))&&ke(l),m!=="right"&&(l?await Co():xr(!1)),{ok:!0,message:l?"Workspace panels opened":"Workspace panels closed"}}if(r.action==="close")return Kt(),M(o,()=>To(null)),{ok:!0,message:"Viewer closed"};if(r.action==="play"){const l=Jg(A(t.slot),X);return l.ok?(M(o,()=>To({initialFrame:l.initialFrame,turnId:o?.id,opener:document.activeElement instanceof HTMLElement?document.activeElement:null})),{ok:!0,message:"Sequence preview opened"}):{ok:!1,message:l.message}}if(!a)return await Ce(e.id,t,void 0,void 0,o),{ok:!0,message:"Choose media for this action"};if(r.action==="copy")return await navigator.clipboard.writeText(a.label),{ok:!0,message:"Media label copied"};if(r.action==="history"){const l=c?.cells.find(m=>m.outputArtifactId===a.artifactId);return l?vi(l.id,a.artifactId):await Ce("tool.asset_history",{asset_id:a.artifactId},void 0,void 0,o),{ok:!0,message:"Media history opened"}}if(r.action==="skeleton"){if(a.type!=="image")throw new Error("Choose an image for a pose guide.");return await Ce("tool.generate_image",{model:"kie:qwen3/image-to-image",refs:{image:[a.artifactId]},prompt:"Create a pose skeleton guide from this reference image. Preserve the visible body poses, joint positions and framing. Show only clearly connected colored skeleton joints and limbs on a black background, without clothing, faces, scenery or text."},void 0,void 0,o),{ok:!0,message:"AI pose guide options opened. Review the provider and cost before generating."}}return await mi(a,r.action==="open"?void 0:r.action,void 0,o),{ok:!0,message:"Media preview opened"}},is=async(e,t,o)=>{try{const n=e.trim().toLowerCase(),r=Ms(e);if(r)return r.promptOverride&&(he||_?.kind!=="generation")?{ok:!1,message:"A quick prompt can only revise a pending generation.",nextInput:e,selectInput:!1}:he?await $d(o):_?await fu(r.promptOverride,o):ce?await Wd(o):{ok:!1,message:"There is no pending action to apply."};if(n==="/cancel")return!he&&!_&&!ce?{ok:!1,message:"There is no pending action to cancel."}:(O(o,!1,()=>qe(null)),O(o,!1,()=>V(null)),O(o,!1,()=>de(null)),{ok:!0,message:"Pending action cancelled"});if(he&&O(o,!1,()=>qe(null)),!i&&!e.startsWith("/"))return{ok:!1,message:"Load or create a book first."};if(!e.startsWith("/")){const P=await b("chat",{book_id:i,...c?{notebook_id:c.id}:{},prompt:e,model:Us},{chat:o});return D(P)?.kind==="chat-action-plan"?await Un(As(P),e,void 0,o):(O(o,!1,()=>V(null)),O(o,!1,()=>de(null)),pl(P)?await Wn(P,Gl(e),void 0,o):(await N(i,c?.id,void 0,o),{ok:!0,message:fn(P,"Command complete")}))}const[s,...a]=e.trim().split(/\s+/),l=s.toLowerCase(),m=a.join(" ");if(l==="/goal")return await fd(m,o);if(l.toLowerCase()==="/actions")return await Ce(void 0,void 0,m,void 0,o),{ok:!0,message:"Actions opened"};const u=l.toLowerCase()==="/duplicate"?[js(a[0]??"",En),...a.slice(1)].filter(Boolean).join(" "):js(m,En),w=xt.length?xt:Is(await b("list_workspace_actions",{detail:"full"},{chat:o})).actions;xt.length||dr(w);const v=$l(Cs(w,bn),l,u),S=w.find(P=>[P.command,...P.aliases].includes(l));if(v?.workspaceActionId||S&&!m&&(S.inputSchema.required??[]).some(P=>!["book_id","notebook_id","sequence_id"].includes(P))){const P=v?St(u,v.params):{};return await Ce(S?.id??v?.workspaceActionId,P,void 0,void 0,o),{ok:!0,message:"Action options opened"}}if(l==="/extract-audio")return!c||a.length!==1?{ok:!1,message:"Usage: /extract-audio @video"}:await ai({sourceReference:lr(a[0])},void 0,o);if(l==="/split"){const P=Tg(e);return P?await rn(P,void 0,o):{ok:!1,message:"Usage: /split @video [at 5s, 12.5s] | keep 0.03-0.11 | remove 0.03-0.11"}}if((l==="/split-chunks"||l==="/even-split")&&new RegExp(`^@${Hl}$`,"iu").test(a[0]??"")){const[P,...L]=a,H=(L.length>0?L:["7"]).map(ee=>Number(ee.replace(/\s*s(?:ec(?:onds?)?)?$/iu,"")));return H.some(ee=>!Number.isFinite(ee)||ee<=0)?{ok:!1,message:"Split durations must be positive seconds."}:await rn({sourceReference:lr(P),cutPointsSeconds:ml(H)},void 0,o)}if(l==="/rough-cut")return await Bd("slash",o);if(l==="/sound-effects")return await Hd("slash",o);if(l==="/generate-cell"){if(!c||a.length!==1)return{ok:!1,message:"Usage: /generate-cell @cell-id"};const P=lr(a[0]),L=c.cells.find(H=>H.id.toLowerCase()===P||U(H.slot).slice(1).toLowerCase()===P);return!L||!Ui(L)?{ok:!1,message:"Choose a configured generation cell"}:await Wr(L.id,"slash",o)}if(l==="/arrange-videos-column"||l==="/arrange-videos-row"){const P=q?.slot??Ve;return P?await Ad(l==="/arrange-videos-column"?"column":"row",P,o):{ok:!1,message:"Select a cell to anchor the arrangement"}}if(l==="/group-images"){const P=q?.slot??Ve;return P?await Oa(P,o):{ok:!1,message:"Select a cell to anchor the grouping"}}if(l==="/track-add"){const P=jg(a);return P.ok?await zd(P.kind,P.name,o):P}if(l==="/track-remove"){const P=Kb(X,a[0]);return!P||a.length!==1?{ok:!1,message:"Usage: /track-remove @track-id"}:await Kd(P.trackId,o)}if(l==="/export-sequence"||l==="/export"&&a.some(P=>P==="@sequence-main"||P.startsWith("--")||P===`@${X?.sequenceId}`)){if(!X)return{ok:!1,message:"Load the primary sequence first."};const P=$g(a,X.sequenceId);if(!P.ok)return P;const{orientation:L,captions:H}=P,ee=Ke(await b("get_primary_sequence",{book_id:i},{chat:o}));if(!ee)return{ok:!1,message:"Load the primary sequence first."};Ee(ee);const le=await b("plan_sequence_export",{book_id:i,source_surface:"slash",actor:"videobook-user",sequence_revision:ee.revision,orientation:L,captions:H},{chat:o}),me=D(le);if(me?.kind==="invalid-export"){const ze=D(me.validation);return{ok:!1,message:(Array.isArray(ze?.errors)?ze.errors.map(Fe=>A(D(Fe)?.message)).filter(Boolean):[]).join(" · ")||"Export validation failed"}}return await Jt(ut(le),o)}const E=qg(l,a,{sequence:X,assets:z,mentionAssets:fe});if(E.handled)return E.ok?await za(E.request,"slash",o):E;const y=$l(bn,l,u);if(!y)return{ok:!1,message:`Unknown command: ${l}`};if(S?.handler.kind==="ui"){const P=y.command==="/post"?Eb(u):St(u,y.params),L=await pi(S,P,o);if(L)return L}if(y.uiAction==="switch_book"){const P=y.command.slice(1),L=x.find(ee=>ee.name.toLowerCase()===P.toLowerCase());if(!L)return{ok:!1,message:`Book not found: ${P}`};const H=await $a(L.bookId);return H.ok?{ok:!0,message:`Opened ${L.name}`}:{ok:!1,message:H.error}}if(y.uiAction==="open_projects"){const P=await Co();return P.ok?{ok:!0,message:"Project selector opened"}:{ok:!1,message:P.error}}if(y.uiAction==="open_notebook")return tt("notebook"),{ok:!0,message:"Notebook opened"};if(y.uiAction==="x_connect")return tt("settings"),nn(),await Yr();if(y.uiAction==="open_provider_keys")return tt("settings"),await nn(),{ok:!0,message:"Settings opened"};if(y.uiAction==="open_music_video"){if(!X)return{ok:!1,message:"Load the primary sequence first."};const P=St(u,y.params),L=A(P.audio_ref),H=Ng(L,z);if(!H.ok)return H;const ee=H.asset,le=Ct(),me=document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:document.querySelector('[aria-label="Videobook command input"]');return M(o,()=>qo(null)),An(null),kt.load(),Ge({key:le,audioArtifactId:ee.artifactId,returnFocus:me,setup:{status:"loading"}}),no("action")&&ke(!0),Ka(le,ee.artifactId,X,o).catch(()=>{}),{ok:!0,message:`Music-video editor opened for ${ee.label}`}}if(y.uiAction==="open_alive_captions"){const P=St(u,y.params),L=Lg(A(P.asset_ref),z);if(!L.ok)return L;const H=L.asset,ee=Ct(),le=document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:document.querySelector('[aria-label="Videobook command input"]');return M(o,()=>qo(null)),An(null),Ge(null),yr({key:ee,asset:{artifactId:H.artifactId,label:H.label,mediaUrl:H.mediaUrl,width:H.width,height:H.height,fps:H.fps},returnFocus:le,state:{status:"loading"}}),ni(ee,H.artifactId,!1,o),{ok:!0,message:`Alive captions opened for ${H.label}`}}if(y.uiAction==="speak_preview"){const P=St(u,y.params),L=Fg({command:y.command,text:A(P.text)??"",voiceId:t?.speakVoiceId,hasNotebook:!!c});return L.kind==="prefill"?{ok:!0,message:L.message,nextInput:L.nextInput,selectInput:!1}:L.kind==="error"?{ok:!1,message:L.message}:await jd(L.text,L.voiceId,o)}if(y.uiAction==="open_cold_open"){const P=St(u,y.params);return es(A(P.asset_ref)??void 0,o)}if(y.uiAction==="open_post_dropbox"||y.uiAction==="open_post_icloud")return rs(m||void 0,y.uiAction==="open_post_dropbox"?"dropbox":"icloud",o);if(y.uiAction==="open_watermark"){const P=St(u,y.params),L=fl(A(P.asset_ref)??void 0,q,z,new Map(fe.map(H=>[H.artifactId,H.cellAddress])));return L.ok?(Ua(L.artifactId,L.label,void 0,o),ft(`Watermark review ready for ${L.label}`)):{ok:!1,message:L.message}}if(!y.mcpTool)return{ok:!1,message:`${y.command} is available from its workspace.`};if(y.mcpTool.tool==="download_video"&&!c)return{ok:!1,message:"Open a notebook before downloading media."};const R=St(u,y.params),F={...Ab(y.mcpTool.adapter,R),...y.mcpTool.injectParams??{}};if(y.mcpTool.autoInject?.includes("book_id")&&(F.book_id=i),y.mcpTool.autoInject?.includes("notebook_id")&&c&&(F.notebook_id=c.id),S&&S.confirmation!=="none")return await Ce(S.id,F,void 0,void 0,o),{ok:!0,message:"Review the action before running it"};const J=await b(y.mcpTool.tool,F,{chat:o});return await fi(y.mcpTool.tool,J,F,y.command,o)}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}},mu=async(e,t)=>{const o=$e;if(e.handler.kind!=="tool"){if(e.handler.kind==="ui"&&e.handler.action==="open_actions")return await Ce(),{message:"Actions opened"};const a=await pi(e,t);if(a){if(!a.ok)throw new Error(a.message);return Qe(w=>w===o?null:w),{message:a.message}}const l=Object.keys(e.inputSchema.properties??{}).map(w=>t[w]).filter(w=>w!=null).map(w=>Array.isArray(w)?w.join(" "):String(w)).join(" "),m=e.command==="/export-sequence"?`/export-sequence --aspect ${String(t.aspect??"16:9")} --captions ${String(t.captions??"burned")}`:`${e.command}${l?` ${l}`:""}`,u=await is(m);if(!u.ok)throw new Error(u.message);return Qe(w=>w===o?null:w),{message:u.message}}const n=e.handler.tool;if(n==="delete_asset"&&t.forget===!0){const a=z.find(m=>m.artifactId===t.asset_id);if(!a)throw new Error("Choose media from the current project.");const l=await bd({...a,errorMessage:null,lastUsedAt:null,owningBookId:i,owningBookName:co?.name??i},!0);if(!l.ok)throw new Error(l.message);return Qe(null),{message:l.message}}if(n==="create_book"||n==="rename_book"||n==="delete_book"){const a=n==="create_book"?await qa(String(t.name??"")):n==="rename_book"?await Na(String(t.book_id??i),String(t.name??"")):await La(String(t.book_id??i),String(t.confirm_name??""));if(!a.ok)throw new Error(a.error);return{message:`${e.title} complete`}}const r=await b(n,t);if(D(r)?.kind==="chat-action-plan"){const a=await Un(As(r),String(t.prompt??""));if(!a.ok)throw new Error(a.message);return Qe(null),{message:a.message}}if(n==="get_notebook"&&typeof t.notebook_id=="string")return await N(String(t.book_id??i),t.notebook_id),_o("notebook"),Qe(null),{message:"Notebook opened"};if(D(r)?.planVersion===1&&Array.isArray(D(r)?.stages)){const a=await Jt(ut(r));if(!a.ok)throw new Error(a.message);return Qe(null),{message:a.message}}const s=await fi(n,r,t,e.title);if(!s.ok)throw new Error(s.message);return{message:s.message,value:r}},pu=async(e,t)=>{if(e.confirmation==="generation"&&e.handler.kind==="tool"){const o=D(await b("estimate_cost",{calls:[{tool_name:e.handler.tool,input:t}]})),n=D(o?.estimate),r=Array.isArray(n?.warnings)?n.warnings.filter(m=>typeof m=="string"):[],s=typeof n?.usd=="number"?n.usd:null,a=Oi(r);return{cost:s!==null&&s>0&&(r.length===0||a)?`Estimated cost: $${s.toFixed(4)}`:"Cost estimate unavailable",message:`This action may send your prompt and selected media to a generation provider and incur charges.${r.length?` ${r.join(" ")}`:""} Confirm to start.`}}return{message:e.confirmation==="external"?`${e.title} sends the selected content outside this workspace. Review the destination and content before confirming.`:`${e.title} changes or removes the selected content. Review the target and values before confirming.`}},gu=async(e,t,o)=>{if(t?.action){const r=xt.find(l=>l.id===t.action?.id);if(!r)return{ok:!1,message:"Reload Actions and choose the command again.",nextInput:e};if(r.handler.kind==="ui"&&(r.handler.action==="open_post_dropbox"||r.handler.action==="open_post_icloud")){const l=e.trim().slice(r.command.length).trim();return rs(l||void 0,r.handler.action==="open_post_dropbox"?"dropbox":"icloud",o)}const s=Cs([r],[]).find(l=>l.command===r.command),a=js(e.trim().slice(r.command.length).trim(),En);return await Ce(r.id,{...t.action.values,...St(a,s.params)},void 0,void 0,o),{ok:!0,message:"Action options opened"}}const n=await is(e,t,o);return Ms(e)||e.trim().toLowerCase()==="/cancel"?Ar.current?.(ul(e,n)):ia.current?.(e,n.message),n},ku=async(e,t,o)=>{const n=(e.subjectMap?.subjects??[]).filter(m=>o.subjectIds.includes(m.id)),r=lg(t),s=cg(r,En);if(!s.ok)return{ok:!1,message:s.error,nextInput:t,selectInput:!1};if(s.artifactIds.includes(e.asset.artifactId))return{ok:!1,message:"Mention a different image as the replacement.",nextInput:t,selectInput:!1};if(s.artifactIds.length>0||Object.keys(o.replacements).length>0){const m=dg(o.regions,n),u=ug(m,o.replacements,s.artifactIds);if(!u.ok)return{ok:!1,message:u.error,nextInput:t,selectInput:!1};const w=Wk(t,r).replace(/\s+/g," ").trim();return await Dn(e,{operation:"replace",subjectIds:n.map(S=>S.id),...w?{prompt:w}:{},regions:fg(m,u.replacements),...o.model?{model:o.model}:{}})?{ok:!0,message:`Region replacement queued for ${m.length} ${m.length===1?"region":"regions"}.`}:{ok:!1,message:"The image replacement was not queued.",nextInput:t,selectInput:!1}}return o.subjectIds.length===0&&o.regions.length===0?t.trim()?await Dn(e,{operation:"whole_image",subjectIds:[],prompt:t,...o.model?{model:o.model}:{}})?{ok:!0,message:"Whole-image edit queued."}:{ok:!1,message:"The whole-image edit was not queued.",nextInput:t,selectInput:!1}:{ok:!1,message:"Describe the whole-image edit first.",nextInput:t,selectInput:!1}:o.subjectIds.length>0&&e.subjectMap?.status!=="ready"?{ok:!1,message:e.subjectMap?.status==="analyzing"?"Wait for people and object analysis to finish before editing.":"Analyze the image before editing subjects, or draw a region to edit.",nextInput:t,selectInput:!1}:await Dn(e,{operation:"edit",subjectIds:n.map(m=>m.id),prompt:t,...o.regions.length>0?{editRegions:o.regions.map(m=>m.box)}:{},...o.model?{model:o.model}:{}})?{ok:!0,message:`Image edit queued for ${o.regions.length+n.length} selected areas.`}:{ok:!1,message:"The image edit was not queued.",nextInput:t,selectInput:!1}},gi=e=>(/^\/(?:apply|cancel)(?:\s|$)/iu.test(e)&&(_||ce||he)||((_||ce||he)&&Be(),Y(null),Ne(null),pt(null),To(null),Qe(null),te&&Kt(),Fo(null)),ca(e)),ls=async(e,t)=>{const o=t?.chat??(Ms(e)||e.trim().toLowerCase()==="/cancel"?ca(e):void 0);o?.working();try{const n=await gu(e,t,o);return o?.finish({...n,...e.trim().toLowerCase()==="/cancel"&&n.ok?{status:"cancelled"}:{}}),n}catch(n){const r={ok:!1,message:n instanceof Error?n.message:String(n)};return o?.finish(r),r}},Eo=e=>{mc(t=>t?.row===e?.row&&t?.column===e?.column?t:e)},ki=(e,t)=>{const o=Do.current?.screenToFlowPosition({x:e,y:t});if(!o)return null;const n=ng(o,Tt);return n?wt.some(r=>r.row===n.row&&r.column===n.column)?null:n:null},bi=(e,t)=>G?null:ki(e,t),bu=e=>{k!=="notebook"||!Dt(e.dataTransfer)||Lo(!0)},wu=e=>{if(k!=="notebook"||!Dt(e.dataTransfer))return;const t=e.relatedTarget;t instanceof Element&&e.currentTarget.contains(t)||(Lo(!1),Eo(null))},hu=e=>{Dt(e.dataTransfer)&&e.preventDefault()},vu=e=>{Dt(e.dataTransfer)&&(Lo(!1),Eo(null))},yu=e=>{!Dt(e.dataTransfer)||e.defaultPrevented||(e.preventDefault(),k==="notebook"&&h("Drop one image, video, or audio file on an open grid square","error"))},Iu=e=>{if(!Dt(e.dataTransfer))return;const t=e.relatedTarget;t instanceof Element&&e.currentTarget.contains(t)||Eo(null)},Cu=e=>{if(e.preventDefault(),Dt(e.dataTransfer)){Gt(null),Lo(!0);const o=bi(e.clientX,e.clientY);Eo(o),e.dataTransfer.dropEffect=o?"copy":"none";return}Eo(null);const t=Do.current?.screenToFlowPosition({x:e.clientX,y:e.clientY});t&&Gt(ll(t))},Su=e=>{if(e.preventDefault(),Dt(e.dataTransfer)){if(e.stopPropagation(),Gt(null),Lo(!1),Eo(null),G){h("Wait for the current operation to finish","error");return}const n=[...e.dataTransfer.files];if(n.length!==1){h("Drop one image, video, or audio file per square","error");return}const r=bi(e.clientX,e.clientY);if(!r){h("Choose an open grid square for the media file","error");return}Jr(r,n[0]);return}const t=e.dataTransfer.getData("application/x-videobook-cell");if(!og(t))return;const o=Do.current?.screenToFlowPosition({x:e.clientX,y:e.clientY});Gt(null),Xr(t,o)},_o=e=>{Et(null),Vt(null),wo(),B&&Vn(),tt(e),e==="settings"&&nn(),e==="jobs"&&i&&N(i,c?.id).catch(t=>{h(t instanceof Error?t.message:String(t),"error")})},xu={ready:p.state==="ready",states:hr,onFile:(e,t)=>{Ga(e,t)},onFileError:Qo,onOpenLibrary:xo},wi=B?c?.cells.find(e=>e.id===B.cellId):void 0,qt=wi?Ft(wi.type):B?.cellId===null?"all":null,Bn=B?{...B,uploading:B.cellId!==null&&hr[B.cellId]?.operation==="upload",mode:ue.state.mode,reference:ue.state.reference,referenceStartSeconds:ue.state.startSeconds,referenceDurationSeconds:ue.state.durationSeconds,preparingReference:ue.state.preparing,error:ue.state.error??B.error}:null,Eu=e=>{ge(t=>t&&{...t,draftQuery:e})},_u=e=>{if(!B||ue.state.mode===e)return;const t=B.cellId;Ae.current+=1,ue.lifecycle.changeMode(e),ge(o=>o&&o.cellId===t?{...o,page:e==="text"?o.page:{...ir,total:o.assets.length},error:null,loading:!1,loadingMore:!1,preparingIndex:!1}:o),e==="text"&&yt(t,B.draftQuery,0,!1,{mode:e,reference:null,referenceStartSeconds:"0",referenceDurationSeconds:""})},Au=async e=>{if(!B||ue.state.mode==="text"||!i)return;const t=B;Ae.current+=1;const o=ue.state.mode;ge(r=>r&&r.cellId===t.cellId?{...r,error:null,loading:!1,loadingMore:!1,preparingIndex:!1}:r);const n=await ue.lifecycle.prepare(o,()=>Hp(e,i,_g(o)));if(n.status==="error"){h(n.error,"error");return}n.status!=="stale"&&await yt(t.cellId,"",0,!1,{mode:n.mode,reference:n.reference,referenceStartSeconds:"0",referenceDurationSeconds:""})},Ru=async e=>{if(!B)return;const t=B;Ae.current+=1;const o=e.type==="image"?"image-reverse":"video-reverse";ge(r=>r&&r.cellId===t.cellId?{...r,error:null,loading:!1,loadingMore:!1,preparingIndex:!1}:r);const n=await ue.lifecycle.prepare(o,()=>Bp(b,{sourceBookId:e.owningBookId,sourceArtifactId:e.artifactId,mode:o,previewUrl:o==="image-reverse"?e.thumbnailUrl??e.mediaUrl:e.mediaUrl}));if(n.status==="error"){h(n.error,"error");return}n.status!=="stale"&&await yt(t.cellId,"",0,!1,{mode:n.mode,reference:n.reference,referenceStartSeconds:"0",referenceDurationSeconds:""})},Pu=()=>{B&&(Ae.current+=1,ue.lifecycle.clearReference(),ge(e=>e&&{...e,error:null,loading:!1,loadingMore:!1,preparingIndex:!1}))},Mu=async()=>{if(!B||!qt||qt==="audio")return;const e=B,t=++Ae.current;ge(o=>o&&{...o,preparingIndex:!0,error:null});try{const o=await Up({start:()=>b("repair_library_search_indexes",{kinds:qt==="all"?["image","video"]:[qt]}),listJobs:(s,a)=>b("list_jobs",{book_id:s,job_ids:a}),isCancelled:()=>Ae.current!==t});if(Ae.current!==t)return;const n=Ae.current+1;if(await yt(e.cellId,e.query,0,!1),Ae.current!==n)return;if((ae(o?.failed)??0)>0){const s=Array.isArray(o?.failures)?o.failures:[],a=A(D(s[0])?.message),l=`Some media could not be indexed.${a?` ${a}`:""}`;ge(m=>m&&{...m,error:l}),h(l,"error")}else h(`Indexed ${ae(o?.indexed)??0} media assets for Similar search`)}catch(o){if(Ae.current!==t)return;const n=o instanceof Error?o.message:String(o);ge(r=>r&&{...r,preparingIndex:!1,error:n}),h(n,"error")}},Tu=()=>{B&&(ue.lifecycle.clearError(),yt(B.cellId,B.draftQuery,0,!1))},ju=()=>{B&&yt(B.cellId,B.query,B.page.offset+B.page.limit,!0)},$u=e=>{if(!B)return;const t=Gp(B.tagFilters,e);Wp(t,B.tagFilters)||yt(B.cellId,B.query,0,!1,void 0,t)},qu=()=>{!B||B.tagFilters.length===0||yt(B.cellId,B.query,0,!1,void 0,[])},Nu=async e=>{if(!B||p.state!=="ready")return;const t=B.cellId;try{const o=await b("suggest_asset_tags",{book_id:i,...e.trim()?{prefix:e.trim()}:{},limit:20},{background:!0}),n=Array.isArray(o?.suggestions)?o.suggestions.flatMap(r=>{const s=r;return typeof s.facet=="string"&&typeof s.key=="string"&&typeof s.label=="string"?[{facet:s.facet,key:s.key,label:s.label,assets:Number(s.assets)||0}]:[]}):[];ge(r=>r&&r.cellId===t?{...r,tagSuggestions:n}:r)}catch{}},Qt=e=>{if(Wa(e)&&p.state==="ready"){xo(e);return}Y(e),Ne(null),pt(null),no("selection")&&ke(!0)},hi=e=>{Y(e),pt(null),Ne(e),no("selection")&&ke(!0);const t=c?.cells.find(o=>o.id===e);t?.outputArtifactId&&!oo(t.type)&&yi(e,t.outputArtifactId)},vi=(e,t)=>{const o=c?.cells.find(n=>n.id===e);if(o&&!oo(o.type)){hi(e);return}Y(e),Ne(null),pt(e),no("selection")&&ke(!0),yi(e,t)},yi=(e,t)=>{if(!i){Cn({cellId:e,assetId:t,loading:!1,error:"Book is unavailable",revisions:[]});return}Cn({cellId:e,assetId:t,loading:!0,error:null,revisions:[]}),b("asset_history",{asset_id:t,book_id:i,limit:20},{background:!0}).then(o=>{const n=Ag(o);Cn(r=>r?.cellId===e&&r.assetId===t?{cellId:e,assetId:t,loading:!1,error:null,revisions:n}:r)}).catch(o=>{Cn(n=>n?.cellId===e&&n.assetId===t?{cellId:e,assetId:t,loading:!1,error:o instanceof Error?o.message:String(o),revisions:[]}:n)})},Z=zt?c?.cells.find(e=>e.id===zt)??null:null,Re=zt?Mt.find(e=>e.id===zt)??null:null,Ao=Ye?.target.kind==="slot"?Ye.target.slot:null,cs=Re?cp({type:Re.data.kind,model:Re.data.model,operation:Re.data.operation,outputArtifactId:Re.data.outputArtifactId,tool:Re.data.tool},Re.data.status):null,Lu=Z?Ft(Z.type):null,Fu=!!(Z&&Re&&Lu&&dp(Z.type,Z.outputArtifactId,Re.data.targetConnectionCount??0)),Le=Re?.data.asset&&Re.data.asset.type!=="audio"&&(Re.data.asset.mediaUrl||Re.data.asset.thumbnailUrl)?Re.data.asset:null,Hn=Z?.outputArtifactId&&Re?.data.asset&&Ls(Re.data.asset.type)?Z.outputArtifactId:null,Du=!!(c&&Z&&Hn&&Z.slot.row+1<un.maximumRowCount&&!wt.some(e=>e.row===Z.slot.row+1&&e.column===Z.slot.column)),ds=Me===zt?rd:null,Ou=Z&&c&&Z.type!=="goal"?["generate_video","generate_image"].filter(e=>{try{return Vl({actions:Je,cellId:`context-menu-${e}`,cellType:e,document:c,lastWorkSlot:Ve,sourceCellId:Z.id}),!0}catch{return!1}}):[],He=[];if(Z&&Re){if(Z.type==="post"){const e=G||p.state!=="ready";He.push({id:"save-iphone",label:"Save to iPhone",icon:"upload",disabled:e},{id:"upload-dropbox",label:"Upload to Dropbox",icon:"upload",disabled:e})}He.push({id:"inspect",label:Z.type==="goal"?"Open goal":"Edit cell",icon:"inspect"}),cs&&He.push({id:"run",label:up(Z.type,cs.label),icon:"run",disabled:G||cs.disabled}),Fu&&He.push({id:"library",label:"Choose media",icon:"library",disabled:G}),Le&&Z.type!=="post"&&["video","image","final"].includes(Le.type)&&He.push({id:"create-post",label:"Create Post",icon:"inspect",disabled:G||p.state!=="ready"}),Le&&He.push({id:"media",label:"Open media",icon:"media"}),Le&&(Le.type==="video"||Le.type==="final")&&(He.push({id:"cold-open",label:"Edit cold open",icon:"split",disabled:G||p.state!=="ready"||!Le.mediaUrl}),He.push({id:"download",label:"Download video",icon:"download",disabled:G||p.state!=="ready"||!Le.mediaUrl}),He.push({id:"extract_frame",label:"Extract frame",icon:"extract-frame",disabled:G}));for(const e of Ou){const t=e==="generate_video";He.push({id:e,label:t?"Generate video":"Generate image",icon:t?"generate-video":"generate-image",disabled:G})}Hn&&He.push({id:"duplicate",label:"Duplicate",icon:"duplicate",disabled:G||!Du}),ds&&He.push({id:"split",label:"Split video",icon:"split",disabled:G})}const zn=[];_a.size>0&&zn.push({id:"group_images",label:"Group images here",icon:"group-images",disabled:G});const Vu=e=>{Ao&&e==="group_images"&&Oa(Ao)},Gu=async()=>{if(!(!Hn||!i||!c)){T(!0);try{const e=D(await b("duplicate_asset",{asset_id:Hn,book_id:i,notebook_id:c.id})),t=A(e?.cell_id),o=A(e?.address);if(!t||!o)throw new Error("The server did not return the duplicated notebook cell");await N(i,c.id),Y(t),se(),h(`Duplicated as ${o}`)}catch(e){h(e instanceof Error?e.message:String(e),"error")}finally{T(!1)}}},Wu=async e=>{if(!i||!c||!Z)return;const t=c.id,o=Z.id;T(!0);try{const n=pe(await b("get_notebook",{book_id:i,notebook_id:t}));if(!n)throw new Error("The server returned an invalid notebook");const r=Vl({actions:Je,cellId:Ct(),cellType:e,document:n,lastWorkSlot:Ve,sourceCellId:o}),s=await gl({bookId:i,callTool:b,document:n,draft:r,...n.revision?{expectedRevision:n.revision}:{}});_e(r.cell.slot);const a=await N(i,t);Qt(s.cellId),Jo(s.cellId,void 0,a),ao(s.cellId),h(`Added ${s.cellAddress} ${e==="generate_video"?"video":"image"} generation from ${s.sourceAddresses[0]}`)}catch(n){h(n instanceof Error?n.message:String(n),"error")}finally{T(!1)}},Uu=async()=>{if(!i||G||p.state!=="ready"||!Le?.mediaUrl)return;const e=Le.artifactId;T(!0);try{const t=await Vg(b,"download",i,e);Q.current.bookId===i&&h(t)}catch(t){Q.current.bookId===i&&h(t instanceof Error?t.message:String(t),"error")}finally{Q.current.bookId===i&&ke(!0),T(!1)}},Bu=e=>{if(Z){if(e==="save-iphone"||e==="upload-dropbox"){const t=ns(Z.id,e==="upload-dropbox"?"dropbox":"icloud");t.ok||h(t.message,"error");return}if(e==="create-post"){Fa(Z.id);return}if(e==="inspect"){Qt(Z.id);return}if(e==="run"){en(Z.id);return}if(e==="library"){xo(Z.id);return}if(e==="cold-open"&&Le){const t=es(Le.artifactId);t.ok||h(t.message,"error");return}if(e==="download"){Uu();return}if(e==="media"||e==="extract_frame"){Le&&Fn(Z,Le,Ye?.returnFocus??null);return}if(e==="duplicate"){Gu();return}if(e==="generate_video"||e==="generate_image"){Wu(e);return}if(e==="split"&&ds){rn({sourceReference:ds.source.id,cutPointsSeconds:[]}).then(t=>{t.ok||h(t.message,"error")});return}}},Hu=()=>{Z&&So([Z])},zu=async e=>{if(!i||!c)return;const t=c.cells.find(a=>a.id===e);if(!t)return;const o=Zp(t,c.cells,c.edges),n=eg({address:U(t.slot),error:Mt.find(a=>a.id===e)?.data.statusError??"the provider rejected the request",mediaLabel:tg(t.type),producerAddress:o?U(o.slot):null,provider:o?.provider??t.provider??null,model:o?.model??t.model??null});ke(!0);const r=gi(n),s=await ls(n,{chat:r});s.ok||h(s.message,"error")},Ku=async e=>{if(!i||!c||G||p.state!=="ready")return;const t=Mt.find(n=>n.id===e)?.data.statusError;if(!Qp(t))return;const o=Yp(c,e);if(!o){h("The generator for this failed output is no longer available","error");return}await en(o.id,void 0,void 0,e)},Xu={ready:!G&&p.state==="ready",deleteCell:async e=>{const t=c?.cells.find(o=>o.id===e);t&&await So([t],{confirm:!1})},repairCell:zu,retryCell:Ku},an=te?.asset.type==="image"?te:null,Ii=f.useMemo(()=>an?fe.filter(e=>e.type.toLowerCase()==="image"&&e.artifactId!==an.asset.artifactId):[],[fe,an]),Ju=f.useMemo(()=>Ii.map(e=>({artifactId:e.artifactId,address:e.cellAddress,label:e.cellAddress,thumbnailUrl:e.thumbnailUrl??e.mediaUrl})),[Ii]),Kn=an?`image-edit:${an.key}`:`chat:${i}`,Ro=wn?.bookId===i&&wn.session===Kn?wn:null,Qu=mr?.bookId===i&&mr.session===Kn?mr:null,Ci=Oe?.turnId!==void 0&&Oe.turnId===la.at(-1)?.id,Si=!!(Ro&&(Oe||te)),us=!Xo&&!ve&&!rt,Yu=e=>{if(!W)return;let t=W,o=!1;for(const n of e){if(n.kind==="prompt"){t=Qn(t,n.prompt);continue}if(n.kind==="model"){const r=Go.find(s=>s.id===n.actionId);if(!r)continue;t=Ki(t,r,gt),o=!0;continue}t=hs(t,n.name,n.value),o=!0}ht(t,o)},Zu=async e=>{const t=_?.kind==="generation"&&W?{kind:"generation",action:W.action,models:Go}:_?.kind==="chain-step"?{kind:"chain-step"}:_||ce||he?{kind:"other"}:{kind:"none"},o=pg(e,t);return o.kind==="refused"?o.outcome:o.kind==="revise"?(Yu(o.edits),{status:"review",message:"The review on screen is updated. It is still waiting for apply or cancel."}):ul(o.input,await ls(o.input))},Yt=fp({bookId:i,notebookId:c?.id,scope:Kn,available:us&&p.state==="ready"&&!!i&&!te&&!Oe&&!ve,disabled:G||!!(he||ce||_),onUserTurn:()=>{he||ce||_||(fa.current=ua(),Y(null),Ne(null),pt(null))},onAction:async(e,t)=>{const o=fa.current??ua(),n=()=>t()&&o.isCurrent();if(!n())return{status:"cancelled",message:"A newer message replaced this request."};if(G||_||ce||he)return{status:"failed",message:"Finish the current command or use Apply or Cancel on screen first."};const r=As(e.plan);if(r.bookId!==i)return{status:"cancelled",message:"The project changed. Repeat the command here."};const s=await Un(r,e.prompt,n,o);return n()?(h(s.message,s.ok?"info":"error"),{status:s.ok?s.nextInput?.startsWith("/apply")?"review":/queued|started|running|processing/i.test(s.message)?"queued":"completed":"failed",message:s.message}):{status:"cancelled",message:"Workspace changed. Check the previous project for accepted work."}},onReviewCommand:Zu});f.useLayoutEffect(()=>{Ar.current=Yt.reportOutcome,ia.current=Yt.shareTypedTurn,Rr.current=Yt.active},[Yt.active,Yt.reportOutcome,Yt.shareTypedTurn]),mp(`${k}:${i}:${c?.id??""}`,us&&p.state==="ready"&&!G&&(!!i||!!Ro));const ef=()=>{te||Gc()},xi=(()=>{if(he){const s=he,a=s.includeQr&&s.includeHandle?"Add handle and QR to the video":s.includeQr?"Add a QR code to the video":"Add a handle to the video";return C.jsx(ct,{kind:"watermark",ariaLabel:"Watermark review",tag:"WATERMARK · CHAT",title:a,address:s.targetLabel,effect:{label:"Rebuilds playable proxy",tone:"default"},validation:gp({...s,handle:s.identities[s.platform].handle}),busy:G,applyFormId:dt,onCancel:Be,children:C.jsx(Tb,{busy:G,state:s,onChange:({handle:l,...m})=>{tl(i,s.platform,{handle:l,...m}),qe(u=>u&&{...u,...m,identities:l===void 0?u.identities:{...u.identities,[u.platform]:{...u.identities[u.platform],handle:l}},error:null})},onMediaMetadata:l=>qe(m=>m&&{...m,...m.durationSeconds===null?pp(m,l.durationSeconds):{},durationSeconds:l.durationSeconds,width:l.width,height:l.height})})})}if(ce){const s=ce.plan,a=Object.values(ce.previews),l=a.reduce((w,v)=>w+v.warnings.length,0),m=`${s.stages.length} stage${s.stages.length===1?"":"s"}`,u=l>0?` · ${l} warning${l===1?"":"s"}`:"";return C.jsx(ct,{kind:"plan",ariaLabel:"Command plan review",tag:`PLAN · ${s.sourceSurface.toUpperCase()}`,title:s.summary,effect:{label:`${m}${u}`,tone:l>0?"warning":"default"},validation:kp({suggestions:s.suggestions,previews:a}),busy:G,applyFormId:dt,onCancel:Be,secondaryActions:Pr?C.jsxs("button",{type:"button",className:"confirm-sheet-secondary",disabled:G,onClick:()=>{Ud()},children:[C.jsx(Yk,{size:13,"aria-hidden":"true"}),"Restore last edit"]}):null,children:C.jsx(qk,{busy:G,plan:s,previews:ce.previews,onToggleSuggestion:w=>{Gd(w)}})})}if(!_)return null;if(_.kind==="generation"){const s=_,a=Wo[0];return C.jsx(ct,{kind:"generation",ariaLabel:"Generation action review",tag:"GENERATION · CHAT",title:s.summary,address:a?`@${a.address}`:null,effect:{label:"Queues 1 job · new cell",tone:"default"},validation:bp({prompt:s.draft.cell.prompt,previewLoading:s.previewLoading,previewError:s.previewError,settingsError:vp(s.draft.action.model,ol(s.draft),Wo),previewStale:s.previewStale,promptLeaks:hp(s.preview).promptLeaks,estimateUnknown:wp(s.preview).unknown}),busy:G,applyFormId:dt,onCancel:Be,children:C.jsx(Nk,{actions:Go,busy:G,draft:s.draft,modes:_c,preview:s.preview,previewError:s.previewError,previewLoading:s.previewLoading,previewStale:s.previewStale,sources:Wo,sourceOptions:Ac,voiceCatalog:Gn,promptHistory:Kc,onActionChange:Xc,onAddSource:ed,onModeChange:Jc,onPromptChange:Ea,onRefreshPreview:Yc,onRemoveSource:td,onSelectSource:Zc,onSettingChange:Qc})})}if(_.kind==="post-delivery"){const s=_.review,a=sn.find(w=>w.id===s.postId)??null,l=c?.cells.find(w=>w.id===s.postId),m=l?.outputArtifactId?re.get(l.outputArtifactId)??null:null,u=s.destination==="icloud";return C.jsx(ct,{kind:"post-delivery",ariaLabel:"Post delivery",tag:"DELIVER",title:u?"Save to iPhone":"Upload to Dropbox",address:a?.address??null,effect:{label:u?"iCloud · shared folder":"Leaves workspace · private",tone:u?"default":"warning"},validation:nl(a,s),busy:G,busyLabel:u?"Saving to iPhone…":"Uploading to Dropbox…",applyLabel:"Upload",applyFormId:dt,onCancel:Be,children:a&&C.jsx(Lk,{post:a,asset:m,review:s,busy:G,onCopyChange:w=>lt({copy:w}),onLanguage:w=>iu(a,s,w),onRegen:()=>lu(a,s),onFolderChange:w=>lt(u?{icloudFolder:w}:{dropboxFolder:w}),onDestination:cu,onConnect:()=>{au()},onCheckConnection:()=>{os()},onOpenPost:()=>Qt(a.id),onLink:async w=>{await b("link_post",{book_id:s.bookId,post_cell_id:a.id,...w}),await N(s.bookId,s.notebookId),Be()}})})}if(_.kind==="cold-open"){const s=_.review,a=s.suggestion;return C.jsx(ct,{kind:"cold-open",ariaLabel:"Cold-open review",tag:"COLD OPEN",title:"Highlight, then the full clip",address:s.label,effect:{label:"New video copy",tone:"default"},validation:{blocking:a?yp(a.startSeconds,a.endSeconds,a.durationSeconds):null,notice:null},busy:G,busyLabel:a?"Creating copy…":"Finding highlight…",applyLabel:a?"Create copy":"Find highlight",applyFormId:dt,onCancel:Be,children:C.jsx(Fk,{review:s,disabled:G,onChange:(l,m)=>V(u=>u?.kind==="cold-open"&&u.review.suggestion?{...u,review:{...u.review,requestId:Ct(),suggestion:{...u.review.suggestion,startSeconds:l,endSeconds:m}}}:u)})})}if(_.kind==="split"&&Pa){const s=Pa,a=Ip({cutPointsSeconds:s.cutPointsSeconds,sourceDurationSeconds:s.sourceDurationSeconds});return C.jsx(ct,{kind:"split",ariaLabel:"Video split review",tag:"SPLIT VIDEO · CHAT",title:Sp({pieces:a,selectedIndex:s.selectedIndex}),address:s.sourceLabel,effect:{label:s.outputMode==="all"?`${a.length} new clip${a.length===1?"":"s"} · source preserved`:"New clip · source preserved",tone:"default"},validation:Cp({availableEmptyCells:s.availableEmptyCells,cutPointsSeconds:s.cutPointsSeconds,outputMode:s.outputMode,sourceDurationSeconds:s.sourceDurationSeconds}),busy:G,applyLabel:"Apply split",applyFormId:dt,hints:C.jsxs("span",{children:[C.jsx("kbd",{children:"← →"})," 0.1s · ",C.jsx("kbd",{children:"⇧← →"})," 1s · ",C.jsx("kbd",{children:"⌥← →"})," 0.01s on the focused bound · ",C.jsx("kbd",{children:"↵"})," apply · ",C.jsx("kbd",{children:"Esc"})," cancel"]}),onCancel:Be,children:C.jsx(Dk,{cutPointsSeconds:s.cutPointsSeconds,mediaUrl:s.mediaUrl,outputMode:s.outputMode,selectedIndex:s.selectedIndex,sourceDurationSeconds:s.sourceDurationSeconds,sourceFps:s.sourceFps,onChange:zc})})}if(_.kind==="routed"){const s=_.plan,a=Ec,l=a?.settings.find(u=>u.label==="Source")?.value,m=`CHAT · ${s.routedTool.toUpperCase()}`;return uo?C.jsx(ct,{kind:"post",ariaLabel:"Chat action review",tag:m,title:a?.title??"Post to X",address:uo.sourceLabel,effect:a?.effect??null,validation:uo.validation,busy:G,busyLabel:"Posting…",applyLabel:"Post to X",applyFormId:dt,onCancel:Be,children:C.jsx(Ok,{asset:uo.asset,busy:G,draft:uo.draft,prompt:s.prompt,settings:a?.settings??[],sourceLabel:uo.sourceLabel,threadReview:_.xPostReview,connection:jo,onChange:Wc,onConnect:()=>{Yr()},onThreadOptionsChange:Uc,onThreadCreditsChange:Hc,onThreadPromptChange:Bc})}):C.jsx(ct,{kind:"routed",ariaLabel:"Chat action review",tag:m,title:a?.title??s.summary,address:l?.startsWith("@")?l:null,effect:a?.effect??null,validation:Ss,busy:G,applyFormId:dt,onCancel:Be,children:C.jsx(El,{prompt:s.prompt,settings:a?.settings??[],speedPreview:ga})})}if(_.kind==="chain-step"){const s=xp(_.review,_.remaining);return C.jsx(ct,{kind:"routed",ariaLabel:"Chain step review",tag:`CHAIN · ${_.review.tool.toUpperCase()}`,title:s.title,address:_.review.address,effect:s.effect,validation:Ss,busy:G,applyFormId:dt,onCancel:Be,children:C.jsx(El,{prompt:s.postText??"",settings:s.settings,speedPreview:null})})}const e=_,t=e.kind==="notebook"?e.plan.summary:e.summary,o=e.kind==="notebook"?e.plan.reason:e.reason,n=e.kind==="notebook"?`${e.plan.action.kind} notebook cell`:e.kind==="split"?"Split video":e.command.frameMode==="time"?`Extract frame at ${e.command.timestampSeconds??0}s`:`Extract ${e.command.frameMode} frame`,r=e.kind==="notebook"?"Edits the notebook graph":e.kind==="frame"?"New image cell":"New clips · source preserved";return C.jsx(ct,{kind:e.kind,ariaLabel:"Chat action review",tag:"NOTEBOOK · CHAT",title:t,effect:{label:r,tone:"default"},validation:Ss,busy:G,applyFormId:dt,onCancel:Be,children:C.jsx(Vk,{kindLabel:e.kind.toUpperCase(),reason:o,stageTitle:n})})})(),ln=f.useMemo(()=>{const e=z.map(a=>{const l=c?.cells.find(m=>m.outputArtifactId===a.artifactId);return{value:a.artifactId,label:l?`${U(l.slot)} · ${a.label}`:a.label,detail:a.type}}),t=c?.cells.map(a=>({value:a.id,label:`${U(a.slot)} · ${a.label??a.type}`}))??[],o=X?.tracks.map(a=>({value:a.trackId,label:a.name,detail:a.kind}))??[],n=X?.clips.map(a=>({value:a.clipId,label:`${a.source.kind} · frame ${a.timelineStartFrame}`,detail:X.tracks.find(l=>l.trackId===a.trackId)?.name}))??[],r={book_id:x.map(a=>({value:a.bookId,label:a.name})),notebook_id:c?[{value:c.id,label:c.name}]:[],cell_id:t,cell:t,source_cell_id:t,target_cell_id:t,clip_id:n,clip_ids:n,narration_clip_id:n,track_id:o,track_ids:o,audio_track_id:o,artifact_id:e,artifact_ids:e,artifact_ref:e,asset_id:e,asset_ref:e,source_artifact_id:e};for(const a of["image","audio","video"]){const l=e.filter(m=>m.detail===a||a==="video"&&m.detail==="final");r[`${a}_ref`]=l,r[`${a}_refs`]=l,r[`${a}_artifact_id`]=l,r[`${a}_asset_id`]=l,r[`${a}_asset_ids`]=l}for(const a of["source_asset_id","target_asset_id","first_asset_id","second_asset_id","additional_asset_ids","output_artifact_id","replacement_artifact_id","expected_output_artifact_id","exclude_artifact_ids"])r[a]=e;for(const a of["osg_asset_id","card_asset_id","qr_image_refs","character_image_refs","first_frame_ref","last_frame_ref","end_frame_ref"])r[a]=r.image_ref;return r.motion_video_refs=r.video_ref,r.layer_asset_id=r.audio_ref,r.sound_effect_ref=r.audio_ref,r.source_script_id=e.filter(a=>a.detail==="script"),r.cell_ids=t,r.audio_id=n,r.outgoing_clip_id=n,r.incoming_clip_id=n,r.source_book_id=r.book_id,r.target_book_id=r.book_id,r.edge_id=c?.edges.map(a=>({value:a.id,label:`${t.find(l=>l.value===a.source)?.label??a.source} → ${t.find(l=>l.value===a.target)?.label??a.target} · ${a.targetInput}`}))??[],{bookId:i,notebookId:c?.id,sequenceId:X?.sequenceId,sequenceRevision:X?.revision,cellId:q?.id,assetId:q?.outputArtifactId,choices:r,cellIds:vt.map(a=>a.id),assetIds:vt.flatMap(a=>a.outputArtifactId?[a.outputArtifactId]:[]),media:Object.fromEntries(z.map(a=>[a.artifactId,{url:a.mediaUrl,type:a.type,width:a.width,height:a.height,objectHash:a.objectHash}]))}},[z,i,x,c,q,vt,X]),tf=f.useMemo(()=>Ep(bn,!!(ce||_||he)),[bn,ce,_,he]),fs=(e,t=et.frame)=>{X&&(Y(e),Ge(null),kt.load(),et.seek(t),An({bookId:i,cellId:e,initialFrame:t,returnFocus:document.activeElement instanceof HTMLElement?document.activeElement:null}))},Ei=()=>{et.closePicker(),kt.stop(),An(null)},ms={sequence:X,assets:z,assembly:Xo?{...et,picker:null}:et,disabled:G||p.state!=="ready",frame:et.frame,onSeek:fs,onPreview:fs,onExport:()=>{is("/export-sequence").then(e=>{e.ok||h(e.message,"error")})},onRemove:e=>{const t=c?.cells.find(o=>o.id===e);t&&So([t])}},cn=Bn&&(Bn.cellId===null||q?.id===Bn.cellId&&!q.outputArtifactId)?Bn:null,ps=cn&&qt?C.jsx(uf,{disabled:G||p.state!=="ready",state:cn,kind:qt,accept:qt==="all"?Object.values(rl).join(","):rl[qt],targetBookId:i,onClose:Md,onMode:_u,onDraftQuery:Eu,onSearch:Tu,onLoadMore:ju,onAttach:e=>{Td(e)},onUpload:e=>{if(cn.cellId){Ga(cn.cellId,e);return}const t=xs(e);if(!(!t||!c))try{const o=B?.slot??Mo(t,c.cells,Ve);Jr(o,e)}catch(o){h(o instanceof Error?o.message:String(o),"error")}},onReferenceFile:e=>{Au(e)},onClearReference:Pu,onReferenceStart:ue.lifecycle.setStartSeconds,onReferenceDuration:ue.lifecycle.setDurationSeconds,onSimilar:e=>{Ru(e)},onRepairIndexes:()=>{Mu()},onToggleTagFilter:$u,onClearTagFilters:qu,onTagQuery:e=>{Nu(e)}}):null,of=cn?.cellId===null&&ps?C.jsxs("div",{className:"composer-notebook-dock inspector",children:[C.jsxs("header",{children:[C.jsxs("span",{className:"inspector-cell-title",children:[C.jsx(Rl,{size:15}),C.jsx("strong",{children:"Library"})]}),C.jsx("div",{className:"inspector-header-actions",children:C.jsx(Mi,{})})]}),ps]}):null,gs=q?.type==="goal"?wa.get(q.id)??null:null,nf=!Xo&&q?.type==="goal"?gs?C.jsx(Kk,{goal:gs,connected:p.state==="ready",onAction:md,onPreview:pd,onSelectCell:Qt,resolveAsset:e=>re.get(e)??null,onPreviewCell:e=>{const t=c?.cells.find(n=>n.id===e),o=t?.outputArtifactId?re.get(t.outputArtifactId):null;t&&o&&Fn(t,o)}},gs.goalId):C.jsx(Xk,{}):null,ks=of??nf??(!Xo&&ie&&q&&q.type!=="timeline"?C.jsxs("div",{className:["composer-notebook-dock","inspector",wr.has(ie.id)?"inspector-deleting":""].filter(Boolean).join(" "),children:[C.jsxs("header",{children:[C.jsxs("span",{className:"inspector-cell-title",title:Es(ie.data.kind),children:[C.jsx(ff,{kind:ie.data.kind}),C.jsx("strong",{children:Es(ie.data.kind)}),C.jsx("code",{className:"inspector-cell-address",children:U(q.slot)}),(zr?.kind==="queued"||zr?.kind==="generating")&&C.jsx("span",{className:"inspector-generating-badge",role:"status",children:zr.kind==="queued"?"Queued":"Generating"})]},ie.id),C.jsxs("div",{className:"inspector-header-actions",children:[q.outputArtifactId&&oo(q.type)&&C.jsx("button",{type:"button",className:Bt===ie.id?"inspector-source-toggle active":"inspector-source-toggle",title:Bt===ie.id?"View cell":"View history","aria-label":Bt===ie.id?"View cell":"View history","aria-pressed":Bt===ie.id,onClick:()=>{if(Bt===ie.id){pt(null);return}vi(ie.id,q.outputArtifactId)},children:C.jsx(Zk,{size:15})}),!on&&C.jsx("button",{type:"button",className:["inspector-source-toggle",oo(q.type)?"":"inspector-source-toggle-labeled",Ut===ie.id?"active":""].filter(Boolean).join(" "),title:Ut===ie.id?"View cell":"View source","aria-label":Ut===ie.id?"View cell":"View source","aria-pressed":Ut===ie.id,onClick:()=>{if(Ut===ie.id){Ne(null);return}hi(ie.id)},children:oo(q.type)?C.jsx(eb,{size:15}):C.jsxs(C.Fragment,{children:[C.jsx(tb,{size:13,"aria-hidden":"true"}),C.jsx("span",{children:"Source"})]})}),q.type.startsWith("generate_")&&C.jsx("span",{className:"composer-dock-close-divider","aria-hidden":"true"}),C.jsx("div",{ref:ec,className:"inspector-header-action-host"}),C.jsx(Mi,{label:q.type.startsWith("generate_")?"Close":void 0,shortcut:q.type.startsWith("generate_"),divider:!q.type.startsWith("generate_")})]})]}),ps??(on?C.jsx(mf,{post:on,cells:c?.cells??[],asset:ie.data.asset,bookId:i,call:p.state==="ready"?b:void 0,onRefresh:()=>N(i,c?.id),onSelectCell:Qt,onDeliver:e=>{const t=ns(on.id,e);t.ok||h(t.message,"error")},onReviewX:ru,onDelete:()=>{So([q])}},on.id):C.jsx(Hk,{headerActionHost:Zl,notebookId:c?.id??"",bookId:i,assetTools:p.state==="ready"?b:void 0,cell:q,cells:c?.cells??[],edges:c?.edges??[],asset:ie.data.asset,cellAssets:tn,versionAssets:nd,status:ie.data.status,error:Aa,queuedCellIds:In,runErrors:so,jobs:Ra,onCancelJob:Ba,generationActions:Je,mentionAssets:fe,voiceCatalog:Gn,busy:G||!!sd?.operation,deleting:wr.has(q.id),sourceVisible:Ut===q.id,historyVisible:Bt===q.id,history:io&&io.cellId===q.id&&io.assetId===q.outputArtifactId?{revisions:io.revisions,loading:io.loading,error:io.error}:Bt===q.id||Ut===q.id&&q.outputArtifactId?{revisions:[],loading:!0,error:null}:void 0,onUpdate:Id,onSetInput:Cd,onRun:en,onDelete:Sd,onOpenFullscreen:(e,t)=>{Fn(q,e,void 0,t)},onPreviewPayload:ad,initialGenerationPreview:ha?.cellId===q.id?ha:void 0,onSelectSource:Y,onLoadGenerationPayload:id,onInspectGenerationRequest:ld,mediaInsightWork:vr,onTranscribeAsset:cd,onLoadTranscriptJson:dd,onDownloadTranscriptSrt:ud},`${q.id}:${q.prompt??""}`))]}):null),rf=mg({musicSession:!!ve,cellInspector:!!ks}),sf=ks||ve?C.jsx("div",{hidden:!!ve,inert:ve?!0:void 0,children:ks}):null;return C.jsxs("main",{className:`app-shell app-screen-${k} ${te?"media-fullscreen-open":""}`,onDragEnter:bu,onDragLeave:wu,onDragOver:hu,onDropCapture:vu,onDrop:yu,onKeyDownCapture:e=>{e.defaultPrevented||(e.ctrlKey||e.metaKey)&&e.shiftKey&&e.key.toLowerCase()==="k"&&!e.nativeEvent.isComposing&&(e.preventDefault(),e.stopPropagation(),Ce())},children:[C.jsxs("header",{className:"topbar",children:[C.jsx("div",{className:"topbar-book-controls",children:C.jsx("div",{className:"brand-project",children:C.jsxs("div",{className:"brand-project-trigger",children:[C.jsxs("button",{type:"button",className:"brand-project-home","data-composer-focus":"return",title:"Open notebook",onClick:()=>_o("notebook"),children:[C.jsx(ob,{size:18}),C.jsx("span",{children:"/videobook"})]}),C.jsx(pf,{activeBook:co,books:x,disabled:G||p.state!=="ready",error:hc,loading:wc,open:bc,onCreate:qa,onDelete:La,onOpenChange:Xt,onRefresh:yd,onRename:Na,onSelect:$a})]})})}),k==="notebook"&&c&&C.jsx(gf,{busy:G||p.state!=="ready",arrangeDisabled:G||p.state!=="ready"||c.cells.length===0,selectedCount:vt.length,activeAddress:q?U(q.slot):null,onAdd:Xr,onAddDragEnd:()=>Gt(null),onArrange:_d,onDeleteSelection:Da,onSelectionActions:()=>{Ce(void 0,{cell_id:q?.id,cell_ids:vt.map(e=>e.id),artifact_ids:vt.flatMap(e=>e.outputArtifactId?[e.outputArtifactId]:[])})},onClearSelection:()=>{Y(null),Ne(null),Wt.current?.focus()}}),C.jsxs("div",{className:"topbar-tools",children:[C.jsxs("nav",{className:"header-navigation","aria-label":"Workspace navigation",children:[C.jsx("button",{type:"button",className:B?.cellId===null&&Sr?"active":"",title:"Library","aria-label":"Open Library","aria-expanded":B?.cellId===null&&Sr,disabled:G||p.state!=="ready"||!c,onClick:()=>Qr(),children:C.jsx(Rl,{size:17})}),Bb.map(e=>{const t=e.icon;return C.jsx("button",{type:"button",className:k===e.id?"active":"",title:e.label,"aria-label":`Open ${e.label}`,"aria-current":k===e.id?"page":void 0,onClick:()=>_o(e.id),children:C.jsx(t,{size:17})},e.id)})]}),C.jsx(kf,{bookName:co?.name??"",enabled:!!i,snapshot:Vr.snapshot,stale:Vr.stale,onRetry:Vr.retry},i)]})]}),!At&&C.jsx("div",{className:"offline-banner",role:"status",children:"Offline · local import, search, editing, playback, history, and export remain available"}),C.jsxs(C.Fragment,{children:[k==="notebook"&&C.jsx(C.Fragment,{children:C.jsx("section",{className:"canvas",style:kc,children:c?C.jsx("div",{className:"notebook-horizontal-scroll","data-composer-focus":"return",ref:Wt,tabIndex:0,"aria-label":"Notebook canvas",onKeyDown:xd,children:C.jsx("div",{className:"notebook-flow-frame",style:Oc,children:C.jsx(bf.Provider,{value:ms,children:C.jsx(wf.Provider,{value:xu,children:C.jsx(hf.Provider,{value:en,children:C.jsx(vf.Provider,{value:Xu,children:C.jsx(yf.Provider,{value:Me,children:C.jsx(If.Provider,{value:oc,children:C.jsx(Cf.Provider,{value:qc,children:C.jsx(Sf.Provider,{value:wa,children:C.jsx(xf.Provider,{value:re,children:C.jsx(Ef.Provider,{value:Mc,children:C.jsxs(lf,{className:"notebook-flow",nodes:Lc,edges:Fc,nodeTypes:tw,edgeTypes:ow,viewport:Vc,onInit:e=>{Do.current=e},onNodesChange:e=>{const t=e.filter(o=>o.type==="select");if(t.length>0){const o=new Set(st.current);for(const l of t)l.selected?o.add(l.id):o.delete(l.id);bo(o);const n=[...o].at(-1)??null,r=Me&&o.has(Me)?Me:n;$o(r),Jo(r);const s=n?c?.cells.find(l=>l.id===n):void 0,a=n?Ue.find(l=>l.id===n):void 0;s?_e(s.slot):a&&_e(a.data.slot)}bt(o=>{let n=Pi(e,o);for(const r of e)r.type!=="position"||!r.dragging||!r.position||(n=Pp(n,r.id,_s(r.position)));return n})},onEdgesChange:e=>{Pn(o=>df(e,o));const t=e.filter(o=>o.type==="remove").map(o=>o.id);t.length>0&&Pd(t)},onNodeClick:(e,t)=>{const o=st.current,n=o.has(t.id)?t.id:[...o].at(-1)??null;$o(n),Jo(n),n===t.id&&_e(t.data.slot),Ne(null),t.type!=="timeline"&&no("selection")&&ke(!0),t.type!=="timeline"&&o.size===1&&n===t.id&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&(ao(t.id),B?.cellId!==t.id&&xo(t.id))},onPaneClick:()=>{wo(),Y(null),Ne(null)},onPaneContextMenu:e=>{if(zn.length===0)return;const t=ki(e.clientX,e.clientY);t&&(e.preventDefault(),$c(t,{x:e.clientX,y:e.clientY},document.activeElement instanceof HTMLElement?document.activeElement:null))},onNodeDrag:(e,t)=>{wo(),Gt(_s(t.position))},onNodeDragStop:(e,t,o)=>{const n=Pi(o.map(({id:a})=>({id:a,type:"position",dragging:!1})),Ue),r=Ap(n,t.id,o.map(a=>a.id),_s(t.position)),s=Rp(Ue,r);if(bt(r),Gt(null),s.length>0){const a=s.find(l=>l.id===t.id)??s[0];a&&_e(a.data.slot),Ed(s)}},isValidConnection:e=>c?sl(c.edges,e,c.cells):!1,onConnect:e=>{Rd(e)},onDrop:Su,onDragLeave:Iu,onDragOver:Cu,minZoom:Te,maxZoom:Te,defaultEdgeOptions:rw,elementsSelectable:!0,multiSelectionKeyCode:sw,panOnDrag:aw,panOnScroll:!1,selectionKeyCode:null,selectionMode:cf.Partial,selectionOnDrag:!0,selectNodesOnDrag:!1,zoomOnScroll:!1,zoomOnPinch:!1,zoomActivationKeyCode:null,zoomOnDoubleClick:!1,preventScrolling:!1,deleteKeyCode:null,proOptions:nw,children:[C.jsx(Pf,{sections:Dc,metrics:Tt,occupiedSlots:wt,previewSlot:No,mediaDropActive:na&&!G,mediaDropSlot:fc,reviewRoles:Lr}),Ue.length===0&&C.jsx(Mf,{busy:G||p.state!=="ready",compact:Hi(Te)>1.8,dimmed:na||No!==null,onUpload:(e,t)=>{Jr(e,t)},onPick:(e,t)=>{Xr(e,_p(t))},onDownload:Qd,onBrowseLibrary:Qr})]})})})})})})})})})})})})}):C.jsxs("div",{className:"canvas-empty-state",children:[C.jsx("strong",{children:"No notebook available"}),C.jsx("button",{type:"button",onClick:()=>{vd(i)},children:"Reload book"})]})})}),k==="jobs"&&C.jsx(Bk,{bookName:co?.name??null,jobs:De,plans:Fr,assets:z,cells:c?.cells??Ub,now:Xl,busy:G,onRefresh:()=>i&&void N(i,c?.id),onCancelJob:e=>{Ba(e)},onRetryJob:e=>{Fd(e)},onContinuePlan:e=>{const t=Fr.find(o=>o.planId===e);t&&Od(t)},onRevisePlan:(e,t)=>{const o=Fr.find(n=>n.planId===e);o&&Dd(o,t)}}),k==="settings"&&C.jsx(Tf,{call:p.state==="ready"?b:void 0,providers:nc,loading:ac,error:ic,refreshed:lc,storage:sc,bookId:i,bookName:co?.name??null,connection:jo,busy:G||p.state!=="ready",onRefresh:nn,onSave:Vd,onConnect:()=>{Yr()}})]}),Ye&&Z&&C.jsx(Ti,{actions:He,address:U(Z.slot),cellType:Es(Z.type),deleteDisabled:G||wr.has(Z.id),menuId:jf(Z.id),position:Ye.position,returnFocus:Ye.returnFocus,onAction:Bu,onClose:wo,onDelete:Hu}),Ye&&Ao&&zn.length>0&&C.jsx(Ti,{actions:zn,address:U(Ao),cellType:"EMPTY",menuId:ew(Ao),menuLabel:`Slot actions for ${U(Ao)}`,position:Ye.position,returnFocus:Ye.returnFocus,onAction:Vu,onClose:wo}),ve&&X&&C.jsx(f.Suspense,{fallback:C.jsx("div",{role:"status",children:"Loading music-video editor…"}),children:C.jsx(ql,{assembly:et,rhythm:kt,onFrameUpdate:et.seek,onExport:()=>{ti(),ms.onExport()},sequence:X,assets:z,audioArtifactId:ve.audioArtifactId,setup:ve.setup,returnFocus:ve.returnFocus,onApplySetup:Xa,onClose:()=>{kt.stop(),ti()},onCommit:Ja,onPlanDraft:Qa,onApplyDraft:Ya,onCreateTrack:ei,onRefreshAssets:async()=>{if(!i)throw new Error("Load or create a book first.");await N(i,c?.id)},onRestore:Za,onReviewSetup:e=>Ka(ve.key,ve.audioArtifactId,e??X)},ve.key)}),rt&&C.jsx(f.Suspense,{fallback:C.jsx("div",{role:"status",children:"Loading alive captions…"}),children:C.jsx(jb,{asset:rt.asset,state:rt.state,returnFocus:rt.returnFocus,onClose:Xd,onSave:e=>ri(rt.asset.artifactId,e),onRender:(e,t)=>Jd(rt.asset.artifactId,e,t),onReanalyze:()=>ni(rt.key,rt.asset.artifactId,!0)},rt.key)}),Xo&&Ko&&Rn&&X&&C.jsx(f.Suspense,{fallback:C.jsx("div",{role:"status",children:"Opening timeline preview…"}),children:C.jsx(ql,{sequence:X,assets:z,assembly:et,rhythm:kt,setup:{status:"timeline"},address:U(Rn.slot),initialFrame:Ko.initialFrame,returnFocus:Ko.returnFocus,onFrameUpdate:et.seek,onExport:()=>{Ei(),ms.onExport()},onClose:Ei,onApplySetup:Xa,onCommit:Ja,onPlanDraft:Qa,onApplyDraft:Ya,onCreateTrack:ei,onRefreshAssets:async()=>{await N(i,c?.id)},onRestore:Za,onReviewSetup:async()=>{await kt.load()}},`${i}:${Rn.id}`)}),te&&C.jsx(zk,{asset:te.asset,address:te.address,initialMode:te.mode,initialInstruction:te.initialInstruction,onInstructionChange:e=>{ta.current.set(te.bookId,e),Ot(`videobook.image-edit-instruction:${te.bookId}`,e)},composerPortalRef:Ir,actionsOpen:!!Ro,subjectMap:te.subjectMap,subjectMapLoading:te.subjectMapLoading,returnFocus:te.returnFocus,analysisUnavailableReason:te.asset.type==="image"&&!te.asset.objectHash?"This version is missing its immutable object hash. Refresh the book data and reopen it.":null,onAnalyzeSubjects:e=>kd(te,e),onCaptureFrame:te.asset.type==="video"||te.asset.type==="final"?e=>gd(te,e):void 0,onEditingChange:Cr,replacementCandidates:Ju,imageEditModels:zo.models,imageEditModelsLoading:zo.loading,defaultImageEditModelId:zo.defaultModelId,onEstimateImageEditCost:Tc,onEditSubjects:e=>Dn(te,e),onSubmitEditInstruction:(e,t)=>ku(te,e,t),onClose:Kt},te.key),C.jsx("input",{ref:Ws,type:"file",multiple:!0,hidden:!0,"aria-label":"Import files from actions",onChange:Nd}),Oe&&C.jsx($f,{media:Oe.media,sequence:Oe.media?void 0:X??void 0,assets:z.flatMap(e=>e.mediaUrl?[{artifactId:e.artifactId,mediaUrl:e.mediaUrl}]:[]),opener:Oe.opener,initialFrame:Oe.initialFrame,composerPortalRef:Yl,actionsOpen:!!(Ro||Ci),onClose:()=>{To(null),Et(null),Vt(null)},onActions:()=>{Ce(void 0,Oe.media?{asset_id:Oe.media.assetId}:void 0)}}),$e?.actionId&&C.jsx(qf,{actions:xt,context:{...ln,entities:$e.resources?.entities,choices:{...ln.choices,...$e.resources?.choices}},initialActionId:$e.actionId,initialValues:$e.values,initialResult:$e.result,returnFocus:$e.opener,loading:ur.loading,error:ur.error,onClose:()=>{mt.current+=1,Qe(null)},onBack:()=>{Ce(void 0,$e.values,$e.query,$e.opener)},onOpenAction:(e,t)=>{Ce(e,{...$e.values,...t})},onExecute:mu,onReview:pu},$e.key),C.jsx(Nf,{chatTurns:la,goalEvents:Rc,previewTurnId:yc,connected:p.state==="ready"&&At,onBeginTurn:gi,onCommandRowHeightChange:pc,onHeightChange:gc,hidden:!us,dockOpen:Sr,onDockOpenChange:ke,contextualContent:sf,contextualHasHeader:rf,goalStatus:fo?C.jsx(Qk,{goal:fo,disabled:p.state!=="ready",onOpen:()=>Kr(fo.cellId)}):null,commands:tf,references:Nr,actions:xt,actionContext:ln,actionDiscovery:Qu,actionStatus:ur,actionsDisabled:G||p.state!=="ready",onOpenActions:()=>{Ce()},onCloseActionSearch:e=>{Et(null),!e&&Si&&ja()},onDismissComposer:Si?ja:void 0,bookId:i,callTool:b,chatModels:pr.models,disabled:G||oa||!i||p.state!=="ready",modelSelectionDisabled:!i||p.state!=="ready",connectionLabel:oa?"Removing selected subjects…":p.state==="ready"?"Load a book to begin":"Connecting to MCP…",mcpCalls:Cc,mcpFlash:Sc,onToggleMcpCall:jc,selectedModel:Us,inputSession:Kn,portalTarget:Oe&&(Ro||Ci)?Ql:te&&Ro?uc:null,pendingInput:he?"/apply":_?.kind==="generation"?"/apply ":ce||_?"/apply":void 0,notice:Ht?{message:Ht.text,tone:Ht.tone}:null,outcomeSlot:xi?"sheet":"composer",onEnsureCatalog:wd,onDismissNotice:()=>Fo(null),onDismissPanel:he||ce||_?Be:void 0,onExecute:ls,voiceCatalog:Gn,voice:Yt,onStartVoice:()=>{Y(null),wo(),Vt(null),Ne(null),pt(null)},onModelChange:hd,onSuccessfulExecute:ef,children:xi})]})}const lw=await $k().catch(()=>null);af.createRoot(document.getElementById("root")).render(C.jsx(iw,{initialWorkspace:lw}));
|