@evolvingmachines/daytona 0.0.50 → 0.0.52-project-sable.20260726.6e95f36

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 CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var sdk=require('@daytonaio/sdk');var h={"evolve-all":"evolvingmachines/evolve-all"},S=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function w(r){let e=r.substring(r.lastIndexOf(".")).toLowerCase();return S.has(e)}function v(r){let e=r.lastIndexOf("/");return e>0?r.substring(0,e):"/"}function P(r){let e=r.lastIndexOf("/");return e>=0?r.substring(e+1):r}function g(r,e,t){let s=r;return e&&(s=`cd '${e.replace(/'/g,"'\\''")}' && ${s}`),t&&Object.keys(t).length>0&&(s=`${Object.entries(t).filter(([,a])=>a!=null).map(([a,o])=>`export ${a}='${o.replace(/'/g,"'\\''")}'`).join("; ")}; ${s}`),s}var C=g,f=class{constructor(e){this.sandbox=e;}async run(e,t){let s=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,n=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);try{let a=await this.sandbox.process.executeSessionCommand(n,{command:g(e,t?.cwd,t?.envs),runAsync:!1},s),o=a.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.sandbox.process.getSessionCommandLogs(n,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let d=a.stdout??a.output??"",i=a.stderr??"";if(!d&&o&&!t?.onStdout)try{let m=await this.sandbox.process.getSessionCommandLogs(n,o);d=m.stdout??m.output??"",i=m.stderr??i;}catch{}return {exitCode:a.exitCode??0,stdout:d,stderr:i}}finally{try{await this.sandbox.process.deleteSession(n);}catch{}}}async spawn(e,t){let s=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(s);let n=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,a=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(s,{command:g(e,t?.cwd,t?.envs),runAsync:true},n)).cmdId;i&&(t?.onStdout||t?.onStderr)&&this.sandbox.process.getSessionCommandLogs(s,i,t.onStdout||(()=>{}),t.onStderr||(()=>{})).catch(()=>{});let m=this.sandbox;return {processId:s,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-a>=o){try{await m.process.deleteSession(s);}catch{}return {exitCode:-1,stdout:"",stderr:"operation timed out"}}try{let c=await m.process.getSessionCommand(s,i);if(c.exitCode!==void 0)try{let l=await m.process.getSessionCommandLogs(s,i);return {exitCode:c.exitCode,stdout:l.stdout??l.output??"",stderr:l.stderr??""}}catch{return {exitCode:c.exitCode,stdout:"",stderr:""}}}catch(c){if((c instanceof Error?c.message.toLowerCase():String(c).toLowerCase()).includes("not found"))return {exitCode:-1,stdout:"",stderr:"session terminated"};throw c}await new Promise(c=>setTimeout(c,500));}},kill:async()=>{try{return await m.process.deleteSession(s),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(t=>({processId:t.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(e){try{return await this.sandbox.process.deleteSession(e),!0}catch{return false}}},p=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return w(e)?new Uint8Array(t):t.toString("utf-8")}async write(e,t){let s;if(typeof t=="string")s=Buffer.from(t,"utf-8");else if(Buffer.isBuffer(t))s=t;else if(t instanceof ArrayBuffer)s=Buffer.from(t);else if(t instanceof Uint8Array)s=Buffer.from(t);else throw new Error(`Unsupported content type: ${typeof t}`);await this.sandbox.fs.uploadFile(s,e);}async writeBatch(e){let t=e.map(s=>{let n;if(typeof s.data=="string")n=Buffer.from(s.data,"utf-8");else if(Buffer.isBuffer(s.data))n=s.data;else if(s.data instanceof ArrayBuffer)n=Buffer.from(s.data);else if(s.data instanceof Uint8Array)n=Buffer.from(s.data);else throw new Error(`Unsupported content type: ${typeof s.data}`);return {source:n,destination:s.path}});await this.sandbox.fs.uploadFiles(t);}async makeDir(e){await this.sandbox.fs.createFolder(e,"755");}async exists(e){try{let t=v(e),s=P(e);return (await this.sandbox.fs.listFiles(t)).some(a=>a.name===s)}catch{return false}}async list(e){return (await this.sandbox.fs.listFiles(e)).map(s=>({name:s.name,path:e.endsWith("/")?`${e}${s.name}`:`${e}/${s.name}`,type:s.isDir?"dir":"file"}))}async remove(e){await this.sandbox.fs.deleteFile(e,true);}async rename(e,t){await this.sandbox.fs.moveFiles(e,t);}},u=class{constructor(e){this.sandbox=e;this.commands=new f(e),this.files=new p(e);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(e){return (await this.sandbox.getPreviewLink(e)).url}async isRunning(){return this.sandbox.state==="started"}async getInfo(){return {sandboxId:this.sandbox.id,image:this.sandbox.snapshot||"unknown",name:this.sandbox.name,metadata:this.sandbox.labels||{},startedAt:new Date().toISOString()}}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},x=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;constructor(e){this.client=new sdk.Daytona({apiKey:e.apiKey,apiUrl:e.apiUrl,target:e.target}),this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.snapshotName=e.snapshotName??"evolve-all";}async create(e){let t=e.timeoutMs??this.defaultTimeoutMs,s=Math.max(1,Math.ceil(t/6e4)),n=e.image||this.snapshotName,a;try{let o=await this.client.snapshot.get(n);if(o&&o.state==="active")console.log(`[daytona] Using cached snapshot: ${n}`),a=await this.client.create({snapshot:n,envVars:e.envs,labels:e.metadata,autoStopInterval:s},{timeout:600});else throw new Error("Snapshot not active")}catch{let o=h[n]??n;console.log(`[daytona] Snapshot "${n}" not found, building from image: ${o}`),console.log("[daytona] First run will take a few minutes (this only happens once)...");try{await this.client.snapshot.create({name:n,image:sdk.Image.base(o),resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{onLogs:d=>console.log(`[daytona] ${d}`)}),console.log(`[daytona] Snapshot "${n}" ready.`),a=await this.client.create({snapshot:n,envVars:e.envs,labels:e.metadata,autoStopInterval:s},{timeout:600});}catch(d){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${d instanceof Error?d.message:d}`),a=await this.client.create({image:o,envVars:e.envs,labels:e.metadata,autoStopInterval:s,resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{timeout:600,onSnapshotCreateLogs:i=>console.log(`[daytona] ${i}`)});}}return e.workingDirectory&&await a.fs.createFolder(e.workingDirectory,"755"),new u(a)}async connect(e,t){let s=await this.client.get(e);return s.state!=="started"&&await s.start(),new u(s)}async list(e){let t=e?.limit??100;return (await this.client.list(e?.metadata,1,t)).items.map(n=>({sandboxId:n.id,image:n.snapshot||"unknown",name:n.name,metadata:n.labels||{},startedAt:new Date().toISOString()}))}};function A(r={}){let e=r.apiKey??process.env.DAYTONA_API_KEY;if(!e)throw new Error("Daytona API key required. Set DAYTONA_API_KEY environment variable or pass apiKey in config. Get your key at https://app.daytona.io/dashboard/keys");return new x({...r,apiKey:e})}
2
- exports.DaytonaProvider=x;exports._testWrapCommand=C;exports.createDaytonaProvider=A;
1
+ 'use strict';var sdk=require('@daytonaio/sdk'),promises=require('dns/promises');var F={"evolve-all":"evolvingmachines/evolve-all"},K=10,A=10,H=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function j(s){let e=s.substring(s.lastIndexOf(".")).toLowerCase();return H.has(e)}function z(s){let e=s.lastIndexOf("/");return e>0?s.substring(0,e):"/"}function Y(s){let e=s.lastIndexOf("/");return e>=0?s.substring(e+1):s}var f=class extends Error{reason;destination;constructor(e,t,n){super(t),this.name="DaytonaNetworkPolicyError",this.reason=e,this.destination=n;}},b=class extends Error{image;constructor(e,t){let n=t instanceof Error?t.message:String(t??"unknown error");super(`Failed to pull image "${e}" on Daytona: ${n}. Private registry images (e.g. AWS ECR) require registry credentials pre-registered in the Daytona dashboard (Registries page) before sandbox creation \u2014 Daytona has no per-call image pull secret. Register the registry at https://app.daytona.io, then retry. Also ensure the image is linux/amd64 and pinned to a tag or digest (floating tags like "latest" are rejected by Daytona's snapshot builder).`),this.name="DaytonaImagePullError",this.image=e;}},h=class extends Error{snapshot;constructor(e){super(`Daytona snapshot "${e}" already exists and pins its cpu/memory/disk sizing \u2014 create-from-snapshot cannot resize it, so the requested \`resources\` cannot be enforced. Pre-build a snapshot with the desired sizing under its own name (sizing-addressed), or omit \`resources\` to accept the snapshot's pinned sizing.`),this.name="DaytonaResourcesError",this.snapshot=e;}};function q(s,e){if(!e||e<=0)return s;let t=Buffer.from(s).toString("base64"),n=`/tmp/.evolve-cmd-${Date.now()}-${Math.random().toString(36).slice(2,8)}.sh`;return `sh -c '${`echo ${t} | base64 -d > ${n}; if command -v timeout >/dev/null 2>&1; then timeout -k 10 ${e} bash ${n}; else bash ${n}; fi; rc=$?; rm -f ${n}; exit $rc`}'`}function x(s,e,t,n){let r=s;return e&&(r=`cd '${e.replace(/'/g,"'\\''")}' && ${r}`),t&&Object.keys(t).length>0&&(r=`${Object.entries(t).filter(([,o])=>o!=null).map(([o,a])=>`export ${o}='${String(a).replace(/'/g,"'\\''")}'`).join("; ")}; ${r}`),n==="root"&&(r=`echo ${Buffer.from(r).toString("base64")} | base64 -d | sudo -n bash`),r}var W=s=>promises.resolve4(s);function U(s){let e=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(s);return !(!e||[e[1],e[2],e[3],e[4]].some(t=>Number(t)>255)||e[5]!==void 0&&Number(e[5])>32)}function X(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!U(s)}function G(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function V(s){return /^[^:]+:\d+$/.test(s)}async function M(s,e=W){if(!s||s.outbound==="open"){if(s?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return s?{networkBlockAll:false}:{}}let t=s.allowedDestinations??[];if(t.length===0)return {networkBlockAll:true};let n=[],r=[];for(let o of t)if(U(o))n.push(o.includes("/")?o:`${o}/32`);else {if(X(o))throw new f("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(G(o))throw new f("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${o}".`,o);if(V(o))throw new f("port-unsupported",`Daytona'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);if(o.includes("*"))throw new f("wildcard-hostname",`Daytona cannot enforce wildcard hostname "${o}": its allowlist is kernel-level IPv4 CIDR filtering with no DNS/domain layer. List concrete hostnames or IPv4 CIDRs instead.`,o);r.push(o);}for(let o of r){let a=[];try{a=await e(o);}catch(i){throw new f("unresolvable-hostname",`Cannot pin hostname "${o}" to stable IPv4 addresses at create time (${i instanceof Error?i.message:String(i)}). Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,o)}if(a.length===0)throw new f("unresolvable-hostname",`Hostname "${o}" resolved to no IPv4 addresses. Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,o);console.warn(`[daytona] Network allowlist: pinning "${o}" to [${a.join(", ")}] (DNS resolved at create time). Daytona enforces IPv4 CIDRs only \u2014 if this host rotates DNS (CDNs and cloud APIs often do), traffic to its new IPs will be BLOCKED for the sandbox's lifetime.`);for(let i of a)n.push(`${i}/32`);}let d=[...new Set(n)];if(d.length>A)throw new f("allowlist-too-large",`Daytona allows at most ${A} entries in its network allowlist; this policy resolved to ${d.length} CIDRs (${d.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:d.join(",")}}function B(s){let e=s.indexOf("/");if(e<0)return;let t=s.substring(0,e);return t.includes(".")||t.includes(":")||t==="localhost"?t:void 0}function D(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function T(s){if(s==="started")return "running";if(s==="stopped"||s==="archived")return "paused"}var S=class extends sdk.Daytona{constructor(t,n){super(t);this.managedToolboxUrl=n;}async getProxyToolboxUrl(){return this.managedToolboxUrl}};function J(s,e){let t=new Uint8Array(new ArrayBuffer(s.length+e.length));return t.set(s,0),t.set(e,s.length),t}function $(s,e,t){e:for(let n=t;n+e.length<=s.length;n++){for(let r=0;r<e.length;r++)if(s[n+r]!==e[r])continue e;return n}return -1}function E(s,e){let t=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),r=new Uint8Array(0),d="stdout",o=a=>{a.length!==0&&(d==="stdout"?s(t.decode(a,{stream:true})):e(n.decode(a,{stream:true})));};return {push(a){for(r=J(r,a);;){let i=$(r,sdk.STDOUT_PREFIX_BYTES,0),c=$(r,sdk.STDERR_PREFIX_BYTES,0),l=-1,u="stdout",m=0;if(i!==-1&&(c===-1||i<c)?(l=i,u="stdout",m=sdk.STDOUT_PREFIX_BYTES.length):c!==-1&&(l=c,u="stderr",m=sdk.STDERR_PREFIX_BYTES.length),l===-1){let g=Math.max(0,r.length-(sdk.MAX_PREFIX_LEN-1));o(r.subarray(0,g)),r=r.slice(g);return}o(r.subarray(0,l)),d=u,r=r.slice(l+m);}},flush(){o(r),r=new Uint8Array(0);let a=t.decode();a&&s(a);let i=n.decode();i&&e(i);}}}async function L(s,e,t,n,r,d){let o=`${s.toolboxUrl.replace(/\/+$/,"")}/${encodeURIComponent(e)}/process/session/${encodeURIComponent(t)}/command/${encodeURIComponent(n)}/logs?follow=true`,a=await fetch(o,{headers:{Authorization:`Bearer ${s.apiKey}`,accept:"application/octet-stream"}});if(!a.ok)throw new Error(`Daytona managed log follow failed: ${a.status} ${await a.text()}`);if(!a.body)return;let i=E(r,d),c=a.body.getReader();try{for(;;){let{done:l,value:u}=await c.read();if(l)break;u&&i.push(u);}}finally{i.flush(),await c.cancel().catch(()=>{});}}function w(s){let e=s.stdout||"",t=s.stderr||"",n=s.output||"";return !e&&!t&&n?{stdout:n,stderr:""}:{stdout:e,stderr:t}}var v=class{constructor(e,t,n){this.sandbox=e;this.user=t;this.managedStream=n;}followLogs(e,t,n,r){return this.managedStream?L(this.managedStream,this.sandbox.id,e,t,n,r):this.sandbox.process.getSessionCommandLogs(e,t,n,r)}async run(e,t){let n=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,r=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(r);try{let d=await this.sandbox.process.executeSessionCommand(r,{command:x(e,t?.cwd,t?.envs,this.user),runAsync:!1},n),o=d.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.followLogs(r,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let{stdout:a,stderr:i}=w(d);if(!a&&!i&&o&&!t?.onStdout)try{let c=await this.sandbox.process.getSessionCommandLogs(r,o),l=w(c);a=l.stdout,i=l.stderr||i;}catch{}return {exitCode:d.exitCode??0,stdout:a,stderr:i}}finally{try{await this.sandbox.process.deleteSession(r);}catch{}}}async spawn(e,t){let n=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);let r=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,d=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(n,{command:q(x(e,t?.cwd,t?.envs,this.user),r),runAsync:true},r)).cmdId;i&&(t?.onStdout||t?.onStderr)&&this.followLogs(n,i,t.onStdout||(()=>{}),t.onStderr||(()=>{})).catch(()=>{});let c=this.sandbox;return {processId:n,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-d>=o){try{await c.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let l=await c.process.getSessionCommand(n,i);if(l.exitCode!==void 0)try{let u=await c.process.getSessionCommandLogs(n,i);return {exitCode:l.exitCode,...w(u)}}catch{return {exitCode:l.exitCode,stdout:"",stderr:""}}}catch(l){let u=l instanceof Error?l.message.toLowerCase():String(l).toLowerCase();if(u.includes("not found")){let m=u.includes("sandbox");try{await c.refreshData(),m=!1;}catch(g){(g instanceof Error?g.message.toLowerCase():String(g).toLowerCase()).includes("not found")&&(m=true);}return {exitCode:-1,stdout:"",stderr:m?"sandbox deleted during run":"session terminated"}}throw l}await new Promise(l=>setTimeout(l,500));}},kill:async()=>{try{return await c.process.deleteSession(n),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(t=>({processId:t.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(e){try{return await this.sandbox.process.deleteSession(e),!0}catch{return false}}},P=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return j(e)?new Uint8Array(t):t.toString("utf-8")}async write(e,t){let n;if(typeof t=="string")n=Buffer.from(t,"utf-8");else if(Buffer.isBuffer(t))n=t;else if(t instanceof ArrayBuffer)n=Buffer.from(t);else if(t instanceof Uint8Array)n=Buffer.from(t);else throw new Error(`Unsupported content type: ${typeof t}`);await this.sandbox.fs.uploadFile(n,e);}async writeBatch(e){let t=e.map(n=>{let r;if(typeof n.data=="string")r=Buffer.from(n.data,"utf-8");else if(Buffer.isBuffer(n.data))r=n.data;else if(n.data instanceof ArrayBuffer)r=Buffer.from(n.data);else if(n.data instanceof Uint8Array)r=Buffer.from(n.data);else throw new Error(`Unsupported content type: ${typeof n.data}`);return {source:r,destination:n.path}});await this.sandbox.fs.uploadFiles(t);}async writeFromPath(e,t){await this.sandbox.fs.uploadFile(t,e);}async makeDir(e){await this.sandbox.fs.createFolder(e,"755");}async exists(e){try{let t=z(e),n=Y(e);return (await this.sandbox.fs.listFiles(t)).some(d=>d.name===n)}catch{return false}}async list(e){return (await this.sandbox.fs.listFiles(e)).map(n=>({name:n.name,path:e.endsWith("/")?`${e}${n.name}`:`${e}/${n.name}`,type:n.isDir?"dir":"file"}))}async remove(e){await this.sandbox.fs.deleteFile(e,true);}async rename(e,t){await this.sandbox.fs.moveFiles(e,t);}},y=class{constructor(e,t,n){this.sandbox=e;this.commands=new v(e,t,n),this.files=new P(e);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(e){return (await this.sandbox.getPreviewLink(e)).url}async isRunning(){try{await this.sandbox.refreshData();}catch{return false}return this.sandbox.state==="started"}async getInfo(){return await this.sandbox.refreshData(),D(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},I=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;sandboxUsers=new Map;managedStream;constructor(e){let t={apiKey:e.apiKey,apiUrl:e.apiUrl,target:e.target};this.client=e.managedToolboxUrl?new S(t,e.managedToolboxUrl):new sdk.Daytona(t),e.managedToolboxUrl&&(this.managedStream={toolboxUrl:e.managedToolboxUrl,apiKey:e.apiKey}),this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.snapshotName=e.snapshotName??"evolve-all";}async create(e){let t=await M(e.network),n=e.user,r=n&&n!=="root"?n:void 0,d=e.timeoutMs??this.defaultTimeoutMs,o=Math.max(1,Math.ceil(d/6e4)),a=e.image||this.snapshotName,i={envVars:e.envs,labels:e.metadata,autoStopInterval:o,autoDeleteInterval:K,...r?{user:r}:{},...t},c,l=e.resources!==void 0&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0);if(this.managedStream){if(l)throw new h(a);let u=await this.client.create({snapshot:a,...i},{timeout:600});return e.workingDirectory&&await u.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(u.id,n),new y(u,n,this.managedStream)}try{let u=await this.client.snapshot.get(a);if(u&&u.state==="active"){if(l)throw new h(a);console.log(`[daytona] Using cached snapshot: ${a}`),c=await this.client.create({snapshot:a,...i},{timeout:600});}else throw new Error("Snapshot not active")}catch(u){if(u instanceof h)throw u;let m=F[a]??a;console.log(`[daytona] Snapshot "${a}" not found, building from image: ${m}`),console.log("[daytona] First run will take a few minutes (this only happens once)...");try{await this.client.snapshot.create({name:a,image:sdk.Image.base(m),resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{onLogs:g=>console.log(`[daytona] ${g}`)}),console.log(`[daytona] Snapshot "${a}" ready.`),c=await this.client.create({snapshot:a,...i},{timeout:600});}catch(g){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${g instanceof Error?g.message:g}`);try{c=await this.client.create({image:m,...i,resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{timeout:600,onSnapshotCreateLogs:p=>console.log(`[daytona] ${p}`)});}catch(p){throw B(m)?new b(m,p):p}}}return e.workingDirectory&&await c.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(c.id,n),new y(c,n,this.managedStream)}async connect(e,t){let n=await this.client.get(e);return n.state!=="started"&&await n.start(),new y(n,this.sandboxUsers.get(e),this.managedStream)}async list(e){let t=e?.limit??100,r=(await this.client.list(e?.metadata,1,t)).items;return e?.state&&(r=r.filter(d=>{let o=T(d.state);return o!==void 0&&e.state.includes(o)})),r.map(D)}};function ee(s={}){let e=s.apiKey??process.env.DAYTONA_API_KEY;if(!e)throw new Error("Daytona API key required. Set DAYTONA_API_KEY environment variable or pass apiKey in config. Get your key at https://app.daytona.io/dashboard/keys");return new I({...s,apiKey:e})}var te=x,ne=M,se=B,re=D,oe=T,ae=E,ie=L,de=w;
2
+ exports.DAYTONA_AUTO_DELETE_GRACE_MINUTES=K;exports.DAYTONA_MAX_NETWORK_ALLOWLIST=A;exports.DaytonaCommands=v;exports.DaytonaFiles=P;exports.DaytonaImagePullError=b;exports.DaytonaNetworkPolicyError=f;exports.DaytonaProvider=I;exports.DaytonaResourcesError=h;exports._testCreateLogDemuxer=ae;exports._testDaytonaStateToEvolveState=oe;exports._testFollowManagedSessionLogs=ie;exports._testImageRegistryHost=se;exports._testMapNetworkPolicy=ne;exports._testReadCommandStreams=de;exports._testToSandboxInfo=re;exports._testWrapCommand=te;exports.createDaytonaProvider=ee;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Sandbox } from '@daytonaio/sdk';
2
+
1
3
  /**
2
4
  * Daytona Sandbox Provider
3
5
  *
@@ -7,17 +9,140 @@
7
9
  * - Mirror E2B provider interface for SDK compatibility
8
10
  * - Uses public Docker images via IMAGE_MAP
9
11
  * - Parallel structure to E2B provider
12
+ *
13
+ * Daytona-specific notes:
14
+ * - Network policy maps to Daytona's networkBlockAll / networkAllowList,
15
+ * enforced by kernel iptables on the runner. The allowlist is IPv4 CIDR
16
+ * ONLY (max 10 entries, DAYTONA_MAX_NETWORK_ALLOWLIST). Hostname
17
+ * destinations are pinned to their IPv4 addresses by a DNS lookup at
18
+ * create time — see the DNS-ROTATION CAVEAT on SandboxCreateOptions.network.
19
+ * Destinations Daytona can never enforce (wildcards, IPv6, unresolvable
20
+ * hostnames, >10 CIDRs) throw DaytonaNetworkPolicyError instead of
21
+ * silently weakening the policy.
22
+ * - The `user` option is a CREATE-TIME OS user (Daytona's osUser field);
23
+ * there is no per-exec user switch — the Daytona daemon runs commands as
24
+ * the container's user (governed by the image's USER directive; default
25
+ * images use "daytona" with passwordless sudo). `user: "root"` keeps the
26
+ * image's default user and elevates every command through a `sudo -n`
27
+ * wrapper instead (mirrors the Modal provider's su wrapper). File
28
+ * operations always go through the Daytona daemon and are NOT elevated.
29
+ * - Private registry images (AWS ECR, GHCR, GCP Artifact Registry, ...)
30
+ * require registry credentials pre-registered in the Daytona dashboard
31
+ * (Registries page) — Daytona has no per-call image pull secret. Pull
32
+ * failures for such images throw DaytonaImagePullError.
33
+ * - getInfo()/list() report the API's real createdAt timestamp (never a
34
+ * fabricated client-side date); Daytona exposes no end timestamp, so
35
+ * endAt is always undefined.
36
+ */
37
+
38
+ /**
39
+ * Daytona's hard cap on network allowlist size (validated server-side too).
40
+ * Policies that resolve to more CIDRs throw DaytonaNetworkPolicyError.
10
41
  */
