
OpenSandbox C# Code Interpreter SDK在 .NET 应用中安全执行多语言代码的完整实践【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandboxOpenSandbox 的 Code Interpreter C# SDK 让 .NET 应用能够在安全沙箱中执行 Python、JavaScript、TypeScript、Go、Java、Bash 代码并原生支持上下文状态保持、流式输出与执行中断。读完本文你将掌握从安装包、创建沙箱到多语言执行、上下文管理、SSE 流式事件的完整调用链路并理解 SDK 内置的严格健康检查为何比单纯的 daemon ping 更可靠。一、前置条件运行时代码解释器镜像该 SDK 依赖一个包含 Code Interpreter 运行时的 Docker 镜像。沙箱必须使用opensandbox/code-interpreter或其衍生镜像创建其中预装了 Python、Java、Go、Node.js 等运行时。创建沙箱时需指定固定的入口脚本/opt/code-interpreter/code-interpreter.sh语言版本选择通过创建沙箱时的环境变量指定各语言运行时版本未设置时使用镜像默认版本语言环境变量示例值默认未设置时PythonPYTHON_VERSION3.11镜像默认JavaJAVA_VERSION17镜像默认Node.jsNODE_VERSION20镜像默认GoGO_VERSION1.24镜像默认安装dotnet add package Alibaba.OpenSandbox.CodeInterpreter环境要求.NET Standard 2.0 / .NET 6.0并依赖 OpenSandbox Sandbox SDKAlibaba.OpenSandbox。二、Quick Start创建沙箱并执行第一段代码以下示例演示了标准工作流建立连接 → 用 code-interpreter 镜像创建沙箱 → 包装为 CodeInterpreter → 执行 Python 代码并读取输出using OpenSandbox; using OpenSandbox.CodeInterpreter; using OpenSandbox.CodeInterpreter.Models; using OpenSandbox.Config; using OpenSandbox.Core; var config new ConnectionConfig(new ConnectionConfigOptions { Domain api.opensandbox.io, ApiKey your-api-key }); try { // 使用 code-interpreter 运行时镜像与入口脚本创建沙箱。 await using var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image opensandbox/code-interpreter:v1.1.0, Entrypoint new[] { /opt/code-interpreter/code-interpreter.sh }, Env new Dictionarystring, string { [PYTHON_VERSION] 3.11, [JAVA_VERSION] 17, [NODE_VERSION] 20, [GO_VERSION] 1.24 }, TimeoutSeconds 15 * 60 }); var interpreter await CodeInterpreter.CreateAsync(sandbox); var execution await interpreter.Codes.RunAsync( print(Hello, World!), new RunCodeOptions { Language SupportedLanguage.Python }); foreach (var msg in execution.Logs.Stdout) { Console.Write(msg.Text); } await sandbox.KillAsync(); } catch (SandboxException ex) { Console.Error.WriteLine($Sandbox Error: [{ex.Error.Code}] {ex.Error.Message}); }几个关键设计点在源码中可以得到印证CodeInterpreter是薄封装门面不拥有远端生命周期。从 CodeInterpreter.cs 的类注释与属性定义看Files、Commands、Metrics属性直接转发到底层Sandbox的同名服务实例DisposeAsync只清理本地资源终止远端沙箱必须显式调用Sandbox.KillAsync()。连接走沙箱自己的 execd 端点。CreateAsync内部通过sandbox.GetEndpointAsync(Constants.DefaultExecdPort)解析端点其中DefaultExecdPort为 44772定义于 Constants.cs并有测试 ConstantsTests.cs 锁定该值。协议按ConnectionConfig.Protocol决定 http/https端点返回的 headers 会与连接配置的 headers 合并见 CodeInterpreter.cs。三、严格健康检查为什么 execd 的 /ping 还不够CodeInterpreter.CreateAsync默认会阻塞直到解释器严格就绪超时则抛出SandboxReadyTimeoutException。默认参数为ReadyTimeoutSeconds 30、轮询间隔 200ms分别对应 Constants.cs 中的DefaultReadyTimeoutSeconds与DefaultHealthCheckPollingIntervalMillis。一次探测被视为健康需要同一轮探测中两个条件同时通过execd 应答GET /ping代码执行服务在解释器自己的端点上响应解释器运行时Jupyter kernel gateway正在沙箱内提供服务SDK 通过 execd 命令 API 在沙箱内部探测其监听端口127.0.0.1:44771可用环境变量JUPYTER_PORT覆盖。第二项检查的实现是一条 bash 端口探测命令定义在 CodeInterpreter.cspublic const string RuntimeCheckCommand bash -c exec 3/dev/tcp/127.0.0.1/${JUPYTER_PORT:-44771} exit 0 || exit 1;源码注释CodeInterpreter.cs解释了为什么不能用更简单的信号替代execd 在入口脚本启动 Jupyter 之前就开始服务/ping且初始化阶段可能出现短暂的jupyter kernelspec辅助进程——因此daemon ping或进程名 grep都无法证明运行时真正就绪只有当服务器接受 TCP 连接时端口探测才会通过。该检查无条件生效与沙箱自身的就绪设置SkipHealthCheck true、池化获取、resume无关。自定义检查行为与按需复查var interpreter await CodeInterpreter.CreateAsync(sandbox, new CodeInterpreterCreateOptions { ReadyTimeoutSeconds 60, // 可选 HealthCheckPollingInterval 200, // 可选毫秒 SkipHealthCheck false // 设为 true 可跳过 }); // 随时重新执行一次健康检查 Console.WriteLine(await interpreter.IsHealthyAsync());SkipHealthCheck true将就绪判断交给调用方例如自行管理健康检查的池化预热场景此时解释器在首次使用时可能失败。CodeInterpreterCreateOptions的完整字段见 CodeInterpreter.csAdapterFactory可注入自定义适配器工厂默认使用DefaultCodeInterpreterAdapterFactory见 DefaultCodeInterpreterAdapterFactory.cs、Diagnostics、SkipHealthCheck、ReadyTimeoutSeconds、HealthCheckPollingInterval。健康检查逻辑有完整的单元测试覆盖例如 CodeInterpreterHealthCheckTests.cs 中的用例验证了两个检查腿必须在同一轮同时通过ping 先失败两次、运行时检查再失败两次共 5 轮才就绪运行时永不出现时抛出SandboxReadyTimeoutException运行时确实执行了RuntimeCheckCommand端口探测脚本。等待循环本身CodeInterpreter.cs用Stopwatch控制总预算每次失败记录errorDetail供超时异常信息引用轮询间隔会自动收敛到剩余预算内并全程尊重CancellationToken。四、日志集成ILoggerSDK 基于Microsoft.Extensions.Logging抽象。创建沙箱与解释器时可以通过Diagnostics选项注入自己的ILoggerFactoryusing Microsoft.Extensions.Logging; using OpenSandbox.Config; using var loggerFactory LoggerFactory.Create(builder { builder.SetMinimumLevel(LogLevel.Debug); builder.AddConsole(); }); await using var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig new ConnectionConfig(), Image opensandbox/code-interpreter:v1.1.0, Entrypoint new[] { /opt/code-interpreter/code-interpreter.sh }, Diagnostics new SdkDiagnosticsOptions { LoggerFactory loggerFactory } }); var interpreter await CodeInterpreter.CreateAsync(sandbox, new CodeInterpreterCreateOptions { Diagnostics new SdkDiagnosticsOptions { LoggerFactory loggerFactory } });从源码看CreateAsync中日志工厂的解析优先级是options.Diagnostics.LoggerFactory→sandbox.SharedLoggerFactory→NullLoggerFactory.InstanceCodeInterpreter.cs因此即使不显式配置也不会抛空引用只是静默不输出。五、执行模型默认语言上下文与显式上下文5.1 用Language走默认语言上下文不需要显式 context ID 时只需在RunCodeOptions中设置Language。当Context省略时execd 会为该语言创建/复用一个默认会话因此状态可以跨多次RunAsync调用持久化await interpreter.Codes.RunAsync( x 42, new RunCodeOptions { Language SupportedLanguage.Python }); var execution await interpreter.Codes.RunAsync( result x\nresult, new RunCodeOptions { Language SupportedLanguage.Python }); Console.WriteLine(execution.Results.FirstOrDefault()?.Text); // 42这一行为在适配器层有直接实现RunAsync在Context为空时用Language构造CodeContext若两者都未提供则回退到 PythonSupportedLanguage.Python为默认语言同时Context与Language互斥同时提供会抛出InvalidArgumentExceptionCodesAdapter.cs。RunCodeOptions的字段定义见 CodeModels.csContext可选执行上下文、Language用于新建临时上下文不可与Context同用、Handlers执行事件回调。5.2 支持的语言语言常量定义在 CodeModels.cs 的SupportedLanguage静态类中共六种常量值SupportedLanguage.PythonpythonSupportedLanguage.JavajavaSupportedLanguage.GogoSupportedLanguage.TypeScripttypescriptSupportedLanguage.JavaScriptjavascriptSupportedLanguage.Bashbash5.3 上下文管理Context显式创建上下文用于在多次执行之间保持状态以及按语言批量管理上下文生命周期// 为 Python 创建上下文 var context await interpreter.Codes.CreateContextAsync(SupportedLanguage.Python); // 在上下文中执行代码 - 变量会持久化 await interpreter.Codes.RunAsync(x 42, new RunCodeOptions { Context context }); var result await interpreter.Codes.RunAsync(print(x), new RunCodeOptions { Context context }); // 输出: 42 // 列出指定语言的上下文 var pythonContexts await interpreter.Codes.ListContextsAsync(SupportedLanguage.Python); // 删除某个具体上下文 await interpreter.Codes.DeleteContextAsync(context.Id!); // 删除某个语言的全部上下文 await interpreter.Codes.DeleteContextsAsync(SupportedLanguage.Python);从适配器实现看这些操作对应的 HTTP 端点分别为POST /code/context创建、GET /code/contexts/{id}查询、GET /code/contexts?language...列表、DELETE /code/contexts/{id}单个删除、DELETE /code/contexts?language...批量删除见 CodesAdapter.cs。所有ICodes方法均支持CancellationToken接口完整定义见 ICodes.cs。六、流式执行与事件回调6.1 SSE 流式执行RunStreamAsync直接消费服务端推送的 SSE 事件流。底层实现是向POST /code发送Accept: text/event-stream请求并用独立的 SSEHttpClient以ResponseHeadersRead模式逐事件解析CodesAdapter.csvar request new RunCodeRequest { Code for i in range(5): print(i), Context new CodeContext { Language SupportedLanguage.Python } }; await foreach (var ev in interpreter.Codes.RunStreamAsync(request)) { switch (ev.Type) { case stdout: Console.Write(ev.Text); break; case stderr: Console.Error.Write(ev.Text); break; case result: var text ev.Results ! null ev.Results.TryGetValue(text/plain, out var value) ? value?.ToString() : null; Console.WriteLine($Result: {text ?? (no text/plain)}); break; case error: Console.WriteLine($Error: {ev.Error}); break; } }事件类型为stdout、stderr、result、errorresult事件的Results是 MIME 类型到值的映射常用text/plain取文本结果。6.2 事件处理器HandlersRunAsync并非独立实现而是内部消费RunStreamAsync的同一个事件流再经ExecutionEventDispatcher分派到你注册的ExecutionHandlersCodesAdapter.cs最后把累积结果封装为Execution返回。因此一次执行既能拿到完整结果对象也能在过程中收到细粒度回调var execution await interpreter.Codes.RunAsync( print(Hello)\nprint(World), new RunCodeOptions { Language SupportedLanguage.Python, Handlers new ExecutionHandlers { OnStdout async msg Console.Write($[OUT] {msg.Text}), OnStderr async msg Console.Error.Write($[ERR] {msg.Text}), OnResult async result Console.WriteLine($[RESULT] {result.Text}), OnError async error Console.WriteLine($[ERROR] {error.Name}: {error.Value}), OnExecutionComplete async complete Console.WriteLine($[DONE] Took {complete.ExecutionTimeMs}ms) } });6.3 中断执行通过init事件获取 execution ID再调用InterruptAsync停止正在运行的代码var context await interpreter.Codes.CreateContextAsync(SupportedLanguage.Python); // 启动一个长任务 var executionId new TaskCompletionSourcestring(); var task interpreter.Codes.RunAsync( import time\nwhile True: time.sleep(1), new RunCodeOptions { Context context, Handlers new ExecutionHandlers { OnInit init { executionId.TrySetResult(init.Id); return Task.CompletedTask; } } }); // 一段时间后中断 await interpreter.Codes.InterruptAsync(await executionId.Task);InterruptAsync的底层实现是DELETE /code?id{executionId}CodesAdapter.csexecution ID 通常来自运行结果或init事件。七、访问底层沙箱服务CodeInterpreter门面直接暴露了底层沙箱的文件、命令与指标服务与Sandbox上是同一实例// 文件操作 await interpreter.Files.WriteFilesAsync(new[] { new WriteEntry { Path /tmp/data.txt, Data Hello, World! } }); var content await interpreter.Files.ReadFileAsync(/tmp/data.txt); // Shell 命令 var commandExecution await interpreter.Commands.RunAsync(ls -la /tmp); foreach (var msg in commandExecution.Logs.Stdout) { Console.Write(msg.Text); } // 资源指标 var metrics await interpreter.Sandbox.GetMetricsAsync(); Console.WriteLine($CPU: {metrics.CpuUsedPercentage}%, Memory: {metrics.MemoryUsedMiB}MiB);在 code 执行的同时做文件读写、Shell 命令和指标采集是构建代码沙箱 数据准备 结果验证类工作流的基础能力。八、API 速查表CodeInterpreter成员说明CreateAsync(sandbox, options?)从已有沙箱创建 code interpreter默认执行严格健康检查Sandbox底层沙箱实例Codes代码执行服务ICodesId沙箱 ID转发Sandbox.IdFiles文件系统操作CommandsShell 命令执行Metrics资源指标ICodes方法说明CreateContextAsync(language)创建新的执行上下文GetContextAsync(contextId)按 ID 获取上下文ListContextsAsync(language)列出指定语言的上下文DeleteContextAsync(contextId)删除指定上下文DeleteContextsAsync(language)删除指定语言的全部上下文RunAsync(code, options?)执行代码并返回完整结果RunStreamAsync(request)流式执行代码SSE 事件InterruptAsync(executionId)按 execution ID 中断运行中的执行所有异步方法均支持CancellationToken。九、生命周期与注意事项生命周期CodeInterpreter包装既有Sandbox复用其连接与服务实例不重复建立通道。默认上下文行为RunAsync(..., new RunCodeOptions { Language ... })使用该语言的默认上下文execd 侧创建/复用Language与Context二者只能取其一。清理DisposeAsync只释放本地 SDK 资源终止远端沙箱实例必须调用Sandbox.KillAsync()。健康检查权衡默认严格检查会带来最多ReadyTimeoutSeconds默认 30s的启动等待对自管就绪逻辑的池化场景可用SkipHealthCheck true换取消除该等待代价是首次调用可能失败。相关实现与测试路径便于深入阅读门面与健康检查CodeInterpreter.cs代码执行适配器HTTP/SSE 调用CodesAdapter.cs服务接口ICodes.cs模型与语言常量CodeModels.cs健康检查测试CodeInterpreterHealthCheckTests.cs本文内容基于 OpenSandbox 仓库当前版本的docs/sdks/code-interpreter/csharp.md文档与 C# SDK 源码整理SDK 遵循 Apache License 2.0。【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考