GitHub Copilot SDK会话持久化:跨重启恢复会话的完整方案
GitHub Copilot SDK会话持久化跨重启恢复会话的完整方案【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdkGitHub Copilot SDK是一款多平台软件开发工具包专为将GitHub Copilot Agent集成到各类应用和服务中而设计。其中会话持久化功能是其核心特性之一它允许用户在应用重启、容器迁移甚至更换客户端实例后仍能无缝恢复之前的会话状态极大地提升了开发体验和工作连续性。会话持久化基础理解会话状态管理会话的生命周期与状态转换当创建一个会话时Copilot CLI会维护对话历史、工具状态和规划上下文。默认情况下这些状态仅存在于内存中会话结束后便会消失。而启用持久化功能后会话可以在暂停后 resume恢复实现跨重启的状态保持。会话主要有以下几种状态Create创建系统为会话分配唯一的session_idActive活跃可以发送提示、进行工具调用和接收响应Paused暂停会话状态被保存到磁盘Resume恢复从磁盘加载之前保存的会话状态持久化会话的存储结构会话状态会被保存到~/.copilot/session-state/{sessionId}/目录下典型的存储结构如下~/.copilot/session-state/ └── user-123-task-456/ ├── checkpoints/ # 对话历史快照 │ ├── 001.json # 初始状态 │ ├── 002.json # 第一次交互后状态 │ └── ... # 增量检查点 ├── plan.md # 代理的规划状态如有 └── files/ # 会话工件 ├── analysis.md # 代理创建的文件 └── notes.txt # 工作文档并非所有数据都会被持久化以下是关键数据的持久化情况数据类型是否持久化说明对话历史✅ 是完整的消息线程工具调用结果✅ 是缓存用于上下文代理规划状态✅ 是存储在plan.md文件中会话工件✅ 是保存在files/目录下提供商/API密钥❌ 否出于安全考虑必须在恢复时重新提供内存中的工具状态❌ 否工具应设计为无状态快速上手创建可恢复的会话创建可恢复会话的关键在于提供自定义的session_id。如果不指定SDK会生成随机ID导致会话无法在后续恢复。TypeScript实现import { CopilotClient } from github/copilot-sdk; const client new CopilotClient(); // 使用有意义的ID创建会话 const session await client.createSession({ sessionId: user-123-task-456, model: gpt-5.2-codex, }); // 执行一些操作... await session.sendAndWait({ prompt: 分析我的代码库 }); // 会话状态会自动持久化 // 你可以安全地关闭客户端Python实现from copilot import CopilotClient from copilot.session import PermissionHandler client CopilotClient() await client.start() # 使用有意义的ID创建会话 session await client.create_session(on_permission_requestPermissionHandler.approve_all, modelgpt-5.2-codex, session_iduser-123-task-456) # 执行一些操作... await session.send_and_wait(分析我的代码库) # 会话状态会自动持久化C# (.NET)实现using GitHub.Copilot; var client new CopilotClient(); // 使用有意义的ID创建会话 var session await client.CreateSessionAsync(new SessionConfig { SessionId user-123-task-456, Model gpt-5.2-codex, }); // 执行一些操作... await session.SendAndWaitAsync(new MessageOptions { Prompt 分析我的代码库 }); // 会话状态会自动持久化恢复会话跨重启继续工作基本恢复操作无论经过几分钟、几小时甚至几天都可以从上次中断的地方恢复会话TypeScript恢复示例// 从不同的客户端实例或重启后恢复 const session await client.resumeSession(user-123-task-456); // 继续之前的工作 await session.sendAndWait({ prompt: 我们之前讨论了什么 });Python恢复示例# 从不同的客户端实例或重启后恢复 session await client.resume_session(user-123-task-456, on_permission_requestPermissionHandler.approve_all) # 继续之前的工作 await session.send_and_wait(我们之前讨论了什么)恢复时的高级配置选项恢复会话时可以选择性地重新配置许多设置这对于更改模型、更新工具配置或修改行为非常有用选项描述model更改恢复会话使用的模型systemMessage覆盖或扩展系统提示availableTools限制可用的工具excludedTools禁用特定工具provider重新提供BYOK凭据BYOK会话必需reasoningEffort调整推理努力级别streaming启用/禁用流式响应workingDirectory更改工作目录示例恢复时更改模型// 使用不同的模型恢复 const session await client.resumeSession(user-123-task-456, { model: claude-sonnet-4, // 切换到不同的模型 reasoningEffort: high, // 增加推理努力 });使用BYOK自带密钥恢复会话使用自己的API密钥时必须在恢复会话时重新提供提供商配置。出于安全原因API密钥永远不会持久化到磁盘// 使用BYOK创建原始会话 const session await client.createSession({ sessionId: user-123-task-456, model: gpt-5.2-codex, provider: { type: azure, endpoint: https://my-resource.openai.azure.com, apiKey: process.env.AZURE_OPENAI_KEY, deploymentId: my-gpt-deployment, }, }); // 恢复时必须重新提供提供商配置 const resumed await client.resumeSession(user-123-task-456, { provider: { type: azure, endpoint: https://my-resource.openai.azure.com, apiKey: process.env.AZURE_OPENAI_KEY, // 再次需要 deploymentId: my-gpt-deployment, }, });会话ID的最佳实践选择能够编码所有权和用途的会话ID这会使审计和清理变得更加容易。推荐的命名模式模式示例用例❌abc123随机ID难以审计没有所有权信息✅user-{userId}-{taskId}user-alice-pr-review-42多用户应用✅tenant-{tenantId}-{workflow}tenant-acme-onboarding多租户SaaS✅{userId}-{taskId}-{timestamp}alice-deploy-1706932800基于时间的清理结构化ID的好处易于审计显示用户alice的所有会话易于清理删除所有早于X的会话自然的访问控制从会话ID解析用户ID生成会话ID的示例代码function createSessionId(userId: string, taskType: string): string { const timestamp Date.now(); return ${userId}-${taskType}-${timestamp}; } const sessionId createSessionId(alice, code-review); // → alice-code-review-1706932800000import time def create_session_id(user_id: str, task_type: str) - str: timestamp int(time.time()) return f{user_id}-{task_type}-{timestamp} session_id create_session_id(alice, code-review) # → alice-code-review-1706932800会话生命周期管理列出活跃会话// 列出所有会话 const sessions await client.listSessions(); console.log(找到 ${sessions.length} 个会话); for (const session of sessions) { console.log(- ${session.sessionId} (创建时间: ${session.createdAt})); } // 按仓库筛选会话 const repoSessions await client.listSessions({ repository: owner/repo });清理旧会话async function cleanupExpiredSessions(maxAgeMs: number) { const sessions await client.listSessions(); const now Date.now(); for (const session of sessions) { const age now - new Date(session.createdAt).getTime(); if (age maxAgeMs) { await client.deleteSession(session.sessionId); console.log(已删除过期会话: ${session.sessionId}); } } } // 清理超过24小时的会话 await cleanupExpiredSessions(24 * 60 * 60 * 1000);断开会话连接disconnect任务完成后显式断开会话连接而不是等待超时。这会释放内存资源但保留磁盘上的会话数据因此会话仍可在以后恢复try { // 执行工作... await session.sendAndWait({ prompt: 完成任务 }); // 任务完成 — 释放内存资源会话可在以后恢复 await session.disconnect(); } catch (error) { // 即使出错也进行清理 await session.disconnect(); throw error; }各SDK还提供了惯用的自动清理模式语言模式示例TypeScriptSymbol.asyncDisposeawait using session await client.createSession(config);Pythonasync with上下文管理器async with await client.create_session(on_permission_requesthandler) as session:C#IAsyncDisposableawait using var session await client.CreateSessionAsync(config);Godeferdefer session.Disconnect()注意destroy()已被disconnect()取代。使用destroy()的现有代码将继续工作但应进行迁移。永久删除会话deleteSession要永久从磁盘删除会话及其所有数据对话历史、规划状态、工件请使用deleteSession。这是不可逆的 — 删除后无法恢复会话// 永久删除会话数据 await client.deleteSession(user-123-task-456);disconnect()与deleteSession()的区别disconnect()释放内存资源但保留磁盘上的会话数据供以后恢复。deleteSession()永久删除所有内容包括磁盘上的文件。自动清理空闲超时默认情况下会话没有空闲超时会无限期存在直到显式断开连接或删除。你可以通过CopilotClientOptions.sessionIdleTimeoutSeconds选择性地配置服务器范围的空闲超时const client new CopilotClient({ sessionIdleTimeoutSeconds: 30 * 60, // 30分钟 });配置超时后超过该持续时间无活动的会话将被自动清理。设置为0或省略以禁用超时。可以监听空闲事件以响应对话不活动session.on(session.idle, (event) { console.log(会话已空闲 ${event.idleDurationMs}毫秒); });部署模式模式1每个用户一个CLI服务器推荐最适合强隔离、多租户环境、Azure动态会话。优点✅ 完全隔离 | ✅ 简单安全 | ✅ 易于扩展模式2共享CLI服务器资源高效最适合内部工具、可信环境、资源受限的设置。要求⚠️ 每个用户唯一的会话ID⚠️ 应用级访问控制⚠️ 操作前验证会话ID// 共享CLI的应用级访问控制 async function resumeSessionWithAuth( client: CopilotClient, sessionId: string, currentUserId: string ): PromiseSession { // 从会话ID解析用户 const [sessionUserId] sessionId.split(-); if (sessionUserId ! currentUserId) { throw new Error(访问被拒绝会话属于其他用户); } return client.resumeSession(sessionId); }容器化部署中的会话持久化对于容器可能重启或迁移的无服务器/容器部署需要将会话状态目录挂载到持久存储# Azure容器实例示例 containers: - name: copilot-agent image: my-agent:latest volumeMounts: - name: session-storage mountPath: /home/app/.copilot/session-state volumes: - name: session-storage azureFile: shareName: copilot-sessions storageAccountName: myaccount通过这种配置会话可以在容器重启后继续存在处理并发访问SDK不提供内置的会话锁定。如果多个客户端可能访问同一个会话可以实现应用级锁定// 选项1使用Redis进行应用级锁定 import Redis from ioredis; const redis new Redis(); async function withSessionLockT( sessionId: string, fn: () PromiseT ): PromiseT { const lockKey session-lock:${sessionId}; const acquired await redis.set(lockKey, locked, NX, EX, 300); if (!acquired) { throw new Error(会话正被另一个客户端使用); } try { return await fn(); } finally { await redis.del(lockKey); } } // 使用方法 await withSessionLock(user-123-task-456, async () { const session await client.resumeSession(user-123-task-456); await session.sendAndWait({ prompt: 继续任务 }); });会话持久化功能摘要功能使用方法创建可恢复会话提供自定义sessionId恢复会话client.resumeSession(sessionId)BYOK恢复重新提供provider配置列出会话client.listSessions(filter?)断开活动会话连接session.disconnect()—释放内存资源磁盘上的会话数据保留用于恢复永久删除会话client.deleteSession(sessionId)—永久删除所有会话数据无法恢复容器化部署将~/.copilot/session-state/挂载到持久存储总结与最佳实践GitHub Copilot SDK的会话持久化功能为开发人员提供了强大的会话状态管理能力通过合理使用这一功能可以显著提升工作效率和连续性。以下是一些关键建议始终使用有意义的会话ID包含用户标识、任务类型和时间戳等信息在使用BYOK时确保安全存储API密钥并在恢复会话时重新提供定期清理不再需要的会话避免存储空间浪费在容器化部署中务必将会话状态目录挂载到持久存储对于多用户环境实现适当的访问控制防止未授权访问会话使用disconnect()而非deleteSession()除非确定不再需要该会话通过遵循这些最佳实践你可以充分利用GitHub Copilot SDK的会话持久化功能构建更健壮、更可靠的Copilot集成应用。更多详细信息请参考官方文档docs/features/session-persistence.md【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考