@evolvingmachines/modal 0.0.59 → 0.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -4
- package/dist/index.d.cts +82 -15
- package/dist/index.d.ts +82 -15
- package/dist/index.js +3 -4
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
'use strict';var modal=require('modal'),tarStream=require('tar-stream');var
|
|
2
|
-
`).slice(1).map(o=>{let s=o.trim().split(/\s+/);return {processId:s[0],cmd:s[1]||"",args:s.slice(2),envs:{}}})}async connect(e,t){throw new Error("Modal does not support connecting to existing processes")}async sendStdin(e,t){throw new Error("Modal does not support sendStdin by process ID")}async kill(e){return await(await this.sandbox.exec(["kill","-9",e],{timeoutMs:1e4})).wait()===0}async accumulateStreams(e,t,n){let o="",s="",i=[];return i.push((async()=>{try{for await(let a of e.stdout){let d=typeof a=="string"?a:new TextDecoder().decode(a);o+=d,t?.(d);}}catch{}})()),i.push((async()=>{try{for await(let a of e.stderr){let d=typeof a=="string"?a:new TextDecoder().decode(a);s+=d,n?.(d);}}catch{}})()),await Promise.all(i),{stdout:o,stderr:s}}},A=class{constructor(e,t){this.sandbox=e;this.user=t;}async chownToUser(e,t=false){if(this.user==="root")return;let n=t?["chown","-R",`${this.user}:${this.user}`,e]:["chown",`${this.user}:${this.user}`,e];await(await this.sandbox.exec(n,{timeoutMs:t?3e4:1e4})).wait();}async writeStdinChunked(e,t){for(let n=0;n<t.length;n+=g)await e.writeBytes(t.subarray(n,n+g));}async writeStdinCoalesced(e,t){let n=[],o=0,s=async()=>{if(o===0)return;let i=n.length===1?n[0]:Buffer.concat(n,o);n=[],o=0,await this.writeStdinChunked(e,i);};for await(let i of t)n.push(i),o+=i.length,o>=g&&await s();await s();}async read(e){let t=await this.sandbox.exec(["cat",e],{timeoutMs:3e5,mode:"binary"}),n=await t.wait();if(n!==0){let s=await t.stderr.readText();throw new Error(`Failed to read file ${e}: ${s||`exit code ${n}`}`)}let o=await t.stdout.readBytes();if(!o.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(o)}catch{}return o}async write(e,t){let n=this.toBuffer(t),o=e.substring(0,e.lastIndexOf("/"));o&&await this.makeDir(o);let s=e.replace(/'/g,"'\\''"),i=await this.sandbox.exec(["bash","-c",`cat > '${s}'`],{mode:"binary"});await this.writeStdinChunked(i.stdin,new Uint8Array(n)),await i.stdin.getWriter().close(),await i.wait(),await this.chownToUser(e);}async writeBatch(e){let t=tarStream.pack(),n=new Set;for(let i of e){let a=this.toBuffer(i.data),d=i.path.startsWith("/")?i.path.slice(1):i.path;t.entry({name:d},a);let c=i.path.substring(0,i.path.lastIndexOf("/"));c&&n.add(c);}t.finalize();let o=await this.sandbox.exec(["tar","-xf","-","-C","/"],{mode:"binary"});if(await this.writeStdinCoalesced(o.stdin,t),await o.stdin.getWriter().close(),await o.wait(),n.size>0){let i=Array.from(n),a=new Set(i.map(d=>d.split("/").slice(0,4).join("/")));for(let d of a)await this.chownToUser(d,true);}}async makeDir(e){await(await this.sandbox.exec(["mkdir","-p",e],{timeoutMs:1e4})).wait(),await this.chownToUser(e,true);}async exists(e){return await(await this.sandbox.exec(["test","-e",e],{timeoutMs:1e4})).wait()===0}async list(e){let t=e.replace(/'/g,"'\\''"),n=await this.sandbox.exec(["bash","-c",`ls -la '${t}' | tail -n +2`],{timeoutMs:3e4});await n.wait();let o=await n.stdout.readText(),s=[];for(let i of o.trim().split(`
|
|
3
|
-
|
|
4
|
-
exports.EVOLVE_IMAGE_VERSION=p;exports.MODAL_MAX_LIFETIME_MS=$;exports.MODAL_MAX_LIST_SANDBOXES=O;exports.MODAL_STDIN_CHUNK_BYTES=g;exports.ModalBootCommandError=P;exports.ModalCommands=M;exports.ModalFiles=A;exports.ModalIdleTimeoutError=f;exports.ModalNetworkPolicyError=w;exports.ModalProvider=k;exports.ModalResourcesError=h;exports.ModalSandboxLifetimeError=v;exports.ModalVolumeError=m;exports._testBuildSandboxInfo=ve;exports._testCollectSandboxes=Pe;exports._testDynamicNetworkPolicyParams=be;exports._testImageMap=he;exports._testMapBootCommand=Ae;exports._testMapIdleTimeout=Me;exports._testMapNetworkPolicy=we;exports._testMapResources=ye;exports._testMapVolumeMounts=ke;exports._testRequiresDynamicNetwork=xe;exports._testResolveImageRegistry=Se;exports._testValidateTimeout=Ie;exports._testWrapCommand=fe;exports.createModalProvider=ge;
|
|
1
|
+
'use strict';var modal=require('modal'),tarStream=require('tar-stream'),fs=require('fs');var l=class extends Error{feature;provider;reason;constructor(e,t,r){super(`${t} does not support ${e}${r?`: ${r}`:""}`),this.name="SandboxFeatureUnsupportedError",this.feature=e,this.provider=t,this.reason=r;}},u=class extends Error{path;provider;constructor(e,t){super(`${t}: no such file or directory: ${e}`),this.name="SandboxPathNotFoundError",this.path=e,this.provider=t;}},w=class extends Error{sandboxId;provider;state;constructor(e,t,r){super(`${t} sandbox ${e} is not running (${r}); inspect never starts or resumes a sandbox`),this.name="SandboxNotRunningError",this.sandboxId=e,this.provider=t,this.state=r;}};function R(n,e){return !!n&&typeof n=="object"&&n.name===e}function ue(n){return R(n,"SandboxFeatureUnsupportedError")}function pe(n){return R(n,"SandboxPathNotFoundError")}function ge(n){return R(n,"SandboxNotRunningError")}var k=2;var _=21;function V(n){return `'${n.replace(/'/g,"'\\''")}'`}function W(n){if(!Number.isInteger(n.offset)||n.offset<0)throw new RangeError(`offset must be a non-negative integer, got ${n.offset}`);if(!Number.isInteger(n.length)||n.length<0)throw new RangeError(`length must be a non-negative integer, got ${n.length}`)}function G(n){if(typeof n=="number")return L((n&4095).toString(8));if(/^[0-7]{1,4}$/.test(n))return L(n);throw new RangeError(`not an octal mode: ${n}`)}function L(n){return n.padStart(4,"0")}function j(n){let e=n&fs.constants.S_IFMT;return e===fs.constants.S_IFDIR?"dir":e===fs.constants.S_IFLNK?"symlink":e===fs.constants.S_IFREG?"file":"other"}function K(n){let e=n instanceof Date?n:typeof n=="number"?new Date(n*1e3):new Date(n);if(Number.isNaN(e.getTime()))throw new RangeError(`not a timestamp: ${String(n)}`);return e.toISOString()}var x="c-4bfce70a407f";var J={[`evolve-all-${x}`]:`evolvingmachines/evolve-all:${x}`,"evolve-all":"evolvingmachines/evolve-all"},Q=1440*60*1e3,y=8*1024*1024;async function*we(n){let e=n.getReader();try{for(;;){let{done:t,value:r}=await e.read();if(t)break;r&&(yield r);}}finally{e.releaseLock();}}var $="user",Z="evolve.image",ee="evolve.startedAt",T=class extends Error{requestedTimeoutMs;constructor(e){let t=(e/36e5).toFixed(1);super(`Modal sandboxes have a hard 24h lifetime cap; requested timeout was ${t}h. For sessions longer than 24h, persist progress with Evolve checkpoints and resume in a fresh sandbox instead of extending the timeout.`),this.name="ModalSandboxLifetimeError",this.requestedTimeoutMs=e;}};function te(n){if(n>Q)throw new T(n)}var S=class extends Error{requestedIdleTimeoutMs;constructor(e,t){super(`Modal idleTimeoutMs of ${e}ms is invalid: ${t}`),this.name="ModalIdleTimeoutError",this.requestedIdleTimeoutMs=e;}};function ne(n){if(n===void 0)return {};if(!Number.isFinite(n)||n<=0)throw new S(n,"it must be a positive number of milliseconds");if(n>Q)throw new S(n,"it exceeds Modal's 24h lifetime cap, so the sandbox would always die of the lifetime first");return {idleTimeoutMs:n}}var N=class extends Error{constructor(e){super(`Modal bootCommand is invalid: ${e}`),this.name="ModalBootCommandError";}};function re(n){if(n===void 0)return {};if(n.length===0)throw new N(`an empty argv is Modal's own "no args" wire shape and would boot the image's ENTRYPOINT/CMD \u2014 omit bootCommand to boot the image's command`);return {command:[...n]}}var f=class extends Error{reason;mountPath;volumeName;constructor(e,t,r,o,s){super(o,s===void 0?void 0:{cause:s}),this.name="ModalVolumeError",this.reason=e,this.mountPath=t,this.volumeName=r;}};function oe(n){if(!n)return [];let e=[];for(let[t,r]of Object.entries(n)){if(!t.startsWith("/")||t==="/")throw new f("invalid-mount-path",t,r.name,`Modal Volume mount path ${JSON.stringify(t)} is invalid: it must be an absolute in-box path other than "/"`);let o=r.name?.trim()??"";if(o.length===0)throw new f("invalid-name",t,r.name??"",`Modal Volume mounted at ${t} has a blank name`);e.push({mountPath:t,name:o,readOnly:r.readOnly===true,createIfMissing:r.createIfMissing===true});}return e}function C(n,e,t,r,o){let s="";r&&Object.keys(r).length>0&&(s=Object.entries(r).filter(([,d])=>d!=null).map(([d,m])=>`export ${d}='${String(m).replace(/'/g,"'\\''")}'`).join("; ")+"; ");let i=t?`cd '${t.replace(/'/g,"'\\''")}' && ${s}${n}`:`${s}${n}`;if(e==="root")return ["bash","-c",i];let a=Buffer.from(i).toString("base64");return ["su",e,o?.sameSession?"--session-command":"-c",`echo ${a} | base64 -d | bash`]}var v=class extends Error{constructor(e){super(e),this.name="ModalResourcesError";}},be=4,xe=4096;function se(n){if(n?.disk!==void 0)throw new v(`Modal's JS SDK has no create-time disk-size parameter, so a ${n.disk} GiB disk request cannot be enforced. Drop \`resources.disk\` (containers get Modal's default disk quota) or run on a provider that sizes disk.`);if((n?.gpu===void 0||n.gpu<=0)&&n?.gpuTypes?.length)throw new v("resources.gpuTypes was set without a positive resources.gpu count \u2014 declare how many GPUs to reserve, or drop gpuTypes.");let e=n?.gpu!==void 0&&n.gpu>0?`${n.gpuTypes?.length?n.gpuTypes[0]:"any"}:${n.gpu}`:void 0;return {cpu:n?.cpu??be,memoryMiB:n?.memory!==void 0?Math.ceil(n.memory*1024):xe,...e!==void 0?{gpu:e}:{}}}var P=class extends Error{reason;destination;constructor(e,t,r){super(t),this.name="ModalNetworkPolicyError",this.reason=e,this.destination=r;}};function ie(n){let e=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(n);return !(!e||[e[1],e[2],e[3],e[4]].some(t=>Number(t)>255)||e[5]!==void 0&&Number(e[5])>32)}function ye(n){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(n)&&!ie(n)}function Se(n){return n.startsWith("[")?true:(n.match(/:/g)?.length??0)>=2}function ve(n){return /^[^:]+:\d+$/.test(n)}function F(n){if(!n||n.outbound==="open"){if(n?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return {}}let e=n.allowedDestinations??[];if(e.length===0)return {blockNetwork:true};let t=[],r=[];for(let o of e)if(ie(o))t.push(o.includes("/")?o:`${o}/32`);else {if(ye(o))throw new P("invalid-ipv4",`"${o}" is not a valid IPv4 address or CIDR (octets must be 0-255, prefix 0-32). Fix the address or list a hostname instead.`,o);if(Se(o))t.push(o.includes("/")?o:`${o}/128`);else {if(ve(o))throw new P("port-unsupported",`Modal's network allowlist filters hosts and IPs only and cannot match a port; drop the ":<port>" from "${o}" and list just the host or IP.`,o);r.push(o);}}return {outboundCidrAllowlist:t,outboundDomainAllowlist:r}}function I(n){if(!n||n.outbound==="open"){if(n?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return {outboundCidrAllowlist:["0.0.0.0/0"],outboundDomainAllowlist:["*"]}}let e=F(n);return {outboundCidrAllowlist:e.outboundCidrAllowlist??[],outboundDomainAllowlist:Ie(e.outboundDomainAllowlist??[])}}var Pe="sealed.invalid";function Ie(n){return n.length>0?n:[Pe]}function ae(n,e){if(!e||e.length===0)return false;let t=o=>o===void 0?"open|":`${o.outbound}|${[...new Set(o.allowedDestinations??[])].sort().join(",")}`,r=t(n);return e.some(o=>t(o)!==r)}function de(n){let e=n.split("/")[0];return /^\d{12}\.dkr\.ecr\.[a-z0-9-]+\.amazonaws\.com$/.test(e)?"aws-ecr":e==="gcr.io"||e.endsWith(".gcr.io")||e.endsWith("-docker.pkg.dev")?"gcp-artifact-registry":"registry"}function B(n,e,t){let{[Z]:r,[ee]:o,...s}=e;return {sandboxId:n,image:r??t??"",metadata:s,startedAt:o??""}}var H=1e4,D=class{constructor(e,t){this.sandbox=e;this.user=t;}async run(e,t){let r=C(e,this.user,t?.cwd,t?.envs),o=await this.sandbox.exec(r,{timeoutMs:t?.timeoutMs}),{stdout:s,stderr:i}=await this.accumulateStreams(o,t?.onStdout,t?.onStderr);return {exitCode:await o.wait(),stdout:s,stderr:i}}async spawn(e,t){let r=t?.stdin===false,o=C(e,this.user,t?.cwd,t?.envs,{sameSession:r}),s=r?["bash","-c",Re,"bash",...o]:o,i=await this.sandbox.exec(s,{timeoutMs:t?.timeoutMs}),a="",d="",m=this.accumulateStreams(i,t?.onStdout?c=>{t.onStdout(c);}:void 0,t?.onStderr?c=>{t.onStderr(c);}:void 0).then(({stdout:c,stderr:h})=>{a=c,d=h;}).catch(()=>{});return {processId:`modal-${Date.now()}-${Math.random().toString(36).slice(2)}`,wait:async()=>(await m,{exitCode:await i.wait(),stdout:a,stderr:d}),kill:async()=>{if(!r)throw new l("commands.kill","modal","the Modal SDK cannot signal a running process; spawn it with `stdin: false` and kill() ends it by closing its stdin");let c=i.stdin.getWriter();try{return await c.close(),!0}catch{return false}}}}async list(){let e=await this.sandbox.exec(["ps","-eo","pid,comm,args"],{timeoutMs:1e4});return await e.wait(),(await e.stdout.readText()).trim().split(`
|
|
2
|
+
`).slice(1).map(o=>{let s=o.trim().split(/\s+/);return {processId:s[0],cmd:s[1]||"",args:s.slice(2),envs:{}}})}async connect(e,t){throw new l("commands.connect","modal","the Modal SDK cannot attach to a process by id")}async sendStdin(e,t){throw new l("commands.sendStdin","modal","the Modal SDK cannot address a process's stdin by id")}async kill(e){return await(await this.sandbox.exec(["kill","-9",e],{timeoutMs:1e4})).wait()===0}async accumulateStreams(e,t,r){let o="",s="",i=[];return i.push((async()=>{try{for await(let a of e.stdout){let d=typeof a=="string"?a:new TextDecoder().decode(a);o+=d,t?.(d);}}catch{}})()),i.push((async()=>{try{for await(let a of e.stderr){let d=typeof a=="string"?a:new TextDecoder().decode(a);s+=d,r?.(d);}}catch{}})()),await Promise.all(i),{stdout:o,stderr:s}}},O=class{constructor(e,t){this.sandbox=e;this.user=t;}async chownToUser(e,t=false){if(this.user==="root")return;let r=t?["chown","-R",`${this.user}:${this.user}`,e]:["chown",`${this.user}:${this.user}`,e];await(await this.sandbox.exec(r,{timeoutMs:t?3e4:1e4})).wait();}async writeStdinChunked(e,t){for(let r=0;r<t.length;r+=y)await e.writeBytes(t.subarray(r,r+y));}async writeStdinCoalesced(e,t){let r=[],o=0,s=async()=>{if(o===0)return;let i=r.length===1?r[0]:Buffer.concat(r,o);r=[],o=0,await this.writeStdinChunked(e,i);};for await(let i of t)r.push(i),o+=i.length,o>=y&&await s();await s();}async read(e){let t=await this.sandbox.exec(["cat",e],{timeoutMs:3e5,mode:"binary"}),r=await t.wait();if(r!==0){let s=await t.stderr.readText();throw new Error(`Failed to read file ${e}: ${s||`exit code ${r}`}`)}let o=await t.stdout.readBytes();if(!o.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(o)}catch{}return o}async write(e,t){let r=this.toBuffer(t),o=e.substring(0,e.lastIndexOf("/"));o&&await this.makeDir(o);let s=e.replace(/'/g,"'\\''"),i=await this.sandbox.exec(["bash","-c",`cat > '${s}'`],{mode:"binary"});await this.writeStdinChunked(i.stdin,new Uint8Array(r)),await i.stdin.getWriter().close(),await i.wait(),await this.chownToUser(e);}async writeBatch(e){let t=tarStream.pack(),r=new Set;for(let i of e){let a=this.toBuffer(i.data),d=i.path.startsWith("/")?i.path.slice(1):i.path;t.entry({name:d},a);let m=i.path.substring(0,i.path.lastIndexOf("/"));m&&r.add(m);}t.finalize();let o=await this.sandbox.exec(["tar","-xf","-","-C","/"],{mode:"binary"});if(await this.writeStdinCoalesced(o.stdin,t),await o.stdin.getWriter().close(),await o.wait(),r.size>0){let i=Array.from(r),a=new Set(i.map(d=>d.split("/").slice(0,4).join("/")));for(let d of a)await this.chownToUser(d,true);}}async makeDir(e){await(await this.sandbox.exec(["mkdir","-p",e],{timeoutMs:1e4})).wait(),await this.chownToUser(e,true);}async exists(e){return await(await this.sandbox.exec(["test","-e",e],{timeoutMs:1e4})).wait()===0}async list(e){try{return (await this.sandbox.filesystem.listFiles(e)).map(r=>z(r))}catch(t){throw X(t)?new u(e,"modal"):t}}async stat(e){try{return z(await this.sandbox.filesystem.stat(e))}catch(t){throw X(t)?new u(e,"modal"):t}}async readRange(e,t){if(W(t),t.length===0)return new Uint8Array(0);let r=V(e),o=`[ -e ${r} ] || exit ${k}; [ -d ${r} ] && exit ${_}; tail -c +${t.offset+1} -- ${r} | head -c ${t.length}; s=("\${PIPESTATUS[@]}"); [ "\${s[1]}" -eq 0 ] || exit "\${s[1]}"; [ "\${s[0]}" -eq 0 ] || [ "\${s[0]}" -eq ${Ae} ] || exit "\${s[0]}"`,s=await this.sandbox.exec(["bash","-c",o],{mode:"binary",timeoutMs:Y}),i=await s.stdout.readBytes(),a=await s.wait();if(a===k)throw new u(e,"modal");if(a===_)throw new Error(`modal: ${e} is a directory`);if(a!==0){let d=new TextDecoder().decode(await s.stderr.readBytes()).trim();throw new Error(`modal: range read of ${e} failed (exit ${a}): ${d}`)}return i}async remove(e){await(await this.sandbox.exec(["rm","-rf",e],{timeoutMs:3e4})).wait();}async rename(e,t){await(await this.sandbox.exec(["mv",e,t],{timeoutMs:3e4})).wait();}async readStream(e){return (await this.sandbox.exec(["cat",e],{timeoutMs:Y,mode:"binary"})).stdout}async writeStream(e,t){let r=e.substring(0,e.lastIndexOf("/"));r&&await this.makeDir(r);let o=e.replace(/'/g,"'\\''"),s=await this.sandbox.exec(["bash","-c",`cat > '${o}'`],{mode:"binary"});await this.writeStdinCoalesced(s.stdin,we(t)),await s.stdin.getWriter().close(),await s.wait(),await this.chownToUser(e);}async writeFromPath(e,t){let{createReadStream:r}=await import('fs'),{Readable:o}=await import('stream'),s=o.toWeb(r(t,{highWaterMark:y}));await this.writeStream(e,s);}async uploadUrl(e,t){throw new l("files.uploadUrl","modal","Modal issues no signed upload URLs")}async downloadUrl(e,t){throw new l("files.downloadUrl","modal","Modal issues no signed download URLs")}async watchDir(e,t,r){await this.stat(e);let o=this.sandbox.filesystem.watch(e,{recursive:r?.recursive??false,filter:[...Me]})[Symbol.asyncIterator](),s=false;return (async()=>{for(;;){let{done:i,value:a}=await o.next();if(i||s)break;for(let d of Ee(a))await t(d);}})().catch(()=>{}),{stop:async()=>{s=true,o.return?.().catch(()=>{});}}}toBuffer(e){if(typeof e=="string")return Buffer.from(e,"utf-8");if(e instanceof Buffer)return e;if(e instanceof ArrayBuffer||e instanceof Uint8Array)return Buffer.from(e);throw new Error(`Unsupported data type: ${typeof e}`)}};function z(n){let e=j(n.mode),t={name:n.name,path:n.path,type:e,size:n.size,mtime:K(n.modifiedTime),mode:G(n.permissions),owner:n.owner,group:n.group};return e==="symlink"&&n.symlinkTarget!==null&&(t.target=n.symlinkTarget),t}function X(n){return !!n&&typeof n=="object"&&n.name==="SandboxFilesystemNotFoundError"}var Me=["Create","Modify","Remove"];function Ee(n){if(n.eventType==="Create")return n.paths.map(e=>({path:e,type:"create"}));if(n.eventType==="Remove")return n.paths.map(e=>({path:e,type:"remove"}));if(n.eventType==="Modify"){let e=n.paths.length>=2?"rename":"write";return n.paths.map(t=>({path:t,type:e}))}return []}var Ae=141,Y=3e5,Re=["set -m","exec 3<&0",'"$@" </dev/null 3<&- & job=$!',"( cat <&3 >/dev/null; kill -TERM -- -$job 2>/dev/null ) & eof=$!","exec 2>/dev/null","trap 'kill -TERM -- -$job' TERM","wait $job; rc=$?","kill -TERM -- -$eof","exit $rc"].join("; "),p=class{constructor(e,t,r){this.sandbox=e;this.commands=new D(e,r),this.files=new O(e,r),this.image=t;}commands;files;image;get sandboxId(){return this.sandbox.sandboxId}async metrics(){throw new l("metrics","modal","Modal has no sandbox metrics API, and /proc and the cgroup files inside its sandbox report host-wide figures (measured 2026-09-16: MemTotal 1 TiB on a 1 GiB sandbox)")}async getHost(e){let r=(await this.sandbox.tunnels())[e];if(!r)throw new Error(`No tunnel found for port ${e}`);return r.url}async isRunning(){try{return await this.sandbox.poll()===null}catch{return false}}async getInfo(){let e=await this.sandbox.getTags();return B(this.sandbox.sandboxId,e,this.image)}async updateNetwork(e){await this.sandbox.updateNetworkPolicy(I(e));}async kill(){try{await this.sandbox.terminate();}catch{await new Promise(e=>setTimeout(e,500)),await this.sandbox.terminate();}}async pause(){throw new Error("Modal does not support pause/resume. Persist progress with Evolve checkpoints and resume in a fresh sandbox, or use kill() to terminate.")}},U=class{providerType="modal";name="Modal";supportsBootCommand=true;supportsVolumes=true;client;appName;defaultTimeoutMs;imageName;imageSecretName;_app;sandboxUsers=new Map;constructor(e){!e.endpoint&&process.env.MODAL_SERVER_URL?.startsWith("unix:")?process.env.MODAL_SERVER_URL="https://api.modal.com:443":e.endpoint&&(process.env.MODAL_SERVER_URL=e.endpoint),this.client=new modal.ModalClient({tokenId:e.tokenId,tokenSecret:e.tokenSecret}),this.appName=e.appName??"evolve-sandbox",this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.imageName=e.imageName??`evolve-all-${x}`,this.imageSecretName=e.imageSecretName;}async getApp(){return this._app||(this._app=await this.client.apps.fromName(this.appName,{createIfMissing:true})),this._app}async resolveImage(e){let t=de(e);if(t==="registry"){let o=this.imageSecretName?await this.client.secrets.fromName(this.imageSecretName):void 0;return this.client.images.fromRegistry(e,o)}if(!this.imageSecretName)throw new Error(`Private registry image "${e}" requires config.imageSecretName \u2014 the name of a Modal Secret holding registry credentials (AWS ECR: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION with read-only ECR IAM). Create one at https://modal.com/secrets`);let r=t==="aws-ecr"?await this.client.secrets.fromName(this.imageSecretName,{requiredKeys:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]}):await this.client.secrets.fromName(this.imageSecretName);return t==="aws-ecr"?this.client.images.fromAwsEcr(e,r):this.client.images.fromGcpArtifactRegistry(e,r)}async resolveAndBuildImage(e){let t=J[e]??e;if(!/[/:@]/.test(t))try{return {tag:t,image:await this.client.images.fromName(t)}}catch(s){if(!(s instanceof modal.NotFoundError))throw s}let r=await this.getApp(),o=await this.resolveImage(t);return {tag:t,image:await o.build(r)}}async publishImageAs(e,t){if(!e.trim())throw new Error("publishImageAs requires a non-empty alias to publish under");let{image:r}=await this.resolveAndBuildImage(t||this.imageName);return await r.publish(e),e}async prepareImage(e){await this.resolveAndBuildImage(e||this.imageName);}async create(e){let t=e.timeoutMs??this.defaultTimeoutMs;te(t);let r=ne(e.idleTimeoutMs),o=re(e.bootCommand),s=oe(e.volumes);for(let g of e.phaseNetworkPolicies??[])I(g);let i=ae(e.network,e.phaseNetworkPolicies)?I(e.network):F(e.network),a=se(e.resources),d=e.user??$,m=await this.getApp(),{tag:M,image:c}=await this.resolveAndBuildImage(e.image||this.imageName),h=await this.resolveVolumes(s),E=e.envs?Object.fromEntries(Object.entries(e.envs).filter(([,g])=>g!=null)):void 0,le=E&&Object.keys(E).length>0?E:void 0,me={...e.metadata,[Z]:M,[ee]:new Date().toISOString()},A=await this.client.sandboxes.create(m,c,{cpu:a.cpu,memoryMiB:a.memoryMiB,...a.gpu!==void 0?{gpu:a.gpu}:{},timeoutMs:t,...r,...o,workdir:e.workingDirectory,env:le,tags:me,...i,...h!==void 0?{volumes:h}:{}});return e.workingDirectory&&d!=="root"&&await(await A.exec(["chown","-R",`${d}:${d}`,e.workingDirectory],{timeoutMs:3e4})).wait(),this.sandboxUsers.set(A.sandboxId,d),new p(A,M,d)}async resolveVolumes(e){if(e.length===0)return;let t={};for(let r of e){let o;try{o=await this.client.volumes.fromName(r.name,{createIfMissing:r.createIfMissing});}catch(s){let i=s instanceof Error?s.message:String(s),a=s instanceof modal.NotFoundError||s instanceof Error&&s.name==="NotFoundError";throw new f(a?"not-found":"resolve-failed",r.mountPath,r.name,a?`Modal Volume "${r.name}" (to mount at ${r.mountPath}) does not exist and createIfMissing was not set: ${i}`:`Modal Volume "${r.name}" (to mount at ${r.mountPath}) could not be resolved: ${i}`,s)}t[r.mountPath]=o.withMountOptions({readOnly:r.readOnly});}return t}async connect(e,t){let r=await this.client.sandboxes.fromId(e),o=this.sandboxUsers.get(e)??$;return new p(r,void 0,o)}async inspect(e,t){let r=await this.attachSandbox(e),o=await r.poll();if(o!==null)throw new w(e,"modal",`exited with code ${o}`);let s=t?.user??this.sandboxUsers.get(e)??$;return new p(r,void 0,s)}async attachSandbox(e){return this.client.sandboxes.fromId(e)}async list(e){let t=await this.walk(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...r}=await this.walk(e);return r}async walk(e){if(e?.state&&!e.state.includes("running"))return {sandboxes:[],complete:true,pagesFetched:0,stoppedAtLimit:false};let t;try{t=await this.getApp();}catch(r){return {sandboxes:[],complete:false,pagesFetched:0,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return ce(()=>this.client.sandboxes.list({appId:t.appId,tags:e?.metadata}),e?.limit)}async listSandboxIds(){let e=new Set;try{let t=await this.getApp();for await(let r of this.client.sandboxes.list({appId:t.appId}))e.add(r.sandboxId);return {ids:e,complete:!0}}catch{return {ids:new Set,complete:false}}}};async function ce(n,e){let t=[];try{for await(let r of n()){if(e!==void 0&&t.length>=e)return {sandboxes:t,complete:!1,pagesFetched:t.length,stoppedAtLimit:!0,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(t.length>=H)return {sandboxes:t,complete:!1,pagesFetched:t.length,stoppedAtLimit:!1,error:`sandbox list exceeded ${H} sandboxes`};let o=await r.getTags();t.push(B(r.sandboxId,o));}}catch(r){return {sandboxes:t,complete:false,pagesFetched:t.length,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return {sandboxes:t,complete:true,pagesFetched:t.length,stoppedAtLimit:false}}function Ge(n={}){let e=n.tokenId??process.env.MODAL_TOKEN_ID,t=n.tokenSecret??process.env.MODAL_TOKEN_SECRET;if(!e||!t)throw new Error("Modal credentials required. Set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables, or pass tokenId/tokenSecret in config. Get your token at https://modal.com/settings/tokens");return new U({...n,tokenId:e,tokenSecret:t})}var je=C,Ke=J,qe=F,He=I,ze=ae,Xe=se,Ye=de,Je=B,Qe=ce,Ze=te,et=ne,tt=re,nt=oe,rt=p;
|
|
3
|
+
exports.EVOLVE_IMAGE_VERSION=x;exports.MODAL_MAX_LIFETIME_MS=Q;exports.MODAL_MAX_LIST_SANDBOXES=H;exports.MODAL_STDIN_CHUNK_BYTES=y;exports.ModalBootCommandError=N;exports.ModalCommands=D;exports.ModalFiles=O;exports.ModalIdleTimeoutError=S;exports.ModalNetworkPolicyError=P;exports.ModalProvider=U;exports.ModalResourcesError=v;exports.ModalSandboxLifetimeError=T;exports.ModalVolumeError=f;exports.SandboxFeatureUnsupportedError=l;exports.SandboxNotRunningError=w;exports.SandboxPathNotFoundError=u;exports._testBuildSandboxInfo=Je;exports._testCollectSandboxes=Qe;exports._testDynamicNetworkPolicyParams=He;exports._testImageMap=Ke;exports._testMapBootCommand=tt;exports._testMapIdleTimeout=et;exports._testMapNetworkPolicy=qe;exports._testMapResources=Xe;exports._testMapVolumeMounts=nt;exports._testModalSandboxImplCtor=rt;exports._testRequiresDynamicNetwork=ze;exports._testResolveImageRegistry=Ye;exports._testValidateTimeout=Ze;exports._testWrapCommand=je;exports.createModalProvider=Ge;exports.isSandboxFeatureUnsupportedError=ue;exports.isSandboxNotRunningError=ge;exports.isSandboxPathNotFoundError=pe;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { Sandbox } from 'modal';
|
|
2
2
|
|
|
3
|
+
/** A capability this provider lacks: `feature` in dotted form (`files.watchDir`), `provider` type, optional `reason`. */
|
|
4
|
+
declare class SandboxFeatureUnsupportedError extends Error {
|
|
5
|
+
readonly feature: string;
|
|
6
|
+
readonly provider: string;
|
|
7
|
+
readonly reason?: string;
|
|
8
|
+
constructor(feature: string, provider: string, reason?: string);
|
|
9
|
+
}
|
|
10
|
+
/** A path the sandbox does not have — never an empty success. */
|
|
11
|
+
declare class SandboxPathNotFoundError extends Error {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly provider: string;
|
|
14
|
+
constructor(path: string, provider: string);
|
|
15
|
+
}
|
|
16
|
+
/** An inspect refused because the sandbox is not running; `state` is the provider's own word (`paused`, `exited with code 137`). */
|
|
17
|
+
declare class SandboxNotRunningError extends Error {
|
|
18
|
+
readonly sandboxId: string;
|
|
19
|
+
readonly provider: string;
|
|
20
|
+
readonly state: string;
|
|
21
|
+
constructor(sandboxId: string, provider: string, state: string);
|
|
22
|
+
}
|
|
23
|
+
/** True for a SandboxFeatureUnsupportedError from ANY package's copy. */
|
|
24
|
+
declare function isSandboxFeatureUnsupportedError(err: unknown): err is SandboxFeatureUnsupportedError;
|
|
25
|
+
/** True for a SandboxPathNotFoundError from ANY package's copy. */
|
|
26
|
+
declare function isSandboxPathNotFoundError(err: unknown): err is SandboxPathNotFoundError;
|
|
27
|
+
/** True for a SandboxNotRunningError from ANY package's copy. */
|
|
28
|
+
declare function isSandboxNotRunningError(err: unknown): err is SandboxNotRunningError;
|
|
29
|
+
|
|
3
30
|
/**
|
|
4
31
|
* GENERATED — DO NOT EDIT. `npm run generate:image-version` (repo root)
|
|
5
32
|
* rewrites this file from the evolve-all image build inputs under
|
|
@@ -9,7 +36,7 @@ import { Sandbox } from 'modal';
|
|
|
9
36
|
* packages/daytona/tests/unit/daytona-image-version.test.ts fails the
|
|
10
37
|
* suite whenever this checked-in copy is stale.
|
|
11
38
|
*/
|
|
12
|
-
declare const EVOLVE_IMAGE_VERSION = "c-
|
|
39
|
+
declare const EVOLVE_IMAGE_VERSION = "c-4bfce70a407f";
|
|
13
40
|
|
|
14
41
|
/**
|
|
15
42
|
* Modal Sandbox Provider - Clean Architecture
|
|
@@ -25,7 +52,7 @@ declare const EVOLVE_IMAGE_VERSION = "c-880c264ce574";
|
|
|
25
52
|
* - Clear naming (run = blocking, spawn = background)
|
|
26
53
|
*
|
|
27
54
|
* Modal-specific notes:
|
|
28
|
-
* -
|
|
55
|
+
* - File content moves over exec() stdin/stdout; list, stat and watch use the SDK's filesystem API
|
|
29
56
|
* - Named Volumes mount at create (`volumes`, keyed by in-box path, read-only
|
|
30
57
|
* or read-write) — Modal's "upload once, read from many sandboxes" store.
|
|
31
58
|
* modal@0.9.0 has no upload-to-Volume call, so a Volume is filled from
|
|
@@ -206,7 +233,7 @@ interface ResolvedVolumeMount {
|
|
|
206
233
|
declare function mapVolumeMounts(volumes?: Record<string, ModalVolumeMount>): ResolvedVolumeMount[];
|
|
207
234
|
/**
|
|
208
235
|
* Wrap a command with cwd + env handling and (when not root) an
|
|
209
|
-
* `su <user> -c` wrapper.
|
|
236
|
+
* `su <user> -c` wrapper (`--session-command` when the caller must be able to signal it).
|
|
210
237
|
*
|
|
211
238
|
* Modal sandboxes run as root by default (ignoring the Dockerfile USER
|
|
212
239
|
* directive), but Claude CLI and other tools refuse certain operations when
|
|
@@ -219,7 +246,9 @@ declare function mapVolumeMounts(volumes?: Record<string, ModalVolumeMount>): Re
|
|
|
219
246
|
* that contain quotes, special characters, etc. Env vars are inlined because
|
|
220
247
|
* su does not preserve the environment the way `sudo -E` does.
|
|
221
248
|
*/
|
|
222
|
-
declare function wrapCommand(command: string, user: string, cwd?: string, envs?: Record<string, string
|
|
249
|
+
declare function wrapCommand(command: string, user: string, cwd?: string, envs?: Record<string, string>, options?: {
|
|
250
|
+
sameSession?: boolean;
|
|
251
|
+
}): string[];
|
|
223
252
|
/**
|
|
224
253
|
* Typed error for sizing requests Modal's create() cannot enforce.
|
|
225
254
|
* The installed Modal JS SDK sizes cpu (cores) and memoryMiB at create time
|
|
@@ -373,18 +402,27 @@ interface SandboxInfo {
|
|
|
373
402
|
/** End time (undefined for running sandboxes) */
|
|
374
403
|
endAt?: string;
|
|
375
404
|
}
|
|
376
|
-
/**
|
|
405
|
+
/** The SDK contract's FileInfo (sdk-ts types.ts), the same entry on every provider. */
|
|
377
406
|
interface FileInfo {
|
|
378
407
|
name: string;
|
|
379
408
|
path: string;
|
|
380
|
-
type: "file" | "dir";
|
|
409
|
+
type: "file" | "dir" | "symlink" | "other";
|
|
410
|
+
size: number;
|
|
411
|
+
mtime: string;
|
|
412
|
+
mode: string;
|
|
413
|
+
owner: string;
|
|
414
|
+
group: string;
|
|
415
|
+
target?: string;
|
|
416
|
+
}
|
|
417
|
+
/** A byte range of a file (the SDK contract's FileRange). */
|
|
418
|
+
interface FileRange {
|
|
419
|
+
offset: number;
|
|
420
|
+
length: number;
|
|
381
421
|
}
|
|
382
|
-
/**
|
|
422
|
+
/** One filesystem change from watchDir: an absolute path, four kinds. */
|
|
383
423
|
interface FilesystemEvent {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
/** Type of filesystem operation */
|
|
387
|
-
type: "create" | "remove" | "rename" | "chmod" | "write";
|
|
424
|
+
path: string;
|
|
425
|
+
type: "create" | "write" | "remove" | "rename";
|
|
388
426
|
}
|
|
389
427
|
/** Handle to stop watching a directory */
|
|
390
428
|
interface WatchHandle {
|
|
@@ -392,9 +430,21 @@ interface WatchHandle {
|
|
|
392
430
|
}
|
|
393
431
|
/** Options for watching a directory */
|
|
394
432
|
interface WatchOptions {
|
|
433
|
+
/** Also report changes in every subdirectory. Default false. */
|
|
395
434
|
recursive?: boolean;
|
|
396
|
-
|
|
397
|
-
|
|
435
|
+
}
|
|
436
|
+
/** One resource-usage sample (the SDK contract's SandboxMetrics). */
|
|
437
|
+
interface SandboxMetrics {
|
|
438
|
+
cpuPct: number;
|
|
439
|
+
memUsedMb: number;
|
|
440
|
+
memTotalMb: number;
|
|
441
|
+
diskUsedMb?: number;
|
|
442
|
+
sampledAt: string;
|
|
443
|
+
source: string;
|
|
444
|
+
}
|
|
445
|
+
/** Options for an inspect-only attach (the SDK contract's SandboxInspectOptions). */
|
|
446
|
+
interface SandboxInspectOptions {
|
|
447
|
+
user?: string;
|
|
398
448
|
}
|
|
399
449
|
/** Options for blocking sandbox command execution */
|
|
400
450
|
interface SandboxRunOptions {
|
|
@@ -618,6 +668,10 @@ interface SandboxFiles {
|
|
|
618
668
|
remove(path: string): Promise<void>;
|
|
619
669
|
/** Rename or move file/directory */
|
|
620
670
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
671
|
+
/** The entry at `path` itself; a symlink is never followed */
|
|
672
|
+
stat(path: string): Promise<FileInfo>;
|
|
673
|
+
/** Exactly the requested bytes, without moving the whole file when the range is small */
|
|
674
|
+
readRange(path: string, range: FileRange): Promise<Uint8Array>;
|
|
621
675
|
/** Watch directory for changes */
|
|
622
676
|
watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
|
|
623
677
|
}
|
|
@@ -632,6 +686,8 @@ interface SandboxInstance {
|
|
|
632
686
|
isRunning(): Promise<boolean>;
|
|
633
687
|
/** Get sandbox metadata and timing */
|
|
634
688
|
getInfo(): Promise<SandboxInfo>;
|
|
689
|
+
/** Always a typed refusal here: Modal gives a sandbox no honest figures (see ModalSandboxImpl.metrics) */
|
|
690
|
+
metrics(): Promise<SandboxMetrics | null>;
|
|
635
691
|
/** Terminate sandbox */
|
|
636
692
|
kill(): Promise<void>;
|
|
637
693
|
/** Pause sandbox (preserves state) */
|
|
@@ -648,6 +704,8 @@ interface SandboxProvider {
|
|
|
648
704
|
readonly providerType: string;
|
|
649
705
|
/** Human-readable provider name for logging */
|
|
650
706
|
readonly name?: string;
|
|
707
|
+
/** Attach to a RUNNING sandbox for reads; refuses one that has exited */
|
|
708
|
+
inspect(sandboxId: string, options?: SandboxInspectOptions): Promise<SandboxInstance>;
|
|
651
709
|
/**
|
|
652
710
|
* TRUE on every build whose create() maps SandboxCreateOptions.bootCommand
|
|
653
711
|
* to Modal's create args. A consumer whose safety depends on an inert boot
|
|
@@ -781,6 +839,9 @@ declare class ModalFiles implements SandboxFiles {
|
|
|
781
839
|
makeDir(path: string): Promise<void>;
|
|
782
840
|
exists(path: string): Promise<boolean>;
|
|
783
841
|
list(path: string): Promise<FileInfo[]>;
|
|
842
|
+
/** stat describes a symlink itself, never its target (modal index.d.ts). */
|
|
843
|
+
stat(path: string): Promise<FileInfo>;
|
|
844
|
+
readRange(path: string, range: FileRange): Promise<Uint8Array>;
|
|
784
845
|
remove(path: string): Promise<void>;
|
|
785
846
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
786
847
|
readStream(path: string): Promise<ReadableStream<Uint8Array>>;
|
|
@@ -800,7 +861,7 @@ declare class ModalFiles implements SandboxFiles {
|
|
|
800
861
|
writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
|
|
801
862
|
uploadUrl(_path: string, _expiresInSeconds?: number): Promise<string>;
|
|
802
863
|
downloadUrl(_path: string, _expiresInSeconds?: number): Promise<string>;
|
|
803
|
-
watchDir(
|
|
864
|
+
watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
|
|
804
865
|
private toBuffer;
|
|
805
866
|
}
|
|
806
867
|
declare class ModalSandboxImpl implements SandboxInstance {
|
|
@@ -810,6 +871,7 @@ declare class ModalSandboxImpl implements SandboxInstance {
|
|
|
810
871
|
private readonly image?;
|
|
811
872
|
constructor(sandbox: Sandbox, image: string | undefined, user: string);
|
|
812
873
|
get sandboxId(): string;
|
|
874
|
+
metrics(): Promise<SandboxMetrics | null>;
|
|
813
875
|
getHost(port: number): Promise<string>;
|
|
814
876
|
isRunning(): Promise<boolean>;
|
|
815
877
|
getInfo(): Promise<SandboxInfo>;
|
|
@@ -970,6 +1032,9 @@ declare class ModalProvider implements SandboxProvider {
|
|
|
970
1032
|
*/
|
|
971
1033
|
private resolveVolumes;
|
|
972
1034
|
connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
|
|
1035
|
+
inspect(sandboxId: string, options?: SandboxInspectOptions): Promise<SandboxInstance>;
|
|
1036
|
+
/** A read; seam for the unit test. */
|
|
1037
|
+
protected attachSandbox(sandboxId: string): Promise<Sandbox>;
|
|
973
1038
|
/**
|
|
974
1039
|
* List sandboxes, walking the whole app.
|
|
975
1040
|
*
|
|
@@ -1078,5 +1143,7 @@ declare const _testMapVolumeMounts: typeof mapVolumeMounts;
|
|
|
1078
1143
|
* the type (never the constructor) gives the seam the real methods to pin.
|
|
1079
1144
|
*/
|
|
1080
1145
|
type _testModalSandboxImpl = ModalSandboxImpl;
|
|
1146
|
+
/** The constructor, for the metrics-refusal unit test. */
|
|
1147
|
+
declare const _testModalSandboxImplCtor: typeof ModalSandboxImpl;
|
|
1081
1148
|
|
|
1082
|
-
export { EVOLVE_IMAGE_VERSION, type FileInfo, type FilesystemEvent, MODAL_MAX_LIFETIME_MS, MODAL_MAX_LIST_SANDBOXES, MODAL_STDIN_CHUNK_BYTES, ModalBootCommandError, ModalCommands, type ModalConfig, ModalFiles, ModalIdleTimeoutError, ModalNetworkPolicyError, type ModalNetworkPolicyReason, ModalProvider, ModalResourcesError, ModalSandboxLifetimeError, type ModalSandboxStream, ModalVolumeError, type ModalVolumeErrorReason, type ModalVolumeMount, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testBuildSandboxInfo, _testCollectSandboxes, _testDynamicNetworkPolicyParams, _testImageMap, _testMapBootCommand, _testMapIdleTimeout, _testMapNetworkPolicy, _testMapResources, _testMapVolumeMounts, type _testModalSandboxImpl, _testRequiresDynamicNetwork, _testResolveImageRegistry, _testValidateTimeout, _testWrapCommand, createModalProvider };
|
|
1149
|
+
export { EVOLVE_IMAGE_VERSION, type FileInfo, type FileRange, type FilesystemEvent, MODAL_MAX_LIFETIME_MS, MODAL_MAX_LIST_SANDBOXES, MODAL_STDIN_CHUNK_BYTES, ModalBootCommandError, ModalCommands, type ModalConfig, ModalFiles, ModalIdleTimeoutError, ModalNetworkPolicyError, type ModalNetworkPolicyReason, ModalProvider, ModalResourcesError, ModalSandboxLifetimeError, type ModalSandboxStream, ModalVolumeError, type ModalVolumeErrorReason, type ModalVolumeMount, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, SandboxFeatureUnsupportedError, type SandboxFiles, type SandboxInfo, type SandboxInspectOptions, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxMetrics, SandboxNotRunningError, SandboxPathNotFoundError, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testBuildSandboxInfo, _testCollectSandboxes, _testDynamicNetworkPolicyParams, _testImageMap, _testMapBootCommand, _testMapIdleTimeout, _testMapNetworkPolicy, _testMapResources, _testMapVolumeMounts, type _testModalSandboxImpl, _testModalSandboxImplCtor, _testRequiresDynamicNetwork, _testResolveImageRegistry, _testValidateTimeout, _testWrapCommand, createModalProvider, isSandboxFeatureUnsupportedError, isSandboxNotRunningError, isSandboxPathNotFoundError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { Sandbox } from 'modal';
|
|
2
2
|
|
|
3
|
+
/** A capability this provider lacks: `feature` in dotted form (`files.watchDir`), `provider` type, optional `reason`. */
|
|
4
|
+
declare class SandboxFeatureUnsupportedError extends Error {
|
|
5
|
+
readonly feature: string;
|
|
6
|
+
readonly provider: string;
|
|
7
|
+
readonly reason?: string;
|
|
8
|
+
constructor(feature: string, provider: string, reason?: string);
|
|
9
|
+
}
|
|
10
|
+
/** A path the sandbox does not have — never an empty success. */
|
|
11
|
+
declare class SandboxPathNotFoundError extends Error {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly provider: string;
|
|
14
|
+
constructor(path: string, provider: string);
|
|
15
|
+
}
|
|
16
|
+
/** An inspect refused because the sandbox is not running; `state` is the provider's own word (`paused`, `exited with code 137`). */
|
|
17
|
+
declare class SandboxNotRunningError extends Error {
|
|
18
|
+
readonly sandboxId: string;
|
|
19
|
+
readonly provider: string;
|
|
20
|
+
readonly state: string;
|
|
21
|
+
constructor(sandboxId: string, provider: string, state: string);
|
|
22
|
+
}
|
|
23
|
+
/** True for a SandboxFeatureUnsupportedError from ANY package's copy. */
|
|
24
|
+
declare function isSandboxFeatureUnsupportedError(err: unknown): err is SandboxFeatureUnsupportedError;
|
|
25
|
+
/** True for a SandboxPathNotFoundError from ANY package's copy. */
|
|
26
|
+
declare function isSandboxPathNotFoundError(err: unknown): err is SandboxPathNotFoundError;
|
|
27
|
+
/** True for a SandboxNotRunningError from ANY package's copy. */
|
|
28
|
+
declare function isSandboxNotRunningError(err: unknown): err is SandboxNotRunningError;
|
|
29
|
+
|
|
3
30
|
/**
|
|
4
31
|
* GENERATED — DO NOT EDIT. `npm run generate:image-version` (repo root)
|
|
5
32
|
* rewrites this file from the evolve-all image build inputs under
|
|
@@ -9,7 +36,7 @@ import { Sandbox } from 'modal';
|
|
|
9
36
|
* packages/daytona/tests/unit/daytona-image-version.test.ts fails the
|
|
10
37
|
* suite whenever this checked-in copy is stale.
|
|
11
38
|
*/
|
|
12
|
-
declare const EVOLVE_IMAGE_VERSION = "c-
|
|
39
|
+
declare const EVOLVE_IMAGE_VERSION = "c-4bfce70a407f";
|
|
13
40
|
|
|
14
41
|
/**
|
|
15
42
|
* Modal Sandbox Provider - Clean Architecture
|
|
@@ -25,7 +52,7 @@ declare const EVOLVE_IMAGE_VERSION = "c-880c264ce574";
|
|
|
25
52
|
* - Clear naming (run = blocking, spawn = background)
|
|
26
53
|
*
|
|
27
54
|
* Modal-specific notes:
|
|
28
|
-
* -
|
|
55
|
+
* - File content moves over exec() stdin/stdout; list, stat and watch use the SDK's filesystem API
|
|
29
56
|
* - Named Volumes mount at create (`volumes`, keyed by in-box path, read-only
|
|
30
57
|
* or read-write) — Modal's "upload once, read from many sandboxes" store.
|
|
31
58
|
* modal@0.9.0 has no upload-to-Volume call, so a Volume is filled from
|
|
@@ -206,7 +233,7 @@ interface ResolvedVolumeMount {
|
|
|
206
233
|
declare function mapVolumeMounts(volumes?: Record<string, ModalVolumeMount>): ResolvedVolumeMount[];
|
|
207
234
|
/**
|
|
208
235
|
* Wrap a command with cwd + env handling and (when not root) an
|
|
209
|
-
* `su <user> -c` wrapper.
|
|
236
|
+
* `su <user> -c` wrapper (`--session-command` when the caller must be able to signal it).
|
|
210
237
|
*
|
|
211
238
|
* Modal sandboxes run as root by default (ignoring the Dockerfile USER
|
|
212
239
|
* directive), but Claude CLI and other tools refuse certain operations when
|
|
@@ -219,7 +246,9 @@ declare function mapVolumeMounts(volumes?: Record<string, ModalVolumeMount>): Re
|
|
|
219
246
|
* that contain quotes, special characters, etc. Env vars are inlined because
|
|
220
247
|
* su does not preserve the environment the way `sudo -E` does.
|
|
221
248
|
*/
|
|
222
|
-
declare function wrapCommand(command: string, user: string, cwd?: string, envs?: Record<string, string
|
|
249
|
+
declare function wrapCommand(command: string, user: string, cwd?: string, envs?: Record<string, string>, options?: {
|
|
250
|
+
sameSession?: boolean;
|
|
251
|
+
}): string[];
|
|
223
252
|
/**
|
|
224
253
|
* Typed error for sizing requests Modal's create() cannot enforce.
|
|
225
254
|
* The installed Modal JS SDK sizes cpu (cores) and memoryMiB at create time
|
|
@@ -373,18 +402,27 @@ interface SandboxInfo {
|
|
|
373
402
|
/** End time (undefined for running sandboxes) */
|
|
374
403
|
endAt?: string;
|
|
375
404
|
}
|
|
376
|
-
/**
|
|
405
|
+
/** The SDK contract's FileInfo (sdk-ts types.ts), the same entry on every provider. */
|
|
377
406
|
interface FileInfo {
|
|
378
407
|
name: string;
|
|
379
408
|
path: string;
|
|
380
|
-
type: "file" | "dir";
|
|
409
|
+
type: "file" | "dir" | "symlink" | "other";
|
|
410
|
+
size: number;
|
|
411
|
+
mtime: string;
|
|
412
|
+
mode: string;
|
|
413
|
+
owner: string;
|
|
414
|
+
group: string;
|
|
415
|
+
target?: string;
|
|
416
|
+
}
|
|
417
|
+
/** A byte range of a file (the SDK contract's FileRange). */
|
|
418
|
+
interface FileRange {
|
|
419
|
+
offset: number;
|
|
420
|
+
length: number;
|
|
381
421
|
}
|
|
382
|
-
/**
|
|
422
|
+
/** One filesystem change from watchDir: an absolute path, four kinds. */
|
|
383
423
|
interface FilesystemEvent {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
/** Type of filesystem operation */
|
|
387
|
-
type: "create" | "remove" | "rename" | "chmod" | "write";
|
|
424
|
+
path: string;
|
|
425
|
+
type: "create" | "write" | "remove" | "rename";
|
|
388
426
|
}
|
|
389
427
|
/** Handle to stop watching a directory */
|
|
390
428
|
interface WatchHandle {
|
|
@@ -392,9 +430,21 @@ interface WatchHandle {
|
|
|
392
430
|
}
|
|
393
431
|
/** Options for watching a directory */
|
|
394
432
|
interface WatchOptions {
|
|
433
|
+
/** Also report changes in every subdirectory. Default false. */
|
|
395
434
|
recursive?: boolean;
|
|
396
|
-
|
|
397
|
-
|
|
435
|
+
}
|
|
436
|
+
/** One resource-usage sample (the SDK contract's SandboxMetrics). */
|
|
437
|
+
interface SandboxMetrics {
|
|
438
|
+
cpuPct: number;
|
|
439
|
+
memUsedMb: number;
|
|
440
|
+
memTotalMb: number;
|
|
441
|
+
diskUsedMb?: number;
|
|
442
|
+
sampledAt: string;
|
|
443
|
+
source: string;
|
|
444
|
+
}
|
|
445
|
+
/** Options for an inspect-only attach (the SDK contract's SandboxInspectOptions). */
|
|
446
|
+
interface SandboxInspectOptions {
|
|
447
|
+
user?: string;
|
|
398
448
|
}
|
|
399
449
|
/** Options for blocking sandbox command execution */
|
|
400
450
|
interface SandboxRunOptions {
|
|
@@ -618,6 +668,10 @@ interface SandboxFiles {
|
|
|
618
668
|
remove(path: string): Promise<void>;
|
|
619
669
|
/** Rename or move file/directory */
|
|
620
670
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
671
|
+
/** The entry at `path` itself; a symlink is never followed */
|
|
672
|
+
stat(path: string): Promise<FileInfo>;
|
|
673
|
+
/** Exactly the requested bytes, without moving the whole file when the range is small */
|
|
674
|
+
readRange(path: string, range: FileRange): Promise<Uint8Array>;
|
|
621
675
|
/** Watch directory for changes */
|
|
622
676
|
watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
|
|
623
677
|
}
|
|
@@ -632,6 +686,8 @@ interface SandboxInstance {
|
|
|
632
686
|
isRunning(): Promise<boolean>;
|
|
633
687
|
/** Get sandbox metadata and timing */
|
|
634
688
|
getInfo(): Promise<SandboxInfo>;
|
|
689
|
+
/** Always a typed refusal here: Modal gives a sandbox no honest figures (see ModalSandboxImpl.metrics) */
|
|
690
|
+
metrics(): Promise<SandboxMetrics | null>;
|
|
635
691
|
/** Terminate sandbox */
|
|
636
692
|
kill(): Promise<void>;
|
|
637
693
|
/** Pause sandbox (preserves state) */
|
|
@@ -648,6 +704,8 @@ interface SandboxProvider {
|
|
|
648
704
|
readonly providerType: string;
|
|
649
705
|
/** Human-readable provider name for logging */
|
|
650
706
|
readonly name?: string;
|
|
707
|
+
/** Attach to a RUNNING sandbox for reads; refuses one that has exited */
|
|
708
|
+
inspect(sandboxId: string, options?: SandboxInspectOptions): Promise<SandboxInstance>;
|
|
651
709
|
/**
|
|
652
710
|
* TRUE on every build whose create() maps SandboxCreateOptions.bootCommand
|
|
653
711
|
* to Modal's create args. A consumer whose safety depends on an inert boot
|
|
@@ -781,6 +839,9 @@ declare class ModalFiles implements SandboxFiles {
|
|
|
781
839
|
makeDir(path: string): Promise<void>;
|
|
782
840
|
exists(path: string): Promise<boolean>;
|
|
783
841
|
list(path: string): Promise<FileInfo[]>;
|
|
842
|
+
/** stat describes a symlink itself, never its target (modal index.d.ts). */
|
|
843
|
+
stat(path: string): Promise<FileInfo>;
|
|
844
|
+
readRange(path: string, range: FileRange): Promise<Uint8Array>;
|
|
784
845
|
remove(path: string): Promise<void>;
|
|
785
846
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
786
847
|
readStream(path: string): Promise<ReadableStream<Uint8Array>>;
|
|
@@ -800,7 +861,7 @@ declare class ModalFiles implements SandboxFiles {
|
|
|
800
861
|
writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
|
|
801
862
|
uploadUrl(_path: string, _expiresInSeconds?: number): Promise<string>;
|
|
802
863
|
downloadUrl(_path: string, _expiresInSeconds?: number): Promise<string>;
|
|
803
|
-
watchDir(
|
|
864
|
+
watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
|
|
804
865
|
private toBuffer;
|
|
805
866
|
}
|
|
806
867
|
declare class ModalSandboxImpl implements SandboxInstance {
|
|
@@ -810,6 +871,7 @@ declare class ModalSandboxImpl implements SandboxInstance {
|
|
|
810
871
|
private readonly image?;
|
|
811
872
|
constructor(sandbox: Sandbox, image: string | undefined, user: string);
|
|
812
873
|
get sandboxId(): string;
|
|
874
|
+
metrics(): Promise<SandboxMetrics | null>;
|
|
813
875
|
getHost(port: number): Promise<string>;
|
|
814
876
|
isRunning(): Promise<boolean>;
|
|
815
877
|
getInfo(): Promise<SandboxInfo>;
|
|
@@ -970,6 +1032,9 @@ declare class ModalProvider implements SandboxProvider {
|
|
|
970
1032
|
*/
|
|
971
1033
|
private resolveVolumes;
|
|
972
1034
|
connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
|
|
1035
|
+
inspect(sandboxId: string, options?: SandboxInspectOptions): Promise<SandboxInstance>;
|
|
1036
|
+
/** A read; seam for the unit test. */
|
|
1037
|
+
protected attachSandbox(sandboxId: string): Promise<Sandbox>;
|
|
973
1038
|
/**
|
|
974
1039
|
* List sandboxes, walking the whole app.
|
|
975
1040
|
*
|
|
@@ -1078,5 +1143,7 @@ declare const _testMapVolumeMounts: typeof mapVolumeMounts;
|
|
|
1078
1143
|
* the type (never the constructor) gives the seam the real methods to pin.
|
|
1079
1144
|
*/
|
|
1080
1145
|
type _testModalSandboxImpl = ModalSandboxImpl;
|
|
1146
|
+
/** The constructor, for the metrics-refusal unit test. */
|
|
1147
|
+
declare const _testModalSandboxImplCtor: typeof ModalSandboxImpl;
|
|
1081
1148
|
|
|
1082
|
-
export { EVOLVE_IMAGE_VERSION, type FileInfo, type FilesystemEvent, MODAL_MAX_LIFETIME_MS, MODAL_MAX_LIST_SANDBOXES, MODAL_STDIN_CHUNK_BYTES, ModalBootCommandError, ModalCommands, type ModalConfig, ModalFiles, ModalIdleTimeoutError, ModalNetworkPolicyError, type ModalNetworkPolicyReason, ModalProvider, ModalResourcesError, ModalSandboxLifetimeError, type ModalSandboxStream, ModalVolumeError, type ModalVolumeErrorReason, type ModalVolumeMount, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testBuildSandboxInfo, _testCollectSandboxes, _testDynamicNetworkPolicyParams, _testImageMap, _testMapBootCommand, _testMapIdleTimeout, _testMapNetworkPolicy, _testMapResources, _testMapVolumeMounts, type _testModalSandboxImpl, _testRequiresDynamicNetwork, _testResolveImageRegistry, _testValidateTimeout, _testWrapCommand, createModalProvider };
|
|
1149
|
+
export { EVOLVE_IMAGE_VERSION, type FileInfo, type FileRange, type FilesystemEvent, MODAL_MAX_LIFETIME_MS, MODAL_MAX_LIST_SANDBOXES, MODAL_STDIN_CHUNK_BYTES, ModalBootCommandError, ModalCommands, type ModalConfig, ModalFiles, ModalIdleTimeoutError, ModalNetworkPolicyError, type ModalNetworkPolicyReason, ModalProvider, ModalResourcesError, ModalSandboxLifetimeError, type ModalSandboxStream, ModalVolumeError, type ModalVolumeErrorReason, type ModalVolumeMount, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, SandboxFeatureUnsupportedError, type SandboxFiles, type SandboxInfo, type SandboxInspectOptions, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxMetrics, SandboxNotRunningError, SandboxPathNotFoundError, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testBuildSandboxInfo, _testCollectSandboxes, _testDynamicNetworkPolicyParams, _testImageMap, _testMapBootCommand, _testMapIdleTimeout, _testMapNetworkPolicy, _testMapResources, _testMapVolumeMounts, type _testModalSandboxImpl, _testModalSandboxImplCtor, _testRequiresDynamicNetwork, _testResolveImageRegistry, _testValidateTimeout, _testWrapCommand, createModalProvider, isSandboxFeatureUnsupportedError, isSandboxNotRunningError, isSandboxPathNotFoundError };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {ModalClient,NotFoundError}from'modal';import {pack}from'tar-stream';var
|
|
2
|
-
`).slice(1).map(o=>{let s=o.trim().split(/\s+/);return {processId:s[0],cmd:s[1]||"",args:s.slice(2),envs:{}}})}async connect(e,t){throw new Error("Modal does not support connecting to existing processes")}async sendStdin(e,t){throw new Error("Modal does not support sendStdin by process ID")}async kill(e){return await(await this.sandbox.exec(["kill","-9",e],{timeoutMs:1e4})).wait()===0}async accumulateStreams(e,t,n){let o="",s="",i=[];return i.push((async()=>{try{for await(let a of e.stdout){let d=typeof a=="string"?a:new TextDecoder().decode(a);o+=d,t?.(d);}}catch{}})()),i.push((async()=>{try{for await(let a of e.stderr){let d=typeof a=="string"?a:new TextDecoder().decode(a);s+=d,n?.(d);}}catch{}})()),await Promise.all(i),{stdout:o,stderr:s}}},A=class{constructor(e,t){this.sandbox=e;this.user=t;}async chownToUser(e,t=false){if(this.user==="root")return;let n=t?["chown","-R",`${this.user}:${this.user}`,e]:["chown",`${this.user}:${this.user}`,e];await(await this.sandbox.exec(n,{timeoutMs:t?3e4:1e4})).wait();}async writeStdinChunked(e,t){for(let n=0;n<t.length;n+=g)await e.writeBytes(t.subarray(n,n+g));}async writeStdinCoalesced(e,t){let n=[],o=0,s=async()=>{if(o===0)return;let i=n.length===1?n[0]:Buffer.concat(n,o);n=[],o=0,await this.writeStdinChunked(e,i);};for await(let i of t)n.push(i),o+=i.length,o>=g&&await s();await s();}async read(e){let t=await this.sandbox.exec(["cat",e],{timeoutMs:3e5,mode:"binary"}),n=await t.wait();if(n!==0){let s=await t.stderr.readText();throw new Error(`Failed to read file ${e}: ${s||`exit code ${n}`}`)}let o=await t.stdout.readBytes();if(!o.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(o)}catch{}return o}async write(e,t){let n=this.toBuffer(t),o=e.substring(0,e.lastIndexOf("/"));o&&await this.makeDir(o);let s=e.replace(/'/g,"'\\''"),i=await this.sandbox.exec(["bash","-c",`cat > '${s}'`],{mode:"binary"});await this.writeStdinChunked(i.stdin,new Uint8Array(n)),await i.stdin.getWriter().close(),await i.wait(),await this.chownToUser(e);}async writeBatch(e){let t=pack(),n=new Set;for(let i of e){let a=this.toBuffer(i.data),d=i.path.startsWith("/")?i.path.slice(1):i.path;t.entry({name:d},a);let c=i.path.substring(0,i.path.lastIndexOf("/"));c&&n.add(c);}t.finalize();let o=await this.sandbox.exec(["tar","-xf","-","-C","/"],{mode:"binary"});if(await this.writeStdinCoalesced(o.stdin,t),await o.stdin.getWriter().close(),await o.wait(),n.size>0){let i=Array.from(n),a=new Set(i.map(d=>d.split("/").slice(0,4).join("/")));for(let d of a)await this.chownToUser(d,true);}}async makeDir(e){await(await this.sandbox.exec(["mkdir","-p",e],{timeoutMs:1e4})).wait(),await this.chownToUser(e,true);}async exists(e){return await(await this.sandbox.exec(["test","-e",e],{timeoutMs:1e4})).wait()===0}async list(e){let t=e.replace(/'/g,"'\\''"),n=await this.sandbox.exec(["bash","-c",`ls -la '${t}' | tail -n +2`],{timeoutMs:3e4});await n.wait();let o=await n.stdout.readText(),s=[];for(let i of o.trim().split(`
|
|
3
|
-
|
|
4
|
-
export{p as EVOLVE_IMAGE_VERSION,$ as MODAL_MAX_LIFETIME_MS,O as MODAL_MAX_LIST_SANDBOXES,g as MODAL_STDIN_CHUNK_BYTES,P as ModalBootCommandError,M as ModalCommands,A as ModalFiles,f as ModalIdleTimeoutError,w as ModalNetworkPolicyError,k as ModalProvider,h as ModalResourcesError,v as ModalSandboxLifetimeError,m as ModalVolumeError,ve as _testBuildSandboxInfo,Pe as _testCollectSandboxes,be as _testDynamicNetworkPolicyParams,he as _testImageMap,Ae as _testMapBootCommand,Me as _testMapIdleTimeout,we as _testMapNetworkPolicy,ye as _testMapResources,ke as _testMapVolumeMounts,xe as _testRequiresDynamicNetwork,Se as _testResolveImageRegistry,Ie as _testValidateTimeout,fe as _testWrapCommand,ge as createModalProvider};
|
|
1
|
+
import {ModalClient,NotFoundError}from'modal';import {pack}from'tar-stream';import {constants}from'fs';var l=class extends Error{feature;provider;reason;constructor(e,t,r){super(`${t} does not support ${e}${r?`: ${r}`:""}`),this.name="SandboxFeatureUnsupportedError",this.feature=e,this.provider=t,this.reason=r;}},u=class extends Error{path;provider;constructor(e,t){super(`${t}: no such file or directory: ${e}`),this.name="SandboxPathNotFoundError",this.path=e,this.provider=t;}},w=class extends Error{sandboxId;provider;state;constructor(e,t,r){super(`${t} sandbox ${e} is not running (${r}); inspect never starts or resumes a sandbox`),this.name="SandboxNotRunningError",this.sandboxId=e,this.provider=t,this.state=r;}};function R(n,e){return !!n&&typeof n=="object"&&n.name===e}function ue(n){return R(n,"SandboxFeatureUnsupportedError")}function pe(n){return R(n,"SandboxPathNotFoundError")}function ge(n){return R(n,"SandboxNotRunningError")}var k=2;var _=21;function V(n){return `'${n.replace(/'/g,"'\\''")}'`}function W(n){if(!Number.isInteger(n.offset)||n.offset<0)throw new RangeError(`offset must be a non-negative integer, got ${n.offset}`);if(!Number.isInteger(n.length)||n.length<0)throw new RangeError(`length must be a non-negative integer, got ${n.length}`)}function G(n){if(typeof n=="number")return L((n&4095).toString(8));if(/^[0-7]{1,4}$/.test(n))return L(n);throw new RangeError(`not an octal mode: ${n}`)}function L(n){return n.padStart(4,"0")}function j(n){let e=n&constants.S_IFMT;return e===constants.S_IFDIR?"dir":e===constants.S_IFLNK?"symlink":e===constants.S_IFREG?"file":"other"}function K(n){let e=n instanceof Date?n:typeof n=="number"?new Date(n*1e3):new Date(n);if(Number.isNaN(e.getTime()))throw new RangeError(`not a timestamp: ${String(n)}`);return e.toISOString()}var x="c-4bfce70a407f";var J={[`evolve-all-${x}`]:`evolvingmachines/evolve-all:${x}`,"evolve-all":"evolvingmachines/evolve-all"},Q=1440*60*1e3,y=8*1024*1024;async function*we(n){let e=n.getReader();try{for(;;){let{done:t,value:r}=await e.read();if(t)break;r&&(yield r);}}finally{e.releaseLock();}}var $="user",Z="evolve.image",ee="evolve.startedAt",T=class extends Error{requestedTimeoutMs;constructor(e){let t=(e/36e5).toFixed(1);super(`Modal sandboxes have a hard 24h lifetime cap; requested timeout was ${t}h. For sessions longer than 24h, persist progress with Evolve checkpoints and resume in a fresh sandbox instead of extending the timeout.`),this.name="ModalSandboxLifetimeError",this.requestedTimeoutMs=e;}};function te(n){if(n>Q)throw new T(n)}var S=class extends Error{requestedIdleTimeoutMs;constructor(e,t){super(`Modal idleTimeoutMs of ${e}ms is invalid: ${t}`),this.name="ModalIdleTimeoutError",this.requestedIdleTimeoutMs=e;}};function ne(n){if(n===void 0)return {};if(!Number.isFinite(n)||n<=0)throw new S(n,"it must be a positive number of milliseconds");if(n>Q)throw new S(n,"it exceeds Modal's 24h lifetime cap, so the sandbox would always die of the lifetime first");return {idleTimeoutMs:n}}var N=class extends Error{constructor(e){super(`Modal bootCommand is invalid: ${e}`),this.name="ModalBootCommandError";}};function re(n){if(n===void 0)return {};if(n.length===0)throw new N(`an empty argv is Modal's own "no args" wire shape and would boot the image's ENTRYPOINT/CMD \u2014 omit bootCommand to boot the image's command`);return {command:[...n]}}var f=class extends Error{reason;mountPath;volumeName;constructor(e,t,r,o,s){super(o,s===void 0?void 0:{cause:s}),this.name="ModalVolumeError",this.reason=e,this.mountPath=t,this.volumeName=r;}};function oe(n){if(!n)return [];let e=[];for(let[t,r]of Object.entries(n)){if(!t.startsWith("/")||t==="/")throw new f("invalid-mount-path",t,r.name,`Modal Volume mount path ${JSON.stringify(t)} is invalid: it must be an absolute in-box path other than "/"`);let o=r.name?.trim()??"";if(o.length===0)throw new f("invalid-name",t,r.name??"",`Modal Volume mounted at ${t} has a blank name`);e.push({mountPath:t,name:o,readOnly:r.readOnly===true,createIfMissing:r.createIfMissing===true});}return e}function C(n,e,t,r,o){let s="";r&&Object.keys(r).length>0&&(s=Object.entries(r).filter(([,d])=>d!=null).map(([d,m])=>`export ${d}='${String(m).replace(/'/g,"'\\''")}'`).join("; ")+"; ");let i=t?`cd '${t.replace(/'/g,"'\\''")}' && ${s}${n}`:`${s}${n}`;if(e==="root")return ["bash","-c",i];let a=Buffer.from(i).toString("base64");return ["su",e,o?.sameSession?"--session-command":"-c",`echo ${a} | base64 -d | bash`]}var v=class extends Error{constructor(e){super(e),this.name="ModalResourcesError";}},be=4,xe=4096;function se(n){if(n?.disk!==void 0)throw new v(`Modal's JS SDK has no create-time disk-size parameter, so a ${n.disk} GiB disk request cannot be enforced. Drop \`resources.disk\` (containers get Modal's default disk quota) or run on a provider that sizes disk.`);if((n?.gpu===void 0||n.gpu<=0)&&n?.gpuTypes?.length)throw new v("resources.gpuTypes was set without a positive resources.gpu count \u2014 declare how many GPUs to reserve, or drop gpuTypes.");let e=n?.gpu!==void 0&&n.gpu>0?`${n.gpuTypes?.length?n.gpuTypes[0]:"any"}:${n.gpu}`:void 0;return {cpu:n?.cpu??be,memoryMiB:n?.memory!==void 0?Math.ceil(n.memory*1024):xe,...e!==void 0?{gpu:e}:{}}}var P=class extends Error{reason;destination;constructor(e,t,r){super(t),this.name="ModalNetworkPolicyError",this.reason=e,this.destination=r;}};function ie(n){let e=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(n);return !(!e||[e[1],e[2],e[3],e[4]].some(t=>Number(t)>255)||e[5]!==void 0&&Number(e[5])>32)}function ye(n){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(n)&&!ie(n)}function Se(n){return n.startsWith("[")?true:(n.match(/:/g)?.length??0)>=2}function ve(n){return /^[^:]+:\d+$/.test(n)}function F(n){if(!n||n.outbound==="open"){if(n?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return {}}let e=n.allowedDestinations??[];if(e.length===0)return {blockNetwork:true};let t=[],r=[];for(let o of e)if(ie(o))t.push(o.includes("/")?o:`${o}/32`);else {if(ye(o))throw new P("invalid-ipv4",`"${o}" is not a valid IPv4 address or CIDR (octets must be 0-255, prefix 0-32). Fix the address or list a hostname instead.`,o);if(Se(o))t.push(o.includes("/")?o:`${o}/128`);else {if(ve(o))throw new P("port-unsupported",`Modal's network allowlist filters hosts and IPs only and cannot match a port; drop the ":<port>" from "${o}" and list just the host or IP.`,o);r.push(o);}}return {outboundCidrAllowlist:t,outboundDomainAllowlist:r}}function I(n){if(!n||n.outbound==="open"){if(n?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return {outboundCidrAllowlist:["0.0.0.0/0"],outboundDomainAllowlist:["*"]}}let e=F(n);return {outboundCidrAllowlist:e.outboundCidrAllowlist??[],outboundDomainAllowlist:Ie(e.outboundDomainAllowlist??[])}}var Pe="sealed.invalid";function Ie(n){return n.length>0?n:[Pe]}function ae(n,e){if(!e||e.length===0)return false;let t=o=>o===void 0?"open|":`${o.outbound}|${[...new Set(o.allowedDestinations??[])].sort().join(",")}`,r=t(n);return e.some(o=>t(o)!==r)}function de(n){let e=n.split("/")[0];return /^\d{12}\.dkr\.ecr\.[a-z0-9-]+\.amazonaws\.com$/.test(e)?"aws-ecr":e==="gcr.io"||e.endsWith(".gcr.io")||e.endsWith("-docker.pkg.dev")?"gcp-artifact-registry":"registry"}function B(n,e,t){let{[Z]:r,[ee]:o,...s}=e;return {sandboxId:n,image:r??t??"",metadata:s,startedAt:o??""}}var H=1e4,D=class{constructor(e,t){this.sandbox=e;this.user=t;}async run(e,t){let r=C(e,this.user,t?.cwd,t?.envs),o=await this.sandbox.exec(r,{timeoutMs:t?.timeoutMs}),{stdout:s,stderr:i}=await this.accumulateStreams(o,t?.onStdout,t?.onStderr);return {exitCode:await o.wait(),stdout:s,stderr:i}}async spawn(e,t){let r=t?.stdin===false,o=C(e,this.user,t?.cwd,t?.envs,{sameSession:r}),s=r?["bash","-c",Re,"bash",...o]:o,i=await this.sandbox.exec(s,{timeoutMs:t?.timeoutMs}),a="",d="",m=this.accumulateStreams(i,t?.onStdout?c=>{t.onStdout(c);}:void 0,t?.onStderr?c=>{t.onStderr(c);}:void 0).then(({stdout:c,stderr:h})=>{a=c,d=h;}).catch(()=>{});return {processId:`modal-${Date.now()}-${Math.random().toString(36).slice(2)}`,wait:async()=>(await m,{exitCode:await i.wait(),stdout:a,stderr:d}),kill:async()=>{if(!r)throw new l("commands.kill","modal","the Modal SDK cannot signal a running process; spawn it with `stdin: false` and kill() ends it by closing its stdin");let c=i.stdin.getWriter();try{return await c.close(),!0}catch{return false}}}}async list(){let e=await this.sandbox.exec(["ps","-eo","pid,comm,args"],{timeoutMs:1e4});return await e.wait(),(await e.stdout.readText()).trim().split(`
|
|
2
|
+
`).slice(1).map(o=>{let s=o.trim().split(/\s+/);return {processId:s[0],cmd:s[1]||"",args:s.slice(2),envs:{}}})}async connect(e,t){throw new l("commands.connect","modal","the Modal SDK cannot attach to a process by id")}async sendStdin(e,t){throw new l("commands.sendStdin","modal","the Modal SDK cannot address a process's stdin by id")}async kill(e){return await(await this.sandbox.exec(["kill","-9",e],{timeoutMs:1e4})).wait()===0}async accumulateStreams(e,t,r){let o="",s="",i=[];return i.push((async()=>{try{for await(let a of e.stdout){let d=typeof a=="string"?a:new TextDecoder().decode(a);o+=d,t?.(d);}}catch{}})()),i.push((async()=>{try{for await(let a of e.stderr){let d=typeof a=="string"?a:new TextDecoder().decode(a);s+=d,r?.(d);}}catch{}})()),await Promise.all(i),{stdout:o,stderr:s}}},O=class{constructor(e,t){this.sandbox=e;this.user=t;}async chownToUser(e,t=false){if(this.user==="root")return;let r=t?["chown","-R",`${this.user}:${this.user}`,e]:["chown",`${this.user}:${this.user}`,e];await(await this.sandbox.exec(r,{timeoutMs:t?3e4:1e4})).wait();}async writeStdinChunked(e,t){for(let r=0;r<t.length;r+=y)await e.writeBytes(t.subarray(r,r+y));}async writeStdinCoalesced(e,t){let r=[],o=0,s=async()=>{if(o===0)return;let i=r.length===1?r[0]:Buffer.concat(r,o);r=[],o=0,await this.writeStdinChunked(e,i);};for await(let i of t)r.push(i),o+=i.length,o>=y&&await s();await s();}async read(e){let t=await this.sandbox.exec(["cat",e],{timeoutMs:3e5,mode:"binary"}),r=await t.wait();if(r!==0){let s=await t.stderr.readText();throw new Error(`Failed to read file ${e}: ${s||`exit code ${r}`}`)}let o=await t.stdout.readBytes();if(!o.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(o)}catch{}return o}async write(e,t){let r=this.toBuffer(t),o=e.substring(0,e.lastIndexOf("/"));o&&await this.makeDir(o);let s=e.replace(/'/g,"'\\''"),i=await this.sandbox.exec(["bash","-c",`cat > '${s}'`],{mode:"binary"});await this.writeStdinChunked(i.stdin,new Uint8Array(r)),await i.stdin.getWriter().close(),await i.wait(),await this.chownToUser(e);}async writeBatch(e){let t=pack(),r=new Set;for(let i of e){let a=this.toBuffer(i.data),d=i.path.startsWith("/")?i.path.slice(1):i.path;t.entry({name:d},a);let m=i.path.substring(0,i.path.lastIndexOf("/"));m&&r.add(m);}t.finalize();let o=await this.sandbox.exec(["tar","-xf","-","-C","/"],{mode:"binary"});if(await this.writeStdinCoalesced(o.stdin,t),await o.stdin.getWriter().close(),await o.wait(),r.size>0){let i=Array.from(r),a=new Set(i.map(d=>d.split("/").slice(0,4).join("/")));for(let d of a)await this.chownToUser(d,true);}}async makeDir(e){await(await this.sandbox.exec(["mkdir","-p",e],{timeoutMs:1e4})).wait(),await this.chownToUser(e,true);}async exists(e){return await(await this.sandbox.exec(["test","-e",e],{timeoutMs:1e4})).wait()===0}async list(e){try{return (await this.sandbox.filesystem.listFiles(e)).map(r=>z(r))}catch(t){throw X(t)?new u(e,"modal"):t}}async stat(e){try{return z(await this.sandbox.filesystem.stat(e))}catch(t){throw X(t)?new u(e,"modal"):t}}async readRange(e,t){if(W(t),t.length===0)return new Uint8Array(0);let r=V(e),o=`[ -e ${r} ] || exit ${k}; [ -d ${r} ] && exit ${_}; tail -c +${t.offset+1} -- ${r} | head -c ${t.length}; s=("\${PIPESTATUS[@]}"); [ "\${s[1]}" -eq 0 ] || exit "\${s[1]}"; [ "\${s[0]}" -eq 0 ] || [ "\${s[0]}" -eq ${Ae} ] || exit "\${s[0]}"`,s=await this.sandbox.exec(["bash","-c",o],{mode:"binary",timeoutMs:Y}),i=await s.stdout.readBytes(),a=await s.wait();if(a===k)throw new u(e,"modal");if(a===_)throw new Error(`modal: ${e} is a directory`);if(a!==0){let d=new TextDecoder().decode(await s.stderr.readBytes()).trim();throw new Error(`modal: range read of ${e} failed (exit ${a}): ${d}`)}return i}async remove(e){await(await this.sandbox.exec(["rm","-rf",e],{timeoutMs:3e4})).wait();}async rename(e,t){await(await this.sandbox.exec(["mv",e,t],{timeoutMs:3e4})).wait();}async readStream(e){return (await this.sandbox.exec(["cat",e],{timeoutMs:Y,mode:"binary"})).stdout}async writeStream(e,t){let r=e.substring(0,e.lastIndexOf("/"));r&&await this.makeDir(r);let o=e.replace(/'/g,"'\\''"),s=await this.sandbox.exec(["bash","-c",`cat > '${o}'`],{mode:"binary"});await this.writeStdinCoalesced(s.stdin,we(t)),await s.stdin.getWriter().close(),await s.wait(),await this.chownToUser(e);}async writeFromPath(e,t){let{createReadStream:r}=await import('fs'),{Readable:o}=await import('stream'),s=o.toWeb(r(t,{highWaterMark:y}));await this.writeStream(e,s);}async uploadUrl(e,t){throw new l("files.uploadUrl","modal","Modal issues no signed upload URLs")}async downloadUrl(e,t){throw new l("files.downloadUrl","modal","Modal issues no signed download URLs")}async watchDir(e,t,r){await this.stat(e);let o=this.sandbox.filesystem.watch(e,{recursive:r?.recursive??false,filter:[...Me]})[Symbol.asyncIterator](),s=false;return (async()=>{for(;;){let{done:i,value:a}=await o.next();if(i||s)break;for(let d of Ee(a))await t(d);}})().catch(()=>{}),{stop:async()=>{s=true,o.return?.().catch(()=>{});}}}toBuffer(e){if(typeof e=="string")return Buffer.from(e,"utf-8");if(e instanceof Buffer)return e;if(e instanceof ArrayBuffer||e instanceof Uint8Array)return Buffer.from(e);throw new Error(`Unsupported data type: ${typeof e}`)}};function z(n){let e=j(n.mode),t={name:n.name,path:n.path,type:e,size:n.size,mtime:K(n.modifiedTime),mode:G(n.permissions),owner:n.owner,group:n.group};return e==="symlink"&&n.symlinkTarget!==null&&(t.target=n.symlinkTarget),t}function X(n){return !!n&&typeof n=="object"&&n.name==="SandboxFilesystemNotFoundError"}var Me=["Create","Modify","Remove"];function Ee(n){if(n.eventType==="Create")return n.paths.map(e=>({path:e,type:"create"}));if(n.eventType==="Remove")return n.paths.map(e=>({path:e,type:"remove"}));if(n.eventType==="Modify"){let e=n.paths.length>=2?"rename":"write";return n.paths.map(t=>({path:t,type:e}))}return []}var Ae=141,Y=3e5,Re=["set -m","exec 3<&0",'"$@" </dev/null 3<&- & job=$!',"( cat <&3 >/dev/null; kill -TERM -- -$job 2>/dev/null ) & eof=$!","exec 2>/dev/null","trap 'kill -TERM -- -$job' TERM","wait $job; rc=$?","kill -TERM -- -$eof","exit $rc"].join("; "),p=class{constructor(e,t,r){this.sandbox=e;this.commands=new D(e,r),this.files=new O(e,r),this.image=t;}commands;files;image;get sandboxId(){return this.sandbox.sandboxId}async metrics(){throw new l("metrics","modal","Modal has no sandbox metrics API, and /proc and the cgroup files inside its sandbox report host-wide figures (measured 2026-09-16: MemTotal 1 TiB on a 1 GiB sandbox)")}async getHost(e){let r=(await this.sandbox.tunnels())[e];if(!r)throw new Error(`No tunnel found for port ${e}`);return r.url}async isRunning(){try{return await this.sandbox.poll()===null}catch{return false}}async getInfo(){let e=await this.sandbox.getTags();return B(this.sandbox.sandboxId,e,this.image)}async updateNetwork(e){await this.sandbox.updateNetworkPolicy(I(e));}async kill(){try{await this.sandbox.terminate();}catch{await new Promise(e=>setTimeout(e,500)),await this.sandbox.terminate();}}async pause(){throw new Error("Modal does not support pause/resume. Persist progress with Evolve checkpoints and resume in a fresh sandbox, or use kill() to terminate.")}},U=class{providerType="modal";name="Modal";supportsBootCommand=true;supportsVolumes=true;client;appName;defaultTimeoutMs;imageName;imageSecretName;_app;sandboxUsers=new Map;constructor(e){!e.endpoint&&process.env.MODAL_SERVER_URL?.startsWith("unix:")?process.env.MODAL_SERVER_URL="https://api.modal.com:443":e.endpoint&&(process.env.MODAL_SERVER_URL=e.endpoint),this.client=new ModalClient({tokenId:e.tokenId,tokenSecret:e.tokenSecret}),this.appName=e.appName??"evolve-sandbox",this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.imageName=e.imageName??`evolve-all-${x}`,this.imageSecretName=e.imageSecretName;}async getApp(){return this._app||(this._app=await this.client.apps.fromName(this.appName,{createIfMissing:true})),this._app}async resolveImage(e){let t=de(e);if(t==="registry"){let o=this.imageSecretName?await this.client.secrets.fromName(this.imageSecretName):void 0;return this.client.images.fromRegistry(e,o)}if(!this.imageSecretName)throw new Error(`Private registry image "${e}" requires config.imageSecretName \u2014 the name of a Modal Secret holding registry credentials (AWS ECR: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION with read-only ECR IAM). Create one at https://modal.com/secrets`);let r=t==="aws-ecr"?await this.client.secrets.fromName(this.imageSecretName,{requiredKeys:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]}):await this.client.secrets.fromName(this.imageSecretName);return t==="aws-ecr"?this.client.images.fromAwsEcr(e,r):this.client.images.fromGcpArtifactRegistry(e,r)}async resolveAndBuildImage(e){let t=J[e]??e;if(!/[/:@]/.test(t))try{return {tag:t,image:await this.client.images.fromName(t)}}catch(s){if(!(s instanceof NotFoundError))throw s}let r=await this.getApp(),o=await this.resolveImage(t);return {tag:t,image:await o.build(r)}}async publishImageAs(e,t){if(!e.trim())throw new Error("publishImageAs requires a non-empty alias to publish under");let{image:r}=await this.resolveAndBuildImage(t||this.imageName);return await r.publish(e),e}async prepareImage(e){await this.resolveAndBuildImage(e||this.imageName);}async create(e){let t=e.timeoutMs??this.defaultTimeoutMs;te(t);let r=ne(e.idleTimeoutMs),o=re(e.bootCommand),s=oe(e.volumes);for(let g of e.phaseNetworkPolicies??[])I(g);let i=ae(e.network,e.phaseNetworkPolicies)?I(e.network):F(e.network),a=se(e.resources),d=e.user??$,m=await this.getApp(),{tag:M,image:c}=await this.resolveAndBuildImage(e.image||this.imageName),h=await this.resolveVolumes(s),E=e.envs?Object.fromEntries(Object.entries(e.envs).filter(([,g])=>g!=null)):void 0,le=E&&Object.keys(E).length>0?E:void 0,me={...e.metadata,[Z]:M,[ee]:new Date().toISOString()},A=await this.client.sandboxes.create(m,c,{cpu:a.cpu,memoryMiB:a.memoryMiB,...a.gpu!==void 0?{gpu:a.gpu}:{},timeoutMs:t,...r,...o,workdir:e.workingDirectory,env:le,tags:me,...i,...h!==void 0?{volumes:h}:{}});return e.workingDirectory&&d!=="root"&&await(await A.exec(["chown","-R",`${d}:${d}`,e.workingDirectory],{timeoutMs:3e4})).wait(),this.sandboxUsers.set(A.sandboxId,d),new p(A,M,d)}async resolveVolumes(e){if(e.length===0)return;let t={};for(let r of e){let o;try{o=await this.client.volumes.fromName(r.name,{createIfMissing:r.createIfMissing});}catch(s){let i=s instanceof Error?s.message:String(s),a=s instanceof NotFoundError||s instanceof Error&&s.name==="NotFoundError";throw new f(a?"not-found":"resolve-failed",r.mountPath,r.name,a?`Modal Volume "${r.name}" (to mount at ${r.mountPath}) does not exist and createIfMissing was not set: ${i}`:`Modal Volume "${r.name}" (to mount at ${r.mountPath}) could not be resolved: ${i}`,s)}t[r.mountPath]=o.withMountOptions({readOnly:r.readOnly});}return t}async connect(e,t){let r=await this.client.sandboxes.fromId(e),o=this.sandboxUsers.get(e)??$;return new p(r,void 0,o)}async inspect(e,t){let r=await this.attachSandbox(e),o=await r.poll();if(o!==null)throw new w(e,"modal",`exited with code ${o}`);let s=t?.user??this.sandboxUsers.get(e)??$;return new p(r,void 0,s)}async attachSandbox(e){return this.client.sandboxes.fromId(e)}async list(e){let t=await this.walk(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...r}=await this.walk(e);return r}async walk(e){if(e?.state&&!e.state.includes("running"))return {sandboxes:[],complete:true,pagesFetched:0,stoppedAtLimit:false};let t;try{t=await this.getApp();}catch(r){return {sandboxes:[],complete:false,pagesFetched:0,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return ce(()=>this.client.sandboxes.list({appId:t.appId,tags:e?.metadata}),e?.limit)}async listSandboxIds(){let e=new Set;try{let t=await this.getApp();for await(let r of this.client.sandboxes.list({appId:t.appId}))e.add(r.sandboxId);return {ids:e,complete:!0}}catch{return {ids:new Set,complete:false}}}};async function ce(n,e){let t=[];try{for await(let r of n()){if(e!==void 0&&t.length>=e)return {sandboxes:t,complete:!1,pagesFetched:t.length,stoppedAtLimit:!0,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(t.length>=H)return {sandboxes:t,complete:!1,pagesFetched:t.length,stoppedAtLimit:!1,error:`sandbox list exceeded ${H} sandboxes`};let o=await r.getTags();t.push(B(r.sandboxId,o));}}catch(r){return {sandboxes:t,complete:false,pagesFetched:t.length,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return {sandboxes:t,complete:true,pagesFetched:t.length,stoppedAtLimit:false}}function Ge(n={}){let e=n.tokenId??process.env.MODAL_TOKEN_ID,t=n.tokenSecret??process.env.MODAL_TOKEN_SECRET;if(!e||!t)throw new Error("Modal credentials required. Set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables, or pass tokenId/tokenSecret in config. Get your token at https://modal.com/settings/tokens");return new U({...n,tokenId:e,tokenSecret:t})}var je=C,Ke=J,qe=F,He=I,ze=ae,Xe=se,Ye=de,Je=B,Qe=ce,Ze=te,et=ne,tt=re,nt=oe,rt=p;
|
|
3
|
+
export{x as EVOLVE_IMAGE_VERSION,Q as MODAL_MAX_LIFETIME_MS,H as MODAL_MAX_LIST_SANDBOXES,y as MODAL_STDIN_CHUNK_BYTES,N as ModalBootCommandError,D as ModalCommands,O as ModalFiles,S as ModalIdleTimeoutError,P as ModalNetworkPolicyError,U as ModalProvider,v as ModalResourcesError,T as ModalSandboxLifetimeError,f as ModalVolumeError,l as SandboxFeatureUnsupportedError,w as SandboxNotRunningError,u as SandboxPathNotFoundError,Je as _testBuildSandboxInfo,Qe as _testCollectSandboxes,He as _testDynamicNetworkPolicyParams,Ke as _testImageMap,tt as _testMapBootCommand,et as _testMapIdleTimeout,qe as _testMapNetworkPolicy,Xe as _testMapResources,nt as _testMapVolumeMounts,rt as _testModalSandboxImplCtor,ze as _testRequiresDynamicNetwork,Ye as _testResolveImageRegistry,Ze as _testValidateTimeout,je as _testWrapCommand,Ge as createModalProvider,ue as isSandboxFeatureUnsupportedError,ge as isSandboxNotRunningError,pe as isSandboxPathNotFoundError};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolvingmachines/modal",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.61",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"ai",
|
|
6
6
|
"agents",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"build": "tsup --minify",
|
|
35
35
|
"dev": "tsup --watch",
|
|
36
36
|
"type-check": "tsc --noEmit",
|
|
37
|
-
"test:unit": "tsx tests/unit/modal-provider.test.ts && tsx tests/unit/modal-list-pagination.test.ts"
|
|
37
|
+
"test:unit": "tsx tests/unit/modal-provider.test.ts && tsx tests/unit/modal-list-pagination.test.ts && tsx tests/unit/modal-files-observe.test.ts"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"modal": "^0.9.0",
|