11
42
  /**
12
- * Wrap command with cwd and envs shell prefixes.
43
+ * Minutes a STOPPED sandbox is kept before Daytona deletes it. Long enough that
44
+ * a stop nobody ordered leaves something to look at and something to collect
45
+ * from; short enough that it is never a way to hold billable state.
46
+ */
47
+ declare const DAYTONA_AUTO_DELETE_GRACE_MINUTES = 10;
48
+ declare const DAYTONA_MAX_NETWORK_ALLOWLIST = 10;
49
+ /** Why a network policy cannot be enforced by Daytona. */
50
+ type DaytonaNetworkPolicyReason = "wildcard-hostname" | "ipv6-unsupported" | "port-unsupported" | "invalid-ipv4" | "unresolvable-hostname" | "allowlist-too-large";
51
+ /**
52
+ * Typed error for network policies Daytona cannot enforce.
13
53
  *
14
- * Daytona's executeSessionCommand doesn't support cwd or envs natively,
15
- * so we inline them as shell commands. Values are single-quoted to handle
16
- * spaces and special characters safely.
54
+ * Daytona's allowlist is kernel-level IPv4 CIDR filtering only (max 10
55
+ * entries) no DNS/domain layer. Anything that cannot be pinned to stable
56
+ * IPv4 CIDRs at create time is rejected loudly instead of silently
57
+ * weakening the sandbox's egress policy.
17
58
  */
