@arker-ai/sdk 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,6 +56,7 @@ var Arker = class {
56
56
  provider;
57
57
  apiKey;
58
58
  fetchImpl;
59
+ http2;
59
60
  retry;
60
61
  constructor(opts = {}) {
61
62
  const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
@@ -77,6 +78,7 @@ var Arker = class {
77
78
  this.region = region ? normalizeRegion(region) : void 0;
78
79
  this.provider = effectiveProvider;
79
80
  this.fetchImpl = opts.fetch ?? globalThis.fetch;
81
+ this.http2 = opts.fetch === void 0;
80
82
  this.retry = normalizeRetry(opts.retry);
81
83
  if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
82
84
  }
@@ -137,7 +139,10 @@ var Arker = class {
137
139
  egress: src.egress ?? null,
138
140
  disk: src.disk ?? true,
139
141
  durable: src.durable ?? null,
140
- resources
142
+ resources,
143
+ // ARK-125: omit to inherit the source's policy; pass a doc to override
144
+ // (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
145
+ policies: src.policies ?? null
141
146
  };
142
147
  const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
143
148
  const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
@@ -232,30 +237,29 @@ var Arker = class {
232
237
  if (value !== void 0) headers[key] = value;
233
238
  }
234
239
  }
235
- const init = { method, headers };
240
+ let requestBody;
236
241
  if (body !== void 0) {
237
242
  headers["content-type"] = "application/json";
238
- init.body = JSON.stringify(withoutUndefined(body));
243
+ requestBody = JSON.stringify(withoutUndefined(body));
239
244
  }
240
245
  let lastStatus = 0;
241
246
  let lastText = "";
242
247
  let lastError;
243
248
  for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
244
249
  try {
245
- const response = await this.fetchImpl(url, init);
246
- const text = await response.text();
250
+ const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
247
251
  const payload = parseJson(text);
248
252
  const parsedError = extractError(payload);
249
- lastStatus = response.status;
253
+ lastStatus = status;
250
254
  lastText = text;
251
255
  lastError = parsedError;
252
- if (isRetryable(response.status, parsedError) && attempt < this.retry.attempts - 1) {
256
+ if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
253
257
  await sleep(retryDelay(this.retry, attempt));
254
258
  continue;
255
259
  }
256
- if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, response.status);
257
- if (!response.ok) {
258
- throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${response.status}`, response.status);
260
+ if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
261
+ if (!ok) {
262
+ throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
259
263
  }
260
264
  return payload;
261
265
  } catch (error) {
@@ -467,6 +471,32 @@ var VM = class _VM {
467
471
  async delete() {
468
472
  return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
469
473
  }
474
+ // ── ARK-125 egress policy ────────────────────────────────────────
475
+ /**
476
+ * Read this VM's outbound egress policy document (ARK-125). Returns an
477
+ * empty doc (`{}`) when no policy is set.
478
+ */
479
+ async getPolicies() {
480
+ return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
481
+ }
482
+ /**
483
+ * Replace this VM's outbound egress policy with `doc` — an ordered,
484
+ * first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
485
+ * clears the policy to allow-all. Returns the stored policy plus the
486
+ * domains it escalates to MITM and any degrade warnings.
487
+ *
488
+ * await vm.setPolicies({
489
+ * policies: [
490
+ * { type: "network.outbound",
491
+ * match: { domains: ["github.com"], ports: [443] },
492
+ * action: "allow" },
493
+ * { type: "network.outbound", action: "deny" },
494
+ * ],
495
+ * });
496
+ */
497
+ async setPolicies(doc) {
498
+ return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
499
+ }
470
500
  // ── Syncs: bindings of a filesystem into this VM at a path ────────
471
501
  async listSyncs(opts = {}) {
472
502
  return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
@@ -518,6 +548,20 @@ var VM = class _VM {
518
548
  async deleteSession(sessionId) {
519
549
  return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
520
550
  }
551
+ /**
552
+ * Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
553
+ * (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
554
+ * PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
555
+ * (which sends an in-band control frame on the live WebSocket).
556
+ */
557
+ async updateSession(sessionId, update) {
558
+ return this._client._request(
559
+ "PATCH",
560
+ `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
561
+ { cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
562
+ this.baseUrl
563
+ );
564
+ }
521
565
  async connectPty(options = {}) {
522
566
  const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
523
567
  const useTicket = options.useTicket ?? !isNodeRuntime();
@@ -929,6 +973,84 @@ function base64ToBytes(text) {
929
973
  function bufferConstructor() {
930
974
  return globalThis.Buffer;
931
975
  }
976
+ var http2Module;
977
+ function loadHttp2() {
978
+ return http2Module ??= (async () => {
979
+ const proc = globalThis.process;
980
+ if (!proc?.versions?.node) return null;
981
+ try {
982
+ return await import(
983
+ /* webpackIgnore: true */
984
+ /* @vite-ignore */
985
+ "http2"
986
+ );
987
+ } catch {
988
+ return null;
989
+ }
990
+ })();
991
+ }
992
+ var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
993
+ var Http2Connection = class {
994
+ confirmed = false;
995
+ streams = 0;
996
+ session;
997
+ constructor(http2, origin) {
998
+ this.session = http2.connect(origin);
999
+ this.session.on("error", () => {
1000
+ });
1001
+ }
1002
+ get closed() {
1003
+ return this.session.closed || this.session.destroyed;
1004
+ }
1005
+ request(method, path, headers, body) {
1006
+ if (this.streams === 0) this.session.ref();
1007
+ this.streams++;
1008
+ return new Promise((resolve, reject) => {
1009
+ const stream = this.session.request({ ...headers, ":method": method, ":path": path });
1010
+ let status = 0;
1011
+ let text = "";
1012
+ stream.setEncoding("utf8");
1013
+ stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
1014
+ stream.on("response", (responseHeaders) => {
1015
+ this.confirmed = true;
1016
+ status = Number(responseHeaders[":status"]) || 0;
1017
+ });
1018
+ stream.on("data", (chunk) => {
1019
+ text += chunk;
1020
+ });
1021
+ stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
1022
+ stream.on("error", reject);
1023
+ stream.end(body);
1024
+ }).finally(() => {
1025
+ if (--this.streams === 0) this.session.unref();
1026
+ });
1027
+ }
1028
+ };
1029
+ var http2Connections = /* @__PURE__ */ new Map();
1030
+ async function sendRequest(url, init, fetchImpl, http2Enabled) {
1031
+ if (http2Enabled) {
1032
+ const http2 = await loadHttp2();
1033
+ if (http2) {
1034
+ const { origin, pathname, search } = new URL(url);
1035
+ const cached = http2Connections.get(origin);
1036
+ if (cached !== null) {
1037
+ let connection = cached;
1038
+ if (!connection || connection.closed) {
1039
+ connection = new Http2Connection(http2, origin);
1040
+ http2Connections.set(origin, connection);
1041
+ }
1042
+ try {
1043
+ return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
1044
+ } catch (error) {
1045
+ if (connection.confirmed) throw error;
1046
+ http2Connections.set(origin, null);
1047
+ }
1048
+ }
1049
+ }
1050
+ }
1051
+ const response = await fetchImpl(url, init);
1052
+ return { status: response.status, ok: response.ok, text: await response.text() };
1053
+ }
932
1054
 
933
1055
  export {
934
1056
  CHUNK_SIZE,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Arker,
3
3
  ArkerError
4
- } from "./chunk-7BHPVQNG.js";
4
+ } from "./chunk-4NHUAVXK.js";
5
5
 
6
6
  // src/compat/common.ts
7
7
  function shouldGuardNested(value) {
package/dist/cli.cjs CHANGED
@@ -89,6 +89,7 @@ var Arker = class {
89
89
  provider;
90
90
  apiKey;
91
91
  fetchImpl;
92
+ http2;
92
93
  retry;
93
94
  constructor(opts = {}) {
94
95
  const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
@@ -110,6 +111,7 @@ var Arker = class {
110
111
  this.region = region ? normalizeRegion(region) : void 0;
111
112
  this.provider = effectiveProvider;
112
113
  this.fetchImpl = opts.fetch ?? globalThis.fetch;
114
+ this.http2 = opts.fetch === void 0;
113
115
  this.retry = normalizeRetry(opts.retry);
114
116
  if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
115
117
  }
@@ -170,7 +172,10 @@ var Arker = class {
170
172
  egress: src.egress ?? null,
171
173
  disk: src.disk ?? true,
172
174
  durable: src.durable ?? null,
173
- resources
175
+ resources,
176
+ // ARK-125: omit to inherit the source's policy; pass a doc to override
177
+ // (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
178
+ policies: src.policies ?? null
174
179
  };
175
180
  const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
176
181
  const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
@@ -265,30 +270,29 @@ var Arker = class {
265
270
  if (value !== void 0) headers[key] = value;
266
271
  }
267
272
  }
268
- const init = { method, headers };
273
+ let requestBody;
269
274
  if (body !== void 0) {
270
275
  headers["content-type"] = "application/json";
271
- init.body = JSON.stringify(withoutUndefined(body));
276
+ requestBody = JSON.stringify(withoutUndefined(body));
272
277
  }
273
278
  let lastStatus = 0;
274
279
  let lastText = "";
275
280
  let lastError;
276
281
  for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
277
282
  try {
278
- const response = await this.fetchImpl(url, init);
279
- const text = await response.text();
283
+ const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
280
284
  const payload = parseJson(text);
281
285
  const parsedError = extractError(payload);
282
- lastStatus = response.status;
286
+ lastStatus = status;
283
287
  lastText = text;
284
288
  lastError = parsedError;
285
- if (isRetryable(response.status, parsedError) && attempt < this.retry.attempts - 1) {
289
+ if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
286
290
  await sleep(retryDelay(this.retry, attempt));
287
291
  continue;
288
292
  }
289
- if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, response.status);
290
- if (!response.ok) {
291
- throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${response.status}`, response.status);
293
+ if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
294
+ if (!ok) {
295
+ throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
292
296
  }
293
297
  return payload;
294
298
  } catch (error) {
@@ -500,6 +504,32 @@ var VM = class _VM {
500
504
  async delete() {
501
505
  return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
502
506
  }
507
+ // ── ARK-125 egress policy ────────────────────────────────────────
508
+ /**
509
+ * Read this VM's outbound egress policy document (ARK-125). Returns an
510
+ * empty doc (`{}`) when no policy is set.
511
+ */
512
+ async getPolicies() {
513
+ return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
514
+ }
515
+ /**
516
+ * Replace this VM's outbound egress policy with `doc` — an ordered,
517
+ * first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
518
+ * clears the policy to allow-all. Returns the stored policy plus the
519
+ * domains it escalates to MITM and any degrade warnings.
520
+ *
521
+ * await vm.setPolicies({
522
+ * policies: [
523
+ * { type: "network.outbound",
524
+ * match: { domains: ["github.com"], ports: [443] },
525
+ * action: "allow" },
526
+ * { type: "network.outbound", action: "deny" },
527
+ * ],
528
+ * });
529
+ */
530
+ async setPolicies(doc) {
531
+ return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
532
+ }
503
533
  // ── Syncs: bindings of a filesystem into this VM at a path ────────
504
534
  async listSyncs(opts = {}) {
505
535
  return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
@@ -551,6 +581,20 @@ var VM = class _VM {
551
581
  async deleteSession(sessionId) {
552
582
  return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
553
583
  }
584
+ /**
585
+ * Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
586
+ * (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
587
+ * PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
588
+ * (which sends an in-band control frame on the live WebSocket).
589
+ */
590
+ async updateSession(sessionId, update) {
591
+ return this._client._request(
592
+ "PATCH",
593
+ `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
594
+ { cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
595
+ this.baseUrl
596
+ );
597
+ }
554
598
  async connectPty(options = {}) {
555
599
  const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
556
600
  const useTicket = options.useTicket ?? !isNodeRuntime();
@@ -962,6 +1006,84 @@ function base64ToBytes(text) {
962
1006
  function bufferConstructor() {
963
1007
  return globalThis.Buffer;
964
1008
  }
1009
+ var http2Module;
1010
+ function loadHttp2() {
1011
+ return http2Module ??= (async () => {
1012
+ const proc = globalThis.process;
1013
+ if (!proc?.versions?.node) return null;
1014
+ try {
1015
+ return await import(
1016
+ /* webpackIgnore: true */
1017
+ /* @vite-ignore */
1018
+ "http2"
1019
+ );
1020
+ } catch {
1021
+ return null;
1022
+ }
1023
+ })();
1024
+ }
1025
+ var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
1026
+ var Http2Connection = class {
1027
+ confirmed = false;
1028
+ streams = 0;
1029
+ session;
1030
+ constructor(http2, origin) {
1031
+ this.session = http2.connect(origin);
1032
+ this.session.on("error", () => {
1033
+ });
1034
+ }
1035
+ get closed() {
1036
+ return this.session.closed || this.session.destroyed;
1037
+ }
1038
+ request(method, path, headers, body) {
1039
+ if (this.streams === 0) this.session.ref();
1040
+ this.streams++;
1041
+ return new Promise((resolve, reject) => {
1042
+ const stream = this.session.request({ ...headers, ":method": method, ":path": path });
1043
+ let status = 0;
1044
+ let text = "";
1045
+ stream.setEncoding("utf8");
1046
+ stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
1047
+ stream.on("response", (responseHeaders) => {
1048
+ this.confirmed = true;
1049
+ status = Number(responseHeaders[":status"]) || 0;
1050
+ });
1051
+ stream.on("data", (chunk) => {
1052
+ text += chunk;
1053
+ });
1054
+ stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
1055
+ stream.on("error", reject);
1056
+ stream.end(body);
1057
+ }).finally(() => {
1058
+ if (--this.streams === 0) this.session.unref();
1059
+ });
1060
+ }
1061
+ };
1062
+ var http2Connections = /* @__PURE__ */ new Map();
1063
+ async function sendRequest(url, init, fetchImpl, http2Enabled) {
1064
+ if (http2Enabled) {
1065
+ const http2 = await loadHttp2();
1066
+ if (http2) {
1067
+ const { origin, pathname, search } = new URL(url);
1068
+ const cached = http2Connections.get(origin);
1069
+ if (cached !== null) {
1070
+ let connection = cached;
1071
+ if (!connection || connection.closed) {
1072
+ connection = new Http2Connection(http2, origin);
1073
+ http2Connections.set(origin, connection);
1074
+ }
1075
+ try {
1076
+ return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
1077
+ } catch (error) {
1078
+ if (connection.confirmed) throw error;
1079
+ http2Connections.set(origin, null);
1080
+ }
1081
+ }
1082
+ }
1083
+ }
1084
+ const response = await fetchImpl(url, init);
1085
+ return { status: response.status, ok: response.ok, text: await response.text() };
1086
+ }
965
1087
 
966
1088
  // src/cli.ts
967
1089
  var import_meta = {};
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  ARKER_ORG_ID,
4
4
  Arker,
5
5
  ArkerError
6
- } from "./chunk-7BHPVQNG.js";
6
+ } from "./chunk-4NHUAVXK.js";
7
7
 
8
8
  // src/cli.ts
9
9
  import { readFileSync, existsSync } from "fs";
package/dist/daytona.cjs CHANGED
@@ -162,6 +162,7 @@ var Arker = class {
162
162
  provider;
163
163
  apiKey;
164
164
  fetchImpl;
165
+ http2;
165
166
  retry;
166
167
  constructor(opts = {}) {
167
168
  const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
@@ -183,6 +184,7 @@ var Arker = class {
183
184
  this.region = region ? normalizeRegion(region) : void 0;
184
185
  this.provider = effectiveProvider;
185
186
  this.fetchImpl = opts.fetch ?? globalThis.fetch;
187
+ this.http2 = opts.fetch === void 0;
186
188
  this.retry = normalizeRetry(opts.retry);
187
189
  if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
188
190
  }
@@ -243,7 +245,10 @@ var Arker = class {
243
245
  egress: src.egress ?? null,
244
246
  disk: src.disk ?? true,
245
247
  durable: src.durable ?? null,
246
- resources
248
+ resources,
249
+ // ARK-125: omit to inherit the source's policy; pass a doc to override
250
+ // (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
251
+ policies: src.policies ?? null
247
252
  };
248
253
  const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
249
254
  const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
@@ -338,30 +343,29 @@ var Arker = class {
338
343
  if (value !== void 0) headers[key] = value;
339
344
  }
340
345
  }
341
- const init = { method, headers };
346
+ let requestBody;
342
347
  if (body !== void 0) {
343
348
  headers["content-type"] = "application/json";
344
- init.body = JSON.stringify(withoutUndefined(body));
349
+ requestBody = JSON.stringify(withoutUndefined(body));
345
350
  }
346
351
  let lastStatus = 0;
347
352
  let lastText = "";
348
353
  let lastError;
349
354
  for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
350
355
  try {
351
- const response = await this.fetchImpl(url, init);
352
- const text = await response.text();
356
+ const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
353
357
  const payload = parseJson(text);
354
358
  const parsedError = extractError(payload);
355
- lastStatus = response.status;
359
+ lastStatus = status;
356
360
  lastText = text;
357
361
  lastError = parsedError;
358
- if (isRetryable(response.status, parsedError) && attempt < this.retry.attempts - 1) {
362
+ if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
359
363
  await sleep(retryDelay(this.retry, attempt));
360
364
  continue;
361
365
  }
362
- if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, response.status);
363
- if (!response.ok) {
364
- throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${response.status}`, response.status);
366
+ if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
367
+ if (!ok) {
368
+ throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
365
369
  }
366
370
  return payload;
367
371
  } catch (error) {
@@ -573,6 +577,32 @@ var VM = class _VM {
573
577
  async delete() {
574
578
  return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
575
579
  }
580
+ // ── ARK-125 egress policy ────────────────────────────────────────
581
+ /**
582
+ * Read this VM's outbound egress policy document (ARK-125). Returns an
583
+ * empty doc (`{}`) when no policy is set.
584
+ */
585
+ async getPolicies() {
586
+ return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
587
+ }
588
+ /**
589
+ * Replace this VM's outbound egress policy with `doc` — an ordered,
590
+ * first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
591
+ * clears the policy to allow-all. Returns the stored policy plus the
592
+ * domains it escalates to MITM and any degrade warnings.
593
+ *
594
+ * await vm.setPolicies({
595
+ * policies: [
596
+ * { type: "network.outbound",
597
+ * match: { domains: ["github.com"], ports: [443] },
598
+ * action: "allow" },
599
+ * { type: "network.outbound", action: "deny" },
600
+ * ],
601
+ * });
602
+ */
603
+ async setPolicies(doc) {
604
+ return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
605
+ }
576
606
  // ── Syncs: bindings of a filesystem into this VM at a path ────────
577
607
  async listSyncs(opts = {}) {
578
608
  return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
@@ -624,6 +654,20 @@ var VM = class _VM {
624
654
  async deleteSession(sessionId) {
625
655
  return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
626
656
  }
657
+ /**
658
+ * Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
659
+ * (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
660
+ * PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
661
+ * (which sends an in-band control frame on the live WebSocket).
662
+ */
663
+ async updateSession(sessionId, update) {
664
+ return this._client._request(
665
+ "PATCH",
666
+ `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
667
+ { cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
668
+ this.baseUrl
669
+ );
670
+ }
627
671
  async connectPty(options = {}) {
628
672
  const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
629
673
  const useTicket = options.useTicket ?? !isNodeRuntime();
@@ -1035,6 +1079,84 @@ function base64ToBytes(text) {
1035
1079
  function bufferConstructor() {
1036
1080
  return globalThis.Buffer;
1037
1081
  }
1082
+ var http2Module;
1083
+ function loadHttp2() {
1084
+ return http2Module ??= (async () => {
1085
+ const proc = globalThis.process;
1086
+ if (!proc?.versions?.node) return null;
1087
+ try {
1088
+ return await import(
1089
+ /* webpackIgnore: true */
1090
+ /* @vite-ignore */
1091
+ "http2"
1092
+ );
1093
+ } catch {
1094
+ return null;
1095
+ }
1096
+ })();
1097
+ }
1098
+ var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
1099
+ var Http2Connection = class {
1100
+ confirmed = false;
1101
+ streams = 0;
1102
+ session;
1103
+ constructor(http2, origin) {
1104
+ this.session = http2.connect(origin);
1105
+ this.session.on("error", () => {
1106
+ });
1107
+ }
1108
+ get closed() {
1109
+ return this.session.closed || this.session.destroyed;
1110
+ }
1111
+ request(method, path, headers, body) {
1112
+ if (this.streams === 0) this.session.ref();
1113
+ this.streams++;
1114
+ return new Promise((resolve, reject) => {
1115
+ const stream = this.session.request({ ...headers, ":method": method, ":path": path });
1116
+ let status = 0;
1117
+ let text = "";
1118
+ stream.setEncoding("utf8");
1119
+ stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
1120
+ stream.on("response", (responseHeaders) => {
1121
+ this.confirmed = true;
1122
+ status = Number(responseHeaders[":status"]) || 0;
1123
+ });
1124
+ stream.on("data", (chunk) => {
1125
+ text += chunk;
1126
+ });
1127
+ stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
1128
+ stream.on("error", reject);
1129
+ stream.end(body);
1130
+ }).finally(() => {
1131
+ if (--this.streams === 0) this.session.unref();
1132
+ });
1133
+ }
1134
+ };
1135
+ var http2Connections = /* @__PURE__ */ new Map();
1136
+ async function sendRequest(url, init, fetchImpl, http2Enabled) {
1137
+ if (http2Enabled) {
1138
+ const http2 = await loadHttp2();
1139
+ if (http2) {
1140
+ const { origin, pathname, search } = new URL(url);
1141
+ const cached = http2Connections.get(origin);
1142
+ if (cached !== null) {
1143
+ let connection = cached;
1144
+ if (!connection || connection.closed) {
1145
+ connection = new Http2Connection(http2, origin);
1146
+ http2Connections.set(origin, connection);
1147
+ }
1148
+ try {
1149
+ return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
1150
+ } catch (error) {
1151
+ if (connection.confirmed) throw error;
1152
+ http2Connections.set(origin, null);
1153
+ }
1154
+ }
1155
+ }
1156
+ }
1157
+ const response = await fetchImpl(url, init);
1158
+ return { status: response.status, ok: response.ok, text: await response.text() };
1159
+ }
1038
1160
 
1039
1161
  // src/compat/arker-provider.ts
1040
1162
  var DEFAULT_REGION = "aws-us-east-1";
package/dist/daytona.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  assertSupportedObjectKeys,
3
3
  createCompatSdk,
4
4
  guardUnsupported
5
- } from "./chunk-35IEV6BU.js";
6
- import "./chunk-7BHPVQNG.js";
5
+ } from "./chunk-YFJEL7PF.js";
6
+ import "./chunk-4NHUAVXK.js";
7
7
 
8
8
  // src/daytona.ts
9
9
  import { daytona as createDaytonaProvider } from "@computesdk/daytona";