@pawlogic/dl 0.3.0-staging.30f9afd → 0.3.0-staging.45adb2f
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/dl.mjs +2 -0
- package/ilands.mjs +2 -0
- package/package.json +18 -47
- package/dist/bundle/dl.mjs +0 -2
- package/dist/bundle/package.json +0 -13
package/dl.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import e,{readFileSync as t,existsSync as i}from"node:fs";import n,{resolve as o,isAbsolute as r,dirname as a,extname as s}from"node:path";import{fileURLToPath as l}from"node:url";import c from"node:events";import d,{spawn as u,spawnSync as p,execFileSync as m}from"node:child_process";import h from"node:process";import{randomUUID as f}from"node:crypto";import{readFile as g,mkdir as v,writeFile as y}from"node:fs/promises";function b(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var _,w,k={},x={},S={};function E(){if(_)return S;_=1;class e extends Error{constructor(e,t,i){super(i),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=t,this.exitCode=e,this.nestedError=void 0}}return S.CommanderError=e,S.InvalidArgumentError=class extends e{constructor(e){super(1,"commander.invalidArgument",e),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}},S}function O(){if(w)return x;w=1;const{InvalidArgumentError:e}=E();return x.Argument=class{constructor(e,t){switch(this.description=t||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,e[0]){case"<":this.required=!0,this._name=e.slice(1,-1);break;case"[":this.required=!1,this._name=e.slice(1,-1);break;default:this.required=!0,this._name=e}this._name.length>3&&"..."===this._name.slice(-3)&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_concatValue(e,t){return t!==this.defaultValue&&Array.isArray(t)?t.concat(e):[e]}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}argParser(e){return this.parseArg=e,this}choices(t){return this.argChoices=t.slice(),this.parseArg=(t,i)=>{if(!this.argChoices.includes(t))throw new e(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,i):t},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}},x.humanReadableArgName=function(e){const t=e.name()+(!0===e.variadic?"...":"");return e.required?"<"+t+">":"["+t+"]"},x}var T,A={},$={};function N(){if(T)return $;T=1;const{humanReadableArgName:e}=O();return $.Help=class{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(e){const t=e.commands.filter(e=>!e._hidden),i=e._getHelpCommand();return i&&!i._hidden&&t.push(i),this.sortSubcommands&&t.sort((e,t)=>e.name().localeCompare(t.name())),t}compareOptions(e,t){const i=e=>e.short?e.short.replace(/^-/,""):e.long.replace(/^--/,"");return i(e).localeCompare(i(t))}visibleOptions(e){const t=e.options.filter(e=>!e.hidden),i=e._getHelpOption();if(i&&!i.hidden){const n=i.short&&e._findOption(i.short),o=i.long&&e._findOption(i.long);n||o?i.long&&!o?t.push(e.createOption(i.long,i.description)):i.short&&!n&&t.push(e.createOption(i.short,i.description)):t.push(i)}return this.sortOptions&&t.sort(this.compareOptions),t}visibleGlobalOptions(e){if(!this.showGlobalOptions)return[];const t=[];for(let i=e.parent;i;i=i.parent){const e=i.options.filter(e=>!e.hidden);t.push(...e)}return this.sortOptions&&t.sort(this.compareOptions),t}visibleArguments(e){return e._argsDescription&&e.registeredArguments.forEach(t=>{t.description=t.description||e._argsDescription[t.name()]||""}),e.registeredArguments.find(e=>e.description)?e.registeredArguments:[]}subcommandTerm(t){const i=t.registeredArguments.map(t=>e(t)).join(" ");return t._name+(t._aliases[0]?"|"+t._aliases[0]:"")+(t.options.length?" [options]":"")+(i?" "+i:"")}optionTerm(e){return e.flags}argumentTerm(e){return e.name()}longestSubcommandTermLength(e,t){return t.visibleCommands(e).reduce((e,i)=>Math.max(e,t.subcommandTerm(i).length),0)}longestOptionTermLength(e,t){return t.visibleOptions(e).reduce((e,i)=>Math.max(e,t.optionTerm(i).length),0)}longestGlobalOptionTermLength(e,t){return t.visibleGlobalOptions(e).reduce((e,i)=>Math.max(e,t.optionTerm(i).length),0)}longestArgumentTermLength(e,t){return t.visibleArguments(e).reduce((e,i)=>Math.max(e,t.argumentTerm(i).length),0)}commandUsage(e){let t=e._name;e._aliases[0]&&(t=t+"|"+e._aliases[0]);let i="";for(let t=e.parent;t;t=t.parent)i=t.name()+" "+i;return i+t+" "+e.usage()}commandDescription(e){return e.description()}subcommandDescription(e){return e.summary()||e.description()}optionDescription(e){const t=[];return e.argChoices&&t.push(`choices: ${e.argChoices.map(e=>JSON.stringify(e)).join(", ")}`),void 0!==e.defaultValue&&(e.required||e.optional||e.isBoolean()&&"boolean"==typeof e.defaultValue)&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),void 0!==e.presetArg&&e.optional&&t.push(`preset: ${JSON.stringify(e.presetArg)}`),void 0!==e.envVar&&t.push(`env: ${e.envVar}`),t.length>0?`${e.description} (${t.join(", ")})`:e.description}argumentDescription(e){const t=[];if(e.argChoices&&t.push(`choices: ${e.argChoices.map(e=>JSON.stringify(e)).join(", ")}`),void 0!==e.defaultValue&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),t.length>0){const i=`(${t.join(", ")})`;return e.description?`${e.description} ${i}`:i}return e.description}formatHelp(e,t){const i=t.padWidth(e,t),n=t.helpWidth||80;function o(e,o){if(o){const r=`${e.padEnd(i+2)}${o}`;return t.wrap(r,n-2,i+2)}return e}function r(e){return e.join("\n").replace(/^/gm," ".repeat(2))}let a=[`Usage: ${t.commandUsage(e)}`,""];const s=t.commandDescription(e);s.length>0&&(a=a.concat([t.wrap(s,n,0),""]));const l=t.visibleArguments(e).map(e=>o(t.argumentTerm(e),t.argumentDescription(e)));l.length>0&&(a=a.concat(["Arguments:",r(l),""]));const c=t.visibleOptions(e).map(e=>o(t.optionTerm(e),t.optionDescription(e)));if(c.length>0&&(a=a.concat(["Options:",r(c),""])),this.showGlobalOptions){const i=t.visibleGlobalOptions(e).map(e=>o(t.optionTerm(e),t.optionDescription(e)));i.length>0&&(a=a.concat(["Global Options:",r(i),""]))}const d=t.visibleCommands(e).map(e=>o(t.subcommandTerm(e),t.subcommandDescription(e)));return d.length>0&&(a=a.concat(["Commands:",r(d),""])),a.join("\n")}padWidth(e,t){return Math.max(t.longestOptionTermLength(e,t),t.longestGlobalOptionTermLength(e,t),t.longestSubcommandTermLength(e,t),t.longestArgumentTermLength(e,t))}wrap(e,t,i,n=40){const o=new RegExp("[\\n][ \\f\\t\\v - \ufeff]+");if(e.match(o))return e;const r=t-i;if(r<n)return e;const a=e.slice(0,i),s=e.slice(i).replace("\r\n","\n"),l=" ".repeat(i),c="\\s",d=new RegExp(`\n|.{1,${r-1}}([${c}]|$)|[^${c}]+?([${c}]|$)`,"g");return a+(s.match(d)||[]).map((e,t)=>"\n"===e?"":(t>0?l:"")+e.trimEnd()).join("\n")}},$}var j,C={};function R(){if(j)return C;j=1;const{InvalidArgumentError:e}=E();return C.Option=class{constructor(e,t){this.flags=e,this.description=t||"",this.required=e.includes("<"),this.optional=e.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(e),this.mandatory=!1;const i=function(e){let t,i;const n=e.split(/[ |,]+/);return n.length>1&&!/^[[<]/.test(n[1])&&(t=n.shift()),i=n.shift(),!t&&/^-[^-]$/.test(i)&&(t=i,i=void 0),{shortFlag:t,longFlag:i}}(e);this.short=i.shortFlag,this.long=i.longFlag,this.negate=!1,this.long&&(this.negate=this.long.startsWith("--no-")),this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}preset(e){return this.presetArg=e,this}conflicts(e){return this.conflictsWith=this.conflictsWith.concat(e),this}implies(e){let t=e;return"string"==typeof e&&(t={[e]:!0}),this.implied=Object.assign(this.implied||{},t),this}env(e){return this.envVar=e,this}argParser(e){return this.parseArg=e,this}makeOptionMandatory(e=!0){return this.mandatory=!!e,this}hideHelp(e=!0){return this.hidden=!!e,this}_concatValue(e,t){return t!==this.defaultValue&&Array.isArray(t)?t.concat(e):[e]}choices(t){return this.argChoices=t.slice(),this.parseArg=(t,i)=>{if(!this.argChoices.includes(t))throw new e(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,i):t},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return this.name().replace(/^no-/,"").split("-").reduce((e,t)=>e+t[0].toUpperCase()+t.slice(1))}is(e){return this.short===e||this.long===e}isBoolean(){return!this.required&&!this.optional&&!this.negate}},C.DualOptions=class{constructor(e){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,e.forEach(e=>{e.negate?this.negativeOptions.set(e.attributeName(),e):this.positiveOptions.set(e.attributeName(),e)}),this.negativeOptions.forEach((e,t)=>{this.positiveOptions.has(t)&&this.dualOptions.add(t)})}valueFromOption(e,t){const i=t.attributeName();if(!this.dualOptions.has(i))return!0;const n=this.negativeOptions.get(i).presetArg,o=void 0!==n&&n;return t.negate===(o===e)}},C}var I,L,z,q={};function P(){return I||(I=1,q.suggestSimilar=function(e,t){if(!t||0===t.length)return"";t=Array.from(new Set(t));const i=e.startsWith("--");i&&(e=e.slice(2),t=t.map(e=>e.slice(2)));let n=[],o=3;return t.forEach(t=>{if(t.length<=1)return;const i=function(e,t){if(Math.abs(e.length-t.length)>3)return Math.max(e.length,t.length);const i=[];for(let t=0;t<=e.length;t++)i[t]=[t];for(let e=0;e<=t.length;e++)i[0][e]=e;for(let n=1;n<=t.length;n++)for(let o=1;o<=e.length;o++){let r=1;r=e[o-1]===t[n-1]?0:1,i[o][n]=Math.min(i[o-1][n]+1,i[o][n-1]+1,i[o-1][n-1]+r),o>1&&n>1&&e[o-1]===t[n-2]&&e[o-2]===t[n-1]&&(i[o][n]=Math.min(i[o][n],i[o-2][n-2]+1))}return i[e.length][t.length]}(e,t),r=Math.max(e.length,t.length);(r-i)/r>.4&&(i<o?(o=i,n=[t]):i===o&&n.push(t))}),n.sort((e,t)=>e.localeCompare(t)),i&&(n=n.map(e=>`--${e}`)),n.length>1?`\n(Did you mean one of ${n.join(", ")}?)`:1===n.length?`\n(Did you mean ${n[0]}?)`:""}),q}var M=function(){if(z)return k;z=1;const{Argument:t}=O(),{Command:i}=function(){if(L)return A;L=1;const t=c.EventEmitter,i=d,o=n,r=e,a=h,{Argument:s,humanReadableArgName:l}=O(),{CommanderError:u}=E(),{Help:p}=N(),{Option:m,DualOptions:f}=R(),{suggestSimilar:g}=P();class v extends t{constructor(e){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=e||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:e=>a.stdout.write(e),writeErr:e=>a.stderr.write(e),getOutHelpWidth:()=>a.stdout.isTTY?a.stdout.columns:void 0,getErrHelpWidth:()=>a.stderr.isTTY?a.stderr.columns:void 0,outputError:(e,t)=>t(e)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(e){return this._outputConfiguration=e._outputConfiguration,this._helpOption=e._helpOption,this._helpCommand=e._helpCommand,this._helpConfiguration=e._helpConfiguration,this._exitCallback=e._exitCallback,this._storeOptionsAsProperties=e._storeOptionsAsProperties,this._combineFlagAndOptionalValue=e._combineFlagAndOptionalValue,this._allowExcessArguments=e._allowExcessArguments,this._enablePositionalOptions=e._enablePositionalOptions,this._showHelpAfterError=e._showHelpAfterError,this._showSuggestionAfterError=e._showSuggestionAfterError,this}_getCommandAndAncestors(){const e=[];for(let t=this;t;t=t.parent)e.push(t);return e}command(e,t,i){let n=t,o=i;"object"==typeof n&&null!==n&&(o=n,n=null),o=o||{};const[,r,a]=e.match(/([^ ]+) *(.*)/),s=this.createCommand(r);return n&&(s.description(n),s._executableHandler=!0),o.isDefault&&(this._defaultCommandName=s._name),s._hidden=!(!o.noHelp&&!o.hidden),s._executableFile=o.executableFile||null,a&&s.arguments(a),this._registerCommand(s),s.parent=this,s.copyInheritedSettings(this),n?this:s}createCommand(e){return new v(e)}createHelp(){return Object.assign(new p,this.configureHelp())}configureHelp(e){return void 0===e?this._helpConfiguration:(this._helpConfiguration=e,this)}configureOutput(e){return void 0===e?this._outputConfiguration:(Object.assign(this._outputConfiguration,e),this)}showHelpAfterError(e=!0){return"string"!=typeof e&&(e=!!e),this._showHelpAfterError=e,this}showSuggestionAfterError(e=!0){return this._showSuggestionAfterError=!!e,this}addCommand(e,t){if(!e._name)throw new Error("Command passed to .addCommand() must have a name\n- specify the name in Command constructor or using .name()");return(t=t||{}).isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,t){return new s(e,t)}argument(e,t,i,n){const o=this.createArgument(e,t);return"function"==typeof i?o.default(n).argParser(i):o.default(i),this.addArgument(o),this}arguments(e){return e.trim().split(/ +/).forEach(e=>{this.argument(e)}),this}addArgument(e){const t=this.registeredArguments.slice(-1)[0];if(t&&t.variadic)throw new Error(`only the last argument can be variadic '${t.name()}'`);if(e.required&&void 0!==e.defaultValue&&void 0===e.parseArg)throw new Error(`a default value for a required argument is never used: '${e.name()}'`);return this.registeredArguments.push(e),this}helpCommand(e,t){if("boolean"==typeof e)return this._addImplicitHelpCommand=e,this;e=e??"help [command]";const[,i,n]=e.match(/([^ ]+) *(.*)/),o=t??"display help for command",r=this.createCommand(i);return r.helpOption(!1),n&&r.arguments(n),o&&r.description(o),this._addImplicitHelpCommand=!0,this._helpCommand=r,this}addHelpCommand(e,t){return"object"!=typeof e?(this.helpCommand(e,t),this):(this._addImplicitHelpCommand=!0,this._helpCommand=e,this)}_getHelpCommand(){return this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))?(void 0===this._helpCommand&&this.helpCommand(void 0,void 0),this._helpCommand):null}hook(e,t){const i=["preSubcommand","preAction","postAction"];if(!i.includes(e))throw new Error(`Unexpected value for event passed to hook : '${e}'.\nExpecting one of '${i.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(t):this._lifeCycleHooks[e]=[t],this}exitOverride(e){return this._exitCallback=e||(e=>{if("commander.executeSubCommandAsync"!==e.code)throw e}),this}_exit(e,t,i){this._exitCallback&&this._exitCallback(new u(e,t,i)),a.exit(e)}action(e){return this._actionHandler=t=>{const i=this.registeredArguments.length,n=t.slice(0,i);return this._storeOptionsAsProperties?n[i]=this:n[i]=this.opts(),n.push(this),e.apply(this,n)},this}createOption(e,t){return new m(e,t)}_callParseArg(e,t,i,n){try{return e.parseArg(t,i)}catch(e){if("commander.invalidArgument"===e.code){const t=`${n} ${e.message}`;this.error(t,{exitCode:e.exitCode,code:e.code})}throw e}}_registerOption(e){const t=e.short&&this._findOption(e.short)||e.long&&this._findOption(e.long);if(t){const i=e.long&&this._findOption(e.long)?e.long:e.short;throw new Error(`Cannot add option '${e.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${i}'\n- already used by option '${t.flags}'`)}this.options.push(e)}_registerCommand(e){const t=e=>[e.name()].concat(e.aliases()),i=t(e).find(e=>this._findCommand(e));if(i){const n=t(this._findCommand(i)).join("|"),o=t(e).join("|");throw new Error(`cannot add command '${o}' as already have command '${n}'`)}this.commands.push(e)}addOption(e){this._registerOption(e);const t=e.name(),i=e.attributeName();if(e.negate){const t=e.long.replace(/^--no-/,"--");this._findOption(t)||this.setOptionValueWithSource(i,void 0===e.defaultValue||e.defaultValue,"default")}else void 0!==e.defaultValue&&this.setOptionValueWithSource(i,e.defaultValue,"default");const n=(t,n,o)=>{null==t&&void 0!==e.presetArg&&(t=e.presetArg);const r=this.getOptionValue(i);null!==t&&e.parseArg?t=this._callParseArg(e,t,r,n):null!==t&&e.variadic&&(t=e._concatValue(t,r)),null==t&&(t=!e.negate&&(!(!e.isBoolean()&&!e.optional)||"")),this.setOptionValueWithSource(i,t,o)};return this.on("option:"+t,t=>{const i=`error: option '${e.flags}' argument '${t}' is invalid.`;n(t,i,"cli")}),e.envVar&&this.on("optionEnv:"+t,t=>{const i=`error: option '${e.flags}' value '${t}' from env '${e.envVar}' is invalid.`;n(t,i,"env")}),this}_optionEx(e,t,i,n,o){if("object"==typeof t&&t instanceof m)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");const r=this.createOption(t,i);if(r.makeOptionMandatory(!!e.mandatory),"function"==typeof n)r.default(o).argParser(n);else if(n instanceof RegExp){const e=n;n=(t,i)=>{const n=e.exec(t);return n?n[0]:i},r.default(o).argParser(n)}else r.default(n);return this.addOption(r)}option(e,t,i,n){return this._optionEx({},e,t,i,n)}requiredOption(e,t,i,n){return this._optionEx({mandatory:!0},e,t,i,n)}combineFlagAndOptionalValue(e=!0){return this._combineFlagAndOptionalValue=!!e,this}allowUnknownOption(e=!0){return this._allowUnknownOption=!!e,this}allowExcessArguments(e=!0){return this._allowExcessArguments=!!e,this}enablePositionalOptions(e=!0){return this._enablePositionalOptions=!!e,this}passThroughOptions(e=!0){return this._passThroughOptions=!!e,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(e=!0){if(this.options.length)throw new Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw new Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!e,this}getOptionValue(e){return this._storeOptionsAsProperties?this[e]:this._optionValues[e]}setOptionValue(e,t){return this.setOptionValueWithSource(e,t,void 0)}setOptionValueWithSource(e,t,i){return this._storeOptionsAsProperties?this[e]=t:this._optionValues[e]=t,this._optionValueSources[e]=i,this}getOptionValueSource(e){return this._optionValueSources[e]}getOptionValueSourceWithGlobals(e){let t;return this._getCommandAndAncestors().forEach(i=>{void 0!==i.getOptionValueSource(e)&&(t=i.getOptionValueSource(e))}),t}_prepareUserArgs(e,t){if(void 0!==e&&!Array.isArray(e))throw new Error("first parameter to parse must be array or undefined");if(t=t||{},void 0===e&&void 0===t.from){a.versions?.electron&&(t.from="electron");const e=a.execArgv??[];(e.includes("-e")||e.includes("--eval")||e.includes("-p")||e.includes("--print"))&&(t.from="eval")}let i;switch(void 0===e&&(e=a.argv),this.rawArgs=e.slice(),t.from){case void 0:case"node":this._scriptPath=e[1],i=e.slice(2);break;case"electron":a.defaultApp?(this._scriptPath=e[1],i=e.slice(2)):i=e.slice(1);break;case"user":i=e.slice(0);break;case"eval":i=e.slice(1);break;default:throw new Error(`unexpected parse option { from: '${t.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",i}parse(e,t){const i=this._prepareUserArgs(e,t);return this._parseCommand([],i),this}async parseAsync(e,t){const i=this._prepareUserArgs(e,t);return await this._parseCommand([],i),this}_executeSubCommand(e,t){t=t.slice();let n=!1;const s=[".js",".ts",".tsx",".mjs",".cjs"];function l(e,t){const i=o.resolve(e,t);if(r.existsSync(i))return i;if(s.includes(o.extname(t)))return;const n=s.find(e=>r.existsSync(`${i}${e}`));return n?`${i}${n}`:void 0}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let c,d=e._executableFile||`${this._name}-${e._name}`,p=this._executableDir||"";if(this._scriptPath){let e;try{e=r.realpathSync(this._scriptPath)}catch(t){e=this._scriptPath}p=o.resolve(o.dirname(e),p)}if(p){let t=l(p,d);if(!t&&!e._executableFile&&this._scriptPath){const i=o.basename(this._scriptPath,o.extname(this._scriptPath));i!==this._name&&(t=l(p,`${i}-${e._name}`))}d=t||d}n=s.includes(o.extname(d)),"win32"!==a.platform?n?(t.unshift(d),t=y(a.execArgv).concat(t),c=i.spawn(a.argv[0],t,{stdio:"inherit"})):c=i.spawn(d,t,{stdio:"inherit"}):(t.unshift(d),t=y(a.execArgv).concat(t),c=i.spawn(a.execPath,t,{stdio:"inherit"})),c.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(e=>{a.on(e,()=>{!1===c.killed&&null===c.exitCode&&c.kill(e)})});const m=this._exitCallback;c.on("close",e=>{e=e??1,m?m(new u(e,"commander.executeSubCommandAsync","(close)")):a.exit(e)}),c.on("error",t=>{if("ENOENT"===t.code){const t=p?`searched for local subcommand relative to directory '${p}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",i=`'${d}' does not exist\n - if '${e._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead\n - if the default executable name is not suitable, use the executableFile option to supply a custom name or path\n - ${t}`;throw new Error(i)}if("EACCES"===t.code)throw new Error(`'${d}' not executable`);if(m){const e=new u(1,"commander.executeSubCommandAsync","(error)");e.nestedError=t,m(e)}else a.exit(1)}),this.runningCommand=c}_dispatchSubcommand(e,t,i){const n=this._findCommand(e);let o;return n||this.help({error:!0}),o=this._chainOrCallSubCommandHook(o,n,"preSubcommand"),o=this._chainOrCall(o,()=>{if(!n._executableHandler)return n._parseCommand(t,i);this._executeSubCommand(n,t.concat(i))}),o}_dispatchHelpCommand(e){e||this.help();const t=this._findCommand(e);return t&&!t._executableHandler&&t.help(),this._dispatchSubcommand(e,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((e,t)=>{e.required&&null==this.args[t]&&this.missingArgument(e.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic||this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){const e=(e,t,i)=>{let n=t;if(null!==t&&e.parseArg){const o=`error: command-argument value '${t}' is invalid for argument '${e.name()}'.`;n=this._callParseArg(e,t,i,o)}return n};this._checkNumberOfArguments();const t=[];this.registeredArguments.forEach((i,n)=>{let o=i.defaultValue;i.variadic?n<this.args.length?(o=this.args.slice(n),i.parseArg&&(o=o.reduce((t,n)=>e(i,n,t),i.defaultValue))):void 0===o&&(o=[]):n<this.args.length&&(o=this.args[n],i.parseArg&&(o=e(i,o,i.defaultValue))),t[n]=o}),this.processedArgs=t}_chainOrCall(e,t){return e&&e.then&&"function"==typeof e.then?e.then(()=>t()):t()}_chainOrCallHooks(e,t){let i=e;const n=[];return this._getCommandAndAncestors().reverse().filter(e=>void 0!==e._lifeCycleHooks[t]).forEach(e=>{e._lifeCycleHooks[t].forEach(t=>{n.push({hookedCommand:e,callback:t})})}),"postAction"===t&&n.reverse(),n.forEach(e=>{i=this._chainOrCall(i,()=>e.callback(e.hookedCommand,this))}),i}_chainOrCallSubCommandHook(e,t,i){let n=e;return void 0!==this._lifeCycleHooks[i]&&this._lifeCycleHooks[i].forEach(e=>{n=this._chainOrCall(n,()=>e(this,t))}),n}_parseCommand(e,t){const i=this.parseOptions(t);if(this._parseOptionsEnv(),this._parseOptionsImplied(),e=e.concat(i.operands),t=i.unknown,this.args=e.concat(t),e&&this._findCommand(e[0]))return this._dispatchSubcommand(e[0],e.slice(1),t);if(this._getHelpCommand()&&e[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(e[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(t),this._dispatchSubcommand(this._defaultCommandName,e,t);!this.commands.length||0!==this.args.length||this._actionHandler||this._defaultCommandName||this.help({error:!0}),this._outputHelpIfRequested(i.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();const n=()=>{i.unknown.length>0&&this.unknownOption(i.unknown[0])},o=`command:${this.name()}`;if(this._actionHandler){let i;return n(),this._processArguments(),i=this._chainOrCallHooks(i,"preAction"),i=this._chainOrCall(i,()=>this._actionHandler(this.processedArgs)),this.parent&&(i=this._chainOrCall(i,()=>{this.parent.emit(o,e,t)})),i=this._chainOrCallHooks(i,"postAction"),i}if(this.parent&&this.parent.listenerCount(o))n(),this._processArguments(),this.parent.emit(o,e,t);else if(e.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",e,t);this.listenerCount("command:*")?this.emit("command:*",e,t):this.commands.length?this.unknownCommand():(n(),this._processArguments())}else this.commands.length?(n(),this.help({error:!0})):(n(),this._processArguments())}_findCommand(e){if(e)return this.commands.find(t=>t._name===e||t._aliases.includes(e))}_findOption(e){return this.options.find(t=>t.is(e))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(e=>{e.options.forEach(t=>{t.mandatory&&void 0===e.getOptionValue(t.attributeName())&&e.missingMandatoryOptionValue(t)})})}_checkForConflictingLocalOptions(){const e=this.options.filter(e=>{const t=e.attributeName();return void 0!==this.getOptionValue(t)&&"default"!==this.getOptionValueSource(t)}),t=e.filter(e=>e.conflictsWith.length>0);t.forEach(t=>{const i=e.find(e=>t.conflictsWith.includes(e.attributeName()));i&&this._conflictingOption(t,i)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(e=>{e._checkForConflictingLocalOptions()})}parseOptions(e){const t=[],i=[];let n=t;const o=e.slice();function r(e){return e.length>1&&"-"===e[0]}let a=null;for(;o.length;){const e=o.shift();if("--"===e){n===i&&n.push(e),n.push(...o);break}if(!a||r(e)){if(a=null,r(e)){const t=this._findOption(e);if(t){if(t.required){const e=o.shift();void 0===e&&this.optionMissingArgument(t),this.emit(`option:${t.name()}`,e)}else if(t.optional){let e=null;o.length>0&&!r(o[0])&&(e=o.shift()),this.emit(`option:${t.name()}`,e)}else this.emit(`option:${t.name()}`);a=t.variadic?t:null;continue}}if(e.length>2&&"-"===e[0]&&"-"!==e[1]){const t=this._findOption(`-${e[1]}`);if(t){t.required||t.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${t.name()}`,e.slice(2)):(this.emit(`option:${t.name()}`),o.unshift(`-${e.slice(2)}`));continue}}if(/^--[^=]+=/.test(e)){const t=e.indexOf("="),i=this._findOption(e.slice(0,t));if(i&&(i.required||i.optional)){this.emit(`option:${i.name()}`,e.slice(t+1));continue}}if(r(e)&&(n=i),(this._enablePositionalOptions||this._passThroughOptions)&&0===t.length&&0===i.length){if(this._findCommand(e)){t.push(e),o.length>0&&i.push(...o);break}if(this._getHelpCommand()&&e===this._getHelpCommand().name()){t.push(e),o.length>0&&t.push(...o);break}if(this._defaultCommandName){i.push(e),o.length>0&&i.push(...o);break}}if(this._passThroughOptions){n.push(e),o.length>0&&n.push(...o);break}n.push(e)}else this.emit(`option:${a.name()}`,e)}return{operands:t,unknown:i}}opts(){if(this._storeOptionsAsProperties){const e={},t=this.options.length;for(let i=0;i<t;i++){const t=this.options[i].attributeName();e[t]=t===this._versionOptionName?this._version:this[t]}return e}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((e,t)=>Object.assign(e,t.opts()),{})}error(e,t){this._outputConfiguration.outputError(`${e}\n`,this._outputConfiguration.writeErr),"string"==typeof this._showHelpAfterError?this._outputConfiguration.writeErr(`${this._showHelpAfterError}\n`):this._showHelpAfterError&&(this._outputConfiguration.writeErr("\n"),this.outputHelp({error:!0}));const i=t||{},n=i.exitCode||1,o=i.code||"commander.error";this._exit(n,o,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in a.env){const t=e.attributeName();(void 0===this.getOptionValue(t)||["default","config","env"].includes(this.getOptionValueSource(t)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,a.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){const e=new f(this.options),t=e=>void 0!==this.getOptionValue(e)&&!["default","implied"].includes(this.getOptionValueSource(e));this.options.filter(i=>void 0!==i.implied&&t(i.attributeName())&&e.valueFromOption(this.getOptionValue(i.attributeName()),i)).forEach(e=>{Object.keys(e.implied).filter(e=>!t(e)).forEach(t=>{this.setOptionValueWithSource(t,e.implied[t],"implied")})})}missingArgument(e){const t=`error: missing required argument '${e}'`;this.error(t,{code:"commander.missingArgument"})}optionMissingArgument(e){const t=`error: option '${e.flags}' argument missing`;this.error(t,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(e){const t=`error: required option '${e.flags}' not specified`;this.error(t,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(e,t){const i=e=>{const t=e.attributeName(),i=this.getOptionValue(t),n=this.options.find(e=>e.negate&&t===e.attributeName()),o=this.options.find(e=>!e.negate&&t===e.attributeName());return n&&(void 0===n.presetArg&&!1===i||void 0!==n.presetArg&&i===n.presetArg)?n:o||e},n=e=>{const t=i(e),n=t.attributeName();return"env"===this.getOptionValueSource(n)?`environment variable '${t.envVar}'`:`option '${t.flags}'`},o=`error: ${n(e)} cannot be used with ${n(t)}`;this.error(o,{code:"commander.conflictingOption"})}unknownOption(e){if(this._allowUnknownOption)return;let t="";if(e.startsWith("--")&&this._showSuggestionAfterError){let i=[],n=this;do{const e=n.createHelp().visibleOptions(n).filter(e=>e.long).map(e=>e.long);i=i.concat(e),n=n.parent}while(n&&!n._enablePositionalOptions);t=g(e,i)}const i=`error: unknown option '${e}'${t}`;this.error(i,{code:"commander.unknownOption"})}_excessArguments(e){if(this._allowExcessArguments)return;const t=this.registeredArguments.length,i=1===t?"":"s",n=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${t} argument${i} but got ${e.length}.`;this.error(n,{code:"commander.excessArguments"})}unknownCommand(){const e=this.args[0];let t="";if(this._showSuggestionAfterError){const i=[];this.createHelp().visibleCommands(this).forEach(e=>{i.push(e.name()),e.alias()&&i.push(e.alias())}),t=g(e,i)}const i=`error: unknown command '${e}'${t}`;this.error(i,{code:"commander.unknownCommand"})}version(e,t,i){if(void 0===e)return this._version;this._version=e,t=t||"-V, --version",i=i||"output the version number";const n=this.createOption(t,i);return this._versionOptionName=n.attributeName(),this._registerOption(n),this.on("option:"+n.name(),()=>{this._outputConfiguration.writeOut(`${e}\n`),this._exit(0,"commander.version",e)}),this}description(e,t){return void 0===e&&void 0===t?this._description:(this._description=e,t&&(this._argsDescription=t),this)}summary(e){return void 0===e?this._summary:(this._summary=e,this)}alias(e){if(void 0===e)return this._aliases[0];let t=this;if(0!==this.commands.length&&this.commands[this.commands.length-1]._executableHandler&&(t=this.commands[this.commands.length-1]),e===t._name)throw new Error("Command alias can't be the same as its name");const i=this.parent?._findCommand(e);if(i){const t=[i.name()].concat(i.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${t}'`)}return t._aliases.push(e),this}aliases(e){return void 0===e?this._aliases:(e.forEach(e=>this.alias(e)),this)}usage(e){if(void 0===e){if(this._usage)return this._usage;const e=this.registeredArguments.map(e=>l(e));return[].concat(this.options.length||null!==this._helpOption?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?e:[]).join(" ")}return this._usage=e,this}name(e){return void 0===e?this._name:(this._name=e,this)}nameFromFilename(e){return this._name=o.basename(e,o.extname(e)),this}executableDir(e){return void 0===e?this._executableDir:(this._executableDir=e,this)}helpInformation(e){const t=this.createHelp();return void 0===t.helpWidth&&(t.helpWidth=e&&e.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth()),t.formatHelp(this,t)}_getHelpContext(e){const t={error:!!(e=e||{}).error};let i;return i=t.error?e=>this._outputConfiguration.writeErr(e):e=>this._outputConfiguration.writeOut(e),t.write=e.write||i,t.command=this,t}outputHelp(e){let t;"function"==typeof e&&(t=e,e=void 0);const i=this._getHelpContext(e);this._getCommandAndAncestors().reverse().forEach(e=>e.emit("beforeAllHelp",i)),this.emit("beforeHelp",i);let n=this.helpInformation(i);if(t&&(n=t(n),"string"!=typeof n&&!Buffer.isBuffer(n)))throw new Error("outputHelp callback must return a string or a Buffer");i.write(n),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",i),this._getCommandAndAncestors().forEach(e=>e.emit("afterAllHelp",i))}helpOption(e,t){return"boolean"==typeof e?(this._helpOption=e?this._helpOption??void 0:null,this):(e=e??"-h, --help",t=t??"display help for command",this._helpOption=this.createOption(e,t),this)}_getHelpOption(){return void 0===this._helpOption&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(e){return this._helpOption=e,this}help(e){this.outputHelp(e);let t=a.exitCode||0;0===t&&e&&"function"!=typeof e&&e.error&&(t=1),this._exit(t,"commander.help","(outputHelp)")}addHelpText(e,t){const i=["beforeAll","before","after","afterAll"];if(!i.includes(e))throw new Error(`Unexpected value for position to addHelpText.\nExpecting one of '${i.join("', '")}'`);const n=`${e}Help`;return this.on(n,e=>{let i;i="function"==typeof t?t({error:e.error,command:e.command}):t,i&&e.write(`${i}\n`)}),this}_outputHelpIfRequested(e){const t=this._getHelpOption();t&&e.find(e=>t.is(e))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}}function y(e){return e.map(e=>{if(!e.startsWith("--inspect"))return e;let t,i,n="127.0.0.1",o="9229";return null!==(i=e.match(/^(--inspect(-brk)?)$/))?t=i[1]:null!==(i=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))?(t=i[1],/^\d+$/.test(i[3])?o=i[3]:n=i[3]):null!==(i=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))&&(t=i[1],n=i[3],o=i[4]),t&&"0"!==o?`${t}=${n}:${parseInt(o)+1}`:e})}return A.Command=v,A}(),{CommanderError:o,InvalidArgumentError:r}=E(),{Help:a}=N(),{Option:s}=R();return k.program=new i,k.createCommand=e=>new i(e),k.createOption=(e,t)=>new s(e,t),k.createArgument=(e,i)=>new t(e,i),k.Command=i,k.Option=s,k.Argument=t,k.Help=a,k.CommanderError=o,k.InvalidArgumentError=r,k.InvalidOptionArgumentError=r,k}(),U=b(M);const{program:F,createCommand:D,createArgument:H,createOption:B,CommanderError:V,InvalidArgumentError:J,InvalidOptionArgumentError:K,Command:Y,Argument:G,Option:W,Help:Z}=U;function X(e,t,i){function n(i,n){if(i._zod||Object.defineProperty(i,"_zod",{value:{def:n,constr:a,traits:new Set},enumerable:!1}),i._zod.traits.has(e))return;i._zod.traits.add(e),t(i,n);const o=a.prototype,r=Object.keys(o);for(let e=0;e<r.length;e++){const t=r[e];t in i||(i[t]=o[t].bind(i))}}const o=i?.Parent??Object;class r extends o{}function a(e){var t;const o=i?.Parent?new r:this;n(o,e),(t=o._zod).deferred??(t.deferred=[]);for(const e of o._zod.deferred)e();return o}return Object.defineProperty(r,"name",{value:e}),Object.defineProperty(a,"init",{value:n}),Object.defineProperty(a,Symbol.hasInstance,{value:t=>!!(i?.Parent&&t instanceof i.Parent)||t?._zod?.traits?.has(e)}),Object.defineProperty(a,"name",{value:e}),a}class Q extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class ee extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name="ZodEncodeError"}}const te={};function ie(e){return te}function ne(e){const t=Object.values(e).filter(e=>"number"==typeof e);return Object.entries(e).filter(([e,i])=>-1===t.indexOf(+e)).map(([e,t])=>t)}function oe(e,t){return"bigint"==typeof t?t.toString():t}function re(e){return{get value(){{const t=e();return Object.defineProperty(this,"value",{value:t}),t}}}}function ae(e){return null==e}function se(e){const t=e.startsWith("^")?1:0,i=e.endsWith("$")?e.length-1:e.length;return e.slice(t,i)}const le=Symbol("evaluating");function ce(e,t,i){let n;Object.defineProperty(e,t,{get(){if(n!==le)return void 0===n&&(n=le,n=i()),n},set(i){Object.defineProperty(e,t,{value:i})},configurable:!0})}function de(e,t,i){Object.defineProperty(e,t,{value:i,writable:!0,enumerable:!0,configurable:!0})}function ue(...e){const t={};for(const i of e){const e=Object.getOwnPropertyDescriptors(i);Object.assign(t,e)}return Object.defineProperties({},t)}function pe(e){return JSON.stringify(e)}const me="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function he(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}const fe=re(()=>{if("undefined"!=typeof navigator&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{return new Function(""),!0}catch(e){return!1}});function ge(e){if(!1===he(e))return!1;const t=e.constructor;if(void 0===t)return!0;if("function"!=typeof t)return!0;const i=t.prototype;return!1!==he(i)&&!1!==Object.prototype.hasOwnProperty.call(i,"isPrototypeOf")}function ve(e){return ge(e)?{...e}:Array.isArray(e)?[...e]:e}const ye=new Set(["string","number","symbol"]);function be(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function _e(e,t,i){const n=new e._zod.constr(t??e._zod.def);return t&&!i?.parent||(n._zod.parent=e),n}function we(e){const t=e;if(!t)return{};if("string"==typeof t)return{error:()=>t};if(void 0!==t?.message){if(void 0!==t?.error)throw new Error("Cannot specify both `message` and `error` params");t.error=t.message}return delete t.message,"string"==typeof t.error?{...t,error:()=>t.error}:t}const ke={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function xe(e,t=0){if(!0===e.aborted)return!0;for(let i=t;i<e.issues.length;i++)if(!0!==e.issues[i]?.continue)return!0;return!1}function Se(e,t){return t.map(t=>{var i;return(i=t).path??(i.path=[]),t.path.unshift(e),t})}function Ee(e){return"string"==typeof e?e:e?.message}function Oe(e,t,i){const n={...e,path:e.path??[]};if(!e.message){const o=Ee(e.inst?._zod.def?.error?.(e))??Ee(t?.error?.(e))??Ee(i.customError?.(e))??Ee(i.localeError?.(e))??"Invalid input";n.message=o}return delete n.inst,delete n.continue,t?.reportInput||delete n.input,n}function Te(e){return Array.isArray(e)?"array":"string"==typeof e?"string":"unknown"}function Ae(...e){const[t,i,n]=e;return"string"==typeof t?{message:t,code:"custom",input:i,inst:n}:{...t}}const $e=(e,t)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:t,enumerable:!1}),e.message=JSON.stringify(t,oe,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},Ne=X("$ZodError",$e),je=X("$ZodError",$e,{Parent:Error}),Ce=e=>(t,i,n,o)=>{const r=n?Object.assign(n,{async:!1}):{async:!1},a=t._zod.run({value:i,issues:[]},r);if(a instanceof Promise)throw new Q;if(a.issues.length){const t=new(o?.Err??e)(a.issues.map(e=>Oe(e,r,ie())));throw me(t,o?.callee),t}return a.value},Re=e=>async(t,i,n,o)=>{const r=n?Object.assign(n,{async:!0}):{async:!0};let a=t._zod.run({value:i,issues:[]},r);if(a instanceof Promise&&(a=await a),a.issues.length){const t=new(o?.Err??e)(a.issues.map(e=>Oe(e,r,ie())));throw me(t,o?.callee),t}return a.value},Ie=e=>(t,i,n)=>{const o=n?{...n,async:!1}:{async:!1},r=t._zod.run({value:i,issues:[]},o);if(r instanceof Promise)throw new Q;return r.issues.length?{success:!1,error:new(e??Ne)(r.issues.map(e=>Oe(e,o,ie())))}:{success:!0,data:r.value}},Le=Ie(je),ze=e=>async(t,i,n)=>{const o=n?Object.assign(n,{async:!0}):{async:!0};let r=t._zod.run({value:i,issues:[]},o);return r instanceof Promise&&(r=await r),r.issues.length?{success:!1,error:new e(r.issues.map(e=>Oe(e,o,ie())))}:{success:!0,data:r.value}},qe=ze(je),Pe=e=>(t,i,n)=>{const o=n?Object.assign(n,{direction:"backward"}):{direction:"backward"};return Ce(e)(t,i,o)},Me=e=>(t,i,n)=>Ce(e)(t,i,n),Ue=e=>async(t,i,n)=>{const o=n?Object.assign(n,{direction:"backward"}):{direction:"backward"};return Re(e)(t,i,o)},Fe=e=>async(t,i,n)=>Re(e)(t,i,n),De=e=>(t,i,n)=>{const o=n?Object.assign(n,{direction:"backward"}):{direction:"backward"};return Ie(e)(t,i,o)},He=e=>(t,i,n)=>Ie(e)(t,i,n),Be=e=>async(t,i,n)=>{const o=n?Object.assign(n,{direction:"backward"}):{direction:"backward"};return ze(e)(t,i,o)},Ve=e=>async(t,i,n)=>ze(e)(t,i,n),Je=/^[cC][^\s-]{8,}$/,Ke=/^[0-9a-z]+$/,Ye=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Ge=/^[0-9a-vA-V]{20}$/,We=/^[A-Za-z0-9]{27}$/,Ze=/^[a-zA-Z0-9_-]{21}$/,Xe=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,Qe=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,et=e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,tt=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,it=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,nt=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,ot=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,rt=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,at=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,st=/^[A-Za-z0-9_-]*$/,lt=/^\+[1-9]\d{6,14}$/,ct="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",dt=new RegExp(`^${ct}$`);function ut(e){const t="(?:[01]\\d|2[0-3]):[0-5]\\d";return"number"==typeof e.precision?-1===e.precision?`${t}`:0===e.precision?`${t}:[0-5]\\d`:`${t}:[0-5]\\d\\.\\d{${e.precision}}`:`${t}(?::[0-5]\\d(?:\\.\\d+)?)?`}const pt=/^-?\d+$/,mt=/^-?\d+(?:\.\d+)?$/,ht=/^(?:true|false)$/i,ft=/^[^A-Z]*$/,gt=/^[^a-z]*$/,vt=X("$ZodCheck",(e,t)=>{var i;e._zod??(e._zod={}),e._zod.def=t,(i=e._zod).onattach??(i.onattach=[])}),yt={number:"number",bigint:"bigint",object:"date"},bt=X("$ZodCheckLessThan",(e,t)=>{vt.init(e,t);const i=yt[typeof t.value];e._zod.onattach.push(e=>{const i=e._zod.bag,n=(t.inclusive?i.maximum:i.exclusiveMaximum)??Number.POSITIVE_INFINITY;t.value<n&&(t.inclusive?i.maximum=t.value:i.exclusiveMaximum=t.value)}),e._zod.check=n=>{(t.inclusive?n.value<=t.value:n.value<t.value)||n.issues.push({origin:i,code:"too_big",maximum:"object"==typeof t.value?t.value.getTime():t.value,input:n.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),_t=X("$ZodCheckGreaterThan",(e,t)=>{vt.init(e,t);const i=yt[typeof t.value];e._zod.onattach.push(e=>{const i=e._zod.bag,n=(t.inclusive?i.minimum:i.exclusiveMinimum)??Number.NEGATIVE_INFINITY;t.value>n&&(t.inclusive?i.minimum=t.value:i.exclusiveMinimum=t.value)}),e._zod.check=n=>{(t.inclusive?n.value>=t.value:n.value>t.value)||n.issues.push({origin:i,code:"too_small",minimum:"object"==typeof t.value?t.value.getTime():t.value,input:n.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),wt=X("$ZodCheckMultipleOf",(e,t)=>{vt.init(e,t),e._zod.onattach.push(e=>{var i;(i=e._zod.bag).multipleOf??(i.multipleOf=t.value)}),e._zod.check=i=>{if(typeof i.value!=typeof t.value)throw new Error("Cannot mix number and bigint in multiple_of check.");("bigint"==typeof i.value?i.value%t.value===BigInt(0):0===function(e,t){const i=(e.toString().split(".")[1]||"").length,n=t.toString();let o=(n.split(".")[1]||"").length;if(0===o&&/\d?e-\d?/.test(n)){const e=n.match(/\d?e-(\d?)/);e?.[1]&&(o=Number.parseInt(e[1]))}const r=i>o?i:o;return Number.parseInt(e.toFixed(r).replace(".",""))%Number.parseInt(t.toFixed(r).replace(".",""))/10**r}(i.value,t.value))||i.issues.push({origin:typeof i.value,code:"not_multiple_of",divisor:t.value,input:i.value,inst:e,continue:!t.abort})}}),kt=X("$ZodCheckNumberFormat",(e,t)=>{vt.init(e,t),t.format=t.format||"float64";const i=t.format?.includes("int"),n=i?"int":"number",[o,r]=ke[t.format];e._zod.onattach.push(e=>{const n=e._zod.bag;n.format=t.format,n.minimum=o,n.maximum=r,i&&(n.pattern=pt)}),e._zod.check=a=>{const s=a.value;if(i){if(!Number.isInteger(s))return void a.issues.push({expected:n,format:t.format,code:"invalid_type",continue:!1,input:s,inst:e});if(!Number.isSafeInteger(s))return void(s>0?a.issues.push({input:s,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:n,inclusive:!0,continue:!t.abort}):a.issues.push({input:s,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:n,inclusive:!0,continue:!t.abort}))}s<o&&a.issues.push({origin:"number",input:s,code:"too_small",minimum:o,inclusive:!0,inst:e,continue:!t.abort}),s>r&&a.issues.push({origin:"number",input:s,code:"too_big",maximum:r,inclusive:!0,inst:e,continue:!t.abort})}}),xt=X("$ZodCheckMaxLength",(e,t)=>{var i;vt.init(e,t),(i=e._zod.def).when??(i.when=e=>{const t=e.value;return!ae(t)&&void 0!==t.length}),e._zod.onattach.push(e=>{const i=e._zod.bag.maximum??Number.POSITIVE_INFINITY;t.maximum<i&&(e._zod.bag.maximum=t.maximum)}),e._zod.check=i=>{const n=i.value;if(n.length<=t.maximum)return;const o=Te(n);i.issues.push({origin:o,code:"too_big",maximum:t.maximum,inclusive:!0,input:n,inst:e,continue:!t.abort})}}),St=X("$ZodCheckMinLength",(e,t)=>{var i;vt.init(e,t),(i=e._zod.def).when??(i.when=e=>{const t=e.value;return!ae(t)&&void 0!==t.length}),e._zod.onattach.push(e=>{const i=e._zod.bag.minimum??Number.NEGATIVE_INFINITY;t.minimum>i&&(e._zod.bag.minimum=t.minimum)}),e._zod.check=i=>{const n=i.value;if(n.length>=t.minimum)return;const o=Te(n);i.issues.push({origin:o,code:"too_small",minimum:t.minimum,inclusive:!0,input:n,inst:e,continue:!t.abort})}}),Et=X("$ZodCheckLengthEquals",(e,t)=>{var i;vt.init(e,t),(i=e._zod.def).when??(i.when=e=>{const t=e.value;return!ae(t)&&void 0!==t.length}),e._zod.onattach.push(e=>{const i=e._zod.bag;i.minimum=t.length,i.maximum=t.length,i.length=t.length}),e._zod.check=i=>{const n=i.value,o=n.length;if(o===t.length)return;const r=Te(n),a=o>t.length;i.issues.push({origin:r,...a?{code:"too_big",maximum:t.length}:{code:"too_small",minimum:t.length},inclusive:!0,exact:!0,input:i.value,inst:e,continue:!t.abort})}}),Ot=X("$ZodCheckStringFormat",(e,t)=>{var i,n;vt.init(e,t),e._zod.onattach.push(e=>{const i=e._zod.bag;i.format=t.format,t.pattern&&(i.patterns??(i.patterns=new Set),i.patterns.add(t.pattern))}),t.pattern?(i=e._zod).check??(i.check=i=>{t.pattern.lastIndex=0,t.pattern.test(i.value)||i.issues.push({origin:"string",code:"invalid_format",format:t.format,input:i.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})}):(n=e._zod).check??(n.check=()=>{})}),Tt=X("$ZodCheckRegex",(e,t)=>{Ot.init(e,t),e._zod.check=i=>{t.pattern.lastIndex=0,t.pattern.test(i.value)||i.issues.push({origin:"string",code:"invalid_format",format:"regex",input:i.value,pattern:t.pattern.toString(),inst:e,continue:!t.abort})}}),At=X("$ZodCheckLowerCase",(e,t)=>{t.pattern??(t.pattern=ft),Ot.init(e,t)}),$t=X("$ZodCheckUpperCase",(e,t)=>{t.pattern??(t.pattern=gt),Ot.init(e,t)}),Nt=X("$ZodCheckIncludes",(e,t)=>{vt.init(e,t);const i=be(t.includes),n=new RegExp("number"==typeof t.position?`^.{${t.position}}${i}`:i);t.pattern=n,e._zod.onattach.push(e=>{const t=e._zod.bag;t.patterns??(t.patterns=new Set),t.patterns.add(n)}),e._zod.check=i=>{i.value.includes(t.includes,t.position)||i.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:t.includes,input:i.value,inst:e,continue:!t.abort})}}),jt=X("$ZodCheckStartsWith",(e,t)=>{vt.init(e,t);const i=new RegExp(`^${be(t.prefix)}.*`);t.pattern??(t.pattern=i),e._zod.onattach.push(e=>{const t=e._zod.bag;t.patterns??(t.patterns=new Set),t.patterns.add(i)}),e._zod.check=i=>{i.value.startsWith(t.prefix)||i.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:t.prefix,input:i.value,inst:e,continue:!t.abort})}}),Ct=X("$ZodCheckEndsWith",(e,t)=>{vt.init(e,t);const i=new RegExp(`.*${be(t.suffix)}$`);t.pattern??(t.pattern=i),e._zod.onattach.push(e=>{const t=e._zod.bag;t.patterns??(t.patterns=new Set),t.patterns.add(i)}),e._zod.check=i=>{i.value.endsWith(t.suffix)||i.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:t.suffix,input:i.value,inst:e,continue:!t.abort})}}),Rt=X("$ZodCheckOverwrite",(e,t)=>{vt.init(e,t),e._zod.check=e=>{e.value=t.tx(e.value)}});class It{constructor(e=[]){this.content=[],this.indent=0,this&&(this.args=e)}indented(e){this.indent+=1,e(this),this.indent-=1}write(e){if("function"==typeof e)return e(this,{execution:"sync"}),void e(this,{execution:"async"});const t=e.split("\n").filter(e=>e),i=Math.min(...t.map(e=>e.length-e.trimStart().length)),n=t.map(e=>e.slice(i)).map(e=>" ".repeat(2*this.indent)+e);for(const e of n)this.content.push(e)}compile(){const e=Function,t=this?.args;return new e(...t,[...(this?.content??[""]).map(e=>` ${e}`)].join("\n"))}}const Lt={major:4,minor:3,patch:6},zt=X("$ZodType",(e,t)=>{var i;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=Lt;const n=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&n.unshift(e);for(const t of n)for(const i of t._zod.onattach)i(e);if(0===n.length)(i=e._zod).deferred??(i.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const t=(e,t,i)=>{let n,o=xe(e);for(const r of t){if(r._zod.def.when){if(!r._zod.def.when(e))continue}else if(o)continue;const t=e.issues.length,a=r._zod.check(e);if(a instanceof Promise&&!1===i?.async)throw new Q;if(n||a instanceof Promise)n=(n??Promise.resolve()).then(async()=>{await a,e.issues.length!==t&&(o||(o=xe(e,t)))});else{if(e.issues.length===t)continue;o||(o=xe(e,t))}}return n?n.then(()=>e):e},i=(i,o,r)=>{if(xe(i))return i.aborted=!0,i;const a=t(o,n,r);if(a instanceof Promise){if(!1===r.async)throw new Q;return a.then(t=>e._zod.parse(t,r))}return e._zod.parse(a,r)};e._zod.run=(o,r)=>{if(r.skipChecks)return e._zod.parse(o,r);if("backward"===r.direction){const t=e._zod.parse({value:o.value,issues:[]},{...r,skipChecks:!0});return t instanceof Promise?t.then(e=>i(e,o,r)):i(t,o,r)}const a=e._zod.parse(o,r);if(a instanceof Promise){if(!1===r.async)throw new Q;return a.then(e=>t(e,n,r))}return t(a,n,r)}}ce(e,"~standard",()=>({validate:t=>{try{const i=Le(e,t);return i.success?{value:i.data}:{issues:i.error?.issues}}catch(i){return qe(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:"zod",version:1}))}),qt=X("$ZodString",(e,t)=>{var i;zt.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??(i=e._zod.bag,new RegExp(`^${i?`[\\s\\S]{${i?.minimum??0},${i?.maximum??""}}`:"[\\s\\S]*"}$`)),e._zod.parse=(i,n)=>{if(t.coerce)try{i.value=String(i.value)}catch(n){}return"string"==typeof i.value||i.issues.push({expected:"string",code:"invalid_type",input:i.value,inst:e}),i}}),Pt=X("$ZodStringFormat",(e,t)=>{Ot.init(e,t),qt.init(e,t)}),Mt=X("$ZodGUID",(e,t)=>{t.pattern??(t.pattern=Qe),Pt.init(e,t)}),Ut=X("$ZodUUID",(e,t)=>{if(t.version){const e={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[t.version];if(void 0===e)throw new Error(`Invalid UUID version: "${t.version}"`);t.pattern??(t.pattern=et(e))}else t.pattern??(t.pattern=et());Pt.init(e,t)}),Ft=X("$ZodEmail",(e,t)=>{t.pattern??(t.pattern=tt),Pt.init(e,t)}),Dt=X("$ZodURL",(e,t)=>{Pt.init(e,t),e._zod.check=i=>{try{const n=i.value.trim(),o=new URL(n);return t.hostname&&(t.hostname.lastIndex=0,t.hostname.test(o.hostname)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:t.hostname.source,input:i.value,inst:e,continue:!t.abort})),t.protocol&&(t.protocol.lastIndex=0,t.protocol.test(o.protocol.endsWith(":")?o.protocol.slice(0,-1):o.protocol)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:t.protocol.source,input:i.value,inst:e,continue:!t.abort})),void(t.normalize?i.value=o.href:i.value=n)}catch(n){i.issues.push({code:"invalid_format",format:"url",input:i.value,inst:e,continue:!t.abort})}}}),Ht=X("$ZodEmoji",(e,t)=>{t.pattern??(t.pattern=new RegExp("^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$","u")),Pt.init(e,t)}),Bt=X("$ZodNanoID",(e,t)=>{t.pattern??(t.pattern=Ze),Pt.init(e,t)}),Vt=X("$ZodCUID",(e,t)=>{t.pattern??(t.pattern=Je),Pt.init(e,t)}),Jt=X("$ZodCUID2",(e,t)=>{t.pattern??(t.pattern=Ke),Pt.init(e,t)}),Kt=X("$ZodULID",(e,t)=>{t.pattern??(t.pattern=Ye),Pt.init(e,t)}),Yt=X("$ZodXID",(e,t)=>{t.pattern??(t.pattern=Ge),Pt.init(e,t)}),Gt=X("$ZodKSUID",(e,t)=>{t.pattern??(t.pattern=We),Pt.init(e,t)}),Wt=X("$ZodISODateTime",(e,t)=>{t.pattern??(t.pattern=function(e){const t=ut({precision:e.precision}),i=["Z"];e.local&&i.push(""),e.offset&&i.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const n=`${t}(?:${i.join("|")})`;return new RegExp(`^${ct}T(?:${n})$`)}(t)),Pt.init(e,t)}),Zt=X("$ZodISODate",(e,t)=>{t.pattern??(t.pattern=dt),Pt.init(e,t)}),Xt=X("$ZodISOTime",(e,t)=>{t.pattern??(t.pattern=new RegExp(`^${ut(t)}$`)),Pt.init(e,t)}),Qt=X("$ZodISODuration",(e,t)=>{t.pattern??(t.pattern=Xe),Pt.init(e,t)}),ei=X("$ZodIPv4",(e,t)=>{t.pattern??(t.pattern=it),Pt.init(e,t),e._zod.bag.format="ipv4"}),ti=X("$ZodIPv6",(e,t)=>{t.pattern??(t.pattern=nt),Pt.init(e,t),e._zod.bag.format="ipv6",e._zod.check=i=>{try{new URL(`http://[${i.value}]`)}catch{i.issues.push({code:"invalid_format",format:"ipv6",input:i.value,inst:e,continue:!t.abort})}}}),ii=X("$ZodCIDRv4",(e,t)=>{t.pattern??(t.pattern=ot),Pt.init(e,t)}),ni=X("$ZodCIDRv6",(e,t)=>{t.pattern??(t.pattern=rt),Pt.init(e,t),e._zod.check=i=>{const n=i.value.split("/");try{if(2!==n.length)throw new Error;const[e,t]=n;if(!t)throw new Error;const i=Number(t);if(`${i}`!==t)throw new Error;if(i<0||i>128)throw new Error;new URL(`http://[${e}]`)}catch{i.issues.push({code:"invalid_format",format:"cidrv6",input:i.value,inst:e,continue:!t.abort})}}});function oi(e){if(""===e)return!0;if(e.length%4!=0)return!1;try{return atob(e),!0}catch{return!1}}const ri=X("$ZodBase64",(e,t)=>{t.pattern??(t.pattern=at),Pt.init(e,t),e._zod.bag.contentEncoding="base64",e._zod.check=i=>{oi(i.value)||i.issues.push({code:"invalid_format",format:"base64",input:i.value,inst:e,continue:!t.abort})}}),ai=X("$ZodBase64URL",(e,t)=>{t.pattern??(t.pattern=st),Pt.init(e,t),e._zod.bag.contentEncoding="base64url",e._zod.check=i=>{(function(e){if(!st.test(e))return!1;const t=e.replace(/[-_]/g,e=>"-"===e?"+":"/");return oi(t.padEnd(4*Math.ceil(t.length/4),"="))})(i.value)||i.issues.push({code:"invalid_format",format:"base64url",input:i.value,inst:e,continue:!t.abort})}}),si=X("$ZodE164",(e,t)=>{t.pattern??(t.pattern=lt),Pt.init(e,t)}),li=X("$ZodJWT",(e,t)=>{Pt.init(e,t),e._zod.check=i=>{(function(e,t=null){try{const i=e.split(".");if(3!==i.length)return!1;const[n]=i;if(!n)return!1;const o=JSON.parse(atob(n));return!("typ"in o&&"JWT"!==o?.typ||!o.alg||t&&(!("alg"in o)||o.alg!==t))}catch{return!1}})(i.value,t.alg)||i.issues.push({code:"invalid_format",format:"jwt",input:i.value,inst:e,continue:!t.abort})}}),ci=X("$ZodNumber",(e,t)=>{zt.init(e,t),e._zod.pattern=e._zod.bag.pattern??mt,e._zod.parse=(i,n)=>{if(t.coerce)try{i.value=Number(i.value)}catch(e){}const o=i.value;if("number"==typeof o&&!Number.isNaN(o)&&Number.isFinite(o))return i;const r="number"==typeof o?Number.isNaN(o)?"NaN":Number.isFinite(o)?void 0:"Infinity":void 0;return i.issues.push({expected:"number",code:"invalid_type",input:o,inst:e,...r?{received:r}:{}}),i}}),di=X("$ZodNumberFormat",(e,t)=>{kt.init(e,t),ci.init(e,t)}),ui=X("$ZodBoolean",(e,t)=>{zt.init(e,t),e._zod.pattern=ht,e._zod.parse=(i,n)=>{if(t.coerce)try{i.value=Boolean(i.value)}catch(e){}const o=i.value;return"boolean"==typeof o||i.issues.push({expected:"boolean",code:"invalid_type",input:o,inst:e}),i}}),pi=X("$ZodUnknown",(e,t)=>{zt.init(e,t),e._zod.parse=e=>e}),mi=X("$ZodNever",(e,t)=>{zt.init(e,t),e._zod.parse=(t,i)=>(t.issues.push({expected:"never",code:"invalid_type",input:t.value,inst:e}),t)});function hi(e,t,i){e.issues.length&&t.issues.push(...Se(i,e.issues)),t.value[i]=e.value}const fi=X("$ZodArray",(e,t)=>{zt.init(e,t),e._zod.parse=(i,n)=>{const o=i.value;if(!Array.isArray(o))return i.issues.push({expected:"array",code:"invalid_type",input:o,inst:e}),i;i.value=Array(o.length);const r=[];for(let e=0;e<o.length;e++){const a=o[e],s=t.element._zod.run({value:a,issues:[]},n);s instanceof Promise?r.push(s.then(t=>hi(t,i,e))):hi(s,i,e)}return r.length?Promise.all(r).then(()=>i):i}});function gi(e,t,i,n,o){if(e.issues.length){if(o&&!(i in n))return;t.issues.push(...Se(i,e.issues))}void 0===e.value?i in n&&(t.value[i]=void 0):t.value[i]=e.value}function vi(e){const t=Object.keys(e.shape);for(const i of t)if(!e.shape?.[i]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${i}": expected a Zod schema`);const i=(n=e.shape,Object.keys(n).filter(e=>"optional"===n[e]._zod.optin&&"optional"===n[e]._zod.optout));var n;return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(i)}}function yi(e,t,i,n,o,r){const a=[],s=o.keySet,l=o.catchall._zod,c=l.def.type,d="optional"===l.optout;for(const o in t){if(s.has(o))continue;if("never"===c){a.push(o);continue}const r=l.run({value:t[o],issues:[]},n);r instanceof Promise?e.push(r.then(e=>gi(e,i,o,t,d))):gi(r,i,o,t,d)}return a.length&&i.issues.push({code:"unrecognized_keys",keys:a,input:t,inst:r}),e.length?Promise.all(e).then(()=>i):i}const bi=X("$ZodObject",(e,t)=>{zt.init(e,t);const i=Object.getOwnPropertyDescriptor(t,"shape");if(!i?.get){const e=t.shape;Object.defineProperty(t,"shape",{get:()=>{const i={...e};return Object.defineProperty(t,"shape",{value:i}),i}})}const n=re(()=>vi(t));ce(e._zod,"propValues",()=>{const e=t.shape,i={};for(const t in e){const n=e[t]._zod;if(n.values){i[t]??(i[t]=new Set);for(const e of n.values)i[t].add(e)}}return i});const o=he,r=t.catchall;let a;e._zod.parse=(t,i)=>{a??(a=n.value);const s=t.value;if(!o(s))return t.issues.push({expected:"object",code:"invalid_type",input:s,inst:e}),t;t.value={};const l=[],c=a.shape;for(const e of a.keys){const n=c[e],o="optional"===n._zod.optout,r=n._zod.run({value:s[e],issues:[]},i);r instanceof Promise?l.push(r.then(i=>gi(i,t,e,s,o))):gi(r,t,e,s,o)}return r?yi(l,s,t,i,n.value,e):l.length?Promise.all(l).then(()=>t):t}}),_i=X("$ZodObjectJIT",(e,t)=>{bi.init(e,t);const i=e._zod.parse,n=re(()=>vi(t));let o;const r=he,a=!te.jitless,s=a&&fe.value,l=t.catchall;let c;e._zod.parse=(d,u)=>{c??(c=n.value);const p=d.value;return r(p)?a&&s&&!1===u?.async&&!0!==u.jitless?(o||(o=(e=>{const t=new It(["shape","payload","ctx"]),i=n.value,o=e=>{const t=pe(e);return`shape[${t}]._zod.run({ value: input[${t}], issues: [] }, ctx)`};t.write("const input = payload.value;");const r=Object.create(null);let a=0;for(const e of i.keys)r[e]="key_"+a++;t.write("const newResult = {};");for(const n of i.keys){const i=r[n],a=pe(n),s=e[n],l="optional"===s?._zod?.optout;t.write(`const ${i} = ${o(n)};`),l?t.write(`\n if (${i}.issues.length) {\n if (${a} in input) {\n payload.issues = payload.issues.concat(${i}.issues.map(iss => ({\n ...iss,\n path: iss.path ? [${a}, ...iss.path] : [${a}]\n })));\n }\n }\n \n if (${i}.value === undefined) {\n if (${a} in input) {\n newResult[${a}] = undefined;\n }\n } else {\n newResult[${a}] = ${i}.value;\n }\n \n `):t.write(`\n if (${i}.issues.length) {\n payload.issues = payload.issues.concat(${i}.issues.map(iss => ({\n ...iss,\n path: iss.path ? [${a}, ...iss.path] : [${a}]\n })));\n }\n \n if (${i}.value === undefined) {\n if (${a} in input) {\n newResult[${a}] = undefined;\n }\n } else {\n newResult[${a}] = ${i}.value;\n }\n \n `)}t.write("payload.value = newResult;"),t.write("return payload;");const s=t.compile();return(t,i)=>s(e,t,i)})(t.shape)),d=o(d,u),l?yi([],p,d,u,c,e):d):i(d,u):(d.issues.push({expected:"object",code:"invalid_type",input:p,inst:e}),d)}});function wi(e,t,i,n){for(const i of e)if(0===i.issues.length)return t.value=i.value,t;const o=e.filter(e=>!xe(e));return 1===o.length?(t.value=o[0].value,o[0]):(t.issues.push({code:"invalid_union",input:t.value,inst:i,errors:e.map(e=>e.issues.map(e=>Oe(e,n,ie())))}),t)}const ki=X("$ZodUnion",(e,t)=>{zt.init(e,t),ce(e._zod,"optin",()=>t.options.some(e=>"optional"===e._zod.optin)?"optional":void 0),ce(e._zod,"optout",()=>t.options.some(e=>"optional"===e._zod.optout)?"optional":void 0),ce(e._zod,"values",()=>{if(t.options.every(e=>e._zod.values))return new Set(t.options.flatMap(e=>Array.from(e._zod.values)))}),ce(e._zod,"pattern",()=>{if(t.options.every(e=>e._zod.pattern)){const e=t.options.map(e=>e._zod.pattern);return new RegExp(`^(${e.map(e=>se(e.source)).join("|")})$`)}});const i=1===t.options.length,n=t.options[0]._zod.run;e._zod.parse=(o,r)=>{if(i)return n(o,r);let a=!1;const s=[];for(const e of t.options){const t=e._zod.run({value:o.value,issues:[]},r);if(t instanceof Promise)s.push(t),a=!0;else{if(0===t.issues.length)return t;s.push(t)}}return a?Promise.all(s).then(t=>wi(t,o,e,r)):wi(s,o,e,r)}}),xi=X("$ZodIntersection",(e,t)=>{zt.init(e,t),e._zod.parse=(e,i)=>{const n=e.value,o=t.left._zod.run({value:n,issues:[]},i),r=t.right._zod.run({value:n,issues:[]},i);return o instanceof Promise||r instanceof Promise?Promise.all([o,r]).then(([t,i])=>Ei(e,t,i)):Ei(e,o,r)}});function Si(e,t){if(e===t)return{valid:!0,data:e};if(e instanceof Date&&t instanceof Date&&+e===+t)return{valid:!0,data:e};if(ge(e)&&ge(t)){const i=Object.keys(t),n=Object.keys(e).filter(e=>-1!==i.indexOf(e)),o={...e,...t};for(const i of n){const n=Si(e[i],t[i]);if(!n.valid)return{valid:!1,mergeErrorPath:[i,...n.mergeErrorPath]};o[i]=n.data}return{valid:!0,data:o}}if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return{valid:!1,mergeErrorPath:[]};const i=[];for(let n=0;n<e.length;n++){const o=Si(e[n],t[n]);if(!o.valid)return{valid:!1,mergeErrorPath:[n,...o.mergeErrorPath]};i.push(o.data)}return{valid:!0,data:i}}return{valid:!1,mergeErrorPath:[]}}function Ei(e,t,i){const n=new Map;let o;for(const i of t.issues)if("unrecognized_keys"===i.code){o??(o=i);for(const e of i.keys)n.has(e)||n.set(e,{}),n.get(e).l=!0}else e.issues.push(i);for(const t of i.issues)if("unrecognized_keys"===t.code)for(const e of t.keys)n.has(e)||n.set(e,{}),n.get(e).r=!0;else e.issues.push(t);const r=[...n].filter(([,e])=>e.l&&e.r).map(([e])=>e);if(r.length&&o&&e.issues.push({...o,keys:r}),xe(e))return e;const a=Si(t.value,i.value);if(!a.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(a.mergeErrorPath)}`);return e.value=a.data,e}const Oi=X("$ZodRecord",(e,t)=>{zt.init(e,t),e._zod.parse=(i,n)=>{const o=i.value;if(!ge(o))return i.issues.push({expected:"record",code:"invalid_type",input:o,inst:e}),i;const r=[],a=t.keyType._zod.values;if(a){i.value={};const s=new Set;for(const e of a)if("string"==typeof e||"number"==typeof e||"symbol"==typeof e){s.add("number"==typeof e?e.toString():e);const a=t.valueType._zod.run({value:o[e],issues:[]},n);a instanceof Promise?r.push(a.then(t=>{t.issues.length&&i.issues.push(...Se(e,t.issues)),i.value[e]=t.value})):(a.issues.length&&i.issues.push(...Se(e,a.issues)),i.value[e]=a.value)}let l;for(const e in o)s.has(e)||(l=l??[],l.push(e));l&&l.length>0&&i.issues.push({code:"unrecognized_keys",input:o,inst:e,keys:l})}else{i.value={};for(const a of Reflect.ownKeys(o)){if("__proto__"===a)continue;let s=t.keyType._zod.run({value:a,issues:[]},n);if(s instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if("string"==typeof a&&mt.test(a)&&s.issues.length){const e=t.keyType._zod.run({value:Number(a),issues:[]},n);if(e instanceof Promise)throw new Error("Async schemas not supported in object keys currently");0===e.issues.length&&(s=e)}if(s.issues.length){"loose"===t.mode?i.value[a]=o[a]:i.issues.push({code:"invalid_key",origin:"record",issues:s.issues.map(e=>Oe(e,n,ie())),input:a,path:[a],inst:e});continue}const l=t.valueType._zod.run({value:o[a],issues:[]},n);l instanceof Promise?r.push(l.then(e=>{e.issues.length&&i.issues.push(...Se(a,e.issues)),i.value[s.value]=e.value})):(l.issues.length&&i.issues.push(...Se(a,l.issues)),i.value[s.value]=l.value)}}return r.length?Promise.all(r).then(()=>i):i}}),Ti=X("$ZodEnum",(e,t)=>{zt.init(e,t);const i=ne(t.entries),n=new Set(i);e._zod.values=n,e._zod.pattern=new RegExp(`^(${i.filter(e=>ye.has(typeof e)).map(e=>"string"==typeof e?be(e):e.toString()).join("|")})$`),e._zod.parse=(t,o)=>{const r=t.value;return n.has(r)||t.issues.push({code:"invalid_value",values:i,input:r,inst:e}),t}}),Ai=X("$ZodTransform",(e,t)=>{zt.init(e,t),e._zod.parse=(i,n)=>{if("backward"===n.direction)throw new ee(e.constructor.name);const o=t.transform(i.value,i);if(n.async)return(o instanceof Promise?o:Promise.resolve(o)).then(e=>(i.value=e,i));if(o instanceof Promise)throw new Q;return i.value=o,i}});function $i(e,t){return e.issues.length&&void 0===t?{issues:[],value:void 0}:e}const Ni=X("$ZodOptional",(e,t)=>{zt.init(e,t),e._zod.optin="optional",e._zod.optout="optional",ce(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),ce(e._zod,"pattern",()=>{const e=t.innerType._zod.pattern;return e?new RegExp(`^(${se(e.source)})?$`):void 0}),e._zod.parse=(e,i)=>{if("optional"===t.innerType._zod.optin){const n=t.innerType._zod.run(e,i);return n instanceof Promise?n.then(t=>$i(t,e.value)):$i(n,e.value)}return void 0===e.value?e:t.innerType._zod.run(e,i)}}),ji=X("$ZodExactOptional",(e,t)=>{Ni.init(e,t),ce(e._zod,"values",()=>t.innerType._zod.values),ce(e._zod,"pattern",()=>t.innerType._zod.pattern),e._zod.parse=(e,i)=>t.innerType._zod.run(e,i)}),Ci=X("$ZodNullable",(e,t)=>{zt.init(e,t),ce(e._zod,"optin",()=>t.innerType._zod.optin),ce(e._zod,"optout",()=>t.innerType._zod.optout),ce(e._zod,"pattern",()=>{const e=t.innerType._zod.pattern;return e?new RegExp(`^(${se(e.source)}|null)$`):void 0}),ce(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,null]):void 0),e._zod.parse=(e,i)=>null===e.value?e:t.innerType._zod.run(e,i)}),Ri=X("$ZodDefault",(e,t)=>{zt.init(e,t),e._zod.optin="optional",ce(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(e,i)=>{if("backward"===i.direction)return t.innerType._zod.run(e,i);if(void 0===e.value)return e.value=t.defaultValue,e;const n=t.innerType._zod.run(e,i);return n instanceof Promise?n.then(e=>Ii(e,t)):Ii(n,t)}});function Ii(e,t){return void 0===e.value&&(e.value=t.defaultValue),e}const Li=X("$ZodPrefault",(e,t)=>{zt.init(e,t),e._zod.optin="optional",ce(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(e,i)=>("backward"===i.direction||void 0===e.value&&(e.value=t.defaultValue),t.innerType._zod.run(e,i))}),zi=X("$ZodNonOptional",(e,t)=>{zt.init(e,t),ce(e._zod,"values",()=>{const e=t.innerType._zod.values;return e?new Set([...e].filter(e=>void 0!==e)):void 0}),e._zod.parse=(i,n)=>{const o=t.innerType._zod.run(i,n);return o instanceof Promise?o.then(t=>qi(t,e)):qi(o,e)}});function qi(e,t){return e.issues.length||void 0!==e.value||e.issues.push({code:"invalid_type",expected:"nonoptional",input:e.value,inst:t}),e}const Pi=X("$ZodCatch",(e,t)=>{zt.init(e,t),ce(e._zod,"optin",()=>t.innerType._zod.optin),ce(e._zod,"optout",()=>t.innerType._zod.optout),ce(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(e,i)=>{if("backward"===i.direction)return t.innerType._zod.run(e,i);const n=t.innerType._zod.run(e,i);return n instanceof Promise?n.then(n=>(e.value=n.value,n.issues.length&&(e.value=t.catchValue({...e,error:{issues:n.issues.map(e=>Oe(e,i,ie()))},input:e.value}),e.issues=[]),e)):(e.value=n.value,n.issues.length&&(e.value=t.catchValue({...e,error:{issues:n.issues.map(e=>Oe(e,i,ie()))},input:e.value}),e.issues=[]),e)}}),Mi=X("$ZodPipe",(e,t)=>{zt.init(e,t),ce(e._zod,"values",()=>t.in._zod.values),ce(e._zod,"optin",()=>t.in._zod.optin),ce(e._zod,"optout",()=>t.out._zod.optout),ce(e._zod,"propValues",()=>t.in._zod.propValues),e._zod.parse=(e,i)=>{if("backward"===i.direction){const n=t.out._zod.run(e,i);return n instanceof Promise?n.then(e=>Ui(e,t.in,i)):Ui(n,t.in,i)}const n=t.in._zod.run(e,i);return n instanceof Promise?n.then(e=>Ui(e,t.out,i)):Ui(n,t.out,i)}});function Ui(e,t,i){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues},i)}const Fi=X("$ZodReadonly",(e,t)=>{zt.init(e,t),ce(e._zod,"propValues",()=>t.innerType._zod.propValues),ce(e._zod,"values",()=>t.innerType._zod.values),ce(e._zod,"optin",()=>t.innerType?._zod?.optin),ce(e._zod,"optout",()=>t.innerType?._zod?.optout),e._zod.parse=(e,i)=>{if("backward"===i.direction)return t.innerType._zod.run(e,i);const n=t.innerType._zod.run(e,i);return n instanceof Promise?n.then(Di):Di(n)}});function Di(e){return e.value=Object.freeze(e.value),e}const Hi=X("$ZodCustom",(e,t)=>{vt.init(e,t),zt.init(e,t),e._zod.parse=(e,t)=>e,e._zod.check=i=>{const n=i.value,o=t.fn(n);if(o instanceof Promise)return o.then(t=>Bi(t,i,n,e));Bi(o,i,n,e)}});function Bi(e,t,i,n){if(!e){const e={code:"custom",input:i,inst:n,path:[...n._zod.def.path??[]],continue:!n._zod.def.abort};n._zod.def.params&&(e.params=n._zod.def.params),t.issues.push(Ae(e))}}var Vi;(Vi=globalThis).__zod_globalRegistry??(Vi.__zod_globalRegistry=new class{constructor(){this._map=new WeakMap,this._idmap=new Map}add(e,...t){const i=t[0];return this._map.set(e,i),i&&"object"==typeof i&&"id"in i&&this._idmap.set(i.id,e),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(e){const t=this._map.get(e);return t&&"object"==typeof t&&"id"in t&&this._idmap.delete(t.id),this._map.delete(e),this}get(e){const t=e._zod.parent;if(t){const i={...this.get(t)??{}};delete i.id;const n={...i,...this._map.get(e)};return Object.keys(n).length?n:void 0}return this._map.get(e)}has(e){return this._map.has(e)}});const Ji=globalThis.__zod_globalRegistry;function Ki(e,t){return new e({type:"string",format:"guid",check:"string_format",abort:!1,...we(t)})}function Yi(e,t){return new bt({check:"less_than",...we(t),value:e,inclusive:!1})}function Gi(e,t){return new bt({check:"less_than",...we(t),value:e,inclusive:!0})}function Wi(e,t){return new _t({check:"greater_than",...we(t),value:e,inclusive:!1})}function Zi(e,t){return new _t({check:"greater_than",...we(t),value:e,inclusive:!0})}function Xi(e,t){return new wt({check:"multiple_of",...we(t),value:e})}function Qi(e,t){return new xt({check:"max_length",...we(t),maximum:e})}function en(e,t){return new St({check:"min_length",...we(t),minimum:e})}function tn(e,t){return new Et({check:"length_equals",...we(t),length:e})}function nn(e){return new Rt({check:"overwrite",tx:e})}function on(e){let t=e?.target??"draft-2020-12";return"draft-4"===t&&(t="draft-04"),"draft-7"===t&&(t="draft-07"),{processors:e.processors??{},metadataRegistry:e?.metadata??Ji,target:t,unrepresentable:e?.unrepresentable??"throw",override:e?.override??(()=>{}),io:e?.io??"output",counter:0,seen:new Map,cycles:e?.cycles??"ref",reused:e?.reused??"inline",external:e?.external??void 0}}function rn(e,t,i={path:[],schemaPath:[]}){var n;const o=e._zod.def,r=t.seen.get(e);if(r)return r.count++,i.schemaPath.includes(e)&&(r.cycle=i.path),r.schema;const a={schema:{},count:1,cycle:void 0,path:i.path};t.seen.set(e,a);const s=e._zod.toJSONSchema?.();if(s)a.schema=s;else{const n={...i,schemaPath:[...i.schemaPath,e],path:i.path};if(e._zod.processJSONSchema)e._zod.processJSONSchema(t,a.schema,n);else{const i=a.schema,r=t.processors[o.type];if(!r)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${o.type}`);r(e,t,i,n)}const r=e._zod.parent;r&&(a.ref||(a.ref=r),rn(r,t,n),t.seen.get(r).isParent=!0)}const l=t.metadataRegistry.get(e);return l&&Object.assign(a.schema,l),"input"===t.io&&ln(e)&&(delete a.schema.examples,delete a.schema.default),"input"===t.io&&a.schema._prefault&&((n=a.schema).default??(n.default=a.schema._prefault)),delete a.schema._prefault,t.seen.get(e).schema}function an(e,t){const i=e.seen.get(t);if(!i)throw new Error("Unprocessed schema. This is a bug in Zod.");const n=new Map;for(const t of e.seen.entries()){const i=e.metadataRegistry.get(t[0])?.id;if(i){const e=n.get(i);if(e&&e!==t[0])throw new Error(`Duplicate schema id "${i}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);n.set(i,t[0])}}const o=t=>{if(t[1].schema.$ref)return;const n=t[1],{ref:o,defId:r}=(t=>{const n="draft-2020-12"===e.target?"$defs":"definitions";if(e.external){const i=e.external.registry.get(t[0])?.id,o=e.external.uri??(e=>e);if(i)return{ref:o(i)};const r=t[1].defId??t[1].schema.id??"schema"+e.counter++;return t[1].defId=r,{defId:r,ref:`${o("__shared")}#/${n}/${r}`}}if(t[1]===i)return{ref:"#"};const o=`#/${n}/`,r=t[1].schema.id??"__schema"+e.counter++;return{defId:r,ref:o+r}})(t);n.def={...n.schema},r&&(n.defId=r);const a=n.schema;for(const e in a)delete a[e];a.$ref=o};if("throw"===e.cycles)for(const t of e.seen.entries()){const e=t[1];if(e.cycle)throw new Error(`Cycle detected: #/${e.cycle?.join("/")}/<root>\n\nSet the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const i of e.seen.entries()){const n=i[1];if(t===i[0]){o(i);continue}if(e.external){const n=e.external.registry.get(i[0])?.id;if(t!==i[0]&&n){o(i);continue}}const r=e.metadataRegistry.get(i[0])?.id;(r||n.cycle||n.count>1&&"ref"===e.reused)&&o(i)}}function sn(e,t){const i=e.seen.get(t);if(!i)throw new Error("Unprocessed schema. This is a bug in Zod.");const n=t=>{const i=e.seen.get(t);if(null===i.ref)return;const o=i.def??i.schema,r={...o},a=i.ref;if(i.ref=null,a){n(a);const i=e.seen.get(a),s=i.schema;if(!s.$ref||"draft-07"!==e.target&&"draft-04"!==e.target&&"openapi-3.0"!==e.target?Object.assign(o,s):(o.allOf=o.allOf??[],o.allOf.push(s)),Object.assign(o,r),t._zod.parent===a)for(const e in o)"$ref"!==e&&"allOf"!==e&&(e in r||delete o[e]);if(s.$ref&&i.def)for(const e in o)"$ref"!==e&&"allOf"!==e&&e in i.def&&JSON.stringify(o[e])===JSON.stringify(i.def[e])&&delete o[e]}const s=t._zod.parent;if(s&&s!==a){n(s);const t=e.seen.get(s);if(t?.schema.$ref&&(o.$ref=t.schema.$ref,t.def))for(const e in o)"$ref"!==e&&"allOf"!==e&&e in t.def&&JSON.stringify(o[e])===JSON.stringify(t.def[e])&&delete o[e]}e.override({zodSchema:t,jsonSchema:o,path:i.path??[]})};for(const t of[...e.seen.entries()].reverse())n(t[0]);const o={};if("draft-2020-12"===e.target?o.$schema="https://json-schema.org/draft/2020-12/schema":"draft-07"===e.target?o.$schema="http://json-schema.org/draft-07/schema#":"draft-04"===e.target?o.$schema="http://json-schema.org/draft-04/schema#":e.target,e.external?.uri){const i=e.external.registry.get(t)?.id;if(!i)throw new Error("Schema is missing an `id` property");o.$id=e.external.uri(i)}Object.assign(o,i.def??i.schema);const r=e.external?.defs??{};for(const t of e.seen.entries()){const e=t[1];e.def&&e.defId&&(r[e.defId]=e.def)}e.external||Object.keys(r).length>0&&("draft-2020-12"===e.target?o.$defs=r:o.definitions=r);try{const i=JSON.parse(JSON.stringify(o));return Object.defineProperty(i,"~standard",{value:{...t["~standard"],jsonSchema:{input:cn(t,"input",e.processors),output:cn(t,"output",e.processors)}},enumerable:!1,writable:!1}),i}catch(e){throw new Error("Error converting schema to JSON.")}}function ln(e,t){const i=t??{seen:new Set};if(i.seen.has(e))return!1;i.seen.add(e);const n=e._zod.def;if("transform"===n.type)return!0;if("array"===n.type)return ln(n.element,i);if("set"===n.type)return ln(n.valueType,i);if("lazy"===n.type)return ln(n.getter(),i);if("promise"===n.type||"optional"===n.type||"nonoptional"===n.type||"nullable"===n.type||"readonly"===n.type||"default"===n.type||"prefault"===n.type)return ln(n.innerType,i);if("intersection"===n.type)return ln(n.left,i)||ln(n.right,i);if("record"===n.type||"map"===n.type)return ln(n.keyType,i)||ln(n.valueType,i);if("pipe"===n.type)return ln(n.in,i)||ln(n.out,i);if("object"===n.type){for(const e in n.shape)if(ln(n.shape[e],i))return!0;return!1}if("union"===n.type){for(const e of n.options)if(ln(e,i))return!0;return!1}if("tuple"===n.type){for(const e of n.items)if(ln(e,i))return!0;return!(!n.rest||!ln(n.rest,i))}return!1}const cn=(e,t,i={})=>n=>{const{libraryOptions:o,target:r}=n??{},a=on({...o??{},target:r,io:t,processors:i});return rn(e,a),an(a,e),sn(a,e)},dn={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},un=(e,t,i,n)=>{const o=e._zod.def;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType},pn=X("ZodISODateTime",(e,t)=>{Wt.init(e,t),Rn.init(e,t)});const mn=X("ZodISODate",(e,t)=>{Zt.init(e,t),Rn.init(e,t)});const hn=X("ZodISOTime",(e,t)=>{Xt.init(e,t),Rn.init(e,t)});const fn=X("ZodISODuration",(e,t)=>{Qt.init(e,t),Rn.init(e,t)});const gn=X("ZodError",(e,t)=>{Ne.init(e,t),e.name="ZodError",Object.defineProperties(e,{format:{value:t=>function(e,t=e=>e.message){const i={_errors:[]},n=e=>{for(const o of e.issues)if("invalid_union"===o.code&&o.errors.length)o.errors.map(e=>n({issues:e}));else if("invalid_key"===o.code)n({issues:o.issues});else if("invalid_element"===o.code)n({issues:o.issues});else if(0===o.path.length)i._errors.push(t(o));else{let e=i,n=0;for(;n<o.path.length;){const i=o.path[n];n===o.path.length-1?(e[i]=e[i]||{_errors:[]},e[i]._errors.push(t(o))):e[i]=e[i]||{_errors:[]},e=e[i],n++}}};return n(e),i}(e,t)},flatten:{value:t=>function(e,t=e=>e.message){const i={},n=[];for(const o of e.issues)o.path.length>0?(i[o.path[0]]=i[o.path[0]]||[],i[o.path[0]].push(t(o))):n.push(t(o));return{formErrors:n,fieldErrors:i}}(e,t)},addIssue:{value:t=>{e.issues.push(t),e.message=JSON.stringify(e.issues,oe,2)}},addIssues:{value:t=>{e.issues.push(...t),e.message=JSON.stringify(e.issues,oe,2)}},isEmpty:{get:()=>0===e.issues.length}})},{Parent:Error}),vn=Ce(gn),yn=Re(gn),bn=Ie(gn),_n=ze(gn),wn=Pe(gn),kn=Me(gn),xn=Ue(gn),Sn=Fe(gn),En=De(gn),On=He(gn),Tn=Be(gn),An=Ve(gn),$n=X("ZodType",(e,t)=>(zt.init(e,t),Object.assign(e["~standard"],{jsonSchema:{input:cn(e,"input"),output:cn(e,"output")}}),e.toJSONSchema=((e,t={})=>i=>{const n=on({...i,processors:t});return rn(e,n),an(n,e),sn(n,e)})(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.check=(...i)=>e.clone(ue(t,{checks:[...t.checks??[],...i.map(e=>"function"==typeof e?{_zod:{check:e,def:{check:"custom"},onattach:[]}}:e)]}),{parent:!0}),e.with=e.check,e.clone=(t,i)=>_e(e,t,i),e.brand=()=>e,e.register=(t,i)=>(t.add(e,i),e),e.parse=(t,i)=>vn(e,t,i,{callee:e.parse}),e.safeParse=(t,i)=>bn(e,t,i),e.parseAsync=async(t,i)=>yn(e,t,i,{callee:e.parseAsync}),e.safeParseAsync=async(t,i)=>_n(e,t,i),e.spa=e.safeParseAsync,e.encode=(t,i)=>wn(e,t,i),e.decode=(t,i)=>kn(e,t,i),e.encodeAsync=async(t,i)=>xn(e,t,i),e.decodeAsync=async(t,i)=>Sn(e,t,i),e.safeEncode=(t,i)=>En(e,t,i),e.safeDecode=(t,i)=>On(e,t,i),e.safeEncodeAsync=async(t,i)=>Tn(e,t,i),e.safeDecodeAsync=async(t,i)=>An(e,t,i),e.refine=(t,i)=>e.check(function(e,t={}){return function(e,t,i){return new Ro({type:"custom",check:"custom",fn:t,...we(i)})}(0,e,t)}(t,i)),e.superRefine=t=>e.check(function(e){const t=function(e){const t=new vt({check:"custom",...we(void 0)});return t._zod.check=e,t}(i=>(i.addIssue=e=>{if("string"==typeof e)i.issues.push(Ae(e,i.value,t._zod.def));else{const n=e;n.fatal&&(n.continue=!1),n.code??(n.code="custom"),n.input??(n.input=i.value),n.inst??(n.inst=t),n.continue??(n.continue=!t._zod.def.abort),i.issues.push(Ae(n))}},e(i.value,i)));return t}(t)),e.overwrite=t=>e.check(nn(t)),e.optional=()=>ko(e),e.exactOptional=()=>new xo({type:"optional",innerType:e}),e.nullable=()=>Eo(e),e.nullish=()=>ko(Eo(e)),e.nonoptional=t=>function(e,t){return new Ao({type:"nonoptional",innerType:e,...we(t)})}(e,t),e.array=()=>uo(e),e.or=t=>fo([e,t]),e.and=t=>new go({type:"intersection",left:e,right:t}),e.transform=t=>jo(e,new _o({type:"transform",transform:t})),e.default=t=>{return i=t,new Oo({type:"default",innerType:e,get defaultValue(){return"function"==typeof i?i():ve(i)}});var i},e.prefault=t=>{return i=t,new To({type:"prefault",innerType:e,get defaultValue(){return"function"==typeof i?i():ve(i)}});var i},e.catch=t=>{return new $o({type:"catch",innerType:e,catchValue:"function"==typeof(i=t)?i:()=>i});var i},e.pipe=t=>jo(e,t),e.readonly=()=>new Co({type:"readonly",innerType:e}),e.describe=t=>{const i=e.clone();return Ji.add(i,{description:t}),i},Object.defineProperty(e,"description",{get:()=>Ji.get(e)?.description,configurable:!0}),e.meta=(...t)=>{if(0===t.length)return Ji.get(e);const i=e.clone();return Ji.add(i,t[0]),i},e.isOptional=()=>e.safeParse(void 0).success,e.isNullable=()=>e.safeParse(null).success,e.apply=t=>t(e),e)),Nn=X("_ZodString",(e,t)=>{qt.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i)=>{const n=i;n.type="string";const{minimum:o,maximum:r,format:a,patterns:s,contentEncoding:l}=e._zod.bag;if("number"==typeof o&&(n.minLength=o),"number"==typeof r&&(n.maxLength=r),a&&(n.format=dn[a]??a,""===n.format&&delete n.format,"time"===a&&delete n.format),l&&(n.contentEncoding=l),s&&s.size>0){const e=[...s];1===e.length?n.pattern=e[0].source:e.length>1&&(n.allOf=[...e.map(e=>({..."draft-07"===t.target||"draft-04"===t.target||"openapi-3.0"===t.target?{type:"string"}:{},pattern:e.source}))])}})(e,t,i);const i=e._zod.bag;e.format=i.format??null,e.minLength=i.minimum??null,e.maxLength=i.maximum??null,e.regex=(...t)=>e.check(function(e,t){return new Tt({check:"string_format",format:"regex",...we(t),pattern:e})}(...t)),e.includes=(...t)=>e.check(function(e,t){return new Nt({check:"string_format",format:"includes",...we(t),includes:e})}(...t)),e.startsWith=(...t)=>e.check(function(e,t){return new jt({check:"string_format",format:"starts_with",...we(t),prefix:e})}(...t)),e.endsWith=(...t)=>e.check(function(e,t){return new Ct({check:"string_format",format:"ends_with",...we(t),suffix:e})}(...t)),e.min=(...t)=>e.check(en(...t)),e.max=(...t)=>e.check(Qi(...t)),e.length=(...t)=>e.check(tn(...t)),e.nonempty=(...t)=>e.check(en(1,...t)),e.lowercase=t=>e.check(function(e){return new At({check:"string_format",format:"lowercase",...we(e)})}(t)),e.uppercase=t=>e.check(function(e){return new $t({check:"string_format",format:"uppercase",...we(e)})}(t)),e.trim=()=>e.check(nn(e=>e.trim())),e.normalize=(...t)=>e.check(function(e){return nn(t=>t.normalize(e))}(...t)),e.toLowerCase=()=>e.check(nn(e=>e.toLowerCase())),e.toUpperCase=()=>e.check(nn(e=>e.toUpperCase())),e.slugify=()=>e.check(nn(e=>function(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}(e)))}),jn=X("ZodString",(e,t)=>{qt.init(e,t),Nn.init(e,t),e.email=t=>e.check(function(e,t){return new In({type:"string",format:"email",check:"string_format",abort:!1,...we(t)})}(0,t)),e.url=t=>e.check(function(e,t){return new qn({type:"string",format:"url",check:"string_format",abort:!1,...we(t)})}(0,t)),e.jwt=t=>e.check(function(e,t){return new Xn({type:"string",format:"jwt",check:"string_format",abort:!1,...we(t)})}(0,t)),e.emoji=t=>e.check(function(e,t){return new Pn({type:"string",format:"emoji",check:"string_format",abort:!1,...we(t)})}(0,t)),e.guid=t=>e.check(Ki(Ln,t)),e.uuid=t=>e.check(function(e,t){return new zn({type:"string",format:"uuid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.uuidv4=t=>e.check(function(e,t){return new zn({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...we(t)})}(0,t)),e.uuidv6=t=>e.check(function(e,t){return new zn({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...we(t)})}(0,t)),e.uuidv7=t=>e.check(function(e,t){return new zn({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...we(t)})}(0,t)),e.nanoid=t=>e.check(function(e,t){return new Mn({type:"string",format:"nanoid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.guid=t=>e.check(Ki(Ln,t)),e.cuid=t=>e.check(function(e,t){return new Un({type:"string",format:"cuid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.cuid2=t=>e.check(function(e,t){return new Fn({type:"string",format:"cuid2",check:"string_format",abort:!1,...we(t)})}(0,t)),e.ulid=t=>e.check(function(e,t){return new Dn({type:"string",format:"ulid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.base64=t=>e.check(function(e,t){return new Gn({type:"string",format:"base64",check:"string_format",abort:!1,...we(t)})}(0,t)),e.base64url=t=>e.check(function(e,t){return new Wn({type:"string",format:"base64url",check:"string_format",abort:!1,...we(t)})}(0,t)),e.xid=t=>e.check(function(e,t){return new Hn({type:"string",format:"xid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.ksuid=t=>e.check(function(e,t){return new Bn({type:"string",format:"ksuid",check:"string_format",abort:!1,...we(t)})}(0,t)),e.ipv4=t=>e.check(function(e,t){return new Vn({type:"string",format:"ipv4",check:"string_format",abort:!1,...we(t)})}(0,t)),e.ipv6=t=>e.check(function(e,t){return new Jn({type:"string",format:"ipv6",check:"string_format",abort:!1,...we(t)})}(0,t)),e.cidrv4=t=>e.check(function(e,t){return new Kn({type:"string",format:"cidrv4",check:"string_format",abort:!1,...we(t)})}(0,t)),e.cidrv6=t=>e.check(function(e,t){return new Yn({type:"string",format:"cidrv6",check:"string_format",abort:!1,...we(t)})}(0,t)),e.e164=t=>e.check(function(e,t){return new Zn({type:"string",format:"e164",check:"string_format",abort:!1,...we(t)})}(0,t)),e.datetime=t=>e.check(function(e){return function(e,t){return new pn({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...we(t)})}(0,e)}(t)),e.date=t=>e.check(function(e){return function(e,t){return new mn({type:"string",format:"date",check:"string_format",...we(t)})}(0,e)}(t)),e.time=t=>e.check(function(e){return function(e,t){return new hn({type:"string",format:"time",check:"string_format",precision:null,...we(t)})}(0,e)}(t)),e.duration=t=>e.check(function(e){return function(e,t){return new fn({type:"string",format:"duration",check:"string_format",...we(t)})}(0,e)}(t))});function Cn(e){return function(e,t){return new jn({type:"string",...we(t)})}(0,e)}const Rn=X("ZodStringFormat",(e,t)=>{Pt.init(e,t),Nn.init(e,t)}),In=X("ZodEmail",(e,t)=>{Ft.init(e,t),Rn.init(e,t)}),Ln=X("ZodGUID",(e,t)=>{Mt.init(e,t),Rn.init(e,t)}),zn=X("ZodUUID",(e,t)=>{Ut.init(e,t),Rn.init(e,t)}),qn=X("ZodURL",(e,t)=>{Dt.init(e,t),Rn.init(e,t)}),Pn=X("ZodEmoji",(e,t)=>{Ht.init(e,t),Rn.init(e,t)}),Mn=X("ZodNanoID",(e,t)=>{Bt.init(e,t),Rn.init(e,t)}),Un=X("ZodCUID",(e,t)=>{Vt.init(e,t),Rn.init(e,t)}),Fn=X("ZodCUID2",(e,t)=>{Jt.init(e,t),Rn.init(e,t)}),Dn=X("ZodULID",(e,t)=>{Kt.init(e,t),Rn.init(e,t)}),Hn=X("ZodXID",(e,t)=>{Yt.init(e,t),Rn.init(e,t)}),Bn=X("ZodKSUID",(e,t)=>{Gt.init(e,t),Rn.init(e,t)}),Vn=X("ZodIPv4",(e,t)=>{ei.init(e,t),Rn.init(e,t)}),Jn=X("ZodIPv6",(e,t)=>{ti.init(e,t),Rn.init(e,t)}),Kn=X("ZodCIDRv4",(e,t)=>{ii.init(e,t),Rn.init(e,t)}),Yn=X("ZodCIDRv6",(e,t)=>{ni.init(e,t),Rn.init(e,t)}),Gn=X("ZodBase64",(e,t)=>{ri.init(e,t),Rn.init(e,t)}),Wn=X("ZodBase64URL",(e,t)=>{ai.init(e,t),Rn.init(e,t)}),Zn=X("ZodE164",(e,t)=>{si.init(e,t),Rn.init(e,t)}),Xn=X("ZodJWT",(e,t)=>{li.init(e,t),Rn.init(e,t)}),Qn=X("ZodNumber",(e,t)=>{ci.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i)=>{const n=i,{minimum:o,maximum:r,format:a,multipleOf:s,exclusiveMaximum:l,exclusiveMinimum:c}=e._zod.bag;"string"==typeof a&&a.includes("int")?n.type="integer":n.type="number","number"==typeof c&&("draft-04"===t.target||"openapi-3.0"===t.target?(n.minimum=c,n.exclusiveMinimum=!0):n.exclusiveMinimum=c),"number"==typeof o&&(n.minimum=o,"number"==typeof c&&"draft-04"!==t.target&&(c>=o?delete n.minimum:delete n.exclusiveMinimum)),"number"==typeof l&&("draft-04"===t.target||"openapi-3.0"===t.target?(n.maximum=l,n.exclusiveMaximum=!0):n.exclusiveMaximum=l),"number"==typeof r&&(n.maximum=r,"number"==typeof l&&"draft-04"!==t.target&&(l<=r?delete n.maximum:delete n.exclusiveMaximum)),"number"==typeof s&&(n.multipleOf=s)})(e,t,i),e.gt=(t,i)=>e.check(Wi(t,i)),e.gte=(t,i)=>e.check(Zi(t,i)),e.min=(t,i)=>e.check(Zi(t,i)),e.lt=(t,i)=>e.check(Yi(t,i)),e.lte=(t,i)=>e.check(Gi(t,i)),e.max=(t,i)=>e.check(Gi(t,i)),e.int=t=>e.check(io(t)),e.safe=t=>e.check(io(t)),e.positive=t=>e.check(Wi(0,t)),e.nonnegative=t=>e.check(Zi(0,t)),e.negative=t=>e.check(Yi(0,t)),e.nonpositive=t=>e.check(Gi(0,t)),e.multipleOf=(t,i)=>e.check(Xi(t,i)),e.step=(t,i)=>e.check(Xi(t,i)),e.finite=()=>e;const i=e._zod.bag;e.minValue=Math.max(i.minimum??Number.NEGATIVE_INFINITY,i.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,e.maxValue=Math.min(i.maximum??Number.POSITIVE_INFINITY,i.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,e.isInt=(i.format??"").includes("int")||Number.isSafeInteger(i.multipleOf??.5),e.isFinite=!0,e.format=i.format??null});function eo(e){return function(e,t){return new Qn({type:"number",checks:[],...we(t)})}(0,e)}const to=X("ZodNumberFormat",(e,t)=>{di.init(e,t),Qn.init(e,t)});function io(e){return function(e,t){return new to({type:"number",check:"number_format",abort:!1,format:"safeint",...we(t)})}(0,e)}const no=X("ZodBoolean",(e,t)=>{ui.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(e,t,i)=>((e,t,i)=>{i.type="boolean"})(0,0,t)});function oo(e){return function(e,t){return new no({type:"boolean",...we(t)})}(0,e)}const ro=X("ZodUnknown",(e,t)=>{pi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(e,t,i)=>{}});function ao(){return new ro({type:"unknown"})}const so=X("ZodNever",(e,t)=>{mi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(e,t,i)=>((e,t,i)=>{i.not={}})(0,0,t)});function lo(e){return function(e,t){return new so({type:"never",...we(t)})}(0,e)}const co=X("ZodArray",(e,t)=>{fi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=i,r=e._zod.def,{minimum:a,maximum:s}=e._zod.bag;"number"==typeof a&&(o.minItems=a),"number"==typeof s&&(o.maxItems=s),o.type="array",o.items=rn(r.element,t,{...n,path:[...n.path,"items"]})})(e,t,i,n),e.element=t.element,e.min=(t,i)=>e.check(en(t,i)),e.nonempty=t=>e.check(en(1,t)),e.max=(t,i)=>e.check(Qi(t,i)),e.length=(t,i)=>e.check(tn(t,i)),e.unwrap=()=>e.element});function uo(e,t){return function(e,t,i){return new co({type:"array",element:t,...we(i)})}(0,e,t)}const po=X("ZodObject",(e,t)=>{_i.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=i,r=e._zod.def;o.type="object",o.properties={};const a=r.shape;for(const e in a)o.properties[e]=rn(a[e],t,{...n,path:[...n.path,"properties",e]});const s=new Set(Object.keys(a)),l=new Set([...s].filter(e=>{const i=r.shape[e]._zod;return"input"===t.io?void 0===i.optin:void 0===i.optout}));l.size>0&&(o.required=Array.from(l)),"never"===r.catchall?._zod.def.type?o.additionalProperties=!1:r.catchall?r.catchall&&(o.additionalProperties=rn(r.catchall,t,{...n,path:[...n.path,"additionalProperties"]})):"output"===t.io&&(o.additionalProperties=!1)})(e,t,i,n),ce(e,"shape",()=>t.shape),e.keyof=()=>bo(Object.keys(e._zod.def.shape)),e.catchall=t=>e.clone({...e._zod.def,catchall:t}),e.passthrough=()=>e.clone({...e._zod.def,catchall:ao()}),e.loose=()=>e.clone({...e._zod.def,catchall:ao()}),e.strict=()=>e.clone({...e._zod.def,catchall:lo()}),e.strip=()=>e.clone({...e._zod.def,catchall:void 0}),e.extend=t=>function(e,t){if(!ge(t))throw new Error("Invalid input to extend: expected a plain object");const i=e._zod.def.checks;if(i&&i.length>0){const i=e._zod.def.shape;for(const e in t)if(void 0!==Object.getOwnPropertyDescriptor(i,e))throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}const n=ue(e._zod.def,{get shape(){const i={...e._zod.def.shape,...t};return de(this,"shape",i),i}});return _e(e,n)}(e,t),e.safeExtend=t=>function(e,t){if(!ge(t))throw new Error("Invalid input to safeExtend: expected a plain object");const i=ue(e._zod.def,{get shape(){const i={...e._zod.def.shape,...t};return de(this,"shape",i),i}});return _e(e,i)}(e,t),e.merge=t=>function(e,t){const i=ue(e._zod.def,{get shape(){const i={...e._zod.def.shape,...t._zod.def.shape};return de(this,"shape",i),i},get catchall(){return t._zod.def.catchall},checks:[]});return _e(e,i)}(e,t),e.pick=t=>function(e,t){const i=e._zod.def,n=i.checks;if(n&&n.length>0)throw new Error(".pick() cannot be used on object schemas containing refinements");return _e(e,ue(e._zod.def,{get shape(){const e={};for(const n in t){if(!(n in i.shape))throw new Error(`Unrecognized key: "${n}"`);t[n]&&(e[n]=i.shape[n])}return de(this,"shape",e),e},checks:[]}))}(e,t),e.omit=t=>function(e,t){const i=e._zod.def,n=i.checks;if(n&&n.length>0)throw new Error(".omit() cannot be used on object schemas containing refinements");const o=ue(e._zod.def,{get shape(){const n={...e._zod.def.shape};for(const e in t){if(!(e in i.shape))throw new Error(`Unrecognized key: "${e}"`);t[e]&&delete n[e]}return de(this,"shape",n),n},checks:[]});return _e(e,o)}(e,t),e.partial=(...t)=>function(e,t,i){const n=t._zod.def.checks;if(n&&n.length>0)throw new Error(".partial() cannot be used on object schemas containing refinements");const o=ue(t._zod.def,{get shape(){const n=t._zod.def.shape,o={...n};if(i)for(const t in i){if(!(t in n))throw new Error(`Unrecognized key: "${t}"`);i[t]&&(o[t]=e?new e({type:"optional",innerType:n[t]}):n[t])}else for(const t in n)o[t]=e?new e({type:"optional",innerType:n[t]}):n[t];return de(this,"shape",o),o},checks:[]});return _e(t,o)}(wo,e,t[0]),e.required=(...t)=>function(e,t,i){const n=ue(t._zod.def,{get shape(){const n=t._zod.def.shape,o={...n};if(i)for(const t in i){if(!(t in o))throw new Error(`Unrecognized key: "${t}"`);i[t]&&(o[t]=new e({type:"nonoptional",innerType:n[t]}))}else for(const t in n)o[t]=new e({type:"nonoptional",innerType:n[t]});return de(this,"shape",o),o}});return _e(t,n)}(Ao,e,t[0])});function mo(e,t){const i={type:"object",shape:e??{},...we(t)};return new po(i)}const ho=X("ZodUnion",(e,t)=>{ki.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def,r=!1===o.inclusive,a=o.options.map((e,i)=>rn(e,t,{...n,path:[...n.path,r?"oneOf":"anyOf",i]}));r?i.oneOf=a:i.anyOf=a})(e,t,i,n),e.options=t.options});function fo(e,t){return new ho({type:"union",options:e,...we(t)})}const go=X("ZodIntersection",(e,t)=>{xi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def,r=rn(o.left,t,{...n,path:[...n.path,"allOf",0]}),a=rn(o.right,t,{...n,path:[...n.path,"allOf",1]}),s=e=>"allOf"in e&&1===Object.keys(e).length,l=[...s(r)?r.allOf:[r],...s(a)?a.allOf:[a]];i.allOf=l})(e,t,i,n)}),vo=X("ZodRecord",(e,t)=>{Oi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=i,r=e._zod.def;o.type="object";const a=r.keyType,s=a._zod.bag,l=s?.patterns;if("loose"===r.mode&&l&&l.size>0){const e=rn(r.valueType,t,{...n,path:[...n.path,"patternProperties","*"]});o.patternProperties={};for(const t of l)o.patternProperties[t.source]=e}else"draft-07"!==t.target&&"draft-2020-12"!==t.target||(o.propertyNames=rn(r.keyType,t,{...n,path:[...n.path,"propertyNames"]})),o.additionalProperties=rn(r.valueType,t,{...n,path:[...n.path,"additionalProperties"]});const c=a._zod.values;if(c){const e=[...c].filter(e=>"string"==typeof e||"number"==typeof e);e.length>0&&(o.required=e)}})(e,t,i,n),e.keyType=t.keyType,e.valueType=t.valueType}),yo=X("ZodEnum",(e,t)=>{Ti.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i)=>{const n=ne(e._zod.def.entries);n.every(e=>"number"==typeof e)&&(i.type="number"),n.every(e=>"string"==typeof e)&&(i.type="string"),i.enum=n})(e,0,i),e.enum=t.entries,e.options=Object.values(t.entries);const i=new Set(Object.keys(t.entries));e.extract=(e,n)=>{const o={};for(const n of e){if(!i.has(n))throw new Error(`Key ${n} not found in enum`);o[n]=t.entries[n]}return new yo({...t,checks:[],...we(n),entries:o})},e.exclude=(e,n)=>{const o={...t.entries};for(const t of e){if(!i.has(t))throw new Error(`Key ${t} not found in enum`);delete o[t]}return new yo({...t,checks:[],...we(n),entries:o})}});function bo(e,t){const i=Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e;return new yo({type:"enum",entries:i,...we(t)})}const _o=X("ZodTransform",(e,t)=>{Ai.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(e,t,i)=>((e,t)=>{if("throw"===t.unrepresentable)throw new Error("Transforms cannot be represented in JSON Schema")})(0,e),e._zod.parse=(i,n)=>{if("backward"===n.direction)throw new ee(e.constructor.name);i.addIssue=n=>{if("string"==typeof n)i.issues.push(Ae(n,i.value,t));else{const t=n;t.fatal&&(t.continue=!1),t.code??(t.code="custom"),t.input??(t.input=i.value),t.inst??(t.inst=e),i.issues.push(Ae(t))}};const o=t.transform(i.value,i);return o instanceof Promise?o.then(e=>(i.value=e,i)):(i.value=o,i)}}),wo=X("ZodOptional",(e,t)=>{Ni.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>un(e,t,0,n),e.unwrap=()=>e._zod.def.innerType});function ko(e){return new wo({type:"optional",innerType:e})}const xo=X("ZodExactOptional",(e,t)=>{ji.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>un(e,t,0,n),e.unwrap=()=>e._zod.def.innerType}),So=X("ZodNullable",(e,t)=>{Ci.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def,r=rn(o.innerType,t,n),a=t.seen.get(e);"openapi-3.0"===t.target?(a.ref=o.innerType,i.nullable=!0):i.anyOf=[r,{type:"null"}]})(e,t,i,n),e.unwrap=()=>e._zod.def.innerType});function Eo(e){return new So({type:"nullable",innerType:e})}const Oo=X("ZodDefault",(e,t)=>{Ri.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType,i.default=JSON.parse(JSON.stringify(o.defaultValue))})(e,t,i,n),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap}),To=X("ZodPrefault",(e,t)=>{Li.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType,"input"===t.io&&(i._prefault=JSON.parse(JSON.stringify(o.defaultValue)))})(e,t,i,n),e.unwrap=()=>e._zod.def.innerType}),Ao=X("ZodNonOptional",(e,t)=>{zi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType})(e,t,0,n),e.unwrap=()=>e._zod.def.innerType}),$o=X("ZodCatch",(e,t)=>{Pi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def;let r;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType;try{r=o.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}i.default=r})(e,t,i,n),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap}),No=X("ZodPipe",(e,t)=>{Mi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def,r="input"===t.io?"transform"===o.in._zod.def.type?o.out:o.in:o.out;rn(r,t,n),t.seen.get(e).ref=r})(e,t,0,n),e.in=t.in,e.out=t.out});function jo(e,t){return new No({type:"pipe",in:e,out:t})}const Co=X("ZodReadonly",(e,t)=>{Fi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(t,i,n)=>((e,t,i,n)=>{const o=e._zod.def;rn(o.innerType,t,n),t.seen.get(e).ref=o.innerType,i.readOnly=!0})(e,t,i,n),e.unwrap=()=>e._zod.def.innerType}),Ro=X("ZodCustom",(e,t)=>{Hi.init(e,t),$n.init(e,t),e._zod.processJSONSchema=(e,t,i)=>((e,t)=>{if("throw"===t.unrepresentable)throw new Error("Custom types cannot be represented in JSON Schema")})(0,e)}),Io=bo(["none","generic_character","real_person","known_ip","realistic_animal","illustrated_human"]).optional().describe("Internal safety hint; stripped before submit."),Lo=fo([Cn(),uo(Cn())]),zo=mo({service:bo(["banana-pro","banana-2","seedream","seedream-5-lte","gpt-image-2"]),prompt:Cn(),aspect_ratio:bo(["1:1","3:4","4:3","16:9","9:16","3:2","2:3","21:9"]).optional(),image_size:bo(["1K","2K"]).optional(),img_url:Lo.optional(),image:Lo.optional(),image_urls:uo(Cn()).optional(),size:Cn().optional(),model:Cn().optional(),vendor:Cn().optional(),nsfw_checker:oo().optional()}),qo=mo({service:bo(["dli2v3","dlim2v","dlai2v","dlai2v_pro","dlai2v_pro_multiframe","happyhorse-1-0-i2v","happyhorse-1-0-r2v","happyhorse-1-0-video-edit","seedance-1-5","seedance-2-0","seedance-2-0-fast","kling3.0","kling-o3-ref2v","kling-o3-pro-ref2v","kling-o3-v2v","kling-o3-pro-v2v","grok-imagine-video-1-5-preview","gemini-omni-video","longcat-avatar-1-5"]),prompt:Cn(),duration:eo().int().optional(),aspect_ratio:Cn().optional(),image_url:Cn().optional(),last_frame_url:Cn().optional(),urls:uo(Cn()).optional(),resolution:Cn().optional(),generate_audio:oo().optional(),mode:bo(["fun","normal","spicy"]).optional(),draft:oo().optional(),seed:eo().int().optional(),keyframes:uo(ao()).optional(),quality_preset:bo(["fast","high","ultra"]).optional(),width:eo().int().optional(),height:eo().int().optional(),sound:oo().optional(),negative_prompt:Cn().optional(),cfg_scale:eo().optional(),end_image_url:Cn().optional(),image_urls:uo(Cn()).optional(),reference_audio_url:Cn().optional(),audio_url:Cn().optional(),ref_video_url:Cn().optional(),video_url:Cn().optional(),video_urls:uo(Cn()).optional(),ark_asset_ids:uo(Cn()).optional(),_reference_subject_type:Io,elements:uo(ao()).optional(),camera_fixed:oo().optional(),audio_setting:bo(["auto","origin"]).optional()}),Po=mo({service:bo(["dlai2v","longcat-avatar","seedance-2-0","seedance-2-0-fast","dlai2v_pro","dlai2v_pro_multiframe"]),image_url:Cn().optional(),audio_url:Cn(),prompt:Cn().optional(),quality_preset:bo(["fast","high","ultra"]).optional(),width:eo().int().optional(),height:eo().int().optional(),seed:eo().int().min(0).optional(),resolution:bo(["480p","720p","1080p"]).optional(),duration:eo().int().min(1).optional(),ark_asset_ids:uo(Cn()).optional(),keyframes:uo(ao()).optional(),_reference_subject_type:Io}),Mo=mo({service:bo(["dreamactor","kling3.0-motion"]),video_url:Cn(),image_url:Cn().optional(),image_urls:uo(Cn()).optional(),image_base64:Cn().optional(),cut_first_second:oo().optional(),character_orientation:bo(["image","video"]).optional(),keep_original_sound:oo().optional(),tier:bo(["pro","std"]).optional(),prompt:Cn().optional(),negative_prompt:Cn().optional(),duration:eo().int().min(1).optional()}).refine(e=>1==(e.image_url?1:0)+(e.image_urls&&e.image_urls.length>0?1:0)+(e.image_base64?1:0),{message:"exactly one of image_url / image_urls / image_base64 is required",path:["image_url"]}),Uo=mo({service:bo(["suno-v5","suno-v5_5","minimax"]),prompt:Cn(),title:Cn().optional(),tags:Cn().optional(),negative_tags:Cn().optional(),custom:oo().optional(),instrumental:oo().optional(),vocal_gender:bo(["Male","Female"]).optional()}),Fo=mo({service:bo(["elevenlabs-sound"]),text:Cn(),duration_seconds:eo().min(.5).max(30).optional(),prompt_influence:eo().min(0).max(1).optional(),loop:oo().optional(),output_format:bo(["mp3_44100_128","mp3_44100_192","mp3_44100_96","mp3_44100_64","mp3_44100_32","mp3_22050_32"]).optional()}),Do=mo({service:bo(["minimax-tts","voxcpm"]),text:Cn(),audio_url:Cn().optional(),control:Cn().optional(),model:bo(["speech-2.8-hd","speech-2.8-turbo","speech-2.6-hd","speech-2.6-turbo"]).optional(),voice_id:Cn().optional(),speed:eo().min(.5).max(2).optional(),vol:eo().optional(),pitch:eo().int().min(-12).max(12).optional(),emotion:bo(["happy","sad","angry","calm","whisper"]).optional(),language_boost:Cn().optional(),format:bo(["mp3","pcm","flac","wav"]).optional(),sample_rate:eo().int().refine(e=>[8e3,16e3,22050,24e3,32e3,44100].includes(e),"sample_rate must be one of: 8000, 16000, 22050, 24000, 32000, 44100").optional(),bitrate:eo().int().refine(e=>[32e3,64e3,128e3,256e3].includes(e),"bitrate must be one of: 32000, 64000, 128000, 256000").optional()}),Ho=mo({service:bo(["elevenlabs","minimax"]),files:uo(Cn()).min(1),name:Cn().optional(),description:Cn().optional(),labels:(Bo=Cn(),Vo=ao(),new vo({type:"record",keyType:Bo,valueType:Vo,...we(void 0)})).optional(),voice_id:Cn().min(8).max(256).optional(),text:Cn().optional(),model:Cn().optional(),language_boost:Cn().optional(),need_noise_reduction:oo().optional(),need_volume_normalization:oo().optional(),prompt_audio:mo({file:Cn(),text:Cn().optional()}).optional()});var Bo,Vo;const Jo=mo({service:bo(["elevenlabs","minimax"]),voice_description:Cn().optional(),text:Cn().optional(),model_id:Cn().optional(),prompt:Cn().optional(),preview_text:Cn().max(500).optional(),voice_id:Cn().optional()}),Ko=mo({service:bo(["elevenlabs"]),generated_voice_id:Cn(),voice_name:Cn(),voice_description:Cn()}),Yo=mo({service:bo(["elevenlabs"]),voice_id:Cn(),voice_description:Cn(),text:Cn(),model_id:Cn().optional()}),Go=mo({audio_url:Cn().describe("Publicly readable audio URL."),transcript_text:Cn().optional().describe("Known transcript text. When set, ASR recognition is skipped and the service only timestamps this text."),language:Cn().optional().describe("Language hint such as auto, en, zh, ja, es."),word_timestamps:oo().optional().describe("Return full text, segments, and word-level timestamps in addition to srt_content."),vad_filter:oo().optional().describe("Enable stable-ts VAD during timestamp alignment."),denoise_audio:oo().optional().describe("Enable Demucs denoising / vocal separation; ASR defaults this to true."),max_segment_duration:eo().min(1).max(30).optional().describe("Maximum subtitle segment duration in seconds.")}),Wo=mo({style_id:Cn().optional(),fill_color:Cn().optional(),border_color:Cn().optional(),font_id:Cn().optional(),font_weight:bo(["normal","bold"]).optional(),shadow:mo({color:Cn().optional(),opacity:eo().min(0).max(1).optional()}).optional(),position:bo(["top","bottom"]).optional(),position_value:eo().min(0).max(.5).optional(),font_size:bo(["sm","md","lg"]).optional(),font_size_px:eo().int().min(12).max(72).optional()}),Zo=mo({video_url:Cn(),srt_content:Cn(),caption:Wo.optional().describe("JSON object controlling caption style. font_size_px wins over font_size."),task_id:Cn().optional()}),Xo=mo({audio_url:Cn(),beat_method:Cn().optional(),analysis_types:uo(Cn()).optional()}),Qo=mo({video_url:Cn(),threshold:eo().min(0).max(1).optional(),output_format:bo(["boundaries","shots","full"]).optional()}),er=mo({url:Cn(),format:bo(["auto","video","audio"]).optional(),video_quality:bo(["best","2160","1440","1080","720","480","360"]).optional(),audio_format:bo(["best","mp3","ogg","wav","opus"]).optional(),filename_pattern:Cn().optional()}),tr=mo({latitude:eo(),longitude:eo(),heading:eo().min(0).max(360).optional(),pitch:eo().min(-90).max(90).optional(),fov:eo().min(1).max(120).optional()}),ir=mo({latitude:eo(),longitude:eo()}),nr=mo({address:Cn().optional(),latitude:eo().optional(),longitude:eo().optional()}),or=mo({query:Cn(),latitude:eo(),longitude:eo(),radius:eo().int().min(100).max(5e4).optional()}),rr=mo({photo_reference:Cn(),max_width:eo().int().min(1).max(4800).optional()}),ar=mo({latitude:eo(),longitude:eo(),zoom:eo().int().min(0).max(21).optional(),size:Cn().optional(),maptype:Cn().optional()}),sr={generate_image:zo,generate_video:qo,lipsync:Po,motion_control:Mo,generate_music:Uo,generate_sound:Fo,generate_tts:Do,generate_tts_elevenlabs:Do,generate_tts_dialogue:Do,clone_voice:Ho,design_voice:Jo,finalize_voice:Ko,remix_voice:Yo,transcribe:Go,render_caption:Zo,analyze_beats:Xo,detect_shots:Qo,download_media:er,streetview_image:tr,streetview_metadata:ir,geocode:nr,places_search:or,place_photo:rr,static_map:ar},lr={name:"generate_image",provider:"api_layer",description:"Generate an image via api-layer. Supports: banana-2 (= nano-banana-2, Imagen4 4K, newest generation — materially faster AND higher quality than banana-pro; default first choice within the banana family), banana-pro (= nano-banana-pro, Imagen3 series up to 2K, older / slower / cheaper — use only when cost-saving is explicit), seedream (Asian aesthetic), seedream-5-lte (next-gen), gpt-image-2 (highest text-in-image fidelity and instruction-following edits; supports multi-image i2i up to 16 refs).",zodSchema:sr.generate_image,token_cost:100,artifact_slot:"generated_image",is_async:!0,timeout:300},cr={name:"generate_video",provider:"api_layer",description:"Generate a video via api-layer. Services: dli2v3 (Veo 3.1), dlim2v (Grok), dlai2v (LTX 2), dlai2v_pro (LTX 2 Pro = LTX 2.3 multi-frame workflow on RunPod; single image_url + duration auto-wrapped into keyframes[0] in api-layer router), dlai2v_pro_multiframe (LTX 2.3 真·多帧变体, 2-4 帧关键帧引导视频生成: 必须传 keyframes=[{image_url, frame_ratio?, weight?}] (2-4 帧) + audio_url; frame_ratio 0.0-1.0 表示该帧在视频中的相对时间位置(不传按数量等分 [0,1] / [0,0.5,1] / [0,0.33,0.67,1]); weight 0.0-1.0 (默认 0.4) 控制 guide 强度; aspect_ratio 16:9/9:16/1:1, resolution 强制 720p), happyhorse-1-0-i2v (Alibaba HappyHorse single first-frame i2v), happyhorse-1-0-r2v (Alibaba HappyHorse 1-9 reference images → video), happyhorse-1-0-video-edit (Alibaba HappyHorse video edit with 0-5 reference images), seedance-1-5, seedance-2-0, seedance-2-0-fast, kling3.0, kling-o3-ref2v, kling-o3-pro-ref2v, kling-o3-v2v (Kling O3 Std video-edit / video-to-video: 输入视频 + prompt 编辑画面,可选 image_urls / elements 作辅助参考), kling-o3-pro-v2v (同 v2v 的 Pro 版,质量更高), gemini-omni-video, grok-imagine-video-1-5-preview, longcat-avatar-1-5. Prompt placeholders: @imageN → image_urls[N-1], @audioN → reference_audio_url, @videoN → ref_video_url, @assetN → ark_asset_ids[N-1] (all 1-indexed).",zodSchema:sr.generate_video,strip_before_submit:["_reference_subject_type"],token_cost:400,artifact_slot:"generated_video",is_async:!0,timeout:300},dr={name:"lipsync",provider:"api_layer",description:"Lip-sync via api-layer. Services: dlai2v (LTX 2), longcat-avatar, seedance-2-0, seedance-2-0-fast, dlai2v_pro (LTX 2 Pro = LTX 2.3 multi-frame workflow on RunPod), dlai2v_pro_multiframe (LTX 2.3 真·多帧变体, 2-4 帧关键帧+音频驱动: 必须传 keyframes=[{image_url, frame_ratio?, weight?}] (2-4) + audio_url; frame_ratio 0.0-1.0 时间位置, weight 默认 0.4, aspect_ratio 16:9/9:16/1:1, resolution 强制 720p). Seedance 2.0 lipsync requires @audio1 in prompt. dlai2v_pro auto-wraps single image_url into keyframes[0] in api-layer router.",zodSchema:sr.lipsync,strip_before_submit:["_reference_subject_type"],token_cost:350,artifact_slot:"lipsync_video",is_async:!0,timeout:300},ur={name:"motion_control",provider:"api_layer",description:"Transfer motion/pose from source video onto target character. Services: dreamactor, kling3.0-motion.",zodSchema:sr.motion_control,token_cost:400,artifact_slot:"motion_video",is_async:!0,timeout:300},pr={name:"generate_music",provider:"api_layer",description:"Generate music via api-layer. Services: suno-v5, suno-v5_5, minimax.",zodSchema:sr.generate_music,token_cost:300,artifact_slot:"music_candidate",is_async:!0,timeout:600},mr={name:"generate_sound",provider:"api_layer",description:"Generate a short sound effect via api-layer (ElevenLabs Sound Effects v2, 0.5–30s). For SFX / Foley / ambient / short loops — not full songs (use generate_music for that).",zodSchema:sr.generate_sound,token_cost:50,artifact_slot:"sound_effect",is_async:!0,timeout:60},hr={name:"generate_tts",provider:"api_layer",description:"Generate speech via api-layer TTS. Services: minimax-tts, voxcpm (self-hosted real-person voice cloning).",zodSchema:sr.generate_tts,token_cost:80,artifact_slot:"tts_audio",is_async:!0,timeout:120},fr={...hr,name:"generate_tts_elevenlabs",zodSchema:sr.generate_tts_elevenlabs,description:"Back-compat alias for generate_tts (routed to api-layer /tts/submit)."},gr={...hr,name:"generate_tts_dialogue",zodSchema:sr.generate_tts_dialogue,description:"Back-compat alias for generate_tts (routed to api-layer /tts/submit)."},vr={name:"clone_voice",provider:"api_layer",description:"Clone a voice from audio sample(s) via api-layer. Services: elevenlabs (multi-file upload), minimax (single file 10s-5min). Returns voice_id + vendor.",zodSchema:sr.clone_voice,token_cost:200,artifact_slot:"voice_profile",is_async:!0,timeout:300},yr={name:"design_voice",provider:"api_layer",description:"Design a voice from text description via api-layer. ElevenLabs: 2-step (preview → finalize_voice). MiniMax: 1-step (permanent).",zodSchema:sr.design_voice,token_cost:100,artifact_slot:"voice_profile",is_async:!0,timeout:120},br={name:"finalize_voice",provider:"api_layer",description:"Finalize an ElevenLabs voice preview (from design_voice / remix_voice) into a permanent voice_id. ElevenLabs-only.",zodSchema:sr.finalize_voice,token_cost:20,artifact_slot:"voice_profile",is_async:!0,timeout:60},_r={name:"remix_voice",provider:"api_layer",description:"Remix an existing ElevenLabs voice (pitch / accent / etc.). Source voice_id must be one the agent created. Returns a preview; call finalize_voice next.",zodSchema:sr.remix_voice,token_cost:150,artifact_slot:"voice_profile",is_async:!0,timeout:120},wr={name:"transcribe",provider:"asr",description:"Transcribe audio to text.",zodSchema:sr.transcribe,default_params:{word_timestamps:!1},strip_before_submit:["model_size"],token_cost:50,artifact_slot:"audio_transcription",is_async:!0,timeout:30},kr={name:"render_caption",provider:"caption_render",description:"Burn SRT captions into a video and return the captioned video URL.",zodSchema:sr.render_caption,token_cost:50,artifact_slot:"captioned_video",is_async:!1,timeout:600},xr={name:"analyze_beats",provider:"audio_analyzer",description:"Analyze beat structure of an audio file.",zodSchema:sr.analyze_beats,token_cost:25,artifact_slot:"beat_analysis",is_async:!1,timeout:900},Sr={name:"detect_shots",provider:"shot_analysis",description:"Detect shot boundaries using TransNetV2.",zodSchema:sr.detect_shots,token_cost:30,artifact_slot:"shot_analysis",is_async:!1,timeout:120},Er={name:"download_media",provider:"media_downloader",description:"Download a video/audio/image from TikTok / Instagram / Twitter / Bilibili / etc. and re-upload to CDN. Returns a persistent public URL. Limits: <=500MB, 30 RPM. YouTube currently unsupported (anti-bot block).",zodSchema:sr.download_media,token_cost:30,artifact_slot:"downloaded_media",is_async:!1,timeout:120},Or={name:"streetview_image",provider:"geo",description:"Street-level image at coordinates; auto-routes provider (Google / AMap / Panoramax).",zodSchema:sr.streetview_image,token_cost:5,artifact_slot:"streetview_image",is_async:!1,timeout:30},Tr={name:"streetview_metadata",provider:"geo",description:"Check street view coverage at coordinates. Returns coverage status. Low cost — call before streetview_image.",zodSchema:sr.streetview_metadata,token_cost:1,is_async:!1,timeout:10},Ar={name:"geocode",provider:"geo",description:"Forward (address→coords) or reverse (coords→address) geocoding.",zodSchema:sr.geocode,token_cost:2,is_async:!1,timeout:10},$r={name:"places_search",provider:"geo",description:"Search places/POIs near coordinates by keyword.",zodSchema:sr.places_search,token_cost:10,is_async:!1,timeout:15},Nr={name:"place_photo",provider:"geo",description:"Fetch a photo by its photo_reference returned from places_search.",zodSchema:sr.place_photo,token_cost:5,artifact_slot:"place_photo",is_async:!1,timeout:15},jr={name:"static_map",provider:"geo",description:"Bird's-eye view map image at coordinates with optional markers.",zodSchema:sr.static_map,token_cost:3,artifact_slot:"static_map",is_async:!1,timeout:15},Cr=Object.freeze({generate_image:lr,generate_video:cr,lipsync:dr,motion_control:ur,generate_music:pr,generate_sound:mr,generate_tts:hr,generate_tts_elevenlabs:fr,generate_tts_dialogue:gr,clone_voice:vr,design_voice:yr,finalize_voice:br,remix_voice:_r,transcribe:wr,render_caption:kr,analyze_beats:xr,detect_shots:Sr,download_media:Er,streetview_image:Or,streetview_metadata:Tr,geocode:Ar,places_search:$r,place_photo:Nr,static_map:jr});function Rr(e){return Cr[e]}const Ir=[{flag:"--print-schema",description:"emit JSON schema for this verb's single + batch shape"},{flag:"--echo-parsed",description:"echo canonicalised input on stderr (debug)"},{flag:"--help",description:"show this help"}],Lr=[{code:"E_SCHEMA",when:"missing/invalid flag value",recovery:"run `dl <verb> --print-schema` to see the expected shape"},{code:"E_BACKEND",when:"backend returned a failure",recovery:"inspect the `data` field on stderr; usually quota / unreachable URL / asset missing"}];function zr(e){const t=[` --${e.flag.padEnd(20)} ${function(e){switch(e.kind){case"string":return"<string>";case"integer":return"<integer>";case"number":return"<number>";case"boolean":return"(boolean flag)";case"array":return e.itemKind?`<${e.itemKind}> (repeatable)`:"<value> (repeatable)";case"object":return"<see --<name>-file>";default:return"<value>"}}(e)}`];if(e.description&&t.push(` ${" ".repeat(22)} ${e.description}`),e.enum&&t.push(` ${" ".repeat(22)} one of: ${e.enum.join(", ")}`),void 0!==e.minimum||void 0!==e.maximum){const i=[void 0!==e.minimum?`>= ${e.minimum}`:"",void 0!==e.maximum?`<= ${e.maximum}`:""].filter(Boolean).join(", ");t.push(` ${" ".repeat(22)} ${i}`)}return void 0!==e.default&&t.push(` ${" ".repeat(22)} default: ${JSON.stringify(e.default)}`),e.internal&&!e.description?.toLowerCase().includes("strip")&&t.push(` ${" ".repeat(22)} (internal hint, stripped before submit)`),t}function qr(e,t,i){if(i)return function(e,t,i){const n=t.services.find(e=>e.service===i);if(!n){const n=t.services.map(e=>e.service).join(" | ");return[`Unknown service '${i}'.`,`Known services for \`dl ${e}\`: ${n}`,`Run \`dl ${e} model -h\` for the ranking + decision logic.`].join("\n")}const o=[];o.push(`SERVICE: ${n.service}${n.label?` — ${n.label}`:""}`),n.tier&&o.push(` Tier: ${n.tier}`),n.bestFor&&o.push(` Best for: ${n.bestFor}`);const r=[];if(n.quality&&r.push(`Quality ${n.quality}`),n.speed&&r.push(`Speed ${n.speed}`),n.cost&&r.push(`Cost ${n.cost}`),r.length>0&&o.push(` ${r.join(" · ")}`),o.push(""),n.description&&n.description.length>0){o.push("DESCRIPTION");for(const e of n.description)o.push(` ${e}`);o.push("")}if(n.promptTips&&n.promptTips.length>0){o.push("PROMPT TIPS (model-specific)");for(const e of n.promptTips)o.push(` - ${e}`);o.push("")}if(n.constraints&&n.constraints.length>0){o.push("CONSTRAINTS");for(const e of n.constraints)o.push(` - ${e}`);o.push("")}if(n.flagSubset&&n.flagSubset.length>0){o.push("FLAG SUBSET (for this service — full schema via `--print-schema`)");for(const e of n.flagSubset)o.push(` --${e}`);o.push("")}if(n.examples&&n.examples.length>0)for(const e of n.examples){o.push(`EXAMPLE — ${e.caption}`);for(const t of e.command.split("\n"))o.push(` ${t}`);o.push("")}for(;o.length>0&&""===o[o.length-1];)o.pop();return o.join("\n")}(e,t,i);const n=[];if(n.push("TOPIC: model — service selection & per-service call shape",""),t.rankingSummary&&t.rankingSummary.length>0){for(const e of t.rankingSummary)n.push(e);n.push("")}if(t.services.length>0){n.push("SERVICES");for(const e of t.services){const t=` ${e.service.padEnd(20)} ${e.tier??""}`.trimEnd();n.push(t),e.bestFor&&n.push(` Best for: ${e.bestFor}`);const i=[];e.quality&&i.push(`Quality ${e.quality}`),e.speed&&i.push(`Speed ${e.speed}`),e.cost&&i.push(`Cost ${e.cost}`),i.length>0&&n.push(` ${i.join(" · ")}`),n.push("")}}if(t.decisionLogic&&t.decisionLogic.length>0){n.push("DECISION LOGIC (按优先级)");const e=Math.max(...t.decisionLogic.map(e=>e.when.length));for(const i of t.decisionLogic)n.push(` ${i.when.padEnd(e)} → ${i.pick}`);n.push("")}n.push("LEARN MORE");const o=t.services.map(e=>e.service).join(" | ");for(n.push(` dl ${e} model <service> per-service flag subset + prompt tips + example`),n.push(` <service> ∈ { ${o} }`);n.length>0&&""===n[n.length-1];)n.pop();return n.join("\n")}function Pr(e,t,i=!1){const n=[];if(n.push("TOPIC: preflight — decisions you must make before the first call",""),t.intro&&n.push(t.intro,""),t.decisions.length>0&&(n.push("DECISIONS"),t.decisions.forEach((e,t)=>{n.push(` ${t+1}. ${e.name}`);for(const t of e.description.split("\n"))n.push(` ${t}`)}),n.push("")),t.notes&&t.notes.length>0){n.push("NOTES");for(const e of t.notes)n.push(` - ${e}`);n.push("")}for(i&&n.push("SEE ALSO",` dl ${e} model -h — service selection (decision #1 usually)`);n.length>0&&""===n[n.length-1];)n.pop();return n.join("\n")}function Mr(e,t){const i=[];i.push("TOPIC: policy — user-facing communication rules + payment-package gate",""),t.intro&&i.push(t.intro,"");for(const e of t.rules){i.push(e.title);for(const t of e.body)i.push(` ${t}`);i.push("")}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Ur(e,t){const i=[];i.push("TOPIC: composition — how upstream / sibling skills consume this verb's output",""),t.intro&&i.push(t.intro,"");for(const e of t.integrations){i.push(`WHEN CALLED FROM: ${e.skill}`);for(const t of e.rule)i.push(` ${t}`);i.push("")}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Fr(e,t){const i=[];if(i.push("TOPIC: async — detach-by-default protocol + result shape",""),t.intro&&t.intro.length>0){for(const e of t.intro)i.push(e);i.push("")}if(t.resultShape&&t.resultShape.length>0){i.push("RESULT SHAPE (delivered via [async-callback])");for(const e of t.resultShape)i.push(` ${e}`);i.push("")}if(t.notes&&t.notes.length>0){i.push("NOTES");for(const e of t.notes)i.push(` - ${e}`);i.push("")}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Dr(e,t){const i=[];if(i.push("TOPIC: publish — handing the result off to publish_content / downstream artifact",""),t.intro&&t.intro.length>0){for(const e of t.intro)i.push(e);i.push("")}if(t.fields&&t.fields.length>0){i.push("PUBLISH_CONTENT FIELD MAPPING");const e=Math.max(...t.fields.map(e=>e.name.length));for(const n of t.fields)i.push(` ${n.name.padEnd(e)} ${n.value}`);i.push("")}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Hr(e,t){const i=[];i.push("TOPIC: examples — copy-paste-ready calls per scenario","");for(const e of t.examples){i.push(`EXAMPLE — ${e.caption}`);for(const t of e.command.split("\n"))i.push(` ${t}`);i.push("")}if(t.notExamples&&t.notExamples.length>0){i.push("NOT AN EXAMPLE (these all fail)");for(const e of t.notExamples){i.push(` # ❌ ${e.whyItFails}`);for(const t of e.command.split("\n"))i.push(` ${t}`);i.push("")}}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Br(e,t){const i=[];i.push("TOPIC: errors — failure codes + recovery breadcrumbs","");const n=t.errors??Lr;if(n.length>0){i.push("CODES");for(const e of n)i.push(` ${e.code}`),i.push(` when: ${e.when}`),e.recovery&&i.push(` recovery: ${e.recovery}`),i.push("")}for(;i.length>0&&""===i[i.length-1];)i.pop();return i.join("\n")}function Vr(e,t){const i=function(){const e=function(e){if(!e)return null;try{const t=JSON.parse(e);return"object"!=typeof t||null===t||Array.isArray(t)?null:t}catch{return null}}(process.env.PI_AGENT_CONTEXT),t={};return Jr(t,"user_id",e?.user_id??process.env.PI_USER_ID),Jr(t,"prompt_id",e?.prompt_id??process.env.PI_PROMPT_ID),Jr(t,"tool_call_id",e?.tool_call_id??process.env.PI_TOOL_CALL_ID),Jr(t,"sub_agent_id",e?.sub_agent_id??process.env.PI_SUB_AGENT_ID),Jr(t,"user_unique_name",e?.user_unique_name??process.env.PI_USER_UNIQUE_NAME),Jr(t,"user_tier",e?.user_tier??process.env.PI_USER_TIER),t}();return{quote:e,trace:{project_id:t.projectId,job_ref:t.jobRef,command:e.command,action:e.action,mode:t.mode,...void 0!==t.batchIndex?{batch_index:t.batchIndex}:{},...t.jobKey?{job_key:t.jobKey}:{},...i}}}function Jr(e,t,i){if("string"!=typeof i)return;const n=i.trim();n&&(e[t]=n)}function Kr(e){switch(e){case"E_BACKEND":case"E_INSUFFICIENT_CREDITS":return 1;default:return 2}}class Yr extends Error{code;hint;extra;constructor(e,t,i,n){super(t),this.code=e,this.hint=i,this.extra=n}}function Gr(e,t){if(e===t)return 0;if(!e.length)return t.length;if(!t.length)return e.length;const i=e.length,n=t.length;let o=Array(n+1).fill(0).map((e,t)=>t),r=Array(n+1).fill(0);for(let a=1;a<=i;a++){r[0]=a;for(let i=1;i<=n;i++){const n=e.charCodeAt(a-1)===t.charCodeAt(i-1)?0:1;r[i]=Math.min(r[i-1]+1,o[i]+1,o[i-1]+n)}[o,r]=[r,o]}return o[n]}function Wr(e,t){if(!t.length)return;let i=t[0],n=Gr(e,i);for(let o=1;o<t.length;o++){const r=Gr(e,t[o]);r<n&&(n=r,i=t[o])}return n<=Math.max(3,Math.floor(e.length/3))?i:void 0}class Zr extends Error{status;bodyText;url;constructor(e,t,i,n){super(e),this.status=t,this.bodyText=i,this.url=n}}async function Xr(e,t={}){const i=t.method??"GET",n={"content-type":"application/json",...t.headers??{}},o=void 0===t.body?void 0:"string"==typeof t.body?t.body:JSON.stringify(t.body),r=t.timeoutMs??3e4,a=(t.retries??0)+1;let s=null;for(let t=1;t<=a;t++){const l=new AbortController,c=setTimeout(()=>l.abort(),r);try{const r=await fetch(e,{method:i,headers:n,body:o,signal:l.signal}),c=await r.text();if(!r.ok){if(402===r.status){const e=ea(c);if(e)throw new Yr("E_INSUFFICIENT_CREDITS",e.message,"充值后重试;本次请求没有提交到上游供应商。",{billing_error:"INSUFFICIENT_CREDITS",...void 0!==e.balance?{balance:e.balance}:{},...void 0!==e.required?{required:e.required}:{}})}if(r.status>=500&&t<a){s=new Zr(`http ${r.status}`,r.status,c,e);continue}throw new Zr(`http ${r.status}: ${Qr(c,500)}`,r.status,c,e)}if(0===c.length)return;try{return JSON.parse(c)}catch{return c}}catch(e){if(e instanceof Zr)throw e;if(s=e,t>=a)break}finally{clearTimeout(c)}}throw s instanceof Error?s:new Error(String(s))}function Qr(e,t){return e.length>t?`${e.slice(0,t)}…`:e}function ea(e){const t=function(e){if(""===e.trim())return null;try{const t=JSON.parse(e);return ta(t)?t:null}catch{return null}}(e);if(!t)return null;const i="detail"in t?t.detail:t,n=ta(i)?i:t,o=na(n,"code"),r=na(n,"error");if("E_INSUFFICIENT_CREDITS"!==o&&"INSUFFICIENT_CREDITS"!==r&&(void 0===n.balance||void 0===n.required))return null;const a=ia(n,"balance"),s=ia(n,"required"),l=na(n,"message")??("string"==typeof i&&""!==i.trim()?i.trim():function(e,t){return void 0!==e&&void 0!==t?`余额不足: 当前 ${e} credits, 需 ${t}。请充值后重试。`:"余额不足。请充值后重试。"}(a,s));return{message:l,...void 0!==a?{balance:a}:{},...void 0!==s?{required:s}:{}}}function ta(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function ia(e,t){const i=e[t];return"number"==typeof i&&Number.isFinite(i)?i:void 0}function na(e,t){const i=e[t];return"string"==typeof i&&""!==i.trim()?i.trim():void 0}class oa extends Error{hint;constructor(e,t){super(e),this.hint=t,this.name="ProxyClientError"}}function ra(e){const t=process.env[e];if(!t)throw new oa(`${e} not set in sandbox env`,"this dl binary is the sandbox flavor; it only works when hono-pi-e2b injects DL_PROXY_TOKEN + CALLBACK_SERVER_URL via commands.run envs.");return t}const aa="X-DL-Billing";function sa(e){const t=ra("PI_PROJECT_ID");return{_dl_billing:Vr(e.quote,{projectId:t,jobRef:e.jobRef,mode:e.trace?.mode??"single",...void 0!==e.trace?.batchIndex?{batchIndex:e.trace.batchIndex}:{},...e.trace?.jobKey?{jobKey:e.trace.jobKey}:{}})}}function la(e){if(!e.billing)return{};const t=Buffer.from(JSON.stringify(sa(e.billing)),"utf-8").toString("base64url");return{[aa]:t}}async function ca(e){const t=ra("CALLBACK_SERVER_URL").replace(/\/+$/,""),i=ra("DL_PROXY_TOKEN"),n=await Xr(`${t}/sandbox-rpc/dl/billing/charge`,{method:"POST",headers:{Authorization:`Bearer ${i}`},body:sa(e),timeoutMs:1e4,retries:0});if(!n.receipt)throw new oa("callback-server returned malformed dl billing charge response");return n.receipt}async function da(e){const t=ra("CALLBACK_SERVER_URL").replace(/\/+$/,""),i=ra("DL_PROXY_TOKEN");await Xr(`${t}/sandbox-rpc/dl/billing/refund`,{method:"POST",headers:{Authorization:`Bearer ${i}`},body:{...sa(e),reason:e.reason,...e.chargeId?{charge_id:e.chargeId}:{}},timeoutMs:1e4,retries:0})}async function ua(e,t,i,n={}){const o=ra("CALLBACK_SERVER_URL").replace(/\/+$/,""),r=ra("DL_PROXY_TOKEN"),a=t.replace(/^\/+/,"").replace(/\/+$/,"");return Xr(a?`${o}/sandbox-rpc/dl/${e}/${a}`:`${o}/sandbox-rpc/dl/${e}`,{method:n.method??"POST",headers:{Authorization:`Bearer ${r}`,...n.headers??{},...la(n)},body:i,timeoutMs:n.timeoutMs??3e4,retries:n.retries??0})}async function pa(e,t,i,n={}){const o=ra("CALLBACK_SERVER_URL").replace(/\/+$/,""),r=ra("DL_PROXY_TOKEN"),a=t.replace(/^\/+/,"").replace(/\/+$/,""),s=Object.entries(i).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(t)}`).join("&"),l=a?`/sandbox-rpc/dl/${e}/${a}`:`/sandbox-rpc/dl/${e}`;return Xr(s?`${o}${l}?${s}`:`${o}${l}`,{method:"GET",headers:{Authorization:`Bearer ${r}`,...n.headers??{},...la(n)},timeoutMs:n.timeoutMs??3e4,retries:n.retries??0})}class ma extends Error{action;errors;constructor(e,t,i){super(e),this.action=t,this.errors=i,this.name="ActionValidationError"}}const ha={generate_music:{path:"/api/agent/music/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_video:{path:"/api/agent/video/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_image:{path:"/api/agent/image/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_sound:{path:"/api/agent/sound/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_tts:{path:"/api/agent/tts/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_tts_elevenlabs:{path:"/api/agent/tts/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},generate_tts_dialogue:{path:"/api/agent/tts/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},clone_voice:{path:"/api/agent/voice/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},design_voice:{path:"/api/agent/voice/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},finalize_voice:{path:"/api/agent/voice/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},remix_voice:{path:"/api/agent/voice/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},lipsync:{path:"/api/agent/video/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},motion_control:{path:"/api/agent/video/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},detect_shots:{path:"/api/v1/shot-analysis/analyze",baseEnv:"SHOT_ANALYSIS_BASE_URL",auth:"x-api-key",authEnv:"SHOT_ANALYSIS_API_KEY"},transcribe:{path:"/api/agent/asr/submit",baseEnv:"API_LAYER_BASE_URL",auth:"bearer",authEnv:"API_LAYER_API_KEY"},render_caption:{path:"/api/v1/caption/render",baseEnv:"CAPTION_RENDER_BASE_URL",auth:"x-api-key",authEnv:"CAPTION_RENDER_API_KEY"},analyze_beats:{path:"/analyze",baseEnv:"AUDIO_ANALYZER_BASE_URL",auth:"x-api-key",authEnv:"AUDIO_ANALYZER_API_KEY"},download_media:{path:"/api/v1/media-download/download",baseEnv:"MEDIA_DOWNLOAD_BASE_URL",auth:"x-api-key",authEnv:"MEDIA_DOWNLOAD_API_KEY"},streetview_image:{path:"/api/v1/streetview/image",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"},streetview_metadata:{path:"/api/v1/streetview/metadata",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"},geocode:{path:"/api/v1/geocode",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"},places_search:{path:"/api/v1/places/search",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"},place_photo:{path:"/api/v1/places/photo",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"},static_map:{path:"/api/v1/maps/static",baseEnv:"GEO_BASE_URL",auth:"x-api-key",authEnv:"GEO_API_KEY"}},fa={clone_voice:"instant-clone",design_voice:"design",finalize_voice:"create",remix_voice:"remix"};function ga(e){const t=ha[e];if(!t)throw new Error(`unknown action: ${e}`);return t}function va(e){const t=ha[e];return void 0!==t&&"x-api-key"===t.auth}const ya={ASR_BASE_URL:"asr",AUDIO_ANALYZER_BASE_URL:"audio-analyzer",CAPTION_RENDER_BASE_URL:"caption-render",SHOT_ANALYSIS_BASE_URL:"shot-analysis",MEDIA_DOWNLOAD_BASE_URL:"media-download",GEO_BASE_URL:"geo"};function ba(e){const t=(process.env.PI_PROJECT_ID??"").trim();if(t)return t;throw new oa("callback"===e?"PI_PROJECT_ID not set — required for callback URL routing under callback-resume v2":"PI_PROJECT_ID not set — required for dl billing trace","hono-pi-e2b injects PI_PROJECT_ID on every commands.run; set it manually in LOCAL_SANDBOX dev")}function _a(e,t,i){return t.billing?{...e,_dl_billing:Vr(t.billing,{projectId:i.projectId,jobRef:i.jobRef,mode:t.billingTrace?.mode??"single",...void 0!==t.billingTrace?.batchIndex?{batchIndex:t.billingTrace.batchIndex}:{},...t.billingTrace?.jobKey?{jobKey:t.billingTrace.jobKey}:{}})}:e}async function wa(e,t,i,n={}){const o=ga(e);!function(e,t){const i=Rr(e);if(!i)return;const n=i.zodSchema.safeParse(t);if(!n.success){const t=n.error.issues,i=t.map(e=>`${e.path.join(".")||"<root>"} ${e.message}`.trim()).join("; ");throw new ma(`params invalid for ${e}: ${i}`,e,t)}}(e,t);const r=Rr(e),a=r?function(e,t){if(!e.strip_before_submit||0===e.strip_before_submit.length)return t;const i={...t};for(const t of e.strip_before_submit)delete i[t];return i}(r,function(e,t){const i={...t};for(const[t,n]of Object.entries(e.default_params??{}))void 0===i[t]&&(i[t]=n);return i}(r,t)):t,{prefix:s,tail:l}=function(e){const t=ga(e),i=t.path.replace(/^\/+/,"");if("bearer"===t.auth)return{prefix:"media/submit",tail:i};const n=ya[t.baseEnv];if(!n)throw new Error(`no sandbox-rpc prefix for ${e} (baseEnv=${t.baseEnv})`);return{prefix:n,tail:i}}(e),c="bearer"===o.auth?(()=>{const t=(process.env.CALLBACK_SERVER_URL??"").replace(/\/+$/,"");if(!t)throw new oa("CALLBACK_SERVER_URL not set — async submit needs it for the vendor callback target","hono-pi-e2b injects this on every commands.run; set it manually in LOCAL_SANDBOX dev");const o=ba("callback"),{service:r,...s}=a,l=fa[e];return l&&(s.action=l),_a({service:r,callback_url:`${t}/callback/${encodeURIComponent(o)}/${i}`,params:s},n,{projectId:o,jobRef:i})})():_a(a,n,{projectId:n.billing?ba("billing"):"",jobRef:i});return{...await ua(s,l,c,{timeoutMs:1e3*(r?.timeout??120),retries:1}),job_ref:i}}function ka(e){return e.replace(/^_+/,"").replace(/_/g,"-")}function xa(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function Sa(e){return e._def??{}}function Ea(e){return Sa(e).type}function Oa(e){let t,i=e,n=!0,o=0;for(;o++<16;){const e=Sa(i),o=e.type;if("optional"!==o&&"nullable"!==o){if("default"!==o)break;if(n=!1,t="function"==typeof e.defaultValue?e.defaultValue():e.defaultValue,!e.innerType)break;i=e.innerType}else{if(n=!1,!e.innerType)break;i=e.innerType}}return{inner:i,required:n,default:t}}function Ta(e){return e.def??e._zod?.def}function Aa(e){const t=Sa(e).checks;if(!t)return!1;for(const e of t){const t=Ta(e);if("number_format"===t?.check&&"safeint"===t.format)return!0}return!1}function $a(e,t){const i=e.startsWith("_"),n=ka(e),{inner:o,required:r,default:a}=Oa(t),s=Ea(o),l={flag:n,jsonName:e,kind:"string",required:r,internal:i,default:a,description:t.description};switch(s){case"string":return l;case"number":{const{minimum:e,maximum:t}=function(e){const t=Sa(e).checks;if(!t)return{};const i={};for(const e of t){const t=Ta(e);t&&("greater_than"===t.check&&"number"==typeof t.value&&(i.minimum=t.value),"less_than"===t.check&&"number"==typeof t.value&&(i.maximum=t.value))}return i}(o);return{...l,kind:Aa(o)?"integer":"number",minimum:e,maximum:t}}case"boolean":return{...l,kind:"boolean"};case"enum":{const e=Sa(o).entries??{},t=Object.keys(e);return{...l,enum:t}}case"literal":{const e=Sa(o),t=e.values?.[0]??e.value;return{...l,enum:[String(t)]}}case"array":{const e=Sa(o).element;return{...l,kind:"array",itemKind:Na(e)}}case"union":{const e=Sa(o).options??[],t=e.some(e=>function(e){return"string"===e||"number"===e||"boolean"===e}(Ea(Oa(e).inner))),i=e.find(e=>"array"===Ea(Oa(e).inner));if(t&&i){const e=Sa(Oa(i).inner).element;return{...l,kind:"array",itemKind:Na(e),scalarOrArray:!0}}return{...l,kind:"object"}}default:return{...l,kind:"object"}}}function Na(e){if(!e)return;const t=Ea(Oa(e).inner);return"string"===t?"string":"number"===t?Aa(Oa(e).inner)?"integer":"number":"boolean"===t?"boolean":void 0}function ja(e,t){switch(e.kind){case"integer":{const e=Number(t);return Number.isFinite(e)?Math.trunc(e):t}case"number":{const e=Number(t);return Number.isFinite(e)?e:t}case"boolean":return Boolean(t);case"array":{const i=(Array.isArray(t)?t:[t]).map(t=>function(e,t){if("integer"===e){const e=Number(t);return Number.isFinite(e)?Math.trunc(e):t}if("number"===e){const e=Number(t);return Number.isFinite(e)?e:t}return"boolean"===e?Boolean(t):t}(e.itemKind,t));return e.scalarOrArray&&1===i.length?i[0]:i}default:if("object"===e.kind&&"string"==typeof t)try{return JSON.parse(t)}catch{return t}return t}}async function Ca(e,t){if("-"===e)try{const e=await async function(){if(process.stdin.isTTY)throw new Yr("E_FILE_MISSING","`--*-file=-` requested stdin but stdin is a TTY (nothing piped in)","pipe a file via stdin, e.g. `cat params.json | dl ... --params-file=-`, or pass a file path",{stdin_is_tty:!0});const e=[];for await(const t of process.stdin)e.push("string"==typeof t?Buffer.from(t):t);return Buffer.concat(e).toString("utf8")}();if(0===e.length)throw new Yr("E_FILE_MISSING",`${t}=- received empty stdin`,`pipe non-empty content into \`${t}=-\`, or pass a file path`,{source:"<stdin>"});return{label:"<stdin>",raw:e}}catch(e){if(e instanceof Yr)throw e;const i=e instanceof Error?e.message:String(e);throw new Yr("E_FILE_MISSING",`failed to read stdin for ${t}: ${i}`,void 0,{source:"<stdin>"})}const i=o(e);try{return{label:i,raw:await g(i,"utf8")}}catch(n){const o=n instanceof Error?n.message:String(n);throw new Yr("E_FILE_MISSING",`${t}: cannot read file at ${i} (${o})`,`check the path is reachable from cwd; cwd=${process.cwd()}; if the file is meant to be on stdin pass \`${t}=-\``,{flag:t,given:e,resolved:i,cwd:process.cwd()})}}function Ra(e,t){try{return JSON.parse(e.raw)}catch(i){const n=i instanceof Error?i.message:String(i),o=/position (\d+)/.exec(n),r=o?Number(o[1]):-1,a=r>=0?function(e,t){const i=e.slice(0,Math.max(0,t)),n=e.split("\n"),o=i.split("\n").length-1,r=t-(i.lastIndexOf("\n")+1),a=Math.max(0,o-1),s=Math.min(n.length,o+2),l=n.slice(a,s).map((e,t)=>`${a+t===o?">":" "} ${(a+t+1).toString().padStart(3," ")}: ${e}`).join("\n");return{line:o+1,column:r+1,snippet:l}}(e.raw,r):void 0;throw new Yr("E_FILE_PARSE",`${t} (${e.label}): JSON parse failed (${n})`,"check for missing/extra commas, unbalanced braces, or single quotes — JSON requires double quotes",{flag:t,source:e.label,...a?{line:a.line,column:a.column,snippet:a.snippet}:{}})}}async function Ia(e,t){const i=await Ca(e,t),n=Ra(i,t);if(!Array.isArray(n))throw new Yr("E_SCHEMA",`${t} (${i.label}): expected JSON array, got ${Ma(n)}`,'rewrite the file to start with `[`. Example: [{"job_key":"a","params":{}}]',{flag:t,source:i.label,got:Ma(n),expected:"JSON array"});return{source:i,data:n}}function La(e,t){const i={label:"inline",raw:e},n=Ra(i,t);if(!Array.isArray(n))throw new Yr("E_SCHEMA",`${t}: expected JSON array, got ${Ma(n)}`,`pass an inline JSON array. Example: ${t} '[{"job_key":"a","params":{}}]'`,{flag:t,got:Ma(n),expected:"JSON array"});return{source:i,data:n}}function za(e){throw new Yr("E_SCHEMA",`${e.inline} and ${e.file} are mutually exclusive`,`prefer ${e.inline} (inline); file/stdin content is invisible to the billing extension / dl adapter`,{inline_flag:e.inline,file_flag:e.file})}async function qa(e,t,i){const n="string"==typeof e&&""!==e,o="string"==typeof t&&""!==t;return n&&o&&za(i),n?function(e,t){const i={label:"inline",raw:e},n=Ra(i,t);if(null===n||"object"!=typeof n||Array.isArray(n))throw new Yr("E_SCHEMA",`${t}: expected JSON object, got ${Ma(n)}`,`pass an inline JSON object. Example: ${t} '{"key":"value"}'`,{flag:t,got:Ma(n),expected:"JSON object"});return{source:i,data:n}}(e,i.inline):o?async function(e,t){const i=await Ca(e,t),n=Ra(i,t);if(null===n||"object"!=typeof n||Array.isArray(n))throw new Yr("E_SCHEMA",`${t} (${i.label}): expected JSON object, got ${Ma(n)}`,'rewrite the file to start with `{`. Example: {"key":"value"}',{flag:t,source:i.label,got:Ma(n),expected:"JSON object"});return{source:i,data:n}}(t,i.file):void 0}async function Pa(e,t,i){const n="string"==typeof e&&""!==e,o="string"==typeof t&&""!==t;if(n&&o&&za(i),n){if(""===e.trim())throw new Yr("E_SCHEMA",`${i.inline}: expected non-empty text, got empty input`,`pass the text content as an inline string to ${i.inline}`,{flag:i.inline,expected:"non-empty text"});return{label:"inline",raw:e}}if(o)return async function(e,t){const i=await Ca(e,t);if(""===i.raw.trim())throw new Yr("E_SCHEMA",`${t} (${i.label}): expected non-empty text, got empty input`,`pipe or write the long-text content into ${t}; an empty file is never a valid value`,{flag:t,source:i.label,expected:"non-empty text"});return i}(t,i.file)}function Ma(e){if(null===e)return"null";if(Array.isArray(e))return"array";const t=typeof e;return"object"===t?"object":t}function Ua(e){process.stdout.write(`${JSON.stringify(e)}\n`),process.exit(0)}function Fa(e,t,i){const n={ok:!1,code:"E_BACKEND",error:e,message:e,...t?{hint:t}:{},...i??{}};process.stderr.write(`${JSON.stringify(n)}\n`),process.exit(1)}function Da(e,t,i,n){const o={ok:!1,code:e,error:t,message:t,...i?{hint:i}:{},...n??{}};process.stderr.write(`${JSON.stringify(o)}\n`),process.exit(Kr(e))}function Ha(e){Da(e.code,e.message,e.hint,e.extra)}function Ba(e,t){if("1"!==process.env.DL_ECHO_PARSED)return;const i=JSON.stringify({echo:"parsed",...e});process.stderr.write(`${i}\n`)}function Va(e){const t=JSON.stringify({event:"submitted",...e});process.stderr.write(`${t}\n`)}class Ja extends Error{constructor(e){super(e),this.name="JsonPointerError"}}const Ka="@file:";function Ya(e){return"string"==typeof e&&e.startsWith(Ka)}function Ga(e,i){if(!e.startsWith(Ka))throw new Yr("E_SCHEMA",`不是 @file: 语法:${e}`,"正确格式:@file:/abs/path.json#/json/pointer",{flag:i.flag});const n=e.slice(6),o=n.indexOf("#");if(o<0)throw new Yr("E_SCHEMA",`${i.flag} 缺少 JSON Pointer(# 之后的部分):${e}`,"@file: 必须带 #/some/pointer 才能定位到具体字段,避免误读入整个文件",{flag:i.flag});const a=n.slice(0,o),s=n.slice(o+1);if(!a)throw new Yr("E_SCHEMA",`${i.flag} 路径为空:${e}`,void 0,{flag:i.flag});if(!r(a))throw new Yr("E_SCHEMA",`${i.flag} 路径必须是绝对路径:${a}`,"避免 cwd 歧义。可在 shell 里用 $PWD/相对路径 转成绝对路径",{flag:i.flag});let l,c,d;try{l=t(a,"utf8")}catch(e){const t=e instanceof Error?e.message:String(e);throw new Yr("E_FILE_MISSING",`${i.flag} 读取文件失败:${a}(${t})`,void 0,{flag:i.flag,path:a})}try{c=JSON.parse(l)}catch(e){const t=e instanceof Error?e.message:String(e);throw new Yr("E_FILE_PARSE",`${i.flag} 不是合法 JSON:${a}(${t})`,void 0,{flag:i.flag,path:a})}try{d=function(e,t){const i=function(e){if(""===e)return[];if(!e.startsWith("/"))throw new Ja(`JSON Pointer 必须以 "/" 开头(或为空字符串表示根节点):${e}`);return e.slice(1).split("/").map(e=>e.replace(/~1/g,"/").replace(/~0/g,"~"))}(t);let n=e;const o=[];for(const e of i){if(o.push(e),null==n)throw new Ja(`JSON Pointer 无法定位:/${o.join("/")}(中途遇到 ${null===n?"null":"undefined"})`);if(Array.isArray(n)){if(!/^\d+$/.test(e))throw new Ja(`JSON Pointer 数组段必须是非负整数:/${o.join("/")}(实际:${JSON.stringify(e)})`);const t=Number(e);if(t>=n.length)throw new Ja(`JSON Pointer 数组越界:/${o.join("/")}(长度 ${n.length})`);n=n[t];continue}if("object"==typeof n){const t=n;if(!Object.hasOwn(t,e))throw new Ja(`JSON Pointer 字段不存在:/${o.join("/")}`);n=t[e];continue}throw new Ja(`JSON Pointer 无法在标量上继续下钻:/${o.join("/")}(当前类型 ${typeof n})`)}return n}(c,s.startsWith("/")?s:`/${s}`)}catch(e){if(e instanceof Ja)throw new Yr("E_SCHEMA",`${i.flag} ${e.message}`,void 0,{flag:i.flag,path:a,pointer:s});throw e}if(i.requireString&&"string"!=typeof d)throw new Yr("E_SCHEMA",`${i.flag} JSON Pointer 命中的值不是字符串:${s}(实际类型:${Array.isArray(d)?"array":typeof d})`,void 0,{flag:i.flag,path:a,pointer:s});return d}function Wa(e,i){if(!e.startsWith(Ka))throw new Yr("E_SCHEMA",`不是 @file: 语法:${e}`,"正确格式:@file:/abs/path.txt",{flag:i.flag});const n=e.slice(6);if(n.indexOf("#")>=0){const t=Ga(e,{flag:i.flag,requireString:!0});if("string"==typeof t)return t;throw new Yr("E_SCHEMA",`${i.flag} JSON Pointer 命中的值不是字符串`,void 0,{flag:i.flag})}const o=n;if(!o)throw new Yr("E_SCHEMA",`${i.flag} 路径为空:${e}`,void 0,{flag:i.flag});if(!r(o))throw new Yr("E_SCHEMA",`${i.flag} 路径必须是绝对路径:${o}`,"避免 cwd 歧义。可在 shell 里用 $PWD/相对路径 转成绝对路径",{flag:i.flag});try{return t(o,"utf8")}catch(e){const t=e instanceof Error?e.message:String(e);throw new Yr("E_FILE_MISSING",`${i.flag} 读取文件失败:${o}(${t})`,void 0,{flag:i.flag,path:o})}}function Za(e){return Ya(e.prompt)?{...e,prompt:Wa(e.prompt,{flag:"--prompt"})}:e}function Xa(e,t){const i=Array.isArray(e)?e:e.issues,n=t.maxErrors??5,o=function(e){const t={invalid_type:0,required:0,invalid_value:1,invalid_enum_value:1,invalid_string:2,too_small:3,too_big:3,unrecognized_keys:4,invalid_union:5,custom:6};return[...e].sort((e,i)=>{const n=t[e.code]??99,o=t[i.code]??99;return n!==o?n-o:Qa(es(e.path)).localeCompare(Qa(es(i.path)))})}(i).slice(0,n);return o.map(e=>function(e,t){switch(e.code){case"invalid_type":return function(e,t){const i=e,n=es(e.path),o=i.received??function(e){if(!e)return;const t=/received\s+(\S+?)\b/.exec(e);return t?.[1]}(e.message),r=void 0===o?ts(t.input??t.jobs,n):void 0,a=o??function(e){if(null===e)return"null";if(void 0===e)return"undefined";if(Array.isArray(e))return"array";const t=typeof e;if("number"===t&&Number.isNaN(e))return"nan";if("object"===t){const t=e.constructor;return t&&t!==Object&&"string"==typeof t.name&&t.name.length>0?t.name:"object"}return t}(r),s="undefined"===o||void 0===o&&void 0===r,l=is(n,t);return s?{code:"E_SCHEMA",message:`${l.prefix} is required`,expected:ns(t.flags,os(es(e.path)))??i.expected,got:void 0,instance_path:l.instance_path,mode:t.mode,verb:t.verb,job_index:l.job_index,job_key:l.job_key,flag:l.flag,hint:`run \`dl ${t.verb} --print-schema\` to see all required fields`}:{code:"E_SCHEMA",message:`${l.prefix}: expected ${i.expected??"<unknown>"}, got ${a??"<unknown>"}`,expected:i.expected,got:a,instance_path:l.instance_path,mode:t.mode,verb:t.verb,job_index:l.job_index,job_key:l.job_key,flag:l.flag,hint:`run \`dl ${t.verb} --print-schema\` to see expected types`}}(e,t);case"invalid_value":case"invalid_enum_value":return function(e,t){const i=e,n=(i.values??[]).map(e=>String(e)),o=i.received??ts(t.input??t.jobs,es(e.path)),r=is(es(e.path),t),a="string"==typeof o?Wr(o,n):void 0;return{code:"E_SCHEMA",message:a?`${r.prefix}: expected one of {${n.join("|")}}, got ${JSON.stringify(o)} (did you mean ${JSON.stringify(a)}?)`:`${r.prefix}: expected one of {${n.join("|")}}, got ${JSON.stringify(o)}`,expected:`enum {${n.join("|")}}`,got:o,instance_path:r.instance_path,mode:t.mode,verb:t.verb,job_index:r.job_index,job_key:r.job_key,flag:r.flag,hint:a?"re-run with the suggested value":`run \`dl ${t.verb} --print-schema\` for the full enum`}}(e,t);case"too_small":case"too_big":return function(e,t){const i=e,n=is(es(e.path),t),o="too_small"===e.code?"at least":"at most",r="too_small"===e.code?i.minimum:i.maximum,a="string"===i.type?" chars":"";return{code:"E_SCHEMA",message:`${n.prefix}: expected ${o} ${r}${a}, got ${rs(i.received)}`,expected:`${o} ${r}${a}`,got:i.received,instance_path:n.instance_path,mode:t.mode,verb:t.verb,job_index:n.job_index,job_key:n.job_key,flag:n.flag,hint:`adjust ${n.prefix} so it satisfies the bound`}}(e,t);case"unrecognized_keys":return function(e,t){const i=e,n=i.keys?.[0]??"<unknown>",o=t.flags.map(e=>e.jsonName),r=Wr(n,o),a=is(es(e.path),t,n),s=`--${ka(n)}`,l=r?`--${ka(r)}`:void 0;return{code:"E_SCHEMA",message:l?`${s} is not a valid flag (did you mean ${l}?)`:`${s} is not a valid flag`,expected:`one of: ${o.map(e=>`--${ka(e)}`).join(", ")}`,got:n,instance_path:a.instance_path,mode:t.mode,verb:t.verb,job_index:a.job_index,job_key:a.job_key,flag:s,hint:l?`re-run with ${l}`:`run \`dl ${t.verb} --help\` for the full flag list`}}(e,t);case"invalid_union":return function(e,t){const i=is(es(e.path),t);return{code:"E_SCHEMA",message:`${i.prefix}: must satisfy one of the conditional shapes (e.g. provide image_url OR image_base64, not both/neither)`,expected:"one-of constraint",got:void 0,instance_path:i.instance_path,mode:t.mode,verb:t.verb,job_index:i.job_index,job_key:i.job_key,flag:i.flag,hint:`run \`dl ${t.verb} --print-schema\` for the conditional required-field combinations`}}(e,t);case"custom":return function(e,t){const i=is(es(e.path),t);return{code:"E_SCHEMA",message:`${i.prefix}: ${e.message??"validation failed"}`,expected:void 0,got:void 0,instance_path:i.instance_path,mode:t.mode,verb:t.verb,job_index:i.job_index,job_key:i.job_key,flag:i.flag,hint:`run \`dl ${t.verb} --print-schema\` for the schema`}}(e,t);default:return function(e,t){const i=is(es(e.path),t);return{code:"E_SCHEMA",message:`${i.prefix}: ${e.message??"validation failed"}`,expected:void 0,got:void 0,instance_path:i.instance_path,mode:t.mode,verb:t.verb,job_index:i.job_index,job_key:i.job_key,flag:i.flag,hint:`run \`dl ${t.verb} --print-schema\` for the schema`}}(e,t)}}(e,t))}function Qa(e){return 0===e.length?"":`/${e.join("/")}`}function es(e){return e.map(e=>"symbol"==typeof e?e.toString():e)}function ts(e,t){let i=e;for(const e of t){if(null==i||"object"!=typeof i)return;i=i[e]}return i}function is(e,t,i){const n=void 0!==i?[...e,i]:[...e],o=0===n.length?"":`/${n.join("/")}`;if("single"===t.mode){const t=i??e[e.length-1],n="string"==typeof t?`--${ka(t)}`:void 0;return{instance_path:o,flag:n,job_index:void 0,job_key:void 0,prefix:n??"<root>"}}const r="number"==typeof e[0]?e[0]:void 0,a=(void 0!==i?[...e.slice(1),i]:e.slice(1)).map(String),s=void 0!==r&&t.jobs?t.jobs[r]:void 0;return{instance_path:o,flag:void 0,job_index:r,job_key:s&&"string"==typeof s.job_key?s.job_key:void 0,prefix:void 0===r?"--jobs-file":a.length>0?`--jobs-file[${r}].${a.join(".")}`:`--jobs-file[${r}]`}}function ns(e,t){if(!t)return;const i=e.find(e=>e.jsonName===t);return i?i.enum?`enum {${i.enum.join("|")}}`:i.kind:void 0}function os(e){const t=e[e.length-1];return"string"==typeof t?t:void 0}function rs(e){if(null===e)return"null";if(void 0===e)return"undefined";if(Array.isArray(e))return"array";const t=typeof e;return"object"===t?"object":"string"===t?JSON.stringify(e):String(e)}function as(e,t){const i=function(e){const{inner:t}=Oa(e);if("object"!==Ea(t))return[];const i=Sa(t).shape??{},n=[];for(const[e,t]of Object.entries(i))n.push($a(e,t));return n}(t.schema),n={verb:t.verb,description:t.description,whenToUse:t.whenToUse,whenNotToUse:t.whenNotToUse,flags:i,supportsBatch:t.supportsBatch,examples:t.examples,notExamples:t.notExamples,outputSingle:t.outputSingle,outputBatch:t.outputBatch,errors:t.errors,notes:t.notes,extraFlags:t.extraFlags?.map(e=>({flag:e.spec.split(/\s+/)[0],description:e.description,...e.enum?{enum:e.enum}:{}})),modelTopic:t.modelTopic,preflightTopic:t.preflightTopic,policyTopic:t.policyTopic,compositionTopic:t.compositionTopic,asyncTopic:t.asyncTopic,publishTopic:t.publishTopic},o=function(e){const t=[],i=!!(e.modelTopic||e.preflightTopic||e.policyTopic||e.compositionTopic||e.asyncTopic||e.publishTopic);if(t.push("DESCRIPTION",` ${e.description}`,""),e.whenToUse.length>0){t.push("WHEN TO USE");for(const i of e.whenToUse)t.push(` - ${i}`);t.push("")}if(e.whenNotToUse&&e.whenNotToUse.length>0){t.push("WHEN NOT TO USE");for(const i of e.whenNotToUse)t.push(` - ${i}`);t.push("")}if(e.notes&&e.notes.length>0){t.push("NOTES");for(const i of e.notes)t.push(` - ${i}`);t.push("")}if(i){const i=function(e,t){if(!(t.modelTopic||t.preflightTopic||t.policyTopic||t.compositionTopic||t.asyncTopic||t.publishTopic))return[];const i=[];t.modelTopic&&i.push({topic:"model",oneLiner:"service ranking + per-service call shape + decision logic"}),t.preflightTopic&&i.push({topic:"preflight",oneLiner:"decisions you must make before the first call"}),t.policyTopic&&i.push({topic:"policy",oneLiner:"user-facing communication rules + payment-package gate"}),t.compositionTopic&&i.push({topic:"composition",oneLiner:"how upstream / sibling skills consume this output"}),t.asyncTopic&&i.push({topic:"async",oneLiner:"detach-by-default protocol + result shape"}),t.publishTopic&&i.push({topic:"publish",oneLiner:"handing the result off to publish_content"}),i.push({topic:"examples",oneLiner:"copy-paste-ready calls per scenario"}),i.push({topic:"errors",oneLiner:"failure codes + recovery breadcrumbs"});const n=["LEARN MORE (drill down for the specific decision you face)"];for(const t of i)n.push(` dl ${e} ${t.topic.padEnd(11)} -h — ${t.oneLiner}`);return n}(e.verb,e);if(i.length>0){for(const e of i)t.push(e);t.push("")}}const n=e.flags.filter(e=>e.required),o=e.flags.filter(e=>!e.required);if(n.length>0){t.push("REQUIRED");for(const e of n)t.push(...zr(e));t.push("")}if(o.length>0||e.extraFlags&&e.extraFlags.length>0){t.push("OPTIONAL");for(const e of o)t.push(...zr(e));for(const i of e.extraFlags??[])t.push(` ${i.flag.padEnd(22)} ${i.description}`),i.enum&&t.push(` one of: ${i.enum.join(", ")}`);t.push("")}e.supportsBatch&&(t.push("BATCH MODE (mutually exclusive with the per-job scalar flags above)"),t.push(" --jobs <inline-json> RECOMMENDED. JSON array of {job_key, ...same fields as scalars above}"," passed as an inline string. Lets the LLM-side billing extension"," preflight charge the full batch cost (= N × per-action cost) so"," insufficient-credits requests block before vendor is touched.",' Usage: --jobs "$(cat /workspace/jobs.json)" — or pass JSON directly.'," --jobs-file <path|-> LEGACY. JSON array via file path; `-` reads stdin. Billing extension"," cannot see the file content, so falls back to per-job best-effort"," charging — users with low balance can partially get free vendor work."," Prefer --jobs unless the JSON is too large for argv (uncommon)."),t.push(""));const r=e.utility??Ir;t.push("UTILITY");for(const e of r)t.push(` ${e.flag.padEnd(22)} ${e.description}`);if(t.push(""),!i){for(const i of e.examples){t.push(`EXAMPLE — ${i.caption}`);for(const e of i.command.split("\n"))t.push(` ${e}`);t.push("")}if(e.notExamples&&e.notExamples.length>0){t.push("NOT AN EXAMPLE (these all fail)");for(const i of e.notExamples){t.push(` # ❌ ${i.whyItFails}`);for(const e of i.command.split("\n"))t.push(` ${e}`);t.push("")}}}if(e.outputSingle){t.push("OUTPUT (single, success)");for(const i of e.outputSingle.split("\n"))t.push(` ${i}`);t.push("")}if(e.outputBatch&&e.supportsBatch){t.push("OUTPUT (batch, success)");for(const i of e.outputBatch.split("\n"))t.push(` ${i}`);t.push("")}if(!i){const i=e.errors??Lr;if(i.length>0){t.push("ERRORS");for(const e of i){const i=e.recovery?` — ${e.recovery}`:"";t.push(` ${e.code.padEnd(11)} ${e.when}${i}`)}}}for(;t.length>0&&""===t[t.length-1];)t.pop();return t.join("\n")}(n),r=e.command(t.verb).description(t.description);r.configureHelp({formatHelp:()=>o}),function(e,t,i){const n=t.verb;if(t.modelTopic){const i=t.modelTopic,o=e.command("model [service]").description("service ranking + decision logic; pass <service> for per-service profile");o.configureHelp({formatHelp:()=>qr(n,i)}),o.action(e=>{console.log(qr(n,i,e)),process.exit(0)})}if(t.preflightTopic){const i=t.preflightTopic,o=!!t.modelTopic,r=e.command("preflight").description("decisions you must make before the first call");r.configureHelp({formatHelp:()=>Pr(n,i,o)}),r.action(()=>{console.log(Pr(n,i,o)),process.exit(0)})}if(t.policyTopic){const i=t.policyTopic,n=e.command("policy").description("user-facing communication rules + payment-package gate");n.configureHelp({formatHelp:()=>Mr(0,i)}),n.action(()=>{console.log(Mr(0,i)),process.exit(0)})}if(t.compositionTopic){const i=t.compositionTopic,n=e.command("composition").description("how upstream / sibling skills consume this output");n.configureHelp({formatHelp:()=>Ur(0,i)}),n.action(()=>{console.log(Ur(0,i)),process.exit(0)})}if(t.asyncTopic){const i=t.asyncTopic,n=e.command("async").description("detach-by-default protocol + result shape");n.configureHelp({formatHelp:()=>Fr(0,i)}),n.action(()=>{console.log(Fr(0,i)),process.exit(0)})}if(t.publishTopic){const i=t.publishTopic,n=e.command("publish").description("handing the result off to publish_content");n.configureHelp({formatHelp:()=>Dr(0,i)}),n.action(()=>{console.log(Dr(0,i)),process.exit(0)})}if(!!(t.modelTopic||t.preflightTopic||t.policyTopic||t.compositionTopic||t.asyncTopic||t.publishTopic)){if(t.examples.length>0||t.notExamples&&t.notExamples.length>0){const t=e.command("examples").description("copy-paste-ready calls per scenario");t.configureHelp({formatHelp:()=>Hr(0,i)}),t.action(()=>{console.log(Hr(0,i)),process.exit(0)})}const n=e.command("errors").description("failure codes + recovery breadcrumbs");n.configureHelp({formatHelp:()=>Br(0,i)}),n.action(()=>{console.log(Br(0,i)),process.exit(0)})}}(r,t,n);const a=function(e){const t=[e.name()];let i=e.parent;for(;i&&i.parent;)t.unshift(i.name()),i=i.parent;return t.join(" ")}(r);for(const e of i)ss(r,e);if(t.extraFlags)for(const e of t.extraFlags)void 0!==e.default?r.option(e.spec,e.description,e.default):r.option(e.spec,e.description);t.supportsBatch&&(r.option("--jobs <inline-json>","BATCH MODE (recommended): JSON array of {job_key, ...same fields as scalars above} as an inline string; lets pi-extension preflight charge the full batch cost"),r.option("--jobs-file <path|->","BATCH MODE (legacy): JSON array via file path; `-` reads stdin. Prefer --jobs because the LLM-side billing extension cannot count jobs from a file path and must fall back to per-job best-effort charging.")),r.option("--print-schema","emit JSON schema for this verb's single + batch shape and exit"),r.option("--echo-parsed","echo canonicalised input on stderr (debug)"),r.action(async e=>{const n=e;n.printSchema&&function(e,t,i){const n={};for(const e of t)e.required&&(n[e.flag]=cs(e));const o=e.extraFlags?.map(e=>({flag:e.spec.split(/\s+/)[0],type:"string",required:!1,...e.enum?{enum:e.enum}:{},...void 0!==e.default?{default:e.default}:{}}))??[],r={ok:!0,verb:i,single:{scalars:[...t.map(e=>({flag:`--${e.flag}`,type:e.kind,required:e.required,...e.enum?{enum:e.enum}:{},...void 0!==e.minimum?{minimum:e.minimum}:{},...void 0!==e.maximum?{maximum:e.maximum}:{},...void 0!==e.default?{default:e.default}:{},...e.internal?{internal:!0,note:"stripped before submit"}:{}})),...o],example:n},batch:e.supportsBatch?{shape:"array<object>",item_required:["job_key",...t.filter(e=>e.required).map(e=>e.jsonName)],example:[{job_key:"job_0",...ds(t)}]}:null};process.stdout.write(`${JSON.stringify(r,null,2)}\n`),process.exit(0)}(t,i,a);const o="string"==typeof n.jobs&&""!==n.jobs,r="string"==typeof n.jobsFile&&""!==n.jobsFile,s=o||r,l=function(e,t){for(const i of e){const e=t[ls(i.flag)];if(void 0!==e&&("boolean"!=typeof e||!1!==e))return!0}return!1}(i,n);o&&r&&Da("E_SCHEMA","--jobs and --jobs-file are mutually exclusive","pick one batch input mode; --jobs is preferred so the billing extension can preflight charge the full batch cost.",{verb:a}),s&&l&&Da("E_SCHEMA","batch flag is mutually exclusive with the per-job scalar flags",`pick one mode: pass a job array via --jobs '<inline-json>' (or --jobs-file=path) OR pass scalar flags directly. Run \`dl ${a} --print-schema\` to see both shapes.`,{verb:a});try{s?await async function(e,t,i,n){const o="string"==typeof i.jobs&&""!==i.jobs,r=o?"--jobs":"--jobs-file",{data:a}=o?La(String(i.jobs),"--jobs"):await Ia(String(i.jobsFile),"--jobs-file");if(!o){const e=String(i.jobsFile),t="-"===e?"<path/to/jobs.json>":e;process.stderr.write(`[dl] DEPRECATED: --jobs-file=${e} prevents the billing extension from sizing the batch, so insufficient-credit requests can only be reconciled after vendor submit (partial free work possible). Switch to --jobs '<inline-json>'.\n[dl] Migration: dl ${n} --jobs "$(cat ${t})"\n[dl] See: dl ${n} -h (BATCH MODE section).\n`)}0===a.length&&Da("E_SCHEMA",`${r} must be a non-empty JSON array`,`run \`dl ${n} --print-schema\` for the batch shape`,{verb:n,flag:r});const s=[],l=[];for(let t=0;t<a.length;t++){try{a[t]=Za(a[t]),e.transformParams&&(a[t]=e.transformParams(a[t],{mode:"batch"}))}catch(e){if(e instanceof Yr){s.push({code:"custom",path:[t],message:e.message});continue}throw e}const i=e.schema.safeParse(a[t]);if(i.success){const n=a[t],o="string"==typeof n.job_key?n.job_key:`job_${t}`;if(e.preflight)try{e.preflight(i.data)}catch(e){if(!(e instanceof Yr))throw e;s.push({code:"custom",path:[t],message:e.message});continue}l.push({jobKey:o,params:i.data})}else for(const e of i.error.issues)s.push({...e,path:[t,...e.path]})}if(s.length>0){const e=Xa(s,{verb:n,flags:t,mode:"batch",jobs:a,input:a}),i=e[0];Da("E_SCHEMA",i.message,i.hint,{verb:i.verb,instance_path:i.instance_path,expected:i.expected,got:i.got,...void 0!==i.job_index?{job_index:i.job_index}:{},...i.job_key?{job_key:i.job_key}:{},...e.length>1?{details:e.slice(1)}:{}})}const c=e.resolveActionName?e.resolveActionName(i):e.actionName,d=l.map((i,o)=>{try{const r=us(e,i.params,{fullVerb:n,flags:t,mode:"batch",input:i.params,command:n,action:c,jobIndex:o,jobKey:i.jobKey});return{...i,billing:r}}catch(e){throw e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_index:o,job_key:i.jobKey}),e}});Ba({command:n,mode:"batch",jobs:a});const u=await Promise.all(d.map(async(e,t)=>{const i=e.params,n=f(),o=e.billing;try{const r=await wa(c,i,n,{billing:o,billingTrace:{mode:"batch",batchIndex:t,jobKey:e.jobKey}});Va({action:c,job_ref:n,mode:"batch",job_key:e.jobKey,index:t});const{job_ref:a,...s}=r;return va(c)?{job_key:e.jobKey,index:t,job_ref:n,...o?{billing:o}:{},...s}:{job_key:e.jobKey,index:t,job_ref:n,status:"pending",...o?{billing:o}:{},...s}}catch(i){if(i instanceof Yr)return{job_key:e.jobKey,index:t,job_ref:n,status:"failed",code:i.code,error:i.message,message:i.message,...i.hint?{hint:i.hint}:{},...i.extra??{}};const o=i instanceof Error?i.message:String(i);return{job_key:e.jobKey,index:t,job_ref:n,status:"failed",error:o}}})),p=u.some(e=>"failed"===e.status),m={ok:!p,action:c,results:u};u.some(e=>"E_INSUFFICIENT_CREDITS"===e.code)&&Da("E_INSUFFICIENT_CREDITS","one or more batch jobs failed because credits are insufficient","充值后重试;status=failed 的 job 没有提交到上游供应商。",m),p&&Fa("one or more batch jobs failed","inspect .results[].status",m),Ua(m)}(t,i,n,a):await async function(e,t,i,n){let o=function(e,t){const i={};for(const n of e){const e=t[xa(n.flag)];void 0!==e&&(i[n.jsonName]=ja(n,e))}return i}(t,i);try{o=Za(o),e.transformParams&&(o=e.transformParams(o,{opts:i,mode:"single"}))}catch(e){throw e instanceof Yr&&Ha(e),e}const r=e.schema.safeParse(o);if(!r.success){const e=Xa(r.error,{verb:n,flags:t,mode:"single",input:o}),i=e[0];Da("E_SCHEMA",i.message,i.hint,{verb:i.verb,instance_path:i.instance_path,expected:i.expected,got:i.got,...i.flag?{flag:i.flag}:{},...e.length>1?{details:e.slice(1)}:{}})}if(e.preflight)try{e.preflight(r.data)}catch(e){throw e instanceof Yr&&Ha(e),e}Ba({command:n,mode:"single",params:r.data});const a=f(),s=e.resolveActionName?e.resolveActionName(i):e.actionName,l=us(e,r.data,{fullVerb:n,flags:t,mode:"single",input:r.data,command:n,action:s});try{const t=r.data,n=await wa(s,t,a,{billing:l,billingTrace:{mode:"single"}}),o=e.transformResult?e.transformResult(n,{params:r.data,opts:i,mode:"single"}):n;Va({action:s,job_ref:a,mode:"single"}),va(s)&&Ua({ok:!0,...o,...l?{billing:l}:{}}),Ua({ok:!0,status:"pending",...o,...l?{billing:l}:{}})}catch(t){t instanceof ma&&Da("E_SCHEMA",t.message,`run \`dl ${n} --print-schema\` for required fields`,{verb:n,details:t.errors}),t instanceof Yr&&Da(t.code,t.message,t.hint,{...t.extra??{},job_ref:a,action:e.actionName}),Fa(t instanceof Error?t.message:String(t),void 0,{job_ref:a,action:e.actionName})}}(t,i,n,a)}catch(e){throw e instanceof Yr&&Ha(e),e}})}function ss(e,t){const i=`--${t.flag}`,n=function(e){const t=[];return t.push(e.required?"REQUIRED":"optional"),e.enum&&t.push(`one of: ${e.enum.join(", ")}`),void 0===e.minimum&&void 0===e.maximum||t.push([void 0!==e.minimum?`>= ${e.minimum}`:void 0,void 0!==e.maximum?`<= ${e.maximum}`:void 0].filter(Boolean).join(", ")),e.description&&t.push(e.description),t.join(" — ")}(t);switch(t.kind){case"boolean":return void e.option(i,n);case"array":return void e.option(`${i} <${t.itemKind??"value"}>`,`${n}; repeatable`,(e,t=[])=>[...t,e]);case"integer":case"number":return void e.option(`${i} <n>`,n,e=>Number(e));default:e.option(`${i} <value>`,n)}}function ls(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function cs(e){if(e.enum&&e.enum.length>0)return e.enum[0];switch(e.kind){case"boolean":return!1;case"integer":case"number":return 0;case"array":return[];default:return"<value>"}}function ds(e){const t={};for(const i of e)i.required&&(t[i.jsonName]=cs(i));return t}function us(e,t,i){if(!e.billing)return null;const n=e.billing.select(t),o=e.billing.schema.safeParse(n);if(!o.success){const e=Xa(o.error,{verb:i.fullVerb,flags:i.flags,mode:i.mode,input:i.input}),t=e[0];Da("E_SCHEMA",`billing schema validation failed: ${t.message}`,t.hint,{verb:t.verb,instance_path:t.instance_path,expected:t.expected,got:t.got,...t.flag?{flag:t.flag}:{},...void 0!==i.jobIndex?{job_index:i.jobIndex}:{},...i.jobKey?{job_key:i.jobKey}:{},...e.length>1?{details:e.slice(1)}:{}})}return e.billing.quote(o.data,{command:i.command,action:i.action})}const ps="for media (video/image/audio) use the upload_file tool and store the returned URL inside a JSON artifact; if this really is text, pass --content-type application/json or text/plain";function ms(e,t){const i=e.resolve?.(t)??e,n={};for(const e of i.scalars)e.required&&(n[e.name]=fs(e));const o={};for(const e of i.files)o[e.name]=JSON.parse(hs(e));process.stdout.write(`${JSON.stringify({ok:!0,command:i.command,summary:i.summary,scalars:i.scalars,files:i.files,example:{scalars:n,files:o}},null,2)}\n`),process.exit(0)}function hs(e){if("text"===e.kind)return JSON.stringify(e.example);try{return JSON.parse(e.example),e.example}catch{return"array"===e.kind?"[]":"{}"}}function fs(e){if(e.enum&&e.enum.length>0)return e.enum[0];switch(e.type){case"boolean":return!1;case"integer":case"number":return 0;default:return"<value>"}}const gs=/^https?:\/\//i,vs=/https?:\/\/[^\s"'<>]+/gi;function ys(e,t="$"){const i=[];return bs(e,t,i),i}function bs(e,t,i){if(null!=e)if("string"!=typeof e){if(Array.isArray(e))for(let n=0;n<e.length;n++)bs(e[n],`${t}[${n}]`,i);else if("object"==typeof e)for(const[n,o]of Object.entries(e))bs(o,`${t}.${n}`,i)}else gs.test(e)&&i.push({path:t,url:e})}function _s(e){let t=e;for(;t.length>0;){const e=t[t.length-1];if(!e)break;if(".,;:!?".includes(e))t=t.slice(0,-1);else if(")"===e&&ws(t,"(")<ws(t,")"))t=t.slice(0,-1);else if("]"===e&&ws(t,"[")<ws(t,"]"))t=t.slice(0,-1);else{if(!("}"===e&&ws(t,"{")<ws(t,"}")))break;t=t.slice(0,-1)}}return t}function ws(e,t){let i=0;for(const n of e)n===t&&i++;return i}async function ks(e,t,i,n,o){const r=n+1;let a;for(let n=1;n<=r;n++)try{const s=await t(e,{method:"HEAD",signal:AbortSignal.timeout(i)});if(s.status>=200&&s.status<400)return{status:s.status};if(s.status>=400&&s.status<500)return{status:s.status};if(a=`http ${s.status}`,n<r){await xs(o);continue}return{status:s.status,reason:a}}catch(e){if(a=e instanceof Error?e.message:String(e),n<r){await xs(o);continue}return{status:0,reason:a}}return{status:0,reason:a}}function xs(e){return new Promise(t=>setTimeout(t,e))}async function Ss(e,t){try{return await ua("artifact",e,t,{timeoutMs:3e4,retries:0})}catch(e){if(e instanceof oa&&Fa(e.message,e.hint),e instanceof Zr){const t=function(e){if(e)try{const t=JSON.parse(e);if(t&&!1===t.ok&&"string"==typeof t.error)return t}catch{}}(e.bodyText);if(t)return t}throw e}}function Es(e){if(e.ok)return e;"E_SCHEMA"===e.code&&Da("E_SCHEMA",e.error,e.hint,void 0!==e.details?{details:e.details}:void 0),Fa(e.error,e.hint,void 0!==e.details?{details:e.details}:void 0)}function Os(e){const{ok:t,...i}=e;return i}function Ts(e,t,i){const n={};for(const i of t)i in e&&(n[i]=e[i]);return i&&"content"in e&&(n.content=e.content),n}async function As(e,t){if(t||0===e.length)return;const i=await async function(e,t={}){const i=t.concurrency??20,n=t.timeoutMs??3e3,o=t.retries??1,r=t.retryDelayMs??500,a=t.fetchImpl??globalThis.fetch,s=new Map;for(const{url:t,path:i}of e){const e=s.get(t);e?e.push(i):s.set(t,[i])}const l=Array.from(s.keys()),c=new Map;let d=0;const u=Math.min(i,l.length);await Promise.all(Array.from({length:u},()=>(async()=>{for(;;){const e=d++;if(e>=l.length)return;const t=l[e];c.set(t,await ks(t,a,n,o,r))}})()));const p=[];for(const e of l){const{status:t,reason:i}=c.get(e)??{status:0};if(!(t>=200&&t<400))for(const n of s.get(e)??[])p.push({path:n,url:e,status:t,...i?{reason:i}:{}})}return p}(e);0!==i.length&&Da("E_URL_UNREACHABLE",function(e){if(0===e.length)return"";const t=e[0],i=1===e.length?"URL is":"URLs are",n=e.length>1?` (${e.length-1} more in details.failures)`:"";return`${e.length} ${i} unreachable${n}: path=${t.path} status=${t.status} url=${t.url}`}(i),"One or more artifact URLs are not reachable by HEAD. Fix each URL at details.failures[].path and retry. Use --skip-url-check only for offline fixtures or intentional non-public URLs.",{failures:i,count:i.length})}function $s(e,i){let n;r(e)||Da("E_SCHEMA",`--contract must be an absolute path, got ${e}`,"skill resource references resolve to absolute paths at tool-call time; pass that absolute path here.",{flag:"--contract",given:e});try{n=JSON.parse(t(e,"utf8"))}catch(t){Da("E_FILE_PARSE",`failed to read --contract ${e}: ${t instanceof Error?t.message:String(t)}`,void 0,{flag:"--contract",given:e})}const s=(n.slots??{})[i],l={},c=o(a(e),".."),d=new Set;s?.schema_ref&&d.add(s.schema_ref);for(const e of d){const i=r(e)?e:o(c,e);try{l[e]=JSON.parse(t(i,"utf8"))}catch(t){Da("E_FILE_PARSE",`failed to read schema_ref ${e} (resolved ${i}): ${t instanceof Error?t.message:String(t)}`,void 0,{schema_ref:e})}}return{contract:n,schemas:l}}const Ns=Ho.pick({service:!0});function js(e,t){return{source:"dl",event:"clone_voice",credits:50,command:t.command,action:t.action??"clone_voice",details:{service:e.service,rule:"clone-voice.fixed"}}}const Cs=Jo.pick({service:!0});function Rs(e,t){return{source:"dl",event:"design_voice",credits:50,command:t.command,action:t.action??"design_voice",details:{service:e.service,rule:"design-voice.fixed"}}}const Is=mo({});function Ls(e,t){return{source:"dl",event:"shot_detect",credits:50,command:t.command,action:t.action??"detect_shots",details:{rule:"detect-shots.fixed"}}}const zs=mo({});function qs(e,t){return{source:"dl",event:"download_media",credits:5,command:t.command,action:t.action??"download_media",details:{rule:"download-media.fixed"}}}mo({mode:bo(["text","markdown","raw"])});const Ps=Ko.pick({service:!0});function Ms(e,t){return{source:"dl",event:"finalize_voice",credits:50,command:t.command,action:t.action??"finalize_voice",details:{service:e.service,rule:"finalize-voice.fixed"}}}const Us=zo.pick({service:!0}),Fs={"banana-pro":150,"banana-2":100,seedream:50,"seedream-5-lte":50,"gpt-image-2":75};function Ds(e,t){const i=e.service||"seedream";return{source:"dl",event:"image_generate",credits:Fs[i],command:t.command,action:t.action??"generate_image",details:{service:e.service,billable_service:i,rule:"generate-image.service.fixed"}}}const Hs=Uo.pick({service:!0}),Bs={"suno-v5":100,"suno-v5_5":100,minimax:200};function Vs(e,t){return{source:"dl",event:"music_generate",credits:Bs[e.service],command:t.command,action:t.action??"generate_music",details:{service:e.service,billable_service:e.service,rule:"generate-music.service.fixed"}}}const Js=Do.pick({text:!0,service:!0});function Ks(e,t){const i=e.text.length>0?e.text.length:100;return{source:"dl",event:"tts_generate",credits:Math.max(1,Math.ceil(i/40)),command:t.command,action:t.action??"generate_tts",details:{service:e.service,text_length:e.text.length,billable_characters:i,chars_per_credit:40,rule:"generate-tts.text-length"}}}const Ys="dlim2v",Gs=qo.pick({service:!0,duration:!0,resolution:!0}),Ws={"seedance-2-0":{"480p":70,"720p":150,"1080p":360},"seedance-2-0-fast":{"480p":55,"720p":120,"1080p":null},"kling-o3-ref2v":{"480p":null,"720p":120,"1080p":null},"kling-o3-pro-ref2v":{"480p":null,"720p":null,"1080p":240},"kling-o3-v2v":{"480p":null,"720p":null,"1080p":null},"kling-o3-pro-v2v":{"480p":null,"720p":null,"1080p":null},"seedance-1-5":{"720p":60,"1080p":120},dli2v3:{_default:30,"720p":30,"1080p":60},dlai2v_pro:{"720p":70,"1080p":200},dlai2v_pro_multiframe:{"720p":70,"1080p":200},"kling3.0":{"720p":100,"1080p":200},dlai2v:{_default:null},dlim2v:{_default:50},"happyhorse-1-0-i2v":{_default:150},"happyhorse-1-0-r2v":{_default:150},"happyhorse-1-0-video-edit":{_default:150},"gemini-omni-video":{"480p":null,"720p":50,"1080p":150,"4k":300},"grok-imagine-video-1-5-preview":{"480p":50,"720p":80},"longcat-avatar-1-5":{_default:100}};function Zs(e,t){const{billableService:i,pricedResolution:n,rate:o}=function(e,t){const i=Ws[e]??Ws[Ys],n=Ws[e]?e:Ys,o=function(e){const t=e?.trim().toLowerCase();return"480p"===t||"720p"===t||"1080p"===t||"4k"===t?t:null}(t);if(o){const e=i?.[o];if(void 0!==e)return{billableService:n,pricedResolution:o,rate:Xs(e,n,o)}}return void 0!==i?._default?{billableService:n,pricedResolution:"_default",rate:Xs(i._default,n,"_default")}:void 0!==i?.["720p"]?{billableService:n,pricedResolution:"720p",rate:Xs(i["720p"],n,"720p")}:{billableService:Ys,pricedResolution:"_default",rate:50}}(e.service,e.resolution),r=function(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?e:8}(e.duration);return{source:"dl",event:"video_generate",credits:Math.ceil(o*r),command:t.command,action:t.action??"generate_video",details:{service:e.service,billable_service:i,resolution:e.resolution,priced_resolution:n,duration_seconds:e.duration,billable_duration_seconds:r,rate_credits_per_second:o,rule:"generate-video.service-resolution.duration"}}}function Xs(e,t,i){if(null!==e)return e;throw new Yr("E_SCHEMA",`generate-video pricing is not defined for service '${t}' at '${i}'`,"Pick a priced service/resolution from docs/billing/billing-pricing.md before submitting the job.",{service:t,resolution:i,pricing_status:"unpriced"})}const Qs=mo({mode:bo(["forward","reverse"])});function el(e,t){return{source:"dl",event:"geocode",credits:5,command:t.command,action:t.action??"geocode",details:{rule:"geocode.fixed",mode:e.mode}}}mo({});const tl=Po.pick({service:!0,duration:!0,resolution:!0}),il={dlai2v_pro:{"720p":70,"1080p":200},dlai2v_pro_multiframe:{"720p":70,"1080p":200},dlai2v:{_default:null},"seedance-2-0":{"480p":70,"720p":150},"seedance-2-0-fast":{"480p":55,"720p":120},"longcat-avatar":{_default:100}};function nl(e,t){const{pricedResolution:i,rate:n}=function(e,t){const i=il[e],n=function(e){const t=e?.trim().toLowerCase();return"480p"===t||"720p"===t||"1080p"===t?t:null}(t);if(n){const t=i?.[n];if(void 0!==t)return{pricedResolution:n,rate:ol(t,e,n)}}return void 0!==i?._default?{pricedResolution:"_default",rate:ol(i._default,e,"_default")}:void 0!==i?.["720p"]?{pricedResolution:"720p",rate:ol(i["720p"],e,"720p")}:{pricedResolution:"_default",rate:190}}(e.service,e.resolution),o=function(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?e:8}(e.duration);return{source:"dl",event:"lipsync_generate",credits:Math.ceil(n*o),command:t.command,action:t.action??"lipsync",details:{service:e.service,resolution:e.resolution,priced_resolution:i,duration_seconds:e.duration,billable_duration_seconds:o,rate_credits_per_second:n,rule:"lipsync.service-resolution.duration"}}}function ol(e,t,i){if(null!==e)return e;throw new Yr("E_SCHEMA",`lipsync pricing is not defined for service '${t}' at '${i}'`,"Pick a priced service/resolution from docs/billing/billing-pricing.md before submitting the job.",{service:t,resolution:i,pricing_status:"unpriced"})}const rl=mo({service:bo(["dreamactor","kling3.0-motion"]),tier:bo(["pro","std"]).optional(),duration:eo().int().min(1).optional()});function al(e,t){const{pricedTier:i,rate:n}=(r=e.service,a=e.tier,"dreamactor"===r?{pricedTier:"_default",rate:60}:"kling3.0-motion"===r?"std"===a?{pricedTier:"std",rate:100}:{pricedTier:"pro",rate:200}:{pricedTier:"_default",rate:100}),o=function(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?e:10}(e.duration);var r,a;return{source:"dl",event:"motion_control_generate",credits:Math.ceil(n*o),command:t.command,action:t.action??"motion_control",details:{service:e.service,tier:e.tier,priced_tier:i,duration_seconds:e.duration,billable_duration_seconds:o,rate_credits_per_second:n,rule:"motion-control.service-tier.duration"}}}const sl=mo({});function ll(e,t){return{source:"dl",event:"places",credits:20,command:t.command,action:t.action??"place_photo",details:{rule:"places.fixed",subcommand:"photo"}}}const cl=mo({});function dl(e,t){return{source:"dl",event:"places",credits:20,command:t.command,action:t.action??"places_search",details:{rule:"places.fixed",subcommand:"search"}}}const ul=Yo.pick({service:!0});function pl(e,t){return{source:"dl",event:"remix_voice",credits:50,command:t.command,action:t.action??"remix_voice",details:{service:e.service,rule:"remix-voice.fixed"}}}mo({});const ml=mo({});function hl(e,t){return{source:"dl",event:"render_caption",credits:50,command:t.command,action:t.action??"render_caption",details:{rule:"render-caption.fixed"}}}mo({provider:bo(["baidu","baidu-image","serper","tavily","brave"])});const fl=mo({});function gl(e,t){return{source:"dl",event:"static_map",credits:5,command:t.command,action:t.action??"static_map",details:{rule:"static-map.fixed"}}}mo({provider:Cn().min(1),native_id:Cn().min(1)}),mo({type:bo(["image","video"]),mode:bo(["fallback","fanout"]),limit:eo().int().min(1).max(30),providers:uo(Cn().min(1)).min(1)});const vl=mo({});function yl(e,t){return{source:"dl",event:"streetview",credits:10,command:t.command,action:t.action??"streetview_image",details:{rule:"streetview.fixed",subcommand:"image"}}}const bl=mo({});function _l(e,t){return{source:"dl",event:"streetview",credits:10,command:t.command,action:t.action??"streetview_metadata",details:{rule:"streetview.fixed",subcommand:"metadata"}}}const wl=mo({});function kl(e,t){return{source:"dl",event:"audio_transcribe",credits:50,command:t.command,action:t.action??"transcribe",details:{rule:"transcribe.fixed"}}}const xl=["text","markdown","raw"];function Sl(e,t,i){const n=Number(e);if(!Number.isFinite(n)||!Number.isInteger(n)||n<1||n>i)throw new Error(`${t} must be a positive integer ≤ ${i}, got ${e}`);return n}const El="按特征选路由: ffprobe / -c copy / 简单 trim 用本地 ffmpeg; -c:v 重编码 / filter_complex / 输入 >2min 走 dl ffmpeg; >5min 编码加 --async 走 callback。";function Ol(e){return e?`${e}; ${El}`:El}const Tl=["minimax","elevenlabs","elevenlabs-dialogue","voxcpm"],Al={minimax:"generate_tts",elevenlabs:"generate_tts_elevenlabs","elevenlabs-dialogue":"generate_tts_dialogue",voxcpm:"generate_tts"},$l="--refs-from";function Nl(e){return null==e?[]:Array.isArray(e)?e.filter(e=>"string"==typeof e):"string"==typeof e?[e]:[]}function jl(e){const t=new Set,i=[];for(const n of e)t.has(n)||(t.add(n),i.push(n));return i}function Cl(e,t){Fa(`dl ${e} is not implemented on pi yet`,t)}const Rl=["sfx","stinger","bgm","amb","audio_any","visual_style","voice","writing_plot","writing_character","writing_payoff","writing_conflict","writing_hook","writing_any","meme"],Il=["elevenlabs","minimax"];function Ll(){const e=JSON.stringify({event:"hint",code:"ASYNC_DETACH",message:"dl poll is single-shot — never call it in a bash loop. Bash has a ~5min hard cap and the sandbox is reclaimed on inactivity, so wait loops die as 'sandbox not running' or 'terminated' before the callback arrives. End your turn; the callback re-spawns a fresh sandbox with [async-callback] when ready."});process.stderr.write(`${e}\n`)}const zl=65536,ql="DL_BEGIN",Pl="DL_END";const Ml=["baidu","baidu-image","serper","tavily","brave"],Ul=new Set(["pd","pw","pm","py"]),Fl=["web","image","video"],Dl=4194304;function Hl(e,t){return Math.min(t??10,{web:50,image:30,video:10}[e])}async function Bl(e){const t=e.extra?.image;if(void 0!==t){if("string"!=typeof t||""===t.trim())throw new Yr("E_SCHEMA","--params-file image must be a non-empty base64 string",void 0,{flag:"--params-file",expected:"object with image:string"});return t}if(!e.imageFile)throw new Yr("E_SCHEMA","--image-file is required for provider=baidu-image",'pass a jpg/png file path, or pass {"image":"<base64>"} through --params-file',{flag:"--image-file",provider:"baidu-image"});const i=o(e.imageFile);let n;try{n=await g(i)}catch(t){const n=t instanceof Error?t.message:String(t);throw new Yr("E_FILE_MISSING",`--image-file: cannot read file at ${i} (${n})`,"make sure the path exists in the sandbox",{flag:"--image-file",given:e.imageFile,resolved:i,cwd:process.cwd()})}if(0===n.byteLength)throw new Yr("E_SCHEMA",`--image-file (${i}): expected non-empty jpg/png image`,void 0,{flag:"--image-file",resolved:i});if(n.byteLength>Dl)throw new Yr("E_SCHEMA",`--image-file (${i}): image must be <= 4MB before base64 encoding`,void 0,{flag:"--image-file",resolved:i,max_bytes:Dl,bytes:n.byteLength});return n.toString("base64")}async function Vl(e,t,i){if("baidu"===e)return async function(e,t){const i=t.resourceType??"web",n={messages:[{role:"user",content:e}],search_source:"baidu_search_v2",resource_type_filter:[{type:i,top_k:Hl(i,t.k)}]};if(t.freshness){const e={pw:"week",pm:"month",py:"year"}[t.freshness];if(!e)throw new Error("--freshness=pd is not supported by baidu; use pw|pm|py or provider=brave");n.search_recency_filter=e}return t.extra&&Object.assign(n,t.extra),((await ua("search/baidu","v2/ai_search/web_search",n,{timeoutMs:2e4,retries:1,...t.billing?{billing:{jobRef:t.billing.jobRef,quote:t.billing.quote}}:{}})).references??[]).slice(0,t.k??10).map(e=>{const t=e.image?.width??e.video?.width,i=e.image?.height??e.video?.height;return{title:e.title??e.web_anchor??"",url:e.url??e.video?.url??e.image?.url??"",snippet:e.snippet??e.content??"",...e.date?{publishedAt:e.date}:{},...e.website?{source:e.website}:{},...e.type?{type:e.type}:{},...e.image?.url?{imageUrl:e.image.url}:{},...e.video?.url?{videoUrl:e.video.url}:{},...e.video?.hover_pic?{thumbnailUrl:e.video.hover_pic}:{},...void 0!==t?{width:t}:{},...void 0!==i?{height:i}:{},...void 0!==e.video?.duration?{duration:e.video.duration}:{},...void 0!==e.video?.size?{size:e.video.size}:{}}})}(t,i);if("baidu-image"===e)return async function(e){const t={image:await Bl(e),count:Math.min(e.k??10,50)};if(e.extra)for(const[i,n]of Object.entries(e.extra))"image"!==i&&(t[i]=n);const i=await ua("search/baidu-image","v2/tools/image_similar_info",t,{timeoutMs:2e4,retries:1,...e.billing?{billing:{jobRef:e.billing.jobRef,quote:e.billing.quote}}:{}}),n=i.result?.res_data?.result_page;return(i.result?.res_data?.res_items??[]).slice(0,e.k??10).map(e=>({title:e.title??"",url:e.fromurl??e.detail_page??e.objurl??"",snippet:e.site_name??"",..."string"==typeof e.update_time||"number"==typeof e.update_time?{publishedAt:String(e.update_time)}:{},...e.site_name?{source:e.site_name}:{},...e.objurl?{imageUrl:e.objurl}:{},...e.result_page??n?{resultPage:e.result_page??n}:{},..."number"==typeof e.sim_level?{similarityLevel:e.sim_level}:{},...e.item_cate?{category:e.item_cate}:{},...void 0!==e.width?{width:e.width}:{},...void 0!==e.height?{height:e.height}:{}}))}(i);if("serper"===e)return async function(e,t){const i={q:e,num:t.k??10};if(t.country&&(i.gl=t.country),t.freshness){const e={pd:"qdr:d",pw:"qdr:w",pm:"qdr:m",py:"qdr:y"};i.tbs=e[t.freshness]??i.tbs}return t.extra&&Object.assign(i,t.extra),((await ua("search/serper","search",i,{timeoutMs:2e4,retries:1,...t.billing?{billing:{jobRef:t.billing.jobRef,quote:t.billing.quote}}:{}})).organic??[]).slice(0,t.k??10).map(e=>({title:e.title??"",url:e.link??"",snippet:e.snippet??"",...e.date?{publishedAt:e.date}:{},...e.source?{source:e.source}:{}}))}(t,i);if("tavily"===e)return async function(e,t){const i={query:e,max_results:t.k??10,search_depth:"basic"};if(t.freshness){const e={pd:"day",pw:"week",pm:"month",py:"year"};i.time_range=e[t.freshness]??i.time_range}return t.extra&&Object.assign(i,t.extra),((await ua("search/tavily","search",i,{timeoutMs:2e4,retries:1,...t.billing?{billing:{jobRef:t.billing.jobRef,quote:t.billing.quote}}:{}})).results??[]).slice(0,t.k??10).map(e=>({title:e.title??"",url:e.url??"",snippet:e.content??"",...e.published_date?{publishedAt:e.published_date}:{}}))}(t,i);if("brave"===e)return async function(e,t){const i={q:e,count:String(t.k??10)};if(t.country&&(i.country=t.country),t.freshness&&(i.freshness=t.freshness),t.extra)for(const[e,n]of Object.entries(t.extra))"string"!=typeof n&&"number"!=typeof n&&"boolean"!=typeof n||(i[e]=String(n));const n=await pa("search/brave","res/v1/web/search",i,{timeoutMs:2e4,retries:1,headers:{Accept:"application/json"},...t.billing?{billing:{jobRef:t.billing.jobRef,quote:t.billing.quote}}:{}});return(n.web?.results??[]).slice(0,t.k??10).map(e=>({title:e.title??"",url:e.url??"",snippet:e.description??"",...e.age?{publishedAt:e.age}:{}}))}(t,i);throw new Error(`unsupported provider: ${e}`)}const Jl="45adb2f",Kl="@pawlogic/dl",Yl="/home/user/.local";async function Gl(){const e=(process.env.CALLBACK_SERVER_URL??"").trim().replace(/\/+$/,"");if(!e)return null;const t=await async function(e){const t=new AbortController,i=setTimeout(()=>t.abort(),5e3);try{const i=await fetch(e,{signal:t.signal});return i.ok?(await i.text()).trim():null}catch{return null}finally{clearTimeout(i)}}(`${e}/health`);if(!t)return null;try{const e=JSON.parse(t),i=e.build_short_sha?.trim();return i&&/^[a-f0-9]{7}$/i.test(i)?i.slice(0,7):null}catch{return null}}function Wl(){for(const e of[`${Yl}/lib/node_modules/${Kl}/package.json`,`${Yl}/lib/node_modules/${Kl.replace("@pawlogic/","")}/package.json`])try{if(!i(e))continue;const n=JSON.parse(t(e,"utf8"));if("string"==typeof n.version&&n.version.trim())return n.version}catch{}try{const e=a(l(import.meta.url));for(const n of["../package.json","../../package.json","../../../package.json"]){const r=o(e,n);if(!i(r))continue;const a=JSON.parse(t(r,"utf8"));if(a.name===Kl&&"string"==typeof a.version)return a.version}}catch{}return null}async function Zl(){const e=(process.env.DL_NPM_DIST_TAG??"").trim()||null;return{dl_build_short_sha:Jl,dl_build_full_sha:"45adb2f81edbbabbf8b75a976d19babb25a5b9e7",npm_dist_tag:e,npm_installed_version:Wl(),callback_server_url:(process.env.CALLBACK_SERVER_URL??"").trim()||null,callback_build_short_sha:await Gl(),updated:!1,skipped_reason:null}}function Xl(e,t){const i=t.replace(/^\/+/,"");var n;n={use_tool:"read",skill:e,relative_path:i,hint:`Call the \`read\` tool with path \`dirname(<location of skill "${e}" in <available_skills>>) + "/${i}"\`.`},process.stdout.write(`${JSON.stringify({ok:!0,...n})}\n`),process.exit(0)}const Ql="/workspace/.stock-media",ec=209715200,tc=/^([a-z0-9_-]+):([a-zA-Z0-9_.-]+)$/,ic=new Map([["image/jpeg","jpg"],["image/jpg","jpg"],["image/png","png"],["image/webp","webp"],["image/gif","gif"],["image/avif","avif"],["video/mp4","mp4"],["video/quicktime","mov"],["video/webm","webm"],["video/x-matroska","mkv"]]);class nc extends Error{hint;constructor(e,t){super(e),this.hint=t,this.name="StockDownloadError"}}function oc(e,t){const i=e&&e.length>0?e:t;return r(i)||Fa(`--to must be an absolute path; got "${i}"`,"use /workspace/... 目录"),i.startsWith("/workspace/")||"/workspace"===i||Fa(`--to must be under /workspace/; got "${i}"`,"stock-media downloads only target sandbox /workspace."),i}const rc={name:"openverse",supports:{image:!0,video:!1},async search(e){if("image"!==e.type)return[];const t={q:e.query,page_size:String(e.perProviderLimit)};"landscape"===e.orientation?t.aspect_ratio="wide":"portrait"===e.orientation?t.aspect_ratio="tall":"square"===e.orientation&&(t.aspect_ratio="square"),void 0!==e.minWidth&&(t.size="large");let i=((await pa("stock-media/openverse","v1/images",t)).results??[]).map(e=>{const t=function(e,t,i){const n=e.toUpperCase(),o=t??"4.0";return{license:"CC0"===n?"CC0 1.0 (Public Domain)":`CC ${n} ${o}`,license_url:i??("CC0"===n?"https://creativecommons.org/publicdomain/zero/1.0/":`https://creativecommons.org/licenses/${e.toLowerCase()}/${o}/`),attribution_required:"CC0"!==n}}(e.license,e.license_version,e.license_url),i=e.creator??"Unknown";return{asset_id:`openverse:${e.id}`,provider:"openverse",type:"image",preview_url:e.thumbnail,download_url:e.url,dimensions:{width:e.width,height:e.height},duration:null,tags:(e.tags??[]).map(e=>e.name).filter(Boolean),author:i,author_url:e.creator_url??"",license:t.license,license_url:t.license_url,attribution_required:t.attribution_required,attribution_text:(n={title:e.title,creator:e.creator,license:t.license},`${n.title?`"${n.title}"`:"Image"}${n.creator?` by ${n.creator}`:""} (${n.license}) via Openverse`),source_url:e.foreign_landing_url??e.url};var n});return void 0!==e.minWidth&&(i=i.filter(t=>t.dimensions.width>=e.minWidth)),i}},ac="Pexels License",sc="https://www.pexels.com/license/";function lc(e,t){const i=e.filter(e=>"video/mp4"===e.file_type),n=i.length>0?i:e,o=t?n.filter(e=>e.width>=t):n;return(o.length>0?o:n).slice().sort((e,t)=>t.width-e.width)[0]??null}const cc={name:"pexels",supports:{image:!0,video:!0},async search(e){const t={query:e.query,per_page:String(e.perProviderLimit)};if(e.orientation&&(t.orientation=e.orientation),"image"===e.type){let i=((await pa("stock-media/pexels","v1/search",t)).photos??[]).map(e=>{const t=e.alt?e.alt.split(/[,\s]+/).filter(e=>e.length>1):[];return{asset_id:`pexels:${e.id}`,provider:"pexels",type:"image",preview_url:e.src.medium??e.src.small??e.src.tiny??e.src.original,download_url:e.src.original,dimensions:{width:e.width,height:e.height},duration:null,tags:t,author:e.photographer,author_url:e.photographer_url,license:ac,license_url:sc,attribution_required:!1,attribution_text:`Photo by ${e.photographer} on Pexels`,source_url:e.url}});return e.minWidth&&(i=i.filter(t=>t.dimensions.width>=e.minWidth)),i}let i=function(e,t){const i=e.videos??[],n=[];for(const e of i){const i=lc(e.video_files,t);i&&n.push({asset_id:`pexels:${e.id}`,provider:"pexels",type:"video",preview_url:e.image,download_url:i.link,dimensions:{width:i.width,height:i.height},duration:e.duration,tags:e.tags??[],author:e.user.name,author_url:e.user.url,license:ac,license_url:sc,attribution_required:!1,attribution_text:`Video by ${e.user.name} on Pexels`,source_url:e.url})}return n}(await pa("stock-media/pexels","videos/search",t),e.minWidth);return void 0!==e.durationMin&&(i=i.filter(t=>(t.duration??0)>=e.durationMin)),void 0!==e.durationMax&&(i=i.filter(t=>(t.duration??0)<=e.durationMax)),i}},dc="Pixabay Content License",uc="https://pixabay.com/service/license-summary/";function pc(e){return e.split(",").map(e=>e.trim()).filter(e=>e.length>0)}function mc(e,t){const i=[e.large,e.medium,e.small,e.tiny].filter(e=>!!e&&!!e.url);if(0===i.length)return null;const n=t?i.filter(e=>e.width>=t):i;return(n.length>0?n:i).slice().sort((e,t)=>t.width-e.width)[0]??null}const hc={name:"pixabay",supports:{image:!0,video:!0},async search(e){const t={q:e.query,per_page:String(e.perProviderLimit)};if("landscape"===e.orientation?t.orientation="horizontal":"portrait"===e.orientation&&(t.orientation="vertical"),"image"===e.type)return t.image_type="photo",void 0!==e.minWidth&&(t.min_width=String(e.minWidth)),((await pa("stock-media/pixabay","api",t)).hits??[]).map(e=>({asset_id:`pixabay:${e.id}`,provider:"pixabay",type:"image",preview_url:e.webformatURL??e.previewURL,download_url:e.largeImageURL??e.webformatURL,dimensions:{width:e.imageWidth,height:e.imageHeight},duration:null,tags:pc(e.tags),author:e.user,author_url:`https://pixabay.com/users/${encodeURIComponent(e.user)}/`,license:dc,license_url:uc,attribution_required:!1,attribution_text:`Image by ${e.user} on Pixabay`,source_url:e.pageURL}));let i=function(e,t){const i=e.hits??[],n=[];for(const e of i){const i=mc(e.videos,t);i&&n.push({asset_id:`pixabay:${e.id}`,provider:"pixabay",type:"video",preview_url:e.picture_id?`https://i.vimeocdn.com/video/${e.picture_id}_640x360.jpg`:e.userImageURL,download_url:i.url,dimensions:{width:i.width,height:i.height},duration:e.duration,tags:pc(e.tags),author:e.user,author_url:`https://pixabay.com/users/${encodeURIComponent(e.user)}/`,license:dc,license_url:uc,attribution_required:!1,attribution_text:`Video by ${e.user} on Pixabay`,source_url:e.pageURL})}return n}(await pa("stock-media/pixabay","api/videos",t),e.minWidth);return void 0!==e.durationMin&&(i=i.filter(t=>(t.duration??0)>=e.durationMin)),void 0!==e.durationMax&&(i=i.filter(t=>(t.duration??0)<=e.durationMax)),i}},fc={pexels:cc,pixabay:hc,openverse:rc},gc=["pexels","pixabay","openverse"],vc=new Set(["landscape","portrait","square"]),yc=new Set(["image","video"]),bc=["fallback","fanout"];function _c(e,t,i){const n=Number(e);return(!Number.isFinite(n)||!Number.isInteger(n)||n<1||n>i)&&Fa(`${t} must be a positive integer ≤ ${i}; got ${e}`),n}function wc(e,t){const i=Number(e);return(!Number.isFinite(i)||i<0)&&Fa(`${t} must be a non-negative number; got ${e}`),i}function kc(e,t){return t instanceof Zr?{provider:e,status:t.status,reason:`${t.status}: ${t.message}`}:t instanceof oa?{provider:e,reason:`proxy-client: ${t.message}${t.hint?` (${t.hint})`:""}`}:t instanceof Error?{provider:e,reason:t.message}:{provider:e,reason:String(t)}}function xc(e,t){const i=[],n=new Set,o=e.map(()=>0);let r=e.filter(e=>e.length>0).length;for(;i.length<t&&r>0;){r=0;for(let a=0;a<e.length;a++){const s=e[a];if(o[a]<s.length){const e=s[o[a]];if(o[a]+=1,!n.has(e.asset_id)&&(n.add(e.asset_id),i.push(e),i.length>=t))break;o[a]<s.length&&(r+=1)}}}return i}const Sc=(e,t)=>fc[e].search(t);async function Ec(e){try{await da({jobRef:e.jobRef,quote:e.quote,reason:e.reason,chargeId:e.receipt.charge_id})}catch(t){process.stderr.write(`${JSON.stringify({level:"warn",event:"dl_billing_refund_failed",job_ref:e.jobRef,reason:e.reason,error:t instanceof Error?t.message:String(t)})}\n`)}}function Oc(e,t){const i={};for(const t of["job_ref","task_id","data"])void 0!==e[t]&&(i[t]=e[t]);return void 0!==e.error&&null!==e.error&&(i.error=e.error),i}const Tc=new Y;Tc.name("dl").description(["DramaLand CLI","","Generation:"," lipsync transcribe generate-image generate-video generate-music generate-sound generate-lyrics"," generate-tts analyze-beats render-caption motion-control detect-shots download-media","","Geo:"," geocode streetview <command> places <command> static-map","","Pipelines:"," ffmpeg remotion poll search stock <command> fetch","","Local:"," self-update script <command> skill <command>","","Resources:"," artifact <command> asset <command> knowledge <command>","","Batch: pass --jobs '<inline-json>' per verb (recommended; --jobs-file is legacy).","Run `dl <command> --help` for the full per-command shape.","","Output: JSON on stdout when ok, JSON {ok:false,code,error,hint?} on stderr on failure.","Codes: E_FILE_MISSING / E_FILE_PARSE / E_SCHEMA / E_UNKNOWN_OPTION (exit 2)"," E_INSUFFICIENT_CREDITS / E_BACKEND (exit 1)"].join("\n")).version(function(){try{const e=a(l(import.meta.url));for(const i of["./package.json","../package.json","../../package.json"])try{const n=JSON.parse(t(o(e,i),"utf8"));if("string"==typeof n.version&&n.version.trim())return`${n.version} (build ${Jl})`}catch{}}catch{}return`unknown (build ${Jl})`}()),function(e){e.command("self-update").description("Reinstall @pawlogic/dl from npmjs.com. Shows dl build SHA vs live callback-server build SHA.").addHelpText("after",["","Sandbox 内部 dl 由 npm install -g --prefix=/home/user/.local @pawlogic/dl@<tag> 装出。","沙箱 wrapper `/usr/local/bin/dl` 每次调用前跑 dl-npm-update.sh(TTL 300s)。本命令绕开 TTL。","","DL_NPM_DIST_TAG env 由 template bake 时按 alias 注入:"," prod (pi-sandbox-dl) → latest"," staging (pi-sandbox-dl-staging) → staging"," PR preview (pi-sandbox-dl-pr-N) → 空 → 本命令 no-op,沙箱 dl 锁版","","CALLBACK_SERVER_URL 用于通过 GET /health 对账 dl ↔ callback-server 是否同 SHA。","","Flags:"," --check 不装,只打印当前状态 JSON"," --force 绕过 TTL 强制重装(默认行为也是绕过)"].join("\n")).option("--check","只打状态 JSON,不联 registry").option("--force","绕过 300s TTL 缓存(CLI 默认就绕)").action(async e=>{const t=e.check?await Zl():await async function(e={}){const t=await Zl();if(!t.npm_dist_tag)return t.skipped_reason="DL_NPM_DIST_TAG unset (PR preview / local — no npm self-update)",t;e.force;try{const e=p("npm",["install","-g",`--prefix=${Yl}`,"--silent","--no-audit","--no-fund","--no-update-notifier",`${Kl}@${t.npm_dist_tag}`],{env:{...process.env,HOME:"/home/user"},stdio:"pipe",timeout:3e4});if(0!==e.status)return t.skipped_reason=`npm install exit=${e.status??"signal"}: ${(e.stderr??Buffer.from("")).toString("utf8").slice(0,200)}`,t}catch(e){return t.skipped_reason=`npm install threw: ${String(e).slice(0,200)}`,t}try{m("sh",["-c","printf '%s' \"$(date +%s)\" > /tmp/dl-npm-checkedat"],{stdio:"ignore"})}catch{}try{m("ln",["-sf","/usr/local/bin/dl",`${Yl}/bin/dl`],{stdio:"ignore"})}catch{}return t.npm_installed_version=Wl(),t.updated=!0,t.skipped_reason=null,t}({force:e.force}),i="unknown"!==t.dl_build_short_sha&&null!==t.callback_build_short_sha&&t.dl_build_short_sha===t.callback_build_short_sha;Ua({ok:!0,...t,build_short_sha_aligned_with_callback:i,hint:i?null:"dl build SHA 跟 live callback-server 的 build SHA 对不齐 —— 可能需要 staging-deploy(staging) 或 prod-deploy(latest) 把 dl 推到同一个 commit"})})}(Tc),function(e){e.command("script").description("Local python3 sandbox — ulimit CPU seconds / 64 KiB output.").command("exec").description(["Run a python3 transform. --inputs-file keys are injected as top-level variables;","assign to `result` to return a value.",""," --script-file=<path|-> python source; `-` reads stdin (preferred for one-off scripts)."," --inputs-file=<path|-> JSON object whose keys become globals; `-` reads stdin.","","Example (script via stdin, inputs from disk):"," cat <<'PY' | dl script exec --script-file=- --inputs-file=/workspace/inputs.json --timeout=5"," result = sum(items)"," PY"].join("\n")).option("--script <text>",'RECOMMENDED: python source inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --script "$(cat script.py)" — keeps multi-line content out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --script-file.').option("--script-file <path|->",'LEGACY: python source via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --script "$(cat file)". Use --script-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--inputs <inline-json>",'RECOMMENDED: JSON object whose keys become globals, inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --inputs "$(cat inputs.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --inputs-file.').option("--inputs-file <path|->",'LEGACY: JSON object whose keys become globals, via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --inputs "$(cat file)". Use --inputs-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--timeout <s>","CPU seconds (1–5, default 5)",e=>Number(e)).option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").action(async e=>{e.printSchema&&ms({command:"dl script exec",summary:"Run a python3 transform in the local sandbox; assign `result` to return a value.",scalars:[{name:"timeout",type:"integer",required:!1,description:"CPU seconds (1–5, default 5)"},{name:"script",type:"string",required:!1,description:"RECOMMENDED inline python source (required: pass this or --script-file)"},{name:"inputs",type:"string",required:!1,description:"RECOMMENDED inline JSON object whose keys become globals (sibling of --inputs-file)"}],files:[{name:"script-file",required:!1,kind:"text",description:"LEGACY: python source via file/stdin (prefer --script inline)",example:"result = sum(items)\n"},{name:"inputs-file",required:!1,kind:"object",description:"LEGACY: JSON object of globals via file/stdin (prefer --inputs inline)",example:'{"items":[1,2,3]}'}]});let t,i,n="",o={};e.script||e.scriptFile||Da("E_SCHEMA","--script is required (pass the python source inline, or use --script-file for the legacy file/stdin path)","run `dl script exec --print-schema` to see the expected shape",{flag:"--script"});try{const r=await Pa(e.script?String(e.script):void 0,e.scriptFile?String(e.scriptFile):void 0,{inline:"--script",file:"--script-file"});r&&(n=r.raw,t=r.label);const a=await qa(e.inputs?String(e.inputs):void 0,e.inputsFile?String(e.inputsFile):void 0,{inline:"--inputs",file:"--inputs-file"});a&&(o=a.data,i=a.source.label)}catch(e){throw e instanceof Yr&&Ha(e),e}Ba({command:"script exec",script_source:t??null,inputs:o,inputs_source:i??null});const r=void 0!==e.timeout?Number(e.timeout):void 0,a=await async function(e,t={},i={}){const n=Date.now(),o=Math.max(1,Math.min(i.timeoutSeconds??5,5)),r=1e3*(o+1),a=`ulimit -t ${o} 2>/dev/null; ulimit -v 65536 2>/dev/null; exec python3 -I -c "$PY_SCRIPT"`,s={PY_SCRIPT:["import json as __dl_json","import sys as __dl_sys","__dl_inputs_raw = __dl_sys.stdin.read()","__dl_inputs = __dl_json.loads(__dl_inputs_raw) if __dl_inputs_raw else {}","for __dl_k, __dl_v in __dl_inputs.items():"," globals()[__dl_k] = __dl_v","__dl_input_keys = set(__dl_inputs.keys())","# --- user script ---",e,"# --- end user script ---","__dl_result = globals().get('result')","__dl_outputs = {}","for __dl_k, __dl_v in list(globals().items()):"," if __dl_k.startswith('_') or __dl_k == 'result':"," continue"," if __dl_k in __dl_input_keys:"," continue"," if __dl_k in ('json','sys') or callable(__dl_v) or isinstance(__dl_v, type):"," continue"," try:"," __dl_json.dumps(__dl_v, default=str)"," except Exception:"," continue"," __dl_outputs[__dl_k] = __dl_v",`__dl_sys.stdout.write(${JSON.stringify(ql)} + __dl_json.dumps({'result': __dl_result, 'output_variables': __dl_outputs}, default=str) + ${JSON.stringify(Pl)} + '\\n')`].join("\n"),LANG:"C.UTF-8",PATH:process.env.PATH??"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},l=u("/bin/sh",["-c",a],{env:s,stdio:["pipe","pipe","pipe"]});let c="",d="",p=0,m=0;l.stdout.on("data",e=>{if(p>=zl)return;const t=zl-p,i=e.length>t?e.subarray(0,t):e;c+=i.toString("utf8"),p+=i.length}),l.stderr.on("data",e=>{if(m>=zl)return;const t=zl-m,i=e.length>t?e.subarray(0,t):e;d+=i.toString("utf8"),m+=i.length}),l.stdin.write(JSON.stringify(t)),l.stdin.end();let h=!1;const f=setTimeout(()=>{h=!0,l.kill("SIGKILL")},r+6e3-6e3+6e3),g=await new Promise(e=>{l.on("close",(t,i)=>e({code:t??-1,signal:i}))});clearTimeout(f);const v=Date.now()-n,y=Buffer.byteLength(e,"utf8"),b=h||"SIGKILL"===g.signal||"SIGXCPU"===g.signal||137===g.code||152===g.code;let _,w={},k=c;const x=c.lastIndexOf(ql),S=c.lastIndexOf(Pl);if(-1!==x&&-1!==S&&S>x){const e=c.slice(x+10,S);try{const t=JSON.parse(e);_=t.result,w=t.output_variables??{},k=c.slice(0,x)}catch{}}return b?{success:!1,result:null,output_variables:{},error:`script timed out (CPU limit ${o}s)`,stdout:k,stderr:d,duration_ms:v,script_size_bytes:y,timed_out:!0,exit_code:g.code}:0!==g.code?{success:!1,result:null,output_variables:{},error:d.trim().slice(-500)||`script exited with code ${g.code}`,stdout:k,stderr:d,duration_ms:v,script_size_bytes:y,timed_out:!1,exit_code:g.code}:{success:!0,result:_,output_variables:w,error:null,stdout:k,stderr:d,duration_ms:v,script_size_bytes:y,timed_out:!1,exit_code:g.code}}(n,o,{timeoutSeconds:r});a.success||Fa(a.error??`script exited with code ${a.exit_code}`,void 0,{stdout:a.stdout,stderr:a.stderr,exit_code:a.exit_code,duration_ms:a.duration_ms,script_size_bytes:a.script_size_bytes,timed_out:a.timed_out}),Ua({ok:!0,success:!0,result:a.result,output_variables:a.output_variables,error:null,duration_ms:a.duration_ms,script_size_bytes:a.script_size_bytes,stdout:a.stdout,stderr:a.stderr})})}(Tc),function(e){const t=e.command("skill").description("Return a pointer the model hands to the built-in `read` tool; no file I/O happens here.");t.command("read").description("Return a `read`-tool pointer for this skill's `SKILL.md`.").requiredOption("--name <name>","skill name (matches `<name>` in `<available_skills>`)").action(e=>{Xl(String(e.name),"SKILL.md")}),t.command("resource").description("Return a `read`-tool pointer for a file inside a skill's directory.").option("--skill <name>","skill name (matches `<name>` in `<available_skills>`)").option("--name <name>","legacy alias of --skill (kept for back-compat with older skill md)").requiredOption("--path <path>","path inside the skill's directory, relative to the skill root").action(e=>{const t=String(e.skill??e.name??"");t||Fa("either --skill or --name is required","e.g. dl skill resource --skill=video-breakdown --path=resources/analysis_system_prompt.txt"),Xl(t,String(e.path))});for(const e of["activate","compile","draft-create","draft-update","fork","publish","search","validate"])t.command(e,{hidden:!0}).description("skill authoring command — NOT implemented on Pi").allowUnknownOption(!0).action(()=>Cl(`skill ${e}`,"skill authoring commands (activate/compile/draft-*/fork/publish/search/validate) are iLands-runtime-only. On Pi, read a skill file with the built-in `read` tool using `dirname(<location>) + <relative-path>`."))._hidden=!0}(Tc),function(e){const t=e.command("artifact").description("Versioned slot store for skill artifacts (drafts, validation, canonical promotion).").addHelpText("after",["","Storage layout per project:"," slots/<slot> + versions/<n> — drafts, latest version pointer."," canonical/<slot> — promoted, immutable."," receipts/<autoId> — finalize / promote event stream.","","Status: draft → verified (finalize) → stale (upstream changed)"," any → invalidated (terminal)."].join("\n"));t.command("list").description("List every slot header in the current session.").option("--quiet","emit only {ok,count,slots:[{slot,status,currentVersion}]}").action(async e=>{try{const t=(Es(await Ss("list",{})).slots??[]).map(t=>({slot:t.slotName,status:t.status,currentVersion:t.currentVersion,contentType:t.contentType,...e.quiet?{}:{updatedAt:t.updatedAt},...e.quiet?{}:t.inputFence?{inputFence:t.inputFence}:{}}));Ua({ok:!0,count:t.length,slots:t})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("read").description("Read a slot version (default: current).").requiredOption("--slot <name>").option("--version <n>","version number (default: header.currentVersion)",e=>parseInt(e,10)).option("--quiet","omit metadata, return content only").action(async e=>{try{const t=Es(await Ss("read",{slot:String(e.slot),...void 0!==e.version?{version:e.version}:{}})),i=t.header,n=t.version;n||Fa(`slot has no version content: ${e.slot}`),e.quiet&&Ua({ok:!0,content:n.content}),Ua({ok:!0,slot:i?.slotName,version:n.version,content:n.content,contentType:n.contentType,changeType:n.changeType,contentHash:n.contentHash,status:n.status,createdAt:n.createdAt,currentVersion:i?.currentVersion,headerStatus:i?.status,...n.changeSummary?{changeSummary:n.changeSummary}:{},...n.inputFence?{inputFence:n.inputFence}:{}})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("write").description("Write a new version of a slot. Resets status to draft.").addHelpText("after",["","`--contract` is OPTIONAL. Without it, write is best-effort: JSON parse +","state-machine checks only. With it, the slot's `schema_ref` is run through","ajv in RELAXED mode (every `additionalProperties: false` in the schema is","flipped to `true` before compile, so extra domain fields are accepted","while `required` / `type` / `enum` / `minLength` still apply). Pass","`--strict-schema` to use the contract schema exactly as written.","Content-type mismatches with the contract downgrade to warnings.","","Example (stdin):"," cat <<EOF | dl artifact write --slot=music_candidate --content-type=application/json --content-file=-",' {"service":"banana-pro","prompt":"a cat in a hat"}'," EOF"].join("\n")).option("--slot <name>").option("--content <text>",'RECOMMENDED: content body inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --content "$(cat body.json)" — keeps multi-line content out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --content-file.').option("--content-file <path|->",'LEGACY: content body as raw text (JSON for application/json) via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --content "$(cat file)". Use --content-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--contract <path>","absolute path to artifact_contract.json (optional)").option("--strict-schema","validate against the contract schema as-written (default: relaxed — `additionalProperties: false` is flipped to `true`)").option("--content-type <ct>","MIME type","application/json").option("--change-summary <text>","human-readable summary of the write").option("--dry-run","validate but do not persist").option("--include-content","include the full written content in the response (default: omitted)").option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").option("--skip-url-check","skip URL reachability preflight for JSON content").action(async e=>{e.printSchema&&ms({command:"dl artifact write",summary:"Write a new version of a slot.",scalars:[{name:"slot",type:"string",required:!0,description:"slot name"},{name:"content-type",type:"string",required:!1,description:"MIME (default application/json)"},{name:"contract",type:"string",required:!1,description:"absolute path to artifact_contract.json (optional)"},{name:"strict-schema",type:"boolean",required:!1,description:"validate against contract schema as-written (default: relaxed)"},{name:"change-summary",type:"string",required:!1,description:""},{name:"dry-run",type:"boolean",required:!1,description:""},{name:"include-content",type:"boolean",required:!1,description:"include full written content in response (default: omitted)"},{name:"skip-url-check",type:"boolean",required:!1,description:"skip URL reachability preflight for JSON content"},{name:"content",type:"string",required:!1,description:"RECOMMENDED inline raw-text content body (required: pass this or --content-file)"}],files:[{name:"content-file",required:!1,kind:"text",description:"LEGACY: content body via file/stdin (prefer --content inline)",example:'{"service":"banana-pro","prompt":"a cat"}'}]}),e.slot||Da("E_SCHEMA","--slot is required","run `dl artifact write --print-schema` for the expected shape",{flag:"--slot"}),e.content||e.contentFile||Da("E_SCHEMA","--content is required (pass the content inline, or use --content-file for the legacy file/stdin path)","run `dl artifact write --print-schema` to see the expected shape",{flag:"--content"});{const i=function(e){const t=e.split(";")[0]?.trim().toLowerCase()??"";return!(!t||"application/json"!==t&&!t.startsWith("text/")&&!t.endsWith("+json")&&!t.endsWith("+xml")&&"application/xml"!==t&&"application/yaml"!==t&&"application/x-yaml"!==t)}(t=String(e.contentType))?null:{message:`artifact content-type "${t}" is not text/JSON — artifact slots store text only`,hint:ps,extra:{contentType:t}};i&&Da("E_SCHEMA",i.message,i.hint,i.extra)}var t;let i,n="";try{const t=await Pa(e.content?String(e.content):void 0,e.contentFile?String(e.contentFile):void 0,{inline:"--content",file:"--content-file"});t&&(n=t.raw,i=t.label)}catch(e){throw e instanceof Yr&&Ha(e),e}Ba({command:"artifact write",slot:String(e.slot),content_source:i??null,content_bytes:Buffer.byteLength(n,"utf8")});{const e=function(e){return function(e){return/[\u0000\uFFFD]/.test(e)}(e)?{message:"artifact content contains binary bytes (NUL or U+FFFD replacement chars) — looks like a binary file read as text",hint:ps,extra:{reason:"binary-content"}}:null}(n);e&&Da("E_SCHEMA",e.message,e.hint,e.extra)}if(!e.skipUrlCheck&&String(e.contentType).includes("json")){let e;try{e=JSON.parse(n)}catch{e=void 0}void 0!==e&&await As(ys(e),!1)}const o=e.contract?$s(String(e.contract),String(e.slot)):void 0;try{Ua({ok:!0,...Ts(Os(Es(await Ss("write",{slot:String(e.slot),content:n,contentType:String(e.contentType),...o?{contract:o.contract,schemas:o.schemas}:{},...e.strictSchema?{strictSchema:!0}:{},...e.changeSummary?{changeSummary:String(e.changeSummary)}:{},...e.dryRun?{dryRun:!0}:{}}))),["slotName","version","status","contentHash","warnings"],!!e.includeContent)})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("patch").description("Text patch: unique find+replace. Writes a new version (changeType=patch).").requiredOption("--slot <name>").requiredOption("--from <string>","exact substring to replace (must match exactly once)").requiredOption("--to <string>","replacement string").option("--change-summary <text>").option("--dry-run","report what would change, do not persist").option("--include-content","include full patched content in response (default: omitted)").option("--skip-url-check","skip URL reachability preflight for --to text").action(async e=>{await As(function(e){const t=new Set,i=[];for(const n of e.matchAll(vs)){const e=_s(n[0]);e&&!t.has(e)&&(t.add(e),i.push({path:"$.to",url:e}))}return i}(String(e.to)),!!e.skipUrlCheck);try{Ua({ok:!0,...Ts(Os(Es(await Ss("patch",{slot:String(e.slot),from:String(e.from),to:String(e.to),...e.changeSummary?{changeSummary:String(e.changeSummary)}:{},...e.dryRun?{dryRun:!0}:{}}))),["slotName","version","status","contentHash"],!!e.includeContent)})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("patch-json").description("Atomic JSONPath-lite patch on a slot's JSON content (set/merge/append/delete).").addHelpText("after",["","`--operations-file` is a JSON array of `{path, op, value?}` entries."," path — JSONPath-lite: dot/bracket access only (`a.b.c[2]`); no filters / wildcards"," op — one of: set | merge | append | delete"," value — required for set/merge/append; omitted for delete","","Example (stdin):"," cat <<EOF | dl artifact patch-json --slot=storyboard --operations-file=-",' [{"path":"segments[0].text","op":"set","value":"hi"}]'," EOF"].join("\n")).option("--slot <name>").option("--operations <inline-json>",'RECOMMENDED: JSON array of {path,op,value?} inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --operations "$(cat ops.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --operations-file.').option("--operations-file <path|->",'LEGACY: JSON array of {path,op,value?} via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --operations "$(cat file)". Use --operations-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--change-summary <text>").option("--dry-run","report op count, do not persist").option("--include-content","include full patched content in response (default: omitted)").option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").option("--skip-url-check","skip URL reachability preflight for operations[].value").action(async e=>{e.printSchema&&ms({command:"dl artifact patch-json",summary:"Atomic JSONPath-lite patch on a slot's JSON content.",scalars:[{name:"slot",type:"string",required:!0,description:"slot name"},{name:"change-summary",type:"string",required:!1,description:""},{name:"dry-run",type:"boolean",required:!1,description:""},{name:"include-content",type:"boolean",required:!1,description:"include full patched content in response (default: omitted)"},{name:"skip-url-check",type:"boolean",required:!1,description:"skip URL reachability preflight for operations[].value"},{name:"operations",type:"string",required:!1,description:"RECOMMENDED inline JSON array of {path,op,value?} (required: pass this or --operations-file)"}],files:[{name:"operations-file",required:!1,kind:"array",description:"LEGACY: array of {path,op,value?} via file/stdin (prefer --operations inline)",example:'[{"path":"segments[0].text","op":"set","value":"hi"}]'}]}),e.slot||Da("E_SCHEMA","--slot is required","run `dl artifact patch-json --print-schema` for the expected shape",{flag:"--slot"}),e.operations||e.operationsFile||Da("E_SCHEMA","--operations is required (pass the JSON array inline, or use --operations-file for the legacy file/stdin path)","run `dl artifact patch-json --print-schema` to see the expected shape",{flag:"--operations"});let t,i=[];try{const n=await async function(e,t,i){const n="string"==typeof e&&""!==e,o="string"==typeof t&&""!==t;return n&&o&&za(i),n?La(e,i.inline):o?Ia(t,i.file):void 0}(e.operations?String(e.operations):void 0,e.operationsFile?String(e.operationsFile):void 0,{inline:"--operations",file:"--operations-file"});n&&(i=n.data,t=n.source.label)}catch(e){throw e instanceof Yr&&Ha(e),e}if(0===i.length&&Da("E_SCHEMA","--operations must be a non-empty JSON array",void 0,{flag:"--operations"}),Ba({command:"artifact patch-json",slot:String(e.slot),operations:i,operations_source:t??null}),!e.skipUrlCheck){const e=[];for(let t=0;t<i.length;t++){const n=i[t].value;if(void 0!==n)for(const i of ys(n,`$.operations[${t}].value`))e.push(i)}await As(e,!1)}try{Ua({ok:!0,...Ts(Os(Es(await Ss("patch-json",{slot:String(e.slot),operations:i,...e.changeSummary?{changeSummary:String(e.changeSummary)}:{},...e.dryRun?{dryRun:!0}:{}}))),["slotName","version","status","contentHash"],!!e.includeContent)})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("diff").description("Line-level diff between two versions of a slot (default: current vs. current-1).").requiredOption("--slot <name>").option("--from <n>","older version",e=>parseInt(e,10)).option("--to <n>","newer version (default: current)",e=>parseInt(e,10)).option("--quiet","just return patch string").action(async e=>{try{const t=Es(await Ss("read",{slot:String(e.slot)})).header;t||Fa(`slot not found: ${e.slot}`);const i=Number(t?.currentVersion??1),n=e.to??i,o=e.from??Math.max(1,n-1);o===n&&Ua({ok:!0,slot:e.slot,from:o,to:n,unchanged:!0,diff:""});const[r,a]=await Promise.all([Ss("read",{slot:String(e.slot),version:o}),Ss("read",{slot:String(e.slot),version:n})]),s=Es(r),l=Es(a),c=function(e,t){const i=e.split("\n"),n=t.split("\n"),o=i.length,r=n.length,a=Array.from({length:o+1},()=>new Array(r+1).fill(0));for(let e=0;e<o;e++)for(let t=0;t<r;t++)a[e+1][t+1]=i[e]===n[t]?a[e][t]+1:Math.max(a[e+1][t],a[e][t+1]);const s=[];let l=o,c=r;for(;l>0&&c>0;)i[l-1]===n[c-1]?(s.push({type:"ctx",line:i[l-1]}),l--,c--):a[l][c-1]>=a[l-1][c]?(s.push({type:"add",line:n[c-1]}),c--):(s.push({type:"del",line:i[l-1]}),l--);for(;l>0;)s.push({type:"del",line:i[l-1]}),l--;for(;c>0;)s.push({type:"add",line:n[c-1]}),c--;return s.reverse()}(String(s.version?.content??""),String(l.version?.content??"")),d=function(e){return e.map(e=>"add"===e.type?`+${e.line}`:"del"===e.type?`-${e.line}`:` ${e.line}`).join("\n")}(c);e.quiet&&Ua({ok:!0,diff:d}),Ua({ok:!0,slot:e.slot,from:o,to:n,added:c.filter(e=>"add"===e.type).length,deleted:c.filter(e=>"del"===e.type).length,diff:d})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("validate").description("Run contract validation without changing state. Returns issues + warnings + staleness.").addHelpText("after",["","`--contract` is OPTIONAL. Without it, only state-machine + emptiness +","staleness checks run. With it, schema is validated in RELAXED mode unless","`--strict-schema` is passed (see `dl artifact write --help`)."].join("\n")).requiredOption("--slot <name>").option("--contract <path>","absolute path to artifact_contract.json (optional)").option("--strict-schema","validate against the contract schema as-written (default: relaxed)").option("--quiet").action(async e=>{try{const t=e.contract?$s(String(e.contract),String(e.slot)):void 0,i=Es(await Ss("validate",{slot:String(e.slot),...t?{contract:t.contract,schemas:t.schemas}:{},...e.strictSchema?{strictSchema:!0}:{}}));e.quiet&&Ua({ok:!0,verified:i.verified,isStale:i.isStale,issueCount:Array.isArray(i.issues)?i.issues.length:0}),Ua({ok:!0,...Os(i)})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("fork").description("Copy the latest version of --source into --target as a new draft (changeType=fork).").requiredOption("--source <name>").requiredOption("--target <name>").option("--dry-run").option("--include-content","include full forked content in response (default: omitted)").action(async e=>{try{Ua({ok:!0,...Ts(Os(Es(await Ss("fork",{source:String(e.source),target:String(e.target),...e.dryRun?{dryRun:!0}:{}}))),["slotName","version","changeType"],!!e.includeContent)})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("finalize").description("Verify slot against its contract. mode=verify_and_promote also flips draft→verified, writes canonical, emits receipt.").addHelpText("after",["","`--contract` is OPTIONAL. Without it, only state-machine + emptiness +","staleness checks run; the slot still flips to `verified` (or promotes","in `verify_and_promote` mode). With it, schema validates in RELAXED mode","unless `--strict-schema` is passed (see `dl artifact write --help`)."].join("\n")).requiredOption("--slot <name>").option("--contract <path>","absolute path to artifact_contract.json (optional)").option("--strict-schema","validate against the contract schema as-written (default: relaxed)").option("--mode <mode>","verify | verify_and_promote","verify").option("--dry-run","never promote, even if mode=verify_and_promote").option("--include-content","include full finalized content in response (default: omitted)").action(async e=>{["verify","verify_and_promote"].includes(String(e.mode))||Fa(`unsupported mode: ${e.mode}`,'use "verify" or "verify_and_promote".');try{const t=e.contract?$s(String(e.contract),String(e.slot)):void 0,i=e.dryRun?"verify":String(e.mode);Ua({ok:!0,...Ts(Os(Es(await Ss("finalize",{slot:String(e.slot),mode:i,...t?{contract:t.contract,schemas:t.schemas}:{},...e.strictSchema?{strictSchema:!0}:{}}))),["slotName","version","verified","promoted","status","canonicalId"],!!e.includeContent),...e.dryRun?{dryRun:!0}:{}})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("select").description("NOT implemented — use `artifact finalize --mode=verify_and_promote` to lock a canonical version.").requiredOption("--slot <name>").option("--quiet").action(()=>{Fa("dl artifact select is not implemented on pi","pi does not model active variants; use `artifact finalize --mode=verify_and_promote` to lock a canonical version instead.")})._hidden=!0,t.command("canonical").description("Read the canonical (promoted) snapshot of a slot, if any.").requiredOption("--slot <name>").option("--quiet").action(async e=>{try{const t=Es(await Ss("canonical",{slot:String(e.slot)})).canonical??null;t||Fa(`no canonical promotion for slot: ${e.slot}`),e.quiet&&Ua({ok:!0,content:t.content,contentHash:t.contentHash}),Ua({ok:!0,...t})}catch(e){Fa(e instanceof Error?e.message:String(e))}})}(Tc),function(e){const t=e.command("asset").description("Register / fetch media assets (groups + assets) for downstream generate-* verbs.");t.command("register").description("Create an asset group and register one asset under it; the server assigns the real group_id.").requiredOption("--group-id <name>","human-readable group NAME (despite the flag's spelling — server assigns the real id)").requiredOption("--name <name>").requiredOption("--url <url>").requiredOption("--asset-type <type>","one of: Image / Video / Audio (iLands capitalization)").option("--project-name <name>","default project","default").action(async e=>{try{const t=await async function(e){return ua("media/register-asset","api/asset/create-group",{name:e.name,project_name:e.project_name??"default",...e.description?{description:e.description}:{}},{timeoutMs:3e4,retries:1})}({name:String(e.groupId),project_name:String(e.projectName??"default")}),i=t.group_id??t.data?.Result?.Id??"";i||Fa("create-group returned no group_id",void 0,{response:t});const n=await async function(e){return ua("media/register-asset","api/asset/create",e,{timeoutMs:3e4,retries:1})}({group_id:i,name:String(e.name),url:String(e.url),asset_type:String(e.assetType)});Ua({ok:!0,group:{group_id:i,name:e.groupId},asset:n})}catch(e){Fa(e instanceof Error?e.message:String(e))}}),t.command("get").description("Fetch a single asset by id.").requiredOption("--id <id>").action(async e=>{try{Ua({ok:!0,asset:await async function(e){return ua("media/get-asset","api/asset/get",{id:e},{timeoutMs:3e4,retries:1})}(String(e.id))})}catch(e){Fa(e instanceof Error?e.message:String(e))}})}(Tc),function(e){const t=e.command("knowledge").description("Knowledge-base search across domain libraries (sfx, bgm, visual_style, voice, writing, meme).");t.command("search").description("Search a knowledge domain; returns `data` plus domain metadata and CDN URLs.").addHelpText("after",["","Domains: sfx, stinger, bgm, amb, audio_any, visual_style, voice,"," writing_plot/character/payoff/conflict/hook/any, meme.","","`--provider` (voice-only): filter to a specific TTS provider —"," `elevenlabs` (high-quality English, audio tags) or `minimax` (CN+EN).",' Equivalent to adding `{"vendor":"<v>"}` to --filters-file but'," surfaces in --help / --print-schema for easier agent discovery.","","Example (stdin):",' cat <<EOF | dl knowledge search --domain=voice --query="deep narrator" --filters-file=-',' {"language":"EN","gender":"Male"}'," EOF","","Example (provider filter):",' dl knowledge search --domain=voice --provider=elevenlabs --query="warm narrator"'].join("\n")).requiredOption("--domain <name>",`one of: ${Rl.join(", ")}`).requiredOption("--query <q>").option("--kind <tag>","domain-specific shape filter (e.g. meme: ready|template)").option("--provider <name>",`(voice domain only) filter to a TTS provider: ${Il.join(" | ")}`).option("--k <n>","max hits (default 10)",e=>{const t=Number(e);if(!Number.isFinite(t)||!Number.isInteger(t)||t<1||t>100)throw new Error(`--k invalid: ${e}`);return t}).option("--filters <inline-json>",'RECOMMENDED: domain-specific filters inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --filters "$(cat filters.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --filters-file.').option("--filters-file <path|->",'LEGACY: domain-specific filters JSON object via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --filters "$(cat file)". Use --filters-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--print-schema","print scalar+file schema and exit").action(async e=>{e.printSchema&&ms({command:"dl knowledge search",summary:"Knowledge-base search for domain-specific asset libraries.",scalars:[{name:"domain",type:"string",required:!0,description:"asset library domain",enum:Rl},{name:"query",type:"string",required:!0,description:"search query"},{name:"kind",type:"string",required:!1,description:"domain-specific shape filter (e.g. meme: ready|template)"},{name:"provider",type:"string",required:!1,description:"voice-domain only: filter by TTS provider (elevenlabs | minimax)",enum:Il},{name:"k",type:"integer",required:!1,description:"max hits (default 10, max 100)"},{name:"filters",type:"string",required:!1,description:"RECOMMENDED inline JSON object of domain-specific filters (sibling of --filters-file)"}],files:[{name:"filters-file",required:!1,kind:"object",description:"LEGACY: domain-specific filters (prefer --filters inline)",example:'{"language":"EN","gender":"Female","vendor":"elevenlabs"}'}]});const t=String(e.domain);Rl.includes(t)||Fa(`--domain must be one of ${Rl.join(", ")}; got ${t}`);const i=String(e.query),n=Math.min(e.k??10,20),o=e.kind?String(e.kind):void 0,r=e.provider?String(e.provider):void 0;r&&(Il.includes(r)||Fa(`--provider must be one of ${Il.join(", ")}; got ${r}`),"voice"!==t&&Fa(`--provider is only valid with --domain=voice; got --domain=${t}`,"drop --provider, or switch --domain=voice if you meant to search voices."));let a={};try{const t=await qa(e.filters?String(e.filters):void 0,e.filtersFile?String(e.filtersFile):void 0,{inline:"--filters",file:"--filters-file"});t&&(a=t.data)}catch(e){throw e instanceof Yr&&Ha(e),e}if("voice"===t&&"provider"in a){const{provider:e,...t}=a;a={...t,..."vendor"in t?{}:{vendor:e}}}const s={...a,...o?{kind:o}:{},...r?{vendor:r}:{}},l={domain:t,query:i,limit:n};Object.keys(s).length>0&&(l.filters=s);try{const e=await ua("knowledge","api/v1/knowledge/search",l,{timeoutMs:3e4,retries:1}),o=Array.isArray(e.data)?e.data:[],r=e.meta&&"object"==typeof e.meta?e.meta:{domain:t,query:i,limit:n,count:o.length};Ua({ok:!0,domain:t,query:i,...e,data:o,meta:r,hits:o})}catch(e){if(e instanceof oa&&Fa(e.message,e.hint),e instanceof Zr){const t=function(e){let t;try{t=JSON.parse(e)}catch{return}if(!t||"object"!=typeof t)return;const i=t.error;if(!i||"object"!=typeof i)return;const n=i.message;return"string"==typeof n&&n.length>0?n:void 0}(e.bodyText),i=e.status>=400&&e.status<500;Fa(`knowledge search failed (http ${e.status})${t?`: ${t}`:""}`,i?"fix request filters; run `dl knowledge search --print-schema` for the expected shape":"check backend reachability",{status:e.status,body:e.bodyText.slice(0,500)})}Fa(e instanceof Error?e.message:String(e))}});for(const e of["agent-profile","context-find","context-write","materials","platform","trending","web","web-read"])t.command(e).description("iLands-runtime-only knowledge verb — NOT implemented on pi").allowUnknownOption(!0).action(()=>Cl(`knowledge ${e}`,"iLands-runtime-only knowledge verb — on Pi, use `dl search` / `dl web-fetch` / `dl artifact write` as appropriate."))._hidden=!0}(Tc),function(e){as(e,{verb:"lipsync",actionName:"lipsync",schema:Po,billing:{schema:tl,select:e=>({service:e.service,duration:e.duration,resolution:e.resolution}),quote:nl},supportsBatch:!0,description:"Generate a talking-head video where a character's lips sync to a driving audio track. Submits one job (or N via --jobs-file) and returns {job_ref, status:'pending'}; the rendered video URL arrives via [async-callback].",notes:["Preferred default service: `dlai2v_pro` (LTX 2 Pro / LTX 2.3 multi-frame).","Use `dlai2v` (LTX 2 baseline) when you need explicit --width / --height / --seed / --quality-preset control.","`--audio-url` determines lipsync duration. Do not pass --duration to control output length; if present, duration is billing-only and vendor does not read it.","","LTX 2 family (`dlai2v_pro` / `dlai2v`) prompt template — every prompt must contain all three:",' 1. Subject is speaking/singing (e.g. "the character speaks naturally with perfect lip synchronization")'," 2. Character action description (head nods, hands, shoulders, breathing, gaze, …)",' 3. Camera movement description (e.g. "Dolly in", "slow push in", "static medium close-up")',"Reference template:",' --prompt="A person speaks naturally with perfect lip synchronization, subtle head nods'," and tilts, hands resting gently or making small conversational gestures, relaxed",' shoulders, natural breathing motion, high quality, natural lighting, Dolly in"',"","## Multi-keyframe mode (--keyframes, dlai2v / dlai2v_pro / dlai2v_pro_multiframe only)","--image-url and --keyframes are mutually exclusive. --image-url = single reference image","(api-layer auto-wraps it into keyframes[0]). --keyframes = 1-5 explicit keyframe images","for richer camera movement — the model interpolates animation between keyframes + audio-driven lip sync.","",'Each --keyframes value is a JSON object: {"image_url":"...","frame_position":"first|middle|last"}'," - frame_position controls where in the timeline the keyframe anchors"," - All keyframe images must be the same character and same aspect ratio"," - Typical MV workflow: generate a 2×2 grid image (same character, 4 poses) via dl generate-image,"," ffmpeg crop into 4 panels, pass as 4 keyframes → rich camera movement + pose transitions","","Constraints: --keyframes only works with dlai2v / dlai2v_pro / dlai2v_pro_multiframe","(preflight rejects other services); 1-5 keyframes for dlai2v / dlai2v_pro,","2-4 keyframes for dlai2v_pro_multiframe; do NOT pass both --image-url and --keyframes.","","## dlai2v_pro_multiframe (LTX 2.3 真·多帧变体)","真正的多帧关键帧引导视频生成(不是单帧 wrap)。必须用 --keyframes (2-4 帧);","每帧支持 {image_url (必填), frame_ratio? (0.0-1.0 时间位置), weight? (0.0-1.0 强度, 默认 0.4)}。","frame_ratio 不传则按数量等分: 2帧=[0,1] / 3帧=[0,0.5,1] / 4帧=[0,0.33,0.67,1]。","api-layer 按 keyframes 数量自动 router 到 mutiframe_{2f,3f,4f} workflow。","--aspect-ratio 支持 16:9/9:16/1:1;resolution 强制 720p (不可改);","不支持显式 --width / --height / --resolution。","","Seedance 2.0 (`seedance-2-0` / `seedance-2-0-fast`): prompt must contain the `@audio1`","placeholder (preflight rejects without it). Wrap alignment cues around `@audio1`; do not","add camera-motion text — for Seedance it competes with articulation weight.","`--audio-url` determines lipsync duration; do not pass --duration.","","⚠ SEEDANCE 2.0 ASSET RULES — read before composing the call:"," 1. Real-person / known-IP face image MUST go through `dl asset register` first;"," passing a raw real-person URL via --image-url is blocked by upstream policy."," 2. Once a face is registered as an asset, reference it ONLY via --ark-asset-ids +"," @assetN in the prompt. Do NOT also pass the same face via --image-url — the two"," channels are mutually exclusive for the same image; double-passing produces"," unpredictable routing on the vendor side."," 3. Set --reference-subject-type=real_person on real-person asset calls."," Full constraint list: `dl lipsync model seedance-2-0` (or `model seedance-2-0-fast`)."],whenToUse:["You have a face image + audio and want a video of the face speaking","Multi-segment lipsync (split the song / dialogue into beats and fan out via --jobs-file)"],whenNotToUse:["You only need text → speech (no face) — use `dl generate-tts`","You need a music track — use `dl generate-music`","You need a talking head from scratch with no audio: not supported on Pi"],examples:[{caption:"single, the common case — dlai2v_pro with the LTX-family prompt template",command:'dl lipsync \\\n --service=dlai2v_pro \\\n --image-url="https://cdn.example.com/face.png" \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --prompt="A person speaks naturally with perfect lip synchronization, subtle head nods and tilts, hands resting gently or making small conversational gestures, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in"'},{caption:"single, dlai2v (LTX 2 baseline) when you need width/height/seed control",command:'dl lipsync \\\n --service=dlai2v \\\n --image-url="https://cdn.example.com/face.png" \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --prompt="the singer performs the chorus line with perfect lip synchronization, subtle head nods, hands lightly gripping the mic, relaxed shoulders, natural breathing between phrases, high quality, natural lighting, slow dolly in" \\\n --quality-preset=high \\\n --width=1280 \\\n --height=736'},{caption:"multi-keyframe (4 poses from a 2×2 grid crop) — richer camera movement",command:'dl lipsync \\\n --service=dlai2v_pro \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf_top_left.png","frame_position":"first"}\' \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf_top_right.png","frame_position":"middle"}\' \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf_bottom_left.png","frame_position":"middle"}\' \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf_bottom_right.png","frame_position":"last"}\' \\\n --audio-url="https://cdn.example.com/segment.mp3" \\\n --prompt="A person sings expressively with perfect lip synchronization, dynamic head movement, confident posture shifts, high quality, natural lighting, slow dolly in"'},{caption:"batch via stdin (parallel fan-out)",command:'cat <<EOF | dl lipsync --jobs-file=-\n[\n {"job_key":"seg_001","service":"dlai2v_pro","image_url":"https://1.png","audio_url":"https://1.mp3","prompt":"A person speaks naturally with perfect lip synchronization, subtle head nods and tilts, hands resting gently, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in"},\n {"job_key":"seg_002","service":"seedance-2-0","image_url":"https://2.png","audio_url":"https://2.mp3","prompt":"the character delivers @audio1 with clear articulation, lips visibly mouthing each syllable, head and camera steady, mouth always visible"}\n]\nEOF'},{caption:"batch with multi-keyframe job",command:'cat <<EOF | dl lipsync --jobs-file=-\n[\n {"job_key":"seg_001","service":"dlai2v_pro","image_url":"https://face.png","audio_url":"https://1.mp3","prompt":"A person speaks naturally with perfect lip synchronization, subtle head nods, hands resting gently, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in"},\n {"job_key":"seg_002","service":"dlai2v_pro","keyframes":[{"image_url":"https://kf1.png","frame_position":"first"},{"image_url":"https://kf2.png","frame_position":"middle"},{"image_url":"https://kf3.png","frame_position":"last"}],"audio_url":"https://2.mp3","prompt":"A person sings expressively with perfect lip synchronization, dynamic head movement, confident posture, high quality, natural lighting, slow push in"}\n]\nEOF'}],notExamples:[{command:'dl lipsync --params=\'{"service":"dlai2v","image_url":"...","audio_url":"..."}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"},{command:"dl lipsync --image-url=... --audio-url=... --jobs-file=batch.json",whyItFails:"scalar flags + --jobs-file are mutually exclusive; raises E_SCHEMA"},{command:"dl lipsync --service=dlai2v_pro --image-url=... --keyframes='...' --audio-url=...",whyItFails:"--image-url and --keyframes are mutually exclusive; preflight rejects. Use one or the other."},{command:"dl lipsync --service=seedance-2-0 --keyframes='...' --audio-url=...",whyItFails:"--keyframes only works with dlai2v / dlai2v_pro; seedance does not support it; preflight rejects"},{command:'dl lipsync --service=seedance-2-0 --image-url=... --audio-url=... --prompt="just speaking"',whyItFails:"seedance-2-0 lipsync requires @audio1 in --prompt; preflight rejects"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"url":"https://storage.../video.mp4","duration_ms":3200}}',outputBatch:'{"ok":true,"action":"lipsync","results":[\n {"job_key":"seg_001","job_ref":"<uuid>","status":"pending"},\n ...\n]} // batch is non-blocking; each completed job is pushed back to the session via [async-callback]',preflight:e=>{const t=String(e.service??""),i="string"==typeof e.image_url&&""!==e.image_url,n=Array.isArray(e.keyframes)&&e.keyframes.length>0,o=Array.isArray(e.ark_asset_ids)&&e.ark_asset_ids.length>0,r=t.startsWith("seedance-2-0");if(!(i||n||r&&o))throw new Yr("E_SCHEMA","either --image-url or --keyframes is required","provide a face image via --image-url, multiple keyframes via --keyframes, or for seedance-2-0 use --ark-asset-ids",{verb:"lipsync",service:t});if(i&&n)throw new Yr("E_SCHEMA","--image-url and --keyframes are mutually exclusive","use --image-url for single-image lipsync, or --keyframes for multi-keyframe lipsync (1-5 frames); do not pass both",{verb:"lipsync",service:t});if(n&&"dlai2v"!==t&&"dlai2v_pro"!==t&&"dlai2v_pro_multiframe"!==t)throw new Yr("E_SCHEMA",`--keyframes is only supported for dlai2v / dlai2v_pro / dlai2v_pro_multiframe, not ${t}`,"use --image-url instead, or switch --service to dlai2v / dlai2v_pro / dlai2v_pro_multiframe for multi-keyframe lipsync",{flag:"--keyframes",verb:"lipsync",service:t});if("dlai2v_pro_multiframe"===t){if(!n)throw new Yr("E_SCHEMA","dlai2v_pro_multiframe requires --keyframes (2-4 frames); --image-url alone is not supported","pass 2-4 --keyframes flags; if you only have 1 image, use --service=dlai2v_pro instead",{verb:"lipsync",service:t});const i=e.keyframes.length;if(i<2||i>4)throw new Yr("E_SCHEMA",`dlai2v_pro_multiframe requires 2-4 keyframes, got ${i}`,"adjust to 2/3/4 keyframes; api-layer routes to mutiframe_{2f,3f,4f} workflow by count",{flag:"--keyframes",verb:"lipsync",service:t})}if(n&&e.keyframes.length>5)throw new Yr("E_SCHEMA",`--keyframes accepts 1-5 frames, got ${e.keyframes.length}`,"reduce to at most 5 keyframe images",{flag:"--keyframes",verb:"lipsync",service:t});if(r){const i=String(e.prompt??"");if(!/@audio1\b/.test(i))throw new Yr("E_SCHEMA","--prompt must contain @audio1 when --service=seedance-2-0 (preflight constraint)","add the @audio1 placeholder to --prompt; e.g. --prompt='speaking naturally @audio1'",{flag:"--prompt",verb:"lipsync",service:t})}},modelTopic:{rankingSummary:["Overall ranking (strongest → weakest) + recommended default:"," 🥇 dlai2v_pro LTX 2 Pro / LTX 2.3 multi-frame — **preferred default for new lipsync work**"," 🥈 dlai2v LTX 2 baseline — when you need explicit width/height/seed/quality-preset control"," 🥉 seedance-2-0 Strict lip + auto-keyframe + character consistency (requires @audio1; real-looking human/IP must asset register first)"," seedance-2-0-fast Same family as seedance-2-0 but faster / cheaper preview"," longcat-avatar Longer audio + simple setup, weaker resolution control"],services:[{service:"dlai2v_pro",label:"LTX 2 Pro (LTX 2.3 multi-frame)",tier:"🥇 Preferred default",bestFor:"Default choice for new lipsync work. LTX-2's successor multi-frame workflow; scene-style prompt (subject + action + camera) + face still + audio",quality:"Very High",speed:"2-5min",cost:"mid",description:["LTX 2 Pro, routes to the LTX-2.3 multi-frame workflow.","","Two input modes:"," Mode 1 (single image): --image-url — api-layer auto-wraps into keyframes[0]."," Mode 2 (multi-keyframe): --keyframes (1-5 frames) — explicit keyframe images for richer"," camera movement. Model interpolates between keyframes + audio-driven lip sync.",' Each keyframe: {"image_url":"...","frame_position":"first|middle|last"}'," Typical workflow: generate 2×2 grid (same character, 4 poses), ffmpeg crop → 4 keyframes.","","--image-url and --keyframes are mutually exclusive."],promptTips:["⚠ LTX family prompt template — all three segments required:"," 1. Subject is speaking/singing (explicitly say the character is *speaking* or *singing* with perfect lip sync)"," 2. Character action (head nods/tilts / gaze / hands / shoulders / breathing)"," 3. Camera movement (Dolly in / slow push in / static medium close-up; static must also be stated explicitly)","Append a quality / lighting tail: 'high quality, natural lighting'","","Reference template:",' "A person speaks naturally with perfect lip synchronization, subtle'," head nods and tilts, hands resting gently or making small conversational"," gestures, relaxed shoulders, natural breathing motion, high quality,",' natural lighting, Dolly in"'],flagSubset:["service","image-url","audio-url","prompt","keyframes"],constraints:["⚠ dlai2v_pro accepts a **strict subset** of flags — do NOT copy a dlai2v example and just swap the service name"," Invalid: --quality-preset / --width / --height / --resolution / --seed"," Invalid: --ark-asset-ids / --reference-subject-type (those are seedance's)"," Invalid: --duration (audio_url determines the output duration)"," Passing them is silently ignored (the multi-frame workflow uses fixed output dimensions)","--keyframes: 1-5 frames, mutually exclusive with --image-url","audio_url ≤ 100MB & ≤ 20s","audio formats: mp3 / wav / ogg / flac / m4a / aac / webm"],examples:[{caption:"single, dlai2v_pro default (LTX 2 Pro)",command:'dl lipsync --service=dlai2v_pro \\\n --image-url="https://cdn.example.com/face.png" \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --prompt="A person speaks naturally with perfect lip synchronization, subtle head nods and tilts, hands resting gently or making small conversational gestures, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in"'}]},{service:"dlai2v",label:"LTX 2 baseline (Multimodal)",tier:"🥈 When you need width/height/seed control",bestFor:"You need explicit --width / --height / --seed / --quality-preset control (dlai2v_pro's fixed-dimension multi-frame does not expose these)",quality:"Very High",speed:"2-5min",cost:"mid",description:["LTX 2 baseline. Prompt template is the same as dlai2v_pro (subject speaking + character action + camera move).","Also supports --keyframes (1-5 frames) for multi-keyframe mode, same as dlai2v_pro."],promptTips:["Same three-segment template as dlai2v_pro","--quality-preset='ultra' gives the best lip sync but is slower"],flagSubset:["service","image-url","audio-url","prompt","quality-preset","width","height","seed","keyframes"],constraints:["audio ≤ 19s & ≤ 50MB","--keyframes: 1-5 frames, mutually exclusive with --image-url","Do NOT pass --duration to control output length; audio_url determines the lipsync length"],examples:[{caption:"dlai2v with explicit width/height/seed",command:'dl lipsync --service=dlai2v \\\n --image-url="https://cdn.example.com/face.png" \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --prompt="A person speaks naturally with perfect lip synchronization, subtle head nods, hands resting gently, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in" \\\n --quality-preset=high --width=1280 --height=736 --seed=42'}]},{service:"seedance-2-0",label:"Seedance 2.0 Pro Lipsync",tier:"🥉 Strict lip + auto-keyframe",bestFor:"Strict lipsync + auto-keyframe + character consistency; the only legitimate path for real-looking human / known-IP input",quality:"Very High",speed:"2-5min",cost:"mid-high",description:["Seedance 2.0 Pro lipsync. Strict lip alignment + auto keyframe + character consistency.","Real-looking human / known-IP input MUST go through this service + dl asset register."],promptTips:["⚠ MUST contain the @audio1 placeholder (preflight hard rejects without it)"," Prompt style: wrap alignment cues around @audio1"," Example: 'the character delivers @audio1 with clear articulation, lips visibly"," mouthing each syllable, head and camera steady, mouth always visible'","","Effective cues: 'clear articulation' / 'mouth shape changes per syllable' /"," 'head and mouth steady' / 'mouth unobstructed' / 'no hand near face'","","⚠ Do NOT add camera-motion text (Dolly in / push in etc.) — Seedance fights for"," weight against articulation, and lip sync degrades instead","","Placeholder rules (all 1-indexed):"," @audioN → audio_url (only N=1 supported)"," @imageN → image input"," @assetN → ark_asset_ids[N-1]"],flagSubset:["service","image-url","audio-url","prompt","ark-asset-ids","reference-subject-type"],constraints:["audio_url ≤ 15s (hard API limit, longer audio is rejected outright)","Do NOT pass --duration; audio_url determines the lipsync length","Resolution: only 480p / 720p supported","Real-looking human / known-IP input MUST `dl asset register` first, then pass --ark-asset-ids + @assetN only; do not also pass the same media URL","Before real-looking human scenarios, MUST read docs/seedance_reference_assets.md (in the lipsync skill directory)"],examples:[{caption:"seedance-2-0 standard lipsync",command:'dl lipsync --service=seedance-2-0 \\\n --image-url=https://... \\\n --audio-url=https://... \\\n --prompt="the character delivers @audio1 with clear articulation, lips visibly mouthing each syllable, head and camera steady, mouth always visible"'},{caption:"seedance-2-0 real-looking human / known IP (must asset register first)",command:'# 1. Register first\ndl asset register --group-id=actor-jane --name=jane-headshot \\\n --url=https://.../actor.jpg --asset-type=Image\n# 2. Then call lipsync — the face is in the asset; do NOT also pass --image-url for the same face.\n# Reference the registered face as @asset1 in the prompt.\ndl lipsync --service=seedance-2-0 \\\n --audio-url=https://... \\\n --prompt="@asset1 delivers @audio1 with clear articulation, mouth always visible" \\\n --ark-asset-ids=asset_xxx --reference-subject-type=real_person'}]},{service:"seedance-2-0-fast",label:"Seedance 2.0 Fast Lipsync",tier:"Fast preview",bestFor:"Same needs as seedance-2-0 but faster / cheaper preview",quality:"High",speed:"1-3min",cost:"low-mid",description:["Fast variant of seedance-2-0. Same family, same capability set; slightly lower quality / faster / cheaper."],promptTips:["Same as seedance-2-0: must contain @audio1, do not add camera-motion text"],flagSubset:["service","image-url","audio-url","prompt","ark-asset-ids","reference-subject-type"],constraints:["Same as seedance-2-0 (15s / 480p|720p / real-looking human IP must asset register, asset-only after registration, no --duration)"]},{service:"longcat-avatar",label:"LongCat Avatar",tier:"Long audio + simple",bestFor:"Longer audio + simple parameter setup",quality:"High",speed:"1-3min",cost:"low",description:["LongCat Avatar. Handles longer audio with relatively simple parameters, but resolution control is weaker."],promptTips:["Relatively permissive — 'a person speaking' will run; the LTX-family three-segment template still produces better results"],flagSubset:["service","image-url","audio-url","prompt","resolution","seed"],constraints:["Few resolution options (mainly 480p); no fine-grained width/height control","Do NOT pass --duration; audio_url determines output length"],examples:[{caption:"longcat-avatar simple setup",command:'dl lipsync --service=longcat-avatar \\\n --image-url=https://... --audio-url=https://... \\\n --prompt="a person speaking" --resolution=480p --seed=42'}]}],decisionLogic:[{when:"Default / unsure / new lipsync work",pick:"dlai2v_pro (LTX 2 Pro, preferred default)"},{when:"Need explicit --width / --height / --seed / --quality-preset control",pick:"dlai2v (LTX 2 baseline)"},{when:"Strict lipsync + auto-keyframe + character consistency",pick:"seedance-2-0"},{when:"Same as seedance but want a faster / cheaper preview",pick:"seedance-2-0-fast"},{when:"Longer audio + simple parameters (< control needs)",pick:"longcat-avatar"},{when:"**Real-looking human / known IP input**",pick:"seedance-2-0 + must `dl asset register` first; read docs/seedance_reference_assets.md"}]},preflightTopic:{intro:"Confirm these 5 items before the first dl lipsync call (MV segment workflow adds a 6th):",decisions:[{name:"Service / model",description:"Pick 1 of 5 (dlai2v_pro default / dlai2v / longcat-avatar / seedance-2-0 / seedance-2-0-fast).\nDetermines prompt template shape + flag subset + audio duration cap."},{name:"Driving duration",description:"Whether audio length is within the service cap (dlai2v_pro ≤ 20s / dlai2v ≤ 19s / seedance ≤ 15s).\n`--audio-url` determines the request duration; do not use --duration to control output length.\nIf the intended final segment is shorter than 3s, trim the driving audio upstream or trim padded output afterward;\nlonger than 15-20s MUST be split upstream. **Driving audio is canonical** — do NOT crop / pad /\nstretch / integer-round it to match vendor duration. If the vendor outputs padded video, trim back\nto exact storyboard / audio duration."},{name:"Resolution package",description:"480p / 720p / explicit width-height (depends on service). dlai2v_pro does NOT accept resolution / width / height (fixed dim);\ndlai2v accepts width / height / quality-preset; seedance is limited to 480p / 720p."},{name:"Face / reference plan",description:"Decide the face image source: real-looking human portrait / generated performance still / registered asset bundle.\n**MV segment workflow**: for the LTX family, do NOT use a raw character reference sheet directly;\nuse dl generate-image to produce a segment-specific performance still first —\nfront-facing / mouth clearly visible / matching the segment's scene / lighting / wardrobe / props."},{name:"(seedance only) Real-looking human / known-IP Asset Register",description:"seedance-2-0 / seedance-2-0-fast with real-looking human / known-IP input → MUST `dl asset register` first\nto get an asset_id, reference it via --ark-asset-ids, and use @assetN in the prompt.\nAfter registration, submit the asset only; do not also pass the same media URL.\n**Skipping = upstream policy block or uncontrolled output; do not gamble.**\nRead docs/seedance_reference_assets.md (in this skill's directory) carefully."}],notes:["Cost-sensitive / service / resolution unclear → read pricing-and-policies-dramaland-faq/SKILL.md first","Batch lipsync goes through --jobs-file; do not block per segment. Do NOT flatten nested jobs[].params"]},policyTopic:{intro:"Six categories of hard rules: User-facing isolation / Package gate / LTX prompt template / Seedance @audio1 / URL hygiene / MV duration & still / Fallback ladder.",rules:[{title:"1. User-Facing Communication — never leak internal details",body:["Vendor / pricing / internal model code (LTX-2.3 multi-frame workflow / Seedance 2.0 Pro) /","trace id must NOT surface to the user. User-facing summary only mentions: service alias","(LTX / Seedance / LongCat) + character / duration + action (lip-sync / lip-sync video)."]},{title:"2. Production Package Gate — never call before authorization",body:["service / model / driving duration / resolution / width-height / job count (including batch","segment range) / face / reference plan / audio source plan are all components of the paid","package authorization. Do not call before the package is authorized; once authorized, batch","within the package. Only re-ask on package overflow (service switch / duration change /","resolution change / quantity increment / swap of a key input / fallback / paid regeneration)."]},{title:"3. LTX-family Prompt Template Discipline (dlai2v_pro / dlai2v)",body:["LTX 2 family prompt MUST contain all three segments:"," (1) Subject speaking/singing (explicitly say the character is *speaking* or *singing* with perfect lip sync)"," (2) Character action (head nods / tilts / gaze / hands / shoulders / breathing)"," (3) Camera movement (Dolly in / slow push in / static medium close-up; static must be stated explicitly)","","Append a quality / lighting tail: 'high quality, natural lighting'.","","❌ Bad — 'a person speaking' (too vague; the model improvises)","✅ Good — see the reference template in the dlai2v_pro service profile"]},{title:"4. Seedance @audio1 hard constraint + Real-looking human / IP Asset Register",body:["seedance-2-0 / seedance-2-0-fast prompts MUST contain the @audio1 placeholder","(this verb's preflight hook hard-rejects calls missing @audio1).","","Placeholder rules (all 1-indexed):"," @audioN → audio_url (N=1) / @imageN → image input / @assetN → ark_asset_ids[N-1]","","Real-looking human / known-IP input → MUST `dl asset register` first to get an asset_id, reference","it via --ark-asset-ids, and use @assetN in the prompt. After registration, submit the asset only;","do not also pass the same real-looking human media as image_url. **Skipping = upstream policy block.**"]},{title:"5. URL Hygiene — public HTTPS / never fabricate storage URLs",body:["All media URLs (image_url / audio_url) MUST be real publicly reachable HTTPS URLs. Legitimate sources:"," - dl generate-image / generate-tts / generate-music submit results (GCS storage URLs)"," - URLs uploaded by the user or provided in the conversation"," - URLs returned by platform queries like dl content list","","NEVER fabricate storage URLs / guess domains / invent paths. Need a face image → run dl generate-image first;","need audio → run dl generate-tts or generate-music first."]},{title:"6. MV Segment Duration & Keyframe Boundary",body:["**Driving audio is canonical**: do NOT crop / pad / stretch / integer-round audio to match","vendor duration, and do NOT pass --duration. If the vendor outputs padded video, ffmpeg trim back to the exact","storyboard / audio duration.","","Intended final segment shorter than 3s → request at least the vendor minimum, then trim back;","longer than 15-20s → MUST split upstream — do not feed it all at once.","","LTX family MUST NOT use a raw character design / reference sheet directly as image_url.","Use dl generate-image to produce a segment-specific performance still — front-facing /","mouth clearly visible / matching the segment's scene / lighting / wardrobe / props."]},{title:"7. Fallback Ladder",body:["When this verb produces jitter / mouth drift / gaze drift / character drift / moderation block, in order:","","1. Retry once (transient network / quota jitter usually clears)","2. Swap model: dlai2v_pro ↔ dlai2v / dlai2v_pro → seedance-2-0 (strict lip) /"," seedance-2-0 → seedance-2-0-fast (cheap preview); adjust quality-preset","3. Re-pick the face still: performance still not sharp enough / not front-facing enough →"," regenerate a segment-specific still via image-generation","4. Edit the prompt: LTX-family three segments incomplete → fill in; seedance missing @audio1 → add","5. Split segments: audio too long / model's segment handling capped → split upstream"]}]},compositionTopic:{intro:"This atomic skill only produces a lipsync video URL; artifact / canvas / publish_content downstream responsibilities are not in this verb's scope.",integrations:[{skill:"generate-tts / generate-music (audio source)",rule:["audio_url sources: dl generate-tts (dialogue / narration) or dl generate-music (song / vocal track).","Confirm ownership before feeding raw user-uploaded audio; never fabricate a GCS URL.","Do not use duration to control output length; audio_url determines the requested length."]},{skill:"generate-image (face / performance still source)",rule:["image_url source: dl generate-image producing a segment-specific performance still.","MV segment workflow: do NOT use a raw character design directly as the lipsync image_url;","generate a segment-specific still first (front-facing / mouth clearly visible / matching scene)."]},{skill:"dl asset register (real-looking human / known IP)",rule:["seedance-2-0 / seedance-2-0-fast with real-looking human / known-IP input → MUST run dl asset register","first to get an asset_id, reference it via --ark-asset-ids, and use @assetN in the prompt.","After registration, submit the asset only; do not also pass the same media URL.","See docs/seedance_reference_assets.md (in this skill's directory) for details."]},{skill:"Right-side canvas (pi_media_log)",rule:["The atomic skill no longer performs dl artifact write / patch-json on pi_media_log on its caller's behalf — that is the composition layer's job."]},{skill:"publish_content (final delivery)",rule:["Hand the lipsync output video URL to publish_content with presentation_family='video'","(see the publish subtopic for details)."]}]},asyncTopic:{intro:["dl lipsync returns { job_ref, status: 'pending' } and exits immediately by default — do NOT poll.","The result is injected into the session as [async-callback] job=<ref> text; typical wait is 1-5 minutes.","If the next step must have the result (e.g. immediately feeding ffmpeg) → query separately with","dl poll --job-ref=<ref>; dl subcommands themselves no longer support --wait blocking (removed in #294)."],resultShape:['{ "url": "https://storage.googleapis.com/.../video.mp4", "original_url": "...", "vendor": "..." }',"vendor / original_url / other internal metadata fields MUST NOT be exposed to the user"],notes:["⚠ Do NOT write a bash poll loop (while sleep + dl poll) — forbidden by the agent runtime async rules (#389)","Batch lipsync goes through --jobs-file; each job's completion is pushed back independently via [async-callback]","⚠ The returned URL already lives on our GCS — feed it directly to downstream tools / artifacts; do NOT pass to upload_file."]},publishTopic:{intro:["After producing the lipsync video URL, call publish_content with presentation_family='video' +","explicit media fields. See 'Publishing Your Work / video' in the creation playbook for the full field map."],fields:[{name:"presentation_family",value:"'video'"},{name:"media_urls.video",value:"<lipsync output URL>"},{name:"delivery_format",value:"'video'"}]}})}(Tc),function(e){as(e,{verb:"transcribe",actionName:"transcribe",schema:Go,billing:{schema:wl,select:()=>({}),quote:kl},supportsBatch:!1,description:"Asynchronously transcribe audio to SRT subtitles. Returns {status:'pending', job_ref} immediately; the SRT lands via [async-callback] in a later turn.",notes:["Async by default — submit returns `{status:'pending', job_ref, data:{task_id}}`; do NOT wrap in `nohup ... &` / bash poll loop. End the turn and wait for `[async-callback] job=<ref>` to land.","`--language` accepts `auto` (detect) or any ISO-639-1 code (`en`, `zh`, `ja`, `es`, `fr`, …).","`--transcript-text` skips ASR recognition and aligns the provided text to the audio to produce SRT/timestamps.","`--word-timestamps` controls whether the callback payload includes full `text`/`segments`/`words` in addition to `srt_url`/`srt_content`.","`--model-size` is intentionally not supported; ASR uses the server-side Qwen3 + stable-ts pipeline."],whenToUse:["You have an audio URL and need SRT subtitles (single language or auto-detect)","Music-video phase 01 / shot-by-shot caption work that needs subtitle timing"],whenNotToUse:["You need beat / tempo analysis (use `dl analyze-beats` instead)","You need to download a remote video before transcribing — `dl transcribe` only accepts a public URL"],examples:[{caption:"auto-detect language, return SRT only when callback lands",command:'dl transcribe --audio-url="https://cdn.example.com/voice.mp3" --language=auto'},{caption:"request word timestamps in callback payload",command:'dl transcribe \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --language=en \\\n --word-timestamps'},{caption:"align an existing transcript without ASR recognition",command:'dl transcribe \\\n --audio-url="https://cdn.example.com/song.mp3" \\\n --transcript-text="Known lyric line. Next lyric line." \\\n --language=auto'}],notExamples:[{command:'nohup dl transcribe --audio-url="https://cdn.example.com/voice.mp3" --language=zh > /tmp/asr.json &',whyItFails:"transcribe is async — submit returns immediately and the result arrives as [async-callback] in a later turn. Backgrounding orphans the child when the sandbox is reclaimed and there is no job_ref to poll."},{command:'dl transcribe --audio-url="https://cdn.example.com/voice.mp3" --model-size=large-v3',whyItFails:"`--model-size` is no longer a valid CLI flag; model selection is server-side"},{command:'dl transcribe --params=\'{"audio_url":"...","language":"auto"}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"},{command:"dl transcribe --audio-url=face.mp3",whyItFails:"audio_url must be a fully-qualified public URL; raises E_BACKEND"}],outputSingle:'{"ok":true,"status":"pending","job_ref":"<uuid>","data":{"task_id":"ag:asr:qwen3-asr:<id>","status":"pending"}}',transformResult:Oc,preflightTopic:{intro:"Confirm these 4 items before the first dl transcribe call:",decisions:[{name:"Audio URL is publicly reachable",description:"audio_url must be a publicly accessible URL (or platform-internal storage URL).\nFor private buckets (GCS / S3) sign the URL first. Local file paths / data: URIs are rejected."},{name:"Language hint",description:"--language=auto (default) works for most content; explicitly write the\nISO-639-1 code (en / zh / ja / es / fr) when the language is known — improves\nASR accuracy and speed."},{name:"Callback payload mode (pick one)",description:'Default callback payload: srt_content + srt_url only (token-thrifty, fits direct caption rendering).\n--word-timestamps: callback also includes text + segments + words (word-level timing,\n for MV beat alignment / lip-sync / by-word fine cut).\n--transcript-text="...": skips ASR recognition; ASR vendor only time-aligns the given text\n to the audio (use for user-supplied lyrics / pre-edited transcripts / alignment-after-other-ASR).'},{name:"Tuning (optional)",description:"--vad-filter: enables stable-ts VAD for cleaner segment splitting.\n--denoise-audio: ASR defaults to true (Demucs denoising / vocal separation); make explicit if you want.\n--max-segment-duration=5: readable upper bound per caption line in seconds; 5 is usually enough."}],notes:["Async by default — submit returns `{status:'pending', job_ref, data:{task_id}}` immediately; end the turn and wait for `[async-callback] job=<ref>`. See `dl transcribe async -h`.","Do NOT pass --model-size — it's not a valid CLI flag (server-side picks the pipeline)","Server-side budget is ~590s per identification (cold-start GPU + long denoised audio can hit this); pre-split very long audio if a single segment risks this limit"]},policyTopic:{intro:"Four hard rules: User-facing isolation / Package gate / Default callback trim / Server-side model selection.",rules:[{title:"1. User-Facing Communication — never leak internal details",body:["Vendor / internal pipeline (Qwen3-ASR / stable-ts / DTW) / trace id must NOT","surface to the end user. User-facing summary only mentions: action (transcribe /","caption / time-align) + language + duration."]},{title:"2. Production Package Gate — never call before authorization",body:["Audio source / target language / word-level need / downstream usage (caption render","vs beat sync vs alignment of known text) are all components of the paid production","package authorization. Do not call before the package is authorized; once authorized,","batch within the package by parallel `dl transcribe` calls (no `--jobs-file`; api-layer","already fan-outs jobs server-side). Only re-ask on package overflow (language switch /","adding word-level / adding text alignment / fallback / paid regeneration).","","Cost reference: 50 platform tokens / transcription, ~590s server-side ASR budget per identification."]},{title:"3. Default Callback Trim — word-timestamps controls the callback payload, not the CLI response",body:["The CLI `dl transcribe` response is always the submit acknowledgement:","`{ok:true, status:'pending', job_ref, data:{task_id}}`. The SRT lives in the","`[async-callback]` payload that lands in a later turn.","","By default the callback payload's `result` carries srt_content + srt_url only.","The text / segments / words fields are **intentionally dropped** from the callback","payload to save tokens. Only pass --word-timestamps when the caller explicitly","needs word-level timing (MV beat sync / lip-sync alignment / by-word fine cut).","Phase 01 storyboards typically need default SRT only; downstream caption renderers","(create-subtitles) also consume srt_content / srt_url directly."]},{title:"4. Server-side Model Selection — --model-size is NOT exposed",body:["The ASR pipeline is server-selected (Qwen3-ASR for text + stable-ts for","timestamps + DTW fallback for alignment). There is no --model-size CLI flag.","Passing it raises E_UNKNOWN_OPTION."]}]},compositionTopic:{intro:"transcribe is an atomic skill — it only produces SRT + optional word-level timing. Downstream caption rendering / beat cutting / alignment publishing are NOT this verb's responsibility.",integrations:[{skill:"create-subtitles (caption rendering)",rule:["The create-subtitles SOP consumes transcribe's callback `result.srt_url` / `srt_content`,","then runs dl render-caption / ffmpeg to burn subtitles. transcribe only","emits the SRT — styling / fonts / burn-in are not its job."]},{skill:"lipsync / hyperframes-cli (lip alignment / beat-driven animation)",rule:["Beat-driven animation / lip alignment workflow: transcribe --word-timestamps →","feed callback `result.words[]` to hyperframes-cli for beat anchoring, or feed","`result.segments[]` to dl lipsync as a prompt condition. These workflows explicitly","need word-level timing, so set --word-timestamps; default trimming drops these","fields from the callback payload."]},{skill:"publish_content (delivering the SRT file to the user)",rule:["If the final deliverable is a .srt file (no further downstream rendering),","go through publish_content's subtitle / transcript slot; see the publish-related","skill for details."]},{skill:"create-complex-music-video-from-music (audio_analysis artifact slot)",rule:["Persist post-fallback transcript to the `audio_analysis` slot via read-modify-write:","`dl artifact read` → set `transcription.text` / `srt_content` / `language` / `segments[]`","(preserve existing `beats` / `track`) → `dl artifact write --contract='<ARTIFACT_CONTRACT_PATH>'`.","Two separate Bash calls. Full procedure: skills/audio-transcription/SKILL.md."]}]},asyncTopic:{intro:["dl transcribe is async via the api-layer task queue (#395). Submit returns","`{ok:true, status:'pending', job_ref, data:{task_id}}` immediately and exits — **do NOT poll**.","The transcription result arrives later as `[async-callback] job=<ref>` user message that","re-enters the session in a new turn.","","End the turn after submit. Do NOT wrap the call in `nohup ... &`, do NOT poll in a","`sleep`/`for`/`while` loop, and do NOT call `dl poll` proactively — see customPrompt §9","for the async detach rules that govern all submit-style verbs."],resultShape:['// Callback payload\'s "result" object (default — srt only)','{ "success": true, "language": "en", "duration": 12.408,',' "srt_content": "1\\n00:00:00,000 --\x3e 00:00:02,500\\nFirst segment of speech.\\n",',' "srt_url": "https://storage.googleapis.com/dramaland-public/asr/srt/<date>/<hash>.srt",',' "alignment_method_used": "stable-ts", "alignment_quality": "high" }','// alignment_quality ∈ "high" | "medium" | "low" or absent — only "high" trustworthy (see Quality fallback note).',"",'// With --word-timestamps, the callback "result" also includes:','{ "text": "...", "segments": [{"id":0,"start":0.0,"end":2.5,"text":"..."}],',' "words": [{"word":"First","start":0.0,"end":0.4,"probability":0.98}] }'],notes:["⚠ Do NOT write a bash poll loop (while sleep + dl poll) — agent runtime async rules forbid it (#389)","Lost-callback escape hatch: if significantly more than the expected window (~5-60s short / longer for cold-start GPU / multi-minute audio) passes without `[async-callback]` landing, you may do exactly ONE single-shot `dl poll --job-ref=<ref>` — never in a loop. See customPrompt §9.","Batch fan-out: api-layer queues each transcribe submit independently — for multiple audios call `dl transcribe` in parallel; do NOT use `--jobs-file` (supportsBatch is false on this verb).","Quality fallback: when `result.alignment_quality` is `low` / `medium` / missing, word-level timing is unreliable. Call the built-in `understand_media` tool on the same audio to recover a clean transcript, then resubmit `dl transcribe --audio-url=<same> --transcript-text=<clean> --word-timestamps=true` to time-align via DTW. The second callback supersedes the first — do not mix segments across the two. Full procedure: skills/audio-transcription/SKILL.md → 'Low alignment_quality → understand_media fallback'."]},publishTopic:{intro:["transcribe atomic does NOT call publish_content directly. Its outputs","srt_content / srt_url usually feed downstream caption renderers","(create-subtitles / hyperframes-cli).","If the final deliverable is the SRT itself, map publish_content fields as:"],fields:[{name:"presentation_family",value:"'document' or 'caption-bundle' (per publish_content schema)"},{name:"media_urls.subtitle",value:"<srt_url>"},{name:"delivery_format",value:"'srt'"}]}})}(Tc),function(e){as(e,{verb:"generate-image",actionName:"generate_image",schema:zo,billing:{schema:Us,select:e=>({service:e.service}),quote:Ds},supportsBatch:!0,description:"Generate a still image from a text prompt (optionally edit one via --img-url / image-to-image).",notes:["`--img-url` (repeatable) is the canonical i2i input; `--image-urls` is its array-form alias.","`--image` is a legacy alias for `--img-url` — prefer `--img-url` in new calls."],whenToUse:["You need a still image from a text prompt","You need to edit an existing image (i2i) — pass `--img-url` (repeatable) or `--image-urls`","Multi-aspect-ratio fan-out (run the same prompt across aspect ratios via --jobs-file)"],whenNotToUse:["You need a video — use `dl generate-video`","You need style-reference search before generating — use `dl knowledge search --domain=visual_style` first"],examples:[{caption:"single, banana-2 (newest in banana family, faster + better)",command:'dl generate-image \\\n --service=banana-2 \\\n --prompt="a corgi astronaut floating above earth, cinematic light" \\\n --aspect-ratio=16:9 \\\n --image-size=2K'},{caption:"i2i with multiple reference images",command:'dl generate-image \\\n --service=gpt-image-2 \\\n --prompt="merge: subject from img1 in the setting of img2" \\\n --img-url="https://1.png" \\\n --img-url="https://2.png"'},{caption:"batch via stdin",command:'cat <<EOF | dl generate-image --jobs-file=-\n[\n {"job_key":"keyframe_01","service":"banana-2","prompt":"opening shot, dawn","aspect_ratio":"16:9"},\n {"job_key":"keyframe_02","service":"banana-2","prompt":"crescendo, fireworks","aspect_ratio":"16:9"}\n]\nEOF'}],notExamples:[{command:'dl generate-image --params=\'{"service":"banana-pro"}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"url":"https://storage.../image.png","width":1920,"height":1080}}',outputBatch:'{"ok":true,"action":"generate_image","results":[\n {"job_key":"keyframe_01","job_ref":"<uuid>","status":"pending"},\n ...\n]} // batch is non-blocking; each completed job is pushed back to the session via [async-callback]',modelTopic:{rankingSummary:["Overall quality ranking (strongest to weakest): gpt-image-2 > banana-2 > banana-pro > seedream-5-lte / seedream.",'Higher rank does NOT mean "better in every scenario" — it means "stronger on the combined axes of','photorealism + text rendering + instruction following + multi-image composition". For specific scenarios pick by the SERVICES table + DECISION LOGIC below.',"Service-name ↔ model-name mapping: banana-pro = nano-banana-pro (Imagen3 series, older / cheaper / slower), banana-2 = nano-banana-2 (Imagen4 4K, newest generation — materially faster AND higher quality than banana-pro; default first choice within the banana family)."],services:[{service:"gpt-image-2",label:"OpenAI GPT-Image-2",tier:"🥇 #1 Overall strongest",bestFor:"Overall strongest. The only reliable choice for precise text rendering, the only instruction-driven editor, and the only multi-image compositor (up to 16 reference images). Expensive and slow — use only when these exclusive capabilities are needed",quality:"Very High",speed:"10s-2min",cost:"high",description:["OpenAI GPT-Image-2 is exposed through the api-layer. Overall quality is strongest + 3 exclusive capabilities (","text rendering / instruction edit / multi-image composition, up to 16 refs).","The api-layer auto-routes to the backend that precisely honors the passed field: passing","`aspect_ratio` routes to a backend that natively honors `aspect_ratio`; passing a `size` pixel string","(`1024*1536`) triggers a backend that precisely honors `size`. Callers do not pick the vendor manually."],promptTips:['To render text you must use quotes: `the word "HELLO" in chrome letters` — this is one of the few models that can render text reliably','For edits, use the "keep X, change Y" framing rather than just describing the target','For multi-image composition, number them in prose: "the subject in image 1", "the background in image 2"',"Prefer full natural-language descriptions, not keyword soup","When using a `search-visual-style` hit as style ref: take the `prompt_gpt` field (gpt-image-2 specific variant), not `prompt` — `prompt` is for other services (banana / seedream etc.)."],constraints:["Expensive + slow (10s-2min); only use when you need the 3 exclusive capabilities","At most 16 reference images (via --image-urls)"],flagSubset:["service","prompt","img-url","image-urls","aspect-ratio","size","nsfw-checker"],examples:[{caption:"text-in-image",command:"dl generate-image --service=gpt-image-2 \\\n --prompt='A minimalist poster: the bold word \"KAIROS\" centered, off-white paper background, subtle grain, Helvetica Bold'"},{caption:"multi-image edit",command:'dl generate-image --service=gpt-image-2 \\\n --prompt="Place the product from image 1 onto the desk in image 2, match the lighting of image 2" \\\n --image-urls=https://.../product.jpg \\\n --image-urls=https://.../scene.jpg'}]},{service:"banana-2",label:"Imagen4 4K (nano-banana-2) — newest, faster + stronger than banana-pro",tier:"🥈 #2",bestFor:"Overall quality runner-up to gpt-image-2 AND faster + higher quality than banana-pro. Imagen4 4K (nano-banana-2), the newest generation in the banana family. Default first choice within the banana family unless explicit cost-saving",quality:"Very High",speed:"10-60s (materially faster than banana-pro)",cost:"high",description:["Google Imagen4 4K family (nano-banana-2). The newest banana generation: BOTH faster AND clearly stronger overall","quality than banana-pro (Imagen3). Cost is higher than banana-pro but typically worth it given the speed + quality","win. Use this as the default within the banana family; drop to banana-pro only when cost-saving is explicit."],flagSubset:["service","prompt","aspect-ratio","image-size","img-url"],examples:[{caption:"single, banana-2 (newest, faster + better)",command:'dl generate-image --service=banana-2 \\\n --prompt="cinematic photo: a mountaineer at dawn on a glacier, ultra-detailed" \\\n --aspect-ratio=3:4 \\\n --image-size=2K'}]},{service:"banana-pro",label:"Imagen3 2K (nano-banana-pro) — older, cheaper, slower",tier:"🥉 #3",bestFor:"Imagen3 family (nano-banana-pro), up to 2K. One generation OLDER than banana-2: cheaper but slower and lower quality. Drop to this tier only when cost-saving is explicit",quality:"High",speed:"30s-3min (slower than banana-2)",cost:"low",description:["Google Imagen3 family (nano-banana-pro). The cheap-and-slow version of banana-2 — one generation older,","both slower and one quality tier below. Pick it only when cost-saving is explicit; banana-2 is the default","banana choice otherwise."],flagSubset:["service","prompt","aspect-ratio","image-size","img-url"],examples:[{caption:"single, banana-pro (cost-saving fallback)",command:'dl generate-image --service=banana-pro \\\n --prompt="a corgi astronaut floating above earth, cinematic light" \\\n --aspect-ratio=16:9 \\\n --image-size=2K'}]},{service:"seedream-5-lte",label:"ByteDance Seedream 5.0",tier:"4",bestFor:"Below the 3 overall tiers above. ByteDance Seedream 5.0, fast (10-30s), usable for general scenarios but overall not as strong as the banana family",quality:"Very High",speed:"10-30s",cost:"low",description:["ByteDance Seedream 5.0. Fast and cheap, overall below the banana family but renders in 10-30s."],flagSubset:["service","prompt","model","size","image"],examples:[{caption:"single, seedream-5-lte",command:'dl generate-image --service=seedream-5-lte \\\n --prompt="风格化插画:一只穿越赛博朋克城市的猫" \\\n --size=1:1'}]},{service:"seedream",label:"Seedream 4.5",tier:"5",bestFor:"Weakest overall tier. Seedream 4.5 — historically strong on Asian aesthetic / Asian-face portraits / marketing imagery, but overall quality is below the four above",quality:"High",speed:"10-30s",cost:"low",description:["ByteDance Seedream 4.5. Historically strong on Asian aesthetic / Asian-face portraits / Chinese marketing imagery;","overall quality is below the top 4 tiers but performs more reliably in these specialized scenarios."],flagSubset:["service","prompt","model","size","image"],examples:[{caption:"single, seedream",command:'dl generate-image --service=seedream \\\n --prompt="温暖光感的亚洲女性肖像,中景,白底" \\\n --model=seedream-4-5-251128 \\\n --size=3:4'}]}],decisionLogic:[{when:"No special user requirements / default case",pick:"gpt-image-2 (overall strongest, first choice)"},{when:"gpt-image-2 is too expensive / too slow and you don't need its exclusive capabilities",pick:"banana-2 (overall runner-up, Imagen4 4K / nano-banana-2, newest banana generation)"},{when:"Must render text — logo / tagline / UI text",pick:"gpt-image-2 (exclusively reliable)"},{when:'Must do instruction-driven edits ("keep the person, swap background to...")',pick:"gpt-image-2 (exclusive)"},{when:"Must do multi-image composition (place an object from image A into the scene of image B)",pick:"gpt-image-2 (exclusive, 16 refs)"},{when:"Explicit 4K / high-resolution / strong photorealism need, and no need for gpt-image-2 exclusives",pick:"banana-2"},{when:"Explicit cost-saving / general scenario can accept one generation lower",pick:"banana-pro (cheap version, Imagen3 2K / nano-banana-pro)"},{when:"Specialized Asian-face portraits / Chinese marketing imagery",pick:"seedream (historical strength)"},{when:"Need a fast preview (10-30s)",pick:"seedream-5-lte or seedream"}]},preflightTopic:{intro:"Before the first `dl generate-image` call, the following four decisions must be explicit (for the per-service flag shape see `dl generate-image model <service>` — positional; `model -h <service>` short-circuits to the overview):",decisions:[{name:"Service / model family",description:"Which service to use. Decide per the SERVICES table + DECISION LOGIC in `dl generate-image model -h` (overview), or `dl generate-image model <service>` (per-service profile)."},{name:"Aspect ratio / size dimension",description:"Ratio / pixel string / resolution tier use different fields across services (the FLAG SUBSET in `dl generate-image model <service>`\nexposes them explicitly); you only need to decide the target ratio + target resolution tier, leave the field mapping to --help."},{name:"Reference-input plan",description:"Whether reference images are needed, which URLs go in, and whether you need multi-reference / instruction-driven\nedit / multi-image composition (only the latter two are reliable on gpt-image-2)."},{name:"Cost / count plan",description:"Single image or batch, batch cap."}],notes:["If cost-sensitive or unsure about service choice, read `pricing-and-policies-dramaland-faq/SKILL.md` before locking the package","Do not submit until all four decisions are explicit — switching service later will trigger production-package re-authorization"]},policyTopic:{intro:"Two classes of hard rules: external communication must not leak internal details (rule 1 below); paid package must be authorized before submit (rule 2 below).",rules:[{title:"1. ⚠ User-Facing Communication Rule — do not leak internal details",body:["Never surface internal infrastructure details to the end user:"," - any vendor / backend internal name"," - any USD / RMB price figure"," - any internal model code name (e.g. `nano-banana-pro`, `seedream-4-5-251128`)"," - any internal trace identifier: job_id / task_id / request_id /"," prompt_id / raw_task_id / or any other UUID / hex-form ID string"," (these are for debug, appear in the raw JSON returned by dl CLI; do not repeat them to the user)","","Applies to: `confirm` / `cost_confirm` cards / chat narration / progress","messages / any user-visible string.","","When confirming a generation with the user, summarize **only**:"," - the service name (e.g. banana-pro, banana-2, gpt-image-2, seedream)"," - the user-meaningful constraint the user actually asked for"," (aspect ratio, count, edit vs. new, etc.)",' - the action ("Generate", "Edit")',"","✅ Good:",' - "确认生成一张 9:16 比例的图片(GPT-Image-2)?"',' - "Confirm: generate 1 image at 9:16 with gpt-image-2?"',"","❌ Bad (leaks internal info):",' - "将使用 GPT-Image-2 + Wavespeed 供应商,预计约 $0.10/张,确认开始生成吗?"',' - "Will route via internal_vendor_name (~$0.10), confirm?"',"","Cost / pricing belongs to the platform's billing UI and the","`pricing-and-policies-dramaland-faq` skill; the chat agent does not quote raw price","figures or vendor-internal names in operational confirmation flows."]},{title:"2. Production Package Gate — do not call before paid authorization",body:["This verb's service / model family, aspect ratio / size, generation count (including","batch range), and reference image plan are all components of the system-prompt-level",'"paid media-production package authorization". Do not call `dl generate-image` before that',"authorization is complete.","","Within the same authorized package you can batch-generate — do not block per-image.","Only re-ask when the package overflows (switching service, changing size / ratio, increasing count,","switching cost tier, fallback, or paid regeneration)."]}]},compositionTopic:{intro:"This atomic skill only produces URLs; artifact / canvas registration and other downstream responsibilities are not this verb's job.",integrations:[{skill:"music-video reference-pack workflow",rule:["Keep every returned candidate URL in the upstream","`reference_list.ref_img_urls` array and choose `selected_url`","explicitly instead of discarding alternates."]},{skill:"full-song MV segment production",rule:["Image generation may also be used for segment-specific lip-sync","keyframe stills. Those stills should combine the segment's selected","character, location, and prop references into a front-facing","performance image that can drive lip-sync.","","Preserve the returned URLs in the downstream segment metadata or","generation notes so the lip-sync input can be audited. When a","composition workflow requires these stills, generate them before","the lip-sync call; do not let the raw character reference sheet","become the final lip-sync input."]},{skill:"right-side canvas (pi_media_log)",rule:["The atomic skill no longer performs `dl artifact write` or `patch-json pi_media_log` on your behalf —","that is the composition layer's job. The upstream workflow (visual-production / music-video","composition) is responsible for placing the returned URL into its own artifact slot","(`reference_list.ref_img_urls` / `storyboard.references` etc.)."]}]},asyncTopic:{intro:['`dl generate-image` by default returns `{ job_ref, status: "pending" }` and exits immediately — do not poll.',"Results are injected into the current session as `[async-callback] job=<ref>` text; during that window you can make","other tool calls, or simply end the turn and let the session sit idle until the callback arrives.","",'Only run `dl poll` separately when "the next step strictly requires the result"; the dl subcommand itself no longer supports',"`--wait` blocking."],resultShape:['{ "url": "https://storage.googleapis.com/.../image.png" }'],notes:["The URL field is the atomic skill's sole product handed up to the upper layer","The upstream workflow is responsible for placing this URL into its own artifact slot; the atomic skill no longer registers canvas on your behalf","⚠ This URL already lives on our GCS — feed it directly to downstream tools / artifacts; do NOT pass to upload_file (would re-host an identical blob under a different URL)."]},publishTopic:{intro:["After producing your image URL(s), call `publish_content` with","`presentation_family='text_image'` and the explicit media fields.",'See "Publishing Your Work / text_image" in your creation playbook for',"the full field mapping template."],fields:[{name:"presentation_family",value:"'text_image'"},{name:"media_urls.images[]",value:"<returned image URLs (preserve all candidates)>"},{name:"thumbnail_url",value:"media_urls.images[0]"},{name:"delivery_format",value:"'image'"},{name:"experience_format",value:"'passive_media'"}]}})}(Tc),function(e){as(e,{verb:"generate-video",actionName:"generate_video",schema:qo,supportsBatch:!0,billing:{schema:Gs,select:e=>({service:e.service,duration:e.duration,resolution:e.resolution}),quote:Zs},description:"Generate a short video clip from a text prompt (optionally seeded with reference images / audio).",notes:["Prompt placeholders are 1-indexed and get substituted at submit time:"," @imageN → image_urls[N-1] @audioN → reference_audio_url"," @videoN → ref_video_url @assetN → ark_asset_ids[N-1]","","--prompt supports loading from a JSON file:"," --prompt=@file:/abs/path.json#/json/pointer"," When prefixed with @file:, extract a string per RFC 6901 JSON Pointer as the prompt.","","--refs-from bulk-binds reference assets from a JSON file such as a storyboard:"," --refs-from=@file:/abs/storyboard.json#/segments/0/references"," The pointer must point at a [{element_id, url}, ...] array; element_id routes by prefix:"," image* → image_urls, asset* → ark_asset_ids,"," audio* → reference_audio_url, video* → ref_video_url.","If Seedance audio output is moderation-blocked, retry with prompt text like 'no BGM' / 'no background music'; do not pass --generate-audio.","","FEEDBACK-BASED GUARDRAILS — avoid the common expensive failures:"," 1. Short continuous video → prefer one Seedance clip; do NOT split only because the prompt has multiple visual beats."," 2. Identity-critical work (real face / selfie / actor / artist / fixed character) → choose a reference-consistent model first; weak reference-following models can produce random people."," 3. Real-looking human / known-IP with Seedance 2.0 → register assets first, then reference @assetN; do not rely on raw image URLs."," 4. Before submitting a segment, check whether a successful or pending job already exists; never resubmit unless the user explicitly asks for regeneration."," 5. For multi-segment lip-sync workflows, use dl lipsync and prove one representative clip before committing a large batch."," 6. Fallback is allowed, but non-Seedance models need role-locked frames/keyframes first; do not pass --ark-asset-ids or @assetN to Veo/Grok/Kling.","","⚠ SEEDANCE 2.0 ASSET RULES (seedance-2-0 / seedance-2-0-fast) — read before composing the call:"," 1. Real-person / known-IP image input MUST go through `dl asset register` first;"," passing a raw real-person URL via --image-url / --image-urls is blocked by upstream policy."," 2. Once an image is registered as an asset, reference it ONLY via --ark-asset-ids + @assetN"," in the prompt. Do NOT also pass that same image through --image-url / --image-urls —"," the two channels are mutually exclusive for the same image; double-passing wastes a ref"," slot and produces unpredictable routing on the vendor side."," 3. Set --reference-subject-type=real_person on real-person asset calls."," 4. --image-urls is reserved for non-registered scene / prop refs that are NOT real people."," Full constraint list: `dl generate-video model seedance-2-0` (or `model seedance-2-0-fast`)."],whenToUse:["You need a short clip (2–10s) from a prompt","You need image-to-video (i2v) using the @imageN placeholders","Multi-segment storyboards with discrete scenes: split intentionally and fan out via --jobs-file"],whenNotToUse:["You need lip-sync — use `dl lipsync`","You need motion transfer between two videos — use `dl motion-control`","You need still images — use `dl generate-image`"],examples:[{caption:"single, seedance-2-0",command:'dl generate-video \\\n --service=seedance-2-0 \\\n --prompt="a corgi astronaut floating, slow zoom in" \\\n --duration=5 \\\n --resolution=720p'},{caption:"i2v with reference frame",command:'dl generate-video \\\n --service=dli2v3 \\\n --prompt="@image1 starts moving forward into the snow" \\\n --image-urls="https://1.png" \\\n --duration=4'},{caption:"prompt + references from storyboard JSON",command:'dl generate-video \\\n --service=seedance-2-0 \\\n --prompt="@file:/abs/storyboard.json#/segments/0/detail/prompt" \\\n --refs-from="@file:/abs/storyboard.json#/segments/0/references" \\\n --duration=10 --resolution=720p'}],notExamples:[{command:'dl generate-video --params=\'{"service":"seedance-2-0","prompt":"..."}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"url":"https://storage.../video.mp4","duration_ms":5000}}',outputBatch:'{"ok":true,"action":"generate_video","results":[\n {"job_key":"scene_01","job_ref":"<uuid>","status":"pending"},\n ...\n]} // batch is non-blocking; each completed job is pushed back to the session via [async-callback]',extraFlags:[{spec:"--refs-from <ref>",description:"Bulk-bind reference assets: @file:PATH#POINTER, pointer must point at a [{element_id, url}, ...] array"}],transformParams:(e,t)=>{let i=e;if(Ya(i.prompt)){const e=Ga(i.prompt,{flag:"--prompt",requireString:!0});i={...i,prompt:e}}if("single"===t.mode){const e=t.opts?.refsFrom;"string"==typeof e&&""!==e&&(i=function(e,t){const i={...e};if(t.image_urls.length>0){const e=Nl(i.image_urls);i.image_urls=jl([...t.image_urls,...e])}if(t.ark_asset_ids.length>0){const e=Nl(i.ark_asset_ids);i.ark_asset_ids=jl([...t.ark_asset_ids,...e])}return t.reference_audio_url&&void 0===i.reference_audio_url&&(i.reference_audio_url=t.reference_audio_url),t.ref_video_url&&void 0===i.ref_video_url&&(i.ref_video_url=t.ref_video_url),i}(i,function(e){if(!Ya(e))throw new Yr("E_SCHEMA",`${$l} 仅支持 @file:PATH#POINTER 语法,收到:${e}`,"示例:--refs-from=@file:/abs/storyboard.json#/segments/0/references",{flag:$l});const t=Ga(e,{flag:$l});if(!Array.isArray(t))throw new Yr("E_SCHEMA",`${$l} JSON Pointer 命中的不是数组(实际类型:${typeof t})`,"references 应该是 [{element_id, url}, ...] 形式",{flag:$l});return function(e){const t={image_urls:[],ark_asset_ids:[]},i=[],n=[],o=[],r=[];if(e.forEach((e,t)=>{if(!e||"object"!=typeof e)throw new Yr("E_SCHEMA",`${$l} references[${t}] 不是对象(实际:${null===e?"null":typeof e})`,void 0,{flag:$l});const a=e,s=a.element_id,l=a.url;if("string"!=typeof s||""===s)throw new Yr("E_SCHEMA",`${$l} references[${t}].element_id 缺失或不是非空字符串`,void 0,{flag:$l});if("string"!=typeof l||""===l)throw new Yr("E_SCHEMA",`${$l} references[${t}].url 缺失或不是非空字符串(element_id=${s})`,void 0,{flag:$l});const c=/^([a-z]+)(\d*)$/i.exec(s);if(!c)throw new Yr("E_SCHEMA",`${$l} references[${t}].element_id 不符合 <prefix><N?> 规范:${s}`,"形如 image1 / asset2 / audio1 / video1",{flag:$l});const d=c[1].toLowerCase(),u=c[2],p=""===u?0:Number(u);switch(d){case"image":o.push({n:p,id:s,url:l});break;case"asset":r.push({n:p,id:s,url:l});break;case"audio":i.push({id:s,url:l});break;case"video":n.push({id:s,url:l});break;default:throw new Yr("E_SCHEMA",`${$l} 未知的 element_id 前缀:${s}`,"支持:image / asset / audio / video(后缀数字可选,作为排序)",{flag:$l})}}),i.length>1)throw new Yr("E_SCHEMA",`${$l} 最多只能有一个 audio* 引用(实际 ${i.length}:${i.map(e=>e.id).join(", ")})`,void 0,{flag:$l});if(n.length>1)throw new Yr("E_SCHEMA",`${$l} 最多只能有一个 video* 引用(实际 ${n.length}:${n.map(e=>e.id).join(", ")})`,void 0,{flag:$l});return o.sort((e,t)=>e.n-t.n),r.sort((e,t)=>e.n-t.n),t.image_urls=o.map(e=>e.url),t.ark_asset_ids=r.map(e=>e.url),i[0]&&(t.reference_audio_url=i[0].url),n[0]&&(t.ref_video_url=n[0].url),t}(t)}(e)))}return i},preflight:e=>{const t=String(e.service??"");if(function(e,t){if(function(e){return"seedance-2-0"===e||"seedance-2-0-fast"===e}(t))return;const i=Array.isArray(e.ark_asset_ids)&&e.ark_asset_ids.length>0,n="string"==typeof e.prompt?e.prompt:"",o=/@asset\d+\b/.test(n);if(i||o)throw new Yr("E_SCHEMA",`Seedance asset references require --service=seedance-2-0 or --service=seedance-2-0-fast, not ${t}`,"Fallback is allowed, but rebuild the segment for the target model first: generate role-locked frame/keyframe images from the character reference, then pass those frames through --image-url / --image-urls / --keyframes as supported by that model. Do not pass --ark-asset-ids or @assetN to non-Seedance services.",{verb:"generate-video",service:t,expected:"seedance-2-0|seedance-2-0-fast",flag:i?"--ark-asset-ids":"--prompt"})}(e,t),"dlai2v_pro"!==t&&"dlai2v_pro_multiframe"!==t)return;const i="string"==typeof e.image_url&&""!==e.image_url,n=Array.isArray(e.keyframes)&&e.keyframes.length>0;if("string"!=typeof e.audio_url||""===e.audio_url)throw new Yr("E_SCHEMA",`--audio-url is required for ${t} (the LTX 2.3 workflow derives video length from the driving audio)`,"pass --audio-url=<driving audio>; output length follows the audio. Do NOT use --duration to control length (billing-only here)",{verb:"generate-video",service:t});if(!i&&!n)throw new Yr("E_SCHEMA",`either --image-url or --keyframes is required for ${t}`,"provide a face/scene still via --image-url, or multiple keyframes via --keyframes",{verb:"generate-video",service:t});if(i&&n)throw new Yr("E_SCHEMA","--image-url and --keyframes are mutually exclusive","use --image-url for a single still (api-layer wraps it into keyframes[0]), or --keyframes for explicit multi-frame guidance; not both",{verb:"generate-video",service:t});if("dlai2v_pro_multiframe"===t){if(!n)throw new Yr("E_SCHEMA","dlai2v_pro_multiframe requires --keyframes (2-4 frames); --image-url alone is not supported","pass 2-4 --keyframes flags; if you only have 1 image, use --service=dlai2v_pro instead",{verb:"generate-video",service:t});const i=e.keyframes.length;if(i<2||i>4)throw new Yr("E_SCHEMA",`dlai2v_pro_multiframe requires 2-4 keyframes, got ${i}`,"adjust to 2/3/4 keyframes; api-layer routes to mutiframe_{2f,3f,4f} workflow by count",{flag:"--keyframes",verb:"generate-video",service:t})}else if(n&&e.keyframes.length>5)throw new Yr("E_SCHEMA",`--keyframes accepts 1-5 frames for dlai2v_pro, got ${e.keyframes.length}`,"reduce to at most 5 keyframe images, or switch to --service=dlai2v_pro_multiframe (2-4 frames)",{flag:"--keyframes",verb:"generate-video",service:t})},modelTopic:{rankingSummary:["Overall quality tiers (strongest to weakest):"," 🥇 Top tier: seedance-2-0 family (Pro + Fast)"," 🥈 Runner-up tier: happyhorse-1-0-* family (r2v / i2v / video-edit)"," 🥈 Unique-capability tier: kling-o3-pro-v2v / kling-o3-v2v (video-to-video editing — Kling-side alternative to happyhorse-1-0-video-edit)"," 🥉 Third tier: rest of kling-o3-* family (ref2v Pro / std) + kling3.0"," Below that: dli2v3 / dlim2v / seedance-1-5","","This ranking is overall quality (character consistency / camera stability / physical plausibility / duration cap);","it does NOT mean you should always pick the top tier — special scenarios (video edit / Chinese prompt /","multi-ref) have exclusive capabilities per family.","","Note: seedance-2-0-fast is the Fast variant of the same generation/family with the same capability set (auto-keyframe /","multi-ref / audio coupling / video ref continuation), just slightly lower quality / faster / cheaper. Do not treat","fast as a lower tier — use it as the baseline when the default scenario has no special requirements.","","Separate category — audio-driven talking / singing video (lip-synced, output length = driving audio, --audio-url REQUIRED):"," dlai2v_pro (single still or 1-5 keyframes) / dlai2v_pro_multiframe (2-4 keyframes, richer movement)"," — same LTX-2.3 engine as the matching `dl lipsync` services; use whichever verb your pipeline composes through."," longcat-avatar-1-5 (self-hosted; very stable lip-sync but slow ~8-10min)."," These are NOT ranked against the t2v/i2v tiers above — they solve a different problem."],services:[{service:"seedance-2-0",label:"Seedance 2.0 Pro",tier:"🥇 Top tier (Pro)",bestFor:"Overall strongest quality. Character consistency + auto-keyframe + video ref / continuation + audio-coupled generation — the fullest feature set. Expensive and requires asset register (for real-looking human / IP scenarios you must first call dl asset register)",quality:"Very High",speed:"2-5min",cost:"high",description:["ByteDance Seedance 2.0 Pro. Currently strongest overall quality, fullest capability set:"," - auto-keyframe (auto-generates multiple keyframes)"," - multi-reference images (image_urls)"," - video ref / continuation (ref_video_url)"," - audio coupling (reference_audio_url + @audio1)"," - duration <=15s or -1 for auto"," - resolution 480p / 720p (1080p not supported)"],promptTips:["Placeholders are 1-indexed: @imageN → image_urls[N-1] / @audioN → reference_audio_url / @videoN → ref_video_url / @assetN → ark_asset_ids[N-1]","For audio + image lip-sync scenarios use dl lipsync — do not force-fit them into generate-video","reference_audio_url must be ≤15s and cannot be the only reference on its own (must be paired with image_urls or ref_video_url)"],constraints:["Real-looking human / known-IP inputs must be passed through dl asset register first; after registration pass that source ref via --ark-asset-ids + @assetN only, never again via --image-urls + @imageN","If generated/output audio triggers moderation, retry with prompt text such as 'no BGM' / 'no background music'; do not pass --generate-audio","Field-name trap: use ref_video_url (not video_url) / reference_audio_url (not audio_url) — get it wrong and the vendor silently drops the ref","duration 4-15s or -1 (auto); the Pi CLI currently requires integer — use ceil(intended) then ffmpeg trim","Read skills/video-generation/docs/seedance_reference_assets.md (real-looking human scenarios)"],flagSubset:["service","prompt","duration","aspect-ratio","resolution","image-urls","reference-audio-url","ref-video-url","ark-asset-ids","generate-audio","reference-subject-type"],examples:[{caption:"single, seedance-2-0 with @audio1 + image ref",command:'dl generate-video --service=seedance-2-0 \\\n --prompt="the character speaks @audio1 with clear articulation, @image1 sets the scene" \\\n --duration=8 --aspect-ratio=16:9 --resolution=720p \\\n --image-urls=https://.../keyframe.jpg \\\n --reference-audio-url=https://.../speech.mp3'},{caption:"real-looking human with asset register",command:'# Register asset first\ndl asset register --group-id=actor-jane --name=jane-headshot \\\n --url=https://.../actor.jpg --asset-type=Image\n# Then generate (use the real asset_id from the previous step\'s response)\ndl generate-video --service=seedance-2-0 \\\n --prompt="@asset1 walks through a cyberpunk street, no BGM" \\\n --duration=6 --resolution=720p \\\n --ark-asset-ids=asset_xxx \\\n --reference-subject-type=real_person'}]},{service:"seedance-2-0-fast",label:"Seedance 2.0 Fast",tier:"🥇 Top tier (Fast variant)",bestFor:"Same family and capabilities as Pro (auto-keyframe / multi-ref / audio coupling / video ref), just slightly lower quality than Pro, faster, and cheaper. Prefer this when Pro is too expensive or you only need a preview — do not drop to a lower-tier model instead",quality:"Very High",speed:"1-3min",cost:"mid",description:["The Fast variant of seedance-2-0. Same family and capability set, slightly lower quality / faster / cheaper.","For default scenarios with no special requirements → pick this; do not default to Pro and do not default to a lower-tier."],constraints:["Constraints are identical to seedance-2-0: real-looking human / IP must go through asset register and then asset-only for that source ref (do not also pass its URL in image_urls); ref_video_url / reference_audio_url field-name trap; duration 4-15s integer; audio moderation fallback is prompt text 'no BGM', not --generate-audio"],flagSubset:["service","prompt","duration","aspect-ratio","resolution","image-urls","reference-audio-url","ref-video-url","ark-asset-ids","generate-audio"],examples:[{caption:"single, seedance-2-0-fast (default first choice)",command:'dl generate-video --service=seedance-2-0-fast \\\n --prompt="a corgi astronaut floating, slow zoom in" \\\n --duration=5 --resolution=720p'}]},{service:"happyhorse-1-0-r2v",label:"HappyHorse 1.0 R2V (Alibaba)",tier:"🥈 Runner-up tier",bestFor:"Overall runner-up to seedance. Made by Alibaba, strong on Chinese prompts. 1-9 ref multi-subject composition",quality:"High",speed:"2-5min",cost:"mid",description:["Alibaba HappyHorse 1.0 reference-to-video (multi-ref composition).","Markedly better on Chinese prompts than other families; 1-9 reference images for multi-subject composition."],constraints:["image_urls 1-9 images is REQUIRED; prompt is also REQUIRED","aspect_ratio only 16:9 / 9:16 / 3:4 / 4:3 / 1:1 (no adaptive / 21:9)","resolution uses uppercase: 720P / 1080P (lowercase 720p is rejected — the opposite of other families!)","duration integer 3-15s"],flagSubset:["service","prompt","image-urls","duration","aspect-ratio","resolution","seed"],examples:[{caption:"multi-character composition",command:'dl generate-video --service=happyhorse-1-0-r2v \\\n --prompt="两个人在花园相遇,午后柔光" \\\n --image-urls=https://1.png --image-urls=https://2.png \\\n --duration=5 --resolution=1080P --aspect-ratio=16:9'}]},{service:"happyhorse-1-0-i2v",label:"HappyHorse 1.0 I2V",tier:"🥈 Runner-up tier",bestFor:"HappyHorse family — use this for the single-first-frame i2v scenario",quality:"High",speed:"2-5min",cost:"mid",description:["HappyHorse 1.0 single-first-frame image-to-video. Same family but only accepts a single image_url (not image_urls)."],constraints:["image_url (singular) is REQUIRED","resolution uppercase: 720P / 1080P (default 1080P)","duration 3-15s integer (default 5)"],flagSubset:["service","prompt","image-url","duration","resolution","seed"],examples:[{caption:"single first-frame i2v",command:'dl generate-video --service=happyhorse-1-0-i2v \\\n --prompt="角色缓慢转身,镜头微微推近" \\\n --image-url=https://.../first-frame.jpg \\\n --duration=5 --resolution=1080P'}]},{service:"happyhorse-1-0-video-edit",label:"HappyHorse 1.0 Video Edit",tier:"🥈 Exclusive capability",bestFor:"HappyHorse family video-to-video edit. The only true video editor in the whole table (change style / change scene while preserving composition)",quality:"High",speed:"3-5min",cost:"mid",description:["HappyHorse video-to-video edit. **The only entry in the generate-video table** that supports true","video editing: input a video + 0-5 refs + prompt, output a new video with changed style / scene but preserved","composition."],constraints:["video_url (singular) is REQUIRED — this is the source video; the field name differs from seedance's ref_video_url and **cannot be interchanged**","image_urls 0-5 optional (repeatable flag)","audio_setting: auto (default, HappyHorse decides) or origin (preserves source audio) — does not accept a generate_audio bool","Output duration = input video duration, do not pass --duration","resolution uppercase: 720P / 1080P"],flagSubset:["service","prompt","video-url","image-urls","resolution","audio-setting","seed"],examples:[{caption:"video edit — change scene to dusk",command:'dl generate-video --service=happyhorse-1-0-video-edit \\\n --prompt="keep original composition, change scene to dusk city skyline" \\\n --video-url=https://.../source.mp4 \\\n --image-urls=https://.../style-ref.png \\\n --resolution=1080P --audio-setting=auto'}]},{service:"kling-o3-pro-ref2v",label:"Kling O3 Pro Ref2V",tier:"🥉 Third tier",bestFor:"Kuaishou Kling O3 high-spec. multi-reference + character elements + first/end frame. Overall behind happyhorse",quality:"High",speed:"3-5min",cost:"mid",description:["Kling O3 ref-to-video Pro. Supports first frame + end frame + multi-reference","+ structured JSON via --elements to control character / scene elements. Overall quality slightly","below happyhorse, but first/end frame control is the advantage."],constraints:["image_url is the first frame, optional (without it, text-to-video only)","end_image_url is the last frame","elements is structured JSON: {frontal_image_url, reference_image_urls[]}"],flagSubset:["service","prompt","image-url","end-image-url","image-urls","elements","duration","aspect-ratio"],examples:[{caption:"first + end frame control",command:'dl generate-video --service=kling-o3-pro-ref2v \\\n --prompt="smooth transition from morning to noon" \\\n --image-url=https://.../start.png \\\n --end-image-url=https://.../end.png \\\n --duration=5 --aspect-ratio=16:9'}]},{service:"kling-o3-ref2v",label:"Kling O3 Ref2V",tier:"🥉 Third tier",bestFor:"Kling O3 standard. Same as Pro but slightly lower quality / cheaper",quality:"High",speed:"2-5min",cost:"low",description:["Kling O3 standard. Same params as Pro, slightly lower quality and cheaper. Backup when Pro is too expensive."],constraints:["Parameters are the same as kling-o3-pro-ref2v"],flagSubset:["service","prompt","image-url","end-image-url","image-urls","elements","duration","aspect-ratio"]},{service:"kling-o3-pro-v2v",label:"Kling O3 Pro V2V (video-edit)",tier:"🥈 Unique capability",bestFor:"Kling O3 Pro **video editing**: input video + prompt to change the frame contents; optional image_urls / elements as auxiliary refs. Pro quality. Use as the Kling-side alternative to happyhorse-1-0-video-edit or as fallback when seedance-2-0 video ref / continuation is unavailable.",quality:"Very High",speed:"3-5min",cost:"mid-high",description:["Kling O3 Pro **V2V (video-to-video) editing**. Input an existing video, write a prompt","describing how to change the frame contents (re-style / change scene / preserve composition),","and the model edits the input video accordingly. Auxiliary references via image_urls (≤4)","or structured elements JSON. Output duration / aspect_ratio **match the input video** —","you must NOT pass --duration / --aspect-ratio.","","Business positioning: Kling-side alternative to `happyhorse-1-0-video-edit` (Alibaba","ecosystem). Also a video-edit fallback when seedance-2-0 video-ref continuation is","unavailable."],promptTips:["Prompt describes the **edit operation** (e.g., 'change style to anime', 'replace background with night city', 'preserve composition, change wardrobe to formal suit')","image_urls (≤4) act as style / element auxiliary refs, not first-frame anchors","elements is structured JSON for fine-grained element control (see --print-schema)"],flagSubset:["service","prompt","video-url","image-urls","elements","negative-prompt","cfg-scale"],constraints:["video_url REQUIRED","Output duration / aspect_ratio = input video's (do NOT pass --duration / --aspect-ratio — raises E_SCHEMA or is silently overridden)","image_urls ≤ 4 auxiliary refs (optional)","Same param contract as kling-o3-v2v; Pro is higher quality / slower / more expensive"],examples:[{caption:"v2v Pro — change scene to anime",command:'dl generate-video --service=kling-o3-pro-v2v \\\n --prompt="re-style the video into anime; preserve composition and motion" \\\n --video-url=https://.../source.mp4 \\\n --image-urls=https://.../style-ref.png \\\n --negative-prompt="blurry, low contrast" --cfg-scale=7'}]},{service:"kling-o3-v2v",label:"Kling O3 Std V2V (video-edit)",tier:"🥈 Unique capability",bestFor:"Kling O3 standard **video editing**. Same param contract as Pro v2v but slightly lower quality / cheaper / faster. The cheap alternative to happyhorse-1-0-video-edit / Pro v2v.",quality:"High",speed:"2-5min",cost:"mid",description:["Kling O3 standard V2V (video-edit). Same input contract as kling-o3-pro-v2v","(video_url + prompt + optional image_urls / elements / negative_prompt / cfg_scale).","Slightly lower quality, faster, cheaper. Use as the cheap variant of Pro v2v, or","the Kling-side cheap alternative to happyhorse-1-0-video-edit."],promptTips:["Same as kling-o3-pro-v2v: prompt describes the edit operation, not a new scene from scratch"],flagSubset:["service","prompt","video-url","image-urls","elements","negative-prompt","cfg-scale"],constraints:["Same as kling-o3-pro-v2v (video_url required, output duration / aspect_ratio match input, image_urls ≤ 4)"]},{service:"kling3.0",label:"Kling 3.0",tier:"🥉 Third tier",bestFor:"Kling legacy version, i2v + audio support",quality:"High",speed:"1-3min",cost:"low",description:["Kling 3.0 (legacy). Usable for simple i2v + audio scenarios; overall behind kling-o3-*."],constraints:["image_url REQUIRED (image-to-video only)","sound / cfg-scale / negative-prompt optional"],flagSubset:["service","prompt","image-url","duration","aspect-ratio","sound","negative-prompt","cfg-scale"],examples:[{caption:"Kling 3.0 i2v with sound",command:'dl generate-video --service=kling3.0 \\\n --prompt="character speaks calmly" \\\n --image-url=https://.../portrait.jpg \\\n --duration=10 --aspect-ratio=16:9 --sound'}]},{service:"dli2v3",label:"Veo 3.1 Fast",tier:"Below that",bestFor:"Google Veo 3.1 Fast variant, text/image-to-video. Overall behind all of the above",quality:"Mid",speed:"1-3min",cost:"low",description:["Google Veo 3.1 Fast. 1-3 reference images, overall quality is middling."],constraints:["image_url 1-3, optional; last_frame_url optional; duration auto"],flagSubset:["service","prompt","image-url","last-frame-url","aspect-ratio"],examples:[{caption:"Veo 3.1 with first frame",command:'dl generate-video --service=dli2v3 \\\n --prompt="@image1 starts moving forward into the snow" \\\n --image-urls=https://1.png --duration=4'}]},{service:"dlim2v",label:"Grok Imagine",tier:"Below that",bestFor:"xAI Grok. Creative / stylized / fun mode is the strong suit, overall quality is middling",quality:"Mid",speed:"1-3min",cost:"low",description:["xAI Grok Imagine. Creative / fun stylized is the signature; overall quality is middling."],constraints:["duration 6s or 10s","mode=normal (default)"],flagSubset:["service","prompt","image-url","duration","aspect-ratio","mode"]},{service:"seedance-1-5",label:"Seedance 1.5 Pro",tier:"Below that",bestFor:"seedance legacy (1.5, NOT the 2.0 family); only suited to draft previews (first+last frame control)",quality:"Mid",speed:"1-3min",cost:"low",description:["seedance 1.5 Pro (legacy family — not the same generation as 2.0). first frame + last frame control,","only suited to draft previews; quality is clearly below the 2.0 family."],constraints:["duration 4-12s","first/last frame URL optional; generate-audio optional"],flagSubset:["service","prompt","image-url","last-frame-url","duration","aspect-ratio","resolution","generate-audio","seed"]},{service:"grok-imagine-video-1-5-preview",label:"Grok Imagine 1.5 (xAI)",tier:"Single-reference i2v",bestFor:"xAI Grok Imagine 1.5 image-to-video from a SINGLE reference image. Fast, creative / stylized motion. Keep the prompt about action / camera / mood — do NOT over-describe makeup or fine facial detail (over-specifying makeup degrades the result).",quality:"Mid-High",speed:"1-3min",cost:"low",description:["xAI Grok Imagine 1.5 (preview). Single-reference image-to-video — one reference image drives the clip."," - takes exactly ONE reference image (image_url); it is NOT a multi-ref model"," - duration 1-15s, resolution 480p / 720p"," - strong at creative / stylized motion"],promptTips:["Single reference image only — pass it via --image-url","Keep the prompt focused on motion / camera / mood; do NOT over-describe makeup or fine facial detail — over-specifying makeup makes results worse"],constraints:["image_url REQUIRED (image-to-video, single reference)","duration 1-15s; resolution 480p / 720p","aspect_ratio: auto / 1:1 / 16:9 / 9:16 / 4:3 / 3:4 / 3:2 / 2:3"],flagSubset:["service","prompt","image-url","duration","aspect-ratio","resolution"],examples:[{caption:"single-ref i2v",command:'dl generate-video --service=grok-imagine-video-1-5-preview \\\n --prompt="she turns toward the camera and smiles, soft cinematic light" \\\n --image-url=https://.../portrait.jpg \\\n --duration=6 --resolution=720p'}]},{service:"gemini-omni-video",label:"Gemini Omni Video (Google)",tier:"Exclusive capability (video editing)",bestFor:"Google Gemini Omni any-to-any video. Its standout strength is VIDEO EDITING — feed a source video + prompt and it re-works the clip impressively. Also does text-to-video and image-to-video (up to 7 reference images).",quality:"High",speed:"2-5min",cost:"mid",description:["Google Gemini Omni any-to-any multimodal video generation."," - **video editing is the killer feature**: pass a source video (--video-url) + prompt to re-edit it"," - also text-to-video and image-to-video (image_urls up to 7)"," - duration 4 / 6 / 8 / 10s; resolution 720p / 1080p / 4k; aspect 16:9 / 9:16"],promptTips:["For video editing pass the source clip via --video-url and describe the edit in the prompt","image_urls (≤7) act as reference subjects for generation"],constraints:["prompt REQUIRED","duration one of 4 / 6 / 8 / 10 (default 8)","resolution 720p / 1080p / 4k (default 720p); aspect_ratio 16:9 / 9:16","image_urls ≤ 7 (optional); --video-url is the source for video editing (optional)"],flagSubset:["service","prompt","duration","aspect-ratio","resolution","image-urls","video-url","seed"],examples:[{caption:"video editing — re-work a source clip",command:'dl generate-video --service=gemini-omni-video \\\n --prompt="restyle this clip into a rainy neon cyberpunk night, keep the subject\'s motion" \\\n --video-url=https://.../source.mp4 \\\n --duration=8 --resolution=720p'},{caption:"text-to-video",command:'dl generate-video --service=gemini-omni-video \\\n --prompt="a paper boat sailing down a sunlit street gutter, cinematic" \\\n --duration=8 --aspect-ratio=16:9 --resolution=720p'}]},{service:"longcat-avatar-1-5",label:"LongCat 1.5 (self-hosted)",tier:"Exclusive capability (audio-driven talking-head)",bestFor:"Audio-driven talking-head: one face image + one driving audio → a lip-synced video. Lip-sync is very stable — that is the reason to pick it; the trade-off is speed (noticeably slow, ~8-10min). Self-hosted on our own RunPod.",quality:"High (lip-sync stability)",speed:"8-10min (slow)",cost:"mid",description:["Self-hosted LongCat 1.5 audio-driven talking-head (distinct from the WaveSpeed longcat-avatar in `dl lipsync`).","Feeds a single face image + a driving audio and renders a lip-synced talking-head video."," - lip-sync is very stable — the strongest reason to pick it"," - output length follows the driving audio (do not pass --duration)"," - width / height default 1280x720 (pass both together to override)"," - noticeably slow (~8-10min); use it when lip-sync fidelity matters more than turnaround"],promptTips:["image_url is the face; audio_url is the driving speech — both REQUIRED","prompt is optional and only lightly steers the scene; the mouth is driven by the audio, not the prompt"],constraints:["image_url (face) REQUIRED","audio_url (driving audio, ≤20s) REQUIRED","output length = audio length; do NOT pass --duration","width / height optional but must be passed as a pair (default 1280x720)"],flagSubset:["service","prompt","image-url","audio-url","width","height"],examples:[{caption:"talking-head from face + audio",command:"dl generate-video --service=longcat-avatar-1-5 \\\n --image-url=https://.../face.jpg \\\n --audio-url=https://.../speech.mp3"}]},{service:"dlai2v_pro",label:"LTX 2 Pro (LTX 2.3 audio-driven)",tier:"Exclusive capability (audio-driven talking / singing video)",bestFor:"Audio-driven talking / singing video: one face/scene still (or 1-5 keyframes) + a driving audio → a lip-synced clip whose length follows the audio. Same engine as `dl lipsync --service=dlai2v_pro`; reach for it here when your pipeline composes through generate-video rather than the lipsync verb.",quality:"Very High",speed:"2-5min",cost:"mid",description:["LTX 2 Pro (routes to the LTX-2.3 audio workflow). **Audio-driven** — the ComfyUI","workflow derives video length from the driving audio, so --audio-url is REQUIRED.","","Two visual-input modes (mutually exclusive):"," Mode 1 (single still): --image-url — api-layer auto-wraps it into keyframes[0]."," Mode 2 (multi-keyframe): --keyframes (1-5 frames) for richer camera movement;",' each keyframe is {"image_url":"...","frame_position":"first|middle|last"}.',"","Output length = audio length; do NOT pass --duration to control length (--duration is","billing-only here, the vendor ignores it)."],promptTips:["⚠ LTX-family prompt template — all three segments required:"," 1. Subject is speaking/singing (explicitly say the character speaks/sings with perfect lip sync)"," 2. Character action (head nods/tilts / gaze / hands / shoulders / breathing)"," 3. Camera movement (Dolly in / slow push in / static medium close-up — state static explicitly)","Append a quality / lighting tail: 'high quality, natural lighting'"],flagSubset:["service","prompt","image-url","audio-url","keyframes","duration"],constraints:["--audio-url REQUIRED (drives output length); audio ≤ 20s & ≤ 100MB; mp3 / wav / ogg / flac / m4a / aac / webm","--image-url and --keyframes are mutually exclusive; --keyframes 1-5 frames","Do NOT pass --duration to control length (billing-only); width / height / resolution are fixed by the workflow","For the same single image + audio lip-sync need you can equally use `dl lipsync --service=dlai2v_pro` — identical engine"],examples:[{caption:"single still + driving audio (talking-head)",command:'dl generate-video --service=dlai2v_pro \\\n --image-url="https://cdn.example.com/face.png" \\\n --audio-url="https://cdn.example.com/voice.mp3" \\\n --prompt="A person speaks naturally with perfect lip synchronization, subtle head nods and tilts, hands resting gently or making small conversational gestures, relaxed shoulders, natural breathing motion, high quality, natural lighting, Dolly in"'}]},{service:"dlai2v_pro_multiframe",label:"LTX 2 Pro Multi-frame (LTX 2.3 真·多帧)",tier:"Exclusive capability (keyframe-guided audio-driven video)",bestFor:"True multi-keyframe (2-4) guided, audio-driven video: the model interpolates animation across the keyframes while lip-syncing to the driving audio — richer camera / pose movement than single-still dlai2v_pro. Same engine as `dl lipsync --service=dlai2v_pro_multiframe`.",quality:"Very High",speed:"2-5min",cost:"mid",description:["LTX 2.3 真·多帧变体(真正的多帧关键帧引导,不是单帧 wrap)。**Audio-driven** — audio","时长决定视频帧数,所以 --audio-url 必填;api-layer 按 keyframes 数量自动 router 到","mutiframe_{2f,3f,4f} workflow。","",'每帧 keyframe:{"image_url"(必填),"frame_ratio"?(0.0-1.0 时间位置),"weight"?(0.0-1.0 强度,默认 0.4)}。',"frame_ratio 不传则按帧数等分:2帧=[0,1] / 3帧=[0,0.5,1] / 4帧=[0,0.33,0.67,1]。","所有 keyframe 必须同一角色、同一画幅。"],promptTips:["Same LTX-family three-segment template as dlai2v_pro (subject speaking/singing + character action + camera move)"],flagSubset:["service","prompt","keyframes","audio-url","aspect-ratio","duration"],constraints:["--keyframes REQUIRED, 2-4 frames (api-layer routes to mutiframe_{2f,3f,4f} by count); --image-url alone not supported — use dlai2v_pro for a single still","--audio-url REQUIRED (drives output length / frame count)","--aspect-ratio 支持 16:9 / 9:16 / 1:1;resolution 强制 720p(不可改);不支持 --width / --height / --resolution","Do NOT pass --duration to control length (billing-only)"],examples:[{caption:"3 keyframes + driving audio",command:'dl generate-video --service=dlai2v_pro_multiframe \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf1.png","frame_ratio":0}\' \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf2.png","frame_ratio":0.5}\' \\\n --keyframes=\'{"image_url":"https://cdn.example.com/kf3.png","frame_ratio":1}\' \\\n --audio-url="https://cdn.example.com/segment.mp3" \\\n --aspect-ratio=9:16 \\\n --prompt="A person sings expressively with perfect lip synchronization, dynamic head movement, confident posture shifts, high quality, natural lighting, slow push in"'}]}],decisionLogic:[{when:"Default / no special requirement",pick:"seedance-2-0-fast (top-tier-family Fast variant, good overall quality + cheap)"},{when:"Want the highest overall quality + need character consistency / video ref / audio coupling",pick:"seedance-2-0 (top-tier Pro, expensive)"},{when:"Real-looking human / known-IP actor",pick:"seedance-2-0 or seedance-2-0-fast, **must first run dl asset register**"},{when:"Video editing (change style / change scene while preserving composition)",pick:"happyhorse-1-0-video-edit (Alibaba-side, Chinese-prompt-friendly) OR kling-o3-pro-v2v / kling-o3-v2v (Kling-side; also serves as fallback when happyhorse / seedance-2-0 video-ref is unavailable)"},{when:"Chinese prompt / Alibaba preference / 1-9 multi-subject refs",pick:"happyhorse-1-0-r2v or happyhorse-1-0-i2v"},{when:"multi-reference + character elements + first/end frame control",pick:"kling-o3-pro-ref2v (quality-priority) or kling-o3-ref2v (cheap)"},{when:"Quick draft preview",pick:"seedance-2-0-fast (preferred, top-tier) or seedance-1-5"},{when:"Creative / fun stylized",pick:"dlim2v (Grok specialty)"},{when:"Single-reference creative i2v (one image → stylized motion)",pick:"grok-imagine-video-1-5-preview (xAI; single ref image, keep prompt off makeup / facial detail)"},{when:"Edit / re-work an existing video clip (any-to-any)",pick:"gemini-omni-video (Google; standout at re-editing a source video) — also see happyhorse-1-0-video-edit / kling-o3-pro-v2v"},{when:"Audio-driven talking-head / stable lip-sync",pick:"longcat-avatar-1-5 (self-hosted; very stable lip-sync, slow ~8-10min). For other lip-sync routes see dl lipsync"},{when:"Audio-driven talking / singing video from a single still (lip-synced, output = audio length)",pick:"dlai2v_pro (LTX 2 Pro, audio-driven; --image-url + --audio-url). Same engine as dl lipsync --service=dlai2v_pro"},{when:"Audio-driven video with 2-4 keyframe guidance (richer camera / pose movement, lip-synced)",pick:"dlai2v_pro_multiframe (LTX 2.3 multi-frame; 2-4 --keyframes + --audio-url). Same engine as dl lipsync --service=dlai2v_pro_multiframe"}]},preflightTopic:{intro:"Before the first dl generate-video call, these five decisions must be explicit (for the per-service flag shape see `dl generate-video model <service>` — positional; `model -h <service>` short-circuits to the overview):",decisions:[{name:"Service / model",description:"Which service to use. Decide per the SERVICES table + DECISION LOGIC in `dl generate-video model -h` (overview), or `dl generate-video model <service>` (per-service profile)."},{name:"Duration plan",description:"Provider's valid duration range + the trim-back plan if the final segment is shorter than the provider min.\nseedance-2-0 / fast currently require integer duration — use ceil(intended) then ffmpeg trim;\nhappyhorse video-edit's duration auto-follows the source video — do not pass it."},{name:"Aspect ratio",description:"Target frame ratio. The allowed enum varies per service:\n seedance-2-0 supports adaptive / 16:9 / 4:3 / 1:1 / 3:4 / 9:16 / 21:9;\n happyhorse-r2v does not accept adaptive / 21:9, only 16:9 / 9:16 / 3:4 / 4:3 / 1:1."},{name:"Resolution package",description:"Resolution tier. Field-casing trap per service:\n seedance-2-0 / fast use lowercase 480p / 720p (1080p not supported);\n happyhorse-* uses **uppercase** 720P / 1080P (lowercase is rejected — opposite of seedance)."},{name:"Reference-input plan",description:"Which image / audio / video / asset will enter this call.\nReal-looking human / IP → seedance-2-0 must first go through dl asset register, then submit that source ref asset-only; do not also submit its URL."}],notes:["Seedance 2.0 family mandatory preflight: using a real-looking human but skipping asset register, or submitting the same source ref both as ark_asset_ids and image_urls, causes upstream policy block or unpredictable result","If Seedance generated/output audio is moderation-blocked, retry with prompt text 'no BGM' / 'no background music'; do not pass --generate-audio","If cost-sensitive or unsure about service choice, read pricing-and-policies-dramaland-faq/SKILL.md before locking the package"]},policyTopic:{intro:"Three classes of hard rules: external communication must not leak internal details; paid package must be authorized before submit; URLs must be real and accessible.",rules:[{title:"1. User-Facing Communication Rule — do not leak internal details",body:["Never surface vendor / backend internal name / USD/RMB price /","internal model code (seedance-2-0 vendor routing etc.) / trace identifier","(job_id / task_id / request_id / other UUIDs) to the end user.","","User-facing summary should mention **only**:"," - service name (seedance-2-0 / happyhorse-1-0-r2v / kling3.0 etc.)",' - user-meaningful constraint (duration, aspect, "edit" vs "generate" etc.)'," - action (generate / edit video)"]},{title:"2. Production Package Gate — do not call before paid authorization",body:["service / model, duration plan, aspect ratio, resolution, generation count (including batch","segment range), and image / audio / video / asset reference plan are all components of the system",'prompt-level "paid media production package authorization". Do not submit before authorization.',"","Within the same authorized package you can batch-generate — do not block per segment.","Only re-ask on package overflow (switching service / changing duration / changing resolution /","adding count / fallback / paid regeneration)."]},{title:"3. URL Hygiene — do not fabricate storage URLs",body:["All reference URLs (image / audio / video) must be real accessible HTTPS. Legal sources:"," - dl generate-image / dl generate-music / other submit results (GCS URLs)"," - URLs uploaded by the user or provided by the conversation context"," - URLs returned by dl content list or other platform queries","","NEVER fabricate or guess storage URLs. If a reference image is missing, generate it via dl","generate-image first; if audio is missing, generate it — do not invent domains / paths.","","Seedance 2.0 real-looking human refs are stricter: after dl asset register, pass only","--ark-asset-ids + @assetN for that media; do not also submit its raw image/video URL.","If output audio is moderation-blocked, retry with prompt text 'no BGM' / 'no background music';","do not pass --generate-audio."]}]},compositionTopic:{intro:"This atomic skill only produces a video URL; artifact / canvas registration and other downstream responsibilities are not this verb's job.",integrations:[{skill:"full-song MV / multi-segment video workflow",rule:["Distinguish the storyboard's intended final segment duration from the provider request","duration. If the final segment is shorter than the provider min, request the provider min, then ffmpeg","trim back to the original intended length. Do not round up to a whole number / do not audio-retime to match provider duration.","","If the provider requires integer duration (seedance-2-0 currently does), use ceil(intended);","do not floor / do not nearest-integer round.","","If the segment already has resolved reference assets (reference_list) → pass those real","URLs / registered asset ids directly; do not rely on prompt text alone.","For Seedance real-looking human media, pass the registered asset id only and omit the same raw URL."]},{skill:"ffmpeg (probe / trim / concat / crop)",rule:["This verb only handles vendor generation, no ffmpeg work. For trim / concat / probe →","load the ffmpeg skill and use dl ffmpeg; do not install system ffmpeg in the sandbox."]},{skill:"right-side canvas (pi_media_log)",rule:["The atomic skill no longer performs dl artifact write / patch-json pi_media_log on your behalf —","that is the composition layer's job. The upstream workflow (visual-production / music-video","composition) is responsible for placing the returned URL into its own artifact slot."]}]},asyncTopic:{intro:["dl generate-video by default returns { job_ref, status: 'pending' } and exits immediately — do not poll.","Results are injected into the current session as [async-callback] job=<ref> text; typical duration 1-5 minutes.","","Only run dl poll separately when 'the next step strictly requires the result' (e.g. immediately feeding ffmpeg)."],resultShape:['{ "url": "https://storage.googleapis.com/.../video.mp4",',' "original_url": "...",',' "vendor": "..." }'],notes:["The URL field is the atomic skill's sole product handed up to the upper layer","The vendor field is debug-only; per the user-facing communication policy, do not leak it to the user","⚠ This URL already lives on our GCS — feed it directly to downstream tools / artifacts; do NOT pass to upload_file (would re-host an identical blob under a different URL)."]},publishTopic:{intro:["After producing your video URL, call publish_content with","presentation_family='video' and the explicit media fields. See","'Publishing Your Work / video' in your creation playbook for the full","field mapping template."],fields:[{name:"presentation_family",value:"'video'"},{name:"media_urls.video",value:"<returned video URL>"},{name:"frameRatio",value:"<from your aspect_ratio decision>"},{name:"thumbnail_url",value:"<optional poster frame>"},{name:"duration_seconds",value:"<intended final, after ffmpeg trim>"},{name:"delivery_format",value:"'video'"},{name:"experience_format",value:"'passive_media'"}]}})}(Tc),function(e){as(e,{verb:"generate-music",actionName:"generate_music",schema:Uo,billing:{schema:Hs,select:e=>({service:e.service}),quote:Vs},supportsBatch:!0,description:"Generate music from a required prompt; prompt is music direction unless --custom makes it lyrics.",notes:["Services: suno-v5, suno-v5_5, minimax.","`--prompt` is always required; there is no title/tags-only mode.","`--custom` changes prompt semantics: with --custom it is lyrics; otherwise it is music direction and Suno may write lyrics.","`--instrumental` requests no vocals; still pass --prompt as music direction and usually omit --custom.","`--vocal-gender` is capitalized: `Male` / `Female` (not lowercase) — backend is case-sensitive.","Need lyrics for `--custom` and the user did not provide any? Run `dl generate-lyrics --prompt=<brief>` first (returns 2-3 candidates with [Verse]/[Chorus] markers); only hand-write lyrics yourself when that command fails."],whenToUse:["You need a generated music track from a required music brief or explicit lyrics","You're producing a music-video reference track and want to fan out style variants via --jobs-file"],whenNotToUse:["You need spoken text — use `dl generate-tts`","You need beat positions of an existing audio file — use `dl analyze-beats`"],examples:[{caption:"suno-v5_5, model-written lyrics",command:'dl generate-music \\\n --service=suno-v5_5 \\\n --prompt="bright synth-pop anthem with retro arcade textures, energetic chorus, glossy modern mix" \\\n --title="Neon High Score" \\\n --tags="synth-pop, retro arcade, energetic, glossy chorus" \\\n --vocal-gender=Female'},{caption:"instrumental only",command:'dl generate-music \\\n --service=suno-v5_5 \\\n --prompt="wordless cinematic piano and warm string pads, slow emotional build, 72 BPM, clean mix" \\\n --title="After the Rain" \\\n --tags="instrumental, cinematic piano, warm strings, reflective, 72 BPM" \\\n --negative-tags="vocals, singing, lyrics, spoken word" \\\n --instrumental'},{caption:"custom lyrics",command:'dl generate-music \\\n --service=suno-v5_5 \\\n --prompt="[Verse] Neon streets are waking [Chorus] We rise above the static" \\\n --title="Above the Static" \\\n --tags="electropop, female vocal, uplifting chorus" \\\n --custom \\\n --vocal-gender=Female'}],notExamples:[{command:'dl generate-music --service=suno-v5_5 --title="After the Rain" --tags="instrumental, cinematic" --instrumental',whyItFails:"--prompt is required even for instrumental tracks; derive a brief from the title/tags instead"},{command:'dl generate-music --params=\'{"service":"suno-v5","prompt":"..."}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"url":"https://storage.../audio.mp3","duration_ms":120000}}',modelTopic:{rankingSummary:["Ranked by overall quality (head-to-head on the same song; earlier = stronger):"," 🥇 suno-v5_5 (2 tracks) — current strongest Suno; vocals / arrangement / mix all beat v5 and minimax;"," long structure (verse / chorus / bridge) is stable. **Default / preferred for final delivery.**"," 🥈 suno-v5 (2 tracks) — previous-generation Suno; clearly lower quality than v5_5, but still **significantly stronger than minimax**."," Fall back to it only when v5_5 is unavailable or when you want dual-service comparison candidates."," 🥉 minimax (1 track) — single-track fast generation; quality below both Suno tiers (more mechanical vocals),"," fastest single-track speed, lowest cost. **Only suitable as a stopgap BGM / placeholder / quick demo**; not recommended for final delivery."],services:[{service:"suno-v5_5",label:"Suno V5.5",tier:"🥇 Default / Strongest",bestFor:"Default / unsure / final delivery. Vocals, arrangement, and mix are all strongest; long structure is stable",quality:"Very High",speed:"1-3min",cost:"mid-high",description:["Suno V5.5, Pi's current strongest music service. Each generation returns **2 candidate tracks**","(MUST normalize them into music_candidate.content[] preserving all of them; finalize only after user pick)."],promptTips:["prompt semantics shift with --custom / --instrumental:"," No-vocal BGM: --instrumental + prompt = music direction (style / mood / arrangement /"," BPM / structure / use case); do NOT write lyrics; usually omit --custom"," Suno writes its own lyrics: omit --custom + omit --instrumental + prompt = music direction"," Custom lyrics: --custom + prompt = actual lyrics; STRONGLY recommended to use [Verse] /"," [Chorus] / [Bridge] / [Outro] structure markers","","title / tags are auxiliary controls only — they CANNOT replace prompt (prompt is always required).","For pure music, add --negative-tags='vocals, singing, lyrics, spoken word' to reinforce no-vocal."],flagSubset:["service","prompt","title","tags","negative-tags","custom","instrumental","vocal-gender"],constraints:["⚠ Always returns 2 tracks; evaluate and recommend the best, but MUST NOT use a track as the downstream music_url without user pick","--vocal-gender is case-sensitive: `Male` / `Female` (not lowercase)","No native duration parameter — express target duration via prompt + tags"],examples:[{caption:"suno-v5_5, Suno-written lyrics (default case)",command:'dl generate-music --service=suno-v5_5 \\\n --prompt="bright synth-pop anthem with retro arcade textures, energetic chorus, glossy modern mix" \\\n --title="Neon High Score" \\\n --tags="synth-pop, retro arcade, energetic, glossy chorus" \\\n --vocal-gender=Female'},{caption:"suno-v5_5, custom lyrics",command:'dl generate-music --service=suno-v5_5 \\\n --prompt="[Verse] Neon streets are waking [Chorus] We rise above the static" \\\n --title="Above the Static" \\\n --tags="electropop, female vocal, uplifting chorus" \\\n --custom --vocal-gender=Female'},{caption:"suno-v5_5, instrumental / no-vocal BGM",command:'dl generate-music --service=suno-v5_5 \\\n --prompt="wordless cinematic piano and warm string pads, slow emotional build, 72 BPM, clean mix for a reflective closing scene" \\\n --title="After the Rain" \\\n --tags="instrumental, cinematic piano, warm strings, reflective, 72 BPM" \\\n --negative-tags="vocals, singing, lyrics, spoken word" --instrumental'}]},{service:"suno-v5",label:"Suno V5",tier:"🥈 Runner-up",bestFor:"v5_5 unavailable, or you want v5_5 + v5 dual-service comparison candidates",quality:"High",speed:"1-3min",cost:"mid",description:["Suno V5, previous generation. Vocal nuance / harmonic layering / style fidelity are all clearly","below v5_5, but still **significantly stronger than minimax**. Also returns 2 tracks. Parameters /","semantics are identical to v5_5 — only the service name differs."],promptTips:["Same as suno-v5_5; the custom / instrumental triangle contract is identical"],flagSubset:["service","prompt","title","tags","negative-tags","custom","instrumental","vocal-gender"],constraints:["Same as suno-v5_5 (2 tracks / user pick required / vocal-gender casing)"]},{service:"minimax",label:"MiniMax Music",tier:"🥉 Stopgap placeholder",bestFor:"ONLY stopgap BGM / placeholder music / quick demo, or when the user explicitly asks for fast/cheap",quality:"Mid",speed:"30-90s",cost:"low",description:["MiniMax single-track fast generation. Quality is below both Suno tiers (more mechanical vocals,","weaker style control, flatter structure). Single track → single candidate (one entry in content[];","the selected fields can be set directly on the first write).","**Not recommended for final delivery.**"],promptTips:["Same custom / instrumental semantics as the Suno family"],flagSubset:["service","prompt","title","tags","negative-tags","custom","instrumental","vocal-gender"],constraints:["⚠ Single-track return — no head-to-head comparison candidate","minimax title is forwarded into params; the api-layer may echo it in the result (not guaranteed to reach the upstream API)"]}],decisionLogic:[{when:"Default / unsure / final delivery",pick:"suno-v5_5 (strongest quality)"},{when:"v5_5 having issues / want dual-service comparison candidates",pick:"add suno-v5 (do NOT fall straight to minimax)"},{when:"ONLY stopgap BGM / placeholder / quick demo, or user explicitly asks fast/cheap",pick:"minimax"},{when:"Need lyrics but user did not provide any",pick:"Call `dl generate-lyrics --prompt=<brief>` first (returns 2-3 candidates), pick one, then Any Suno service + custom: true. Fall back to agent-written lyrics or `custom: false` only when generate-lyrics is unavailable"},{when:"Let Suno write its own lyrics (no separate lyrics call)",pick:"Any Suno service + custom: false"},{when:"User has already provided complete lyrics",pick:"Any Suno service + custom: true + [Verse]/[Chorus] markers"},{when:"No-vocal BGM (no lyrics)",pick:"Any service + --instrumental + prompt = music direction"}]},preflightTopic:{intro:"Explicitly prepare the generation brief before the first dl generate-music call — if ANY of the 7 items below is undecided, do not start the call:",decisions:[{name:"Generation mode",description:"Net-new generation vs remix / continuation. **The current CLI only exposes net-new.**\nIf the request is remix / continuation and the runtime exposes no true remix controls, STOP and\nsurface the capability mismatch directly — do not disguise it as a normal generate call."},{name:"Instrumental vs vocal",description:"Decide whether to pass --instrumental. The prompt-writing rule follows from this choice."},{name:"Custom mode (decide explicitly, do not rely on default)",description:"--custom determines prompt semantics:\n --custom=true → prompt is the **actual lyrics**; use [Verse] / [Chorus] / [Bridge] structure markers\n --custom=false → prompt is **music direction**; Suno may write its own lyrics (unless --instrumental)\nDo not rely on defaults — make the decision explicit."},{name:"Lyrics strategy",description:'For a vocal track: are lyrics provided by the user / generated via `dl generate-lyrics` / written by the agent / left to Suno via non-custom mode?\n**Preferred order when the user did not hand over lyrics:**\n 1. Try `dl generate-lyrics --prompt="<short brief, ≤200 chars>"` first — returns 2-3 KIE-Suno lyric candidates with [Verse]/[Chorus] markers; pick one and feed it as `dl generate-music --custom --prompt=<lyrics>`.\n 2. If `dl generate-lyrics` returns E_BACKEND / sensitive-word block / timeout, fall back to writing lyrics yourself with explicit [Verse]/[Chorus]/[Bridge] structure markers.\n 3. Only let Suno auto-write lyrics (omit --custom) when neither route is available or the brief is too vague to land lyrics.\nA pure instrumental track MUST NOT include lyric text in the prompt and SHOULD NOT call generate-lyrics.'},{name:"Target duration",description:"Target seconds or duration band. The current generate_music CLI has NO native duration parameter,\nso this intent must be expressed via prompt / title / tags and reflected in the subsequent evaluation."},{name:"Style package",description:"title / tags / negative-tags / era / genre / energy / tempo feel / instrumentation /\nvocal-gender (when relevant) — all need to be decided before calling the service."},{name:"Service choice (decide only after the brief is fully clear)",description:"Choose service from the brief: default suno-v5_5 / add suno-v5 for dual candidates / minimax only for stopgap.\nCost-sensitive or unclear choice → read pricing-and-policies-dramaland-faq/SKILL.md first, then lock."}],notes:["Cost-sensitive / unclear service → read pricing-and-policies-dramaland-faq/SKILL.md first","Batch generation goes through --jobs-file (JSON array); do not block per item; escape multi-line lyrics with \\n inside JSON strings"]},policyTopic:{intro:"Five categories of hard rules: User-facing isolation / Package gate / **Prompt-Custom-Instrumental triangle contract** / **Artifact-Finalize Gate** / Fallback ladder.",rules:[{title:"1. User-Facing Communication — never leak internal details",body:["Vendor / pricing / internal model code (Suno V5.5 / Suno V5 / MiniMax) / trace id must NOT","surface to the user. User-facing summary only mentions: service alias (Suno / MiniMax) +","action (generate music / score / candidate songs) + candidate count."]},{title:"2. Production Package Gate — never call before authorization",body:["service / generation count / candidate count / instrumental / vocal / custom mode / lyrics","strategy / target duration / style package / source / brief plan are all components of the paid","package authorization. Do not call before authorization; once authorized, batch and normalize","candidates within the package — do not block per candidate. Only re-ask on package overflow","(service swap / candidate-count change / duration change / lyrics-strategy change / fallback /","paid regeneration)."]},{title:"3. Prompt / Custom / Instrumental Triangle Contract (#391)",body:["`prompt` is ALWAYS required; there is no 'title + tags only' generation mode.","","| Goal | Flags | prompt meaning |","|-----|-----|-------------|","| No-vocal BGM | --instrumental, usually OMIT --custom | **Music direction**: style / mood / arrangement / tempo / structure / scene. Do NOT write lyrics |","| Suno writes lyrics | OMIT --custom, OMIT --instrumental | **Music direction**; Suno V5.5 / V5 writes its own lyrics based on the brief |","| Custom lyrics | Pass --custom | **Actual lyrics**; recommended to use [Verse] / [Chorus] / [Bridge] / [Outro] structure markers |","","For pure music, add --negative-tags='vocals, singing, lyrics, spoken word' to reinforce the no-vocal constraint.","title and tags are auxiliary controls only — they CANNOT replace prompt.","If the user only provided title / tags, synthesize a short prompt from them first — do not omit prompt.","For multi-line lyrics, prefer --jobs-file and escape with \\n inside JSON strings; do not use literal heredoc newlines.","Need lyrics but the user did not provide any? Call `dl generate-lyrics --prompt=<short brief>` first (KIE Suno, returns 2-3 candidates with [Verse]/[Chorus] markers) and feed the chosen text into --custom. Only hand-write lyrics yourself when generate-lyrics fails."]},{title:"4. Artifact-Finalize Gate (music_candidate slot)",body:["Results from this verb MUST land in the music_candidate slot (new artifact protocol — pure","domain `data`, no UI fields). Landing flow:",""," 1. Read schemas/artifact_contract.json (in this skill's directory); record ARTIFACT_CONTRACT_PATH"," 2. Read schemas/music_candidate.schema.json + templates/music_candidate.minimum.json"," 3. Normalize the provider response into data.candidates[] — preserve ALL tracks;"," normalize tags 'pop, electronic' into the array ['pop', 'electronic']; each candidate"," includes a lyrics field (#306)"," 4. Single-track (minimax) → one entry; data.selected_candidate_index = 0 and"," data.selected_audio_url copied from candidates[0].audio_url on the first write"," 5. Multi-track (suno-v5 / suno-v5_5) → multiple entries in data.candidates[]; selected_* = null;"," MUST wait for user pick (media_choice ask rendered from candidates[]) before patch-json"," selected_candidate_index + selected_audio_url, then re-finalize","","⚠ Any artifact call failure → the slot does not exist; do NOT pretend it succeeded / do NOT keep using a temp file.","⚠ ARTIFACT-FINALIZE GATE requires user consent before finalize; do NOT finalize a multi-track candidate before pick."," selected_audio_url is only usable as the downstream music_url when the slot is verified + non-null."]},{title:"5. Fallback Ladder",body:["When this verb produces issues (insufficient quality / wrong style / moderation block / service unavailable), in order:","","1. Retry once (transient network / quota jitter usually clears)","2. Edit prompt: strengthen style brief; add negative-tags; fill missing [Verse]/[Chorus] structure markers","3. Swap service: v5_5 → add v5 head-to-head (do NOT fall straight to minimax)","4. Adjust mode switches: vocal-gender / instrumental / custom","5. Only fall back to minimax when the user explicitly asks for 'fast/cheap' or confirms it is a stopgap placeholder"]}]},compositionTopic:{intro:"This atomic skill mandatorily lands results in the music_candidate artifact slot; downstream (lipsync / analyze-beats / publish_content) consumes selected_audio_url (only after user pick + finalize).",integrations:[{skill:"dl artifact (music_candidate slot)",rule:["MANDATORY: after generation, normalize results into the music_candidate slot (Artifact protocol 0509)."," - Multi-track providers (suno-v5 / suno-v5_5) → preserve all candidates in content[];"," selected_* = null; wait for user pick before patch-json + re-finalize"," - Single-track provider (minimax) → wrapper selected_* can be set on the first write","See schemas/music_candidate.schema.json and the schemas/ + templates/ in this skill's directory."]},{skill:"dl lipsync (audio source for lipsync)",rule:["selected_audio_url can be used as lipsync --audio-url.","⚠ Only usable when the slot is verified + selected_audio_url is non-null; otherwise treat as not generated."]},{skill:"dl analyze-beats (beat / sync points)",rule:["MV beat sync: selected_audio_url → dl analyze-beats to extract beats + segmentation."]},{skill:"publish_content (final delivery)",rule:["publish_content presentation_family='text' + media_urls.audio=<url> +","delivery_format='audio' (the runtime does NOT auto-infer audio from presentation_family,","media_urls.audio MUST be written explicitly)."]}]},asyncTopic:{intro:["dl generate-music returns { job_ref, status: 'pending' } and exits immediately by default — do NOT poll.","The result is injected into the session as [async-callback] job=<ref> text; typical wait is 1-3 minutes (minimax 30-90s).","If the next step must have the result (immediately normalize into the artifact or feed lipsync) →","query separately with dl poll --job-ref=<ref>; dl subcommands themselves no longer support --wait blocking (#294)."],resultShape:["// suno-v5 / suno-v5_5 (2 tracks)",'{ "musics": [',' { "id": "<uuid>", "audio_url": "https://storage.../track1.mp3",',' "title": "...", "tags": "...", "prompt": "..." },',' { "id": "<uuid>", "audio_url": "https://storage.../track2.mp3", ... }'," ] }","// minimax (1 track)",'{ "audio_url": "https://storage.../track.mp3", "title": "...", ... }',"vendor / internal metadata fields MUST NOT be exposed to the user"],notes:["⚠ Do NOT write a bash poll loop (while sleep + dl poll) — forbidden by the agent runtime async rules (#389)","Batch goes through --jobs-file; each job's completion is pushed back independently via [async-callback]"]},publishTopic:{intro:["After producing audio_url, publish_content goes through the 'text' presentation_family (audio is not a standalone family).","The runtime does NOT auto-infer audio from presentation_family; media_urls.audio MUST be written explicitly."],fields:[{name:"presentation_family",value:"'text'"},{name:"media_urls.audio",value:"<selected_audio_url> (only available after user pick + slot verified)"},{name:"delivery_format",value:"'audio'"}]}})}(Tc),function(e){as(e,{verb:"generate-sound",actionName:"generate_sound",schema:Fo,supportsBatch:!0,description:"Generate a short sound effect (SFX / Foley / ambient / short loop) from a text description. ElevenLabs Sound Effects v2, duration 0.5–30s.",notes:["Only service is `elevenlabs-sound` (single provider for now).","`--duration-seconds` hard cap is 30s (ElevenLabs v2 limit). Omit to let the model pick a duration.","`--loop` produces a seamlessly looping clip — only valid on v2 (the default model).","`--prompt-influence` controls how strictly the model follows the text (0–1, default 0.3 server-side).","For a full song with vocals or longer than 30s, use `dl generate-music` instead."],whenToUse:["You need a short cinematic SFX / Foley / ambient bed / UI sound / short loop","You want a looping background texture for a video or scene transition","Batch dispatch a set of SFX cues via --jobs-file (each job 0.5–30s)"],whenNotToUse:["You need a full music track with melody / vocals / structure — use `dl generate-music`","You need spoken text — use `dl generate-tts`","You need an audio file longer than 30 seconds — current SFX model caps at 30s"],examples:[{caption:"rain ambience, 10s",command:'dl generate-sound \\\n --service=elevenlabs-sound \\\n --text="steady rain on a tin roof, distant low thunder, no music" \\\n --duration-seconds=10'},{caption:"UI confirmation chime, seamless loop",command:'dl generate-sound \\\n --service=elevenlabs-sound \\\n --text="soft synthetic confirmation chime, two short notes, clean digital" \\\n --duration-seconds=2 \\\n --loop \\\n --prompt-influence=0.6'},{caption:"short emotional music bed (probe SFX model for short-music territory)",command:'dl generate-sound \\\n --service=elevenlabs-sound \\\n --text="dreamy romantic piano with soft strings, warm and intimate, slow tempo" \\\n --duration-seconds=15'}],notExamples:[{command:'dl generate-sound --service=elevenlabs-sound --text="..." --duration-seconds=60',whyItFails:"duration_seconds is capped at 30 by the ElevenLabs SFX v2 model; the schema rejects values > 30"},{command:'dl generate-sound --service=elevenlabs-sound --text="full pop song with vocals and chorus"',whyItFails:"This verb is short-SFX only; for vocal songs / longer compositions use `dl generate-music`"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"audio_url":"https://storage.../sound.mp3","duration_ms":10031,"format":"mp3","sample_rate":44100}}'})}(Tc),function(e){e.command("generate-lyrics").description("Generate Suno-style song lyrics from a short brief (<=200 chars). Returns 2-3 candidates synchronously; pick one and feed to `dl generate-music --custom`.").addHelpText("after",["","WHEN TO USE"," - You're about to call `dl generate-music --custom` and need lyrics with [Verse]/[Chorus] markers."," - You want 2-3 lyric variants to choose from before committing to a music generation.","","WHEN NOT TO USE"," - The song is instrumental — skip lyrics entirely, pass `--instrumental` to generate-music."," - You already have lyrics from the user — pass them directly to `dl generate-music --custom --prompt=...`.","","FALLBACK"," - If this command fails (E_BACKEND / E_SENSITIVE / E_TIMEOUT), hand-write lyrics yourself with [Verse]/[Chorus] structure and continue to generate-music.","","OUTPUT",' {"ok":true,"data":{"task_id":"...","lyrics":[{"title":"...","text":"[Verse]...","status":"complete"}, ...]}}',"","Example:",' dl generate-lyrics --prompt="bittersweet synth-pop about leaving a small town at sunrise"'].join("\n")).requiredOption("--prompt <text>","REQUIRED — short brief describing the song (<=200 chars)").action(async e=>{const t=String(e.prompt??"").trim();t||Fa("--prompt is required and must be non-empty"),t.length>200&&Fa("--prompt must be <=200 characters (KIE limit)",`current length: ${t.length}`);try{const e=await ua("media/submit","api/forward/lyrics",{prompt:t},{timeoutMs:14e4,retries:0});e.success&&e.data?.lyrics||Fa(e.error||"lyrics generation returned no candidates"),Ua({ok:!0,data:e.data})}catch(e){e instanceof oa&&Fa(e.message,e.hint),Fa(e instanceof Error?e.message:String(e))}})}(Tc),function(e){as(e,{verb:"analyze-beats",actionName:"analyze_beats",schema:Xo,supportsBatch:!1,description:"Analyse beat structure of an audio file. Synchronous — returns the beat list directly.",notes:["`--beat-method` is one of: `madmom_rnn` (default), `librosa`. Override only when you have a specific reason."],whenToUse:["Music-video planning: you need beat positions to anchor segment boundaries","Tempo / downbeat estimation before scheduling cuts"],whenNotToUse:["You need a transcript — use `dl transcribe`","You need to generate music — use `dl generate-music`"],examples:[{caption:"default beat method",command:'dl analyze-beats --audio-url="https://cdn.example.com/song.mp3"'},{caption:"explicit librosa (faster but different output)",command:'dl analyze-beats \\\n --audio-url="https://cdn.example.com/song.mp3" \\\n --beat-method=librosa'}],notExamples:[{command:'dl analyze-beats --params=\'{"audio_url":"..."}\'',whyItFails:"inline JSON via --params is removed; raises E_UNKNOWN_OPTION"}],outputSingle:'{"ok":true,"success":true,"beats":[{"position":1,"time":0.45,"strength":0.9}, ...]}'})}(Tc),function(e){as(e,{verb:"render-caption",actionName:"render_caption",schema:Zo,billing:{schema:ml,select:()=>({}),quote:hl},supportsBatch:!1,description:"Burn SRT captions into a video. Synchronous — returns the captioned video URL directly.",notes:["`--caption` is a JSON object. Supported fields include fill_color, border_color, font_id, font_weight, shadow, position, position_value, font_size, and font_size_px.","`font_size_px` takes precedence over the `font_size` preset."],whenToUse:["You already have a video URL and SRT content and need a burned-caption video","The create-subtitles skill has generated SRT and the user requested embedded subtitles"],whenNotToUse:["You need ASR first — use `dl transcribe` or the create-subtitles skill","You only need an external SRT file — do not render captions"],examples:[{caption:"burn default-style captions",command:'dl render-caption \\\n --video-url="https://cdn.example.com/video.mp4" \\\n --srt-content="1\\n00:00:00,000 --\x3e 00:00:02,500\\nHello\\n" \\\n --caption=\'{"fill_color":"#FFFFFF","border_color":"#000000","font_id":"noto_sans","font_weight":"bold","position":"bottom","position_value":0.1,"font_size_px":36}\''}],notExamples:[{command:'dl render-caption --params=\'{"video_url":"..."}\'',whyItFails:"inline JSON via --params is removed; pass scalar flags directly"}],outputSingle:'{"ok":true,"success":true,"video_url":"https://.../captioned.mp4"}'})}(Tc),function(e){as(e,{verb:"motion-control",actionName:"motion_control",schema:Mo,billing:{schema:rl,select:e=>({service:e.service,tier:e.tier,duration:e.duration}),quote:al},supportsBatch:!0,description:"Transfer motion / pose from a source video onto one or more target characters (services: dreamactor, kling3.0-motion). dreamactor supports multi-person via --image-urls; kling3.0-motion is single-person only.",notes:["Provide exactly one of --image-url / --image-urls / --image-base64; supplying more than one (or none) raises E_SCHEMA.","`--image-urls` 是多人入口,**仅 dreamactor 支持**——传 N 个 URL,driving video 里就要有匹配的 N 个角色;kling3.0-motion 传 --image-urls 会被 vendor 拒绝。","`--duration=<seconds>` 是**计费专用**字段(整数,driving video 的秒数),vendor 不读。不传时计费按 10s 兜底,可能少扣 —— 请用 dl ffmpeg / 上传 metadata 拿到真实长度后传过来。"],whenToUse:["You have a reference performance video and a target character image","You need multi-character motion transfer (dreamactor + --image-urls)"],whenNotToUse:["You want a clip generated from scratch — use `dl generate-video`","You need lip-sync (not body motion) — use `dl lipsync`"],examples:[{caption:"single, dreamactor (--duration 整 driving video 秒数,计费用)",command:"dl motion-control --service=dreamactor --video-url=https://v.mp4 --image-url=https://char.png --duration=12"},{caption:"multi-person, dreamactor (N image_urls ↔ N 角色 in driving video)",command:"dl motion-control --service=dreamactor \\\n --video-url=https://.../two-people-dancing.mp4 \\\n --image-urls=https://.../alice.png \\\n --image-urls=https://.../bob.png \\\n --duration=12"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed","data":{"url":"https://...mp4"}}',modelTopic:{rankingSummary:["2 services: dreamactor (fast + simple) / kling3.0-motion (quality + orientation control)."],services:[{service:"dreamactor",label:"DreamActor M2.0 (BytePlus)",tier:"Fast + simple",bestFor:"Single- or multi-character pose / motion transfer from video to image(s)",quality:"High",speed:"1-3min",cost:"low",description:["BytePlus DreamActor M2.0. General motion transfer, fast and with simple parameters.","Supports multi-person: pass N reference images via --image-urls and the driving video should contain N matching characters."],constraints:["GCS URL → api-layer rewrites to CDN URL automatically (BytePlus cannot reach GCS directly)","Recommend cut_first_second=true to drop the first-second transition artifact","Multi-person via --image-urls: 数组里每个 URL 对应 driving video 里一个角色,数量需匹配"],flagSubset:["service","video-url","image-url","image-urls","image-base64","cut-first-second"],examples:[{caption:"single, dreamactor",command:"dl motion-control --service=dreamactor \\\n --video-url=https://.../driving.mp4 \\\n --image-url=https://.../character.png \\\n --cut-first-second"},{caption:"multi-person, dreamactor (image_urls 数组)",command:"dl motion-control --service=dreamactor \\\n --video-url=https://.../two-people-dancing.mp4 \\\n --image-urls=https://.../alice.png \\\n --image-urls=https://.../bob.png \\\n --cut-first-second"}]},{service:"kling3.0-motion",label:"Kling 3.0 Motion",tier:"High quality + control",bestFor:"High-quality motion transfer + orientation control + quality tier + negative prompt",quality:"Very High",speed:"2-5min",cost:"mid",description:["Kling 3.0 Motion. Higher quality, supports:"," - character_orientation control (image / video)"," - tier (std / pro quality)"," - negative_prompt / prompt guidance"],constraints:["character_orientation='image' → character orientation follows the image; 'video' → follows the driving video","tier='pro' is higher quality than 'std' but slower"],flagSubset:["service","video-url","image-url","image-base64","character-orientation","tier","prompt","negative-prompt","sound"],examples:[{caption:"kling3.0-motion high quality + orientation",command:"dl motion-control --service=kling3.0-motion \\\n --video-url=https://.../driving.mp4 \\\n --image-url=https://.../character.png \\\n --character-orientation=image --tier=pro"}]}],decisionLogic:[{when:"Simple motion transfer, fast",pick:"dreamactor"},{when:"Need character orientation control / quality tier / negative prompt",pick:"kling3.0-motion"}]},preflightTopic:{intro:"Confirm these 3 items before the first dl motion-control call:",decisions:[{name:"Service",description:"dreamactor (fast and simple) or kling3.0-motion (high quality + control)."},{name:"Driving video + target character image(s)",description:"Driving video source + character image source.\nvideo_url is always required. Image source: exactly one of --image-url (single, both services) / --image-urls (multi-person, dreamactor only) / --image-base64 (single, both services). Missing all three or supplying more than one raises E_SCHEMA."},{name:"kling3.0-motion-specific",description:"If choosing kling3.0-motion, decide up front: character_orientation (image / video) +\ntier (std / pro) + whether to include prompt / negative_prompt / sound."}]},policyTopic:{rules:[{title:"1. User-Facing Communication",body:["Do not leak vendor / price / internal model code. Only mention service name + action (motion transfer)."]},{title:"2. Production Package Gate",body:["service / tier / task count / source video plan / target image plan /","character_orientation / sound / prompt are all components of the paid-package authorization.","Do not call before authorization; only re-ask on package overflow (switching service / tier / adding count /","replacing key inputs / fallback / paid regeneration)."]}]},compositionTopic:{intro:"This atomic skill only produces a motion-controlled video URL; artifact / canvas registration and other downstream responsibilities are not this verb's job.",integrations:[{skill:"right-side canvas (pi_media_log)",rule:["The atomic skill no longer performs dl artifact write / patch-json pi_media_log on your behalf — that is the composition layer's job."]}]},asyncTopic:{intro:["dl motion-control by default returns { job_ref, status: 'pending' } and exits immediately — do not poll.","Results are injected into the session as [async-callback] job=<ref> text; typical duration 1-5 minutes."],resultShape:['{ "url": "https://storage.googleapis.com/.../video.mp4", ... }'],notes:["The URL field is the atomic skill's sole product","vendor / internal metadata fields must not be leaked to the user"]},publishTopic:{intro:["After producing motion-controlled video URL, call publish_content with","presentation_family='video' + media fields."],fields:[{name:"presentation_family",value:"'video'"},{name:"media_urls.video",value:"<motion control output URL>"},{name:"delivery_format",value:"'video'"}]}})}(Tc),function(e){as(e,{verb:"generate-tts",actionName:"generate_tts",schema:Do,billing:{schema:Js,select:e=>({service:e.service,text:e.text}),quote:Ks},supportsBatch:!0,description:"Generate speech audio from text. `--provider` picks the backend (minimax / elevenlabs / elevenlabs-dialogue / voxcpm).",whenToUse:["You need synthetic speech from text","Multi-line / multi-voice via --jobs-file","As the first step of a talking-head pipeline; pipe the resulting `audio_url` into `dl lipsync`","You need to clone a specific real person's voice from a reference audio clip — use `--provider=voxcpm` with `--audio-url=<reference>` (self-hosted, not subject to MiniMax / ElevenLabs voice-library limits or platform moderation; the strongest option for arbitrary real-person cloning incl. copyright-sensitive voices)","You need a custom voice from a free-form voice description — use `--provider=voxcpm` without `--audio-url` and put the description in `--control`"],whenNotToUse:["You need a music track (vocals or instrumental) — use `dl generate-music`","You only need the lip-sync stage and already have the audio — use `dl lipsync` directly"],notes:["Per-provider routing is via `--provider` (extraFlag). The `--service` enum (minimax-tts / voxcpm) is selected to match the provider.","For minimax / elevenlabs / elevenlabs-dialogue, look up the voice id with `dl knowledge search --domain=voice --query=…`.","`--provider=voxcpm` does NOT use voice_id. Pass `--audio-url` (reference audio) to clone; omit it to synthesize from `--control` (voice description). See `dl generate-tts model voxcpm` for the full call shape."],examples:[{caption:"single, minimax (default)",command:'dl generate-tts --service=minimax-tts --text="Hello, world." --emotion=calm'},{caption:"elevenlabs single voice",command:'dl generate-tts --provider=elevenlabs --service=minimax-tts \\\n --voice-id=<elevenlabs_voice_id> --text="Hello, world." --speed=1'},{caption:"elevenlabs multi-voice dialogue",command:'dl generate-tts --provider=elevenlabs-dialogue --service=minimax-tts \\\n --text="Speaker turns…" --speed=1'},{caption:"voxcpm clone — clone a real person's voice from reference audio",command:'dl generate-tts --provider=voxcpm --service=voxcpm \\\n --audio-url=https://.../reference.m4a \\\n --text="要朗读的台词" --control="calm warm"'},{caption:"voxcpm prompt — synthesize from voice description (no reference audio)",command:'dl generate-tts --provider=voxcpm --service=voxcpm \\\n --text="要朗读的台词" --control="warm calm female narrator"'}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed","data":{"url":"https://...mp3"}}',extraFlags:[{spec:"--provider <name>",description:"backend route",default:"minimax",enum:Tl}],resolveActionName:e=>{const t=String(e.provider??"minimax"),i=Al[t];if(!i)throw new Error(`unknown --provider: ${t}; expected one of ${Tl.join(", ")}`);return i},modelTopic:{rankingSummary:["⚠ provider is selected via the `--provider` extraFlag. `--service` mirrors the chosen","provider (minimax-tts for the three platform providers; voxcpm for self-hosted voxcpm).","The four providers route to different backend actions / wire shapes:"," --provider=minimax → MiniMax TTS (default, multilingual + explicit pause control)"," --provider=elevenlabs → ElevenLabs single voice"," --provider=elevenlabs-dialogue → ElevenLabs multi-voice dialogue"," --provider=voxcpm → VoxCPM2 self-hosted (audio-reference voice cloning or description-based custom voice)"],services:[{service:"minimax",label:"MiniMax TTS",tier:"🥇 Default",bestFor:"Multilingual (Chinese / English / Japanese / etc.), explicit pause control, emotion control",quality:"High",speed:"30-60s",cost:"low",description:["MiniMax TTS, Pi's default provider.","Multilingual + emotion control via --emotion + <#X#> pause + language boost.","The voice library is searchable via dl knowledge search --domain=voice","(101 profiles: 40 Chinese + 61 English)."],promptTips:["Use native MiniMax markers only for deliberate pauses: <#X#> pause (X seconds, decimal); punctuation — long dashes / ... ellipsis are processed as natural short pauses","Keep --text to spoken words, punctuation, and pause markers; do not add inline emotion tags","Do not apply other TTS vendors' bracketed tags — MiniMax does not recognize them and reads them as literal characters","For code-mixed text, you must add --language-boost"],constraints:["voice_id must be found via dl knowledge search --domain=voice — do not rely on memory or fabricate","text length cap / model list / speed / vol / pitch / sample_rate / bitrate valid ranges all per --help"],flagSubset:["provider","service","text","voice-id","model","speed","vol","pitch","emotion","language-boost","format","sample-rate","bitrate"],examples:[{caption:"single, minimax default",command:'dl generate-tts --provider=minimax --service=minimax-tts \\\n --text="今天<#0.5#>真是个好天气,你看天上多蓝。" \\\n --voice-id=<voice_id> --emotion=calm --language-boost=auto'}]},{service:"elevenlabs",label:"ElevenLabs single voice",tier:"High-quality English / multilingual",bestFor:"ElevenLabs single voice. Higher quality, rich English / multilingual detail",quality:"Very High",speed:"30-60s",cost:"mid",description:["ElevenLabs single voice. Higher quality — suits scenarios that need the ElevenLabs distinctive voice library or","mixed Chinese-English / long-form narration.","","⚠ voice_id must be an ElevenLabs one, not MiniMax — use","dl knowledge search --domain=voice --query='<desc>' with filters to","pick a voice sourced from elevenlabs."],constraints:["voice_id must come from ElevenLabs — cannot use a MiniMax voice_id","--provider=elevenlabs (not --service)"],flagSubset:["provider","service","text","voice-id","model","speed"],examples:[{caption:"elevenlabs single voice",command:'dl generate-tts --provider=elevenlabs --service=minimax-tts \\\n --voice-id=<elevenlabs_voice_id> --text="Hello, world." --speed=1'}]},{service:"elevenlabs-dialogue",label:"ElevenLabs multi-voice dialogue",tier:"Multi-character dialogue",bestFor:"Multi-character dialogue synthesis (dialogue / interview / multi speaker turns)",quality:"Very High",speed:"1-2min",cost:"high",description:["ElevenLabs multi-voice dialogue. One call synthesizes dialogue across multiple speakers.","Usage differs from single voice — write text in multi-turn form and the vendor routes the voices itself."],constraints:["text must follow the vendor-expected multi-speaker format; run --print-schema for the exact schema"],flagSubset:["provider","service","text","speed"],examples:[{caption:"elevenlabs dialogue",command:'dl generate-tts --provider=elevenlabs-dialogue --service=minimax-tts \\\n --text="Speaker A: Hello.\\nSpeaker B: Hi there!" --speed=1'}]},{service:"voxcpm",label:"VoxCPM2 (self-hosted custom voice / real-person voice cloning)",tier:"Custom voice generator + strongest cloner — no platform voice-library limit",bestFor:"Create a custom voice from a free-form text description when no reference audio exists, or clone an arbitrary real person's voice from one reference audio clip. The strongest option when MiniMax / ElevenLabs voice libraries don't cover the target speaker or platform moderation rejects the request (incl. copyright-sensitive real-person voices). Also serves as the catch-all when no usable voice_id exists in the platform libraries.",quality:"Very High (clone fidelity scales with reference audio quality)",speed:"10-30s inference + 0-150s RunPod cold start",cost:"low (self-hosted, only pays RunPod GPU seconds)",description:["VoxCPM2 deployed on RunPod serverless (dramaland-ai-small). Self-hosted means it is","NOT subject to MiniMax / ElevenLabs platform voice-library boundaries or platform moderation —","any audio_url can be used as the reference timbre, including copyright-sensitive real-person","voices that ElevenLabs design-voice / voice-cloning would refuse.","","Two internal modes, automatically chosen by api-layer from the `--audio-url` field:"," - voiceclone (audio_url present) → reference audio + text → clone the audio's voice"," - voiceprompt (audio_url absent) → voice description + text → synthesize from description","","There is NO voice_id concept in voxcpm — voice identity is either the reference audio or","the textual description in --control."],promptTips:["`--audio-url` should be a clean 3-30s clip of the target voice; clearer reference → better clone fidelity","`--control` semantics flip by mode:"," - clone mode (with --audio-url): emotion / style controls, e.g. `calm`, `excited`, `whisper`"," - prompt mode (without --audio-url): voice description, e.g. `warm calm female narrator`"," English short phrases work best either way","voxcpm reads text literally — MiniMax pause markers like <#X#> are NOT recognized; use punctuation for pauses instead"],constraints:["text length cap 4096 characters","reference audio max 50MB; content-type must be audio/* (video / image refused)","clone mode requires `--audio-url`; if you don't have a reference clip, omit `--audio-url` (auto-falls to prompt mode)","do NOT pass --voice-id / --emotion / --language-boost / etc. — those are minimax-specific and ignored here","cold start can add up to ~150s on first call; the api-layer's async submit/poll handles this transparently — don't add your own retries"],flagSubset:["provider","service","text","audio-url","control"],examples:[{caption:"voxcpm clone — clone the voice in a reference audio",command:'dl generate-tts --provider=voxcpm --service=voxcpm \\\n --audio-url=https://.../target-voice.m4a \\\n --text="要朗读的台词" --control="calm"'},{caption:"voxcpm prompt — no reference audio, synthesize from voice description",command:'dl generate-tts --provider=voxcpm --service=voxcpm \\\n --text="要朗读的台词" --control="warm calm female narrator"'}]}],decisionLogic:[{when:"Default / Chinese / pause markers + request-level emotion",pick:"--provider=minimax (default)"},{when:"Need the ElevenLabs voice library / higher English quality",pick:"--provider=elevenlabs"},{when:"Multi-speaker dialogue synthesis",pick:"--provider=elevenlabs-dialogue"},{when:"Need to clone a specific real person's voice (target voice NOT in MiniMax/ElevenLabs libraries, or platform moderation refuses, or copyright-sensitive real-person voice)",pick:"--provider=voxcpm with --audio-url=<reference>"},{when:"Need a custom voice from a free-form text description, when no reference audio is available",pick:"--provider=voxcpm with --control='<voice description>' (no --audio-url)"}]},preflightTopic:{intro:"Confirm these 4 items before the first dl generate-tts call:",decisions:[{name:"Provider",description:"Which provider to use (minimax / elevenlabs / elevenlabs-dialogue / voxcpm). Decides the voice-identity mechanism + marker syntax + which flags are read.\n - minimax / elevenlabs / elevenlabs-dialogue → platform voice library (voice_id required)\n - voxcpm → no voice_id; supply --audio-url (clone) or --control (voice description)"},{name:"Voice identity",description:"For minimax / elevenlabs / elevenlabs-dialogue: search a voice_id via `dl knowledge search --domain=voice`\n(query is natural-language; filter fields / valid enums per `dl knowledge search --help`).\nFor voxcpm: either an `--audio-url` reference clip (clone) OR a textual `--control` voice description (prompt). voxcpm ignores voice_id."},{name:"Text preparation",description:"Prepare text per the chosen provider's marker syntax.\n - MiniMax: <#X#> pauses + standard punctuation for short pauses; set tone with --emotion instead of inline tags\n - voxcpm: plain text, no markers — punctuation only (markers are read literally)\n - elevenlabs / elevenlabs-dialogue: per ElevenLabs marker conventions (see model -h)"},{name:"Audio format",description:"format / sample_rate / bitrate — defaults are usually enough. Adjust only if downstream has special requirements (lipsync / concat). voxcpm's output format follows its handler default (mp3 / flac) and ignores these flags."}],notes:["If cost-sensitive → read pricing-and-policies-dramaland-faq/SKILL.md first","For batch generation use --jobs-file, do not block per item"]},policyTopic:{intro:"Five classes of hard rules: User-facing non-leak / Package gate / **Marker syntax discipline** / **TTS pronounceability discipline** / Failure fallback ladder.",rules:[{title:"1. User-Facing Communication — do not leak internal details",body:["vendor / price / internal model code / trace id must not be surfaced to the user.","User-facing summary only mentions: provider name (MiniMax / ElevenLabs) + character /","language + action (generate TTS / TTS dialogue)."]},{title:"2. Production Package Gate — do not call before paid authorization",body:["provider / model / voice_id / generation count / text segment range / text length / target","duration / audio format parameters / downstream usage are all components of the paid package authorization. Do not call before authorization;","within the same package you can batch; only re-ask on package overflow (switching model / voice / adding count /","changing format / fallback / paid regeneration)."]},{title:"3. MiniMax Marker syntax discipline (provider=minimax only)",body:["MiniMax marker syntax **must use native forms** — do not apply other TTS vendors' bracketed","tags (MiniMax does not recognize them and reads them as literal characters, producing noise).","Keep script text to spoken words, punctuation, and explicit pause markers; do not add inline emotion tags.","","### Pauses"," - <#X#>, X is seconds as a decimal (<#0.3#> / <#0.8#> / <#1.5#>)"," - Punctuation substitutes: long dashes (—) / ... ellipsis are processed naturally as short pauses","","### Emotion"," - Do not put inline emotion tags in --text"," - Per-request: attach --emotion=... (valid enum per --help)","","### Language hint"," - For code-mixed text, you must add --language-boost (valid values per --help)"]},{title:"4. TTS pronounceability discipline — hard constraint on the script side",body:["When writing the script, spell out complex numbers / currency / abbreviations / units / dates / ratios — **do not bet","on TTS getting them right on its own**. Simple integers (5 / 27 / 120) / bare 4-digit years (2024) / whole percentages","(50%) are usually OK; otherwise spell them out:",""," $1.4M → one point four million dollars"," 42.7% → forty-two point seven percent"," Q3 2024 → third quarter of twenty twenty-four"," 3:1 → three to one"," 42°F → forty-two degrees Fahrenheit"," ROI → R O I (spaces force letter-by-letter) or return on investment"," Chinese percent → 百分之四十二点七"," Chinese currency magnitude → 一点四亿美元 or 14 亿美元","","Mispronunciation can only be fixed by editing the caption — you cannot re-pronounce the audio — so **handle it at script time**."]},{title:"5. voxcpm input discipline (provider=voxcpm only)",body:["voxcpm reads text **literally**. Markers from other TTS vendors (MiniMax `<#X#>`, ElevenLabs","`[break]`, inline emotion tags) are NOT recognized and will be pronounced as","literal characters. Use plain text + punctuation for pauses.","","### Voice identity"," - Clone mode (with --audio-url): voice timbre comes from the reference audio; --control controls emotion / style (`calm` / `excited`)"," - Prompt mode (without --audio-url): voice timbre comes from the --control description (`warm calm female narrator`); English short phrases work best","","### Flags voxcpm ignores"," --voice-id / --emotion / --language-boost / --model / --sample-rate / --bitrate / --pitch / --vol"," (those are minimax-specific; voxcpm silently drops them)"]},{title:"6. Failure fallback ladder",body:["When this verb produces jitter / silence / clipping / content-moderation blocks, in order:","","1. Retry once (transient network / quota wobbles usually pass; voxcpm cold start can add ~150s)","2. Switch model / tune knobs: step within the model list listed by --help (high-quality vs fast)"," or tune speed / emotion / language_boost (minimax only)","3. Re-pick voice identity:"," - minimax / elevenlabs: pick another voice_id via dl knowledge search --domain=voice"," - voxcpm clone: try a cleaner / longer / different reference --audio-url"," - voxcpm prompt: refine --control description","4. Switch provider — esp. when MiniMax / ElevenLabs voice library cannot match the target speaker"," or platform moderation rejects: fall back to --provider=voxcpm with a reference audio.","5. Fall back to script changes: too long / too dense markers / too many hard-to-pronounce expressions → shorten + dilute"," markers + convert un-spelled-out complex numbers / abbreviations into pronounceable form (see rule 4)"]}]},compositionTopic:{intro:"This atomic skill only produces an audio URL; artifact / canvas registration and other downstream responsibilities are not this verb's job.",integrations:[{skill:"Voice ID search (dl knowledge search --domain=voice) — minimax / elevenlabs only",rule:["MiniMax voice library has 101 profiles (40 CN + 61 EN). Search:"," dl knowledge search --domain=voice --query='<natural-language description>' \\",' --filters-file=- <<<\'{"language":"CN","gender":"Female"}\'',"","For specific filter fields / valid enums see dl knowledge search --help.","","For the ElevenLabs voice library, filter via --filters-file with 'provider': 'elevenlabs'.","","voxcpm does NOT use this knowledge base — its voice identity is either the reference","--audio-url (clone) or the --control description (prompt). Skip voice search entirely","when --provider=voxcpm."]},{skill:"downstream lipsync / video composition",rule:["The generated audio_url can be fed directly into:"," - dl lipsync --audio-url=... (seedance 2.0 ≤ 15s / dlai2v ≤ 19s, see lipsync model -h)"," - dl generate-video --reference-audio-url=... (seedance 2.0 same 15s cap)","","Target duration must be aligned with the downstream audio duration cap during the generate-tts stage."]},{skill:"right-side canvas (pi_media_log)",rule:["The atomic skill no longer performs dl artifact write / patch-json pi_media_log on your behalf —","that is the composition layer's job."]}]},asyncTopic:{intro:["dl generate-tts by default returns { job_ref, status: 'pending' } and exits immediately — do not poll.","Results are injected into the session as [async-callback] job=<ref> text; typical duration 30s-2min.","","Only run dl poll separately when the next step strictly requires the result (immediately feeding lipsync / ffmpeg concat)."],resultShape:['{ "audio_url": "https://storage.googleapis.com/.../speech.mp3",',' "duration_ms": 3200,',' "format": "mp3",',' "usage_characters": 42 }'],notes:["audio_url is the atomic skill's sole product and can serve directly as a downstream reference_audio_url","vendor-internal metadata fields must not be leaked to the user"]},publishTopic:{intro:["After producing TTS audio URL, call publish_content with presentation_family='text',","media_urls.audio=<url>, delivery_format='audio'. The playbook 'Publishing Your Work /","text' template is the closest match; pass media_urls.audio explicitly (the runtime will not infer audio from","presentation_family)."],fields:[{name:"presentation_family",value:"'text'"},{name:"media_urls.audio",value:"<TTS audio URL>"},{name:"delivery_format",value:"'audio'"}]}})}(Tc),function(e){as(e,{verb:"clone-voice",actionName:"clone_voice",schema:Ho,billing:{schema:Ns,select:e=>({service:e.service}),quote:js},supportsBatch:!0,description:"Clone a voice from audio sample(s). Services: elevenlabs (multi-file), minimax (single file 10s-5min). Returns {voice_id, vendor} usable with `dl generate-tts`.",whenToUse:["You have a reference audio URL and want to create a reusable voice profile","`search-voice` returned no matching candidate voice — you must bring your own sample"],whenNotToUse:["You only need to look up an existing voice — use `dl knowledge search --domain=voice`","You only have a text description (no audio) — use `dl design-voice`"],notes:["ElevenLabs accepts multiple file URLs; MiniMax only uses files[0] (10s-5min).","MiniMax requires `voice_id` (8-256 chars, alphanumeric + `+-_`); the namespace is account-shared, pick a unique name to avoid colliding with others.","In the response, `vendor` determines downstream TTS: elevenlabs → `dl generate-tts --provider=elevenlabs`; minimax → `dl generate-tts` (default minimax)."],examples:[{caption:"ElevenLabs multi-file clone",command:'dl clone-voice \\\n --service=elevenlabs \\\n --name="British Narrator" \\\n --files=\'["https://example.com/sample1.mp3","https://example.com/sample2.mp3"]\' \\\n --description="A warm male voice"'},{caption:"MiniMax single-file clone",command:"dl clone-voice \\\n --service=minimax \\\n --voice-id=my_unique_voice_001 \\\n --files='[\"https://example.com/sample.mp3\"]' \\\n --language-boost=Chinese \\\n --need-noise-reduction"}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"voice_id":"<id>","vendor":"elevenlabs"}}',modelTopic:{rankingSummary:["2 vendors: elevenlabs (multi-file sample, stable on English content) / minimax (single file 10s-5min, Chinese-first + cheap).","The returned vendor field decides which --provider to use for downstream dl generate-tts."],services:[{service:"elevenlabs",label:"ElevenLabs Voice Clone",tier:"Multi-file + high quality",bestFor:"Multi-sample clone, more stable quality on English content. Ready to use immediately",quality:"Very High",speed:"30-60s",cost:"mid",description:["ElevenLabs accepts multiple URLs as samples; the cloned voice is usable immediately.","Returns {voice_id, vendor: 'elevenlabs'} → use with dl generate-tts --provider=elevenlabs."],constraints:["ElevenLabs account custom-voice quota pool is shared — a full pool raises an error; try search-voice first","Sample quality determines clone quality: noisy / too short / heavily compressed → bad voice; use clean 10s+ samples"],flagSubset:["service","name","files","description"]},{service:"minimax",label:"MiniMax Voice Clone",tier:"Single file + Chinese-first",bestFor:"Single sample (10s-5min). Cheap, stable performance on Chinese content",quality:"High",speed:"<60s",cost:"low",description:["MiniMax single-file clone — only uses files[0]. Returns {voice_id, vendor: 'minimax'} →","use with dl generate-tts (default provider=minimax)."],constraints:["voice_id is required (8-256 chars, alphanumeric + +-_)","⚠ MiniMax voice_id namespace is **shared across all agents** — add a unique prefix (agent role / hash) to avoid overwriting others","Single file, only files[0] is used; with multiple samples, merge the audio or pick the cleanest take"],flagSubset:["service","voice-id","files","language-boost","need-noise-reduction"]}],decisionLogic:[{when:"Multiple samples / English content / want more stable",pick:"elevenlabs"},{when:"Single sample / Chinese content / cost-priority",pick:"minimax"}]},policyTopic:{rules:[{title:"1. Output contract — vendor decides downstream TTS",body:["Returns {voice_id, vendor}. Downstream TTS calls must route by vendor:"," vendor=elevenlabs → dl generate-tts --provider=elevenlabs --voice-id=<id>"," vendor=minimax → dl generate-tts (default) --voice-id=<id>","To reuse the voice → record both voice_id and vendor; the ID alone does not tell you which TTS route to take."]},{title:"2. Sample-source compliance",body:["Only clone audio you or the platform owns / is authorized for. **Do not clone real people without their consent.**"]},{title:"3. MiniMax voice_id naming discipline",body:["MiniMax account voice_id namespace is shared across all agents. Prefix with your own agent","role or hash to avoid collisions. e.g. my_<agent>_<purpose>_<random>."]}]},compositionTopic:{intro:"This verb is the entry point to the voice-creation pipeline. The returned voice_id + vendor are the inputs for downstream TTS.",integrations:[{skill:"downstream dl generate-tts",rule:["Pass voice_id directly as --voice-id; vendor decides --provider (elevenlabs / minimax).","For marker syntax / pronunciation discipline see dl generate-tts policy -h."]},{skill:"search-voice (try first)",rule:["Before cloning, try dl knowledge search --domain=voice. The library has 197 curated voices","(101 MiniMax + 96 ElevenLabs); searching first to find a hit saves cost and time over cloning."]}]}})}(Tc),function(e){as(e,{verb:"design-voice",actionName:"design_voice",schema:Jo,billing:{schema:Cs,select:e=>({service:e.service}),quote:Rs},supportsBatch:!0,description:"Design a voice from a text description. ElevenLabs: 2-step (preview → finalize_voice). MiniMax: 1-step permanent. Returns vendor + (voice_id | generated_voice_id).",whenToUse:['You have a textual voice description (e.g. "warm British male narrator") but no audio sample'],whenNotToUse:["You have audio — use `dl clone-voice`","You want to tweak an existing voice — use `dl remix-voice`"],notes:["ElevenLabs returns `previews[].generated_voice_id` — you must call `dl finalize-voice` **as the very next call**; do not insert unrelated tool calls in between or the preview expires.","MiniMax returns `voice_id` + `trial_audio` directly, no finalize step needed."],examples:[{caption:"ElevenLabs preview",command:'dl design-voice \\\n --service=elevenlabs \\\n --voice-description="A deep male voice with a British accent" \\\n --text="Hello, this is a sample of the generated voice."'},{caption:"MiniMax one-step",command:'dl design-voice \\\n --service=minimax \\\n --prompt="温柔的年轻女性声音,语速适中" \\\n --preview-text="你好,这是一段用于试听的文本。" \\\n --voice-id=my_designed_voice_001'}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"vendor":"elevenlabs","previews":[{"generated_voice_id":"<preview_id>",...}]}}',modelTopic:{rankingSummary:["2 vendors, with **completely different flows**:"," - elevenlabs: 2-step (design → finalize), preview expires quickly"," - minimax: 1-step, permanent immediately, includes trial_audio"],services:[{service:"elevenlabs",label:"ElevenLabs Design Voice",tier:"2-step flow",bestFor:"English voice description → preview → finalize for permanent voice",quality:"Very High",speed:"30s + finalize",cost:"mid",description:["ElevenLabs 2-step: design returns previews[].generated_voice_id, and the **next tool","call** must be dl finalize-voice to persist it. Wait too long in between and the preview expires → re-run."],constraints:["⚠ ElevenLabs preview **expires quickly** — the next tool call after design must be finalize-voice","Inserting an unrelated tool call in between → preview expired / 404 → re-run design"],flagSubset:["service","voice-description","text"]},{service:"minimax",label:"MiniMax Design Voice",tier:"1-step permanent",bestFor:"Chinese voice description → directly produces permanent voice_id + trial_audio",quality:"High",speed:"<60s",cost:"low",description:["MiniMax 1-step: returns {voice_id, vendor:'minimax', trial_audio} directly.","No finalize step needed, **ready to use immediately**."],constraints:["voice_id required (same naming rules as clone-voice + shared namespace across agents)","Add a unique prefix to avoid overwriting others"],flagSubset:["service","prompt","preview-text","voice-id"]}],decisionLogic:[{when:"English voice description + want more stable quality",pick:"elevenlabs (remember finalize must immediately follow design)"},{when:"Chinese voice description / ready to use immediately",pick:"minimax (1 step produces permanent voice)"}]},policyTopic:{rules:[{title:"1. ⚠ ElevenLabs preview expires quickly — finalize must immediately follow",body:["The previews[].generated_voice_id returned by ElevenLabs design-voice has a short TTL.","**finalize-voice must be the next tool call** — do not insert unrelated tool calls.","If you see 'preview expired' / 404 → re-run design-voice.","","Call: dl finalize-voice --service=elevenlabs"," --generated-voice-id=<preview_id>"," --voice-name='...' --voice-description='...'"]},{title:"2. Output contract — vendor decides downstream",body:["vendor=elevenlabs → must finalize-voice first to get the permanent voice_id, then"," dl generate-tts --provider=elevenlabs","vendor=minimax → voice_id is already permanent, go straight to dl generate-tts (default)"]},{title:"3. MiniMax voice_id naming discipline",body:["Same as clone-voice: namespace is shared across agents, add a unique prefix."]}]},compositionTopic:{intro:"design-voice is the entry point for voice creation; the flow branches based on vendor.",integrations:[{skill:"ElevenLabs 2-step flow",rule:["step 1: dl design-voice --service=elevenlabs --voice-description='...' --text='...'"," → previews[].generated_voice_id","step 2 (immediately next call): dl finalize-voice --service=elevenlabs"," --generated-voice-id=<preview_id> --voice-name='...' --voice-description='...'"," → permanent voice_id","step 3: dl generate-tts --provider=elevenlabs --voice-id=<final_id> --text='...'"]},{skill:"MiniMax 1-step flow",rule:["step 1: dl design-voice --service=minimax --prompt='...' --voice-id=<unique>"," → {voice_id, vendor:minimax, trial_audio}","step 2: dl generate-tts --voice-id=<voice_id> --text='...' (default minimax)"]}]}})}(Tc),function(e){as(e,{verb:"finalize-voice",actionName:"finalize_voice",schema:Ko,billing:{schema:Ps,select:e=>({service:e.service}),quote:Ms},supportsBatch:!1,description:"Finalize an ElevenLabs voice preview (from design-voice or remix-voice) into a permanent voice_id. ElevenLabs-only — MiniMax returns 422.",whenToUse:["The previous `dl design-voice` or `dl remix-voice` step returned `generated_voice_id` and you want to turn it into a permanent voice_id"],whenNotToUse:["MiniMax — its design/clone is already 1-step, no finalize needed"],notes:["ElevenLabs preview TTL is short — call this **immediately after the previous step**; do not insert other tool calls in between.",'If you see a "preview expired" / 404 error, re-run `dl design-voice` or `dl remix-voice`.'],examples:[{caption:"turn the preview into a permanent voice",command:'dl finalize-voice \\\n --service=elevenlabs \\\n --generated-voice-id=<preview_id> \\\n --voice-name="British Narrator" \\\n --voice-description="A deep male voice with a British accent"'}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"voice_id":"<final_id>","vendor":"elevenlabs"}}',policyTopic:{rules:[{title:"1. ⚠ ElevenLabs-only — MiniMax returns 422",body:["This verb is ElevenLabs-only (MiniMax design/clone is already 1-step permanent, no finalize needed).","Calling dl finalize-voice against MiniMax returns 422."]},{title:"2. ⚠ Must immediately follow design-voice / remix-voice",body:["ElevenLabs preview TTL is short. **finalize-voice must be the next tool call","after design/remix** — do not insert unrelated tools in between. If you see","'preview expired' / 404 → re-run design-voice or remix-voice; do not keep trying to","finalize with an old generated_voice_id."]},{title:"3. Output contract",body:["On success returns {voice_id, vendor:'elevenlabs'} → permanent. Immediately usable with:"," dl generate-tts --provider=elevenlabs --voice-id=<final_id>"]}]},compositionTopic:{intro:"Only used as step 2 of the ElevenLabs 2-step voice creation flow.",integrations:[{skill:"ElevenLabs 2-step flow",rule:["Must be preceded by dl design-voice / dl remix-voice.","Take previews[].generated_voice_id and **immediately** pass it as --generated-voice-id;","do not insert other tool calls in between."]}]}})}(Tc),function(e){as(e,{verb:"remix-voice",actionName:"remix_voice",schema:Yo,billing:{schema:ul,select:e=>({service:e.service}),quote:pl},supportsBatch:!1,description:"Remix an existing ElevenLabs voice (pitch / accent / etc.). ElevenLabs-only — source voice_id must be a voice the agent created. Returns a preview; finalize next.",whenToUse:["You have an existing ElevenLabs voice_id that you created and want to tweak it (higher pitch / different accent / etc.)"],whenNotToUse:["You want to remix a platform built-in voice — not supported, you can only remix voices you created yourself","MiniMax — remix is ElevenLabs-only"],notes:["After getting back `generated_voice_id`, call `dl finalize-voice` **immediately** — preview TTL is short."],examples:[{caption:"raise pitch + change accent",command:'dl remix-voice \\\n --service=elevenlabs \\\n --voice-id=<existing_voice_you_created> \\\n --voice-description="Make the voice higher pitched with a Boston accent" \\\n --text="Hello, this is a test of the remixed voice."'}],outputSingle:'{"ok":true,"job_ref":"<uuid>","status":"completed",\n "data":{"vendor":"elevenlabs","previews":[{"generated_voice_id":"<preview_id>",...}]}}',policyTopic:{rules:[{title:"1. ⚠ ElevenLabs-only + can only remix voices you created yourself",body:["This verb is ElevenLabs-only (MiniMax does not support remix).","**You can only remix voices that you (the agent) previously created** — you cannot remix platform built-in voices.","If source voice_id was not created by the agent → fails."]},{title:"2. ⚠ Must immediately follow with finalize",body:["remix returns previews[].generated_voice_id with the same short TTL as design-voice:","**the next tool call must be dl finalize-voice**. Insert something else in between →","preview expired → re-run remix."]},{title:"3. Output contract",body:["Returns {generated_voice_id, vendor:'elevenlabs'} → finalize to get the permanent voice_id","→ dl generate-tts --provider=elevenlabs."]}]},compositionTopic:{intro:"remix is fine-tuning of an existing voice — a 2-step flow (same shape as design-voice).",integrations:[{skill:"ElevenLabs remix 2-step flow",rule:["step 1: dl remix-voice --service=elevenlabs --voice-id=<existing> --voice-description='...'"," → previews[].generated_voice_id","step 2 (immediately next call): dl finalize-voice --service=elevenlabs"," --generated-voice-id=<preview_id> --voice-name='...' --voice-description='...'","step 3: dl generate-tts --provider=elevenlabs --voice-id=<final_id> --text='...'"]}]}})}(Tc),function(e){as(e,{verb:"detect-shots",actionName:"detect_shots",schema:Qo,billing:{schema:Is,select:()=>({}),quote:Ls},supportsBatch:!1,description:"Detect shot boundaries via TransNetV2. Synchronous — returns the shot list directly.",whenToUse:["You need shot-level segmentation of a video for breakdown / analysis"],whenNotToUse:["You need a transcript of the video's audio — use `dl transcribe`","You need beat / tempo of the audio track — use `dl analyze-beats`"],examples:[{caption:"default threshold",command:"dl detect-shots --video-url=https://example.com/clip.mp4 --output-format=full"}],outputSingle:'{"ok":true,"success":true,"shots":[{"index":0,"start_time":0,"end_time":7.97,...}, ...]}'})}(Tc),function(e){as(e,{verb:"download-media",actionName:"download_media",schema:er,billing:{schema:zs,select:()=>({}),quote:qs},supportsBatch:!1,description:"Download social-media media (TikTok / Instagram / Twitter / Bilibili / …) and re-host on CDN.",notes:["Sources supported: TikTok, Instagram, Twitter/X, Bilibili, and most cobalt-supported sites.","YouTube is currently NOT supported. Limits: ≤500MB per asset, 30 requests/minute."],whenToUse:["You have a social-media URL and need a persistent CDN copy for downstream tools"],whenNotToUse:["The URL is a YouTube link — not supported; surface the limitation to the user instead","You only need to fetch+extract HTML/text — use `dl fetch`"],examples:[{caption:"auto format",command:"dl download-media --url=https://www.tiktok.com/@user/video/123 --format=auto"}],outputSingle:'{"ok":true,"success":true,"data":{"url":"https://storage.../media.mp4"}}',preflightTopic:{intro:"Confirm these 2 items before the first dl download-media call:",decisions:[{name:"Source platform",description:"Supported: TikTok / Instagram / Twitter / Bilibili / Reddit / Vimeo /\nSoundCloud / Twitch / Pinterest / Dailymotion / Loom / Rutube / Streamable.\n**YouTube is NOT supported** (anti-bot block) — if the user gives a YouTube link,\nsurface the limitation; do not retry blindly."},{name:"Format / quality",description:"--format=auto (default) / video / audio / image.\n--video-quality: default is usually enough; on large files + file_too_large error → lower\nquality and retry."}],notes:["≤500MB per file","30 req/min/instance (rate limit)","Synchronous call, no dl poll"]},policyTopic:{rules:[{title:"1. Error handling loop (full error-code table)",body:["When error_code is returned, handle per the table:",""," rate_limited → wait the hinted seconds and retry"," cobalt_unavailable → ~30s retry"," download_timeout → ~30s retry"," gcs_upload_failed → ~30s retry"," content_not_found → unrecoverable, tell the user the source is unreachable"," content_requires_auth → same as above (common for YouTube)"," content_geo_restricted → same as above"," content_age_restricted → same as above"," file_too_large → lower video_quality or --format=audio and retry"," local_processing_required → same as above"," platform_unsupported → unrecoverable, platform not supported"," internal_error / service_misconfigured → escalate (do not retry)"]},{title:"2. Warning handling",body:["warning_code: gcs_fallback → R2 upload failed, the URL is a temporary direct link that may expire."," If you need a persistent URL, re-run.","","warning_code: picker_first_only → the source has multiple items (e.g. Instagram carousel),"," only the first was taken. For others, the source URL must explicitly point to the specific item."]},{title:"3. YouTube hard-unsupported",body:["YouTube links are currently blocked by anti-bot and return content_requires_auth.","Do not retry blindly — tell the user that YouTube is not supported."]}]},compositionTopic:{intro:"The download result is a persistent CDN URL on our R2 — feed it directly into downstream verbs / artifacts. Do NOT pass to upload_file (it is already hosted by us).",integrations:[{skill:"downstream verbs using the downloaded URL",rule:["output_url is public + permanent and can be passed directly to:"," - dl generate-video --image-urls=... / --ref-video-url=..."," - dl lipsync --image-url=... / --audio-url=..."," - dl render-caption / dl ffmpeg, etc.","","If you hit warning_code: gcs_fallback, re-run first to get a stable URL before feeding downstream;","do not risk expiration."]}]},asyncTopic:{intro:["⚠ dl download-media is **synchronous** (supportsBatch=false). The response includes output_url","+ filename + content_type + file_size_bytes + source_platform and other fields.","Typical duration 5-15s (short clips) / up to 120s (large files)."],resultShape:['{ "ok": true, "success": true,',' "data": { "output_url": "https://public.ilands.ai/.../media.mp4",',' "filename": "...",',' "content_type": "video/mp4",',' "file_size_bytes": 12345678,',' "source_platform": "tiktok" } }']}})}(Tc),function(e){as(e,{verb:"geocode",actionName:"geocode",schema:nr,billing:{schema:Qs,select:e=>({mode:"string"==typeof e.address&&e.address.trim()?"forward":"reverse"}),quote:el},supportsBatch:!1,description:"Forward (address → coords) or reverse (coords → address) geocoding.",notes:["Pass exactly one of: `--address` (forward) OR `--latitude`+`--longitude` (reverse).","Provider auto-routes by region (Google globally, AMap inside China, Panoramax in France)."],whenToUse:["You need to look up coordinates for a place name, or a place name for coordinates"],whenNotToUse:["You need a list of POIs near a point — use `dl places search`"],examples:[{caption:"forward",command:'dl geocode --address="Tokyo Tower, Tokyo"'},{caption:"reverse",command:"dl geocode --latitude=35.6586 --longitude=139.7454"}],outputSingle:'{"ok":true,"success":true,"data":{...}}'})}(Tc),function(e){const t=e.command("streetview").description("Street-level imagery and coverage info (Google / AMap / Panoramax).");as(t,{verb:"metadata",actionName:"streetview_metadata",schema:ir,billing:{schema:bl,select:()=>({}),quote:_l},supportsBatch:!1,description:"Check street-view coverage at coordinates. Low-cost — call before `dl streetview image`.",whenToUse:["You're about to fetch a streetview image but want to confirm coverage exists first"],examples:[{caption:"coverage probe",command:"dl streetview metadata --latitude=35.6586 --longitude=139.7454"}]}),as(t,{verb:"image",actionName:"streetview_image",schema:tr,billing:{schema:vl,select:()=>({}),quote:yl},supportsBatch:!1,description:"Street-level image at coordinates; auto-routes provider (Google / AMap / Panoramax).",whenToUse:["You need a ground-level photo at known coordinates"],examples:[{caption:"with view direction",command:"dl streetview image --latitude=35.6586 --longitude=139.7454 --heading=90 --pitch=0 --fov=90"}]})}(Tc),function(e){const t=e.command("places").description("Search places / POIs near coordinates and fetch their photos.");as(t,{verb:"search",actionName:"places_search",schema:or,billing:{schema:cl,select:()=>({}),quote:dl},supportsBatch:!1,description:"Search places / POIs near coordinates by keyword.",whenToUse:["You need a list of places matching a keyword near a known location"],examples:[{caption:"ramen near Tokyo Tower",command:"dl places search --query=ramen --latitude=35.6586 --longitude=139.7454 --radius=500"}]}),as(t,{verb:"photo",actionName:"place_photo",schema:rr,billing:{schema:sl,select:()=>({}),quote:ll},supportsBatch:!1,description:"Fetch a photo by photo_reference (returned from `dl places search`).",whenToUse:["You have a photo_reference token from places search and want to materialise the image"],examples:[{caption:"default size",command:"dl places photo --photo-reference=<token> --max-width=1600"}]})}(Tc),function(e){as(e,{verb:"static-map",actionName:"static_map",schema:ar,billing:{schema:fl,select:()=>({}),quote:gl},supportsBatch:!1,description:"Bird's-eye view map image at coordinates with optional markers.",notes:["`--size` is `WIDTHxHEIGHT` in pixels (e.g. `600x400`); both must be positive integers."],whenToUse:["You need a static map tile centred on coordinates for embedding / reference"],whenNotToUse:["You need a street-level photo, not a top-down map — use `dl streetview image`","You need to search for POIs at the location — use `dl places search`"],examples:[{caption:"default",command:"dl static-map --latitude=35.6586 --longitude=139.7454 --zoom=15 --size=600x400"}],outputSingle:'{"ok":true,"success":true,"data":{"url":"https://storage.../map.png"}}'})}(Tc),function(e){e.command("ffmpeg").description("Run raw ffmpeg / ffprobe in the remote ffmpeg sandbox. Synchronous by default (returns URL or probe JSON). Pass --async for long encodes — returns { status: 'pending', job_ref } and resumes via [async-callback].").addHelpText("after",["","Routing guidance:"," ffprobe / -c copy / 简单 trim 用本地 ffmpeg (秒级)。"," -c:v 重编码 / filter_complex / 输入 >2min 走 dl ffmpeg (同步, 默认)。"," >5min 编码 / MV 长任务 加 --async 走 callback (远程 sandbox 上限 1800s)。","","Sync mode (default):"," Polls until done or --timeout-ms expires. Default budget 10min;"," wrap with bash { timeout: N } to extend past the 5min sandbox cap.","","Async mode (--async):"," Returns { status: 'pending', job_ref } immediately. End the turn —"," result arrives as [async-callback] job=<ref> in a later turn."," Do NOT poll, do NOT re-submit, do NOT sleep/while wait.","","Example (sync, 默认):"," cat <<EOF | dl ffmpeg --command-file=- --input=src=https://…"," ffprobe -v quiet -print_format json -show_format -show_streams /input/src"," EOF","","Example (async, 长编码):"," cat <<EOF | dl ffmpeg --async --command-file=- --input=src=https://…"," ffmpeg -i /input/src -c:v libx264 -preset medium -crf 23 /output/out.mp4"," EOF"," # 命令立刻返回 pending; end turn 等 [async-callback]。"].join("\n")).option("--command <text>",'RECOMMENDED: ffmpeg/ffprobe command line inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --command "$(cat cmd.txt)" — keeps multi-line content out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --command-file.').option("--command-file <path|->",'LEGACY: ffmpeg/ffprobe command line as raw text via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --command "$(cat file)". Use --command-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--input <name=url>","name=url for /input/{name}; pass multiple --input flags",(e,t={})=>{const i=e.indexOf("=");if(i<=0)throw new J(`--input expects name=url, got ${e}`);return t[e.slice(0,i)]=e.slice(i+1),t},{}).option("--output-kind <tag>","classification tag echoed back in the response").option("--timeout <s>","sandbox-side timeout seconds (capped at 1800)",e=>Number(e)).option("--agent-id <n>","",e=>Number(e)).option("--async","async callback mode: return { status: 'pending', job_ref } immediately, resume via [async-callback]. Default is sync polling.").option("--timeout-ms <n>","[sync only] client polling budget (default 600000 = 10min)",e=>Number(e)).option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").action(async e=>{e.printSchema&&ms({command:"dl ffmpeg",summary:"Run raw ffmpeg / ffprobe in the remote sandbox. Synchronous by default (returns URL or probe JSON). Pass --async for long encodes — returns { status: 'pending', job_ref } and resumes via [async-callback].",scalars:[{name:"input",type:"string",required:!1,description:"name=url; repeatable; mounted as /input/<name>"},{name:"output-kind",type:"string",required:!1,description:"tag echoed back in response"},{name:"timeout",type:"integer",required:!1,description:"sandbox timeout seconds (capped at 1800)"},{name:"agent-id",type:"integer",required:!1,description:""},{name:"async",type:"boolean",required:!1,description:"async callback mode (default is sync polling)"},{name:"timeout-ms",type:"integer",required:!1,description:"[sync only] client polling budget (default 600000)"},{name:"command",type:"string",required:!1,description:"RECOMMENDED inline ffmpeg/ffprobe command line (required: pass this or --command-file)"}],files:[{name:"command-file",required:!1,kind:"text",description:"LEGACY: ffmpeg/ffprobe command line via file/stdin (prefer --command inline)",example:'ffmpeg -i /input/a -i /input/b -filter_complex "[0:v][1:v]overlay" /output/out.mp4'}]});let t,i="";try{const n=await Pa(e.command?String(e.command):void 0,e.commandFile?String(e.commandFile):void 0,{inline:"--command",file:"--command-file"});n&&(i=n.raw.trim(),t=n.label)}catch(e){throw e instanceof Yr&&Ha(e),e}i||Da("E_SCHEMA","--command is required (pass the ffmpeg command inline, or use --command-file for the legacy file/stdin path)",Ol("run `dl ffmpeg --print-schema` to see the expected shape"),{flag:"--command"});const n=e.input&&Object.keys(e.input).length>0?e.input:void 0,o=!0===e.async;Ba({command:"ffmpeg",ffmpeg_command:i,inputs:n??null,source:t??null,mode:o?"async":"sync"});const r=f();try{let t;if(o&&(t=function(e){const t=(process.env.CALLBACK_SERVER_URL??"").replace(/\/+$/,"");if(!t)throw new oa("CALLBACK_SERVER_URL not set — async ffmpeg submit needs it for the vendor callback target","hono-pi-e2b injects this on every commands.run; drop --async to use the default polling path, or set it manually in LOCAL_SANDBOX dev");const i=(process.env.PI_PROJECT_ID??"").trim();if(!i)throw new oa("PI_PROJECT_ID not set — required for callback URL routing under callback-resume v2","hono-pi-e2b injects PI_PROJECT_ID on every commands.run; drop --async to use the default polling path, or set it manually in LOCAL_SANDBOX dev");return`${t}/callback/${encodeURIComponent(i)}/${e}`}(r)),await ua("ffmpeg-sandbox","cli",{job_id:r,command:i,...n?{inputs:n}:{},...void 0!==e.timeout?{timeout:Number(e.timeout)}:{},...void 0!==e.agentId?{agent_id:Number(e.agentId)}:{},...e.outputKind?{output_kind:String(e.outputKind)}:{},...t?{callback_url:t}:{}}),o)return Va({action:"ffmpeg",job_ref:r,mode:"single"}),void Ua({ok:!0,status:"pending",job_ref:r,output_kind:e.outputKind??null});const a=await async function(e,t){const i=Date.now();for(;Date.now()-i<t;){const t=await pa("ffmpeg-sandbox",`jobs/${e}`,{},{timeoutMs:3e4,retries:0});if("completed"===t.status)return t.data??t;if("failed"===t.status)throw new Error(`ffmpeg-sandbox: ${t.error??"failed"}`);await new Promise(e=>setTimeout(e,2e3))}throw new Error(`ffmpeg-sandbox: timeout after ${t}ms`)}(r,e.timeoutMs??6e5);Ua({ok:!0,output_kind:e.outputKind??null,data:a})}catch(e){e instanceof oa&&Fa(e.message,Ol(e.hint)),Fa(e instanceof Error?e.message:String(e),El)}})}(Tc),function(e){e.command("remotion").description("Render a Remotion composition.").addHelpText("after",["","`--source-file` is the LOCAL path to a Component.tsx file readable at","runtime — dl reads it, ships the source through the gateway, and the","renderer compiles it server-side. No upload step required.","","Example (stdin for inputProps):"," cat <<EOF | dl remotion --source-file=/workspace/remotion/title_card.tsx \\"," --duration-in-frames=120 --fps=30 --width=1080 --height=1920 \\"," --input-props-file=-",' {"title":"Hello"}'," EOF"].join("\n")).option("--source <text>",'RECOMMENDED: Component.tsx source inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --source "$(cat title_card.tsx)" — keeps multi-line content out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --source-file.').option("--source-file <path>",'LEGACY: local path to a Component.tsx file (read at submit time, shipped server-side). File content is invisible to the billing extension + dl adapter, so prefer --source "$(cat file)". Use --source-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--duration-in-frames <n>","",e=>Number(e)).option("--fps <n>","",e=>Number(e)).option("--width <n>","",e=>Number(e)).option("--height <n>","",e=>Number(e)).option("--composition-id <id>").option("--input-props <inline-json>",'RECOMMENDED: JSON inputProps inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --input-props "$(cat props.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --input-props-file.').option("--input-props-file <path|->",'LEGACY: JSON inputProps via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --input-props "$(cat file)". Use --input-props-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--agent-id <n>","",e=>Number(e)).option("--timeout-ms <n>","client polling budget (default 900000 = 15min)",e=>Number(e)).option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").action(async e=>{let t,i,n,o;if(e.printSchema&&ms({command:"dl remotion",summary:"Render a Remotion composition.",scalars:[{name:"source",type:"string",required:!1,description:"RECOMMENDED inline Component.tsx source (required: pass this or --source-file)"},{name:"source-file",type:"string",required:!1,description:"LEGACY: absolute path to a Component.tsx (prefer --source inline)"},{name:"duration-in-frames",type:"integer",required:!0,description:""},{name:"fps",type:"integer",required:!1,description:""},{name:"width",type:"integer",required:!1,description:""},{name:"height",type:"integer",required:!1,description:""},{name:"composition-id",type:"string",required:!1,description:""},{name:"agent-id",type:"integer",required:!1,description:""},{name:"timeout-ms",type:"integer",required:!1,description:""},{name:"input-props",type:"string",required:!1,description:"RECOMMENDED inline JSON inputProps (sibling of --input-props-file)"}],files:[{name:"input-props-file",required:!1,kind:"object",description:"LEGACY: JSON inputProps via file/stdin (prefer --input-props inline)",example:'{"title":"Hello"}'}]}),e.source||e.sourceFile||Da("E_SCHEMA","--source is required (pass the Component.tsx inline, or use --source-file for the legacy file path)","pi skills should pass the component inline via --source, or an absolute path via --source-file",{flag:"--source"}),e.source&&e.sourceFile&&Da("E_SCHEMA","--source and --source-file are mutually exclusive","prefer --source (inline); file content is invisible to the billing extension / dl adapter",{inline_flag:"--source",file_flag:"--source-file"}),void 0===e.durationInFrames&&Da("E_SCHEMA","--duration-in-frames is required",void 0,{flag:"--duration-in-frames"}),e.source)t=String(e.source),i="inline";else{try{t=await g(String(e.sourceFile),"utf8")}catch(t){const i=t instanceof Error?t.message:String(t);Da("E_FILE_MISSING",`--source-file: cannot read ${e.sourceFile} (${i})`,"make sure the path exists in the sandbox",{flag:"--source-file",given:String(e.sourceFile)})}i=String(e.sourceFile)}t||Da("E_SCHEMA",e.source?"--source is empty":"--source-file is empty","pi skills should resolve the component via --source (inline) or an absolute --source-file path.",{flag:e.source?"--source":"--source-file"});try{const t=await qa(e.inputProps?String(e.inputProps):void 0,e.inputPropsFile?String(e.inputPropsFile):void 0,{inline:"--input-props",file:"--input-props-file"});t&&(n=t.data,o=t.source.label)}catch(e){throw e instanceof Yr&&Ha(e),e}Ba({command:"remotion",source_file:i,input_props:n??null,input_props_source:o??null});const r=f(),a={source:"dl",event:"remotion_render",credits:20,command:(s={command:"remotion",action:"remotion_render"}).command,action:s.action??"remotion_render",details:{rule:"remotion.fixed"}};var s;const l={source_code:t,duration_in_frames:Number(e.durationInFrames),...e.compositionId?{composition_id:String(e.compositionId)}:{},...void 0!==e.fps?{fps:Number(e.fps)}:{},...void 0!==e.width?{width:Number(e.width)}:{},...void 0!==e.height?{height:Number(e.height)}:{},...n?{input_props:n}:{}};let c=!1;try{await ua("remotion","renders",{job_id:r,params:l,agent_id:e.agentId??0},{billing:{jobRef:r,quote:a}}),c=!0;const t=await async function(e,t){const i=Date.now();for(;Date.now()-i<t;){const t=await pa("remotion",`renders/${e}`,{},{timeoutMs:3e4,retries:0});if("completed"===t.status)return t.data??t;if("failed"===t.status)throw new Error(`remotion: ${t.error??"failed"}`);await new Promise(e=>setTimeout(e,2e3))}throw new Error(`remotion: timeout after ${t}ms`)}(r,e.timeoutMs??9e5);Ua({ok:!0,job_ref:r,data:t,billing:a})}catch(e){c&&await async function(e){try{await da({jobRef:e.jobRef,quote:e.quote,reason:e.reason})}catch(t){process.stderr.write(`${JSON.stringify({level:"warn",event:"dl_billing_refund_failed",job_ref:e.jobRef,reason:e.reason,error:t instanceof Error?t.message:String(t)})}\n`)}}({jobRef:r,quote:a,reason:"remotion_render_failed"}),e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:r}),e instanceof oa&&Fa(e.message,e.hint,{job_ref:r}),Fa(e instanceof Error?e.message:String(e),void 0,{job_ref:r})}})}(Tc),function(e){e.command("hyperframes").description("Render a HyperFrames HTML composition to MP4 (remote fallback path).").addHelpText("after",["","`--source-file` is the LOCAL path to a `.html` composition file —","dl reads it, ships the source through the gateway, and the renderer","runs hyperframes CLI server-side. No upload step required.","","Prefer local `npx hyperframes render` for short renders; use `dl","hyperframes` when sandbox CPU/memory limits are hit or the job is","large enough to want the GCS-uploaded output URL directly.","","Example (stdin for inputProps):"," cat <<EOF | dl hyperframes --source-file=/workspace/hf/title-card.html \\"," --duration-in-frames=120 --fps=30 --width=1080 --height=1920 \\"," --input-props-file=-",' {"title":"Hello"}'," EOF"].join("\n")).option("--source <text>",'RECOMMENDED: HTML composition source inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --source "$(cat title-card.html)" — keeps multi-line content out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --source-file.').option("--source-file <path>",'LEGACY: local path to an HTML composition file (read at submit time, shipped server-side). File content is invisible to the billing extension + dl adapter, so prefer --source "$(cat file)". Use --source-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--duration-in-frames <n>","",e=>Number(e)).option("--fps <n>","",e=>Number(e)).option("--width <n>","",e=>Number(e)).option("--height <n>","",e=>Number(e)).option("--composition-id <id>").option("--input-props <inline-json>",'RECOMMENDED: JSON inputProps inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --input-props "$(cat props.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --input-props-file.').option("--input-props-file <path|->",'LEGACY: JSON inputProps via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --input-props "$(cat file)". Use --input-props-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--agent-id <n>","",e=>Number(e)).option("--timeout-ms <n>","client polling budget (default 900000 = 15min)",e=>Number(e)).option("--print-schema","print scalar+file schema and exit").option("--echo-parsed","echo canonical parsed input on stderr").action(async e=>{let t,i,n,o;if(e.printSchema&&ms({command:"dl hyperframes",summary:"Render a HyperFrames HTML composition to MP4 (remote fallback path).",scalars:[{name:"source",type:"string",required:!1,description:"RECOMMENDED inline HTML composition source (required: pass this or --source-file)"},{name:"source-file",type:"string",required:!1,description:"LEGACY: absolute path to a .html composition (prefer --source inline)"},{name:"duration-in-frames",type:"integer",required:!0,description:""},{name:"fps",type:"integer",required:!1,description:""},{name:"width",type:"integer",required:!1,description:""},{name:"height",type:"integer",required:!1,description:""},{name:"composition-id",type:"string",required:!1,description:""},{name:"agent-id",type:"integer",required:!1,description:""},{name:"timeout-ms",type:"integer",required:!1,description:""},{name:"input-props",type:"string",required:!1,description:"RECOMMENDED inline JSON inputProps (sibling of --input-props-file)"}],files:[{name:"input-props-file",required:!1,kind:"object",description:"LEGACY: JSON inputProps via file/stdin (prefer --input-props inline)",example:'{"title":"Hello"}'}]}),e.source||e.sourceFile||Da("E_SCHEMA","--source is required (pass the HTML composition inline, or use --source-file for the legacy file path)","pi skills should pass the composition inline via --source, or an absolute path via --source-file",{flag:"--source"}),e.source&&e.sourceFile&&Da("E_SCHEMA","--source and --source-file are mutually exclusive","prefer --source (inline); file content is invisible to the billing extension / dl adapter",{inline_flag:"--source",file_flag:"--source-file"}),void 0===e.durationInFrames&&Da("E_SCHEMA","--duration-in-frames is required",void 0,{flag:"--duration-in-frames"}),e.source)t=String(e.source),i="inline";else{try{t=await g(String(e.sourceFile),"utf8")}catch(t){const i=t instanceof Error?t.message:String(t);Da("E_FILE_MISSING",`--source-file: cannot read ${e.sourceFile} (${i})`,"make sure the path exists in the sandbox",{flag:"--source-file",given:String(e.sourceFile)})}i=String(e.sourceFile)}t||Da("E_SCHEMA",e.source?"--source is empty":"--source-file is empty","pi skills should resolve the composition via --source (inline) or an absolute --source-file path.",{flag:e.source?"--source":"--source-file"});try{const t=await qa(e.inputProps?String(e.inputProps):void 0,e.inputPropsFile?String(e.inputPropsFile):void 0,{inline:"--input-props",file:"--input-props-file"});t&&(n=t.data,o=t.source.label)}catch(e){throw e instanceof Yr&&Ha(e),e}Ba({command:"hyperframes",source_file:i,input_props:n??null,input_props_source:o??null});const r=f(),a={source:"dl",event:"hyperframes_render",credits:50,command:(s={command:"hyperframes",action:"hyperframes_render"}).command,action:s.action??"hyperframes_render",details:{rule:"hyperframes.fixed"}};var s;const l={source_code:t,duration_in_frames:Number(e.durationInFrames),...e.compositionId?{composition_id:String(e.compositionId)}:{},...void 0!==e.fps?{fps:Number(e.fps)}:{},...void 0!==e.width?{width:Number(e.width)}:{},...void 0!==e.height?{height:Number(e.height)}:{},...n?{input_props:n}:{}};let c=!1;try{await ua("hyperframes","renders",{job_id:r,params:l,agent_id:e.agentId??0},{billing:{jobRef:r,quote:a}}),c=!0;const t=await async function(e,t){const i=Date.now();for(;Date.now()-i<t;){const t=await pa("hyperframes",`renders/${e}`,{},{timeoutMs:3e4,retries:0});if("completed"===t.status)return t.data??t;if("failed"===t.status)throw new Error(`hyperframes: ${t.error??"failed"}`);await new Promise(e=>setTimeout(e,2e3))}throw new Error(`hyperframes: timeout after ${t}ms`)}(r,e.timeoutMs??9e5);Ua({ok:!0,job_ref:r,data:t,billing:a})}catch(e){c&&await async function(e){try{await da({jobRef:e.jobRef,quote:e.quote,reason:e.reason})}catch(t){process.stderr.write(`${JSON.stringify({level:"warn",event:"dl_billing_refund_failed",job_ref:e.jobRef,reason:e.reason,error:t instanceof Error?t.message:String(t)})}\n`)}}({jobRef:r,quote:a,reason:"hyperframes_render_failed"}),e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:r}),e instanceof oa&&Fa(e.message,e.hint,{job_ref:r}),Fa(e instanceof Error?e.message:String(e),void 0,{job_ref:r})}})}(Tc),function(e){e.command("poll").description("Single one-shot status check for an async job by job_ref. Does NOT loop — call at most once; end your turn and let [async-callback] resume you when the job lands.").addHelpText("after",["","Output (success):",' {"ok":true,"job_ref":"<uuid>","status":"completed"|"failed"|"pending","data":{...}}',"","`status=pending` means the job exists but hasn't terminated yet. 404 from","the backend also maps to `pending` (job_ref not yet registered).","","DO NOT call this inside `sleep` / `for` / `while` loops to wait for a job to","finish. Bash commands have a ~5-minute cap, the sandbox is reclaimed on","inactivity, and the proxy token TTL tracks the command budget — any wait","loop will be killed before the callback fires. End the turn instead; the","vendor result arrives as a `[async-callback] job=<ref>` user message in a","later turn, re-spawning a fresh sandbox."].join("\n")).requiredOption("--job-ref <ref>","the job_ref returned by a previous async submit (e.g. dl generate-music)").action(async e=>{try{const t=(process.env.CALLBACK_SERVER_URL??"").replace(/\/+$/,"");t||Fa("CALLBACK_SERVER_URL not set","hono-pi-e2b injects this on every commands.run; set it manually in LOCAL_SANDBOX dev");const i=await fetch(`${t}/result/${encodeURIComponent(String(e.jobRef))}`,{method:"GET",signal:AbortSignal.timeout(15e3)});i.ok||(404===i.status&&(Ll(),Ua({ok:!0,job_ref:e.jobRef,status:"pending"})),Fa(`poll http ${i.status}`));const n=await i.json();"pending"===n.status&&Ll(),Ua({ok:!0,job_ref:e.jobRef,...n})}catch(e){Fa(e instanceof Error?e.message:String(e))}})}(Tc),function(e){e.command("search").description("External web search via Baidu / Serper / Tavily / Brave, plus Baidu similar-image search.").addHelpText("after",["","`--provider` is required; pick the adapter to use (no auto-fanout).","For Baidu image/video discovery, use `--provider=baidu --resource-type=image|video`.","For Baidu similar-image search, use `--provider=baidu-image --image-file=<jpg|png>`.","For URL fetch (not a query), use `dl fetch` instead.","","Example (stdin):",' cat <<EOF | dl search --query="cats" --provider=tavily --params-file=-',' {"safe":"strict"}'," EOF"].join("\n")).option("--query <q>","search query string").requiredOption("--provider <name>","search adapter: baidu|baidu-image|serper|tavily|brave").option("--k <n>","max hits (default 10, max 100)",e=>function(e,t,i=100){const n=Number(e);if(!Number.isFinite(n)||!Number.isInteger(n)||n<1||n>i)throw new Error(`${t} must be a positive integer ≤ ${i}, got ${e}`);return n}(e,"--k")).option("--resource-type <type>","baidu only: web|image|video (default web)").option("--image-file <path>","jpg/png file for provider=baidu-image").option("--country <cc>","ISO country hint (serper/brave only)").option("--freshness <win>","freshness window: pd (day) | pw (week) | pm (month) | py (year)").option("--params <inline-json>",'RECOMMENDED: adapter-specific extras inline so the billing extension + dl adapter can read it from argv. Write it to a file and pass --params "$(cat extras.json)" — keeps complex JSON out of shell quoting. Over ~100KB (argv single-arg cap ~128KB) fall back to --params-file.').option("--params-file <path|->",'LEGACY: adapter-specific extras JSON object via file path; `-` reads stdin. File/stdin content is invisible to the billing extension + dl adapter, so prefer --params "$(cat file)". Use --params-file only when the payload is too large for argv (single-arg cap ~128KB).').option("--print-schema","print scalar+file schema and exit").action(async e=>{e.printSchema&&ms({command:"dl search",summary:"External web search via Baidu / Serper / Tavily / Brave, plus Baidu similar-image search.",scalars:[{name:"query",type:"string",required:!1,description:"search query (required except provider=baidu-image)"},{name:"provider",type:"string",required:!0,description:"baidu|baidu-image|serper|tavily|brave",enum:Ml},{name:"k",type:"integer",required:!1,description:"max hits (default 10, max 100)"},{name:"resource-type",type:"string",required:!1,description:"baidu only: web|image|video (default web)",enum:Fl},{name:"image-file",type:"string",required:!1,description:"jpg/png path for provider=baidu-image"},{name:"country",type:"string",required:!1,description:"ISO country hint (serper/brave)"},{name:"freshness",type:"string",required:!1,description:"pd|pw|pm|py",enum:["pd","pw","pm","py"]},{name:"params",type:"string",required:!1,description:"RECOMMENDED inline JSON object of adapter-specific extras (sibling of --params-file)"}],files:[{name:"params-file",required:!1,kind:"object",description:"LEGACY: adapter-specific extras (prefer --params inline)",example:'{"safe":"strict"}'}]});const t=String(e.provider??"");let i;if(Ml.includes(t)||Fa(`--provider must be one of ${Ml.join(", ")}; got ${t}`,"only baidu/baidu-image/serper/tavily/brave are wired; auto-fanout is not supported."),"baidu-image"===t||e.query||Da("E_SCHEMA","--query is required","pass --query for text search providers",{flag:"--query"}),e.resourceType){const t=String(e.resourceType);n=t,Fl.includes(n)||Da("E_SCHEMA",`--resource-type must be web|image|video; got ${t}`,void 0,{flag:"--resource-type"}),i=t}var n;let o;i&&"baidu"!==t&&Da("E_SCHEMA","--resource-type is only supported with --provider=baidu",void 0,{flag:"--resource-type",provider:t}),e.freshness&&!Ul.has(String(e.freshness))&&Fa(`--freshness must be pd|pw|pm|py; got ${e.freshness}`);try{const t=await qa(e.params?String(e.params):void 0,e.paramsFile?String(e.paramsFile):void 0,{inline:"--params",file:"--params-file"});t&&(o=t.data)}catch(e){throw e instanceof Yr&&Ha(e),e}const r=f(),a={source:"dl",event:"search",credits:10,command:(s={command:"search",action:"search"}).command,action:s.action??"search",details:{rule:"search.fixed",provider:{provider:t}.provider}};var s;try{Ua({ok:!0,job_ref:r,provider:t,hits:await Vl(t,e.query?String(e.query):"",{k:e.k,...i?{resourceType:i}:{},...e.imageFile?{imageFile:String(e.imageFile)}:{},...e.country?{country:String(e.country)}:{},...e.freshness?{freshness:e.freshness}:{},...o?{extra:o}:{},billing:{jobRef:r,quote:a}}),billing:a})}catch(e){e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:r}),e instanceof oa&&Fa(e.message,e.hint),Fa(e instanceof Error?e.message:String(e))}})}(Tc),function(e){const t=e.command("stock").description("Search and download public stock media (Pexels / Pixabay / Openverse) for b-roll.");t.command("search").description("Sequential-fallback search across providers (Pexels → Pixabay → Openverse). Use --mode=fanout for parallel.").addHelpText("after",["","Modes:"," fallback (default) —— Pexels → Pixabay → Openverse 顺序调,累计 limit 条就停。"," 某家返回不够会 fall through 到下一家,API budget 最省。"," fanout —— 并发打所有 enabled providers,按 provider 多样性 merge。"," 贵 3x,只在确实需要 cross-vendor diversity 时用 (冷门 query)。","","Provider selection:"," --providers defaults to all supports-current-type providers in default order."," Openverse is image-only; for --type=video it is auto-skipped."," Custom order: --providers=pixabay,pexels lets agent reorder fallback.","","Output: JSON { ok, job_ref, query, type, mode, results[], providers_queried, providers_failed[], billing }."," Fallback mode: providers_queried 可能短于 enabled (后续 provider 不需要就跳过)。"," Each result carries asset_id, download_url and full license metadata —"," pass them to `dl stock download` for the fetch.","","Examples:",' dl stock search --query="sunset beach" --type=image --limit=10',' dl stock search --query="city traffic" --type=video --duration-min=5 --duration-max=15',' dl stock search --query="rare landscape" --type=image --mode=fanout # 需要 diversity',' dl stock search --query="..." --providers=pixabay,pexels # 自定顺序'].join("\n")).requiredOption("--query <q>","natural-language search query").requiredOption("--type <t>","image | video").option("--orientation <o>","landscape | portrait | square").option("--min-width <n>","minimum dimensions.width in px (filter post-normalize)",e=>_c(e,"--min-width",1e5)).option("--duration-min <s>","minimum video duration in seconds (video only)",e=>wc(e,"--duration-min")).option("--duration-max <s>","maximum video duration in seconds (video only)",e=>wc(e,"--duration-max")).option("--limit <n>","max results to return (1..30, default 10)",e=>_c(e,"--limit",30),10).option("--providers <list>",`csv of providers in custom order; default order: ${gc.join(", ")}`).option("--mode <m>",`search strategy: ${bc.join(" | ")} (default fallback;省 API budget,fanout 仅在 diversity 必要时用)`,"fallback").action(async e=>{const t=String(e.type);yc.has(t)||Fa(`--type must be image|video; got ${e.type}`),e.orientation&&!vc.has(String(e.orientation))&&Fa(`--orientation must be landscape|portrait|square; got ${e.orientation}`);const i=String(e.mode);bc.includes(i)||Fa(`--mode must be one of ${bc.join(", ")}; got ${e.mode}`);const n=e.limit??10,o=function(e,t){const i=e?e.split(",").map(e=>e.trim()).filter(Boolean):[...gc],n=[];for(const e of i){const i=fc[e];i||Fa(`unknown stock provider: ${e}`,`supported providers: ${gc.join(", ")}`),("image"===t&&i.supports.image||"video"===t&&i.supports.video)&&n.push(e)}return 0===n.length&&Fa(`no providers support type=${t}`,"try --providers=pexels,pixabay"),n}(e.providers?String(e.providers):void 0,t),r="fanout"===i?Math.max(1,Math.ceil(1.5*n/o.length)):n,a={query:String(e.query),type:t,orientation:e.orientation?String(e.orientation):void 0,minWidth:e.minWidth,durationMin:e.durationMin,durationMax:e.durationMax,perProviderLimit:r},s=f(),l={source:"dl",event:"stock_search",credits:5,command:(d={command:"stock search",action:"stock_search"}).command,action:d.action??"stock_search",details:{rule:"stock-search.fixed",type:(c={type:t,mode:i,limit:n,providers:o}).type,mode:c.mode,limit:c.limit,providers:c.providers}};var c,d;let u=null;try{u=await ca({jobRef:s,quote:l});const{results:r,queried:c,failed:d}="fanout"===i?await async function(e,t,i,n=Sc){const o=await Promise.allSettled(e.map(e=>n(e,t))),r=[],a=[];for(let t=0;t<e.length;t++){const i=o[t];"fulfilled"===i.status?r.push(i.value):(r.push([]),a.push(kc(e[t],i.reason)))}return{results:xc(r,i),queried:[...e],failed:a}}(o,a,n):await async function(e,t,i,n=Sc){const o=[],r=new Set,a=[],s=[];for(const l of e){a.push(l);try{const e=await n(l,t);for(const t of e)if(!r.has(t.asset_id)&&(r.add(t.asset_id),o.push(t),o.length>=i))break}catch(e){s.push(kc(l,e))}if(o.length>=i)break}return{results:o.slice(0,i),queried:a,failed:s}}(o,a,n);0===r.length&&d.length>0&&d.length===c.length&&(await Ec({jobRef:s,quote:l,receipt:u,reason:"stock_search_failed"}),Fa(`all stock-media providers failed for "${e.query}"`,"check API keys / quota; see providers_failed for per-provider reason.",{job_ref:s,mode:i,providers_queried:c,providers_failed:d})),Ua({ok:!0,job_ref:s,query:a.query,type:t,mode:i,results:r,providers_queried:c,providers_failed:d,billing:l})}catch(e){u&&await Ec({jobRef:s,quote:l,receipt:u,reason:"stock_search_failed"}),e instanceof oa&&Fa(e.message,e.hint,{job_ref:s}),e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:s}),Fa(e instanceof Error?e.message:String(e),void 0,{job_ref:s})}}),function(e){e.command("download").description("Fetch a stock-media asset (CDN URL from search result) into /workspace and echo full metadata.").addHelpText("after",["","Flow: callback-server handles billing-only charge/refund; dl directly fetches the public CDN URL."," The --metadata-json from your search result is passed through verbatim,"," so agents have everything to write credits / track usage later.","","Example:"," RESULT=$(dl stock search --query=cats --type=image --limit=1 | jq '.results[0]')"," dl stock download \\",' --asset-id="$(jq -r .asset_id <<<"$RESULT")" \\',' --url="$(jq -r .download_url <<<\\"$RESULT\\")" \\',' --metadata-json="$RESULT"'].join("\n")).requiredOption("--asset-id <id>","<provider>:<native_id> from a search result").requiredOption("--url <url>","direct CDN URL from search result's download_url").option("--to <path>",`absolute path under /workspace (default: ${Ql}/<provider>-<id>.<ext>)`).option("--metadata-json <json>","JSON-encoded metadata object from search result; echoed back in output for downstream credit-tracking").action(async e=>{const{provider:t,nativeId:i}=function(e){const t=tc.exec(e);return t||Fa(`invalid --asset-id "${e}"`,"expected `<provider>:<native_id>`, e.g. pexels:12345 (from search results)."),{provider:t[1],nativeId:t[2]}}(String(e.assetId)),n=String(e.url);try{const e=new URL(n);"https:"!==e.protocol&&"http:"!==e.protocol&&Fa(`--url must be http(s); got protocol ${e.protocol}`)}catch(e){throw"TypeError"===e.name&&Fa(`--url is not a valid URL: ${n}`),e}const o=function(e){if(!e)return null;try{const t=JSON.parse(e);return("object"!=typeof t||null===t||Array.isArray(t))&&Fa("--metadata-json must be a JSON object; got "+("object"==typeof t?"array/null":typeof t)),t}catch(e){Fa(`--metadata-json failed to parse: ${e.message}`)}}(e.metadataJson),r=e.to?oc(String(e.to),String(e.to)):void 0,l=f(),c={source:"dl",event:"stock_download",credits:5,command:(u={command:"stock download",action:"stock_download"}).command,action:u.action??"stock_download",details:{rule:"stock-download.fixed",provider:(d={provider:t,native_id:i}).provider,native_id:d.native_id}};var d,u;let p=null;try{p=await ca({jobRef:l,quote:c});const{buf:e,contentType:d}=await async function(e){const t=new AbortController,i=setTimeout(()=>t.abort(),6e4);try{const i=await fetch(e,{signal:t.signal});if(!i.ok)throw new nc(`download failed: HTTP ${i.status} from ${e}`);const n=i.headers.get("content-length");if(n&&Number(n)>ec)throw new nc(`download too large: ${n} bytes exceeds 209715200 cap`,"this looks like an unusually large asset; double-check the URL.");const o=await i.arrayBuffer();if(o.byteLength>ec)throw new nc(`download too large: ${o.byteLength} bytes exceeds 209715200 cap`,"this looks like an unusually large asset; double-check the URL.");return{buf:Buffer.from(o),contentType:i.headers.get("content-type")}}catch(t){if(t instanceof nc)throw t;if("AbortError"===t.name)throw new nc("download timed out after 60000ms",`url: ${e}`);throw new nc(`download fetch error: ${t.message}`,`url: ${e}`)}finally{clearTimeout(i)}}(n),u=function(e,t){if(t){const e=t.split(";")[0]?.trim().toLowerCase();if(e&&ic.has(e))return ic.get(e)}try{const t=new URL(e),i=s(t.pathname).replace(/^\./,"").toLowerCase();if(i&&/^[a-z0-9]{2,5}$/.test(i))return i}catch{}return"bin"}(n,d),m=r??oc(void 0,`${Ql}/${t}-${i}.${u}`);await v(a(m),{recursive:!0}),await y(m,e),Ua({ok:!0,job_ref:l,asset_id:`${t}:${i}`,local_path:m,size_bytes:e.length,mime_type:d?.split(";")[0]?.trim()??null,metadata:o,billing:c})}catch(e){p&&await async function(e){try{await da({jobRef:e.jobRef,quote:e.quote,reason:e.reason,chargeId:e.receipt.charge_id})}catch(t){process.stderr.write(`${JSON.stringify({level:"warn",event:"dl_billing_refund_failed",job_ref:e.jobRef,reason:e.reason,error:t instanceof Error?t.message:String(t)})}\n`)}}({jobRef:l,quote:c,receipt:p,reason:"stock_download_failed"}),e instanceof nc&&Fa(e.message,e.hint,{job_ref:l}),e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:l}),Fa(e instanceof Error?e.message:String(e),void 0,{job_ref:l})}})}(t)}(Tc),function(e){e.command("fetch").description("Fetch a URL and emit extracted text / markdown / raw body (--mode). Non-2xx → error.").addHelpText("after",["","For a search query (not a URL), use `dl search`.","For social-media downloads (TikTok / IG / etc.), use `dl download-media`.","","Example:"," dl fetch --url=https://example.com --mode=markdown --max-bytes=1000000"].join("\n")).requiredOption("--url <url>").option("--mode <mode>","text|markdown|raw","text").option("--max-bytes <n>","max bytes to read (default 2000000, max 50000000)",e=>Sl(e,"--max-bytes",5e7)).option("--timeout-ms <n>","request timeout in ms (default 20000, max 120000)",e=>Sl(e,"--timeout-ms",12e4)).option("--user-agent <ua>","override UA header").action(async e=>{const t=String(e.mode??"text");var i;i=t,xl.includes(i)||Fa(`--mode must be text|markdown|raw, got ${t}`);const n=f(),o={source:"dl",event:"fetch",credits:5,command:(r={command:"fetch",action:"fetch"}).command,action:r.action??"fetch",details:{rule:"fetch.fixed",mode:{mode:t}.mode}};var r;try{Ua({ok:!0,job_ref:n,...await ua("web-fetch","",{url:String(e.url),mode:t,max_bytes:e.maxBytes??2e6,...void 0!==e.timeoutMs?{timeout_ms:e.timeoutMs}:{},...e.userAgent?{user_agent:String(e.userAgent)}:{}},{timeoutMs:e.timeoutMs??2e4,retries:0,billing:{jobRef:n,quote:o}}),billing:o})}catch(e){e instanceof Yr&&Da(e.code,e.message,e.hint,{...e.extra??{},job_ref:n}),e instanceof oa&&Fa(e.message,e.hint,{job_ref:n}),Fa(e instanceof Error?e.message:String(e),void 0,{job_ref:n})}})}(Tc),Tc.configureHelp({subcommandTerm(e){const t=e.name(),i=e.commands.length>0,n=(e.registeredArguments??[]).length>0;return i?`${t} <command>`:n?`${t} ${e.usage()}`:`${t} [options]`}}),function(e){const t=e=>{e.exitOverride(),e.configureOutput({writeErr:()=>{},outputError:()=>{}}),e.commands.forEach(t)};t(e);const i=e.parseAsync.bind(e);e.parseAsync=async n=>{t(e);try{return await i(n)}catch(t){!function(e,t){const i=t,n=i?.code??"",o=i?.message??String(t??"");if("commander.unknownOption"===n){const t=function(e){const t=/unknown option ['`"]?([-a-zA-Z0-9_]+)['`"]?/.exec(e);return t?.[1]}(o)??"",i=function(e){const t=new Set,i=e=>{for(const i of e.options)i.long&&t.add(i.long),i.short&&t.add(i.short);for(const t of e.commands)i(t)};return i(e),[...t]}(e),n=t?Wr(t,i):void 0,r=n&&n!==t?n:void 0;Da("E_UNKNOWN_OPTION",r?`unknown option \`${t}\` (did you mean \`${r}\`?)`:`unknown option \`${t||"<unknown>"}\``,"run the command with --help for the full flag list",{flag:t,...r?{suggestion:r}:{}})}"commander.unknownCommand"===n&&Da("E_UNKNOWN_OPTION",`unknown command: ${o}`,"run --help for the list of subcommands",{commander_code:n}),"commander.help"!==n&&"commander.helpDisplayed"!==n&&"commander.version"!==n||process.exit(0),"commander.missingMandatoryOptionValue"!==n&&"commander.missingArgument"!==n||Da("E_SCHEMA",o,"see --help; required scalar / argument is missing",{commander_code:n}),"commander.invalidOptionArgumentValue"!==n&&"commander.invalidArgument"!==n||Da("E_SCHEMA",o,"see --help for accepted values",{commander_code:n}),process.stderr.write(`${JSON.stringify({ok:!1,code:"E_BACKEND",error:o})}\n`),process.exit("number"==typeof i?.exitCode?i.exitCode:1)}(e,t)}}}(Tc),Tc.parseAsync(process.argv).catch(e=>{e instanceof Yr&&(process.stderr.write(`${JSON.stringify({ok:!1,code:e.code,error:e.message,message:e.message,...e.hint?{hint:e.hint}:{},...e.extra??{}})}\n`),process.exit(Kr(e.code)));const t=e instanceof Error?e.message:String(e);process.stderr.write(`${JSON.stringify({ok:!1,code:"E_BACKEND",error:t})}\n`),process.exit(1)});
|