18
- declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>): string;
19
- /** @internal Test-only export for unit testing wrapCommand logic. */
20
- declare const _testWrapCommand: typeof wrapCommand;
59
+ declare class DaytonaNetworkPolicyError extends Error {
60
+ readonly reason: DaytonaNetworkPolicyReason;
61
+ /** The offending destination (absent for list-level violations). */
62
+ readonly destination?: string;
63
+ constructor(reason: DaytonaNetworkPolicyReason, message: string, destination?: string);
64
+ }
65
+ /**
66
+ * Typed error for image pull failures on private registries.
67
+ *
68
+ * Daytona has no per-call image pull secret: credentials for private
69
+ * registries (AWS ECR, GHCR, GCP Artifact Registry, private Docker Hub)
70
+ * must be pre-registered in the Daytona dashboard BEFORE creating the
71
+ * sandbox (dashboard → Registries → Add Registry).
72
+ */
73
+ declare class DaytonaImagePullError extends Error {
74
+ /** The image reference that failed to pull. */
75
+ readonly image: string;
76
+ constructor(image: string, cause?: unknown);
77
+ }
78
+ /**
79
+ * Typed error for create-time sizing requests an EXISTING snapshot cannot
80
+ * honor. Daytona pins cpu/memory/disk on the SNAPSHOT at build time;
81
+ * create-from-snapshot has no resources parameter, so a `resources` request
82
+ * against a cached snapshot would be silently ignored. Per the provider law
83
+ * (reject what you cannot enforce) it is refused loudly instead: pre-build a
84
+ * snapshot with the desired sizing under its own name, or drop `resources`.
85
+ */
86
+ declare class DaytonaResourcesError extends Error {
87
+ /** The existing snapshot whose pinned sizing cannot be overridden. */
88
+ readonly snapshot: string;
89
+ constructor(snapshot: string);
90
+ }
91
+ declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>, user?: string): string;
92
+ /** Daytona create() params derived from Evolve's provider-neutral network policy. */
93
+ interface DaytonaNetworkCreateParams {
94
+ networkBlockAll?: boolean;
95
+ networkAllowList?: string;
96
+ }
97
+ /** Resolves a hostname to its IPv4 addresses (injectable for tests). */
98
+ type HostnameResolver = (hostname: string) => Promise<string[]>;
99
+ /**
100
+ * Map Evolve's provider-neutral network policy onto Daytona create() params.
101
+ *
102
+ * - outbound "open" (or no policy) → no restrictions
103
+ * - outbound "blocked", no allowlist → networkBlockAll: true (kernel DROP of all egress)
104
+ * - outbound "blocked" with allowlist → networkAllowList (comma-separated IPv4
105
+ * CIDRs; bare IPv4 gets /32). Daytona enforces the allowlist with kernel
106
+ * iptables and supports IPv4 CIDRs ONLY, max 10 entries.
107
+ *
108
+ * DNS-ROTATION CAVEAT (load-bearing): hostname destinations are resolved to
109
+ * their IPv4 A records ONCE, at create time, and pinned as /32 CIDRs. If the
110
+ * host rotates DNS afterwards (CDNs and cloud APIs often do), traffic to the
111
+ * new IPs is BLOCKED for the sandbox's lifetime. Prefer stable IPs/CIDRs for
112
+ * anything long-running.
113
+ *
114
+ * Anything that cannot be pinned to stable IPv4 CIDRs throws
115
+ * DaytonaNetworkPolicyError (wildcard hostnames, IPv6, unresolvable
116
+ * hostnames, >10 resolved CIDRs) — never silently weakened.
117
+ */
118
+ declare function mapNetworkPolicy(network?: SandboxCreateOptions["network"], resolveHostname?: HostnameResolver): Promise<DaytonaNetworkCreateParams>;
119
+ /**
120
+ * Registry host of an image reference, or undefined for Docker Hub images.
121
+ * A reference carries a registry host only when its first path segment
122
+ * contains "." or ":" or is "localhost" (Docker's own heuristic).
123
+ */
124
+ declare function imageRegistryHost(image: string): string | undefined;
125
+ /** Fields we read off a Daytona SDK sandbox to build a SandboxInfo. */
126
+ interface DaytonaSandboxLike {
127
+ id: string;
128
+ name?: string;
129
+ snapshot?: string;
130
+ labels?: Record<string, string>;
131
+ createdAt?: string;
132
+ }
133
+ /**
134
+ * Build a SandboxInfo from a Daytona sandbox entity. Timestamps come from
135
+ * the API's createdAt (never fabricated client-side; empty string when the
136
+ * API omits it). Daytona exposes no end timestamp, so endAt is always
137
+ * undefined.
138
+ */
139
+ declare function toSandboxInfo(sandbox: DaytonaSandboxLike): SandboxInfo;
140
+ /**
141
+ * Map a Daytona sandbox state onto Evolve's list() filter states.
142
+ * "started" → running; "stopped"/"archived" → paused (our pause() stops the
143
+ * sandbox); transitional and terminal states match no filter.
144
+ */
145
+ declare function daytonaStateToEvolveState(state?: string): "running" | "paused" | undefined;
21
146
  /** Result of a completed sandbox command */
