@veris-ai/daytona 0.3.0 → 0.3.1

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 CHANGED
@@ -243,6 +243,35 @@ for you, between `--setup` and the command; a sandbox from `provision` carries
243
243
  the same patcher as a script at `/tmp/veris-patch-bundled-cas.sh`, so whoever
244
244
  installed the dependencies can run it with no SDK in hand.
245
245
 
246
+ ### Node, and what `NODE_OPTIONS` carries
247
+
248
+ Three things make a Node process in the sandbox reach the twin, and the SDK
249
+ sets all of them at create time:
250
+
251
+ | variable | why |
252
+ |---|---|
253
+ | `NODE_USE_ENV_PROXY=1` | Node ignores `HTTPS_PROXY` otherwise, and Daytona blocks a direct dial |
254
+ | `NODE_OPTIONS=--require /tmp/veris-node-proxy.cjs` | `NODE_USE_ENV_PROXY` reaches only the global agents; the preload gives every `http(s).Agent` the proxy environment, which is what an SDK with its own keep-alive agent (stripe-node, the AWS SDK, Twilio) needs |
255
+ | `NODE_OPTIONS=--use-openssl-ca` | Daytona overwrites `NODE_EXTRA_CA_CERTS`; this makes Node read the system store the Veris CA is installed into |
256
+
257
+ `NODE_OPTIONS` is one variable, so an application that sets its own value for
258
+ a command (`--experimental-vm-modules`, `--max-old-space-size`) would drop
259
+ both flags and every vendor call would fail on DNS or on the certificate. Build
260
+ the value with `verisNodeOptions(yourOptions)`, which appends the two flags
261
+ once, or pass it through `exec --env NODE_OPTIONS=…`, which merges them for
262
+ you:
263
+
264
+ ```ts
265
+ import { verisNodeOptions } from '@veris-ai/daytona'
266
+ await sbx.process.executeCommand('npx jest', cwd, {
267
+ ...sbx.veris.getTrustEnv(),
268
+ NODE_OPTIONS: verisNodeOptions('--experimental-vm-modules'),
269
+ })
270
+ ```
271
+
272
+ Clients built on undici `Pool` or `Client` hold their own dispatcher and are
273
+ not covered by the preload.
274
+
246
275
  ## Options
247
276
 
248
277
  ```ts
package/dist/cli.js CHANGED
@@ -480,9 +480,38 @@ function bundledCaPatchScript() {
480
480
  }
481
481
  var NODE_TRUST_FLAG = "--use-openssl-ca";
482
482
  function nodeOptionsWithTrust(existing) {
483
+ return appendFlag(existing, NODE_TRUST_FLAG);
484
+ }
485
+ var NODE_PROXY_PRELOAD = "/tmp/veris-node-proxy.cjs";
486
+ var NODE_PROXY_FLAG = `--require ${NODE_PROXY_PRELOAD}`;
487
+ function nodeProxyPreloadScript() {
488
+ return [
489
+ `// Preloaded by @veris-ai/daytona through NODE_OPTIONS=--require.`,
490
+ `// Gives every http(s).Agent the proxy environment, which Node applies only`,
491
+ `// to its global agents under NODE_USE_ENV_PROXY=1. An SDK that builds its own`,
492
+ `// Agent would otherwise dial the vendor directly, which this sandbox cannot.`,
493
+ `for (const mod of [require("http"), require("https")]) {`,
494
+ ` const Base = mod.Agent`,
495
+ ` mod.Agent = class Agent extends Base {`,
496
+ ` constructor(options) {`,
497
+ ` super({ proxyEnv: process.env, ...(options || {}) })`,
498
+ ` }`,
499
+ ` }`,
500
+ `}`,
501
+ ``
502
+ ].join("\n");
503
+ }
504
+ function nodeOptionsWithProxy(existing) {
505
+ return appendFlag(existing, NODE_PROXY_FLAG);
506
+ }
507
+ function verisNodeOptions(existing, opts = {}) {
508
+ const withProxy = nodeOptionsWithProxy(existing);
509
+ return opts.trust === false ? withProxy : nodeOptionsWithTrust(withProxy);
510
+ }
511
+ function appendFlag(existing, flag) {
483
512
  const base = (existing ?? "").trim();
484
- if (base.split(/\s+/).includes(NODE_TRUST_FLAG)) return base;
485
- return base ? `${base} ${NODE_TRUST_FLAG}` : NODE_TRUST_FLAG;
513
+ if (base === flag || base.startsWith(`${flag} `) || base.endsWith(` ${flag}`) || base.includes(` ${flag} `)) return base;
514
+ return base ? `${base} ${flag}` : flag;
486
515
  }
