@agentproto/sandbox 0.6.1 → 0.7.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.
@@ -6,7 +6,7 @@ import { createDoctype } from '@agentproto/define-doctype';
6
6
  * AIP-36 SANDBOX.md `defineSandbox` reference implementation.
7
7
  */
8
8
 
9
- var sandboxFrontmatterSchema = z.object({ "schema": z.literal("sandbox/v1").describe("Standalone-only. Identifies the doctype + version. Absent when the block is inlined.").optional(), "id": z.string().regex(new RegExp("^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$")).describe("Standalone-only. Globally addressable id `@<owner-slug>/<sandbox-slug>`.").optional(), "version": z.string().regex(new RegExp("^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.\\-]+)?$")).describe("Standalone-only. Spec version of THIS file.").optional(), "provider": z.string().min(1).describe("Backend kind. Day-1 enumerated set: local | mastra-e2b | mastra-modal | mastra-daytona | mastra-blaxel | node-permission. Hosts MAY register additional ids."), "config": z.object({ "installAdapters": z.array(z.string().min(1)).describe(`Semantic harness slugs to pre-install in the box at boot (e.g. ["hermes", "claude-code"]). Each expands to @agentproto/adapter-<slug>@latest plus that adapter's declared boot extras; a config.installPackages pin for the same package always wins. Additive \u2014 absent means no extra install.`).optional() }).catchall(z.any()).describe("Provider-specific connection fields. Shape varies per provider (see AIP-36 \xA7Provider config shapes)."), "limits": z.object({ "timeout_ms": z.number().int().gte(1).optional(), "memory_mb": z.number().int().gte(1).optional(), "cpu_ms": z.number().int().gte(1).optional() }).strict().describe("Resource caps per command.").optional(), "env": z.object({ "auth": z.any().optional(), "passthrough": z.array(z.string()).describe("Static host env-var names to forward into the sandbox.").default([]), "autoPassthrough": z.boolean().describe("Opt-in: forward the spawn's resolved billing-credential env-var NAME (e.g. ANTHROPIC_API_KEY) into passthrough so a fresh box inherits host auth without the caller naming vars. Only the name is injected \u2014 the value travels via the normal passthrough mechanism.").optional() }).strict().optional(), "network": z.object({ "egress": z.array(z.string()).describe("Hostnames the sandbox MAY reach. Empty / missing = no egress.").default([]) }).strict().optional(), "mounts": z.array(z.any()).describe("Filesystems mounted inside the sandbox at declared paths. Maps to Mastra Workspace.mounts.").default([]), "identity": z.any().describe("AIP-23 identity-ref \u2014 owner of the sandbox processes.").optional(), "policy": z.any().describe("AIP-38 POLICY block \u2014 access grants on sandbox actions.").optional(), "lifecycle": z.object({ "pause_after_idle": z.string().min(1).describe("AIP-37 event name (e.g. `idle-600` for 10 min). Provider-supported only (modal, daytona).").optional(), "destroy_on": z.string().min(1).describe("AIP-37 event name (e.g. `workspace-close`).").optional() }).strict().optional(), "read_only": z.boolean().describe("Reject command execution at the sandbox layer. Read-only sandbox calls fail with `sandbox_read_only`.").default(false), "extraPorts": z.array(z.number().int().gte(1)).describe("App ports to expose at boot time. Resolved into BootedSandbox.ports (port \u2192 public URL) by providers that support port exposure.").optional(), "metadata": z.record(z.string(), z.any()).describe("Free-form, namespaced. Adapter hints under `metadata.<adapter>.*`.").optional() }).strict().describe("Validates the YAML frontmatter portion of an AIP-36 SANDBOX.md manifest, OR the inline form embedded in any other manifest's `sandbox:` block. Compute-only \u2014 durable filesystem backings live in AIP-35 STORAGE.md.");
9
+ var sandboxFrontmatterSchema = z.object({ "schema": z.literal("sandbox/v1").describe("Standalone-only. Identifies the doctype + version. Absent when the block is inlined.").optional(), "id": z.string().regex(new RegExp("^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$")).describe("Standalone-only. Globally addressable id `@<owner-slug>/<sandbox-slug>`.").optional(), "version": z.string().regex(new RegExp("^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.\\-]+)?$")).describe("Standalone-only. Spec version of THIS file.").optional(), "provider": z.string().min(1).describe("Backend kind. Day-1 enumerated set: local | mastra-e2b | mastra-modal | mastra-daytona | mastra-blaxel | node-permission. Hosts MAY register additional ids."), "config": z.object({ "installAdapters": z.array(z.string().min(1)).describe(`Semantic harness slugs to pre-install in the box at boot (e.g. ["hermes", "claude-code"]). Each expands to @agentproto/adapter-<slug>@latest plus that adapter's declared boot extras; a config.installPackages pin for the same package always wins. Additive \u2014 absent means no extra install.`).optional() }).catchall(z.any()).describe("Provider-specific connection fields. Shape varies per provider (see AIP-36 \xA7Provider config shapes)."), "limits": z.object({ "timeout_ms": z.number().int().gte(1).optional(), "memory_mb": z.number().int().gte(1).optional(), "cpu_ms": z.number().int().gte(1).optional() }).strict().describe("Resource caps per command.").optional(), "env": z.object({ "auth": z.any().optional(), "passthrough": z.array(z.string()).describe("Static host env-var names to forward into the sandbox.").default([]), "autoPassthrough": z.boolean().describe("Opt-in: forward the spawn's resolved billing-credential env-var NAME (e.g. ANTHROPIC_API_KEY) into passthrough so a fresh box inherits host auth without the caller naming vars. Only the name is injected \u2014 the value travels via the normal passthrough mechanism.").optional() }).strict().optional(), "network": z.object({ "egress": z.array(z.string()).describe("Hostnames the sandbox MAY reach. Empty / missing = no egress.").default([]) }).strict().optional(), "join": z.object({ "tokenEnv": z.string().min(1).describe("Name of a host env var whose value (a join-token URL) should be forwarded into the sandbox under the SAME name at boot, so the box can auto-register with the daemon that minted the token. Equivalent to adding that name to env.passthrough \u2014 provided as a distinct, self-documenting field because its purpose (auto-join) is different from an arbitrary forwarded secret. Absent/no-op when the named host env var isn't actually set (e.g. a fork's CI run with no AGENTPROTO_JOIN secret) \u2014 never fails the boot.") }).strict().describe("Auto-join wiring: forwards a host env var (holding a join-token URL) into the sandbox by the same name, so the box can register itself with the daemon that minted the token.").optional(), "mounts": z.array(z.any()).describe("Filesystems mounted inside the sandbox at declared paths. Maps to Mastra Workspace.mounts.").default([]), "identity": z.any().describe("AIP-23 identity-ref \u2014 owner of the sandbox processes.").optional(), "policy": z.any().describe("AIP-38 POLICY block \u2014 access grants on sandbox actions.").optional(), "lifecycle": z.object({ "pause_after_idle": z.string().min(1).describe("AIP-37 event name (e.g. `idle-600` for 10 min). Provider-supported only (modal, daytona).").optional(), "destroy_on": z.string().min(1).describe("AIP-37 event name (e.g. `workspace-close`).").optional() }).strict().optional(), "read_only": z.boolean().describe("Reject command execution at the sandbox layer. Read-only sandbox calls fail with `sandbox_read_only`.").default(false), "extraPorts": z.array(z.number().int().gte(1)).describe("App ports to expose at boot time. Resolved into BootedSandbox.ports (port \u2192 public URL) by providers that support port exposure.").optional(), "metadata": z.record(z.string(), z.any()).describe("Free-form, namespaced. Adapter hints under `metadata.<adapter>.*`.").optional() }).strict().describe("Validates the YAML frontmatter portion of an AIP-36 SANDBOX.md manifest, OR the inline form embedded in any other manifest's `sandbox:` block. Compute-only \u2014 durable filesystem backings live in AIP-35 STORAGE.md.");
10
10
  var defineSandboxInner = createDoctype({
11
11
  aip: 36,
12
12
  name: "sandbox",
@@ -43,5 +43,5 @@ function defineSandbox(definition) {
43
43
  }
44
44
 
45
45
  export { defineSandbox, sandboxFrontmatterSchema };
46
- //# sourceMappingURL=chunk-VGEBUSSP.mjs.map
47
- //# sourceMappingURL=chunk-VGEBUSSP.mjs.map
46
+ //# sourceMappingURL=chunk-JEUFE7GR.mjs.map
47
+ //# sourceMappingURL=chunk-JEUFE7GR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/define-sandbox.ts"],"names":[],"mappings":"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","file":"chunk-JEUFE7GR.mjs","sourcesContent":["/**\n * AIP-36 SANDBOX.md frontmatter zod schema.\n *\n * Generated from `resources/aip-36/draft/SANDBOX.schema.json` via\n * json-schema-to-zod. Imported by both `define-sandbox.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-sandbox.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const sandboxFrontmatterSchema = z.object({ \"schema\": z.literal(\"sandbox/v1\").describe(\"Standalone-only. Identifies the doctype + version. Absent when the block is inlined.\").optional(), \"id\": z.string().regex(new RegExp(\"^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$\")).describe(\"Standalone-only. Globally addressable id `@<owner-slug>/<sandbox-slug>`.\").optional(), \"version\": z.string().regex(new RegExp(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+(?:[-+][\\\\w.\\\\-]+)?$\")).describe(\"Standalone-only. Spec version of THIS file.\").optional(), \"provider\": z.string().min(1).describe(\"Backend kind. Day-1 enumerated set: local | mastra-e2b | mastra-modal | mastra-daytona | mastra-blaxel | node-permission. Hosts MAY register additional ids.\"), \"config\": z.object({ \"installAdapters\": z.array(z.string().min(1)).describe(\"Semantic harness slugs to pre-install in the box at boot (e.g. [\\\"hermes\\\", \\\"claude-code\\\"]). Each expands to @agentproto/adapter-<slug>@latest plus that adapter's declared boot extras; a config.installPackages pin for the same package always wins. Additive — absent means no extra install.\").optional() }).catchall(z.any()).describe(\"Provider-specific connection fields. Shape varies per provider (see AIP-36 §Provider config shapes).\"), \"limits\": z.object({ \"timeout_ms\": z.number().int().gte(1).optional(), \"memory_mb\": z.number().int().gte(1).optional(), \"cpu_ms\": z.number().int().gte(1).optional() }).strict().describe(\"Resource caps per command.\").optional(), \"env\": z.object({ \"auth\": z.any().optional(), \"passthrough\": z.array(z.string()).describe(\"Static host env-var names to forward into the sandbox.\").default([] as never), \"autoPassthrough\": z.boolean().describe(\"Opt-in: forward the spawn's resolved billing-credential env-var NAME (e.g. ANTHROPIC_API_KEY) into passthrough so a fresh box inherits host auth without the caller naming vars. Only the name is injected — the value travels via the normal passthrough mechanism.\").optional() }).strict().optional(), \"network\": z.object({ \"egress\": z.array(z.string()).describe(\"Hostnames the sandbox MAY reach. Empty / missing = no egress.\").default([] as never) }).strict().optional(), \"join\": z.object({ \"tokenEnv\": z.string().min(1).describe(\"Name of a host env var whose value (a join-token URL) should be forwarded into the sandbox under the SAME name at boot, so the box can auto-register with the daemon that minted the token. Equivalent to adding that name to env.passthrough — provided as a distinct, self-documenting field because its purpose (auto-join) is different from an arbitrary forwarded secret. Absent/no-op when the named host env var isn't actually set (e.g. a fork's CI run with no AGENTPROTO_JOIN secret) — never fails the boot.\") }).strict().describe(\"Auto-join wiring: forwards a host env var (holding a join-token URL) into the sandbox by the same name, so the box can register itself with the daemon that minted the token.\").optional(), \"mounts\": z.array(z.any()).describe(\"Filesystems mounted inside the sandbox at declared paths. Maps to Mastra Workspace.mounts.\").default([] as never), \"identity\": z.any().describe(\"AIP-23 identity-ref — owner of the sandbox processes.\").optional(), \"policy\": z.any().describe(\"AIP-38 POLICY block — access grants on sandbox actions.\").optional(), \"lifecycle\": z.object({ \"pause_after_idle\": z.string().min(1).describe(\"AIP-37 event name (e.g. `idle-600` for 10 min). Provider-supported only (modal, daytona).\").optional(), \"destroy_on\": z.string().min(1).describe(\"AIP-37 event name (e.g. `workspace-close`).\").optional() }).strict().optional(), \"read_only\": z.boolean().describe(\"Reject command execution at the sandbox layer. Read-only sandbox calls fail with `sandbox_read_only`.\").default(false), \"extraPorts\": z.array(z.number().int().gte(1)).describe(\"App ports to expose at boot time. Resolved into BootedSandbox.ports (port → public URL) by providers that support port exposure.\").optional(), \"metadata\": z.record(z.string(), z.any()).describe(\"Free-form, namespaced. Adapter hints under `metadata.<adapter>.*`.\").optional() }).strict().describe(\"Validates the YAML frontmatter portion of an AIP-36 SANDBOX.md manifest, OR the inline form embedded in any other manifest's `sandbox:` block. Compute-only — durable filesystem backings live in AIP-35 STORAGE.md.\")\n\nexport type SandboxFrontmatter = z.infer<typeof sandboxFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { sandboxFrontmatterSchema } from \"./schema.js\"\nimport type {\n SandboxRuntimeHandle,\n SandboxRuntimeInput,\n} from \"./types.js\"\n\n/**\n * AIP-36 reference implementation of `defineSandbox`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"defineSandbox (AIP-36): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the manifest portion of the input. The\n * AIP-43 runtime slots (`factory`, `capabilities`) are HOST-OPAQUE\n * TS-runtime metadata stripped before validation and re-attached in\n * `build` — same pattern as `@agentproto/storage`'s `defineStorage`.\n *\n * Generic params:\n * TFactory — host-typed factory (e.g. `(input) => WorkspaceSandbox`\n * for the Guilde host). Defaults to `unknown`.\n * TCapabilities — opaque metadata the registry queries on. Per\n * AIP-43 § Capability metadata namespace.\n */\nconst defineSandboxInner = createDoctype<\n SandboxRuntimeInput,\n SandboxRuntimeHandle\n>({\n aip: 36,\n name: \"sandbox\",\n readDescription: false,\n // AIP-36 makes `id` standalone-only — inline sandbox blocks fall\n // back to `provider` for the cross-AIP id-pattern check (mirrors\n // AIP-43 § Identity).\n readIdentity: def => {\n if (typeof def.id === \"string\" && def.id.length > 0) return def.id\n return def.provider\n },\n validate(def) {\n const { factory: _factory, capabilities: _capabilities, ...manifest } = def\n const result = sandboxFrontmatterSchema.safeParse(manifest)\n if (!result.success) {\n throw new Error(\n `defineSandbox (AIP-36): ${result.error.issues\n .map(i => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n // TODO: spec-36-specific cross-field rules (if/then/allOf in\n // the JSON Schema) — those don't translate to zod cleanly and\n // belong here. See @agentproto/operator's autonomy=gated rule.\n },\n build(def) {\n const { factory, capabilities, ...manifest } = def\n return {\n ...manifest,\n ...(factory !== undefined ? { factory } : {}),\n ...(capabilities !== undefined\n ? { capabilities: Object.freeze({ ...capabilities }) }\n : {}),\n } as SandboxRuntimeHandle\n },\n})\n\n/**\n * Type-aware wrapper preserving `TFactory` / `TCapabilities` generics\n * across the call.\n */\nexport function defineSandbox<\n TFactory = unknown,\n TCapabilities extends Record<string, unknown> = Record<string, unknown>,\n>(\n definition: SandboxRuntimeInput<TFactory, TCapabilities>,\n): SandboxRuntimeHandle<TFactory, TCapabilities> {\n return defineSandboxInner(\n definition as SandboxRuntimeInput,\n ) as SandboxRuntimeHandle<TFactory, TCapabilities>\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SandboxRuntimeInput, a as SandboxRuntimeHandle, b as SandboxHandle } from './schema-h9uR_HeR.js';
2
- export { c as SandboxDefinition, s as SandboxSpecSchema } from './schema-h9uR_HeR.js';
1
+ import { S as SandboxRuntimeInput, a as SandboxRuntimeHandle, b as SandboxHandle } from './schema-Bq1O5CzW.js';
2
+ export { c as SandboxDefinition, s as SandboxSpecSchema } from './schema-Bq1O5CzW.js';
3
3
  import { SecretResolver } from '@agentproto/secrets/exposure';
4
4
  import { DaemonAgentSessionHost } from '@agentproto/worktree';
5
5
  import 'zod';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { sandboxFrontmatterSchema as SandboxSpecSchema, defineSandbox } from './chunk-VGEBUSSP.mjs';
1
+ export { sandboxFrontmatterSchema as SandboxSpecSchema, defineSandbox } from './chunk-JEUFE7GR.mjs';
2
2
  import { assertSafeSecretValue } from '@agentproto/secrets/exposure';
3
3
  import { connectDaemonAgentSessionHost } from '@agentproto/worktree';
4
4
 
@@ -1,5 +1,5 @@
1
- import { d as SandboxFrontmatter, b as SandboxHandle } from '../schema-h9uR_HeR.js';
2
- export { s as sandboxFrontmatterSchema } from '../schema-h9uR_HeR.js';
1
+ import { d as SandboxFrontmatter, b as SandboxHandle } from '../schema-Bq1O5CzW.js';
2
+ export { s as sandboxFrontmatterSchema } from '../schema-Bq1O5CzW.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { sandboxFrontmatterSchema, defineSandbox } from '../chunk-VGEBUSSP.mjs';
2
- export { sandboxFrontmatterSchema } from '../chunk-VGEBUSSP.mjs';
1
+ import { sandboxFrontmatterSchema, defineSandbox } from '../chunk-JEUFE7GR.mjs';
2
+ export { sandboxFrontmatterSchema } from '../chunk-JEUFE7GR.mjs';
3
3
  import matter from 'gray-matter';
4
4
 
5
5
  /**
@@ -90,6 +90,15 @@ interface SandboxDefinition {
90
90
  */
91
91
  egress?: string[];
92
92
  };
93
+ /**
94
+ * Auto-join wiring: forwards a host env var (holding a join-token URL) into the sandbox by the same name, so the box can register itself with the daemon that minted the token.
95
+ */
96
+ join?: {
97
+ /**
98
+ * Name of a host env var whose value (a join-token URL) should be forwarded into the sandbox under the SAME name at boot, so the box can auto-register with the daemon that minted the token. Equivalent to adding that name to `env.passthrough` — provided as a distinct, self-documenting field because its purpose (auto-join) is different from an arbitrary forwarded secret. Absent/no-op when the named host env var isn't actually set (e.g. a fork's CI run with no `AGENTPROTO_JOIN` secret) — never fails the boot.
99
+ */
100
+ tokenEnv: string;
101
+ };
93
102
  /**
94
103
  * Filesystems mounted inside the sandbox at declared paths. Maps to Mastra Workspace.mounts.
95
104
  */
@@ -360,6 +369,9 @@ declare const sandboxFrontmatterSchema: z.ZodObject<{
360
369
  network: z.ZodOptional<z.ZodObject<{
361
370
  egress: z.ZodDefault<z.ZodArray<z.ZodString>>;
362
371
  }, z.core.$strict>>;
372
+ join: z.ZodOptional<z.ZodObject<{
373
+ tokenEnv: z.ZodString;
374
+ }, z.core.$strict>>;
363
375
  mounts: z.ZodDefault<z.ZodArray<z.ZodAny>>;
364
376
  identity: z.ZodOptional<z.ZodAny>;
365
377
  policy: z.ZodOptional<z.ZodAny>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/sandbox",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "@agentproto/sandbox — AIP-36 SANDBOX.md reference implementation. A composable schema block defining the `sandbox` field — provider, config, command env, network egress, resource limits — for any manifest that names a compute environment for agent-issued shell commands. Sibling primitive to STORAGE.md (AIP-35); inline or ref, mirroring AIP-17 RUNNER and AIP-19 SECRETS. Also ships createSandboxAgentSessionHost — the provider-agnostic seam that runs an AgentStep's coding-agent turn inside a booted sandbox by pointing the existing daemon-backed AgentSessionHost at its MCP URL.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -50,8 +50,8 @@
50
50
  "zod": "^4.6.5",
51
51
  "@agentproto/define-doctype": "0.1.2",
52
52
  "@agentproto/secrets": "1.1.0",
53
- "@agentproto/workflow-runtime": "0.13.1",
54
- "@agentproto/worktree": "0.10.0"
53
+ "@agentproto/workflow-runtime": "0.14.0",
54
+ "@agentproto/worktree": "0.13.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/node": "^25.9.5",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schema.ts","../src/define-sandbox.ts"],"names":[],"mappings":"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","file":"chunk-VGEBUSSP.mjs","sourcesContent":["/**\n * AIP-36 SANDBOX.md frontmatter zod schema.\n *\n * Generated from `resources/aip-36/draft/SANDBOX.schema.json` via\n * json-schema-to-zod. Imported by both `define-sandbox.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-sandbox.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const sandboxFrontmatterSchema = z.object({ \"schema\": z.literal(\"sandbox/v1\").describe(\"Standalone-only. Identifies the doctype + version. Absent when the block is inlined.\").optional(), \"id\": z.string().regex(new RegExp(\"^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$\")).describe(\"Standalone-only. Globally addressable id `@<owner-slug>/<sandbox-slug>`.\").optional(), \"version\": z.string().regex(new RegExp(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+(?:[-+][\\\\w.\\\\-]+)?$\")).describe(\"Standalone-only. Spec version of THIS file.\").optional(), \"provider\": z.string().min(1).describe(\"Backend kind. Day-1 enumerated set: local | mastra-e2b | mastra-modal | mastra-daytona | mastra-blaxel | node-permission. Hosts MAY register additional ids.\"), \"config\": z.object({ \"installAdapters\": z.array(z.string().min(1)).describe(\"Semantic harness slugs to pre-install in the box at boot (e.g. [\\\"hermes\\\", \\\"claude-code\\\"]). Each expands to @agentproto/adapter-<slug>@latest plus that adapter's declared boot extras; a config.installPackages pin for the same package always wins. Additive — absent means no extra install.\").optional() }).catchall(z.any()).describe(\"Provider-specific connection fields. Shape varies per provider (see AIP-36 §Provider config shapes).\"), \"limits\": z.object({ \"timeout_ms\": z.number().int().gte(1).optional(), \"memory_mb\": z.number().int().gte(1).optional(), \"cpu_ms\": z.number().int().gte(1).optional() }).strict().describe(\"Resource caps per command.\").optional(), \"env\": z.object({ \"auth\": z.any().optional(), \"passthrough\": z.array(z.string()).describe(\"Static host env-var names to forward into the sandbox.\").default([] as never), \"autoPassthrough\": z.boolean().describe(\"Opt-in: forward the spawn's resolved billing-credential env-var NAME (e.g. ANTHROPIC_API_KEY) into passthrough so a fresh box inherits host auth without the caller naming vars. Only the name is injected — the value travels via the normal passthrough mechanism.\").optional() }).strict().optional(), \"network\": z.object({ \"egress\": z.array(z.string()).describe(\"Hostnames the sandbox MAY reach. Empty / missing = no egress.\").default([] as never) }).strict().optional(), \"mounts\": z.array(z.any()).describe(\"Filesystems mounted inside the sandbox at declared paths. Maps to Mastra Workspace.mounts.\").default([] as never), \"identity\": z.any().describe(\"AIP-23 identity-ref — owner of the sandbox processes.\").optional(), \"policy\": z.any().describe(\"AIP-38 POLICY block — access grants on sandbox actions.\").optional(), \"lifecycle\": z.object({ \"pause_after_idle\": z.string().min(1).describe(\"AIP-37 event name (e.g. `idle-600` for 10 min). Provider-supported only (modal, daytona).\").optional(), \"destroy_on\": z.string().min(1).describe(\"AIP-37 event name (e.g. `workspace-close`).\").optional() }).strict().optional(), \"read_only\": z.boolean().describe(\"Reject command execution at the sandbox layer. Read-only sandbox calls fail with `sandbox_read_only`.\").default(false), \"extraPorts\": z.array(z.number().int().gte(1)).describe(\"App ports to expose at boot time. Resolved into BootedSandbox.ports (port → public URL) by providers that support port exposure.\").optional(), \"metadata\": z.record(z.string(), z.any()).describe(\"Free-form, namespaced. Adapter hints under `metadata.<adapter>.*`.\").optional() }).strict().describe(\"Validates the YAML frontmatter portion of an AIP-36 SANDBOX.md manifest, OR the inline form embedded in any other manifest's `sandbox:` block. Compute-only — durable filesystem backings live in AIP-35 STORAGE.md.\")\n\nexport type SandboxFrontmatter = z.infer<typeof sandboxFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { sandboxFrontmatterSchema } from \"./schema.js\"\nimport type {\n SandboxRuntimeHandle,\n SandboxRuntimeInput,\n} from \"./types.js\"\n\n/**\n * AIP-36 reference implementation of `defineSandbox`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"defineSandbox (AIP-36): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the manifest portion of the input. The\n * AIP-43 runtime slots (`factory`, `capabilities`) are HOST-OPAQUE\n * TS-runtime metadata stripped before validation and re-attached in\n * `build` — same pattern as `@agentproto/storage`'s `defineStorage`.\n *\n * Generic params:\n * TFactory — host-typed factory (e.g. `(input) => WorkspaceSandbox`\n * for the Guilde host). Defaults to `unknown`.\n * TCapabilities — opaque metadata the registry queries on. Per\n * AIP-43 § Capability metadata namespace.\n */\nconst defineSandboxInner = createDoctype<\n SandboxRuntimeInput,\n SandboxRuntimeHandle\n>({\n aip: 36,\n name: \"sandbox\",\n readDescription: false,\n // AIP-36 makes `id` standalone-only — inline sandbox blocks fall\n // back to `provider` for the cross-AIP id-pattern check (mirrors\n // AIP-43 § Identity).\n readIdentity: def => {\n if (typeof def.id === \"string\" && def.id.length > 0) return def.id\n return def.provider\n },\n validate(def) {\n const { factory: _factory, capabilities: _capabilities, ...manifest } = def\n const result = sandboxFrontmatterSchema.safeParse(manifest)\n if (!result.success) {\n throw new Error(\n `defineSandbox (AIP-36): ${result.error.issues\n .map(i => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n // TODO: spec-36-specific cross-field rules (if/then/allOf in\n // the JSON Schema) — those don't translate to zod cleanly and\n // belong here. See @agentproto/operator's autonomy=gated rule.\n },\n build(def) {\n const { factory, capabilities, ...manifest } = def\n return {\n ...manifest,\n ...(factory !== undefined ? { factory } : {}),\n ...(capabilities !== undefined\n ? { capabilities: Object.freeze({ ...capabilities }) }\n : {}),\n } as SandboxRuntimeHandle\n },\n})\n\n/**\n * Type-aware wrapper preserving `TFactory` / `TCapabilities` generics\n * across the call.\n */\nexport function defineSandbox<\n TFactory = unknown,\n TCapabilities extends Record<string, unknown> = Record<string, unknown>,\n>(\n definition: SandboxRuntimeInput<TFactory, TCapabilities>,\n): SandboxRuntimeHandle<TFactory, TCapabilities> {\n return defineSandboxInner(\n definition as SandboxRuntimeInput,\n ) as SandboxRuntimeHandle<TFactory, TCapabilities>\n}\n"]}