@lingjingai/scriptctl 0.66.11 → 0.66.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{b as s}from"./chunk-4MGRUUNV.js";import{Console as r}from"node:console";var o=new r({stdout:process.stderr,stderr:process.stderr});console.debug=o.debug.bind(o);console.info=o.info.bind(o);console.log=o.log.bind(o);s(process.argv.slice(2)).then(e=>{process.exitCode=e}).catch(e=>{console.error(e),process.exitCode=70});
2
+ import{b as s}from"./chunk-QBAD7GAY.js";import{Console as r}from"node:console";var o=new r({stdout:process.stderr,stderr:process.stderr});console.debug=o.debug.bind(o);console.info=o.info.bind(o);console.log=o.log.bind(o);s(process.argv.slice(2)).then(e=>{process.exitCode=e}).catch(e=>{console.error(e),process.exitCode=70});
@@ -119,7 +119,7 @@ Rules:
119
119
  - \u7FA4\u4F53\u8BCD\uFF08\u4F17\u4EBA / \u7FA4\u4F17 / \u56F4\u89C2\u8005 / \u8DEF\u4EBA\u4EEC\uFF09\u4E0D\u8FDB \u4EBA\u7269.md\uFF0C\u767B\u5230 \u53D1\u58F0\u6E90.md \u7528 group \u6216\u5199\u52A8\u4F5C\u65C1\u767D\u3002
120
120
  - \u52A8\u4F5C / \u5BF9\u767D\u6B63\u6587\u9010\u5B57\u4FDD\u7559\uFF0C\u4E0D\u8981\u8F6C\u8FF0 / \u7FFB\u8BD1 / \u6982\u62EC / \u52A0\u6CE8\u91CA\uFF1B\u52A8\u4F5C\u79CD\u7C7B\u53EA\u6709 act/dlg/think\u3002
121
121
  - \u6BCF\u4E2A\u51FA\u73B0\u5728\u6B63\u6587\u91CC\u7684\u89D2\u8272\uFF0C\u90FD\u8981\u5728 \u4EBA\u7269.md \u7ED9\u51FA\u975E\u7A7A\u63CF\u8FF0\uFF08\u5426\u5219\u6821\u9A8C\u62A5\u9519\uFF09\u3002
