summary-hook.js
定义与身份
summary-hook.js 是 claude-mem 五阶段 Hook 生命周期中 Stop 阶段对应的脚本,由 hooks 配置在 Stop 生命周期事件中调用。它不是会话结束后的清理器,而是会话进行中的摘要生成器,用于在 Claude 停止时生成当前会话的阶段性摘要。
在配置中,它通过如下命令路径执行:
node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js
原始源码与构建产物的映射为:
src/hooks/summary-hook.ts → plugin/scripts/summary-hook.js
在 Hook 生命周期中的位置
summary-hook.js 对应 Stop 事件,属于 Hooks architecture 摘要 中第 4 个执行环节,位于 PostToolUse 之后、SessionEnd 之前。其触发条件是 Claude 停止,而不是用户真正关闭会话。
这意味着它生成的是“检查点式”摘要,而不是“终局总结”。原文明确强调:
- 由 Stop lifecycle event 触发
- 从 v4.2.0+ 开始,一个 session 可以有多份 summary
- 这些 summary 是 checkpoints,不是 endings
- 使用 Claude Agent SDK 做 AI 压缩
hooks 配置
Stop 阶段的配置形式如下:
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js"
}]
}]
}
}
这说明 summary-hook.js 是由 hooks 配置直接挂到 Stop 阶段的命令型脚本。
角色职责
summary-hook.js 的职责不是保存单次工具调用,也不是结束会话清理,而是处理“结构化摘要”的生成与持久化。原文给出的处理流程有 4 步:
- 从数据库收集当前会话的 observations
- 将这些内容发送给 Claude Agent SDK 做摘要生成
- 处理返回结果并提取结构化 summary
- 将结果写入
session_summaries表
因此,它在系统中的角色更接近会话级压缩器:把前面由 save-hook.js 持续沉淀的 observation,压缩成可检索、可延续使用的会话摘要。
摘要结构
summary-hook.js 处理的不是任意自由文本,而是结构化摘要。原文示例中的 summary 结构如下:
<summary>
<request>User's original request</request>
<investigated>What was examined</investigated>
<learned>Key discoveries</learned>
<completed>Work finished</completed>
<next_steps>Remaining tasks</next_steps>
<files_read>
<file>path/to/file1.ts</file>
<file>path/to/file2.ts</file>
</files_read>
<files_modified>
<file>path/to/file3.ts</file>
</files_modified>
<notes>Additional context</notes>
</summary>
从这个结构可以看出,摘要至少覆盖以下信息维度:
request:用户原始请求investigated:本轮检查过什么learned:得到的关键发现completed:已经完成的工作next_steps:剩余待办files_read:读过的文件列表files_modified:修改过的文件列表notes:补充上下文
这也是它区别于普通日志或 observation 队列的关键点:输出是面向后续恢复和理解的结构化会话状态。
关键信息
- 调用阶段:Stop
- 调用方式:hooks 中的 command
- 命令路径:
${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js - 源码映射:
src/hooks/summary-hook.ts→plugin/scripts/summary-hook.js - 核心依赖:Claude Agent SDK
- 持久化位置:
session_summaries表 - 摘要语义:阶段性 checkpoint,而非会话结束总结
- 版本边界:v4.2.0+ 支持同一 session 产生多份 summaries
细节与边界
1. 它在会话中途运行,不等于结束流程
Stop 触发的是 Claude 停止,而不是 SessionEnd。因此 summary-hook.js 生成摘要时,会话可能仍会继续,后续仍可能继续产生 observation、继续生成新的 summary。
2. 一个会话可以有多份摘要
原文明确给出 “Multiple summaries per session (v4.2.0+)”。这意味着系统设计上不假定每个 session 只有一条最终摘要,而是允许随着会话推进反复生成多个检查点。
3. 它依赖 observation,而不是直接监听工具输出
在职责描述里,它首先是“从数据库收集 session observations”。也就是说,summary-hook.js 主要消费前序链路已落库的数据,而不是像 save-hook.js 那样直接处理单次工具事件。
4. 输出去向是数据库,不是上下文注入或日志显示
在 Hook Timing 表中,Summary 一行对应:
- Timing:Worker triggered
- Blocking:No
- Timeout:120s
- Output Handling:Database
这说明它的结果主要写数据库,而不是像 SessionStart 那样注入 hookSpecificOutput.additionalContext,也不是仅写 stderr 日志。
5. 它是非阻塞的,超时为 120 秒
虽然 Stop 阶段会触发摘要生成,但该流程在时序表中被标记为非阻塞(No),并且超时时间是 120 秒。这表明摘要生成被设计成尽量不阻塞主交互流程。
6. 摘要生成由 worker 触发链路承接
时序表把 Summary 的 Timing 标成 “Worker triggered”,说明即便 Stop 是生命周期事件,实际摘要执行与 Worker Service Architecture 存在直接关系,不是单纯前台同步脚本输出。
与相邻脚本的分工
与 save-hook.js 的区别
save-hook.js 属于 PostToolUse,负责在每次工具使用后,把 observation 排队送入后续处理流程;summary-hook.js 则消费这些 observation,生成会话级结构化摘要并写入 session_summaries。前者偏事件采集,后者偏会话压缩。
与 cleanup-hook.js 的区别
cleanup-hook.js 属于 SessionEnd,职责是把 session 标记为 completed 并执行优雅清理;summary-hook.js 不负责完成态标记,也不负责结束 worker,而是负责在会话过程中生成摘要。
与 version-check.js 的区别
version-check.js 属于 Setup 阶段,负责安装版本检查与提示;summary-hook.js 不参与安装检查,也不处理启动前校验。
在整体架构中的意义
summary-hook.js 是 Progressive Enhancement 思路中的关键组成部分:系统不是等到会话彻底结束才总结,而是在 Stop 节点持续形成结构化 checkpoint。这样做有几个直接意义:
- 降低长会话上下文膨胀问题
- 为后续恢复会话提供更清晰的阶段摘要
- 让 worker 可以基于已积累 observation 持续压缩信息
- 避免把“总结”完全推迟到结束时才进行