@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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -0
  3. package/dist/command.d.ts +3 -0
  4. package/dist/command.mjs +18 -0
  5. package/dist/constants.d.ts +1 -0
  6. package/dist/constants.mjs +7 -0
  7. package/dist/daytona-allow-list.d.ts +5 -0
  8. package/dist/daytona-allow-list.mjs +9 -0
  9. package/dist/defaults.d.ts +3 -0
  10. package/dist/defaults.mjs +14 -0
  11. package/dist/driver-catalog.d.ts +62 -0
  12. package/dist/driver-catalog.mjs +206 -0
  13. package/dist/drivers/cloudflare-egress.d.ts +40 -0
  14. package/dist/drivers/cloudflare-egress.mjs +115 -0
  15. package/dist/drivers/cloudflare.d.ts +37 -0
  16. package/dist/drivers/cloudflare.mjs +151 -0
  17. package/dist/drivers/daytona.d.ts +94 -0
  18. package/dist/drivers/daytona.mjs +235 -0
  19. package/dist/drivers/docker.d.ts +36 -0
  20. package/dist/drivers/docker.mjs +329 -0
  21. package/dist/drivers/fetch-bridge.d.ts +10 -0
  22. package/dist/drivers/fetch-bridge.mjs +104 -0
  23. package/dist/drivers/modal.d.ts +68 -0
  24. package/dist/drivers/modal.mjs +227 -0
  25. package/dist/drivers/vercel.d.ts +109 -0
  26. package/dist/drivers/vercel.mjs +297 -0
  27. package/dist/image-name.d.ts +7 -0
  28. package/dist/image.d.ts +8 -0
  29. package/dist/image.mjs +124 -0
  30. package/dist/index.d.ts +316 -0
  31. package/dist/index.mjs +330 -0
  32. package/dist/lease-policy.d.ts +49 -0
  33. package/dist/lease-policy.mjs +126 -0
  34. package/dist/lease-types.d.ts +89 -0
  35. package/dist/lease-types.mjs +1 -0
  36. package/dist/runtime-env.d.ts +24 -0
  37. package/dist/runtime-env.mjs +35 -0
  38. package/dist/runtime-version.d.ts +1 -0
  39. package/dist/runtime-version.mjs +24 -0
  40. package/dist/service-url-exposure.d.ts +10 -0
  41. package/dist/service-url-exposure.mjs +46 -0
  42. package/dist/stores/memory.d.ts +6 -0
  43. package/dist/stores/memory.mjs +117 -0
  44. 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
+ }