@evolvingmachines/daytona 0.0.52-project-sable.20260730.c2cb2d2 → 0.0.52-project-sable.20260810.ca7ed91
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/README.md +9 -1
- package/dist/index.cjs +7 -2
- package/dist/index.d.cts +277 -48
- package/dist/index.d.ts +277 -48
- package/dist/index.js +7 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
<br><br>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/evolving-machines-lab/evolve/main/logo/evolving-machines-ink.png" alt="Evolving Machines" width="380">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<br><br>
|
|
8
|
+
|
|
9
|
+
# Evolving Machines — Evolve Daytona Provider
|
|
2
10
|
|
|
3
11
|
Daytona sandbox provider for [Evolve SDK](https://www.npmjs.com/package/@evolvingmachines/sdk).
|
|
4
12
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
'use strict';var sdk=require('@daytonaio/sdk'),promises=require('dns/promises');var z={"evolve-all":"evolvingmachines/evolve-all"},q=10,L=10,T=100,y=100,W=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 X(s){let e=s.substring(s.lastIndexOf(".")).toLowerCase();return W.has(e)}function G(s){let e=s.lastIndexOf("/");return e>0?s.substring(0,e):"/"}function J(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;}},w=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;}},S=class extends Error{constructor(){super("Daytona has no separate idle timeout: auto-stop IS its only clock and it already measures inactivity, so `timeoutMs` is what sets it (autoStopInterval). Set the inactivity bound with `timeoutMs`; a hard bound on the process itself is enforced in-box instead (see withInBoxTimeout)."),this.name="DaytonaIdleTimeoutError";}};function v(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} && [ -s ${n} ] || { rm -f ${n}; exit 126; }; 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 P(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 V=s=>promises.resolve4(s);function E(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 Z(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!E(s)}function Q(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function ee(s){return /^[^:]+:\d+$/.test(s)}async function B(s,e=V){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(E(o))n.push(o.includes("/")?o:`${o}/32`);else {if(Z(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(Q(o))throw new f("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${o}".`,o);if(ee(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 l=[...new Set(n)];if(l.length>L)throw new f("allowlist-too-large",`Daytona allows at most ${L} entries in its network allowlist; this policy resolved to ${l.length} CIDRs (${l.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:l.join(",")}}function O(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 k(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function _(s){if(s==="started")return "running";if(s==="stopped"||s==="archived")return "paused"}var I=class extends sdk.Daytona{constructor(t,n){super(t);this.managedToolboxUrl=n;}async getProxyToolboxUrl(){return this.managedToolboxUrl}};function te(s,e){let t=new Uint8Array(new ArrayBuffer(s.length+e.length));return t.set(s,0),t.set(e,s.length),t}function U(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 N(s,e){let t=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),r=new Uint8Array(0),l="stdout",o=a=>{a.length!==0&&(l==="stdout"?s(t.decode(a,{stream:true})):e(n.decode(a,{stream:true})));};return {push(a){for(r=te(r,a);;){let i=U(r,sdk.STDOUT_PREFIX_BYTES,0),d=U(r,sdk.STDERR_PREFIX_BYTES,0),c=-1,u="stdout",m=0;if(i!==-1&&(d===-1||i<d)?(c=i,u="stdout",m=sdk.STDOUT_PREFIX_BYTES.length):d!==-1&&(c=d,u="stderr",m=sdk.STDERR_PREFIX_BYTES.length),c===-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,c)),l=u,r=r.slice(c+m);}},flush(){o(r),r=new Uint8Array(0);let a=t.decode();a&&s(a);let i=n.decode();i&&e(i);}}}async function F(s,e,t,n,r,l){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=N(r,l),d=a.body.getReader();try{for(;;){let{done:c,value:u}=await d.read();if(c)break;u&&i.push(u);}}finally{i.flush(),await d.cancel().catch(()=>{});}}function x(s){let e=s.stdout||"",t=s.stderr||"",n=s.output||"";return !e&&!t&&n?{stdout:n,stderr:""}:{stdout:e,stderr:t}}var D=class{constructor(e,t,n){this.sandbox=e;this.user=t;this.managedStream=n;}followLogs(e,t,n,r){return this.managedStream?F(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 l=await this.sandbox.process.executeSessionCommand(r,{command:v(P(e,t?.cwd,t?.envs,this.user),n),runAsync:!1},n),o=l.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.followLogs(r,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let{stdout:a,stderr:i}=x(l);if(!a&&!i&&o&&!t?.onStdout)try{let d=await this.sandbox.process.getSessionCommandLogs(r,o),c=x(d);a=c.stdout,i=c.stderr||i;}catch{}return {exitCode:l.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,l=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(n,{command:v(P(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 d=this.sandbox;return {processId:n,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-l>=o){try{await d.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let c=await d.process.getSessionCommand(n,i);if(c.exitCode!==void 0)try{let u=await d.process.getSessionCommandLogs(n,i);return {exitCode:c.exitCode,...x(u)}}catch{return {exitCode:c.exitCode,stdout:"",stderr:""}}}catch(c){let u=c instanceof Error?c.message.toLowerCase():String(c).toLowerCase();if(u.includes("not found")){let m=u.includes("sandbox");try{await d.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 c}await new Promise(c=>setTimeout(c,500));}},kill:async()=>{try{return await d.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}}},A=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return X(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=G(e),n=J(e);return (await this.sandbox.fs.listFiles(t)).some(l=>l.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);}},b=class{constructor(e,t,n){this.sandbox=e;this.commands=new D(e,t,n),this.files=new A(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(),k(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},C=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 I(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){if(e.idleTimeoutMs!==void 0)throw new S;let t=await B(e.network),n=e.user,r=n&&n!=="root"?n:void 0,l=e.timeoutMs??this.defaultTimeoutMs,o=Math.max(1,Math.ceil(l/6e4)),a=e.image||this.snapshotName,i={envVars:e.envs,labels:e.metadata,autoStopInterval:o,autoDeleteInterval:q,...r?{user:r}:{},...t},d,c=e.resources!==void 0&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0);if(this.managedStream){if(c)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 b(u,n,this.managedStream)}try{let u=await this.client.snapshot.get(a);if(u&&u.state==="active"){if(c)throw new h(a);console.log(`[daytona] Using cached snapshot: ${a}`),d=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=z[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.`),d=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{d=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 O(m)?new w(m,p):p}}}return e.workingDirectory&&await d.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(d.id,n),new b(d,n,this.managedStream)}async connect(e,t){let n=await this.client.get(e);return n.state!=="started"&&await n.start(),new b(n,this.sandboxUsers.get(e),this.managedStream)}async list(e){let t=await this.paginate(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...n}=await this.paginate(e);return n}async paginate(e){return K(t=>this.listPage(e,t),e)}async listPage(e,t){let n=e?.state?ne(e.state):void 0;if(n&&n.length>0){let r=this.client.sandboxApi;if(typeof r?.listSandboxesPaginated=="function")try{let l=await r.listSandboxesPaginated(void 0,t,T,void 0,void 0,e?.metadata?JSON.stringify(e.metadata):void 0,void 0,n);return {items:l.data.items,totalPages:l.data.totalPages}}catch{}}return this.client.list(e?.metadata,t,T)}};function ne(s){let e=[];for(let t of s)t==="running"&&e.push("started"),t==="paused"&&e.push("stopped","archived");return e}async function K(s,e){let t=e?.limit,n=[],r=0,l=new Set;for(let o=1;o<=y;o+=1){let a;try{a=await s(o);}catch(d){return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list failed: ${d instanceof Error?d.message:String(d)}`}}r+=1;for(let d of a.items){if(e?.state){let c=_(d.state);if(c===void 0||!e.state.includes(c))continue}if(!l.has(d.id)){if(t!==void 0&&n.length>=t)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${t} with more sandboxes available`};l.add(d.id),n.push(k(d));}}let i=a.items.length===0||typeof a.totalPages=="number"&&o>=a.totalPages;if(t!==void 0&&n.length>=t&&!i)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${t} with more sandboxes available`};if(i)break;if(o===y)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list exceeded ${y} pages`}}return {sandboxes:n,complete:true,pagesFetched:r,stoppedAtLimit:false}}var oe=K;function ae(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 C({...s,apiKey:e})}var ie=P,de=v,le=B,ce=O,ue=k,me=_,ge=N,fe=F,pe=x;
|
|
2
|
-
|
|
1
|
+
'use strict';var sdk=require('@daytonaio/sdk'),promises=require('dns/promises');var D="c-7bcda3467a79";var X={[`evolve-all-${D}`]:`evolvingmachines/evolve-all:${D}`,"evolve-all":"evolvingmachines/evolve-all"},ft=10,W=10,gt=18e4,pt=2e3,ht={pollMinMs:250,pollMaxMs:2e3,drainMs:1e3,killGraceMs:15e3,settleMs:6e4},v=s=>new Promise(t=>setTimeout(t,Math.max(0,s))),yt=100,I=1e4;function wt(s){let t=s.lastIndexOf("/");return t>0?s.substring(0,t):"/"}function xt(s){let t=s.lastIndexOf("/");return t>=0?s.substring(t+1):s}var h=class extends Error{reason;destination;constructor(t,e,n){super(e),this.name="DaytonaNetworkPolicyError",this.reason=t,this.destination=n;}},k=class extends Error{image;constructor(t,e){let n=e instanceof Error?e.message:String(e??"unknown error");super(`Failed to pull image "${t}" 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=t;}},j=class extends Error{snapshot;constructor(t){super(`Daytona cannot constrain the GPU type for "${t}": the snapshot already exists and pins its resources \u2014 pre-build a snapshot with the desired GPU type under its own name.`),this.name="DaytonaGpuTypeError",this.snapshot=t;}},P=class extends Error{snapshot;constructor(t){super(`Daytona snapshot "${t}" 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=t;}},C=class extends Error{constructor(){super("Daytona has no separate idle timeout: auto-stop IS its only clock and it already measures inactivity, so `timeoutMs` is what sets it (autoStopInterval). Set the inactivity bound with `timeoutMs`; a hard bound on the process itself is enforced in-box instead (see withInBoxTimeout)."),this.name="DaytonaIdleTimeoutError";}},y=class extends Error{snapshot;constructor(t,e){super(`Daytona snapshot "${t}" exists but could not be activated: ${e}. Daytona deactivates snapshots unused for 2 weeks; activation normally completes in seconds. Retry, or activate it manually in the Daytona dashboard (Snapshots page).`),this.name="DaytonaSnapshotActivationError",this.snapshot=t;}};async function Q(s,t,e,n){let o=n?.timeoutMs??gt,l=n?.pollMs??pt;console.log(`[daytona] Snapshot "${t}" is inactive (unused for 2+ weeks) \u2014 reactivating...`);let r;try{r=await s.snapshot.activate(e);}catch(i){throw new y(t,`the activate call failed (${i instanceof Error?i.message:String(i)})`)}let a=Date.now()+o;for(;r?.state!=="active";){if(r?.state==="error"||r?.state==="build_failed")throw new y(t,`it entered state "${r.state}"`);if(Date.now()>=a)throw new y(t,`still "${r?.state??"unknown"}" after ${o}ms`);await v(l);try{r=await s.snapshot.get(t);}catch(i){throw new y(t,`the activation poll failed (${i instanceof Error?i.message:String(i)})`)}}return console.log(`[daytona] Snapshot "${t}" reactivated.`),r}function $(s,t){if(!t||t<=0)return s;let e=Buffer.from(s).toString("base64"),n=`/tmp/.evolve-cmd-${Date.now()}-${Math.random().toString(36).slice(2,8)}.sh`;return `sh -c '${`echo ${e} | base64 -d > ${n} && [ -s ${n} ] || { rm -f ${n}; exit 126; }; if command -v timeout >/dev/null 2>&1; then timeout -k 10 ${t} bash ${n}; else bash ${n}; fi; rc=$?; rm -f ${n}; exit $rc`}'`}function V(){return `EVOLVE-EOS-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function T(s,t){return s.trim()?`{ :
|
|
2
|
+
${s}
|
|
3
|
+
|
|
4
|
+
}; __evolve_eos=$?; printf '%s' '${t}'; (exit $__evolve_eos)`:s}function Z(s,t){return s.endsWith(`${t}
|
|
5
|
+
`)?s.slice(0,-(t.length+1)):s.endsWith(t)?s.slice(0,-t.length):s}function x(s,t){let e=at(s);return {stdout:Z(e.stdout,t),stderr:e.stderr}}function M(s,t){let e=`${s}
|
|
6
|
+
`,n="",o=l=>{for(let r=Math.min(l.length,e.length);r>0;r--)if(e.startsWith(l.slice(l.length-r)))return r;return 0};return {push(l){n+=l;let r=o(n);r!==n.length&&(t(n.slice(0,n.length-r)),n=n.slice(n.length-r));},flush(){let l=n===e||n===s?"":n;n="",l&&t(l);}}}function E(s,t,e,n){let o=s;return t&&(o=`cd '${t.replace(/'/g,"'\\''")}' && ${o}`),e&&Object.keys(e).length>0&&(o=`${Object.entries(e).filter(([,r])=>r!=null).map(([r,a])=>`export ${r}='${String(a).replace(/'/g,"'\\''")}'`).join("; ")}; ${o}`),n==="root"&&(o=`echo ${Buffer.from(o).toString("base64")} | base64 -d | sudo -n bash`),o}var bt=s=>promises.resolve4(s);function J(s){let t=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(s);return !(!t||[t[1],t[2],t[3],t[4]].some(e=>Number(e)>255)||t[5]!==void 0&&Number(t[5])>32)}function St(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!J(s)}function vt(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function Pt(s){return /^[^:]+:\d+$/.test(s)}async function tt(s,t=bt){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 e=s.allowedDestinations??[];if(e.length===0)return {networkBlockAll:true};let n=[],o=[];for(let r of e)if(J(r))n.push(r.includes("/")?r:`${r}/32`);else {if(St(r))throw new h("invalid-ipv4",`"${r}" is not a valid IPv4 address or CIDR (octets must be 0-255, prefix 0-32). Fix the address or list a hostname instead.`,r);if(vt(r))throw new h("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${r}".`,r);if(Pt(r))throw new h("port-unsupported",`Daytona's network allowlist filters hosts and IPs only and cannot match a port; drop the ":<port>" from "${r}" and list just the host or IP.`,r);if(r.includes("*"))throw new h("wildcard-hostname",`Daytona cannot enforce wildcard hostname "${r}": its allowlist is kernel-level IPv4 CIDR filtering with no DNS/domain layer. List concrete hostnames or IPv4 CIDRs instead.`,r);o.push(r);}for(let r of o){let a=[];try{a=await t(r);}catch(i){throw new h("unresolvable-hostname",`Cannot pin hostname "${r}" 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.`,r)}if(a.length===0)throw new h("unresolvable-hostname",`Hostname "${r}" resolved to no IPv4 addresses. Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,r);console.warn(`[daytona] Network allowlist: pinning "${r}" 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 l=[...new Set(n)];if(l.length>W)throw new h("allowlist-too-large",`Daytona allows at most ${W} entries in its network allowlist; this policy resolved to ${l.length} CIDRs (${l.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:l.join(",")}}function et(s){let t=s.indexOf("/");if(t<0)return;let e=s.substring(0,t);return e.includes(".")||e.includes(":")||e==="localhost"?e:void 0}function U(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function nt(s){if(s==="started")return "running";if(s==="stopped"||s==="archived"||s==="paused")return "paused"}function st(s,t){if(!s||typeof s!="object")return;let e=s;if(typeof e.toolboxProxyUrl=="string"&&(e.toolboxProxyUrl=t),Array.isArray(e.items))for(let n of e.items)st(n,t);}function At(s,t){return new Proxy(s,{get(e,n,o){if(n==="getToolboxProxyUrl")return async()=>({data:{url:t}});let l=Reflect.get(e,n,o);return typeof l!="function"?l:function(...r){let a=l.apply(e,r);return a instanceof Promise?a.then(i=>(st(i?.data,t),i)):a}}})}var _=class extends sdk.Daytona{constructor(t,e){super(t);let n=this;n.sandboxApi=At(n.sandboxApi,e);}};function Dt(s,t){let e=new Uint8Array(new ArrayBuffer(s.length+t.length));return e.set(s,0),e.set(t,s.length),e}function q(s,t,e){t:for(let n=e;n+t.length<=s.length;n++){for(let o=0;o<t.length;o++)if(s[n+o]!==t[o])continue t;return n}return -1}function rt(s,t){let e=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),o=new Uint8Array(0),l="stdout",r=a=>{a.length!==0&&(l==="stdout"?s(e.decode(a,{stream:true})):t(n.decode(a,{stream:true})));};return {push(a){for(o=Dt(o,a);;){let i=q(o,sdk.STDOUT_PREFIX_BYTES,0),u=q(o,sdk.STDERR_PREFIX_BYTES,0),m=-1,d="stdout",c=0;if(i!==-1&&(u===-1||i<u)?(m=i,d="stdout",c=sdk.STDOUT_PREFIX_BYTES.length):u!==-1&&(m=u,d="stderr",c=sdk.STDERR_PREFIX_BYTES.length),m===-1){let f=Math.max(0,o.length-(sdk.MAX_PREFIX_LEN-1));r(o.subarray(0,f)),o=o.slice(f);return}r(o.subarray(0,m)),l=d,o=o.slice(m+c);}},flush(){r(o),o=new Uint8Array(0);let a=e.decode();a&&s(a);let i=n.decode();i&&t(i);}}}async function ot(s,t,e,n,o,l,r){let a=`${s.toolboxUrl.replace(/\/+$/,"")}/${encodeURIComponent(t)}/process/session/${encodeURIComponent(e)}/command/${encodeURIComponent(n)}/logs?follow=true`,i=await fetch(a,{headers:{Authorization:`Bearer ${s.apiKey}`,accept:"application/octet-stream"},...r?{signal:r}:{}});if(!i.ok)throw new Error(`Daytona managed log follow failed: ${i.status} ${await i.text()}`);if(!i.body)return;let u=rt(o,l),m=i.body.getReader();try{for(;;){let{done:d,value:c}=await m.read();if(d)break;c&&u.push(c);}}finally{u.flush(),await m.cancel().catch(()=>{});}}function at(s){let t=s.stdout||"",e=s.stderr||"",n=s.output||"";return !t&&!e&&n?{stdout:n,stderr:""}:{stdout:t,stderr:e}}var L=class{constructor(t,e,n){this.sandbox=t;this.user=e;this.managedStream=n;}streamTimings=ht;followLogs(t,e,n,o,l){return this.managedStream?ot(this.managedStream,this.sandbox.id,t,e,n,o,l):this.sandbox.process.getSessionCommandLogs(t,e,n,o)}async run(t,e){let n=e?.timeoutMs?Math.floor(e.timeoutMs/1e3):void 0,o=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(o);try{let l=!!(e?.onStdout||e?.onStderr),r=V(),a=await this.sandbox.process.executeSessionCommand(o,{command:$(E(T(t,r),e?.cwd,e?.envs,this.user),n),runAsync:l},n),i=a.cmdId;if(l&&!i)throw new Error("Daytona returned no command id for an async command \u2014 cannot stream it or read its exit code");if(l&&i){let d="",c="",f=!0,p=Date.now(),w=M(r,g=>{d+=g,e?.onStdout?.(g);}),B=new AbortController,N=this.followLogs(o,i,g=>{f&&(p=Date.now(),w.push(g));},g=>{f&&(p=Date.now(),c+=g,e?.onStderr?.(g));},B.signal),F=!1,b,dt=N.then(()=>{},g=>{F||(b=g);}),G;try{G=await this.awaitStreamedExit(o,i,N,()=>p,e?.timeoutMs);}finally{F=!0,B.abort(),await Promise.race([dt,v(this.streamTimings.drainMs)]),f=!1,b===void 0&&w.flush();}if(b!==void 0){let g;try{let lt=await this.sandbox.process.getSessionCommandLogs(o,i);g=x(lt,r);}catch{throw b}if(!g.stdout.startsWith(d)||!g.stderr.startsWith(c))throw b;let S=g.stdout.slice(d.length),K=g.stderr.slice(c.length);d=g.stdout,c=g.stderr,S&&e?.onStdout?.(S),K&&e?.onStderr?.(K);}else if(!d&&!c)try{let g=await this.sandbox.process.getSessionCommandLogs(o,i),S=x(g,r);d=S.stdout,c=S.stderr,d&&e?.onStdout?.(d),c&&e?.onStderr?.(c);}catch{}return {exitCode:G,stdout:d,stderr:c}}let{stdout:u,stderr:m}=x(a,r);if(!u&&!m&&i)try{let d=await this.sandbox.process.getSessionCommandLogs(o,i),c=x(d,r);u=c.stdout,m=c.stderr||m;}catch{}return {exitCode:a.exitCode??0,stdout:u,stderr:m}}finally{try{await this.sandbox.process.deleteSession(o);}catch{}}}async awaitStreamedExit(t,e,n,o,l){let r=this.streamTimings,a,i,u=n.then(()=>{a=Date.now();},c=>{a=Date.now(),i=c;}),m=l!==void 0&&l>0?Date.now()+l+r.killGraceMs:void 0,d=r.pollMinMs;for(;;){let c=await this.sandbox.process.getSessionCommand(t,e);if(c.exitCode!==void 0&&c.exitCode!==null){for(;a===void 0;){let w=Date.now()-o();if(w>=r.drainMs)break;await Promise.race([u,v(r.drainMs-w)]);}return c.exitCode}let f=a!==void 0?a+r.settleMs:void 0,p=m!==void 0&&f!==void 0?Math.min(m,f):m??f;if(p!==void 0&&Date.now()>=p)throw i!==void 0?i:new Error(`Daytona reported no exit code for command ${e} after `+(a!==void 0?"its log stream closed":`${l}ms`));await v(d),d=Math.min(d*2,r.pollMaxMs);}}async spawn(t,e){let n=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);let o=e?.timeoutMs?Math.floor(e.timeoutMs/1e3):void 0,l=Date.now(),r=e?.timeoutMs,a=V(),u=(await this.sandbox.process.executeSessionCommand(n,{command:$(E(T(t,a),e?.cwd,e?.envs,this.user),o),runAsync:true},o)).cmdId;if(u&&(e?.onStdout||e?.onStderr)){let d=M(a,e.onStdout||(()=>{}));this.followLogs(n,u,c=>d.push(c),e.onStderr||(()=>{})).catch(()=>{}).finally(()=>d.flush());}let m=this.sandbox;return {processId:n,wait:async()=>{if(!u)return {exitCode:0,stdout:"",stderr:""};for(;;){if(r&&Date.now()-l>=r){try{await m.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let d=await m.process.getSessionCommand(n,u);if(d.exitCode!==void 0)try{let c=await m.process.getSessionCommandLogs(n,u);return {exitCode:d.exitCode,...x(c,a)}}catch{return {exitCode:d.exitCode,stdout:"",stderr:""}}}catch(d){let c=d instanceof Error?d.message.toLowerCase():String(d).toLowerCase();if(c.includes("not found")){let f=c.includes("sandbox");try{await m.refreshData(),f=!1;}catch(p){(p instanceof Error?p.message.toLowerCase():String(p).toLowerCase()).includes("not found")&&(f=true);}return {exitCode:-1,stdout:"",stderr:f?"sandbox deleted during run":"session terminated"}}throw d}await v(500);}},kill:async()=>{try{return await m.process.deleteSession(n),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(e=>({processId:e.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(t){try{return await this.sandbox.process.deleteSession(t),!0}catch{return false}}},R=class{constructor(t){this.sandbox=t;}async read(t){let e=new Uint8Array(await this.sandbox.fs.downloadFile(t));if(!e.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{}return e}async write(t,e){let n;if(typeof e=="string")n=Buffer.from(e,"utf-8");else if(Buffer.isBuffer(e))n=e;else if(e instanceof ArrayBuffer)n=Buffer.from(e);else if(e instanceof Uint8Array)n=Buffer.from(e);else throw new Error(`Unsupported content type: ${typeof e}`);await this.sandbox.fs.uploadFile(n,t);}async writeBatch(t){let e=t.map(n=>{let o;if(typeof n.data=="string")o=Buffer.from(n.data,"utf-8");else if(Buffer.isBuffer(n.data))o=n.data;else if(n.data instanceof ArrayBuffer)o=Buffer.from(n.data);else if(n.data instanceof Uint8Array)o=Buffer.from(n.data);else throw new Error(`Unsupported content type: ${typeof n.data}`);return {source:o,destination:n.path}});await this.sandbox.fs.uploadFiles(e);}async writeFromPath(t,e){await this.sandbox.fs.uploadFile(e,t);}async makeDir(t){await this.sandbox.fs.createFolder(t,"755");}async exists(t){try{let e=wt(t),n=xt(t);return (await this.sandbox.fs.listFiles(e)).some(l=>l.name===n)}catch{return false}}async list(t){return (await this.sandbox.fs.listFiles(t)).map(n=>({name:n.name,path:t.endsWith("/")?`${t}${n.name}`:`${t}/${n.name}`,type:n.isDir?"dir":"file"}))}async remove(t){await this.sandbox.fs.deleteFile(t,true);}async rename(t,e){await this.sandbox.fs.moveFiles(t,e);}},A=class{constructor(t,e,n){this.sandbox=t;this.commands=new L(t,e,n),this.files=new R(t);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(t){return (await this.sandbox.getPreviewLink(t)).url}async isRunning(){try{await this.sandbox.refreshData();}catch{return false}return this.sandbox.state==="started"}async getInfo(){return await this.sandbox.refreshData(),U(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},O=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;sandboxUsers=new Map;managedStream;constructor(t){let e={apiKey:t.apiKey,apiUrl:t.apiUrl,target:t.target,useDeprecatedPolling:true};this.client=t.managedToolboxUrl?new _(e,t.managedToolboxUrl):new sdk.Daytona(e),t.managedToolboxUrl&&(this.managedStream={toolboxUrl:t.managedToolboxUrl,apiKey:t.apiKey}),this.defaultTimeoutMs=t.defaultTimeoutMs??36e5,this.snapshotName=t.snapshotName??(t.managedToolboxUrl?"evolve-all":`evolve-all-${D}`);}async create(t){if(t.idleTimeoutMs!==void 0)throw new C;let e=await tt(t.network),n=t.user,o=n&&n!=="root"?n:void 0,l=t.timeoutMs??this.defaultTimeoutMs,r=Math.max(1,Math.ceil(l/6e4)),a=t.image||this.snapshotName,i={envVars:t.envs,labels:t.metadata,autoStopInterval:r,autoDeleteInterval:ft,...o?{user:o}:{},...e},u,m=t.resources!==void 0&&(t.resources.cpu!==void 0||t.resources.memory!==void 0||t.resources.disk!==void 0||t.resources.gpu!==void 0||t.resources.gpuTypes!==void 0);if(this.managedStream){if(m)throw new P(a);let d=await this.client.create({snapshot:a,...i},{timeout:600});return t.workingDirectory&&await d.fs.createFolder(t.workingDirectory,"755"),n&&this.sandboxUsers.set(d.id,n),new A(d,n,this.managedStream)}try{let d=await this.client.snapshot.get(a),c=d?.state;if(d&&(c==="active"||c==="inactive")&&m)throw new P(a);if(d&&c==="inactive"&&(c=(await Q(this.client,a,d)).state),d&&c==="active")console.log(`[daytona] Using cached snapshot: ${a}`),u=await this.client.create({snapshot:a,...i},{timeout:600});else throw new Error("Snapshot not active")}catch(d){if(d instanceof P||d instanceof y)throw d;let c=X[a]??a;console.log(`[daytona] Snapshot "${a}" not found, building from image: ${c}`),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(c),resources:{cpu:t.resources?.cpu??4,memory:t.resources?.memory??4,disk:t.resources?.disk??10,...(t.resources?.gpu??0)>0?{gpu:t.resources.gpu}:{},...t.resources?.gpuTypes?.length?{gpuType:t.resources.gpuTypes}:{}}},{onLogs:f=>console.log(`[daytona] ${f}`)}),console.log(`[daytona] Snapshot "${a}" ready.`),u=await this.client.create({snapshot:a,...i},{timeout:600});}catch(f){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${f instanceof Error?f.message:f}`);try{u=await this.client.create({image:c,...i,resources:{cpu:t.resources?.cpu??4,memory:t.resources?.memory??4,disk:t.resources?.disk??10,...(t.resources?.gpu??0)>0?{gpu:t.resources.gpu}:{},...t.resources?.gpuTypes?.length?{gpuType:t.resources.gpuTypes}:{}}},{timeout:600,onSnapshotCreateLogs:p=>console.log(`[daytona] ${p}`)});}catch(p){throw et(c)?new k(c,p):p}}}return t.workingDirectory&&await u.fs.createFolder(t.workingDirectory,"755"),n&&this.sandboxUsers.set(u.id,n),new A(u,n,this.managedStream)}async connect(t,e){let n=await this.client.get(t);return n.state!=="started"&&await n.start(),new A(n,this.sandboxUsers.get(t),this.managedStream)}async list(t){let e=await this.paginate(t);if(e.error&&!e.stoppedAtLimit)throw new Error(e.error);return e.sandboxes}async listAll(t){let{stoppedAtLimit:e,...n}=await this.paginate(t);return n}async paginate(t){return it(this.listStream(t),t)}listStream(t){let e=t?.state?It(t.state):void 0,n={limit:yt,...t?.metadata?{labels:t.metadata}:{},...e&&e.length>0?{states:e}:{}};return this.client.list(n)}};function It(s){let t=[];for(let e of s)e==="running"&&t.push("started"),e==="paused"&&t.push("stopped","archived","paused");return t}async function it(s,t){let e=t?.limit,n=[],o=0,l=new Set;try{for await(let r of s){if(e!==void 0&&n.length>=e)return {sandboxes:n,complete:!1,pagesFetched:o,stoppedAtLimit:!0,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(o+=1,o>I)return {sandboxes:n,complete:!1,pagesFetched:I,stoppedAtLimit:!1,error:`sandbox list exceeded ${I} sandboxes scanned`};if(t?.state){let a=nt(r.state);if(a===void 0||!t.state.includes(a))continue}l.has(r.id)||(l.add(r.id),n.push(U(r)));}}catch(r){return {sandboxes:n,complete:false,pagesFetched:o,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return {sandboxes:n,complete:true,pagesFetched:o,stoppedAtLimit:false}}var Mt=it;function Et(s={}){let t=s.apiKey??process.env.DAYTONA_API_KEY;if(!t)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 O({...s,apiKey:t})}var _t=E,Lt=$,Rt=tt,Ot=et,Ut=U,Bt=nt,Nt=Q,Ft=X,Gt=T,Kt=Z,Ht=x,Yt=M,Wt=rt,jt=ot,Vt=at;
|
|
7
|
+
exports.DAYTONA_AUTO_DELETE_GRACE_MINUTES=ft;exports.DAYTONA_LIST_PAGE_SIZE=yt;exports.DAYTONA_MAX_LIST_SCAN=I;exports.DAYTONA_MAX_NETWORK_ALLOWLIST=W;exports.DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS=gt;exports.DAYTONA_STREAM_TIMINGS=ht;exports.DaytonaCommands=L;exports.DaytonaFiles=R;exports.DaytonaGpuTypeError=j;exports.DaytonaIdleTimeoutError=C;exports.DaytonaImagePullError=k;exports.DaytonaNetworkPolicyError=h;exports.DaytonaProvider=O;exports.DaytonaResourcesError=P;exports.DaytonaSnapshotActivationError=y;exports.EVOLVE_IMAGE_VERSION=D;exports._testActivateSnapshot=Nt;exports._testCollectSandboxStream=Mt;exports._testCreateLogDemuxer=Wt;exports._testCreateSentinelFilter=Yt;exports._testDaytonaStateToEvolveState=Bt;exports._testFollowManagedSessionLogs=jt;exports._testImageMap=Ft;exports._testImageRegistryHost=Ot;exports._testMapNetworkPolicy=Rt;exports._testReadCommandStreams=Vt;exports._testSettledStreams=Ht;exports._testStripEndOfOutputSentinel=Kt;exports._testToSandboxInfo=Ut;exports._testWithEndOfOutputSentinel=Gt;exports._testWithInBoxTimeout=Lt;exports._testWrapCommand=_t;exports.createDaytonaProvider=Et;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { Sandbox } from '@daytonaio/sdk';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* GENERATED — DO NOT EDIT. `npm run generate:image-version` (repo root)
|
|
5
|
+
* rewrites this file from the evolve-all image build inputs under
|
|
6
|
+
* assets/docker/ (see assets/docker/image-digest.ts for the derivation).
|
|
7
|
+
* The value is content-addressed: same inputs → same tag, any input
|
|
8
|
+
* change → a new tag. The coherence test in
|
|
9
|
+
* packages/daytona/tests/unit/daytona-image-version.test.ts fails the
|
|
10
|
+
* suite whenever this checked-in copy is stale.
|
|
11
|
+
*/
|
|
12
|
+
declare const EVOLVE_IMAGE_VERSION = "c-7bcda3467a79";
|
|
13
|
+
|
|
3
14
|
/**
|
|
4
15
|
* Daytona Sandbox Provider
|
|
5
16
|
*
|
|
6
|
-
* @requires @daytonaio/sdk >= 0.
|
|
17
|
+
* @requires @daytonaio/sdk >= 0.203.0 (cursor-based list pagination; Daytona
|
|
18
|
+
* retired the page-numbered endpoint on 2026-06-25)
|
|
7
19
|
*
|
|
8
20
|
* Design principles:
|
|
9
21
|
* - Mirror E2B provider interface for SDK compatibility
|
|
@@ -47,17 +59,49 @@ import { Sandbox } from '@daytonaio/sdk';
|
|
|
47
59
|
declare const DAYTONA_AUTO_DELETE_GRACE_MINUTES = 10;
|
|
48
60
|
declare const DAYTONA_MAX_NETWORK_ALLOWLIST = 10;
|
|
49
61
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
62
|
+
* How long a reactivated snapshot may take to come back before create() gives
|
|
63
|
+
* up. Daytona deactivates any snapshot unused for two weeks (official docs:
|
|
64
|
+
* "Snapshots automatically become inactive after 2 weeks of not being used"),
|
|
65
|
+
* so exists-but-inactive is the steady state of every image that shipped more
|
|
66
|
+
* than a fortnight before its next user — reactivation is a pull, not a build,
|
|
67
|
+
* and one that outlives this bound is a provider incident worth a loud error.
|
|
68
|
+
*/
|
|
69
|
+
declare const DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS = 180000;
|
|
70
|
+
/**
|
|
71
|
+
* Clocks of a STREAMED run (see awaitStreamedExit). The poll that reads the
|
|
72
|
+
* command's exit code backs off from pollMin to pollMax. A follow whose
|
|
73
|
+
* command has already ended is cut once it has been SILENT for drainMs —
|
|
74
|
+
* silence, never elapsed time, so a stream still delivering is never
|
|
75
|
+
* truncated. killGrace is what the caller's timeoutMs is widened by before a
|
|
76
|
+
* streamed run gives up, because withInBoxTimeout kills with `timeout -k 10`:
|
|
77
|
+
* the box may legitimately take ten seconds past the deadline to record a
|
|
78
|
+
* status. And a follow that has CLOSED means the command ended, so its record
|
|
79
|
+
* must catch up within settleMs — the only backstop a caller who passed no
|
|
80
|
+
* timeoutMs has, which is why it is generous rather than tight.
|
|
81
|
+
*/
|
|
82
|
+
declare const DAYTONA_STREAM_TIMINGS: {
|
|
83
|
+
pollMinMs: number;
|
|
84
|
+
pollMaxMs: number;
|
|
85
|
+
drainMs: number;
|
|
86
|
+
killGraceMs: number;
|
|
87
|
+
settleMs: number;
|
|
88
|
+
};
|
|
89
|
+
type DaytonaStreamTimings = typeof DAYTONA_STREAM_TIMINGS;
|
|
90
|
+
/**
|
|
91
|
+
* Sandboxes requested per list fetch — the cursor API's per-page size
|
|
92
|
+
* (ListSandboxesQuery.limit bounds one fetch, never the total). Held at the
|
|
93
|
+
* value every provider in this lineup accepts, so one number is valid
|
|
94
|
+
* everywhere a fleet is enumerated.
|
|
52
95
|
*/
|
|
53
96
|
declare const DAYTONA_LIST_PAGE_SIZE = 100;
|
|
54
97
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* a
|
|
98
|
+
* Row ceiling for one enumeration — the same 10,000 sandboxes the old
|
|
99
|
+
* 100-pages-of-100 ceiling allowed, restated in rows because cursor pagination
|
|
100
|
+
* has no page numbers to count. A walk that reaches it stops and reports
|
|
101
|
+
* itself INCOMPLETE, because the one thing a fleet enumeration may never do is
|
|
102
|
+
* return a short list that reads like a whole one.
|
|
59
103
|
*/
|
|
60
|
-
declare const
|
|
104
|
+
declare const DAYTONA_MAX_LIST_SCAN = 10000;
|
|
61
105
|
/** Why a network policy cannot be enforced by Daytona. */
|
|
62
106
|
type DaytonaNetworkPolicyReason = "wildcard-hostname" | "ipv6-unsupported" | "port-unsupported" | "invalid-ipv4" | "unresolvable-hostname" | "allowlist-too-large";
|
|
63
107
|
/**
|
|
@@ -95,6 +139,19 @@ declare class DaytonaImagePullError extends Error {
|
|
|
95
139
|
* (reject what you cannot enforce) it is refused loudly instead: pre-build a
|
|
96
140
|
* snapshot with the desired sizing under its own name, or drop `resources`.
|
|
97
141
|
*/
|
|
142
|
+
/**
|
|
143
|
+
* @deprecated No longer thrown. @daytonaio/sdk 0.203.0 grew a real
|
|
144
|
+
* `Resources.gpuType` field, so `resources.gpuTypes` is now FORWARDED on the
|
|
145
|
+
* snapshot-build path instead of refused (Daytona validates the type names
|
|
146
|
+
* server-side). Sizing against an EXISTING snapshot — GPU type included —
|
|
147
|
+
* still throws DaytonaResourcesError like every other pinned field. The class
|
|
148
|
+
* stays exported so callers with `instanceof` checks keep compiling.
|
|
149
|
+
*/
|
|
150
|
+
declare class DaytonaGpuTypeError extends Error {
|
|
151
|
+
/** The snapshot/image the create named. */
|
|
152
|
+
readonly snapshot: string;
|
|
153
|
+
constructor(snapshot: string);
|
|
154
|
+
}
|
|
98
155
|
declare class DaytonaResourcesError extends Error {
|
|
99
156
|
/** The existing snapshot whose pinned sizing cannot be overridden. */
|
|
100
157
|
readonly snapshot: string;
|
|
@@ -109,6 +166,45 @@ declare class DaytonaResourcesError extends Error {
|
|
|
109
166
|
declare class DaytonaIdleTimeoutError extends Error {
|
|
110
167
|
constructor();
|
|
111
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Typed error for a snapshot that exists but could not be brought back to
|
|
171
|
+
* `active`. This is a final verdict, not a build trigger: the snapshot IS
|
|
172
|
+
* there, so rebuilding under the same name can only fail on the name conflict
|
|
173
|
+
* and then mask the real problem behind a slow direct image pull.
|
|
174
|
+
*/
|
|
175
|
+
declare class DaytonaSnapshotActivationError extends Error {
|
|
176
|
+
/** The snapshot that would not activate. */
|
|
177
|
+
readonly snapshot: string;
|
|
178
|
+
constructor(snapshot: string, detail: string);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The slice of the Daytona client the reactivation path touches — structural,
|
|
182
|
+
* so the unit tests can drive it with a plain mock.
|
|
183
|
+
*/
|
|
184
|
+
interface SnapshotActivationClient {
|
|
185
|
+
snapshot: {
|
|
186
|
+
get(name: string): Promise<{
|
|
187
|
+
state?: string;
|
|
188
|
+
}>;
|
|
189
|
+
activate(snapshot: unknown): Promise<{
|
|
190
|
+
state?: string;
|
|
191
|
+
}>;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Bring an exists-but-inactive snapshot back to `active`, or say loudly why
|
|
196
|
+
* not. Activation is asynchronous on Daytona's side — the activate call may
|
|
197
|
+
* answer with a transitional state (`pulling`) — so the result is polled until
|
|
198
|
+
* it lands on `active`, a terminal failure state, or the deadline.
|
|
199
|
+
*/
|
|
200
|
+
declare function activateSnapshot(client: SnapshotActivationClient, name: string, snapshot: {
|
|
201
|
+
state?: string;
|
|
202
|
+
}, timing?: {
|
|
203
|
+
timeoutMs?: number;
|
|
204
|
+
pollMs?: number;
|
|
205
|
+
}): Promise<{
|
|
206
|
+
state?: string;
|
|
207
|
+
}>;
|
|
112
208
|
/**
|
|
113
209
|
* Wrap command with cwd and envs shell prefixes, and (for user "root") a
|
|
114
210
|
* `sudo -n` elevation wrapper.
|
|
@@ -163,6 +259,79 @@ declare class DaytonaIdleTimeoutError extends Error {
|
|
|
163
259
|
* to every caller that checks.
|
|
164
260
|
*/
|
|
165
261
|
declare function withInBoxTimeout(wrapped: string, timeoutSec?: number): string;
|
|
262
|
+
/**
|
|
263
|
+
* NOTHING IS APPENDED TO THE CALLER'S LAST LINE. The command goes inside a
|
|
264
|
+
* brace group whose closing brace opens a line of its own, so what follows is
|
|
265
|
+
* never read as a continuation of whatever the command ended with. Appending
|
|
266
|
+
* `; ...` directly broke three shapes, all measured:
|
|
267
|
+
*
|
|
268
|
+
* a command ending in a NEWLINE (every multi-line template literal) —
|
|
269
|
+
* `\n; __evolve_eos=$?` is a syntax error, exit 2
|
|
270
|
+
* a command ending in `&` — `& ;` is a syntax error and the command NEVER RAN
|
|
271
|
+
* a HEREDOC whose terminator is the command's last line — the appended text
|
|
272
|
+
* became part of the heredoc BODY: no error, exit 0, corrupt payload. That
|
|
273
|
+
* is the shape of the managed-secret proxy readiness probe (agent.ts), and
|
|
274
|
+
* it turned a healthy proxy into "failed to start".
|
|
275
|
+
*
|
|
276
|
+
* The group needs two guards of its own, both measured against /bin/sh,
|
|
277
|
+
* /bin/bash and /bin/dash:
|
|
278
|
+
*
|
|
279
|
+
* a leading `:` so the body is never EMPTY. A comment-only command
|
|
280
|
+
* (`# nothing`) otherwise leaves `{ # nothing\n}` — "syntax error near
|
|
281
|
+
* unexpected token `}'", exit 2, where the caller's own shell would have
|
|
282
|
+
* done nothing and exited 0. It runs BEFORE the command, so the status the
|
|
283
|
+
* group reports is still the command's own.
|
|
284
|
+
* a BLANK LINE before the closing brace, to be eaten by a command that ends
|
|
285
|
+
* in a dangling backslash. That backslash continues onto whatever line
|
|
286
|
+
* comes next; the blank line is what it consumes instead of the `}`, and
|
|
287
|
+
* `echo HI \` then runs as the caller's shell would run it — exit 0, "HI",
|
|
288
|
+
* with the exit code of a failing one (`false \` -> 1) still its own.
|
|
289
|
+
*
|
|
290
|
+
* WHAT STILL FAILS, LOUDLY: an UNTERMINATED heredoc (`cat <<'EOF'` with no
|
|
291
|
+
* EOF line). Its body swallows everything that follows, including the closing
|
|
292
|
+
* brace, so the command is a syntax error — exit 2, no output, the shell's own
|
|
293
|
+
* message on stderr. No text can fix that from out here: anything added lands
|
|
294
|
+
* inside the heredoc. A shell run of the same input without a wrapper prints
|
|
295
|
+
* the body and exits 0, so this is the one shape the sentinel changes, and it
|
|
296
|
+
* changes it to a loud failure rather than a quiet wrong answer.
|
|
297
|
+
*/
|
|
298
|
+
declare function withEndOfOutputSentinel(command: string, token: string): string;
|
|
299
|
+
/**
|
|
300
|
+
* Shed the sentinel, and the terminator the transport put after it, from a
|
|
301
|
+
* settled stream.
|
|
302
|
+
*
|
|
303
|
+
* ONLY AT THE END, because that is the only place the sentinel can be: it is
|
|
304
|
+
* the last thing the command prints. A token anywhere else in the output is
|
|
305
|
+
* the caller's own bytes — `ps` shows this very command line, and `sh -x`
|
|
306
|
+
* traces the printf that writes it — and deleting those would be corruption,
|
|
307
|
+
* silent and impossible to debug.
|
|
308
|
+
*/
|
|
309
|
+
declare function stripEndOfOutputSentinel(text: string, token: string): string;
|
|
310
|
+
/**
|
|
311
|
+
* A settled log read with the sentinel shed — from STDOUT only, because that is
|
|
312
|
+
* the only stream the command prints one to. Shedding anything from stderr
|
|
313
|
+
* could only ever delete bytes the command itself wrote (`sh -x` traces the
|
|
314
|
+
* printf that writes the token, and that trace goes to stderr).
|
|
315
|
+
*/
|
|
316
|
+
declare function settledStreams(logs: unknown, token: string): {
|
|
317
|
+
stdout: string;
|
|
318
|
+
stderr: string;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Shed the sentinel from a stream still arriving, without holding back output
|
|
322
|
+
* that is merely on its way.
|
|
323
|
+
*
|
|
324
|
+
* Same rule as the settled read — only the end of the stream can be the
|
|
325
|
+
* sentinel — applied to bytes still coming: what could still GROW INTO it (the
|
|
326
|
+
* longest tail that is a prefix of `<token>\n`) waits for the rest, and
|
|
327
|
+
* everything else goes straight through, so a chunk that cannot be the start
|
|
328
|
+
* of a sentinel is never delayed. Nothing mid-stream is ever dropped.
|
|
329
|
+
*/
|
|
330
|
+
declare function createSentinelFilter(token: string, emit: (chunk: string) => void): {
|
|
331
|
+
push(chunk: string): void;
|
|
332
|
+
/** The stream is over: what was held is the sentinel, or it was output after all. */
|
|
333
|
+
flush(): void;
|
|
334
|
+
};
|
|
166
335
|
declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>, user?: string): string;
|
|
167
336
|
/** Daytona create() params derived from Evolve's provider-neutral network policy. */
|
|
168
337
|
interface DaytonaNetworkCreateParams {
|
|
@@ -214,8 +383,10 @@ interface DaytonaSandboxLike {
|
|
|
214
383
|
declare function toSandboxInfo(sandbox: DaytonaSandboxLike): SandboxInfo;
|
|
215
384
|
/**
|
|
216
385
|
* Map a Daytona sandbox state onto Evolve's list() filter states.
|
|
217
|
-
* "started" → running; "stopped"/"archived" → paused (our pause()
|
|
218
|
-
* sandbox
|
|
386
|
+
* "started" → running; "stopped"/"archived"/"paused" → paused (our pause()
|
|
387
|
+
* stops the sandbox; Daytona 0.203.0 added a native "paused" state for
|
|
388
|
+
* pause-capable sandbox classes, and a box resting in it is paused by any
|
|
389
|
+
* reading); transitional and terminal states match no filter.
|
|
219
390
|
*/
|
|
220
391
|
declare function daytonaStateToEvolveState(state?: string): "running" | "paused" | undefined;
|
|
221
392
|
/** Result of a completed sandbox command */
|
|
@@ -275,6 +446,19 @@ interface SandboxResources {
|
|
|
275
446
|
memory?: number;
|
|
276
447
|
/** Disk in GB (default: 10) */
|
|
277
448
|
disk?: number;
|
|
449
|
+
/**
|
|
450
|
+
* GPU reservation (count). Applied when a SNAPSHOT IS BUILT (Daytona
|
|
451
|
+
* allocates GPU at snapshot build; GPU machines are tier-gated on Daytona's
|
|
452
|
+
* side) — against an existing snapshot it throws DaytonaResourcesError like
|
|
453
|
+
* every other pinned sizing field.
|
|
454
|
+
*/
|
|
455
|
+
gpu?: number;
|
|
456
|
+
/**
|
|
457
|
+
* Acceptable GPU types (Daytona's GpuType names, e.g. "H100", "H200",
|
|
458
|
+
* "RTX-PRO-6000"). Forwarded on the build path — Daytona validates the
|
|
459
|
+
* names server-side — and refused on an existing snapshot alongside `gpu`.
|
|
460
|
+
*/
|
|
461
|
+
gpuTypes?: string[];
|
|
278
462
|
}
|
|
279
463
|
/** Options for creating a sandbox */
|
|
280
464
|
interface SandboxCreateOptions {
|
|
@@ -345,6 +529,13 @@ interface SandboxListOptions {
|
|
|
345
529
|
interface SandboxListPage {
|
|
346
530
|
sandboxes: SandboxInfo[];
|
|
347
531
|
complete: boolean;
|
|
532
|
+
/**
|
|
533
|
+
* Fetch units consumed: rows scanned from the cursor stream (before
|
|
534
|
+
* filtering). Cursor pagination has no page numbers to count — and the modal
|
|
535
|
+
* provider already reports item counts here — so "pages" reads as "units of
|
|
536
|
+
* enumeration work", kept under this name because the field is shared
|
|
537
|
+
* provider-neutral surface.
|
|
538
|
+
*/
|
|
348
539
|
pagesFetched: number;
|
|
349
540
|
error?: string;
|
|
350
541
|
}
|
|
@@ -402,7 +593,7 @@ interface DaytonaConfig {
|
|
|
402
593
|
target?: string;
|
|
403
594
|
/** Default timeout in ms */
|
|
404
595
|
defaultTimeoutMs?: number;
|
|
405
|
-
/** Daytona snapshot name (default: 'evolve-all'). Create custom snapshots via `cd assets && ./build.sh daytona` */
|
|
596
|
+
/** Daytona snapshot name (default: 'evolve-all-<EVOLVE_IMAGE_VERSION>' direct, the platform's stable 'evolve-all' managed). Explicit names pass through untouched. Create custom snapshots via `cd assets && ./build.sh daytona` */
|
|
406
597
|
snapshotName?: string;
|
|
407
598
|
/**
|
|
408
599
|
* Evolve-managed toolbox base URL. Setting it puts the provider in MANAGED
|
|
@@ -466,7 +657,7 @@ declare function createLogDemuxer(onStdout: (chunk: string) => void, onStderr: (
|
|
|
466
657
|
* streaming through a plain response body, which is what the Dashboard route
|
|
467
658
|
* pipes through unbuffered.
|
|
468
659
|
*/
|
|
469
|
-
declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): Promise<void>;
|
|
660
|
+
declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void, signal?: AbortSignal): Promise<void>;
|
|
470
661
|
/**
|
|
471
662
|
* Read a command's streams out of whatever shape Daytona returned.
|
|
472
663
|
*
|
|
@@ -495,15 +686,44 @@ declare class DaytonaCommands implements SandboxCommands {
|
|
|
495
686
|
private sandbox;
|
|
496
687
|
private user?;
|
|
497
688
|
private managedStream?;
|
|
689
|
+
/** The streamed-run clocks, shrinkable by a subclass so a test need not wait them out. */
|
|
690
|
+
protected streamTimings: DaytonaStreamTimings;
|
|
498
691
|
constructor(sandbox: Sandbox, user?: string | undefined, managedStream?: ManagedStreamContext | undefined);
|
|
499
692
|
/**
|
|
500
693
|
* Stream a command's output to callbacks. Direct mode uses the Daytona
|
|
501
694
|
* SDK's own follow, which is a websocket; managed mode uses the HTTP
|
|
502
695
|
* chunked follow, because a Dashboard route handler cannot terminate a
|
|
503
696
|
* websocket upgrade (see followManagedSessionLogs).
|
|
697
|
+
*
|
|
698
|
+
* Only the managed follow takes the abandon signal — the SDK's websocket
|
|
699
|
+
* follow exposes none, so a direct-mode stall is stopped from waiting on
|
|
700
|
+
* but not closed; the ephemeral session's delete is what ends it.
|
|
504
701
|
*/
|
|
505
702
|
private followLogs;
|
|
506
703
|
run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
|
|
704
|
+
/**
|
|
705
|
+
* WHAT SAYS A STREAMED RUN IS OVER: the command's record, never the follow.
|
|
706
|
+
*
|
|
707
|
+
* A chunked follow can stall open long after its command exited — nothing
|
|
708
|
+
* acks a response body — and awaiting it first, then polling for an exit
|
|
709
|
+
* code 20 times at 500ms, gave a streaming run() two failure modes the
|
|
710
|
+
* blocking path never had: a stalled socket hung run() forever (with no
|
|
711
|
+
* timeoutMs, nothing in the box or out of it bounds the wait), and a follow
|
|
712
|
+
* that closed a moment early threw "no exit code" on a command that had
|
|
713
|
+
* already succeeded.
|
|
714
|
+
*
|
|
715
|
+
* So the poll and the follow run TOGETHER. The poll decides when the run
|
|
716
|
+
* ended; the follow then gets as long as it keeps delivering and is cut
|
|
717
|
+
* only once it has been SILENT for the drain window, so a live stream is
|
|
718
|
+
* never truncated and a dead one is never waited on. Two ceilings bound the
|
|
719
|
+
* wait: the caller's timeoutMs widened by the in-box kill grace, and — for
|
|
720
|
+
* the caller who passed none — the settle bound measured from the moment
|
|
721
|
+
* the follow closed, because a closed stream means the command ended and a
|
|
722
|
+
* record that never catches up is a provider incident, not a long run.
|
|
723
|
+
* A run with no timeoutMs whose command is genuinely still streaming is
|
|
724
|
+
* still waited on indefinitely: that is what asking for no bound means.
|
|
725
|
+
*/
|
|
726
|
+
private awaitStreamedExit;
|
|
507
727
|
spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
|
|
508
728
|
list(): Promise<ProcessInfo[]>;
|
|
509
729
|
kill(processId: string): Promise<boolean>;
|
|
@@ -551,18 +771,21 @@ declare class DaytonaProvider implements SandboxProvider {
|
|
|
551
771
|
create(options: SandboxCreateOptions): Promise<SandboxInstance>;
|
|
552
772
|
connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
|
|
553
773
|
/**
|
|
554
|
-
* List sandboxes, walking
|
|
774
|
+
* List sandboxes, walking the cursor stream to exhaustion.
|
|
555
775
|
*
|
|
556
|
-
*
|
|
776
|
+
* An early version requested page 1 and stopped, discarding the rest — an
|
|
557
777
|
* organization with more than one page of sandboxes was silently truncated,
|
|
558
778
|
* and nothing in the return value said so. For any caller that reads absence
|
|
559
|
-
* from the list as "this sandbox is gone", that is a correctness bug.
|
|
779
|
+
* from the list as "this sandbox is gone", that is a correctness bug. Cursor
|
|
780
|
+
* pagination (mandatory since Daytona retired page numbers on 2026-06-25)
|
|
781
|
+
* changes the mechanics, not the law: the walk still runs to the end or says
|
|
782
|
+
* it could not.
|
|
560
783
|
*
|
|
561
|
-
* ORDER OF OPERATIONS, because it is observable: `limit` bounds the
|
|
562
|
-
* RETURNED, and
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
784
|
+
* ORDER OF OPERATIONS, because it is observable: `limit` bounds the
|
|
785
|
+
* sandboxes RETURNED, and the state filter runs client-side on every row
|
|
786
|
+
* BEFORE the limit is counted. Asking for 10 running sandboxes therefore
|
|
787
|
+
* keeps walking until ten running ones have been found, rather than
|
|
788
|
+
* filtering ten arbitrary rows down to whatever survives.
|
|
566
789
|
*/
|
|
567
790
|
list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
|
|
568
791
|
/**
|
|
@@ -576,45 +799,45 @@ declare class DaytonaProvider implements SandboxProvider {
|
|
|
576
799
|
listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
|
|
577
800
|
private paginate;
|
|
578
801
|
/**
|
|
579
|
-
*
|
|
802
|
+
* The cursor stream, asking the API to narrow server-side where it can.
|
|
580
803
|
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
* So the server filter is applied OPPORTUNISTICALLY, through the private
|
|
590
|
-
* field when it is shaped the way we expect, and the client-side filter in
|
|
591
|
-
* the walk stays the authority regardless. That ordering is the whole point:
|
|
592
|
-
* if a future SDK refactor renames or removes the field, this degrades to the
|
|
593
|
-
* request count it has today, and can never degrade to admitting states the
|
|
594
|
-
* caller excluded.
|
|
804
|
+
* Since 0.203.0 the SDK's public `list(query)` takes `states` and `labels`
|
|
805
|
+
* directly and pages by cursor internally (items + nextCursor,
|
|
806
|
+
* esm/Daytona.js:430-476), so the old reach-around through the private
|
|
807
|
+
* `sandboxApi.listSandboxesPaginated` field is gone along with the method
|
|
808
|
+
* itself. The client-side filter in the walk stays the authority regardless:
|
|
809
|
+
* a server filter that silently stopped applying must never be able to admit
|
|
810
|
+
* a state the caller excluded.
|
|
595
811
|
*/
|
|
596
|
-
private
|
|
597
|
-
}
|
|
598
|
-
/** One page as Daytona's `list(labels?, page?, limit?)` returns it. */
|
|
599
|
-
interface DaytonaSandboxPage {
|
|
600
|
-
items: Sandbox[];
|
|
601
|
-
totalPages?: number;
|
|
812
|
+
private listStream;
|
|
602
813
|
}
|
|
603
814
|
/**
|
|
604
|
-
* Walk
|
|
815
|
+
* Walk the cursor stream into one answer, with an honest completeness verdict.
|
|
605
816
|
*
|
|
606
817
|
* Separate from the provider because everything worth getting wrong lives here
|
|
607
818
|
* and none of it needs a network: the ways a walk can fail to terminate, the
|
|
608
|
-
* difference between "the caller asked for ten" and "the provider ran out",
|
|
609
|
-
* the rule that a failure mid-walk yields the sandboxes seen so far marked
|
|
819
|
+
* difference between "the caller asked for ten" and "the provider ran out",
|
|
820
|
+
* and the rule that a failure mid-walk yields the sandboxes seen so far marked
|
|
610
821
|
* INCOMPLETE rather than either an exception or a short complete list.
|
|
611
822
|
*
|
|
612
|
-
*
|
|
823
|
+
* WHAT CURSORS CHANGED HERE, and what they did not. The vendor's iterator ends
|
|
824
|
+
* itself when nextCursor runs out, so "exhausted" is now the stream ending
|
|
825
|
+
* rather than a totalPages comparison; a fetch failure mid-walk surfaces as
|
|
826
|
+
* the iterator throwing. The LAWS are unchanged: a walk that could not finish
|
|
827
|
+
* reports `complete: false` with what it saw, a caller's limit is reported as
|
|
828
|
+
* truncation whenever one more row provably exists (the row after the limit is
|
|
829
|
+
* that proof — the walk holds it, so no extra fetch is spent on it beyond, at
|
|
830
|
+
* worst, the one the iterator was already making), and a runaway fleet stops
|
|
831
|
+
* at the scan ceiling as a refusal, never as a short list that reads complete.
|
|
832
|
+
*
|
|
833
|
+
* Exported for its test (`_testCollectSandboxStream`).
|
|
613
834
|
*/
|
|
614
|
-
declare function
|
|
835
|
+
declare function collectSandboxStream(stream: AsyncIterable<DaytonaSandboxLike & {
|
|
836
|
+
state?: string;
|
|
837
|
+
}>, options?: SandboxListOptions): Promise<SandboxListPage & {
|
|
615
838
|
stoppedAtLimit: boolean;
|
|
616
839
|
}>;
|
|
617
|
-
declare const
|
|
840
|
+
declare const _testCollectSandboxStream: typeof collectSandboxStream;
|
|
618
841
|
/**
|
|
619
842
|
* Create Daytona sandbox provider.
|
|
620
843
|
*
|
|
@@ -629,8 +852,14 @@ declare const _testMapNetworkPolicy: typeof mapNetworkPolicy;
|
|
|
629
852
|
declare const _testImageRegistryHost: typeof imageRegistryHost;
|
|
630
853
|
declare const _testToSandboxInfo: typeof toSandboxInfo;
|
|
631
854
|
declare const _testDaytonaStateToEvolveState: typeof daytonaStateToEvolveState;
|
|
855
|
+
declare const _testActivateSnapshot: typeof activateSnapshot;
|
|
856
|
+
declare const _testImageMap: Record<string, string>;
|
|
857
|
+
declare const _testWithEndOfOutputSentinel: typeof withEndOfOutputSentinel;
|
|
858
|
+
declare const _testStripEndOfOutputSentinel: typeof stripEndOfOutputSentinel;
|
|
859
|
+
declare const _testSettledStreams: typeof settledStreams;
|
|
860
|
+
declare const _testCreateSentinelFilter: typeof createSentinelFilter;
|
|
632
861
|
declare const _testCreateLogDemuxer: typeof createLogDemuxer;
|
|
633
862
|
declare const _testFollowManagedSessionLogs: typeof followManagedSessionLogs;
|
|
634
863
|
declare const _testReadCommandStreams: typeof readCommandStreams;
|
|
635
864
|
|
|
636
|
-
export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_LIST_PAGE_SIZE,
|
|
865
|
+
export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_LIST_PAGE_SIZE, DAYTONA_MAX_LIST_SCAN, DAYTONA_MAX_NETWORK_ALLOWLIST, DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS, DAYTONA_STREAM_TIMINGS, DaytonaCommands, type DaytonaConfig, DaytonaFiles, DaytonaGpuTypeError, DaytonaIdleTimeoutError, DaytonaImagePullError, DaytonaNetworkPolicyError, type DaytonaNetworkPolicyReason, DaytonaProvider, DaytonaResourcesError, DaytonaSnapshotActivationError, type DaytonaStreamTimings, EVOLVE_IMAGE_VERSION, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testActivateSnapshot, _testCollectSandboxStream, _testCreateLogDemuxer, _testCreateSentinelFilter, _testDaytonaStateToEvolveState, _testFollowManagedSessionLogs, _testImageMap, _testImageRegistryHost, _testMapNetworkPolicy, _testReadCommandStreams, _testSettledStreams, _testStripEndOfOutputSentinel, _testToSandboxInfo, _testWithEndOfOutputSentinel, _testWithInBoxTimeout, _testWrapCommand, createDaytonaProvider };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { Sandbox } from '@daytonaio/sdk';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* GENERATED — DO NOT EDIT. `npm run generate:image-version` (repo root)
|
|
5
|
+
* rewrites this file from the evolve-all image build inputs under
|
|
6
|
+
* assets/docker/ (see assets/docker/image-digest.ts for the derivation).
|
|
7
|
+
* The value is content-addressed: same inputs → same tag, any input
|
|
8
|
+
* change → a new tag. The coherence test in
|
|
9
|
+
* packages/daytona/tests/unit/daytona-image-version.test.ts fails the
|
|
10
|
+
* suite whenever this checked-in copy is stale.
|
|
11
|
+
*/
|
|
12
|
+
declare const EVOLVE_IMAGE_VERSION = "c-7bcda3467a79";
|
|
13
|
+
|
|
3
14
|
/**
|
|
4
15
|
* Daytona Sandbox Provider
|
|
5
16
|
*
|
|
6
|
-
* @requires @daytonaio/sdk >= 0.
|
|
17
|
+
* @requires @daytonaio/sdk >= 0.203.0 (cursor-based list pagination; Daytona
|
|
18
|
+
* retired the page-numbered endpoint on 2026-06-25)
|
|
7
19
|
*
|
|
8
20
|
* Design principles:
|
|
9
21
|
* - Mirror E2B provider interface for SDK compatibility
|
|
@@ -47,17 +59,49 @@ import { Sandbox } from '@daytonaio/sdk';
|
|
|
47
59
|
declare const DAYTONA_AUTO_DELETE_GRACE_MINUTES = 10;
|
|
48
60
|
declare const DAYTONA_MAX_NETWORK_ALLOWLIST = 10;
|
|
49
61
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
62
|
+
* How long a reactivated snapshot may take to come back before create() gives
|
|
63
|
+
* up. Daytona deactivates any snapshot unused for two weeks (official docs:
|
|
64
|
+
* "Snapshots automatically become inactive after 2 weeks of not being used"),
|
|
65
|
+
* so exists-but-inactive is the steady state of every image that shipped more
|
|
66
|
+
* than a fortnight before its next user — reactivation is a pull, not a build,
|
|
67
|
+
* and one that outlives this bound is a provider incident worth a loud error.
|
|
68
|
+
*/
|
|
69
|
+
declare const DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS = 180000;
|
|
70
|
+
/**
|
|
71
|
+
* Clocks of a STREAMED run (see awaitStreamedExit). The poll that reads the
|
|
72
|
+
* command's exit code backs off from pollMin to pollMax. A follow whose
|
|
73
|
+
* command has already ended is cut once it has been SILENT for drainMs —
|
|
74
|
+
* silence, never elapsed time, so a stream still delivering is never
|
|
75
|
+
* truncated. killGrace is what the caller's timeoutMs is widened by before a
|
|
76
|
+
* streamed run gives up, because withInBoxTimeout kills with `timeout -k 10`:
|
|
77
|
+
* the box may legitimately take ten seconds past the deadline to record a
|
|
78
|
+
* status. And a follow that has CLOSED means the command ended, so its record
|
|
79
|
+
* must catch up within settleMs — the only backstop a caller who passed no
|
|
80
|
+
* timeoutMs has, which is why it is generous rather than tight.
|
|
81
|
+
*/
|
|
82
|
+
declare const DAYTONA_STREAM_TIMINGS: {
|
|
83
|
+
pollMinMs: number;
|
|
84
|
+
pollMaxMs: number;
|
|
85
|
+
drainMs: number;
|
|
86
|
+
killGraceMs: number;
|
|
87
|
+
settleMs: number;
|
|
88
|
+
};
|
|
89
|
+
type DaytonaStreamTimings = typeof DAYTONA_STREAM_TIMINGS;
|
|
90
|
+
/**
|
|
91
|
+
* Sandboxes requested per list fetch — the cursor API's per-page size
|
|
92
|
+
* (ListSandboxesQuery.limit bounds one fetch, never the total). Held at the
|
|
93
|
+
* value every provider in this lineup accepts, so one number is valid
|
|
94
|
+
* everywhere a fleet is enumerated.
|
|
52
95
|
*/
|
|
53
96
|
declare const DAYTONA_LIST_PAGE_SIZE = 100;
|
|
54
97
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* a
|
|
98
|
+
* Row ceiling for one enumeration — the same 10,000 sandboxes the old
|
|
99
|
+
* 100-pages-of-100 ceiling allowed, restated in rows because cursor pagination
|
|
100
|
+
* has no page numbers to count. A walk that reaches it stops and reports
|
|
101
|
+
* itself INCOMPLETE, because the one thing a fleet enumeration may never do is
|
|
102
|
+
* return a short list that reads like a whole one.
|
|
59
103
|
*/
|
|
60
|
-
declare const
|
|
104
|
+
declare const DAYTONA_MAX_LIST_SCAN = 10000;
|
|
61
105
|
/** Why a network policy cannot be enforced by Daytona. */
|
|
62
106
|
type DaytonaNetworkPolicyReason = "wildcard-hostname" | "ipv6-unsupported" | "port-unsupported" | "invalid-ipv4" | "unresolvable-hostname" | "allowlist-too-large";
|
|
63
107
|
/**
|
|
@@ -95,6 +139,19 @@ declare class DaytonaImagePullError extends Error {
|
|
|
95
139
|
* (reject what you cannot enforce) it is refused loudly instead: pre-build a
|
|
96
140
|
* snapshot with the desired sizing under its own name, or drop `resources`.
|
|
97
141
|
*/
|
|
142
|
+
/**
|
|
143
|
+
* @deprecated No longer thrown. @daytonaio/sdk 0.203.0 grew a real
|
|
144
|
+
* `Resources.gpuType` field, so `resources.gpuTypes` is now FORWARDED on the
|
|
145
|
+
* snapshot-build path instead of refused (Daytona validates the type names
|
|
146
|
+
* server-side). Sizing against an EXISTING snapshot — GPU type included —
|
|
147
|
+
* still throws DaytonaResourcesError like every other pinned field. The class
|
|
148
|
+
* stays exported so callers with `instanceof` checks keep compiling.
|
|
149
|
+
*/
|
|
150
|
+
declare class DaytonaGpuTypeError extends Error {
|
|
151
|
+
/** The snapshot/image the create named. */
|
|
152
|
+
readonly snapshot: string;
|
|
153
|
+
constructor(snapshot: string);
|
|
154
|
+
}
|
|
98
155
|
declare class DaytonaResourcesError extends Error {
|
|
99
156
|
/** The existing snapshot whose pinned sizing cannot be overridden. */
|
|
100
157
|
readonly snapshot: string;
|
|
@@ -109,6 +166,45 @@ declare class DaytonaResourcesError extends Error {
|
|
|
109
166
|
declare class DaytonaIdleTimeoutError extends Error {
|
|
110
167
|
constructor();
|
|
111
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Typed error for a snapshot that exists but could not be brought back to
|
|
171
|
+
* `active`. This is a final verdict, not a build trigger: the snapshot IS
|
|
172
|
+
* there, so rebuilding under the same name can only fail on the name conflict
|
|
173
|
+
* and then mask the real problem behind a slow direct image pull.
|
|
174
|
+
*/
|
|
175
|
+
declare class DaytonaSnapshotActivationError extends Error {
|
|
176
|
+
/** The snapshot that would not activate. */
|
|
177
|
+
readonly snapshot: string;
|
|
178
|
+
constructor(snapshot: string, detail: string);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The slice of the Daytona client the reactivation path touches — structural,
|
|
182
|
+
* so the unit tests can drive it with a plain mock.
|
|
183
|
+
*/
|
|
184
|
+
interface SnapshotActivationClient {
|
|
185
|
+
snapshot: {
|
|
186
|
+
get(name: string): Promise<{
|
|
187
|
+
state?: string;
|
|
188
|
+
}>;
|
|
189
|
+
activate(snapshot: unknown): Promise<{
|
|
190
|
+
state?: string;
|
|
191
|
+
}>;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Bring an exists-but-inactive snapshot back to `active`, or say loudly why
|
|
196
|
+
* not. Activation is asynchronous on Daytona's side — the activate call may
|
|
197
|
+
* answer with a transitional state (`pulling`) — so the result is polled until
|
|
198
|
+
* it lands on `active`, a terminal failure state, or the deadline.
|
|
199
|
+
*/
|
|
200
|
+
declare function activateSnapshot(client: SnapshotActivationClient, name: string, snapshot: {
|
|
201
|
+
state?: string;
|
|
202
|
+
}, timing?: {
|
|
203
|
+
timeoutMs?: number;
|
|
204
|
+
pollMs?: number;
|
|
205
|
+
}): Promise<{
|
|
206
|
+
state?: string;
|
|
207
|
+
}>;
|
|
112
208
|
/**
|
|
113
209
|
* Wrap command with cwd and envs shell prefixes, and (for user "root") a
|
|
114
210
|
* `sudo -n` elevation wrapper.
|
|
@@ -163,6 +259,79 @@ declare class DaytonaIdleTimeoutError extends Error {
|
|
|
163
259
|
* to every caller that checks.
|
|
164
260
|
*/
|
|
165
261
|
declare function withInBoxTimeout(wrapped: string, timeoutSec?: number): string;
|
|
262
|
+
/**
|
|
263
|
+
* NOTHING IS APPENDED TO THE CALLER'S LAST LINE. The command goes inside a
|
|
264
|
+
* brace group whose closing brace opens a line of its own, so what follows is
|
|
265
|
+
* never read as a continuation of whatever the command ended with. Appending
|
|
266
|
+
* `; ...` directly broke three shapes, all measured:
|
|
267
|
+
*
|
|
268
|
+
* a command ending in a NEWLINE (every multi-line template literal) —
|
|
269
|
+
* `\n; __evolve_eos=$?` is a syntax error, exit 2
|
|
270
|
+
* a command ending in `&` — `& ;` is a syntax error and the command NEVER RAN
|
|
271
|
+
* a HEREDOC whose terminator is the command's last line — the appended text
|
|
272
|
+
* became part of the heredoc BODY: no error, exit 0, corrupt payload. That
|
|
273
|
+
* is the shape of the managed-secret proxy readiness probe (agent.ts), and
|
|
274
|
+
* it turned a healthy proxy into "failed to start".
|
|
275
|
+
*
|
|
276
|
+
* The group needs two guards of its own, both measured against /bin/sh,
|
|
277
|
+
* /bin/bash and /bin/dash:
|
|
278
|
+
*
|
|
279
|
+
* a leading `:` so the body is never EMPTY. A comment-only command
|
|
280
|
+
* (`# nothing`) otherwise leaves `{ # nothing\n}` — "syntax error near
|
|
281
|
+
* unexpected token `}'", exit 2, where the caller's own shell would have
|
|
282
|
+
* done nothing and exited 0. It runs BEFORE the command, so the status the
|
|
283
|
+
* group reports is still the command's own.
|
|
284
|
+
* a BLANK LINE before the closing brace, to be eaten by a command that ends
|
|
285
|
+
* in a dangling backslash. That backslash continues onto whatever line
|
|
286
|
+
* comes next; the blank line is what it consumes instead of the `}`, and
|
|
287
|
+
* `echo HI \` then runs as the caller's shell would run it — exit 0, "HI",
|
|
288
|
+
* with the exit code of a failing one (`false \` -> 1) still its own.
|
|
289
|
+
*
|
|
290
|
+
* WHAT STILL FAILS, LOUDLY: an UNTERMINATED heredoc (`cat <<'EOF'` with no
|
|
291
|
+
* EOF line). Its body swallows everything that follows, including the closing
|
|
292
|
+
* brace, so the command is a syntax error — exit 2, no output, the shell's own
|
|
293
|
+
* message on stderr. No text can fix that from out here: anything added lands
|
|
294
|
+
* inside the heredoc. A shell run of the same input without a wrapper prints
|
|
295
|
+
* the body and exits 0, so this is the one shape the sentinel changes, and it
|
|
296
|
+
* changes it to a loud failure rather than a quiet wrong answer.
|
|
297
|
+
*/
|
|
298
|
+
declare function withEndOfOutputSentinel(command: string, token: string): string;
|
|
299
|
+
/**
|
|
300
|
+
* Shed the sentinel, and the terminator the transport put after it, from a
|
|
301
|
+
* settled stream.
|
|
302
|
+
*
|
|
303
|
+
* ONLY AT THE END, because that is the only place the sentinel can be: it is
|
|
304
|
+
* the last thing the command prints. A token anywhere else in the output is
|
|
305
|
+
* the caller's own bytes — `ps` shows this very command line, and `sh -x`
|
|
306
|
+
* traces the printf that writes it — and deleting those would be corruption,
|
|
307
|
+
* silent and impossible to debug.
|
|
308
|
+
*/
|
|
309
|
+
declare function stripEndOfOutputSentinel(text: string, token: string): string;
|
|
310
|
+
/**
|
|
311
|
+
* A settled log read with the sentinel shed — from STDOUT only, because that is
|
|
312
|
+
* the only stream the command prints one to. Shedding anything from stderr
|
|
313
|
+
* could only ever delete bytes the command itself wrote (`sh -x` traces the
|
|
314
|
+
* printf that writes the token, and that trace goes to stderr).
|
|
315
|
+
*/
|
|
316
|
+
declare function settledStreams(logs: unknown, token: string): {
|
|
317
|
+
stdout: string;
|
|
318
|
+
stderr: string;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Shed the sentinel from a stream still arriving, without holding back output
|
|
322
|
+
* that is merely on its way.
|
|
323
|
+
*
|
|
324
|
+
* Same rule as the settled read — only the end of the stream can be the
|
|
325
|
+
* sentinel — applied to bytes still coming: what could still GROW INTO it (the
|
|
326
|
+
* longest tail that is a prefix of `<token>\n`) waits for the rest, and
|
|
327
|
+
* everything else goes straight through, so a chunk that cannot be the start
|
|
328
|
+
* of a sentinel is never delayed. Nothing mid-stream is ever dropped.
|
|
329
|
+
*/
|
|
330
|
+
declare function createSentinelFilter(token: string, emit: (chunk: string) => void): {
|
|
331
|
+
push(chunk: string): void;
|
|
332
|
+
/** The stream is over: what was held is the sentinel, or it was output after all. */
|
|
333
|
+
flush(): void;
|
|
334
|
+
};
|
|
166
335
|
declare function wrapCommand(command: string, cwd?: string, envs?: Record<string, string>, user?: string): string;
|
|
167
336
|
/** Daytona create() params derived from Evolve's provider-neutral network policy. */
|
|
168
337
|
interface DaytonaNetworkCreateParams {
|
|
@@ -214,8 +383,10 @@ interface DaytonaSandboxLike {
|
|
|
214
383
|
declare function toSandboxInfo(sandbox: DaytonaSandboxLike): SandboxInfo;
|
|
215
384
|
/**
|
|
216
385
|
* Map a Daytona sandbox state onto Evolve's list() filter states.
|
|
217
|
-
* "started" → running; "stopped"/"archived" → paused (our pause()
|
|
218
|
-
* sandbox
|
|
386
|
+
* "started" → running; "stopped"/"archived"/"paused" → paused (our pause()
|
|
387
|
+
* stops the sandbox; Daytona 0.203.0 added a native "paused" state for
|
|
388
|
+
* pause-capable sandbox classes, and a box resting in it is paused by any
|
|
389
|
+
* reading); transitional and terminal states match no filter.
|
|
219
390
|
*/
|
|
220
391
|
declare function daytonaStateToEvolveState(state?: string): "running" | "paused" | undefined;
|
|
221
392
|
/** Result of a completed sandbox command */
|
|
@@ -275,6 +446,19 @@ interface SandboxResources {
|
|
|
275
446
|
memory?: number;
|
|
276
447
|
/** Disk in GB (default: 10) */
|
|
277
448
|
disk?: number;
|
|
449
|
+
/**
|
|
450
|
+
* GPU reservation (count). Applied when a SNAPSHOT IS BUILT (Daytona
|
|
451
|
+
* allocates GPU at snapshot build; GPU machines are tier-gated on Daytona's
|
|
452
|
+
* side) — against an existing snapshot it throws DaytonaResourcesError like
|
|
453
|
+
* every other pinned sizing field.
|
|
454
|
+
*/
|
|
455
|
+
gpu?: number;
|
|
456
|
+
/**
|
|
457
|
+
* Acceptable GPU types (Daytona's GpuType names, e.g. "H100", "H200",
|
|
458
|
+
* "RTX-PRO-6000"). Forwarded on the build path — Daytona validates the
|
|
459
|
+
* names server-side — and refused on an existing snapshot alongside `gpu`.
|
|
460
|
+
*/
|
|
461
|
+
gpuTypes?: string[];
|
|
278
462
|
}
|
|
279
463
|
/** Options for creating a sandbox */
|
|
280
464
|
interface SandboxCreateOptions {
|
|
@@ -345,6 +529,13 @@ interface SandboxListOptions {
|
|
|
345
529
|
interface SandboxListPage {
|
|
346
530
|
sandboxes: SandboxInfo[];
|
|
347
531
|
complete: boolean;
|
|
532
|
+
/**
|
|
533
|
+
* Fetch units consumed: rows scanned from the cursor stream (before
|
|
534
|
+
* filtering). Cursor pagination has no page numbers to count — and the modal
|
|
535
|
+
* provider already reports item counts here — so "pages" reads as "units of
|
|
536
|
+
* enumeration work", kept under this name because the field is shared
|
|
537
|
+
* provider-neutral surface.
|
|
538
|
+
*/
|
|
348
539
|
pagesFetched: number;
|
|
349
540
|
error?: string;
|
|
350
541
|
}
|
|
@@ -402,7 +593,7 @@ interface DaytonaConfig {
|
|
|
402
593
|
target?: string;
|
|
403
594
|
/** Default timeout in ms */
|
|
404
595
|
defaultTimeoutMs?: number;
|
|
405
|
-
/** Daytona snapshot name (default: 'evolve-all'). Create custom snapshots via `cd assets && ./build.sh daytona` */
|
|
596
|
+
/** Daytona snapshot name (default: 'evolve-all-<EVOLVE_IMAGE_VERSION>' direct, the platform's stable 'evolve-all' managed). Explicit names pass through untouched. Create custom snapshots via `cd assets && ./build.sh daytona` */
|
|
406
597
|
snapshotName?: string;
|
|
407
598
|
/**
|
|
408
599
|
* Evolve-managed toolbox base URL. Setting it puts the provider in MANAGED
|
|
@@ -466,7 +657,7 @@ declare function createLogDemuxer(onStdout: (chunk: string) => void, onStderr: (
|
|
|
466
657
|
* streaming through a plain response body, which is what the Dashboard route
|
|
467
658
|
* pipes through unbuffered.
|
|
468
659
|
*/
|
|
469
|
-
declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void): Promise<void>;
|
|
660
|
+
declare function followManagedSessionLogs(context: ManagedStreamContext, sandboxId: string, sessionId: string, commandId: string, onStdout: (chunk: string) => void, onStderr: (chunk: string) => void, signal?: AbortSignal): Promise<void>;
|
|
470
661
|
/**
|
|
471
662
|
* Read a command's streams out of whatever shape Daytona returned.
|
|
472
663
|
*
|
|
@@ -495,15 +686,44 @@ declare class DaytonaCommands implements SandboxCommands {
|
|
|
495
686
|
private sandbox;
|
|
496
687
|
private user?;
|
|
497
688
|
private managedStream?;
|
|
689
|
+
/** The streamed-run clocks, shrinkable by a subclass so a test need not wait them out. */
|
|
690
|
+
protected streamTimings: DaytonaStreamTimings;
|
|
498
691
|
constructor(sandbox: Sandbox, user?: string | undefined, managedStream?: ManagedStreamContext | undefined);
|
|
499
692
|
/**
|
|
500
693
|
* Stream a command's output to callbacks. Direct mode uses the Daytona
|
|
501
694
|
* SDK's own follow, which is a websocket; managed mode uses the HTTP
|
|
502
695
|
* chunked follow, because a Dashboard route handler cannot terminate a
|
|
503
696
|
* websocket upgrade (see followManagedSessionLogs).
|
|
697
|
+
*
|
|
698
|
+
* Only the managed follow takes the abandon signal — the SDK's websocket
|
|
699
|
+
* follow exposes none, so a direct-mode stall is stopped from waiting on
|
|
700
|
+
* but not closed; the ephemeral session's delete is what ends it.
|
|
504
701
|
*/
|
|
505
702
|
private followLogs;
|
|
506
703
|
run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
|
|
704
|
+
/**
|
|
705
|
+
* WHAT SAYS A STREAMED RUN IS OVER: the command's record, never the follow.
|
|
706
|
+
*
|
|
707
|
+
* A chunked follow can stall open long after its command exited — nothing
|
|
708
|
+
* acks a response body — and awaiting it first, then polling for an exit
|
|
709
|
+
* code 20 times at 500ms, gave a streaming run() two failure modes the
|
|
710
|
+
* blocking path never had: a stalled socket hung run() forever (with no
|
|
711
|
+
* timeoutMs, nothing in the box or out of it bounds the wait), and a follow
|
|
712
|
+
* that closed a moment early threw "no exit code" on a command that had
|
|
713
|
+
* already succeeded.
|
|
714
|
+
*
|
|
715
|
+
* So the poll and the follow run TOGETHER. The poll decides when the run
|
|
716
|
+
* ended; the follow then gets as long as it keeps delivering and is cut
|
|
717
|
+
* only once it has been SILENT for the drain window, so a live stream is
|
|
718
|
+
* never truncated and a dead one is never waited on. Two ceilings bound the
|
|
719
|
+
* wait: the caller's timeoutMs widened by the in-box kill grace, and — for
|
|
720
|
+
* the caller who passed none — the settle bound measured from the moment
|
|
721
|
+
* the follow closed, because a closed stream means the command ended and a
|
|
722
|
+
* record that never catches up is a provider incident, not a long run.
|
|
723
|
+
* A run with no timeoutMs whose command is genuinely still streaming is
|
|
724
|
+
* still waited on indefinitely: that is what asking for no bound means.
|
|
725
|
+
*/
|
|
726
|
+
private awaitStreamedExit;
|
|
507
727
|
spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
|
|
508
728
|
list(): Promise<ProcessInfo[]>;
|
|
509
729
|
kill(processId: string): Promise<boolean>;
|
|
@@ -551,18 +771,21 @@ declare class DaytonaProvider implements SandboxProvider {
|
|
|
551
771
|
create(options: SandboxCreateOptions): Promise<SandboxInstance>;
|
|
552
772
|
connect(sandboxId: string, _timeoutMs?: number): Promise<SandboxInstance>;
|
|
553
773
|
/**
|
|
554
|
-
* List sandboxes, walking
|
|
774
|
+
* List sandboxes, walking the cursor stream to exhaustion.
|
|
555
775
|
*
|
|
556
|
-
*
|
|
776
|
+
* An early version requested page 1 and stopped, discarding the rest — an
|
|
557
777
|
* organization with more than one page of sandboxes was silently truncated,
|
|
558
778
|
* and nothing in the return value said so. For any caller that reads absence
|
|
559
|
-
* from the list as "this sandbox is gone", that is a correctness bug.
|
|
779
|
+
* from the list as "this sandbox is gone", that is a correctness bug. Cursor
|
|
780
|
+
* pagination (mandatory since Daytona retired page numbers on 2026-06-25)
|
|
781
|
+
* changes the mechanics, not the law: the walk still runs to the end or says
|
|
782
|
+
* it could not.
|
|
560
783
|
*
|
|
561
|
-
* ORDER OF OPERATIONS, because it is observable: `limit` bounds the
|
|
562
|
-
* RETURNED, and
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
784
|
+
* ORDER OF OPERATIONS, because it is observable: `limit` bounds the
|
|
785
|
+
* sandboxes RETURNED, and the state filter runs client-side on every row
|
|
786
|
+
* BEFORE the limit is counted. Asking for 10 running sandboxes therefore
|
|
787
|
+
* keeps walking until ten running ones have been found, rather than
|
|
788
|
+
* filtering ten arbitrary rows down to whatever survives.
|
|
566
789
|
*/
|
|
567
790
|
list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
|
|
568
791
|
/**
|
|
@@ -576,45 +799,45 @@ declare class DaytonaProvider implements SandboxProvider {
|
|
|
576
799
|
listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
|
|
577
800
|
private paginate;
|
|
578
801
|
/**
|
|
579
|
-
*
|
|
802
|
+
* The cursor stream, asking the API to narrow server-side where it can.
|
|
580
803
|
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
* So the server filter is applied OPPORTUNISTICALLY, through the private
|
|
590
|
-
* field when it is shaped the way we expect, and the client-side filter in
|
|
591
|
-
* the walk stays the authority regardless. That ordering is the whole point:
|
|
592
|
-
* if a future SDK refactor renames or removes the field, this degrades to the
|
|
593
|
-
* request count it has today, and can never degrade to admitting states the
|
|
594
|
-
* caller excluded.
|
|
804
|
+
* Since 0.203.0 the SDK's public `list(query)` takes `states` and `labels`
|
|
805
|
+
* directly and pages by cursor internally (items + nextCursor,
|
|
806
|
+
* esm/Daytona.js:430-476), so the old reach-around through the private
|
|
807
|
+
* `sandboxApi.listSandboxesPaginated` field is gone along with the method
|
|
808
|
+
* itself. The client-side filter in the walk stays the authority regardless:
|
|
809
|
+
* a server filter that silently stopped applying must never be able to admit
|
|
810
|
+
* a state the caller excluded.
|
|
595
811
|
*/
|
|
596
|
-
private
|
|
597
|
-
}
|
|
598
|
-
/** One page as Daytona's `list(labels?, page?, limit?)` returns it. */
|
|
599
|
-
interface DaytonaSandboxPage {
|
|
600
|
-
items: Sandbox[];
|
|
601
|
-
totalPages?: number;
|
|
812
|
+
private listStream;
|
|
602
813
|
}
|
|
603
814
|
/**
|
|
604
|
-
* Walk
|
|
815
|
+
* Walk the cursor stream into one answer, with an honest completeness verdict.
|
|
605
816
|
*
|
|
606
817
|
* Separate from the provider because everything worth getting wrong lives here
|
|
607
818
|
* and none of it needs a network: the ways a walk can fail to terminate, the
|
|
608
|
-
* difference between "the caller asked for ten" and "the provider ran out",
|
|
609
|
-
* the rule that a failure mid-walk yields the sandboxes seen so far marked
|
|
819
|
+
* difference between "the caller asked for ten" and "the provider ran out",
|
|
820
|
+
* and the rule that a failure mid-walk yields the sandboxes seen so far marked
|
|
610
821
|
* INCOMPLETE rather than either an exception or a short complete list.
|
|
611
822
|
*
|
|
612
|
-
*
|
|
823
|
+
* WHAT CURSORS CHANGED HERE, and what they did not. The vendor's iterator ends
|
|
824
|
+
* itself when nextCursor runs out, so "exhausted" is now the stream ending
|
|
825
|
+
* rather than a totalPages comparison; a fetch failure mid-walk surfaces as
|
|
826
|
+
* the iterator throwing. The LAWS are unchanged: a walk that could not finish
|
|
827
|
+
* reports `complete: false` with what it saw, a caller's limit is reported as
|
|
828
|
+
* truncation whenever one more row provably exists (the row after the limit is
|
|
829
|
+
* that proof — the walk holds it, so no extra fetch is spent on it beyond, at
|
|
830
|
+
* worst, the one the iterator was already making), and a runaway fleet stops
|
|
831
|
+
* at the scan ceiling as a refusal, never as a short list that reads complete.
|
|
832
|
+
*
|
|
833
|
+
* Exported for its test (`_testCollectSandboxStream`).
|
|
613
834
|
*/
|
|
614
|
-
declare function
|
|
835
|
+
declare function collectSandboxStream(stream: AsyncIterable<DaytonaSandboxLike & {
|
|
836
|
+
state?: string;
|
|
837
|
+
}>, options?: SandboxListOptions): Promise<SandboxListPage & {
|
|
615
838
|
stoppedAtLimit: boolean;
|
|
616
839
|
}>;
|
|
617
|
-
declare const
|
|
840
|
+
declare const _testCollectSandboxStream: typeof collectSandboxStream;
|
|
618
841
|
/**
|
|
619
842
|
* Create Daytona sandbox provider.
|
|
620
843
|
*
|
|
@@ -629,8 +852,14 @@ declare const _testMapNetworkPolicy: typeof mapNetworkPolicy;
|
|
|
629
852
|
declare const _testImageRegistryHost: typeof imageRegistryHost;
|
|
630
853
|
declare const _testToSandboxInfo: typeof toSandboxInfo;
|
|
631
854
|
declare const _testDaytonaStateToEvolveState: typeof daytonaStateToEvolveState;
|
|
855
|
+
declare const _testActivateSnapshot: typeof activateSnapshot;
|
|
856
|
+
declare const _testImageMap: Record<string, string>;
|
|
857
|
+
declare const _testWithEndOfOutputSentinel: typeof withEndOfOutputSentinel;
|
|
858
|
+
declare const _testStripEndOfOutputSentinel: typeof stripEndOfOutputSentinel;
|
|
859
|
+
declare const _testSettledStreams: typeof settledStreams;
|
|
860
|
+
declare const _testCreateSentinelFilter: typeof createSentinelFilter;
|
|
632
861
|
declare const _testCreateLogDemuxer: typeof createLogDemuxer;
|
|
633
862
|
declare const _testFollowManagedSessionLogs: typeof followManagedSessionLogs;
|
|
634
863
|
declare const _testReadCommandStreams: typeof readCommandStreams;
|
|
635
864
|
|
|
636
|
-
export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_LIST_PAGE_SIZE,
|
|
865
|
+
export { DAYTONA_AUTO_DELETE_GRACE_MINUTES, DAYTONA_LIST_PAGE_SIZE, DAYTONA_MAX_LIST_SCAN, DAYTONA_MAX_NETWORK_ALLOWLIST, DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS, DAYTONA_STREAM_TIMINGS, DaytonaCommands, type DaytonaConfig, DaytonaFiles, DaytonaGpuTypeError, DaytonaIdleTimeoutError, DaytonaImagePullError, DaytonaNetworkPolicyError, type DaytonaNetworkPolicyReason, DaytonaProvider, DaytonaResourcesError, DaytonaSnapshotActivationError, type DaytonaStreamTimings, EVOLVE_IMAGE_VERSION, type FileInfo, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxListPage, type SandboxProvider, type SandboxResources, type SandboxRunOptions, type SandboxSpawnOptions, _testActivateSnapshot, _testCollectSandboxStream, _testCreateLogDemuxer, _testCreateSentinelFilter, _testDaytonaStateToEvolveState, _testFollowManagedSessionLogs, _testImageMap, _testImageRegistryHost, _testMapNetworkPolicy, _testReadCommandStreams, _testSettledStreams, _testStripEndOfOutputSentinel, _testToSandboxInfo, _testWithEndOfOutputSentinel, _testWithInBoxTimeout, _testWrapCommand, createDaytonaProvider };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import {STDOUT_PREFIX_BYTES,STDERR_PREFIX_BYTES,MAX_PREFIX_LEN,Daytona,Image}from'@daytonaio/sdk';import {resolve4}from'dns/promises';var z={"evolve-all":"evolvingmachines/evolve-all"},q=10,L=10,T=100,y=100,W=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 X(s){let e=s.substring(s.lastIndexOf(".")).toLowerCase();return W.has(e)}function G(s){let e=s.lastIndexOf("/");return e>0?s.substring(0,e):"/"}function J(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;}},w=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;}},S=class extends Error{constructor(){super("Daytona has no separate idle timeout: auto-stop IS its only clock and it already measures inactivity, so `timeoutMs` is what sets it (autoStopInterval). Set the inactivity bound with `timeoutMs`; a hard bound on the process itself is enforced in-box instead (see withInBoxTimeout)."),this.name="DaytonaIdleTimeoutError";}};function v(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} && [ -s ${n} ] || { rm -f ${n}; exit 126; }; 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 P(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 V=s=>resolve4(s);function E(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 Z(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!E(s)}function Q(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function ee(s){return /^[^:]+:\d+$/.test(s)}async function B(s,e=V){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(E(o))n.push(o.includes("/")?o:`${o}/32`);else {if(Z(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(Q(o))throw new f("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${o}".`,o);if(ee(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 l=[...new Set(n)];if(l.length>L)throw new f("allowlist-too-large",`Daytona allows at most ${L} entries in its network allowlist; this policy resolved to ${l.length} CIDRs (${l.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:l.join(",")}}function O(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 k(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function _(s){if(s==="started")return "running";if(s==="stopped"||s==="archived")return "paused"}var I=class extends Daytona{constructor(t,n){super(t);this.managedToolboxUrl=n;}async getProxyToolboxUrl(){return this.managedToolboxUrl}};function te(s,e){let t=new Uint8Array(new ArrayBuffer(s.length+e.length));return t.set(s,0),t.set(e,s.length),t}function U(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 N(s,e){let t=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),r=new Uint8Array(0),l="stdout",o=a=>{a.length!==0&&(l==="stdout"?s(t.decode(a,{stream:true})):e(n.decode(a,{stream:true})));};return {push(a){for(r=te(r,a);;){let i=U(r,STDOUT_PREFIX_BYTES,0),d=U(r,STDERR_PREFIX_BYTES,0),c=-1,u="stdout",m=0;if(i!==-1&&(d===-1||i<d)?(c=i,u="stdout",m=STDOUT_PREFIX_BYTES.length):d!==-1&&(c=d,u="stderr",m=STDERR_PREFIX_BYTES.length),c===-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,c)),l=u,r=r.slice(c+m);}},flush(){o(r),r=new Uint8Array(0);let a=t.decode();a&&s(a);let i=n.decode();i&&e(i);}}}async function F(s,e,t,n,r,l){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=N(r,l),d=a.body.getReader();try{for(;;){let{done:c,value:u}=await d.read();if(c)break;u&&i.push(u);}}finally{i.flush(),await d.cancel().catch(()=>{});}}function x(s){let e=s.stdout||"",t=s.stderr||"",n=s.output||"";return !e&&!t&&n?{stdout:n,stderr:""}:{stdout:e,stderr:t}}var D=class{constructor(e,t,n){this.sandbox=e;this.user=t;this.managedStream=n;}followLogs(e,t,n,r){return this.managedStream?F(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 l=await this.sandbox.process.executeSessionCommand(r,{command:v(P(e,t?.cwd,t?.envs,this.user),n),runAsync:!1},n),o=l.cmdId;o&&(t?.onStdout||t?.onStderr)&&await this.followLogs(r,o,t.onStdout||(()=>{}),t.onStderr||(()=>{}));let{stdout:a,stderr:i}=x(l);if(!a&&!i&&o&&!t?.onStdout)try{let d=await this.sandbox.process.getSessionCommandLogs(r,o),c=x(d);a=c.stdout,i=c.stderr||i;}catch{}return {exitCode:l.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,l=Date.now(),o=t?.timeoutMs,i=(await this.sandbox.process.executeSessionCommand(n,{command:v(P(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 d=this.sandbox;return {processId:n,wait:async()=>{if(!i)return {exitCode:0,stdout:"",stderr:""};for(;;){if(o&&Date.now()-l>=o){try{await d.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let c=await d.process.getSessionCommand(n,i);if(c.exitCode!==void 0)try{let u=await d.process.getSessionCommandLogs(n,i);return {exitCode:c.exitCode,...x(u)}}catch{return {exitCode:c.exitCode,stdout:"",stderr:""}}}catch(c){let u=c instanceof Error?c.message.toLowerCase():String(c).toLowerCase();if(u.includes("not found")){let m=u.includes("sandbox");try{await d.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 c}await new Promise(c=>setTimeout(c,500));}},kill:async()=>{try{return await d.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}}},A=class{constructor(e){this.sandbox=e;}async read(e){let t=await this.sandbox.fs.downloadFile(e);return X(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=G(e),n=J(e);return (await this.sandbox.fs.listFiles(t)).some(l=>l.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);}},b=class{constructor(e,t,n){this.sandbox=e;this.commands=new D(e,t,n),this.files=new A(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(),k(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},C=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 I(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){if(e.idleTimeoutMs!==void 0)throw new S;let t=await B(e.network),n=e.user,r=n&&n!=="root"?n:void 0,l=e.timeoutMs??this.defaultTimeoutMs,o=Math.max(1,Math.ceil(l/6e4)),a=e.image||this.snapshotName,i={envVars:e.envs,labels:e.metadata,autoStopInterval:o,autoDeleteInterval:q,...r?{user:r}:{},...t},d,c=e.resources!==void 0&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0);if(this.managedStream){if(c)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 b(u,n,this.managedStream)}try{let u=await this.client.snapshot.get(a);if(u&&u.state==="active"){if(c)throw new h(a);console.log(`[daytona] Using cached snapshot: ${a}`),d=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=z[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.`),d=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{d=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 O(m)?new w(m,p):p}}}return e.workingDirectory&&await d.fs.createFolder(e.workingDirectory,"755"),n&&this.sandboxUsers.set(d.id,n),new b(d,n,this.managedStream)}async connect(e,t){let n=await this.client.get(e);return n.state!=="started"&&await n.start(),new b(n,this.sandboxUsers.get(e),this.managedStream)}async list(e){let t=await this.paginate(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...n}=await this.paginate(e);return n}async paginate(e){return K(t=>this.listPage(e,t),e)}async listPage(e,t){let n=e?.state?ne(e.state):void 0;if(n&&n.length>0){let r=this.client.sandboxApi;if(typeof r?.listSandboxesPaginated=="function")try{let l=await r.listSandboxesPaginated(void 0,t,T,void 0,void 0,e?.metadata?JSON.stringify(e.metadata):void 0,void 0,n);return {items:l.data.items,totalPages:l.data.totalPages}}catch{}}return this.client.list(e?.metadata,t,T)}};function ne(s){let e=[];for(let t of s)t==="running"&&e.push("started"),t==="paused"&&e.push("stopped","archived");return e}async function K(s,e){let t=e?.limit,n=[],r=0,l=new Set;for(let o=1;o<=y;o+=1){let a;try{a=await s(o);}catch(d){return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list failed: ${d instanceof Error?d.message:String(d)}`}}r+=1;for(let d of a.items){if(e?.state){let c=_(d.state);if(c===void 0||!e.state.includes(c))continue}if(!l.has(d.id)){if(t!==void 0&&n.length>=t)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${t} with more sandboxes available`};l.add(d.id),n.push(k(d));}}let i=a.items.length===0||typeof a.totalPages=="number"&&o>=a.totalPages;if(t!==void 0&&n.length>=t&&!i)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${t} with more sandboxes available`};if(i)break;if(o===y)return {sandboxes:n,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list exceeded ${y} pages`}}return {sandboxes:n,complete:true,pagesFetched:r,stoppedAtLimit:false}}var oe=K;function ae(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 C({...s,apiKey:e})}var ie=P,de=v,le=B,ce=O,ue=k,me=_,ge=N,fe=F,pe=x;
|
|
2
|
-
|
|
1
|
+
import {STDOUT_PREFIX_BYTES,STDERR_PREFIX_BYTES,MAX_PREFIX_LEN,Daytona,Image}from'@daytonaio/sdk';import {resolve4}from'dns/promises';var D="c-7bcda3467a79";var X={[`evolve-all-${D}`]:`evolvingmachines/evolve-all:${D}`,"evolve-all":"evolvingmachines/evolve-all"},ft=10,W=10,gt=18e4,pt=2e3,ht={pollMinMs:250,pollMaxMs:2e3,drainMs:1e3,killGraceMs:15e3,settleMs:6e4},v=s=>new Promise(t=>setTimeout(t,Math.max(0,s))),yt=100,I=1e4;function wt(s){let t=s.lastIndexOf("/");return t>0?s.substring(0,t):"/"}function xt(s){let t=s.lastIndexOf("/");return t>=0?s.substring(t+1):s}var h=class extends Error{reason;destination;constructor(t,e,n){super(e),this.name="DaytonaNetworkPolicyError",this.reason=t,this.destination=n;}},k=class extends Error{image;constructor(t,e){let n=e instanceof Error?e.message:String(e??"unknown error");super(`Failed to pull image "${t}" 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=t;}},j=class extends Error{snapshot;constructor(t){super(`Daytona cannot constrain the GPU type for "${t}": the snapshot already exists and pins its resources \u2014 pre-build a snapshot with the desired GPU type under its own name.`),this.name="DaytonaGpuTypeError",this.snapshot=t;}},P=class extends Error{snapshot;constructor(t){super(`Daytona snapshot "${t}" 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=t;}},C=class extends Error{constructor(){super("Daytona has no separate idle timeout: auto-stop IS its only clock and it already measures inactivity, so `timeoutMs` is what sets it (autoStopInterval). Set the inactivity bound with `timeoutMs`; a hard bound on the process itself is enforced in-box instead (see withInBoxTimeout)."),this.name="DaytonaIdleTimeoutError";}},y=class extends Error{snapshot;constructor(t,e){super(`Daytona snapshot "${t}" exists but could not be activated: ${e}. Daytona deactivates snapshots unused for 2 weeks; activation normally completes in seconds. Retry, or activate it manually in the Daytona dashboard (Snapshots page).`),this.name="DaytonaSnapshotActivationError",this.snapshot=t;}};async function Q(s,t,e,n){let o=n?.timeoutMs??gt,l=n?.pollMs??pt;console.log(`[daytona] Snapshot "${t}" is inactive (unused for 2+ weeks) \u2014 reactivating...`);let r;try{r=await s.snapshot.activate(e);}catch(i){throw new y(t,`the activate call failed (${i instanceof Error?i.message:String(i)})`)}let a=Date.now()+o;for(;r?.state!=="active";){if(r?.state==="error"||r?.state==="build_failed")throw new y(t,`it entered state "${r.state}"`);if(Date.now()>=a)throw new y(t,`still "${r?.state??"unknown"}" after ${o}ms`);await v(l);try{r=await s.snapshot.get(t);}catch(i){throw new y(t,`the activation poll failed (${i instanceof Error?i.message:String(i)})`)}}return console.log(`[daytona] Snapshot "${t}" reactivated.`),r}function $(s,t){if(!t||t<=0)return s;let e=Buffer.from(s).toString("base64"),n=`/tmp/.evolve-cmd-${Date.now()}-${Math.random().toString(36).slice(2,8)}.sh`;return `sh -c '${`echo ${e} | base64 -d > ${n} && [ -s ${n} ] || { rm -f ${n}; exit 126; }; if command -v timeout >/dev/null 2>&1; then timeout -k 10 ${t} bash ${n}; else bash ${n}; fi; rc=$?; rm -f ${n}; exit $rc`}'`}function V(){return `EVOLVE-EOS-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function T(s,t){return s.trim()?`{ :
|
|
2
|
+
${s}
|
|
3
|
+
|
|
4
|
+
}; __evolve_eos=$?; printf '%s' '${t}'; (exit $__evolve_eos)`:s}function Z(s,t){return s.endsWith(`${t}
|
|
5
|
+
`)?s.slice(0,-(t.length+1)):s.endsWith(t)?s.slice(0,-t.length):s}function x(s,t){let e=at(s);return {stdout:Z(e.stdout,t),stderr:e.stderr}}function M(s,t){let e=`${s}
|
|
6
|
+
`,n="",o=l=>{for(let r=Math.min(l.length,e.length);r>0;r--)if(e.startsWith(l.slice(l.length-r)))return r;return 0};return {push(l){n+=l;let r=o(n);r!==n.length&&(t(n.slice(0,n.length-r)),n=n.slice(n.length-r));},flush(){let l=n===e||n===s?"":n;n="",l&&t(l);}}}function E(s,t,e,n){let o=s;return t&&(o=`cd '${t.replace(/'/g,"'\\''")}' && ${o}`),e&&Object.keys(e).length>0&&(o=`${Object.entries(e).filter(([,r])=>r!=null).map(([r,a])=>`export ${r}='${String(a).replace(/'/g,"'\\''")}'`).join("; ")}; ${o}`),n==="root"&&(o=`echo ${Buffer.from(o).toString("base64")} | base64 -d | sudo -n bash`),o}var bt=s=>resolve4(s);function J(s){let t=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,3}))?$/.exec(s);return !(!t||[t[1],t[2],t[3],t[4]].some(e=>Number(e)>255)||t[5]!==void 0&&Number(t[5])>32)}function St(s){return /^\d{1,3}(\.\d{1,3}){3}(\/\d+)?$/.test(s)&&!J(s)}function vt(s){return s.startsWith("[")?true:(s.match(/:/g)?.length??0)>=2}function Pt(s){return /^[^:]+:\d+$/.test(s)}async function tt(s,t=bt){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 e=s.allowedDestinations??[];if(e.length===0)return {networkBlockAll:true};let n=[],o=[];for(let r of e)if(J(r))n.push(r.includes("/")?r:`${r}/32`);else {if(St(r))throw new h("invalid-ipv4",`"${r}" is not a valid IPv4 address or CIDR (octets must be 0-255, prefix 0-32). Fix the address or list a hostname instead.`,r);if(vt(r))throw new h("ipv6-unsupported",`Daytona's network allowlist supports IPv4 CIDRs only; cannot allow IPv6 destination "${r}".`,r);if(Pt(r))throw new h("port-unsupported",`Daytona's network allowlist filters hosts and IPs only and cannot match a port; drop the ":<port>" from "${r}" and list just the host or IP.`,r);if(r.includes("*"))throw new h("wildcard-hostname",`Daytona cannot enforce wildcard hostname "${r}": its allowlist is kernel-level IPv4 CIDR filtering with no DNS/domain layer. List concrete hostnames or IPv4 CIDRs instead.`,r);o.push(r);}for(let r of o){let a=[];try{a=await t(r);}catch(i){throw new h("unresolvable-hostname",`Cannot pin hostname "${r}" 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.`,r)}if(a.length===0)throw new h("unresolvable-hostname",`Hostname "${r}" resolved to no IPv4 addresses. Daytona enforces IPv4 CIDRs only; use an IPv4 CIDR for this destination instead.`,r);console.warn(`[daytona] Network allowlist: pinning "${r}" 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 l=[...new Set(n)];if(l.length>W)throw new h("allowlist-too-large",`Daytona allows at most ${W} entries in its network allowlist; this policy resolved to ${l.length} CIDRs (${l.join(", ")}). Aggregate destinations into broader CIDRs or reduce the list.`);return {networkBlockAll:false,networkAllowList:l.join(",")}}function et(s){let t=s.indexOf("/");if(t<0)return;let e=s.substring(0,t);return e.includes(".")||e.includes(":")||e==="localhost"?e:void 0}function U(s){return {sandboxId:s.id,image:s.snapshot??"",name:s.name,metadata:s.labels??{},startedAt:s.createdAt??""}}function nt(s){if(s==="started")return "running";if(s==="stopped"||s==="archived"||s==="paused")return "paused"}function st(s,t){if(!s||typeof s!="object")return;let e=s;if(typeof e.toolboxProxyUrl=="string"&&(e.toolboxProxyUrl=t),Array.isArray(e.items))for(let n of e.items)st(n,t);}function At(s,t){return new Proxy(s,{get(e,n,o){if(n==="getToolboxProxyUrl")return async()=>({data:{url:t}});let l=Reflect.get(e,n,o);return typeof l!="function"?l:function(...r){let a=l.apply(e,r);return a instanceof Promise?a.then(i=>(st(i?.data,t),i)):a}}})}var _=class extends Daytona{constructor(t,e){super(t);let n=this;n.sandboxApi=At(n.sandboxApi,e);}};function Dt(s,t){let e=new Uint8Array(new ArrayBuffer(s.length+t.length));return e.set(s,0),e.set(t,s.length),e}function q(s,t,e){t:for(let n=e;n+t.length<=s.length;n++){for(let o=0;o<t.length;o++)if(s[n+o]!==t[o])continue t;return n}return -1}function rt(s,t){let e=new TextDecoder("utf-8"),n=new TextDecoder("utf-8"),o=new Uint8Array(0),l="stdout",r=a=>{a.length!==0&&(l==="stdout"?s(e.decode(a,{stream:true})):t(n.decode(a,{stream:true})));};return {push(a){for(o=Dt(o,a);;){let i=q(o,STDOUT_PREFIX_BYTES,0),u=q(o,STDERR_PREFIX_BYTES,0),m=-1,d="stdout",c=0;if(i!==-1&&(u===-1||i<u)?(m=i,d="stdout",c=STDOUT_PREFIX_BYTES.length):u!==-1&&(m=u,d="stderr",c=STDERR_PREFIX_BYTES.length),m===-1){let f=Math.max(0,o.length-(MAX_PREFIX_LEN-1));r(o.subarray(0,f)),o=o.slice(f);return}r(o.subarray(0,m)),l=d,o=o.slice(m+c);}},flush(){r(o),o=new Uint8Array(0);let a=e.decode();a&&s(a);let i=n.decode();i&&t(i);}}}async function ot(s,t,e,n,o,l,r){let a=`${s.toolboxUrl.replace(/\/+$/,"")}/${encodeURIComponent(t)}/process/session/${encodeURIComponent(e)}/command/${encodeURIComponent(n)}/logs?follow=true`,i=await fetch(a,{headers:{Authorization:`Bearer ${s.apiKey}`,accept:"application/octet-stream"},...r?{signal:r}:{}});if(!i.ok)throw new Error(`Daytona managed log follow failed: ${i.status} ${await i.text()}`);if(!i.body)return;let u=rt(o,l),m=i.body.getReader();try{for(;;){let{done:d,value:c}=await m.read();if(d)break;c&&u.push(c);}}finally{u.flush(),await m.cancel().catch(()=>{});}}function at(s){let t=s.stdout||"",e=s.stderr||"",n=s.output||"";return !t&&!e&&n?{stdout:n,stderr:""}:{stdout:t,stderr:e}}var L=class{constructor(t,e,n){this.sandbox=t;this.user=e;this.managedStream=n;}streamTimings=ht;followLogs(t,e,n,o,l){return this.managedStream?ot(this.managedStream,this.sandbox.id,t,e,n,o,l):this.sandbox.process.getSessionCommandLogs(t,e,n,o)}async run(t,e){let n=e?.timeoutMs?Math.floor(e.timeoutMs/1e3):void 0,o=`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(o);try{let l=!!(e?.onStdout||e?.onStderr),r=V(),a=await this.sandbox.process.executeSessionCommand(o,{command:$(E(T(t,r),e?.cwd,e?.envs,this.user),n),runAsync:l},n),i=a.cmdId;if(l&&!i)throw new Error("Daytona returned no command id for an async command \u2014 cannot stream it or read its exit code");if(l&&i){let d="",c="",f=!0,p=Date.now(),w=M(r,g=>{d+=g,e?.onStdout?.(g);}),B=new AbortController,N=this.followLogs(o,i,g=>{f&&(p=Date.now(),w.push(g));},g=>{f&&(p=Date.now(),c+=g,e?.onStderr?.(g));},B.signal),F=!1,b,dt=N.then(()=>{},g=>{F||(b=g);}),G;try{G=await this.awaitStreamedExit(o,i,N,()=>p,e?.timeoutMs);}finally{F=!0,B.abort(),await Promise.race([dt,v(this.streamTimings.drainMs)]),f=!1,b===void 0&&w.flush();}if(b!==void 0){let g;try{let lt=await this.sandbox.process.getSessionCommandLogs(o,i);g=x(lt,r);}catch{throw b}if(!g.stdout.startsWith(d)||!g.stderr.startsWith(c))throw b;let S=g.stdout.slice(d.length),K=g.stderr.slice(c.length);d=g.stdout,c=g.stderr,S&&e?.onStdout?.(S),K&&e?.onStderr?.(K);}else if(!d&&!c)try{let g=await this.sandbox.process.getSessionCommandLogs(o,i),S=x(g,r);d=S.stdout,c=S.stderr,d&&e?.onStdout?.(d),c&&e?.onStderr?.(c);}catch{}return {exitCode:G,stdout:d,stderr:c}}let{stdout:u,stderr:m}=x(a,r);if(!u&&!m&&i)try{let d=await this.sandbox.process.getSessionCommandLogs(o,i),c=x(d,r);u=c.stdout,m=c.stderr||m;}catch{}return {exitCode:a.exitCode??0,stdout:u,stderr:m}}finally{try{await this.sandbox.process.deleteSession(o);}catch{}}}async awaitStreamedExit(t,e,n,o,l){let r=this.streamTimings,a,i,u=n.then(()=>{a=Date.now();},c=>{a=Date.now(),i=c;}),m=l!==void 0&&l>0?Date.now()+l+r.killGraceMs:void 0,d=r.pollMinMs;for(;;){let c=await this.sandbox.process.getSessionCommand(t,e);if(c.exitCode!==void 0&&c.exitCode!==null){for(;a===void 0;){let w=Date.now()-o();if(w>=r.drainMs)break;await Promise.race([u,v(r.drainMs-w)]);}return c.exitCode}let f=a!==void 0?a+r.settleMs:void 0,p=m!==void 0&&f!==void 0?Math.min(m,f):m??f;if(p!==void 0&&Date.now()>=p)throw i!==void 0?i:new Error(`Daytona reported no exit code for command ${e} after `+(a!==void 0?"its log stream closed":`${l}ms`));await v(d),d=Math.min(d*2,r.pollMaxMs);}}async spawn(t,e){let n=`evolve-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await this.sandbox.process.createSession(n);let o=e?.timeoutMs?Math.floor(e.timeoutMs/1e3):void 0,l=Date.now(),r=e?.timeoutMs,a=V(),u=(await this.sandbox.process.executeSessionCommand(n,{command:$(E(T(t,a),e?.cwd,e?.envs,this.user),o),runAsync:true},o)).cmdId;if(u&&(e?.onStdout||e?.onStderr)){let d=M(a,e.onStdout||(()=>{}));this.followLogs(n,u,c=>d.push(c),e.onStderr||(()=>{})).catch(()=>{}).finally(()=>d.flush());}let m=this.sandbox;return {processId:n,wait:async()=>{if(!u)return {exitCode:0,stdout:"",stderr:""};for(;;){if(r&&Date.now()-l>=r){try{await m.process.deleteSession(n);}catch{}return {exitCode:124,stdout:"",stderr:"operation timed out"}}try{let d=await m.process.getSessionCommand(n,u);if(d.exitCode!==void 0)try{let c=await m.process.getSessionCommandLogs(n,u);return {exitCode:d.exitCode,...x(c,a)}}catch{return {exitCode:d.exitCode,stdout:"",stderr:""}}}catch(d){let c=d instanceof Error?d.message.toLowerCase():String(d).toLowerCase();if(c.includes("not found")){let f=c.includes("sandbox");try{await m.refreshData(),f=!1;}catch(p){(p instanceof Error?p.message.toLowerCase():String(p).toLowerCase()).includes("not found")&&(f=true);}return {exitCode:-1,stdout:"",stderr:f?"sandbox deleted during run":"session terminated"}}throw d}await v(500);}},kill:async()=>{try{return await m.process.deleteSession(n),!0}catch{return false}}}}async list(){try{return (await this.sandbox.process.listSessions()).map(e=>({processId:e.sessionId||"",cmd:"",args:[],envs:{}}))}catch{return []}}async kill(t){try{return await this.sandbox.process.deleteSession(t),!0}catch{return false}}},R=class{constructor(t){this.sandbox=t;}async read(t){let e=new Uint8Array(await this.sandbox.fs.downloadFile(t));if(!e.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{}return e}async write(t,e){let n;if(typeof e=="string")n=Buffer.from(e,"utf-8");else if(Buffer.isBuffer(e))n=e;else if(e instanceof ArrayBuffer)n=Buffer.from(e);else if(e instanceof Uint8Array)n=Buffer.from(e);else throw new Error(`Unsupported content type: ${typeof e}`);await this.sandbox.fs.uploadFile(n,t);}async writeBatch(t){let e=t.map(n=>{let o;if(typeof n.data=="string")o=Buffer.from(n.data,"utf-8");else if(Buffer.isBuffer(n.data))o=n.data;else if(n.data instanceof ArrayBuffer)o=Buffer.from(n.data);else if(n.data instanceof Uint8Array)o=Buffer.from(n.data);else throw new Error(`Unsupported content type: ${typeof n.data}`);return {source:o,destination:n.path}});await this.sandbox.fs.uploadFiles(e);}async writeFromPath(t,e){await this.sandbox.fs.uploadFile(e,t);}async makeDir(t){await this.sandbox.fs.createFolder(t,"755");}async exists(t){try{let e=wt(t),n=xt(t);return (await this.sandbox.fs.listFiles(e)).some(l=>l.name===n)}catch{return false}}async list(t){return (await this.sandbox.fs.listFiles(t)).map(n=>({name:n.name,path:t.endsWith("/")?`${t}${n.name}`:`${t}/${n.name}`,type:n.isDir?"dir":"file"}))}async remove(t){await this.sandbox.fs.deleteFile(t,true);}async rename(t,e){await this.sandbox.fs.moveFiles(t,e);}},A=class{constructor(t,e,n){this.sandbox=t;this.commands=new L(t,e,n),this.files=new R(t);}commands;files;get sandboxId(){return this.sandbox.id}async getHost(t){return (await this.sandbox.getPreviewLink(t)).url}async isRunning(){try{await this.sandbox.refreshData();}catch{return false}return this.sandbox.state==="started"}async getInfo(){return await this.sandbox.refreshData(),U(this.sandbox)}async kill(){await this.sandbox.delete();}async pause(){await this.sandbox.stop();}},O=class{providerType="daytona";name="Daytona";client;defaultTimeoutMs;snapshotName;sandboxUsers=new Map;managedStream;constructor(t){let e={apiKey:t.apiKey,apiUrl:t.apiUrl,target:t.target,useDeprecatedPolling:true};this.client=t.managedToolboxUrl?new _(e,t.managedToolboxUrl):new Daytona(e),t.managedToolboxUrl&&(this.managedStream={toolboxUrl:t.managedToolboxUrl,apiKey:t.apiKey}),this.defaultTimeoutMs=t.defaultTimeoutMs??36e5,this.snapshotName=t.snapshotName??(t.managedToolboxUrl?"evolve-all":`evolve-all-${D}`);}async create(t){if(t.idleTimeoutMs!==void 0)throw new C;let e=await tt(t.network),n=t.user,o=n&&n!=="root"?n:void 0,l=t.timeoutMs??this.defaultTimeoutMs,r=Math.max(1,Math.ceil(l/6e4)),a=t.image||this.snapshotName,i={envVars:t.envs,labels:t.metadata,autoStopInterval:r,autoDeleteInterval:ft,...o?{user:o}:{},...e},u,m=t.resources!==void 0&&(t.resources.cpu!==void 0||t.resources.memory!==void 0||t.resources.disk!==void 0||t.resources.gpu!==void 0||t.resources.gpuTypes!==void 0);if(this.managedStream){if(m)throw new P(a);let d=await this.client.create({snapshot:a,...i},{timeout:600});return t.workingDirectory&&await d.fs.createFolder(t.workingDirectory,"755"),n&&this.sandboxUsers.set(d.id,n),new A(d,n,this.managedStream)}try{let d=await this.client.snapshot.get(a),c=d?.state;if(d&&(c==="active"||c==="inactive")&&m)throw new P(a);if(d&&c==="inactive"&&(c=(await Q(this.client,a,d)).state),d&&c==="active")console.log(`[daytona] Using cached snapshot: ${a}`),u=await this.client.create({snapshot:a,...i},{timeout:600});else throw new Error("Snapshot not active")}catch(d){if(d instanceof P||d instanceof y)throw d;let c=X[a]??a;console.log(`[daytona] Snapshot "${a}" not found, building from image: ${c}`),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(c),resources:{cpu:t.resources?.cpu??4,memory:t.resources?.memory??4,disk:t.resources?.disk??10,...(t.resources?.gpu??0)>0?{gpu:t.resources.gpu}:{},...t.resources?.gpuTypes?.length?{gpuType:t.resources.gpuTypes}:{}}},{onLogs:f=>console.log(`[daytona] ${f}`)}),console.log(`[daytona] Snapshot "${a}" ready.`),u=await this.client.create({snapshot:a,...i},{timeout:600});}catch(f){console.warn(`[daytona] Snapshot creation failed, falling back to direct image: ${f instanceof Error?f.message:f}`);try{u=await this.client.create({image:c,...i,resources:{cpu:t.resources?.cpu??4,memory:t.resources?.memory??4,disk:t.resources?.disk??10,...(t.resources?.gpu??0)>0?{gpu:t.resources.gpu}:{},...t.resources?.gpuTypes?.length?{gpuType:t.resources.gpuTypes}:{}}},{timeout:600,onSnapshotCreateLogs:p=>console.log(`[daytona] ${p}`)});}catch(p){throw et(c)?new k(c,p):p}}}return t.workingDirectory&&await u.fs.createFolder(t.workingDirectory,"755"),n&&this.sandboxUsers.set(u.id,n),new A(u,n,this.managedStream)}async connect(t,e){let n=await this.client.get(t);return n.state!=="started"&&await n.start(),new A(n,this.sandboxUsers.get(t),this.managedStream)}async list(t){let e=await this.paginate(t);if(e.error&&!e.stoppedAtLimit)throw new Error(e.error);return e.sandboxes}async listAll(t){let{stoppedAtLimit:e,...n}=await this.paginate(t);return n}async paginate(t){return it(this.listStream(t),t)}listStream(t){let e=t?.state?It(t.state):void 0,n={limit:yt,...t?.metadata?{labels:t.metadata}:{},...e&&e.length>0?{states:e}:{}};return this.client.list(n)}};function It(s){let t=[];for(let e of s)e==="running"&&t.push("started"),e==="paused"&&t.push("stopped","archived","paused");return t}async function it(s,t){let e=t?.limit,n=[],o=0,l=new Set;try{for await(let r of s){if(e!==void 0&&n.length>=e)return {sandboxes:n,complete:!1,pagesFetched:o,stoppedAtLimit:!0,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(o+=1,o>I)return {sandboxes:n,complete:!1,pagesFetched:I,stoppedAtLimit:!1,error:`sandbox list exceeded ${I} sandboxes scanned`};if(t?.state){let a=nt(r.state);if(a===void 0||!t.state.includes(a))continue}l.has(r.id)||(l.add(r.id),n.push(U(r)));}}catch(r){return {sandboxes:n,complete:false,pagesFetched:o,stoppedAtLimit:false,error:`sandbox list failed: ${r instanceof Error?r.message:String(r)}`}}return {sandboxes:n,complete:true,pagesFetched:o,stoppedAtLimit:false}}var Mt=it;function Et(s={}){let t=s.apiKey??process.env.DAYTONA_API_KEY;if(!t)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 O({...s,apiKey:t})}var _t=E,Lt=$,Rt=tt,Ot=et,Ut=U,Bt=nt,Nt=Q,Ft=X,Gt=T,Kt=Z,Ht=x,Yt=M,Wt=rt,jt=ot,Vt=at;
|
|
7
|
+
export{ft as DAYTONA_AUTO_DELETE_GRACE_MINUTES,yt as DAYTONA_LIST_PAGE_SIZE,I as DAYTONA_MAX_LIST_SCAN,W as DAYTONA_MAX_NETWORK_ALLOWLIST,gt as DAYTONA_SNAPSHOT_ACTIVATE_TIMEOUT_MS,ht as DAYTONA_STREAM_TIMINGS,L as DaytonaCommands,R as DaytonaFiles,j as DaytonaGpuTypeError,C as DaytonaIdleTimeoutError,k as DaytonaImagePullError,h as DaytonaNetworkPolicyError,O as DaytonaProvider,P as DaytonaResourcesError,y as DaytonaSnapshotActivationError,D as EVOLVE_IMAGE_VERSION,Nt as _testActivateSnapshot,Mt as _testCollectSandboxStream,Wt as _testCreateLogDemuxer,Yt as _testCreateSentinelFilter,Bt as _testDaytonaStateToEvolveState,jt as _testFollowManagedSessionLogs,Ft as _testImageMap,Ot as _testImageRegistryHost,Rt as _testMapNetworkPolicy,Vt as _testReadCommandStreams,Ht as _testSettledStreams,Kt as _testStripEndOfOutputSentinel,Ut as _testToSandboxInfo,Gt as _testWithEndOfOutputSentinel,Lt as _testWithInBoxTimeout,_t as _testWrapCommand,Et as createDaytonaProvider};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolvingmachines/daytona",
|
|
3
|
-
"version": "0.0.52-project-sable.
|
|
3
|
+
"version": "0.0.52-project-sable.20260810.ca7ed91",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"ai",
|
|
6
6
|
"agents",
|
|
@@ -33,10 +33,10 @@
|
|
|
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 && tsx tests/unit/daytona-provider.test.ts && tsx tests/unit/daytona-managed.test.ts && tsx tests/unit/daytona-list-pagination.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 && tsx tests/unit/daytona-list-pagination.test.ts && tsx tests/unit/daytona-image-version.test.ts && tsx tests/unit/daytona-files-read.test.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@daytonaio/sdk": "^0.
|
|
39
|
+
"@daytonaio/sdk": "^0.203.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^22.15.18",
|