122
- `,x=class extends Error{exitCode;errorCode;hint;data;constructor(t,n){super(t),this.name="CliError",this.exitCode=n.exitCode,this.errorCode=n.errorCode,this.hint=n.hint,this.data=n.data??{}}};function Pw(e){return new Ns(e)}function ru(e){return Pw(e).directDir}function me(e){let t=e.script_path??e.scriptPath;return Sr.resolve(typeof t=="string"&&t.length>0?t:Uw)}function Ir(e){return Ls.readJson(e)}function kc(e,t){Ls.writeJson(e,t)}function Ho(e){return Ls.exists(e)}function _e(e){return Ac.createHash("sha256").update(e,"utf-8").digest("hex")}function bc(e){let t=Ac.createHash("sha256"),n=Li.openSync(e,"r");try{let o=Buffer.alloc(1048576);for(;;){let i=Li.readSync(n,o,0,o.length,null);if(i<=0)break;t.update(o.subarray(0,i))}}finally{Li.closeSync(n)}return t.digest("hex")}var Nt={policy:["content_blocked"],network:["dns_failed","connection_refused","connection_reset","network_unreachable","tls_failed","network_failed"],timeout:["connect_timeout","request_timeout","media_processing_timeout"],rate_limit:["rate_limited"],authentication:["authentication_failed"],authorization:["permission_denied"],provider:["resource_not_found","provider_unavailable","request_rejected","attempts_exhausted"],media:["media_upload_failed","media_processing_failed","media_too_large","unsupported_media"],response:["output_truncated","empty_response","malformed_response"],pipeline:["serial_parse_failed","source_mismatch","pipeline_mismatch"],validation:["script_validation_failed"],cancelled:["cancelled"],unknown:["unknown","legacy_unclassified"]};function Lt(e,t){return typeof e=="string"&&t.some(n=>n===e)}function su(e,t){switch(e){case"policy":return Lt(t,Nt.policy)?{failure_type:e,failure_code:t}:null;case"network":return Lt(t,Nt.network)?{failure_type:e,failure_code:t}:null;case"timeout":return Lt(t,Nt.timeout)?{failure_type:e,failure_code:t}:null;case"rate_limit":return Lt(t,Nt.rate_limit)?{failure_type:e,failure_code:t}:null;case"authentication":return Lt(t,Nt.authentication)?{failure_type:e,failure_code:t}:null;case"authorization":return Lt(t,Nt.authorization)?{failure_type:e,failure_code:t}:null;case"provider":return Lt(t,Nt.provider)?{failure_type:e,failure_code:t}:null;case"media":return Lt(t,Nt.media)?{failure_type:e,failure_code:t}:null;case"response":return Lt(t,Nt.response)?{failure_type:e,failure_code:t}:null;case"pipeline":return Lt(t,Nt.pipeline)?{failure_type:e,failure_code:t}:null;case"validation":return Lt(t,Nt.validation)?{failure_type:e,failure_code:t}:null;case"cancelled":return Lt(t,Nt.cancelled)?{failure_type:e,failure_code:t}:null;case"unknown":return Lt(t,Nt.unknown)?{failure_type:e,failure_code:t}:null;default:return null}}function Ut(e,t){return{...e,...t}}function Ui(e){switch(e.failure_type){case"policy":return{failure_type:e.failure_type,failure_code:e.failure_code};case"network":return{failure_type:e.failure_type,failure_code:e.failure_code};case"timeout":return{failure_type:e.failure_type,failure_code:e.failure_code};case"rate_limit":return{failure_type:e.failure_type,failure_code:e.failure_code};case"authentication":return{failure_type:e.failure_type,failure_code:e.failure_code};case"authorization":return{failure_type:e.failure_type,failure_code:e.failure_code};case"provider":return{failure_type:e.failure_type,failure_code:e.failure_code};case"media":return{failure_type:e.failure_type,failure_code:e.failure_code};case"response":return{failure_type:e.failure_type,failure_code:e.failure_code};case"pipeline":return{failure_type:e.failure_type,failure_code:e.failure_code};case"validation":return{failure_type:e.failure_type,failure_code:e.failure_code};case"cancelled":return{failure_type:e.failure_type,failure_code:e.failure_code};case"unknown":return{failure_type:e.failure_type,failure_code:e.failure_code}}}function Ar(e){return{...e.provider!==void 0?{provider:e.provider}:{},...e.model!==void 0?{model:e.model}:{},...e.operation!==void 0?{operation:e.operation}:{},...e.http_status!==void 0?{http_status:e.http_status}:{},...e.system_code!==void 0?{system_code:e.system_code}:{},...e.provider_source!==void 0?{provider_source:e.provider_source}:{},...e.provider_reason!==void 0?{provider_reason:e.provider_reason}:{},...e.provider_reason_raw!==void 0?{provider_reason_raw:e.provider_reason_raw}:{},...e.finish_message!==void 0?{finish_message:e.finish_message}:{},...e.safety_ratings!==void 0?{safety_ratings:e.safety_ratings}:{},...e.details!==void 0?{details:e.details}:{}}}function au(e,t){if(e.length===0)return Ut({failure_type:"unknown",failure_code:"unknown"},{retryable:!1,message:t});let n=e[0],i=e.every(r=>r.failure_type===n.failure_type&&r.failure_code===n.failure_code)?Ui(n):{failure_type:"provider",failure_code:"attempts_exhausted"};return Ut(i,{retryable:e.some(r=>r.retryable),message:t})}function hn(e){let t=e.provider||e.model?`${e.provider??"provider"}/${e.model??"model"} `:"",n=e.provider_reason?` provider_reason=${e.provider_reason}`:"",o=e.system_code?` system_code=${e.system_code}`:"",i=e.http_status!==void 0?` http_status=${e.http_status}`:"",r=e.details?.length?` | ${e.details.join(" | ")}`:"";return`${t}${e.failure_type}/${e.failure_code}${n}${o}${i}: ${e.message}${r}`}import*as Su from"node:crypto";import*as Iu from"node:fs";import*as Au from"node:path";import*as gu from"node:crypto";var Tn=["action","dialogue","inner_thought","transition"],qt=new Set(Tn),Vn=["system","broadcast","offscreen","group"],Fo=new Set(Vn),$n=["featured","background"],Pt=new Set($n),Pi=["\u4E3B\u89D2","\u914D\u89D2"],uo=new Set(Pi),Us=["day","night","dawn","dusk"],vc=new Set(Us);function kr(e){return typeof e=="string"&&vc.has(e)}var Oc=["interior","exterior"],cu=new Set(Oc);function dt(e){return e.normalize("NFKC").toLowerCase()}function du(e){return JSON.stringify([e.code,e.path,e.message])}function Rc(e){let t=new Map;for(let n of e){let o=du(n);t.set(o,(t.get(o)??0)+1)}return t}function Mc(e,t){if(e.ok||t.errors.length>=e.errors.length)return!1;let n=Rc(e.errors),o=Rc(t.errors);for(let[i,r]of o)if(r>(n.get(i)??0))return!1;return!0}function Nc(e,t){let n=Rc(e),o=[];for(let i of t){let r=du(i),s=n.get(r)??0;s>0?n.set(r,s-1):o.push(i)}return o}import{customAlphabet as Cw}from"nanoid";var Ci="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",Lc=6,Ti={episode:"ep",scene:"scn",action:"ac",actor:"act",location:"loc",prop:"prp",state:"st"},Tw=Cw(Ci,Lc),Vw=`[${Ci}]`,pu=Object.fromEntries(Object.entries(Ti).map(([e,t])=>[e,new RegExp(`^${t}${Vw}{${Lc}}$`)]));function V(e,t){return typeof t=="string"&&pu[e].test(t)}var Uc="ID_SPACE_EXHAUSTED";function br(e,t=new Set,n=Tw){let o=Ti[e];for(let i=0;i<128;i++){let r=`${o}${n()}`;if(!t.has(r))return r}throw Object.assign(new Error(`Could not generate an unused ${e} ID after 128 attempts.`),{code:Uc})}var et=class extends Error{input;constructor(t,n){super(n),this.input=t,this.name="TimestampParseError"}},$w=/^(\d+):(\d{2})(?:\.(\d{1,3}))?$/,Dw=/^(\d+):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/;function lu(e){return e?Number(e.padEnd(3,"0")):0}function uu(e,t){if(!Number.isSafeInteger(t))throw new et(e,"Timestamp exceeds the supported numeric range.");return t}function fu(e,t){let n=Math.floor(e/1e3),o=Math.floor(n/3600),i=Math.floor(n%3600/60),r=n%60,s=t?`.${t}`:"";return o>0?`${o}:${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}${s}`:`${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}${s}`}function fo(e){let t=e.trim();if(!t)throw new et(e,"Timestamp must not be empty.");let n=t.match(Dw);if(n){let a=Number(n[1]),d=Number(n[2]),p=Number(n[3]),l=n[4];if(d>59)throw new et(e,"Hour-form timestamps require minutes between 00 and 59.");if(p>59)throw new et(e,"Timestamp seconds must be between 00 and 59.");let f=uu(e,((a*60+d)*60+p)*1e3+lu(l));return{canonical:fu(f,l),milliseconds:f,fractionDigits:l?.length??0}}let o=t.match($w);if(!o)throw new et(e,"Use M:SS, MM:SS, or H:MM:SS with an optional 1-3 digit fraction.");let i=Number(o[1]),r=Number(o[2]),s=o[3];if(r>59)throw new et(e,"Timestamp seconds must be between 00 and 59.");let c=uu(e,(i*60+r)*1e3+lu(s));return{canonical:fu(c,s),milliseconds:c,fractionDigits:s?.length??0}}function Gw(e){if(typeof e!="object"||e===null||Array.isArray(e))return;let t=e.extend;if(!(typeof t!="object"||t===null||Array.isArray(t)))return t.timestamp}function Ps(e,t,n){let o=null;e.forEach((i,r)=>{let s=Gw(i);if(s===void 0)return;let c=`${t}[${r}].extend.timestamp`;if(typeof s!="string"){n("timestamp_invalid",c,"timestamp must be a string in M:SS, MM:SS, or H:MM:SS form");return}let a;try{a=fo(s)}catch(d){if(!(d instanceof et))throw d;n("timestamp_invalid",c,d.message);return}o!==null&&a.milliseconds<o.timestamp.milliseconds&&n("timestamp_out_of_order",c,`timestamp ${a.canonical} is earlier than Action ${o.actionIndex+1} timestamp ${o.timestamp.canonical}; equal timestamps are allowed`),o={actionIndex:r,timestamp:a}})}var yt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Dn=e=>Array.isArray(e),Ie=e=>typeof e=="string",Bw=["state_changes","actor_id","speakers","lines"];function wt(e){let t=[],n=[],o=(u,m,h,g)=>t.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}}),i=(u,m,h)=>n.push({code:u,path:m,message:h});if(!yt(e))return{ok:!1,errors:[{code:"not_object",path:"$",message:"script must be an object"}],warnings:n};e.version!==3&&o("version","$.version","version must be 3");for(let u of["title","worldview","style"])Ie(e[u])||o("field",`$.${u}`,`${u} must be a string`);let r=new Map,s=new Map,c=new Map,a=(u,m,h,g,w)=>{if(!Dn(u)){o("field",w,`${w} must be an array`);return}u.forEach((y,_)=>{let S=`${w}[${_}]`;if(!yt(y)){o("asset",S,"asset must be an object");return}let E=y[h];if(!Ie(E)){o("asset_id",`${S}.${h}`,`${h} required`);return}if(s.has(E)&&o("dup_id",`${S}.${h}`,`duplicate id ${E}`),s.set(E,m),!Ie(y[g]))o("asset_name",`${S}.${g}`,`${g} required`);else if(m==="actor"){let M=dt(y[g]),I=c.get(M);I!==void 0?o("dup_actor_name",`${S}.${g}`,`actor name ${y[g]} already belongs to ${I}`):c.set(M,E)}(!Ie(y.importance)||!$n.includes(y.importance))&&o("importance",`${S}.importance`,`importance must be one of ${$n.join("|")}`),Ie(y.description)||o("asset_desc",`${S}.description`,"description must be a string");let A=new Set,b=new Set,U=0;!Dn(y.states)||y.states.length===0?o("states",`${S}.states`,"states must be a non-empty array"):y.states.forEach((M,I)=>{let O=`${S}.states[${I}]`;if(!yt(M)||!Ie(M.state_id)){o("state_id",O,"state_id required");return}A.has(M.state_id)&&o("dup_state",O,`duplicate state_id ${M.state_id}`),A.add(M.state_id),M.state_id==="default"&&U++,Ie(M.state_name)?(b.has(M.state_name)&&o("dup_state_name",`${O}.state_name`,`duplicate state_name ${M.state_name}`),b.add(M.state_name)):o("state_name",`${O}.state_name`,"state_name required")}),Dn(y.states)&&U!==1&&o("default_state",`${S}.states`,`exactly one 'default' state required, found ${U}`),r.set(E,A)})};a(e.actors,"actor","actor_id","actor_name","$.actors"),a(e.locations,"location","location_id","location_name","$.locations"),a(e.props,"prop","prop_id","prop_name","$.props");let d=(u,m,h,g)=>{if(s.get(u)!==h){o("ref",g,`${h} ${u} not found`);return}m!==void 0&&(!Ie(m)||!r.get(u)?.has(m))&&o("state_ref",g,`state ${String(m)} not materialized on ${u}`)},p=(u,m,h,g)=>{if(u===void 0){o("field",g,`${g} required (may be empty array)`);return}if(!Dn(u)){o("field",g,`${g} must be an array`);return}u.forEach((w,y)=>{if(!yt(w)||!Ie(w[h])){o("ref",`${g}[${y}]`,`${h} required`);return}d(w[h],w.state_id,m,`${g}[${y}]`)})},l=(u,m,h,g)=>{if(!yt(u)){o("action",m,"action must be an object");return}for(let y of Bw)y in u&&o("legacy_field",`${m}.${y}`,`v3 forbids action.${y}`);let w=u.type;if((!Ie(w)||!Tn.includes(w))&&o("action_type",`${m}.type`,`invalid action type ${String(w)}`),Ie(u.content)||o("content",`${m}.content`,"content must be a plain-text string"),w==="dialogue"||w==="inner_thought"){let y=u.speaker;if(!yt(y))o("speaker",`${m}.speaker`,"dialogue/inner_thought needs a speaker");else if("kind"in y)(!Ie(y.kind)||!Vn.includes(y.kind))&&o("speaker_kind",`${m}.speaker.kind`,"invalid non-actor speaker kind");else if(Ie(y.actor_id)){if(d(y.actor_id,y.state_id,"actor",`${m}.speaker`),!h.has(y.actor_id)){let _=r.get(y.actor_id),S=Ie(y.state_id)&&_?.has(y.state_id)?y.state_id:_?.has("default")?"default":_?.values().next().value,E=g&&S?`scriptctl scene-ref ${g} actor:${y.actor_id} --state ${S} -p "$SCRIPT"`:void 0;o("actor_not_in_scene",`${m}.speaker.actor_id`,`actor ${y.actor_id} is not referenced by this scene`,E)}}else o("speaker",`${m}.speaker`,"speaker needs actor_id or kind")}},f=e.episodes;return Dn(f)?f.forEach((u,m)=>{let h=`$.episodes[${m}]`;if(!yt(u)||!Ie(u.episode_id)){o("episode_id",h,"episode_id required");return}if(!Dn(u.scenes)){o("scenes",`${h}.scenes`,"scenes must be an array");return}u.scenes.forEach((g,w)=>{let y=`${h}.scenes[${w}]`;if(!yt(g)){o("scene",y,"scene must be an object");return}"context"in g&&o("legacy_field",`${y}.context`,"v3 forbids scene.context"),Ie(g.scene_id)||o("scene_id",y,"scene_id required");let _=g.environment;_===void 0||yt(_)&&(!Ie(_.time)||_.time.trim()==="")?i("scene_time_missing",`${y}.environment.time`,"scene time is required for production review"):!yt(_)||_.space!==void 0&&!Ie(_.space)||!Ie(_.time)?o("environment",`${y}.environment`,"environment must contain optional string space and a time string"):kr(_.time)||o("scene_time",`${y}.environment.time`,"scene time must be day|night|dawn|dusk"),(g.environment===void 0||yt(g.environment)&&(!Ie(g.environment.space)||g.environment.space.trim()===""))&&i("scene_space_missing",`${y}.environment.space`,"scene interior/exterior is required for production review"),g.location===null&&i("scene_location_missing",`${y}.location`,"scene location is required for production review");let S=g.location;if(S!==null&&(!yt(S)||!Ie(S.location_id)?o("location",`${y}.location`,"location must be null or {location_id}"):d(S.location_id,S.state_id,"location",`${y}.location`)),p(g.actors,"actor","actor_id",`${y}.actors`),p(g.props,"prop","prop_id",`${y}.props`),Dn(g.props)){let A=new Set;g.props.forEach((b,U)=>{!yt(b)||!Ie(b.prop_id)||(A.has(b.prop_id)&&o("dup_prop_ref",`${y}.props[${U}]`,`duplicate prop ref ${b.prop_id}`),A.add(b.prop_id))})}let E=new Set(Dn(g.actors)?g.actors.filter(A=>yt(A)).map(A=>A.actor_id).filter(A=>Ie(A)):[]);if(!Dn(g.actions))o("actions",`${y}.actions`,"actions must be an array");else{let A=Ie(g.scene_id)?`${u.episode_id}/${g.scene_id}`:void 0;g.actions.forEach((b,U)=>l(b,`${y}.actions[${U}]`,E,A)),Ps(g.actions,`${y}.actions`,o)}})}):o("episodes","$.episodes","episodes must be an array"),{ok:t.length===0,errors:t,warnings:n}}var tt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),de=e=>typeof e=="string",yn=e=>Array.isArray(e);function Pc(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?!0:Array.isArray(e)?e.every(Pc):tt(e)&&Object.values(e).every(Pc)}function Vi(e,t,n){e!==void 0&&(!tt(e)||!Object.values(e).every(Pc))&&n("extend",t,"extend must be an object containing JSON values")}function Jw(e){for(let t=1;t<e.length;t++)if(e[t-1]>e[t])return!1;return!0}function Pe(e){let t=[],n=[],o=(u,m,h,g)=>t.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}}),i=(u,m,h,g)=>n.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}});if(!tt(e))return{ok:!1,errors:[{code:"not_object",path:"$",message:"script must be an object"}],warnings:n};e.version!==4&&o("version","$.version","version must be 4");for(let u of["title","worldview","style"])de(e[u])||o("field",`$.${u}`,`${u} must be a string`);for(let u of["worldview_raw","synopsis","logline","theme"])e[u]!==void 0&&!de(e[u])&&o("field",`$.${u}`,`${u} must be a string`);e.main_characters!==void 0&&(!yn(e.main_characters)||!e.main_characters.every(u=>tt(u)&&de(u.name)&&de(u.role)))&&o("main_characters","$.main_characters","main_characters must contain {name, role} string records"),Vi(e.extend,"$.extend",o);let r=new Map,s=new Map,c=new Set,a=(u,m,h,g,w)=>{if(!yn(u)){o("field",w,`${w} must be an array`);return}let y=new Set;u.forEach((_,S)=>{let E=`${w}[${S}]`;if(!tt(_)){o("asset",E,"asset must be an object");return}let A=_[h];if(!V(m,A)){o("asset_id",`${E}.${h}`,`${h} must be ${m} ID`);return}if(y.has(A)&&o("dup_id",`${E}.${h}`,`duplicate ${h} ${A}`),y.add(A),r.set(A,m),!de(_[g])||_[g].trim()==="")o("asset_name",`${E}.${g}`,`${g} must be a non-empty string`);else if(m==="actor"){let I=_[g].trim().toLocaleLowerCase();c.has(I)&&o("dup_actor_name",`${E}.${g}`,`duplicate actor name ${_[g]}`),c.add(I)}if((!de(_.importance)||!$n.includes(_.importance))&&o("importance",`${E}.importance`,`importance must be ${$n.join("|")}`),m==="actor"&&_.role_type!==void 0&&(!de(_.role_type)||!Pi.includes(_.role_type))&&o("role_type",`${E}.role_type`,`role_type must be ${Pi.join("|")}`),de(_.description)||o("asset_desc",`${E}.description`,"description must be a string"),_.aliases!==void 0&&(!yn(_.aliases)||!_.aliases.every(de)))o("aliases",`${E}.aliases`,"aliases must be an array of strings");else if(yn(_.aliases)&&_.aliases.every(de)){let I=new Set,O=de(_[g])?_[g]:"";_.aliases.forEach((L,C)=>{L===""&&o("alias_empty",`${E}.aliases[${C}]`,"alias must not be empty"),L===O&&o("alias_equals_name",`${E}.aliases[${C}]`,"alias must differ from the asset name"),I.has(L)&&o("dup_alias",`${E}.aliases[${C}]`,`duplicate alias ${L}`),I.add(L)})}Vi(_.extend,`${E}.extend`,o);let b=new Set,U=new Set,M=0;!yn(_.states)||_.states.length===0?o("states",`${E}.states`,"states must be a non-empty array"):_.states.forEach((I,O)=>{let L=`${E}.states[${O}]`;if(!tt(I)){o("state",L,"state must be an object");return}let C=I.state_id;if(C!=="default"&&!V("state",C)){o("state_id",`${L}.state_id`,"state_id must be default or st plus six Base58 characters");return}b.has(C)&&o("dup_state",`${L}.state_id`,`duplicate state_id ${C}`),b.add(C),C==="default"&&M++,!de(I.state_name)||I.state_name.trim()===""?o("state_name",`${L}.state_name`,"state_name must be a non-empty string"):(U.has(I.state_name)&&o("dup_state_name",`${L}.state_name`,`duplicate state_name ${I.state_name}`),U.add(I.state_name)),de(I.description)||o("state_description",`${L}.description`,"description must be a string"),Vi(I.extend,`${L}.extend`,o)}),M!==1&&o("default_state",`${E}.states`,`exactly one default state required, found ${M}`),s.set(A,b)})};a(e.actors,"actor","actor_id","actor_name","$.actors"),a(e.locations,"location","location_id","location_name","$.locations"),a(e.props,"prop","prop_id","prop_name","$.props");let d=(u,m,h)=>{if(!yn(m)||m.length===0||!m.every(de))return o("state_ids",h,"state_ids must be a non-empty array of strings"),[];let g=m,w=new Set;return g.forEach((y,_)=>{w.has(y)&&o("dup_state_ref",`${h}[${_}]`,`duplicate state_id ${y}`),w.add(y),s.get(u)?.has(y)||o("state_ref",`${h}[${_}]`,`state ${y} not found on ${u}`)}),Jw(g)||o("state_ids_order",h,"state_ids must be sorted lexically"),g},p=new Set,l=new Set,f=new Set;return yn(e.episodes)?e.episodes.forEach((u,m)=>{let h=`$.episodes[${m}]`;if(!tt(u)){o("episode",h,"episode must be an object");return}V("episode",u.episode_id)?(p.has(u.episode_id)&&o("dup_episode_id",`${h}.episode_id`,`duplicate episode_id ${u.episode_id}`),p.add(u.episode_id)):o("episode_id",`${h}.episode_id`,"episode_id must be ep plus six Base58 characters");for(let g of["title","synopsis"])u[g]!==void 0&&!de(u[g])&&o("field",`${h}.${g}`,`${g} must be a string`);if(Vi(u.extend,`${h}.extend`,o),!yn(u.scenes)){o("scenes",`${h}.scenes`,"scenes must be an array");return}u.scenes.forEach((g,w)=>{let y=`${h}.scenes[${w}]`;if(!tt(g)){o("scene",y,"scene must be an object");return}V("scene",g.scene_id)?(l.has(g.scene_id)&&o("dup_scene_id",`${y}.scene_id`,`duplicate scene_id ${g.scene_id}`),l.add(g.scene_id)):o("scene_id",`${y}.scene_id`,"scene_id must be scn plus six Base58 characters"),Vi(g.extend,`${y}.extend`,o),g.environment===void 0||tt(g.environment)&&(!de(g.environment.time)||g.environment.time.trim()==="")?i("scene_time_missing",`${y}.environment.time`,"scene time is required for production review"):!tt(g.environment)||g.environment.space!==void 0&&!de(g.environment.space)||!de(g.environment.time)?o("environment",`${y}.environment`,"environment must contain optional string space and a time string"):kr(g.environment.time)||o("scene_time",`${y}.environment.time`,"scene time must be day|night|dawn|dusk"),(g.environment===void 0||tt(g.environment)&&(!de(g.environment.space)||g.environment.space.trim()===""))&&i("scene_space_missing",`${y}.environment.space`,"scene interior/exterior is required for production review"),g.location===null&&i("scene_location_missing",`${y}.location`,"scene location is required for production review"),g.location!==null&&(!tt(g.location)||!V("location",g.location.location_id)?o("location",`${y}.location`,"location must be null or a typed v4 location reference"):("state_id"in g.location&&o("v3_field",`${y}.location.state_id`,"Script v4 scene references use state_ids"),r.get(g.location.location_id)!=="location"&&o("location_ref",`${y}.location.location_id`,`location ${g.location.location_id} not found`),d(g.location.location_id,g.location.state_ids,`${y}.location.state_ids`)));let _=new Map,S=(E,A,b,U)=>{if(!yn(E)){o("field",U,`${U} must be an array`);return}let M=new Set;E.forEach((I,O)=>{let L=`${U}[${O}]`;if(!tt(I)||!V(A,I[b])){o("ref",L,`${b} must be a typed v4 ID`);return}let C=I[b];"state_id"in I&&o("v3_field",`${L}.state_id`,"Script v4 scene references use state_ids"),M.has(C)&&o("dup_asset_ref",`${L}.${b}`,`duplicate ${A} ref ${C}`),M.add(C),r.get(C)!==A&&o("asset_ref",`${L}.${b}`,`${A} ${C} not found`);let R=d(C,I.state_ids,`${L}.state_ids`);A==="actor"&&_.set(C,new Set(R))})};if(S(g.actors,"actor","actor_id",`${y}.actors`),S(g.props,"prop","prop_id",`${y}.props`),!yn(g.actions)){o("actions",`${y}.actions`,"actions must be an array");return}g.actions.forEach((E,A)=>{let b=`${y}.actions[${A}]`;if(!tt(E)){o("action",b,"action must be an object");return}if(V("action",E.action_id)?(f.has(E.action_id)&&o("dup_action_id",`${b}.action_id`,`duplicate action_id ${E.action_id}`),f.add(E.action_id)):o("action_id",`${b}.action_id`,"action_id must be ac plus six Base58 characters"),(!de(E.type)||!Tn.includes(E.type))&&o("action_type",`${b}.type`,`invalid action type ${String(E.type)}`),de(E.content)||o("content",`${b}.content`,"content must be a string"),"emotion"in E&&o("v3_field",`${b}.emotion`,"Script v4 does not allow emotion"),Vi(E.extend,`${b}.extend`,o),E.type==="dialogue"||E.type==="inner_thought")if(E.parenthetical!==void 0&&!de(E.parenthetical)&&o("parenthetical",`${b}.parenthetical`,"parenthetical must be a string"),!tt(E.speaker))o("speaker",`${b}.speaker`,"dialogue/inner_thought requires a speaker");else if(de(E.speaker.actor_id)){("kind"in E.speaker||"label"in E.speaker)&&o("speaker_shape",`${b}.speaker`,"actor speaker cannot contain non-actor speaker fields");let M=E.speaker.actor_id;(!V("actor",M)||r.get(M)!=="actor")&&o("speaker_actor",`${b}.speaker.actor_id`,`actor ${M} not found`);let I=_.get(M),O=s.get(M),L=de(E.speaker.state_id)&&O?.has(E.speaker.state_id)?E.speaker.state_id:void 0,C=O?.has("default")?"default":O?.values().next().value,R=L?[L]:C?[C]:[],J=V("scene",g.scene_id)&&V("actor",M)&&R.length>0?`scriptctl scene-ref ${g.scene_id} ${M} ${R.map(W=>`--state ${W}`).join(" ")} -p "$SCRIPT"`:void 0;if(I||o("actor_not_in_scene",`${b}.speaker.actor_id`,`actor ${M} is not referenced by this scene`,J),E.speaker.state_id!==void 0&&(!de(E.speaker.state_id)||!I?.has(E.speaker.state_id))){let W=L?[...new Set([...I??[],L])].sort():[],Re=V("scene",g.scene_id)&&V("actor",M)&&W.length>0?`scriptctl scene-ref ${g.scene_id} ${M} ${W.map(ie=>`--state ${ie}`).join(" ")} -p "$SCRIPT"`:J;o("speaker_state",`${b}.speaker.state_id`,`speaker state ${String(E.speaker.state_id)} is not in this scene's actor state_ids`,Re)}}else de(E.speaker.kind)?(("actor_id"in E.speaker||"state_id"in E.speaker)&&o("speaker_shape",`${b}.speaker`,"non-actor speaker cannot contain actor speaker fields"),Vn.includes(E.speaker.kind)||o("speaker_kind",`${b}.speaker.kind`,"invalid non-actor speaker kind"),E.speaker.label!==void 0&&!de(E.speaker.label)&&o("speaker_label",`${b}.speaker.label`,"speaker label must be a string")):o("speaker",`${b}.speaker`,"speaker needs actor_id or kind");else"parenthetical"in E&&o("parenthetical_type",`${b}.parenthetical`,"parenthetical only belongs to speaking actions"),"speaker"in E&&o("speaker_type",`${b}.speaker`,"speaker only belongs to speaking actions");if(E.transition_prompt!==void 0){let M=E.transition_prompt;!tt(M)||!de(M.target)||!de(M.process)||M.process===""||!de(M.contrast)||M.contrast===""?o("transition_prompt",`${b}.transition_prompt`,"transition_prompt requires non-empty target/process/contrast"):r.has(M.target)||o("transition_target",`${b}.transition_prompt.target`,`asset ${M.target} not found`)}}),Ps(g.actions,`${y}.actions`,o)})}):o("episodes","$.episodes","episodes must be an array"),{ok:t.length===0,errors:t,warnings:n}}function Qo(e,t=new Set,n){try{return n?br(e,t,n):br(e,t)}catch(o){throw o?.code!==Uc?o:new x(`Could not generate an unused ${e} ID.`,{exitCode:k,errorCode:"ID_SPACE_RETRY_EXHAUSTED",hint:"Retry the command. If this persists, inspect the configured ID generator."})}}function Ae(e,t=[]){throw new x(e,{exitCode:k,errorCode:"CREATIVE_DRAFT_INVALID",hint:"Use the readable creative draft schema; do not include Script IDs or .scriptctl syntax.",data:{actual:t.map(String)}})}function Gn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function q(e,t=""){return String(e??"").replace(/\s+/gu," ").trim()||t}function jw(e,t){let n=Number(e);return(!Number.isSafeInteger(n)||n<1)&&Ae(`${t} must be a positive integer.`,[e]),n}function Kw(e){return e===void 0?{}:(Gn(e)||Ae("Action extensions must be an object."),structuredClone(e))}function zw(e){let t=new Set;for(let n of e.actors){t.add(n.actor_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.locations){t.add(n.location_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.props){t.add(n.prop_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.episodes){t.add(n.episode_id);for(let o of n.scenes){t.add(o.scene_id);for(let i of o.actions)t.add(i.action_id)}}return t}function mo(e,t,n){for(let o=0;o<128;o+=1){let i=gu.createHash("sha256").update(`${e}:${t}:${o}`).digest(),r="";for(let c=0;c<6;c+=1)r+=Ci[i[c]%Ci.length];let s=`${Ti[e]}${r}`;if(!n.has(s))return n.add(s),s}Ae(`Could not allocate a stable ${e} ID.`)}function Hw(e){let t=q(e).match(/^(\d+):([0-5]\d)(?:\.(\d{1,3}))?$/u);return t?(Number(t[1])*60+Number(t[2]))*1e3+Number((t[3]??"").padEnd(3,"0")):null}function Fw(e){return`${Math.floor(e/6e4)}:${String(Math.floor(e%6e4/1e3)).padStart(2,"0")}.${String(e%1e3).padStart(3,"0")}`}function Qw(e){let t=Number(e.extend?.duration_ms??e.extend?.rewrite_duration_ms);return Number.isFinite(t)&&t>0?Math.round(t):1200}function Yw(e){let t=0;for(let n of e.scenes.flatMap(o=>o.actions))t=(Hw(n.extend?.timestamp)??t)+Qw(n);return t}function hu(e){return e===void 0?[]:((!Array.isArray(e)||!e.every(Gn))&&Ae("Asset variants must be an array of readable objects."),e)}function qw(e,t){let n=e.assets;if(n===void 0)return[];Gn(n)||Ae("assets must be an object.");let o=n[t];return o===void 0?[]:((!Array.isArray(o)||!o.every(Gn))&&Ae(`assets.${t} must be an array.`),o)}function Zw(e,t){return e==="actors"?t.actor_name:e==="locations"?t.location_name:t.prop_name}function Ww(e,t){return e[t]}function Xw(e,t){return[Zw(e,t),...t.aliases??[]].map(dt)}function yu(e,t,n){let o=dt(n);return qw(e,t).find(i=>[i.name,...Array.isArray(i.aliases)?i.aliases:[]].map(r=>dt(q(r))).includes(o))??null}function wu(e,t){if(!e)return null;let n=dt(t);return hu(e.variants).find(o=>{let i=dt(q(o.name));return i===n||["default","\u9ED8\u8BA4"].includes(n)&&["default","\u9ED8\u8BA4"].includes(i)})??null}function _u(e,t,n){let o=wu(e,n),i=q(o?.description);return(!o||!i)&&Ae(`${t}/${n} is a new variant and requires a readable assets declaration with a self-contained description.`),o}function e_(e,t){let n=q(t?.name);return n&&!["default","\u9ED8\u8BA4"].includes(dt(n))?n:e==="actors"?"\u57FA\u7840\u9020\u578B":e==="locations"?"\u5E38\u89C4\u5E03\u7F6E":"\u57FA\u7840\u5916\u89C2"}function t_(e,t,n,o,i,r){let s=yu(t,n,o);s||Ae(`${o} is not an existing ${n} asset and has no readable declaration.`);let c=q(s.name,o),a=hu(s.variants),d=wu(s,"\u9ED8\u8BA4")??a[0]??null;n==="actors"&&!q(s.description)&&Ae(`${c} requires an identity description separate from its appearance variants.`),n==="actors"&&!q(d?.description)&&Ae(`${c} requires its first variant to provide a self-contained base appearance description.`);let p=[{state_id:"default",state_name:e_(n,d),description:q(d?.description,q(s.description,`${c}\u7684\u57FA\u7840\u53C2\u8003\u5916\u89C2\u3002`))}];for(let u of a){let m=q(u.name);if(u===d||!m||["default","\u9ED8\u8BA4"].includes(dt(m)))continue;let h=mo("state",`${n}:${c}:${m}`,i);p.push({state_id:h,state_name:m,description:q(_u(s,c,m).description)}),r.states.push(`${c}/${m}`)}let l={aliases:Array.isArray(s.aliases)?[...new Set(s.aliases.map(u=>q(u)).filter(u=>u&&u!==c))]:[],importance:s.importance==="background"?"background":"featured",description:q(s.description,`${c}\u7684\u57FA\u7840\u8BBE\u5B9A\u3002`),states:p};if(n==="actors"){let u={...l,actor_id:mo("actor",c,i),actor_name:c,...s.roleType==="\u4E3B\u89D2"||s.roleType==="\u914D\u89D2"?{role_type:s.roleType}:{}};return e.actors.push(u),r.actors.push(c),u}if(n==="locations"){let u={...l,location_id:mo("location",c,i),location_name:c};return e.locations.push(u),r.locations.push(c),u}let f={...l,prop_id:mo("prop",c,i),prop_name:c};return e.props.push(f),r.props.push(c),f}function Ts(e,t,n,o,i,r){let s=q(o);s||Ae(`${n} reference requires a readable name.`);let c=dt(s);return Ww(e,n).find(d=>Xw(n,d).includes(c))??t_(e,t,n,s,i,r)}function vr(e,t,n,o,i,r){let s=q(t,"\u9ED8\u8BA4"),c=dt(s),a=e.states.find(u=>dt(u.state_name)===c||u.state_id==="default"&&["default","\u9ED8\u8BA4"].includes(c));if(a)return a.state_id;let d="actor_name"in e?e.actor_name:"location_name"in e?e.location_name:e.prop_name,p=yu(n,o,d),l=_u(p,d,s),f={state_id:mo("state",`${d}:${s}`,i),state_name:s,description:q(l.description)};return e.states.push(f),r.states.push(`${d}/${s}`),f.state_id}function mu(e,t){return e===void 0?[]:((!Array.isArray(e)||!e.every(Gn))&&Ae(`${t} must be an array of readable references.`),e)}function Cs(e,t,n){let o=structuredClone(e);for(let i of t){let r=o.find(s=>n(s)===n(i));r?r.state_ids=[...new Set([...r.state_ids,...i.state_ids])].sort():o.push(structuredClone(i))}return o}function n_(e,t){return!!(e&&e.location?.location_id&&t.location?.location_id&&e.location.location_id===t.location.location_id&&q(e.environment?.space)===q(t.environment?.space)&&q(e.environment?.time)===q(t.environment?.time))}function o_(e,t,n,o,i,r,s,c){(!Array.isArray(e)||e.length===0||!e.every(Gn))&&Ae("scene.actions must contain at least one readable Action.");let a=structuredClone(o),d=r;return{actions:e.map((l,f)=>{let u=q(l.type,"action");["action","transition","dialogue","inner_thought"].includes(u)||Ae(`Action ${f+1} has an unsupported type.`,[u]);let m=q(l.content);m||Ae(`Action ${f+1} has empty content.`);let h=Math.max(400,Math.min(8e3,Math.round(Number(l.durationMs)||Number(l.weight||1)*1200))),g=Kw(l.extensions);g.timestamp=Fw(d),g.duration_ms=h,g.rewrite_duration_ms!==void 0&&(g.rewrite_duration_ms=h);let w={action_id:mo("action",`${i}:${f+1}:${m}`,s),type:u,content:m,extend:g};if(d+=h,u==="action"||u==="transition")return w;let y=q(l.speaker);y||Ae(`Action ${f+1} requires a speaker.`);let _=y.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&");new RegExp(`^${_}\\s*[:\uFF1A]`,"iu").test(m)&&Ae(`Action ${f+1} repeats the speaker name in dialogue content.`),/^(?:“[^”]+”|「[^」]+」|『[^』]+』|"[^"]+")$/u.test(m)&&Ae(`Action ${f+1} wraps dialogue content in quotation marks.`);let S=dt(y);if(["\u65C1\u767D","narrator"].includes(S))return{...w,speaker:{kind:"broadcast",label:"\u65C1\u767D"},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}};if(["\u753B\u5916\u97F3","offscreen"].includes(S))return{...w,speaker:{kind:"offscreen",label:"\u753B\u5916\u97F3"},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}};let E=Ts(t,n,"actors",y,s,c),A=q(l.speakerVariant),b=a.find(M=>M.actor_id===E.actor_id),U;if(A)U=vr(E,A,n,"actors",s,c),b?b.state_ids=[...new Set([...b.state_ids,U])].sort():a.push({actor_id:E.actor_id,state_ids:[U]});else if(!b){let M=vr(E,"\u9ED8\u8BA4",n,"actors",s,c);a.push({actor_id:E.actor_id,state_ids:[M]})}return{...w,speaker:{actor_id:E.actor_id,...U?{state_id:U}:{}},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}}}),actorRefs:a}}function Eu(e,t){(!Gn(t)||t.version!==1)&&Ae("Creative draft version must be 1."),(!Gn(t.episode)||!Gn(t.scene))&&Ae("Creative draft requires episode and scene objects.");let n=structuredClone(t),o=n.episode,i=n.scene,r=structuredClone(e),s=zw(r),c={actors:[],locations:[],props:[],states:[]},a=jw(o.number,"episode.number");a>r.episodes.length+1&&Ae("Episodes must be composed in order.",[a]);let d=r.episodes[a-1];d?(q(d.title)||(d.title=q(o.title,`\u7B2C ${a} \u96C6`)),q(d.synopsis)||(d.synopsis=q(o.synopsis,`\u7B2C ${a} \u96C6\u5267\u60C5\u3002`))):(d={episode_id:mo("episode",`episode:${a}`,s),title:q(o.title,`\u7B2C ${a} \u96C6`),synopsis:q(o.synopsis,`\u7B2C ${a} \u96C6\u5267\u60C5\u3002`),scenes:[]},r.episodes.push(d));let p=Ts(r,n,"locations",i.location,s,c),l=vr(p,i.locationVariant,n,"locations",s,c),f=mu(i.actors,"scene.actors").map(I=>{let O=Ts(r,n,"actors",I.name,s,c);return{actor_id:O.actor_id,state_ids:[vr(O,I.variant,n,"actors",s,c)]}}),u=Cs([],f,I=>I.actor_id),m=mu(i.props,"scene.props").map(I=>{let O=Ts(r,n,"props",I.name,s,c);return{prop_id:O.prop_id,state_ids:[vr(O,I.variant,n,"props",s,c)]}}),h=Cs([],m,I=>I.prop_id),g=d.scenes.at(-1),w={scene_id:mo("scene",`episode:${a}:scene:${d.scenes.length+1}:${q(i.title)}`,s),environment:{space:q(i.space,"interior"),time:q(i.time,"day")},location:{location_id:p.location_id,state_ids:[l]},actors:u,props:h,actions:[],extend:{scene_title:q(i.title,`\u7B2C ${d.scenes.length+1} \u573A`)}},y=q(i.boundary,"auto");["auto","new","continue"].includes(y)||Ae("scene.boundary must be auto, new, or continue.");let _=n_(g,w);y==="continue"&&!_&&Ae("scene.boundary=continue requires the same location, space, and time as the previous scene.");let S=y!=="new"&&_,E=S&&g?g:w,A=S?d.scenes.length:d.scenes.length+1,b=Cs(E.actors,w.actors,I=>I.actor_id),U=o_(i.actions,r,n,b,E.scene_id,Yw(d),s,c);E.actors=U.actorRefs,E.props=Cs(E.props,w.props,I=>I.prop_id),E.location&&w.location&&(E.location.state_ids=[...new Set([...E.location.state_ids,...w.location.state_ids])].sort()),E.actions.push(...U.actions),S||d.scenes.push(E);let M=Pe(r);return M.ok||Ae("Composed screenplay does not pass Script v4 validation.",M.errors.slice(0,12).map(I=>`${I.path}: ${I.message}`)),{script:r,validation:M,episodeNumber:a,sceneNumber:A,sceneId:E.scene_id,actionIds:U.actions.map(I=>I.action_id),joinedPreviousScene:S,created:c}}function He(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function wn(e,t){return e[t]===void 0||typeof e[t]=="string"}function Cc(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?!0:Array.isArray(e)?e.every(Cc):He(e)&&Object.values(e).every(Cc)}function $i(e){return e.extend===void 0||He(e.extend)&&Object.values(e.extend).every(Cc)}function Tc(e){return e==="default"||V("state",e)}function i_(e){return He(e)&&Tc(e.state_id)&&typeof e.state_name=="string"&&typeof e.description=="string"&&$i(e)}function Vc(e){return typeof e.importance=="string"&&Pt.has(e.importance)&&typeof e.description=="string"&&(e.aliases===void 0||Array.isArray(e.aliases)&&e.aliases.every(t=>typeof t=="string"))&&Array.isArray(e.states)&&e.states.every(i_)&&$i(e)}function r_(e){return He(e)&&V("actor",e.actor_id)&&typeof e.actor_name=="string"&&(e.role_type===void 0||typeof e.role_type=="string"&&uo.has(e.role_type))&&Vc(e)}function s_(e){return He(e)&&V("location",e.location_id)&&typeof e.location_name=="string"&&Vc(e)}function a_(e){return He(e)&&V("prop",e.prop_id)&&typeof e.prop_name=="string"&&Vc(e)}function $c(e){return Array.isArray(e)&&e.every(Tc)}function c_(e){return He(e)&&V("actor",e.actor_id)&&$c(e.state_ids)}function d_(e){return He(e)&&V("location",e.location_id)&&$c(e.state_ids)}function p_(e){return He(e)&&V("prop",e.prop_id)&&$c(e.state_ids)}function l_(e){return V("actor",e.actor_id)&&(e.state_id===void 0||Tc(e.state_id))}function u_(e){return typeof e.kind=="string"&&Fo.has(e.kind)&&wn(e,"label")}function f_(e){return!(!He(e)||!V("action",e.action_id)||typeof e.type!="string"||!qt.has(e.type)||typeof e.content!="string"||!wn(e,"parenthetical")||!$i(e)||(e.type==="dialogue"||e.type==="inner_thought")&&(!He(e.speaker)||!l_(e.speaker)&&!u_(e.speaker))||e.transition_prompt!==void 0&&(!He(e.transition_prompt)||!V("actor",e.transition_prompt.target)&&!V("location",e.transition_prompt.target)&&!V("prop",e.transition_prompt.target)||typeof e.transition_prompt.process!="string"||typeof e.transition_prompt.contrast!="string"))}function m_(e){return!(!He(e)||!V("scene",e.scene_id)||!Array.isArray(e.actors)||!e.actors.every(c_)||!Array.isArray(e.props)||!e.props.every(p_)||!Array.isArray(e.actions)||!e.actions.every(f_)||!$i(e)||e.location!==null&&!d_(e.location)||e.environment!==void 0&&(!He(e.environment)||!wn(e.environment,"space")||!wn(e.environment,"time")))}function g_(e){return He(e)&&V("episode",e.episode_id)&&wn(e,"title")&&wn(e,"synopsis")&&Array.isArray(e.scenes)&&e.scenes.every(m_)&&$i(e)}function h_(e){return He(e)&&e.version===4&&typeof e.title=="string"&&typeof e.worldview=="string"&&typeof e.style=="string"&&wn(e,"worldview_raw")&&wn(e,"synopsis")&&wn(e,"logline")&&wn(e,"theme")&&(e.main_characters===void 0||Array.isArray(e.main_characters)&&e.main_characters.every(t=>He(t)&&typeof t.name=="string"&&typeof t.role=="string"))&&Array.isArray(e.actors)&&e.actors.every(r_)&&Array.isArray(e.locations)&&e.locations.every(s_)&&Array.isArray(e.props)&&e.props.every(a_)&&Array.isArray(e.episodes)&&e.episodes.every(g_)&&$i(e)}function Di(e){let t=Pe(e);if(t.ok)return e;throw new x("The local file is not a valid Script v4 document.",{exitCode:k,errorCode:"SCRIPT_V4_INVALID",hint:"Run `scriptctl validate --script-path <path>` and repair the reported v4 fields.",data:{expected:["A valid Script v4 document"],actual:t.errors.slice(0,20).map(n=>`${n.path}: ${n.message}`)}})}function _n(e){if(h_(e))return e;throw new x("The local file is not a structurally readable Script v4 document.",{exitCode:k,errorCode:"SCRIPT_V4_SHAPE_INVALID",hint:"Repair the local Script v4 structure, then rerun the command.",data:{expected:["Script v4 with typed assets, episodes, scenes, references, and actions"],actual:[Array.isArray(e)?"array":typeof e]}})}import*as Or from"node:crypto";import*as $e from"node:fs";import*as Ct from"node:path";import y_ from"proper-lockfile";function Gc(e){if(Array.isArray(e))return e.map(Gc);if(e!==null&&typeof e=="object"){let t=e,n={};for(let o of Object.keys(t).sort())n[o]=Gc(t[o]);return n}return e}function Je(e){let t=JSON.stringify(Gc(e));return`sha256:${Or.createHash("sha256").update(t).digest("hex")}`}function Rr(e){return $e.existsSync(e)?`sha256:${Or.createHash("sha256").update($e.readFileSync(e)).digest("hex")}`:null}function Mr(e,t){let n=Rr(e);if(n!==t)throw new x("The local script changed while the command was running.",{exitCode:k,errorCode:"LOCAL_SCRIPT_CHANGED",hint:"Read the latest local script and retry the command.",data:{actual:[`loadedFingerprint=${t??"<missing>"}`,`currentFingerprint=${n??"<missing>"}`,e]}})}function Nr(e){let t=Ct.resolve(e),n=Ct.join(Ct.dirname(t),".scriptctl"),o=Ct.basename(t);return{scriptPath:t,stateDir:n,metadataPath:Ct.join(n,`${o}.working-copy.json`),lockPath:Ct.join(n,o)}}async function Vs(e,t){let n=Nr(e);$e.mkdirSync(n.stateDir,{recursive:!0});let o=null;try{o=await y_.lock(n.lockPath,{realpath:!1,stale:12e4,update:1e4,retries:{retries:60,factor:1,minTimeout:500,maxTimeout:500}})}catch(i){throw new x("Timed out waiting for the script file lock.",{exitCode:X,errorCode:"WORKING_COPY_LOCK_TIMEOUT",hint:"Wait for the other scriptctl command to finish, then retry.",data:{actual:[n.scriptPath,i instanceof Error?i.message:String(i)]}})}try{return await t()}finally{await o()}}function Fe(e,t){$s(e,`${JSON.stringify(t,null,2)}
122
+ `,x=class extends Error{exitCode;errorCode;hint;data;constructor(t,n){super(t),this.name="CliError",this.exitCode=n.exitCode,this.errorCode=n.errorCode,this.hint=n.hint,this.data=n.data??{}}};function Pw(e){return new Ns(e)}function ru(e){return Pw(e).directDir}function me(e){let t=e.script_path??e.scriptPath;return Sr.resolve(typeof t=="string"&&t.length>0?t:Uw)}function Ir(e){return Ls.readJson(e)}function kc(e,t){Ls.writeJson(e,t)}function Ho(e){return Ls.exists(e)}function _e(e){return Ac.createHash("sha256").update(e,"utf-8").digest("hex")}function bc(e){let t=Ac.createHash("sha256"),n=Li.openSync(e,"r");try{let o=Buffer.alloc(1048576);for(;;){let i=Li.readSync(n,o,0,o.length,null);if(i<=0)break;t.update(o.subarray(0,i))}}finally{Li.closeSync(n)}return t.digest("hex")}var Nt={policy:["content_blocked"],network:["dns_failed","connection_refused","connection_reset","network_unreachable","tls_failed","network_failed"],timeout:["connect_timeout","request_timeout","media_processing_timeout"],rate_limit:["rate_limited"],authentication:["authentication_failed"],authorization:["permission_denied"],provider:["resource_not_found","provider_unavailable","request_rejected","attempts_exhausted"],media:["media_upload_failed","media_processing_failed","media_too_large","unsupported_media"],response:["output_truncated","empty_response","malformed_response"],pipeline:["serial_parse_failed","source_mismatch","pipeline_mismatch"],validation:["script_validation_failed"],cancelled:["cancelled"],unknown:["unknown","legacy_unclassified"]};function Lt(e,t){return typeof e=="string"&&t.some(n=>n===e)}function su(e,t){switch(e){case"policy":return Lt(t,Nt.policy)?{failure_type:e,failure_code:t}:null;case"network":return Lt(t,Nt.network)?{failure_type:e,failure_code:t}:null;case"timeout":return Lt(t,Nt.timeout)?{failure_type:e,failure_code:t}:null;case"rate_limit":return Lt(t,Nt.rate_limit)?{failure_type:e,failure_code:t}:null;case"authentication":return Lt(t,Nt.authentication)?{failure_type:e,failure_code:t}:null;case"authorization":return Lt(t,Nt.authorization)?{failure_type:e,failure_code:t}:null;case"provider":return Lt(t,Nt.provider)?{failure_type:e,failure_code:t}:null;case"media":return Lt(t,Nt.media)?{failure_type:e,failure_code:t}:null;case"response":return Lt(t,Nt.response)?{failure_type:e,failure_code:t}:null;case"pipeline":return Lt(t,Nt.pipeline)?{failure_type:e,failure_code:t}:null;case"validation":return Lt(t,Nt.validation)?{failure_type:e,failure_code:t}:null;case"cancelled":return Lt(t,Nt.cancelled)?{failure_type:e,failure_code:t}:null;case"unknown":return Lt(t,Nt.unknown)?{failure_type:e,failure_code:t}:null;default:return null}}function Ut(e,t){return{...e,...t}}function Ui(e){switch(e.failure_type){case"policy":return{failure_type:e.failure_type,failure_code:e.failure_code};case"network":return{failure_type:e.failure_type,failure_code:e.failure_code};case"timeout":return{failure_type:e.failure_type,failure_code:e.failure_code};case"rate_limit":return{failure_type:e.failure_type,failure_code:e.failure_code};case"authentication":return{failure_type:e.failure_type,failure_code:e.failure_code};case"authorization":return{failure_type:e.failure_type,failure_code:e.failure_code};case"provider":return{failure_type:e.failure_type,failure_code:e.failure_code};case"media":return{failure_type:e.failure_type,failure_code:e.failure_code};case"response":return{failure_type:e.failure_type,failure_code:e.failure_code};case"pipeline":return{failure_type:e.failure_type,failure_code:e.failure_code};case"validation":return{failure_type:e.failure_type,failure_code:e.failure_code};case"cancelled":return{failure_type:e.failure_type,failure_code:e.failure_code};case"unknown":return{failure_type:e.failure_type,failure_code:e.failure_code}}}function Ar(e){return{...e.provider!==void 0?{provider:e.provider}:{},...e.model!==void 0?{model:e.model}:{},...e.operation!==void 0?{operation:e.operation}:{},...e.http_status!==void 0?{http_status:e.http_status}:{},...e.system_code!==void 0?{system_code:e.system_code}:{},...e.provider_source!==void 0?{provider_source:e.provider_source}:{},...e.provider_reason!==void 0?{provider_reason:e.provider_reason}:{},...e.provider_reason_raw!==void 0?{provider_reason_raw:e.provider_reason_raw}:{},...e.finish_message!==void 0?{finish_message:e.finish_message}:{},...e.safety_ratings!==void 0?{safety_ratings:e.safety_ratings}:{},...e.details!==void 0?{details:e.details}:{}}}function au(e,t){if(e.length===0)return Ut({failure_type:"unknown",failure_code:"unknown"},{retryable:!1,message:t});let n=e[0],i=e.every(r=>r.failure_type===n.failure_type&&r.failure_code===n.failure_code)?Ui(n):{failure_type:"provider",failure_code:"attempts_exhausted"};return Ut(i,{retryable:e.some(r=>r.retryable),message:t})}function hn(e){let t=e.provider||e.model?`${e.provider??"provider"}/${e.model??"model"} `:"",n=e.provider_reason?` provider_reason=${e.provider_reason}`:"",o=e.system_code?` system_code=${e.system_code}`:"",i=e.http_status!==void 0?` http_status=${e.http_status}`:"",r=e.details?.length?` | ${e.details.join(" | ")}`:"";return`${t}${e.failure_type}/${e.failure_code}${n}${o}${i}: ${e.message}${r}`}import*as Su from"node:crypto";import*as Iu from"node:fs";import*as Au from"node:path";import*as gu from"node:crypto";var Tn=["action","dialogue","inner_thought","transition"],qt=new Set(Tn),Vn=["system","broadcast","offscreen","group"],Fo=new Set(Vn),$n=["featured","background"],Pt=new Set($n),Pi=["\u4E3B\u89D2","\u914D\u89D2"],uo=new Set(Pi),Us=["day","night","dawn","dusk"],vc=new Set(Us);function kr(e){return typeof e=="string"&&vc.has(e)}var Oc=["interior","exterior"],cu=new Set(Oc);function dt(e){return e.normalize("NFKC").toLowerCase()}function du(e){return JSON.stringify([e.code,e.path,e.message])}function Rc(e){let t=new Map;for(let n of e){let o=du(n);t.set(o,(t.get(o)??0)+1)}return t}function Mc(e,t){if(e.ok||t.errors.length>=e.errors.length)return!1;let n=Rc(e.errors),o=Rc(t.errors);for(let[i,r]of o)if(r>(n.get(i)??0))return!1;return!0}function Nc(e,t){let n=Rc(e),o=[];for(let i of t){let r=du(i),s=n.get(r)??0;s>0?n.set(r,s-1):o.push(i)}return o}import{customAlphabet as Cw}from"nanoid";var Ci="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",Lc=6,Ti={episode:"ep",scene:"scn",action:"ac",actor:"act",location:"loc",prop:"prp",state:"st"},Tw=Cw(Ci,Lc),Vw=`[${Ci}]`,pu=Object.fromEntries(Object.entries(Ti).map(([e,t])=>[e,new RegExp(`^${t}${Vw}{${Lc}}$`)]));function V(e,t){return typeof t=="string"&&pu[e].test(t)}var Uc="ID_SPACE_EXHAUSTED";function br(e,t=new Set,n=Tw){let o=Ti[e];for(let i=0;i<128;i++){let r=`${o}${n()}`;if(!t.has(r))return r}throw Object.assign(new Error(`Could not generate an unused ${e} ID after 128 attempts.`),{code:Uc})}var et=class extends Error{input;constructor(t,n){super(n),this.input=t,this.name="TimestampParseError"}},$w=/^(\d+):(\d{2})(?:\.(\d{1,3}))?$/,Dw=/^(\d+):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/;function lu(e){return e?Number(e.padEnd(3,"0")):0}function uu(e,t){if(!Number.isSafeInteger(t))throw new et(e,"Timestamp exceeds the supported numeric range.");return t}function fu(e,t){let n=Math.floor(e/1e3),o=Math.floor(n/3600),i=Math.floor(n%3600/60),r=n%60,s=t?`.${t}`:"";return o>0?`${o}:${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}${s}`:`${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}${s}`}function fo(e){let t=e.trim();if(!t)throw new et(e,"Timestamp must not be empty.");let n=t.match(Dw);if(n){let a=Number(n[1]),d=Number(n[2]),p=Number(n[3]),l=n[4];if(d>59)throw new et(e,"Hour-form timestamps require minutes between 00 and 59.");if(p>59)throw new et(e,"Timestamp seconds must be between 00 and 59.");let f=uu(e,((a*60+d)*60+p)*1e3+lu(l));return{canonical:fu(f,l),milliseconds:f,fractionDigits:l?.length??0}}let o=t.match($w);if(!o)throw new et(e,"Use M:SS, MM:SS, or H:MM:SS with an optional 1-3 digit fraction.");let i=Number(o[1]),r=Number(o[2]),s=o[3];if(r>59)throw new et(e,"Timestamp seconds must be between 00 and 59.");let c=uu(e,(i*60+r)*1e3+lu(s));return{canonical:fu(c,s),milliseconds:c,fractionDigits:s?.length??0}}function Gw(e){if(typeof e!="object"||e===null||Array.isArray(e))return;let t=e.extend;if(!(typeof t!="object"||t===null||Array.isArray(t)))return t.timestamp}function Ps(e,t,n){let o=null;e.forEach((i,r)=>{let s=Gw(i);if(s===void 0)return;let c=`${t}[${r}].extend.timestamp`;if(typeof s!="string"){n("timestamp_invalid",c,"timestamp must be a string in M:SS, MM:SS, or H:MM:SS form");return}let a;try{a=fo(s)}catch(d){if(!(d instanceof et))throw d;n("timestamp_invalid",c,d.message);return}o!==null&&a.milliseconds<o.timestamp.milliseconds&&n("timestamp_out_of_order",c,`timestamp ${a.canonical} is earlier than Action ${o.actionIndex+1} timestamp ${o.timestamp.canonical}; equal timestamps are allowed`),o={actionIndex:r,timestamp:a}})}var yt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Dn=e=>Array.isArray(e),Ie=e=>typeof e=="string",Bw=["state_changes","actor_id","speakers","lines"];function wt(e){let t=[],n=[],o=(u,m,h,g)=>t.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}}),i=(u,m,h)=>n.push({code:u,path:m,message:h});if(!yt(e))return{ok:!1,errors:[{code:"not_object",path:"$",message:"script must be an object"}],warnings:n};e.version!==3&&o("version","$.version","version must be 3");for(let u of["title","worldview","style"])Ie(e[u])||o("field",`$.${u}`,`${u} must be a string`);let r=new Map,s=new Map,c=new Map,a=(u,m,h,g,w)=>{if(!Dn(u)){o("field",w,`${w} must be an array`);return}u.forEach((y,_)=>{let S=`${w}[${_}]`;if(!yt(y)){o("asset",S,"asset must be an object");return}let E=y[h];if(!Ie(E)){o("asset_id",`${S}.${h}`,`${h} required`);return}if(s.has(E)&&o("dup_id",`${S}.${h}`,`duplicate id ${E}`),s.set(E,m),!Ie(y[g]))o("asset_name",`${S}.${g}`,`${g} required`);else if(m==="actor"){let M=dt(y[g]),I=c.get(M);I!==void 0?o("dup_actor_name",`${S}.${g}`,`actor name ${y[g]} already belongs to ${I}`):c.set(M,E)}(!Ie(y.importance)||!$n.includes(y.importance))&&o("importance",`${S}.importance`,`importance must be one of ${$n.join("|")}`),Ie(y.description)||o("asset_desc",`${S}.description`,"description must be a string");let A=new Set,b=new Set,U=0;!Dn(y.states)||y.states.length===0?o("states",`${S}.states`,"states must be a non-empty array"):y.states.forEach((M,I)=>{let O=`${S}.states[${I}]`;if(!yt(M)||!Ie(M.state_id)){o("state_id",O,"state_id required");return}A.has(M.state_id)&&o("dup_state",O,`duplicate state_id ${M.state_id}`),A.add(M.state_id),M.state_id==="default"&&U++,Ie(M.state_name)?(b.has(M.state_name)&&o("dup_state_name",`${O}.state_name`,`duplicate state_name ${M.state_name}`),b.add(M.state_name)):o("state_name",`${O}.state_name`,"state_name required")}),Dn(y.states)&&U!==1&&o("default_state",`${S}.states`,`exactly one 'default' state required, found ${U}`),r.set(E,A)})};a(e.actors,"actor","actor_id","actor_name","$.actors"),a(e.locations,"location","location_id","location_name","$.locations"),a(e.props,"prop","prop_id","prop_name","$.props");let d=(u,m,h,g)=>{if(s.get(u)!==h){o("ref",g,`${h} ${u} not found`);return}m!==void 0&&(!Ie(m)||!r.get(u)?.has(m))&&o("state_ref",g,`state ${String(m)} not materialized on ${u}`)},p=(u,m,h,g)=>{if(u===void 0){o("field",g,`${g} required (may be empty array)`);return}if(!Dn(u)){o("field",g,`${g} must be an array`);return}u.forEach((w,y)=>{if(!yt(w)||!Ie(w[h])){o("ref",`${g}[${y}]`,`${h} required`);return}d(w[h],w.state_id,m,`${g}[${y}]`)})},l=(u,m,h,g)=>{if(!yt(u)){o("action",m,"action must be an object");return}for(let y of Bw)y in u&&o("legacy_field",`${m}.${y}`,`v3 forbids action.${y}`);let w=u.type;if((!Ie(w)||!Tn.includes(w))&&o("action_type",`${m}.type`,`invalid action type ${String(w)}`),Ie(u.content)||o("content",`${m}.content`,"content must be a plain-text string"),w==="dialogue"||w==="inner_thought"){let y=u.speaker;if(!yt(y))o("speaker",`${m}.speaker`,"dialogue/inner_thought needs a speaker");else if("kind"in y)(!Ie(y.kind)||!Vn.includes(y.kind))&&o("speaker_kind",`${m}.speaker.kind`,"invalid non-actor speaker kind");else if(Ie(y.actor_id)){if(d(y.actor_id,y.state_id,"actor",`${m}.speaker`),!h.has(y.actor_id)){let _=r.get(y.actor_id),S=Ie(y.state_id)&&_?.has(y.state_id)?y.state_id:_?.has("default")?"default":_?.values().next().value,E=g&&S?`scriptctl scene-ref ${g} actor:${y.actor_id} --state ${S} -p "$SCRIPT"`:void 0;o("actor_not_in_scene",`${m}.speaker.actor_id`,`actor ${y.actor_id} is not referenced by this scene`,E)}}else o("speaker",`${m}.speaker`,"speaker needs actor_id or kind")}},f=e.episodes;return Dn(f)?f.forEach((u,m)=>{let h=`$.episodes[${m}]`;if(!yt(u)||!Ie(u.episode_id)){o("episode_id",h,"episode_id required");return}if(!Dn(u.scenes)){o("scenes",`${h}.scenes`,"scenes must be an array");return}u.scenes.forEach((g,w)=>{let y=`${h}.scenes[${w}]`;if(!yt(g)){o("scene",y,"scene must be an object");return}"context"in g&&o("legacy_field",`${y}.context`,"v3 forbids scene.context"),Ie(g.scene_id)||o("scene_id",y,"scene_id required");let _=g.environment;_===void 0||yt(_)&&(!Ie(_.time)||_.time.trim()==="")?i("scene_time_missing",`${y}.environment.time`,"scene time is required for production review"):!yt(_)||_.space!==void 0&&!Ie(_.space)||!Ie(_.time)?o("environment",`${y}.environment`,"environment must contain optional string space and a time string"):kr(_.time)||o("scene_time",`${y}.environment.time`,"scene time must be day|night|dawn|dusk"),(g.environment===void 0||yt(g.environment)&&(!Ie(g.environment.space)||g.environment.space.trim()===""))&&i("scene_space_missing",`${y}.environment.space`,"scene interior/exterior is required for production review"),g.location===null&&i("scene_location_missing",`${y}.location`,"scene location is required for production review");let S=g.location;if(S!==null&&(!yt(S)||!Ie(S.location_id)?o("location",`${y}.location`,"location must be null or {location_id}"):d(S.location_id,S.state_id,"location",`${y}.location`)),p(g.actors,"actor","actor_id",`${y}.actors`),p(g.props,"prop","prop_id",`${y}.props`),Dn(g.props)){let A=new Set;g.props.forEach((b,U)=>{!yt(b)||!Ie(b.prop_id)||(A.has(b.prop_id)&&o("dup_prop_ref",`${y}.props[${U}]`,`duplicate prop ref ${b.prop_id}`),A.add(b.prop_id))})}let E=new Set(Dn(g.actors)?g.actors.filter(A=>yt(A)).map(A=>A.actor_id).filter(A=>Ie(A)):[]);if(!Dn(g.actions))o("actions",`${y}.actions`,"actions must be an array");else{let A=Ie(g.scene_id)?`${u.episode_id}/${g.scene_id}`:void 0;g.actions.forEach((b,U)=>l(b,`${y}.actions[${U}]`,E,A)),Ps(g.actions,`${y}.actions`,o)}})}):o("episodes","$.episodes","episodes must be an array"),{ok:t.length===0,errors:t,warnings:n}}var tt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),de=e=>typeof e=="string",yn=e=>Array.isArray(e);function Pc(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?!0:Array.isArray(e)?e.every(Pc):tt(e)&&Object.values(e).every(Pc)}function Vi(e,t,n){e!==void 0&&(!tt(e)||!Object.values(e).every(Pc))&&n("extend",t,"extend must be an object containing JSON values")}function Jw(e){for(let t=1;t<e.length;t++)if(e[t-1]>e[t])return!1;return!0}function Pe(e){let t=[],n=[],o=(u,m,h,g)=>t.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}}),i=(u,m,h,g)=>n.push({code:u,path:m,message:h,...g?{repair_hint:g}:{}});if(!tt(e))return{ok:!1,errors:[{code:"not_object",path:"$",message:"script must be an object"}],warnings:n};e.version!==4&&o("version","$.version","version must be 4");for(let u of["title","worldview","style"])de(e[u])||o("field",`$.${u}`,`${u} must be a string`);for(let u of["worldview_raw","synopsis","logline","theme"])e[u]!==void 0&&!de(e[u])&&o("field",`$.${u}`,`${u} must be a string`);e.main_characters!==void 0&&(!yn(e.main_characters)||!e.main_characters.every(u=>tt(u)&&de(u.name)&&de(u.role)))&&o("main_characters","$.main_characters","main_characters must contain {name, role} string records"),Vi(e.extend,"$.extend",o);let r=new Map,s=new Map,c=new Set,a=(u,m,h,g,w)=>{if(!yn(u)){o("field",w,`${w} must be an array`);return}let y=new Set;u.forEach((_,S)=>{let E=`${w}[${S}]`;if(!tt(_)){o("asset",E,"asset must be an object");return}let A=_[h];if(!V(m,A)){o("asset_id",`${E}.${h}`,`${h} must be ${m} ID`);return}if(y.has(A)&&o("dup_id",`${E}.${h}`,`duplicate ${h} ${A}`),y.add(A),r.set(A,m),!de(_[g])||_[g].trim()==="")o("asset_name",`${E}.${g}`,`${g} must be a non-empty string`);else if(m==="actor"){let I=_[g].trim().toLocaleLowerCase();c.has(I)&&o("dup_actor_name",`${E}.${g}`,`duplicate actor name ${_[g]}`),c.add(I)}if((!de(_.importance)||!$n.includes(_.importance))&&o("importance",`${E}.importance`,`importance must be ${$n.join("|")}`),m==="actor"&&_.role_type!==void 0&&(!de(_.role_type)||!Pi.includes(_.role_type))&&o("role_type",`${E}.role_type`,`role_type must be ${Pi.join("|")}`),de(_.description)||o("asset_desc",`${E}.description`,"description must be a string"),_.aliases!==void 0&&(!yn(_.aliases)||!_.aliases.every(de)))o("aliases",`${E}.aliases`,"aliases must be an array of strings");else if(yn(_.aliases)&&_.aliases.every(de)){let I=new Set,O=de(_[g])?_[g]:"";_.aliases.forEach((L,C)=>{L===""&&o("alias_empty",`${E}.aliases[${C}]`,"alias must not be empty"),L===O&&o("alias_equals_name",`${E}.aliases[${C}]`,"alias must differ from the asset name"),I.has(L)&&o("dup_alias",`${E}.aliases[${C}]`,`duplicate alias ${L}`),I.add(L)})}Vi(_.extend,`${E}.extend`,o);let b=new Set,U=new Set,M=0;!yn(_.states)||_.states.length===0?o("states",`${E}.states`,"states must be a non-empty array"):_.states.forEach((I,O)=>{let L=`${E}.states[${O}]`;if(!tt(I)){o("state",L,"state must be an object");return}let C=I.state_id;if(C!=="default"&&!V("state",C)){o("state_id",`${L}.state_id`,"state_id must be default or st plus six Base58 characters");return}b.has(C)&&o("dup_state",`${L}.state_id`,`duplicate state_id ${C}`),b.add(C),C==="default"&&M++,!de(I.state_name)||I.state_name.trim()===""?o("state_name",`${L}.state_name`,"state_name must be a non-empty string"):(U.has(I.state_name)&&o("dup_state_name",`${L}.state_name`,`duplicate state_name ${I.state_name}`),U.add(I.state_name)),de(I.description)||o("state_description",`${L}.description`,"description must be a string"),Vi(I.extend,`${L}.extend`,o)}),M!==1&&o("default_state",`${E}.states`,`exactly one default state required, found ${M}`),s.set(A,b)})};a(e.actors,"actor","actor_id","actor_name","$.actors"),a(e.locations,"location","location_id","location_name","$.locations"),a(e.props,"prop","prop_id","prop_name","$.props");let d=(u,m,h)=>{if(!yn(m)||m.length===0||!m.every(de))return o("state_ids",h,"state_ids must be a non-empty array of strings"),[];let g=m,w=new Set;return g.forEach((y,_)=>{w.has(y)&&o("dup_state_ref",`${h}[${_}]`,`duplicate state_id ${y}`),w.add(y),s.get(u)?.has(y)||o("state_ref",`${h}[${_}]`,`state ${y} not found on ${u}`)}),Jw(g)||o("state_ids_order",h,"state_ids must be sorted lexically"),g},p=new Set,l=new Set,f=new Set;return yn(e.episodes)?e.episodes.forEach((u,m)=>{let h=`$.episodes[${m}]`;if(!tt(u)){o("episode",h,"episode must be an object");return}V("episode",u.episode_id)?(p.has(u.episode_id)&&o("dup_episode_id",`${h}.episode_id`,`duplicate episode_id ${u.episode_id}`),p.add(u.episode_id)):o("episode_id",`${h}.episode_id`,"episode_id must be ep plus six Base58 characters");for(let g of["title","synopsis"])u[g]!==void 0&&!de(u[g])&&o("field",`${h}.${g}`,`${g} must be a string`);if(Vi(u.extend,`${h}.extend`,o),!yn(u.scenes)){o("scenes",`${h}.scenes`,"scenes must be an array");return}u.scenes.forEach((g,w)=>{let y=`${h}.scenes[${w}]`;if(!tt(g)){o("scene",y,"scene must be an object");return}V("scene",g.scene_id)?(l.has(g.scene_id)&&o("dup_scene_id",`${y}.scene_id`,`duplicate scene_id ${g.scene_id}`),l.add(g.scene_id)):o("scene_id",`${y}.scene_id`,"scene_id must be scn plus six Base58 characters"),Vi(g.extend,`${y}.extend`,o),g.environment===void 0||tt(g.environment)&&(!de(g.environment.time)||g.environment.time.trim()==="")?i("scene_time_missing",`${y}.environment.time`,"scene time is required for production review"):!tt(g.environment)||g.environment.space!==void 0&&!de(g.environment.space)||!de(g.environment.time)?o("environment",`${y}.environment`,"environment must contain optional string space and a time string"):kr(g.environment.time)||o("scene_time",`${y}.environment.time`,"scene time must be day|night|dawn|dusk"),(g.environment===void 0||tt(g.environment)&&(!de(g.environment.space)||g.environment.space.trim()===""))&&i("scene_space_missing",`${y}.environment.space`,"scene interior/exterior is required for production review"),g.location===null&&i("scene_location_missing",`${y}.location`,"scene location is required for production review"),g.location!==null&&(!tt(g.location)||!V("location",g.location.location_id)?o("location",`${y}.location`,"location must be null or a typed v4 location reference"):("state_id"in g.location&&o("v3_field",`${y}.location.state_id`,"Script v4 scene references use state_ids"),r.get(g.location.location_id)!=="location"&&o("location_ref",`${y}.location.location_id`,`location ${g.location.location_id} not found`),d(g.location.location_id,g.location.state_ids,`${y}.location.state_ids`)));let _=new Map,S=(E,A,b,U)=>{if(!yn(E)){o("field",U,`${U} must be an array`);return}let M=new Set;E.forEach((I,O)=>{let L=`${U}[${O}]`;if(!tt(I)||!V(A,I[b])){o("ref",L,`${b} must be a typed v4 ID`);return}let C=I[b];"state_id"in I&&o("v3_field",`${L}.state_id`,"Script v4 scene references use state_ids"),M.has(C)&&o("dup_asset_ref",`${L}.${b}`,`duplicate ${A} ref ${C}`),M.add(C),r.get(C)!==A&&o("asset_ref",`${L}.${b}`,`${A} ${C} not found`);let R=d(C,I.state_ids,`${L}.state_ids`);A==="actor"&&_.set(C,new Set(R))})};if(S(g.actors,"actor","actor_id",`${y}.actors`),S(g.props,"prop","prop_id",`${y}.props`),!yn(g.actions)){o("actions",`${y}.actions`,"actions must be an array");return}g.actions.forEach((E,A)=>{let b=`${y}.actions[${A}]`;if(!tt(E)){o("action",b,"action must be an object");return}if(V("action",E.action_id)?(f.has(E.action_id)&&o("dup_action_id",`${b}.action_id`,`duplicate action_id ${E.action_id}`),f.add(E.action_id)):o("action_id",`${b}.action_id`,"action_id must be ac plus six Base58 characters"),(!de(E.type)||!Tn.includes(E.type))&&o("action_type",`${b}.type`,`invalid action type ${String(E.type)}`),de(E.content)||o("content",`${b}.content`,"content must be a string"),"emotion"in E&&o("v3_field",`${b}.emotion`,"Script v4 does not allow emotion"),Vi(E.extend,`${b}.extend`,o),E.type==="dialogue"||E.type==="inner_thought")if(E.parenthetical!==void 0&&!de(E.parenthetical)&&o("parenthetical",`${b}.parenthetical`,"parenthetical must be a string"),!tt(E.speaker))o("speaker",`${b}.speaker`,"dialogue/inner_thought requires a speaker");else if(de(E.speaker.actor_id)){("kind"in E.speaker||"label"in E.speaker)&&o("speaker_shape",`${b}.speaker`,"actor speaker cannot contain non-actor speaker fields");let M=E.speaker.actor_id;(!V("actor",M)||r.get(M)!=="actor")&&o("speaker_actor",`${b}.speaker.actor_id`,`actor ${M} not found`);let I=_.get(M),O=s.get(M),L=de(E.speaker.state_id)&&O?.has(E.speaker.state_id)?E.speaker.state_id:void 0,C=O?.has("default")?"default":O?.values().next().value,R=L?[L]:C?[C]:[],J=V("scene",g.scene_id)&&V("actor",M)&&R.length>0?`scriptctl scene-ref ${g.scene_id} ${M} ${R.map(W=>`--state ${W}`).join(" ")} -p "$SCRIPT"`:void 0;if(I||o("actor_not_in_scene",`${b}.speaker.actor_id`,`actor ${M} is not referenced by this scene`,J),E.speaker.state_id!==void 0&&(!de(E.speaker.state_id)||!I?.has(E.speaker.state_id))){let W=L?[...new Set([...I??[],L])].sort():[],Re=V("scene",g.scene_id)&&V("actor",M)&&W.length>0?`scriptctl scene-ref ${g.scene_id} ${M} ${W.map(ie=>`--state ${ie}`).join(" ")} -p "$SCRIPT"`:J;o("speaker_state",`${b}.speaker.state_id`,`speaker state ${String(E.speaker.state_id)} is not in this scene's actor state_ids`,Re)}}else de(E.speaker.kind)?(("actor_id"in E.speaker||"state_id"in E.speaker)&&o("speaker_shape",`${b}.speaker`,"non-actor speaker cannot contain actor speaker fields"),Vn.includes(E.speaker.kind)||o("speaker_kind",`${b}.speaker.kind`,"invalid non-actor speaker kind"),E.speaker.label!==void 0&&!de(E.speaker.label)&&o("speaker_label",`${b}.speaker.label`,"speaker label must be a string")):o("speaker",`${b}.speaker`,"speaker needs actor_id or kind");else"parenthetical"in E&&o("parenthetical_type",`${b}.parenthetical`,"parenthetical only belongs to speaking actions"),"speaker"in E&&o("speaker_type",`${b}.speaker`,"speaker only belongs to speaking actions");if(E.transition_prompt!==void 0){let M=E.transition_prompt;!tt(M)||!de(M.target)||!de(M.process)||M.process===""||!de(M.contrast)||M.contrast===""?o("transition_prompt",`${b}.transition_prompt`,"transition_prompt requires non-empty target/process/contrast"):r.has(M.target)||o("transition_target",`${b}.transition_prompt.target`,`asset ${M.target} not found`)}}),Ps(g.actions,`${y}.actions`,o)})}):o("episodes","$.episodes","episodes must be an array"),{ok:t.length===0,errors:t,warnings:n}}function Qo(e,t=new Set,n){try{return n?br(e,t,n):br(e,t)}catch(o){throw o?.code!==Uc?o:new x(`Could not generate an unused ${e} ID.`,{exitCode:k,errorCode:"ID_SPACE_RETRY_EXHAUSTED",hint:"Retry the command. If this persists, inspect the configured ID generator."})}}function Ae(e,t=[]){throw new x(e,{exitCode:k,errorCode:"CREATIVE_DRAFT_INVALID",hint:"Use the readable creative draft schema; do not include Script IDs or .scriptctl syntax.",data:{actual:t.map(String)}})}function Gn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function q(e,t=""){return String(e??"").replace(/\s+/gu," ").trim()||t}function jw(e,t){let n=Number(e);return(!Number.isSafeInteger(n)||n<1)&&Ae(`${t} must be a positive integer.`,[e]),n}function Kw(e){return e===void 0?{}:(Gn(e)||Ae("Action extensions must be an object."),structuredClone(e))}function zw(e){let t=new Set;for(let n of e.actors){t.add(n.actor_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.locations){t.add(n.location_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.props){t.add(n.prop_id);for(let o of n.states)t.add(o.state_id)}for(let n of e.episodes){t.add(n.episode_id);for(let o of n.scenes){t.add(o.scene_id);for(let i of o.actions)t.add(i.action_id)}}return t}function mo(e,t,n){for(let o=0;o<128;o+=1){let i=gu.createHash("sha256").update(`${e}:${t}:${o}`).digest(),r="";for(let c=0;c<6;c+=1)r+=Ci[i[c]%Ci.length];let s=`${Ti[e]}${r}`;if(!n.has(s))return n.add(s),s}Ae(`Could not allocate a stable ${e} ID.`)}function Hw(e){let t=q(e).match(/^(\d+):([0-5]\d)(?:\.(\d{1,3}))?$/u);return t?(Number(t[1])*60+Number(t[2]))*1e3+Number((t[3]??"").padEnd(3,"0")):null}function Fw(e){return`${Math.floor(e/6e4)}:${String(Math.floor(e%6e4/1e3)).padStart(2,"0")}.${String(e%1e3).padStart(3,"0")}`}function Qw(e){let t=Number(e.extend?.duration_ms??e.extend?.rewrite_duration_ms);return Number.isFinite(t)&&t>0?Math.round(t):1200}function Yw(e){let t=0;for(let n of e.scenes.flatMap(o=>o.actions))t=(Hw(n.extend?.timestamp)??t)+Qw(n);return t}function hu(e){return e===void 0?[]:((!Array.isArray(e)||!e.every(Gn))&&Ae("Asset variants must be an array of readable objects."),e)}function qw(e,t){let n=e.assets;if(n===void 0)return[];Gn(n)||Ae("assets must be an object.");let o=n[t];return o===void 0?[]:((!Array.isArray(o)||!o.every(Gn))&&Ae(`assets.${t} must be an array.`),o)}function Zw(e,t){return e==="actors"?t.actor_name:e==="locations"?t.location_name:t.prop_name}function Ww(e,t){return e[t]}function Xw(e,t){return[Zw(e,t),...t.aliases??[]].map(dt)}function yu(e,t,n){let o=dt(n);return qw(e,t).find(i=>[i.name,...Array.isArray(i.aliases)?i.aliases:[]].map(r=>dt(q(r))).includes(o))??null}function wu(e,t){if(!e)return null;let n=dt(t);return hu(e.variants).find(o=>{let i=dt(q(o.name));return i===n||["default","\u9ED8\u8BA4"].includes(n)&&["default","\u9ED8\u8BA4"].includes(i)})??null}function _u(e,t,n){let o=wu(e,n),i=q(o?.description);return(!o||!i)&&Ae(`${t}/${n} is a new variant and requires a readable assets declaration with a self-contained description.`),o}function e_(e,t){let n=q(t?.name);return n&&!["default","\u9ED8\u8BA4"].includes(dt(n))?n:e==="actors"?"\u57FA\u7840\u9020\u578B":e==="locations"?"\u5E38\u89C4\u5E03\u7F6E":"\u57FA\u7840\u5916\u89C2"}function t_(e,t,n,o,i,r){let s=yu(t,n,o);s||Ae(`${o} is not an existing ${n} asset and has no readable declaration.`);let c=q(s.name,o),a=hu(s.variants),d=wu(s,"\u9ED8\u8BA4")??a[0]??null;n==="actors"&&!q(s.description)&&Ae(`${c} requires an identity description separate from its appearance variants.`),n==="actors"&&!q(d?.description)&&Ae(`${c} requires its first variant to provide a self-contained base appearance description.`);let p=[{state_id:"default",state_name:e_(n,d),description:q(d?.description,q(s.description,`${c}\u7684\u57FA\u7840\u53C2\u8003\u5916\u89C2\u3002`))}];for(let u of a){let m=q(u.name);if(u===d||!m||["default","\u9ED8\u8BA4"].includes(dt(m)))continue;let h=mo("state",`${n}:${c}:${m}`,i);p.push({state_id:h,state_name:m,description:q(_u(s,c,m).description)}),r.states.push(`${c}/${m}`)}let l={aliases:Array.isArray(s.aliases)?[...new Set(s.aliases.map(u=>q(u)).filter(u=>u&&u!==c))]:[],importance:s.importance==="background"?"background":"featured",description:q(s.description,`${c}\u7684\u57FA\u7840\u8BBE\u5B9A\u3002`),states:p};if(n==="actors"){let u={...l,actor_id:mo("actor",c,i),actor_name:c,...s.roleType==="\u4E3B\u89D2"||s.roleType==="\u914D\u89D2"?{role_type:s.roleType}:{}};return e.actors.push(u),r.actors.push(c),u}if(n==="locations"){let u={...l,location_id:mo("location",c,i),location_name:c};return e.locations.push(u),r.locations.push(c),u}let f={...l,prop_id:mo("prop",c,i),prop_name:c};return e.props.push(f),r.props.push(c),f}function Ts(e,t,n,o,i,r){let s=q(o);s||Ae(`${n} reference requires a readable name.`);let c=dt(s);return Ww(e,n).find(d=>Xw(n,d).includes(c))??t_(e,t,n,s,i,r)}function vr(e,t,n,o,i,r){let s=q(t,"\u9ED8\u8BA4"),c=dt(s),a=e.states.find(u=>dt(u.state_name)===c||u.state_id==="default"&&["default","\u9ED8\u8BA4"].includes(c));if(a)return a.state_id;let d="actor_name"in e?e.actor_name:"location_name"in e?e.location_name:e.prop_name,p=yu(n,o,d),l=_u(p,d,s),f={state_id:mo("state",`${d}:${s}`,i),state_name:s,description:q(l.description)};return e.states.push(f),r.states.push(`${d}/${s}`),f.state_id}function mu(e,t){return e===void 0?[]:((!Array.isArray(e)||!e.every(Gn))&&Ae(`${t} must be an array of readable references.`),e)}function Cs(e,t,n){let o=structuredClone(e);for(let i of t){let r=o.find(s=>n(s)===n(i));r?r.state_ids=[...new Set([...r.state_ids,...i.state_ids])].sort():o.push(structuredClone(i))}return o}function n_(e,t){return!!(e&&e.location?.location_id&&t.location?.location_id&&e.location.location_id===t.location.location_id&&q(e.environment?.space)===q(t.environment?.space)&&q(e.environment?.time)===q(t.environment?.time))}function o_(e,t,n,o,i,r,s,c){(!Array.isArray(e)||e.length===0||!e.every(Gn))&&Ae("scene.actions must contain at least one readable Action.");let a=structuredClone(o),d=r;return{actions:e.map((l,f)=>{let u=q(l.type,"action");["action","transition","dialogue","inner_thought"].includes(u)||Ae(`Action ${f+1} has an unsupported type.`,[u]);let m=q(l.content);m||Ae(`Action ${f+1} has empty content.`);let h=Math.max(400,Math.min(8e3,Math.round(Number(l.durationMs)||Number(l.weight||1)*1200))),g=Kw(l.extensions);g.timestamp=Fw(d),g.duration_ms=h,g.rewrite_duration_ms!==void 0&&(g.rewrite_duration_ms=h);let w={action_id:mo("action",`${i}:${f+1}:${m}`,s),type:u,content:m,extend:g};if(d+=h,u==="action"||u==="transition")return w;let y=q(l.speaker);y||Ae(`Action ${f+1} requires a speaker.`);let _=y.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&");new RegExp(`^${_}\\s*[:\uFF1A]`,"iu").test(m)&&Ae(`Action ${f+1} repeats the speaker name in dialogue content.`),/^(?:“[^”]+”|「[^」]+」|『[^』]+』|"[^"]+")$/u.test(m)&&Ae(`Action ${f+1} wraps dialogue content in quotation marks.`);let S=dt(y);if(["\u65C1\u767D","narrator"].includes(S))return{...w,speaker:{kind:"broadcast",label:"\u65C1\u767D"},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}};if(["\u753B\u5916\u97F3","offscreen"].includes(S))return{...w,speaker:{kind:"offscreen",label:"\u753B\u5916\u97F3"},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}};let E=Ts(t,n,"actors",y,s,c),A=q(l.speakerVariant),b=a.find(M=>M.actor_id===E.actor_id),U;if(A)U=vr(E,A,n,"actors",s,c),b?b.state_ids=[...new Set([...b.state_ids,U])].sort():a.push({actor_id:E.actor_id,state_ids:[U]});else if(!b){let M=vr(E,"\u9ED8\u8BA4",n,"actors",s,c);a.push({actor_id:E.actor_id,state_ids:[M]})}return{...w,speaker:{actor_id:E.actor_id,...U?{state_id:U}:{}},...q(l.parenthetical)?{parenthetical:q(l.parenthetical)}:{}}}),actorRefs:a}}function Eu(e,t){(!Gn(t)||t.version!==1)&&Ae("Creative draft version must be 1."),(!Gn(t.episode)||!Gn(t.scene))&&Ae("Creative draft requires episode and scene objects.");let n=structuredClone(t),o=n.episode,i=n.scene,r=structuredClone(e),s=zw(r),c={actors:[],locations:[],props:[],states:[]},a=jw(o.number,"episode.number");a>r.episodes.length+1&&Ae("Episodes must be composed in order.",[a]);let d=r.episodes[a-1];d?(q(d.title)||(d.title=q(o.title,`\u7B2C ${a} \u96C6`)),q(d.synopsis)||(d.synopsis=q(o.synopsis,`\u7B2C ${a} \u96C6\u5267\u60C5\u3002`))):(d={episode_id:mo("episode",`episode:${a}`,s),title:q(o.title,`\u7B2C ${a} \u96C6`),synopsis:q(o.synopsis,`\u7B2C ${a} \u96C6\u5267\u60C5\u3002`),scenes:[]},r.episodes.push(d));let p=Ts(r,n,"locations",i.location,s,c),l=vr(p,i.locationVariant,n,"locations",s,c),f=mu(i.actors,"scene.actors").map(I=>{let O=Ts(r,n,"actors",I.name,s,c);return{actor_id:O.actor_id,state_ids:[vr(O,I.variant,n,"actors",s,c)]}}),u=Cs([],f,I=>I.actor_id),m=mu(i.props,"scene.props").map(I=>{let O=Ts(r,n,"props",I.name,s,c);return{prop_id:O.prop_id,state_ids:[vr(O,I.variant,n,"props",s,c)]}}),h=Cs([],m,I=>I.prop_id),g=d.scenes.at(-1),w={scene_id:mo("scene",`episode:${a}:scene:${d.scenes.length+1}:${q(i.title)}`,s),environment:{space:q(i.space,"interior"),time:q(i.time,"day")},location:{location_id:p.location_id,state_ids:[l]},actors:u,props:h,actions:[],extend:{scene_title:q(i.title,`\u7B2C ${d.scenes.length+1} \u573A`)}},y=q(i.boundary,"auto");["auto","new","continue"].includes(y)||Ae("scene.boundary must be auto, new, or continue.");let _=n_(g,w);y==="continue"&&!_&&Ae("scene.boundary=continue requires the same location, space, and time as the previous scene.");let S=y!=="new"&&_,E=S&&g?g:w,A=S?d.scenes.length:d.scenes.length+1,b=Cs(E.actors,w.actors,I=>I.actor_id),U=o_(i.actions,r,n,b,E.scene_id,Yw(d),s,c);E.actors=U.actorRefs,E.props=Cs(E.props,w.props,I=>I.prop_id),E.location&&w.location&&(E.location.state_ids=[...new Set([...E.location.state_ids,...w.location.state_ids])].sort()),E.actions.push(...U.actions),S||d.scenes.push(E);let M=Pe(r);return M.ok||Ae("Composed screenplay does not pass Script v4 validation.",M.errors.slice(0,12).map(I=>`${I.path}: ${I.message}`)),{script:r,validation:M,episodeNumber:a,sceneNumber:A,sceneId:E.scene_id,actionIds:U.actions.map(I=>I.action_id),joinedPreviousScene:S,created:c}}function He(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function wn(e,t){return e[t]===void 0||typeof e[t]=="string"}function Cc(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?!0:Array.isArray(e)?e.every(Cc):He(e)&&Object.values(e).every(Cc)}function $i(e){return e.extend===void 0||He(e.extend)&&Object.values(e.extend).every(Cc)}function Tc(e){return e==="default"||V("state",e)}function i_(e){return He(e)&&Tc(e.state_id)&&typeof e.state_name=="string"&&typeof e.description=="string"&&$i(e)}function Vc(e){return typeof e.importance=="string"&&Pt.has(e.importance)&&typeof e.description=="string"&&(e.aliases===void 0||Array.isArray(e.aliases)&&e.aliases.every(t=>typeof t=="string"))&&Array.isArray(e.states)&&e.states.every(i_)&&$i(e)}function r_(e){return He(e)&&V("actor",e.actor_id)&&typeof e.actor_name=="string"&&(e.role_type===void 0||typeof e.role_type=="string"&&uo.has(e.role_type))&&Vc(e)}function s_(e){return He(e)&&V("location",e.location_id)&&typeof e.location_name=="string"&&Vc(e)}function a_(e){return He(e)&&V("prop",e.prop_id)&&typeof e.prop_name=="string"&&Vc(e)}function $c(e){return Array.isArray(e)&&e.every(Tc)}function c_(e){return He(e)&&V("actor",e.actor_id)&&$c(e.state_ids)}function d_(e){return He(e)&&V("location",e.location_id)&&$c(e.state_ids)}function p_(e){return He(e)&&V("prop",e.prop_id)&&$c(e.state_ids)}function l_(e){return V("actor",e.actor_id)&&(e.state_id===void 0||Tc(e.state_id))}function u_(e){return typeof e.kind=="string"&&Fo.has(e.kind)&&wn(e,"label")}function f_(e){return!(!He(e)||!V("action",e.action_id)||typeof e.type!="string"||!qt.has(e.type)||typeof e.content!="string"||!wn(e,"parenthetical")||!$i(e)||(e.type==="dialogue"||e.type==="inner_thought")&&(!He(e.speaker)||!l_(e.speaker)&&!u_(e.speaker))||e.transition_prompt!==void 0&&(!He(e.transition_prompt)||!V("actor",e.transition_prompt.target)&&!V("location",e.transition_prompt.target)&&!V("prop",e.transition_prompt.target)||typeof e.transition_prompt.process!="string"||typeof e.transition_prompt.contrast!="string"))}function m_(e){return!(!He(e)||!V("scene",e.scene_id)||!Array.isArray(e.actors)||!e.actors.every(c_)||!Array.isArray(e.props)||!e.props.every(p_)||!Array.isArray(e.actions)||!e.actions.every(f_)||!$i(e)||e.location!==null&&!d_(e.location)||e.environment!==void 0&&(!He(e.environment)||!wn(e.environment,"space")||!wn(e.environment,"time")))}function g_(e){return He(e)&&V("episode",e.episode_id)&&wn(e,"title")&&wn(e,"synopsis")&&Array.isArray(e.scenes)&&e.scenes.every(m_)&&$i(e)}function h_(e){return He(e)&&e.version===4&&typeof e.title=="string"&&typeof e.worldview=="string"&&typeof e.style=="string"&&wn(e,"worldview_raw")&&wn(e,"synopsis")&&wn(e,"logline")&&wn(e,"theme")&&(e.main_characters===void 0||Array.isArray(e.main_characters)&&e.main_characters.every(t=>He(t)&&typeof t.name=="string"&&typeof t.role=="string"))&&Array.isArray(e.actors)&&e.actors.every(r_)&&Array.isArray(e.locations)&&e.locations.every(s_)&&Array.isArray(e.props)&&e.props.every(a_)&&Array.isArray(e.episodes)&&e.episodes.every(g_)&&$i(e)}function Di(e){let t=Pe(e);if(t.ok)return e;throw new x("The local file is not a valid Script v4 document.",{exitCode:k,errorCode:"SCRIPT_V4_INVALID",hint:"Run `scriptctl validate --script-path <path>` and repair the reported v4 fields.",data:{expected:["A valid Script v4 document"],actual:t.errors.slice(0,20).map(n=>`${n.path}: ${n.message}`)}})}function _n(e){if(h_(e))return e;throw new x("The local file is not a structurally readable Script v4 document.",{exitCode:k,errorCode:"SCRIPT_V4_SHAPE_INVALID",hint:"Repair the local Script v4 structure, then rerun the command.",data:{expected:["Script v4 with typed assets, episodes, scenes, references, and actions"],actual:[Array.isArray(e)?"array":typeof e]}})}import*as Or from"node:crypto";import*as $e from"node:fs";import*as Ct from"node:path";import y_ from"proper-lockfile";function Gc(e){if(Array.isArray(e))return e.map(Gc);if(e!==null&&typeof e=="object"){let t=e,n={};for(let o of Object.keys(t).sort())n[o]=Gc(t[o]);return n}return e}function Je(e){let t=JSON.stringify(Gc(e));return`sha256:${Or.createHash("sha256").update(t).digest("hex")}`}function Rr(e){return $e.existsSync(e)?`sha256:${Or.createHash("sha256").update($e.readFileSync(e)).digest("hex")}`:null}function Mr(e,t){let n=Rr(e);if(n!==t)throw new x("The local script changed while the command was running.",{exitCode:k,errorCode:"LOCAL_SCRIPT_CHANGED",hint:"Read the latest local script and retry the command.",data:{actual:[`loadedFingerprint=${t??"<missing>"}`,`currentFingerprint=${n??"<missing>"}`,e]}})}function Nr(e){let t=Ct.resolve(e),n=Ct.join(Ct.dirname(t),".scriptctl"),o=Ct.basename(t);return{scriptPath:t,stateDir:n,metadataPath:Ct.join(n,`${o}.working-copy.json`),lockPath:Ct.join(n,o)}}async function Vs(e,t){let n=Nr(e);$e.mkdirSync(n.stateDir,{recursive:!0});let o=null;try{o=await y_.lock(n.lockPath,{realpath:!1,stale:12e4,update:1e4,retries:{retries:260,factor:1,minTimeout:500,maxTimeout:500}})}catch(i){throw new x("Timed out waiting for the script file lock.",{exitCode:X,errorCode:"WORKING_COPY_LOCK_TIMEOUT",hint:"Wait for the other scriptctl command to finish, then retry.",data:{actual:[n.scriptPath,i instanceof Error?i.message:String(i)]}})}try{return await t()}finally{await o()}}function Fe(e,t){$s(e,`${JSON.stringify(t,null,2)}
123
123
  `)}function $s(e,t){let n=Ct.dirname(e);$e.mkdirSync(n,{recursive:!0});let o=Ct.join(n,`.${Ct.basename(e)}.${process.pid}.${Or.randomUUID()}.tmp`),i=$e.openSync(o,"wx");try{$e.writeFileSync(i,t,"utf-8"),$e.fsyncSync(i)}finally{$e.closeSync(i)}$e.renameSync(o,e)}function Ds(e){let t=Nr(e).metadataPath;if(!$e.existsSync(t))return null;let n;try{n=JSON.parse($e.readFileSync(t,"utf-8"))}catch(i){throw Dc(t,i instanceof Error?i.message:String(i))}if(n===null||typeof n!="object"||Array.isArray(n))throw Dc(t,"metadata root must be an object");let o=n;if(o.schemaVersion!==1||typeof o.projectGroupNo!="string"||o.projectGroupNo.length===0||typeof o.apiBaseUrl!="string"||o.apiBaseUrl.length===0||!Number.isInteger(o.baseRevision)||Number(o.baseRevision)<0||typeof o.baseContentHash!="string"||!o.baseContentHash.startsWith("sha256:"))throw Dc(t,"required fields are missing or invalid");return{schemaVersion:1,projectGroupNo:o.projectGroupNo,apiBaseUrl:o.apiBaseUrl,baseRevision:Number(o.baseRevision),baseContentHash:o.baseContentHash}}function Gs(e,t){Fe(Nr(e).metadataPath,t)}function Dc(e,t){return new x("Working copy metadata is invalid.",{exitCode:k,errorCode:"WORKING_COPY_METADATA_INVALID",hint:"Run `scriptctl checkout --discard-local` to recreate the working copy metadata.",data:{expected:["valid scriptctl working-copy metadata"],actual:[e,t]}})}function Gt(e,t){let n;try{n=JSON.parse($e.readFileSync(e,"utf-8"))}catch(i){throw new x("The local script changed while the command was running.",{exitCode:k,errorCode:"LOCAL_SCRIPT_CHANGED",hint:"Read the latest local script and re-apply the operation.",data:{actual:[e,i instanceof Error?i.message:String(i)]}})}let o=Je(n);if(o!==t)throw new x("The local script changed while the command was running.",{exitCode:k,errorCode:"LOCAL_SCRIPT_CHANGED",hint:"Read the latest local script and re-apply the operation.",data:{actual:[`loadedHash=${t}`,`currentHash=${o}`,e]}})}function v(e){return e==null?"":String(e)}function oe(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Bn(e){return Array.isArray(e)}function re(e){return Array.isArray(e)?e:[]}function Bc(e,t=[]){throw new x(e,{exitCode:B,errorCode:"CREATIVE_DRAFT_USAGE_INVALID",hint:"Run `scriptctl authoring compose <draft.json> --script-path <script.json>` and apply the returned plan digest.",data:{actual:t}})}function xu(e,t){let n=Au.resolve(e),o;try{o=Iu.readFileSync(n)}catch{throw new x(`${t} does not exist.`,{exitCode:k,errorCode:"CREATIVE_DRAFT_SOURCE_UNAVAILABLE",data:{actual:[n]}})}try{return{path:n,bytes:o,value:JSON.parse(o.toString("utf-8"))}}catch(i){throw new x(`${t} is not valid JSON.`,{exitCode:k,errorCode:"CREATIVE_DRAFT_JSON_INVALID",data:{actual:[n,i instanceof Error?i.message:String(i)]}})}}function ku(e){let t=Array.isArray(e._args)?e._args:[],n=typeof t[0]=="string"?t[0]:"";(!n||n==="-")&&Bc("Creative draft input must be a named JSON file.",[n||"<missing>"]);let o=xu(n,"The creative draft"),i=me(e),r=xu(i,"The target Script v4 file"),s=_n(r.value),c=Je(s),a=Eu(s,o.value),d=`sha256:${Su.createHash("sha256").update(o.bytes).digest("hex")}`,p={version:1,op:"compose",sourceDigest:d,baseline:c,proposed:Je(a.script),episodeNumber:a.episodeNumber,sceneNumber:a.sceneNumber,sceneId:a.sceneId,actionIds:a.actionIds,joinedPreviousScene:a.joinedPreviousScene,created:a.created},l=`sha256:${_e(JSON.stringify(p))}`,f=e.apply===!0,u=v(e.plan).trim();if(f&&!u&&Bc("--apply requires the exact digest returned by the current plan.",["plan=<missing>"]),!f&&u&&Bc("--plan is only valid together with --apply.",[`plan=${u}`]),f&&u!==l)throw new x("The supplied plan does not match the current draft or script baseline.",{exitCode:k,errorCode:"CREATIVE_DRAFT_PLAN_MISMATCH",hint:"Review the newly computed plan, then apply its exact digest.",data:{expected:[l],actual:[u]}});return f&&(Gt(i,c),Fe(i,a.script)),[{text:[`${f?"Applied":"Planned"} readable scene draft as episode ${a.episodeNumber}, scene ${a.sceneNumber}${a.joinedPreviousScene?" (joined previous scene)":""}`,`plan: ${l}`].join(`
