@multiplayer-app/agent 0.1.20 → 0.1.21
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 +14 -7
- package/dist/agent/definition.test.js +8 -3
- package/dist/agent/definition.test.js.map +1 -1
- package/dist/agent/profiles/coding.d.ts +1 -1
- package/dist/agent/profiles/coding.d.ts.map +1 -1
- package/dist/agent/profiles/coding.js +21 -4
- package/dist/agent/profiles/coding.js.map +1 -1
- package/dist/agent/profiles/index.js +1 -1
- package/dist/agent/profiles/index.js.map +1 -1
- package/dist/agent/profiles/research.d.ts.map +1 -1
- package/dist/agent/profiles/research.js +2 -2
- package/dist/agent/profiles/research.js.map +1 -1
- package/dist/agent/turn-history.d.ts.map +1 -1
- package/dist/agent/turn-history.js +7 -1
- package/dist/agent/turn-history.js.map +1 -1
- package/dist/agent/turn-runner.d.ts +8 -0
- package/dist/agent/turn-runner.d.ts.map +1 -1
- package/dist/agent/turn-runner.js +35 -10
- package/dist/agent/turn-runner.js.map +1 -1
- package/dist/app/app-host.d.ts +57 -0
- package/dist/app/app-host.d.ts.map +1 -0
- package/dist/app/app-host.js +252 -0
- package/dist/app/app-host.js.map +1 -0
- package/dist/app/app-host.test.d.ts +2 -0
- package/dist/app/app-host.test.d.ts.map +1 -0
- package/dist/app/app-host.test.js +639 -0
- package/dist/app/app-host.test.js.map +1 -0
- package/dist/app/config.d.ts +196 -0
- package/dist/app/config.d.ts.map +1 -0
- package/dist/app/config.js +362 -0
- package/dist/app/config.js.map +1 -0
- package/dist/app/config.test.d.ts +2 -0
- package/dist/app/config.test.d.ts.map +1 -0
- package/dist/app/config.test.js +224 -0
- package/dist/app/config.test.js.map +1 -0
- package/dist/app/detect.d.ts +68 -0
- package/dist/app/detect.d.ts.map +1 -0
- package/dist/app/detect.js +449 -0
- package/dist/app/detect.js.map +1 -0
- package/dist/app/detect.test.d.ts +2 -0
- package/dist/app/detect.test.d.ts.map +1 -0
- package/dist/app/detect.test.js +267 -0
- package/dist/app/detect.test.js.map +1 -0
- package/dist/app/env.d.ts +5 -0
- package/dist/app/env.d.ts.map +1 -0
- package/dist/app/env.js +22 -0
- package/dist/app/env.js.map +1 -0
- package/dist/app/functions-cli.d.ts +3 -0
- package/dist/app/functions-cli.d.ts.map +1 -0
- package/dist/app/functions-cli.js +27 -0
- package/dist/app/functions-cli.js.map +1 -0
- package/dist/app/functions-host.d.ts +15 -0
- package/dist/app/functions-host.d.ts.map +1 -0
- package/dist/app/functions-host.js +276 -0
- package/dist/app/functions-host.js.map +1 -0
- package/dist/app/functions-host.test.d.ts +2 -0
- package/dist/app/functions-host.test.d.ts.map +1 -0
- package/dist/app/functions-host.test.js +117 -0
- package/dist/app/functions-host.test.js.map +1 -0
- package/dist/app/functions-routes.d.ts +23 -0
- package/dist/app/functions-routes.d.ts.map +1 -0
- package/dist/app/functions-routes.js +85 -0
- package/dist/app/functions-routes.js.map +1 -0
- package/dist/app/functions-routes.test.d.ts +2 -0
- package/dist/app/functions-routes.test.d.ts.map +1 -0
- package/dist/app/functions-routes.test.js +40 -0
- package/dist/app/functions-routes.test.js.map +1 -0
- package/dist/app/manifest.d.ts +17 -0
- package/dist/app/manifest.d.ts.map +1 -0
- package/dist/app/manifest.js +64 -0
- package/dist/app/manifest.js.map +1 -0
- package/dist/app/manifest.test.d.ts +2 -0
- package/dist/app/manifest.test.d.ts.map +1 -0
- package/dist/app/manifest.test.js +173 -0
- package/dist/app/manifest.test.js.map +1 -0
- package/dist/app/release-artifacts.d.ts +39 -0
- package/dist/app/release-artifacts.d.ts.map +1 -0
- package/dist/app/release-artifacts.js +229 -0
- package/dist/app/release-artifacts.js.map +1 -0
- package/dist/app/release-artifacts.test.d.ts +2 -0
- package/dist/app/release-artifacts.test.d.ts.map +1 -0
- package/dist/app/release-artifacts.test.js +295 -0
- package/dist/app/release-artifacts.test.js.map +1 -0
- package/dist/app/route-pattern.d.ts +23 -0
- package/dist/app/route-pattern.d.ts.map +1 -0
- package/dist/app/route-pattern.js +339 -0
- package/dist/app/route-pattern.js.map +1 -0
- package/dist/app/route-pattern.test.d.ts +2 -0
- package/dist/app/route-pattern.test.d.ts.map +1 -0
- package/dist/app/route-pattern.test.js +187 -0
- package/dist/app/route-pattern.test.js.map +1 -0
- package/dist/app/rules.d.ts +61 -0
- package/dist/app/rules.d.ts.map +1 -0
- package/dist/app/rules.js +90 -0
- package/dist/app/rules.js.map +1 -0
- package/dist/app/rules.test.d.ts +2 -0
- package/dist/app/rules.test.d.ts.map +1 -0
- package/dist/app/rules.test.js +69 -0
- package/dist/app/rules.test.js.map +1 -0
- package/dist/app/runner.d.ts +109 -0
- package/dist/app/runner.d.ts.map +1 -0
- package/dist/app/runner.js +429 -0
- package/dist/app/runner.js.map +1 -0
- package/dist/app/site.d.ts +73 -0
- package/dist/app/site.d.ts.map +1 -0
- package/dist/app/site.js +161 -0
- package/dist/app/site.js.map +1 -0
- package/dist/app/site.test.d.ts +2 -0
- package/dist/app/site.test.d.ts.map +1 -0
- package/dist/app/site.test.js +291 -0
- package/dist/app/site.test.js.map +1 -0
- package/dist/app/static-server.d.ts +20 -0
- package/dist/app/static-server.d.ts.map +1 -0
- package/dist/app/static-server.js +145 -0
- package/dist/app/static-server.js.map +1 -0
- package/dist/persistence/conversation-store.d.ts +21 -0
- package/dist/persistence/conversation-store.d.ts.map +1 -0
- package/dist/persistence/conversation-store.js +59 -0
- package/dist/persistence/conversation-store.js.map +1 -0
- package/dist/persistence/conversation-store.test.d.ts +2 -0
- package/dist/persistence/conversation-store.test.d.ts.map +1 -0
- package/dist/persistence/conversation-store.test.js +98 -0
- package/dist/persistence/conversation-store.test.js.map +1 -0
- package/dist/persistence/git-sync.d.ts +14 -1
- package/dist/persistence/git-sync.d.ts.map +1 -1
- package/dist/persistence/git-sync.js +73 -17
- package/dist/persistence/git-sync.js.map +1 -1
- package/dist/persistence/git-sync.test.js +155 -6
- package/dist/persistence/git-sync.test.js.map +1 -1
- package/dist/persistence/snapshot-sync.d.ts +19 -2
- package/dist/persistence/snapshot-sync.d.ts.map +1 -1
- package/dist/persistence/snapshot-sync.js +194 -83
- package/dist/persistence/snapshot-sync.js.map +1 -1
- package/dist/persistence/snapshot-sync.test.js +145 -27
- package/dist/persistence/snapshot-sync.test.js.map +1 -1
- package/dist/persistence/workspace.d.ts +3 -0
- package/dist/persistence/workspace.d.ts.map +1 -1
- package/dist/persistence/workspace.js +1 -0
- package/dist/persistence/workspace.js.map +1 -1
- package/dist/research/extract-texts.d.ts.map +1 -1
- package/dist/research/extract-texts.js +6 -13
- package/dist/research/extract-texts.js.map +1 -1
- package/dist/research/filingramp/attachment-tools.d.ts.map +1 -1
- package/dist/research/filingramp/attachment-tools.js +7 -4
- package/dist/research/filingramp/attachment-tools.js.map +1 -1
- package/dist/research/filingramp/shared.d.ts.map +1 -1
- package/dist/research/filingramp/shared.js +5 -5
- package/dist/research/filingramp/shared.js.map +1 -1
- package/dist/runtime/app-mode.d.ts +10 -0
- package/dist/runtime/app-mode.d.ts.map +1 -0
- package/dist/runtime/app-mode.js +172 -0
- package/dist/runtime/app-mode.js.map +1 -0
- package/dist/runtime/app-mode.test.d.ts +2 -0
- package/dist/runtime/app-mode.test.d.ts.map +1 -0
- package/dist/runtime/app-mode.test.js +130 -0
- package/dist/runtime/app-mode.test.js.map +1 -0
- package/dist/runtime/app-rehearsal.d.ts +2 -0
- package/dist/runtime/app-rehearsal.d.ts.map +1 -0
- package/dist/runtime/app-rehearsal.js +56 -0
- package/dist/runtime/app-rehearsal.js.map +1 -0
- package/dist/runtime/build-mode.d.ts +12 -0
- package/dist/runtime/build-mode.d.ts.map +1 -0
- package/dist/runtime/build-mode.js +116 -0
- package/dist/runtime/build-mode.js.map +1 -0
- package/dist/runtime/build-mode.test.d.ts +2 -0
- package/dist/runtime/build-mode.test.d.ts.map +1 -0
- package/dist/runtime/build-mode.test.js +121 -0
- package/dist/runtime/build-mode.test.js.map +1 -0
- package/dist/runtime/cli.js +7 -2
- package/dist/runtime/cli.js.map +1 -1
- package/dist/runtime/config.d.ts +4 -0
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +13 -2
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/guest-server.d.ts +3 -0
- package/dist/runtime/guest-server.d.ts.map +1 -0
- package/dist/runtime/{lambda-microvm.js → guest-server.js} +49 -18
- package/dist/runtime/guest-server.js.map +1 -0
- package/dist/runtime/image-hooks.d.ts +5 -0
- package/dist/runtime/image-hooks.d.ts.map +1 -0
- package/dist/runtime/image-hooks.js +68 -0
- package/dist/runtime/image-hooks.js.map +1 -0
- package/dist/runtime/image-hooks.test.d.ts +2 -0
- package/dist/runtime/image-hooks.test.d.ts.map +1 -0
- package/dist/runtime/image-hooks.test.js +74 -0
- package/dist/runtime/image-hooks.test.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +53 -35
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/listening-ports.d.ts +13 -0
- package/dist/runtime/listening-ports.d.ts.map +1 -0
- package/dist/runtime/listening-ports.js +78 -0
- package/dist/runtime/listening-ports.js.map +1 -0
- package/dist/runtime/listening-ports.test.d.ts +2 -0
- package/dist/runtime/listening-ports.test.d.ts.map +1 -0
- package/dist/runtime/listening-ports.test.js +39 -0
- package/dist/runtime/listening-ports.test.js.map +1 -0
- package/dist/runtime/preview-proxy.d.ts +56 -0
- package/dist/runtime/preview-proxy.d.ts.map +1 -0
- package/dist/runtime/preview-proxy.js +302 -0
- package/dist/runtime/preview-proxy.js.map +1 -0
- package/dist/runtime/preview-proxy.test.d.ts +2 -0
- package/dist/runtime/preview-proxy.test.d.ts.map +1 -0
- package/dist/runtime/preview-proxy.test.js +122 -0
- package/dist/runtime/preview-proxy.test.js.map +1 -0
- package/dist/runtime/session-mode.d.ts +3 -0
- package/dist/runtime/session-mode.d.ts.map +1 -0
- package/dist/runtime/session-mode.js +60 -0
- package/dist/runtime/session-mode.js.map +1 -0
- package/dist/runtime/workload.d.ts +44 -0
- package/dist/runtime/workload.d.ts.map +1 -0
- package/dist/runtime/workload.js +222 -0
- package/dist/runtime/workload.js.map +1 -0
- package/dist/runtime/workload.test.d.ts +2 -0
- package/dist/runtime/workload.test.d.ts.map +1 -0
- package/dist/runtime/workload.test.js +235 -0
- package/dist/runtime/workload.test.js.map +1 -0
- package/dist/session/conversation.d.ts +3 -2
- package/dist/session/conversation.d.ts.map +1 -1
- package/dist/session/conversation.js +11 -7
- package/dist/session/conversation.js.map +1 -1
- package/dist/session/conversation.test.js +2 -3
- package/dist/session/conversation.test.js.map +1 -1
- package/dist/session/runtime.d.ts +16 -3
- package/dist/session/runtime.d.ts.map +1 -1
- package/dist/session/runtime.js +80 -13
- package/dist/session/runtime.js.map +1 -1
- package/dist/session/runtime.test.js +18 -7
- package/dist/session/runtime.test.js.map +1 -1
- package/dist/session/tools.d.ts.map +1 -1
- package/dist/session/tools.js +3 -3
- package/dist/session/tools.js.map +1 -1
- package/dist/task/loop.d.ts.map +1 -1
- package/dist/task/loop.js +6 -4
- package/dist/task/loop.js.map +1 -1
- package/dist/tools/exec-tools.d.ts +12 -0
- package/dist/tools/exec-tools.d.ts.map +1 -1
- package/dist/tools/exec-tools.js +46 -3
- package/dist/tools/exec-tools.js.map +1 -1
- package/dist/tools/exec-tools.test.d.ts +2 -0
- package/dist/tools/exec-tools.test.d.ts.map +1 -0
- package/dist/tools/exec-tools.test.js +48 -0
- package/dist/tools/exec-tools.test.js.map +1 -0
- package/dist/tools/fs-tools.d.ts.map +1 -1
- package/dist/tools/fs-tools.js +5 -5
- package/dist/tools/fs-tools.js.map +1 -1
- package/dist/transport/link.d.ts.map +1 -1
- package/dist/transport/link.js +16 -5
- package/dist/transport/link.js.map +1 -1
- package/dist/transport/link.test.js +24 -0
- package/dist/transport/link.test.js.map +1 -1
- package/dist/transport/protocol.d.ts +190 -3
- package/dist/transport/protocol.d.ts.map +1 -1
- package/dist/transport/protocol.js +147 -7
- package/dist/transport/protocol.js.map +1 -1
- package/dist/transport/protocol.test.js +41 -0
- package/dist/transport/protocol.test.js.map +1 -1
- package/dist/workspace-sync/eligibility.d.ts +14 -0
- package/dist/workspace-sync/eligibility.d.ts.map +1 -0
- package/dist/workspace-sync/eligibility.js +53 -0
- package/dist/workspace-sync/eligibility.js.map +1 -0
- package/dist/workspace-sync/merge.d.ts +15 -0
- package/dist/workspace-sync/merge.d.ts.map +1 -0
- package/dist/workspace-sync/merge.js +66 -0
- package/dist/workspace-sync/merge.js.map +1 -0
- package/dist/workspace-sync/merge.test.d.ts +2 -0
- package/dist/workspace-sync/merge.test.d.ts.map +1 -0
- package/dist/workspace-sync/merge.test.js +28 -0
- package/dist/workspace-sync/merge.test.js.map +1 -0
- package/dist/workspace-sync/workspace-sync.d.ts +48 -0
- package/dist/workspace-sync/workspace-sync.d.ts.map +1 -0
- package/dist/workspace-sync/workspace-sync.js +308 -0
- package/dist/workspace-sync/workspace-sync.js.map +1 -0
- package/dist/workspace-sync/workspace-sync.test.d.ts +2 -0
- package/dist/workspace-sync/workspace-sync.test.d.ts.map +1 -0
- package/dist/workspace-sync/workspace-sync.test.js +111 -0
- package/dist/workspace-sync/workspace-sync.test.js.map +1 -0
- package/dist/workspace-sync/write-drafts.d.ts +24 -0
- package/dist/workspace-sync/write-drafts.d.ts.map +1 -0
- package/dist/workspace-sync/write-drafts.js +87 -0
- package/dist/workspace-sync/write-drafts.js.map +1 -0
- package/dist/workspace-sync/write-drafts.test.d.ts +2 -0
- package/dist/workspace-sync/write-drafts.test.d.ts.map +1 -0
- package/dist/workspace-sync/write-drafts.test.js +36 -0
- package/dist/workspace-sync/write-drafts.test.js.map +1 -0
- package/package.json +12 -2
- package/dist/runtime/lambda-microvm.d.ts +0 -3
- package/dist/runtime/lambda-microvm.d.ts.map +0 -1
- package/dist/runtime/lambda-microvm.js.map +0 -1
|
@@ -3,48 +3,96 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SessionStorageSync = exports.
|
|
7
|
-
|
|
6
|
+
exports.SessionStorageSync = exports.MAX_SESSION_FILE_BYTES = void 0;
|
|
7
|
+
exports.fileRoute = fileRoute;
|
|
8
|
+
exports.inPool = inPool;
|
|
9
|
+
// A standalone session's workspace lives in the session's folder in storage, one object per file,
|
|
10
|
+
// reached through the authenticated storage service (never S3 directly). A checkpoint uploads only
|
|
11
|
+
// what changed. Text the session mirrors is already there (workspace live sync): it is uploaded too
|
|
12
|
+
// only while the session has not confirmed that version, so a lost connection never loses an edit.
|
|
8
13
|
// No Git repository is created in the guest or in the session's bucket folder.
|
|
9
14
|
const node_crypto_1 = require("node:crypto");
|
|
10
15
|
const node_fs_1 = require("node:fs");
|
|
11
16
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
|
|
17
|
+
const workload_1 = require("../runtime/workload");
|
|
18
|
+
const protocol_1 = require("../transport/protocol");
|
|
19
|
+
const eligibility_1 = require("../workspace-sync/eligibility");
|
|
20
|
+
exports.MAX_SESSION_FILE_BYTES = 64 * 1024 * 1024;
|
|
13
21
|
const MARKER = '.builder/session-storage.json';
|
|
14
22
|
const TIMEOUT_MS = 60000;
|
|
23
|
+
const FILE_TIMEOUT_MS = 5 * 60000;
|
|
24
|
+
const CONCURRENCY = 8;
|
|
25
|
+
// The storage layer's own objects beside a session's files (lib/session-pages/artifact-storage-paths.ts in the api).
|
|
26
|
+
const STORAGE_SIDECAR = /\.latest\.state$|\.snapshot-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z$/;
|
|
15
27
|
function validPath(value) {
|
|
16
28
|
return typeof value === 'string' && !/[\\\x00-\x1f]/.test(value)
|
|
17
29
|
&& value !== MARKER && value.split('/').every((part) => !['', '.', '..', '.git'].includes(part));
|
|
18
30
|
}
|
|
19
31
|
function excluded(relative) {
|
|
20
|
-
return relative === MARKER || relative === 'data/attachments' || relative.startsWith('data/attachments/')
|
|
32
|
+
return relative === MARKER || relative === protocol_1.SESSION_CONVERSATION_FILE || relative === 'data/attachments' || relative.startsWith('data/attachments/')
|
|
33
|
+
|| relative === '.builder/logs' || relative.startsWith('.builder/logs/')
|
|
34
|
+
|| relative === '.builder/releases' || relative.startsWith('.builder/releases/')
|
|
21
35
|
|| relative.split('/').some((part) => ['.git', 'node_modules', '.venv'].includes(part))
|
|
22
|
-
|| /\.sqlite(?:-journal)?$/.test(relative);
|
|
36
|
+
|| /\.sqlite(?:-journal)?$/.test(relative) || STORAGE_SIDECAR.test(relative);
|
|
37
|
+
}
|
|
38
|
+
function sha256(data) {
|
|
39
|
+
return (0, node_crypto_1.createHash)('sha256').update(data).digest('hex');
|
|
40
|
+
}
|
|
41
|
+
function isMirrorable(relative, content) {
|
|
42
|
+
return (0, eligibility_1.isSyncablePath)(relative) && (0, eligibility_1.syncableText)(content) !== undefined;
|
|
43
|
+
}
|
|
44
|
+
function fileRoute(relative) {
|
|
45
|
+
return `/files/${relative.split('/').map(encodeURIComponent).join('/')}`;
|
|
46
|
+
}
|
|
47
|
+
/** Runs `work` over `items`, a few at a time; the first failure stops new work and is rethrown. */
|
|
48
|
+
async function inPool(items, work) {
|
|
49
|
+
let next = 0;
|
|
50
|
+
let failed = false;
|
|
51
|
+
const errors = [];
|
|
52
|
+
await Promise.all(Array.from({ length: Math.min(CONCURRENCY, items.length) }, async () => {
|
|
53
|
+
while (!failed && next < items.length) {
|
|
54
|
+
const item = items[next++];
|
|
55
|
+
try {
|
|
56
|
+
await work(item);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
failed = true;
|
|
60
|
+
errors.push(error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}));
|
|
64
|
+
if (errors.length)
|
|
65
|
+
throw errors[0];
|
|
23
66
|
}
|
|
24
67
|
class SessionStorageSync {
|
|
25
68
|
constructor(config) {
|
|
26
69
|
this.config = config;
|
|
70
|
+
this.known = new Map();
|
|
27
71
|
this.busy = Promise.resolve();
|
|
28
72
|
}
|
|
29
73
|
get dir() { return this.config.dir; }
|
|
74
|
+
/** Live sync's answer for mirrored text; without it every changed file is uploaded. */
|
|
75
|
+
setMirror(check) {
|
|
76
|
+
this.mirror = check;
|
|
77
|
+
}
|
|
30
78
|
serialize(work) {
|
|
31
79
|
const next = this.busy.then(work, work);
|
|
32
80
|
this.busy = next.catch(() => undefined);
|
|
33
81
|
return next;
|
|
34
82
|
}
|
|
35
|
-
async request(method, body) {
|
|
83
|
+
async request(method, route, body, timeoutMs = TIMEOUT_MS) {
|
|
36
84
|
var _a;
|
|
37
|
-
const response = await fetch(this.config.url
|
|
38
|
-
method, body, redirect: 'error', signal: AbortSignal.timeout(
|
|
39
|
-
headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/
|
|
85
|
+
const response = await fetch(`${this.config.url}${route}`, {
|
|
86
|
+
method, body: body, redirect: 'error', signal: AbortSignal.timeout(timeoutMs),
|
|
87
|
+
headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/octet-stream' },
|
|
40
88
|
});
|
|
41
|
-
if (!response.ok && !(method
|
|
89
|
+
if (!response.ok && !(method !== 'PUT' && response.status === 404)) {
|
|
42
90
|
await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
|
|
43
91
|
throw new Error(`Session storage ${method} failed (${response.status})`);
|
|
44
92
|
}
|
|
45
93
|
return response;
|
|
46
94
|
}
|
|
47
|
-
async writeFile(relative, data
|
|
95
|
+
async writeFile(relative, data) {
|
|
48
96
|
// Never follow a workspace symlink while restoring a file (including parent directories).
|
|
49
97
|
let parent = this.dir;
|
|
50
98
|
for (const part of relative.split('/').slice(0, -1)) {
|
|
@@ -59,99 +107,162 @@ class SessionStorageSync {
|
|
|
59
107
|
const file = await node_fs_1.promises.open(node_path_1.default.join(this.dir, relative), node_fs_1.constants.O_WRONLY | node_fs_1.constants.O_CREAT | node_fs_1.constants.O_TRUNC | node_fs_1.constants.O_NOFOLLOW, 0o600);
|
|
60
108
|
try {
|
|
61
109
|
await file.writeFile(data);
|
|
62
|
-
await file.chmod(
|
|
110
|
+
await file.chmod(0o644);
|
|
63
111
|
}
|
|
64
112
|
finally {
|
|
65
113
|
await file.close();
|
|
66
114
|
}
|
|
67
115
|
}
|
|
116
|
+
/** `atBoot`: restoring, before any workload exists and so still as the runtime. */
|
|
117
|
+
async saveMarker(atBoot = false) {
|
|
118
|
+
const marker = { url: this.config.url, files: Object.fromEntries(this.known) };
|
|
119
|
+
if (atBoot)
|
|
120
|
+
await this.writeFile(MARKER, JSON.stringify(marker));
|
|
121
|
+
else
|
|
122
|
+
await (0, workload_1.writeWorkloadFile)(node_path_1.default.join(this.dir, MARKER), JSON.stringify(marker));
|
|
123
|
+
}
|
|
124
|
+
async download(relative) {
|
|
125
|
+
var _a;
|
|
126
|
+
const response = await this.request('GET', fileRoute(relative), undefined, FILE_TIMEOUT_MS);
|
|
127
|
+
if (response.status === 404) {
|
|
128
|
+
// Deleted since it was listed.
|
|
129
|
+
await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const content = Buffer.from(await response.arrayBuffer());
|
|
133
|
+
await this.writeFile(relative, content);
|
|
134
|
+
const stat = await node_fs_1.promises.lstat(node_path_1.default.join(this.dir, relative));
|
|
135
|
+
this.known.set(relative, { hash: sha256(content), size: stat.size, mtimeMs: stat.mtimeMs, mirrored: isMirrorable(relative, content) });
|
|
136
|
+
}
|
|
137
|
+
async applyExecutables() {
|
|
138
|
+
const text = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), 'utf8').catch(() => undefined);
|
|
139
|
+
if (text === undefined)
|
|
140
|
+
return;
|
|
141
|
+
const files = JSON.parse(text);
|
|
142
|
+
if (!Array.isArray(files))
|
|
143
|
+
throw new Error('Invalid session file list');
|
|
144
|
+
for (const relative of files) {
|
|
145
|
+
if (!validPath(relative))
|
|
146
|
+
throw new Error('Invalid session file list');
|
|
147
|
+
const handle = await node_fs_1.promises.open(node_path_1.default.join(this.dir, relative), node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW).catch(() => undefined);
|
|
148
|
+
if (!handle)
|
|
149
|
+
continue;
|
|
150
|
+
try {
|
|
151
|
+
await handle.chmod(0o755);
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
await handle.close();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
68
158
|
restore() {
|
|
69
159
|
return this.serialize(async () => {
|
|
70
160
|
var _a;
|
|
71
161
|
await node_fs_1.promises.mkdir(this.dir, { recursive: true });
|
|
72
162
|
// A process restart on a retained disk must preserve uncheckpointed local edits/deletions.
|
|
73
|
-
const
|
|
163
|
+
const saved = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, MARKER), 'utf8').catch((error) => {
|
|
74
164
|
if (error.code !== 'ENOENT')
|
|
75
165
|
throw error;
|
|
76
166
|
return undefined;
|
|
77
167
|
});
|
|
78
|
-
|
|
168
|
+
const marker = saved ? JSON.parse(saved) : undefined;
|
|
169
|
+
if (marker && marker.url === this.config.url) {
|
|
170
|
+
for (const [relative, file] of Object.entries(marker.files))
|
|
171
|
+
this.known.set(relative, file);
|
|
79
172
|
return true;
|
|
80
|
-
const response = await this.request('GET');
|
|
81
|
-
const found = response.status !== 404;
|
|
82
|
-
if (found) {
|
|
83
|
-
const chunks = [];
|
|
84
|
-
let size = 0;
|
|
85
|
-
if (response.body)
|
|
86
|
-
for await (const chunk of response.body) {
|
|
87
|
-
size += chunk.byteLength;
|
|
88
|
-
if (size > exports.MAX_SESSION_SNAPSHOT_BYTES)
|
|
89
|
-
throw new Error('Session snapshot exceeds size limit');
|
|
90
|
-
chunks.push(chunk);
|
|
91
|
-
}
|
|
92
|
-
const snapshot = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
93
|
-
const seen = new Set();
|
|
94
|
-
if (snapshot.version !== 1 || !Array.isArray(snapshot.files))
|
|
95
|
-
throw new Error('Invalid session snapshot');
|
|
96
|
-
// Validate the complete manifest before writing anything.
|
|
97
|
-
for (const file of snapshot.files) {
|
|
98
|
-
if (!file || !validPath(file.path) || seen.has(file.path) || typeof file.content !== 'string'
|
|
99
|
-
|| typeof file.executable !== 'boolean' || Buffer.from(file.content, 'base64').toString('base64') !== file.content) {
|
|
100
|
-
throw new Error('Invalid session snapshot file');
|
|
101
|
-
}
|
|
102
|
-
seen.add(file.path);
|
|
103
|
-
}
|
|
104
|
-
for (const file of snapshot.files)
|
|
105
|
-
await this.writeFile(file.path, Buffer.from(file.content, 'base64'), file.executable);
|
|
106
173
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
174
|
+
const listed = await this.request('GET', '/files');
|
|
175
|
+
const files = listed.status === 404 ? (await ((_a = listed.body) === null || _a === void 0 ? void 0 : _a.cancel()), []) : (await listed.json()).files;
|
|
176
|
+
const paths = files.map((file) => file.path);
|
|
177
|
+
if (!paths.every(validPath))
|
|
178
|
+
throw new Error('Invalid session file');
|
|
179
|
+
await inPool(paths.filter((relative) => !excluded(relative)), (relative) => this.download(relative));
|
|
180
|
+
await this.applyExecutables();
|
|
181
|
+
await this.saveMarker(true);
|
|
182
|
+
return paths.length > 0;
|
|
111
183
|
});
|
|
112
184
|
}
|
|
185
|
+
async walk(relative = '') {
|
|
186
|
+
const files = [];
|
|
187
|
+
const entries = await node_fs_1.promises.readdir(node_path_1.default.join(this.dir, relative), { withFileTypes: true });
|
|
188
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
const name = relative ? `${relative}/${entry.name}` : entry.name;
|
|
191
|
+
if (excluded(name))
|
|
192
|
+
continue;
|
|
193
|
+
if (!validPath(name)) {
|
|
194
|
+
console.warn(`[storage] not saving a file with an unsupported name: ${JSON.stringify(name)}`);
|
|
195
|
+
}
|
|
196
|
+
else if (entry.isDirectory()) {
|
|
197
|
+
files.push(...(await this.walk(name)));
|
|
198
|
+
}
|
|
199
|
+
else if (entry.isFile()) {
|
|
200
|
+
const stat = await node_fs_1.promises.lstat(node_path_1.default.join(this.dir, name));
|
|
201
|
+
files.push({ path: name, size: stat.size, mtimeMs: stat.mtimeMs, executable: Boolean(stat.mode & 0o111) });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return files;
|
|
205
|
+
}
|
|
206
|
+
/** Brings the list of executables up to date; whether it changed. */
|
|
207
|
+
async recordExecutables(files) {
|
|
208
|
+
const text = `${JSON.stringify(files.filter((file) => file.executable).map((file) => file.path), null, 2)}\n`;
|
|
209
|
+
const current = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), 'utf8').catch(() => undefined);
|
|
210
|
+
if (current === text)
|
|
211
|
+
return false;
|
|
212
|
+
await (0, workload_1.writeWorkloadFile)(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), text);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
/** Saves `file` if it changed; whether it did. */
|
|
216
|
+
async save(file) {
|
|
217
|
+
var _a;
|
|
218
|
+
const known = this.known.get(file.path);
|
|
219
|
+
if (known && known.size === file.size && known.mtimeMs === file.mtimeMs)
|
|
220
|
+
return false;
|
|
221
|
+
if (file.size > exports.MAX_SESSION_FILE_BYTES) {
|
|
222
|
+
console.warn(`[storage] not saving ${file.path}: ${file.size} bytes is over the ${exports.MAX_SESSION_FILE_BYTES} byte limit`);
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
const handle = await (0, workload_1.openInside)(this.dir, node_path_1.default.join(this.dir, file.path), node_fs_1.constants.O_NOFOLLOW);
|
|
226
|
+
let content;
|
|
227
|
+
try {
|
|
228
|
+
content = await handle.readFile();
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
await handle.close();
|
|
232
|
+
}
|
|
233
|
+
const hash = sha256(content);
|
|
234
|
+
const mirrored = isMirrorable(file.path, content);
|
|
235
|
+
const changed = (known === null || known === void 0 ? void 0 : known.hash) !== hash;
|
|
236
|
+
if (changed && !(mirrored && ((_a = this.mirror) === null || _a === void 0 ? void 0 : _a.call(this, file.path, content)))) {
|
|
237
|
+
await this.request('PUT', fileRoute(file.path), new Uint8Array(content.buffer, content.byteOffset, content.byteLength), FILE_TIMEOUT_MS);
|
|
238
|
+
}
|
|
239
|
+
this.known.set(file.path, { hash, size: file.size, mtimeMs: file.mtimeMs, mirrored });
|
|
240
|
+
return changed;
|
|
241
|
+
}
|
|
113
242
|
commit(_reason) {
|
|
114
243
|
return this.serialize(async () => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
throw new Error('Session snapshot exceeds size limit');
|
|
136
|
-
files.push({ path: name, content: (await handle.readFile()).toString('base64'), executable: Boolean(stat.mode & 0o111) });
|
|
137
|
-
}
|
|
138
|
-
finally {
|
|
139
|
-
await handle.close();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
await walk('');
|
|
145
|
-
const body = JSON.stringify({ version: 1, files });
|
|
146
|
-
if (Buffer.byteLength(body) > exports.MAX_SESSION_SNAPSHOT_BYTES)
|
|
147
|
-
throw new Error('Session snapshot exceeds size limit');
|
|
148
|
-
const hash = (0, node_crypto_1.createHash)('sha256').update(body).digest('hex');
|
|
149
|
-
if (hash === this.lastHash)
|
|
244
|
+
await (0, workload_1.makeWorkloadDir)(node_path_1.default.join(this.dir, '.builder'));
|
|
245
|
+
let files = await this.walk();
|
|
246
|
+
if (await this.recordExecutables(files))
|
|
247
|
+
files = await this.walk();
|
|
248
|
+
let changed = false;
|
|
249
|
+
await inPool(files, async (file) => {
|
|
250
|
+
if (await this.save(file))
|
|
251
|
+
changed = true;
|
|
252
|
+
});
|
|
253
|
+
// Only what this guest knows was there: a file someone added meanwhile is never touched.
|
|
254
|
+
const present = new Set(files.map((file) => file.path));
|
|
255
|
+
await inPool([...this.known].filter(([relative]) => !present.has(relative)), async ([relative, file]) => {
|
|
256
|
+
// Live sync already told the session about a mirrored file.
|
|
257
|
+
if (!file.mirrored)
|
|
258
|
+
await this.request('DELETE', fileRoute(relative));
|
|
259
|
+
this.known.delete(relative);
|
|
260
|
+
changed = true;
|
|
261
|
+
});
|
|
262
|
+
await this.saveMarker();
|
|
263
|
+
if (!changed)
|
|
150
264
|
return undefined;
|
|
151
|
-
|
|
152
|
-
await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
|
|
153
|
-
this.lastHash = hash; // A failed upload must be retried even when files have not changed.
|
|
154
|
-
return hash;
|
|
265
|
+
return sha256([...this.known].sort(([a], [b]) => a.localeCompare(b)).map(([relative, file]) => `${relative}\0${file.hash}`).join('\n'));
|
|
155
266
|
});
|
|
156
267
|
}
|
|
157
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-sync.js","sourceRoot":"","sources":["../../src/persistence/snapshot-sync.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"snapshot-sync.js","sourceRoot":"","sources":["../../src/persistence/snapshot-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,34 +10,49 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
10
10
|
const node_test_1 = require("node:test");
|
|
11
11
|
const snapshot_sync_1 = require("./snapshot-sync");
|
|
12
12
|
const URL = 'https://git.test/workspaces/5c5ad0ca633de27c588a5bb1/6ad5fd18a798fd253b05d5d2';
|
|
13
|
-
|
|
13
|
+
const BINARY = Buffer.from([0x89, 0x50, 0x00, 0xff, 0x01]);
|
|
14
|
+
/** The git service's /workspaces routes over an in-memory session folder. */
|
|
14
15
|
function storageService() {
|
|
15
|
-
const service = {
|
|
16
|
+
const service = {
|
|
17
|
+
files: new Map(),
|
|
18
|
+
requests: [],
|
|
19
|
+
failPuts: 0,
|
|
20
|
+
};
|
|
16
21
|
node_test_1.mock.method(globalThis, 'fetch', async (url, init) => {
|
|
17
|
-
strict_1.default.
|
|
22
|
+
strict_1.default.ok(url.startsWith(URL));
|
|
18
23
|
strict_1.default.equal(init.headers.Authorization, 'Bearer session-token');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const route = url.slice(URL.length);
|
|
25
|
+
service.requests.push(`${init.method} ${route}`);
|
|
26
|
+
if (route === '/files')
|
|
27
|
+
return Response.json({ files: [...service.files].map(([file, data]) => ({ path: file, size: data.length })) });
|
|
28
|
+
const file = decodeURIComponent(route.slice('/files/'.length));
|
|
29
|
+
if (init.method === 'GET') {
|
|
30
|
+
const data = service.files.get(file);
|
|
31
|
+
return data ? new Response(new Uint8Array(data)) : new Response(null, { status: 404 });
|
|
32
|
+
}
|
|
33
|
+
if (init.method === 'DELETE') {
|
|
34
|
+
service.files.delete(file);
|
|
26
35
|
return new Response(null, { status: 204 });
|
|
27
36
|
}
|
|
28
|
-
service.
|
|
29
|
-
|
|
37
|
+
if (service.failPuts > 0) {
|
|
38
|
+
service.failPuts -= 1;
|
|
39
|
+
return new Response(null, { status: 503 });
|
|
40
|
+
}
|
|
41
|
+
service.files.set(file, Buffer.from(init.body));
|
|
42
|
+
return new Response(null, { status: 204 });
|
|
30
43
|
});
|
|
31
44
|
return service;
|
|
32
45
|
}
|
|
33
|
-
(0, node_test_1.describe)('session workspace
|
|
46
|
+
(0, node_test_1.describe)('a session workspace kept as files in its folder', () => {
|
|
34
47
|
let root;
|
|
35
48
|
const sync = (vm) => new snapshot_sync_1.SessionStorageSync({ url: URL, token: 'session-token', dir: node_path_1.default.join(root, vm) });
|
|
36
49
|
const write = async (vm, relative, content, mode = 0o644) => {
|
|
37
50
|
const file = node_path_1.default.join(root, vm, relative);
|
|
38
51
|
await node_fs_1.promises.mkdir(node_path_1.default.dirname(file), { recursive: true });
|
|
39
|
-
await node_fs_1.promises.writeFile(file, content
|
|
52
|
+
await node_fs_1.promises.writeFile(file, content);
|
|
53
|
+
await node_fs_1.promises.chmod(file, mode);
|
|
40
54
|
};
|
|
55
|
+
const puts = (service) => service.requests.filter((request) => request.startsWith('PUT'));
|
|
41
56
|
(0, node_test_1.beforeEach)(async () => {
|
|
42
57
|
root = await node_fs_1.promises.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), 'session-storage-'));
|
|
43
58
|
});
|
|
@@ -45,52 +60,155 @@ function storageService() {
|
|
|
45
60
|
node_test_1.mock.restoreAll();
|
|
46
61
|
await node_fs_1.promises.rm(root, { recursive: true, force: true });
|
|
47
62
|
});
|
|
48
|
-
(0, node_test_1.it)('
|
|
63
|
+
(0, node_test_1.it)('stores real files, and a new VM gets them back byte for byte, executable bits included', async () => {
|
|
49
64
|
const service = storageService();
|
|
50
65
|
const original = sync('original-vm');
|
|
51
66
|
strict_1.default.equal(await original.restore(), false);
|
|
52
67
|
await write('original-vm', '.builder/conversation.json', '{"version":1}');
|
|
53
68
|
await write('original-vm', 'research/findings.md', '# Three filings');
|
|
69
|
+
await write('original-vm', 'report.png', BINARY);
|
|
54
70
|
await write('original-vm', 'bin/run.sh', 'echo hi', 0o755);
|
|
55
71
|
await write('original-vm', '.git/config', '[core]');
|
|
56
72
|
await write('original-vm', 'node_modules/pkg/index.js', 'x');
|
|
57
73
|
await write('original-vm', 'data/attachments/filing.pdf', 'pdf');
|
|
74
|
+
await write('original-vm', '.builder/logs/app.log', 'log');
|
|
58
75
|
strict_1.default.ok(await original.commit('checkpoint: turn'));
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
strict_1.default.deepEqual([...service.files.keys()].sort(), [
|
|
77
|
+
'.builder/executables.json', 'bin/run.sh', 'report.png', 'research/findings.md',
|
|
78
|
+
]);
|
|
79
|
+
strict_1.default.deepEqual(service.files.get('report.png'), BINARY, 'stored as itself, not encoded');
|
|
61
80
|
const replacement = sync('replacement-vm');
|
|
62
81
|
strict_1.default.equal(await replacement.restore(), true);
|
|
63
82
|
strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'replacement-vm/research/findings.md'), 'utf8'), '# Three filings');
|
|
83
|
+
strict_1.default.deepEqual(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'replacement-vm/report.png')), BINARY);
|
|
64
84
|
strict_1.default.equal((await node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/bin/run.sh'))).mode & 0o111, 0o111);
|
|
85
|
+
strict_1.default.equal((await node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/report.png'))).mode & 0o111, 0);
|
|
65
86
|
await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/.git')));
|
|
66
87
|
});
|
|
67
|
-
(0, node_test_1.it)('
|
|
88
|
+
(0, node_test_1.it)('starts a session that only ever had stored files with those files', async () => {
|
|
89
|
+
const service = storageService();
|
|
90
|
+
service.files.set('index.html', Buffer.from('<h1>published</h1>'));
|
|
91
|
+
strict_1.default.equal(await sync('vm').restore(), true);
|
|
92
|
+
strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'vm/index.html'), 'utf8'), '<h1>published</h1>');
|
|
93
|
+
});
|
|
94
|
+
(0, node_test_1.it)('uploads only what changed', async () => {
|
|
95
|
+
var _a;
|
|
96
|
+
const service = storageService();
|
|
97
|
+
const vm = sync('vm');
|
|
98
|
+
await vm.restore();
|
|
99
|
+
await write('vm', 'a.txt', 'a');
|
|
100
|
+
await write('vm', 'b.txt', 'b');
|
|
101
|
+
strict_1.default.ok(await vm.commit('checkpoint'));
|
|
102
|
+
service.requests.length = 0;
|
|
103
|
+
strict_1.default.equal(await vm.commit('checkpoint'), undefined, 'nothing changed');
|
|
104
|
+
strict_1.default.deepEqual(puts(service), []);
|
|
105
|
+
await write('vm', 'b.txt', 'b2');
|
|
106
|
+
strict_1.default.ok(await vm.commit('checkpoint'));
|
|
107
|
+
strict_1.default.deepEqual(puts(service), ['PUT /files/b.txt']);
|
|
108
|
+
strict_1.default.equal((_a = service.files.get('b.txt')) === null || _a === void 0 ? void 0 : _a.toString(), 'b2');
|
|
109
|
+
});
|
|
110
|
+
(0, node_test_1.it)('does not re-upload a restored file, nor one touched without changing', async () => {
|
|
111
|
+
const service = storageService();
|
|
112
|
+
service.files.set('a.png', BINARY);
|
|
113
|
+
const vm = sync('vm');
|
|
114
|
+
await vm.restore();
|
|
115
|
+
service.requests.length = 0;
|
|
116
|
+
await vm.commit('checkpoint');
|
|
117
|
+
strict_1.default.deepEqual(puts(service), ['PUT /files/.builder/executables.json']);
|
|
118
|
+
service.requests.length = 0;
|
|
119
|
+
await node_fs_1.promises.utimes(node_path_1.default.join(root, 'vm/a.png'), new Date(), new Date(Date.now() + 5000));
|
|
120
|
+
strict_1.default.equal(await vm.commit('checkpoint'), undefined);
|
|
121
|
+
strict_1.default.deepEqual(puts(service), []);
|
|
122
|
+
});
|
|
123
|
+
(0, node_test_1.it)('leaves text the session has confirmed to live sync, and uploads what it has not', async () => {
|
|
124
|
+
var _a;
|
|
125
|
+
const service = storageService();
|
|
126
|
+
const vm = sync('vm');
|
|
127
|
+
await vm.restore();
|
|
128
|
+
const confirmed = new Set(['synced.md']);
|
|
129
|
+
vm.setMirror((file, content) => {
|
|
130
|
+
strict_1.default.equal(content.toString(), file === 'synced.md' ? 'done' : 'edit not acknowledged');
|
|
131
|
+
return confirmed.has(file);
|
|
132
|
+
});
|
|
133
|
+
await write('vm', 'synced.md', 'done');
|
|
134
|
+
await write('vm', 'unconfirmed.md', 'edit not acknowledged');
|
|
135
|
+
await write('vm', 'photo.png', BINARY);
|
|
136
|
+
await write('vm', 'dist/bundle.js', 'x');
|
|
137
|
+
await vm.commit('checkpoint');
|
|
138
|
+
strict_1.default.equal(service.files.has('synced.md'), false);
|
|
139
|
+
strict_1.default.equal((_a = service.files.get('unconfirmed.md')) === null || _a === void 0 ? void 0 : _a.toString(), 'edit not acknowledged', 'a lost connection never loses an edit');
|
|
140
|
+
strict_1.default.deepEqual(service.files.get('photo.png'), BINARY);
|
|
141
|
+
strict_1.default.equal(service.files.has('dist/bundle.js'), true, 'build output is not mirrored');
|
|
142
|
+
});
|
|
143
|
+
(0, node_test_1.it)('deletes only files it knows, never one someone added meanwhile', async () => {
|
|
144
|
+
const service = storageService();
|
|
145
|
+
service.files.set('old.png', BINARY);
|
|
146
|
+
const vm = sync('vm');
|
|
147
|
+
await vm.restore();
|
|
148
|
+
service.files.set('added-while-running.png', BINARY);
|
|
149
|
+
await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/old.png'));
|
|
150
|
+
strict_1.default.ok(await vm.commit('checkpoint'));
|
|
151
|
+
strict_1.default.equal(service.files.has('old.png'), false);
|
|
152
|
+
strict_1.default.equal(service.files.has('added-while-running.png'), true);
|
|
153
|
+
});
|
|
154
|
+
(0, node_test_1.it)('leaves a deleted mirrored file to live sync, which removes its document too', async () => {
|
|
155
|
+
const service = storageService();
|
|
156
|
+
service.files.set('notes.md', Buffer.from('text'));
|
|
157
|
+
const vm = sync('vm');
|
|
158
|
+
await vm.restore();
|
|
159
|
+
await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/notes.md'));
|
|
160
|
+
await vm.commit('checkpoint');
|
|
161
|
+
strict_1.default.equal(service.files.has('notes.md'), true);
|
|
162
|
+
strict_1.default.deepEqual(service.requests.filter((request) => request.startsWith('DELETE')), []);
|
|
163
|
+
});
|
|
164
|
+
(0, node_test_1.it)('remembers what it knows when the agent restarts on the same disk, keeping local edits', async () => {
|
|
68
165
|
const service = storageService();
|
|
69
166
|
const first = sync('vm');
|
|
70
167
|
await first.restore();
|
|
168
|
+
await write('vm', 'photo.png', BINARY);
|
|
71
169
|
await write('vm', 'notes.md', 'v1');
|
|
72
170
|
await first.commit('checkpoint');
|
|
73
171
|
await write('vm', 'notes.md', 'v2 (not checkpointed)');
|
|
74
|
-
|
|
75
|
-
|
|
172
|
+
service.requests.length = 0;
|
|
173
|
+
const second = sync('vm');
|
|
174
|
+
strict_1.default.equal(await second.restore(), true);
|
|
175
|
+
strict_1.default.deepEqual(service.requests, [], 'the retained disk is not overwritten from storage');
|
|
76
176
|
strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'vm/notes.md'), 'utf8'), 'v2 (not checkpointed)');
|
|
177
|
+
await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/photo.png'));
|
|
178
|
+
await second.commit('checkpoint');
|
|
179
|
+
strict_1.default.equal(service.files.has('photo.png'), false);
|
|
77
180
|
});
|
|
78
|
-
(0, node_test_1.it)('
|
|
181
|
+
(0, node_test_1.it)('retries an upload that failed', async () => {
|
|
182
|
+
var _a;
|
|
79
183
|
const service = storageService();
|
|
80
184
|
const vm = sync('vm');
|
|
81
185
|
await vm.restore();
|
|
82
186
|
await write('vm', 'notes.md', 'v1');
|
|
83
|
-
service.failPuts =
|
|
187
|
+
service.failPuts = 2;
|
|
84
188
|
await strict_1.default.rejects(vm.commit('checkpoint'), /Session storage PUT failed \(503\)/);
|
|
85
189
|
strict_1.default.ok(await vm.commit('checkpoint'));
|
|
190
|
+
strict_1.default.equal((_a = service.files.get('notes.md')) === null || _a === void 0 ? void 0 : _a.toString(), 'v1');
|
|
86
191
|
strict_1.default.equal(await vm.commit('checkpoint'), undefined);
|
|
87
|
-
strict_1.default.equal(service.puts, 2);
|
|
88
192
|
});
|
|
89
|
-
(0, node_test_1.it)('
|
|
193
|
+
(0, node_test_1.it)('skips a file over the limit instead of failing the whole checkpoint', async () => {
|
|
194
|
+
const service = storageService();
|
|
195
|
+
const warn = node_test_1.mock.method(console, 'warn', () => { });
|
|
196
|
+
const vm = sync('vm');
|
|
197
|
+
await vm.restore();
|
|
198
|
+
await write('vm', 'small.txt', 'ok');
|
|
199
|
+
const file = await node_fs_1.promises.open(node_path_1.default.join(root, 'vm/huge.bin'), 'w');
|
|
200
|
+
await file.truncate(64 * 1024 * 1024 + 1);
|
|
201
|
+
await file.close();
|
|
202
|
+
await vm.commit('checkpoint');
|
|
203
|
+
strict_1.default.equal(service.files.has('small.txt'), true);
|
|
204
|
+
strict_1.default.equal(service.files.has('huge.bin'), false);
|
|
205
|
+
strict_1.default.match(String(warn.mock.calls[0].arguments[0]), /huge\.bin/);
|
|
206
|
+
});
|
|
207
|
+
(0, node_test_1.it)('refuses paths that would write outside the workspace, before writing anything', async () => {
|
|
90
208
|
const service = storageService();
|
|
91
|
-
|
|
92
|
-
service.
|
|
93
|
-
await strict_1.default.rejects(sync('vm').restore(), /Invalid session
|
|
209
|
+
service.files.set('ok.md', Buffer.from('x'));
|
|
210
|
+
service.files.set('../escape.md', Buffer.from('x'));
|
|
211
|
+
await strict_1.default.rejects(sync('vm').restore(), /Invalid session file/);
|
|
94
212
|
await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'vm/ok.md')));
|
|
95
213
|
await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'escape.md')));
|
|
96
214
|
});
|