问题现象

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()

主要改动包括:

  1. 给 session 索引添加 fallback 路径;
  2. 兼容 Windows 路径大小写和项目目录映射;
  3. 避免 listSessions() 阶段整文件读取所有 .jsonl;
  4. 只在历史列表阶段读取 .jsonl 文件头尾内容,用于提取标题;
  5. 点击具体会话时,再由 getSession() 完整读取对应 session;
  6. 过滤 <ide_opened_file>、<ide_selected_code> 等 IDE 噪音事件,避免它们被当成会话标题或聊天消息显示;
  7. 对 zd()、Ld()、getSessionDiffs() 等可能卡住的异步调用增加 timeout,防止插件一直停留在 Loading sessions。

操作步骤

  1. 先找到 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
  1. 备份原文件:
$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
  1. 打开extension.js,搜索并替换:async listSessions()async getSession(K),具体替换代码如下所示。
    替换完成后,在 VSCode 中执行:
Ctrl + Shift + P
Developer: Reload Window
  1. 如果插件异常,恢复备份:
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
  };
}
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