feat: add a .NET SDK
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
This is a design proposal for a new sdk/dotnet/ package built from the OpenShell gRPC service in proto/. Start with the draft's PARITY.md and README.md on the linked fork branch to see the proposed API and the feature gaps against the Go, Rust, TypeScript and Python SDKs. Done means maintainers agree on the scope, feed and ownership questions, and the work is split into the proposed PRs.
由索引模型根据 Issue 内容生成。
描述
User Story
As a C# developer, I want a first-party OpenShell SDK for .NET, so that I can create and manage sandboxes, run commands, and watch their state from C# applications with the same capabilities Rust, Go, TypeScript, and Python developers already have.
Problem Statement
OpenShell ships SDKs for Rust, Go, TypeScript, and Python. There is no .NET SDK, so the C# community has no supported way to use the gateway API beyond generating gRPC bindings from proto/ by hand.
Impact / Why This Matters
Each .NET team must generate and maintain its own bindings and re-implement what the other SDKs already provide: OIDC token renewal, mTLS, the Cloudflare Access tunnel, pagination, readiness and deletion waits, typed errors, and safe credential handling. The copies drift from the gateway and from each other. A first-party SDK built from the same proto/ directory removes that duplication and keeps client and gateway in step.
Proposed Design
Add sdk/dotnet/ and publish it as NuGet packages, documented alongside the other SDKs:
OpenShell.Sdk: an async client fornet8.0andnet10.0with the union of the other SDKs' features (health, sandboxes, exec, files, services, SSH and TCP forwarding, config and policy, providers, templates, workspaces), typed errors, and a raw gRPC escape hatch.OpenShell.Sdk.DependencyInjection:Microsoft.Extensions.DependencyInjectionregistration, options validated at startup, and a health check.OpenShell.Sdk.Testing: an in-memory fake client for unit tests.
Authentication covers bearer tokens, OIDC (client credentials and interactive flows), mTLS, Cloudflare Access, and gateways registered on disk by the CLI. Every call emits OpenTelemetry traces and metrics when a listener subscribes. The code uses current C# idioms and is trimming and AOT compatible. Protobuf bindings are generated at build time from proto/ and never committed.
using OpenShell;
using var client = new OpenShellClient(new OpenShellClientOptions
{
Address = new Uri("https://gateway.example.com"),
Auth = Auth.StaticToken(Environment.GetEnvironmentVariable("OPENSHELL_TOKEN")!),
});
var sandbox = await client.Sandboxes.CreateAsync("demo", new SandboxSpec { Image = "registry.example.com/agent:1.0" });
await client.Sandboxes.WaitReadyAsync(sandbox.Name);
var result = await client.Exec.RunAsync(sandbox.Name, ["python", "-c", "print('hello')"]);
await client.Sandboxes.DeleteAsync(sandbox.Name);
Acceptance Criteria
-
OpenShell.Sdkcovers every user-facing RPC of theOpenShellgRPC service. The supervisor and sandbox-internal RPCs stay out of scope and remain reachable through the raw client. - The feature set matches the union of the other SDKs, tracked in a parity matrix in the repository.
- Credentials are never sent over plaintext HTTP to a non-loopback host unless the caller opts in, and never appear in logs, exceptions, or
ToStringoutput. -
OpenShell.Sdk.DependencyInjectionregisters a singleton client and its per-area clients, binds options from configuration, validates them at startup, supports several named gateways, and provides a health check and a fluent builder. - Every RPC emits one OpenTelemetry client span and a duration measurement under the
OpenShell.Sdkactivity source and meter, following the OpenTelemetry gRPC conventions. Nothing is recorded or allocated without a listener, and payloads and credentials are never recorded. The SDK also logs its own events throughILogger. - The SDK uses modern C#: nullable reference types, async-only APIs with
CancellationTokenandIAsyncEnumerable<T>, records withrequiredandinitmembers, pattern matching and switch expressions, file-scoped namespaces, andTimeProviderfor time. An.editorconfigand analyzers built as errors enforce the style, and the SDK is trimming and AOT compatible. - Unit tests run on every supported .NET version, and integration tests run against a real gateway in an opt-in lane.
- Branch checks run format, build, tests, and a package dry run through
misetasks, and release tags publish the packages. - A published docs page and the contributor docs describe the SDK.
Alternatives Considered
- Generate bindings in each .NET project: repeats the authentication, waits, and safety behavior in every consumer.
- Call another SDK or the CLI from .NET: adds a second runtime and gives .NET callers no native types, cancellation, or streaming.
- Wrap the Rust SDK through native interop: needs a native binary per platform and complicates packaging and AOT.
- An OpenShell extension point (middleware, interceptor, provider): these extend the gateway or sandbox, not a client application.
- A community SDK outside this repository: trails gateway releases. In-repo, an incompatible proto change fails CI.
Agent Investigation
The OpenShell service has 83 RPCs: 65 are user-facing and 18 belong to the in-sandbox supervisor and gateway peers, which no existing SDK implements.
A draft implementation, offered as a starting point for review, is on a fork branch: https://github.com/zcsizmadia/OpenShell/tree/feat/4392-dotnet-sdk/zcsizmadia (sdk/dotnet/). Two documents in it describe the proposal:
sdk/dotnet/README.md: the proposed user-facing API, with usage examples for authentication, retries, dependency injection, observability, and testing.sdk/dotnet/PARITY.md: the feature parity matrix against the Go, Rust, TypeScript, and Python SDKs, with the status of each feature and the known differences.
The draft builds without warnings and passes its unit tests on net8.0 and net10.0. It has not run against a real gateway, and its CI jobs have not run yet.
The branch is large (about 170 files, half of them tests), so I propose landing it as separate PRs: core client and API areas, OIDC and gateway discovery, retry and telemetry with the DI package, the testing package, then CI and docs.
Related: #2565 (stabilize public API, SDK, and extension contracts) and #2825 (proto drift detection and SDK sync notifications). A .NET SDK would join both.
Questions for maintainers: is GitHub Packages the intended feed, are the DI and testing packages in scope, and who owns sdk/dotnet/?
Checklist
- I've reviewed existing issues and the published docs
- This is a design proposal, not a "please build this" request
- 主要语言
- Rust
- 星标
- 15.4k
- 派生
- 1.7k
- 平均合并
- 1 天 21 小时
- 30 天内合并 PR
- 358
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
NVIDIA/OpenShell 的其他 Issue
-
state:triage-needed
难度 2/5 1-3 小时 新手友好度 65/100
维护者通常 1 天内回复
-
state:triage-needed
难度 2/5 1-3 小时 新手友好度 70/100
维护者通常 1 天内回复
-
docs: document workspace and provider label capabilities可能已有人在做 @johntmyers 于 4 天前认领。 未关闭area:docs
难度 2/5 1-3 小时 新手友好度 72/100
NVIDIA/OpenShell#4250 · 2 条评论 ·
维护者通常 1 天内回复
-
bug(driver-mxc): test helper fails to compile after gateway-name argument可能已有人在做 @feloy 于 6 天前认领。 未关闭state:triage-needed
难度 1/5 1 小时以内 新手友好度 88/100
维护者通常 1 天内回复
-
bug: install.sh ignores XDG_CONFIG_HOME for the local gateway config可能已有人在做 @fede-kamel 于 10 天前认领。 未关闭area:cli os:linux os:macos state:validated
难度 2/5 1-3 小时 新手友好度 88/100
NVIDIA/OpenShell#4042 · 2 条评论 ·
维护者通常 1 天内回复
相似的 Issue
-
Progress difficulty filter lists Hard before Medium可能已有人在做 @Pandamachi 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 86/100
sysprog21/codetrial#281 · 1 条评论 ·
维护者通常 1 天内回复
-
C-bug
难度 2/5 1-3 小时 新手友好度 78/100
rust-lang/rust-analyzer#23501 ·
维护者通常 1 天内回复
-
Streamable HTTP client: a 401 or 403 with a JSON-RPC error body and no WWW-Authenticate loses its HTTP status可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭bug P2 ready for work T-security T-transport
难度 2/5 1-3 小时 新手友好度 68/100
modelcontextprotocol/rust-sdk#1339 ·
维护者通常 3 天内回复
-
scripts/gen-gallery.py:118: a ready session now reports in_progress, so SESSION_READY_OLD can go未关闭nightly-audit
难度 2/5 1-3 小时 新手友好度 84/100
antithesishq/snouty#396 ·
维护者通常 1 天内回复
-
French BIP39 wordlist starts with a UTF-8 BOM, so generated French mnemonics carry U+FEFF and derive a non-canonical seed可能已有人在做 @Kshot3000 今天认领。 未关闭
难度 1/5 1 小时以内 新手友好度 91/100
ergoplatform/sigma-rust#976 ·
维护者通常 1 天内回复