Skip to main content

エラー処理フック

onErrorOccurred フックは、セッションの実行中にエラーが発生したときに呼び出されます。 これは次の目的で使用されます。

  • カスタム エラー ログを実装する
  • エラー パターンを追跡する
  • わかりやすいエラー メッセージを提供する
  • 重大なエラーのアラートをトリガーする

フック署名

コード言語 navigation

TypeScript
import type { ErrorOccurredHookInput, HookInvocation, ErrorOccurredHookOutput } from "@github/copilot-sdk";
type ErrorOccurredHandler = (
  input: ErrorOccurredHookInput,
  invocation: HookInvocation
) => Promise<ErrorOccurredHookOutput | null | undefined>;
type ErrorOccurredHandler = (
  input: ErrorOccurredHookInput,
  invocation: HookInvocation
) => Promise<ErrorOccurredHookOutput | null | undefined>;

入力

フィールドタイプDescription
timestamp数値エラーが発生したときの Unix タイムスタンプ
cwd文字列現在の作業ディレクトリ
error文字列エラー メッセージ
errorContext文字列エラーが発生した場所: "model_call""tool_execution""system"、または "user_input"
recoverablebooleanエラーを復旧できる可能性があるかどうか

アウトプット

既定のエラー処理を使用するには、 null または undefined を返します。 それ以外の場合は、次のオブジェクトを返します。

フィールドタイプDescription
suppressOutputbooleantrue、エラー出力をユーザーに表示しない
errorHandling文字列処理方法: "retry""skip"、または "abort"
retryCount数値再試行する回数 (errorHandling が "retry"場合)
userNotification文字列ユーザーを表示するカスタム メッセージ

基本的なエラー ログ

コード言語 navigation

TypeScript
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;
    },
  },
});

監視サービスにエラーを送信する

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:
- Check if required dependencies are installed
- Verify file paths are correct
- Try a simpler approach
          `.trim(),
        };
      }
      
      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;
    },
  },
});

コンテキストの他のフックと組み合わせる

const sessionContext = new Map<string, { lastTool?: string; lastPrompt?: string }>();

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input, invocation) => {
      const ctx = sessionContext.get(invocation.sessionId) || {};
      ctx.lastTool = input.toolName;
      sessionContext.set(invocation.sessionId, ctx);
      return { permissionDecision: "allow" };
    },
    
    onUserPromptSubmitted: async (input, invocation) => {
      const ctx = sessionContext.get(invocation.sessionId) || {};
      ctx.lastPrompt = input.prompt.substring(0, 100);
      sessionContext.set(invocation.sessionId, ctx);
      return null;
    },
    
    onErrorOccurred: async (input, invocation) => {
      const ctx = sessionContext.get(invocation.sessionId);
      
      console.error(`Error in session ${invocation.sessionId}:`);
      console.error(`  Error: ${input.error}`);
      console.error(`  Context: ${input.errorContext}`);
      if (ctx?.lastTool) {
        console.error(`  Last tool: ${ctx.lastTool}`);
      }
      if (ctx?.lastPrompt) {
        console.error(`  Last prompt: ${ctx.lastPrompt}...`);
      }
      
      return null;
    },
  },
});

ベスト プラクティス

  1. 常にエラーをログに記録 する - ユーザーからエラーを抑制した場合でも、デバッグのためにログを保持します。

  2. エラーの分類 - errorType を使用して、さまざまなエラーを適切に処理します。

  3. 重大なエラーを飲み込まない - 重大 でないと確信しているエラーのみを抑制します。

  4. フックを高速に保つ - エラー処理によって回復速度が低下しないようにする必要があります。

  5. 便利なコンテキストを提供 する - エラーが発生した場合、 additionalContext はモデルの回復に役立ちます。

  6. エラー パターンの監視 - 定期的なエラーを追���して、全身的な問題を特定します。

こちらも参照ください