內嵌 Copilot SDK¶
本導覽說明 API 如何內嵌 GitHub Copilot SDK,並將 Copilot 工作階段轉換為應用程式服務。您將瞭解應用程式如何啟動 SDK 用戶端、建立串流工作階段、接聽工作階段事件,以及避免使用過期的模型目錄。
SDK 的使用位置¶
主要整合點是
CopilotChatService。它以下列方式匯入 SDK:
這個命名空間是常見的移轉陷阱。在 1.0.0 SDK 發行前,命名空間為 GitHub.Copilot.SDK;此處使用的 v1.x 程式碼中,命名空間為
GitHub.Copilot ,即使套件參考仍名為
GitHub.Copilot.SDK。
一個長時間存續的用戶端¶
Program.cs
將 CopilotChatService 註冊為單一執行個體:
服務擁有單一 CopilotClient 欄位,存續期間與 API 處理程序相同。如此可避免每個 HTTP 要求都啟動及停止 Copilot 連線,並透過單一受控服務提供模型清單與聊天串流。
CopilotChatService 會實作 IAsyncDisposable。當主機釋放此單一執行個體時, CopilotChatService.DisposeAsync 會呼叫
CopilotClient.StopAsync() ,使 SDK 連線能順利關閉。
啟動及復原用戶端¶
CopilotChatService.EnsureStartedAsync 是列出模型或進行聊天前的閘道:
if (_isStarted && _client != null) return;
_isStarted = false;
if (_client != null)
{
try { await _client.StopAsync(); } catch { }
}
_client = new CopilotClient();
await _client.StartAsync();
_isStarted = true;
此方法會將 _isStarted 以及 _client 作為單一真實來源。如果用戶端尚未啟動,或先前的失敗已將其標記為狀況不良,服務會停止所有舊用戶端並建立新的 CopilotClient、啟動它,並記錄新狀態。
復原作業會在下列位置完成: CopilotChatService.ChatStreamAsync。背景工作階段會攔截 IOException,記錄 Copilot 連線已中斷、將
_isStarted = false,並以例外狀況完成輸出通道。下一個要求將再次呼叫 EnsureStartedAsync 並重新建立用戶端。
建立串流工作階段¶
CopilotChatService.ChatStreamAsync 會建立 SessionConfig ,供每個提示詞使用:
SessionConfig config = new()
{
Model = model,
Streaming = true,
SystemMessage = systemMessage != null ? new SystemMessageConfig
{
Mode = SystemMessageMode.Append,
Content = systemMessage
} : null
};
選取的模型來自要求,若未指定則使用 claude-haiku-4.5 作為服務預設值。 Streaming = true 會要求 SDK 發出回應增量。若提供系統訊息,則會建立 SystemMessageConfig,並以 Append
模式傳送,因此會附加應用程式內容,而不是取代工作階段的基礎系統行為。
工作階段使用下列方式建立: await using,因此會在該提示詞完成後以非同步方式釋放:
工作階段事件¶
服務會使用明確的泛型型別引數訂閱 SDK 事件:
在 v1.x 中,明確的 <SessionEvent> 是必要的。舊版非泛型形式已無法可靠推斷事件型別,因此省略型別引數是常見的升級失敗原因。
CopilotChatService 會處理四種事件結構:
AssistantMessageDeltaEvent會將DeltaContent寫入輸出串流。AssistantMessageEvent會記錄助理回應已完成。SessionIdleEvent會完成TaskCompletionSource,用於等候該回合完成。SessionErrorEvent會記錄 SDK 錯誤,並以例外狀況完成等候工作。
訂閱後,會使用下列方式傳送提示詞:
將 SDK 事件銜接至 IAsyncEnumerable¶
SDK 工作階段會在背景 Task。增量內容會寫入
Channel<string>,而外層非同步迭代器會讀取該通道:
var outputChannel = Channel.CreateUnbounded<string>();
_ = Task.Run(async () =>
{
// create session, handle events, write chunks
}, cancellationToken);
await foreach (var chunk in outputChannel.Reader.ReadAllAsync(cancellationToken))
{
yield return chunk;
}
這個結構是刻意設計的。C# 非同步迭代器無法在 try/catch 區塊內使用 yield return;該區塊擁有 SDK 工作階段。通道可讓工作階段在內部處理例外狀況與完成作業,外層方法則向控制器公開簡潔的 IAsyncEnumerable<string>。
列出線上模型¶
CopilotChatService.ListModelsAsync 會呼叫 CopilotClient.ListModelsAsync() ,並回傳已連線 Copilot CLI 實際提供的 ID 與顯示名稱:
硬式編碼模型 ID 是個陷阱。模型可用性會因帳戶、推出階段與提供者而異;此示範先前使用的過期硬式編碼清單,導致六個模型中只有一個可用。API 在下列位置仍保有靜態目錄:
ChatController.AvailableModels,但它僅用作中繼資料與備援。正常路徑會從 SDK 擷取線上模型清單。