@claxedo/sandbox-manager 0.10.1 → 0.10.3

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 (42) hide show
  1. package/README.md +100 -30
  2. package/dist/checkpoint-manager.mjs +19 -0
  3. package/dist/contract.d.ts +40 -17
  4. package/dist/driver-billing.d.ts +23 -0
  5. package/dist/driver-catalog.mjs +57 -3
  6. package/dist/driver-ensure-input.d.ts +22 -0
  7. package/dist/drivers/agent37-client.d.ts +87 -0
  8. package/dist/drivers/agent37.d.ts +25 -0
  9. package/dist/drivers/agent37.mjs +888 -0
  10. package/dist/drivers/boat-client.d.ts +4 -4
  11. package/dist/drivers/boat-machine.d.ts +80 -0
  12. package/dist/drivers/boat-preparation.test-support.d.ts +2 -0
  13. package/dist/drivers/boat-template.mjs +196 -92
  14. package/dist/drivers/boat.d.ts +0 -17
  15. package/dist/drivers/boat.mjs +200 -108
  16. package/dist/drivers/cloudflare.d.ts +5 -9
  17. package/dist/drivers/cloudflare.mjs +71 -7
  18. package/dist/drivers/docker.mjs +57 -2
  19. package/dist/drivers/local-brokering.d.ts +12 -0
  20. package/dist/drivers/local-brokering.mjs +99 -24
  21. package/dist/drivers/modal.mjs +57 -2
  22. package/dist/drivers/transient-error.d.ts +0 -1
  23. package/dist/drivers/vercel.mjs +61 -3
  24. package/dist/egress-policy.d.ts +33 -32
  25. package/dist/egress-warnings.d.ts +4 -6
  26. package/dist/hosted-network-policy.d.ts +10 -64
  27. package/dist/hosted-network-policy.mjs +1 -1
  28. package/dist/image-name.d.ts +0 -1
  29. package/dist/image-name.mjs +5 -0
  30. package/dist/image.d.ts +1 -0
  31. package/dist/image.mjs +6 -0
  32. package/dist/index.mjs +180 -112
  33. package/dist/json.d.ts +1 -10
  34. package/dist/lease-failure.d.ts +20 -1
  35. package/dist/lease-types.d.ts +1 -10
  36. package/dist/runtime-env.d.ts +6 -0
  37. package/dist/runtime-env.mjs +5 -0
  38. package/dist/runtime-version.d.ts +25 -7
  39. package/dist/runtime-version.mjs +13 -2
  40. package/dist/start-admission.d.ts +32 -0
  41. package/dist/start-telemetry.d.ts +5 -3
  42. package/package.json +12 -4
@@ -73,6 +73,11 @@ var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
73
73
  function workspaceRuntimeVersion() {
74
74
  return process.env.WORKSPACE_RUNTIME_VERSION || DEFAULT_WORKSPACE_RUNTIME_VERSION;
75
75
  }
76
+ var SERVED_WORKSPACE_RUNTIME_FLOOR = {
77
+ version: "0.10.1",
78
+ image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
79
+ };
80
+ var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
76
81
 
77
82
  // src/command.ts
78
83
  function shell(input) {
@@ -96,6 +101,27 @@ var boatBilling = {
96
101
  large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
97
102
  }
98
103
  };
104
+ var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
105
+ var AGENT37_MONTH_HOURS = 730;
106
+ var agent37MachineShapes = {
107
+ small: { cpu: 2, memory: 4, disk: 10 },
108
+ default: { cpu: 4, memory: 8, disk: 20 },
109
+ large: { cpu: 4, memory: 16, disk: 40 }
110
+ };
111
+ function agent37Rate(shape) {
112
+ const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
113
+ return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
114
+ }
115
+ var agent37Billing = {
116
+ source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
117
+ meter: "Agent37 meters an instance per minute at a monthly rate over 730 hours: $0.80 per vCPU, $0.70 per GB of memory and $0.09 per GB of disk while it runs, and the disk alone while it is stopped.",
118
+ rates: {
119
+ small: agent37Rate(agent37MachineShapes.small),
120
+ default: agent37Rate(agent37MachineShapes.default),
121
+ large: agent37Rate(agent37MachineShapes.large)
122
+ },
123
+ excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
124
+ };
99
125
  var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
