news 2026/9/14 12:20:38

Hindsight × Cline:用生命周期 Hooks 为 Cline 装上确定性长期记忆(免 MCP 方案)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Hindsight × Cline:用生命周期 Hooks 为 Cline 装上确定性长期记忆(免 MCP 方案)

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)包含hookNametaskIdprompt(UserPromptSubmit)、task(TaskStart/TaskComplete/TaskCancel)、workspaceRootsmodel等字段,被解析为强类型的HookInputdataclass;
  • 出参(stdout)固定为三个字段:
{"cancel": false, "contextModification": "<hindsight_memories>…", "errorMessage": ""}

其中contextModification就是 hook 向模型上下文注入文本的通道——召回到的记忆会被渲染成<hindsight_memories>块,通过该字段注入。

值得注意的两个防御性设计(见 hooks_impl.py):

  1. 绝不抛异常:所有 entrypoint 用try/except包裹,任何记忆侧故障都降级为空输出(no-op),"记忆服务的抖动永远不会阻塞 Cline 本身";
  2. 最小长度门槛: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携带querymax_tokensbudget(low/mid/high)、types
retain()POST /v1/default/banks/{bank_id}/memoriesitems+async: true提交,服务端后台异步处理
set_bank_mission()PATCH /v1/default/banks/{bank_id}/config写入reflect_missionretain_mission

两个工程细节值得记录:

  1. User-Agent 伪装:每个请求都带上hindsight-cline/<version>的 UA,原因是自托管部署如果架在 Cloudflare 等按 UA 过滤机器人的反代后面,标准库默认的Python-urllib/X.Y会触发 Cloudflare 1010 错误(client.py 有明确注释);
  2. 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)具体做了三件事:

  1. 从 wheel 包内的hindsight_cline/hooks/数据目录(经importlib.resources解析)拷贝四个 hook 脚本TaskStartUserPromptSubmitTaskCompleteTaskCancel到目标目录,并逐个chmod 0o755(Cline 只执行有可执行位 hook 文件);
  2. 拷贝共享库lib/与 settings.json 到同一目录(hook 脚本通过sys.path.insert加载本目录下的lib/);
  3. 把连接信息写入~/.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上的本地服务
hindsightApiTokennullHindsight Cloud 的 API key
bankIdcline该集成使用的记忆库
autoRecalltrue任务/消息前注入记忆
autoRetaintrue任务结束时沉淀 transcript
recallBudgetmid召回深度:low/mid/high
recallTypes["world","experience"]要召回的记忆类型
dynamicBankIdfalse按项目/会话拆库(见dynamicBankGranularity
debugfalse向日志输出(stderr)

而完整键集合可以从 settings.json 和配置数据类 HindsightClineConfig 交叉确认,还包括若干 README 未逐一列出但同样可调的项:

Setting默认值说明(来自源码)
recallMaxTokens1024recall 结果的最大 token 预算
recallTimeout/retainTimeout10/15recall / retain 请求超时
recallContextTurns1recall query 携带的上下文轮数(≤1 时仅用最新消息)
recallMaxQueryChars800组合 query 的字符上限,超限时优先保最新消息
recallPromptPreamble"Relevant memories from past conversations…"注入块中的引导语
retainContextclineretain 的来源标记,帮助服务端按来源聚类
retainTags["{task_id}"]支持{task_id}/{project}/{status}/{timestamp}模板变量
retainMetadata{}自由键值元数据,字符串值同样支持模板变量
apiPort9077未配置hindsightApiUrl时探测的本地端口
bankIdPrefix""bank id 前缀,多集成共用一个 Hindsight 实例时隔离用
dynamicBankGranularity["agent","project"]动态 bank 的粒度维度(可选agent/project/session/user
agentNamecline动态 bank 中 agent 维度的取值
bankMission/retainMission面向编码场景的英文 mission 文本bank 首用时自动 PATCH 到服务端(见下文)

5.2 加载顺序与类型转换

config.py 中load_config()的合并顺序(后者覆盖前者):

  1. 内置默认值(dataclass 字段默认);
  2. 插件settings.json(经find_settings_path()向上逐级查找,兼容仓库布局与安装布局);
  3. 用户配置~/.hindsight/cline.json
  4. 环境变量覆盖。

落盘格式统一为camelCase,加载时经camel_to_snake()转换为 snake_case 字段。环境变量映射表ENV_OVERRIDES目前覆盖 15 个键,例如HINDSIGHT_BANK_IDHINDSIGHT_AUTO_RECALL=falseHINDSIGHT_API_URLHINDSIGHT_RECALL_BUDGET等;bool 类型接受true/1/yes,解析失败静默忽略。未知键(不在 dataclass 字段集内的)在文件合并阶段直接跳过,因此 schema 演进时旧配置不会报错。

5.3 动态 Bank:按 agent / 项目 / 会话 / 用户拆库

默认所有记忆汇入单一 bankcline。开启dynamicBankId: true后,bank.py 的derive_bank_id()dynamicBankGranularity指定的维度用::拼接出 bank id,四个合法维度及其取值来源:

  • agentagentName配置(默认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 侧明确"忽略寒暄与临时性操作细节"——这直接决定了记忆提取的信噪比。

六、验证安装

  1. 启动 Hindsight(hindsight-api或 Hindsight Cloud),运行hindsight-cline install并带上 URL/key;
  2. 在 Cline 中开启 hooks(Settings → Features → Hooks);
  3. 发起一个任务——召回的记忆会以<hindsight_memories>块出现在上下文中;
  4. 完成任务后检查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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 12:20:20

AI编程工具选型指南:上下文感知能力决定开发效率

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 12:19:39

axum 嵌套路由会剥离前缀,如何用 OriginalUri 取回原始 URI

axum 嵌套路由会剥离前缀&#xff0c;如何用 OriginalUri 取回原始 URI 【免费下载链接】axum HTTP routing and request-handling library for Rust that focuses on ergonomics and modularity 项目地址: https://gitcode.com/GitHub_Trending/ax/axum 用 axum 的 nes…

作者头像 李华
网站建设 2026/9/14 12:17:38

Vue3+Element-Plus图书管理系统源码拆解:从登录到部署全流程

简介&#xff1a;基于Vue3与Element-Plus构建的图书管理系统设计源码&#xff0c;面向需要快速搭建图书管理功能的前端学习者和初级工程师&#xff0c;可支撑图书信息维护、借阅归还、读者管理等常见业务场景。压缩包共33个文件&#xff0c;主要由14个Vue组件、10个JavaScript脚…

作者头像 李华
网站建设 2026/9/14 12:16:30

网页游戏源码合集高效利用:分类、本地运行与改造指南

简介&#xff1a;这份网页游戏源码合集以HTML、JS、CSS为主&#xff0c;集中了植物大战僵尸、黄金矿工、扫雷、开心消消乐等数十款经典网页游戏的完整前端实现&#xff0c;适合前端初学者、游戏开发爱好者及需要网页互动案例的课件制作者参考。压缩包共2003个文件&#xff0c;其…

作者头像 李华