thunderjar 0.2.0-preview-cb023da → 0.2.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +20 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- var $4=Object.create;var{getPrototypeOf:X4,defineProperty:V1,getOwnPropertyNames:q4}=Object;var G4=Object.prototype.hasOwnProperty;function K4(Z){return this[Z]}var U4,W4,d2=(Z,z,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=z?U4??=new WeakMap:W4??=new WeakMap,$=J.get(Z);if($)return $}Q=Z!=null?$4(X4(Z)):{};let X=z||!Z||!Z.__esModule?V1(Q,"default",{value:Z,enumerable:!0}):Q;for(let q of q4(Z))if(!G4.call(X,q))V1(X,q,{get:K4.bind(Z,q),enumerable:!0});if(Y)J.set(Z,X);return X};var l2=(Z,z)=>()=>(z||Z((z={exports:{}}).exports,z),z.exports);var H4=(Z)=>Z;function B4(Z,z){this[Z]=H4.bind(null,z)}var m2=(Z,z)=>{for(var Q in z)V1(Z,Q,{get:z[Q],enumerable:!0,configurable:!0,set:B4.bind(z,Q)})};var i2=(Z,z)=>()=>(Z&&(z=Z(Z=0)),z);var g1=(Z)=>JSON.parse(Z);class B0 extends Error{constructor(Z,z,Q){super(Q);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=z,this.exitCode=Z,this.nestedError=void 0}}class e extends B0{constructor(Z){super(1,"commander.invalidArgument",Z);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}class f0{constructor(Z,z){switch(this.description=z||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,Z[0]){case"<":this.required=!0,this._name=Z.slice(1,-1);break;case"[":this.required=!1,this._name=Z.slice(1,-1);break;default:this.required=!0,this._name=Z;break}if(this._name.endsWith("..."))this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_collectValue(Z,z){if(z===this.defaultValue||!Array.isArray(z))return[Z];return z.push(Z),z}default(Z,z){return this.defaultValue=Z,this.defaultValueDescription=z,this}argParser(Z){return this.parseArg=Z,this}choices(Z){return this.argChoices=Z.slice(),this.parseArg=(z,Q)=>{if(!this.argChoices.includes(z))throw new e(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._collectValue(z,Q);return z},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function g0(Z){let z=Z.name()+(Z.variadic===!0?"...":"");return Z.required?"<"+z+">":"["+z+"]"}import{EventEmitter as L4}from"events";import L1 from"child_process";import a from"path";import c0 from"fs";import A from"process";import{stripVTControlCharacters as M4}from"util";import{stripVTControlCharacters as V4}from"util";class h0{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(Z){this.helpWidth=this.helpWidth??Z.helpWidth??80}visibleCommands(Z){let z=Z.commands.filter((Y)=>!Y._hidden),Q=Z._getHelpCommand();if(Q&&!Q._hidden)z.push(Q);if(this.sortSubcommands)z.sort((Y,J)=>{return Y.name().localeCompare(J.name())});return z}compareOptions(Z,z){let Q=(Y)=>{return Y.short?Y.short.replace(/^-/,""):Y.long.replace(/^--/,"")};return Q(Z).localeCompare(Q(z))}visibleOptions(Z){let z=Z.options.filter((Y)=>!Y.hidden),Q=Z._getHelpOption();if(Q&&!Q.hidden){let Y=Q.short&&Z._findOption(Q.short),J=Q.long&&Z._findOption(Q.long);if(!Y&&!J)z.push(Q);else if(Q.long&&!J)z.push(Z.createOption(Q.long,Q.description));else if(Q.short&&!Y)z.push(Z.createOption(Q.short,Q.description))}if(this.sortOptions)z.sort(this.compareOptions);return z}visibleGlobalOptions(Z){if(!this.showGlobalOptions)return[];let z=[];for(let Q=Z.parent;Q;Q=Q.parent){let Y=Q.options.filter((J)=>!J.hidden);z.push(...Y)}if(this.sortOptions)z.sort(this.compareOptions);return z}visibleArguments(Z){if(Z._argsDescription)Z.registeredArguments.forEach((z)=>{z.description=z.description||Z._argsDescription[z.name()]||""});if(Z.registeredArguments.find((z)=>z.description))return Z.registeredArguments;return[]}subcommandTerm(Z){let z=Z.registeredArguments.map((Q)=>g0(Q)).join(" ");return Z._name+(Z._aliases[0]?"|"+Z._aliases[0]:"")+(Z.options.length?" [options]":"")+(z?" "+z:"")}optionTerm(Z){return Z.flags}argumentTerm(Z){return Z.name()}longestSubcommandTermLength(Z,z){return z.visibleCommands(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleSubcommandTerm(z.subcommandTerm(Y))))},0)}longestOptionTermLength(Z,z){return z.visibleOptions(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleOptionTerm(z.optionTerm(Y))))},0)}longestGlobalOptionTermLength(Z,z){return z.visibleGlobalOptions(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleOptionTerm(z.optionTerm(Y))))},0)}longestArgumentTermLength(Z,z){return z.visibleArguments(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleArgumentTerm(z.argumentTerm(Y))))},0)}commandUsage(Z){let z=Z._name;if(Z._aliases[0])z=z+"|"+Z._aliases[0];let Q="";for(let Y=Z.parent;Y;Y=Y.parent)Q=Y.name()+" "+Q;return Q+z+" "+Z.usage()}commandDescription(Z){return Z.description()}subcommandDescription(Z){return Z.summary()||Z.description()}optionDescription(Z){let z=[];if(Z.argChoices)z.push(`choices: ${Z.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if(Z.defaultValue!==void 0){if(Z.required||Z.optional||Z.isBoolean()&&typeof Z.defaultValue==="boolean")z.push(`default: ${Z.defaultValueDescription||JSON.stringify(Z.defaultValue)}`)}if(Z.presetArg!==void 0&&Z.optional)z.push(`preset: ${JSON.stringify(Z.presetArg)}`);if(Z.envVar!==void 0)z.push(`env: ${Z.envVar}`);if(z.length>0){let Q=`(${z.join(", ")})`;if(Z.description)return`${Z.description} ${Q}`;return Q}return Z.description}argumentDescription(Z){let z=[];if(Z.argChoices)z.push(`choices: ${Z.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if(Z.defaultValue!==void 0)z.push(`default: ${Z.defaultValueDescription||JSON.stringify(Z.defaultValue)}`);if(z.length>0){let Q=`(${z.join(", ")})`;if(Z.description)return`${Z.description} ${Q}`;return Q}return Z.description}formatItemList(Z,z,Q){if(z.length===0)return[];return[Q.styleTitle(Z),...z,""]}groupItems(Z,z,Q){let Y=new Map;return Z.forEach((J)=>{let $=Q(J);if(!Y.has($))Y.set($,[])}),z.forEach((J)=>{let $=Q(J);if(!Y.has($))Y.set($,[]);Y.get($).push(J)}),Y}formatHelp(Z,z){let Q=z.padWidth(Z,z),Y=z.helpWidth??80;function J(U,H){return z.formatItem(U,Q,H,z)}let $=[`${z.styleTitle("Usage:")} ${z.styleUsage(z.commandUsage(Z))}`,""],X=z.commandDescription(Z);if(X.length>0)$=$.concat([z.boxWrap(z.styleCommandDescription(X),Y),""]);let q=z.visibleArguments(Z).map((U)=>{return J(z.styleArgumentTerm(z.argumentTerm(U)),z.styleArgumentDescription(z.argumentDescription(U)))});if($=$.concat(this.formatItemList("Arguments:",q,z)),this.groupItems(Z.options,z.visibleOptions(Z),(U)=>U.helpGroupHeading??"Options:").forEach((U,H)=>{let _=U.map((I)=>{return J(z.styleOptionTerm(z.optionTerm(I)),z.styleOptionDescription(z.optionDescription(I)))});$=$.concat(this.formatItemList(H,_,z))}),z.showGlobalOptions){let U=z.visibleGlobalOptions(Z).map((H)=>{return J(z.styleOptionTerm(z.optionTerm(H)),z.styleOptionDescription(z.optionDescription(H)))});$=$.concat(this.formatItemList("Global Options:",U,z))}return this.groupItems(Z.commands,z.visibleCommands(Z),(U)=>U.helpGroup()||"Commands:").forEach((U,H)=>{let _=U.map((I)=>{return J(z.styleSubcommandTerm(z.subcommandTerm(I)),z.styleSubcommandDescription(z.subcommandDescription(I)))});$=$.concat(this.formatItemList(H,_,z))}),$.join(`
3
+ var $4=Object.create;var{getPrototypeOf:X4,defineProperty:V1,getOwnPropertyNames:q4}=Object;var G4=Object.prototype.hasOwnProperty;function K4(Z){return this[Z]}var U4,W4,d8=(Z,z,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=z?U4??=new WeakMap:W4??=new WeakMap,$=J.get(Z);if($)return $}Q=Z!=null?$4(X4(Z)):{};let X=z||!Z||!Z.__esModule?V1(Q,"default",{value:Z,enumerable:!0}):Q;for(let q of q4(Z))if(!G4.call(X,q))V1(X,q,{get:K4.bind(Z,q),enumerable:!0});if(Y)J.set(Z,X);return X};var l8=(Z,z)=>()=>(z||Z((z={exports:{}}).exports,z),z.exports);var H4=(Z)=>Z;function B4(Z,z){this[Z]=H4.bind(null,z)}var m8=(Z,z)=>{for(var Q in z)V1(Z,Q,{get:z[Q],enumerable:!0,configurable:!0,set:B4.bind(z,Q)})};var i8=(Z,z)=>()=>(Z&&(z=Z(Z=0)),z);var g1=(Z)=>JSON.parse(Z);class B0 extends Error{constructor(Z,z,Q){super(Q);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=z,this.exitCode=Z,this.nestedError=void 0}}class e extends B0{constructor(Z){super(1,"commander.invalidArgument",Z);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}class f0{constructor(Z,z){switch(this.description=z||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,Z[0]){case"<":this.required=!0,this._name=Z.slice(1,-1);break;case"[":this.required=!1,this._name=Z.slice(1,-1);break;default:this.required=!0,this._name=Z;break}if(this._name.endsWith("..."))this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_collectValue(Z,z){if(z===this.defaultValue||!Array.isArray(z))return[Z];return z.push(Z),z}default(Z,z){return this.defaultValue=Z,this.defaultValueDescription=z,this}argParser(Z){return this.parseArg=Z,this}choices(Z){return this.argChoices=Z.slice(),this.parseArg=(z,Q)=>{if(!this.argChoices.includes(z))throw new e(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._collectValue(z,Q);return z},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function g0(Z){let z=Z.name()+(Z.variadic===!0?"...":"");return Z.required?"<"+z+">":"["+z+"]"}import{EventEmitter as L4}from"events";import L1 from"child_process";import a from"path";import c0 from"fs";import A from"process";import{stripVTControlCharacters as M4}from"util";import{stripVTControlCharacters as V4}from"util";class h0{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(Z){this.helpWidth=this.helpWidth??Z.helpWidth??80}visibleCommands(Z){let z=Z.commands.filter((Y)=>!Y._hidden),Q=Z._getHelpCommand();if(Q&&!Q._hidden)z.push(Q);if(this.sortSubcommands)z.sort((Y,J)=>{return Y.name().localeCompare(J.name())});return z}compareOptions(Z,z){let Q=(Y)=>{return Y.short?Y.short.replace(/^-/,""):Y.long.replace(/^--/,"")};return Q(Z).localeCompare(Q(z))}visibleOptions(Z){let z=Z.options.filter((Y)=>!Y.hidden),Q=Z._getHelpOption();if(Q&&!Q.hidden){let Y=Q.short&&Z._findOption(Q.short),J=Q.long&&Z._findOption(Q.long);if(!Y&&!J)z.push(Q);else if(Q.long&&!J)z.push(Z.createOption(Q.long,Q.description));else if(Q.short&&!Y)z.push(Z.createOption(Q.short,Q.description))}if(this.sortOptions)z.sort(this.compareOptions);return z}visibleGlobalOptions(Z){if(!this.showGlobalOptions)return[];let z=[];for(let Q=Z.parent;Q;Q=Q.parent){let Y=Q.options.filter((J)=>!J.hidden);z.push(...Y)}if(this.sortOptions)z.sort(this.compareOptions);return z}visibleArguments(Z){if(Z._argsDescription)Z.registeredArguments.forEach((z)=>{z.description=z.description||Z._argsDescription[z.name()]||""});if(Z.registeredArguments.find((z)=>z.description))return Z.registeredArguments;return[]}subcommandTerm(Z){let z=Z.registeredArguments.map((Q)=>g0(Q)).join(" ");return Z._name+(Z._aliases[0]?"|"+Z._aliases[0]:"")+(Z.options.length?" [options]":"")+(z?" "+z:"")}optionTerm(Z){return Z.flags}argumentTerm(Z){return Z.name()}longestSubcommandTermLength(Z,z){return z.visibleCommands(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleSubcommandTerm(z.subcommandTerm(Y))))},0)}longestOptionTermLength(Z,z){return z.visibleOptions(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleOptionTerm(z.optionTerm(Y))))},0)}longestGlobalOptionTermLength(Z,z){return z.visibleGlobalOptions(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleOptionTerm(z.optionTerm(Y))))},0)}longestArgumentTermLength(Z,z){return z.visibleArguments(Z).reduce((Q,Y)=>{return Math.max(Q,this.displayWidth(z.styleArgumentTerm(z.argumentTerm(Y))))},0)}commandUsage(Z){let z=Z._name;if(Z._aliases[0])z=z+"|"+Z._aliases[0];let Q="";for(let Y=Z.parent;Y;Y=Y.parent)Q=Y.name()+" "+Q;return Q+z+" "+Z.usage()}commandDescription(Z){return Z.description()}subcommandDescription(Z){return Z.summary()||Z.description()}optionDescription(Z){let z=[];if(Z.argChoices)z.push(`choices: ${Z.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if(Z.defaultValue!==void 0){if(Z.required||Z.optional||Z.isBoolean()&&typeof Z.defaultValue==="boolean")z.push(`default: ${Z.defaultValueDescription||JSON.stringify(Z.defaultValue)}`)}if(Z.presetArg!==void 0&&Z.optional)z.push(`preset: ${JSON.stringify(Z.presetArg)}`);if(Z.envVar!==void 0)z.push(`env: ${Z.envVar}`);if(z.length>0){let Q=`(${z.join(", ")})`;if(Z.description)return`${Z.description} ${Q}`;return Q}return Z.description}argumentDescription(Z){let z=[];if(Z.argChoices)z.push(`choices: ${Z.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if(Z.defaultValue!==void 0)z.push(`default: ${Z.defaultValueDescription||JSON.stringify(Z.defaultValue)}`);if(z.length>0){let Q=`(${z.join(", ")})`;if(Z.description)return`${Z.description} ${Q}`;return Q}return Z.description}formatItemList(Z,z,Q){if(z.length===0)return[];return[Q.styleTitle(Z),...z,""]}groupItems(Z,z,Q){let Y=new Map;return Z.forEach((J)=>{let $=Q(J);if(!Y.has($))Y.set($,[])}),z.forEach((J)=>{let $=Q(J);if(!Y.has($))Y.set($,[]);Y.get($).push(J)}),Y}formatHelp(Z,z){let Q=z.padWidth(Z,z),Y=z.helpWidth??80;function J(U,H){return z.formatItem(U,Q,H,z)}let $=[`${z.styleTitle("Usage:")} ${z.styleUsage(z.commandUsage(Z))}`,""],X=z.commandDescription(Z);if(X.length>0)$=$.concat([z.boxWrap(z.styleCommandDescription(X),Y),""]);let q=z.visibleArguments(Z).map((U)=>{return J(z.styleArgumentTerm(z.argumentTerm(U)),z.styleArgumentDescription(z.argumentDescription(U)))});if($=$.concat(this.formatItemList("Arguments:",q,z)),this.groupItems(Z.options,z.visibleOptions(Z),(U)=>U.helpGroupHeading??"Options:").forEach((U,H)=>{let _=U.map((I)=>{return J(z.styleOptionTerm(z.optionTerm(I)),z.styleOptionDescription(z.optionDescription(I)))});$=$.concat(this.formatItemList(H,_,z))}),z.showGlobalOptions){let U=z.visibleGlobalOptions(Z).map((H)=>{return J(z.styleOptionTerm(z.optionTerm(H)),z.styleOptionDescription(z.optionDescription(H)))});$=$.concat(this.formatItemList("Global Options:",U,z))}return this.groupItems(Z.commands,z.visibleCommands(Z),(U)=>U.helpGroup()||"Commands:").forEach((U,H)=>{let _=U.map((I)=>{return J(z.styleSubcommandTerm(z.subcommandTerm(I)),z.styleSubcommandDescription(z.subcommandDescription(I)))});$=$.concat(this.formatItemList(H,_,z))}),$.join(`
4
4
  `)}displayWidth(Z){return V4(Z).length}styleTitle(Z){return Z}styleUsage(Z){return Z.split(" ").map((z)=>{if(z==="[options]")return this.styleOptionText(z);if(z==="[command]")return this.styleSubcommandText(z);if(z[0]==="["||z[0]==="<")return this.styleArgumentText(z);return this.styleCommandText(z)}).join(" ")}styleCommandDescription(Z){return this.styleDescriptionText(Z)}styleOptionDescription(Z){return this.styleDescriptionText(Z)}styleSubcommandDescription(Z){return this.styleDescriptionText(Z)}styleArgumentDescription(Z){return this.styleDescriptionText(Z)}styleDescriptionText(Z){return Z}styleOptionTerm(Z){return this.styleOptionText(Z)}styleSubcommandTerm(Z){return Z.split(" ").map((z)=>{if(z==="[options]")return this.styleOptionText(z);if(z[0]==="["||z[0]==="<")return this.styleArgumentText(z);return this.styleSubcommandText(z)}).join(" ")}styleArgumentTerm(Z){return this.styleArgumentText(Z)}styleOptionText(Z){return Z}styleArgumentText(Z){return Z}styleSubcommandText(Z){return Z}styleCommandText(Z){return Z}padWidth(Z,z){return Math.max(z.longestOptionTermLength(Z,z),z.longestGlobalOptionTermLength(Z,z),z.longestSubcommandTermLength(Z,z),z.longestArgumentTermLength(Z,z))}preformatted(Z){return/\n[^\S\r\n]/.test(Z)}formatItem(Z,z,Q,Y){let $=" ".repeat(2);if(!Q)return $+Z;let X=Z.padEnd(z+Z.length-Y.displayWidth(Z)),q=2,G=(this.helpWidth??80)-z-q-2,U;if(G<this.minWidthToWrap||Y.preformatted(Q))U=Q;else U=Y.boxWrap(Q,G).replace(/\n/g,`
5
5
  `+" ".repeat(z+q));return $+X+" ".repeat(q)+U.replace(/\n/g,`
6
6
  ${$}`)}boxWrap(Z,z){if(z<this.minWidthToWrap)return Z;let Q=Z.split(/\r\n|\n/),Y=/[\s]*[^\s]+/g,J=[];return Q.forEach(($)=>{let X=$.match(Y);if(X===null){J.push("");return}let q=[X.shift()],K=this.displayWidth(q[0]);X.forEach((G)=>{let U=this.displayWidth(G);if(K+U<=z){q.push(G),K+=U;return}J.push(q.join(""));let H=G.trimStart();q=[H],K=this.displayWidth(H)}),J.push(q.join(""))}),J.join(`
@@ -25,18 +25,18 @@ Expecting one of '${Q.join("', '")}'`);if(this._lifeCycleHooks[Z])this._lifeCycl
25
25
  `),this.outputHelp({error:!0});let Q=z||{},Y=Q.exitCode||1,J=Q.code||"commander.error";this._exit(Y,J,Z)}_parseOptionsEnv(){this.options.forEach((Z)=>{if(Z.envVar&&Z.envVar in A.env){let z=Z.attributeName();if(this.getOptionValue(z)===void 0||["default","config","env"].includes(this.getOptionValueSource(z)))if(Z.required||Z.optional)this.emit(`optionEnv:${Z.name()}`,A.env[Z.envVar]);else this.emit(`optionEnv:${Z.name()}`)}})}_parseOptionsImplied(){let Z=new _1(this.options),z=(Q)=>{return this.getOptionValue(Q)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(Q))};this.options.filter((Q)=>Q.implied!==void 0&&z(Q.attributeName())&&Z.valueFromOption(this.getOptionValue(Q.attributeName()),Q)).forEach((Q)=>{Object.keys(Q.implied).filter((Y)=>!z(Y)).forEach((Y)=>{this.setOptionValueWithSource(Y,Q.implied[Y],"implied")})})}missingArgument(Z){let z=`error: missing required argument '${Z}'`;this.error(z,{code:"commander.missingArgument"})}optionMissingArgument(Z){let z=`error: option '${Z.flags}' argument missing`;this.error(z,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(Z){let z=`error: required option '${Z.flags}' not specified`;this.error(z,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(Z,z){let Q=($)=>{let X=$.attributeName(),q=this.getOptionValue(X),K=this.options.find((U)=>U.negate&&X===U.attributeName()),G=this.options.find((U)=>!U.negate&&X===U.attributeName());if(K&&(K.presetArg===void 0&&q===!1||K.presetArg!==void 0&&q===K.presetArg))return K;return G||$},Y=($)=>{let X=Q($),q=X.attributeName();if(this.getOptionValueSource(q)==="env")return`environment variable '${X.envVar}'`;return`option '${X.flags}'`},J=`error: ${Y(Z)} cannot be used with ${Y(z)}`;this.error(J,{code:"commander.conflictingOption"})}unknownOption(Z){if(this._allowUnknownOption)return;let z="";if(Z.startsWith("--")&&this._showSuggestionAfterError){let Y=[],J=this;do{let $=J.createHelp().visibleOptions(J).filter((X)=>X.long).map((X)=>X.long);Y=Y.concat($),J=J.parent}while(J&&!J._enablePositionalOptions);z=j1(Z,Y)}let Q=`error: unknown option '${Z}'${z}`;this.error(Q,{code:"commander.unknownOption"})}_excessArguments(Z){if(this._allowExcessArguments)return;let z=this.registeredArguments.length,Q=z===1?"":"s",Y=Z.length,J=this.parent?` for '${this.name()}'`:"",$=Z.join(", "),X=`error: too many arguments${J}. Expected ${z} argument${Q} but got ${Y}: ${$}.`;this.error(X,{code:"commander.excessArguments"})}unknownCommand(){let Z=this.args[0],z="";if(this._showSuggestionAfterError){let Y=[];this.createHelp().visibleCommands(this).forEach((J)=>{if(Y.push(J.name()),J.alias())Y.push(J.alias())}),z=j1(Z,Y)}let Q=`error: unknown command '${Z}'${z}`;this.error(Q,{code:"commander.unknownCommand"})}version(Z,z,Q){if(Z===void 0)return this._version;this._version=Z,z=z||"-V, --version",Q=Q||"output the version number";let Y=this.createOption(z,Q);return this._versionOptionName=Y.attributeName(),this._registerOption(Y),this.on("option:"+Y.name(),()=>{this._outputConfiguration.writeOut(`${Z}
26
26
  `),this._exit(0,"commander.version",Z)}),this}description(Z,z){if(Z===void 0&&z===void 0)return this._description;if(this._description=Z,z)this._argsDescription=z;return this}summary(Z){if(Z===void 0)return this._summary;return this._summary=Z,this}alias(Z){if(Z===void 0)return this._aliases[0];let z=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)z=this.commands[this.commands.length-1];if(Z===z._name)throw Error("Command alias can't be the same as its name");let Q=this.parent?._findCommand(Z);if(Q){let Y=[Q.name()].concat(Q.aliases()).join("|");throw Error(`cannot add alias '${Z}' to command '${this.name()}' as already have command '${Y}'`)}return z._aliases.push(Z),this}aliases(Z){if(Z===void 0)return this._aliases;return Z.forEach((z)=>this.alias(z)),this}usage(Z){if(Z===void 0){if(this._usage)return this._usage;let z=this.registeredArguments.map((Q)=>{return g0(Q)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?z:[]).join(" ")}return this._usage=Z,this}name(Z){if(Z===void 0)return this._name;return this._name=Z,this}helpGroup(Z){if(Z===void 0)return this._helpGroupHeading??"";return this._helpGroupHeading=Z,this}commandsGroup(Z){if(Z===void 0)return this._defaultCommandGroup??"";return this._defaultCommandGroup=Z,this}optionsGroup(Z){if(Z===void 0)return this._defaultOptionGroup??"";return this._defaultOptionGroup=Z,this}_initOptionGroup(Z){if(this._defaultOptionGroup&&!Z.helpGroupHeading)Z.helpGroup(this._defaultOptionGroup)}_initCommandGroup(Z){if(this._defaultCommandGroup&&!Z.helpGroup())Z.helpGroup(this._defaultCommandGroup)}nameFromFilename(Z){return this._name=a.basename(Z,a.extname(Z)),this}executableDir(Z){if(Z===void 0)return this._executableDir;return this._executableDir=Z,this}helpInformation(Z){let z=this.createHelp(),Q=this._getOutputContext(Z);z.prepareContext({error:Q.error,helpWidth:Q.helpWidth,outputHasColors:Q.hasColors});let Y=z.formatHelp(this,z);if(Q.hasColors)return Y;return this._outputConfiguration.stripColor(Y)}_getOutputContext(Z){Z=Z||{};let z=!!Z.error,Q,Y,J;if(z)Q=(X)=>this._outputConfiguration.writeErr(X),Y=this._outputConfiguration.getErrHasColors(),J=this._outputConfiguration.getErrHelpWidth();else Q=(X)=>this._outputConfiguration.writeOut(X),Y=this._outputConfiguration.getOutHasColors(),J=this._outputConfiguration.getOutHelpWidth();return{error:z,write:(X)=>{if(!Y)X=this._outputConfiguration.stripColor(X);return Q(X)},hasColors:Y,helpWidth:J}}outputHelp(Z){let z;if(typeof Z==="function")z=Z,Z=void 0;let Q=this._getOutputContext(Z),Y={error:Q.error,write:Q.write,command:this};this._getCommandAndAncestors().reverse().forEach(($)=>$.emit("beforeAllHelp",Y)),this.emit("beforeHelp",Y);let J=this.helpInformation({error:Q.error});if(z){if(J=z(J),typeof J!=="string"&&!Buffer.isBuffer(J))throw Error("outputHelp callback must return a string or a Buffer")}if(Q.write(J),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",Y),this._getCommandAndAncestors().forEach(($)=>$.emit("afterAllHelp",Y))}helpOption(Z,z){if(typeof Z==="boolean"){if(Z){if(this._helpOption===null)this._helpOption=void 0;if(this._defaultOptionGroup)this._initOptionGroup(this._getHelpOption())}else this._helpOption=null;return this}if(this._helpOption=this.createOption(Z??"-h, --help",z??"display help for command"),Z||z)this._initOptionGroup(this._helpOption);return this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption(Z){return this._helpOption=Z,this._initOptionGroup(Z),this}help(Z){this.outputHelp(Z);let z=Number(A.exitCode??0);if(z===0&&Z&&typeof Z!=="function"&&Z.error)z=1;this._exit(z,"commander.help","(outputHelp)")}addHelpText(Z,z){let Q=["beforeAll","before","after","afterAll"];if(!Q.includes(Z))throw Error(`Unexpected value for position to addHelpText.
27
27
  Expecting one of '${Q.join("', '")}'`);let Y=`${Z}Help`;return this.on(Y,(J)=>{let $;if(typeof z==="function")$=z({error:J.error,command:J.command});else $=z;if($)J.write(`${$}
28
- `)}),this}_outputHelpIfRequested(Z){let z=this._getHelpOption();if(z&&Z.find((Y)=>z.is(Y)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function c1(Z){return Z.map((z)=>{if(!z.startsWith("--inspect"))return z;let Q,Y="127.0.0.1",J="9229",$;if(($=z.match(/^(--inspect(-brk)?)$/))!==null)Q=$[1];else if(($=z.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(Q=$[1],/^\d+$/.test($[3]))J=$[3];else Y=$[3];else if(($=z.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)Q=$[1],Y=$[3],J=$[4];if(Q&&J!=="0")return`${Q}=${Y}:${parseInt(J)+1}`;return z})}function u1(){if(A.env.NO_COLOR||A.env.FORCE_COLOR==="0"||A.env.FORCE_COLOR==="false")return!1;if(A.env.FORCE_COLOR||A.env.CLICOLOR_FORCE!==void 0)return!0;return}var T8=new y;var M1={name:"thunderjar",version:"0.2.0-preview-cb023da",type:"module",description:"Thunderjar",license:"MIT",repository:{type:"git",url:"git+https://github.com/dwjohnston/thunderjar.git"},bin:{thunderjar:"./dist/index.js"},main:"./src/api/index.ts",types:"./src/api/index.ts",exports:{".":"./src/api/index.ts"},files:["dist","src/api","!src/**/*.test.ts","!src/**/*.result.json"],publishConfig:{access:"public"},scripts:{build:"rm -rf dist && bun build src/cli/index.ts --target bun --outdir dist --entry-naming [name].[ext] --production",lint:"bun scripts/lint-layers.ts --check && oxlint","lint:generate":"bun scripts/lint-layers.ts",typecheck:"tsc --noEmit",test:"bun test","test:docker":"THUNDERJAR_DOCKER_TESTS=1 bun test --timeout 600000 .docker.test","test:agent":"THUNDERJAR_AGENT_TESTS=1 bun test --timeout 900000 .agent.test","test:package":"bun scripts/package-smoke-test.ts",fixture:"bun scripts/fixture.ts","docs:dev":"vitepress dev docs","docs:build":"vitepress build docs","docs:build:versions":"bun scripts/build-versioned-docs.ts","docs:preview":"vitepress preview docs",changeset:"changeset",version:"changeset version",release:"changeset publish","skills:update":"bunx skills update dwjohnston/agent-skills","skills:add":"bunx skills add dwjohnston/agent-skills"},dependencies:{bun:"1.3.14",commander:"^15.0.0",react:"19","react-dom":"19"},devDependencies:{"@changesets/cli":"^2.31.0","@changesets/get-release-plan":"^4.0.16","@types/bun":"^1.4.3","@types/react":"19","@types/react-dom":"19",oxlint:"^1.88.0",typescript:"^7.0.2",vitepress:"^2.0.0-alpha.18"}};var T4=Symbol.for("thunderjar.declaredBy");function p1(Z){if((typeof Z!=="object"||Z===null)&&typeof Z!=="function")return;let z=Z[T4];return typeof z==="string"?z:void 0}var O=".thunderjar";class k extends Error{problems;constructor(...Z){super(Z.join(`
29
- `));this.problems=Z}}function f(Z){return new k(...Z.map(({file:z,field:Q,message:Y})=>`${O}/${z}: ${Q?`${Q}: `:""}${Y}`))}async function d1(Z){try{return(await Bun.file(Z).stat()).isDirectory()}catch{return!1}}async function v(Z,z){return z.endsWith("/")?d1(`${Z}/${z}`):Bun.file(`${Z}/${z}`).exists()}var F4=(Z)=>Z.slice(0,Z.lastIndexOf("/"))||"/";async function C(Z){let z=Z.replace(/(.)\/+$/,"$1");for(;;){let Q=z==="/"?`/${O}`:`${z}/${O}`;if(await d1(Q))return Q;if(z==="/")break;z=F4(z)}throw new k(`No ${O}/ folder in ${Z} or any folder above it. Run \`thunderjar init\` first.`)}async function E(Z,z,Q,Y){if(!await v(Z,z)){Y.push({file:z,message:`is missing. Export \`${Q}(...)\` from it as the default.`});return}let J;try{J=await import(`${Z}/${z}`)}catch(X){Y.push({file:z,message:`could not be loaded: ${X instanceof Error?X.message:String(X)}`});return}if(J.default===void 0){Y.push({file:z,message:`has no default export. Export \`${Q}(...)\` as the default.`});return}let $=p1(J.default);if($!==Q){Y.push({file:z,message:$?`default export is wrapped in ${$}, expected ${Q}.`:`default export is not wrapped in ${Q}(...).`});return}return J.default}var{Glob:I4}=globalThis.Bun;var P="test-case-parameters",u0="files",S4=(Z)=>[...new Set(Z)].toSorted();async function l1(Z,z,Q,Y){if(!await v(Z,`${z}/`))return[];try{return S4(new I4(Q).scanSync({cwd:`${Z}/${z}`,onlyFiles:Y}))}catch(J){throw new k(`${O}/${z}/ could not be read: ${J instanceof Error?J.message:String(J)}`)}}async function Z0(Z,z){let Q=[];for(let Y of await l1(Z,z,"*",!1))if(await v(Z,`${z}/${Y}/`))Q.push(Y);return Q}async function p0(Z,z){return(await l1(Z,z,"*.ts",!0)).map((Q)=>Q.slice(0,-3))}var{CryptoHasher:f4}=globalThis.Bun;var d0=(Z)=>JSON.stringify(Z)??String(Z),y0=(Z,z,Q)=>typeof z==="string"&&z!==""?[]:[[Z,`must be ${Q}, got ${d0(z)}`]],P4={async evaluate({glob:Z},z){return{outcome:"measured",data:(await z.glob(Z)).length>0}},checkConfig(Z){return y0("config.glob",Z?.glob,"a glob pattern")}},D4=(Z)=>Z===""?[]:Z.replace(/\r?\n$/,"").split(/\r?\n/),A4={async evaluate({glob:Z,pattern:z},Q){let Y=await Q.glob(Z);if(Y.length===0)return{outcome:"skipped",reason:`no file matches ${Z}`};let J=new RegExp(z),$=0;for(let X of Y)for(let q of D4(await Q.readFile(X)))if(J.test(q))$++;return{outcome:"measured",data:$}},checkConfig(Z){let{glob:z,pattern:Q}=Z??{};return[...y0("config.glob",z,"a glob pattern"),...s1(Q)]}};function s1(Z){if(typeof Z!=="string")return[["config.pattern",`must be a JavaScript regular expression, got ${d0(Z)}`]];try{return new RegExp(Z),[]}catch(z){let Q=z.message.replace(/^Invalid regular expression: /,"");return[["config.pattern",`${d0(Z)} is not a valid regular expression: ${Q}`]]}}var O4={async evaluate({pattern:Z,turn:z},Q){let Y=z===void 0?Q.reply:Q.replies[z-1];if(!Y)return{outcome:"skipped",reason:`no turn ${z}: the initial prompt has ${Q.replies.length}`};if(Y.outcome!=="collected")return{outcome:"skipped",reason:`no reply: ${Y.reason}`};return{outcome:"measured",data:new RegExp(Z).test(Y.text)}},checkConfig(Z){let{pattern:z,turn:Q}=Z??{},Y=s1(z);if(Q!==void 0&&(typeof Q!=="number"||!Number.isInteger(Q)||Q<1))Y.push(["config.turn",`must be a turn, counting from 1, got ${d0(Q)}`]);return Y},usesContainer:!1},y4=(Z)=>`'${Z.replaceAll("'","'\\''")}'`,R4=(Z)=>Z.includes("/")?Z.slice(0,Z.lastIndexOf("/")):".",E4=(Z)=>Z.slice(Z.lastIndexOf("/")+1),m1=(Z)=>Z.lastIndexOf(".")>0?Z.slice(Z.lastIndexOf(".")):"",i1=(Z,z)=>Z==="."?z:`${Z}/${z}`,w4={".js":"js",".mjs":"js",".cjs":"js",".jsx":"jsx",".tsx":"tsx"},k4=(Z)=>{let z=Z.replace(/[^\w$]/g,"_");return/^[0-9]/.test(z)?`_${z}`:z||"subject"};class z0 extends Error{}async function C4(Z,z,Q){let Y=R4(z),J=E4(z),$=J.slice(0,J.length-m1(J).length),X;try{X=new Bun.Transpiler({loader:w4[m1(J)]??"ts"}).scan(await Q.readFile(z)).exports}catch(_){throw new z0(`can't read the exports of ${z}: ${_.message}`)}if(X.length===0)throw new z0(`${z} has no export to bind {{defaultExport}} to`);if(X.length>1)throw new z0(`${z} has ${X.length} exports (${X.join(", ")}); {{defaultExport}} binds to a single one`);let q=X[0],K=`./${J}`;if(q==="default"){q=k4($);let _=`${$}.templateTest.bind.ts`;K=`./${_}`,await Q.writeFile(i1(Y,_),`export { default as ${q} } from "./${J}";
28
+ `)}),this}_outputHelpIfRequested(Z){let z=this._getHelpOption();if(z&&Z.find((Y)=>z.is(Y)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function c1(Z){return Z.map((z)=>{if(!z.startsWith("--inspect"))return z;let Q,Y="127.0.0.1",J="9229",$;if(($=z.match(/^(--inspect(-brk)?)$/))!==null)Q=$[1];else if(($=z.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(Q=$[1],/^\d+$/.test($[3]))J=$[3];else Y=$[3];else if(($=z.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)Q=$[1],Y=$[3],J=$[4];if(Q&&J!=="0")return`${Q}=${Y}:${parseInt(J)+1}`;return z})}function u1(){if(A.env.NO_COLOR||A.env.FORCE_COLOR==="0"||A.env.FORCE_COLOR==="false")return!1;if(A.env.FORCE_COLOR||A.env.CLICOLOR_FORCE!==void 0)return!0;return}var T2=new y;var M1={name:"thunderjar",version:"0.2.0-rc.0",type:"module",description:"Thunderjar",license:"MIT",repository:{type:"git",url:"git+https://github.com/dwjohnston/thunderjar.git"},bin:{thunderjar:"./dist/index.js"},main:"./src/api/index.ts",types:"./src/api/index.ts",exports:{".":"./src/api/index.ts"},files:["dist","src/api","!src/**/*.test.ts","!src/**/*.result.json"],publishConfig:{access:"public"},scripts:{build:"rm -rf dist && bun build src/cli/index.ts --target bun --outdir dist --entry-naming [name].[ext] --production",lint:"bun scripts/lint-layers.ts --check && oxlint","lint:generate":"bun scripts/lint-layers.ts",typecheck:"tsc --noEmit",test:"bun test","test:docker":"THUNDERJAR_DOCKER_TESTS=1 bun test --timeout 600000 .docker.test","test:agent":"THUNDERJAR_AGENT_TESTS=1 bun test --timeout 900000 .agent.test","test:package":"bun scripts/package-smoke-test.ts",fixture:"bun scripts/fixture.ts","docs:dev":"vitepress dev docs","docs:build":"vitepress build docs","docs:build:versions":"bun scripts/build-versioned-docs.ts","docs:preview":"vitepress preview docs",changeset:"changeset",version:"changeset version",release:"changeset publish","skills:update":"bunx skills update dwjohnston/agent-skills","skills:add":"bunx skills add dwjohnston/agent-skills"},dependencies:{bun:"1.3.14",commander:"^15.0.0",react:"19","react-dom":"19"},devDependencies:{"@changesets/cli":"^2.31.0","@changesets/get-release-plan":"^4.0.16","@types/bun":"^1.4.3","@types/react":"19","@types/react-dom":"19",oxlint:"^1.88.0",typescript:"^7.0.2",vitepress:"^2.0.0-alpha.18"}};var T4=Symbol.for("thunderjar.declaredBy");function p1(Z){if((typeof Z!=="object"||Z===null)&&typeof Z!=="function")return;let z=Z[T4];return typeof z==="string"?z:void 0}var O=".thunderjar";class w extends Error{problems;constructor(...Z){super(Z.join(`
29
+ `));this.problems=Z}}function f(Z){return new w(...Z.map(({file:z,field:Q,message:Y})=>`${O}/${z}: ${Q?`${Q}: `:""}${Y}`))}async function d1(Z){try{return(await Bun.file(Z).stat()).isDirectory()}catch{return!1}}async function v(Z,z){return z.endsWith("/")?d1(`${Z}/${z}`):Bun.file(`${Z}/${z}`).exists()}var F4=(Z)=>Z.slice(0,Z.lastIndexOf("/"))||"/";async function C(Z){let z=Z.replace(/(.)\/+$/,"$1");for(;;){let Q=z==="/"?`/${O}`:`${z}/${O}`;if(await d1(Q))return Q;if(z==="/")break;z=F4(z)}throw new w(`No ${O}/ folder in ${Z} or any folder above it. Run \`thunderjar init\` first.`)}async function E(Z,z,Q,Y){if(!await v(Z,z)){Y.push({file:z,message:`is missing. Export \`${Q}(...)\` from it as the default.`});return}let J;try{J=await import(`${Z}/${z}`)}catch(X){Y.push({file:z,message:`could not be loaded: ${X instanceof Error?X.message:String(X)}`});return}if(J.default===void 0){Y.push({file:z,message:`has no default export. Export \`${Q}(...)\` as the default.`});return}let $=p1(J.default);if($!==Q){Y.push({file:z,message:$?`default export is wrapped in ${$}, expected ${Q}.`:`default export is not wrapped in ${Q}(...).`});return}return J.default}var{Glob:I4}=globalThis.Bun;var P="test-case-parameters",u0="files",S4=(Z)=>[...new Set(Z)].toSorted();async function l1(Z,z,Q,Y){if(!await v(Z,`${z}/`))return[];try{return S4(new I4(Q).scanSync({cwd:`${Z}/${z}`,onlyFiles:Y}))}catch(J){throw new w(`${O}/${z}/ could not be read: ${J instanceof Error?J.message:String(J)}`)}}async function Z0(Z,z){let Q=[];for(let Y of await l1(Z,z,"*",!1))if(await v(Z,`${z}/${Y}/`))Q.push(Y);return Q}async function p0(Z,z){return(await l1(Z,z,"*.ts",!0)).map((Q)=>Q.slice(0,-3))}var{CryptoHasher:f4}=globalThis.Bun;var d0=(Z)=>JSON.stringify(Z)??String(Z),y0=(Z,z,Q)=>typeof z==="string"&&z!==""?[]:[[Z,`must be ${Q}, got ${d0(z)}`]],P4={async evaluate({glob:Z},z){return{outcome:"measured",data:(await z.glob(Z)).length>0}},checkConfig(Z){return y0("config.glob",Z?.glob,"a glob pattern")}},D4=(Z)=>Z===""?[]:Z.replace(/\r?\n$/,"").split(/\r?\n/),A4={async evaluate({glob:Z,pattern:z},Q){let Y=await Q.glob(Z);if(Y.length===0)return{outcome:"skipped",reason:`no file matches ${Z}`};let J=new RegExp(z),$=0;for(let X of Y)for(let q of D4(await Q.readFile(X)))if(J.test(q))$++;return{outcome:"measured",data:$}},checkConfig(Z){let{glob:z,pattern:Q}=Z??{};return[...y0("config.glob",z,"a glob pattern"),...s1(Q)]}};function s1(Z){if(typeof Z!=="string")return[["config.pattern",`must be a JavaScript regular expression, got ${d0(Z)}`]];try{return new RegExp(Z),[]}catch(z){let Q=z.message.replace(/^Invalid regular expression: /,"");return[["config.pattern",`${d0(Z)} is not a valid regular expression: ${Q}`]]}}var O4={async evaluate({pattern:Z,turn:z},Q){let Y=z===void 0?Q.reply:Q.replies[z-1];if(!Y)return{outcome:"skipped",reason:`no turn ${z}: the initial prompt has ${Q.replies.length}`};if(Y.outcome!=="collected")return{outcome:"skipped",reason:`no reply: ${Y.reason}`};return{outcome:"measured",data:new RegExp(Z).test(Y.text)}},checkConfig(Z){let{pattern:z,turn:Q}=Z??{},Y=s1(z);if(Q!==void 0&&(typeof Q!=="number"||!Number.isInteger(Q)||Q<1))Y.push(["config.turn",`must be a turn, counting from 1, got ${d0(Q)}`]);return Y},usesContainer:!1},y4=(Z)=>`'${Z.replaceAll("'","'\\''")}'`,R4=(Z)=>Z.includes("/")?Z.slice(0,Z.lastIndexOf("/")):".",E4=(Z)=>Z.slice(Z.lastIndexOf("/")+1),m1=(Z)=>Z.lastIndexOf(".")>0?Z.slice(Z.lastIndexOf(".")):"",i1=(Z,z)=>Z==="."?z:`${Z}/${z}`,k4={".js":"js",".mjs":"js",".cjs":"js",".jsx":"jsx",".tsx":"tsx"},w4=(Z)=>{let z=Z.replace(/[^\w$]/g,"_");return/^[0-9]/.test(z)?`_${z}`:z||"subject"};class z0 extends Error{}async function C4(Z,z,Q){let Y=R4(z),J=E4(z),$=J.slice(0,J.length-m1(J).length),X;try{X=new Bun.Transpiler({loader:k4[m1(J)]??"ts"}).scan(await Q.readFile(z)).exports}catch(_){throw new z0(`can't read the exports of ${z}: ${_.message}`)}if(X.length===0)throw new z0(`${z} has no export to bind {{defaultExport}} to`);if(X.length>1)throw new z0(`${z} has ${X.length} exports (${X.join(", ")}); {{defaultExport}} binds to a single one`);let q=X[0],K=`./${J}`;if(q==="default"){q=w4($);let _=`${$}.templateTest.bind.ts`;K=`./${_}`,await Q.writeFile(i1(Y,_),`export { default as ${q} } from "./${J}";
30
30
  `)}let G={defaultExport:q,subjectPath:K},U=Z.replace(/\{\{\s*(\w+)\s*\}\}/g,(_,I)=>{if(!Object.hasOwn(G,I))throw new z0(`the template has an unknown placeholder ${_}`);return G[I]}),H=i1(Y,`${$}.templateTest.test.ts`);return await Q.writeFile(H,U),H}async function b4(Z,z){let{stdout:Q,stderr:Y}=await z.exec(`bun test ${y4(`./${Z}`)}`),J=`${Q}
31
31
  ${Y}`,$=(q)=>Number(new RegExp(`^\\s*(\\d+) ${q}$`,"m").exec(J)?.[1]??"0"),X=/^Ran (\d+) tests? /m.exec(J);if(!X||X[1]==="0"){let q=J.trim().split(`
32
- `).at(-1);throw new z0(`bun test ./${Z} reported no results${q?`: ${q}`:""}`)}if($("errors?")>0){let q=/^\w*error: .*$/im.exec(J)?.[0];throw new z0(`bun test ./${Z} failed outside any test${q?`: ${q}`:""}`)}return{passed:$("pass"),failed:$("fail")}}var v4={async evaluate({subject:Z,template:z},Q){let Y=await Q.glob(Z);if(Y.length===0)return{outcome:"skipped",reason:`no file matches ${Z}`};let J=await Bun.file(z).text(),$={passed:0,failed:0};try{for(let X of Y){let{passed:q,failed:K}=await b4(await C4(J,X,Q),Q);$.passed+=q,$.failed+=K}}catch(X){if(X instanceof z0)return{outcome:"erroredWhileMeasuring",error:X};throw X}return{outcome:"measured",data:$}},checkConfig(Z){let{subject:z,template:Q}=Z??{};return[...y0("config.subject",z,"a glob pattern"),...y0("config.template",Q,"a path relative to the measurement's file")]},bundledFiles:["template"]},x4={async evaluate({command:Z},z){let{exitCode:Q}=await z.exec(Z);return{outcome:"measured",data:Q===0}},checkConfig(Z){return y0("config.command",Z?.command,"a shell command")}},L0={fileCreated:P4,grep:A4,templateTest:v4,replyMatches:O4,shell:x4},n1={fileCreated:["rate","count"],grep:["mean","median","min","max","sum"],templateTest:["sum","mean"],replyMatches:["rate","count"],shell:["rate","count"]},a1=(Z)=>typeof Z==="string"&&Object.hasOwn(L0,Z);var l0=(Z)=>JSON.stringify(Z)??String(Z),o1=(Z)=>new f4("sha256").update(Z).digest("hex");function g4(Z){let z=[];for(let Q of Z.split("/"))if(Q==="..")z.pop();else if(Q!=="."&&Q!=="")z.push(Q);return`${Z.startsWith("/")?"/":""}${z.join("/")}`}async function N1(Z,z,Q){let Y=`${P}/tasks/${z}/measurements`,J=[];for(let $ of(await p0(Z,Y)).filter((X)=>!X.includes("."))){let X=`${Y}/${$}.ts`,q=(M,j)=>Q.push({file:X,field:M,message:j}),K=await E(Z,X,"declareMeasurement",Q);if(!K)continue;let{instrument:G,config:U,aggregate:H}=K;if(!a1(G)){q("instrument",`${l0(G)} is not a known instrument. Known instruments: ${Object.keys(L0).join(", ")}`);continue}let _=Q.length,{checkConfig:I,bundledFiles:R=[]}=L0[G],L=I(U);for(let[M,j]of L)q(M,j);let B={...U},V={};if(L.length===0)for(let M of R){let j=g4(`${Y}/${B[M]}`);if(!await v(Z,j)){q(`config.${M}`,`${l0(B[M])} has no matching ${O}/${j}`);continue}B[M]=`${Z}/${j}`,V[M]=o1(await Bun.file(B[M]).arrayBuffer())}if(!Array.isArray(H))q("aggregate",`must be an array of aggregation methods, got ${l0(H)}`);else{let M=n1[G];for(let j of H.filter((W)=>!M.includes(W)))q("aggregate",`${l0(j)} is not a way ${G}'s values combine. Use one of: ${M.join(", ")}`)}if(Q.length===_)J.push({name:$,declaration:K,config:B,contentHash:o1(JSON.stringify({instrument:G,config:U,files:V}))})}return J}async function m0(Z,z){let Q=[],Y=await N1(Z,z,Q);if(Q.length>0)throw f(Q);return Y}var i0=/^[A-Za-z_][A-Za-z0-9_]*$/;var w=["baseImage","codeState","promptSet","harnessModel","initialPrompt"];function s0(Z){return w.map((z)=>Z[z].length)}function t1(Z){return w.reduce((z,Q)=>z.flatMap((Y)=>Z[Q].map((J)=>({...Y,[Q]:J}))),[{}])}var o=(Z)=>Z.slice(0,8);function c(Z){let z=Z.indexOf("/");return{harness:Z.slice(0,z),modelId:Z.slice(z+1)}}var r1=(Z)=>JSON.stringify(Z)??String(Z);function e1(Z){if(Z===void 0)return;if(!Array.isArray(Z))return`must be an array of environment variable names, got ${r1(Z)}`;let z=Z.filter((Q)=>typeof Q!=="string"||!i0.test(Q));if(z.length>0)return`${z.map(r1).join(", ")} ${z.length===1?"is not an environment variable name":"are not environment variable names"}`;return}var T1=(Z)=>Z.requiredEnv??[];async function R0(Z,z,Q=Bun.env){let Y=[...new Set(z.harnessModel.map((q)=>c(q).harness))],J=[],$=[];for(let q of Y){let K=await E(Z,`${P}/harnessModels/${q}/index.ts`,"declareHarness",J);for(let G of K?T1(K):[])if(!Q[G])$.push(`${q} needs ${G}, which is not set.`)}if(J.length>0)throw f(J);if($.length===0)return;let X=`Export ${$.length===1?"it":"them"} in the shell that runs thunderjar.`;throw new k(...$.slice(0,-1),`${$.at(-1)}
33
- ${X}`)}var Z9=(Z)=>JSON.stringify(Z)??String(Z),h4=["--name","--pull","--entrypoint","--rm","--detach","-d"];function z9(Z){if(Z===void 0)return;if(!Array.isArray(Z)||Z.some((Q)=>typeof Q!=="string"))return`must be an array of docker run options and their values, each a string, got ${Z9(Z)}`;let z=Z.filter((Q)=>h4.includes(Q.split("=")[0]));if(z.length>0)return`${z.map(Z9).join(", ")} can't be given: Thunderjar sets ${z.length===1?"it":"them"} itself`;return}var x=(Z)=>JSON.stringify(Z)??String(Z),c4=[["baseImages","base images"],["codeStates","code states"],["promptSets","prompt sets"],["harnessModels","harnesses"],["tasks","tasks"]];async function u4(Z){let z=[];for(let[Q,Y]of c4)if((await Z0(Z,`${P}/${Q}`)).length===0)z.push(`${O}/${P}/${Q}/ has no ${Y}`);if(z.length>0)throw new k(...z)}var p4=[["baseImage","baseImages","declareBaseImage"],["codeState","codeStates","declareCodeState"],["promptSet","promptSets","declarePromptSet"]],d4=["baseImage","codeState","promptSet","harnessModel","initialPrompt"],l4=/^([^/]+)\/(.+)$/;class Q9{root;file;problems=[];harnesses=new Set;constructor(Z,z){this.root=Z;this.file=z}problem(Z,z){this.problems.push({file:this.file,field:Z,message:z})}async requires(Z,z,Q){if(await v(this.root,Q))return!0;return this.problem(Z,`${x(z)} has no matching ${O}/${Q}`),!1}arrays(Z){let z={};for(let Q of d4){let Y=Z[Q];if(!Array.isArray(Y)||Y.some((J)=>typeof J!=="string"))this.problem(Q,`must be an array of names, got ${x(Y)}`);else if(Y.length===0)this.problem(Q,"must name at least one value, got []");else z[Q]=Y}return z}checkIterations(Z){if(typeof Z!=="number"||!Number.isInteger(Z)||Z<1)this.problem("iterations",`must be a positive integer, got ${x(Z)}`)}async checkFolderFields(Z){for(let[z,Q,Y]of p4)for(let J of Z[z]??[]){let $=`${P}/${Q}/${J}/index.ts`;if(await this.requires(z,J,$)){let X=await E(this.root,$,Y,this.problems),q=z==="baseImage"&&X&&z9(X.runOptions);if(q)this.problems.push({file:$,field:"runOptions",message:q})}}}async checkTask(Z,z){if(typeof Z!=="string"){this.problem("task",`must be a task name, got ${x(Z)}`);return}if(!await this.requires("task",Z,`${P}/tasks/${Z}/`))return;await N1(this.root,Z,this.problems);for(let Q of z){let Y=`${P}/tasks/${Z}/initial-prompts/${Q}.ts`;if(await v(this.root,Y)){let $=await E(this.root,Y,"declareInitialPrompt",this.problems),X=$?.timeoutSeconds;if($&&(typeof X!=="number"||!Number.isFinite(X)||X<=0))this.problems.push({file:Y,field:"timeoutSeconds",message:`must be a number of seconds above 0, got ${x(X)}`});if($)this.checkPrompt(Y,$);continue}let J=new Bun.Glob(`${P}/tasks/*/initial-prompts/${Q}.ts`).scanSync({cwd:this.root}).next().value;this.problem("initialPrompt",J?`${x(Q)} belongs to task ${x(J.split("/")[2])}, not ${x(Z)}`:`${x(Q)} has no matching ${O}/${Y}`)}}checkPrompt(Z,{prompt:z,turns:Q}){let Y=(J,$)=>this.problems.push({file:Z,field:J,message:$});if(z!==void 0&&Q!==void 0)Y("turns","can't be given beside prompt. Give a single prompt, or a list of turns.");else if(Q!==void 0){if(!Array.isArray(Q)||Q.length===0||Q.some((J)=>typeof J!=="string"))Y("turns",`must be a list of at least one prompt, got ${x(Q)}`)}else if(typeof z!=="string")Y("prompt",`must be the prompt's text, or give a list of turns instead, got ${x(z)}`)}async checkHarness(Z){if(this.harnesses.has(Z))return;this.harnesses.add(Z);let z=`${P}/harnessModels/${Z}/index.ts`,Q=await E(this.root,z,"declareHarness",this.problems);if(!Q)return;let Y=($,X)=>this.problems.push({file:z,field:$,message:X});if(typeof Q.version!=="string"||Q.version.trim()==="")Y("version",`must be the version of the agent the harness installs, e.g. "2.1.311", got ${x(Q.version)}`);let J=e1(Q.requiredEnv);if(J)Y("requiredEnv",J);for(let $ of["collectReply","collectTokenCosts"])if(Q[$]!==void 0&&typeof Q[$]!=="function")Y($,`must be a function of the result file's text, got ${x(Q[$])}`)}async checkHarnessModels(Z){for(let z of Z){let Q=l4.exec(z);if(!Q){this.problem("harnessModel",`${x(z)} is not of the form <harness>/<model ID>`);continue}let Y=Q[1];if(Y.includes("@")&&!await v(this.root,`${P}/harnessModels/${Y}/`)){let J=Y.slice(0,Y.indexOf("@"));this.problem("harnessModel",`${x(z)} is in the old form, <harness>@<version>/<model>. Name a harness folder, which pins its version, then the model ID its agent takes, e.g. "${J}/<model ID>"`);continue}if(await this.requires("harnessModel",z,`${P}/harnessModels/${Y}/`))await this.checkHarness(Y)}}async check(Z){let z=this.arrays(Z);this.checkIterations(Z.iterations),await this.checkFolderFields(z),await this.checkTask(Z.task,z.initialPrompt??[]),await this.checkHarnessModels(z.harnessModel??[])}}async function Q0(Z,z){await u4(Z);let Q=`test-cases/${z}.ts`;if(!await v(Z,Q))throw new k(`No test case named "${z}": expected ${O}/${Q}.`);let Y=new Q9(Z,Q),J=await E(Z,Q,"declareTestCase",Y.problems);if(J)await Y.check(J);if(Y.problems.length>0)throw f(Y.problems);return J}var F1="thunderjar.config.ts",l=(Z)=>JSON.stringify(Z)??String(Z),m4=/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*(?::[0-9]+)?$/,i4=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/,Y9=(Z)=>Z.includes(".")||Z.includes(":")||Z==="localhost";function n0(Z){let[z,...Q]=Z.split("/");return Q.length>0&&Y9(z)?z:"docker.io"}function s4(Z){let z=Z.split("/"),Q=z.length>1&&Y9(z[0])?z.slice(1):z;if((Q===z||m4.test(z[0]))&&Q.every((J)=>i4.test(J)))return;return`${l(Z)} is not a Docker repository name. Expected e.g. "ghcr.io/acme/thunderjar-images", without a tag.`}function n4(Z){if(Z===null)return;if(typeof Z!=="object"||Array.isArray(Z))return`must be { repository: "<registry>/<name>" }, or null to keep images local, got ${l(Z)}`;let{repository:z}=Z;if(typeof z!=="string")return`repository must be a string, got ${l(z)}`;return s4(z)}var a4=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function o4(Z){if(Z===void 0)return;if(typeof Z!=="object"||Z===null||Array.isArray(Z))return`must be { secrets: [{ id, env }], ssh: true }, either of them left out, got ${l(Z)}`;let{secrets:z,ssh:Q}=Z;if(Q!==void 0&&typeof Q!=="boolean")return`ssh must be true or false, got ${l(Q)}`;if(z===void 0)return;if(!Array.isArray(z))return`secrets must be a list of { id, env }, got ${l(z)}`;let Y=new Set;for(let J of z){let{id:$,env:X}=J??{};if(typeof $!=="string"||!a4.test($))return`secrets: ${l($)} is not a secret ID: letters, digits, ".", "_" and "-"`;if(typeof X!=="string"||!i0.test(X))return`secrets: ${l(X)}, secret ${l($)}'s env, is not an environment variable name`;if(Y.has($))return`secrets: ${l($)} is given twice`;Y.add($)}return}function M0(Z,z=Bun.env){let Q=Z.secrets.filter(({env:J})=>!z[J]).map(({id:J,env:$})=>`Build secret "${J}" needs ${$}, which is not set.`);if(Q.length===0)return;let Y=`Export ${Q.length===1?"it":"them"} in the shell that runs thunderjar.`;throw new k(...Q.slice(0,-1),`${Q.at(-1)}
32
+ `).at(-1);throw new z0(`bun test ./${Z} reported no results${q?`: ${q}`:""}`)}if($("errors?")>0){let q=/^\w*error: .*$/im.exec(J)?.[0];throw new z0(`bun test ./${Z} failed outside any test${q?`: ${q}`:""}`)}return{passed:$("pass"),failed:$("fail")}}var v4={async evaluate({subject:Z,template:z},Q){let Y=await Q.glob(Z);if(Y.length===0)return{outcome:"skipped",reason:`no file matches ${Z}`};let J=await Bun.file(z).text(),$={passed:0,failed:0};try{for(let X of Y){let{passed:q,failed:K}=await b4(await C4(J,X,Q),Q);$.passed+=q,$.failed+=K}}catch(X){if(X instanceof z0)return{outcome:"erroredWhileMeasuring",error:X};throw X}return{outcome:"measured",data:$}},checkConfig(Z){let{subject:z,template:Q}=Z??{};return[...y0("config.subject",z,"a glob pattern"),...y0("config.template",Q,"a path relative to the measurement's file")]},bundledFiles:["template"]},x4={async evaluate({command:Z},z){let{exitCode:Q}=await z.exec(Z);return{outcome:"measured",data:Q===0}},checkConfig(Z){return y0("config.command",Z?.command,"a shell command")}},L0={fileCreated:P4,grep:A4,templateTest:v4,replyMatches:O4,shell:x4},n1={fileCreated:["rate","count"],grep:["mean","median","min","max","sum"],templateTest:["sum","mean"],replyMatches:["rate","count"],shell:["rate","count"]},a1=(Z)=>typeof Z==="string"&&Object.hasOwn(L0,Z);var l0=(Z)=>JSON.stringify(Z)??String(Z),o1=(Z)=>new f4("sha256").update(Z).digest("hex");function g4(Z){let z=[];for(let Q of Z.split("/"))if(Q==="..")z.pop();else if(Q!=="."&&Q!=="")z.push(Q);return`${Z.startsWith("/")?"/":""}${z.join("/")}`}async function N1(Z,z,Q){let Y=`${P}/tasks/${z}/measurements`,J=[];for(let $ of(await p0(Z,Y)).filter((X)=>!X.includes("."))){let X=`${Y}/${$}.ts`,q=(M,j)=>Q.push({file:X,field:M,message:j}),K=await E(Z,X,"declareMeasurement",Q);if(!K)continue;let{instrument:G,config:U,aggregate:H}=K;if(!a1(G)){q("instrument",`${l0(G)} is not a known instrument. Known instruments: ${Object.keys(L0).join(", ")}`);continue}let _=Q.length,{checkConfig:I,bundledFiles:R=[]}=L0[G],L=I(U);for(let[M,j]of L)q(M,j);let B={...U},V={};if(L.length===0)for(let M of R){let j=g4(`${Y}/${B[M]}`);if(!await v(Z,j)){q(`config.${M}`,`${l0(B[M])} has no matching ${O}/${j}`);continue}B[M]=`${Z}/${j}`,V[M]=o1(await Bun.file(B[M]).arrayBuffer())}if(!Array.isArray(H))q("aggregate",`must be an array of aggregation methods, got ${l0(H)}`);else{let M=n1[G];for(let j of H.filter((W)=>!M.includes(W)))q("aggregate",`${l0(j)} is not a way ${G}'s values combine. Use one of: ${M.join(", ")}`)}if(Q.length===_)J.push({name:$,declaration:K,config:B,contentHash:o1(JSON.stringify({instrument:G,config:U,files:V}))})}return J}async function m0(Z,z){let Q=[],Y=await N1(Z,z,Q);if(Q.length>0)throw f(Q);return Y}var i0=/^[A-Za-z_][A-Za-z0-9_]*$/;var k=["baseImage","codeState","promptSet","harnessModel","initialPrompt"];function s0(Z){return k.map((z)=>Z[z].length)}function t1(Z){return k.reduce((z,Q)=>z.flatMap((Y)=>Z[Q].map((J)=>({...Y,[Q]:J}))),[{}])}var o=(Z)=>Z.slice(0,8);function c(Z){let z=Z.indexOf("/");return{harness:Z.slice(0,z),modelId:Z.slice(z+1)}}var r1=(Z)=>JSON.stringify(Z)??String(Z);function e1(Z){if(Z===void 0)return;if(!Array.isArray(Z))return`must be an array of environment variable names, got ${r1(Z)}`;let z=Z.filter((Q)=>typeof Q!=="string"||!i0.test(Q));if(z.length>0)return`${z.map(r1).join(", ")} ${z.length===1?"is not an environment variable name":"are not environment variable names"}`;return}var T1=(Z)=>Z.requiredEnv??[];async function R0(Z,z,Q=Bun.env){let Y=[...new Set(z.harnessModel.map((q)=>c(q).harness))],J=[],$=[];for(let q of Y){let K=await E(Z,`${P}/harnessModels/${q}/index.ts`,"declareHarness",J);for(let G of K?T1(K):[])if(!Q[G])$.push(`${q} needs ${G}, which is not set.`)}if(J.length>0)throw f(J);if($.length===0)return;let X=`Export ${$.length===1?"it":"them"} in the shell that runs thunderjar.`;throw new w(...$.slice(0,-1),`${$.at(-1)}
33
+ ${X}`)}var Z9=(Z)=>JSON.stringify(Z)??String(Z),h4=["--name","--pull","--entrypoint","--rm","--detach","-d"];function z9(Z){if(Z===void 0)return;if(!Array.isArray(Z)||Z.some((Q)=>typeof Q!=="string"))return`must be an array of docker run options and their values, each a string, got ${Z9(Z)}`;let z=Z.filter((Q)=>h4.includes(Q.split("=")[0]));if(z.length>0)return`${z.map(Z9).join(", ")} can't be given: Thunderjar sets ${z.length===1?"it":"them"} itself`;return}var x=(Z)=>JSON.stringify(Z)??String(Z),c4=[["baseImages","base images"],["codeStates","code states"],["promptSets","prompt sets"],["harnessModels","harnesses"],["tasks","tasks"]];async function u4(Z){let z=[];for(let[Q,Y]of c4)if((await Z0(Z,`${P}/${Q}`)).length===0)z.push(`${O}/${P}/${Q}/ has no ${Y}`);if(z.length>0)throw new w(...z)}var p4=[["baseImage","baseImages","declareBaseImage"],["codeState","codeStates","declareCodeState"],["promptSet","promptSets","declarePromptSet"]],d4=["baseImage","codeState","promptSet","harnessModel","initialPrompt"],l4=/^([^/]+)\/(.+)$/;class Q9{root;file;problems=[];harnesses=new Set;constructor(Z,z){this.root=Z;this.file=z}problem(Z,z){this.problems.push({file:this.file,field:Z,message:z})}async requires(Z,z,Q){if(await v(this.root,Q))return!0;return this.problem(Z,`${x(z)} has no matching ${O}/${Q}`),!1}arrays(Z){let z={};for(let Q of d4){let Y=Z[Q];if(!Array.isArray(Y)||Y.some((J)=>typeof J!=="string"))this.problem(Q,`must be an array of names, got ${x(Y)}`);else if(Y.length===0)this.problem(Q,"must name at least one value, got []");else z[Q]=Y}return z}checkIterations(Z){if(typeof Z!=="number"||!Number.isInteger(Z)||Z<1)this.problem("iterations",`must be a positive integer, got ${x(Z)}`)}async checkFolderFields(Z){for(let[z,Q,Y]of p4)for(let J of Z[z]??[]){let $=`${P}/${Q}/${J}/index.ts`;if(await this.requires(z,J,$)){let X=await E(this.root,$,Y,this.problems),q=z==="baseImage"&&X&&z9(X.runOptions);if(q)this.problems.push({file:$,field:"runOptions",message:q})}}}async checkTask(Z,z){if(typeof Z!=="string"){this.problem("task",`must be a task name, got ${x(Z)}`);return}if(!await this.requires("task",Z,`${P}/tasks/${Z}/`))return;await N1(this.root,Z,this.problems);for(let Q of z){let Y=`${P}/tasks/${Z}/initial-prompts/${Q}.ts`;if(await v(this.root,Y)){let $=await E(this.root,Y,"declareInitialPrompt",this.problems),X=$?.timeoutSeconds;if($&&(typeof X!=="number"||!Number.isFinite(X)||X<=0))this.problems.push({file:Y,field:"timeoutSeconds",message:`must be a number of seconds above 0, got ${x(X)}`});if($)this.checkPrompt(Y,$);continue}let J=new Bun.Glob(`${P}/tasks/*/initial-prompts/${Q}.ts`).scanSync({cwd:this.root}).next().value;this.problem("initialPrompt",J?`${x(Q)} belongs to task ${x(J.split("/")[2])}, not ${x(Z)}`:`${x(Q)} has no matching ${O}/${Y}`)}}checkPrompt(Z,{prompt:z,turns:Q}){let Y=(J,$)=>this.problems.push({file:Z,field:J,message:$});if(z!==void 0&&Q!==void 0)Y("turns","can't be given beside prompt. Give a single prompt, or a list of turns.");else if(Q!==void 0){if(!Array.isArray(Q)||Q.length===0||Q.some((J)=>typeof J!=="string"))Y("turns",`must be a list of at least one prompt, got ${x(Q)}`)}else if(typeof z!=="string")Y("prompt",`must be the prompt's text, or give a list of turns instead, got ${x(z)}`)}async checkHarness(Z){if(this.harnesses.has(Z))return;this.harnesses.add(Z);let z=`${P}/harnessModels/${Z}/index.ts`,Q=await E(this.root,z,"declareHarness",this.problems);if(!Q)return;let Y=($,X)=>this.problems.push({file:z,field:$,message:X});if(typeof Q.version!=="string"||Q.version.trim()==="")Y("version",`must be the version of the agent the harness installs, e.g. "2.1.311", got ${x(Q.version)}`);let J=e1(Q.requiredEnv);if(J)Y("requiredEnv",J);for(let $ of["collectReply","collectTokenCosts"])if(Q[$]!==void 0&&typeof Q[$]!=="function")Y($,`must be a function of the result file's text, got ${x(Q[$])}`)}async checkHarnessModels(Z){for(let z of Z){let Q=l4.exec(z);if(!Q){this.problem("harnessModel",`${x(z)} is not of the form <harness>/<model ID>`);continue}let Y=Q[1];if(Y.includes("@")&&!await v(this.root,`${P}/harnessModels/${Y}/`)){let J=Y.slice(0,Y.indexOf("@"));this.problem("harnessModel",`${x(z)} is in the old form, <harness>@<version>/<model>. Name a harness folder, which pins its version, then the model ID its agent takes, e.g. "${J}/<model ID>"`);continue}if(await this.requires("harnessModel",z,`${P}/harnessModels/${Y}/`))await this.checkHarness(Y)}}async check(Z){let z=this.arrays(Z);this.checkIterations(Z.iterations),await this.checkFolderFields(z),await this.checkTask(Z.task,z.initialPrompt??[]),await this.checkHarnessModels(z.harnessModel??[])}}async function Q0(Z,z){await u4(Z);let Q=`test-cases/${z}.ts`;if(!await v(Z,Q))throw new w(`No test case named "${z}": expected ${O}/${Q}.`);let Y=new Q9(Z,Q),J=await E(Z,Q,"declareTestCase",Y.problems);if(J)await Y.check(J);if(Y.problems.length>0)throw f(Y.problems);return J}var F1="thunderjar.config.ts",l=(Z)=>JSON.stringify(Z)??String(Z),m4=/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*(?::[0-9]+)?$/,i4=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/,Y9=(Z)=>Z.includes(".")||Z.includes(":")||Z==="localhost";function n0(Z){let[z,...Q]=Z.split("/");return Q.length>0&&Y9(z)?z:"docker.io"}function s4(Z){let z=Z.split("/"),Q=z.length>1&&Y9(z[0])?z.slice(1):z;if((Q===z||m4.test(z[0]))&&Q.every((J)=>i4.test(J)))return;return`${l(Z)} is not a Docker repository name. Expected e.g. "ghcr.io/acme/thunderjar-images", without a tag.`}function n4(Z){if(Z===null)return;if(typeof Z!=="object"||Array.isArray(Z))return`must be { repository: "<registry>/<name>" }, or null to keep images local, got ${l(Z)}`;let{repository:z}=Z;if(typeof z!=="string")return`repository must be a string, got ${l(z)}`;return s4(z)}var a4=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function o4(Z){if(Z===void 0)return;if(typeof Z!=="object"||Z===null||Array.isArray(Z))return`must be { secrets: [{ id, env }], ssh: true }, either of them left out, got ${l(Z)}`;let{secrets:z,ssh:Q}=Z;if(Q!==void 0&&typeof Q!=="boolean")return`ssh must be true or false, got ${l(Q)}`;if(z===void 0)return;if(!Array.isArray(z))return`secrets must be a list of { id, env }, got ${l(z)}`;let Y=new Set;for(let J of z){let{id:$,env:X}=J??{};if(typeof $!=="string"||!a4.test($))return`secrets: ${l($)} is not a secret ID: letters, digits, ".", "_" and "-"`;if(typeof X!=="string"||!i0.test(X))return`secrets: ${l(X)}, secret ${l($)}'s env, is not an environment variable name`;if(Y.has($))return`secrets: ${l($)} is given twice`;Y.add($)}return}function M0(Z,z=Bun.env){let Q=Z.secrets.filter(({env:J})=>!z[J]).map(({id:J,env:$})=>`Build secret "${J}" needs ${$}, which is not set.`);if(Q.length===0)return;let Y=`Export ${Q.length===1?"it":"them"} in the shell that runs thunderjar.`;throw new w(...Q.slice(0,-1),`${Q.at(-1)}
34
34
  ${Y}`)}async function N0(Z){let z=[],Q=await E(Z,F1,"declareConfig",z);if(Q){let $=n4(Q.imageStore);if($)z.push({file:F1,field:"imageStore",message:$});let X=o4(Q.build);if(X)z.push({file:F1,field:"build",message:X})}if(z.length>0)throw f(z);let{imageStore:Y,build:J}=Q;return{imageStore:Y===null?null:{repository:Y.repository},build:{secrets:(J?.secrets??[]).map(({id:$,env:X})=>({id:$,env:X})),ssh:J?.ssh??!1}}}var{$:t}=globalThis.Bun;class m extends Error{}class T0 extends Error{}class a0 extends Error{}class F0 extends Error{}class i extends Error{}var Y0=()=>Bun.env.THUNDERJAR_DOCKER||"docker",J0=(Z)=>Z.toString().trim().split(`
35
35
  `).at(-1);async function J9(Z,z,Q={}){let Y=Y0(),J=(Q.secrets??[]).flatMap(({id:q,env:K})=>["--secret",`id=${q},env=${K}`]),$=Q.ssh?["--ssh","default"]:[],X=await t`${Y} build ${J} ${$} -t ${z} ${Z}`.env({...Bun.env,DOCKER_BUILDKIT:"1"}).quiet().nothrow();if(X.exitCode!==0)throw new T0(J0(X.stderr)||`\`${Y} build\` exited ${X.exitCode}`)}async function o0(Z){let z=Y0(),Q=await t`${z} image ls --format ${"{{.Repository}}:{{.Tag}}"} ${Z}`.quiet().nothrow();if(Q.exitCode!==0)throw new m(J0(Q.stderr)||`\`${z} image ls\` exited ${Q.exitCode}`);return new Set(Q.stdout.toString().split(`
36
- `).filter(Boolean))}var t4=/Cannot connect to the Docker daemon|error during connect/;async function $9(Z){let z=Y0(),Q=Bun.spawn([z,"login",Z],{env:{...Bun.env},stdin:"ignore",stdout:"ignore",stderr:"pipe"}),[Y,J]=await Promise.all([Q.exited,new Response(Q.stderr).text()]);if(Y===0)return;let $=J0(J)?.replace(/^error: /i,"")||`\`${z} login\` exited ${Y}`;if(t4.test(J))throw new m($);throw new a0($)}async function X9(Z,z){let Q=Y0();for(let Y of[["tag",Z,z],["push","--quiet",z]]){let J=await t`${Q} ${Y}`.quiet().nothrow();if(J.exitCode!==0)throw new F0(J0(J.stderr)||`\`${Q} ${Y[0]}\` exited ${J.exitCode}`)}}async function E0(Z){let z=Y0(),Q=await t`${z} ${Z}`.quiet().nothrow();if(Q.exitCode!==0)throw new i(J0(Q.stderr)||`\`${z} ${Z[0]}\` exited ${Q.exitCode}`);return Q.stdout.toString()}async function q9(Z,z,Q,{env:Y=[],runOptions:J=[],timeoutSeconds:$}={}){let X=Y0(),q=Y.flatMap((L)=>["-e",L]),K=["run","--name",z,"--pull","never",...q,...J,"--entrypoint","sh",Z,"-c",Q],G=Bun.spawn([X,...K],{env:{...Bun.env},stdin:"ignore",stdout:"ignore",stderr:"pipe"}),U,H=$===void 0?void 0:setTimeout(()=>{let L=Date.now();U=E0(["kill",z]).then(()=>L,()=>{return})},$*1000),[_,I]=await Promise.all([G.exited,new Response(G.stderr).text()]);clearTimeout(H);let R=await U;if(R!==void 0)return{timedOut:!0,killedAt:R};if(_!==0)throw new i(J0(I)||`\`${X} run\` exited ${_}`);return{timedOut:!1}}async function I1(Z,z){let Q=`${Bun.env.TMPDIR||"/tmp"}/thunderjar-cp-${crypto.randomUUID()}`;await t`mkdir -p ${Q}`.quiet();try{let Y=Y0(),J=await t`${Y} cp ${`${Z}:${z}`} ${Q}/file`.quiet().nothrow();if(J.exitCode!==0){let $=J0(J.stderr);if($?.includes("Could not find the file"))return;throw new i($||`\`${Y} cp\` exited ${J.exitCode}`)}return await Bun.file(`${Q}/file`).text()}finally{await t`rm -rf ${Q}`.quiet()}}async function G9(Z,z,Q){let Y=await E0(["image","inspect","--format","{{json .Config.Entrypoint}}\t{{json .Config.Cmd}}",Q]),[J,$]=Y.trim().split("\t"),X=[`ENTRYPOINT ${J==="null"?'[""]':J}`,`CMD ${$==="null"?'["sh"]':$}`];await E0(["commit",...X.flatMap((q)=>["--change",q]),Z,z])}async function w0(Z){await E0(["rm","--force",Z])}async function K9(Z,z){await E0(["run","--detach","--name",z,"--pull","never","--entrypoint","sh",Z,"-c","exec sleep 2147483647"])}async function U9(Z,z,Q,Y){let J=Y0(),$=["exec",...Y===void 0?[]:["--interactive"],"--workdir",z,Z,...Q],X=Y===void 0?await t`${J} ${$}`.quiet().nothrow():await t`${J} ${$} < ${new Response(Y)}`.quiet().nothrow();if(X.exitCode!==0&&/^(Error response from daemon|OCI runtime exec failed|Cannot connect to the Docker daemon)/.test(X.stderr.toString()))throw new i(J0(X.stderr)||`\`${J} exec\` exited ${X.exitCode}`);return{stdout:X.stdout.toString(),stderr:X.stderr.toString(),exitCode:X.exitCode}}var $0="thunderjar",r4=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function W9(Z){if(r4.test(Z))return;return"must be lowercase letters and digits, joined by single separators (., _, __ or -), as a Docker repository name is."}var k0=(Z=$0)=>`${Z}-prerun`,s=(Z,z=$0)=>`${k0(z)}:${o(Z)}`,H9=(Z,z,Q,Y=$0)=>`${Y}-postrun:${Z}-${z}-${Q}`,B9=(Z,z,Q,Y=$0)=>`${Y}-run-${Z}-${z}-${Q}`,V9=(Z,z)=>`${Z}:prerun-h${o(z)}`,_9=(Z,z,Q,Y)=>`${Z}:postrun-e${z}-h${o(Q)}-i${String(Y-1).padStart(2,"0")}`;class I0 extends Error{repository;host;reason;constructor(Z,z,Q){super(`Can't push to ${Z}: no valid Docker login for ${z} (${Q}). Run \`docker login ${z}\`.`);this.repository=Z;this.host=z;this.reason=Q}}async function t0(Z){if(Z===null)return;let z=n0(Z.repository);try{await $9(z)}catch(Q){if(Q instanceof a0)throw new I0(Z.repository,z,Q.message);throw Q}}async function S1(Z,z,Q={}){Q.onPushing?.(Z,z),await X9(Z,z),Q.onPushed?.(Z,z)}async function r0(Z,z,Q,Y={}){if(z===null)return[];let J=[...new Set(Z.map(({imageHash:X})=>X))],$=[];for(let X of J){let q=V9(z.repository,X);await S1(s(X,Q),q,Y),$.push(q)}return $}var{$:e0}=globalThis.Bun;var X0={baseImage:"parameters/baseImage",codeState:"parameters/codeState",promptSet:"parameters/promptSet",harness:"parameters/harness"},e4={baseImage:"base image",codeState:"code state",promptSet:"prompt set",harness:"harness"},ZZ=(Z,z)=>Object.keys(X0).filter((Q)=>Q!==Z&&new RegExp(`(^|[^\\w/.]|\\./)${X0[Q]}(?![\\w-])`).test(z));function j9(Z,{file:z,declaration:Q},Y,J){let $=(G)=>J.push({file:z,field:"applyParameter",message:G}),X=Q.applyParameter;if(!X){if(Z!=="baseImage")return"";$("is missing. A base image's fragment provides the FROM.");return}let q;try{q=X(Q.config,Y)}catch(G){$(`threw: ${G instanceof Error?G.message:String(G)}`);return}if(typeof q!=="string"){$(`must return a Dockerfile fragment, a string, got ${typeof q}.`);return}if(Z==="baseImage"&&!/^FROM\s/i.test(q.trim())){$(`must return a fragment that starts with FROM, got ${JSON.stringify(q.trim().split(`
36
+ `).filter(Boolean))}var t4=/Cannot connect to the Docker daemon|error during connect/;async function $9(Z){let z=Y0(),Q=Bun.spawn([z,"login",Z],{env:{...Bun.env},stdin:"ignore",stdout:"ignore",stderr:"pipe"}),[Y,J]=await Promise.all([Q.exited,new Response(Q.stderr).text()]);if(Y===0)return;let $=J0(J)?.replace(/^error: /i,"")||`\`${z} login\` exited ${Y}`;if(t4.test(J))throw new m($);throw new a0($)}async function X9(Z,z){let Q=Y0();for(let Y of[["tag",Z,z],["push","--quiet",z]]){let J=await t`${Q} ${Y}`.quiet().nothrow();if(J.exitCode!==0)throw new F0(J0(J.stderr)||`\`${Q} ${Y[0]}\` exited ${J.exitCode}`)}}async function E0(Z){let z=Y0(),Q=await t`${z} ${Z}`.quiet().nothrow();if(Q.exitCode!==0)throw new i(J0(Q.stderr)||`\`${z} ${Z[0]}\` exited ${Q.exitCode}`);return Q.stdout.toString()}async function q9(Z,z,Q,{env:Y=[],runOptions:J=[],timeoutSeconds:$}={}){let X=Y0(),q=Y.flatMap((L)=>["-e",L]),K=["run","--name",z,"--pull","never",...q,...J,"--entrypoint","sh",Z,"-c",Q],G=Bun.spawn([X,...K],{env:{...Bun.env},stdin:"ignore",stdout:"ignore",stderr:"pipe"}),U,H=$===void 0?void 0:setTimeout(()=>{let L=Date.now();U=E0(["kill",z]).then(()=>L,()=>{return})},$*1000),[_,I]=await Promise.all([G.exited,new Response(G.stderr).text()]);clearTimeout(H);let R=await U;if(R!==void 0)return{timedOut:!0,killedAt:R};if(_!==0)throw new i(J0(I)||`\`${X} run\` exited ${_}`);return{timedOut:!1}}async function I1(Z,z){let Q=`${Bun.env.TMPDIR||"/tmp"}/thunderjar-cp-${crypto.randomUUID()}`;await t`mkdir -p ${Q}`.quiet();try{let Y=Y0(),J=await t`${Y} cp ${`${Z}:${z}`} ${Q}/file`.quiet().nothrow();if(J.exitCode!==0){let $=J0(J.stderr);if($?.includes("Could not find the file"))return;throw new i($||`\`${Y} cp\` exited ${J.exitCode}`)}return await Bun.file(`${Q}/file`).text()}finally{await t`rm -rf ${Q}`.quiet()}}async function G9(Z,z,Q){let Y=await E0(["image","inspect","--format","{{json .Config.Entrypoint}}\t{{json .Config.Cmd}}",Q]),[J,$]=Y.trim().split("\t"),X=[`ENTRYPOINT ${J==="null"?'[""]':J}`,`CMD ${$==="null"?'["sh"]':$}`];await E0(["commit",...X.flatMap((q)=>["--change",q]),Z,z])}async function k0(Z){await E0(["rm","--force",Z])}async function K9(Z,z){await E0(["run","--detach","--name",z,"--pull","never","--entrypoint","sh",Z,"-c","exec sleep 2147483647"])}async function U9(Z,z,Q,Y){let J=Y0(),$=["exec",...Y===void 0?[]:["--interactive"],"--workdir",z,Z,...Q],X=Y===void 0?await t`${J} ${$}`.quiet().nothrow():await t`${J} ${$} < ${new Response(Y)}`.quiet().nothrow();if(X.exitCode!==0&&/^(Error response from daemon|OCI runtime exec failed|Cannot connect to the Docker daemon)/.test(X.stderr.toString()))throw new i(J0(X.stderr)||`\`${J} exec\` exited ${X.exitCode}`);return{stdout:X.stdout.toString(),stderr:X.stderr.toString(),exitCode:X.exitCode}}var $0="thunderjar",r4=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function W9(Z){if(r4.test(Z))return;return"must be lowercase letters and digits, joined by single separators (., _, __ or -), as a Docker repository name is."}var w0=(Z=$0)=>`${Z}-prerun`,s=(Z,z=$0)=>`${w0(z)}:${o(Z)}`,H9=(Z,z,Q,Y=$0)=>`${Y}-postrun:${Z}-${z}-${Q}`,B9=(Z,z,Q,Y=$0)=>`${Y}-run-${Z}-${z}-${Q}`,V9=(Z,z)=>`${Z}:prerun-h${o(z)}`,_9=(Z,z,Q,Y)=>`${Z}:postrun-e${z}-h${o(Q)}-i${String(Y-1).padStart(2,"0")}`;class I0 extends Error{repository;host;reason;constructor(Z,z,Q){super(`Can't push to ${Z}: no valid Docker login for ${z} (${Q}). Run \`docker login ${z}\`.`);this.repository=Z;this.host=z;this.reason=Q}}async function t0(Z){if(Z===null)return;let z=n0(Z.repository);try{await $9(z)}catch(Q){if(Q instanceof a0)throw new I0(Z.repository,z,Q.message);throw Q}}async function S1(Z,z,Q={}){Q.onPushing?.(Z,z),await X9(Z,z),Q.onPushed?.(Z,z)}async function r0(Z,z,Q,Y={}){if(z===null)return[];let J=[...new Set(Z.map(({imageHash:X})=>X))],$=[];for(let X of J){let q=V9(z.repository,X);await S1(s(X,Q),q,Y),$.push(q)}return $}var{$:e0}=globalThis.Bun;var X0={baseImage:"parameters/baseImage",codeState:"parameters/codeState",promptSet:"parameters/promptSet",harness:"parameters/harness"},e4={baseImage:"base image",codeState:"code state",promptSet:"prompt set",harness:"harness"},ZZ=(Z,z)=>Object.keys(X0).filter((Q)=>Q!==Z&&new RegExp(`(^|[^\\w/.]|\\./)${X0[Q]}(?![\\w-])`).test(z));function j9(Z,{file:z,declaration:Q},Y,J){let $=(G)=>J.push({file:z,field:"applyParameter",message:G}),X=Q.applyParameter;if(!X){if(Z!=="baseImage")return"";$("is missing. A base image's fragment provides the FROM.");return}let q;try{q=X(Q.config,Y)}catch(G){$(`threw: ${G instanceof Error?G.message:String(G)}`);return}if(typeof q!=="string"){$(`must return a Dockerfile fragment, a string, got ${typeof q}.`);return}if(Z==="baseImage"&&!/^FROM\s/i.test(q.trim())){$(`must return a fragment that starts with FROM, got ${JSON.stringify(q.trim().split(`
37
37
  `)[0])}.`);return}let K=ZZ(Z,q);if(K.length>0){let G=K.map((U)=>`the ${e4[U]}'s, ${X0[U]}`).join(", and ");$(`uses another parameter's folder in the build context: ${G}. A fragment can only use its own files/, through ctx.dir.`);return}return q.trim()}function L9(Z){return`${[Z.baseImage,"WORKDIR /workspace",Z.codeState,Z.promptSet,Z.harness,Z.initialPrompt].filter((Q)=>Q!=="").join(`
38
38
  `)}
39
- `}var zZ=(Z)=>({baseImage:`${P}/baseImages/${Z.baseImage}`,codeState:`${P}/codeStates/${Z.codeState}`,promptSet:`${P}/promptSets/${Z.promptSet}`,harness:`${P}/harnessModels/${c(Z.harnessModel).harness}`});async function QZ(){let Z=`${Bun.env.TMPDIR||"/tmp"}/thunderjar-build-${crypto.randomUUID()}`;return await e0`mkdir -p ${Z}`.quiet(),Z}async function YZ(Z,z,Q){let Y=zZ(z);for(let J of Object.keys(X0)){let $=`${Y[J]}/${u0}/`;if(!await v(Z,$))continue;let X=`${Q}/${X0[J]}`;await e0`mkdir -p ${X}`.quiet(),await e0`cp -RL ${Z}/${$}. ${X}`.quiet()}}async function Z1(Z,z,Q,Y={},J={}){let $=[...new Map(z.map((G)=>[G.imageHash,G])).values()],X=await o0(k0(Q)),q=$.map((G)=>({permutation:G,image:s(G.imageHash,Q)})),K=q.filter(({image:G})=>!X.has(G));for(let{permutation:G,image:U}of K){Y.onBuilding?.(U);let H=await QZ();try{await YZ(Z,G,H),await Bun.write(`${H}/Dockerfile`,G.dockerfile),await J9(H,U,J)}finally{await e0`rm -rf ${H}`.quiet()}Y.onBuilt?.(U)}return{built:K.map(({image:G})=>G),present:q.filter(({image:G})=>X.has(G)).map(({image:G})=>G)}}var{$:JZ,CryptoHasher:$Z,Glob:XZ}=globalThis.Bun;var S0=(Z)=>new $Z("sha256").update(Z).digest("hex");async function N9(Z,z="",Q=new Set){let{dev:Y,ino:J}=await Bun.file(Z).stat(),$=`${Y}:${J}`;if(Q.has($))return[];let X=new Set([...Q,$]),q=[...new XZ("*").scanSync({cwd:Z,onlyFiles:!1,dot:!0})];return(await Promise.all(q.map(async(G)=>{let U=await Bun.file(`${Z}/${G}`).stat().catch(()=>{return});if(!U)return[{file:`${z}${G}`,dangling:!0}];if(U.isDirectory())return N9(`${Z}/${G}`,`${z}${G}/`,X);return[{file:`${z}${G}`}]}))).flat()}async function M9(Z,z){let Q=`${z}/${u0}/`;if(!await v(Z,Q))return[];let Y=(await N9(`${Z}/${Q}`)).toSorted((J,$)=>J.file<$.file?-1:J.file>$.file?1:0);return Promise.all(Y.map(async({file:J,dangling:$})=>[J,$?null:S0(await Bun.file(`${Z}/${Q}${J}`).arrayBuffer())]))}var qZ={baseImage:["baseImages","declareBaseImage"],codeState:["codeStates","declareCodeState"],promptSet:["promptSets","declarePromptSet"]},GZ={modelId:"<modelId>",initialPrompt:"<initialPrompt>",promptPath:"<promptPath>",resultPath:"<resultPath>",sessionId:"<sessionId>"};async function KZ(Z){let z=Z.slice(0,Z.lastIndexOf("/"))||"/";for(let Q=z;;Q=Q.slice(0,Q.lastIndexOf("/"))||"/"){if(await Bun.file(`${Q}/.git`).stat().then(()=>!0,()=>!1))return Q;if(Q==="/")return z}}function UZ(Z){return async(z)=>{let Q=await JZ`sh -c ${z}`.cwd(Z).quiet().nothrow();if(Q.exitCode===0)return Q.stdout.toString().trim();let Y=Q.stderr.toString().trim();throw Error(`\`${z}\` exited with ${Q.exitCode}${Y?`: ${Y}`:""}`)}}function D1(Z){if(Z===null||typeof Z==="string"||typeof Z==="boolean")return!0;if(typeof Z==="number")return Number.isFinite(Z);if(Array.isArray(Z))return Z.every(D1);if(typeof Z!=="object"||Object.getPrototypeOf(Z)!==Object.prototype)return!1;return Object.values(Z).every(D1)}var P1={baseImage:"base image",codeState:"code state",promptSet:"prompt set",harnessModel:"harness",initialPrompt:"initial prompt"};async function V0(Z,z,Q={}){let Y=[],J=new Map,$=(W,T)=>{if(!J.has(W))J.set(W,T());return J.get(W)},X=(W,T)=>$(`load\x00${W}`,async()=>await E(Z,W,T,Y)),q=async(W,T)=>{let[S,N]=qZ[W],F=`${P}/${S}/${T}`,D=`${F}/index.ts`,b=await X(D,N);return b&&{key:`${W}\x00${T}`,label:`${P1[W]} ${JSON.stringify(T)}`,file:D,dir:F,declaration:b}},K=async(W)=>{let{harness:T,modelId:S}=c(W),N=`${P}/harnessModels/${T}`,F=`${N}/index.ts`,D=await X(F,"declareHarness");if(!D)return;return{key:`harnessModel\x00${T}`,label:`${P1.harnessModel} ${JSON.stringify(T)}`,file:F,dir:N,declaration:D,version:D.version,modelId:S}},G=async(W)=>{let T=`${P}/tasks/${z.task}/initial-prompts/${W}.ts`,S=await X(T,"declareInitialPrompt");return S&&{key:`initialPrompt\x00${W}`,label:`${P1.initialPrompt} ${JSON.stringify(W)}`,file:T,declaration:S}},U=[];for(let W of t1(z))U.push({permutation:W,baseImage:await q("baseImage",W.baseImage),codeState:await q("codeState",W.codeState),promptSet:await q("promptSet",W.promptSet),harnessModel:await K(W.harnessModel),initialPrompt:await G(W.initialPrompt)});if(Y.length>0)throw f(Y);let H=Q.exec??UZ(await KZ(Z)),_=new Map,I=[];for(let W of U)for(let T of w){let{key:S,label:N,declaration:F}=W[T];if(_.has(S))continue;if(_.set(S,void 0),F.resolve===void 0)continue;try{let D=await F.resolve(F.config,{exec:H});if(D1(D))_.set(S,D);else I.push(`${N}: resolve must return a string, number, boolean or null, or a list or object of them, got ${D===void 0?"undefined":typeof D}.`)}catch(D){I.push(`${N}: resolve threw: ${D instanceof Error?D.message:String(D)}`)}}if(I.length>0)throw new k(...I);let R=new Map,L=(W,T,S)=>{let N=R.get(W.key);if(N)return N;let F=_.get(W.key),D={...W.dir!==void 0&&{dir:X0[T]},...W.version!==void 0&&{version:W.version},resolved:F},b=j9(T,W,D,Y),n=b===void 0?Promise.resolve(void 0):S(b);return R.set(W.key,n),n},B=(W,T)=>L(T,W,async(S)=>{let N=await M9(Z,T.dir),F=W==="baseImage"?{runOptions:T.declaration.runOptions??[]}:{};return{fragment:S,files:N,hash:S0(JSON.stringify({fragment:S,files:N,...F}))}}),V=(W)=>L(W,"harness",async(T)=>{let S;try{let F=_.get(W.key);S=[0,1].map((D)=>String(W.declaration.cli({...GZ,version:W.version,turn:D,resolved:F})))}catch(F){Y.push({file:W.file,field:"cli",message:`threw: ${F instanceof Error?F.message:String(F)}`});return}let N=await M9(Z,W.dir);return{fragment:T,files:N,hash:S0(JSON.stringify({fragment:T,cli:S,requiredEnv:W.declaration.requiredEnv??[],files:N}))}}),M=(W)=>L(W,"initialPrompt",async(T)=>{let{prompt:S,turns:N,timeoutSeconds:F}=W.declaration;return{fragment:T,files:[],hash:S0(JSON.stringify({fragment:T,prompt:S,turns:N,timeoutSeconds:F}))}}),j=[];for(let W of U){let{permutation:T}=W,S=W.harnessModel,N=await B("baseImage",W.baseImage),F=await B("codeState",W.codeState),D=await B("promptSet",W.promptSet),b=await V(S),n=await M(W.initialPrompt);if(!N||!F||!D||!b||!n)continue;let r={baseImage:N.hash,codeState:F.hash,promptSet:D.hash,harnessModel:b.hash,initialPrompt:n.hash},u=L9({baseImage:N.fragment,codeState:F.fragment,promptSet:D.fragment,harness:b.fragment,initialPrompt:n.fragment}),J4={baseImage:N.files,codeState:F.files,promptSet:D.files,harness:b.files},v1={};for(let x1 of w){let f1=_.get(W[x1].key);if(f1!==void 0)v1[x1]=f1}j.push({...T,hash:S0(JSON.stringify({parameterHashes:r,modelId:S.modelId})),parameterHashes:r,modelId:S.modelId,imageHash:S0(JSON.stringify({dockerfile:u,files:J4})),dockerfile:u,resolved:v1})}if(Y.length>0)throw f(Y);return j}function g(Z){return async(...z)=>{try{await Z(...z)}catch(Q){if(!(Q instanceof k))throw Q;for(let Y of Q.problems)console.error(`Error: ${Y}`);process.exitCode=1}}}function z1(Z,z){if(Z.timedOut)return`timed out after ${Z.timeoutSeconds}s`;let Q=Z.exitCode===0?"done":`exited ${Z.exitCode}`;return z===null?`${Q}, no result file`:Q}var T9=(Z,z)=>!Z.timedOut&&Z.exitCode===0&&z!==null,q0=(Z)=>Math.round(Z).toLocaleString("en-US"),WZ=({inputTokens:Z,outputTokens:z,cacheCreationTokens:Q,cacheReadTokens:Y})=>Z+z+Q+Y,Q1=(Z)=>Z?.outcome==="collected"?Z.models.reduce((z,Q)=>z+WZ(Q),0):void 0;function Y1(Z){if(Z?.outcome!=="collected"||Z.models.length===0)return;if(Z.models.some(({costUsd:z,costBasis:Q})=>z===void 0||Q==="unknown"))return;return Z.models.reduce((z,{costUsd:Q})=>z+Q,0)}var C0=(Z)=>Z>0&&Z<0.0005?"<$0.001":`$${Z.toFixed(3)}`,_0=(Z,z)=>`${Z} ${z}${Z===1?"":"s"}`,b0=(Z)=>new Date(Z).toISOString().slice(0,16).replace("T"," ");function J1(Z,z){let Q=Z.slice(0,Z.lastIndexOf(":"));return`Pushing ${Z} failed: ${z.message}
39
+ `}var zZ=(Z)=>({baseImage:`${P}/baseImages/${Z.baseImage}`,codeState:`${P}/codeStates/${Z.codeState}`,promptSet:`${P}/promptSets/${Z.promptSet}`,harness:`${P}/harnessModels/${c(Z.harnessModel).harness}`});async function QZ(){let Z=`${Bun.env.TMPDIR||"/tmp"}/thunderjar-build-${crypto.randomUUID()}`;return await e0`mkdir -p ${Z}`.quiet(),Z}async function YZ(Z,z,Q){let Y=zZ(z);for(let J of Object.keys(X0)){let $=`${Y[J]}/${u0}/`;if(!await v(Z,$))continue;let X=`${Q}/${X0[J]}`;await e0`mkdir -p ${X}`.quiet(),await e0`cp -RL ${Z}/${$}. ${X}`.quiet()}}async function Z1(Z,z,Q,Y={},J={}){let $=[...new Map(z.map((G)=>[G.imageHash,G])).values()],X=await o0(w0(Q)),q=$.map((G)=>({permutation:G,image:s(G.imageHash,Q)})),K=q.filter(({image:G})=>!X.has(G));for(let{permutation:G,image:U}of K){Y.onBuilding?.(U);let H=await QZ();try{await YZ(Z,G,H),await Bun.write(`${H}/Dockerfile`,G.dockerfile),await J9(H,U,J)}finally{await e0`rm -rf ${H}`.quiet()}Y.onBuilt?.(U)}return{built:K.map(({image:G})=>G),present:q.filter(({image:G})=>X.has(G)).map(({image:G})=>G)}}var{$:JZ,CryptoHasher:$Z,Glob:XZ}=globalThis.Bun;var S0=(Z)=>new $Z("sha256").update(Z).digest("hex");async function N9(Z,z="",Q=new Set){let{dev:Y,ino:J}=await Bun.file(Z).stat(),$=`${Y}:${J}`;if(Q.has($))return[];let X=new Set([...Q,$]),q=[...new XZ("*").scanSync({cwd:Z,onlyFiles:!1,dot:!0})];return(await Promise.all(q.map(async(G)=>{let U=await Bun.file(`${Z}/${G}`).stat().catch(()=>{return});if(!U)return[{file:`${z}${G}`,dangling:!0}];if(U.isDirectory())return N9(`${Z}/${G}`,`${z}${G}/`,X);return[{file:`${z}${G}`}]}))).flat()}async function M9(Z,z){let Q=`${z}/${u0}/`;if(!await v(Z,Q))return[];let Y=(await N9(`${Z}/${Q}`)).toSorted((J,$)=>J.file<$.file?-1:J.file>$.file?1:0);return Promise.all(Y.map(async({file:J,dangling:$})=>[J,$?null:S0(await Bun.file(`${Z}/${Q}${J}`).arrayBuffer())]))}var qZ={baseImage:["baseImages","declareBaseImage"],codeState:["codeStates","declareCodeState"],promptSet:["promptSets","declarePromptSet"]},GZ={modelId:"<modelId>",initialPrompt:"<initialPrompt>",promptPath:"<promptPath>",resultPath:"<resultPath>",sessionId:"<sessionId>"};async function KZ(Z){let z=Z.slice(0,Z.lastIndexOf("/"))||"/";for(let Q=z;;Q=Q.slice(0,Q.lastIndexOf("/"))||"/"){if(await Bun.file(`${Q}/.git`).stat().then(()=>!0,()=>!1))return Q;if(Q==="/")return z}}function UZ(Z){return async(z)=>{let Q=await JZ`sh -c ${z}`.cwd(Z).quiet().nothrow();if(Q.exitCode===0)return Q.stdout.toString().trim();let Y=Q.stderr.toString().trim();throw Error(`\`${z}\` exited with ${Q.exitCode}${Y?`: ${Y}`:""}`)}}function D1(Z){if(Z===null||typeof Z==="string"||typeof Z==="boolean")return!0;if(typeof Z==="number")return Number.isFinite(Z);if(Array.isArray(Z))return Z.every(D1);if(typeof Z!=="object"||Object.getPrototypeOf(Z)!==Object.prototype)return!1;return Object.values(Z).every(D1)}var P1={baseImage:"base image",codeState:"code state",promptSet:"prompt set",harnessModel:"harness",initialPrompt:"initial prompt"};async function V0(Z,z,Q={}){let Y=[],J=new Map,$=(W,T)=>{if(!J.has(W))J.set(W,T());return J.get(W)},X=(W,T)=>$(`load\x00${W}`,async()=>await E(Z,W,T,Y)),q=async(W,T)=>{let[S,N]=qZ[W],F=`${P}/${S}/${T}`,D=`${F}/index.ts`,b=await X(D,N);return b&&{key:`${W}\x00${T}`,label:`${P1[W]} ${JSON.stringify(T)}`,file:D,dir:F,declaration:b}},K=async(W)=>{let{harness:T,modelId:S}=c(W),N=`${P}/harnessModels/${T}`,F=`${N}/index.ts`,D=await X(F,"declareHarness");if(!D)return;return{key:`harnessModel\x00${T}`,label:`${P1.harnessModel} ${JSON.stringify(T)}`,file:F,dir:N,declaration:D,version:D.version,modelId:S}},G=async(W)=>{let T=`${P}/tasks/${z.task}/initial-prompts/${W}.ts`,S=await X(T,"declareInitialPrompt");return S&&{key:`initialPrompt\x00${W}`,label:`${P1.initialPrompt} ${JSON.stringify(W)}`,file:T,declaration:S}},U=[];for(let W of t1(z))U.push({permutation:W,baseImage:await q("baseImage",W.baseImage),codeState:await q("codeState",W.codeState),promptSet:await q("promptSet",W.promptSet),harnessModel:await K(W.harnessModel),initialPrompt:await G(W.initialPrompt)});if(Y.length>0)throw f(Y);let H=Q.exec??UZ(await KZ(Z)),_=new Map,I=[];for(let W of U)for(let T of k){let{key:S,label:N,declaration:F}=W[T];if(_.has(S))continue;if(_.set(S,void 0),F.resolve===void 0)continue;try{let D=await F.resolve(F.config,{exec:H});if(D1(D))_.set(S,D);else I.push(`${N}: resolve must return a string, number, boolean or null, or a list or object of them, got ${D===void 0?"undefined":typeof D}.`)}catch(D){I.push(`${N}: resolve threw: ${D instanceof Error?D.message:String(D)}`)}}if(I.length>0)throw new w(...I);let R=new Map,L=(W,T,S)=>{let N=R.get(W.key);if(N)return N;let F=_.get(W.key),D={...W.dir!==void 0&&{dir:X0[T]},...W.version!==void 0&&{version:W.version},resolved:F},b=j9(T,W,D,Y),n=b===void 0?Promise.resolve(void 0):S(b);return R.set(W.key,n),n},B=(W,T)=>L(T,W,async(S)=>{let N=await M9(Z,T.dir),F=W==="baseImage"?{runOptions:T.declaration.runOptions??[]}:{};return{fragment:S,files:N,hash:S0(JSON.stringify({fragment:S,files:N,...F}))}}),V=(W)=>L(W,"harness",async(T)=>{let S;try{let F=_.get(W.key);S=[0,1].map((D)=>String(W.declaration.cli({...GZ,version:W.version,turn:D,resolved:F})))}catch(F){Y.push({file:W.file,field:"cli",message:`threw: ${F instanceof Error?F.message:String(F)}`});return}let N=await M9(Z,W.dir);return{fragment:T,files:N,hash:S0(JSON.stringify({fragment:T,cli:S,requiredEnv:W.declaration.requiredEnv??[],files:N}))}}),M=(W)=>L(W,"initialPrompt",async(T)=>{let{prompt:S,turns:N,timeoutSeconds:F}=W.declaration;return{fragment:T,files:[],hash:S0(JSON.stringify({fragment:T,prompt:S,turns:N,timeoutSeconds:F}))}}),j=[];for(let W of U){let{permutation:T}=W,S=W.harnessModel,N=await B("baseImage",W.baseImage),F=await B("codeState",W.codeState),D=await B("promptSet",W.promptSet),b=await V(S),n=await M(W.initialPrompt);if(!N||!F||!D||!b||!n)continue;let r={baseImage:N.hash,codeState:F.hash,promptSet:D.hash,harnessModel:b.hash,initialPrompt:n.hash},u=L9({baseImage:N.fragment,codeState:F.fragment,promptSet:D.fragment,harness:b.fragment,initialPrompt:n.fragment}),J4={baseImage:N.files,codeState:F.files,promptSet:D.files,harness:b.files},v1={};for(let x1 of k){let f1=_.get(W[x1].key);if(f1!==void 0)v1[x1]=f1}j.push({...T,hash:S0(JSON.stringify({parameterHashes:r,modelId:S.modelId})),parameterHashes:r,modelId:S.modelId,imageHash:S0(JSON.stringify({dockerfile:u,files:J4})),dockerfile:u,resolved:v1})}if(Y.length>0)throw f(Y);return j}function g(Z){return async(...z)=>{try{await Z(...z)}catch(Q){if(!(Q instanceof w))throw Q;for(let Y of Q.problems)console.error(`Error: ${Y}`);process.exitCode=1}}}function z1(Z,z){if(Z.timedOut)return`timed out after ${Z.timeoutSeconds}s`;let Q=Z.exitCode===0?"done":`exited ${Z.exitCode}`;return z===null?`${Q}, no result file`:Q}var T9=(Z,z)=>!Z.timedOut&&Z.exitCode===0&&z!==null,q0=(Z)=>Math.round(Z).toLocaleString("en-US"),WZ=({inputTokens:Z,outputTokens:z,cacheCreationTokens:Q,cacheReadTokens:Y})=>Z+z+Q+Y,Q1=(Z)=>Z?.outcome==="collected"?Z.models.reduce((z,Q)=>z+WZ(Q),0):void 0;function Y1(Z){if(Z?.outcome!=="collected"||Z.models.length===0)return;if(Z.models.some(({costUsd:z,costBasis:Q})=>z===void 0||Q==="unknown"))return;return Z.models.reduce((z,{costUsd:Q})=>z+Q,0)}var C0=(Z)=>Z>0&&Z<0.0005?"<$0.001":`$${Z.toFixed(3)}`,_0=(Z,z)=>`${Z} ${z}${Z===1?"":"s"}`,b0=(Z)=>new Date(Z).toISOString().slice(0,16).replace("T"," ");function J1(Z,z){let Q=Z.slice(0,Z.lastIndexOf(":"));return`Pushing ${Z} failed: ${z.message}
40
40
  Check that your Docker login for ${n0(Q)} can push to ${Q}: on ghcr.io, a token needs the write:packages scope.`}var $1=(Z)=>typeof Z==="string"?Z:JSON.stringify(Z);function P0(){return new p("--image-prefix <name>","start every image name with <name>, e.g. <name>-prerun:<hash>, instead of thunderjar").default($0).argParser((Z)=>{let z=W9(Z);if(z)throw new e(`It ${z}`);return Z})}async function HZ(Z,z,Q){let Y=await C(Z),J=await Q0(Y,z),$=await V0(Y,J);return[...new Map($.map((q)=>[q.imageHash,q])).values()].map(({imageHash:q,dockerfile:K})=>`# ${s(q,Q)}
41
41
  ${K.trimEnd()}`).join(`
42
42
 
@@ -169,7 +169,7 @@ export default declareTestCase({
169
169
  initialPrompt: ["plain"],
170
170
  iterations: 1,
171
171
  });
172
- `,wZ=`import { declareBaseImage } from "thunderjar";
172
+ `,kZ=`import { declareBaseImage } from "thunderjar";
173
173
 
174
174
  // With bun, which the templateTest measurement runs its tests with, and a git identity, so the
175
175
  // agent and a prompt set can commit. \`--system\`, so a harness that runs as another user has it too.
@@ -179,7 +179,7 @@ RUN npm install --global bun@1.3.14
179
179
  RUN git config --system user.name "Thunderjar agent" \\\\
180
180
  && git config --system user.email agent@thunderjar.invalid\`,
181
181
  });
182
- `,kZ=G1("declareInitialPrompt",`{
182
+ `,wZ=G1("declareInitialPrompt",`{
183
183
  prompt: "Create a file isPrime.ts exporting a function that tests for primality.",
184
184
  timeoutSeconds: 600,
185
185
  }`),CZ=G1("declareMeasurement",`{
@@ -248,20 +248,20 @@ RUN cd /workspace && git add -A && git commit --quiet -m "Thunderjar: apply prom
248
248
  - Add a test beside each new module.
249
249
  `,d="test-case-parameters";function R9({nestedPackage:Z,repository:z}){return{...Z&&{"package.json":y9({name:"thunderjar-config",private:!0,type:"module",dependencies:{thunderjar:"latest"}})},"tsconfig.json":yZ,".gitignore":["_generated/",".data/",...Z?["node_modules/"]:[]].join(`
250
250
  `)+`
251
- `,"thunderjar.config.ts":OZ,"test-cases/compare-models.ts":RZ,"test-cases/compare-harnesses.ts":EZ,[`${d}/baseImages/node20/index.ts`]:wZ,[`${d}/codeStates/baseline/index.ts`]:fZ(z),[`${d}/promptSets/snerk/index.ts`]:gZ,[`${d}/promptSets/house-style/index.ts`]:hZ,[`${d}/promptSets/house-style/files/AGENTS.md`]:cZ,...Object.fromEntries(Object.entries(O9).map(([Q,Y])=>[`${d}/harnessModels/${Q}/index.ts`,Y])),[`${d}/tasks/is-prime/initial-prompts/plain.ts`]:kZ,[`${d}/tasks/is-prime/measurements/isPrimeTsExists.ts`]:CZ,[`${d}/tasks/is-prime/measurements/isPrimeTemplateTest.ts`]:bZ,[`${d}/tasks/is-prime/measurements/templates/isPrime.test.ts.template`]:vZ,[`${d}/tasks/is-prime/measurements/tsIgnoreCount.ts`]:xZ}}var K1=".thunderjar";async function pZ(Z){try{return(await Bun.file(Z).stat()).isDirectory()}catch{return!1}}async function dZ(Z){let z=async(J)=>{let $=await uZ`git ${J}`.cwd(Z).quiet().nothrow();return $.exitCode===0?$.stdout.toString().trim():void 0},Q=await z(["rev-parse","--verify","--quiet","HEAD"]),Y=Q&&await z(["remote","get-url","origin"]);return Q&&Y?{url:Y,commit:Q}:void 0}async function lZ(Z){let z=`${Z}/${K1}`,Q=!await pZ(z),Y=!await Bun.file(`${Z}/package.json`).exists(),J=await dZ(Z),$={createdFolder:Q,created:[],existing:[]};for(let[X,q]of Object.entries(R9({nestedPackage:Y,repository:J}))){let K=Bun.file(`${z}/${X}`);if(await K.exists()){$.existing.push(X);continue}await Bun.write(K,q),$.created.push(X)}return $}function E9(){return new y("init").description("Scaffold the .thunderjar/ configuration folder in the current directory, with two test cases, one comparing models and one comparing harnesses, and starter prompt sets and harnesses to copy. Existing files are left as they are.").action(async()=>{let{createdFolder:Z,created:z,existing:Q}=await lZ(process.cwd());if(Z)console.log(`Created ${K1}/`);for(let Y of z)console.log(`Created ${K1}/${Y}`);for(let Y of Q)console.log(`Exists ${K1}/${Y}`)})}var w9=[["baseImage",(Z)=>Z.baseImage.join(", ")],["codeState",(Z)=>Z.codeState.join(", ")],["promptSet",(Z)=>Z.promptSet.join(", ")],["harnessModel",(Z)=>Z.harnessModel.join(", ")],["task",(Z)=>Z.task],["initialPrompt",(Z)=>Z.initialPrompt.join(", ")]],mZ=Math.max(...w9.map(([Z])=>`${Z}: `.length));function iZ(Z){return w9.map(([z,Q])=>`${`${z}:`.padEnd(mZ)}${Q(Z)}`).join(`
252
- `)}function sZ(Z,z,Q){let Y=z.length,J=`Matrix shape: ${s0(Z).join("/")} (${Y} ${Y===1?"permutation":"permutations"})`,$=Math.max(2,String(Y).length),X=w.map((K)=>Math.max(...z.map((G)=>G[K].length))),q=z.map((K,G)=>{let U=w.map((H,_)=>K[H].padEnd(X[_])).join(" | ");return`${String(G+1).padStart($)} ${U} ${o(K.hash)} ${Q[G]}`});return[J,"",...q].join(`
253
- `)}function nZ(Z){let z=new Map;for(let Y of Z)for(let J of w){let $=Y.resolved[J];if($!==void 0)z.set(`${J}\x00${Y[J]}`,[J,Y[J],$1($)])}if(z.size===0)return[];let Q=[0,1].map((Y)=>Math.max(...[...z.values()].map((J)=>J[Y].length)));return["Resolved",...[...z.values()].map(([Y,J,$])=>` ${Y.padEnd(Q[0])} ${J.padEnd(Q[1])} ${$}`)]}async function aZ(Z,z){try{let Q=await o0(k0(z));return{statuses:Z.map((Y)=>Q.has(s(Y.imageHash,z))?"built":"missing")}}catch(Q){if(!(Q instanceof m))throw Q;return{statuses:Z.map(()=>"unknown"),unavailable:Q.message}}}async function oZ(Z,z,Q){let Y=await C(Z),{build:J}=await N0(Y),$=await Q0(Y,z);await R0(Y,$),M0(J);let X=await V0(Y,$),{statuses:q,unavailable:K}=await aZ(X,Q);return{output:[iZ($),sZ($,X,q),nZ(X).join(`
251
+ `,"thunderjar.config.ts":OZ,"test-cases/compare-models.ts":RZ,"test-cases/compare-harnesses.ts":EZ,[`${d}/baseImages/node20/index.ts`]:kZ,[`${d}/codeStates/baseline/index.ts`]:fZ(z),[`${d}/promptSets/snerk/index.ts`]:gZ,[`${d}/promptSets/house-style/index.ts`]:hZ,[`${d}/promptSets/house-style/files/AGENTS.md`]:cZ,...Object.fromEntries(Object.entries(O9).map(([Q,Y])=>[`${d}/harnessModels/${Q}/index.ts`,Y])),[`${d}/tasks/is-prime/initial-prompts/plain.ts`]:wZ,[`${d}/tasks/is-prime/measurements/isPrimeTsExists.ts`]:CZ,[`${d}/tasks/is-prime/measurements/isPrimeTemplateTest.ts`]:bZ,[`${d}/tasks/is-prime/measurements/templates/isPrime.test.ts.template`]:vZ,[`${d}/tasks/is-prime/measurements/tsIgnoreCount.ts`]:xZ}}var K1=".thunderjar";async function pZ(Z){try{return(await Bun.file(Z).stat()).isDirectory()}catch{return!1}}async function dZ(Z){let z=async(J)=>{let $=await uZ`git ${J}`.cwd(Z).quiet().nothrow();return $.exitCode===0?$.stdout.toString().trim():void 0},Q=await z(["rev-parse","--verify","--quiet","HEAD"]),Y=Q&&await z(["remote","get-url","origin"]);return Q&&Y?{url:Y,commit:Q}:void 0}async function lZ(Z){let z=`${Z}/${K1}`,Q=!await pZ(z),Y=!await Bun.file(`${Z}/package.json`).exists(),J=await dZ(Z),$={createdFolder:Q,created:[],existing:[]};for(let[X,q]of Object.entries(R9({nestedPackage:Y,repository:J}))){let K=Bun.file(`${z}/${X}`);if(await K.exists()){$.existing.push(X);continue}await Bun.write(K,q),$.created.push(X)}return $}function E9(){return new y("init").description("Scaffold the .thunderjar/ configuration folder in the current directory, with two test cases, one comparing models and one comparing harnesses, and starter prompt sets and harnesses to copy. Existing files are left as they are.").action(async()=>{let{createdFolder:Z,created:z,existing:Q}=await lZ(process.cwd());if(Z)console.log(`Created ${K1}/`);for(let Y of z)console.log(`Created ${K1}/${Y}`);for(let Y of Q)console.log(`Exists ${K1}/${Y}`)})}var k9=[["baseImage",(Z)=>Z.baseImage.join(", ")],["codeState",(Z)=>Z.codeState.join(", ")],["promptSet",(Z)=>Z.promptSet.join(", ")],["harnessModel",(Z)=>Z.harnessModel.join(", ")],["task",(Z)=>Z.task],["initialPrompt",(Z)=>Z.initialPrompt.join(", ")]],mZ=Math.max(...k9.map(([Z])=>`${Z}: `.length));function iZ(Z){return k9.map(([z,Q])=>`${`${z}:`.padEnd(mZ)}${Q(Z)}`).join(`
252
+ `)}function sZ(Z,z,Q){let Y=z.length,J=`Matrix shape: ${s0(Z).join("/")} (${Y} ${Y===1?"permutation":"permutations"})`,$=Math.max(2,String(Y).length),X=k.map((K)=>Math.max(...z.map((G)=>G[K].length))),q=z.map((K,G)=>{let U=k.map((H,_)=>K[H].padEnd(X[_])).join(" | ");return`${String(G+1).padStart($)} ${U} ${o(K.hash)} ${Q[G]}`});return[J,"",...q].join(`
253
+ `)}function nZ(Z){let z=new Map;for(let Y of Z)for(let J of k){let $=Y.resolved[J];if($!==void 0)z.set(`${J}\x00${Y[J]}`,[J,Y[J],$1($)])}if(z.size===0)return[];let Q=[0,1].map((Y)=>Math.max(...[...z.values()].map((J)=>J[Y].length)));return["Resolved",...[...z.values()].map(([Y,J,$])=>` ${Y.padEnd(Q[0])} ${J.padEnd(Q[1])} ${$}`)]}async function aZ(Z,z){try{let Q=await o0(w0(z));return{statuses:Z.map((Y)=>Q.has(s(Y.imageHash,z))?"built":"missing")}}catch(Q){if(!(Q instanceof m))throw Q;return{statuses:Z.map(()=>"unknown"),unavailable:Q.message}}}async function oZ(Z,z,Q){let Y=await C(Z),{build:J}=await N0(Y),$=await Q0(Y,z);await R0(Y,$),M0(J);let X=await V0(Y,$),{statuses:q,unavailable:K}=await aZ(X,Q);return{output:[iZ($),sZ($,X,q),nZ(X).join(`
254
254
  `)].filter(Boolean).join(`
255
255
 
256
- `),warning:K&&`Warning: Docker can't be reached, so whether each prerun image is built is unknown: ${K}`}}function k9(){return new y("plan").description("Show what a test case would run, without running it: the parameters it names, each permutation of them with its hash, and whether its prerun image is built, then what each parameter with a resolve resolved to.").argument("<test case>",`the name of a test case, declared in ${O}/test-cases/<test case>.ts`).addOption(P0()).action(g(async(Z,z)=>{let{output:Q,warning:Y}=await oZ(process.cwd(),Z,z.imagePrefix);if(console.log(Q),Y)console.error(Y)}))}var tZ="/thunderjar/result.json",rZ="/thunderjar/prompt.txt";function eZ(Z,z){if(z===1)return{promptPath:rZ,resultPath:tZ};return{promptPath:`/thunderjar/turns/${Z+1}/prompt.txt`,resultPath:`/thunderjar/turns/${Z+1}/result.json`}}var Z2=(Z)=>Z.turns??[Z.prompt],z2=()=>({outcome:"unavailable",reason:"notReported"});async function Q2(Z,z,Q,Y){let{harness:J}=c(Q.harnessModel),[$,X,q]=await Promise.all([E(Z,`${P}/baseImages/${Q.baseImage}/index.ts`,"declareBaseImage",Y),E(Z,`${P}/harnessModels/${J}/index.ts`,"declareHarness",Y),E(Z,`${P}/tasks/${z}/initial-prompts/${Q.initialPrompt}.ts`,"declareInitialPrompt",Y)]);if(!$||!X||!q)return;let K=X.collectTokenCosts??z2;return{baseImage:$,harness:X,collectTokenCosts:K,version:X.version,modelId:Q.modelId,initialPrompt:q}}function Y2({harness:Z,version:z,modelId:Q,initialPrompt:Y},J,$){let X=Z2(Y);return X.map((q,K)=>{let G=eZ(K,X.length),U=Z.cli({version:z,modelId:Q,initialPrompt:q,...G,turn:K,sessionId:J,resolved:$});return{prompt:q,...G,command:U}})}async function y1(Z,z,Q,Y=$0,J={}){let $=await V0(Z,z,J),X=[],q=await Promise.all($.map((K)=>Q2(Z,z.task,K,X)));if(X.length>0)throw f(X);return{executionId:Q,permutations:$.map((K,G)=>{let U=q[G];return{number:G+1,permutation:K,prerunImage:s(K.imageHash,Y),env:T1(U.harness),runOptions:U.baseImage.runOptions??[],timeoutSeconds:U.initialPrompt.timeoutSeconds,harness:U.harness,collectTokenCosts:U.collectTokenCosts,version:U.version,modelId:U.modelId,iterations:Array.from({length:z.iterations},(H,_)=>{let I=crypto.randomUUID();return{number:_+1,postrunImage:H9(Q,G+1,_+1,Y),sessionId:I,turns:Y2(U,I,K.resolved.harnessModel)}})}})}}var U1="/thunderjar/run.json",C9=(Z)=>`'${Z.replaceAll("'","'\\''")}'`,J2=["now_ms() {"," ms=$(date +%s%3N)"," case $ms in",` ${"[0-9]".repeat(13)}) echo "$ms" ;;`," *) echo $(( $(date +%s) * 1000 )) ;;"," esac","}"].join(`
257
- `);function $2(Z){let z=[...new Set(["/thunderjar",...Z.map(({promptPath:J})=>J.slice(0,J.lastIndexOf("/")))])],Q=Z.length>1,Y=({command:J},$)=>{let X=["turn_start=$(now_ms)",`sh -c ${C9(J)}`,"code=$?",...Q?[`turns="$turns${$===0?"":","}{\\"startedAt\\":$turn_start,\\"finishedAt\\":$(now_ms),\\"exitCode\\":$code}"`]:[]];return $===0?X:["if [ $code -eq 0 ]; then",...X.map((q)=>` ${q}`),"fi"]};return[`mkdir -p ${z.join(" ")}`,...Z.map(({prompt:J,promptPath:$})=>`printf '%s' ${C9(J)} > ${$}`),J2,"start=$(now_ms)",`echo "{\\"startedAt\\":$start}" > ${U1}`,...Q?['turns=""']:[],...Z.flatMap(Y),"end=$(now_ms)",`echo "{\\"startedAt\\":$start,\\"finishedAt\\":$end,\\"exitCode\\":$code${Q?",\\\"turns\\\":[$turns]":""}}" > ${U1}`].join(`
258
- `)}var W1=(Z)=>Number.isInteger(Z)&&Z>=1000000000000&&Z<10000000000000,X2=(Z)=>{let{startedAt:z,finishedAt:Q,exitCode:Y}=Z??{};return W1(z)&&W1(Q)&&typeof Y==="number"};function q2(Z,z,Q){let Y;try{Y=Z===void 0?void 0:JSON.parse(Z)}catch{Y=void 0}let{startedAt:J,finishedAt:$,exitCode:X,turns:q}=Y??{},K=()=>new i(`The execution wrapper left no valid ${U1}: ${Z===void 0?"there is none":Z.trim()}`);if(!W1(J))throw K();if(Q!==void 0)return{startedAt:J,finishedAt:Q,exitCode:null,timedOut:!0,timeoutSeconds:z};if(!W1($)||typeof X!=="number")throw K();if(q!==void 0&&(!Array.isArray(q)||!q.every(X2)))throw K();return{startedAt:J,finishedAt:$,exitCode:X,timedOut:!1,timeoutSeconds:z,...q&&{turns:q}}}async function b9(Z){try{let z=await q9(Z.prerunImage,Z.container,$2(Z.turns),{env:Z.env,runOptions:Z.runOptions,timeoutSeconds:Z.timeoutSeconds}),Q=z.timedOut?z.killedAt:void 0,Y=q2(await I1(Z.container,U1),Z.timeoutSeconds,Q),J=[];for(let{resultPath:$}of Z.turns)J.push(await I1(Z.container,$)??null);return await G9(Z.container,Z.postrunImage,Z.prerunImage),{execution:Y,harnessResults:J}}finally{await w0(Z.container).catch(()=>{})}}var v9=(Z)=>Z instanceof Error?Z.message:String(Z),G2=(Z)=>Z.outcome==="erroredWhileMeasuring"?{outcome:"erroredWhileMeasuring",error:{message:v9(Z.error)}}:Z;async function x9(Z,z,Q=()=>new Date){let Y={};for(let{name:J,declaration:$,config:X,contentHash:q}of Z){let K=L0[$.instrument],G=await z(K.usesContainer!==!1),U;try{U=G2(await K.evaluate(X,G))}catch(H){U={outcome:"erroredWhileMeasuring",error:{message:v9(H)}}}finally{await G.close()}Y[J]={instrument:$.instrument,contentHash:q,measuredAt:Q().toISOString(),outcome:U}}return Y}var H1="/workspace";function f9({harnessResult:Z,reply:z,replies:Q}){let Y=async()=>{throw Error("this instrument has no measurement container: it reads only what was recorded of the run")};return{workdir:H1,harnessResult:Z,reply:z,replies:Q,exec:Y,readFile:Y,writeFile:Y,glob:Y,close:async()=>{}}}async function g9(Z,z,{harnessResult:Q,reply:Y,replies:J}){try{await K9(Z,z)}catch(q){throw await w0(z).catch(()=>{}),q}let $=(q,K)=>U9(z,H1,q,K),X=async(q,K,G)=>{let U=await $(K,G);if(U.exitCode!==0)throw Error(`${q}: ${U.stderr.trim()||`exited ${U.exitCode}`}`);return U.stdout};return{workdir:H1,harnessResult:Q,reply:Y,replies:J,exec:(q)=>$(["sh","-c",q]),readFile:(q)=>X(`can't read ${q}`,["cat","--",q]),async writeFile(q,K){await X(`can't write ${q}`,["sh","-c",'mkdir -p -- "$(dirname -- "$1")" && cat > "$1"',"sh",q],K)},async glob(q){let K=await X(`can't list the files in ${H1}`,["find",".","(","-type","f","-o","-type","l",")"]),G=new Bun.Glob(q);return K.split(`
259
- `).filter(Boolean).map((U)=>U.replace(/^\.\//,"")).filter((U)=>G.match(U)).toSorted()},close:()=>w0(z)}}var K2=(Z)=>Z instanceof Error?Z.message:String(Z);function h9(Z,z){if(z===null)return{outcome:"unavailable",reason:"the agent left no result file"};if(!Z)return{outcome:"unavailable",reason:"its harness has no collectReply"};let Q;try{Q=Z(z)}catch(Y){return{outcome:"unavailable",reason:`collectReply threw: ${K2(Y)}`}}if(typeof Q!=="string")return{outcome:"unavailable",reason:`collectReply returned ${typeof Q}, not a string`};return{outcome:"collected",text:Q}}var R1=(Z)=>typeof Z==="number"&&Number.isFinite(Z)&&Z>=0;function U2(Z){let z=Z;if(typeof z!=="object"||z===null)return!1;if(z.outcome==="unavailable")return["absent","unparseable","notReported"].includes(z.reason);if(z.outcome!=="collected"||!Array.isArray(z.models))return!1;if(z.apiDurationMs!==void 0&&!R1(z.apiDurationMs))return!1;return z.models.every((Q)=>{let Y=[Q.inputTokens,Q.outputTokens,Q.cacheCreationTokens,Q.cacheReadTokens];return typeof Q.model==="string"&&Y.every(R1)&&(Q.costUsd===void 0||R1(Q.costUsd))})}function W2(Z,z,Q){if(z===null)return{outcome:"unavailable",reason:"absent"};try{let Y=Z(z,Q);return U2(Y)?Y:{outcome:"unavailable",reason:"unparseable"}}catch{return{outcome:"unavailable",reason:"unparseable"}}}function H2(Z,z){let Q=Z.costUsd!==void 0&&z.costUsd!==void 0?Z.costUsd+z.costUsd:void 0,Y=Z.costBasis===z.costBasis?Z.costBasis:"unknown";return{model:Z.model,inputTokens:Z.inputTokens+z.inputTokens,outputTokens:Z.outputTokens+z.outputTokens,cacheCreationTokens:Z.cacheCreationTokens+z.cacheCreationTokens,cacheReadTokens:Z.cacheReadTokens+z.cacheReadTokens,...Q!==void 0&&{costUsd:Q},...Y!==void 0&&{costBasis:Y}}}function c9(Z,z,Q){let Y=z.map((K)=>W2(Z,K,Q)),J=Y.filter((K)=>K.outcome==="collected");if(J.length===0)return Y[0]??{outcome:"unavailable",reason:"absent"};let $=new Map;for(let K of J.flatMap((G)=>G.models)){let G=$.get(K.model);$.set(K.model,G?H2(G,K):K)}let X=J.map((K)=>K.apiDurationMs),q=X.every((K)=>K!==void 0)?X.reduce((K,G)=>K+G,0):void 0;return{outcome:"collected",models:[...$.values()],...q!==void 0&&{apiDurationMs:q}}}function B2({plan:Z,name:z,testCase:Q},{number:Y,permutation:J,version:$},X,q,K,G){let U=K.at(-1),{harness:H}=c(J.harnessModel);return{executionId:Z.executionId,testCase:z,task:Q.task,permutation:Y,permutationHash:J.hash,iteration:X.number,postrunImage:X.postrunImage,ranAt:new Date(q.startedAt).toISOString(),parameters:Object.fromEntries(w.map((_)=>[_,{name:J[_],parameterHash:J.parameterHashes[_],...J.resolved[_]!==void 0&&{resolved:J.resolved[_]}}])),harnessModel:{harness:H,version:$,modelId:J.modelId},execution:q,harnessResult:U.harnessResult,reply:U.reply,tokenCosts:G,sessionId:X.sessionId,...K.length>1&&{turns:K},result:{}}}async function u9(Z,z,Q={}){let{root:Y,testCase:J,plan:$,imagePrefix:X,imageStore:q=null,build:K={}}=Z,G=await m0(Y,J.task),U=$.permutations.map(({permutation:L})=>L);await Z1(Y,U,X,Q,K),await r0(U,q,X,Q);let H=new Date().toISOString(),_=(L,B)=>({executionId:$.executionId,testCase:Z.name,task:J.task,startedAt:H,finishedAt:B,status:L,matrix:{shape:s0(J),permutations:$.permutations.length,iterations:J.iterations}});await z.recordExecution(_("running"));let I="complete",R;try{for(let L of $.permutations)for(let B of L.iterations){Q.onRunning?.(L,B);let V=B9($.executionId,L.number,B.number,X),{execution:M,harnessResults:j}=await b9({prerunImage:L.prerunImage,postrunImage:B.postrunImage,turns:B.turns,env:L.env,runOptions:L.runOptions,timeoutSeconds:L.timeoutSeconds,container:V}),W=j.map((u)=>({harnessResult:u,reply:h9(L.harness.collectReply,u)})),T=c9(L.collectTokenCosts,j,{version:L.version,modelId:L.modelId}),S=B2(Z,L,B,M,W,T),{harnessResult:N,reply:F}=S;if(await z.recordContainerRun(S),M.exitCode!==0)I="failed";if(Q.onRan?.(L,B,S),q!==null){let u=_9(q.repository,$.executionId,L.permutation.hash,B.number);await S1(B.postrunImage,u,Q)}if(G.length===0)continue;let D=0,b={harnessResult:N??"",reply:F,replies:W.map((u)=>u.reply)},r=await x9(G,async(u)=>u?g9(B.postrunImage,`${V}-measure-${++D}`,b):f9(b));await z.recordContainerRun({...S,result:r}),Q.onMeasured?.(L,B,r)}}catch(L){throw I="failed",L}finally{R=_(I,new Date().toISOString()),await z.recordExecution(R)}return R}function E1(Z=Date.now(),z=crypto.getRandomValues(new Uint8Array(10))){if(!Number.isInteger(Z)||Z<0||Z>=281474976710656)throw RangeError(`ULID time out of range: ${Z}`);if(z.length!==10)throw RangeError(`ULID randomness must be 10 bytes, got ${z.length}`);let Q="";for(let $=Z,X=0;X<10;X++,$=Math.floor($/32))Q="0123456789abcdefghjkmnpqrstvwxyz"[$%32]+Q;let Y=0n;for(let $ of z)Y=Y<<8n|BigInt($);let J="";for(let $=0;$<16;$++,Y>>=5n)J="0123456789abcdefghjkmnpqrstvwxyz"[Number(Y&31n)]+J;return Q+J}var p9=" ",d9=10,j0=(Z,z)=>`${p9}${`${Z}:`.padEnd(d9)}${z.split(`
256
+ `),warning:K&&`Warning: Docker can't be reached, so whether each prerun image is built is unknown: ${K}`}}function w9(){return new y("plan").description("Show what a test case would run, without running it: the parameters it names, each permutation of them with its hash, and whether its prerun image is built, then what each parameter with a resolve resolved to.").argument("<test case>",`the name of a test case, declared in ${O}/test-cases/<test case>.ts`).addOption(P0()).action(g(async(Z,z)=>{let{output:Q,warning:Y}=await oZ(process.cwd(),Z,z.imagePrefix);if(console.log(Q),Y)console.error(Y)}))}var tZ="/thunderjar/result.json",rZ="/thunderjar/prompt.txt";function eZ(Z,z){if(z===1)return{promptPath:rZ,resultPath:tZ};return{promptPath:`/thunderjar/turns/${Z+1}/prompt.txt`,resultPath:`/thunderjar/turns/${Z+1}/result.json`}}var Z8=(Z)=>Z.turns??[Z.prompt],z8=()=>({outcome:"unavailable",reason:"notReported"});async function Q8(Z,z,Q,Y){let{harness:J}=c(Q.harnessModel),[$,X,q]=await Promise.all([E(Z,`${P}/baseImages/${Q.baseImage}/index.ts`,"declareBaseImage",Y),E(Z,`${P}/harnessModels/${J}/index.ts`,"declareHarness",Y),E(Z,`${P}/tasks/${z}/initial-prompts/${Q.initialPrompt}.ts`,"declareInitialPrompt",Y)]);if(!$||!X||!q)return;let K=X.collectTokenCosts??z8;return{baseImage:$,harness:X,collectTokenCosts:K,version:X.version,modelId:Q.modelId,initialPrompt:q}}function Y8({harness:Z,version:z,modelId:Q,initialPrompt:Y},J,$){let X=Z8(Y);return X.map((q,K)=>{let G=eZ(K,X.length),U=Z.cli({version:z,modelId:Q,initialPrompt:q,...G,turn:K,sessionId:J,resolved:$});return{prompt:q,...G,command:U}})}async function y1(Z,z,Q,Y=$0,J={}){let $=await V0(Z,z,J),X=[],q=await Promise.all($.map((K)=>Q8(Z,z.task,K,X)));if(X.length>0)throw f(X);return{executionId:Q,permutations:$.map((K,G)=>{let U=q[G];return{number:G+1,permutation:K,prerunImage:s(K.imageHash,Y),env:T1(U.harness),runOptions:U.baseImage.runOptions??[],timeoutSeconds:U.initialPrompt.timeoutSeconds,harness:U.harness,collectTokenCosts:U.collectTokenCosts,version:U.version,modelId:U.modelId,iterations:Array.from({length:z.iterations},(H,_)=>{let I=crypto.randomUUID();return{number:_+1,postrunImage:H9(Q,G+1,_+1,Y),sessionId:I,turns:Y8(U,I,K.resolved.harnessModel)}})}})}}var U1="/thunderjar/run.json",C9=(Z)=>`'${Z.replaceAll("'","'\\''")}'`,J8=["now_ms() {"," ms=$(date +%s%3N)"," case $ms in",` ${"[0-9]".repeat(13)}) echo "$ms" ;;`," *) echo $(( $(date +%s) * 1000 )) ;;"," esac","}"].join(`
257
+ `);function $8(Z){let z=[...new Set(["/thunderjar",...Z.map(({promptPath:J})=>J.slice(0,J.lastIndexOf("/")))])],Q=Z.length>1,Y=({command:J},$)=>{let X=["turn_start=$(now_ms)",`sh -c ${C9(J)}`,"code=$?",...Q?[`turns="$turns${$===0?"":","}{\\"startedAt\\":$turn_start,\\"finishedAt\\":$(now_ms),\\"exitCode\\":$code}"`]:[]];return $===0?X:["if [ $code -eq 0 ]; then",...X.map((q)=>` ${q}`),"fi"]};return[`mkdir -p ${z.join(" ")}`,...Z.map(({prompt:J,promptPath:$})=>`printf '%s' ${C9(J)} > ${$}`),J8,"start=$(now_ms)",`echo "{\\"startedAt\\":$start}" > ${U1}`,...Q?['turns=""']:[],...Z.flatMap(Y),"end=$(now_ms)",`echo "{\\"startedAt\\":$start,\\"finishedAt\\":$end,\\"exitCode\\":$code${Q?",\\\"turns\\\":[$turns]":""}}" > ${U1}`].join(`
258
+ `)}var W1=(Z)=>Number.isInteger(Z)&&Z>=1000000000000&&Z<10000000000000,X8=(Z)=>{let{startedAt:z,finishedAt:Q,exitCode:Y}=Z??{};return W1(z)&&W1(Q)&&typeof Y==="number"};function q8(Z,z,Q){let Y;try{Y=Z===void 0?void 0:JSON.parse(Z)}catch{Y=void 0}let{startedAt:J,finishedAt:$,exitCode:X,turns:q}=Y??{},K=()=>new i(`The execution wrapper left no valid ${U1}: ${Z===void 0?"there is none":Z.trim()}`);if(!W1(J))throw K();if(Q!==void 0)return{startedAt:J,finishedAt:Q,exitCode:null,timedOut:!0,timeoutSeconds:z};if(!W1($)||typeof X!=="number")throw K();if(q!==void 0&&(!Array.isArray(q)||!q.every(X8)))throw K();return{startedAt:J,finishedAt:$,exitCode:X,timedOut:!1,timeoutSeconds:z,...q&&{turns:q}}}async function b9(Z){try{let z=await q9(Z.prerunImage,Z.container,$8(Z.turns),{env:Z.env,runOptions:Z.runOptions,timeoutSeconds:Z.timeoutSeconds}),Q=z.timedOut?z.killedAt:void 0,Y=q8(await I1(Z.container,U1),Z.timeoutSeconds,Q),J=[];for(let{resultPath:$}of Z.turns)J.push(await I1(Z.container,$)??null);return await G9(Z.container,Z.postrunImage,Z.prerunImage),{execution:Y,harnessResults:J}}finally{await k0(Z.container).catch(()=>{})}}var v9=(Z)=>Z instanceof Error?Z.message:String(Z),G8=(Z)=>Z.outcome==="erroredWhileMeasuring"?{outcome:"erroredWhileMeasuring",error:{message:v9(Z.error)}}:Z;async function x9(Z,z,Q=()=>new Date){let Y={};for(let{name:J,declaration:$,config:X,contentHash:q}of Z){let K=L0[$.instrument],G=await z(K.usesContainer!==!1),U;try{U=G8(await K.evaluate(X,G))}catch(H){U={outcome:"erroredWhileMeasuring",error:{message:v9(H)}}}finally{await G.close()}Y[J]={instrument:$.instrument,contentHash:q,measuredAt:Q().toISOString(),outcome:U}}return Y}var H1="/workspace";function f9({harnessResult:Z,reply:z,replies:Q}){let Y=async()=>{throw Error("this instrument has no measurement container: it reads only what was recorded of the run")};return{workdir:H1,harnessResult:Z,reply:z,replies:Q,exec:Y,readFile:Y,writeFile:Y,glob:Y,close:async()=>{}}}async function g9(Z,z,{harnessResult:Q,reply:Y,replies:J}){try{await K9(Z,z)}catch(q){throw await k0(z).catch(()=>{}),q}let $=(q,K)=>U9(z,H1,q,K),X=async(q,K,G)=>{let U=await $(K,G);if(U.exitCode!==0)throw Error(`${q}: ${U.stderr.trim()||`exited ${U.exitCode}`}`);return U.stdout};return{workdir:H1,harnessResult:Q,reply:Y,replies:J,exec:(q)=>$(["sh","-c",q]),readFile:(q)=>X(`can't read ${q}`,["cat","--",q]),async writeFile(q,K){await X(`can't write ${q}`,["sh","-c",'mkdir -p -- "$(dirname -- "$1")" && cat > "$1"',"sh",q],K)},async glob(q){let K=await X(`can't list the files in ${H1}`,["find",".","(","-type","f","-o","-type","l",")"]),G=new Bun.Glob(q);return K.split(`
259
+ `).filter(Boolean).map((U)=>U.replace(/^\.\//,"")).filter((U)=>G.match(U)).toSorted()},close:()=>k0(z)}}var K8=(Z)=>Z instanceof Error?Z.message:String(Z);function h9(Z,z){if(z===null)return{outcome:"unavailable",reason:"the agent left no result file"};if(!Z)return{outcome:"unavailable",reason:"its harness has no collectReply"};let Q;try{Q=Z(z)}catch(Y){return{outcome:"unavailable",reason:`collectReply threw: ${K8(Y)}`}}if(typeof Q!=="string")return{outcome:"unavailable",reason:`collectReply returned ${typeof Q}, not a string`};return{outcome:"collected",text:Q}}var R1=(Z)=>typeof Z==="number"&&Number.isFinite(Z)&&Z>=0;function U8(Z){let z=Z;if(typeof z!=="object"||z===null)return!1;if(z.outcome==="unavailable")return["absent","unparseable","notReported"].includes(z.reason);if(z.outcome!=="collected"||!Array.isArray(z.models))return!1;if(z.apiDurationMs!==void 0&&!R1(z.apiDurationMs))return!1;return z.models.every((Q)=>{let Y=[Q.inputTokens,Q.outputTokens,Q.cacheCreationTokens,Q.cacheReadTokens];return typeof Q.model==="string"&&Y.every(R1)&&(Q.costUsd===void 0||R1(Q.costUsd))})}function W8(Z,z,Q){if(z===null)return{outcome:"unavailable",reason:"absent"};try{let Y=Z(z,Q);return U8(Y)?Y:{outcome:"unavailable",reason:"unparseable"}}catch{return{outcome:"unavailable",reason:"unparseable"}}}function H8(Z,z){let Q=Z.costUsd!==void 0&&z.costUsd!==void 0?Z.costUsd+z.costUsd:void 0,Y=Z.costBasis===z.costBasis?Z.costBasis:"unknown";return{model:Z.model,inputTokens:Z.inputTokens+z.inputTokens,outputTokens:Z.outputTokens+z.outputTokens,cacheCreationTokens:Z.cacheCreationTokens+z.cacheCreationTokens,cacheReadTokens:Z.cacheReadTokens+z.cacheReadTokens,...Q!==void 0&&{costUsd:Q},...Y!==void 0&&{costBasis:Y}}}function c9(Z,z,Q){let Y=z.map((K)=>W8(Z,K,Q)),J=Y.filter((K)=>K.outcome==="collected");if(J.length===0)return Y[0]??{outcome:"unavailable",reason:"absent"};let $=new Map;for(let K of J.flatMap((G)=>G.models)){let G=$.get(K.model);$.set(K.model,G?H8(G,K):K)}let X=J.map((K)=>K.apiDurationMs),q=X.every((K)=>K!==void 0)?X.reduce((K,G)=>K+G,0):void 0;return{outcome:"collected",models:[...$.values()],...q!==void 0&&{apiDurationMs:q}}}function B8({plan:Z,name:z,testCase:Q},{number:Y,permutation:J,version:$},X,q,K,G){let U=K.at(-1),{harness:H}=c(J.harnessModel);return{executionId:Z.executionId,testCase:z,task:Q.task,permutation:Y,permutationHash:J.hash,iteration:X.number,postrunImage:X.postrunImage,ranAt:new Date(q.startedAt).toISOString(),parameters:Object.fromEntries(k.map((_)=>[_,{name:J[_],parameterHash:J.parameterHashes[_],...J.resolved[_]!==void 0&&{resolved:J.resolved[_]}}])),harnessModel:{harness:H,version:$,modelId:J.modelId},execution:q,harnessResult:U.harnessResult,reply:U.reply,tokenCosts:G,sessionId:X.sessionId,...K.length>1&&{turns:K},result:{}}}async function u9(Z,z,Q={}){let{root:Y,testCase:J,plan:$,imagePrefix:X,imageStore:q=null,build:K={}}=Z,G=await m0(Y,J.task),U=$.permutations.map(({permutation:L})=>L);await Z1(Y,U,X,Q,K),await r0(U,q,X,Q);let H=new Date().toISOString(),_=(L,B)=>({executionId:$.executionId,testCase:Z.name,task:J.task,startedAt:H,finishedAt:B,status:L,matrix:{shape:s0(J),permutations:$.permutations.length,iterations:J.iterations}});await z.recordExecution(_("running"));let I="complete",R;try{for(let L of $.permutations)for(let B of L.iterations){Q.onRunning?.(L,B);let V=B9($.executionId,L.number,B.number,X),{execution:M,harnessResults:j}=await b9({prerunImage:L.prerunImage,postrunImage:B.postrunImage,turns:B.turns,env:L.env,runOptions:L.runOptions,timeoutSeconds:L.timeoutSeconds,container:V}),W=j.map((u)=>({harnessResult:u,reply:h9(L.harness.collectReply,u)})),T=c9(L.collectTokenCosts,j,{version:L.version,modelId:L.modelId}),S=B8(Z,L,B,M,W,T),{harnessResult:N,reply:F}=S;if(await z.recordContainerRun(S),M.exitCode!==0)I="failed";if(Q.onRan?.(L,B,S),q!==null){let u=_9(q.repository,$.executionId,L.permutation.hash,B.number);await S1(B.postrunImage,u,Q)}if(G.length===0)continue;let D=0,b={harnessResult:N??"",reply:F,replies:W.map((u)=>u.reply)},r=await x9(G,async(u)=>u?g9(B.postrunImage,`${V}-measure-${++D}`,b):f9(b));await z.recordContainerRun({...S,result:r}),Q.onMeasured?.(L,B,r)}}catch(L){throw I="failed",L}finally{R=_(I,new Date().toISOString()),await z.recordExecution(R)}return R}function E1(Z=Date.now(),z=crypto.getRandomValues(new Uint8Array(10))){if(!Number.isInteger(Z)||Z<0||Z>=281474976710656)throw RangeError(`ULID time out of range: ${Z}`);if(z.length!==10)throw RangeError(`ULID randomness must be 10 bytes, got ${z.length}`);let Q="";for(let $=Z,X=0;X<10;X++,$=Math.floor($/32))Q="0123456789abcdefghjkmnpqrstvwxyz"[$%32]+Q;let Y=0n;for(let $ of z)Y=Y<<8n|BigInt($);let J="";for(let $=0;$<16;$++,Y>>=5n)J="0123456789abcdefghjkmnpqrstvwxyz"[Number(Y&31n)]+J;return Q+J}var p9=" ",d9=10,j0=(Z,z)=>`${p9}${`${Z}:`.padEnd(d9)}${z.split(`
260
260
  `).join(`
261
- ${p9}${" ".repeat(d9)}`)}`;function V2({executionId:Z,permutations:z}){let Q=z.map((Y)=>[`Permutation ${Y.number}: prerun image ${Y.prerunImage}`,...Y.iterations.flatMap((J)=>[` Iteration ${J.number}: postrun image ${J.postrunImage}`,...Y.env.length>0?[j0("env",Y.env.join(", "))]:[],...Y.runOptions.length>0?[j0("docker",Y.runOptions.join(" "))]:[],...J.turns.length===1?[j0("prompt",J.turns[0].prompt),j0("command",J.turns[0].command)]:[j0("session",J.sessionId),...J.turns.flatMap(({prompt:$,command:X},q)=>[j0(`prompt ${q+1}`,$),j0(`turn ${q+1}`,X)])]])].join(`
261
+ ${p9}${" ".repeat(d9)}`)}`;function V8({executionId:Z,permutations:z}){let Q=z.map((Y)=>[`Permutation ${Y.number}: prerun image ${Y.prerunImage}`,...Y.iterations.flatMap((J)=>[` Iteration ${J.number}: postrun image ${J.postrunImage}`,...Y.env.length>0?[j0("env",Y.env.join(", "))]:[],...Y.runOptions.length>0?[j0("docker",Y.runOptions.join(" "))]:[],...J.turns.length===1?[j0("prompt",J.turns[0].prompt),j0("command",J.turns[0].command)]:[j0("session",J.sessionId),...J.turns.flatMap(({prompt:$,command:X},q)=>[j0(`prompt ${q+1}`,$),j0(`turn ${q+1}`,X)])]])].join(`
262
262
  `));return[`Execution ${Z}`,...Q].join(`
263
263
 
264
- `)}async function _2(Z,z,Q){let Y=await C(Z),J=E1(),$=await Q0(Y,z);return await R0(Y,$),V2(await y1(Y,$,J,Q))}var B1=(Z,z)=>`${String(Z).padStart(String(z).length)}/${z}`,j2=(Z)=>Z<1000?`${Z}ms`:`${(Z/1000).toFixed(1)}s`,l9=(Z)=>typeof Z==="object"&&Z!==null&&!Array.isArray(Z)?`{${Object.entries(Z).map(([z,Q])=>`${z}: ${l9(Q)}`).join(", ")}}`:JSON.stringify(Z)??String(Z),L2=(Z)=>Z.outcome==="measured"?l9(Z.data):Z.outcome==="skipped"?`skipped${Z.reason?` (${Z.reason})`:""}`:`erroredWhileMeasuring (${Z.error.message})`,M2=(Z)=>Object.entries(Z).map(([z,{outcome:Q}])=>`${z}: ${L2(Q)}`).join(" ");function N2(Z,{permutation:z}){let Q=w.filter(($)=>$!=="harnessModel"&&$!=="initialPrompt"&&Z[$].length>1),J=new Set(Z.harnessModel.map(($)=>c($).harness)).size===Z.harnessModel.length?c(z.harnessModel).harness:z.harnessModel;return[...Q.map(($)=>z[$]),J,z.initialPrompt].join(" | ")}async function T2(Z,z,Q,Y){let J=await C(Z),{imageStore:$,build:X}=await N0(J),q=await Q0(J,z);await R0(J,q),M0(X);try{await t0($)}catch(B){if(B instanceof I0)console.error(`Error: ${B.message}`);else if(B instanceof m)console.error(`Error: Docker can't be reached, so nothing can be run: ${B.message}`);else throw B;process.exitCode=1;return}let K=await y1(J,q,E1(),Q),G=H0(Z,J,Y),U=K.permutations.length,H=" ".repeat(B1(U,U).length+3);console.log(`Execution ${K.executionId}`);let _,I,R=!1,L=!1;try{let B=await u9({root:J,name:z,testCase:q,plan:K,imagePrefix:Q,imageStore:$,build:X},K0(G),{onBuilding:(V)=>{_=V,L=!0,process.stdout.write(`Building ${V} ... `)},onBuilt:()=>{_=void 0,L=!1,console.log("done")},onPushing:(V,M)=>{I=M,L=!0,process.stdout.write(`${R?H:""}Pushing ${M} ... `)},onPushed:()=>{I=void 0,L=!1,console.log("done")},onRunning:(V,M)=>{R=!0,L=!0,process.stdout.write(` ${B1(V.number,U)} iteration ${B1(M.number,q.iterations)} ${N2(q,V)} ... `)},onRan:(V,M,{execution:j,harnessResult:W,tokenCosts:T})=>{L=!1;let S=z1(j,W),N=Y1(T),F=Q1(T),D=N!==void 0?`, ${C0(N)}`:F!==void 0?`, ${q0(F)} tokens`:"";console.log(j.timedOut?S:`${S} (${j2(j.finishedAt-j.startedAt)}${D})`)},onMeasured:(V,M,j)=>{console.log(`${" ".repeat(B1(V.number,U).length+3)}${M2(j)}`)}});if(console.log(`Wrote ${D0(Z,v0(G,K.executionId))}/`),B.status==="failed")process.exitCode=1}catch(B){if(B instanceof m)console.error(`Error: Docker can't be reached, so nothing can be run: ${B.message}`);else if(B instanceof T0)console.log("failed"),console.error(`Error: Building ${_} failed: ${B.message}`);else if(B instanceof F0)console.log("failed"),console.error(`Error: ${J1(I,B)}`);else if(B instanceof i&&L)console.log("failed"),console.error(`Error: Running a container failed: ${B.message}`);else if(B instanceof i)console.error(`Error: Measuring a container run failed: ${B.message}`);else throw B;process.exitCode=1}}function m9(){return new y("run").description("Run a test case: one execution, with a new ID. Builds any missing prerun image, then runs each iteration of each permutation in a container from its prerun image, commits it into its postrun image, takes the task's measurements of it, each in a container from its postrun image, and records it in the run data store. With an image store in thunderjar.config.ts, checks your docker login for its registry first, and pushes each prerun and postrun image there.").argument("<test case>",`the name of a test case, declared in ${O}/test-cases/<test case>.ts`).option("--dry-run","print the images, environment variables, prompts and harness commands the execution would use, without running anything").addOption(P0()).addOption(U0()).action(g(async(Z,z)=>{if(z.dryRun)console.log(await _2(process.cwd(),Z,z.imagePrefix));else await T2(process.cwd(),Z,z.imagePrefix,z.dataDir)}))}var w1=(Z)=>Z.reduce((z,Q)=>z+Q,0),s9=(Z)=>w1(Z)/Z.length,F2=(Z)=>{let z=Z.toSorted((Y,J)=>Y-J),Q=z.length>>1;return z.length%2===1?z[Q]:(z[Q-1]+z[Q])/2},i9=(Z,z)=>{let Q=[...new Set(Z.flatMap((Y)=>Object.keys(Y)))];return Object.fromEntries(Q.map((Y)=>[Y,z(Z.map((J)=>J[Y]??0))]))},I2={rate:(Z)=>Z.filter(Boolean).length/Z.length,count:(Z)=>Z.filter(Boolean).length},S2={mean:s9,median:F2,min:(Z)=>Math.min(...Z),max:(Z)=>Math.max(...Z),sum:w1},P2={sum:(Z)=>i9(Z,w1),mean:(Z)=>i9(Z,s9)},D2=(Z)=>typeof Z==="object"&&Z!==null&&!Array.isArray(Z)&&Object.values(Z).every((z)=>typeof z==="number");function A2(Z){if(Z.every((z)=>typeof z==="boolean"))return["booleans",I2];if(Z.every((z)=>typeof z==="number"))return["numbers",S2];if(Z.every(D2))return["records of numbers",P2];return}function O2(Z,z){if(Z.length===0)return{values:{}};let Q=A2([...Z]);if(!Q)return{incompatible:"recorded values aren't all booleans, numbers or records of numbers"};let[Y,J]=Q,$=z.filter((X)=>!J[X]);if($.length>0){let X=$.map((q)=>`"${q}"`).join(", ");return{incompatible:`recorded values are ${Y}; ${X} ${$.length===1?"doesn't":"don't"} combine them`}}return{values:Object.fromEntries(z.map((X)=>[X,J[X]([...Z])]))}}function n9(Z,z){return Object.fromEntries(z.map(({name:Q,declaration:Y})=>{let J=Z.flatMap(({result:q})=>{let K=q[Q]?.outcome;return K?.outcome==="measured"?[K.data]:[]}),$=O2(J,Y.aggregate),X="incompatible"in $?{measured:J.length,values:{},incompatible:$.incompatible}:{measured:J.length,values:$.values};return[Q,X]}))}var k1=" ",b1=(Z)=>{let z=Math.max(...Z.map(([Q])=>Q.length));return Z.map(([Q,Y])=>`${Q.padEnd(z)} ${Y}`)};function O0(Z){let z=Z[0].map((Q,Y)=>Math.max(...Z.map((J)=>J[Y]?.length??0)));return Z.map((Q)=>` ${Q.map((Y,J)=>Y.padEnd(z[J])).join(" ")}`.trimEnd())}var a9=(Z,z)=>z===void 0?String(Z):Z.toFixed(z);function t9(Z,z){if(typeof Z==="number")return a9(Z,z);if(typeof Z==="object"&&Z!==null&&!Array.isArray(Z))return`{${Object.entries(Z).map(([Y,J])=>`${Y}: ${typeof J==="number"?a9(J,z):JSON.stringify(J)}`).join(", ")}}`;return JSON.stringify(Z)??String(Z)}function y2(Z,z,Q){if(Z==="rate"&&typeof z==="number")return`${Math.round(z*Q)}/${Q}`;return t9(z,Z==="mean"||Z==="median"?1:void 0)}function r9(Z){if(Z===void 0)return"not measured";if(Z.outcome==="skipped")return`skipped${Z.reason===void 0?"":` (${Z.reason})`}`;if(Z.outcome==="erroredWhileMeasuring")return`errored while measuring (${Z.error.message})`;return t9(Z.data)}function R2(Z){let z=Math.round(Z/1000);return`${Math.floor(z/60)}:${String(z%60).padStart(2,"0")}`}var x0=({permutation:Z,iteration:z})=>`${Z}-${z}`,E2=(Z)=>Z===void 0?"not recorded":Z.outcome==="unavailable"?`not reported (${Z.reason})`:"";function w2(Z){let z=($)=>$.reduce((X,q)=>X+q,0)/$.length,Q=Z.flatMap(({tokenCosts:$})=>Q1($)??[]),Y=Z.flatMap(({tokenCosts:$})=>Y1($)??[]),J=($)=>$<Z.length?"*":"";return[Q.length===0?"not reported":`${q0(z(Q))}${J(Q.length)}`,Y.length===0?"\u2014":`${C0(z(Y))}${J(Y.length)}`]}function k2(Z){if(Z.outcome==="unavailable")return[` none (${Z.reason})`];let z=({costUsd:Q,costBasis:Y})=>Q===void 0?"not reported":Y==="unknown"?"not reported (its price table doesn't know the model)":C0(Q);return O0([["model","input","output","cache write","cache read","cost"],...Z.models.map((Q)=>[Q.model,q0(Q.inputTokens),q0(Q.outputTokens),q0(Q.cacheCreationTokens),q0(Q.cacheReadTokens),z(Q)])])}function C2(Z){let z=w.filter((Q)=>new Set(Z.map(({parameters:Y})=>Y[Q].name)).size>1);return z.length>0?z:[...w]}function b2(Z,z,Q){let Y=C2(z),J=Q.flatMap(({name:V,declaration:M})=>M.aggregate.map((j,W)=>({name:V,method:j,first:W===0}))),$=String(Z.matrix.permutations).length,X=z.some(({tokenCosts:V})=>V!==void 0),q=[],K=[],G=new Map;for(let V=1;V<=Z.matrix.permutations;V++){let M=String(V).padStart($),j=z.filter((N)=>N.permutation===V),[W]=j;if(!W){q.push([M,"no container runs"]);continue}let T=n9(j,Q);for(let[N,F]of Object.entries(T))if(F.incompatible!==void 0)G.set(N,(G.get(N)??new Set).add(F.incompatible));for(let{name:N}of Q)for(let F of j){let D=F.result[N]?.outcome;if(D?.outcome!=="measured")K.push([x0(F),N,r9(D)])}let S=X?w2(j):[];if(X){for(let N of j)if(N.tokenCosts?.outcome!=="collected")K.push([x0(N),"tokens",E2(N.tokenCosts)])}q.push([M,Y.map((N)=>W.parameters[N].name).join(" | "),`${j.length}/${Z.matrix.iterations}`,...J.map(({name:N,method:F})=>{let{measured:D,values:b,incompatible:n}=T[N];if(n!==void 0)return"?";let r=b[F];if(r===void 0)return"\u2014";return`${y2(F,r,D)}${D<j.length?"*":""}`}),...S])}let U=["",Y.join(" | "),"runs",...J.map(({method:V})=>V),...X?["tokens (mean)","cost (mean)"]:[]],H=U.map((V,M)=>Math.max(V.length,...q.map((j)=>j[M]?.length??0)));for(let{name:V,declaration:M}of Q){let j=3+J.findIndex((S)=>S.name===V),W=j+M.aggregate.length-1,T=H.slice(j,W+1).reduce((S,N)=>S+N,0)+k1.length*(W-j);if(T<V.length)H[W]+=V.length-T}let _=(V)=>` ${V.map((M,j)=>M.padEnd(H[j])).join(k1)}`.trimEnd(),I=(V)=>1+H.slice(0,V).reduce((M,j)=>M+j+k1.length,0),R=J.reduce((V,{name:M,first:j},W)=>j?`${V.padEnd(I(3+W))}${M}`:V,""),L=[...Q.length>0?[R]:[],_(U),...q.map(_)],B=z.filter(({execution:V,harnessResult:M})=>!T9(V,M));if(B.length>0)L.push("","! Agents that didn't end cleanly:",...O0(B.map((V)=>[x0(V),z1(V.execution,V.harnessResult)])));if(K.length>0)L.push("","* Left out of the aggregate:",...O0(K));if(G.size>0){let V=[...G].flatMap(([M,j])=>[...j].map((W)=>[`${M}:`,`${W} (remeasure)`]));L.push("","? Can't aggregate as declared today:",...O0(V))}return L}function v2(Z,z,Q){let{executionId:Y,testCase:J,task:$,startedAt:X,status:q,matrix:K}=Z,G=b1([["Execution",Y],["Test case",J],["Task",$],["Started",b0(X)],["Status",q],["Matrix",`${_0(K.permutations,"permutation")} \xD7 ${_0(K.iterations,"iteration")}`]]),U=z.length===0?["No container runs recorded."]:b2(Z,z,Q);return[...G,"",...U].join(`
264
+ `)}async function _8(Z,z,Q){let Y=await C(Z),J=E1(),$=await Q0(Y,z);return await R0(Y,$),V8(await y1(Y,$,J,Q))}var B1=(Z,z)=>`${String(Z).padStart(String(z).length)}/${z}`,j8=(Z)=>Z<1000?`${Z}ms`:`${(Z/1000).toFixed(1)}s`,l9=(Z)=>typeof Z==="object"&&Z!==null&&!Array.isArray(Z)?`{${Object.entries(Z).map(([z,Q])=>`${z}: ${l9(Q)}`).join(", ")}}`:JSON.stringify(Z)??String(Z),L8=(Z)=>Z.outcome==="measured"?l9(Z.data):Z.outcome==="skipped"?`skipped${Z.reason?` (${Z.reason})`:""}`:`erroredWhileMeasuring (${Z.error.message})`,M8=(Z)=>Object.entries(Z).map(([z,{outcome:Q}])=>`${z}: ${L8(Q)}`).join(" ");function N8(Z,{permutation:z}){let Q=k.filter(($)=>$!=="harnessModel"&&$!=="initialPrompt"&&Z[$].length>1),J=new Set(Z.harnessModel.map(($)=>c($).harness)).size===Z.harnessModel.length?c(z.harnessModel).harness:z.harnessModel;return[...Q.map(($)=>z[$]),J,z.initialPrompt].join(" | ")}async function T8(Z,z,Q,Y){let J=await C(Z),{imageStore:$,build:X}=await N0(J),q=await Q0(J,z);await R0(J,q),M0(X);try{await t0($)}catch(B){if(B instanceof I0)console.error(`Error: ${B.message}`);else if(B instanceof m)console.error(`Error: Docker can't be reached, so nothing can be run: ${B.message}`);else throw B;process.exitCode=1;return}let K=await y1(J,q,E1(),Q),G=H0(Z,J,Y),U=K.permutations.length,H=" ".repeat(B1(U,U).length+3);console.log(`Execution ${K.executionId}`);let _,I,R=!1,L=!1;try{let B=await u9({root:J,name:z,testCase:q,plan:K,imagePrefix:Q,imageStore:$,build:X},K0(G),{onBuilding:(V)=>{_=V,L=!0,process.stdout.write(`Building ${V} ... `)},onBuilt:()=>{_=void 0,L=!1,console.log("done")},onPushing:(V,M)=>{I=M,L=!0,process.stdout.write(`${R?H:""}Pushing ${M} ... `)},onPushed:()=>{I=void 0,L=!1,console.log("done")},onRunning:(V,M)=>{R=!0,L=!0,process.stdout.write(` ${B1(V.number,U)} iteration ${B1(M.number,q.iterations)} ${N8(q,V)} ... `)},onRan:(V,M,{execution:j,harnessResult:W,tokenCosts:T})=>{L=!1;let S=z1(j,W),N=Y1(T),F=Q1(T),D=N!==void 0?`, ${C0(N)}`:F!==void 0?`, ${q0(F)} tokens`:"";console.log(j.timedOut?S:`${S} (${j8(j.finishedAt-j.startedAt)}${D})`)},onMeasured:(V,M,j)=>{console.log(`${" ".repeat(B1(V.number,U).length+3)}${M8(j)}`)}});if(console.log(`Wrote ${D0(Z,v0(G,K.executionId))}/`),B.status==="failed")process.exitCode=1}catch(B){if(B instanceof m)console.error(`Error: Docker can't be reached, so nothing can be run: ${B.message}`);else if(B instanceof T0)console.log("failed"),console.error(`Error: Building ${_} failed: ${B.message}`);else if(B instanceof F0)console.log("failed"),console.error(`Error: ${J1(I,B)}`);else if(B instanceof i&&L)console.log("failed"),console.error(`Error: Running a container failed: ${B.message}`);else if(B instanceof i)console.error(`Error: Measuring a container run failed: ${B.message}`);else throw B;process.exitCode=1}}function m9(){return new y("run").description("Run a test case: one execution, with a new ID. Builds any missing prerun image, then runs each iteration of each permutation in a container from its prerun image, commits it into its postrun image, takes the task's measurements of it, each in a container from its postrun image, and records it in the run data store. With an image store in thunderjar.config.ts, checks your docker login for its registry first, and pushes each prerun and postrun image there.").argument("<test case>",`the name of a test case, declared in ${O}/test-cases/<test case>.ts`).option("--dry-run","print the images, environment variables, prompts and harness commands the execution would use, without running anything").addOption(P0()).addOption(U0()).action(g(async(Z,z)=>{if(z.dryRun)console.log(await _8(process.cwd(),Z,z.imagePrefix));else await T8(process.cwd(),Z,z.imagePrefix,z.dataDir)}))}var k1=(Z)=>Z.reduce((z,Q)=>z+Q,0),s9=(Z)=>k1(Z)/Z.length,F8=(Z)=>{let z=Z.toSorted((Y,J)=>Y-J),Q=z.length>>1;return z.length%2===1?z[Q]:(z[Q-1]+z[Q])/2},i9=(Z,z)=>{let Q=[...new Set(Z.flatMap((Y)=>Object.keys(Y)))];return Object.fromEntries(Q.map((Y)=>[Y,z(Z.map((J)=>J[Y]??0))]))},I8={rate:(Z)=>Z.filter(Boolean).length/Z.length,count:(Z)=>Z.filter(Boolean).length},S8={mean:s9,median:F8,min:(Z)=>Math.min(...Z),max:(Z)=>Math.max(...Z),sum:k1},P8={sum:(Z)=>i9(Z,k1),mean:(Z)=>i9(Z,s9)},D8=(Z)=>typeof Z==="object"&&Z!==null&&!Array.isArray(Z)&&Object.values(Z).every((z)=>typeof z==="number");function A8(Z){if(Z.every((z)=>typeof z==="boolean"))return["booleans",I8];if(Z.every((z)=>typeof z==="number"))return["numbers",S8];if(Z.every(D8))return["records of numbers",P8];return}function O8(Z,z){if(Z.length===0)return{values:{}};let Q=A8([...Z]);if(!Q)return{incompatible:"recorded values aren't all booleans, numbers or records of numbers"};let[Y,J]=Q,$=z.filter((X)=>!J[X]);if($.length>0){let X=$.map((q)=>`"${q}"`).join(", ");return{incompatible:`recorded values are ${Y}; ${X} ${$.length===1?"doesn't":"don't"} combine them`}}return{values:Object.fromEntries(z.map((X)=>[X,J[X]([...Z])]))}}function n9(Z,z){return Object.fromEntries(z.map(({name:Q,declaration:Y})=>{let J=Z.flatMap(({result:q})=>{let K=q[Q]?.outcome;return K?.outcome==="measured"?[K.data]:[]}),$=O8(J,Y.aggregate),X="incompatible"in $?{measured:J.length,values:{},incompatible:$.incompatible}:{measured:J.length,values:$.values};return[Q,X]}))}var w1=" ",b1=(Z)=>{let z=Math.max(...Z.map(([Q])=>Q.length));return Z.map(([Q,Y])=>`${Q.padEnd(z)} ${Y}`)};function O0(Z){let z=Z[0].map((Q,Y)=>Math.max(...Z.map((J)=>J[Y]?.length??0)));return Z.map((Q)=>` ${Q.map((Y,J)=>Y.padEnd(z[J])).join(" ")}`.trimEnd())}var a9=(Z,z)=>z===void 0?String(Z):Z.toFixed(z);function t9(Z,z){if(typeof Z==="number")return a9(Z,z);if(typeof Z==="object"&&Z!==null&&!Array.isArray(Z))return`{${Object.entries(Z).map(([Y,J])=>`${Y}: ${typeof J==="number"?a9(J,z):JSON.stringify(J)}`).join(", ")}}`;return JSON.stringify(Z)??String(Z)}function y8(Z,z,Q){if(Z==="rate"&&typeof z==="number")return`${Math.round(z*Q)}/${Q}`;return t9(z,Z==="mean"||Z==="median"?1:void 0)}function r9(Z){if(Z===void 0)return"not measured";if(Z.outcome==="skipped")return`skipped${Z.reason===void 0?"":` (${Z.reason})`}`;if(Z.outcome==="erroredWhileMeasuring")return`errored while measuring (${Z.error.message})`;return t9(Z.data)}function R8(Z){let z=Math.round(Z/1000);return`${Math.floor(z/60)}:${String(z%60).padStart(2,"0")}`}var x0=({permutation:Z,iteration:z})=>`${Z}-${z}`,E8=(Z)=>Z===void 0?"not recorded":Z.outcome==="unavailable"?`not reported (${Z.reason})`:"";function k8(Z){let z=($)=>$.reduce((X,q)=>X+q,0)/$.length,Q=Z.flatMap(({tokenCosts:$})=>Q1($)??[]),Y=Z.flatMap(({tokenCosts:$})=>Y1($)??[]),J=($)=>$<Z.length?"*":"";return[Q.length===0?"not reported":`${q0(z(Q))}${J(Q.length)}`,Y.length===0?"\u2014":`${C0(z(Y))}${J(Y.length)}`]}function w8(Z){if(Z.outcome==="unavailable")return[` none (${Z.reason})`];let z=({costUsd:Q,costBasis:Y})=>Q===void 0?"not reported":Y==="unknown"?"not reported (its price table doesn't know the model)":C0(Q);return O0([["model","input","output","cache write","cache read","cost"],...Z.models.map((Q)=>[Q.model,q0(Q.inputTokens),q0(Q.outputTokens),q0(Q.cacheCreationTokens),q0(Q.cacheReadTokens),z(Q)])])}function C8(Z){let z=k.filter((Q)=>new Set(Z.map(({parameters:Y})=>Y[Q].name)).size>1);return z.length>0?z:[...k]}function b8(Z,z,Q){let Y=C8(z),J=Q.flatMap(({name:V,declaration:M})=>M.aggregate.map((j,W)=>({name:V,method:j,first:W===0}))),$=String(Z.matrix.permutations).length,X=z.some(({tokenCosts:V})=>V!==void 0),q=[],K=[],G=new Map;for(let V=1;V<=Z.matrix.permutations;V++){let M=String(V).padStart($),j=z.filter((N)=>N.permutation===V),[W]=j;if(!W){q.push([M,"no container runs"]);continue}let T=n9(j,Q);for(let[N,F]of Object.entries(T))if(F.incompatible!==void 0)G.set(N,(G.get(N)??new Set).add(F.incompatible));for(let{name:N}of Q)for(let F of j){let D=F.result[N]?.outcome;if(D?.outcome!=="measured")K.push([x0(F),N,r9(D)])}let S=X?k8(j):[];if(X){for(let N of j)if(N.tokenCosts?.outcome!=="collected")K.push([x0(N),"tokens",E8(N.tokenCosts)])}q.push([M,Y.map((N)=>W.parameters[N].name).join(" | "),`${j.length}/${Z.matrix.iterations}`,...J.map(({name:N,method:F})=>{let{measured:D,values:b,incompatible:n}=T[N];if(n!==void 0)return"?";let r=b[F];if(r===void 0)return"\u2014";return`${y8(F,r,D)}${D<j.length?"*":""}`}),...S])}let U=["",Y.join(" | "),"runs",...J.map(({method:V})=>V),...X?["tokens (mean)","cost (mean)"]:[]],H=U.map((V,M)=>Math.max(V.length,...q.map((j)=>j[M]?.length??0)));for(let{name:V,declaration:M}of Q){let j=3+J.findIndex((S)=>S.name===V),W=j+M.aggregate.length-1,T=H.slice(j,W+1).reduce((S,N)=>S+N,0)+w1.length*(W-j);if(T<V.length)H[W]+=V.length-T}let _=(V)=>` ${V.map((M,j)=>M.padEnd(H[j])).join(w1)}`.trimEnd(),I=(V)=>1+H.slice(0,V).reduce((M,j)=>M+j+w1.length,0),R=J.reduce((V,{name:M,first:j},W)=>j?`${V.padEnd(I(3+W))}${M}`:V,""),L=[...Q.length>0?[R]:[],_(U),...q.map(_)],B=z.filter(({execution:V,harnessResult:M})=>!T9(V,M));if(B.length>0)L.push("","! Agents that didn't end cleanly:",...O0(B.map((V)=>[x0(V),z1(V.execution,V.harnessResult)])));if(K.length>0)L.push("","* Left out of the aggregate:",...O0(K));if(G.size>0){let V=[...G].flatMap(([M,j])=>[...j].map((W)=>[`${M}:`,`${W} (remeasure)`]));L.push("","? Can't aggregate as declared today:",...O0(V))}return L}function v8(Z,z,Q){let{executionId:Y,testCase:J,task:$,startedAt:X,status:q,matrix:K}=Z,G=b1([["Execution",Y],["Test case",J],["Task",$],["Started",b0(X)],["Status",q],["Matrix",`${_0(K.permutations,"permutation")} \xD7 ${_0(K.iterations,"iteration")}`]]),U=z.length===0?["No container runs recorded."]:b8(Z,z,Q);return[...G,"",...U].join(`
265
265
  `)}var o9=(Z,z="")=>{return(Z.outcome==="collected"?Z.text.split(`
266
- `):[`none (${Z.reason})`]).map((Y,J)=>` ${J===0?z:" ".repeat(z.length)}${Y}`.trimEnd())},x2=({reply:Z,turns:z})=>z?z.flatMap((Q,Y)=>o9(Q.reply,`Turn ${Y+1}: `)):o9(Z);function f2(Z){let{executionId:z,testCase:Q,permutation:Y,permutationHash:J,iteration:$,postrunImage:X,ranAt:q,parameters:K,harnessModel:G,execution:U,harnessResult:H,reply:_,result:I}=Z,R=U.turns===void 0?[]:[["Turns",`${U.turns.length} of ${Z.turns?.length??"?"} ran`]],L=Object.keys(I).toSorted();return[...b1([["Container run",x0(Z)],["Execution",`${z} (${Q})`],["Permutation",`${Y} (${o(J)}), iteration ${$}`],["Postrun image",X],["Ran at",b0(q)]]),"","Parameters",...O0(w.map((B)=>{let{name:V,parameterHash:M,resolved:j}=K[B];return[B,V,o(M),...j===void 0?[]:[`resolved ${$1(j)}`]]})),"",...b1([["Harness",`${G.harness} ${G.version}`],["Model",G.model===void 0?G.modelId:`${G.model} (${G.modelId})`],["Duration",R2(U.finishedAt-U.startedAt)],["Exit",U.timedOut?`timed out after ${U.timeoutSeconds}s`:String(U.exitCode)],...R,["Result file",H===null?"none":_0(new TextEncoder().encode(H).length,"byte")]]),"",..._===void 0?[]:["Reply",...x2(Z),""],...Z.tokenCosts===void 0?[]:["Token costs",...k2(Z.tokenCosts),""],"Measures",...L.length===0?[" none"]:O0(L.map((B)=>[B,r9(I[B].outcome)]))].join(`
267
- `)}function C1(Z){console.error(`Error: ${Z}`),process.exitCode=1}async function g2(Z,z,Q,Y){let J=Q===void 0||Y===void 0?await C(Z):void 0,$=K0(Y===void 0?H0(Z,J):W0(Z,Y)),X,q;try{if(X=(await $.listExecutions()).find((G)=>G.executionId===z),!X)return C1(`No execution ${z} recorded. List them with \`thunderjar executions\`.`);q=await $.containerRunsOf(z)}catch(G){if(!(G instanceof G0))throw G;return C1(`Can't read ${D0(Z,G.path)}: ${G.message}`)}if(Q===void 0){console.log(v2(X,q,await m0(J,X.task)));return}let K=q.find((G)=>x0(G)===Q||G.postrunImage===Q);if(!K)return C1(`Execution ${z} has no container run ${Q}.`);console.log(f2(K))}function e9(){return new y("show").description("Show an execution's recorded results: a row per permutation, with each measure aggregated across its iterations by its measurement's methods. Given a container run, show that one iteration instead: its parameters, how the agent ran, and each measure.").argument("<execution>","the execution's ID, as listed by `thunderjar executions`").argument("[container run]","one of its container runs, as `<permutation>-<iteration>`, e.g. `1-1`, or its postrun image").addOption(U0()).action(g(async(Z,z,Q)=>{await g2(process.cwd(),Z,z,Q.dataDir)}))}var Z4=g1("{\"index\":\"./index.html\",\"files\":[{\"input\":\"commands/view/app/index.html\",\"path\":\"./index-dpkwdp4n.js\",\"loader\":\"js\",\"isEntry\":true,\"headers\":{\"etag\":\"zZZTnI3WxJU\",\"content-type\":\"text/javascript;charset=utf-8\"}},{\"input\":\"commands/view/app/index.html\",\"path\":\"./index.html\",\"loader\":\"html\",\"isEntry\":true,\"headers\":{\"etag\":\"pxuvJYDPTl4\",\"content-type\":\"text/html;charset=utf-8\"}},{\"input\":\"commands/view/app/index.html\",\"path\":\"./index-hjdm1eyn.css\",\"loader\":\"css\",\"isEntry\":true,\"headers\":{\"etag\":\"cTIttEGu3tU\",\"content-type\":\"text/css;charset=utf-8\"}}]}");var c2=4300;async function z4(Z){try{let z=await Z();return z instanceof Response?z:Response.json(z)}catch(z){if(!(z instanceof G0))throw z;return Response.json({error:`Can't read ${z.path}: ${z.message}`},{status:500})}}function u2(Z,z){return Bun.serve({port:z,development:!1,routes:{"/":Z4,"/api/executions":()=>z4(()=>Z.listExecutions()),"/api/executions/:id":(Q)=>z4(async()=>{let{id:Y}=Q.params,J=(await Z.listExecutions()).find(($)=>$.executionId===Y);if(J===void 0)return Response.json({error:`No execution ${Y} recorded.`},{status:404});return{execution:J,containerRuns:await Z.containerRunsOf(Y)}}),"/api/*":()=>Response.json({error:"Not found."},{status:404})},fetch:()=>new Response("Not found.",{status:404})})}async function p2(Z,z,Q){let Y=Q===void 0?H0(Z,await C(Z)):W0(Z,Q);process.chdir(import.meta.dir);let J=u2(K0(Y),z);console.log(`Viewing ${Y}`),console.log(`Open ${J.url}`)}function Q4(){return new y("view").description("Start a local web page for browsing the executions and container runs in the run data store. Runs until stopped.").addOption(U0()).addOption(new p("--port <port>","the port to serve on, 0 for any free one").default(c2).argParser((Z)=>{let z=Number(Z);if(!Number.isInteger(z)||z<0||z>65535)throw Error(`Invalid port: ${Z}`);return z})).action(g(async(Z)=>{await p2(process.cwd(),Z.port,Z.dataDir)}))}function Y4(){return new y().name("thunderjar").description(M1.description).version(M1.version).addCommand(E9()).addCommand(A9()).addCommand(k9()).addCommand(F9()).addCommand(m9()).addCommand(P9()).addCommand(e9()).addCommand(Q4())}await Y4().parseAsync();
266
+ `):[`none (${Z.reason})`]).map((Y,J)=>` ${J===0?z:" ".repeat(z.length)}${Y}`.trimEnd())},x8=({reply:Z,turns:z})=>z?z.flatMap((Q,Y)=>o9(Q.reply,`Turn ${Y+1}: `)):o9(Z);function f8(Z){let{executionId:z,testCase:Q,permutation:Y,permutationHash:J,iteration:$,postrunImage:X,ranAt:q,parameters:K,harnessModel:G,execution:U,harnessResult:H,reply:_,result:I}=Z,R=U.turns===void 0?[]:[["Turns",`${U.turns.length} of ${Z.turns?.length??"?"} ran`]],L=Object.keys(I).toSorted();return[...b1([["Container run",x0(Z)],["Execution",`${z} (${Q})`],["Permutation",`${Y} (${o(J)}), iteration ${$}`],["Postrun image",X],["Ran at",b0(q)]]),"","Parameters",...O0(k.map((B)=>{let{name:V,parameterHash:M,resolved:j}=K[B];return[B,V,o(M),...j===void 0?[]:[`resolved ${$1(j)}`]]})),"",...b1([["Harness",`${G.harness} ${G.version}`],["Model",G.model===void 0?G.modelId:`${G.model} (${G.modelId})`],["Duration",R8(U.finishedAt-U.startedAt)],["Exit",U.timedOut?`timed out after ${U.timeoutSeconds}s`:String(U.exitCode)],...R,["Result file",H===null?"none":_0(new TextEncoder().encode(H).length,"byte")]]),"",..._===void 0?[]:["Reply",...x8(Z),""],...Z.tokenCosts===void 0?[]:["Token costs",...w8(Z.tokenCosts),""],"Measures",...L.length===0?[" none"]:O0(L.map((B)=>[B,r9(I[B].outcome)]))].join(`
267
+ `)}function C1(Z){console.error(`Error: ${Z}`),process.exitCode=1}async function g8(Z,z,Q,Y){let J=Q===void 0||Y===void 0?await C(Z):void 0,$=K0(Y===void 0?H0(Z,J):W0(Z,Y)),X,q;try{if(X=(await $.listExecutions()).find((G)=>G.executionId===z),!X)return C1(`No execution ${z} recorded. List them with \`thunderjar executions\`.`);q=await $.containerRunsOf(z)}catch(G){if(!(G instanceof G0))throw G;return C1(`Can't read ${D0(Z,G.path)}: ${G.message}`)}if(Q===void 0){console.log(v8(X,q,await m0(J,X.task)));return}let K=q.find((G)=>x0(G)===Q||G.postrunImage===Q);if(!K)return C1(`Execution ${z} has no container run ${Q}.`);console.log(f8(K))}function e9(){return new y("show").description("Show an execution's recorded results: a row per permutation, with each measure aggregated across its iterations by its measurement's methods. Given a container run, show that one iteration instead: its parameters, how the agent ran, and each measure.").argument("<execution>","the execution's ID, as listed by `thunderjar executions`").argument("[container run]","one of its container runs, as `<permutation>-<iteration>`, e.g. `1-1`, or its postrun image").addOption(U0()).action(g(async(Z,z,Q)=>{await g8(process.cwd(),Z,z,Q.dataDir)}))}var Z4=g1("{\"index\":\"./index.html\",\"files\":[{\"input\":\"commands/view/app/index.html\",\"path\":\"./index-dpkwdp4n.js\",\"loader\":\"js\",\"isEntry\":true,\"headers\":{\"etag\":\"zZZTnI3WxJU\",\"content-type\":\"text/javascript;charset=utf-8\"}},{\"input\":\"commands/view/app/index.html\",\"path\":\"./index.html\",\"loader\":\"html\",\"isEntry\":true,\"headers\":{\"etag\":\"pxuvJYDPTl4\",\"content-type\":\"text/html;charset=utf-8\"}},{\"input\":\"commands/view/app/index.html\",\"path\":\"./index-hjdm1eyn.css\",\"loader\":\"css\",\"isEntry\":true,\"headers\":{\"etag\":\"cTIttEGu3tU\",\"content-type\":\"text/css;charset=utf-8\"}}]}");var c8=4300;async function z4(Z){try{let z=await Z();return z instanceof Response?z:Response.json(z)}catch(z){if(!(z instanceof G0))throw z;return Response.json({error:`Can't read ${z.path}: ${z.message}`},{status:500})}}function u8(Z,z){return Bun.serve({port:z,development:!1,routes:{"/":Z4,"/api/executions":()=>z4(()=>Z.listExecutions()),"/api/executions/:id":(Q)=>z4(async()=>{let{id:Y}=Q.params,J=(await Z.listExecutions()).find(($)=>$.executionId===Y);if(J===void 0)return Response.json({error:`No execution ${Y} recorded.`},{status:404});return{execution:J,containerRuns:await Z.containerRunsOf(Y)}}),"/api/*":()=>Response.json({error:"Not found."},{status:404})},fetch:()=>new Response("Not found.",{status:404})})}async function p8(Z,z,Q){let Y=Q===void 0?H0(Z,await C(Z)):W0(Z,Q);process.chdir(import.meta.dir);let J=u8(K0(Y),z);console.log(`Viewing ${Y}`),console.log(`Open ${J.url}`)}function Q4(){return new y("view").description("Start a local web page for browsing the executions and container runs in the run data store. Runs until stopped.").addOption(U0()).addOption(new p("--port <port>","the port to serve on, 0 for any free one").default(c8).argParser((Z)=>{let z=Number(Z);if(!Number.isInteger(z)||z<0||z>65535)throw Error(`Invalid port: ${Z}`);return z})).action(g(async(Z)=>{await p8(process.cwd(),Z.port,Z.dataDir)}))}function Y4(){return new y().name("thunderjar").description(M1.description).version(M1.version).addCommand(E9()).addCommand(A9()).addCommand(w9()).addCommand(F9()).addCommand(m9()).addCommand(P9()).addCommand(e9()).addCommand(Q4())}await Y4().parseAsync();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thunderjar",
3
- "version": "0.2.0-preview-cb023da",
3
+ "version": "0.2.0-rc.0",
4
4
  "type": "module",
5
5
  "description": "Thunderjar",
6
6
  "license": "MIT",