22
147
  interface SandboxCommandResult {
23
148
  exitCode: number;
@@ -46,6 +171,7 @@ interface SandboxInfo {
46
171
  name?: string;
47
172
  metadata: Record<string, string>;
48
173
  startedAt: string;
174
+ /** End time (undefined for running sandboxes; Daytona never exposes one) */
49
175
  endAt?: string;
50
176
  }
51
177
  /** File or directory entry info */
@@ -82,11 +208,47 @@ interface SandboxCreateOptions {
82
208
  metadata?: Record<string, string>;
83
209
  timeoutMs?: number;
84
210
  workingDirectory?: string;
85
- /** Resource allocation for the sandbox */
211
+ /**
212
+ * Resource allocation (cpu cores, memory GiB, disk GiB), applied when a
213
+ * SNAPSHOT IS BUILT for the image (Daytona pins sizing on the snapshot).
214
+ * When the named snapshot ALREADY exists it cannot be resized at create —
215
+ * declaring resources then throws DaytonaResourcesError rather than
216
+ * silently ignoring them (pre-build a sizing-addressed snapshot instead).
217
+ */
86
218
  resources?: SandboxResources;
219
+ /**
220
+ * Provider-neutral outbound network policy, enforced by kernel iptables on
221
+ * the Daytona runner. "blocked" with no allowedDestinations drops all
222
+ * egress. With allowedDestinations, Daytona supports IPv4 CIDRs ONLY (max
223
+ * 10): IPs/CIDRs pass through; hostnames are DNS-resolved ONCE at create
224
+ * time and pinned as /32 CIDRs — if the host rotates DNS later (CDNs and
225
+ * cloud APIs often do), its new IPs are BLOCKED for the sandbox's
226
+ * lifetime. Wildcards, IPv6, and unresolvable hostnames throw
227
+ * DaytonaNetworkPolicyError rather than silently weakening the policy.
228
+ * Note: on Daytona orgs below Tier 3, org network policy overrides
229
+ * per-sandbox settings server-side.
230
+ */
231
+ network?: {
232
+ outbound: "open" | "blocked";
233
+ allowedDestinations?: string[];
234
+ };
235
+ /**
236
+ * OS user for the sandbox, applied at CREATE time (Daytona's osUser field)
237
+ * — Daytona has no per-exec user switch, so the user commands actually run
238
+ * as is governed by the sandbox image (USER directive; default Daytona
239
+ * images use "daytona" with passwordless sudo). A non-root value must
240
+ * exist in the image. Pass "root" to keep the image's default user and
241
+ * elevate every command through a `sudo -n` wrapper instead (requires
242
+ * passwordless sudo in the image; default images have it). File operations
243
+ * go through the Daytona daemon and are NOT elevated.
244
+ */
245
+ user?: string;
246
+ /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
247
+ homeDir?: string;
87
248
  }
88
249
  /** Options for listing sandboxes */
89
250
  interface SandboxListOptions {
251
+ /** "running" matches Daytona "started"; "paused" matches "stopped"/"archived". */
90
252
  state?: ("running" | "paused")[];
91
253
  metadata?: Record<string, string>;
92
254
  limit?: number;
@@ -106,6 +268,8 @@ interface SandboxFiles {
106
268
  path: string;
107
269
  data: string | Buffer | ArrayBuffer | Uint8Array;
108
270
  }>): Promise<void>;
271
+ /** Upload a local file by path, without buffering it whole */
272
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
109
273
  makeDir(path: string): Promise<void>;
110
274
  exists(path: string): Promise<boolean>;
111
275
  list(path: string): Promise<FileInfo[]>;
@@ -142,6 +306,20 @@ interface DaytonaConfig {
142
306
  defaultTimeoutMs?: number;
143
307
  /** Daytona snapshot name (default: 'evolve-all'). Create custom snapshots via `cd assets && ./build.sh daytona` */
144
308
  snapshotName?: string;
309
+ /**
310
+ * Evolve-managed toolbox base URL. Setting it puts the provider in MANAGED
311
+ * mode, where `apiKey` is an Evolve API key rather than a Daytona one and
312
+ * both planes ride the Dashboard.
313
+ *
314
+ * One field rather than a separate `managed: true` because the two effects
315
+ * have one cause: if the toolbox belongs to the platform, so do the
316
+ * snapshots behind it, so managed creates name an existing platform snapshot
317
+ * and never build one. Resolved by the Evolve SDK; direct/BYO callers leave
318
+ * it unset.
319
+ *
320
+ * @internal
321
+ */
322
+ managedToolboxUrl?: string;
145
323
  }
146
324
  interface ResolvedDaytonaConfig {
147
325
  apiKey: string;
@@ -149,6 +327,110 @@ interface ResolvedDaytonaConfig {
149
327
  target?: string;
150
328
  defaultTimeoutMs?: number;
151
329
  snapshotName?: string;
330
+ managedToolboxUrl?: string;
331
+ }
332
+ /** What a managed sandbox's streaming log follow needs to reach the Dashboard. */
333
+ interface ManagedStreamContext {
334
+ toolboxUrl: string;
335
+ apiKey: string;
336
+ }
337
+ /**
338
+ * Split Daytona's multiplexed command log into stdout and stderr as the bytes
339
+ * arrive.
340
+ *
341
+ * The wire format is one byte stream with 3-byte markers announcing which
342
+ * stream the following bytes belong to (STDOUT_PREFIX_BYTES /
343
+ * STDERR_PREFIX_BYTES, both exported by the Daytona SDK — this reads their
344
+ * framing, it does not invent one). Two things make a streaming demux
345
+ * different from the SDK's whole-buffer one: a marker can be split across two
346
+ * chunks, so the last MAX_PREFIX_LEN-1 bytes are always held back rather than
347
+ * emitted; and a multi-byte UTF-8 character can be split too, so each stream
348
+ * keeps its own decoder in streaming mode.
349
+ */
350
+ declare function createLogDemuxer(onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): {
351
+ push(chunk: Uint8Array): void;
352
+ flush(): void;
353
+ };
354
+ /**
355
+ * Follow a session command's logs over plain HTTP.
356
+ *
357
+ * The Daytona SDK follows logs over a WEBSOCKET (Process.js:289 rewrites the
358
+ * toolbox base to ws:// and opens a socket). A managed sandbox's toolbox base
359
+ * is a Next.js route handler, and a Next route handler never sees a websocket
360
+ * upgrade — the codebase's one websocket proxy lives in a separate custom
361
+ * server for exactly that reason. So managed mode cannot use that transport.
362
+ *
363
+ * It does not have to. MEASURED 2026-07-26 against a live sandbox: the same
364
+ * endpoint with `?follow=true` over ordinary HTTP answers 200 with
365
+ * `transfer-encoding: chunked` and `content-type: application/octet-stream`,
366
+ * and chunks arrive as the command produces them — 95 ms, 1045 ms, 2127 ms,
367
+ * 2984 ms, 3976 ms for a command printing one line per second. That is real
368
+ * streaming through a plain response body, which is what the Dashboard route
369
+ * pipes through unbuffered.
370
+ */
371
+ declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): Promise<void>;
372
+ /**
373
+ * Read a command's streams out of whatever shape Daytona returned.
374
+ *
375
+ * Session logs are USUALLY framed with per-stream markers, and the Daytona
376
+ * SDK's demux returns "" for a stream whose marker never appears. An empty
377
+ * string is not "this command printed nothing" — it means "this daemon build
378
+ * did not frame the output" — and `??` does not fall through an empty string,
379
+ * so reading `stdout ?? output` silently reports every such command as silent.
380
+ *
381
+ * Measured 2026-07-26 on a live sandbox booted from ubuntu:22.04: a command
382
+ * printing one line to each stream came back as
383
+ * {output: "hello-managed\noops\n", stdout: null, exitCode: 0} with no marker
384
+ * bytes anywhere in the log body, and the provider reported exit 0 with empty
385
+ * stdout. Unframed output goes to stdout, because that is what the combined
386
+ * `output` field is; a framed response is untouched.
387
+ */
388
+ declare function readCommandStreams(source: {
389
+ stdout?: string | null;
390
+ stderr?: string | null;
391
+ output?: string | null;
392
+ }): {
393
+ stdout: string;
394
+ stderr: string;
395
+ };
396
+ declare class DaytonaCommands implements SandboxCommands {
397
+ private sandbox;
398
+ private user?;
399
+ private managedStream?;
400
+ constructor(sandbox: Sandbox, user?: string | undefined, managedStream?: ManagedStreamContext | undefined);
401
+ /**
402
+ * Stream a command's output to callbacks. Direct mode uses the Daytona
403
+ * SDK's own follow, which is a websocket; managed mode uses the HTTP
404
+ * chunked follow, because a Dashboard route handler cannot terminate a
405
+ * websocket upgrade (see followManagedSessionLogs).
406
+ */
407
+ private followLogs;
408
+ run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
409
+ spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
410
+ list(): Promise<ProcessInfo[]>;
411
+ kill(processId: string): Promise<boolean>;
412
+ }
413
+ declare class DaytonaFiles implements SandboxFiles {
414
+ private sandbox;
415
+ constructor(sandbox: Sandbox);
416
+ read(path: string): Promise<string | Uint8Array>;
417
+ write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
418
+ writeBatch(files: Array<{
419
+ path: string;
420
+ data: string | Buffer | ArrayBuffer | Uint8Array;
421
+ }>): Promise<void>;
422
+ /**
423
+ * Upload a local file by PATH. Daytona's own uploadFile has a local-path
424
+ * overload (FileSystem.d.ts: `uploadFile(localPath: string, remotePath:
425
+ * string, timeout?)`), so the bytes never pass through this process's heap —
426
+ * which is what makes a large artifact safe to upload under concurrency.
427
+ */
428
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
429
+ makeDir(path: string): Promise<void>;
430
+ exists(path: string): Promise<boolean>;
431
+ list(path: string): Promise<FileInfo[]>;
432
+ remove(path: string): Promise<void>;
433
+ rename(oldPath: string, newPath: string): Promise<void>;
152
434
  }
153
435
  declare class DaytonaProvider implements SandboxProvider {
154
436
  readonly providerType: "daytona";
@@ -156,6 +438,17 @@ declare class DaytonaProvider implements SandboxProvider {
156
438
  private readonly client;
157
439
  private readonly defaultTimeoutMs;
158
440
  private readonly snapshotName;
441
+ /**
442
+ * Sandbox user configured at create time, reapplied on connect() so the
443
+ * root sudo wrapper keeps applying. In-memory only: a connect() from a
444
+ * fresh process falls back to the sandbox's create-time OS user without
445
+ * the wrapper — callers reconnecting across processes must recreate the
446
+ * provider and sandbox with the same user, or root-only operations fail
447
+ * loudly.
448
+ */
449
+ private readonly sandboxUsers;
450
+ /** Set only in Evolve-managed mode; see the EVOLVE-MANAGED MODE section. */
451
+ private readonly managedStream?;
159
452
  constructor(config: ResolvedDaytonaConfig);
160
453
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
161
454
  connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
@@ -168,5 +461,14 @@ declare class DaytonaProvider implements SandboxProvider {
168
461
  * @throws Error if apiKey cannot be resolved
169
462
  */
170
463
  declare function createDaytonaProvider(config?: DaytonaConfig): SandboxProvider;
464
+ /** @internal Test-only export for unit testing wrapCommand logic. */
465
+ declare const _testWrapCommand: typeof wrapCommand;
466
+ declare const _testMapNetworkPolicy: typeof mapNetworkPolicy;
467
+ declare const _testImageRegistryHost: typeof imageRegistryHost;
468
+ declare const _testToSandboxInfo: typeof toSandboxInfo;
469
+ declare const _testDaytonaStateToEvolveState: typeof daytonaStateToEvolveState;
470
+ declare const _testCreateLogDemuxer: typeof createLogDemuxer;
471
+ declare const _testFollowManagedSessionLogs: typeof followManagedSessionLogs;
472
+ declare const _testReadCommandStreams: typeof readCommandStreams;
171
473
 
172
- export { type DaytonaConfig, DaytonaProvider, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testWrapCommand, createDaytonaProvider };
474
+ export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_MAX_NETWORK_ALLOWLIST, DaytonaCommands, type DaytonaConfig, DaytonaFiles, DaytonaImagePullError, DaytonaNetworkPolicyError, type DaytonaNetworkPolicyReason, DaytonaProvider, DaytonaResourcesError, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testCreateLogDemuxer, _testDaytonaStateToEvolveState, _testFollowManagedSessionLogs, _testImageRegistryHost, _testMapNetworkPolicy, _testReadCommandStreams, _testToSandboxInfo, _testWrapCommand, createDaytonaProvider };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Sandbox } from '@daytonaio/sdk';
2
+
1
3
  /**
2
4
  * Daytona Sandbox Provider
3
5
  *
@@ -7,17 +9,140 @@
7
9
  * - Mirror E2B provider interface for SDK compatibility
8
10
  * - Uses public Docker images via IMAGE_MAP
9
11
  * - Parallel structure to E2B provider
12
+ *
13
+ * Daytona-specific notes:
14
+ * - Network policy maps to Daytona's networkBlockAll / networkAllowList,
15
+ * enforced by kernel iptables on the runner. The allowlist is IPv4 CIDR
16
+ * ONLY (max 10 entries, DAYTONA_MAX_NETWORK_ALLOWLIST). Hostname
17
+ * destinations are pinned to their IPv4 addresses by a DNS lookup at
18
+ * create time — see the DNS-ROTATION CAVEAT on SandboxCreateOptions.network.
19
+ * Destinations Daytona can never enforce (wildcards, IPv6, unresolvable
20
+ * hostnames, >10 CIDRs) throw DaytonaNetworkPolicyError instead of
21
+ * silently weakening the policy.
22
+ * - The `user` option is a CREATE-TIME OS user (Daytona's osUser field);
23
+ * there is no per-exec user switch — the Daytona daemon runs commands as
24
+ * the container's user (governed by the image's USER directive; default
25
+ * images use "daytona" with passwordless sudo). `user: "root"` keeps the
26
+ * image's default user and elevates every command through a `sudo -n`
27
+ * wrapper instead (mirrors the Modal provider's su wrapper). File
28
+ * operations always go through the Daytona daemon and are NOT elevated.
29
+ * - Private registry images (AWS ECR, GHCR, GCP Artifact Registry, ...)
30
+ * require registry credentials pre-registered in the Daytona dashboard
31
+ * (Registries page) — Daytona has no per-call image pull secret. Pull
32
+ * failures for such images throw DaytonaImagePullError.
33
+ * - getInfo()/list() report the API's real createdAt timestamp (never a
34
+ * fabricated client-side date); Daytona exposes no end timestamp, so
35
+ * endAt is always undefined.
36
+ */
37
+
38
+ /**
39
+ * Daytona's hard cap on network allowlist size (validated server-side too).
40
+ * Policies that resolve to more CIDRs throw DaytonaNetworkPolicyError.
10
41
  */
11
42
  /**
12
- * Wrap command with cwd and envs shell prefixes.
43
+ * Minutes a STOPPED sandbox is kept before Daytona deletes it. Long enough that
44
+ * a stop nobody ordered leaves something to look at and something to collect
45
+ * from; short enough that it is never a way to hold billable state.
46
+ */
47
+ declare const DAYTONA_AUTO_DELETE_GRACE_MINUTES = 10;
48
+ declare const DAYTONA_MAX_NETWORK_ALLOWLIST = 10;
49
+ /** Why a network policy cannot be enforced by Daytona. */
50
+ type DaytonaNetworkPolicyReason = "wildcard-hostname" | "ipv6-unsupported" | "port-unsupported" | "invalid-ipv4" | "unresolvable-hostname" | "allowlist-too-large";
51
+ /**
52
+ * Typed error for network policies Daytona cannot enforce.
13
53
  *
14
- * Daytona's executeSessionCommand doesn't support cwd or envs natively,
15
- * so we inline them as shell commands. Values are single-quoted to handle
16
- * spaces and special characters safely.
54
+ * Daytona's allowlist is kernel-level IPv4 CIDR filtering only (max 10
55
+ * entries) no DNS/domain layer. Anything that cannot be pinned to stable
56
+ * IPv4 CIDRs at create time is rejected loudly instead of silently
57
+ * weakening the sandbox's egress policy.
17
58
  */
18
- declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>): string;
19
- /** @internal Test-only export for unit testing wrapCommand logic. */
20
- declare const _testWrapCommand: typeof wrapCommand;
59
+ declare class DaytonaNetworkPolicyError extends Error {
60
+ readonly reason: DaytonaNetworkPolicyReason;
61
+ /** The offending destination (absent for list-level violations). */
62
+ readonly destination?: string;
63
+ constructor(reason: DaytonaNetworkPolicyReason, message: string, destination?: string);
64
+ }
65
+ /**
66
+ * Typed error for image pull failures on private registries.
67
+ *
68
+ * Daytona has no per-call image pull secret: credentials for private
69
+ * registries (AWS ECR, GHCR, GCP Artifact Registry, private Docker Hub)
70
+ * must be pre-registered in the Daytona dashboard BEFORE creating the
71
+ * sandbox (dashboard → Registries → Add Registry).
72
+ */
73
+ declare class DaytonaImagePullError extends Error {
74
+ /** The image reference that failed to pull. */
75
+ readonly image: string;
76
+ constructor(image: string, cause?: unknown);
77
+ }
78
+ /**
79
+ * Typed error for create-time sizing requests an EXISTING snapshot cannot
80
+ * honor. Daytona pins cpu/memory/disk on the SNAPSHOT at build time;
81
+ * create-from-snapshot has no resources parameter, so a `resources` request
82
+ * against a cached snapshot would be silently ignored. Per the provider law
83
+ * (reject what you cannot enforce) it is refused loudly instead: pre-build a
84
+ * snapshot with the desired sizing under its own name, or drop `resources`.
85
+ */
86
+ declare class DaytonaResourcesError extends Error {
87
+ /** The existing snapshot whose pinned sizing cannot be overridden. */
88
+ readonly snapshot: string;
89
+ constructor(snapshot: string);
90
+ }
91
+ declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>, user?: string): string;
92
+ /** Daytona create() params derived from Evolve's provider-neutral network policy. */
93
+ interface DaytonaNetworkCreateParams {
94
+ networkBlockAll?: boolean;
95
+ networkAllowList?: string;
96
+ }
97
+ /** Resolves a hostname to its IPv4 addresses (injectable for tests). */
98
+ type HostnameResolver = (hostname: string) => Promise<string[]>;
99
+ /**
100
+ * Map Evolve's provider-neutral network policy onto Daytona create() params.
101
+ *
102
+ * - outbound "open" (or no policy) → no restrictions
103
+ * - outbound "blocked", no allowlist → networkBlockAll: true (kernel DROP of all egress)
104
+ * - outbound "blocked" with allowlist → networkAllowList (comma-separated IPv4
105
+ * CIDRs; bare IPv4 gets /32). Daytona enforces the allowlist with kernel
106
+ * iptables and supports IPv4 CIDRs ONLY, max 10 entries.
107
+ *
108
+ * DNS-ROTATION CAVEAT (load-bearing): hostname destinations are resolved to
109
+ * their IPv4 A records ONCE, at create time, and pinned as /32 CIDRs. If the
110
+ * host rotates DNS afterwards (CDNs and cloud APIs often do), traffic to the
111
+ * new IPs is BLOCKED for the sandbox's lifetime. Prefer stable IPs/CIDRs for
112
+ * anything long-running.
113
+ *
114
+ * Anything that cannot be pinned to stable IPv4 CIDRs throws
115
+ * DaytonaNetworkPolicyError (wildcard hostnames, IPv6, unresolvable
116
+ * hostnames, >10 resolved CIDRs) — never silently weakened.
117
+ */
118
+ declare function mapNetworkPolicy(network?: SandboxCreateOptions["network"], resolveHostname?: HostnameResolver): Promise<DaytonaNetworkCreateParams>;
119
+ /**
120
+ * Registry host of an image reference, or undefined for Docker Hub images.
121
+ * A reference carries a registry host only when its first path segment
122
+ * contains "." or ":" or is "localhost" (Docker's own heuristic).
123
+ */
124
+ declare function imageRegistryHost(image: string): string | undefined;
125
+ /** Fields we read off a Daytona SDK sandbox to build a SandboxInfo. */
126
+ interface DaytonaSandboxLike {
127
+ id: string;
128
+ name?: string;
129
+ snapshot?: string;
130
+ labels?: Record<string, string>;
131
+ createdAt?: string;
132
+ }
133
+ /**
134
+ * Build a SandboxInfo from a Daytona sandbox entity. Timestamps come from
135
+ * the API's createdAt (never fabricated client-side; empty string when the
136
+ * API omits it). Daytona exposes no end timestamp, so endAt is always
137
+ * undefined.
138
+ */
139
+ declare function toSandboxInfo(sandbox: DaytonaSandboxLike): SandboxInfo;
140
+ /**
141
+ * Map a Daytona sandbox state onto Evolve's list() filter states.
142
+ * "started" → running; "stopped"/"archived" → paused (our pause() stops the
143
+ * sandbox); transitional and terminal states match no filter.
144
+ */
145
+ declare function daytonaStateToEvolveState(state?: string): "running" | "paused" | undefined;
21
146
  /** Result of a completed sandbox command */