124
124
  `),data:{op:"compose",applied:f,source_path:o.path,source_digest:d,script_path:i,baseline:c,plan_digest:l,episode_number:a.episodeNumber,scene_number:a.sceneNumber,scene_id:a.sceneId,action_ids:a.actionIds,joined_previous_scene:a.joinedPreviousScene,created:a.created,validation:a.validation}},G]}import*as Cu from"node:fs";import*as Tu from"node:path";var Zt={line:1,column:1};function w_(e){let t=[];for(let n of e.actors){let o=structuredClone(n);o.states=[],t.push({declarationKind:"actor",value:o,source:Zt});for(let i of n.states)t.push(Jc("actor",n.actor_id,i))}for(let n of e.locations){let o=structuredClone(n);o.states=[],t.push({declarationKind:"location",value:o,source:Zt});for(let i of n.states)t.push(Jc("location",n.location_id,i))}for(let n of e.props){let o=structuredClone(n);o.states=[],t.push({declarationKind:"prop",value:o,source:Zt});for(let i of n.states)t.push(Jc("prop",n.prop_id,i))}return t}function Jc(e,t,n){return{declarationKind:"state",ownerKind:e,ownerId:t,value:structuredClone(n),source:Zt}}function bu(e){let t={kind:"script",title:e.title,worldview:e.worldview,style:e.style,episodes:structuredClone(e.episodes),source:Zt};return e.worldview_raw!==void 0&&(t.worldviewRaw=e.worldview_raw),e.synopsis!==void 0&&(t.synopsis=e.synopsis),e.logline!==void 0&&(t.logline=e.logline),e.theme!==void 0&&(t.theme=e.theme),e.main_characters!==void 0&&(t.mainCharacters=structuredClone(e.main_characters)),e.extend!==void 0&&(t.extend=structuredClone(e.extend)),{version:1,declarations:w_(e),targets:[t],targetKind:"script"}}function Gi(e,t){return{version:1,declarations:[],targets:t,targetKind:e}}function __(e){return e.replace(/\\/g,"\\\\").replace(/\|/g,"\\|").replace(/\]/g,"\\]").replace(/\n/g,"\\n")}function E_(e){return e.replace(/\\/g,"\\\\").replace(/\n/g,"\\n")}function ue(e,t,n){let o=[e,...t].map(__).join("|"),i=E_(n);return`[${o}]${i.length>0?` ${i}`:""}`}function Kc(e){if(Array.isArray(e))return e.map(Kc);if(e!==null&&typeof e=="object"){let t={};for(let n of Object.keys(e).sort())t[n]=Kc(e[n]);return t}return e}function Jn(e){return e===void 0?[]:[ue("extensions",[],""),...Object.keys(e).sort().map(t=>ue("extend",[t],JSON.stringify(Kc(e[t]))))]}function x_(e){return"actor_id"in e?e.state_id===void 0?e.actor_id:`${e.actor_id}/${e.state_id}`:e.label===void 0?e.kind:`${e.kind}:${e.label}`}function vu(e){let t=Jn(e.extend);if(e.transition_prompt!==void 0&&t.push(ue("prompt",[e.transition_prompt.target,e.transition_prompt.process,e.transition_prompt.contrast],"")),e.type==="dialogue"||e.type==="inner_thought"){let o=e.type==="dialogue"?"dlg":"think",i=[x_(e.speaker)];return e.emotion!==void 0&&i.push(e.emotion),t.push(ue(o,i,e.content)),t}let n=e.type==="action"?"act":"trans";return t.push(ue(n,e.emotion===void 0?[]:[e.emotion],e.content)),t}function zc(e,t){let n=[...Jn(e.extend),`<scene ${t}>`];if(e.environment!==void 0&&(e.environment.time!==void 0?n.push(ue("environment",[e.environment.space??"",e.environment.time],"")):e.environment.space!==void 0?n.push(ue("environment",[e.environment.space],"")):n.push(ue("environment",[],""))),e.location===null)n.push(ue("location",[],""));else{let o=[e.location.location_id];e.location.state_id!==void 0&&o.push(e.location.state_id),n.push(ue("location",o,""))}for(let o of e.actors){let i=[o.actor_id];o.state_id!==void 0&&i.push(o.state_id),n.push(ue("cast",i,""))}for(let o of e.props){let i=[o.prop_id];o.state_id!==void 0&&i.push(o.state_id),n.push(ue("prop",i,""))}n.push("","<body>");for(let o of e.actions)n.push(...vu(o));return n.push("</body>","","</scene>"),n}function jc(e){let t=[...Jn(e.extend),`<episode id=${e.episode_id}>`];return e.title!==void 0&&t.push(ue("title",[],e.title)),e.synopsis!==void 0&&t.push(ue("synopsis",[],e.synopsis)),(e.title!==void 0||e.synopsis!==void 0)&&e.scenes.length>0&&t.push(""),e.scenes.forEach((n,o)=>{t.push(...zc(n,`id=${n.scene_id}`)),o<e.scenes.length-1&&t.push("")}),t.push("</episode>"),t}function S_(e){if(e.declarationKind==="state")return I_(e.ownerKind,e.ownerId,e.value);let t=e.value,n=Jn(t.extend);t.aliases!==void 0&&n.push(ue("aliases",[],""));for(let o of t.aliases??[])n.push(ue("alias",[],o));if(e.declarationKind==="actor"){let o=e.value,i=[o.actor_id,o.actor_name,o.importance];o.role_type!==void 0&&i.push(o.role_type),n.push(ue("actor",i,o.description))}else if(e.declarationKind==="location"){let o=e.value;n.push(ue("location",[o.location_id,o.location_name,o.importance],o.description))}else{let o=e.value;n.push(ue("prop",[o.prop_id,o.prop_name,o.importance],o.description))}return n}function I_(e,t,n){return[...Jn(n.extend),ue("state",[`${e}:${t}`,n.state_id,n.state_name],n.description)]}function A_(e){switch(e.kind){case"script":{let t=[...Jn(e.extend),"<script>"];if(t.push(ue("title",[],e.title)),t.push(ue("worldview",[],e.worldview)),e.worldviewRaw!==void 0&&t.push(ue("worldview-raw",[],e.worldviewRaw)),t.push(ue("style",[],e.style)),e.synopsis!==void 0&&t.push(ue("synopsis",[],e.synopsis)),e.logline!==void 0&&t.push(ue("logline",[],e.logline)),e.theme!==void 0&&t.push(ue("theme",[],e.theme)),e.mainCharacters!==void 0){t.push(ue("main-characters",[],""));for(let n of e.mainCharacters)t.push(ue("main-character",[n.name,n.role],""))}return e.episodes.length>0&&t.push(""),e.episodes.forEach((n,o)=>{t.push(...jc(n)),o<e.episodes.length-1&&t.push("")}),t.push("</script>"),t}case"episode":return jc(e.value);case"episode-span":{let t=[...Jn(e.extend),`<episode-span from=${e.from} through=${e.through}>`];return e.episodes.forEach((n,o)=>{t.push(...jc(n)),o<e.episodes.length-1&&t.push("")}),t.push("</episode-span>"),t}case"scene":return zc(e.value,`id=${e.value.scene_id} parent=${e.parent}`);case"scene-span":{let t=[...Jn(e.extend),`<scene-span parent=${e.parent} from=${e.from} through=${e.through}>`];return e.scenes.forEach((n,o)=>{t.push(...zc(n,`id=${n.scene_id}`)),o<e.scenes.length-1&&t.push("")}),t.push("</scene-span>"),t}case"action-span":{let t=[...Jn(e.extend),`<action-span parent=${e.parent} from=${e.from} through=${e.through}>`,"<body>"];for(let n of e.actions)t.push(...vu(n));return t.push("</body>","</action-span>"),t}}}function Ou(e){let t=["<authoring version=1>",""];if(e.declarations.length>0){t.push("<create>");for(let n of e.declarations)t.push(...S_(n));t.push("</create>","")}return e.targets.forEach((n,o)=>{t.push(...A_(n)),o<e.targets.length-1&&t.push("")}),t.push("","</authoring>"),`${t.join(`
125
125
  `)}
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- import{a,b}from"./chunk-4MGRUUNV.js";export{a as buildProgram,b as main};
1
+ import{a,b}from"./chunk-QBAD7GAY.js";export{a as buildProgram,b as main};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingjingai/scriptctl",
3
- "version": "0.66.11",
3
+ "version": "0.66.12",
4
4
  "description": "剧本阶段统一 CLI:素材转 Script v4,并兼容 Script v3 的本地写作、精修、校验和发布。",
5
5
  "type": "module",
6
6
  "bin": {