487
516
  var CA_INSTALL_CMD = [
488
517
  "update-ca-certificates",
@@ -555,6 +584,7 @@ function assertProxyUrl(raw) {
555
584
  async function installCa(sandbox, caPem) {
556
585
  await sandbox.fs.uploadFile(Buffer.from(caPem, "utf8"), VERIS_CA_FILE);
557
586
  await sandbox.fs.uploadFile(Buffer.from(bundledCaPatchScript(), "utf8"), BUNDLED_CA_PATCH_SCRIPT);
587
+ await installNodeProxyPreload(sandbox);
558
588
  const script = [
559
589
  `chmod 0644 ${VERIS_CA_FILE}`,
560
590
  // Public roots first so they keep working; ours appended. `cat` of a
@@ -580,6 +610,9 @@ async function installCa(sandbox, caPem) {
580
610
  );
581
611
  }
582
612
  }
613
+ async function installNodeProxyPreload(sandbox) {
614
+ await sandbox.fs.uploadFile(Buffer.from(nodeProxyPreloadScript(), "utf8"), NODE_PROXY_PRELOAD);
615
+ }
583
616
  async function patchBundledCas(sandbox) {
584
617
  const r = await sh(sandbox, `sh ${BUNDLED_CA_PATCH_SCRIPT}`, 180).catch((e) => ({ exitCode: 1, result: String(e) }));
585
618
  return (r.result ?? "").split("\n").filter((line) => line.startsWith(BUNDLED_CA_PATCHED_MARKER)).map((line) => line.slice(BUNDLED_CA_PATCHED_MARKER.length).trim()).filter(Boolean);
@@ -872,7 +905,7 @@ function requireVerisCredentials(opts = {}) {
872
905
  }
873
906
 
874
907
  // src/version.ts
875
- var SDK_VERSION = true ? "0.3.0" : "0.0.0-dev";
908
+ var SDK_VERSION = true ? "0.3.1" : "0.0.0-dev";
876
909
 
877
910
  // src/daytona.ts
878
911
  var LABEL = {
@@ -950,9 +983,12 @@ var Daytona = class extends BaseDaytona {
950
983
  const verisManaged = {
951
984
  ...v.installCa !== false ? sanitizeTrustEnv(void 0) : {},
952
985
  // Node reads none of the variables above once Daytona has overwritten
953
- // them; the flag makes it read OpenSSL's store, which the CA install
954
- // fills. Appended, not replaced: a caller's own NODE_OPTIONS keep working.
955
- ...v.installCa !== false ? { NODE_OPTIONS: nodeOptionsWithTrust(rest.envVars?.NODE_OPTIONS) } : {},
986
+ // them; the trust flag makes it read OpenSSL's store, which the CA
987
+ // install fills. The preload gives every http(s).Agent the proxy
988
+ // environment, which NODE_USE_ENV_PROXY below reaches only for the
989
+ // global ones. Appended, not replaced: a caller's own NODE_OPTIONS keep
990
+ // working.
991
+ NODE_OPTIONS: verisNodeOptions(rest.envVars?.NODE_OPTIONS, { trust: v.installCa !== false }),
956
992
  // Node ignores HTTPS_PROXY unless told to, and Daytona blocks anything
957
993
  // that dials out directly — so without this every plain `https.get`
958
994
  // and `fetch` in Node 24+ dies with ECONNRESET instead of reaching
@@ -995,7 +1031,8 @@ var Daytona = class extends BaseDaytona {
995
1031
  });
996
1032
  }
997
1033
  try {
998
- await installCa(sandbox, credential.ca_pem);
1034
+ if (v.installCa !== false) await installCa(sandbox, credential.ca_pem);
1035
+ else await installNodeProxyPreload(sandbox);
999
1036
  await probeCanary(sandbox, credential.canary_host, twin.id);
1000
1037
  } catch (err) {
1001
1038
  await sandbox.delete().catch(() => {
@@ -1344,7 +1381,9 @@ function shellQuote2(s) {
1344
1381
  return `'${s.replace(/'/g, `'\\''`)}'`;
1345
1382
  }
1346
1383
  function commandEnv(trust, user) {
1347
- return { ...trust, ...user };
1384
+ const env = { ...trust, ...user };
1385
+ if (typeof user.NODE_OPTIONS === "string") env.NODE_OPTIONS = verisNodeOptions(user.NODE_OPTIONS);
1386
+ return env;
1348
1387
  }
1349
1388
 
1350
1389
  // src/push.ts