Skip to main content

사용자 프롬프트 제출 후크

          `onUserPromptSubmitted` 후크를 사용하여 프롬프트를 수정하고, 컨텍스트를 추가하고, 사용자 입력을 필터링합니다코필로트 SDK.

누가 이 기능을 사용할 수 있나요?

GitHub Copilot SDK 는 모든 Copilot 계획에서 사용할 수 있습니다.

참고

코필로트 SDK가 현재 기술 미리 보기에 있습니다. 기능 및 가용성은 변경될 수 있습니다.

          `onUserPromptSubmitted` 사용자가 메시지를 제출할 때 후크가 호출됩니다. 이를 사용하여 다음을 수행합니다.
  • 사용자 프롬프트 수정 또는 향상
  • 처리하기 전에 컨텍스트 추가
  • 사용자 입력 필터링 또는 유효성 검사
  • 프롬프트 템플릿 구현

후크 서명

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

Python, Go 및 .NET의 후크 서명은 리포지토리를github/copilot-sdk 참조하세요.

입력

분야유형설명
timestamp숫자후크가 트리거될 때의 Unix 타임스탬프
cwd문자열현재 작업 디렉터리
prompt문자열사용자가 제출한 프롬프트

출력

          `null` 또는 `undefined`를 반환하여 프롬프트를 변경하지 않고 사용합니다. 그렇지 않으면 다음 필드 중 하나가 있는 객체를 반환합니다.
분야유형설명
modifiedPrompt문자열원래 대신 사용할 수정된 프롬프트
additionalContext문자열대화에 추가된 추가 컨텍스트
suppressOutput부울true이면 도우미의 응답 출력을 표시하지 않습니다.

예제

모든 사용자 프롬프트 기록

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (
      input, invocation
    ) => {
      console.log(
        `[${invocation.sessionId}] `
        + `User: ${input.prompt}`
      );
      return null; // Pass through unchanged
    },
  },
});

Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요.

프로젝트 컨텍스트 추가

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      const projectInfo = await getProjectInfo();

      return {
        additionalContext: `
Project: ${projectInfo.name}
Language: ${projectInfo.language}
Framework: ${projectInfo.framework}
        `.trim(),
      };
    },
  },
});

축약 명령어 확장

const SHORTCUTS: Record<string, string> = {
  "/fix":
    "Please fix the errors in the code",
  "/explain":
    "Please explain this code in detail",
  "/test":
    "Please write unit tests for this code",
  "/refactor":
    "Please refactor this code to improve "
    + "readability and maintainability",
};

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      for (const [shortcut, expansion]
        of Object.entries(SHORTCUTS)) {
        if (input.prompt.startsWith(shortcut)) {
          const rest = input.prompt
            .slice(shortcut.length).trim();
          return {
            modifiedPrompt:
              `${expansion}`
              + `${rest ? `: ${rest}` : ""}`,
          };
        }
      }
      return null;
    },
  },
});

콘텐츠 필터링

const BLOCKED_PATTERNS = [
  /password\s*[:=]/i,
  /api[_-]?key\s*[:=]/i,
  /secret\s*[:=]/i,
];

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      for (const pattern of BLOCKED_PATTERNS) {
        if (pattern.test(input.prompt)) {
          return {
            modifiedPrompt:
              "[Content blocked: Please don't "
              + "include sensitive credentials "
              + "in your prompts. Use environment "
              + "variables instead.]",
            suppressOutput: true,
          };
        }
      }
      return null;
    },
  },
});

프롬프트 제한 길이 적용

const MAX_PROMPT_LENGTH = 10000;

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      if (input.prompt.length > MAX_PROMPT_LENGTH) {
        // Truncate the prompt and add context
        return {
          modifiedPrompt: input.prompt.substring(0, MAX_PROMPT_LENGTH),
          additionalContext: `Note: The original prompt was ${input.prompt.length} characters and was truncated to ${MAX_PROMPT_LENGTH} characters.`,
        };
      }
      return null;
    },
  },
});

사용자 기본 설정 추가

interface UserPreferences {
  codeStyle: "concise" | "verbose";
  preferredLanguage: string;
  experienceLevel: "beginner" | "intermediate" | "expert";
}

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      const prefs: UserPreferences = await loadUserPreferences();
      
      const contextParts = [];
      
      if (prefs.codeStyle === "concise") {
        contextParts.push("User prefers concise code with minimal comments.");
      } else {
        contextParts.push("User prefers verbose code with detailed comments.");
      }
      
      if (prefs.experienceLevel === "beginner") {
        contextParts.push("Explain concepts in simple terms.");
      }
      
      return {
        additionalContext: contextParts.join(" "),
      };
    },
  },
});

속도 제한

const promptTimestamps: number[] = [];
const RATE_LIMIT = 10; // prompts
const RATE_WINDOW = 60000; // 1 minute

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      const now = Date.now();
      
      // Remove timestamps outside the window
      while (promptTimestamps.length > 0 && promptTimestamps[0] < now - RATE_WINDOW) {
        promptTimestamps.shift();
      }
      
      if (promptTimestamps.length >= RATE_LIMIT) {
        return {
          reject: true,
          rejectReason: `Rate limit exceeded. Please wait before sending more prompts.`,
        };
      }
      
      promptTimestamps.push(now);
      return null;
    },
  },
});

프롬프트 템플릿

const TEMPLATES: Record<
  string, (args: string) => string
> = {
  "bug:": (desc) =>
    `I found a bug: ${desc}\n\n`
    + `Please help me:\n`
    + `1. Understand why this is happening\n`
    + `2. Suggest a fix\n`
    + `3. Explain how to prevent similar bugs`,

  "feature:": (desc) =>
    `I want to implement this feature: `
    + `${desc}\n\n`
    + `Please:\n`
    + `1. Outline the implementation approach\n`
    + `2. Identify potential challenges\n`
    + `3. Provide sample code`,
};

const session = await client.createSession({
  hooks: {
    onUserPromptSubmitted: async (input) => {
      for (const [prefix, template]
        of Object.entries(TEMPLATES)) {
        if (
          input.prompt.toLowerCase()
            .startsWith(prefix)
        ) {
          const args = input.prompt
            .slice(prefix.length).trim();
          return {
            modifiedPrompt: template(args),
          };
        }
      }
      return null;
    },
  },
});

모범 사례

  •         **사용자 의도를 유지합니다.** 프롬프트를 수정할 때 핵심 의도를 명확하게 유지합니다.
    
  •         **수정 내용에 대해 투명하게 설명합니다.** 프롬프트를 크게 변경하는 경우 로깅하거나 사용자에게 알리는 것이 좋습니다.
    
  •         **
            `additionalContext`를 `modifiedPrompt`보다 사용하십시오.** 컨텍스트를 추가하는 것은 프롬프트를 다시 작성하는 것보다 덜 방해가 됩니다.
    
  •         **명확한 거부 이유를 제공합니다.** 프롬프트를 거부할 때 문제를 해결하는 이유와 방법을 설명합니다.
    
  •         **처리를 빠르게 유지합니다.** 이 후크는 모든 사용자 메시지에서 실행됩니다. 느린 작업을 방지합니다.
    

추가 읽기

  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/quickstart)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/session-lifecycle)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/pre-tool-use)