# 远程会话

远程会话允许用户通过 Mission Control 从 GitHub Web 和移动设备访问其Copilot会话。 启用后，SDK 会将每个会话连接到任务控制，生成一个 URL，可以作为链接或 QR 码共享。

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

有关在 GitHub 托管的计算资源上运行会话的信息，请参阅 [云会话](/zh/copilot/how-tos/copilot-sdk/features/cloud-sessions)。

## 先决条件

* 必须对用户进行身份验证（GitHub令牌或登录用户）
* 会话的工作目录必须是GitHub存储库

## 启用远程会话

### 始终开启（客户端级别）

创建客户端时设置 `enableRemoteSessions: true` 。 GitHub存储库中的每个会话都会自动获取远程 URL。

<!-- tabs:start -->

#### TypeScript

<!-- docs-validate: skip -->

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({ enableRemoteSessions: true });
const session = await client.createSession({
  workingDirectory: "/path/to/github-repo",
  onPermissionRequest: async () => ({ allowed: true }),
});

session.on("session.info", (event) => {
  if (event.data.infoType === "remote") {
    console.log("Remote URL:", event.data.url);
  }
});
```

#### Python

<!-- docs-validate: skip -->

```python
from copilot import CopilotClient

client = CopilotClient(enable_remote_sessions=True)
session = await client.create_session(
    working_directory="/path/to/github-repo",
    on_permission_request=lambda req: {"allowed": True},
)

def on_event(event):
    if event.type == "session.info" and event.data.info_type == "remote":
        print(f"Remote URL: {event.data.url}")

session.on(on_event)
```

#### Go

<!-- docs-validate: skip -->

```golang
client := copilot.NewClient(&copilot.ClientOptions{EnableRemoteSessions: true})
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    WorkingDirectory: "/path/to/github-repo",
    OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
        return &rpc.PermissionDecisionApproveOnce{}, nil
    },
})

session.On(func(event copilot.SessionEvent) {
    if event.Type == "session.info" {
        // Check infoType and extract URL
    }
})
```

#### C\#

<!-- docs-validate: skip -->

```csharp
var client = new CopilotClient(new CopilotClientOptions { EnableRemoteSessions = true });
var session = await client.CreateSessionAsync(new SessionConfig
{
    WorkingDirectory = "/path/to/github-repo",
    OnPermissionRequest = (req, inv) =>
        Task.FromResult(PermissionDecision.ApproveOnce()),
});

session.On((SessionEvent e) =>
{
    if (e is SessionInfoEvent info && info.Data.InfoType == "remote")
    {
        Console.WriteLine($"Remote URL: {info.Data.Url}");
    }
});
```

#### Rust

<!-- docs-validate: skip -->

```rust
use github_copilot_sdk::{Client, ClientOptions, SessionConfig};
use github_copilot_sdk::handler::PermissionResult;

let client = Client::start(
    ClientOptions::new().with_enable_remote_sessions(true)
).await?;
let session = client.create_session(
    SessionConfig::new("/path/to/github-repo")
        .with_permission_handler(|_req, _inv| async {
            Ok(PermissionResult::approve_once())
        }),
).await?;

let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
    if event.event_type == "session.info" {
        // Check info_type and extract URL
    }
}
```

<!-- tabs:end -->

### 按需（按会话切换）

使用 `session.rpc.remote.enable()` 在会话进行中启动远程访问，并使用 `session.rpc.remote.disable()` 停止远程访问。 这相当于 CLI 的 `/remote on` 和 `/remote off` 命令。

<!-- tabs:start -->

#### TypeScript

<!-- docs-validate: skip -->

```typescript
const result = await session.rpc.remote.enable();
console.log("Remote URL:", result.url);

// Later: stop sharing
await session.rpc.remote.disable();
```

#### Python

<!-- docs-validate: skip -->

```python
result = await session.rpc.remote.enable()
print(f"Remote URL: {result.url}")

# Later: stop sharing
await session.rpc.remote.disable()
```

#### Go

<!-- docs-validate: skip -->

```golang
result, err := session.RPC.Remote.Enable(ctx)
if result.URL != nil {
    fmt.Println("Remote URL:", *result.URL)
}

// Later: stop sharing
err = session.RPC.Remote.Disable(ctx)
```

#### C\#

<!-- docs-validate: skip -->

```csharp
var result = await session.Rpc.Remote.EnableAsync();
Console.WriteLine($"Remote URL: {result.Url}");

// Later: stop sharing
await session.Rpc.Remote.DisableAsync();
```

#### Rust

<!-- docs-validate: skip -->

```rust
let result = session.rpc().remote().enable().await?;
if let Some(url) = &result.url {
    println!("Remote URL: {url}");
}

// Later: stop sharing
session.rpc().remote().disable().await?;
```

<!-- tabs:end -->

## QR 码生成

远程 URL 可以呈现为 QR 码，以便轻松进行移动访问。 SDK 提供 URL - 使用首选 QR 码库：

* **TypeScript**： [qrcode](https://www.npmjs.com/package/qrcode)
* **Python**：[qrcode](https://pypi.org/project/qrcode/)
* **Go**： [go-qrcode](https://github.com/skip2/go-qrcode)
* **C#**： [QRCoder](https://www.nuget.org/packages/QRCoder)
* **Rust**： [qrcode](https://crates.io/crates/qrcode)

## 笔记

* 当 SDK 启动运行时（作为子进程或进程内主机）时，客户端 `enableRemoteSessions` 选项适用。 连接到已运行的运行时时，将忽略它。
* 如果工作目录不是 GitHub 仓库，则会静默跳过远程配置（始终启用模式），或返回错误（按需模式）。
* 远程会话需要身份验证。 确保 `gitHubToken` 或 `useLoggedInUser` 已配置。