Skip to content

深度分析 #17: Hook 系统完整架构 — 脚本钩子与异步 Webhook

新增维度 — 此前仅部分覆盖类型定义,完整钩子系统未分析 日期: 2026-06-25 | 来源: strings atomcode.bin.bak 完整挖掘


1. 概述

Hook 系统是 AtomCode 的事件驱动的扩展机制,允许在 Agent 生命周期的关键节点插入用户自定义脚本或 HTTP webhooks。

涉及源文件:

crates/atomcode-core/src/hook/engine.rs         — Hook 引擎核心
crates/atomcode-core/src/hook/script_runner.rs  — 脚本执行器
crates/atomcode-core/src/hook/webhook.rs        — HTTP webhook 发送
crates/atomcode-core/src/hook/async_batcher.rs  — 异步批量 webhook

2. Hook 生命周期与事件点

2.1 6 个注入点

Hook 系统在 Agent 执行循环中定义了 6 个事件注入点

Agent Turn Lifecycle:
                        Hook Point
Start Turn ──────────▶ SessionStart


System Prompt Setup ──▶ PreHookResult
    │                      ↓
    │              ┌─────────────────┐
    │              │ Block? → 阻止执行 │
    │              │ Modify? → 修改    │
    │              │ Pass   → 继续    │
    │              └─────────────────┘


LLM Call ──────────▶ PreToolUse
    │                    ↓
    │              ┌─────────────────┐
    │              │ 验证工具调用     │
    │              │ 可以修改或阻止   │
    │              └─────────────────┘


Tool Execution ───▶ PostToolUse
    │                    ↓
    │              ┌─────────────────┐
    │              │ 工具结果后处理   │
    │              └─────────────────┘


Turn Complete ───▶ SessionEnd / TurnComplete

                  ┌─────────────────┐
                  │ 写入 hooks.json  │
                  └─────────────────┘

2.2 HookEvent 枚举

从二进制提取的钩子事件枚举:

rust
enum HookEvent {
    PreHookResult,        // 执行前钩子结果
    SessionStart,         // 会话开始
    SessionEnd,           // 会话结束
    PreToolUse,           // 工具调用前
    PostToolUse,          // 工具调用后
    TurnComplete,         // 回合完成
}

关键字段(从二进制字符串还原):

bash
strings atomcode.bin.bak | grep -E "HookEvent|PreHookResult|PostToolUse|SessionStart|SessionEnd|TurnComplete"

3. PreHookResult — 钩子执行结果

3.1 三个结果变体

rust
enum PreHookResult {
    Pass,                  // 继续执行
    Block { reason: String },   // 阻止执行 (含原因)
    Modify { context: String }, // 修改后继续 (含修改后上下文)
}

从二进制中提取的枚举变体:

bash
strings atomcode.bin.bak | grep "struct variant PreHookResult"

输出:

struct variant PreHookResult::Block
struct variant PreHookResult::Modified
struct variant PreHookResult::Block with 1 element
struct variant PreHookResult::Modify with 1 element

3.2 HookContext — 钩子上下文

rust
struct HookContext {
    model_name: String,
    provider_name: String,
    tool_name: String,         // 当前工具名
    tool_args: String,         // 工具参数字符串
    turn_number: u64,          // 回合序号
    tokens_used: u64,          // 已消耗 token
    truncated: bool,           // 上下文是否截断
    edited_files: Vec<String>, // 已编辑文件列表
    timestamp: u64,            // 时间戳
}

4. 脚本钩子执行器 (ScriptRunner)

4.1 ScriptHookConfig (7 字段)

rust
struct ScriptHookConfig {
    // 7 个元素
    script_type: String,         // "bash" | "python" | "node" | ...
    hook_type: String,           // "PreToolUse" | "PostToolUse" | ...
    additional_context: String,  // 额外上下文模板
    timeout: u64,                // 执行超时(秒)
    // 3 个额外元素
}

4.2 执行流程

ScriptRunner

    ├── 1. 设置环境变量:
    │     ATOMCODE_HOOK_EVENT   = "PreToolUse"
    │     ATOMCODE_HOOK_CONTEXT = <JSON 序列化上下文>
    │     ATOMCODE_TOOL_NAME    = "bash"

    ├── 2. 执行脚本:
    │     /bin/bash -c "<script_content>"

    ├── 3. 解析 stdout (JSON):
    │     {"action": "block", "reason": "工具不被允许"}
    │     {"action": "modify", "context": "修改后上下文"}
    │     {"action": "allow"}

    └── 4. 超时处理:
          Script execution timed out → 默认 allow

4.3 环境变量注入

bash
# Script Runner 自动设置的环境变量
ATOMCODE_HOOK_EVENT="${hook_event_name}"    # 事件名
ATOMCODE_HOOK_CONTEXT="${HookContext}"       # JSON 上下文
ATOMCODE_TOOL_NAME="${tool_name}"            # 当前工具名

5. Webhook 系统

5.1 同步 Webhook

rust
struct WebhookConfig {
    // 9 个元素
    url: String,                // Webhook URL
    method: String,             // "POST" | "PUT"
    headers: Vec<(String, String)>,  // 自定义头
    timeout_secs: u64,          // 超时秒数
    retries: u64,               // 重试次数
    // 4 个额外元素
}

