Skip to main content

Конфигурация крючков

Найдите информацию о настройке крючков для использования с GitHub Copilot CLI и Агент кодирования Copilot.

В этой справочной статье описываются доступные типы хуков с примерами, включая их форматы ввода и вывода, лучшие практики скриптов и продвинутые шаблоны логирования, обеспечения безопасности и внешних интеграций. Для общей информации о создании крючков см. АВТОЗАГОЛОВОК.

Типы крючков

Крюк для начала сессии

Выполняется при начале новой сессии агента или при возобновлении существующей сессии.

          **Ввод JSON:**
JSON
{
  "timestamp": 1704614400000,
  "cwd": "/path/to/project",
  "source": "new",
  "initialPrompt": "Create a new feature"
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * source: Либо "new" (новая сессия), "resume" (возобновленная сессия), или "startup" * initialPrompt: Первоначальный запрос пользователя (если он предоставлен)

          **Результаты:** Игнорировано (возвратное значение не обработано)

          **Пример хука:**
JSON
{
  "type": "command",
  "bash": "./scripts/session-start.sh",
  "powershell": "./scripts/session-start.ps1",
  "cwd": "scripts",
  "timeoutSec": 30
}
          **Пример сценария (Bash):**
Shell
#!/bin/bash
INPUT=$(cat)
SOURCE=$(echo "$INPUT" | jq -r '.source')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

echo "Session started from $SOURCE at $TIMESTAMP" >> session.log

Хук в конце сессии

Выполняется после завершения или завершения сессии агента.

          **Ввод JSON:**
JSON
{
  "timestamp": 1704618000000,
  "cwd": "/path/to/project",
  "reason": "complete"
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * reason: Один из "complete", "error", "abort", "timeout", или "user_exit"

          **Результаты:** Игнорируется

          **Пример скрипта:**
Shell
#!/bin/bash
INPUT=$(cat)
REASON=$(echo "$INPUT" | jq -r '.reason')

echo "Session ended: $REASON" >> session.log
# Cleanup temporary files
rm -rf /tmp/session-*

Хук, присланный пользовательским запросом

Выполняется, когда пользователь отправляет запрос агенту.

          **Ввод JSON:**
JSON
{
  "timestamp": 1704614500000,
  "cwd": "/path/to/project",
  "prompt": "Fix the authentication bug"
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * prompt: Точный текст, который пользователь отправил

          **Результаты:** Игнорируется (изменение запросов в настоящее время не поддерживается в клиентских хуках)

          **Пример скрипта:**
Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

# Log to a structured file
echo "$(date -d @$((TIMESTAMP/1000))): $PROMPT" >> prompts.log

Крючок для использования до использования инструмента

Выполняется до того, как агент использует какой-либо инструмент (напримерbash, , edit). view Это самый мощный крючок, так как он может одобрять или отклонять выполнение инструментов.

          **Ввод JSON:**
JSON
{
  "timestamp": 1704614600000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"rm -rf dist\",\"description\":\"Clean build directory\"}"
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * toolName: Название вызываемого инструмента (например, «bash», «edit», «view», «create») * toolArgs: JSON-строка, содержащая аргументы инструмента

          **Вывод JSON (по желанию):**
JSON
{
  "permissionDecision": "deny",
  "permissionDecisionReason": "Destructive operations require approval"
}
          **Выходные поля:**

* permissionDecision: Либо "allow", "deny", , или "ask" (только "deny" в настоящее время обрабатывается) * permissionDecisionReason: Объяснение решения для человека

          **Пример крючка для блокировки опасных команд:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TOOL_ARGS=$(echo "$INPUT" | jq -r '.toolArgs')

# Log the tool use
echo "$(date): Tool=$TOOL_NAME Args=$TOOL_ARGS" >> tool-usage.log

# Check for dangerous patterns
if echo "$TOOL_ARGS" | grep -qE "rm -rf /|format|DROP TABLE"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous command detected"}'
  exit 0
fi

# Allow by default (or omit output to allow)
echo '{"permissionDecision":"allow"}'
          **Пример крючка для обеспечения разрешения файлов:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only allow editing specific directories
if [ "$TOOL_NAME" = "edit" ]; then
  PATH_ARG=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.path')
  
  if [[ ! "$PATH_ARG" =~ ^(src/|test/) ]]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Can only edit files in src/ or test/ directories"}'
    exit 0
  fi
fi

# Allow all other tools

Крючок после использования инструмента

Выполняется после завершения выполнения инструмента (независимо от того, успешный или неудачный).

          **Пример ввода JSON:**
JSON
{
  "timestamp": 1704614700000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"npm test\"}",
  "toolResult": {
    "resultType": "success",
    "textResultForLlm": "All tests passed (15/15)"
  }
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * toolName: Название инструмента, который был реализован * toolArgs: JSON-строка, содержащая аргументы инструмента * toolResult: Объект результата, содержащий: * resultType: Либо "success", "failure", или "denied" * textResultForLlm: Текст результата, показанный агенту

          **Результаты:** Игнорируется (изменение результатов в настоящее время не поддерживается)

          **Пример скрипта, который ведёт статистику выполнения инструментов в CSV-файл:**

Этот скрипт фиксирует статистику выполнения инструментов в CSV-файле и отправляет уведомление по электронной почте при отказе инструмента.

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Track statistics
echo "$(date),${TOOL_NAME},${RESULT_TYPE}" >> tool-stats.csv

# Alert on failures
if [ "$RESULT_TYPE" = "failure" ]; then
  RESULT_TEXT=$(echo "$INPUT" | jq -r '.toolResult.textResultForLlm')
  echo "FAILURE: $TOOL_NAME - $RESULT_TEXT" | mail -s "Agent Tool Failed" [email protected]
fi

Возникла ошибка, крюк

Выполняется, когда возникает ошибка во время выполнения агента.

          **Пример ввода JSON:**
JSON
{
  "timestamp": 1704614800000,
  "cwd": "/path/to/project",
  "error": {
    "message": "Network timeout",
    "name": "TimeoutError",
    "stack": "TimeoutError: Network timeout\n    at ..."
  }
}
          **Поля:**

* timestamp: Тайммет Unix в миллисекундах * cwd: Текущий рабочий справочник * error: Объект ошибки, содержащий: * message: Сообщение об ошибке * name: Тип/название ошибки * stack: Трассировка стека (если доступна)

          **Результаты:** Игнорируется (модификация с обработкой ошибок в настоящее время не поддерживается)

          **Пример скрипта, который извлекает детали ошибки в файл журнала:**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')
ERROR_NAME=$(echo "$INPUT" | jq -r '.error.name')

echo "$(date): [$ERROR_NAME] $ERROR_MSG" >> errors.log

Лучшие практики скриптов

Чтение

Этот пример скрипта считывает JSON-вход из stdin в переменную, затем использует jq для извлечения timestamp полей and cwd .

          **Bash:**
Shell
#!/bin/bash
# Read JSON from stdin
INPUT=$(cat)

# Parse with jq
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
CWD=$(echo "$INPUT" | jq -r '.cwd')
          **PowerShell:**
PowerShell
# Read JSON from stdin
$input = [Console]::In.ReadToEnd() | ConvertFrom-Json

# Access properties
$timestamp = $input.timestamp
$cwd = $input.cwd

Вывод JSON

Этот пример скрипта показывает, как выводить валидный JSON из вашего скрипта hook. Используйте jq -c в Bash для компактного однострочного вывода или ConvertTo-Json -Compress в PowerShell.

          **Bash:**
Shell
#!/bin/bash
# Use jq to compact the JSON output to a single line
echo '{"permissionDecision":"deny","permissionDecisionReason":"Security policy violation"}' | jq -c

# Or construct with variables
REASON="Too dangerous"
jq -n --arg reason "$REASON" '{permissionDecision: "deny", permissionDecisionReason: $reason}'
          **PowerShell:**
PowerShell
# Use ConvertTo-Json to compact the JSON output to a single line
$output = @{
    permissionDecision = "deny"
    permissionDecisionReason = "Security policy violation"
}
$output | ConvertTo-Json -Compress

Обработка ошибок

Этот пример скрипта демонстрирует, как обрабатывать ошибки в скриптах с крючками.

          **Bash:**
Shell
#!/bin/bash
set -e  # Exit on error

INPUT=$(cat)
# ... process input ...

# Exit with 0 for success
exit 0
          **PowerShell:**
PowerShell
$ErrorActionPreference = "Stop"

try {
    $input = [Console]::In.ReadToEnd() | ConvertFrom-Json
    # ... process input ...
    exit 0
} catch {
    Write-Error $_.Exception.Message
    exit 1
}

Обработка времени ожидания

У хуков по умолчанию тайм-аут составляет 30 секунд. Для более длительных операций увеличивайте timeoutSec:

JSON
{
  "type": "command",
  "bash": "./scripts/slow-validation.sh",
  "timeoutSec": 120
}

Продвинутые паттерны

Несколько крючков одного типа

Вы можете определить несколько крючков для одного и того же события. Они выполняются в следующем порядке:

JSON
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/security-check.sh",
        "comment": "Security validation - runs first"
      },
      {
        "type": "command", 
        "bash": "./scripts/audit-log.sh",
        "comment": "Audit logging - runs second"
      },
      {
        "type": "command",
        "bash": "./scripts/metrics.sh",
        "comment": "Metrics collection - runs third"
      }
    ]
  }
}

Условная логика в скриптах

          **Пример: блокировать только определённые инструменты**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only validate bash commands
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0  # Allow all non-bash tools
fi

# Check bash command for dangerous patterns
COMMAND=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.command')
if echo "$COMMAND" | grep -qE "rm -rf|sudo|mkfs"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous system command"}'
fi

Структурированное ведение журнала

          **Пример: формат JSON Lines**
Shell
#!/bin/bash
INPUT=$(cat)
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Output structured log entry
jq -n \
  --arg ts "$TIMESTAMP" \
  --arg tool "$TOOL_NAME" \
  --arg result "$RESULT_TYPE" \
  '{timestamp: $ts, tool: $tool, result: $result}' >> logs/audit.jsonl

Интеграция с внешними системами

          **Пример: отправить уведомления в Slack**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

curl -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Agent Error: $ERROR_MSG\"}"

Примеры вариантов использования

Следы аудита соответствия

Ведите журнал всех действий агента для соответствия требованиям, используя скрипты журнала:

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [{"type": "command", "bash": "./audit/log-session-start.sh"}],
    "userPromptSubmitted": [{"type": "command", "bash": "./audit/log-prompt.sh"}],
    "preToolUse": [{"type": "command", "bash": "./audit/log-tool-use.sh"}],
    "postToolUse": [{"type": "command", "bash": "./audit/log-tool-result.sh"}],
    "sessionEnd": [{"type": "command", "bash": "./audit/log-session-end.sh"}]
  }
}

Отслеживание затрат

Отслеживайте использование инструментов для распределения затрат:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
USER=${USER:-unknown}

echo "$TIMESTAMP,$USER,$TOOL_NAME" >> /var/log/copilot/usage.csv

Контроль качества кодекса

Предотвращение коммитов, нарушающих стандарты кода:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

if [ "$TOOL_NAME" = "edit" ] || [ "$TOOL_NAME" = "create" ]; then
  # Run linter before allowing edits
  npm run lint-staged
  if [ $? -ne 0 ]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Code does not pass linting"}'
  fi
fi

Система уведомлений

Отправляйте уведомления о важных событиях:

Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')

# Notify on production-related prompts
if echo "$PROMPT" | grep -iq "production"; then
  echo "ALERT: Production-related prompt: $PROMPT" | mail -s "Agent Alert" [email protected]
fi