@finalai/agent-provider 0.1.0

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.

Potentially problematic release.


This version of @finalai/agent-provider might be problematic. Click here for more details.

Files changed (176) hide show
  1. package/README.md +12 -0
  2. package/dist/modules/channel-context.d.mts +102 -0
  3. package/dist/modules/channel-context.mjs +52 -0
  4. package/dist/modules/channel-context.mjs.map +7 -0
  5. package/dist/modules/channel-socket.d.mts +65 -0
  6. package/dist/modules/channel-socket.mjs +188 -0
  7. package/dist/modules/channel-socket.mjs.map +7 -0
  8. package/dist/modules/channel.d.mts +382 -0
  9. package/dist/modules/channel.mjs +146 -0
  10. package/dist/modules/channel.mjs.map +7 -0
  11. package/dist/modules/conformance/agent.d.mts +20 -0
  12. package/dist/modules/conformance/agent.mjs +623 -0
  13. package/dist/modules/conformance/agent.mjs.map +7 -0
  14. package/dist/modules/conformance/fixtures.d.mts +41 -0
  15. package/dist/modules/conformance/fixtures.mjs +190 -0
  16. package/dist/modules/conformance/fixtures.mjs.map +7 -0
  17. package/dist/modules/conformance/harness-kit.d.mts +82 -0
  18. package/dist/modules/conformance/harness-kit.mjs +1303 -0
  19. package/dist/modules/conformance/harness-kit.mjs.map +7 -0
  20. package/dist/modules/conformance/image.d.mts +2 -0
  21. package/dist/modules/conformance/image.mjs +79 -0
  22. package/dist/modules/conformance/image.mjs.map +7 -0
  23. package/dist/modules/conformance/index.d.mts +8 -0
  24. package/dist/modules/conformance/index.mjs +12 -0
  25. package/dist/modules/conformance/index.mjs.map +7 -0
  26. package/dist/modules/conformance/local-harness.d.mts +25 -0
  27. package/dist/modules/conformance/local-harness.mjs +108 -0
  28. package/dist/modules/conformance/local-harness.mjs.map +7 -0
  29. package/dist/modules/conformance/protocol.d.mts +30 -0
  30. package/dist/modules/conformance/protocol.mjs +56 -0
  31. package/dist/modules/conformance/protocol.mjs.map +7 -0
  32. package/dist/modules/conformance/sandbox-kit.d.mts +19 -0
  33. package/dist/modules/conformance/sandbox-kit.mjs +320 -0
  34. package/dist/modules/conformance/sandbox-kit.mjs.map +7 -0
  35. package/dist/modules/conformance/scripted-model/chat-completions.d.mts +30 -0
  36. package/dist/modules/conformance/scripted-model/chat-completions.mjs +125 -0
  37. package/dist/modules/conformance/scripted-model/chat-completions.mjs.map +7 -0
  38. package/dist/modules/conformance/scripted-model/directives.d.mts +84 -0
  39. package/dist/modules/conformance/scripted-model/directives.mjs +304 -0
  40. package/dist/modules/conformance/scripted-model/directives.mjs.map +7 -0
  41. package/dist/modules/conformance/scripted-model/handler.d.mts +14 -0
  42. package/dist/modules/conformance/scripted-model/handler.mjs +133 -0
  43. package/dist/modules/conformance/scripted-model/handler.mjs.map +7 -0
  44. package/dist/modules/conformance/scripted-model/index.d.mts +6 -0
  45. package/dist/modules/conformance/scripted-model/index.mjs +7 -0
  46. package/dist/modules/conformance/scripted-model/index.mjs.map +7 -0
  47. package/dist/modules/conformance/scripted-model/messages.d.mts +39 -0
  48. package/dist/modules/conformance/scripted-model/messages.mjs +139 -0
  49. package/dist/modules/conformance/scripted-model/messages.mjs.map +7 -0
  50. package/dist/modules/conformance/scripted-model/responses.d.mts +62 -0
  51. package/dist/modules/conformance/scripted-model/responses.mjs +273 -0
  52. package/dist/modules/conformance/scripted-model/responses.mjs.map +7 -0
  53. package/dist/modules/conformance/scripted-model/sse.d.mts +15 -0
  54. package/dist/modules/conformance/scripted-model/sse.mjs +75 -0
  55. package/dist/modules/conformance/scripted-model/sse.mjs.map +7 -0
  56. package/dist/modules/conformance/v1-agent.d.mts +24 -0
  57. package/dist/modules/conformance/v1-agent.mjs +40 -0
  58. package/dist/modules/conformance/v1-agent.mjs.map +7 -0
  59. package/dist/modules/credential-routes.d.mts +24 -0
  60. package/dist/modules/credential-routes.mjs +25 -0
  61. package/dist/modules/credential-routes.mjs.map +7 -0
  62. package/dist/modules/credentials.d.mts +206 -0
  63. package/dist/modules/credentials.mjs +207 -0
  64. package/dist/modules/credentials.mjs.map +7 -0
  65. package/dist/modules/dynamic.d.mts +32 -0
  66. package/dist/modules/dynamic.mjs +77 -0
  67. package/dist/modules/dynamic.mjs.map +7 -0
  68. package/dist/modules/harness.d.mts +397 -0
  69. package/dist/modules/harness.mjs +213 -0
  70. package/dist/modules/harness.mjs.map +7 -0
  71. package/dist/modules/index.d.mts +15 -0
  72. package/dist/modules/index.mjs +40 -0
  73. package/dist/modules/index.mjs.map +7 -0
  74. package/dist/modules/json.d.mts +12 -0
  75. package/dist/modules/json.mjs +19 -0
  76. package/dist/modules/json.mjs.map +7 -0
  77. package/dist/modules/local-channel-socket.d.mts +23 -0
  78. package/dist/modules/local-channel-socket.mjs +141 -0
  79. package/dist/modules/local-channel-socket.mjs.map +7 -0
  80. package/dist/modules/manifest.d.mts +558 -0
  81. package/dist/modules/manifest.mjs +266 -0
  82. package/dist/modules/manifest.mjs.map +7 -0
  83. package/dist/modules/mcp-content.d.mts +21 -0
  84. package/dist/modules/mcp-content.mjs +86 -0
  85. package/dist/modules/mcp-content.mjs.map +7 -0
  86. package/dist/modules/provider-ref.d.mts +29 -0
  87. package/dist/modules/provider-ref.mjs +55 -0
  88. package/dist/modules/provider-ref.mjs.map +7 -0
  89. package/dist/modules/sandbox/bytes.d.mts +9 -0
  90. package/dist/modules/sandbox/bytes.mjs +154 -0
  91. package/dist/modules/sandbox/bytes.mjs.map +7 -0
  92. package/dist/modules/sandbox/client.d.mts +51 -0
  93. package/dist/modules/sandbox/client.mjs +500 -0
  94. package/dist/modules/sandbox/client.mjs.map +7 -0
  95. package/dist/modules/sandbox/confined-files.d.mts +22 -0
  96. package/dist/modules/sandbox/confined-files.mjs +142 -0
  97. package/dist/modules/sandbox/confined-files.mjs.map +7 -0
  98. package/dist/modules/sandbox/convenience.d.mts +10 -0
  99. package/dist/modules/sandbox/convenience.mjs +116 -0
  100. package/dist/modules/sandbox/convenience.mjs.map +7 -0
  101. package/dist/modules/sandbox/editor.d.mts +49 -0
  102. package/dist/modules/sandbox/editor.mjs +43 -0
  103. package/dist/modules/sandbox/editor.mjs.map +7 -0
  104. package/dist/modules/sandbox/frame-channel.d.mts +47 -0
  105. package/dist/modules/sandbox/frame-channel.mjs +153 -0
  106. package/dist/modules/sandbox/frame-channel.mjs.map +7 -0
  107. package/dist/modules/sandbox/index.d.mts +18 -0
  108. package/dist/modules/sandbox/index.mjs +70 -0
  109. package/dist/modules/sandbox/index.mjs.map +7 -0
  110. package/dist/modules/sandbox/mcp-channel.d.mts +9 -0
  111. package/dist/modules/sandbox/mcp-channel.mjs +77 -0
  112. package/dist/modules/sandbox/mcp-channel.mjs.map +7 -0
  113. package/dist/modules/sandbox/mcp-hosted.d.mts +46 -0
  114. package/dist/modules/sandbox/mcp-hosted.mjs +221 -0
  115. package/dist/modules/sandbox/mcp-hosted.mjs.map +7 -0
  116. package/dist/modules/sandbox/mcp-search.d.mts +51 -0
  117. package/dist/modules/sandbox/mcp-search.mjs +129 -0
  118. package/dist/modules/sandbox/mcp-search.mjs.map +7 -0
  119. package/dist/modules/sandbox/mcp-shell.d.mts +21 -0
  120. package/dist/modules/sandbox/mcp-shell.mjs +205 -0
  121. package/dist/modules/sandbox/mcp-shell.mjs.map +7 -0
  122. package/dist/modules/sandbox/mcp-testing.d.mts +11 -0
  123. package/dist/modules/sandbox/mcp-testing.mjs +33 -0
  124. package/dist/modules/sandbox/mcp-testing.mjs.map +7 -0
  125. package/dist/modules/sandbox/mcp.d.mts +83 -0
  126. package/dist/modules/sandbox/mcp.mjs +971 -0
  127. package/dist/modules/sandbox/mcp.mjs.map +7 -0
  128. package/dist/modules/sandbox/memory-sandbox.d.mts +32 -0
  129. package/dist/modules/sandbox/memory-sandbox.mjs +416 -0
  130. package/dist/modules/sandbox/memory-sandbox.mjs.map +7 -0
  131. package/dist/modules/sandbox/memory-shell.d.mts +29 -0
  132. package/dist/modules/sandbox/memory-shell.mjs +278 -0
  133. package/dist/modules/sandbox/memory-shell.mjs.map +7 -0
  134. package/dist/modules/sandbox/open-scope-node.d.mts +4 -0
  135. package/dist/modules/sandbox/open-scope-node.mjs +19 -0
  136. package/dist/modules/sandbox/open-scope-node.mjs.map +7 -0
  137. package/dist/modules/sandbox/open-scope.d.mts +16 -0
  138. package/dist/modules/sandbox/open-scope.mjs +66 -0
  139. package/dist/modules/sandbox/open-scope.mjs.map +7 -0
  140. package/dist/modules/sandbox/paths.d.mts +7 -0
  141. package/dist/modules/sandbox/paths.mjs +50 -0
  142. package/dist/modules/sandbox/paths.mjs.map +7 -0
  143. package/dist/modules/sandbox/rpc-peer.d.mts +35 -0
  144. package/dist/modules/sandbox/rpc-peer.mjs +224 -0
  145. package/dist/modules/sandbox/rpc-peer.mjs.map +7 -0
  146. package/dist/modules/sandbox/seeds.d.mts +26 -0
  147. package/dist/modules/sandbox/seeds.mjs +228 -0
  148. package/dist/modules/sandbox/seeds.mjs.map +7 -0
  149. package/dist/modules/sandbox/server.d.mts +66 -0
  150. package/dist/modules/sandbox/server.mjs +567 -0
  151. package/dist/modules/sandbox/server.mjs.map +7 -0
  152. package/dist/modules/sandbox/snapshots.d.mts +49 -0
  153. package/dist/modules/sandbox/snapshots.mjs +55 -0
  154. package/dist/modules/sandbox/snapshots.mjs.map +7 -0
  155. package/dist/modules/sandbox/stream-mux.d.mts +18 -0
  156. package/dist/modules/sandbox/stream-mux.mjs +285 -0
  157. package/dist/modules/sandbox/stream-mux.mjs.map +7 -0
  158. package/dist/modules/sandbox/testing.d.mts +25 -0
  159. package/dist/modules/sandbox/testing.mjs +64 -0
  160. package/dist/modules/sandbox/testing.mjs.map +7 -0
  161. package/dist/modules/sandbox/types.d.mts +352 -0
  162. package/dist/modules/sandbox/types.mjs +86 -0
  163. package/dist/modules/sandbox/types.mjs.map +7 -0
  164. package/dist/modules/sandbox/wire.d.mts +671 -0
  165. package/dist/modules/sandbox/wire.mjs +537 -0
  166. package/dist/modules/sandbox/wire.mjs.map +7 -0
  167. package/dist/modules/sandbox/workspace-root.d.mts +8 -0
  168. package/dist/modules/sandbox/workspace-root.mjs +79 -0
  169. package/dist/modules/sandbox/workspace-root.mjs.map +7 -0
  170. package/dist/modules/schemas.d.mts +121 -0
  171. package/dist/modules/schemas.mjs +146 -0
  172. package/dist/modules/schemas.mjs.map +7 -0
  173. package/dist/modules/semantic-events.d.mts +31 -0
  174. package/dist/modules/semantic-events.mjs +23 -0
  175. package/dist/modules/semantic-events.mjs.map +7 -0
  176. package/package.json +199 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/sandbox/mcp.ts"],
