zeitlich 0.2.49 → 0.2.50
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 +26 -23
- package/dist/{activities-zG_FBoY2.d.ts → activities-IuOIvPHO.d.ts} +6 -6
- package/dist/{activities-7OcT_vdR.d.cts → activities-cIlq1y1y.d.cts} +6 -6
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +3 -3
- package/dist/adapters/sandbox/daytona/index.d.ts +3 -3
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.cts +2 -2
- package/dist/adapters/sandbox/daytona/workflow.d.ts +2 -2
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +1 -1
- package/dist/adapters/sandbox/e2b/index.d.ts +1 -1
- package/dist/adapters/sandbox/e2b/index.js.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.ts +1 -1
- package/dist/adapters/thread/anthropic/index.cjs +45 -42
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +10 -10
- package/dist/adapters/thread/anthropic/index.d.ts +10 -10
- package/dist/adapters/thread/anthropic/index.js +45 -42
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +7 -7
- package/dist/adapters/thread/anthropic/workflow.d.ts +7 -7
- package/dist/adapters/thread/google-genai/index.cjs +117 -54
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +27 -23
- package/dist/adapters/thread/google-genai/index.d.ts +27 -23
- package/dist/adapters/thread/google-genai/index.js +117 -54
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +8 -8
- package/dist/adapters/thread/google-genai/workflow.d.ts +8 -8
- package/dist/adapters/thread/langchain/index.cjs +45 -42
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +10 -10
- package/dist/adapters/thread/langchain/index.d.ts +10 -10
- package/dist/adapters/thread/langchain/index.js +45 -42
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +7 -7
- package/dist/adapters/thread/langchain/workflow.d.ts +7 -7
- package/dist/{cold-store-CkWoNtMh.d.cts → cold-store-C0uvYTSi.d.cts} +1 -1
- package/dist/{cold-store-DKMAO1Dd.d.ts → cold-store-CCnZYWjx.d.ts} +1 -1
- package/dist/index.cjs +15050 -420
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -83
- package/dist/index.d.ts +79 -83
- package/dist/index.js +15051 -417
- package/dist/index.js.map +1 -1
- package/dist/{proxy-B7CWEV-T.d.cts → proxy-BVznA2_p.d.cts} +1 -1
- package/dist/{proxy-ByFHMVRX.d.ts → proxy-C4J1pNUk.d.ts} +1 -1
- package/dist/{thread-manager-Cibe0X5m.d.cts → thread-manager-BqjzWsP7.d.ts} +4 -4
- package/dist/{thread-manager-B9rtMEVn.d.cts → thread-manager-CzIs47uG.d.cts} +4 -4
- package/dist/{thread-manager-nK-WcFzM.d.ts → thread-manager-Dzl1fHhV.d.cts} +4 -4
- package/dist/{thread-manager-7AW4rhfu.d.ts → thread-manager-SkSWRPRc.d.ts} +4 -4
- package/dist/{types-gVa5XCWD.d.ts → types-BQvXWcft.d.ts} +1 -1
- package/dist/{types-DO4Tkwxo.d.ts → types-CbPnU4RM.d.ts} +3 -3
- package/dist/{types-CJ7tCdl6.d.ts → types-D8W5TnSa.d.cts} +3 -3
- package/dist/{types-CJ7tCdl6.d.cts → types-D8W5TnSa.d.ts} +3 -3
- package/dist/{types-DeVNWqlb.d.ts → types-DZnUqCAP.d.cts} +709 -709
- package/dist/{types-CjY93AWZ.d.cts → types-OEN1xrFg.d.cts} +1 -1
- package/dist/{types-XUUFvrJ9.d.cts → types-YNesmGKV.d.ts} +709 -709
- package/dist/{types-BR-k7h0e.d.cts → types-d2RvEP6v.d.cts} +3 -3
- package/dist/{workflow-uhOIj9D-.d.ts → workflow-B3oTe2_D.d.cts} +34 -3
- package/dist/{workflow-KbGsxpfh.d.cts → workflow-Bkzg0cjB.d.ts} +34 -3
- package/dist/workflow.cjs +15008 -377
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3 -3
- package/dist/workflow.d.ts +3 -3
- package/dist/workflow.js +15009 -374
- package/dist/workflow.js.map +1 -1
- package/package.json +10 -37
- package/src/adapters/thread/anthropic/activities.ts +1 -1
- package/src/adapters/thread/anthropic/fork-transform.test.ts +17 -11
- package/src/adapters/thread/anthropic/model-invoker.test.ts +4 -3
- package/src/adapters/thread/anthropic/model-invoker.ts +1 -1
- package/src/adapters/thread/anthropic/thread-manager.test.ts +2 -2
- package/src/adapters/thread/anthropic/thread-manager.ts +1 -1
- package/src/adapters/thread/google-genai/activities.ts +1 -1
- package/src/adapters/thread/google-genai/fork-transform.test.ts +17 -11
- package/src/adapters/thread/google-genai/model-invoker.test.ts +337 -0
- package/src/adapters/thread/google-genai/model-invoker.ts +107 -23
- package/src/adapters/thread/google-genai/thread-manager.test.ts +2 -2
- package/src/adapters/thread/google-genai/thread-manager.ts +1 -1
- package/src/adapters/thread/langchain/activities.ts +1 -1
- package/src/adapters/thread/langchain/fork-transform.test.ts +17 -11
- package/src/adapters/thread/langchain/model-invoker.ts +1 -1
- package/src/adapters/thread/langchain/thread-manager.test.ts +2 -2
- package/src/adapters/thread/langchain/thread-manager.ts +1 -1
- package/src/index.ts +2 -2
- package/src/lib/sandbox/capability-types.test.ts +2 -2
- package/src/lib/sandbox/manager.ts +2 -6
- package/src/lib/sandbox/sandbox.test.ts +1 -1
- package/src/lib/sandbox/types.ts +2 -2
- package/src/lib/session/session.integration.test.ts +92 -0
- package/src/lib/session/session.ts +23 -11
- package/src/lib/thread/keys.test.ts +9 -9
- package/src/lib/thread/keys.ts +1 -1
- package/src/lib/thread/manager.test.ts +24 -14
- package/src/lib/thread/manager.ts +19 -23
- package/src/lib/thread/snapshot.test.ts +51 -43
- package/src/lib/thread/snapshot.ts +54 -32
- package/src/lib/thread/test-utils.ts +106 -59
- package/src/lib/thread/tiered.test.ts +1 -1
- package/src/lib/thread/types.ts +2 -2
- package/src/lib/tool-router/router.integration.test.ts +44 -0
- package/src/lib/tool-router/router.ts +140 -32
- package/src/lib/workflow.ts +49 -0
- package/src/{adapters/sandbox/inmemory/proxy.ts → test-utils/in-memory-sandbox-proxy.ts} +5 -16
- package/src/{adapters/sandbox/inmemory/index.ts → test-utils/in-memory-sandbox.ts} +11 -3
- package/src/tools/bash/bash.test.ts +1 -1
- package/src/tools/edit/handler.test.ts +1 -1
- package/tsup.config.ts +2 -4
- package/dist/adapters/sandbox/inmemory/index.cjs +0 -214
- package/dist/adapters/sandbox/inmemory/index.cjs.map +0 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +0 -40
- package/dist/adapters/sandbox/inmemory/index.d.ts +0 -40
- package/dist/adapters/sandbox/inmemory/index.js +0 -211
- package/dist/adapters/sandbox/inmemory/index.js.map +0 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +0 -36
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +0 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +0 -27
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +0 -27
- package/dist/adapters/sandbox/inmemory/workflow.js +0 -34
- package/dist/adapters/sandbox/inmemory/workflow.js.map +0 -1
|
@@ -1,26 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Test-only workflow-safe proxy for the in-memory sandbox fixture.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* By default the scope is derived from `workflowInfo().workflowType`,
|
|
8
|
-
* so activities are automatically namespaced per workflow.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { proxyInMemorySandboxOps } from 'zeitlich/adapters/sandbox/inmemory/workflow';
|
|
13
|
-
*
|
|
14
|
-
* // Auto-scoped to the current workflow name
|
|
15
|
-
* const sandbox = proxyInMemorySandboxOps();
|
|
16
|
-
* ```
|
|
4
|
+
* Not part of the shipped public surface — used by the capability-type
|
|
5
|
+
* fixtures to exercise the full-capability proxy shape.
|
|
17
6
|
*/
|
|
18
7
|
import { proxyActivities, workflowInfo } from "@temporalio/workflow";
|
|
19
8
|
import type {
|
|
20
9
|
SandboxCreateOptions,
|
|
21
10
|
SandboxOps,
|
|
22
|
-
} from "
|
|
23
|
-
import type { InMemoryCaps } from "./
|
|
11
|
+
} from "../lib/sandbox/types";
|
|
12
|
+
import type { InMemoryCaps } from "./in-memory-sandbox";
|
|
24
13
|
|
|
25
14
|
const ADAPTER_PREFIX = "inMemory";
|
|
26
15
|
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only in-memory {@link Sandbox} provider backed by `just-bash`.
|
|
3
|
+
*
|
|
4
|
+
* This is **not** part of the shipped public surface — it lives under
|
|
5
|
+
* `src/test-utils` purely so the sandbox manager, tool handlers, and
|
|
6
|
+
* capability-type fixtures have a lightweight, fully-featured backend to
|
|
7
|
+
* exercise against. `just-bash` is a dev dependency for the same reason.
|
|
8
|
+
*/
|
|
1
9
|
import {
|
|
2
10
|
Bash,
|
|
3
11
|
InMemoryFs,
|
|
@@ -18,9 +26,9 @@ import type {
|
|
|
18
26
|
ExecResult,
|
|
19
27
|
DirentEntry,
|
|
20
28
|
FileStat,
|
|
21
|
-
} from "
|
|
22
|
-
import { SandboxNotFoundError } from "
|
|
23
|
-
import { getShortId } from "
|
|
29
|
+
} from "../lib/sandbox/types";
|
|
30
|
+
import { SandboxNotFoundError } from "../lib/sandbox/types";
|
|
31
|
+
import { getShortId } from "../lib/thread/id";
|
|
24
32
|
|
|
25
33
|
// ============================================================================
|
|
26
34
|
// Adapter: IFileSystem → SandboxFileSystem
|
|
@@ -2,7 +2,7 @@ import { describe, expect, it, beforeEach } from "vitest";
|
|
|
2
2
|
import { bashHandler } from "./handler";
|
|
3
3
|
import { withSandbox } from "../../lib/tool-router/with-sandbox";
|
|
4
4
|
import { SandboxManager } from "../../lib/sandbox/manager";
|
|
5
|
-
import { InMemorySandboxProvider } from "../../
|
|
5
|
+
import { InMemorySandboxProvider } from "../../test-utils/in-memory-sandbox";
|
|
6
6
|
import type { RouterContext } from "../../lib/tool-router/types";
|
|
7
7
|
import type { Sandbox, SandboxCreateOptions } from "../../lib/sandbox";
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import { InMemorySandboxProvider } from "../../
|
|
2
|
+
import { InMemorySandboxProvider } from "../../test-utils/in-memory-sandbox";
|
|
3
3
|
import type { Sandbox, SandboxCreateOptions } from "../../lib/sandbox";
|
|
4
4
|
import { SandboxManager } from "../../lib/sandbox/manager";
|
|
5
5
|
import type { RouterContext } from "../../lib/tool-router/types";
|
package/tsup.config.ts
CHANGED
|
@@ -15,9 +15,6 @@ export default defineConfig({
|
|
|
15
15
|
"adapters/thread/anthropic/index": "src/adapters/thread/anthropic/index.ts",
|
|
16
16
|
"adapters/thread/anthropic/workflow":
|
|
17
17
|
"src/adapters/thread/anthropic/proxy.ts",
|
|
18
|
-
"adapters/sandbox/inmemory/index": "src/adapters/sandbox/inmemory/index.ts",
|
|
19
|
-
"adapters/sandbox/inmemory/workflow":
|
|
20
|
-
"src/adapters/sandbox/inmemory/proxy.ts",
|
|
21
18
|
"adapters/sandbox/daytona/index": "src/adapters/sandbox/daytona/index.ts",
|
|
22
19
|
"adapters/sandbox/daytona/workflow":
|
|
23
20
|
"src/adapters/sandbox/daytona/proxy.ts",
|
|
@@ -38,7 +35,8 @@ export default defineConfig({
|
|
|
38
35
|
/^@anthropic-ai\//,
|
|
39
36
|
/^@daytonaio\//,
|
|
40
37
|
/^@e2b\//,
|
|
41
|
-
"
|
|
38
|
+
"redis",
|
|
39
|
+
/^@redis\//,
|
|
42
40
|
"@mongodb-js/zstd",
|
|
43
41
|
"node-liblzma",
|
|
44
42
|
],
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var justBash = require('just-bash');
|
|
4
|
-
var common = require('@temporalio/common');
|
|
5
|
-
var workflow = require('@temporalio/workflow');
|
|
6
|
-
|
|
7
|
-
// src/adapters/sandbox/inmemory/index.ts
|
|
8
|
-
var SandboxNotFoundError = class extends common.ApplicationFailure {
|
|
9
|
-
constructor(sandboxId) {
|
|
10
|
-
super(`Sandbox not found: ${sandboxId}`, "SandboxNotFoundError", true);
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
14
|
-
function getShortId(length = 12) {
|
|
15
|
-
const hex = workflow.uuid4().replace(/-/g, "");
|
|
16
|
-
let result = "";
|
|
17
|
-
for (let i = 0; i < length; i++) {
|
|
18
|
-
const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
19
|
-
result += BASE62[byte % BASE62.length];
|
|
20
|
-
}
|
|
21
|
-
return result;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// src/adapters/sandbox/inmemory/index.ts
|
|
25
|
-
function toSandboxFs(fs) {
|
|
26
|
-
const workspaceBase = "/";
|
|
27
|
-
const normalisePath = (path) => fs.resolvePath(workspaceBase, path);
|
|
28
|
-
return {
|
|
29
|
-
workspaceBase,
|
|
30
|
-
readFile: (path) => fs.readFile(normalisePath(path)),
|
|
31
|
-
readFileBuffer: (path) => fs.readFileBuffer(normalisePath(path)),
|
|
32
|
-
writeFile: (path, content) => fs.writeFile(normalisePath(path), content),
|
|
33
|
-
appendFile: (path, content) => fs.appendFile(normalisePath(path), content),
|
|
34
|
-
exists: (path) => fs.exists(normalisePath(path)),
|
|
35
|
-
stat: async (path) => {
|
|
36
|
-
const s = await fs.stat(normalisePath(path));
|
|
37
|
-
return {
|
|
38
|
-
isFile: s.isFile,
|
|
39
|
-
isDirectory: s.isDirectory,
|
|
40
|
-
isSymbolicLink: s.isSymbolicLink,
|
|
41
|
-
size: s.size,
|
|
42
|
-
mtime: s.mtime
|
|
43
|
-
};
|
|
44
|
-
},
|
|
45
|
-
mkdir: (path, opts) => fs.mkdir(normalisePath(path), opts),
|
|
46
|
-
readdir: (path) => fs.readdir(normalisePath(path)),
|
|
47
|
-
readdirWithFileTypes: async (path) => {
|
|
48
|
-
const dirPath = normalisePath(path);
|
|
49
|
-
if (!fs.readdirWithFileTypes) {
|
|
50
|
-
const names = await fs.readdir(dirPath);
|
|
51
|
-
return Promise.all(
|
|
52
|
-
names.map(async (name) => {
|
|
53
|
-
const childPath = fs.resolvePath(dirPath, name);
|
|
54
|
-
const s = await fs.stat(childPath);
|
|
55
|
-
return {
|
|
56
|
-
name,
|
|
57
|
-
isFile: s.isFile,
|
|
58
|
-
isDirectory: s.isDirectory,
|
|
59
|
-
isSymbolicLink: s.isSymbolicLink
|
|
60
|
-
};
|
|
61
|
-
})
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
return fs.readdirWithFileTypes(dirPath);
|
|
65
|
-
},
|
|
66
|
-
rm: (path, opts) => fs.rm(normalisePath(path), opts),
|
|
67
|
-
cp: (src, dest, opts) => fs.cp(normalisePath(src), normalisePath(dest), opts),
|
|
68
|
-
mv: (src, dest) => fs.mv(normalisePath(src), normalisePath(dest)),
|
|
69
|
-
readlink: (path) => fs.readlink(normalisePath(path)),
|
|
70
|
-
resolvePath: (base, p) => fs.resolvePath(normalisePath(base), p)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
var InMemorySandboxImpl = class {
|
|
74
|
-
constructor(id, justBashFs, options) {
|
|
75
|
-
this.id = id;
|
|
76
|
-
this.justBashFs = justBashFs;
|
|
77
|
-
this.fs = toSandboxFs(justBashFs);
|
|
78
|
-
this.bashOptions = {
|
|
79
|
-
executionLimits: { maxStringLength: 52428800 },
|
|
80
|
-
...options?.bashOptions
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
id;
|
|
84
|
-
justBashFs;
|
|
85
|
-
capabilities = {
|
|
86
|
-
filesystem: true,
|
|
87
|
-
execution: true,
|
|
88
|
-
persistence: true
|
|
89
|
-
};
|
|
90
|
-
fs;
|
|
91
|
-
bashOptions;
|
|
92
|
-
async exec(command, _options) {
|
|
93
|
-
const bash = new justBash.Bash({ ...this.bashOptions, fs: this.justBashFs });
|
|
94
|
-
const { exitCode, stderr, stdout } = await bash.exec(command);
|
|
95
|
-
return { exitCode, stdout, stderr };
|
|
96
|
-
}
|
|
97
|
-
async destroy() {
|
|
98
|
-
}
|
|
99
|
-
/** Expose the underlying IFileSystem for snapshot serialisation */
|
|
100
|
-
_getJustBashFs() {
|
|
101
|
-
return this.justBashFs;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
var IN_MEMORY_CAPS = [
|
|
105
|
-
"pause",
|
|
106
|
-
"resume",
|
|
107
|
-
"snapshot",
|
|
108
|
-
"restore",
|
|
109
|
-
"fork"
|
|
110
|
-
];
|
|
111
|
-
var InMemorySandboxProvider = class {
|
|
112
|
-
constructor(defaultOptions) {
|
|
113
|
-
this.defaultOptions = defaultOptions;
|
|
114
|
-
}
|
|
115
|
-
defaultOptions;
|
|
116
|
-
id = "inMemory";
|
|
117
|
-
capabilities = {
|
|
118
|
-
filesystem: true,
|
|
119
|
-
execution: true,
|
|
120
|
-
persistence: true
|
|
121
|
-
};
|
|
122
|
-
supportedCapabilities = new Set(
|
|
123
|
-
IN_MEMORY_CAPS
|
|
124
|
-
);
|
|
125
|
-
sandboxes = /* @__PURE__ */ new Map();
|
|
126
|
-
async get(id) {
|
|
127
|
-
const sandbox = this.sandboxes.get(id);
|
|
128
|
-
if (!sandbox) throw new SandboxNotFoundError(id);
|
|
129
|
-
return sandbox;
|
|
130
|
-
}
|
|
131
|
-
async destroy(id) {
|
|
132
|
-
const sandbox = this.sandboxes.get(id);
|
|
133
|
-
if (sandbox) {
|
|
134
|
-
await sandbox.destroy();
|
|
135
|
-
this.sandboxes.delete(id);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
async pause(_sandboxId, _ttlSeconds) {
|
|
139
|
-
}
|
|
140
|
-
async resume(_sandboxId) {
|
|
141
|
-
}
|
|
142
|
-
async create(options) {
|
|
143
|
-
const id = options?.id ?? getShortId();
|
|
144
|
-
const initialFiles = {};
|
|
145
|
-
if (options?.initialFiles) {
|
|
146
|
-
for (const [path, content] of Object.entries(options.initialFiles)) {
|
|
147
|
-
initialFiles[path] = content;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
const fs = new justBash.InMemoryFs(initialFiles);
|
|
151
|
-
const sandbox = new InMemorySandboxImpl(id, fs, this.defaultOptions);
|
|
152
|
-
this.sandboxes.set(id, sandbox);
|
|
153
|
-
return { sandbox };
|
|
154
|
-
}
|
|
155
|
-
async snapshot(sandboxId, _options) {
|
|
156
|
-
const sandbox = this.sandboxes.get(sandboxId);
|
|
157
|
-
if (!sandbox) throw new SandboxNotFoundError(sandboxId);
|
|
158
|
-
const fs = sandbox._getJustBashFs();
|
|
159
|
-
const paths = fs.getAllPaths();
|
|
160
|
-
const files = {};
|
|
161
|
-
for (const p of paths) {
|
|
162
|
-
try {
|
|
163
|
-
const stat = await fs.stat(p);
|
|
164
|
-
if (stat.isFile) {
|
|
165
|
-
files[p] = await fs.readFile(p);
|
|
166
|
-
}
|
|
167
|
-
} catch {
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
sandboxId,
|
|
172
|
-
providerId: this.id,
|
|
173
|
-
data: { files },
|
|
174
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
async fork(sandboxId, _options) {
|
|
178
|
-
const sandbox = await this.get(sandboxId);
|
|
179
|
-
const entries = await sandbox.fs.readdirWithFileTypes("/");
|
|
180
|
-
const initialFiles = {};
|
|
181
|
-
for (const entry of entries) {
|
|
182
|
-
if (entry.isFile) {
|
|
183
|
-
initialFiles[entry.name] = await sandbox.fs.readFileBuffer(entry.name);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const newSandbox = await this.create({
|
|
187
|
-
id: getShortId(),
|
|
188
|
-
initialFiles
|
|
189
|
-
});
|
|
190
|
-
return newSandbox.sandbox;
|
|
191
|
-
}
|
|
192
|
-
async restore(snapshot, _options) {
|
|
193
|
-
const { files } = snapshot.data;
|
|
194
|
-
const initialFiles = {};
|
|
195
|
-
for (const [path, content] of Object.entries(files)) {
|
|
196
|
-
initialFiles[path] = content;
|
|
197
|
-
}
|
|
198
|
-
const fs = new justBash.InMemoryFs(initialFiles);
|
|
199
|
-
const sandbox = new InMemorySandboxImpl(
|
|
200
|
-
snapshot.sandboxId,
|
|
201
|
-
fs,
|
|
202
|
-
this.defaultOptions
|
|
203
|
-
);
|
|
204
|
-
this.sandboxes.set(sandbox.id, sandbox);
|
|
205
|
-
return sandbox;
|
|
206
|
-
}
|
|
207
|
-
async deleteSnapshot(_snapshot) {
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
exports.IN_MEMORY_CAPS = IN_MEMORY_CAPS;
|
|
212
|
-
exports.InMemorySandboxProvider = InMemorySandboxProvider;
|
|
213
|
-
//# sourceMappingURL=index.cjs.map
|
|
214
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/sandbox/types.ts","../../../../src/lib/thread/id.ts","../../../../src/adapters/sandbox/inmemory/index.ts"],"names":["ApplicationFailure","uuid4","Bash","InMemoryFs"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// Sandbox Filesystem\n// ============================================================================\n\nexport interface DirentEntry {\n name: string;\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n}\n\nexport interface FileStat {\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n size: number;\n mtime: Date;\n}\n\n// ============================================================================\n// Network & lifecycle\n// ============================================================================\n\nexport interface SandboxNetworkConfig {\n allowOut?: string[];\n denyOut?: string[];\n allowPublicTraffic?: boolean;\n}\n\nexport interface SandboxLifecycleConfig {\n onTimeout: \"kill\" | \"pause\";\n autoResume?: boolean;\n}\n\n/**\n * Provider-agnostic filesystem interface.\n *\n * Implementations that don't support a method should throw\n * {@link SandboxNotSupportedError}.\n */\nexport interface SandboxFileSystem {\n /** Base directory used when resolving relative paths. */\n readonly workspaceBase: string;\n readFile(path: string): Promise<string>;\n readFileBuffer(path: string): Promise<Uint8Array>;\n writeFile(path: string, content: string | Uint8Array): Promise<void>;\n appendFile(path: string, content: string | Uint8Array): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<FileStat>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n readdir(path: string): Promise<string[]>;\n readdirWithFileTypes(path: string): Promise<DirentEntry[]>;\n rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void>;\n cp(\n src: string,\n dest: string,\n options?: { recursive?: boolean }\n ): Promise<void>;\n mv(src: string, dest: string): Promise<void>;\n readlink(path: string): Promise<string>;\n resolvePath(base: string, path: string): string;\n}\n\n// ============================================================================\n// Execution\n// ============================================================================\n\nexport interface ExecOptions {\n timeout?: number;\n cwd?: string;\n env?: Record<string, string>;\n}\n\nexport interface ExecResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n// ============================================================================\n// Capabilities\n// ============================================================================\n\n/**\n * Runtime capability flags carried by a {@link Sandbox} instance.\n *\n * These are an orthogonal mechanism to the type-level\n * {@link SandboxCapability} union: this flag bag is for runtime\n * introspection (\"does the sandbox support a filesystem?\") whereas\n * {@link SandboxCapability} narrows the type-level provider/ops contract.\n */\nexport interface SandboxCapabilities {\n /** Sandbox supports filesystem operations */\n filesystem: boolean;\n /** Sandbox supports shell/command execution */\n execution: boolean;\n /** Sandbox state can be persisted and restored */\n persistence: boolean;\n}\n\n/**\n * Type-level capability vocabulary for {@link SandboxProvider} and\n * {@link SandboxOps}. Adapters declare the subset they actually support; the\n * conditional types on each contract gate the corresponding methods so\n * unsupported calls become a compile-time error rather than a runtime\n * {@link SandboxNotSupportedError}.\n *\n * `pause` and `resume` are split because some adapters might support one\n * direction without the other. The `snapshot` cap covers both `snapshot()`\n * and `deleteSnapshot()` since they always travel together in practice.\n */\nexport type SandboxCapability =\n | \"pause\"\n | \"resume\"\n | \"snapshot\"\n | \"restore\"\n | \"fork\";\n\n// ============================================================================\n// Sandbox\n// ============================================================================\n\nexport interface Sandbox {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n readonly fs: SandboxFileSystem;\n\n exec(command: string, options?: ExecOptions): Promise<ExecResult>;\n destroy(): Promise<void>;\n}\n\n// ============================================================================\n// Snapshots\n// ============================================================================\n\nexport interface SandboxSnapshot {\n sandboxId: string;\n providerId: string;\n /** Provider-specific serialised state */\n data: unknown;\n createdAt: string;\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface SandboxCreateOptions {\n /** Preferred sandbox ID (provider may ignore) */\n id?: string;\n /** Seed the filesystem with these files */\n initialFiles?: Record<string, string | Uint8Array>;\n /** Environment variables available inside the sandbox */\n env?: Record<string, string>;\n /** Key-value metadata surfaced via provider list/query APIs */\n metadata?: Record<string, string>;\n /** Sandbox idle timeout in milliseconds */\n timeoutMs?: number;\n /** Enable or disable outbound internet access */\n allowInternetAccess?: boolean;\n /** Outbound network allow/deny rules */\n network?: SandboxNetworkConfig;\n /** Sandbox timeout behaviour */\n lifecycle?: SandboxLifecycleConfig;\n}\n\nexport interface SandboxCreateResult {\n sandbox: Sandbox;\n}\n\n/**\n * Internal helper: drop keys whose value is `never` from an object type.\n *\n * Used by the capability-gated contracts below so that an absent capability\n * removes the corresponding key entirely, instead of leaving a required\n * field with type `never` (which would make implementations impossible).\n */\ntype OmitNever<T> = {\n [K in keyof T as [T[K]] extends [never] ? never : K]: T[K];\n};\n\n/**\n * Capability-gated provider lifecycle methods.\n *\n * Each field becomes `never` when its capability is absent from `TCaps`;\n * the wrapping `OmitNever` removes those keys entirely, so the method\n * isn't part of the type surface for adapters that don't support it.\n */\ntype SandboxProviderCapMethods<\n TOptions extends SandboxCreateOptions,\n TSandbox extends Sandbox,\n TCaps extends SandboxCapability,\n> = OmitNever<{\n pause: \"pause\" extends TCaps\n ? (sandboxId: string, ttlSeconds?: number) => Promise<void>\n : never;\n resume: \"resume\" extends TCaps ? (sandboxId: string) => Promise<void> : never;\n snapshot: \"snapshot\" extends TCaps\n ? (sandboxId: string, options?: TOptions) => Promise<SandboxSnapshot>\n : never;\n deleteSnapshot: \"snapshot\" extends TCaps\n ? (snapshot: SandboxSnapshot) => Promise<void>\n : never;\n restore: \"restore\" extends TCaps\n ? (snapshot: SandboxSnapshot, options?: TOptions) => Promise<TSandbox>\n : never;\n fork: \"fork\" extends TCaps\n ? (sandboxId: string, options?: TOptions) => Promise<TSandbox>\n : never;\n}>;\n\n/**\n * Always-present provider lifecycle methods. These do not depend on the\n * capability set and are required by every adapter.\n */\ninterface SandboxProviderBase<\n TOptions extends SandboxCreateOptions,\n TSandbox extends Sandbox,\n TCaps extends SandboxCapability,\n> {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n /**\n * Runtime-introspectable list of supported capabilities.\n *\n * Constrained to `ReadonlySet<TCaps & SandboxCapability>` so the runtime\n * set cannot include capabilities not declared at the type level — a\n * provider typed as `SandboxProvider<…, never>` cannot ship a runtime\n * set that contains `\"pause\"`, etc.\n *\n * The other direction (type declares a cap, runtime set omits it)\n * cannot be enforced by TypeScript alone; adapters should derive both\n * `TCaps` and the runtime set from the same `as const` array (see\n * `SandboxManager`'s constructor-time consistency check) so the two\n * surfaces cannot drift.\n */\n readonly supportedCapabilities: ReadonlySet<TCaps & SandboxCapability>;\n\n create(options?: TOptions): Promise<SandboxCreateResult>;\n get(sandboxId: string): Promise<TSandbox>;\n destroy(sandboxId: string): Promise<void>;\n}\n\n/**\n * Provider-side sandbox lifecycle contract.\n *\n * Generic over an optional capability set (`TCaps`). Each capability gates\n * a specific method: when the cap is absent the corresponding key is\n * **removed** from the type entirely, so calling it produces a TypeScript\n * error at the call site instead of a runtime\n * {@link SandboxNotSupportedError}.\n *\n * The default `TCaps = SandboxCapability` resolves to the full union, so\n * existing usages that only pass `TOptions` / `TSandbox` continue to see\n * the full method surface (backwards compatible).\n *\n * Adapters that don't support a method should narrow `TCaps` accordingly:\n *\n * - In-memory / E2B: `SandboxCapability` (default — all caps present).\n * - Bedrock Code Interpreter / Daytona: `never` (only base ops).\n * - Bedrock AgentCore Runtime: `\"pause\" | \"resume\"`.\n */\nexport type SandboxProvider<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n TSandbox extends Sandbox = Sandbox,\n TCaps extends SandboxCapability = SandboxCapability,\n> = SandboxProviderBase<TOptions, TSandbox, TCaps> &\n SandboxProviderCapMethods<TOptions, TSandbox, TCaps>;\n\n// ============================================================================\n// SandboxOps — workflow-side activity interface (like ThreadOps)\n// ============================================================================\n\n/**\n * Capability-gated workflow-side methods. Mirrors the provider's gating:\n * keys whose capability is absent from `TCaps` are removed from the type.\n */\ntype SandboxOpsCapMethods<\n TOptions extends SandboxCreateOptions,\n TCaps extends SandboxCapability,\n> = OmitNever<{\n pauseSandbox: \"pause\" extends TCaps\n ? (sandboxId: string) => Promise<void>\n : never;\n resumeSandbox: \"resume\" extends TCaps\n ? (sandboxId: string) => Promise<void>\n : never;\n snapshotSandbox: \"snapshot\" extends TCaps\n ? (sandboxId: string, options?: TOptions) => Promise<SandboxSnapshot>\n : never;\n deleteSandboxSnapshot: \"snapshot\" extends TCaps\n ? (snapshot: SandboxSnapshot) => Promise<void>\n : never;\n restoreSandbox: \"restore\" extends TCaps\n ? (snapshot: SandboxSnapshot, options?: TOptions) => Promise<string>\n : never;\n forkSandbox: \"fork\" extends TCaps\n ? (sandboxId: string, options?: TOptions) => Promise<string>\n : never;\n}>;\n\n/**\n * Always-present workflow-side lifecycle methods.\n */\ninterface SandboxOpsBase<\n TOptions extends SandboxCreateOptions,\n TCtx,\n> {\n createSandbox(\n options?: TOptions,\n ctx?: TCtx\n ): Promise<{ sandboxId: string } | null>;\n destroySandbox(sandboxId: string): Promise<void>;\n}\n\n/**\n * Workflow-side counterpart to {@link SandboxProvider}. Exposed as a set of\n * Temporal activities and consumed by `createSession`'s `sandboxOps` field\n * and by `defineSubagent`'s `sandbox.proxy`.\n *\n * Generic over a capability set (`TCaps`) — same semantics as the provider:\n * keys whose capability is absent are removed from the type, so calling\n * them is a TypeScript error rather than a runtime throw. The default\n * `TCaps = SandboxCapability` keeps the full method surface for existing\n * consumers.\n */\nexport type SandboxOps<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n TCtx = unknown,\n TCaps extends SandboxCapability = SandboxCapability,\n> = SandboxOpsBase<TOptions, TCtx> & SandboxOpsCapMethods<TOptions, TCaps>;\n\n/**\n * Maps generic {@link SandboxOps} method names to adapter-prefixed names.\n *\n * Inherits the capability gating from {@link SandboxOps}: when `TCaps` omits\n * a capability the prefixed key carries the `never` type so call sites are\n * type-protected.\n *\n * @example\n * ```typescript\n * type InMemOps = PrefixedSandboxOps<\"inMemory\">;\n * // → { inMemoryCreateSandbox, inMemoryDestroySandbox, inMemorySnapshotSandbox, … }\n * ```\n */\nexport type PrefixedSandboxOps<\n TPrefix extends string,\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n TCtx = unknown,\n TCaps extends SandboxCapability = SandboxCapability,\n> = {\n [K in keyof SandboxOps<\n TOptions,\n TCtx,\n TCaps\n > as `${TPrefix}${Capitalize<K & string>}`]: SandboxOps<\n TOptions,\n TCtx,\n TCaps\n >[K];\n};\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nimport { ApplicationFailure } from \"@temporalio/common\";\n\n/**\n * Thrown by adapters that still surface an unsupported method at runtime.\n *\n * After the capability-generic refactor most adapters drop their\n * unsupported methods entirely so the type system rejects them at call\n * sites. This symbol is still exported so consumers running against older\n * adapter versions can keep their backwards-compatible error-handling\n * paths until they finish migrating.\n */\nexport class SandboxNotSupportedError extends ApplicationFailure {\n constructor(operation: string) {\n super(\n `Sandbox does not support: ${operation}`,\n \"SandboxNotSupportedError\",\n true\n );\n }\n}\n\nexport class SandboxNotFoundError extends ApplicationFailure {\n constructor(sandboxId: string) {\n super(`Sandbox not found: ${sandboxId}`, \"SandboxNotFoundError\", true);\n }\n}\n","import { uuid4 } from \"@temporalio/workflow\";\n\nconst BASE62 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/**\n * Generate a compact, workflow-deterministic identifier.\n *\n * Uses Temporal's `uuid4()` internally (seeded by the workflow's RNG),\n * then re-encodes the hex bytes into a base-62 alphabet for a shorter,\n * more token-efficient identifier (~3 tokens vs ~10 for a full UUID).\n *\n * Suitable for thread IDs, child workflow IDs, or any workflow-scoped identifier.\n *\n * @param length - Number of base-62 characters (default 12, ~71 bits of entropy)\n */\nexport function getShortId(length = 12): string {\n const hex = uuid4().replace(/-/g, \"\");\n let result = \"\";\n for (let i = 0; i < length; i++) {\n const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n result += BASE62[byte % BASE62.length];\n }\n return result;\n}\n","import {\n Bash,\n InMemoryFs,\n type BashOptions,\n type IFileSystem,\n type InitialFiles,\n} from \"just-bash\";\nimport type {\n Sandbox,\n SandboxCapabilities,\n SandboxCapability,\n SandboxCreateOptions,\n SandboxCreateResult,\n SandboxFileSystem,\n SandboxProvider,\n SandboxSnapshot,\n ExecOptions,\n ExecResult,\n DirentEntry,\n FileStat,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotFoundError } from \"../../../lib/sandbox/types\";\nimport { getShortId } from \"../../../lib/thread/id\";\n\n// ============================================================================\n// Adapter: IFileSystem → SandboxFileSystem\n// ============================================================================\n\nfunction toSandboxFs(fs: IFileSystem): SandboxFileSystem {\n const workspaceBase = \"/\";\n const normalisePath = (path: string): string =>\n fs.resolvePath(workspaceBase, path);\n\n return {\n workspaceBase,\n readFile: (path) => fs.readFile(normalisePath(path)),\n readFileBuffer: (path) => fs.readFileBuffer(normalisePath(path)),\n writeFile: (path, content) => fs.writeFile(normalisePath(path), content),\n appendFile: (path, content) => fs.appendFile(normalisePath(path), content),\n exists: (path) => fs.exists(normalisePath(path)),\n stat: async (path): Promise<FileStat> => {\n const s = await fs.stat(normalisePath(path));\n return {\n isFile: s.isFile,\n isDirectory: s.isDirectory,\n isSymbolicLink: s.isSymbolicLink,\n size: s.size,\n mtime: s.mtime,\n };\n },\n mkdir: (path, opts) => fs.mkdir(normalisePath(path), opts),\n readdir: (path) => fs.readdir(normalisePath(path)),\n readdirWithFileTypes: async (path): Promise<DirentEntry[]> => {\n const dirPath = normalisePath(path);\n if (!fs.readdirWithFileTypes) {\n const names = await fs.readdir(dirPath);\n return Promise.all(\n names.map(async (name) => {\n const childPath = fs.resolvePath(dirPath, name);\n const s = await fs.stat(childPath);\n return {\n name,\n isFile: s.isFile,\n isDirectory: s.isDirectory,\n isSymbolicLink: s.isSymbolicLink,\n };\n })\n );\n }\n return fs.readdirWithFileTypes(dirPath);\n },\n rm: (path, opts) => fs.rm(normalisePath(path), opts),\n cp: (src, dest, opts) =>\n fs.cp(normalisePath(src), normalisePath(dest), opts),\n mv: (src, dest) => fs.mv(normalisePath(src), normalisePath(dest)),\n readlink: (path) => fs.readlink(normalisePath(path)),\n resolvePath: (base, p) => fs.resolvePath(normalisePath(base), p),\n };\n}\n\n// ============================================================================\n// InMemorySandbox\n// ============================================================================\n\nexport interface InMemorySandboxOptions {\n /** Options forwarded to `just-bash` `Bash` (minus `fs` which is managed) */\n bashOptions?: Omit<BashOptions, \"fs\">;\n}\n\n/**\n * An in-memory {@link Sandbox} backed by `just-bash`.\n */\nexport type InMemorySandbox = Sandbox & { fs: SandboxFileSystem };\n\nclass InMemorySandboxImpl implements Sandbox {\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: true,\n };\n\n readonly fs: SandboxFileSystem;\n private bashOptions: Omit<BashOptions, \"fs\">;\n\n constructor(\n readonly id: string,\n private justBashFs: IFileSystem,\n options?: InMemorySandboxOptions\n ) {\n this.fs = toSandboxFs(justBashFs);\n this.bashOptions = {\n executionLimits: { maxStringLength: 52_428_800 },\n ...options?.bashOptions,\n };\n }\n\n async exec(command: string, _options?: ExecOptions): Promise<ExecResult> {\n const bash = new Bash({ ...this.bashOptions, fs: this.justBashFs });\n const { exitCode, stderr, stdout } = await bash.exec(command);\n return { exitCode, stdout, stderr };\n }\n\n async destroy(): Promise<void> {\n // In-memory: nothing to clean up\n }\n\n /** Expose the underlying IFileSystem for snapshot serialisation */\n _getJustBashFs(): IFileSystem {\n return this.justBashFs;\n }\n}\n\n// ============================================================================\n// InMemorySandboxProvider\n// ============================================================================\n\n/**\n * Single source of truth for the in-memory adapter's capability set. The\n * runtime `supportedCapabilities` set and the type-level `TCaps` are both\n * derived from this array, so the two surfaces cannot drift.\n */\nexport const IN_MEMORY_CAPS = [\n \"pause\",\n \"resume\",\n \"snapshot\",\n \"restore\",\n \"fork\",\n] as const satisfies readonly SandboxCapability[];\nexport type InMemoryCaps = (typeof IN_MEMORY_CAPS)[number];\n\nexport class InMemorySandboxProvider\n implements SandboxProvider<SandboxCreateOptions, Sandbox, InMemoryCaps>\n{\n readonly id = \"inMemory\";\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: true,\n };\n readonly supportedCapabilities: ReadonlySet<InMemoryCaps> = new Set(\n IN_MEMORY_CAPS\n );\n\n private sandboxes = new Map<string, InMemorySandboxImpl>();\n\n constructor(private defaultOptions?: InMemorySandboxOptions) {}\n\n async get(id: string): Promise<Sandbox> {\n const sandbox = this.sandboxes.get(id);\n if (!sandbox) throw new SandboxNotFoundError(id);\n return sandbox;\n }\n\n async destroy(id: string): Promise<void> {\n const sandbox = this.sandboxes.get(id);\n if (sandbox) {\n await sandbox.destroy();\n this.sandboxes.delete(id);\n }\n }\n\n async pause(_sandboxId: string, _ttlSeconds?: number): Promise<void> {\n // In-memory: nothing to pause\n }\n\n async resume(_sandboxId: string): Promise<void> {\n // In-memory: nothing to resume\n }\n\n async create(options?: SandboxCreateOptions): Promise<SandboxCreateResult> {\n const id = options?.id ?? getShortId();\n const initialFiles: InitialFiles = {};\n\n if (options?.initialFiles) {\n for (const [path, content] of Object.entries(options.initialFiles)) {\n initialFiles[path] = content;\n }\n }\n\n const fs = new InMemoryFs(initialFiles);\n const sandbox = new InMemorySandboxImpl(id, fs, this.defaultOptions);\n this.sandboxes.set(id, sandbox);\n return { sandbox };\n }\n\n async snapshot(\n sandboxId: string,\n _options?: SandboxCreateOptions\n ): Promise<SandboxSnapshot> {\n const sandbox = this.sandboxes.get(sandboxId);\n if (!sandbox) throw new SandboxNotFoundError(sandboxId);\n\n const fs = sandbox._getJustBashFs();\n const paths = fs.getAllPaths();\n const files: Record<string, string> = {};\n\n for (const p of paths) {\n try {\n const stat = await fs.stat(p);\n if (stat.isFile) {\n files[p] = await fs.readFile(p);\n }\n } catch {\n // skip entries that can't be read (e.g. broken symlinks)\n }\n }\n\n return {\n sandboxId,\n providerId: this.id,\n data: { files },\n createdAt: new Date().toISOString(),\n };\n }\n\n async fork(\n sandboxId: string,\n _options?: SandboxCreateOptions\n ): Promise<Sandbox> {\n const sandbox = await this.get(sandboxId);\n\n const entries = await sandbox.fs.readdirWithFileTypes(\"/\");\n const initialFiles: Record<string, Uint8Array> = {};\n for (const entry of entries) {\n if (entry.isFile) {\n initialFiles[entry.name] = await sandbox.fs.readFileBuffer(entry.name);\n }\n }\n\n const newSandbox = await this.create({\n id: getShortId(),\n initialFiles,\n });\n return newSandbox.sandbox;\n }\n\n async restore(\n snapshot: SandboxSnapshot,\n _options?: SandboxCreateOptions\n ): Promise<Sandbox> {\n const { files } = snapshot.data as { files: Record<string, string> };\n const initialFiles: InitialFiles = {};\n for (const [path, content] of Object.entries(files)) {\n initialFiles[path] = content;\n }\n\n const fs = new InMemoryFs(initialFiles);\n const sandbox = new InMemorySandboxImpl(\n snapshot.sandboxId,\n fs,\n this.defaultOptions\n );\n this.sandboxes.set(sandbox.id, sandbox);\n return sandbox;\n }\n\n async deleteSnapshot(_snapshot: SandboxSnapshot): Promise<void> {\n // In-memory snapshots are opaque data held by the caller — nothing to\n // delete on the provider side.\n }\n}\n"]}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { BashOptions } from 'just-bash';
|
|
2
|
-
import { b as Sandbox, c as SandboxFileSystem, d as SandboxProvider, a as SandboxCreateOptions, e as SandboxCapabilities, f as SandboxCreateResult, g as SandboxSnapshot } from '../../../types-CJ7tCdl6.cjs';
|
|
3
|
-
import '@temporalio/common';
|
|
4
|
-
|
|
5
|
-
interface InMemorySandboxOptions {
|
|
6
|
-
/** Options forwarded to `just-bash` `Bash` (minus `fs` which is managed) */
|
|
7
|
-
bashOptions?: Omit<BashOptions, "fs">;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* An in-memory {@link Sandbox} backed by `just-bash`.
|
|
11
|
-
*/
|
|
12
|
-
type InMemorySandbox = Sandbox & {
|
|
13
|
-
fs: SandboxFileSystem;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Single source of truth for the in-memory adapter's capability set. The
|
|
17
|
-
* runtime `supportedCapabilities` set and the type-level `TCaps` are both
|
|
18
|
-
* derived from this array, so the two surfaces cannot drift.
|
|
19
|
-
*/
|
|
20
|
-
declare const IN_MEMORY_CAPS: readonly ["pause", "resume", "snapshot", "restore", "fork"];
|
|
21
|
-
type InMemoryCaps = (typeof IN_MEMORY_CAPS)[number];
|
|
22
|
-
declare class InMemorySandboxProvider implements SandboxProvider<SandboxCreateOptions, Sandbox, InMemoryCaps> {
|
|
23
|
-
private defaultOptions?;
|
|
24
|
-
readonly id = "inMemory";
|
|
25
|
-
readonly capabilities: SandboxCapabilities;
|
|
26
|
-
readonly supportedCapabilities: ReadonlySet<InMemoryCaps>;
|
|
27
|
-
private sandboxes;
|
|
28
|
-
constructor(defaultOptions?: InMemorySandboxOptions | undefined);
|
|
29
|
-
get(id: string): Promise<Sandbox>;
|
|
30
|
-
destroy(id: string): Promise<void>;
|
|
31
|
-
pause(_sandboxId: string, _ttlSeconds?: number): Promise<void>;
|
|
32
|
-
resume(_sandboxId: string): Promise<void>;
|
|
33
|
-
create(options?: SandboxCreateOptions): Promise<SandboxCreateResult>;
|
|
34
|
-
snapshot(sandboxId: string, _options?: SandboxCreateOptions): Promise<SandboxSnapshot>;
|
|
35
|
-
fork(sandboxId: string, _options?: SandboxCreateOptions): Promise<Sandbox>;
|
|
36
|
-
restore(snapshot: SandboxSnapshot, _options?: SandboxCreateOptions): Promise<Sandbox>;
|
|
37
|
-
deleteSnapshot(_snapshot: SandboxSnapshot): Promise<void>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export { IN_MEMORY_CAPS, type InMemoryCaps, type InMemorySandbox, type InMemorySandboxOptions, InMemorySandboxProvider };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { BashOptions } from 'just-bash';
|
|
2
|
-
import { b as Sandbox, c as SandboxFileSystem, d as SandboxProvider, a as SandboxCreateOptions, e as SandboxCapabilities, f as SandboxCreateResult, g as SandboxSnapshot } from '../../../types-CJ7tCdl6.js';
|
|
3
|
-
import '@temporalio/common';
|
|
4
|
-
|
|
5
|
-
interface InMemorySandboxOptions {
|
|
6
|
-
/** Options forwarded to `just-bash` `Bash` (minus `fs` which is managed) */
|
|
7
|
-
bashOptions?: Omit<BashOptions, "fs">;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* An in-memory {@link Sandbox} backed by `just-bash`.
|
|
11
|
-
*/
|
|
12
|
-
type InMemorySandbox = Sandbox & {
|
|
13
|
-
fs: SandboxFileSystem;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Single source of truth for the in-memory adapter's capability set. The
|
|
17
|
-
* runtime `supportedCapabilities` set and the type-level `TCaps` are both
|
|
18
|
-
* derived from this array, so the two surfaces cannot drift.
|
|
19
|
-
*/
|
|
20
|
-
declare const IN_MEMORY_CAPS: readonly ["pause", "resume", "snapshot", "restore", "fork"];
|
|
21
|
-
type InMemoryCaps = (typeof IN_MEMORY_CAPS)[number];
|
|
22
|
-
declare class InMemorySandboxProvider implements SandboxProvider<SandboxCreateOptions, Sandbox, InMemoryCaps> {
|
|
23
|
-
private defaultOptions?;
|
|
24
|
-
readonly id = "inMemory";
|
|
25
|
-
readonly capabilities: SandboxCapabilities;
|
|
26
|
-
readonly supportedCapabilities: ReadonlySet<InMemoryCaps>;
|
|
27
|
-
private sandboxes;
|
|
28
|
-
constructor(defaultOptions?: InMemorySandboxOptions | undefined);
|
|
29
|
-
get(id: string): Promise<Sandbox>;
|
|
30
|
-
destroy(id: string): Promise<void>;
|
|
31
|
-
pause(_sandboxId: string, _ttlSeconds?: number): Promise<void>;
|
|
32
|
-
resume(_sandboxId: string): Promise<void>;
|
|
33
|
-
create(options?: SandboxCreateOptions): Promise<SandboxCreateResult>;
|
|
34
|
-
snapshot(sandboxId: string, _options?: SandboxCreateOptions): Promise<SandboxSnapshot>;
|
|
35
|
-
fork(sandboxId: string, _options?: SandboxCreateOptions): Promise<Sandbox>;
|
|
36
|
-
restore(snapshot: SandboxSnapshot, _options?: SandboxCreateOptions): Promise<Sandbox>;
|
|
37
|
-
deleteSnapshot(_snapshot: SandboxSnapshot): Promise<void>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export { IN_MEMORY_CAPS, type InMemoryCaps, type InMemorySandbox, type InMemorySandboxOptions, InMemorySandboxProvider };
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { InMemoryFs, Bash } from 'just-bash';
|
|
2
|
-
import { ApplicationFailure } from '@temporalio/common';
|
|
3
|
-
import { uuid4 } from '@temporalio/workflow';
|
|
4
|
-
|
|
5
|
-
// src/adapters/sandbox/inmemory/index.ts
|
|
6
|
-
var SandboxNotFoundError = class extends ApplicationFailure {
|
|
7
|
-
constructor(sandboxId) {
|
|
8
|
-
super(`Sandbox not found: ${sandboxId}`, "SandboxNotFoundError", true);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
12
|
-
function getShortId(length = 12) {
|
|
13
|
-
const hex = uuid4().replace(/-/g, "");
|
|
14
|
-
let result = "";
|
|
15
|
-
for (let i = 0; i < length; i++) {
|
|
16
|
-
const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
17
|
-
result += BASE62[byte % BASE62.length];
|
|
18
|
-
}
|
|
19
|
-
return result;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// src/adapters/sandbox/inmemory/index.ts
|
|
23
|
-
function toSandboxFs(fs) {
|
|
24
|
-
const workspaceBase = "/";
|
|
25
|
-
const normalisePath = (path) => fs.resolvePath(workspaceBase, path);
|
|
26
|
-
return {
|
|
27
|
-
workspaceBase,
|
|
28
|
-
readFile: (path) => fs.readFile(normalisePath(path)),
|
|
29
|
-
readFileBuffer: (path) => fs.readFileBuffer(normalisePath(path)),
|
|
30
|
-
writeFile: (path, content) => fs.writeFile(normalisePath(path), content),
|
|
31
|
-
appendFile: (path, content) => fs.appendFile(normalisePath(path), content),
|
|
32
|
-
exists: (path) => fs.exists(normalisePath(path)),
|
|
33
|
-
stat: async (path) => {
|
|
34
|
-
const s = await fs.stat(normalisePath(path));
|
|
35
|
-
return {
|
|
36
|
-
isFile: s.isFile,
|
|
37
|
-
isDirectory: s.isDirectory,
|
|
38
|
-
isSymbolicLink: s.isSymbolicLink,
|
|
39
|
-
size: s.size,
|
|
40
|
-
mtime: s.mtime
|
|
41
|
-
};
|
|
42
|
-
},
|
|
43
|
-
mkdir: (path, opts) => fs.mkdir(normalisePath(path), opts),
|
|
44
|
-
readdir: (path) => fs.readdir(normalisePath(path)),
|
|
45
|
-
readdirWithFileTypes: async (path) => {
|
|
46
|
-
const dirPath = normalisePath(path);
|
|
47
|
-
if (!fs.readdirWithFileTypes) {
|
|
48
|
-
const names = await fs.readdir(dirPath);
|
|
49
|
-
return Promise.all(
|
|
50
|
-
names.map(async (name) => {
|
|
51
|
-
const childPath = fs.resolvePath(dirPath, name);
|
|
52
|
-
const s = await fs.stat(childPath);
|
|
53
|
-
return {
|
|
54
|
-
name,
|
|
55
|
-
isFile: s.isFile,
|
|
56
|
-
isDirectory: s.isDirectory,
|
|
57
|
-
isSymbolicLink: s.isSymbolicLink
|
|
58
|
-
};
|
|
59
|
-
})
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return fs.readdirWithFileTypes(dirPath);
|
|
63
|
-
},
|
|
64
|
-
rm: (path, opts) => fs.rm(normalisePath(path), opts),
|
|
65
|
-
cp: (src, dest, opts) => fs.cp(normalisePath(src), normalisePath(dest), opts),
|
|
66
|
-
mv: (src, dest) => fs.mv(normalisePath(src), normalisePath(dest)),
|
|
67
|
-
readlink: (path) => fs.readlink(normalisePath(path)),
|
|
68
|
-
resolvePath: (base, p) => fs.resolvePath(normalisePath(base), p)
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
var InMemorySandboxImpl = class {
|
|
72
|
-
constructor(id, justBashFs, options) {
|
|
73
|
-
this.id = id;
|
|
74
|
-
this.justBashFs = justBashFs;
|
|
75
|
-
this.fs = toSandboxFs(justBashFs);
|
|
76
|
-
this.bashOptions = {
|
|
77
|
-
executionLimits: { maxStringLength: 52428800 },
|
|
78
|
-
...options?.bashOptions
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
id;
|
|
82
|
-
justBashFs;
|
|
83
|
-
capabilities = {
|
|
84
|
-
filesystem: true,
|
|
85
|
-
execution: true,
|
|
86
|
-
persistence: true
|
|
87
|
-
};
|
|
88
|
-
fs;
|
|
89
|
-
bashOptions;
|
|
90
|
-
async exec(command, _options) {
|
|
91
|
-
const bash = new Bash({ ...this.bashOptions, fs: this.justBashFs });
|
|
92
|
-
const { exitCode, stderr, stdout } = await bash.exec(command);
|
|
93
|
-
return { exitCode, stdout, stderr };
|
|
94
|
-
}
|
|
95
|
-
async destroy() {
|
|
96
|
-
}
|
|
97
|
-
/** Expose the underlying IFileSystem for snapshot serialisation */
|
|
98
|
-
_getJustBashFs() {
|
|
99
|
-
return this.justBashFs;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
var IN_MEMORY_CAPS = [
|
|
103
|
-
"pause",
|
|
104
|
-
"resume",
|
|
105
|
-
"snapshot",
|
|
106
|
-
"restore",
|
|
107
|
-
"fork"
|
|
108
|
-
];
|
|
109
|
-
var InMemorySandboxProvider = class {
|
|
110
|
-
constructor(defaultOptions) {
|
|
111
|
-
this.defaultOptions = defaultOptions;
|
|
112
|
-
}
|
|
113
|
-
defaultOptions;
|
|
114
|
-
id = "inMemory";
|
|
115
|
-
capabilities = {
|
|
116
|
-
filesystem: true,
|
|
117
|
-
execution: true,
|
|
118
|
-
persistence: true
|
|
119
|
-
};
|
|
120
|
-
supportedCapabilities = new Set(
|
|
121
|
-
IN_MEMORY_CAPS
|
|
122
|
-
);
|
|
123
|
-
sandboxes = /* @__PURE__ */ new Map();
|
|
124
|
-
async get(id) {
|
|
125
|
-
const sandbox = this.sandboxes.get(id);
|
|
126
|
-
if (!sandbox) throw new SandboxNotFoundError(id);
|
|
127
|
-
return sandbox;
|
|
128
|
-
}
|
|
129
|
-
async destroy(id) {
|
|
130
|
-
const sandbox = this.sandboxes.get(id);
|
|
131
|
-
if (sandbox) {
|
|
132
|
-
await sandbox.destroy();
|
|
133
|
-
this.sandboxes.delete(id);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async pause(_sandboxId, _ttlSeconds) {
|
|
137
|
-
}
|
|
138
|
-
async resume(_sandboxId) {
|
|
139
|
-
}
|
|
140
|
-
async create(options) {
|
|
141
|
-
const id = options?.id ?? getShortId();
|
|
142
|
-
const initialFiles = {};
|
|
143
|
-
if (options?.initialFiles) {
|
|
144
|
-
for (const [path, content] of Object.entries(options.initialFiles)) {
|
|
145
|
-
initialFiles[path] = content;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const fs = new InMemoryFs(initialFiles);
|
|
149
|
-
const sandbox = new InMemorySandboxImpl(id, fs, this.defaultOptions);
|
|
150
|
-
this.sandboxes.set(id, sandbox);
|
|
151
|
-
return { sandbox };
|
|
152
|
-
}
|
|
153
|
-
async snapshot(sandboxId, _options) {
|
|
154
|
-
const sandbox = this.sandboxes.get(sandboxId);
|
|
155
|
-
if (!sandbox) throw new SandboxNotFoundError(sandboxId);
|
|
156
|
-
const fs = sandbox._getJustBashFs();
|
|
157
|
-
const paths = fs.getAllPaths();
|
|
158
|
-
const files = {};
|
|
159
|
-
for (const p of paths) {
|
|
160
|
-
try {
|
|
161
|
-
const stat = await fs.stat(p);
|
|
162
|
-
if (stat.isFile) {
|
|
163
|
-
files[p] = await fs.readFile(p);
|
|
164
|
-
}
|
|
165
|
-
} catch {
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
sandboxId,
|
|
170
|
-
providerId: this.id,
|
|
171
|
-
data: { files },
|
|
172
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
async fork(sandboxId, _options) {
|
|
176
|
-
const sandbox = await this.get(sandboxId);
|
|
177
|
-
const entries = await sandbox.fs.readdirWithFileTypes("/");
|
|
178
|
-
const initialFiles = {};
|
|
179
|
-
for (const entry of entries) {
|
|
180
|
-
if (entry.isFile) {
|
|
181
|
-
initialFiles[entry.name] = await sandbox.fs.readFileBuffer(entry.name);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
const newSandbox = await this.create({
|
|
185
|
-
id: getShortId(),
|
|
186
|
-
initialFiles
|
|
187
|
-
});
|
|
188
|
-
return newSandbox.sandbox;
|
|
189
|
-
}
|
|
190
|
-
async restore(snapshot, _options) {
|
|
191
|
-
const { files } = snapshot.data;
|
|
192
|
-
const initialFiles = {};
|
|
193
|
-
for (const [path, content] of Object.entries(files)) {
|
|
194
|
-
initialFiles[path] = content;
|
|
195
|
-
}
|
|
196
|
-
const fs = new InMemoryFs(initialFiles);
|
|
197
|
-
const sandbox = new InMemorySandboxImpl(
|
|
198
|
-
snapshot.sandboxId,
|
|
199
|
-
fs,
|
|
200
|
-
this.defaultOptions
|
|
201
|
-
);
|
|
202
|
-
this.sandboxes.set(sandbox.id, sandbox);
|
|
203
|
-
return sandbox;
|
|
204
|
-
}
|
|
205
|
-
async deleteSnapshot(_snapshot) {
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
export { IN_MEMORY_CAPS, InMemorySandboxProvider };
|
|
210
|
-
//# sourceMappingURL=index.js.map
|
|
211
|
-
//# sourceMappingURL=index.js.map
|