100
126
  var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
101
127
  var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
@@ -130,6 +156,7 @@ var sandboxDriverCredentialFields = {
130
156
  { key: "worker_url", label: "Worker URL" }
131
157
  ],
132
158
  boat: [{ key: "api_key", label: "API Key", secret: true }],
159
+ agent37: [{ key: "api_key", label: "API Key", secret: true }],
133
160
  docker: [{ key: "image", label: "Image" }]
134
161
  };
135
162
  var sandboxDriverLabels = {
@@ -137,6 +164,7 @@ var sandboxDriverLabels = {
137
164
  vercel: "Vercel",
138
165
  cloudflare: "Cloudflare",
139
166
  boat: "Boat",
167
+ agent37: "Agent37",
140
168
  docker: "Docker"
141
169
  };
142
170
 
@@ -207,8 +235,8 @@ var sandboxDriverCatalog = {
207
235
  hostWatchesIdle: true,
208
236
  targetAccess: "relay",
209
237
  secretBrokering: "native",
210
- // Credential handlers do not restrict unrelated destinations.
211
- egressControl: "none",
238
+ // The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
239
+ egressControl: "hosts",
212
240
  // A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
213
241
  persistence: {
214
242
  resume: "replacement-restore",
@@ -246,6 +274,33 @@ var sandboxDriverCatalog = {
246
274
  machineClasses: ["small", "default", "large"]
247
275
  }
248
276
  },
277
+ agent37: {
278
+ id: "agent37",
279
+ label: sandboxDriverLabels.agent37,
280
+ credentialFields: sandboxDriverCredentialFields.agent37,
281
+ runtimeNetwork: { controlPlane: "direct", relay: "configured" },
282
+ runtimeEnv: "callback",
283
+ preparedImage: true,
284
+ billing: agent37Billing,
285
+ metadata: {
286
+ driverRunsIn: ["worker", "node"],
287
+ hostStopBehavior: "suspends-host",
288
+ hostResumeBehavior: "same-host",
289
+ targetAccess: "relay",
290
+ secretBrokering: "none",
291
+ // An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
292
+ egressControl: "hosts-and-cidrs",
293
+ persistence: {
294
+ resume: "same-sandbox",
295
+ capture: "none",
296
+ clone: false,
297
+ captureSource: "not-applicable",
298
+ retention: "provider-managed",
299
+ restoreMount: "same-resource"
300
+ },
301
+ machineClasses: ["small", "default", "large"]
302
+ }
303
+ },
249
304
  docker: {
250
305
  id: "docker",
251
306
  label: sandboxDriverLabels.docker,
@@ -487,17 +542,20 @@ function createVercelSandboxDriver(options) {
487
542
  "curl https://cursor.com/install -fsS | bash",
488
543
  "curl -fsSL https://ampcode.com/install.sh | bash",
489
544
  "curl -fsSL https://app.factory.ai/cli | sh",
545
+ "curl -fsSL https://antigravity.google/cli/install.sh | bash",
490
546
  "sudo ln -sf $HOME/.local/bin/agent /usr/local/bin/agent",
491
547
  "sudo ln -sf $HOME/.local/bin/cursor-agent /usr/local/bin/cursor-agent",
492
548
  "sudo ln -sf $HOME/.local/bin/amp /usr/local/bin/amp",
493
549
  "sudo ln -sf $HOME/.local/bin/droid /usr/local/bin/droid",
550
+ "sudo ln -sf $HOME/.local/bin/agy /usr/local/bin/agy",
494
551
  "command -v opencode",
495
552
  "command -v claude",
496
553
  "command -v codex",
497
554
  "command -v agent",
498
555
  "command -v cursor-agent",
499
556
  "command -v amp",
500
- "command -v droid"
557
+ "command -v droid",
558
+ "command -v agy"
501
559
  ].join(" && "));
502
560
  await runSetup(builder, [
503
561
  `sudo mkdir -p ${shell(RUNTIME_DIR)}`,
@@ -8,26 +8,32 @@ export declare function sandboxNetworkPolicyWithBrokeredHosts(policy: SandboxNet
8
8
  /** @see SandboxDriverMetadata.egressControl */
9
9
  export type SandboxEgressControl = "none" | "hosts" | "hosts-and-cidrs";
10
10
  /**
11
- * What the manager does with a caller's `net` for a given driver: enforce
12
- * where the driver can, and say so loudly rather than refuse where it cannot.
11
+ * What a start does with a restricted policy on a driver that cannot contain
12
+ * egress: `"refuse"` the start, or `"allow"` the sandbox to run with the policy
13
+ * withheld and the gap reported. Refusing is the default; allowing is the
14
+ * workspace owner's explicit, auditable decision.
15
+ */
16
+ export type SandboxUncontainedEgress = "refuse" | "allow";
17
+ /**
18
+ * What the manager does with a caller's `net` for a given driver.
13
19
  *
14
20
  * - `"enforce"` — the driver gets the policy verbatim and contains the
15
21
  * sandbox. Also the answer when the caller asked for no containment
16
22
  * (absent / `allow-all`), which is nothing to enforce.
17
- * - `"withhold"` — the driver declares `egressControl: "none"`, so there is no
18
- * containment to be had. The policy is NOT handed down: half the `"none"`
19
- * drivers throw on a restricted policy (docker, modal, boat) and the
20
- * other half silently drop it (cloudflare, the fetch bridge). Withholding at
21
- * the manager means the throwing drivers never see one — their throws stay
22
- * in place as their own last line of defence — and the silently-dropping
23
- * ones stop pretending. The sandbox comes up with UNRESTRICTED egress, which
24
- * is a real exposure, so the manager warns (see `onEgressUnenforced`).
25
- * - `"refuse"` — the driver HAS egress control but cannot express this
26
- * particular policy's encoding (a hosts-only driver handed an address-only
27
- * allowlist). Deliberately still fail-closed: this is a composition mistake
28
- * on an otherwise-enforcing driver, and degrading it to "withhold" would
29
- * weaken the enforcing path. `hostedSandboxNetworkPolicy` only ever emits
30
- * hosts, so no production path reaches it.
23
+ * - `"withhold"` — the driver declares `egressControl: "none"` and the
24
+ * start allows uncontained egress. The policy is NOT handed down: the
25
+ * `"none"` drivers throw on a restricted policy (docker, modal, boat), so
26
+ * withholding at the manager keeps their throws as their own last line of
27
+ * defence. The sandbox comes up with UNRESTRICTED egress, which is a real
28
+ * exposure, so the manager warns (see `onEgressUnenforced`).
29
+ * - `"refuse"` — either the driver declares `egressControl: "none"` and the
30
+ * start does not allow uncontained egress (`sandbox_egress_uncontained`,
31
+ * the default), or the driver HAS egress control but cannot express this
32
+ * particular policy's encoding (`sandbox_egress_policy_unenforceable`: a
33
+ * hosts-only driver handed an address-only allowlist). The second is a
34
+ * composition mistake on an otherwise-enforcing driver; degrading it to
35
+ * "withhold" would weaken the enforcing path, and `hostedSandboxNetworkPolicy`
36
+ * only ever emits hosts, so no production path reaches it.
31
37
  *
32
38
  * Pure, like `validateSandboxPersistenceCapabilities`, so the manager, the
33
39
  * composition layer, and tests can all ask the same question.
@@ -39,22 +45,18 @@ export type SandboxEgressDisposition = {
39
45
  reason: "sandbox_egress_uncontained";
40
46
  } | {
41
47
  action: "refuse";
42
- reason: "sandbox_egress_policy_unenforceable";
48
+ reason: "sandbox_egress_uncontained" | "sandbox_egress_policy_unenforceable";
43
49
  };
44
50
  /** @see SandboxEgressDisposition */
45
- export declare function sandboxEgressDisposition(control: SandboxEgressControl, net: SandboxNetworkPolicy | undefined): SandboxEgressDisposition;
51
+ export declare function sandboxEgressDisposition(control: SandboxEgressControl, net: SandboxNetworkPolicy | undefined, uncontained?: SandboxUncontainedEgress): SandboxEgressDisposition;
46
52
  /**
47
- * Emitted whenever a restricted egress policy is withheld because the composed
48
- * driver declares no egress control: an unrestricted sandbox that nobody was
49
- * told about is the exposure, so the degrade is never silent.
50
- *
51
- * Two phases, because a per-create line is easy to miss in request logs:
52
- * - `"composition"` — once per `createSandboxManager` per driver, at boot.
53
- * - `"ensure"` — every time a caller's policy is actually withheld, naming the
54
- * workspace and the allowlist that did not take effect.
53
+ * Emitted the first time per driver per isolate that a start which allows
54
+ * uncontained egress has its restricted policy withheld because the driver
55
+ * declares no egress control: an unrestricted sandbox that nobody was told
56
+ * about is the exposure, so the degrade is never silent. A start that refuses
57
+ * uncontained egress emits none: it never runs.
55
58
  */
56
59
  export type SandboxEgressUnenforcedEvent = {
57
- phase: "composition" | "ensure";
58
60
  reason: "sandbox_egress_uncontained";
59
61
  /** `SandboxDriver.id` of the composed driver. */
60
62
  driver: string;
@@ -62,12 +64,11 @@ export type SandboxEgressUnenforcedEvent = {
62
64
  egressControl: SandboxEgressControl;
63
65
  /** Ready-to-log sentence. Sinks that only forward text can use this alone. */
64
66
  message: string;
65
- /** Present on `"ensure"`. */
66
- workspaceId?: string;
67
- /** The start's placement labels. Present on `"ensure"`. */
67
+ workspaceId: string;
68
+ /** The start's placement labels. */
68
69
  labels?: Record<string, string>;
69
- /** The allowlist the caller asked for and did NOT get. Present on `"ensure"`. */
70
- requested?: SandboxNetworkPolicy;
70
+ /** The allowlist the caller asked for and did NOT get. */
71
+ requested: SandboxNetworkPolicy;
71
72
  };
72
73
  /**
73
74
  * A credential the SANDBOX must be able to USE for outbound requests but must
@@ -1,11 +1,8 @@
1
1
  import type { SandboxEgressControl, SandboxEgressUnenforcedEvent, SandboxNetworkPolicy } from "./egress-policy";
2
2
  /**
3
- * The two halves of the warning that a driver runs sandboxes with unrestricted
4
- * egress. The composition half is raised here, once per driver per isolate: a
5
- * per-create line lands in request logs and is easy to miss, this one lands
6
- * wherever the process starts, so an operator learns of it BEFORE the first
7
- * workspace exists. `withheld` is the start half, raised once per driver per
8
- * isolate from the first start whose policy the driver could not enforce.
3
+ * The warning that a start runs with unrestricted egress, raised once per
4
+ * driver per isolate from the first start whose policy the driver could not
5
+ * enforce. A refused start raises none: its refusal is that start's own answer.
9
6
  */
10
7
  export declare function createEgressWarnings(input: {
11
8
  driver: {
@@ -20,3 +17,4 @@ export declare function createEgressWarnings(input: {
20
17
  requested: SandboxNetworkPolicy;
21
18
  }): void;
22
19
  };
20
+ export type EgressWarnings = ReturnType<typeof createEgressWarnings>;
@@ -1,67 +1,17 @@
1
- /**
2
- * The egress allowlist a HOSTED, multi-tenant sandbox is provisioned with.
3
- *
4
- * A hosted sandbox runs agent-authored code on the operator's infrastructure,
5
- * next to other tenants' sandboxes, holding a checkout of the user's private
6
- * repository and (via `SandboxBrokeredSecret`) the ability to spend the
7
- * operator's model credits. The default for that shape of workload is
8
- * restrictive, not allow-all: the interesting attack is not "the agent
9
- * downloads a package", it is "the agent POSTs the repository to a host the
10
- * attacker controls". An allowlist is what makes that fail.
11
- *
12
- * Every entry below has to earn its place, so the list is assembled from three
13
- * sources of truth rather than from taste:
14
- *
15
- * 1. DERIVED PER REQUEST — the control plane the sandbox reports back to and
16
- * the git host it clones from. These differ per deployment and per
17
- * workspace, so they are inputs, not constants.
18
- * 2. MODEL PROVIDERS — the endpoints an agent harness must reach to do any
19
- * work at all. Taken from the harness→provider mapping the credential
20
- * layer already maintains (`PROVIDER_TO_GROUP` /`DEFAULT_ALLOWLIST` in
21
- * claxedo-server's `network/types.ts`), narrowed to the API hostnames.
22
- * 3. PACKAGE REGISTRIES — an agent that cannot install a dependency cannot
23
- * edit a real repository. Same source, again narrowed.
24
- *
25
- * What is deliberately NOT here, despite being in that same default list:
26
- * general-purpose object storage and CDN wildcards (`*.workers.dev`,
27
- * `r2.cloudflarestorage.com`, `storage.googleapis.com`,
28
- * `*.blob.core.windows.net`, `*.amazonaws.com`). Every one of those is a
29
- * bucket an attacker can create in their own account, so allowlisting them
30
- * hands back exactly the exfiltration channel the policy exists to close. A
31
- * deployment that genuinely needs one adds it through `extraHosts` as an
32
- * explicit, auditable decision.
33
- *
34
- * This module is data + string handling only, so it runs unchanged inside the
35
- * hosted Worker (no DNS, no node builtins). That matters: name-based policy is
36
- * the only kind the Worker can compute, which is why `egressControl` treats
37
- * name filtering as the capability that qualifies a driver for hosted use.
38
- */
39
1
  import type { SandboxSource } from "./contract";
40
2
  import type { SandboxNetworkPolicy } from "./egress-policy";
41
- /**
42
- * Model-provider endpoints. Derived from the harness→provider groups in
43
- * claxedo-server `network/types.ts` (`PROVIDER_TO_GROUP`): claude-sdk →
44
- * anthropic, codex-app-server/cursor-sdk → openai,
45
- * google → google_ai; plus the aggregator and catalog endpoints the engine
46
- * itself fetches at startup.
47
- */
48
3
  export declare const SANDBOX_MODEL_PROVIDER_HOSTS: readonly ["api.anthropic.com", "api.openai.com", "generativelanguage.googleapis.com", "openrouter.ai", "models.dev", "opencode.ai"];
49
4
  /**
50
- * Package registries. Narrowed from the npm / pypi / rust / golang groups of
51
- * `DEFAULT_ALLOWLIST` to the hostnames a package install actually contacts —
52
- * the wildcard CDN entries in those groups are excluded on purpose (see the
53
- * module comment).
5
+ * Object-storage and CDN wildcards (`*.workers.dev`, `*.amazonaws.com`,
6
+ * `storage.googleapis.com`) stay out: each is a bucket an attacker can create
7
+ * in their own account, which reopens the exfiltration channel the allowlist
8
+ * closes. A deployment that needs one adds it through `extraHosts`.
54
9
  */
55
10
  export declare const SANDBOX_PACKAGE_REGISTRY_HOSTS: readonly ["registry.npmjs.org", "nodejs.org", "pypi.org", "files.pythonhosted.org", "crates.io", "static.crates.io", "index.crates.io", "proxy.golang.org", "sum.golang.org"];
56
- /** The deployment-independent floor: providers + registries. */
57
11
  export declare const SANDBOX_BASELINE_EGRESS_HOSTS: readonly ["api.anthropic.com", "api.openai.com", "generativelanguage.googleapis.com", "openrouter.ai", "models.dev", "opencode.ai", "registry.npmjs.org", "nodejs.org", "pypi.org", "files.pythonhosted.org", "crates.io", "static.crates.io", "index.crates.io", "proxy.golang.org", "sum.golang.org"];
58
12
  /**
59
- * The git host this workspace clones from.
60
- *
61
- * Scoped to the ONE repository host in the request rather than to a forge
62
- * allowlist, matching how `githubCloneSecret` scopes the clone
63
- * credential it brokers (`hosts: ["github.com"]`) — the credential and the
64
- * network policy should describe the same reachable surface.
13
+ * The one repository host the request clones from, matching the hosts the
14
+ * brokered clone credential is scoped to.
65
15
  *
66
16
  * The host is caller-selected, so only a public spelling earns an allowlist
67
17
  * entry: `169.254.169.254` or `localhost` named as a repoUrl would otherwise
@@ -78,17 +28,13 @@ export type HostedSandboxNetworkPolicyInput = {
78
28
  * plus register/heartbeat. URLs or bare hostnames; blanks are ignored.
79
29
  */
80
30
  controlPlane: Array<string | undefined>;
81
- /** Workspace source — its git host is allowed, nothing else on that forge. */
31
+ /** Its git host is allowed, nothing else on that forge. */
82
32
  source?: SandboxSource;
83
- /** Operator escape hatch for deployment-specific hosts. */
84
33
  extraHosts?: readonly string[];
85
34
  };
86
35
  /**
87
- * Build the restricted policy for a hosted sandbox.
88
- *
89
- * Always `mode: "restricted"`. There is no input that makes this return
90
- * allow-all — a hosted sandbox with an empty or unresolvable control-plane URL
91
- * is a misconfiguration, and answering it with "then allow everything" is how
92
- * the gap this closes came to exist in the first place.
36
+ * Always `mode: "restricted"`: a hosted sandbox with an empty or unresolvable
37
+ * control-plane URL is a misconfiguration, never a reason to allow everything.
38
+ * Name-based only (no DNS), so it also runs inside the Worker.
93
39
  */
94
40
  export declare function hostedSandboxNetworkPolicy(input: HostedSandboxNetworkPolicyInput): SandboxNetworkPolicy;
@@ -221,7 +221,7 @@ var SANDBOX_MODEL_PROVIDER_HOSTS = [
221
221
  "api.openai.com",
222
222
  "generativelanguage.googleapis.com",
223
223
  "openrouter.ai",
224
- // Model catalog + engine config, fetched on runner startup.
224
+ // The model catalog and engine config a runner fetches at startup.
225
225
  "models.dev",
226
226
  "opencode.ai"
227
227
  ];
@@ -13,5 +13,4 @@ export declare function sandboxImageRepository(env?: SandboxImageEnv): string;
13
13
  export declare function defaultSandboxImage(version?: string, buildId?: string, env?: SandboxImageEnv, options?: {
14
14
  agentPlugins?: boolean;
15
15
  }): string;
16
- /** Whether an image's tag names a build that carries the Agent Plugins runtime entry. */
17
16
  export declare function sandboxImageCarriesAgentPlugins(image: string): boolean;
@@ -3,6 +3,11 @@ var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
3
3
  function workspaceRuntimeVersion() {
4
4
  return process.env.WORKSPACE_RUNTIME_VERSION || DEFAULT_WORKSPACE_RUNTIME_VERSION;
5
5
  }
6
+ var SERVED_WORKSPACE_RUNTIME_FLOOR = {
7
+ version: "0.10.1",
8
+ image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
9
+ };
10
+ var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
6
11
 
7
12
  // src/image-name.ts
8
13
  var SNAPSHOT_SCHEMA_VERSION = 8;
package/dist/image.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { RUNTIME_DIR, WORKSPACE_RUNTIME_PORT, WORKSPACE_DIR } from "./defaults";
2
2
  export { SNAPSHOT_SCHEMA_VERSION, snapshotVersion, assertSandboxImageReference, defaultSandboxImage, } from "./image-name";
3
+ export { SERVED_WORKSPACE_RUNTIME_FLOOR } from "./runtime-version";
3
4
  export declare const SANDBOX_IMAGE_REPOSITORY: string;
4
5
  export declare const SANDBOX_IMAGE: string;
package/dist/image.mjs CHANGED
@@ -11,6 +11,11 @@ var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
11
11
  function workspaceRuntimeVersion() {
12
12
  return process.env.WORKSPACE_RUNTIME_VERSION || DEFAULT_WORKSPACE_RUNTIME_VERSION;
13
13
  }
14
+ var SERVED_WORKSPACE_RUNTIME_FLOOR = {
15
+ version: "0.10.1",
16
+ image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
17
+ };
18
+ var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
14
19
 
15
20
  // src/image-name.ts
16
21
  var SNAPSHOT_SCHEMA_VERSION = 8;
@@ -45,6 +50,7 @@ export {
45
50
  RUNTIME_DIR,
46
51
  SANDBOX_IMAGE,
47
52
  SANDBOX_IMAGE_REPOSITORY,
53
+ SERVED_WORKSPACE_RUNTIME_FLOOR,
48
54
  SNAPSHOT_SCHEMA_VERSION,
49
55
  WORKSPACE_DIR,
50
56
  WORKSPACE_RUNTIME_PORT,