GitHub Copilot SDK手动工具恢复:处理工具调用中断的完整指南
GitHub Copilot SDK手动工具恢复:处理工具调用中断的完整指南
在AI驱动的应用开发中,工具调用中断是常见挑战。GitHub Copilot SDK提供了强大的手动工具恢复机制,让您能够在会话中断后优雅地恢复工作流程。本文将深入探讨如何处理工具调用中断,并介绍实用的恢复策略。😊
为什么需要手动工具恢复?
当您的应用程序使用GitHub Copilot SDK进行AI驱动的任务时,可能会遇到各种中断场景:
- 网络连接不稳定导致会话断开
- 应用程序重启或进程崩溃
- 用户主动暂停长时间运行的任务
- 权限审批流程需要人工干预
在这些情况下,传统方法会丢失所有进度,而GitHub Copilot SDK的手动恢复机制让您能够从断点继续,避免重复工作。
核心概念:会话持久化与恢复
GitHub Copilot SDK通过会话持久化功能,将对话历史、工具状态和规划上下文保存到磁盘。这意味着即使会话中断,您也可以使用相同的会话ID恢复工作。
会话恢复的关键配置
在恢复会话时,ContinuePendingWork参数至关重要:
// TypeScript示例
const session = await client.resumeSession(sessionId, {
tools: [myTool],
continuePendingWork: true // 继续未完成的工具调用
});
当设置为true时,之前会话中未完成的工具调用和权限请求会保持挂起状态,等待您手动处理。设置为false(默认值)时,这些请求会被标记为中断。
手动工具恢复的三种场景
1. 权限请求恢复
当工具需要用户权限批准时,会话可能在此处暂停。恢复会话后,您可以处理挂起的权限请求:
# Python示例
permission_event = await wait_for_permission_event(session)
await session.rpc.permissions.handle_pending_permission_request(
request_id=permission_event.request_id,
result=PermissionDecisionApproveOnce()
)
2. 外部工具调用恢复
对于声明式工具(只有定义没有实现处理器),您需要手动提供结果:
// Go示例
toolRequest := receiveToolRequest(session)
_, err := session.RPC.Tools.HandlePendingToolCall(ctx, &rpc.HandlePendingToolCallRequest{
RequestID: toolRequest.RequestID,
Result: rpc.ExternalToolStringResult("手动提供的结果"),
})
3. 完整恢复工作流程
完整的恢复流程通常涉及多个步骤:
- 创建初始会话并触发工具调用
- 保存会话状态和挂起的请求ID
- 恢复会话并继续处理挂起的工作
- 提供缺失的结果让AI继续处理
实用恢复策略
策略一:声明式工具模式
创建只有声明没有实现的工具,让SDK用户完全控制执行时机:
// .NET示例
var tool = AIFunctionFactory.Create(
([Description("Identifier to look up")] string id) => $"not used: {id}",
"manual_resume_status",
"Looks up a status value. The SDK consumer supplies the result manually."
).AsDeclarationOnly();
策略二:错误处理与重试
结合错误处理钩子,实现智能恢复:
// TypeScript错误处理示例
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input, invocation) => {
if (input.errorContext === "tool_execution" && input.recoverable) {
console.log(`工具执行错误,可恢复: ${input.error}`);
return {
errorHandling: "retry",
retryCount: 3,
userNotification: "正在重试工具调用...",
};
}
return null;
},
},
});
策略三:状态检查点
定期保存会话状态,实现断点续传:
# Python状态检查点示例
async def save_checkpoint(session_id, tool_requests):
checkpoint = {
"session_id": session_id,
"pending_tools": tool_requests,
"timestamp": datetime.now().isoformat(),
}
await save_to_storage(session_id, checkpoint)
async def restore_from_checkpoint(session_id):
checkpoint = await load_from_storage(session_id)
session = await client.resume_session(
session_id,
ResumeSessionConfig(
tools=checkpoint["tools"],
continue_pending_work=True
)
)
return session, checkpoint["pending_tools"]
实战示例:构建可恢复的AI助手
让我们通过一个完整示例展示如何构建一个可恢复的AI助手:
步骤1:定义可恢复工具
在plugins/ai/目录中创建自定义工具:
// 自定义工具定义
const weatherTool = defineTool("get_weather", {
description: "获取城市天气信息",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "城市名称" },
date: { type: "string", description: "日期(YYYY-MM-DD)" }
},
required: ["city"]
},
// 声明式工具,由外部提供结果
skipPermission: true
});
const stockTool = defineTool("get_stock_price", {
description: "获取股票价格",
parameters: {
type: "object",
properties: {
symbol: { type: "string", description: "股票代码" }
},
required: ["symbol"]
}
});
步骤2:实现恢复逻辑
// Java恢复逻辑示例
public class ToolResumeManager {
private Map<String, PendingToolRequest> pendingRequests = new ConcurrentHashMap<>();
public void handleSessionResume(String sessionId) {
// 加载之前保存的会话状态
SessionState state = loadSessionState(sessionId);
// 恢复会话并继续挂起的工作
CopilotSession session = client.resumeSession(sessionId,
new ResumeSessionConfig()
.setTools(state.getTools())
.setContinuePendingWork(true)
);
// 处理挂起的工具调用
for (PendingToolRequest request : state.getPendingRequests()) {
Object result = executeToolExternally(request);
session.getRpc().tools().handlePendingToolCall(
new HandlePendingToolCallRequest()
.setRequestId(request.getRequestId())
.setResult(result)
);
}
}
}
步骤3:集成错误恢复机制
// 集成错误恢复
const resilientSession = await client.createSession({
hooks: {
onPreToolUse: async (input, invocation) => {
// 记录工具调用用于恢复
await logToolCall(invocation.sessionId, input);
return { permissionDecision: "allow" };
},
onPostToolUseFailure: async (input, invocation) => {
// 工具调用失败时提供恢复指导
return {
additionalContext: `工具调用失败: ${input.error}。建议检查输入参数或重试。`
};
},
onErrorOccurred: async (input, invocation) => {
// 保存错误状态用于恢复
await saveErrorState(invocation.sessionId, input);
if (input.recoverable) {
return {
errorHandling: "retry",
retryCount: 2,
userNotification: "遇到可恢复错误,正在重试..."
};
}
return null;
}
}
});
最佳实践与注意事项
✅ 最佳实践
- 始终启用会话持久化:确保
session.persistence.enabled = true - 定期保存检查点:在关键步骤后保存会话状态
- 实现幂等工具:工具多次执行产生相同结果
- 提供清晰的用户反馈:让用户知道恢复进度
- 设置合理的超时:避免无限期等待恢复
⚠️ 注意事项
- 内存管理:长时间运行的会话可能占用大量内存
- 并发控制:避免多个客户端同时恢复同一会话
- 安全考虑:验证恢复请求的合法性
- 状态一致性:确保恢复后的状态与中断前一致
故障排除指南
常见问题与解决方案
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 恢复后工具调用失败 | 工具定义不匹配 | 确保恢复时提供相同的工具定义 |
| 权限请求丢失 | ContinuePendingWork未设置 |
恢复会话时设置为true |
| 会话状态不一致 | 存储损坏 | 实现状态验证和修复机制 |
| 恢复超时 | 网络或资源问题 | 增加超时设置,实现重试机制 |
调试技巧
- 检查会话事件日志:查看
~/.copilot/session-state/<sessionId>/events.jsonl - 验证工具定义:确保恢复时工具签名一致
- 监控挂起请求:使用
session.rpc.permissions.pendingRequests()API - 启用详细日志:设置
COPILOT_LOG_LEVEL=debug环境变量
性能优化建议
减少恢复延迟
# 预加载常用工具定义
common_tools = load_tool_definitions_from_cache()
async def fast_resume(session_id):
# 使用缓存的工具定义
session = await client.resume_session(
session_id,
ResumeSessionConfig(
tools=common_tools,
continue_pending_work=True
)
)
return session
批量处理挂起请求
// 批量处理恢复请求
async function batchResumeToolCalls(
session: CopilotSession,
pendingRequests: ToolRequest[]
) {
const results = await Promise.allSettled(
pendingRequests.map(async (request) => {
try {
const result = await executeToolExternally(request);
await session.rpc.tools.handlePendingToolCall({
requestId: request.requestId,
result
});
return { success: true, requestId: request.requestId };
} catch (error) {
return { success: false, requestId: request.requestId, error };
}
})
);
return results;
}
实际应用场景
场景一:长时间运行的代码生成任务
当AI助手正在生成大型代码库时,网络中断可能导致任务失败。使用手动恢复机制,您可以:
- 保存当前生成进度
- 恢复会话时继续从断点生成
- 保持代码结构和风格一致性
场景二:需要人工审批的敏感操作
对于需要人工审批的文件修改或系统操作:
- AI请求权限时暂停会话
- 人工审批后恢复会话
- 继续执行批准的操作
场景三:多步骤数据处理流水线
处理复杂的数据转换任务:
- 每个步骤完成后保存状态
- 任何步骤失败时可从该步骤恢复
- 避免重复处理已完成的数据
总结
GitHub Copilot SDK的手动工具恢复机制为构建健壮的AI应用提供了坚实基础。通过合理利用会话持久化、声明式工具和错误处理钩子,您可以创建能够优雅处理中断的智能应用。
记住关键要点:
- **使用
ContinuePendingWork: true**恢复挂起的工作 - 实现声明式工具以获得完全控制权
- 结合错误处理钩子实现智能恢复
- 定期保存检查点确保状态一致性
通过本文介绍的策略和最佳实践,您将能够构建出真正可靠、可恢复的AI驱动应用,为用户提供无缝的体验。🚀
如需更多技术细节,请参考官方文档和AI功能源码中的实现示例。
更多推荐


所有评论(0)