@tickernelz/paperclip-pro-plugin-daytona 2026.925.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.
- package/README.md +49 -0
- package/dist/duplex-command-stream.d.ts +97 -0
- package/dist/duplex-command-stream.d.ts.map +1 -0
- package/dist/duplex-command-stream.js +205 -0
- package/dist/duplex-command-stream.js.map +1 -0
- package/dist/duplex-command-stream.live.test.d.ts +2 -0
- package/dist/duplex-command-stream.live.test.d.ts.map +1 -0
- package/dist/duplex-command-stream.live.test.js +324 -0
- package/dist/duplex-command-stream.live.test.js.map +1 -0
- package/dist/duplex-command-stream.test.d.ts +2 -0
- package/dist/duplex-command-stream.test.d.ts.map +1 -0
- package/dist/duplex-command-stream.test.js +519 -0
- package/dist/duplex-command-stream.test.js.map +1 -0
- package/dist/file-sync.d.ts +77 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +1055 -0
- package/dist/file-sync.js.map +1 -0
- package/dist/file-sync.test.d.ts +2 -0
- package/dist/file-sync.test.d.ts.map +1 -0
- package/dist/file-sync.test.js +974 -0
- package/dist/file-sync.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/login-pty.d.ts +162 -0
- package/dist/login-pty.d.ts.map +1 -0
- package/dist/login-pty.js +258 -0
- package/dist/login-pty.js.map +1 -0
- package/dist/login-pty.test.d.ts +2 -0
- package/dist/login-pty.test.d.ts.map +1 -0
- package/dist/login-pty.test.js +319 -0
- package/dist/login-pty.test.js.map +1 -0
- package/dist/manifest.d.ts +4 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +179 -0
- package/dist/manifest.js.map +1 -0
- package/dist/plugin.d.ts +49 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +2563 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugin.test.d.ts +2 -0
- package/dist/plugin.test.d.ts.map +1 -0
- package/dist/plugin.test.js +4701 -0
- package/dist/plugin.test.js.map +1 -0
- package/dist/pty-chunked-input.d.ts +48 -0
- package/dist/pty-chunked-input.d.ts.map +1 -0
- package/dist/pty-chunked-input.js +74 -0
- package/dist/pty-chunked-input.js.map +1 -0
- package/dist/pty-chunked-input.test.d.ts +2 -0
- package/dist/pty-chunked-input.test.d.ts.map +1 -0
- package/dist/pty-chunked-input.test.js +115 -0
- package/dist/pty-chunked-input.test.js.map +1 -0
- package/dist/worker.d.ts +3 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +5 -0
- package/dist/worker.js.map +1 -0
- package/package.json +44 -0
|
@@ -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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"}
|
package/dist/worker.d.ts
ADDED
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,eAAe,MAAM,CAAC;AACtB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tickernelz/paperclip-pro-plugin-daytona",
|
|
3
|
+
"version": "2026.925.0",
|
|
4
|
+
"description": "Daytona sandbox provider plugin for Paperclip environments",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/tickernelz/paperclip-pro",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/tickernelz/paperclip-pro/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/tickernelz/paperclip-pro",
|
|
13
|
+
"directory": "packages/plugins/sandbox-providers/daytona"
|
|
14
|
+
},
|
|
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",
|
|
24
|
+
"publishConfig": {
|
|
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/paperclip-pro-plugin-sdk": "2026.925.0"
|
|
43
|
+
}
|
|
44
|
+
}
|