读取会话历史 Skill
用途
在本地文件系统中定位、查询和提取会话/对话历史的结构化工作流。支持多种 IDE/工具的历史存储格式。
输出原则
仅输出搜索结果表格,不附加任何过程说明。 AI 在执行搜索过程中所做的任何操作(运行脚本、读取输出、清理临时文件、环境探测、路径发现等)均不得向用户提及。只呈现最终的结果表格,其他一切都不必说。
工作流
前置步骤:确定 Skill 目录
本 skill 内的脚本路径必须以 skill 根目录为基准动态拼接,禁止硬编码从 workspace root 出发的相对路径。执行时先读取本 SKILL.md 所在目录作为 $SKILL_DIR,后续所有 scripts/ 下的文件路径均使用 $SKILL_DIR/scripts/xxx.js。
> 获取方式:脚本内部已通过 path.resolve(__dirname, '..') 动态获取。
临时文件约定
运行脚本生成的重定向输出文件(如 scan_output.txt、discover_output.txt)统一存放在 $SKILL_DIR\temp\ 目录中。AI 在运行脚本前需确保该目录存在并在完成后清理其下所有临时文件。
第 0 步:确定运行环境(自动探测 + 用户选择兜底)
默认使用 --env=auto,脚本会自动探测磁盘上有真实会话数据的环境。
> <user_info> 中不包含 IDE 类型字段,AI 无法可靠判定当前运行环境。因此交由脚本读取磁盘证据——哪个环境目录下有真实的会话数据文件,就是当前使用的环境。
自动探测流程:
--env=auto(默认)
→ discover_paths.js 遍历 codebuddy_extension / codebuddy_ide / workbuddy / learnbuddy 四个环境
→ 每个环境检查磁盘路径是否存在 + 是否含真实会话数据
→ 结果分三种情况:
| 探测结果 | 行为 | AI 后续操作 |
|---|---|---|
| 恰好 1 个候选 | 自动写入 index.conf,继续扫描 |
无需操作,正常进行 |
| 多于 1 个候选 | 输出 mode: 'choose' 候选清单 JSON(按环境合并,同一环境多个数据源视为一个选项),不写 index.conf,脚本退出 |
AI 用 ask_followup_question 让用户选择;选定后运行 discover_paths.js --env=<选定值> 写入 conf |
| 0 个候选 | 输出 mode: 'none' 错误,脚本退出 |
提示用户手动指定 --env |
环境划分说明: 四个环境互不重叠,每个环境独立负责自己的数据源:
| 环境(--env) | 显示名称 | 数据源 |
|---|---|---|
codebuddy_ide |
CodeBuddy IDE | codebuddy-sessions.vscdb + CodeBuddyIDE/{userId}/history/ |
codebuddy_extension |
CodeBuddyExtension | JetBrains/{userId}/history/ |
workbuddy |
WorkBuddy | ~/.workbuddy/workbuddy.db + ~/.workbuddy/projects/ |
learnbuddy |
LearnBuddy | ~/.learnbuddy/workbuddy.db + ~/.learnbuddy/projects/(复用 WorkBuddy 命名) |
> codebuddy_ide 的 vscdb 和 IDE JSON 历史合并展示为"CodeBuddy IDE"(同一产品的不同数据格式),其余环境各为独立选项。
多候选交互流程(AI 执行):
scan_history.js返回mode: 'choose'的 JSON,其中candidates数组每项含env/label/sources/convCount/msgCount/lastActivity- AI 用
ask_followup_question展示所有候选(单选),每个选项label为环境名称(如 "CodeBuddy IDE"),description包含该环境下的所有数据源组合及总会话数量。提问时必须明确告知用户请谨慎选择,后续同环境的检索将自动复用该配置,不会再次弹窗选择。除非在下一轮对话中告知"切换环境",AI 将重新运行环境选择流程。 - 用户选定后,AI 运行
discover_paths.js --env=<选定值>写入index.conf - 再运行
scan_history.js --env=<选定值>完成扫描 - 必须是给出单选项,让用户可以直接点击选择,而不是手动输入
第 1 步:运行路径发现脚本
> 临时文件统一存放在 $SKILL_DIR\temp\ 目录,AI 在运行脚本前需确保该目录存在。
一般情况下 scan_history.js 会自动调用 discover_paths.js,无需手动执行。如需单独运行:
# auto 自动探测(默认)
cmd /c "if not exist \"$SKILL_DIR\\temp\" mkdir \"$SKILL_DIR\\temp\" && $NODE $SKILL_DIR\scripts\discover_paths.js > $SKILL_DIR\temp\discover_output.txt 2>&1"
# 指定环境
cmd /c "if not exist \"$SKILL_DIR\\temp\" mkdir \"$SKILL_DIR\\temp\" && $NODE $SKILL_DIR\scripts\discover_paths.js --env=codebuddy_ide > $SKILL_DIR\temp\discover_output.txt 2>&1"
然后 read_file 读取 $SKILL_DIR\temp\discover_output.txt,或直接读缓存 index.conf。
index.conf 缓存:
- 位于 skill 根目录:$SKILL_DIR\index.conf
- 首次运行写入,后续同环境调用直接复用(除非 --force 或路径失效)
- 不同环境有独立的缓存策略:环境不匹配时自动重新扫描
- auto 模式:复用任何有效缓存,无需环境匹配
各环境扫描的路径:
| --env= | 扫描路径 |
|---|---|
codebuddy_ide |
%APPDATA%\CodeBuddy CN\codebuddy-sessions.vscdb + %LOCALAPPDATA%\CodeBuddyExtension\Data\{userId}\CodeBuddyIDE\{userId}\history\ |
codebuddy_extension |
%LOCALAPPDATA%\CodeBuddyExtension\Data\{userId}\JetBrains\{userId}\history\ |
workbuddy |
%USERPROFILE%\.workbuddy\workbuddy.db(SQLite sessions 表) + %USERPROFILE%\.workbuddy\projects\<key>\<id>.jsonl(消息) |
learnbuddy |
%USERPROFILE%\.learnbuddy\workbuddy.db(SQLite,复用 WorkBuddy 命名) + %USERPROFILE%\.learnbuddy\projects\<key>\<id>.jsonl(消息) |
> WorkBuddy/LearnBuddy 的消息存储在 .jsonl 文件中(每行一个 JSON),而非 JetBrains 的 index.json + messages/*.json 结构。projects/ 下的子目录名由 cwd 转换而来:盘符 E:\ → e-,路径分隔符 \ → -。
第 2 步:确定 Node.js 可执行文件路径
按以下优先级定位 Node.js:
- 检查
<user_rules>/<always_applied_user_rules>中是否有Node.js 安装目录配置(如D:\nodejs),拼接为<目录>\node.exe - 执行
where node查找 PATH 中的 node - 直接尝试
node(依赖 PATH)
始终先用 --version 验证(如 D:\nodejs\node.exe --version)确认路径可用,记为 $NODE。
第 3 步:使用预置扫描脚本
scan_history.js 默认使用 --env=auto 自动探测环境:
# 列出所有对话(auto 自动探测)
cmd /c "if not exist \"%SKILL_DIR%\\temp\" mkdir \"%SKILL_DIR%\\temp\" && $NODE $SKILL_DIR\scripts\scan_history.js > $SKILL_DIR\temp\scan_output.txt 2>&1"
# 按关键词搜索(auto 自动探测)
cmd /c "if not exist \"%SKILL_DIR%\\temp\" mkdir \"%SKILL_DIR%\\temp\" && $NODE $SKILL_DIR\scripts\scan_history.js 关键词 > $SKILL_DIR\temp\scan_output.txt 2>&1"
# 指定环境
cmd /c "if not exist \"%SKILL_DIR%\\temp\" mkdir \"%SKILL_DIR%\\temp\" && $NODE $SKILL_DIR\scripts\scan_history.js --env=codebuddy_extension > $SKILL_DIR\temp\scan_output.txt 2>&1"
> 注意: PowerShell 的 stdout 捕获存在问题,始终使用 cmd /c 重定向到文件后用 read_file 读取 $SKILL_DIR\temp\scan_output.txt。
第 4 步:提取消息数据(手动模式)
仅当预置脚本不满足需求时使用。
CodeBuddyExtension/CodeBuddy IDE JSON 消息文件结构:
{
"role": "user | assistant | tool",
"message": "内容文本或数组", // ← 内容字段!不是 "content"
"id": "message-uuid",
"extra": { /* 可选:工具执行错误、函数调用、元数据 */ },
"createdAt": "ISO-8601 时间戳"
}
关键注意: 内容存储在 message 键下,不是 content。message 可以是纯文本字符串或 [{type, text}] 数组。
WorkBuddy/LearnBuddy JSONL 消息行结构(每行一个 JSON):
{
"type": "message", // message | reasoning | function_call | ai-title | file-history-snapshot
"role": "user | assistant", // 仅 type=message 时有
"content": [{"type": "input_text", "text": "用户/助手消息文本"}],
"sessionId": "uuid",
"cwd": "工作目录",
"timestamp": 1784851790543 // Unix epoch ms
}
> 注意:user 消息的 content[].text 包含大量系统注入(<system-reminder>, <user_info>, <connector-status> 等),搜索/提取时应过滤 <user_query> 之外的内容。
对话元数据 在分组级别的 index.json 中:
{
"conversations": [
{
"id": "conversation-uuid",
"name": "对话标题",
"type": "craft",
"createdAt": "ISO-8601",
"lastMessageAt": "ISO-8601"
}
],
"current": "当前对话-id"
}
第 5 步:呈现结果(⭐ 强制表格输出)
这是输出给用户的核心环节。仅输出结果表格和必需的"结果后提示",不输出任何其他过程性内容。
将搜索结果呈现给用户时,仅输出以下表格及"结果后提示",前置不附加任何文字说明,不可使用其他格式:
表格列(4 列,不可省略):
| 序号 | 会话标题 | 会话时间 | 匹配消息摘要 |
表格规范:
- 序号:从 1 开始递增
- 会话标题:conv.name(对话名称),不可省略
- 会话时间:conv.createdAt,格式 YYYY-MM-DD HH:MM:SS,不可省略
- 匹配消息摘要:提炼与搜索关键词相关的核心内容,简明扼要
禁止行为:
- ❌ 输出任何过程说明("正在扫描""已找到X个会话""正在读取临时文件""已清理"等)
- ❌ 标题+正文叙事格式
- ❌ 无序/有序列表代替表格
- ❌ 仅输出消息摘要不带会话标题
- ❌ 省略时间戳
- ❌ 合并多会话为一行
- ❌ 告知用户即将执行什么、正在执行什么、已完成什么
> 例外:结果表格下方的"结果后提示"段落不属于禁止行为范围,每次输出表格后必须附加。
正确示例:
| 序号 | 会话标题 | 会话时间 | 匹配消息摘要 |
|---|---|---|---|
| 1 | 修复首页路由配置 | 2026-07-24 00:07:23 | Route.php:3-11 路由设置不正确,参数格式需用 (<key>) |
| 2 | 在后台增加 IP 封禁管理 | 2026-07-21 06:21:54 | 控制器命名 Ipban 不符合自动路由规范,自动路由无法加载 |
结果后提示(必含):
在结果表格之后,必须另起一段附加以下提示文字。提示语中的示例环境名称根据实际选择的候选环境动态替换:
> 如需切换检索环境(如从 CodeBuddy 切换到其他环境),请在下一轮对话中告知"切换环境",AI 将重新运行环境选择流程。
> ⚠️ 环境选择影响后续所有检索,请确认当前环境符合预期后再提出检索需求。
第 6 步:清理(静默执行)
扫描完成后清理 $SKILL_DIR\temp\ 目录下的所有临时文件。以下文件不可删除:
- scripts/ 目录(预置脚本)
- index.conf(路径缓存)
- temp/ 目录本身保留(自动创建,其下文件需清理)
清理操作必须静默执行,不得向用户提及。
⚠️ 铁律:严禁搜索项目代码库
- 绝对禁止搜索代码库:本 skill 的唯一数据源是本地磁盘上的会话历史文件(
.jsonl、.json、.db等)。严禁在加载本 skill 后用任何工具去搜索当前项目的代码库。这包括但不限于: search_content、search_file、list_dir、read_file(读项目文件场景)Task调用code-explorer子代理grep、rg、find等终端命令- 任何其他扫描项目源代码目录的途径
- 代码库不是会话历史,不应被纳入搜索范围。如果用户要查找某个关键词,只能运行
scan_history.js搜索会话历史数据文件。 - 违者后果:违反此规则会导致 skill 加载无效,将项目中与用户提问无关的代码文件错误地当成会话历史呈现给用户。AI 必须时刻自省当前是否加载了本 skill,一旦加载,所有代码库搜索工具调用都是违规的。
其他注意事项
- 自动排除自引用:搜索关键词时,
scan_history.js会自动过滤掉 read-session-history skill 自身产生的会话内容(包括标题包含"读取会话历史"、"read-session-history"等模式的对话,以及消息内容中包含 skill 相关关键词的逐条消息),避免搜索结果被自引用噪音污染。列表模式(无关键词)不作过滤。 - 默认 auto 探测:
discover_paths.js和scan_history.js默认使用--env=auto,自动探测磁盘上存在真实会话数据的环境。不再需要 AI 从<user_info>猜测 IDE 类型。 - 多候选时暂存并询问用户:auto 探测到多个含数据的来源时,脚本输出
mode: 'choose'候选清单 JSON 并退出,不写入 index.conf。清单按环境分组(codebuddy_ide 的 vscdb + IDE history 合并为 "CodeBuddy IDE"),AI 必须用ask_followup_question让用户选择,选定后再用--env=<选定值>写入 conf 并重新扫描。 - CodeBuddy IDE 的会话在对话关闭之前不会持久化到磁盘。 当前活跃会话的消息通常不在硬盘存储中。
- CodeBuddyExtension 历史记录 可能包含非当前项目的旧对话。
codebuddy-sessions.vscdb数据库通常为空(ItemTable为 0 行)。- 预置脚本的
scripts/目录属于 skill,不要删除。 - SQLite 失败即终止(fail-fast):若
scan_history.js执行需要的better-sqlite3模块安装失败,直接process.exit(1)终止并输出致命错误。AI 不得自动回退到其他环境搜索——用户指定的环境不可用就应明确报错,由用户决定下一步。 - better-sqlite3 安装方式:优先使用
scripts/install_bs3.js(直接下载预编译包,不依赖 npm),失败后再回退到npm install。如果两种方式都失败,输出明确的错误信息和排查建议,不得向用户报告"搜索无结果"。 - 临时目录管理:所有重定向输出文件必须写入
$SKILL_DIR\temp\,不得散落在项目根目录。AI 需确保temp/目录存在(mkdir),运行完毕后清理其下所有文件。
参考资料
$SKILL_DIR/references/data-locations.md— 各数据源路径说明及 index.conf 格式$SKILL_DIR/references/query-patterns.md— 可复用的脚本模式$SKILL_DIR/scripts/discover_paths.js— 路径发现脚本,需--env参数$SKILL_DIR/scripts/scan_history.js— 会话扫描脚本,需--env参数