4
+ "sourcesContent": ["import type { FetchLike } from '@modelcontextprotocol/client';\nimport {\n createMcpHandler,\n fromJsonSchema,\n McpServer,\n ResourceTemplate,\n type CallToolResult,\n type McpHttpHandler,\n type ReadResourceResult,\n} from '@modelcontextprotocol/server';\nimport * as z from 'zod';\nimport type { JsonObject, JsonSchema, JsonValue } from \"../json.mjs\";\nimport { SandboxAccess, ToolApproval, type ToolDescriptorIface } from \"../manifest.mjs\";\nimport { bytesToBase64, utf8Decode } from \"./bytes.mjs\";\nimport {\n createHostedMcpConnections,\n EMPTY_MCP_CATALOG,\n hostedTools,\n SandboxHostedServerKind,\n type HostedToolIface,\n type SandboxHostedServer,\n} from \"./mcp-hosted.mjs\";\nimport { globFiles, grepFiles } from \"./mcp-search.mjs\";\nimport { createSandboxShell, SandboxShellMode } from \"./mcp-shell.mjs\";\nimport { resolvePosixPath } from \"./paths.mjs\";\nimport {\n PortProtocol,\n SandboxCapability,\n SandboxEntryType,\n type NetworkSandboxSessionIface,\n type SandboxMcpCatalogIface,\n type SandboxProcessIface,\n} from \"./types.mjs\";\n\nexport {\n COMPUTER_USE_SERVER_NAME,\n SandboxHostedServerKind,\n withHostedMcpEndpoints,\n type SandboxHostedServer,\n} from \"./mcp-hosted.mjs\";\nexport { SandboxShellMode } from \"./mcp-shell.mjs\";\n\n// The standard sandbox MCP projection, generated from a\n// handle for harnesses that do not speak the handle RPC. `tools/list` is\n// answered from static descriptors, so enumerating tools never starts a\n// sandbox; the handle is obtained on the first tool call.\n//\n// The sandbox's hosted MCP servers (computer use, local MCP) are projected as\n// their own tools. Their catalogs come from the provider when it knows them\n// before anything starts (`catalog`); otherwise the projection lists what it\n// knows, learns the rest from the servers once the sandbox is attached, and\n// announces it with `notifications/tools/list_changed`.\n\nexport enum SandboxMcpTool {\n Run = 'run',\n Spawn = 'spawn',\n ProcessOutput = 'process_output',\n ProcessInput = 'process_input',\n ProcessTerminate = 'process_terminate',\n ReadFile = 'read_file',\n WriteFile = 'write_file',\n EditFile = 'edit_file',\n ListDir = 'list_dir',\n Stat = 'stat',\n Grep = 'grep',\n Glob = 'glob',\n GetHost = 'get_host',\n}\n\n// What one projection serves: everything, only the hosted servers (for\n// harnesses whose native tools use the handle RPC), the computer-use server,\n// or one local MCP server (the per-server addresses the handle RPC hands out).\nexport enum SandboxMcpScopeKind {\n All = 'all',\n Hosted = 'hosted',\n ComputerUse = 'computerUse',\n LocalServer = 'localServer',\n}\n\nexport type SandboxMcpScope =\n | { kind: SandboxMcpScopeKind.All | SandboxMcpScopeKind.Hosted | SandboxMcpScopeKind.ComputerUse }\n | { kind: SandboxMcpScopeKind.LocalServer; server: string };\n\nexport const SANDBOX_FILE_RESOURCE_SCHEME = 'sandbox-file';\n\nexport interface SandboxMcpDescriptorOptionsIface {\n capabilities: readonly SandboxCapability[];\n access?: SandboxAccess;\n // The hosted servers' tools known so far (the provider's `mcpCatalog`, or\n // learned on an earlier attach). Default: none known.\n catalog?: SandboxMcpCatalogIface;\n scope?: SandboxMcpScope;\n}\n\ninterface ToolSpecIface {\n descriptor: ToolDescriptorIface;\n capability: SandboxCapability;\n write: boolean;\n // toolPolicy keys after the tool name, most specific first.\n policyKeys: string[];\n // A tool of a hosted MCP server, proxied to it.\n hosted?: HostedToolIface;\n}\n\nconst objectSchema = (properties: JsonObject, required: string[]): JsonSchema => ({\n type: 'object',\n properties,\n required,\n additionalProperties: false,\n});\n\nconst str = (description: string): JsonObject => ({ type: 'string', description });\nconst int = (description: string, minimum = 0): JsonObject => ({\n type: 'integer',\n minimum,\n description,\n});\nconst envSchema: JsonObject = {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Extra environment variables for this command only.',\n};\n\ntype ToolAnnotationsIface = NonNullable<ToolDescriptorIface['annotations']>;\n\nconst readOnly = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n};\nconst mutating = {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: false,\n};\n\nconst tool = (args: {\n name: string;\n title: string;\n description: string;\n inputSchema: JsonSchema;\n capability: SandboxCapability;\n write: boolean;\n policyKeys: string[];\n idempotent?: boolean;\n destructive?: boolean;\n}): ToolSpecIface => {\n const annotations: ToolAnnotationsIface = {\n title: args.title,\n ...(args.write ? mutating : readOnly),\n };\n if (args.destructive != null) annotations.destructiveHint = args.destructive;\n if (args.idempotent != null) annotations.idempotentHint = args.idempotent;\n return {\n descriptor: {\n name: args.name,\n description: args.description,\n inputSchema: args.inputSchema,\n annotations,\n },\n capability: args.capability,\n write: args.write,\n policyKeys: args.policyKeys,\n };\n};\n\nconst BUILT_IN_TOOLS: readonly ToolSpecIface[] = [\n tool({\n name: SandboxMcpTool.Run,\n title: 'Run command',\n description:\n 'Run a shell command in the sandbox and wait for it. The shell persists between calls (cd and exported variables carry over). Returns exit_code, stdout and stderr.',\n inputSchema: objectSchema(\n {\n command: str('The bash command to run.'),\n cwd: str('Directory to run in (absolute, or relative to the working directory).'),\n timeout_ms: int('Kill the command after this many milliseconds.', 1),\n env: envSchema,\n },\n ['command'],\n ),\n capability: SandboxCapability.Process,\n write: true,\n policyKeys: ['shell', 'process'],\n }),\n tool({\n name: SandboxMcpTool.Spawn,\n title: 'Start background process',\n description:\n 'Start a long-running command (a server, a watcher) without waiting. Returns process_id; read its output with process_output.',\n inputSchema: objectSchema(\n {\n command: str('The bash command to start.'),\n cwd: str('Directory to run in.'),\n env: envSchema,\n },\n ['command'],\n ),\n capability: SandboxCapability.Process,\n write: true,\n policyKeys: ['shell', 'process'],\n }),\n tool({\n name: SandboxMcpTool.ProcessOutput,\n title: 'Read process output',\n description:\n 'Read output of a process started with spawn, from byte offsets (pass the next_offset values from the previous call). Optionally waits for new output.',\n inputSchema: objectSchema(\n {\n process_id: str('The id returned by spawn.'),\n stdout_offset: int('Byte offset into stdout.'),\n stderr_offset: int('Byte offset into stderr.'),\n max_bytes: int('Maximum bytes per stream to return (default 65536).', 1),\n wait_ms: int('Wait up to this long for new output or exit (max 30000).'),\n },\n ['process_id'],\n ),\n capability: SandboxCapability.Process,\n write: false,\n policyKeys: ['shell', 'process'],\n idempotent: false,\n }),\n tool({\n name: SandboxMcpTool.ProcessInput,\n title: 'Write process input',\n description: 'Write text to the stdin of a process started with spawn; set end to close stdin.',\n inputSchema: objectSchema(\n {\n process_id: str('The id returned by spawn.'),\n data: str('Text to write.'),\n end: { type: 'boolean' },\n },\n ['process_id'],\n ),\n capability: SandboxCapability.Process,\n write: true,\n policyKeys: ['shell', 'process'],\n destructive: false,\n }),\n tool({\n name: SandboxMcpTool.ProcessTerminate,\n title: 'Terminate process',\n description: 'Stop a process started with spawn.',\n inputSchema: objectSchema(\n {\n process_id: str('The id returned by spawn.'),\n signal: str('Signal name (default SIGTERM).'),\n },\n ['process_id'],\n ),\n capability: SandboxCapability.Process,\n write: true,\n policyKeys: ['shell', 'process'],\n }),\n tool({\n name: SandboxMcpTool.ReadFile,\n title: 'Read file',\n description:\n 'Read a text file. Use offset (1-based line) and limit (line count) for large files; large or binary files also come back as a resource link.',\n inputSchema: objectSchema(\n {\n path: str('File path (absolute, or relative to the working directory).'),\n offset: int('First line to read (1-based).', 1),\n limit: int('Number of lines to read.', 1),\n },\n ['path'],\n ),\n capability: SandboxCapability.Files,\n write: false,\n policyKeys: ['files.read', 'files'],\n }),\n tool({\n name: SandboxMcpTool.WriteFile,\n title: 'Write file',\n description: 'Create or overwrite a text file. Parent directories are created.',\n inputSchema: objectSchema({ path: str('File path.'), content: str('Full file content.') }, [\n 'path',\n 'content',\n ]),\n capability: SandboxCapability.Files,\n write: true,\n policyKeys: ['files.write', 'files'],\n }),\n tool({\n name: SandboxMcpTool.EditFile,\n title: 'Edit file',\n description:\n 'Replace an exact string in a file. old_string must occur exactly once unless replace_all is true; include surrounding lines to make it unique.',\n inputSchema: objectSchema(\n {\n path: str('File path.'),\n old_string: str('Exact text to replace.'),\n new_string: str('Replacement text.'),\n replace_all: { type: 'boolean', description: 'Replace every occurrence.' },\n },\n ['path', 'old_string', 'new_string'],\n ),\n capability: SandboxCapability.Files,\n write: true,\n policyKeys: ['files.write', 'files'],\n }),\n tool({\n name: SandboxMcpTool.ListDir,\n title: 'List directory',\n description: 'List the entries of a directory (name, type, size).',\n inputSchema: objectSchema(\n { path: str('Directory path (default: the working directory).') },\n [],\n ),\n capability: SandboxCapability.Files,\n write: false,\n policyKeys: ['files.read', 'files'],\n }),\n tool({\n name: SandboxMcpTool.Stat,\n title: 'Stat path',\n description: 'Type, size, modification time and mode of a path, or exists: false.',\n inputSchema: objectSchema({ path: str('Path to inspect.') }, ['path']),\n capability: SandboxCapability.Files,\n write: false,\n policyKeys: ['files.read', 'files'],\n }),\n tool({\n name: SandboxMcpTool.Grep,\n title: 'Search file contents',\n description:\n 'Search files under a path for a regular expression. Returns path:line:text matches. Skips .git and node_modules.',\n inputSchema: objectSchema(\n {\n pattern: str('JavaScript regular expression.'),\n path: str('File or directory to search (default: the working directory).'),\n glob: str('Only search files matching this glob (e.g. \"*.ts\").'),\n ignore_case: { type: 'boolean' },\n max_results: int('Maximum matches (default 200).', 1),\n },\n ['pattern'],\n ),\n capability: SandboxCapability.Files,\n write: false,\n policyKeys: ['files.read', 'files'],\n }),\n tool({\n name: SandboxMcpTool.Glob,\n title: 'Find files',\n description: 'Find files whose path (relative to path) matches a glob such as \"**/*.ts\".',\n inputSchema: objectSchema(\n {\n pattern: str('Glob pattern.'),\n path: str('Directory to search (default: the working directory).'),\n max_results: int('Maximum paths (default 500).', 1),\n },\n ['pattern'],\n ),\n capability: SandboxCapability.Files,\n write: false,\n policyKeys: ['files.read', 'files'],\n }),\n tool({\n name: SandboxMcpTool.GetHost,\n title: 'Get port URL',\n description:\n 'The URL (and any required headers) at which a port served inside the sandbox is reachable.',\n inputSchema: objectSchema(\n {\n port: int('Port number.', 1),\n protocol: {\n type: 'string',\n enum: Object.values(PortProtocol),\n description: 'Default http.',\n },\n },\n ['port'],\n ),\n capability: SandboxCapability.Ports,\n write: false,\n policyKeys: ['ports'],\n }),\n];\n\nconst scopeOf = (options: SandboxMcpDescriptorOptionsIface): SandboxMcpScope =>\n options.scope ?? { kind: SandboxMcpScopeKind.All };\n\ninterface HostedServersIface {\n computerUse: boolean;\n localMcp: boolean;\n // Only this local server (a per-server address).\n localServer?: string;\n}\n\n// Which hosted servers a projection serves, given its capabilities and scope.\n// Computer use and local MCP servers act on the machine: a reader gets neither.\nconst hostedServersOf = (options: SandboxMcpDescriptorOptionsIface): HostedServersIface => {\n if (options.access === SandboxAccess.Read) return { computerUse: false, localMcp: false };\n // Execute access acts on the machine but writes no files directly: hosted servers stay.\n const capabilities = new Set(options.capabilities);\n const scope = scopeOf(options);\n const computerUse =\n capabilities.has(SandboxCapability.ComputerUse) &&\n scope.kind !== SandboxMcpScopeKind.LocalServer;\n const localMcp =\n capabilities.has(SandboxCapability.LocalMcp) && scope.kind !== SandboxMcpScopeKind.ComputerUse;\n return scope.kind === SandboxMcpScopeKind.LocalServer\n ? { computerUse, localMcp, localServer: scope.server }\n : { computerUse, localMcp };\n};\n\nconst hostedSpec = (hosted: HostedToolIface): ToolSpecIface => {\n const annotations: ToolAnnotationsIface = { ...mutating, ...hosted.tool.annotations };\n return {\n descriptor: { ...hosted.tool, name: hosted.name, annotations },\n capability:\n hosted.server.kind === SandboxHostedServerKind.ComputerUse\n ? SandboxCapability.ComputerUse\n : SandboxCapability.LocalMcp,\n write: true,\n policyKeys: hosted.policyKeys,\n hosted,\n };\n};\n\nconst toolSpecs = (options: SandboxMcpDescriptorOptionsIface): ToolSpecIface[] => {\n const capabilities = new Set(options.capabilities);\n // Shell-like capabilities imply processes for the projection.\n const builtIn =\n scopeOf(options).kind === SandboxMcpScopeKind.All\n ? BUILT_IN_TOOLS.filter((spec) => capabilities.has(spec.capability))\n : [];\n // Read hides every mutating tool; execute hides only the file writes.\n const visible =\n options.access === SandboxAccess.Read\n ? builtIn.filter((spec) => !spec.write)\n : options.access === SandboxAccess.Execute\n ? builtIn.filter((spec) => !spec.write || spec.capability !== SandboxCapability.Files)\n : builtIn;\n const hosted = hostedTools({\n catalog: options.catalog ?? EMPTY_MCP_CATALOG,\n ...hostedServersOf(options),\n taken: new Set(builtIn.map((spec) => spec.descriptor.name)),\n });\n return [...visible, ...hosted.map(hostedSpec)];\n};\n\n// The projection's tools for a sandbox with these capabilities and the hosted\n// catalogs known so far, without a handle: what `tools/list` answers.\nexport const sandboxMcpToolDescriptors = (\n options: SandboxMcpDescriptorOptionsIface,\n): ToolDescriptorIface[] => toolSpecs(options).map((spec) => spec.descriptor);\n\n// The toolPolicy keys a projection tool is decided by, most specific first\n// (its name, then capability keys such as `shell` or `files.write`), as the\n// projection checks them; null for a tool these options do not list. Lets the\n// MCP host raise an `ask` approval before it calls the projection.\nexport const sandboxMcpToolPolicyKeys = (\n options: SandboxMcpDescriptorOptionsIface,\n name: string,\n): string[] | null => {\n const spec = toolSpecs(options).find((candidate) => candidate.descriptor.name === name);\n return spec == null ? null : [name, ...spec.policyKeys];\n};\n\nexport interface CreateSandboxMcpServerArgsIface extends SandboxMcpDescriptorOptionsIface {\n // Obtains (and on the first call starts) the sandbox. Called lazily.\n getSandbox: () => Promise<NetworkSandboxSessionIface>;\n // Keys are tool names or capability keys (`shell`, `files.write`, ...).\n toolPolicy?: Record<string, ToolApproval>;\n // Asked for tools whose policy is `ask`; no hook means deny.\n approve?: (toolName: string, args: JsonObject) => Promise<boolean>;\n shell?: SandboxShellMode;\n name?: string;\n version?: string;\n // Fetch for sandbox-hosted MCP servers reached over HTTP (tests, service bindings).\n fetch?: FetchLike;\n limits?: Partial<SandboxMcpLimitsIface>;\n onError?: (error: Error) => void;\n // The sandbox when it is already attached (no start): a `tools/list` that\n // finds a hosted catalog unknown reads it from the live sandbox before\n // answering. Without a live sandbox the list answers at once and the catalog\n // is learned in the background.\n peekSandbox?: () => NetworkSandboxSessionIface | null;\n // Called with the hosted catalogs whenever more of them become known.\n onCatalog?: (catalog: SandboxMcpCatalogIface) => void;\n // A background process started with `spawn` exited on its own and no client\n // has read its exit (`process_output`) within `exitReportGraceMs`: the host\n // reports it as a sandbox result. Never called for a process\n // ended with `process_terminate` or by `close`.\n onProcessExit?: (exit: SandboxProcessExitIface) => void;\n}\n\nexport interface SandboxProcessExitIface {\n processId: string;\n command: string;\n // Null when the sandbox lost the process without an exit code.\n exitCode: number | null;\n // The end of each stream, at most `exitOutputChars`.\n stdout: string;\n stderr: string;\n}\n\nexport interface SandboxMcpLimitsIface {\n // Characters of stdout/stderr returned per run (head and tail kept).\n maxOutputChars: number;\n // Files above this size are not inlined without a line range.\n maxInlineBytes: number;\n // Bytes of background-process output kept per stream.\n processBufferBytes: number;\n maxProcesses: number;\n // How long an exit may go unread before onProcessExit reports it.\n exitReportGraceMs: number;\n // Characters of each stream's tail an exit report carries.\n exitOutputChars: number;\n}\n\nconst DEFAULT_LIMITS: SandboxMcpLimitsIface = {\n maxOutputChars: 64_000,\n maxInlineBytes: 256 * 1024,\n processBufferBytes: 4 * 1024 * 1024,\n maxProcesses: 32,\n exitReportGraceMs: 2_000,\n exitOutputChars: 4_000,\n};\n\nexport interface SandboxMcpServerIface {\n readonly descriptors: readonly ToolDescriptorIface[];\n // Streamable HTTP MCP endpoint (2026-07-28 and stateless 2025 clients).\n fetch(request: Request): Promise<Response>;\n // Direct entry points for hosts that relay MCP themselves (MCP over ACP).\n listTools(): ToolDescriptorIface[];\n // `listTools` after what a `tools/list` does first (reading hosted catalogs\n // from a live sandbox, or starting their discovery).\n refreshTools(): Promise<ToolDescriptorIface[]>;\n // Catalogs learned elsewhere (another projection of the same sandbox).\n updateCatalog(catalog: SandboxMcpCatalogIface): void;\n callTool(name: string, args: JsonObject, signal?: AbortSignal): Promise<CallToolResult>;\n close(): Promise<void>;\n}\n\ninterface OutputBufferIface {\n chunks: Uint8Array[];\n // Absolute offset of chunks[0].\n base: number;\n size: number;\n}\n\ninterface BackgroundProcessIface {\n process: SandboxProcessIface;\n stdout: OutputBufferIface;\n stderr: OutputBufferIface;\n exitCode: number | null;\n exited: boolean;\n changed: Set<() => void>;\n command: string;\n // A client read the exit, or ended the process itself.\n exitSeen: boolean;\n}\n\nconst textResult = (text: string): CallToolResult => ({ content: [{ type: 'text', text }] });\nconst jsonResult = (value: JsonValue): CallToolResult => textResult(JSON.stringify(value, null, 2));\nconst errorResult = (message: string): CallToolResult => ({\n content: [{ type: 'text', text: message }],\n isError: true,\n});\n\nconst truncateMiddle = (text: string, max: number): string => {\n if (text.length <= max) return text;\n const half = Math.floor(max / 2);\n return `${text.slice(0, half)}\\n[... ${text.length - max} characters omitted ...]\\n${text.slice(text.length - half)}`;\n};\n\nconst listRequestSchema = z.object({ method: z.literal('tools/list') });\n\nconst runArgsSchema = z.object({\n command: z.string().min(1),\n cwd: z.string().optional(),\n timeout_ms: z.number().int().positive().optional(),\n env: z.record(z.string(), z.string()).optional(),\n});\nconst spawnArgsSchema = runArgsSchema.omit({ timeout_ms: true });\nconst processOutputArgsSchema = z.object({\n process_id: z.string().min(1),\n stdout_offset: z.number().int().nonnegative().optional(),\n stderr_offset: z.number().int().nonnegative().optional(),\n max_bytes: z.number().int().positive().optional(),\n wait_ms: z.number().int().nonnegative().optional(),\n});\nconst processInputArgsSchema = z.object({\n process_id: z.string().min(1),\n data: z.string().optional(),\n end: z.boolean().optional(),\n});\nconst processTerminateArgsSchema = z.object({\n process_id: z.string().min(1),\n signal: z.string().optional(),\n});\nconst readFileArgsSchema = z.object({\n path: z.string().min(1),\n offset: z.number().int().positive().optional(),\n limit: z.number().int().positive().optional(),\n});\nconst writeFileArgsSchema = z.object({ path: z.string().min(1), content: z.string() });\nconst editFileArgsSchema = z.object({\n path: z.string().min(1),\n old_string: z.string().min(1),\n new_string: z.string(),\n replace_all: z.boolean().optional(),\n});\nconst pathArgsSchema = z.object({ path: z.string().min(1) });\nconst listDirArgsSchema = z.object({ path: z.string().optional() });\nconst grepArgsSchema = z.object({\n pattern: z.string().min(1),\n path: z.string().optional(),\n glob: z.string().optional(),\n ignore_case: z.boolean().optional(),\n max_results: z.number().int().positive().optional(),\n});\nconst globArgsSchema = z.object({\n pattern: z.string().min(1),\n path: z.string().optional(),\n max_results: z.number().int().positive().optional(),\n});\nconst getHostArgsSchema = z.object({\n port: z.number().int().min(1).max(65535),\n protocol: z.nativeEnum(PortProtocol).optional(),\n});\n\nconst appendOutput = (buffer: OutputBufferIface, chunk: Uint8Array, cap: number) => {\n buffer.chunks.push(chunk);\n buffer.size += chunk.byteLength;\n while (buffer.size > cap && buffer.chunks.length > 1) {\n const dropped = buffer.chunks.shift();\n if (dropped == null) break;\n buffer.size -= dropped.byteLength;\n buffer.base += dropped.byteLength;\n }\n};\n\nconst readOutput = (buffer: OutputBufferIface, offset: number, maxBytes: number) => {\n const start = Math.max(offset, buffer.base);\n const end = buffer.base + buffer.size;\n const out = new Uint8Array(Math.max(0, Math.min(end - start, maxBytes)));\n let position = buffer.base;\n let written = 0;\n for (const chunk of buffer.chunks) {\n const chunkEnd = position + chunk.byteLength;\n if (chunkEnd > start && written < out.byteLength) {\n const from = Math.max(0, start - position);\n const take = Math.min(chunk.byteLength - from, out.byteLength - written);\n out.set(chunk.subarray(from, from + take), written);\n written += take;\n }\n position = chunkEnd;\n }\n return {\n data: utf8Decode(out),\n offset: start,\n next_offset: start + written,\n skipped: start - offset,\n available: end,\n };\n};\n\nexport const createSandboxMcpServer = (\n args: CreateSandboxMcpServerArgsIface,\n): SandboxMcpServerIface => {\n const limits: SandboxMcpLimitsIface = { ...DEFAULT_LIMITS, ...args.limits };\n let catalog: SandboxMcpCatalogIface = args.catalog ?? EMPTY_MCP_CATALOG;\n let specs = toolSpecs({ ...args, catalog });\n let byName = new Map(specs.map((spec) => [spec.descriptor.name, spec]));\n const processes = new Map<string, BackgroundProcessIface>();\n const served = hostedServersOf(args);\n let handler: McpHttpHandler | null = null;\n let learning: Promise<void> | null = null;\n let discovering = false;\n // Hosted servers whose known catalog was checked against the live server.\n const checked = new Set<string>();\n\n const asError = (cause: unknown): Error =>\n cause instanceof Error ? cause : new Error(String(cause));\n const reportError = (error: Error) => args.onError?.(error);\n\n // Merges catalogs as they become known; a change relists the tools and tells\n // `subscriptions/listen` clients (`notifications/tools/list_changed`).\n const mergeCatalog = (next: Partial<SandboxMcpCatalogIface>): boolean => {\n const merged: SandboxMcpCatalogIface = {\n computerUse: next.computerUse ?? catalog.computerUse,\n localMcp: next.localMcp ?? catalog.localMcp,\n };\n if (JSON.stringify(merged) === JSON.stringify(catalog)) return false;\n catalog = merged;\n specs = toolSpecs({ ...args, catalog });\n byName = new Map(specs.map((spec) => [spec.descriptor.name, spec]));\n handler?.notify.toolsChanged();\n return true;\n };\n\n const unknownCatalogs = () => ({\n computerUse: served.computerUse && catalog.computerUse == null,\n localMcp: served.localMcp && catalog.localMcp == null,\n });\n\n const connections = createHostedMcpConnections({\n getSandbox: () => sandboxFor(),\n fetch: args.fetch,\n name: args.name,\n version: args.version,\n });\n\n // Reads the unknown hosted catalogs from an attached sandbox, once at a time.\n const learnFrom = (sandbox: NetworkSandboxSessionIface): Promise<void> => {\n const needed = unknownCatalogs();\n if (!needed.computerUse && !needed.localMcp) return Promise.resolve();\n learning ??= (async () => {\n try {\n if (mergeCatalog(await connections.learn(sandbox, needed))) args.onCatalog?.(catalog);\n } finally {\n learning = null;\n }\n })();\n return learning;\n };\n\n // Every attach through this projection also learns what it does not know yet.\n const sandboxFor = async (): Promise<NetworkSandboxSessionIface> => {\n const sandbox = await args.getSandbox();\n learnFrom(sandbox).catch((cause: unknown) => reportError(asError(cause)));\n return sandbox;\n };\n\n // Before answering `tools/list`: a live sandbox is asked for the catalogs it\n // can give now; without one, the first list attaches in the background (the\n // only way to learn a catalog the provider cannot give) and the tools follow\n // with `notifications/tools/list_changed`.\n const beforeList = async (waitForDiscovery = false): Promise<void> => {\n const needed = unknownCatalogs();\n if (!needed.computerUse && !needed.localMcp) return;\n const live = args.peekSandbox?.() ?? null;\n if (live != null) {\n // The combined projection stays responsive; dedicated endpoints need\n // their live catalog before a harness can use them.\n const discovered = learnFrom(live).catch((cause: unknown) => reportError(asError(cause)));\n if (waitForDiscovery || scopeOf(args).kind !== SandboxMcpScopeKind.All) await discovered;\n return;\n }\n if (discovering) return;\n discovering = true;\n sandboxFor()\n .then((sandbox) => learnFrom(sandbox))\n .catch((cause: unknown) => {\n discovering = false;\n reportError(asError(cause));\n });\n };\n\n // A known catalog may be stale (the server changed since it was recorded).\n // It is checked against the live server the first time a call opens that\n // server, never by opening servers the session does not use; a change is\n // announced like a new catalog.\n const checkCatalog = (server: SandboxHostedServer): void => {\n const key = server.kind === SandboxHostedServerKind.Local ? `local:${server.name}` : 'cu';\n if (checked.has(key)) return;\n checked.add(key);\n void (async () => {\n const tools = await connections.tools(server);\n const next: Partial<SandboxMcpCatalogIface> =\n server.kind === SandboxHostedServerKind.ComputerUse\n ? { computerUse: tools }\n : catalog.localMcp == null\n ? {}\n : { localMcp: { ...catalog.localMcp, [server.name]: tools } };\n if (mergeCatalog(next)) args.onCatalog?.(catalog);\n })().catch((cause: unknown) => {\n checked.delete(key);\n reportError(asError(cause));\n });\n };\n\n const shell = createSandboxShell({ getSandbox: sandboxFor, mode: args.shell });\n const isAllowed = async (\n spec: ToolSpecIface,\n name: string,\n input: JsonObject,\n ): Promise<boolean> => {\n for (const key of [name, ...spec.policyKeys]) {\n const decision = args.toolPolicy?.[key];\n if (decision === ToolApproval.Allow) return true;\n if (decision === ToolApproval.Ask)\n return args.approve == null ? false : args.approve(name, input);\n }\n return true;\n };\n\n const backgroundProcess = (id: string): BackgroundProcessIface => {\n const entry = processes.get(id);\n if (entry == null) throw new Error(`no process ${id}; start one with spawn`);\n return entry;\n };\n\n const notifyProcess = (entry: BackgroundProcessIface) => {\n for (const listener of [...entry.changed]) listener();\n };\n\n // Up to four UTF-8 bytes per character are read back from the end.\n const tailOf = (buffer: OutputBufferIface): string => {\n const end = buffer.base + buffer.size;\n const text = readOutput(\n buffer,\n end - limits.exitOutputChars * 4,\n limits.exitOutputChars * 4,\n ).data;\n return text.length <= limits.exitOutputChars\n ? text\n : text.slice(text.length - limits.exitOutputChars);\n };\n\n let closed = false;\n const reportExit = (id: string, entry: BackgroundProcessIface) => {\n const report = args.onProcessExit;\n if (report == null) return;\n setTimeout(() => {\n if (closed || entry.exitSeen) return;\n entry.exitSeen = true;\n report({\n processId: id,\n command: entry.command,\n exitCode: entry.exitCode,\n stdout: tailOf(entry.stdout),\n stderr: tailOf(entry.stderr),\n });\n }, limits.exitReportGraceMs);\n };\n\n const pumpOutput = async (\n entry: BackgroundProcessIface,\n stream: ReadableStream<Uint8Array>,\n buffer: OutputBufferIface,\n ) => {\n const reader = stream.getReader();\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n appendOutput(buffer, value, limits.processBufferBytes);\n notifyProcess(entry);\n }\n } catch {\n // Reported through `exited`.\n }\n };\n\n const run = async (\n name: string,\n rawArgs: JsonObject,\n signal: AbortSignal | undefined,\n ): Promise<CallToolResult> => {\n switch (name) {\n case SandboxMcpTool.Run: {\n const input = runArgsSchema.parse(rawArgs);\n const result = await shell.run({\n command: input.command,\n cwd: input.cwd,\n env: input.env,\n timeoutMs: input.timeout_ms ?? 120_000,\n signal,\n });\n return jsonResult({\n exit_code: result.exitCode,\n stdout: truncateMiddle(result.stdout, limits.maxOutputChars),\n stderr: truncateMiddle(result.stderr, limits.maxOutputChars),\n });\n }\n case SandboxMcpTool.Spawn: {\n const input = spawnArgsSchema.parse(rawArgs);\n if (processes.size >= limits.maxProcesses) {\n for (const [id, entry] of processes)\n if (entry.exited && entry.exitSeen) processes.delete(id);\n }\n if (processes.size >= limits.maxProcesses) {\n return errorResult(\n `too many background processes (${limits.maxProcesses}); terminate one first`,\n );\n }\n const sandbox = await sandboxFor();\n const child = await sandbox.spawn({\n command: input.command,\n shell: true,\n cwd: input.cwd,\n env: input.env,\n });\n const id = `p${crypto.randomUUID().slice(0, 8)}`;\n const entry: BackgroundProcessIface = {\n process: child,\n stdout: { chunks: [], base: 0, size: 0 },\n stderr: { chunks: [], base: 0, size: 0 },\n exitCode: null,\n exited: false,\n changed: new Set(),\n command: input.command,\n exitSeen: false,\n };\n processes.set(id, entry);\n void pumpOutput(entry, child.stdout, entry.stdout);\n void pumpOutput(entry, child.stderr, entry.stderr);\n child.wait().then(\n (result) => {\n entry.exited = true;\n entry.exitCode = result.exitCode;\n notifyProcess(entry);\n reportExit(id, entry);\n },\n () => {\n entry.exited = true;\n notifyProcess(entry);\n reportExit(id, entry);\n },\n );\n return jsonResult({ process_id: id, pid: child.pid });\n }\n case SandboxMcpTool.ProcessOutput: {\n const input = processOutputArgsSchema.parse(rawArgs);\n const entry = backgroundProcess(input.process_id);\n const stdoutOffset = input.stdout_offset ?? 0;\n const stderrOffset = input.stderr_offset ?? 0;\n const hasNews = () =>\n entry.exited ||\n entry.stdout.base + entry.stdout.size > stdoutOffset ||\n entry.stderr.base + entry.stderr.size > stderrOffset;\n const waitMs = Math.min(input.wait_ms ?? 0, 30_000);\n if (waitMs > 0 && !hasNews()) {\n await new Promise<void>((resolve) => {\n const done = () => {\n clearTimeout(timer);\n entry.changed.delete(listener);\n signal?.removeEventListener('abort', done);\n resolve();\n };\n const listener = () => {\n if (hasNews()) done();\n };\n const timer = setTimeout(done, waitMs);\n entry.changed.add(listener);\n signal?.addEventListener('abort', done, { once: true });\n });\n }\n const maxBytes = input.max_bytes ?? 65_536;\n if (entry.exited) entry.exitSeen = true;\n return jsonResult({\n stdout: readOutput(entry.stdout, stdoutOffset, maxBytes),\n stderr: readOutput(entry.stderr, stderrOffset, maxBytes),\n running: !entry.exited,\n exit_code: entry.exitCode,\n });\n }\n case SandboxMcpTool.ProcessInput: {\n const input = processInputArgsSchema.parse(rawArgs);\n const entry = backgroundProcess(input.process_id);\n await entry.process.write(input.data ?? '', { end: input.end === true });\n return jsonResult({ written: input.data?.length ?? 0, stdin_closed: input.end === true });\n }\n case SandboxMcpTool.ProcessTerminate: {\n const input = processTerminateArgsSchema.parse(rawArgs);\n const entry = backgroundProcess(input.process_id);\n entry.exitSeen = true;\n await entry.process.kill(input.signal);\n const result = await entry.process.wait().catch(() => ({ exitCode: entry.exitCode ?? -1 }));\n processes.delete(input.process_id);\n return jsonResult({ process_id: input.process_id, exit_code: result.exitCode });\n }\n case SandboxMcpTool.ReadFile: {\n const input = readFileArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const path = resolvePosixPath(sandbox.defaultWorkingDirectory, input.path);\n const stat = await sandbox.stat({ path, abortSignal: signal });\n if (stat == null) return errorResult(`${path}: no such file`);\n if (stat.type === SandboxEntryType.Directory)\n return errorResult(`${path} is a directory; use list_dir`);\n const link = {\n type: 'resource_link' as const,\n uri: `${SANDBOX_FILE_RESOURCE_SCHEME}://${encodeURI(path)}`,\n name: path.split('/').pop() ?? path,\n size: stat.size,\n };\n const ranged = input.offset != null || input.limit != null;\n const startLine = input.offset ?? 1;\n const endLine = input.limit == null ? undefined : startLine + input.limit - 1;\n if (!ranged && stat.size > limits.maxInlineBytes) {\n const head =\n (await sandbox.readTextFile({\n path,\n startLine: 1,\n endLine: 200,\n abortSignal: signal,\n })) ?? '';\n return {\n content: [\n {\n type: 'text',\n text: `${path} is ${stat.size} bytes, too large to return whole. First 200 lines below; read more with offset and limit, or fetch the resource.\\n\\n${truncateMiddle(head, limits.maxOutputChars)}`,\n },\n link,\n ],\n };\n }\n const text = await sandbox.readTextFile({\n path,\n startLine: ranged ? startLine : undefined,\n endLine,\n abortSignal: signal,\n });\n if (text == null) return errorResult(`${path}: no such file`);\n if (text.includes('\\u0000')) {\n return {\n content: [\n { type: 'text', text: `${path} is a binary file (${stat.size} bytes).` },\n link,\n ],\n };\n }\n return textResult(\n truncateMiddle(text, Math.max(limits.maxOutputChars, limits.maxInlineBytes)),\n );\n }\n case SandboxMcpTool.WriteFile: {\n const input = writeFileArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const path = resolvePosixPath(sandbox.defaultWorkingDirectory, input.path);\n await sandbox.writeTextFile({ path, content: input.content, abortSignal: signal });\n return textResult(\n `Wrote ${new TextEncoder().encode(input.content).byteLength} bytes to ${path}`,\n );\n }\n case SandboxMcpTool.EditFile: {\n const input = editFileArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const path = resolvePosixPath(sandbox.defaultWorkingDirectory, input.path);\n const text = await sandbox.readTextFile({ path, abortSignal: signal });\n if (text == null) return errorResult(`${path}: no such file`);\n const count = text.split(input.old_string).length - 1;\n if (count === 0) return errorResult(`old_string was not found in ${path}`);\n if (count > 1 && input.replace_all !== true) {\n return errorResult(\n `old_string occurs ${count} times in ${path}; add surrounding context or set replace_all`,\n );\n }\n const next =\n input.replace_all === true\n ? text.split(input.old_string).join(input.new_string)\n : text.replace(input.old_string, () => input.new_string);\n await sandbox.writeTextFile({ path, content: next, abortSignal: signal });\n return textResult(\n `Replaced ${input.replace_all === true ? count : 1} occurrence(s) in ${path}`,\n );\n }\n case SandboxMcpTool.ListDir: {\n const input = listDirArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const path = resolvePosixPath(sandbox.defaultWorkingDirectory, input.path ?? '.');\n const entries = await sandbox.readDir({ path, abortSignal: signal });\n return jsonResult({\n path,\n entries: entries.map((entry) => ({\n name: entry.name,\n type: entry.type,\n size: entry.size,\n })),\n });\n }\n case SandboxMcpTool.Stat: {\n const input = pathArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const path = resolvePosixPath(sandbox.defaultWorkingDirectory, input.path);\n const stat = await sandbox.stat({ path, abortSignal: signal });\n return jsonResult(stat == null ? { path, exists: false } : { exists: true, ...stat });\n }\n case SandboxMcpTool.Grep: {\n const input = grepArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const result = await grepFiles({\n sandbox,\n cwd: sandbox.defaultWorkingDirectory,\n pattern: input.pattern,\n path: input.path,\n glob: input.glob,\n ignoreCase: input.ignore_case,\n maxResults: input.max_results ?? 200,\n signal,\n });\n const lines = result.matches.map((match) => `${match.path}:${match.line}:${match.text}`);\n if (result.truncated) lines.push('[results truncated]');\n return textResult(lines.length === 0 ? 'No matches.' : lines.join('\\n'));\n }\n case SandboxMcpTool.Glob: {\n const input = globArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const result = await globFiles({\n sandbox,\n cwd: sandbox.defaultWorkingDirectory,\n pattern: input.pattern,\n path: input.path,\n maxResults: input.max_results ?? 500,\n signal,\n });\n const lines = [...result.paths];\n if (result.truncated) lines.push('[results truncated]');\n return textResult(lines.length === 0 ? 'No files matched.' : lines.join('\\n'));\n }\n case SandboxMcpTool.GetHost: {\n const input = getHostArgsSchema.parse(rawArgs);\n const sandbox = await sandboxFor();\n const endpoint = await sandbox.getPortEndpoint({\n port: input.port,\n protocol: input.protocol,\n });\n return jsonResult({ url: endpoint.url, headers: endpoint.headers ?? {} });\n }\n default:\n return errorResult(`unknown tool ${name}`);\n }\n };\n\n const callTool = async (\n name: string,\n rawArgs: JsonObject,\n signal?: AbortSignal,\n ): Promise<CallToolResult> => {\n const spec = byName.get(name);\n if (spec == null) return errorResult(`unknown tool ${name}`);\n if (!(await isAllowed(spec, name, rawArgs))) return errorResult(`${name} was not approved`);\n try {\n if (spec.hosted != null) {\n try {\n return await connections.call(spec.hosted.server, spec.hosted.tool.name, rawArgs);\n } finally {\n // Also after a failure: a stale tool name is how a changed catalog shows.\n checkCatalog(spec.hosted.server);\n }\n }\n return await run(name, rawArgs, signal);\n } catch (error) {\n if (error instanceof z.ZodError)\n return errorResult(`invalid arguments: ${z.prettifyError(error)}`);\n return errorResult(error instanceof Error ? error.message : String(error));\n }\n };\n\n const readResource = async (uri: URL): Promise<ReadResourceResult> => {\n const path = decodeURI(uri.pathname);\n const spec = byName.get(SandboxMcpTool.ReadFile);\n if (spec == null || !(await isAllowed(spec, SandboxMcpTool.ReadFile, { path })))\n throw new Error(`${path}: file read was not approved`);\n const sandbox = await sandboxFor();\n const bytes = await sandbox.readBinaryFile({ path });\n if (bytes == null) throw new Error(`${path}: no such file`);\n const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes);\n if (!text.includes('\\u0000') && !text.includes('\uFFFD')) {\n return { contents: [{ uri: uri.href, mimeType: 'text/plain', text }] };\n }\n return {\n contents: [\n { uri: uri.href, mimeType: 'application/octet-stream', blob: bytesToBase64(bytes) },\n ],\n };\n };\n\n const buildServer = (): McpServer => {\n const server = new McpServer(\n { name: args.name ?? 'final-sandbox', version: args.version ?? '1' },\n // The hosted servers' tools can follow the first list (see beforeList).\n {\n capabilities: {\n tools: { listChanged: served.computerUse || served.localMcp },\n resources: {},\n },\n },\n );\n for (const spec of specs) {\n server.registerTool(\n spec.descriptor.name,\n {\n title: spec.descriptor.annotations?.title,\n description: spec.descriptor.description,\n inputSchema: fromJsonSchema<JsonObject>(spec.descriptor.inputSchema),\n annotations: spec.descriptor.annotations,\n },\n (input, ctx) => callTool(spec.descriptor.name, input, ctx.mcpReq.signal),\n );\n }\n if (args.capabilities.includes(SandboxCapability.Files)) {\n server.registerResource(\n 'sandbox-file',\n new ResourceTemplate(`${SANDBOX_FILE_RESOURCE_SCHEME}://{+path}`, { list: undefined }),\n { description: 'A file in the sandbox, by absolute path.' },\n (uri) => readResource(uri),\n );\n }\n return server;\n };\n\n const isListRequest = async (request: Request): Promise<boolean> => {\n if (request.method !== 'POST') return false;\n try {\n const body: unknown = await request.clone().json();\n return (Array.isArray(body) ? body : [body]).some(\n (message) => listRequestSchema.safeParse(message).success,\n );\n } catch {\n return false;\n }\n };\n\n const getHandler = () => {\n handler ??= createMcpHandler(() => buildServer(), { onerror: args.onError });\n return handler;\n };\n\n return {\n get descriptors() {\n return specs.map((spec) => spec.descriptor);\n },\n fetch: async (request) => {\n if (await isListRequest(request)) await beforeList();\n return getHandler().fetch(request);\n },\n listTools: () => specs.map((spec) => spec.descriptor),\n refreshTools: async () => {\n await beforeList(true);\n return specs.map((spec) => spec.descriptor);\n },\n updateCatalog: (next) => {\n mergeCatalog(next);\n },\n callTool,\n close: async () => {\n closed = true;\n await shell.close();\n for (const entry of processes.values()) await entry.process.kill().catch(() => undefined);\n processes.clear();\n await connections.close();\n await handler?.close();\n },\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["SandboxHostedServerKind", "SandboxShellMode", "SandboxMcpTool", "SandboxMcpScopeKind", "id", "entry"]
7
+ }
@@ -0,0 +1,32 @@
1
+ import type { JsonValue } from "../json.mjs";
2
+ import { PortProtocol, type NetworkPolicyIface, type NetworkSandboxSessionIface, type SandboxMcpEndpoint } from "./types.mjs";
3
+ export interface MemorySandboxIface extends NetworkSandboxSessionIface {
4
+ readonly networkPolicy: NetworkPolicyIface;
5
+ readonly stopped: boolean;
6
+ }
7
+ export interface CreateMemorySandboxArgsIface {
8
+ id?: string;
9
+ files?: Record<string, string | Uint8Array>;
10
+ cwd?: string;
11
+ ports?: number[];
12
+ portUrl?: (args: {
13
+ port: number;
14
+ protocol: PortProtocol;
15
+ }) => string;
16
+ computerUse?: () => Promise<SandboxMcpEndpoint>;
17
+ screen?: NetworkSandboxSessionIface['screen'];
18
+ localMcp?: () => Promise<SandboxMcpEndpoint[]>;
19
+ networkPolicy?: boolean;
20
+ now?: () => Date;
21
+ }
22
+ export declare const createMemorySandbox: (args?: CreateMemorySandboxArgsIface) => MemorySandboxIface;
23
+ export declare const memorySandboxTextFiles: (sandbox: NetworkSandboxSessionIface, root?: string) => Promise<Record<string, string>>;
24
+ export type MemorySandboxArtifact = {
25
+ files: Record<string, string>;
26
+ cwd: string;
27
+ ports: number[];
28
+ };
29
+ export type MemorySandboxState = {
30
+ id: string;
31
+ };
32
+ export declare const memorySandboxProvider: import("./types.mjs").SandboxProviderIface<JsonValue, JsonValue, MemorySandboxArtifact, MemorySandboxState, MemorySandboxIface>;
@@ -0,0 +1,416 @@
1
+ import * as z from "zod";
2
+ import { encodeSandboxText, readAllBytes, utf8Encode } from "./bytes.mjs";
3
+ import { readTextFileStream, runCollect } from "./convenience.mjs";
4
+ import { runMemoryArgv, runMemoryScript } from "./memory-shell.mjs";
5
+ import { normalizePosixPath, posixDirname, resolvePosixPath } from "./paths.mjs";
6
+ import {
7
+ defineSandboxProvider,
8
+ NetworkPolicy,
9
+ PortProtocol,
10
+ SandboxEntryType
11
+ } from "./types.mjs";
12
+ const fsError = (code, message) => Object.assign(new Error(`${code}: ${message}`), { code });
13
+ const abortableSleep = (ms, signal) => new Promise((resolve, reject) => {
14
+ if (signal.aborted) {
15
+ reject(signal.reason);
16
+ return;
17
+ }
18
+ const timer = setTimeout(() => {
19
+ signal.removeEventListener("abort", onAbort);
20
+ resolve();
21
+ }, ms);
22
+ const onAbort = () => {
23
+ clearTimeout(timer);
24
+ reject(signal.reason);
25
+ };
26
+ signal.addEventListener("abort", onAbort, { once: true });
27
+ });
28
+ const signalExitCode = (signal) => {
29
+ if (signal === "SIGKILL" || signal === "KILL" || signal === "9") return 137;
30
+ if (signal === "SIGINT" || signal === "INT") return 130;
31
+ return 143;
32
+ };
33
+ const createMemorySandbox = (args = {}) => {
34
+ const id = args.id ?? `memory-${crypto.randomUUID()}`;
35
+ const cwd = normalizePosixPath(args.cwd ?? "/workspace");
36
+ const now = args.now ?? (() => /* @__PURE__ */ new Date());
37
+ const entries = /* @__PURE__ */ new Map();
38
+ const processes = /* @__PURE__ */ new Set();
39
+ let networkPolicy = { mode: NetworkPolicy.AllowAll };
40
+ let stopped = false;
41
+ const resolve = (path) => resolvePosixPath(cwd, path);
42
+ const ensureDirectory = (path) => {
43
+ const normalized = normalizePosixPath(path);
44
+ const existing = entries.get(normalized);
45
+ if (existing?.type === "directory") return;
46
+ if (existing?.type === "file") throw fsError("ENOTDIR", `${normalized} is a file`);
47
+ if (normalized !== "/") ensureDirectory(posixDirname(normalized));
48
+ entries.set(normalized, { type: "directory", modifiedAt: now() });
49
+ };
50
+ const putFile = (path, data) => {
51
+ const normalized = normalizePosixPath(path);
52
+ if (entries.get(normalized)?.type === "directory")
53
+ throw fsError("EISDIR", `${normalized} is a directory`);
54
+ ensureDirectory(posixDirname(normalized));
55
+ entries.set(normalized, { type: "file", data, modifiedAt: now() });
56
+ };
57
+ const children = (path) => {
58
+ const prefix = path === "/" ? "/" : `${path}/`;
59
+ const names = [];
60
+ for (const key of entries.keys()) {
61
+ if (key !== path && key.startsWith(prefix) && !key.slice(prefix.length).includes("/")) {
62
+ names.push(key.slice(prefix.length));
63
+ }
64
+ }
65
+ return names.sort();
66
+ };
67
+ ensureDirectory("/");
68
+ ensureDirectory(cwd);
69
+ for (const [path, content] of Object.entries(args.files ?? {})) {
70
+ putFile(resolve(path), content instanceof Uint8Array ? content : utf8Encode(content));
71
+ }
72
+ const shellFs = {
73
+ readFile: (path) => {
74
+ const entry = entries.get(normalizePosixPath(path));
75
+ return entry?.type === "file" ? entry.data : null;
76
+ },
77
+ writeFile: (path, data, options) => {
78
+ const entry = entries.get(normalizePosixPath(path));
79
+ if (options.append && entry?.type === "file") {
80
+ const merged = new Uint8Array(entry.data.byteLength + data.byteLength);
81
+ merged.set(entry.data, 0);
82
+ merged.set(data, entry.data.byteLength);
83
+ putFile(path, merged);
84
+ return;
85
+ }
86
+ putFile(path, data);
87
+ },
88
+ kind: (path) => {
89
+ const entry = entries.get(normalizePosixPath(path));
90
+ return entry == null ? null : entry.type;
91
+ },
92
+ list: (path) => {
93
+ const normalized = normalizePosixPath(path);
94
+ return entries.get(normalized)?.type === "directory" ? children(normalized) : null;
95
+ },
96
+ mkdir: (path, options) => {
97
+ const normalized = normalizePosixPath(path);
98
+ if (!options.parents && entries.get(posixDirname(normalized))?.type !== "directory") {
99
+ throw fsError("ENOENT", "No such file or directory");
100
+ }
101
+ if (!options.parents && entries.has(normalized)) throw fsError("EEXIST", "File exists");
102
+ ensureDirectory(normalized);
103
+ }
104
+ };
105
+ const statOf = (path) => {
106
+ const entry = entries.get(path);
107
+ if (entry == null) return null;
108
+ return {
109
+ path,
110
+ type: entry.type === "file" ? SandboxEntryType.File : SandboxEntryType.Directory,
111
+ size: entry.type === "file" ? entry.data.byteLength : 0,
112
+ modifiedAt: entry.modifiedAt.toISOString(),
113
+ mode: entry.type === "file" ? 420 : 493
114
+ };
115
+ };
116
+ const spawn = async (options) => {
117
+ const controller = new AbortController();
118
+ let killedWith = null;
119
+ const outputs = { stdout: null, stderr: null };
120
+ const stdout = new ReadableStream({
121
+ start: (c) => {
122
+ outputs.stdout = c;
123
+ }
124
+ });
125
+ const stderr = new ReadableStream({
126
+ start: (c) => {
127
+ outputs.stderr = c;
128
+ }
129
+ });
130
+ let self = null;
131
+ let stdinWriter = null;
132
+ let stdinSource;
133
+ if (options.stdin == null) {
134
+ const pipe = new TransformStream();
135
+ stdinWriter = pipe.writable.getWriter();
136
+ stdinSource = pipe.readable;
137
+ } else if (options.stdin instanceof ReadableStream) {
138
+ stdinSource = options.stdin;
139
+ } else {
140
+ const bytes = utf8Encode(options.stdin);
141
+ stdinSource = new ReadableStream({
142
+ start: (c) => {
143
+ if (bytes.byteLength > 0) c.enqueue(bytes);
144
+ c.close();
145
+ }
146
+ });
147
+ }
148
+ const stdinReader = stdinSource.getReader();
149
+ const abortPromise = new Promise(
150
+ (resolveAbort) => controller.signal.addEventListener("abort", () => resolveAbort(null), { once: true })
151
+ );
152
+ const readStdin = async () => {
153
+ const result = await Promise.race([stdinReader.read(), abortPromise]);
154
+ if (result == null) throw controller.signal.reason;
155
+ return result.done ? null : result.value;
156
+ };
157
+ const emit = (target, bytes) => {
158
+ if (bytes.byteLength > 0) target?.enqueue(bytes.slice());
159
+ };
160
+ const context = {
161
+ fs: shellFs,
162
+ io: {
163
+ readStdin,
164
+ stdout: (bytes) => emit(outputs.stdout, bytes),
165
+ stderr: (bytes) => emit(outputs.stderr, bytes),
166
+ signal: controller.signal
167
+ },
168
+ cwd: options.cwd == null ? cwd : resolve(options.cwd),
169
+ sleep: abortableSleep
170
+ };
171
+ const timeout = options.timeoutMs == null ? null : setTimeout(() => {
172
+ killedWith = "timeout";
173
+ controller.abort(new Error("timed out"));
174
+ }, options.timeoutMs);
175
+ const onAbortSignal = () => {
176
+ killedWith ??= "SIGTERM";
177
+ controller.abort(new Error("aborted"));
178
+ };
179
+ options.abortSignal?.addEventListener("abort", onAbortSignal, { once: true });
180
+ const exited = (async () => {
181
+ let exitCode;
182
+ try {
183
+ if (context.fs.kind(context.cwd) !== "directory") {
184
+ context.io.stderr(utf8Encode(`cd: ${context.cwd}: No such file or directory
185
+ `));
186
+ exitCode = 1;
187
+ } else if (options.shell === true) {
188
+ const script = [options.command, ...options.args ?? []].join(" ");
189
+ exitCode = await runMemoryScript({ ...context, script });
190
+ } else {
191
+ exitCode = await runMemoryArgv({
192
+ ...context,
193
+ argv: [options.command, ...options.args ?? []]
194
+ });
195
+ }
196
+ } catch (error) {
197
+ if (!controller.signal.aborted) {
198
+ context.io.stderr(
199
+ utf8Encode(`${error instanceof Error ? error.message : String(error)}
200
+ `)
201
+ );
202
+ exitCode = 1;
203
+ } else {
204
+ exitCode = killedWith === "timeout" ? 124 : signalExitCode(killedWith ?? void 0);
205
+ }
206
+ }
207
+ if (timeout != null) clearTimeout(timeout);
208
+ options.abortSignal?.removeEventListener("abort", onAbortSignal);
209
+ stdinReader.cancel().catch(() => void 0);
210
+ outputs.stdout?.close();
211
+ outputs.stderr?.close();
212
+ if (self != null) processes.delete(self);
213
+ return { exitCode };
214
+ })();
215
+ const child = {
216
+ pid: null,
217
+ stdout,
218
+ stderr,
219
+ write: async (data, writeOptions) => {
220
+ if (stdinWriter == null) throw new Error("stdin was provided at spawn");
221
+ const bytes = data instanceof Uint8Array ? data : utf8Encode(data);
222
+ if (bytes.byteLength > 0) await stdinWriter.write(bytes);
223
+ if (writeOptions?.end === true) await stdinWriter.close();
224
+ },
225
+ wait: () => exited,
226
+ kill: async (signal) => {
227
+ killedWith ??= signal ?? "SIGTERM";
228
+ controller.abort(new Error(`killed (${signal ?? "SIGTERM"})`));
229
+ await exited;
230
+ }
231
+ };
232
+ self = child;
233
+ processes.add(child);
234
+ return child;
235
+ };
236
+ const sandbox = {
237
+ id,
238
+ defaultWorkingDirectory: cwd,
239
+ ports: args.ports ?? [],
240
+ get description() {
241
+ return `In-memory sandbox ${id}. Working directory ${cwd}. Commands: echo, cat, ls, pwd, cd, true, false, sleep, exit, mkdir, sh -c.`;
242
+ },
243
+ get networkPolicy() {
244
+ return networkPolicy;
245
+ },
246
+ get stopped() {
247
+ return stopped;
248
+ },
249
+ readFile: async (options) => {
250
+ const path = resolve(options.path);
251
+ const entry = entries.get(path);
252
+ if (entry == null) return null;
253
+ if (entry.type === "directory") throw fsError("EISDIR", `${path} is a directory`);
254
+ const data = entry.data;
255
+ const chunkBytes = 64 * 1024;
256
+ let offset = 0;
257
+ return new ReadableStream({
258
+ pull: (controller) => {
259
+ if (offset >= data.byteLength) {
260
+ controller.close();
261
+ return;
262
+ }
263
+ const end = Math.min(data.byteLength, offset + chunkBytes);
264
+ controller.enqueue(data.slice(offset, end));
265
+ offset = end;
266
+ }
267
+ });
268
+ },
269
+ readBinaryFile: async (options) => {
270
+ const stream = await sandbox.readFile(options);
271
+ return stream == null ? null : readAllBytes(stream);
272
+ },
273
+ readTextFile: async (options) => {
274
+ const stream = await sandbox.readFile(options);
275
+ return stream == null ? null : readTextFileStream(stream, options);
276
+ },
277
+ writeFile: async (options) => {
278
+ const data = await readAllBytes(options.content);
279
+ putFile(resolve(options.path), data);
280
+ },
281
+ writeBinaryFile: async (options) => {
282
+ putFile(resolve(options.path), options.content.slice());
283
+ },
284
+ writeTextFile: async (options) => {
285
+ putFile(resolve(options.path), encodeSandboxText(options.content, options.encoding));
286
+ },
287
+ spawn,
288
+ run: (options) => runCollect({ spawn }, options),
289
+ stat: async (options) => statOf(resolve(options.path)),
290
+ readDir: async (options) => {
291
+ const path = resolve(options.path);
292
+ const entry = entries.get(path);
293
+ if (entry == null) throw fsError("ENOENT", `${path}: No such file or directory`);
294
+ if (entry.type !== "directory") throw fsError("ENOTDIR", `${path} is not a directory`);
295
+ return children(path).map((name) => {
296
+ const childPath = path === "/" ? `/${name}` : `${path}/${name}`;
297
+ const child = entries.get(childPath);
298
+ return {
299
+ name,
300
+ path: childPath,
301
+ type: child?.type === "file" ? SandboxEntryType.File : SandboxEntryType.Directory,
302
+ size: child?.type === "file" ? child.data.byteLength : null
303
+ };
304
+ });
305
+ },
306
+ resolvePath: resolve,
307
+ removePath: async (options) => {
308
+ const path = resolve(options.path);
309
+ const entry = entries.get(path);
310
+ if (entry == null) {
311
+ if (options.force === true) return;
312
+ throw fsError("ENOENT", `${path}: No such file or directory`);
313
+ }
314
+ if (path === "/") throw fsError("EPERM", "refusing to remove /");
315
+ if (entry.type === "directory") {
316
+ const prefix = `${path}/`;
317
+ const nested = [...entries.keys()].filter((key) => key.startsWith(prefix));
318
+ if (nested.length > 0 && options.recursive !== true)
319
+ throw fsError("ENOTEMPTY", `${path}: Directory not empty`);
320
+ for (const key of nested) entries.delete(key);
321
+ }
322
+ entries.delete(path);
323
+ },
324
+ getPortEndpoint: async (options) => {
325
+ const protocol = options.protocol ?? PortProtocol.Http;
326
+ return {
327
+ url: args.portUrl?.({ port: options.port, protocol }) ?? `${protocol}://127.0.0.1:${options.port}`
328
+ };
329
+ },
330
+ getPortUrl: async (options) => (await sandbox.getPortEndpoint(options)).url,
331
+ stop: async () => {
332
+ stopped = true;
333
+ await Promise.all([...processes].map((child) => child.kill()));
334
+ },
335
+ destroy: async () => {
336
+ await sandbox.stop();
337
+ entries.clear();
338
+ ensureDirectory("/");
339
+ }
340
+ };
341
+ if (args.networkPolicy === true) {
342
+ sandbox.setNetworkPolicy = async (policy) => {
343
+ networkPolicy = policy;
344
+ };
345
+ }
346
+ if (args.computerUse != null) sandbox.computerUse = args.computerUse;
347
+ if (args.screen != null) sandbox.screen = args.screen;
348
+ if (args.localMcp != null) sandbox.localMcp = args.localMcp;
349
+ return sandbox;
350
+ };
351
+ const memorySandboxTextFiles = async (sandbox, root = "/") => {
352
+ const out = {};
353
+ const walk = async (path) => {
354
+ for (const entry of await sandbox.readDir({ path })) {
355
+ if (entry.type === SandboxEntryType.Directory) await walk(entry.path);
356
+ else {
357
+ const text = await sandbox.readTextFile({ path: entry.path });
358
+ if (text != null) out[entry.path] = text;
359
+ }
360
+ }
361
+ };
362
+ await walk(root);
363
+ return out;
364
+ };
365
+ const memoryEnvironmentSchema = z.object({
366
+ files: z.record(z.string(), z.string()).optional(),
367
+ cwd: z.string().optional(),
368
+ ports: z.array(z.number().int()).optional()
369
+ }).nullable().optional();
370
+ const fingerprint = (value) => {
371
+ let hash = 2166136261;
372
+ for (let i = 0; i < value.length; i += 1) {
373
+ hash ^= value.charCodeAt(i);
374
+ hash = Math.imul(hash, 16777619) >>> 0;
375
+ }
376
+ return hash.toString(16).padStart(8, "0");
377
+ };
378
+ const memoryHandle = (sandbox) => ({
379
+ sandbox,
380
+ onSandboxStop: () => sandbox.stop(),
381
+ onSandboxDelete: () => sandbox.destroy(),
382
+ onRuntimeShutdown: () => sandbox.stop()
383
+ });
384
+ const memorySandboxProvider = defineSandboxProvider({
385
+ name: "memory",
386
+ environment: (rawOptions) => {
387
+ const options = memoryEnvironmentSchema.parse(rawOptions) ?? {};
388
+ const artifactFor = (files) => ({
389
+ files: { ...options.files, ...files },
390
+ cwd: options.cwd ?? "/workspace",
391
+ ports: options.ports ?? []
392
+ });
393
+ const open = (bindingId, artifact) => createMemorySandbox({
394
+ id: bindingId,
395
+ files: artifact.files,
396
+ cwd: artifact.cwd,
397
+ ports: artifact.ports
398
+ });
399
+ return {
400
+ artifactKey: async (ctx) => `memory:${fingerprint(JSON.stringify(artifactFor(ctx.files)))}`,
401
+ prepare: async (ctx) => artifactFor(ctx.files),
402
+ start: async (ctx, _openOptions, artifact) => ({
403
+ handle: memoryHandle(open(ctx.session.bindingId, artifact)),
404
+ state: { id: ctx.session.bindingId }
405
+ }),
406
+ resume: async (_ctx, artifact, state) => memoryHandle(open(state.id, artifact)),
407
+ park: async (_ctx, _artifact, state) => state
408
+ };
409
+ }
410
+ });
411
+ export {
412
+ createMemorySandbox,
413
+ memorySandboxProvider,
414
+ memorySandboxTextFiles
415
+ };
416
+ //# sourceMappingURL=memory-sandbox.mjs.map