跳转到主要内容

会话钩子

使用 hooks 可以在 Copilot 会话的各个生命周期节点插入处理。 你可以在不修改核心实现的前提下,添加工具执行控制、审计日志、prompt 增强、错误处理等。

钩子流程

基本使用方式

use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionHooks;
use Revolution\Copilot\Types\Hooks\ErrorOccurredHookInput;
use Revolution\Copilot\Types\Hooks\ErrorOccurredHookOutput;
use Revolution\Copilot\Types\Hooks\PostToolUseHookInput;
use Revolution\Copilot\Types\Hooks\PostToolUseHookOutput;
use Revolution\Copilot\Types\Hooks\PreToolUseHookInput;
use Revolution\Copilot\Types\Hooks\PreToolUseHookOutput;
use Revolution\Copilot\Types\Hooks\SessionEndHookInput;
use Revolution\Copilot\Types\Hooks\SessionEndHookOutput;
use Revolution\Copilot\Types\Hooks\SessionStartHookInput;
use Revolution\Copilot\Types\Hooks\SessionStartHookOutput;
use Revolution\Copilot\Types\Hooks\UserPromptSubmittedHookInput;
use Revolution\Copilot\Types\Hooks\UserPromptSubmittedHookOutput;

Copilot::start(function (CopilotSession $session) {
    $response = $session->sendAndWait(prompt: '总结 README 的要点');
    dump($response->content());
}, config: [
    'model' => 'gpt-5',
    'hooks' => new SessionHooks(
        onSessionStart: function (SessionStartHookInput $input): ?SessionStartHookOutput {
            return new SessionStartHookOutput(
                additionalContext: "Project root: {$input->cwd}",
            );
        },

        onUserPromptSubmitted: function (UserPromptSubmittedHookInput $input): ?UserPromptSubmittedHookOutput {
            if (str_starts_with($input->prompt, '/fix')) {
                return new UserPromptSubmittedHookOutput(
                    modifiedPrompt: '请修复当前的错误,并总结变更点。',
                );
            }

            return null;
        },

        onPreToolUse: function (PreToolUseHookInput $input): ?PreToolUseHookOutput {
            $blocked = ['bash', 'shell', 'delete_file'];

            if (in_array($input->toolName, $blocked, true)) {
                return new PreToolUseHookOutput(
                    permissionDecision: 'deny',
                    permissionDecisionReason: "{$input->toolName} 在此环境中不被允许",
                );
            }

            return new PreToolUseHookOutput(permissionDecision: 'allow');
        },

        onPostToolUse: function (PostToolUseHookInput $input): ?PostToolUseHookOutput {
            if ($input->toolName === 'read_file') {
                return new PostToolUseHookOutput(
                    additionalContext: '必要时也可以搜索相关文件进行比较。',
                );
            }

            return null;
        },

        onErrorOccurred: function (ErrorOccurredHookInput $input): ?ErrorOccurredHookOutput {
            if ($input->errorContext === 'model_call' && $input->recoverable) {
                return new ErrorOccurredHookOutput(
                    errorHandling: 'retry',
                    retryCount: 2,
                    userNotification: '由于临时的模型错误将进行重试。',
                );
            }

            return null;
        },

        onSessionEnd: function (SessionEndHookInput $input): ?SessionEndHookOutput {
            if ($input->reason !== 'complete') {
                return new SessionEndHookOutput(
                    sessionSummary: "Session ended with reason: {$input->reason}",
                );
            }

            return null;
        },
    ),
]);

可用的钩子

Hook触发时机主要用途
onSessionStart会话开始(new / resume / startup注入初始上下文、覆盖配置
onUserPromptSubmitted用户 prompt 发送时prompt 增强、模板展开、输入过滤
onPreToolUse工具执行前允许 / 拒绝 / 需确认、修改参数、抑制输出
onPostToolUse工具执行后修改结果、脱敏敏感信息、审计日志
onErrorOccurred会话内发生错误时重试、通知、错误分类
onSessionEnd会话结束时清理、指标、结束摘要
返回 null 时会继续默认行为。

典型用例

1) Permission control(执行控制)

  • 通过 onPreToolUse 用 allow-list 方式限制允许的工具
  • 破坏性操作用 permissionDecision: 'ask' 请求人工确认
  • 通过 permissionDecisionReason 明确拒绝理由
  • toolName 的候选值请参考 Tools 的列表(例如 viewglobbash

2) Auditing / compliance(审计)

  • 组合生命周期钩子收集审计事件
  • 按 session ID 单位持久化收集的数据

