Skip to main content

Sitzungslebenszyklus-Hooks

Mit Sitzungslebenszyklus-Hooks können Sie auf Start- und Endereignisse der Sitzung reagieren. Verwenden Sie sie für:

  • Initialisieren des Kontexts, wenn Sitzungen beginnen
  • Bereinigen von Ressourcen beim Beenden von Sitzungen
  • Sitzungsmetriken und Analysen nachverfolgen
  • Dynamisches Konfigurieren des Sitzungsverhaltens

Sitzungsstart-Hook {#session-start}

Der onSessionStart Hook wird aufgerufen, wenn eine Sitzung beginnt (neu oder fortgesetzt).

Hook-Signatur

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

SessionStartHandler = Callable[
    [SessionStartHookInput, dict[str, str]],
    Awaitable[SessionStartHookOutput | None]
]
SessionStartHandler = Callable[
    [SessionStartHookInput, dict[str, str]],
    Awaitable[SessionStartHookOutput | None]
]
Go
package main

import copilot "github.com/github/copilot-sdk/go"

type SessionStartHandler func(
    input copilot.SessionStartHookInput,
    invocation copilot.HookInvocation,
) (*copilot.SessionStartHookOutput, error)

func main() {}
type SessionStartHandler func(
    input SessionStartHookInput,
    invocation HookInvocation,
) (*SessionStartHookOutput, error)
.NET
using GitHub.Copilot;

public delegate Task<SessionStartHookOutput?> SessionStartHandler(
    SessionStartHookInput input,
    HookInvocation invocation);
public delegate Task<SessionStartHookOutput?> SessionStartHandler(
    SessionStartHookInput input,
    HookInvocation invocation);
Java
import com.github.copilot.sdk.json.*;

SessionStartHandler sessionStartHandler;

Eingabe

FeldTypBeschreibung
timestampnumberUnix-Zeitstempel, zu dem der Hook ausgelöst wurde
cwdstringAktuelles Arbeitsverzeichnis
source
"startup"
|
"resume"
|
"new"
Wie die Sitzung gestartet wurde
initialPromptZeichenfolge | undefiniertDie anfängliche Eingabeaufforderung, falls angegeben

Output

FeldTypBeschreibung
additionalContextstringKontext zum Hinzufügen am Sitzungsstart
modifiedConfigObjektSitzungskonfiguration außer Kraft setzen

Beispiele

Projektkontext zu Beginn hinzufügen

TypeScript
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.
Main language: ${projectInfo.language}
Package manager: ${projectInfo.packageManager}
        `.trim(),
      };
    },
  },
});
Python
from copilot.session import PermissionHandler

async def on_session_start(input_data, invocation):
    print(f"Session {invocation['session_id']} started ({input_data['source']})")
    
    project_info = await detect_project_type(input_data["cwd"])
    
    return {
        "additionalContext": f"""
This is a {project_info['type']} project.
Main language: {project_info['language']}
Package manager: {project_info['packageManager']}
        """.strip()
    }

session = await client.create_session(on_permission_request=PermissionHandler.approve_all, hooks={"on_session_start": on_session_start})

Verwaltung der Sitzungswiederaufnahme

const session = await client.createSession({
  hooks: {
    onSessionStart: async (input, invocation) => {
      if (input.source === "resume") {
        // Load previous session state
        const previousState = await loadSessionState(invocation.sessionId);
        
        return {
          additionalContext: `
Session resumed. Previous context:
- Last topic: ${previousState.lastTopic}
- Open files: ${previousState.openFiles.join(", ")}
          `.trim(),
        };
      }
      return null;
    },
  },
});

Laden von Benutzereinstellungen

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

Hook für das Sitzungsende {#session-end}

Der onSessionEnd Hook wird aufgerufen, wenn eine Sitzung endet.

Hook-Signatur

TypeScript
type SessionEndHandler = (
  input: SessionEndHookInput,
  invocation: HookInvocation
) => Promise<SessionEndHookOutput | null | undefined>;
Python
from copilot.session import SessionEndHookInput
from typing import Callable, Awaitable

SessionEndHandler = Callable[
    [SessionEndHookInput, dict[str, str]],
    Awaitable[None]
]
SessionEndHandler = Callable[
    [SessionEndHookInput, dict[str, str]],
    Awaitable[SessionEndHookOutput | None]
]
Go
package main

import copilot "github.com/github/copilot-sdk/go"

type SessionEndHandler func(
    input copilot.SessionEndHookInput,
    invocation copilot.HookInvocation,
) error

func main() {}
type SessionEndHandler func(
    input SessionEndHookInput,
    invocation HookInvocation,
) (*SessionEndHookOutput, error)
.NET
public delegate Task<SessionEndHookOutput?> SessionEndHandler(
    SessionEndHookInput input,
    HookInvocation invocation);
Java
import com.github.copilot.sdk.json.*;

SessionEndHandler sessionEndHandler;

Eingabe

FeldTypBeschreibung
timestampnumberUnix-Zeitstempel, zu dem der Hook ausgelöst wurde
cwdstringAktuelles Arbeitsverzeichnis
reasonstringWarum die Sitzung beendet wurde (siehe unten)
finalMessageZeichenfolge | undefiniertDie letzte Nachricht aus der Sitzung
errorZeichenfolge | undefiniertFehlermeldung, wenn die Sitzung aufgrund eines Fehlers beendet wurde

Endgründe

GrundBeschreibung
"complete"Die Sitzung wurde normal abgeschlossen.
"error"Sitzung aufgrund eines Fehlers beendet
"abort"Die Sitzung wurde durch den Benutzer oder durch Code abgebrochen.
"timeout"Sitzung abgelaufen
"user_exit"Der Benutzer hat die Sitzung explizit beendet.

Output

FeldTypBeschreibung
suppressOutputbooleanEndgültige Sitzungsausgabe unterdrücken
cleanupActionsstring[]Liste der auszuführenden Bereinigungsaktionen
sessionSummarystringZusammenfassung der Sitzung für Protokollierung/Analyse

Beispiele

Nachverfolgen von Sitzungsmetriken

TypeScript
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
from copilot.session import PermissionHandler

session_start_times = {}

async def on_session_start(input_data, invocation):
    session_start_times[invocation["session_id"]] = input_data["timestamp"]
    return None

async def on_session_end(input_data, invocation):
    start_time = session_start_times.get(invocation["session_id"])
    duration = input_data["timestamp"] - start_time if start_time else 0
    
    await record_metrics({
        "session_id": invocation["session_id"],
        "duration": duration,
        "end_reason": input_data["reason"],
    })
    
    session_start_times.pop(invocation["session_id"], None)
    return None

session = await client.create_session(on_permission_request=PermissionHandler.approve_all, hooks={
        "on_session_start": on_session_start,
        "on_session_end": on_session_end,
    })

Bereinigen von Ressourcen

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) {
        // Clean up temp files
        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;
    },
  },
});

Sitzungsstatus zum Fortsetzen speichern

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

Protokollsitzungszusammenfassung

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];
      console.log(`
Session Summary:
  ID: ${invocation.sessionId}
  Duration: ${(input.timestamp - data.startTime) / 1000}s
  Prompts: ${data.prompts}
  Tool calls: ${data.tools}
  End reason: ${input.reason}
      `.trim());
      
      delete sessionData[invocation.sessionId];
      return null;
    },
  },
});

Bewährte Methoden

  1. Sorgen Sie dafür, dass onSessionStart schnell bleibt – Die Benutzer warten darauf, dass die Sitzung einsatzbereit ist.

  2. Berücksichtigen Sie alle Gründe für die Beendigung – Gehen Sie nicht davon aus, dass Sitzungen immer ordnungsgemäß beendet werden; behandeln Sie auch Fehler und Abbrüche.

  3. Ressourcen freigeben – Verwenden Sie onSessionEnd, um alle während der Sitzung zugewiesenen Ressourcen freizugeben.

  4. Speichern Sie so wenig Status wie möglich - Wenn Sie Sitzungsdaten verfolgen, halten Sie sie so schlank wie möglich.

  5. Make cleanup idempotent - onSessionEnd wird möglicherweise nicht aufgerufen, wenn der Prozess abstürzt.

Siehe auch