struct WebhookResponse {
    // 3 个元素
    status_code: u64,           // HTTP 状态码
    body: String,               // 响应体
    duration_ms: u64,           // 耗时
}

5.2 异步批量 Webhook

rust
struct AsyncWebhookConfig {
    // 10 个元素 — 最大配置结构体之一
    url: String,                // Webhook URL
    batch_size: u64,            // 批量发送大小
    flush_interval_ms: u64,     // 刷新间隔 (毫秒)
    timeout_secs: u64,          // 单次超时
    retries: u64,               // 单条重试次数
    headers: Vec<(String, String)>,  // 自定义头
    // 4 个额外元素
}

5.3 HTTP Headers

从二进制提取的 Webhook 专用头:

X-AtomCode-Version       ← 版本号
X-AtomCode-Webhook       ← 事件类型标记
X-AtomCode-Batch-Size    ← 批量大小
X-AtomCode-Hook          ← 钩子标识

5.4 事件队列 JSON

json
{
  "BatchRequest": {
    "events": [
      {
        "event_type": "PreToolUse",
        "timestamp_ms": 1781279460123,
        "hook_context": { ... }
      }
    ],
    "system_prompt": "...",
    "turn_start": "..."
  }
}

6. HookConfig 存储结构

6.1 文件格式

~/.atomcode/hooks.json
~/.atomcode/hooks.toml

6.2 HooksConfig 顶层结构

从二进制还原的顶层结构:

rust
struct HooksConfig {
    pre_tool_use: Vec<HookEntry>,     // 工具调用前钩子列表
    post_tool_use: Vec<HookEntry>,    // 工具调用后钩子列表
    session_start: Vec<HookEntry>,    // 会话开始钩子
    session_end: Vec<HookEntry>,      // 会话结束钩子
    async_webhooks: Vec<AsyncWebhookConfig>,  // 异步 webhook 配置
    // 多个配置段
}

6.3 HookEntry (5 字段)

rust
struct HookEntry {
    // 5 个元素
    matcher: String,            // 匹配模式(如 "bash" 只匹配 bash 工具)
    hook_type: String,          // "script" | "webhook" | "async_webhook"
    script_type: String?,       // 脚本类型(脚本钩子时)
    additional_context: String?,// 额外上下文
    // 1 个额外元素
}

6.4 CCHookSpec / CCHookGroup

来自 claude_code 兼容层的钩子结构:

rust
struct CCHookSpec {
    // 3 个元素
    script_type: String,     // 脚本类型
    additional_context: String,
    // 1 个元素
}

struct CCHookGroup {
    // 2 个元素
    matcher: String,         // 匹配模式
    hooks: Vec<CCHookSpec>,  // 钩子列表
}

7. 配置文件中钩子示例

hooks.toml 结构推断的配置格式:

toml
# 工具调用前钩子
[[pre_tool_use]]
matcher = "bash"                          # 只对 bash 工具生效
hook_type = "script"
script_type = "bash"
additional_context = """
工具名称: {{tool_name}}
参数: {{tool_args}}
"""

# 全局 webhook
[[async_webhooks]]
url = "https://hooks.example.com/atomcode"
batch_size = 10
flush_interval_ms = 5000
timeout_secs = 30
retries = 3

8. 钩子优先级与执行顺序

对于每个工具调用:
  1. pre_tool_use hooks → 按配置顺序执行

     ├── 任何 hook 返回 Block → 阻止执行,记录原因
     ├── 任何 hook 返回 Modify → 修改上下文
     └── 全部 Pass → 继续

  2. 执行工具

  3. post_tool_use hooks → 按配置顺序执行
     (不能 Block,只能记录)
  
  4. async_webhooks → 异步批量发送(不阻塞主流程)

9. 逆向命令索引

bash
# 提取所有钩子相关字符串
strings atomcode.bin.bak | grep -iE "pre_hook|hook_event|script_runner|webhook" | sort -u

# 提取钩子配置
strings atomcode.bin.bak | grep -E "hooks\.toml|hooks\.json|HookConfig|HookEntry" | sort -u

# 提取事件类型
strings atomcode.bin.bak | grep -E "SessionStart|SessionEnd|PreToolUse|PostToolUse|TurnComplete" | sort -u

# 提取异步 webhook 字段
strings atomcode.bin.bak | grep -iE "batch_size|flush_interval|AsyncWebhookConfig" | sort -u

# 提取 PreHookResult 变体
strings atomcode.bin.bak | grep -B2 -A2 "PreHookResult"

10. 新增覆盖统计

组件源文件结构体覆盖状态
Hook Enginehook/engine.rsHookEntry (5)、HookContext✅ 完整
Script Runnerhook/script_runner.rsScriptHookConfig (7)✅ 完整
Webhookhook/webhook.rsWebhookConfig (9)、WebhookResponse (3)✅ 完整
Async Batcherhook/async_batcher.rsAsyncWebhookConfig (10)✅ 完整
CC 兼容层CCHookSpec (3)、CCHookGroup (2)✅ 完整
新增覆盖4 文件7 结构体此前 ~30% → 100%

📅 最后更新: 2026-06-25🔍 来源: strings atomcode.bin.bak 二进制挖掘 + 错误消息推断

基于 VitePress 构建 · AtomCode v4.25.3 逆向工程分析文档