22
147
  interface SandboxCommandResult {
23
148
  exitCode: number;
@@ -46,6 +171,7 @@ interface SandboxInfo {
46
171
  name?: string;
47
172
  metadata: Record<string, string>;
48
173
  startedAt: string;
174
+ /** End time (undefined for running sandboxes; Daytona never exposes one) */
49
175
  endAt?: string;
50
176
  }
51
177
  /** File or directory entry info */
@@ -82,11 +208,47 @@ interface SandboxCreateOptions {
82
208
  metadata?: Record<string, string>;
83
209
  timeoutMs?: number;
84
210
  workingDirectory?: string;
85
- /** Resource allocation for the sandbox */
211
+ /**
212
+ * Resource allocation (cpu cores, memory GiB, disk GiB), applied when a
213
+ * SNAPSHOT IS BUILT for the image (Daytona pins sizing on the snapshot).
214
+ * When the named snapshot ALREADY exists it cannot be resized at create —
215
+ * declaring resources then throws DaytonaResourcesError rather than
216
+ * silently ignoring them (pre-build a sizing-addressed snapshot instead).
217
+ */
86
218
  resources?: SandboxResources;
219
+ /**
220
+ * Provider-neutral outbound network policy, enforced by kernel iptables on
221
+ * the Daytona runner. "blocked" with no allowedDestinations drops all
222
+ * egress. With allowedDestinations, Daytona supports IPv4 CIDRs ONLY (max
223
+ * 10): IPs/CIDRs pass through; hostnames are DNS-resolved ONCE at create
224
+ * time and pinned as /32 CIDRs — if the host rotates DNS later (CDNs and
225
+ * cloud APIs often do), its new IPs are BLOCKED for the sandbox's
226
+ * lifetime. Wildcards, IPv6, and unresolvable hostnames throw
227
+ * DaytonaNetworkPolicyError rather than silently weakening the policy.
228
+ * Note: on Daytona orgs below Tier 3, org network policy overrides
229
+ * per-sandbox settings server-side.
230
+ */
231
+ network?: {
232
+ outbound: "open" | "blocked";
233
+ allowedDestinations?: string[];
234
+ };
235
+ /**
236
+ * OS user for the sandbox, applied at CREATE time (Daytona's osUser field)
237
+ * — Daytona has no per-exec user switch, so the user commands actually run
238
+ * as is governed by the sandbox image (USER directive; default Daytona
239
+ * images use "daytona" with passwordless sudo). A non-root value must
240
+ * exist in the image. Pass "root" to keep the image's default user and
241
+ * elevate every command through a `sudo -n` wrapper instead (requires
242
+ * passwordless sudo in the image; default images have it). File operations
243
+ * go through the Daytona daemon and are NOT elevated.
244
+ */
245
+ user?: string;
246
+ /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
247
+ homeDir?: string;
87
248
  }
88
249
  /** Options for listing sandboxes */
89
250
  interface SandboxListOptions {
251
+ /** "running" matches Daytona "started"; "paused" matches "stopped"/"archived". */
90
252
  state?: ("running" | "paused")[];
91
253
  metadata?: Record<string, string>;
92
254
  limit?: number;
@@ -106,6 +268,8 @@ interface SandboxFiles {
106
268
  path: string;
107
269
  data: string | Buffer | ArrayBuffer | Uint8Array;
108
270
  }>): Promise<void>;
271
+ /** Upload a local file by path, without buffering it whole */
272
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
109
273
  makeDir(path: string): Promise<void>;
110
274
  exists(path: string): Promise<boolean>;
111
275
  list(path: string): Promise<FileInfo[]>;
@@ -142,6 +306,20 @@ interface DaytonaConfig {
142
306
  defaultTimeoutMs?: number;
143
307
  /** Daytona snapshot name (default: 'evolve-all'). Create custom snapshots via `cd assets && ./build.sh daytona` */
144
308
  snapshotName?: string;
309
+ /**
310
+ * Evolve-managed toolbox base URL. Setting it puts the provider in MANAGED
311
+ * mode, where `apiKey` is an Evolve API key rather than a Daytona one and
312
+ * both planes ride the Dashboard.
313
+ *
314
+ * One field rather than a separate `managed: true` because the two effects
315
+ * have one cause: if the toolbox belongs to the platform, so do the
316
+ * snapshots behind it, so managed creates name an existing platform snapshot
317
+ * and never build one. Resolved by the Evolve SDK; direct/BYO callers leave
318
+ * it unset.
319
+ *
320
+ * @internal
321
+ */
322
+ managedToolboxUrl?: string;
145
323
  }
146
324
  interface ResolvedDaytonaConfig {
147
325
  apiKey: string;
@@ -149,6 +327,110 @@ interface ResolvedDaytonaConfig {
149
327
  target?: string;
150
328
  defaultTimeoutMs?: number;
151
329
  snapshotName?: string;
330
+ managedToolboxUrl?: string;
331
+ }
332
+ /** What a managed sandbox's streaming log follow needs to reach the Dashboard. */
333
+ interface ManagedStreamContext {
334
+ toolboxUrl: string;
335
+ apiKey: string;
336
+ }
337
+ /**
338
+ * Split Daytona's multiplexed command log into stdout and stderr as the bytes
339
+ * arrive.
340
+ *
341
+ * The wire format is one byte stream with 3-byte markers announcing which
342
+ * stream the following bytes belong to (STDOUT_PREFIX_BYTES /
343
+ * STDERR_PREFIX_BYTES, both exported by the Daytona SDK — this reads their
344
+ * framing, it does not invent one). Two things make a streaming demux
345
+ * different from the SDK's whole-buffer one: a marker can be split across two
346
+ * chunks, so the last MAX_PREFIX_LEN-1 bytes are always held back rather than
347
+ * emitted; and a multi-byte UTF-8 character can be split too, so each stream
348
+ * keeps its own decoder in streaming mode.
349
+ */
350
+ declare function createLogDemuxer(onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): {
351
+ push(chunk: Uint8Array): void;
352
+ flush(): void;
353
+ };
354
+ /**
355
+ * Follow a session command's logs over plain HTTP.
356
+ *
357
+ * The Daytona SDK follows logs over a WEBSOCKET (Process.js:289 rewrites the
358
+ * toolbox base to ws:// and opens a socket). A managed sandbox's toolbox base
359
+ * is a Next.js route handler, and a Next route handler never sees a websocket
360
+ * upgrade — the codebase's one websocket proxy lives in a separate custom
361
+ * server for exactly that reason. So managed mode cannot use that transport.
362
+ *
363
+ * It does not have to. MEASURED 2026-07-26 against a live sandbox: the same
364
+ * endpoint with `?follow=true` over ordinary HTTP answers 200 with
365
+ * `transfer-encoding: chunked` and `content-type: application/octet-stream`,
366
+ * and chunks arrive as the command produces them — 95 ms, 1045 ms, 2127 ms,
367
+ * 2984 ms, 3976 ms for a command printing one line per second. That is real
368
+ * streaming through a plain response body, which is what the Dashboard route
369
+ * pipes through unbuffered.
370
+ */
371
+ declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): Promise<void>;
372
+ /**
373
+ * Read a command's streams out of whatever shape Daytona returned.
374
+ *
375
+ * Session logs are USUALLY framed with per-stream markers, and the Daytona
376
+ * SDK's demux returns "" for a stream whose marker never appears. An empty
377
+ * string is not "this command printed nothing" — it means "this daemon build
378
+ * did not frame the output" — and `??` does not fall through an empty string,
379
+ * so reading `stdout ?? output` silently reports every such command as silent.
380
+ *
381
+ * Measured 2026-07-26 on a live sandbox booted from ubuntu:22.04: a command
382
+ * printing one line to each stream came back as
383
+ * {output: "hello-managed\noops\n", stdout: null, exitCode: 0} with no marker
384
+ * bytes anywhere in the log body, and the provider reported exit 0 with empty
385
+ * stdout. Unframed output goes to stdout, because that is what the combined
386
+ * `output` field is; a framed response is untouched.
387
+ */
388
+ declare function readCommandStreams(source: {
389
+ stdout?: string | null;
390
+ stderr?: string | null;
391
+ output?: string | null;
392
+ }): {
393
+ stdout: string;
394
+ stderr: string;
395
+ };
396
+ declare class DaytonaCommands implements SandboxCommands {
397
+ private sandbox;
398
+ private user?;
399
+ private managedStream?;
400
+ constructor(sandbox: Sandbox, user?: string | undefined, managedStream?: ManagedStreamContext | undefined);
401
+ /**
402
+ * Stream a command's output to callbacks. Direct mode uses the Daytona
403
+ * SDK's own follow, which is a websocket; managed mode uses the HTTP
404
+ * chunked follow, because a Dashboard route handler cannot terminate a
405
+ * websocket upgrade (see followManagedSessionLogs).
406
+ */
407
+ private followLogs;
408
+ run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
409
+ spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
410
+ list(): Promise<ProcessInfo[]>;
411
+ kill(processId: string): Promise<boolean>;
412
+ }
413
+ declare class DaytonaFiles implements SandboxFiles {
414
+ private sandbox;
415
+ constructor(sandbox: Sandbox);
416
+ read(path: string): Promise<string | Uint8Array>;
417
+ write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
418
+ writeBatch(files: Array<{
419
+ path: string;
420
+ data: string | Buffer | ArrayBuffer | Uint8Array;
421
+ }>): Promise<void>;
422
+ /**
423
+ * Upload a local file by PATH. Daytona's own uploadFile has a local-path
424
+ * overload (FileSystem.d.ts: `uploadFile(localPath: string, remotePath:
425
+ * string, timeout?)`), so the bytes never pass through this process's heap —
426
+ * which is what makes a large artifact safe to upload under concurrency.
427
+ */
428
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
429
+ makeDir(path: string): Promise<void>;
430
+ exists(path: string): Promise<boolean>;
431
+ list(path: string): Promise<FileInfo[]>;
432
+ remove(path: string): Promise<void>;
433
+ rename(oldPath: string, newPath: string): Promise<void>;
152
434
  }
153
435
  declare class DaytonaProvider implements SandboxProvider {
154
436
  readonly providerType: "daytona";
@@ -156,6 +438,17 @@ declare class DaytonaProvider implements SandboxProvider {
156
438
  private readonly client;
157
439
  private readonly defaultTimeoutMs;
158
440
  private readonly snapshotName;
441
+ /**
442
+ * Sandbox user configured at create time, reapplied on connect() so the
443
+ * root sudo wrapper keeps applying. In-memory only: a connect() from a
444
+ * fresh process falls back to the sandbox's create-time OS user without
445
+ * the wrapper — callers reconnecting across processes must recreate the
446
+ * provider and sandbox with the same user, or root-only operations fail
447
+ * loudly.
448
+ */
449
+ private readonly sandboxUsers;
450
+ /** Set only in Evolve-managed mode; see the EVOLVE-MANAGED MODE section. */
451
+ private readonly managedStream?;
159
452
  constructor(config: ResolvedDaytonaConfig);
160
453
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
161
454
  connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
@@ -168,5 +461,14 @@ declare class DaytonaProvider implements SandboxProvider {
168
461
  * @throws Error if apiKey cannot be resolved
169
462
  */
170
463
  declare function createDaytonaProvider(config?: DaytonaConfig): SandboxProvider;
464
+ /** @internal Test-only export for unit testing wrapCommand logic. */
465
+ declare const _testWrapCommand: typeof wrapCommand;
466
+ declare const _testMapNetworkPolicy: typeof mapNetworkPolicy;
467
+ declare const _testImageRegistryHost: typeof imageRegistryHost;
468
+ declare const _testToSandboxInfo: typeof toSandboxInfo;
469
+ declare const _testDaytonaStateToEvolveState: typeof daytonaStateToEvolveState;
470
+ declare const _testCreateLogDemuxer: typeof createLogDemuxer;
471
+ declare const _testFollowManagedSessionLogs: typeof followManagedSessionLogs;
472
+ declare const _testReadCommandStreams: typeof readCommandStreams;
171
473
 
172
- export { type DaytonaConfig, DaytonaProvider, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testWrapCommand, createDaytonaProvider };
474
+ export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_MAX_NETWORK_ALLOWLIST, DaytonaCommands, type DaytonaConfig, DaytonaFiles, DaytonaImagePullError, DaytonaNetworkPolicyError, type DaytonaNetworkPolicyReason, DaytonaProvider, DaytonaResourcesError, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testCreateLogDemuxer, _testDaytonaStateToEvolveState, _testFollowManagedSessionLogs, _testImageRegistryHost, _testMapNetworkPolicy, _testReadCommandStreams, _testToSandboxInfo, _testWrapCommand, createDaytonaProvider };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import {Daytona,Image}from'@daytonaio/sdk';var h={"evolve-all":"evolvingmachines/evolve-all"},S=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function w(r){let e=r.substring(r.lastIndexOf(".")).toLowerCase();return S.has(e)}function v(r){let e=r.lastIndexOf("/");return e>0?r.substring(0,e):"/"}function P(r){let e=r.lastIndexOf("/");return e>=0?r.substring(e+1):r}function g(r,e,t){let s=r;return e&&(s=`cd '${e.replace(/'/g,"'\\''")}' && ${s}`),t&&Object.keys(t).length>0&&(s=`${Object.entries(t).filter(([,a])=>a!=null).map(([a,o])=>`export ${a}='${o.replace(/'/g,"'\\''")}'`).join("; ")}; ${s}`),s}var C=g,f=class{constructor(e){this.sandbox=e;}async run(e,t){let s=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,n=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);try{let a=await this.sandbox.process.executeSessionCommand(n,{command:g(e,t?.cwd,t?.envs),runAsync:!1},s),o=a.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.sandbox.process.getSessionCommandLogs(n,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let d=a.stdout??a.output??"",i=a.stderr??"";if(!d&&o&&!t?.onStdout)try{let m=await this.sandbox.process.getSessionCommandLogs(n,o);d=m.stdout??m.output??"",i=m.stderr??i;}catch{}return {exitCode:a.exitCode??0,stdout:d,stderr:i}}finally{try{await this.sandbox.process.deleteSession(n);}catch{}}}async spawn(e,t){let s=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(s);let n=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,a=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(s,{command:g(e,t?.cwd,t?.envs),runAsync:true},n)).cmdId;i&&(t?.onStdout||t?.onStderr)&&this.sandbox.process.getSessionCommandLogs(s,i,t.onStdout||(()=>{}),t.onStderr||(()=>{})).catch(()=>{});let m=this.sandbox;return {processId:s,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-a>=o){try{await m.process.deleteSession(s);}catch{}return {exitCode:-1,stdout:"",stderr:"operation timed out"}}try{let c=await m.process.getSessionCommand(s,i);if(c.exitCode!==void 0)try{let l=await m.process.getSessionCommandLogs(s,i);return {exitCode:c.exitCode,stdout:l.stdout??l.output??"",stderr:l.stderr??""}}catch{return {exitCode:c.exitCode,stdout:"",stderr:""}}}catch(c){if((c instanceof Error?c.message.toLowerCase():String(c).toLowerCase()).includes("not found"))return {exitCode:-1,stdout:"",stderr:"session terminated"};throw c}await new Promise(c=>setTimeout(c,500));}},kill:async()=>{try{return await m.process.deleteSession(s),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(t=>({processId:t.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(e){try{return await this.sandbox.process.deleteSession(e),!0}catch{return false}}},p=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return w(e)?new Uint8Array(t):t.toString("utf-8")}async write(e,t){let s;if(typeof t=="string")s=Buffer.from(t,"utf-8");else if(Buffer.isBuffer(t))s=t;else if(t instanceof ArrayBuffer)s=Buffer.from(t);else if(t instanceof Uint8Array)s=Buffer.from(t);else throw new Error(`Unsupported content type: ${typeof t}`);await this.sandbox.fs.uploadFile(s,e);}async writeBatch(e){let t=e.map(s=>{let n;if(typeof s.data=="string")n=Buffer.from(s.data,"utf-8");else if(Buffer.isBuffer(s.data))n=s.data;else if(s.data instanceof ArrayBuffer)n=Buffer.from(s.data);else if(s.data instanceof Uint8Array)n=Buffer.from(s.data);else throw new Error(`Unsupported content type: ${typeof s.data}`);return {source:n,destination:s.path}});await this.sandbox.fs.uploadFiles(t);}async makeDir(e){await this.sandbox.fs.createFolder(e,"755");}async exists(e){try{let t=v(e),s=P(e);return (await this.sandbox.fs.listFiles(t)).some(a=>a.name===s)}catch{return false}}async list(e){return (await this.sandbox.fs.listFiles(e)).map(s=>({name:s.name,path:e.endsWith("/")?`${e}${s.name}`:`${e}/${s.name}`,type:s.isDir?"dir":"file"}))}async remove(e){await this.sandbox.fs.deleteFile(e,true);}async rename(e,t){await this.sandbox.fs.moveFiles(e,t);}},u=class{constructor(e){this.sandbox=e;this.commands=new f(e),this.files=new p(e);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(e){return (await this.sandbox.getPreviewLink(e)).url}async isRunning(){return this.sandbox.state==="started"}async getInfo(){return {sandboxId:this.sandbox.id,image:this.sandbox.snapshot||"unknown",name:this.sandbox.name,metadata:this.sandbox.labels||{},startedAt:new Date().toISOString()}}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},x=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;constructor(e){this.client=new Daytona({apiKey:e.apiKey,apiUrl:e.apiUrl,target:e.target}),this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.snapshotName=e.snapshotName??"evolve-all";}async create(e){let t=e.timeoutMs??this.defaultTimeoutMs,s=Math.max(1,Math.ceil(t/6e4)),n=e.image||this.snapshotName,a;try{let o=await this.client.snapshot.get(n);if(o&&o.state==="active")console.log(`[daytona] Using cached snapshot: ${n}`),a=await this.client.create({snapshot:n,envVars:e.envs,labels:e.metadata,autoStopInterval:s},{timeout:600});else throw new Error("Snapshot not active")}catch{let o=h[n]??n;console.log(`[daytona] Snapshot "${n}" not found, building from image: ${o}`),console.log("[daytona] First run will take a few minutes (this only happens once)...");try{await this.client.snapshot.create({name:n,image:Image.base(o),resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{onLogs:d=>console.log(`[daytona] ${d}`)}),console.log(`[daytona] Snapshot "${n}" ready.`),a=await this.client.create({snapshot:n,envVars:e.envs,labels:e.metadata,autoStopInterval:s},{timeout:600});}catch(d){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${d instanceof Error?d.message:d}`),a=await this.client.create({image:o,envVars:e.envs,labels:e.metadata,autoStopInterval:s,resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{timeout:600,onSnapshotCreateLogs:i=>console.log(`[daytona] ${i}`)});}}return e.workingDirectory&&await a.fs.createFolder(e.workingDirectory,"755"),new u(a)}async connect(e,t){let s=await this.client.get(e);return s.state!=="started"&&await s.start(),new u(s)}async list(e){let t=e?.limit??100;return (await this.client.list(e?.metadata,1,t)).items.map(n=>({sandboxId:n.id,image:n.snapshot||"unknown",name:n.name,metadata:n.labels||{},startedAt:new Date().toISOString()}))}};function A(r={}){let e=r.apiKey??process.env.DAYTONA_API_KEY;if(!e)throw new Error("Daytona API key required. Set DAYTONA_API_KEY environment variable or pass apiKey in config. Get your key at https://app.daytona.io/dashboard/keys");return new x({...r,apiKey:e})}
2
- export{x as DaytonaProvider,C as _testWrapCommand,A as createDaytonaProvider};
1
+ import {STDOUT_PREFIX_BYTES,STDERR_PREFIX_BYTES,MAX_PREFIX_LEN,Daytona,Image}from'@daytonaio/sdk';import {resolve4}from'dns/promises';var F={"evolve-all":"evolvingmachines/evolve-all"},K=10,A=10,H=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function j(s){let e=s.substring(s.lastIndexOf(".")).toLowerCase();return H.has(e)}function z(s){let e=s.lastIndexOf("/");return e>0?s.substring(0,e):"/"}function Y(s){let e=s.lastIndexOf("/");return e>=0?s.substring(e+1):s}var f=class extends Error{reason;destination;constructor(e,t,n){super(t),this.name="DaytonaNetworkPolicyError",this.reason=e,this.destination=n;}},b=class extends Error{image;constructor(e,t){let n=t instanceof Error?t.message:String(t??"unknown error");super(`Failed to pull image "${e}" on Daytona: ${n}. Private registry images (e.g. AWS ECR) require registry credentials pre-registered in the Daytona dashboard (Registries page) before sandbox creation \u2014 Daytona has no per-call image pull secret. Register the registry at https://app.daytona.io, then retry. Also ensure the image is linux/amd64 and pinned to a tag or digest (floating tags like "latest" are rejected by Daytona's snapshot builder).`),this.name="DaytonaImagePullError",this.image=e;}},h=class extends Error{snapshot;constructor(e){super(`Daytona snapshot "${e}" already exists and pins its cpu/memory/disk sizing \u2014 create-from-snapshot cannot resize it, so the requested \`resources\` cannot be enforced. Pre-build a snapshot with the desired sizing under its own name (sizing-addressed), or omit \`resources\` to accept the snapshot's pinned sizing.`),this.name="DaytonaResourcesError",this.snapshot=e;}};function q(s,e){if(!e||e<=0)return s;let t=Buffer.from(s).toString("base64"),n=`/tmp/.evolve-cmd-${Date.now()}-${Math.random().toString(36).slice(2,8)}.sh`;return `sh -c '${`echo ${t} | base64 -d > ${n}; if command -v timeout >/dev/null 2>&1; then timeout -k 10 ${e} bash ${n}; else bash ${n}; fi; rc=$?; rm -f ${n}; exit $rc`}'`}function x(s,e,t,n){let r=s;return e&&(r=`cd '${e.replace(/'/g,"'\\''")}' && ${r}`),t&&Object.keys(t).length>0&&(r=`${Object.entries(t).filter(([,o])=>o!=null).map(([o,a])=>`export ${o}='${String(a).replace(/'/g,"'\\''")}'`).join("; ")}; ${r}`),n==="root"&&(r=`echo ${Buffer.from(r).toString("base64")} | base64 -d | sudo -n bash`),r}var W=s=>resolve4(s);function U(s){let e=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(s);return !(!e||[e[1],e[2],e[3],e[4]].some(t=>Number(t)>255)||e[5]!==void 0&&Number(e[5])>32)}function X(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!U(s)}function G(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function V(s){return /^[^:]+:\d+$/.test(s)}async function M(s,e=W){if(!s||s.outbound==="open"){if(s?.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");return s?{networkBlockAll:false}:{}}let t=s.allowedDestinations??[];if(t.length===0)return {networkBlockAll:true};let n=[],r=[];for(let o of t)if(U(o))n.push(o.includes("/")?o:`${o}/32`);else {if(X(o))throw new f("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(G(o))throw new f("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${o}".`,o);if(V(o))throw new f("port-unsupported",`Daytona'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);if(o.includes("*"))throw new f("wildcard-hostname",`Daytona cannot enforce wildcard hostname "${o}": its allowlist is kernel-level IPv4 CIDR filtering with no DNS/domain layer. List concrete hostnames or IPv4 CIDRs instead.`,o);r.push(o);}for(let o of r){let a=[];try{a=await e(o);}catch(i){throw new f("unresolvable-hostname",`Cannot pin hostname "${o}" to stable IPv4 addresses at create time (${i instanceof Error?i.message:String(i)}). Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,o)}if(a.length===0)throw new f("unresolvable-hostname",`Hostname "${o}" resolved to no IPv4 addresses. Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,o);console.warn(`[daytona] Network allowlist: pinning "${o}" to [${a.join(", ")}] (DNS resolved at create time). Daytona enforces IPv4 CIDRs only \u2014 if this host rotates DNS (CDNs and cloud APIs often do), traffic to its new IPs will be BLOCKED for the sandbox's lifetime.`);for(let i of a)n.push(`${i}/32`);}let d=[...new Set(n)];if(d.length>A)throw new f("allowlist-too-large",`Daytona allows at most ${A} entries in its network allowlist; this policy resolved to ${d.length} CIDRs (${d.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:d.join(",")}}function B(s){let e=s.indexOf("/");if(e<0)return;let t=s.substring(0,e);return t.includes(".")||t.includes(":")||t==="localhost"?t:void 0}function D(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function T(s){if(s==="started")return "running";if(s==="stopped"||s==="archived")return "paused"}var S=class extends Daytona{constructor(t,n){super(t);this.managedToolboxUrl=n;}async getProxyToolboxUrl(){return this.managedToolboxUrl}};function J(s,e){let t=new Uint8Array(new ArrayBuffer(s.length+e.length));return t.set(s,0),t.set(e,s.length),t}function $(s,e,t){e:for(let n=t;n+e.length<=s.length;n++){for(let r=0;r<e.length;r++)if(s[n+r]!==e[r])continue e;return n}return -1}function E(s,e){let t=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),r=new Uint8Array(0),d="stdout",o=a=>{a.length!==0&&(d==="stdout"?s(t.decode(a,{stream:true})):e(n.decode(a,{stream:true})));};return {push(a){for(r=J(r,a);;){let i=$(r,STDOUT_PREFIX_BYTES,0),c=$(r,STDERR_PREFIX_BYTES,0),l=-1,u="stdout",m=0;if(i!==-1&&(c===-1||i<c)?(l=i,u="stdout",m=STDOUT_PREFIX_BYTES.length):c!==-1&&(l=c,u="stderr",m=STDERR_PREFIX_BYTES.length),l===-1){let g=Math.max(0,r.length-(MAX_PREFIX_LEN-1));o(r.subarray(0,g)),r=r.slice(g);return}o(r.subarray(0,l)),d=u,r=r.slice(l+m);}},flush(){o(r),r=new Uint8Array(0);let a=t.decode();a&&s(a);let i=n.decode();i&&e(i);}}}async function L(s,e,t,n,r,d){let o=`${s.toolboxUrl.replace(/\/+$/,"")}/${encodeURIComponent(e)}/process/session/${encodeURIComponent(t)}/command/${encodeURIComponent(n)}/logs?follow=true`,a=await fetch(o,{headers:{Authorization:`Bearer ${s.apiKey}`,accept:"application/octet-stream"}});if(!a.ok)throw new Error(`Daytona managed log follow failed: ${a.status} ${await a.text()}`);if(!a.body)return;let i=E(r,d),c=a.body.getReader();try{for(;;){let{done:l,value:u}=await c.read();if(l)break;u&&i.push(u);}}finally{i.flush(),await c.cancel().catch(()=>{});}}function w(s){let e=s.stdout||"",t=s.stderr||"",n=s.output||"";return !e&&!t&&n?{stdout:n,stderr:""}:{stdout:e,stderr:t}}var v=class{constructor(e,t,n){this.sandbox=e;this.user=t;this.managedStream=n;}followLogs(e,t,n,r){return this.managedStream?L(this.managedStream,this.sandbox.id,e,t,n,r):this.sandbox.process.getSessionCommandLogs(e,t,n,r)}async run(e,t){let n=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,r=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(r);try{let d=await this.sandbox.process.executeSessionCommand(r,{command:x(e,t?.cwd,t?.envs,this.user),runAsync:!1},n),o=d.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.followLogs(r,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let{stdout:a,stderr:i}=w(d);if(!a&&!i&&o&&!t?.onStdout)try{let c=await this.sandbox.process.getSessionCommandLogs(r,o),l=w(c);a=l.stdout,i=l.stderr||i;}catch{}return {exitCode:d.exitCode??0,stdout:a,stderr:i}}finally{try{await this.sandbox.process.deleteSession(r);}catch{}}}async spawn(e,t){let n=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);let r=t?.timeoutMs?Math.floor(t.timeoutMs/1e3):void 0,d=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(n,{command:q(x(e,t?.cwd,t?.envs,this.user),r),runAsync:true},r)).cmdId;i&&(t?.onStdout||t?.onStderr)&&this.followLogs(n,i,t.onStdout||(()=>{}),t.onStderr||(()=>{})).catch(()=>{});let c=this.sandbox;return {processId:n,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-d>=o){try{await c.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let l=await c.process.getSessionCommand(n,i);if(l.exitCode!==void 0)try{let u=await c.process.getSessionCommandLogs(n,i);return {exitCode:l.exitCode,...w(u)}}catch{return {exitCode:l.exitCode,stdout:"",stderr:""}}}catch(l){let u=l instanceof Error?l.message.toLowerCase():String(l).toLowerCase();if(u.includes("not found")){let m=u.includes("sandbox");try{await c.refreshData(),m=!1;}catch(g){(g instanceof Error?g.message.toLowerCase():String(g).toLowerCase()).includes("not found")&&(m=true);}return {exitCode:-1,stdout:"",stderr:m?"sandbox deleted during run":"session terminated"}}throw l}await new Promise(l=>setTimeout(l,500));}},kill:async()=>{try{return await c.process.deleteSession(n),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(t=>({processId:t.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(e){try{return await this.sandbox.process.deleteSession(e),!0}catch{return false}}},P=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return j(e)?new Uint8Array(t):t.toString("utf-8")}async write(e,t){let n;if(typeof t=="string")n=Buffer.from(t,"utf-8");else if(Buffer.isBuffer(t))n=t;else if(t instanceof ArrayBuffer)n=Buffer.from(t);else if(t instanceof Uint8Array)n=Buffer.from(t);else throw new Error(`Unsupported content type: ${typeof t}`);await this.sandbox.fs.uploadFile(n,e);}async writeBatch(e){let t=e.map(n=>{let r;if(typeof n.data=="string")r=Buffer.from(n.data,"utf-8");else if(Buffer.isBuffer(n.data))r=n.data;else if(n.data instanceof ArrayBuffer)r=Buffer.from(n.data);else if(n.data instanceof Uint8Array)r=Buffer.from(n.data);else throw new Error(`Unsupported content type: ${typeof n.data}`);return {source:r,destination:n.path}});await this.sandbox.fs.uploadFiles(t);}async writeFromPath(e,t){await this.sandbox.fs.uploadFile(t,e);}async makeDir(e){await this.sandbox.fs.createFolder(e,"755");}async exists(e){try{let t=z(e),n=Y(e);return (await this.sandbox.fs.listFiles(t)).some(d=>d.name===n)}catch{return false}}async list(e){return (await this.sandbox.fs.listFiles(e)).map(n=>({name:n.name,path:e.endsWith("/")?`${e}${n.name}`:`${e}/${n.name}`,type:n.isDir?"dir":"file"}))}async remove(e){await this.sandbox.fs.deleteFile(e,true);}async rename(e,t){await this.sandbox.fs.moveFiles(e,t);}},y=class{constructor(e,t,n){this.sandbox=e;this.commands=new v(e,t,n),this.files=new P(e);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(e){return (await this.sandbox.getPreviewLink(e)).url}async isRunning(){try{await this.sandbox.refreshData();}catch{return false}return this.sandbox.state==="started"}async getInfo(){return await this.sandbox.refreshData(),D(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},I=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;sandboxUsers=new Map;managedStream;constructor(e){let t={apiKey:e.apiKey,apiUrl:e.apiUrl,target:e.target};this.client=e.managedToolboxUrl?new S(t,e.managedToolboxUrl):new Daytona(t),e.managedToolboxUrl&&(this.managedStream={toolboxUrl:e.managedToolboxUrl,apiKey:e.apiKey}),this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.snapshotName=e.snapshotName??"evolve-all";}async create(e){let t=await M(e.network),n=e.user,r=n&&n!=="root"?n:void 0,d=e.timeoutMs??this.defaultTimeoutMs,o=Math.max(1,Math.ceil(d/6e4)),a=e.image||this.snapshotName,i={envVars:e.envs,labels:e.metadata,autoStopInterval:o,autoDeleteInterval:K,...r?{user:r}:{},...t},c,l=e.resources!==void 0&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0);if(this.managedStream){if(l)throw new h(a);let u=await this.client.create({snapshot:a,...i},{timeout:600});return e.workingDirectory&&await u.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(u.id,n),new y(u,n,this.managedStream)}try{let u=await this.client.snapshot.get(a);if(u&&u.state==="active"){if(l)throw new h(a);console.log(`[daytona] Using cached snapshot: ${a}`),c=await this.client.create({snapshot:a,...i},{timeout:600});}else throw new Error("Snapshot not active")}catch(u){if(u instanceof h)throw u;let m=F[a]??a;console.log(`[daytona] Snapshot "${a}" not found, building from image: ${m}`),console.log("[daytona] First run will take a few minutes (this only happens once)...");try{await this.client.snapshot.create({name:a,image:Image.base(m),resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{onLogs:g=>console.log(`[daytona] ${g}`)}),console.log(`[daytona] Snapshot "${a}" ready.`),c=await this.client.create({snapshot:a,...i},{timeout:600});}catch(g){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${g instanceof Error?g.message:g}`);try{c=await this.client.create({image:m,...i,resources:{cpu:e.resources?.cpu??4,memory:e.resources?.memory??4,disk:e.resources?.disk??10}},{timeout:600,onSnapshotCreateLogs:p=>console.log(`[daytona] ${p}`)});}catch(p){throw B(m)?new b(m,p):p}}}return e.workingDirectory&&await c.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(c.id,n),new y(c,n,this.managedStream)}async connect(e,t){let n=await this.client.get(e);return n.state!=="started"&&await n.start(),new y(n,this.sandboxUsers.get(e),this.managedStream)}async list(e){let t=e?.limit??100,r=(await this.client.list(e?.metadata,1,t)).items;return e?.state&&(r=r.filter(d=>{let o=T(d.state);return o!==void 0&&e.state.includes(o)})),r.map(D)}};function ee(s={}){let e=s.apiKey??process.env.DAYTONA_API_KEY;if(!e)throw new Error("Daytona API key required. Set DAYTONA_API_KEY environment variable or pass apiKey in config. Get your key at https://app.daytona.io/dashboard/keys");return new I({...s,apiKey:e})}var te=x,ne=M,se=B,re=D,oe=T,ae=E,ie=L,de=w;
2
+ export{K as DAYTONA_AUTO_DELETE_GRACE_MINUTES,A as DAYTONA_MAX_NETWORK_ALLOWLIST,v as DaytonaCommands,P as DaytonaFiles,b as DaytonaImagePullError,f as DaytonaNetworkPolicyError,I as DaytonaProvider,h as DaytonaResourcesError,ae as _testCreateLogDemuxer,oe as _testDaytonaStateToEvolveState,ie as _testFollowManagedSessionLogs,se as _testImageRegistryHost,ne as _testMapNetworkPolicy,de as _testReadCommandStreams,re as _testToSandboxInfo,te as _testWrapCommand,ee as createDaytonaProvider};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolvingmachines/daytona",
3
- "version": "0.0.50",
3
+ "version": "0.0.52-project-sable.20260726.6e95f36",
4
4
  "keywords": [
5
5
  "ai",
6
6
  "agents",
@@ -33,7 +33,7 @@
33
33
  "build": "tsup --minify",
34
34
  "dev": "tsup --watch",
35
35
  "type-check": "tsc --noEmit",
36
- "test:unit": "tsx tests/unit/daytona-commands.test.ts"
36
+ "test:unit": "tsx tests/unit/daytona-commands.test.ts && tsx tests/unit/daytona-provider.test.ts && tsx tests/unit/daytona-managed.test.ts"
37
37
  },
38
38
  "dependencies": {
39
39
  "@daytonaio/sdk": "^0.134.0"