3) Prompt enrichment(输入增强)

  • onSessionStart 中把项目信息(语言、框架、约定)加入 additionalContext
  • onUserPromptSubmitted 中展开快捷方式(/fix/test

4) Result filtering(结果整形)

  • onPostToolUse 中对 API key / token / password 等进行脱敏
  • 对过长的结果进行摘要,仅在需要时返回详细内容

5) Error recovery(故障恢复)

  • onErrorOccurred 中仅在 model_callrecoverable=trueretry
  • 无法恢复的错误通过 userNotification 向用户简明通知

6) Session metrics(度量)

  • onSessionStart 中记录开始时间
  • onPreToolUse / onUserPromptSubmitted 中更新计数器
  • onSessionEnd 中输出耗时、工具调用次数、结束原因

Hook input / output 类型

共通输入(BaseHookInput

属性类型说明
timestampint钩子触发时间(Unix ms)
cwdstring当前工作目录

PreToolUseHookInput

属性类型说明
toolNamestring将要执行的工具名
toolArgsmixed将要执行的参数

PreToolUseHookOutput

属性类型说明
permissionDecision?stringallow / deny / ask
permissionDecisionReason?string拒绝 / 确认时的理由
modifiedArgsmixed覆盖后的参数
additionalContext?string追加的上下文
suppressOutput?bool抑制工具输出

PostToolUseHookInput

属性类型说明
toolNamestring已执行的工具名
toolArgsmixed执行时参数
toolResultToolResultObject|array工具结果

PostToolUseHookOutput

属性类型说明
modifiedResultToolResultObject|array|null修改后的结果
additionalContext?string追加的上下文
suppressOutput?bool抑制工具结果显示

UserPromptSubmittedHookInput

属性类型说明
promptstring用户输入的 prompt

UserPromptSubmittedHookOutput

属性类型说明
modifiedPrompt?string修改后的 prompt
additionalContext?string补充上下文
suppressOutput?bool抑制响应显示

SessionStartHookInput

属性类型说明
sourcestringstartup / resume / new
initialPrompt?string初始 prompt

SessionStartHookOutput

属性类型说明
additionalContext?string会话初始上下文
modifiedConfig?array会话配置的部分覆盖

SessionEndHookInput

属性类型说明
reasonstringcomplete / error / abort / timeout / user_exit
finalMessage?string最终消息
error?string结束时的错误

SessionEndHookOutput

属性类型说明
suppressOutput?bool抑制最终输出
cleanupActions?array执行的清理信息
sessionSummary?string会话摘要

ErrorOccurredHookInput

属性类型说明
errorstring错误信息
errorContext?stringmodel_call / tool_execution / system / user_input 之一
recoverablebool是否可恢复

ErrorOccurredHookOutput

属性类型说明
suppressOutput?bool抑制错误显示
errorHandling?stringretry / skip / abort
retryCount?int重试次数
userNotification?string对用户的通知文本

ToolResultObject

工具执行结果的标准对象。
属性类型说明
textResultForLlm?string传给 LLM 的文本结果
resultType?stringsuccess / failure / rejected / denied
resultForAssistant?array面向助手的结果数据

最佳实践

  1. 不要在钩子内直接执行过重的同步处理。如有必要请异步化。
  2. 不需要修改时返回 null,交给默认行为处理。
  3. 尽可能显式地设置 permissionDecision
  4. 关键错误不要过度抑制,请保留日志 / 通知通道。
  5. 会话级状态请基于 session id 管理,并在 onSessionEnd 时清理。
最新信息请参考 GitHub 仓库
最后修改于 2026年7月13日