Skip to main content

セッションライフサイクルフック

          `onSessionStart`と`onSessionEnd`フックを使用して、コンテキストの初期化、リソースのクリーンアップ、Copilot SDKでのセッション メトリックの追跡を行います。

この機能を使用できるユーザーについて

GitHub Copilot SDK は、すべての Copilot プランで使用できます。

メモ

Copilot SDK は現在 テクニカル プレビューです。 機能と可用性は変更される場合があります。

セッション ライフサイクル フックを使用すると、セッションの開始イベントと終了イベントに応答できます。 次の場合に使用します。

  • セッションの開始時にコンテキストを初期化する
  • セッションの終了時にリソースをクリーンアップする
  • セッション メトリックと分析を追跡する
  • セッション動作を動的に構成する

セッション開始フック

          `onSessionStart` フックは、セッションの開始時 (新規または再開) に呼び出されます。

フック署名

import type { SessionStartHookInput, HookInvocation, SessionStartHookOutput } from "@github/copilot-sdk";
type SessionStartHandler = (
  input: SessionStartHookInput,
  invocation: HookInvocation
) => Promise<
  SessionStartHookOutput | null | undefined
>;

Python、Go、.NET のフック署名については、 github/copilot-sdk リポジトリを参照してください。

入力

フィールドタイプ説明
timestamp数値フックがトリガーされたときの Unix タイムスタンプ
cwd文字列現在の作業ディレクトリ
source
          `"startup"`
          \|
          `"resume"`
          \|
          `"new"`
         | セッションの開始方法 |

| initialPrompt | 文字列 | 未定義 | 最初のプロンプト (指定されている場合) |

アウトプット

フィールドタイプ説明
additionalContext文字列セッション開始時に追加するコンテキスト
modifiedConfigオブジェクトセッション構成をオーバーライドする

例示

開始時にプロジェクト コンテキストを追加する

const session = await client.createSession({
  hooks: {
    onSessionStart: async (
      input, invocation
    ) => {
      console.log(
        `Session ${invocation.sessionId} `
        + `started (${input.source})`
      );

      const projectInfo =
        await detectProjectType(input.cwd);

      return {
        additionalContext:
          `This is a ${projectInfo.type} project.\n`
          + `Main language: `
          + `${projectInfo.language}\n`
          + `Package manager: `
          + `${projectInfo.packageManager}`,
      };
    },
  },
});

Python の例については、 github/copilot-sdk リポジトリを参照してください。

セッションの再開を処理する

const session = await client.createSession({
  hooks: {
    onSessionStart: async (
      input, invocation
    ) => {
      if (input.source === "resume") {
        const previousState =
          await loadSessionState(
            invocation.sessionId
          );

        return {
          additionalContext:
            `Session resumed. Previous context:\n`
            + `- Last topic: `
            + `${previousState.lastTopic}\n`
            + `- Open files: `
            + previousState.openFiles.join(", "),
        };
      }
      return null;
    },
  },
});

ユーザー設定を読み込む

const session = await client.createSession({
  hooks: {
    onSessionStart: async () => {
      const preferences =
        await loadUserPreferences();

      const contextParts = [];

      if (preferences.language) {
        contextParts.push(
          `Preferred language: `
          + `${preferences.language}`
        );
      }
      if (preferences.codeStyle) {
        contextParts.push(
          `Code style: ${preferences.codeStyle}`
        );
      }
      if (preferences.verbosity === "concise") {
        contextParts.push(
          "Keep responses brief and "
          + "to the point."
        );
      }

      return {
        additionalContext:
          contextParts.join("\n"),
      };
    },
  },
});

セッション終了フック

          `onSessionEnd` フックは、セッションの終了時に呼び出されます。

フック署名

import {
  HookInvocation,
  SessionEndHookInput,
  SessionEndHookOutput,
} from "@github/copilot-sdk";

type SessionEndHandler = (
  input: SessionEndHookInput,
  invocation: HookInvocation
) => Promise<
  SessionEndHookOutput | null | undefined
>;

Python、Go、.NET のフック署名については、 github/copilot-sdk リポジトリを参照してください。

入力

フィールドタイプ説明
timestamp数値フックがトリガーされたときの Unix タイムスタンプ
cwd文字列現在の作業ディレクトリ
reason文字列セッションが終了した理由 (次の表を参照)
finalMessage文字列 | 未定義セッションからの最後のメッセージ
error文字列 | 未定義エラーが原因でセッションが終了した場合のエラー メッセージ

終了の理由

