Hindsight × Cline:用生命周期 Hooks 为 Cline 装上确定性长期记忆(免 MCP 方案)
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
Hindsight 的 Cline 集成(hindsight-cline)通过 Cline 的生命周期 Hooks 实现"任务前自动召回、任务结束自动沉淀"的长期记忆闭环,全程不依赖 MCP、不需要模型主动调用任何工具。本文基于仓库中 hindsight-integrations/cline/README.md 及其配套源码,完整讲解这套集成的工作机制、安装流程、全部配置项与底层实现细节,读完你可以直接在 macOS/Linux 环境下为自己的 Cline 工作流接入跨会话记忆。
一、为什么选择 Hooks 而不是 MCP
传统方式为编码智能体接入记忆的做法通常是注册一个 MCP Server,让模型在对话中"决定"是否调用记忆工具。这种方式有一个根本弱点:记忆行为依赖模型的临场判断——模型忘了调用,记忆就丢了。
hindsight-cline换了条路线:Cline 提供了一套lifecycle hooks 机制,允许用户在关键时点执行外部脚本。本集成注册了四个 hook 脚本,把记忆读写变成确定性的旁路逻辑:
| Hook 事件 | 触发时机 | 行为 |
|---|---|---|
TaskStart | 任务开始时 | 以任务描述为 query 执行 recall,注入相关记忆 |
UserPromptSubmit | 每次用户发消息 | 以 prompt 为 query 执行 recall 注入记忆,同时把 prompt 追加到任务 transcript |
TaskComplete | 任务完成时 | retain 累积的完整 transcript + 最终摘要 |
TaskCancel | 任务被取消时 | retain 部分 transcript(标记为 cancelled) |
由于运行在 hooks 上,记忆注入与沉淀是自动发生的,与模型是否"愿意"调用工具无关。这是该集成 README 中反复强调的核心设计动机。
二、工作机制:从 stdin JSON 到<hindsight_memories>注入
2.1 Cline Hooks 的 I/O 契约
Cline 以子进程方式运行每个 hook:把一段 JSON 写入 hook 的stdin,再从stdout读回一段固定形状的 JSON。这个契约在 cline_io.py 中有精确实现:
- 入参(stdin)包含
hookName、taskId、prompt(UserPromptSubmit)、task(TaskStart/TaskComplete/TaskCancel)、workspaceRoots、model等字段,被解析为强类型的HookInputdataclass; - 出参(stdout)固定为三个字段:
{"cancel": false, "contextModification": "<hindsight_memories>…", "errorMessage": ""}其中contextModification就是 hook 向模型上下文注入文本的通道——召回到的记忆会被渲染成<hindsight_memories>块,通过该字段注入。
值得注意的两个防御性设计(见 hooks_impl.py):
- 绝不抛异常:所有 entrypoint 用
try/except包裹,任何记忆侧故障都降级为空输出(no-op),"记忆服务的抖动永远不会阻塞 Cline 本身"; - 最小长度门槛:prompt 或任务描述少于
RECALL_MIN_CHARS = 5个字符时直接跳过 recall(cline_io.py),避免为 "hi" 这类寒暄发起无意义的检索。
2.2 转录累积:Cline 不给 transcript,就自己攒
一个关键约束是:Cline 不会把会话 transcript 传给 hooks。因此集成自己维护了每任务一份的转录文件,逻辑在 state.py 与 content.py:
- 每个
UserPromptSubmit把用户 prompt 以{role: "user", content: ...}追加到~/.hindsight/cline/state/transcript_<taskId>.json; TaskStart把任务描述作为首轮写入(hooks_impl.py);TaskComplete/TaskCancel时,把完成摘要(hook 的task字段)作为assistant轮追加,再将整段 transcript 格式化为纯文本后提交 retain,成功后清空状态文件;- 状态文件采用tmp +
os.replace原子写,且任务轮次上限 500 条防止文件无限膨胀;文件名经过路径穿越净化(_safe_filename替换危险字符并做 realpath 前缀校验)。
retain提交时的元数据也做了精心设计:document_id使用taskId(便于按任务追溯)、context默认为"cline"(帮助 Hindsight 按来源聚类)、metadata携带task_id/project/status(completed 或 cancelled)、tags默认为["{task_id}"]且支持模板变量{task_id}、{project}、{status}、{timestamp}。
另一个容易被忽略的细节是反馈环防护:retain 前会用正则剥掉内容中的<hindsight_memories>/<relevant_memories>块(content.py 的strip_memory_tags)。因为这些块是 recall 阶段注入到上下文里的,若不剥离就会被当成"用户说的话"再次存储,形成记忆自我复制。
三、服务端与客户端:零第三方依赖的 REST 集成
集成支持两类 Hindsight 后端:
- Hindsight Cloud:注册获取 API key,使用
https://api.hindsight.vectorize.io; - 自托管:
pip install hindsight-all export HINDSIGHT_API_LLM_API_KEY=your-openai-key hindsight-api # starts on http://localhost:8888客户端实现在 client.py:刻意只用Python 标准库(urllib)发 HTTP 请求,保证 hook 脚本零第三方依赖。三个核心 API:
| 方法 | 端点 | 说明 |
|---|---|---|
recall() | POST /v1/default/banks/{bank_id}/memories/recall | 携带query、max_tokens、budget(low/mid/high)、types |
retain() | POST /v1/default/banks/{bank_id}/memories | 以items+async: true提交,服务端后台异步处理 |
set_bank_mission() | PATCH /v1/default/banks/{bank_id}/config | 写入reflect_mission与retain_mission |
两个工程细节值得记录:
- User-Agent 伪装:每个请求都带上
hindsight-cline/<version>的 UA,原因是自托管部署如果架在 Cloudflare 等按 UA 过滤机器人的反代后面,标准库默认的Python-urllib/X.Y会触发 Cloudflare 1010 错误(client.py 有明确注释); - API URL 解析策略(cline_io.py 的
resolve_api_url):优先用配置的外部 URL;若为空则探测http://localhost:{apiPort}(默认 9077)的/health。探不通就静默降级为 no-op——它永远不自动拉起 daemon,找不到服务就不做记忆操作,绝不让 Cline 卡住。
四、安装与卸载
4.1 平台前提
Cline hooks 仅在macOS 和 Linux上运行(不支持 Windows),hooks 需要 Python 3。
4.2 安装
pip install hindsight-cline然后在项目目录下:
hindsight-cline install --api-url https://api.hindsight.vectorize.io --api-token YOUR_KEY全局安装(对所有项目生效):
hindsight-cline install --global --api-url https://api.hindsight.vectorize.io --api-token YOUR_KEY卸载:hindsight-cline uninstall(全局安装则加--global)。
CLI 的完整参数在 cli.py 中定义:install/uninstall子命令均支持--project-dir(默认当前目录)与--global;--api-url与--api-token可省略而改用环境变量HINDSIGHT_API_URL/HINDSIGHT_API_TOKEN提供。
安装动作(install.py)具体做了三件事:
- 从 wheel 包内的
hindsight_cline/hooks/数据目录(经importlib.resources解析)拷贝四个 hook 脚本TaskStart、UserPromptSubmit、TaskComplete、TaskCancel到目标目录,并逐个chmod 0o755(Cline 只执行有可执行位 hook 文件); - 拷贝共享库
lib/与 settings.json 到同一目录(hook 脚本通过sys.path.insert加载本目录下的lib/); - 把连接信息写入
~/.hindsight/cline.json(该文件在重装/升级时保留不动,配置因此是稳定的)。
目标目录二选一:
- 项目安装 →
.clinerules/hooks/(建议提交进版本库与团队共享); - 全局安装 →
~/Documents/Cline/Rules/Hooks/。
每个 hook 脚本本体极薄,例如 TaskStart 只是把脚本所在目录加入sys.path后调用lib.hooks_impl.main_task_start()。
最后一步——在 Cline 中启用 hooks:Settings → Features → Hooks。
五、配置系统:四层合并、typed dataclass
5.1 常用配置项
默认值写在随包安装的settings.json中;个人覆盖写在~/.hindsight/cline.json(跨重装稳定)。README 列出的常用键:
| Setting | 默认值 | 说明 |
|---|---|---|
hindsightApiUrl | (空) | Hindsight 服务 URL。留空则探测apiPort上的本地服务 |
hindsightApiToken | null | Hindsight Cloud 的 API key |
bankId | cline | 该集成使用的记忆库 |
autoRecall | true | 任务/消息前注入记忆 |
autoRetain | true | 任务结束时沉淀 transcript |
recallBudget | mid | 召回深度:low/mid/high |
recallTypes | ["world","experience"] | 要召回的记忆类型 |
dynamicBankId | false | 按项目/会话拆库(见dynamicBankGranularity) |
debug | false | 向日志输出(stderr) |
而完整键集合可以从 settings.json 和配置数据类 HindsightClineConfig 交叉确认,还包括若干 README 未逐一列出但同样可调的项:
| Setting | 默认值 | 说明(来自源码) |
|---|---|---|
recallMaxTokens | 1024 | recall 结果的最大 token 预算 |
recallTimeout/retainTimeout | 10/15秒 | recall / retain 请求超时 |
recallContextTurns | 1 | recall query 携带的上下文轮数(≤1 时仅用最新消息) |
recallMaxQueryChars | 800 | 组合 query 的字符上限,超限时优先保最新消息 |
recallPromptPreamble | "Relevant memories from past conversations…" | 注入块中的引导语 |
retainContext | cline | retain 的来源标记,帮助服务端按来源聚类 |
retainTags | ["{task_id}"] | 支持{task_id}/{project}/{status}/{timestamp}模板变量 |
retainMetadata | {} | 自由键值元数据,字符串值同样支持模板变量 |
apiPort | 9077 | 未配置hindsightApiUrl时探测的本地端口 |
bankIdPrefix | "" | bank id 前缀,多集成共用一个 Hindsight 实例时隔离用 |
dynamicBankGranularity | ["agent","project"] | 动态 bank 的粒度维度(可选agent/project/session/user) |
agentName | cline | 动态 bank 中 agent 维度的取值 |
bankMission/retainMission | 面向编码场景的英文 mission 文本 | bank 首用时自动 PATCH 到服务端(见下文) |
5.2 加载顺序与类型转换
config.py 中load_config()的合并顺序(后者覆盖前者):
- 内置默认值(dataclass 字段默认);
- 插件
settings.json(经find_settings_path()向上逐级查找,兼容仓库布局与安装布局); - 用户配置
~/.hindsight/cline.json; - 环境变量覆盖。
落盘格式统一为camelCase,加载时经camel_to_snake()转换为 snake_case 字段。环境变量映射表ENV_OVERRIDES目前覆盖 15 个键,例如HINDSIGHT_BANK_ID、HINDSIGHT_AUTO_RECALL=false、HINDSIGHT_API_URL、HINDSIGHT_RECALL_BUDGET等;bool 类型接受true/1/yes,解析失败静默忽略。未知键(不在 dataclass 字段集内的)在文件合并阶段直接跳过,因此 schema 演进时旧配置不会报错。
5.3 动态 Bank:按 agent / 项目 / 会话 / 用户拆库
默认所有记忆汇入单一 bankcline。开启dynamicBankId: true后,bank.py 的derive_bank_id()按dynamicBankGranularity指定的维度用::拼接出 bank id,四个合法维度及其取值来源:
agent→agentName配置(默认cline);project→ 第一个workspaceRoots的 basename;session→ hook 输入的taskId;user→ 环境变量HINDSIGHT_USER_ID(缺省anonymous)。
例如粒度["agent","project"]下,工作区/home/me/myapp的记忆落在 bankcline::myapp。非法维度名会在 stderr 打印告警但不中断。
配套的bank mission 机制:ensure_bank_mission()在 bank 首次使用时把bankMission(reflect 侧人格设定)与retainMission(retain 侧提取指令)PATCH 到服务端,并用状态文件bank_missions.json记录"已设置"避免重复请求(记录超过 10000 条时裁剪一半防止膨胀)。默认 mission 把 bank 定位为"Cline AI 编码助手",聚焦技术决策、代码变更、调试会话、架构选择等,并在 retain 侧明确"忽略寒暄与临时性操作细节"——这直接决定了记忆提取的信噪比。
六、验证安装
- 启动 Hindsight(
hindsight-api或 Hindsight Cloud),运行hindsight-cline install并带上 URL/key; - 在 Cline 中开启 hooks(Settings → Features → Hooks);
- 发起一个任务——召回的记忆会以
<hindsight_memories>块出现在上下文中; - 完成任务后检查
clinebank(通过 API 或 dashboard),应能看到新记忆。
不启动 Cline 也能冒烟测试单个 hook——stdin 喂入 payload,stdout 即返回契约 JSON:
echo '{"hookName":"UserPromptSubmit","prompt":"how do we authenticate?","taskId":"t1","workspaceRoots":["/tmp/x"]}' \ | .clinerules/hooks/UserPromptSubmit # → {"cancel": false, "contextModification": "<hindsight_memories>…", "errorMessage": ""}七、开发与测试
仓库内该集成的开发流程(README 原文):
uv sync uv run pytest tests/ -v测试集位于 hindsight-integrations/cline/tests/,覆盖四个层面:
test_hooks.py:recall 注入/转录累积/禁用开关/短 prompt 跳过、retain 提交内容与元数据、tags 模板渲染、stdin→stdout 契约,以及"服务端整体宕机时优雅降级为空输出且不抛异常"(test_main_degrades_gracefully_when_server_down);test_bank.py:动态 bank 派生与粒度字段校验;test_content.py:多轮 query 组合、超长按"先丢最旧上下文行"策略截断、<hindsight_memories>标签剥离等;test_install.py:安装/卸载的文件落位与可执行位。
这套测试也侧面印证了前述源码结论:recall 与 retain 完全解耦、故障隔离是显式验收项。
八、总结
hindsight-cline用四个生命周期 hook 脚本 + 一个零依赖的 REST 客户端,把 Hindsight 的 recall/retain 能力确定性地织入 Cline 的任务生命周期:任务开始时按任务描述召回、每条消息按 prompt 召回并累积转录、任务结束(无论完成还是取消)异步 retain 整段 transcript 并打上 task_id/project/status 元数据。配置采用"内置默认 → settings.json → 用户 json → 环境变量"四层合并,支持静态单 bank 与按 agent/project/session/user 维度的动态 bank,且所有故障路径都设计为静默降级——记忆层出问题,Cline 永远照常工作。对于希望在编码智能体中积累跨会话项目记忆、又不想引入 MCP 运行时开销的开发者,这是当前 Hindsight 仓库中最轻量的接入路径之一,完整源码可参考 hindsight-integrations/cline/ 目录。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考