@tickernelz/wardmote-plugin-daytona 0.0.0 → 2026.1108.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.
Files changed (67) hide show
  1. package/README.md +51 -6
  2. package/dist/duplex-command-stream.d.ts +97 -0
  3. package/dist/duplex-command-stream.d.ts.map +1 -0
  4. package/dist/duplex-command-stream.js +205 -0
  5. package/dist/duplex-command-stream.js.map +1 -0
  6. package/dist/duplex-command-stream.live.test.d.ts +2 -0
  7. package/dist/duplex-command-stream.live.test.d.ts.map +1 -0
  8. package/dist/duplex-command-stream.live.test.js +324 -0
  9. package/dist/duplex-command-stream.live.test.js.map +1 -0
  10. package/dist/duplex-command-stream.test.d.ts +2 -0
  11. package/dist/duplex-command-stream.test.d.ts.map +1 -0
  12. package/dist/duplex-command-stream.test.js +519 -0
  13. package/dist/duplex-command-stream.test.js.map +1 -0
  14. package/dist/file-sync-diagnostics.test.d.ts +2 -0
  15. package/dist/file-sync-diagnostics.test.d.ts.map +1 -0
  16. package/dist/file-sync-diagnostics.test.js +117 -0
  17. package/dist/file-sync-diagnostics.test.js.map +1 -0
  18. package/dist/file-sync.d.ts +79 -0
  19. package/dist/file-sync.d.ts.map +1 -0
  20. package/dist/file-sync.js +1197 -0
  21. package/dist/file-sync.js.map +1 -0
  22. package/dist/file-sync.test.d.ts +2 -0
  23. package/dist/file-sync.test.d.ts.map +1 -0
  24. package/dist/file-sync.test.js +1047 -0
  25. package/dist/file-sync.test.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +3 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/login-pty.d.ts +162 -0
  31. package/dist/login-pty.d.ts.map +1 -0
  32. package/dist/login-pty.js +258 -0
  33. package/dist/login-pty.js.map +1 -0
  34. package/dist/login-pty.test.d.ts +2 -0
  35. package/dist/login-pty.test.d.ts.map +1 -0
  36. package/dist/login-pty.test.js +319 -0
  37. package/dist/login-pty.test.js.map +1 -0
  38. package/dist/manifest.d.ts +5 -0
  39. package/dist/manifest.d.ts.map +1 -0
  40. package/dist/manifest.js +182 -0
  41. package/dist/manifest.js.map +1 -0
  42. package/dist/plugin.d.ts +49 -0
  43. package/dist/plugin.d.ts.map +1 -0
  44. package/dist/plugin.js +2930 -0
  45. package/dist/plugin.js.map +1 -0
  46. package/dist/plugin.test.d.ts +2 -0
  47. package/dist/plugin.test.d.ts.map +1 -0
  48. package/dist/plugin.test.js +5627 -0
  49. package/dist/plugin.test.js.map +1 -0
  50. package/dist/pty-chunked-input.d.ts +48 -0
  51. package/dist/pty-chunked-input.d.ts.map +1 -0
  52. package/dist/pty-chunked-input.js +74 -0
  53. package/dist/pty-chunked-input.js.map +1 -0
  54. package/dist/pty-chunked-input.test.d.ts +2 -0
  55. package/dist/pty-chunked-input.test.d.ts.map +1 -0
  56. package/dist/pty-chunked-input.test.js +115 -0
  57. package/dist/pty-chunked-input.test.js.map +1 -0
  58. package/dist/tar-listing.test.d.ts +2 -0
  59. package/dist/tar-listing.test.d.ts.map +1 -0
  60. package/dist/tar-listing.test.js +220 -0
  61. package/dist/tar-listing.test.js.map +1 -0
  62. package/dist/worker.d.ts +3 -0
  63. package/dist/worker.d.ts.map +1 -0
  64. package/dist/worker.js +5 -0
  65. package/dist/worker.js.map +1 -0
  66. package/package.json +35 -9
  67. package/index.js +0 -1
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The provider PTY WebSocket message cap, in bytes. The provider rejects a single
3
+ * PTY message over this size with WebSocket close code 1009 and closes the
4
+ * connection.
5
+ */
6
+ export declare const PTY_MESSAGE_CAP_BYTES = 65536;
7
+ /**
8
+ * The maximum byte length of one host-to-sandbox chunk. It holds about 5 KiB of
9
+ * headroom under {@link PTY_MESSAGE_CAP_BYTES}, so a chunk never sits on the cap
10
+ * boundary. A later change in how the provider counts message overhead does not
11
+ * push one chunk over the cap and back into the close-code-1009 failure. The
12
+ * headroom costs about nine percent more messages for a large payload.
13
+ *
14
+ * The chunker slices bytes, not string characters, so a chunk boundary can split
15
+ * a multi-byte UTF-8 sequence. The read-side streaming `TextDecoder` rejoins a
16
+ * split sequence, so a byte slice is safe. A string-index slice could split a
17
+ * surrogate pair, so the chunker never slices by character.
18
+ */
19
+ export declare const PTY_INPUT_CHUNK_BYTES: number;
20
+ /**
21
+ * Send one host-to-sandbox payload as byte-bounded chunks under the provider
22
+ * message cap. The function encodes a string payload to UTF-8 bytes, slices the
23
+ * byte array into chunks of at most {@link PTY_INPUT_CHUNK_BYTES}, and calls
24
+ * `sendInput` for each chunk in order.
25
+ *
26
+ * The loop awaits each chunk before it sends the next chunk. The `await` keeps
27
+ * the wire order equal to the slice order, and it makes the chunk send fail-fast:
28
+ * after a chunk rejects, the function sends no further chunk of this payload. A
29
+ * synchronous loop could not fail-fast, because `sendInput` reaches `ws.send`
30
+ * before its first `await`, so a synchronous loop puts every chunk on the wire
31
+ * before the first rejection settles. The awaited loop learns the rejection
32
+ * before it sends the next chunk, so it stops.
33
+ *
34
+ * The function does not overlap two calls for the same channel. The caller
35
+ * serializes its writes (for example, through a promise chain), so the awaited
36
+ * loop of one payload never interleaves its chunks with the chunks of the next
37
+ * payload.
38
+ *
39
+ * `onError` runs at most one time. The function reports the first rejected chunk
40
+ * and returns. A rejected send never throws out of this function, so the caller's
41
+ * stream stays the single result path.
42
+ *
43
+ * @param sendInput - Sends one raw byte chunk to the pseudo-terminal.
44
+ * @param payload - The host-to-sandbox payload, as a string or raw bytes.
45
+ * @param onError - Optional. The function calls it one time on the first rejected chunk.
46
+ */
47
+ export declare function sendPtyInputInChunks(sendInput: (chunk: Uint8Array) => Promise<void>, payload: string | Uint8Array, onError?: () => void): Promise<void>;
48
+ //# sourceMappingURL=pty-chunked-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-chunked-input.d.ts","sourceRoot":"","sources":["../src/pty-chunked-input.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAK/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,EAC/C,OAAO,EAAE,MAAM,GAAG,UAAU,EAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -0,0 +1,74 @@
1
+ // The shared host-to-sandbox write chunker for the Daytona pseudo-terminal (PTY)
2
+ // sessions. The provider PTY WebSocket rejects any single message over 65536
3
+ // bytes with WebSocket close code 1009 and closes the connection. `sendInput`
4
+ // sends a whole payload in one message, so a payload above the cap takes the
5
+ // channel down. Real duplex frames cross the cap (single frames of 127582 and
6
+ // 150416 bytes are observed). This module slices each payload into byte-bounded
7
+ // chunks under the cap and sends each chunk in order.
8
+ /**
9
+ * The provider PTY WebSocket message cap, in bytes. The provider rejects a single
10
+ * PTY message over this size with WebSocket close code 1009 and closes the
11
+ * connection.
12
+ */
13
+ export const PTY_MESSAGE_CAP_BYTES = 65536;
14
+ /**
15
+ * The maximum byte length of one host-to-sandbox chunk. It holds about 5 KiB of
16
+ * headroom under {@link PTY_MESSAGE_CAP_BYTES}, so a chunk never sits on the cap
17
+ * boundary. A later change in how the provider counts message overhead does not
18
+ * push one chunk over the cap and back into the close-code-1009 failure. The
19
+ * headroom costs about nine percent more messages for a large payload.
20
+ *
21
+ * The chunker slices bytes, not string characters, so a chunk boundary can split
22
+ * a multi-byte UTF-8 sequence. The read-side streaming `TextDecoder` rejoins a
23
+ * split sequence, so a byte slice is safe. A string-index slice could split a
24
+ * surrogate pair, so the chunker never slices by character.
25
+ */
26
+ export const PTY_INPUT_CHUNK_BYTES = 60 * 1024;
27
+ /** The single UTF-8 encoder the chunker reuses for every string payload. */
28
+ const PTY_INPUT_TEXT_ENCODER = new TextEncoder();
29
+ /**
30
+ * Send one host-to-sandbox payload as byte-bounded chunks under the provider
31
+ * message cap. The function encodes a string payload to UTF-8 bytes, slices the
32
+ * byte array into chunks of at most {@link PTY_INPUT_CHUNK_BYTES}, and calls
33
+ * `sendInput` for each chunk in order.
34
+ *
35
+ * The loop awaits each chunk before it sends the next chunk. The `await` keeps
36
+ * the wire order equal to the slice order, and it makes the chunk send fail-fast:
37
+ * after a chunk rejects, the function sends no further chunk of this payload. A
38
+ * synchronous loop could not fail-fast, because `sendInput` reaches `ws.send`
39
+ * before its first `await`, so a synchronous loop puts every chunk on the wire
40
+ * before the first rejection settles. The awaited loop learns the rejection
41
+ * before it sends the next chunk, so it stops.
42
+ *
43
+ * The function does not overlap two calls for the same channel. The caller
44
+ * serializes its writes (for example, through a promise chain), so the awaited
45
+ * loop of one payload never interleaves its chunks with the chunks of the next
46
+ * payload.
47
+ *
48
+ * `onError` runs at most one time. The function reports the first rejected chunk
49
+ * and returns. A rejected send never throws out of this function, so the caller's
50
+ * stream stays the single result path.
51
+ *
52
+ * @param sendInput - Sends one raw byte chunk to the pseudo-terminal.
53
+ * @param payload - The host-to-sandbox payload, as a string or raw bytes.
54
+ * @param onError - Optional. The function calls it one time on the first rejected chunk.
55
+ */
56
+ export async function sendPtyInputInChunks(sendInput, payload, onError) {
57
+ const bytes = typeof payload === "string" ? PTY_INPUT_TEXT_ENCODER.encode(payload) : payload;
58
+ for (let offset = 0; offset < bytes.length; offset += PTY_INPUT_CHUNK_BYTES) {
59
+ const chunk = bytes.subarray(offset, offset + PTY_INPUT_CHUNK_BYTES);
60
+ try {
61
+ // Await the send before the next chunk. The await keeps the wire order and
62
+ // lets the loop learn a rejection before it starts a later send.
63
+ await sendInput(chunk);
64
+ }
65
+ catch {
66
+ // Report the first rejected chunk one time and stop. The function starts no
67
+ // later send for this payload, so the wire keeps the ordered, fail-fast
68
+ // behavior. The raw provider error never leaves this function.
69
+ onError?.();
70
+ return;
71
+ }
72
+ }
73
+ }
74
+ //# sourceMappingURL=pty-chunked-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-chunked-input.js","sourceRoot":"","sources":["../src/pty-chunked-input.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,sDAAsD;AAEtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,sBAAsB,GAAG,IAAI,WAAW,EAAE,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAA+C,EAC/C,OAA4B,EAC5B,OAAoB;IAEpB,MAAM,KAAK,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7F,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,qBAAqB,EAAE,CAAC;QAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAAC,CAAC;QACrE,IAAI,CAAC;YACH,2EAA2E;YAC3E,iEAAiE;YACjE,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;YAC5E,wEAAwE;YACxE,+DAA+D;YAC/D,OAAO,EAAE,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pty-chunked-input.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-chunked-input.test.d.ts","sourceRoot":"","sources":["../src/pty-chunked-input.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,115 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { PTY_INPUT_CHUNK_BYTES, PTY_MESSAGE_CAP_BYTES, sendPtyInputInChunks, } from "./pty-chunked-input.js";
3
+ /**
4
+ * A fake `sendInput`. It records each raw byte chunk, so a test asserts the chunk
5
+ * count, the chunk sizes, and the rejoined bytes. It copies each chunk, because
6
+ * the chunker passes a `subarray` view of one shared byte array.
7
+ */
8
+ function createByteRecorder() {
9
+ const chunks = [];
10
+ return {
11
+ chunks,
12
+ async sendInput(chunk) {
13
+ chunks.push(Uint8Array.from(chunk));
14
+ },
15
+ };
16
+ }
17
+ /** Concatenate the recorded chunks into one byte array. */
18
+ function concatChunks(chunks) {
19
+ const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
20
+ const joined = new Uint8Array(total);
21
+ let offset = 0;
22
+ for (const chunk of chunks) {
23
+ joined.set(chunk, offset);
24
+ offset += chunk.length;
25
+ }
26
+ return joined;
27
+ }
28
+ describe("sendPtyInputInChunks", () => {
29
+ it("sends a payload below the cap as exactly one send", async () => {
30
+ const recorder = createByteRecorder();
31
+ await sendPtyInputInChunks(recorder.sendInput, "a small frame\n");
32
+ expect(recorder.chunks).toHaveLength(1);
33
+ expect(recorder.chunks[0]?.length).toBeLessThanOrEqual(PTY_MESSAGE_CAP_BYTES);
34
+ });
35
+ it("splits a payload above the cap into more than one send, each at or below the cap", async () => {
36
+ const recorder = createByteRecorder();
37
+ // A fixed payload well above the provider message cap. It stays fixed, so a
38
+ // raised chunk size above this size makes the payload one send and fails this
39
+ // test.
40
+ const payload = new Uint8Array(150_416).fill(65);
41
+ await sendPtyInputInChunks(recorder.sendInput, payload);
42
+ expect(recorder.chunks.length).toBeGreaterThan(1);
43
+ for (const chunk of recorder.chunks) {
44
+ expect(chunk.length).toBeLessThanOrEqual(PTY_INPUT_CHUNK_BYTES);
45
+ expect(chunk.length).toBeLessThanOrEqual(PTY_MESSAGE_CAP_BYTES);
46
+ }
47
+ expect(concatChunks(recorder.chunks)).toEqual(payload);
48
+ });
49
+ it("slices a multi-byte character across a boundary by bytes and rejoins it", async () => {
50
+ const recorder = createByteRecorder();
51
+ // A fixed payload: one 1-byte "x", then the 3-byte character "€" repeated. It
52
+ // stays fixed, so a raised chunk size above this size makes the payload one
53
+ // send and fails this test. The chunk size is a multiple of 3, so a pure "€"
54
+ // run would put every boundary on a character edge. The 1-byte prefix shifts
55
+ // the "€" run by one byte, so the first chunk boundary lands inside one "€"
56
+ // sequence.
57
+ const text = `x${"€".repeat(30_000)}`;
58
+ const inputBytes = new TextEncoder().encode(text);
59
+ expect(inputBytes.length).toBe(90_001);
60
+ await sendPtyInputInChunks(recorder.sendInput, text);
61
+ expect(recorder.chunks.length).toBeGreaterThan(1);
62
+ // The first chunk holds exactly the byte cap and ends inside a "€" sequence,
63
+ // because the 1-byte prefix shifts the 3-byte run off the cap boundary. A
64
+ // character-index slice could never end mid-sequence, so the slice is by bytes.
65
+ expect(recorder.chunks[0]?.length).toBe(PTY_INPUT_CHUNK_BYTES);
66
+ // The rejoined bytes equal the input bytes, so a split multi-byte sequence is
67
+ // whole again. A streaming decoder on the read side then decodes it.
68
+ const joined = concatChunks(recorder.chunks);
69
+ expect(joined).toEqual(inputBytes);
70
+ expect(new TextDecoder("utf-8").decode(joined)).toBe(text);
71
+ });
72
+ it("resolves each send before it starts the next send", async () => {
73
+ let active = 0;
74
+ let maxActive = 0;
75
+ const sendCount = { value: 0 };
76
+ // A `sendInput` that stays active across a microtask. The awaited loop starts
77
+ // the next send only after the previous send resolves, so at most one send is
78
+ // active at a time. A synchronous burst would start every send at once.
79
+ const sendInput = async () => {
80
+ active += 1;
81
+ maxActive = Math.max(maxActive, active);
82
+ await Promise.resolve();
83
+ sendCount.value += 1;
84
+ active -= 1;
85
+ };
86
+ // Three chunks of the byte cap plus a short tail.
87
+ const payload = new Uint8Array(PTY_INPUT_CHUNK_BYTES * 3 + 10).fill(65);
88
+ await sendPtyInputInChunks(sendInput, payload);
89
+ expect(sendCount.value).toBe(4);
90
+ expect(maxActive).toBe(1);
91
+ });
92
+ it("stops sending later chunks after a chunk rejects", async () => {
93
+ const chunks = [];
94
+ let errorCount = 0;
95
+ // A `sendInput` that records the chunk, then rejects on a later microtask. The
96
+ // rejection is asynchronous, so a synchronous burst could not stop the later
97
+ // sends. The awaited loop learns the rejection before the next send, so it
98
+ // sends one chunk only.
99
+ const sendInput = async (chunk) => {
100
+ chunks.push(chunk);
101
+ await Promise.resolve();
102
+ throw new Error("RAW-PROVIDER-BROKEN-PIPE");
103
+ };
104
+ // A payload above the cap, so the chunker would fire more than one chunk with
105
+ // no fail-fast. The loop stops after the first rejected chunk.
106
+ await sendPtyInputInChunks(sendInput, new Uint8Array(150_416).fill(65), () => {
107
+ errorCount += 1;
108
+ });
109
+ // The loop sent one chunk, learned the rejection, and started no later send.
110
+ expect(chunks).toHaveLength(1);
111
+ // The error handler ran one time for the whole payload.
112
+ expect(errorCount).toBe(1);
113
+ });
114
+ });
115
+ //# sourceMappingURL=pty-chunked-input.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-chunked-input.test.js","sourceRoot":"","sources":["../src/pty-chunked-input.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tar-listing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tar-listing.test.d.ts","sourceRoot":"","sources":["../src/tar-listing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,220 @@
1
+ import { promises as fs } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, expect, it, vi } from "vitest";
5
+ vi.mock("./plugin.js", () => ({ getPluginTracer: () => undefined }));
6
+ import { environmentSyncErrorData, withEnvironmentSyncErrorCapture, withEnvironmentSyncTransferStep, readEnvironmentSyncErrorDiagnostic } from "@tickernelz/wardmote-plugin-sdk";
7
+ import { assertTarballEntriesConfined } from "./file-sync.js";
8
+ const temporaryDirectories = [];
9
+ afterEach(async () => {
10
+ vi.unstubAllEnvs();
11
+ await Promise.all(temporaryDirectories.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
12
+ });
13
+ async function temporaryDirectory() {
14
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "daytona-tar-listing-"));
15
+ temporaryDirectories.push(dir);
16
+ return dir;
17
+ }
18
+ // Empty USTAR members are sufficient to exercise the real host tar listing.
19
+ // Repeating a member is valid tar and avoids creating 145,000 host files just
20
+ // to reproduce the archive metadata buffer limit.
21
+ function tarHeader(name, prefix = "", target) {
22
+ const header = Buffer.alloc(512);
23
+ header.write(name, 0, 100);
24
+ header.write("0000644\0", 100);
25
+ header.write("0000000\0", 108);
26
+ header.write("0000000\0", 116);
27
+ header.write("00000000000\0", 124);
28
+ header.write("00000000000\0", 136);
29
+ header.fill(32, 148, 156);
30
+ header.write(target === undefined ? "0" : "2", 156);
31
+ if (target !== undefined)
32
+ header.write(target, 157, 100);
33
+ header.write("ustar\0", 257);
34
+ header.write("00", 263);
35
+ header.write(prefix, 345, 155);
36
+ const sum = header.reduce((total, value) => total + value, 0);
37
+ header.write(`${sum.toString(8).padStart(6, "0")}\0 `, 148);
38
+ return header;
39
+ }
40
+ it.each([false, true])("validates every member beyond 32 MiB of real tar names (unsafe suffix: %s)", async (unsafeSuffix) => {
41
+ const archive = path.join(await temporaryDirectory(), "large.tar");
42
+ const prefix = "nested-".repeat(21);
43
+ const name = "asset-".repeat(15);
44
+ const count = 145_000;
45
+ expect((prefix.length + 1 + name.length) * count).toBeGreaterThan(32 * 1024 * 1024);
46
+ const header = tarHeader(name, prefix);
47
+ const batch = Buffer.concat(Array.from({ length: 1_000 }, () => header));
48
+ const file = await fs.open(archive, "w");
49
+ try {
50
+ for (let written = 0; written < count; written += 1_000)
51
+ await file.write(batch);
52
+ if (unsafeSuffix)
53
+ await file.write(tarHeader("escape", "", "../../outside"));
54
+ await file.write(Buffer.alloc(1_024));
55
+ }
56
+ finally {
57
+ await file.close();
58
+ }
59
+ if (unsafeSuffix) {
60
+ await expect(assertTarballEntriesConfined(archive)).rejects.toThrow("link whose target escapes");
61
+ }
62
+ else {
63
+ await expect(assertTarballEntriesConfined(archive)).resolves.toBeUndefined();
64
+ }
65
+ }, 30_000);
66
+ async function fakeTar(script) {
67
+ const directory = await temporaryDirectory();
68
+ const pidFile = path.join(directory, "pid");
69
+ await fs.writeFile(path.join(directory, "tar"), `#!${process.execPath}\n` +
70
+ `require("node:fs").appendFileSync(${JSON.stringify(pidFile)}, String(process.pid) + "\\n");\n${script}\n`, { mode: 0o755 });
71
+ vi.stubEnv("PATH", `${directory}${path.delimiter}${process.env.PATH}`);
72
+ return async () => {
73
+ const pids = (await fs.readFile(pidFile, "utf8")).trim().split("\n").map(Number);
74
+ for (const pid of pids)
75
+ expect(() => process.kill(pid, 0)).toThrow();
76
+ };
77
+ }
78
+ const safeLine = "-rw-r--r-- 0/0 0 2026-09-27 12:00 nested/café.txt";
79
+ // The child streams batches with pipe backpressure; quota tests do not allocate
80
+ // a complete oversized listing in either the parent or the child.
81
+ function listingWriter(line, count, tail = "") {
82
+ return `
83
+ const { once } = require("node:events");
84
+ const line = Buffer.from(${JSON.stringify(line)});
85
+ (async () => {
86
+ let left = ${count};
87
+ while (left > 0) {
88
+ const size = Math.min(left, Math.max(1, Math.floor(65536 / line.length)));
89
+ const batch = Buffer.concat(Array.from({ length: size }, () => line));
90
+ if (!process.stdout.write(batch)) await once(process.stdout, "drain");
91
+ left -= size;
92
+ }
93
+ process.stdout.write(${JSON.stringify(tail)});
94
+ })();
95
+ `;
96
+ }
97
+ it.each([false, true])("bounds aggregate listing bytes at 64 MiB (over quota: %s)", async (overQuota) => {
98
+ const line = "-rw-r--r-- 0/0 0 2026-09-27 12:00 ".padEnd(4095, "x") + "\n";
99
+ const count = 64 * 1024 * 1024 / Buffer.byteLength(line) + Number(overQuota);
100
+ const checkReaped = await fakeTar(listingWriter(line, count));
101
+ await withEnvironmentSyncErrorCapture(async () => {
102
+ const result = assertTarballEntriesConfined("unused.tar");
103
+ if (overQuota) {
104
+ const error = await result.catch(error => error);
105
+ expect(error.message).toContain("total listing byte limit");
106
+ expect(readEnvironmentSyncErrorDiagnostic({ data: environmentSyncErrorData(error) })?.transferFailureKind).toBe("listing_byte_limit");
107
+ }
108
+ else
109
+ await expect(result).resolves.toBeUndefined();
110
+ });
111
+ await checkReaped();
112
+ }, 30_000);
113
+ it.each([false, true])("bounds aggregate listing entries at 250,000 (over quota: %s)", async (overQuota) => {
114
+ // The over-quota member has no newline: EOF must pass the same admission gate.
115
+ const checkReaped = await fakeTar(listingWriter(safeLine + "\n", 250_000, overQuota ? safeLine : ""));
116
+ await withEnvironmentSyncErrorCapture(async () => {
117
+ const result = assertTarballEntriesConfined("unused.tar");
118
+ if (overQuota) {
119
+ const error = await result.catch(error => error);
120
+ expect(error.message).toContain("listing entry limit");
121
+ expect(readEnvironmentSyncErrorDiagnostic({ data: environmentSyncErrorData(error) })?.transferFailureKind).toBe("listing_entry_limit");
122
+ }
123
+ else
124
+ await expect(result).resolves.toBeUndefined();
125
+ });
126
+ await checkReaped();
127
+ }, 30_000);
128
+ it("counts blank lines against the aggregate parsing quota", async () => {
129
+ const checkReaped = await fakeTar(listingWriter("\n", 250_001));
130
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("listing entry limit");
131
+ await checkReaped();
132
+ });
133
+ it("enforces quotas independently on repeated and concurrent listings and reaps every child", async () => {
134
+ const checkReaped = await fakeTar(`
135
+ if (process.argv[3] === "small.tar") process.stdout.write(${JSON.stringify(safeLine + "\n")});
136
+ else { ${listingWriter(safeLine + "\n", 250_001)} }
137
+ `);
138
+ const results = await Promise.allSettled([
139
+ assertTarballEntriesConfined("large-a.tar"),
140
+ assertTarballEntriesConfined("small.tar"),
141
+ assertTarballEntriesConfined("large-b.tar"),
142
+ ]);
143
+ expect(results[0]).toMatchObject({ status: "rejected", reason: expect.objectContaining({ message: expect.stringContaining("listing entry limit") }) });
144
+ expect(results[1]).toMatchObject({ status: "fulfilled" });
145
+ expect(results[2]).toMatchObject({ status: "rejected", reason: expect.objectContaining({ message: expect.stringContaining("listing entry limit") }) });
146
+ await expect(assertTarballEntriesConfined("large-again.tar")).rejects.toThrow("listing entry limit");
147
+ await checkReaped();
148
+ }, 30_000);
149
+ it("preserves UTF-8 split across chunks and checks a final line without a newline", async () => {
150
+ const checkReaped = await fakeTar(`
151
+ const bytes = Buffer.from(${JSON.stringify(safeLine)});
152
+ const split = bytes.indexOf(Buffer.from("é")) + 1;
153
+ process.stdout.write(bytes.subarray(0, split));
154
+ setTimeout(() => process.stdout.write(bytes.subarray(split)), 30);
155
+ `);
156
+ await expect(assertTarballEntriesConfined("unused.tar")).resolves.toBeUndefined();
157
+ await checkReaped();
158
+ });
159
+ it.each([
160
+ "not a tar listing",
161
+ "-rw-r--r-- 0/0 0 2026-09-27 12:00 ../escape",
162
+ "lrwxrwxrwx 0/0 0 2026-09-27 12:00 link -> /outside",
163
+ "hrw-r--r-- 0/0 0 2026-09-27 12:00 link link to ../../outside",
164
+ "lrwxrwxrwx 0/0 0 2026-09-27 12:00 link -> decoy -> ../../outside",
165
+ ])("rejects an unsafe final listing and reaps the child: %s", async (line) => {
166
+ const checkReaped = await fakeTar(`process.stdout.write(${JSON.stringify(line)});`);
167
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("Daytona syncOut refusing");
168
+ await checkReaped();
169
+ });
170
+ it("bounds an unterminated entry instead of buffering it indefinitely", async () => {
171
+ const checkReaped = await fakeTar(`process.stdout.write("x".repeat(65_537)); setInterval(() => {}, 1_000);`);
172
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("entry listing exceeding the byte limit");
173
+ await checkReaped();
174
+ });
175
+ it("bounds stderr and reaps a noisy tar process", async () => {
176
+ const checkReaped = await fakeTar(`process.stderr.write("x".repeat(65_537)); setInterval(() => {}, 1_000);`);
177
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("diagnostics exceed the byte limit");
178
+ await checkReaped();
179
+ });
180
+ it("rejects nonzero tar exit even after a valid listing", async () => {
181
+ const checkReaped = await fakeTar(`process.stdout.write(${JSON.stringify(safeLine + "\n")}); process.exitCode = 2;`);
182
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("tar listing failed (2)");
183
+ await checkReaped();
184
+ });
185
+ it("times out and reaps a stalled listing process", async () => {
186
+ const checkReaped = await fakeTar(`setInterval(() => {}, 1_000);`);
187
+ // Leave enough startup time for the PID witness under parallel test load.
188
+ await expect(assertTarballEntriesConfined("unused.tar", 2_000)).rejects.toThrow("timed out");
189
+ await checkReaped();
190
+ });
191
+ it("rejects spawn failures without hanging", async () => {
192
+ vi.stubEnv("PATH", await temporaryDirectory());
193
+ await expect(assertTarballEntriesConfined("unused.tar")).rejects.toThrow("ENOENT");
194
+ });
195
+ it.each([
196
+ ["process.exitCode = 2;", "command_failed", 2, "unknown"],
197
+ ['process.stdout.write("x".repeat(65_537)); setInterval(() => {}, 1_000);', "listing_line_limit", undefined, "unknown"],
198
+ ['process.stderr.write("x".repeat(65_537)); setInterval(() => {}, 1_000);', "listing_stderr_limit", undefined, "unknown"],
199
+ ['process.stdout.write("invalid-private-listing");', "unsafe_archive", undefined, "unknown"],
200
+ ['setInterval(() => {}, 1_000);', "listing_timeout", undefined, "ETIMEDOUT"],
201
+ ])("records bounded listing evidence and reaps the child (%s)", async (script, kind, exitCode, errorCode) => {
202
+ const checkReaped = await fakeTar(script);
203
+ await withEnvironmentSyncErrorCapture(async () => {
204
+ let caught;
205
+ try {
206
+ await withEnvironmentSyncTransferStep("archive_validate", () => assertTarballEntriesConfined("private-archive.tar", 2_000));
207
+ }
208
+ catch (error) {
209
+ caught = error;
210
+ }
211
+ expect(caught).toBeInstanceOf(Error);
212
+ const diagnostic = readEnvironmentSyncErrorDiagnostic({ data: environmentSyncErrorData(caught) });
213
+ expect(diagnostic).toEqual({ errorCode, transferStep: "archive_validate", transferFailureKind: kind,
214
+ ...(exitCode !== undefined ? { exitCode } : {}),
215
+ });
216
+ expect(JSON.stringify(diagnostic)).not.toContain("private-");
217
+ });
218
+ await checkReaped();
219
+ });
220
+ //# sourceMappingURL=tar-listing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tar-listing.test.js","sourceRoot":"","sources":["../src/tar-listing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEnD,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,+BAA+B,EAAE,kCAAkC,EAAE,MAAM,iCAAiC,CAAC;AACjL,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,oBAAoB,GAAa,EAAE,CAAC;AAC1C,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,EAAE,CAAC,aAAa,EAAE,CAAC;IACnB,MAAM,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/G,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,kBAAkB;IAC/B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAC7E,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,4EAA4E;AAC5E,8EAA8E;AAC9E,kDAAkD;AAClD,SAAS,SAAS,CAAC,IAAY,EAAE,MAAM,GAAG,EAAE,EAAE,MAAe;IAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACpD,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,4EAA4E,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE;IAC1H,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,kBAAkB,EAAE,EAAE,WAAW,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC;IACtB,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjF,IAAI,YAAY;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QAC7E,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,MAAM,CAAC,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACnG,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,CAAC,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAC/E,CAAC;AACH,CAAC,EAAE,MAAM,CAAC,CAAC;AAEX,KAAK,UAAU,OAAO,CAAC,MAAc;IACnC,MAAM,SAAS,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,QAAQ,IAAI;QACvE,qCAAqC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,oCAAoC,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/H,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACvE,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjF,KAAK,MAAM,GAAG,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,mDAAmD,CAAC;AAErE,gFAAgF;AAChF,kEAAkE;AAClE,SAAS,aAAa,CAAC,IAAY,EAAE,KAAa,EAAE,IAAI,GAAG,EAAE;IAC3D,OAAO;;+BAEsB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;mBAEhC,KAAK;;;;;;;6BAOK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;GAE9C,CAAC;AACJ,CAAC;AAED,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,2DAA2D,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IACtG,MAAM,IAAI,GAAG,oCAAoC,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAC3E,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,+BAA+B,CAAC,KAAK,IAAI,EAAE;QAC/C,MAAM,MAAM,GAAG,4BAA4B,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;YAC5D,MAAM,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,wBAAwB,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACxI,CAAC;;YAAM,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,EAAE,MAAM,CAAC,CAAC;AAEX,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,8DAA8D,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IACzG,+EAA+E;IAC/E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtG,MAAM,+BAA+B,CAAC,KAAK,IAAI,EAAE;QAC/C,MAAM,MAAM,GAAG,4BAA4B,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;YACvD,MAAM,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,wBAAwB,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACzI,CAAC;;YAAM,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,EAAE,MAAM,CAAC,CAAC;AAEX,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;IACtE,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAChG,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;IACvG,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC;gEAC4B,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;aAClF,aAAa,CAAC,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC;GACjD,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACvC,4BAA4B,CAAC,aAAa,CAAC;QAC3C,4BAA4B,CAAC,WAAW,CAAC;QACzC,4BAA4B,CAAC,aAAa,CAAC;KAC5C,CAAC,CAAC;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvJ,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvJ,MAAM,MAAM,CAAC,4BAA4B,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACrG,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,EAAE,MAAM,CAAC,CAAC;AACX,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;IAC7F,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC;gCACJ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;;GAIrD,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAClF,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC;IACN,mBAAmB;IACnB,6CAA6C;IAC7C,oDAAoD;IACpD,8DAA8D;IAC9D,kEAAkE;CACnE,CAAC,CAAC,yDAAyD,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC3E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACrG,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,yEAAyE,CAAC,CAAC;IAC7G,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;IACnH,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;IAC3D,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,yEAAyE,CAAC,CAAC;IAC7G,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IAC9G,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACrH,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACnG,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;IAC7D,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,+BAA+B,CAAC,CAAC;IACnE,0EAA0E;IAC1E,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7F,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;IACtD,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,kBAAkB,EAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACrF,CAAC,CAAC,CAAC;AAGH,EAAE,CAAC,IAAI,CAAC;IACN,CAAC,uBAAuB,EAAE,gBAAgB,EAAE,CAAC,EAAE,SAAS,CAAC;IACzD,CAAC,yEAAyE,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,CAAC;IACvH,CAAC,yEAAyE,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS,CAAC;IACzH,CAAC,kDAAkD,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,CAAC;IAC5F,CAAC,+BAA+B,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,CAAC;CACpE,CAAC,CAAC,2DAA2D,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IACnH,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,+BAA+B,CAAC,KAAK,IAAI,EAAE;QAC/C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YAAC,MAAM,+BAA+B,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,4BAA4B,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC;QAAC,CAAC;QACpI,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,GAAG,KAAK,CAAC;QAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,kCAAkC,CAAC,EAAE,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClG,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,IAAI;YACjG,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import plugin from "./plugin.js";
2
+ export default plugin;
3
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,eAAe,MAAM,CAAC"}
package/dist/worker.js ADDED
@@ -0,0 +1,5 @@
1
+ import { runWorker } from "@tickernelz/wardmote-plugin-sdk";
2
+ import plugin from "./plugin.js";
3
+ export default plugin;
4
+ runWorker(plugin, import.meta.url);
5
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,eAAe,MAAM,CAAC;AACtB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,18 +1,44 @@
1
1
  {
2
2
  "name": "@tickernelz/wardmote-plugin-daytona",
3
- "version": "0.0.0",
4
- "description": "Placeholder publish reserving this name for Paperclip's release pipeline. Do not install this version.",
3
+ "version": "2026.1108.1",
4
+ "description": "Daytona sandbox provider plugin for Paperclip environments",
5
5
  "license": "MIT",
6
- "main": "index.js",
7
- "files": [
8
- "index.js"
9
- ],
6
+ "homepage": "https://github.com/tickernelz/wardmote",
7
+ "bugs": {
8
+ "url": "https://github.com/tickernelz/wardmote/issues"
9
+ },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "git+https://github.com/tickernelz/wardmote.git"
12
+ "url": "https://github.com/tickernelz/wardmote",
13
+ "directory": "packages/plugins/sandbox-providers/daytona"
13
14
  },
14
- "homepage": "https://github.com/tickernelz/wardmote",
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ }
21
+ },
22
+ "main": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
15
24
  "publishConfig": {
16
25
  "access": "public"
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "paperclipPlugin": {
31
+ "manifest": "./dist/manifest.js",
32
+ "worker": "./dist/worker.js"
33
+ },
34
+ "keywords": [
35
+ "paperclip",
36
+ "plugin",
37
+ "sandbox",
38
+ "daytona"
39
+ ],
40
+ "dependencies": {
41
+ "@daytonaio/sdk": "0.203.0",
42
+ "@tickernelz/wardmote-plugin-sdk": "2026.1108.1"
17
43
  }
18
- }
44
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- throw new Error("@tickernelz/wardmote-plugin-daytona@0.0.0 is a placeholder that reserves the package name for Paperclip's release pipeline. It contains no functionality; the first real release supersedes it. See https://github.com/tickernelz/wardmote");