Claude Code VSCode 插件历史记录不显示问题修复记录
·
问题现象
CCSwitch + VsCode的Cluade code 插件
插件版本为2.1.195
在 Windows 10 + VSCode 中使用 Claude Code 插件(Claude code版本是 2.1.68)时,关闭 VSCode 后重新打开,Past Conversations / History Sessions 页面无法正常显示历史会话,表现为:
- CLI 中 claude --resume 可以正常看到历史;
- claude/projects/…/*.jsonl 历史文件实际存在;
- VSCode 插件历史面板为空,或一直停留在 Loading sessions;
- 打过 GitHub issue #12872 中的补丁后,历史能被扫描到,但可能因为 .jsonl 文件过大或标题提取逻辑不完善,导致加载卡住或标题显示为 <ide_opened_file> 之类的 IDE 事件。
注意打开的路径不同,也会导致会话丢失,原因是C:\Users\Administrator\.claude\projects 这里的项目名字不一样了。
比如同一个项目,之前是 xxx-xx-test,现在是 xxxx-xx-test。
判断结论
该问题不是 Claude Code 配置丢失,也不是历史文件丢失,而是 VSCode 插件在 Windows 路径映射、session 索引和 .jsonl 读取逻辑上的兼容问题。
当前状态可理解为:
- Claude Code CLI:正常
- settings.json:正常
- 历史 .jsonl 文件:正常
- VSCode 插件历史面板:索引/渲染异常
修复思路
在 VSCode 插件的 extension.js 中修改两个核心方法:listSessions() 和 getSession()
主要改动包括:
- 给 session 索引添加 fallback 路径;
- 兼容 Windows 路径大小写和项目目录映射;
- 避免 listSessions() 阶段整文件读取所有 .jsonl;
- 只在历史列表阶段读取 .jsonl 文件头尾内容,用于提取标题;
- 点击具体会话时,再由 getSession() 完整读取对应 session;
- 过滤 <ide_opened_file>、<ide_selected_code> 等 IDE 噪音事件,避免它们被当成会话标题或聊天消息显示;
- 对 zd()、Ld()、getSessionDiffs() 等可能卡住的异步调用增加 timeout,防止插件一直停留在 Loading sessions。
操作步骤
- 先找到 Claude Code 插件目录(一般在
C:\Users\Administrator\.vscode\extensions\anthropic.claude-code-2.1.169-win32-x64),例如:
Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Directory | Where-Object {
$_.Name -like "anthropic.claude-code-*"
} | Select-Object FullName
- 备份原文件:
$ext = "C:\Users\Administrator\.vscode\extensions\anthropic.claude-code-2.1.168-win32-x64"
Copy-Item "$ext\extension.js" "$ext\extension.js.bak_loading" -Force
- 打开
extension.js,搜索并替换:async listSessions()和async getSession(K),具体替换代码如下所示。
替换完成后,在 VSCode 中执行:
Ctrl + Shift + P
Developer: Reload Window
- 如果插件异常,恢复备份:
Copy-Item "$ext\extension.js.bak_loading" "$ext\extension.js" -Force
最终建议
如果补丁生效,建议把最终可用版本单独备份:
Copy-Item "$ext\extension.js" "$ext\extension.final_working.js" -Force
也可以备份到其他位置,避免 Claude Code 插件更新后覆盖:
Copy-Item "$ext\extension.js" "D:\backup\claude\extension.final_working.js" -Force
后续如果插件更新后历史记录再次失效,可以重新对新版 extension.js 应用同样的 listSessions() 和 getSession() 修复逻辑。
总体结论:终端入口最稳定,VSCode 插件历史面板问题可以通过修改 extension.js 解决,但该补丁属于本地热修复,插件更新后可能需要重新应用。
async listSessions(){
const cwd=this.cwd;
let sessions=[];
try{
const store=await vi.load(cwd,this.logger);
const raw=await store.fetchSessions(false);
const teleport=await vi.readTeleportMetadata(
cwd,
raw.map((s)=>s.id)
);
sessions=raw.map((s)=>({
...s,
worktree:cwd,
isCurrentWorkspace:true,
...(teleport.get(s.id)??{})
})).sort((a,b)=>b.lastModified-a.lastModified);
}catch(e){
this.logger.warn(`listSessions failed: ${e}`);
}
const hidden=new Set(this.settings.getHiddenSessionIds());
const visible=hidden.size>0
?sessions.filter((s)=>!hidden.has(s.id))
:sessions;
this.logger.log(
`listSessions cwd=${cwd} total=${sessions.length} hidden=${hidden.size} returned=${visible.length}`
);
return {
type:"list_sessions_response",
sessions:visible
};
}
async getSession(K){
const cwd=this.cwd;
let raw=[];
let sessionDiffs;
try{
const store=await vi.load(cwd,this.logger);
await store.ensureSessionLoaded(K);
const sessionMessageIds=store.sessionMessages.get(K);
if(sessionMessageIds){
raw=Array.from(store.messages.values())
.filter((message)=>sessionMessageIds.has(message.uuid))
.sort(
(a,b)=>
new Date(a.timestamp).getTime()-
new Date(b.timestamp).getTime()
);
}else{
this.logger.warn(`getSession session not found: ${K} cwd=${cwd}`);
}
try{
sessionDiffs=await store.getSessionDiffs(K,cwd,raw);
}catch(e){
this.logger.warn(`getSession diffs skipped: ${e}`);
}
}catch(e){
this.logger.warn(
`getSession failed: session=${K} cwd=${cwd} error=${e}`
);
}
const isNoiseMessage=(entry)=>{
try{
if(!entry||entry.type!=="user") return false;
const content=entry?.message?.content;
const texts=[];
if(typeof content==="string"){
texts.push(content);
}else if(Array.isArray(content)){
for(const part of content){
if(part?.type==="text"&&typeof part.text==="string"){
texts.push(part.text);
}
}
}
return texts.some((text)=>{
const value=text.trim();
return (
value.startsWith("<ide_opened_file>") ||
value.startsWith("<ide_selected_code>") ||
value.startsWith("<ide_diagnostics>") ||
value.includes("The user opened the file")
);
});
}catch{
return false;
}
};
const messages=raw.filter((entry)=>
!isNoiseMessage(entry)&&(
entry?.type==="user"||
entry?.type==="assistant"||
entry?.type==="system"||
entry?.type==="meta"||
entry?.type==="compact"
)
);
this.logger.log(
`getSession id=${K} raw=${raw.length} filtered=${messages.length} cwd=${cwd}`
);
return {
type:"get_session_response",
messages,
sessionDiffs
};
}
更多推荐


所有评论(0)