@claxedo/sandbox-manager 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/command.d.ts +3 -0
- package/dist/command.mjs +18 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.mjs +7 -0
- package/dist/daytona-allow-list.d.ts +5 -0
- package/dist/daytona-allow-list.mjs +9 -0
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.mjs +14 -0
- package/dist/driver-catalog.d.ts +62 -0
- package/dist/driver-catalog.mjs +206 -0
- package/dist/drivers/cloudflare-egress.d.ts +40 -0
- package/dist/drivers/cloudflare-egress.mjs +115 -0
- package/dist/drivers/cloudflare.d.ts +37 -0
- package/dist/drivers/cloudflare.mjs +151 -0
- package/dist/drivers/daytona.d.ts +94 -0
- package/dist/drivers/daytona.mjs +235 -0
- package/dist/drivers/docker.d.ts +36 -0
- package/dist/drivers/docker.mjs +329 -0
- package/dist/drivers/fetch-bridge.d.ts +10 -0
- package/dist/drivers/fetch-bridge.mjs +104 -0
- package/dist/drivers/modal.d.ts +68 -0
- package/dist/drivers/modal.mjs +227 -0
- package/dist/drivers/vercel.d.ts +109 -0
- package/dist/drivers/vercel.mjs +297 -0
- package/dist/image-name.d.ts +7 -0
- package/dist/image.d.ts +8 -0
- package/dist/image.mjs +124 -0
- package/dist/index.d.ts +316 -0
- package/dist/index.mjs +330 -0
- package/dist/lease-policy.d.ts +49 -0
- package/dist/lease-policy.mjs +126 -0
- package/dist/lease-types.d.ts +89 -0
- package/dist/lease-types.mjs +1 -0
- package/dist/runtime-env.d.ts +24 -0
- package/dist/runtime-env.mjs +35 -0
- package/dist/runtime-version.d.ts +1 -0
- package/dist/runtime-version.mjs +24 -0
- package/dist/service-url-exposure.d.ts +10 -0
- package/dist/service-url-exposure.mjs +46 -0
- package/dist/stores/memory.d.ts +6 -0
- package/dist/stores/memory.mjs +117 -0
- package/package.json +178 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SandboxDriverID } from "./driver-catalog";
|
|
2
|
+
export type SandboxServiceUrlExposure = {
|
|
3
|
+
source: "driver-service-url";
|
|
4
|
+
access: "private" | "public" | "driver-authenticated" | "unknown";
|
|
5
|
+
driver: SandboxDriverID;
|
|
6
|
+
fallbackAccess?: "private" | "public" | "driver-authenticated" | "unknown";
|
|
7
|
+
note?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function sandboxServiceUrlExposure(driver: SandboxDriverID): SandboxServiceUrlExposure;
|
|
10
|
+
export declare function sandboxServiceUrlExposureEnv(driver: SandboxDriverID): Record<string, string>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'module';var require = __createRequire(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// src/runtime-env.ts
|
|
4
|
+
function workspaceRuntimeServiceExposureEnv(input) {
|
|
5
|
+
return {
|
|
6
|
+
...input.driver === "docker" ? { WORKSPACE_RUNTIME_HOST: "0.0.0.0" } : {},
|
|
7
|
+
WORKSPACE_RUNTIME_SERVICE_EXPOSURE_SOURCE: input.source,
|
|
8
|
+
WORKSPACE_RUNTIME_SERVICE_EXPOSURE_ACCESS: input.access,
|
|
9
|
+
WORKSPACE_RUNTIME_SERVICE_EXPOSURE_DRIVER: input.driver,
|
|
10
|
+
...input.fallbackAccess ? { WORKSPACE_RUNTIME_SERVICE_EXPOSURE_FALLBACK_ACCESS: input.fallbackAccess } : {},
|
|
11
|
+
...input.note ? { WORKSPACE_RUNTIME_SERVICE_EXPOSURE_NOTE: input.note } : {}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/service-url-exposure.ts
|
|
16
|
+
function sandboxServiceUrlExposure(driver) {
|
|
17
|
+
if (driver === "docker") {
|
|
18
|
+
return {
|
|
19
|
+
source: "driver-service-url",
|
|
20
|
+
access: "private",
|
|
21
|
+
driver,
|
|
22
|
+
note: "Docker service URLs resolve to a local loopback port on the host."
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (driver === "daytona") {
|
|
26
|
+
return {
|
|
27
|
+
source: "driver-service-url",
|
|
28
|
+
access: "driver-authenticated",
|
|
29
|
+
driver,
|
|
30
|
+
fallbackAccess: "public",
|
|
31
|
+
note: "Daytona uses a signed preview URL when available and falls back to a preview link."
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
source: "driver-service-url",
|
|
36
|
+
access: "public",
|
|
37
|
+
driver
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function sandboxServiceUrlExposureEnv(driver) {
|
|
41
|
+
return workspaceRuntimeServiceExposureEnv(sandboxServiceUrlExposure(driver));
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
sandboxServiceUrlExposure,
|
|
45
|
+
sandboxServiceUrlExposureEnv
|
|
46
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SandboxLeaseStore, SandboxLease, SandboxRegion } from "..";
|
|
2
|
+
export declare function createMemoryLeaseStore(seed?: SandboxLease[]): SandboxLeaseStore;
|
|
3
|
+
export declare function sandboxLease(input: Partial<SandboxLease> & {
|
|
4
|
+
workspaceId: string;
|
|
5
|
+
homeRegion?: SandboxRegion;
|
|
6
|
+
}): SandboxLease;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'module';var require = __createRequire(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
function applySandboxLeasePatch(current, patch, updatedAt) {
|
|
5
|
+
return {
|
|
6
|
+
...current,
|
|
7
|
+
...patch.status === void 0 ? {} : { status: patch.status },
|
|
8
|
+
...patch.sandboxId === void 0 ? {} : { sandboxId: patch.sandboxId },
|
|
9
|
+
...patch.url === void 0 ? {} : { url: patch.url },
|
|
10
|
+
...patch.hostId === void 0 ? {} : { hostId: patch.hostId },
|
|
11
|
+
...patch.driverResourceId === void 0 ? {} : { driverResourceId: patch.driverResourceId },
|
|
12
|
+
...patch.retryCount === void 0 ? {} : { retryCount: patch.retryCount },
|
|
13
|
+
...patch.lastHeartbeatAt === void 0 ? {} : { lastHeartbeatAt: patch.lastHeartbeatAt },
|
|
14
|
+
...patch.lastActivityAt === void 0 ? {} : { lastActivityAt: patch.lastActivityAt },
|
|
15
|
+
...patch.labels === void 0 ? {} : { labels: patch.labels },
|
|
16
|
+
...patch.nextRetryAt === void 0 ? {} : { nextRetryAt: patch.nextRetryAt ?? void 0 },
|
|
17
|
+
...patch.lastError === void 0 ? {} : { lastError: patch.lastError ?? void 0 },
|
|
18
|
+
updatedAt
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/stores/memory.ts
|
|
23
|
+
function createMemoryLeaseStore(seed = []) {
|
|
24
|
+
const leases = new Map(seed.map((lease) => [lease.workspaceId, { ...lease }]));
|
|
25
|
+
return {
|
|
26
|
+
async acquire(workspaceId, input) {
|
|
27
|
+
const now = input.now ?? Date.now();
|
|
28
|
+
const current = leases.get(workspaceId);
|
|
29
|
+
if (current?.status === "ready") {
|
|
30
|
+
return { acquired: false, lease: current, retryAfterMs: 0 };
|
|
31
|
+
}
|
|
32
|
+
if (current?.status === "acquiring" && now - current.updatedAt < input.staleAfterMs) {
|
|
33
|
+
return {
|
|
34
|
+
acquired: false,
|
|
35
|
+
lease: current,
|
|
36
|
+
retryAfterMs: Math.max(0, input.staleAfterMs - (now - current.updatedAt))
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const resumable = current?.status === "stopped";
|
|
40
|
+
const next = {
|
|
41
|
+
workspaceId,
|
|
42
|
+
homeRegion: current?.homeRegion ?? input.homeRegion,
|
|
43
|
+
driver: current?.driver ?? input.driver,
|
|
44
|
+
epoch: (current?.epoch ?? 0) + 1,
|
|
45
|
+
status: "acquiring",
|
|
46
|
+
retryCount: current?.retryCount ?? 0,
|
|
47
|
+
createdAt: current?.createdAt ?? now,
|
|
48
|
+
updatedAt: now,
|
|
49
|
+
sandboxId: resumable ? current.sandboxId : void 0,
|
|
50
|
+
url: resumable ? current.url : void 0,
|
|
51
|
+
hostId: resumable ? current.hostId : void 0,
|
|
52
|
+
driverResourceId: resumable ? current.driverResourceId : void 0,
|
|
53
|
+
lastHeartbeatAt: resumable ? current.lastHeartbeatAt : void 0,
|
|
54
|
+
lastActivityAt: resumable ? current.lastActivityAt : void 0,
|
|
55
|
+
labels: resumable ? current.labels : void 0
|
|
56
|
+
};
|
|
57
|
+
leases.set(workspaceId, next);
|
|
58
|
+
return { acquired: true, lease: next };
|
|
59
|
+
},
|
|
60
|
+
async update(workspaceId, expectedEpoch, patch) {
|
|
61
|
+
const current = leases.get(workspaceId);
|
|
62
|
+
if (!current || current.epoch !== expectedEpoch) return;
|
|
63
|
+
const next = applySandboxLeasePatch(current, patch, Date.now());
|
|
64
|
+
leases.set(workspaceId, next);
|
|
65
|
+
return next;
|
|
66
|
+
},
|
|
67
|
+
async recordFailure(workspaceId, expectedEpoch, error, nextRetryAt) {
|
|
68
|
+
const current = leases.get(workspaceId);
|
|
69
|
+
if (!current || current.epoch !== expectedEpoch) return;
|
|
70
|
+
const next = {
|
|
71
|
+
...current,
|
|
72
|
+
status: "unavailable",
|
|
73
|
+
retryCount: current.retryCount + 1,
|
|
74
|
+
lastError: error,
|
|
75
|
+
nextRetryAt,
|
|
76
|
+
updatedAt: Date.now()
|
|
77
|
+
};
|
|
78
|
+
leases.set(workspaceId, next);
|
|
79
|
+
return next;
|
|
80
|
+
},
|
|
81
|
+
async release(workspaceId) {
|
|
82
|
+
leases.delete(workspaceId);
|
|
83
|
+
},
|
|
84
|
+
async get(workspaceId) {
|
|
85
|
+
const lease = leases.get(workspaceId);
|
|
86
|
+
return lease ? { ...lease, labels: lease.labels ? { ...lease.labels } : void 0 } : void 0;
|
|
87
|
+
},
|
|
88
|
+
async list() {
|
|
89
|
+
return [...leases.values()].map((lease) => ({ ...lease }));
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function sandboxLease(input) {
|
|
94
|
+
return {
|
|
95
|
+
workspaceId: input.workspaceId,
|
|
96
|
+
homeRegion: input.homeRegion ?? "us-east",
|
|
97
|
+
driver: input.driver ?? "test",
|
|
98
|
+
epoch: input.epoch ?? 1,
|
|
99
|
+
status: input.status ?? "ready",
|
|
100
|
+
retryCount: input.retryCount ?? 0,
|
|
101
|
+
createdAt: input.createdAt ?? Date.now(),
|
|
102
|
+
updatedAt: input.updatedAt ?? Date.now(),
|
|
103
|
+
sandboxId: input.sandboxId,
|
|
104
|
+
url: input.url,
|
|
105
|
+
hostId: input.hostId,
|
|
106
|
+
driverResourceId: input.driverResourceId,
|
|
107
|
+
nextRetryAt: input.nextRetryAt,
|
|
108
|
+
lastError: input.lastError,
|
|
109
|
+
lastHeartbeatAt: input.lastHeartbeatAt,
|
|
110
|
+
lastActivityAt: input.lastActivityAt,
|
|
111
|
+
labels: input.labels
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
createMemoryLeaseStore,
|
|
116
|
+
sandboxLease
|
|
117
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@claxedo/sandbox-manager",
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Sandbox lifecycle manager with epoch-based leases and pluggable drivers for Daytona, Modal, Vercel Sandbox, Cloudflare, and Docker",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/kyashrathore/Claxedo.git",
|
|
10
|
+
"directory": "packages/sandbox-manager"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claxedo",
|
|
14
|
+
"sandbox",
|
|
15
|
+
"daytona",
|
|
16
|
+
"modal",
|
|
17
|
+
"agents"
|
|
18
|
+
],
|
|
19
|
+
"main": "./dist/index.mjs",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"bun": "./dist/index.mjs",
|
|
25
|
+
"development": "./dist/index.mjs",
|
|
26
|
+
"import": "./dist/index.mjs",
|
|
27
|
+
"default": "./dist/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"./command": {
|
|
30
|
+
"types": "./dist/command.d.ts",
|
|
31
|
+
"bun": "./dist/command.mjs",
|
|
32
|
+
"development": "./dist/command.mjs",
|
|
33
|
+
"import": "./dist/command.mjs",
|
|
34
|
+
"default": "./dist/command.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./constants": {
|
|
37
|
+
"types": "./dist/constants.d.ts",
|
|
38
|
+
"bun": "./dist/constants.mjs",
|
|
39
|
+
"development": "./dist/constants.mjs",
|
|
40
|
+
"import": "./dist/constants.mjs",
|
|
41
|
+
"default": "./dist/constants.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./defaults": {
|
|
44
|
+
"types": "./dist/defaults.d.ts",
|
|
45
|
+
"bun": "./dist/defaults.mjs",
|
|
46
|
+
"development": "./dist/defaults.mjs",
|
|
47
|
+
"import": "./dist/defaults.mjs",
|
|
48
|
+
"default": "./dist/defaults.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./driver-catalog": {
|
|
51
|
+
"types": "./dist/driver-catalog.d.ts",
|
|
52
|
+
"bun": "./dist/driver-catalog.mjs",
|
|
53
|
+
"development": "./dist/driver-catalog.mjs",
|
|
54
|
+
"import": "./dist/driver-catalog.mjs",
|
|
55
|
+
"default": "./dist/driver-catalog.mjs"
|
|
56
|
+
},
|
|
57
|
+
"./drivers/cloudflare": {
|
|
58
|
+
"types": "./dist/drivers/cloudflare.d.ts",
|
|
59
|
+
"bun": "./dist/drivers/cloudflare.mjs",
|
|
60
|
+
"development": "./dist/drivers/cloudflare.mjs",
|
|
61
|
+
"import": "./dist/drivers/cloudflare.mjs",
|
|
62
|
+
"default": "./dist/drivers/cloudflare.mjs"
|
|
63
|
+
},
|
|
64
|
+
"./drivers/daytona": {
|
|
65
|
+
"types": "./dist/drivers/daytona.d.ts",
|
|
66
|
+
"bun": "./dist/drivers/daytona.mjs",
|
|
67
|
+
"development": "./dist/drivers/daytona.mjs",
|
|
68
|
+
"import": "./dist/drivers/daytona.mjs",
|
|
69
|
+
"default": "./dist/drivers/daytona.mjs"
|
|
70
|
+
},
|
|
71
|
+
"./drivers/docker": {
|
|
72
|
+
"types": "./dist/drivers/docker.d.ts",
|
|
73
|
+
"bun": "./dist/drivers/docker.mjs",
|
|
74
|
+
"development": "./dist/drivers/docker.mjs",
|
|
75
|
+
"import": "./dist/drivers/docker.mjs",
|
|
76
|
+
"default": "./dist/drivers/docker.mjs"
|
|
77
|
+
},
|
|
78
|
+
"./drivers/fetch-bridge": {
|
|
79
|
+
"types": "./dist/drivers/fetch-bridge.d.ts",
|
|
80
|
+
"bun": "./dist/drivers/fetch-bridge.mjs",
|
|
81
|
+
"development": "./dist/drivers/fetch-bridge.mjs",
|
|
82
|
+
"import": "./dist/drivers/fetch-bridge.mjs",
|
|
83
|
+
"default": "./dist/drivers/fetch-bridge.mjs"
|
|
84
|
+
},
|
|
85
|
+
"./drivers/modal": {
|
|
86
|
+
"types": "./dist/drivers/modal.d.ts",
|
|
87
|
+
"bun": "./dist/drivers/modal.mjs",
|
|
88
|
+
"development": "./dist/drivers/modal.mjs",
|
|
89
|
+
"import": "./dist/drivers/modal.mjs",
|
|
90
|
+
"default": "./dist/drivers/modal.mjs"
|
|
91
|
+
},
|
|
92
|
+
"./drivers/vercel": {
|
|
93
|
+
"types": "./dist/drivers/vercel.d.ts",
|
|
94
|
+
"bun": "./dist/drivers/vercel.mjs",
|
|
95
|
+
"development": "./dist/drivers/vercel.mjs",
|
|
96
|
+
"import": "./dist/drivers/vercel.mjs",
|
|
97
|
+
"default": "./dist/drivers/vercel.mjs"
|
|
98
|
+
},
|
|
99
|
+
"./image": {
|
|
100
|
+
"types": "./dist/image.d.ts",
|
|
101
|
+
"bun": "./dist/image.mjs",
|
|
102
|
+
"development": "./dist/image.mjs",
|
|
103
|
+
"import": "./dist/image.mjs",
|
|
104
|
+
"default": "./dist/image.mjs"
|
|
105
|
+
},
|
|
106
|
+
"./lease-policy": {
|
|
107
|
+
"types": "./dist/lease-policy.d.ts",
|
|
108
|
+
"bun": "./dist/lease-policy.mjs",
|
|
109
|
+
"development": "./dist/lease-policy.mjs",
|
|
110
|
+
"import": "./dist/lease-policy.mjs",
|
|
111
|
+
"default": "./dist/lease-policy.mjs"
|
|
112
|
+
},
|
|
113
|
+
"./lease-types": {
|
|
114
|
+
"types": "./dist/lease-types.d.ts",
|
|
115
|
+
"bun": "./dist/lease-types.mjs",
|
|
116
|
+
"development": "./dist/lease-types.mjs",
|
|
117
|
+
"import": "./dist/lease-types.mjs",
|
|
118
|
+
"default": "./dist/lease-types.mjs"
|
|
119
|
+
},
|
|
120
|
+
"./runtime-env": {
|
|
121
|
+
"types": "./dist/runtime-env.d.ts",
|
|
122
|
+
"bun": "./dist/runtime-env.mjs",
|
|
123
|
+
"development": "./dist/runtime-env.mjs",
|
|
124
|
+
"import": "./dist/runtime-env.mjs",
|
|
125
|
+
"default": "./dist/runtime-env.mjs"
|
|
126
|
+
},
|
|
127
|
+
"./service-url-exposure": {
|
|
128
|
+
"types": "./dist/service-url-exposure.d.ts",
|
|
129
|
+
"bun": "./dist/service-url-exposure.mjs",
|
|
130
|
+
"development": "./dist/service-url-exposure.mjs",
|
|
131
|
+
"import": "./dist/service-url-exposure.mjs",
|
|
132
|
+
"default": "./dist/service-url-exposure.mjs"
|
|
133
|
+
},
|
|
134
|
+
"./stores/memory": {
|
|
135
|
+
"types": "./dist/stores/memory.d.ts",
|
|
136
|
+
"bun": "./dist/stores/memory.mjs",
|
|
137
|
+
"development": "./dist/stores/memory.mjs",
|
|
138
|
+
"import": "./dist/stores/memory.mjs",
|
|
139
|
+
"default": "./dist/stores/memory.mjs"
|
|
140
|
+
},
|
|
141
|
+
"./drivers/cloudflare-egress": {
|
|
142
|
+
"types": "./dist/drivers/cloudflare-egress.d.ts",
|
|
143
|
+
"bun": "./dist/drivers/cloudflare-egress.mjs",
|
|
144
|
+
"development": "./dist/drivers/cloudflare-egress.mjs",
|
|
145
|
+
"import": "./dist/drivers/cloudflare-egress.mjs",
|
|
146
|
+
"default": "./dist/drivers/cloudflare-egress.mjs"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"files": [
|
|
150
|
+
"README.md",
|
|
151
|
+
"LICENSE",
|
|
152
|
+
"dist"
|
|
153
|
+
],
|
|
154
|
+
"publishConfig": {
|
|
155
|
+
"access": "public"
|
|
156
|
+
},
|
|
157
|
+
"dependencies": {
|
|
158
|
+
"@claxedo/workspace-runtime": "0.5.1",
|
|
159
|
+
"@daytona/sdk": "0.192.0",
|
|
160
|
+
"@vercel/sandbox": "1.10.2",
|
|
161
|
+
"modal": "0.7.5"
|
|
162
|
+
},
|
|
163
|
+
"scripts": {
|
|
164
|
+
"build": "tsx scripts/build.ts",
|
|
165
|
+
"prepublishOnly": "npm run build",
|
|
166
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
167
|
+
"test": "bun test src"
|
|
168
|
+
},
|
|
169
|
+
"devDependencies": {
|
|
170
|
+
"@tsconfig/node-lts": "22.0.4",
|
|
171
|
+
"@types/bun": "1.3.13",
|
|
172
|
+
"@types/node": "24.12.2",
|
|
173
|
+
"esbuild": "0.25.12",
|
|
174
|
+
"tsx": "4.22.3",
|
|
175
|
+
"typescript": "5.8.2",
|
|
176
|
+
"vitest": "2.1.9"
|
|
177
|
+
}
|
|
178
|
+
}
|