Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

## Project-specific conventions & patterns ✅

- **Cross-SDK features ship in a single PR.** When adding or changing a feature that lives in multiple SDKs (client/session API, wire protocol, etc.), put all the language implementations in **one** pull request — not one PR per language. The `sdk-consistency-review` workflow (`.github/workflows/sdk-consistency-review.md`) auto-reviews every PR touching `nodejs/`, `python/`, `go/`, or `dotnet/` and will flag per-language PRs as "missing in N other languages" even when follow-ups are planned. Exception: an early, isolated reference implementation (e.g. the Rust spike at PR #1394) can ship alone; the remaining languages then follow up as **one** consolidated PR.

- Tools: each SDK has helper APIs to expose functions as tools; prefer the language's `DefineTool`/`@define_tool`/`CopilotTool.DefineTool` patterns (see language READMEs).
- Infinite sessions are enabled by default and persist workspace state to `~/.copilot/session-state/{sessionId}`; compaction events are emitted (`session.compaction_start`, `session.compaction_complete`). See language READMEs for usage.
- Streaming: when `streaming`/`Streaming=true` you receive delta events (`assistant.message_delta`, `assistant.reasoning_delta`) and final events (`assistant.message`, `assistant.reasoning`) — tests expect this behavior.
Expand Down
42 changes: 42 additions & 0 deletions dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,47 @@ Resume an existing session. Returns the session with `WorkspacePath` populated i

- `OnPermissionRequest` - Optional handler called before each tool execution to approve or deny it. See [Permission Handling](#permission-handling) section.

##### `CreateCloudSessionAsync(CloudSessionConfig config): Task<CopilotSession>`

Create a session that is hosted by and routed to a remote Copilot cloud server rather than the local CLI. The returned `CopilotSession` behaves identically to a locally-created session: send messages, receive events, and use tools through the same API.

A `Cloud` configuration is required; passing `Cloud = null` throws `ArgumentException`. Conversely, passing a `Cloud` config to the regular `CreateSessionAsync` also throws, preventing accidental misconfiguration.

The session ID is assigned by the cloud server. After `CreateCloudSessionAsync` returns, `session.SessionId` contains the server-assigned ID and `session.RemoteUrl` contains the URL of the cloud server that owns the session. Any RPC requests (user-input, permission, hooks, etc.) that arrive from the server before the session is fully registered are buffered and replayed automatically — your handlers will never miss an early request.

**CloudSessionConfig:**

- `Cloud` *(required)* — Cloud routing options:
- `Repository` *(required)* — The repository to route the session to:
- `Nwo` *(required)* — Full `owner/repo` name (e.g. `"github/my-repo"`)
- `Ref` *(optional)* — Branch or tag ref (e.g. `"refs/heads/main"`)
- `SdkOptions` *(optional)* — Pass-through options forwarded to the cloud provider
- `Model`, `ReasoningEffort`, `Tools`, `SystemMessage`, `AvailableTools`, `ExcludedTools`, `Provider`, `Streaming`, `InfiniteSessions`, `OnPermissionRequest`, `OnUserInputRequest`, `Hooks` — Same as `SessionConfig`

**Returned session properties:**

- `SessionId` — Server-assigned session ID
- `RemoteUrl` — URL of the cloud server that owns this session

```csharp
await using var session = await client.CreateCloudSessionAsync(new CloudSessionConfig
{
Cloud = new CloudSessionOptions
{
Repository = new CloudSessionRepository { Nwo = "github/my-repo" }
},
OnUserInputRequest = async (request, _) =>
{
Console.Write($"{request.Question} ");
return new UserInputResponse { Answer = Console.ReadLine()! };
}
});

Console.WriteLine($"Cloud session: {session.SessionId} at {session.RemoteUrl}");
var reply = await session.SendAsync(new MessageOptions { Content = "Hello from the cloud!" });
Console.WriteLine(reply);
```

##### `PingAsync(string? message = null): Task<PingResponse>`

Ping the server to check connectivity.
Expand Down Expand Up @@ -193,6 +234,7 @@ Represents a single conversation session.

- `SessionId` - The unique identifier for this session
- `WorkspacePath` - Path to the session workspace directory when infinite sessions are enabled. Contains `checkpoints/`, `plan.md`, and `files/` subdirectories. Null if infinite sessions are disabled.
- `RemoteUrl` - URL of the cloud server that owns this session. Non-null only for sessions created via `CreateCloudSessionAsync`.

#### Methods

Expand Down
Loading
Loading