注意
Copilot SDK 目前处于公开预览阶段。功能和可用性可能会更改。
当会话执行期间出现错误时,会调用 onErrorOccurred 钩子。可用于
- 实现自定义错误日志记录
- 跟踪错误模式
- 提供用户友好的错误消息
- 对关键错误触发警报
钩子签名
import type { ErrorOccurredHookInput, HookInvocation, ErrorOccurredHookOutput } from "@github/copilot-sdk";
type ErrorOccurredHandler = (
input: ErrorOccurredHookInput,
invocation: HookInvocation
) => Promise<
ErrorOccurredHookOutput | null | undefined
>;
有关 Python、Go 和 .NET 中的钩子签名,请参阅 github/copilot-sdk 仓库。对于 Java,请参阅 github/copilot-sdk-java 仓库。
输入
| 字段 | 类型 | 描述 |
|---|---|---|
时间戳 | number | 错误发生时的 Unix 时间戳 |
cwd | string | 当前工作目录 |
error | string | 错误信息 |
errorContext | string | 错误发生的地点:"model_call"、"tool_execution"、"system" 或 "user_input" |
recoverable | boolean | 错误是否有可能被恢复 |
输出
返回 null 或 undefined 以使用默认错误处理。否则,返回包含以下任意字段的对象。
| 字段 | 类型 | 描述 |
|---|---|---|
suppressOutput | boolean | 如果为 true,则不向用户显示错误输出 |
errorHandling | string | 处理方式:"retry"、"skip" 或 "abort" |
retryCount | number | 重试次数(如果 errorHandling 为 "retry") |
userNotification | string | 向用户显示的自定义消息 |
示例
基础错误日志记录
const session = await client.createSession({
hooks: {
onErrorOccurred: async (
input, invocation
) => {
console.error(
`[${invocation.sessionId}] `
+ `Error: ${input.error}`
);
console.error(
` Context: ${input.errorContext}`
);
console.error(
` Recoverable: ${input.recoverable}`
);
return null;
},
},
});
有关 Python、Go 和 .NET 中的示例,请参阅 github/copilot-sdk 仓库。对于 Java,请参阅 github/copilot-sdk-java 仓库。
将错误发送至监控服务
import { captureException } from "@sentry/node"; // or your monitoring service
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input, invocation) => {
captureException(new Error(input.error), {
tags: {
sessionId: invocation.sessionId,
errorContext: input.errorContext,
},
extra: {
error: input.error,
recoverable: input.recoverable,
cwd: input.cwd,
},
});
return null;
},
},
});
用户友好的错误消息
const ERROR_MESSAGES: Record<string, string> = {
"model_call":
"There was an issue communicating "
+ "with the AI model. Please try again.",
"tool_execution":
"A tool failed to execute. "
+ "Please check your inputs and try again.",
"system":
"A system error occurred. "
+ "Please try again later.",
"user_input":
"There was an issue with your input. "
+ "Please check and try again.",
};
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
const friendlyMessage =
ERROR_MESSAGES[input.errorContext];
if (friendlyMessage) {
return {
userNotification: friendlyMessage,
};
}
return null;
},
},
});
抑制非关键错误
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
// Suppress tool execution errors
// that are recoverable
if (
input.errorContext === "tool_execution"
&& input.recoverable
) {
console.log(
`Suppressed recoverable error: `
+ `${input.error}`
);
return { suppressOutput: true };
}
return null;
},
},
});
添加恢复上下文
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
if (
input.errorContext === "tool_execution"
) {
return {
userNotification:
"The tool failed. Here are some "
+ "recovery suggestions:\n"
+ "- Check if required dependencies "
+ "are installed\n"
+ "- Verify file paths are correct\n"
+ "- Try a simpler approach",
};
}
if (
input.errorContext === "model_call"
&& input.error.includes("rate")
) {
return {
errorHandling: "retry",
retryCount: 3,
userNotification:
"Rate limit hit. Retrying...",
};
}
return null;
},
},
});
跟踪错误模式
interface ErrorStats {
count: number;
lastOccurred: number;
contexts: string[];
}
const errorStats =
new Map<string, ErrorStats>();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (
input, invocation
) => {
const key =
`${input.errorContext}:`
+ `${input.error.substring(0, 50)}`;
const existing =
errorStats.get(key) || {
count: 0,
lastOccurred: 0,
contexts: [],
};
existing.count++;
existing.lastOccurred = input.timestamp;
existing.contexts.push(
invocation.sessionId
);
errorStats.set(key, existing);
// Alert if error is recurring
if (existing.count >= 5) {
console.warn(
`Recurring error detected: `
+ `${key} (${existing.count} times)`
);
}
return null;
},
},
});
关键错误警报
const CRITICAL_CONTEXTS = [
"system", "model_call",
];
const session = await client.createSession({
hooks: {
onErrorOccurred: async (
input, invocation
) => {
if (
CRITICAL_CONTEXTS.includes(
input.errorContext
)
&& !input.recoverable
) {
await sendAlert({
level: "critical",
message:
`Critical error in session `
+ `${invocation.sessionId}`,
error: input.error,
context: input.errorContext,
timestamp: new Date(
input.timestamp
).toISOString(),
});
}
return null;
},
},
});
最佳实践
- 始终记录错误。 即使对用户隐藏,也要保留日志以便调试。
- 对错误进行分类。 使用
errorContext适当地处理不同错误。 - 不要吞掉关键错误。 只有在确信错误非关键时才抑制它们。
- 保持钩子快速。 错误处理不应拖慢恢复速度。
- 监控错误模式。 跟踪重复错误以识别系统性问题。