理由説明
"complete"セッションが正常に完了しました
"error"エラーが原因でセッションが終了しました
"abort"ユーザーまたはコードによってセッションが中止されました
"timeout"セッションがタイムアウトしました
"user_exit"ユーザーがセッションを明示的に終了した

アウトプット

フィールドタイプ説明
suppressOutputブーリアン最後のセッション出力を抑制する
cleanupActionsstring[]実行するクリーンアップ アクションの一覧
sessionSummary文字列ログ記録/分析のセッションの概要

例示

セッション メトリックを追跡する

const sessionStartTimes =
  new Map<string, number>();

const session = await client.createSession({
  hooks: {
    onSessionStart: async (
      input, invocation
    ) => {
      sessionStartTimes.set(
        invocation.sessionId, input.timestamp
      );
      return null;
    },
    onSessionEnd: async (
      input, invocation
    ) => {
      const startTime = sessionStartTimes.get(
        invocation.sessionId
      );
      const duration = startTime
        ? input.timestamp - startTime
        : 0;

      await recordMetrics({
        sessionId: invocation.sessionId,
        duration,
        endReason: input.reason,
      });

      sessionStartTimes.delete(
        invocation.sessionId
      );
      return null;
    },
  },
});

Python の例については、 github/copilot-sdk リポジトリを参照してください。

リソースをクリーンアップする

const sessionResources =
  new Map<string, { tempFiles: string[] }>();

const session = await client.createSession({
  hooks: {
    onSessionStart: async (
      input, invocation
    ) => {
      sessionResources.set(
        invocation.sessionId,
        { tempFiles: [] }
      );
      return null;
    },
    onSessionEnd: async (
      input, invocation
    ) => {
      const resources =
        sessionResources.get(
          invocation.sessionId
        );

      if (resources) {
        for (const file
          of resources.tempFiles) {
          await fs.unlink(file).catch(() => {});
        }
        sessionResources.delete(
          invocation.sessionId
        );
      }

      console.log(
        `Session ${invocation.sessionId} `
        + `ended: ${input.reason}`
      );
      return null;
    },
  },
});

再開のためにセッション状態を保存する

const session = await client.createSession({
  hooks: {
    onSessionEnd: async (input, invocation) => {
      if (input.reason !== "error") {
        // Save state for potential resume
        await saveSessionState(invocation.sessionId, {
          endTime: input.timestamp,
          cwd: input.cwd,
          reason: input.reason,
        });
      }
      return null;
    },
  },
});

ログ セッションの概要

const sessionData: Record<
  string,
  { prompts: number; tools: number;
    startTime: number }
> = {};

const session = await client.createSession({
  hooks: {
    onSessionStart: async (
      input, invocation
    ) => {
      sessionData[invocation.sessionId] = {
        prompts: 0,
        tools: 0,
        startTime: input.timestamp,
      };
      return null;
    },
    onUserPromptSubmitted: async (
      _, invocation
    ) => {
      sessionData[
        invocation.sessionId
      ].prompts++;
      return null;
    },
    onPreToolUse: async (_, invocation) => {
      sessionData[
        invocation.sessionId
      ].tools++;
      return { permissionDecision: "allow" };
    },
    onSessionEnd: async (
      input, invocation
    ) => {
      const data =
        sessionData[invocation.sessionId];
      const durationSec =
        (input.timestamp - data.startTime)
        / 1000;
      console.log(
        `Session Summary:\n`
        + `  ID: ${invocation.sessionId}\n`
        + `  Duration: ${durationSec}s\n`
        + `  Prompts: ${data.prompts}\n`
        + `  Tool calls: ${data.tools}\n`
        + `  End reason: ${input.reason}`
      );

      delete sessionData[
        invocation.sessionId
      ];
      return null;
    },
  },
});

ベスト プラクティス

  •         **
            `onSessionStart`速度を維持します。** ユーザーはセッションの準備を待っている。
    
  •         **すべての終了の理由を処理します。** セッションが正常に終了することを想定しないでください。エラーと中止を処理します。
    
  •         **リソースをクリーンアップします。** 
            `onSessionEnd`を使用して、セッション中に割り当てられたリソースを解放します。
    
  •         **最小状態を格納します。** セッション データを追跡する場合は、軽量のままにします。
    
  •         **クリーンアップを冪等性にします。** 
            `onSessionEnd` は、プロセスがクラッシュした場合に呼び出されない可能性があります。
    

詳細については、次を参照してください。

  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/quickstart)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/error-handling)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/user-prompt-submitted)