ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

claude-mem Windows 平台支持实战:从 WMIC 移除、uvx 启动修复到 FTS5 优雅降级

claude-mem Windows 平台支持实战:从 WMIC 移除、uvx 启动修复到 FTS5 优雅降级 claude-mem Windows 平台支持实战从 WMIC 移除、uvx 启动修复到 FTS5 优雅降级【免费下载链接】claude-memPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode More项目地址: https://gitcode.com/GitHub_Trending/cl/claude-mem本文围绕 claude-mem 的 Windows 平台专项修复记录Playbook Phase 06系统讲解该项目在 Windows 上遭遇的四大类核心平台问题——Windows 11 25H2 移除 WMIC 导致孤儿进程清理失效、uvx 子进程无法直接 spawn、PowerShell 管道语法在 Git Bash 下被误解析、以及 Bun 运行时 FTS5 扩展可用性不确定——并逐条给出仓库中对应的源码级修复方案taskkill/Get-CimInstance替代 WMIC、绝对路径直接 spawnuvx.exe、WQL-Filter服务端过滤、windowsHide: true全局纪律以及 FTS5 运行时探测加搜索降级策略。读完本文你可以掌握一个跨平台 Node/Bun 项目在 Windows 上做进程管理、子进程启动和数据库能力探测的完整工程范式。背景一次覆盖约 20 个 Issue 的平台修复战役claude-mem 是一个为 AI Agent 提供跨会话持久上下文的工具它捕获 Agent 在会话中的操作用 AI 压缩后再把相关上下文注入未来的会话。其核心组件是一个常驻的 worker daemon依赖bun:sqlite以及一个通过 MCP 拉起的 ChromaDB 向量搜索子进程。这两个常驻 子进程的设计在 Windows 上恰好踩中了所有平台差异的雷区。仓库中的修复记录 TRIAGE-06-Windows-Platform-Support.md 明确列出了本阶段解决的问题面约 20 个 Windows 相关 Issue其中最高优先级的修复包括问题域关联 Issue根因WMIC 被移除#785Win11 25H2 移除了wmic孤儿进程清理orphan reaper失效PowerShell 语法错误#1024孤儿清理函数中的$_管道语法出错uvx 启动失败#1190、#1192、#1199uvx.cmd这类 shim 无法被无 shell 的spawn()解析FTS5 不可用#791bun:sqlite在 Windows 上可能没有 FTS5 扩展worker 启动 / 控制台弹窗 / Git Bash#1139、#1048、#1062spawn 缺少windowsHidePowerShell 管道中的$_被 Git Bash 解释该 Playbook 的根因验证部分给出了两条关键判断MCP SDK v1.26.0 的StdioClientTransport不支持shell: true选项因此最初方案是路由到cmd.exe /c uvx让 cmd.exe 原生处理.cmd扩展名解析与 PATH 查找而 WMIC 的移除是 Windows 11 25H2 的真实平台回归所有wmic用法必须替换。以下按问题域逐条展开每条都附仓库中当前生效的源码证据。问题一uvx.cmd 无法被 spawn —— MCP SDK 无 shell 选项时的替代路径问题本质ChromaDB 的 MCP server 通过uvxuv 的包执行器拉起。在 Windows 上uvx实际上是一个uvx.cmd批处理 shim而 Node 的无 shellspawn()不会走PATHEXT解析直接 spawn 裸的uvx或uvx.cmd都会失败。由于 MCP SDK 的StdioClientTransport内部固定使用spawn()且不提供shell选项问题无法在传输层解决。仓库中的最终解法最初 Playbook 记录的方案是路由到cmd.exe /c uvx。但在后续迭代中Issue #2696 修订源码演进了一个更彻底的方案在 Windows 上直接 spawnuvx.exe的绝对路径完全绕开 cmd.exe shell 包装。ChromaMcpManager.ts 的源码注释解释了为什么必须放弃cmd.exe包装cmd.exe会在 uvx 看到之前把依赖覆盖规格如onnxruntime1.20、protobuf7中的/解析为 shell 重定向而 Node 的 child_process 针对 cmd.exe 的参数转义又会破坏预先加引号的参数最终 cmd.exe 在约 10ms 内以 The directory name is invalid 崩溃。resolveUvxCommand()的实现策略是非 Windows直接返回uvx依赖 PATHWindows从 uv 的安装 bin 目录通过 uvx-bin-dirs.ts 枚举中解析出uvx.exe的绝对路径并直接 spawn若 uv 的 bin 目录不在 worker 继承的 PATH 中spawn 环境会显式补上这些目录保证即使 worker 启动早于用户把 uv 加入 PATH子进程也能找到uvx。配套的isUvxAvailable()预检含可注入的uvxAvailabilityProbe测试缝在启动前对候选路径做stat校验避免带着坏路径进入 MCP 启动流程。相关测试见 chroma-windows-lifecycle.test.ts。问题二WMIC 移除 —— 用 taskkill Get-CimInstance 重建进程管理能力Windows 11 25H2 移除wmic后claude-mem 的进程管理需要完全迁移到三个现代工具上。从当前源码看迁移落在两个共享模块中。2.1 进程树清理taskkill /T /Fkill-process-tree.ts 是全仓库统一的进程树拆除实现从 ChromaMcpManager 提取而来供所有 teardown 路径复用。选择它的动机在文件头注释中写得很清楚Windows 没有进程组Node 的process.kill(pid, signal)只能强杀单个 PID。任何超过一层的 spawn 链uvx - uv - python - chroma-mcp或包裹真实二进制的.cmdshim都会留下存活的后代进程——它们继承监听套接字卡死 worker 端口。Windows 分支的实现要点kill-process-tree.ts#L138-L165await execFileAsync(taskkill, [/PID, String(pid), /T, /F], { timeout: 5_000, windowsHide: true });/T递归杀整棵子树/F强制退出码语义精确区分taskkill在目标不存在时退出码为 128这是唯一代表已经死了的非零状态代码只把 128 或 stderr 匹配not found|no running instance|no tasks的情形当作成功。注释特意说明不能匹配could not be terminated前缀因为 taskkill 对实例不存在和Access is denied都输出该前缀——匹配前缀会把访问拒绝吞掉而拒绝访问恰恰是要向上抛出的真实失败。其余任何失败访问拒绝、超时、/T遍历卡死都会抛出ProcessTreeKillError确保server stop这类调用方不会在杀进程失败时误报成功。2.2 进程身份识别Get-CimInstance 替代 wmic 查启动时间仅杀 PID 在 Windows 上不安全——OS 会回收并重新发放 PID 编号快照时刻记录的 PID 到杀进程时刻可能已经指向无关进程。process-identity.ts 的注释直接点明了迁移原因Windows 没有廉价的 /proc 式启动时间读取也没有ps lstart所以我们 shell 到 PowerShell 的 CIMwmic 已在 Windows 11 上移除。其实现分三层捕获 start tokenqueryWindowsCreationDate(pid)执行(Get-CimInstance Win32_Process -Filter ProcessIdpid).CreationDate.ToString(yyyyMMddHHmmss.ffffff)注意这里用的正是 Playbook 中提到的WQL-Filter服务端过滤而非Where-Object { $_ }客户端管道——这正是同时修复 #1024PowerShell 语法错误和 #1062Git Bash 把$_解释为 shell 变量的根因级改动。CreationDate是 CIM DATETIME在 (pid, 一次开机) 内足够唯一可用来检测 PID 复用。缓存策略单次 CIM 查询约 100–300ms因此 token 按 PID 缓存 5 秒WINDOWS_START_TOKEN_CACHE_TTL_MS校验必须绕过缓存isSameProcess(pid, snapshotToken)内部故意绕过缓存重新读 OS。注释解释得很尖锐如果走缓存快照捕获会填充缓存条目随后的重新校验读回同一条目在 5 秒 TTL 内 100% 命中——一个被复用的 PID 会被认证为原进程然后taskkill /PID pid /T /F会连坐杀掉一个无关进程及其整棵子树。未导出的无缓存读取器只通过该谓词可达调用方无法拿到裸探针用于其他位置。2.3 进程表枚举一次查询同时拿到父子关系与身份kill-process-tree.ts#L414-L447 的readProcessTableWindows()用一条 PowerShell 命令一次性取回全表Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId, {NameStartToken;Expression{$_.CreationDate.ToString(yyyyMMddHHmmss.ffffff)}} | ConvertTo-Csv -NoTypeInformation这里的设计考量值得注意枚举 PID 后再逐个探测 token 比不检查还糟——如果探测间隙 PID 退出并被重新发放探测拿到的是替代进程的 token后续比对等于拿替代进程和自己比必然认证通过反而给无关进程发了击杀许可证。把父子关系ParentProcessId和身份CreationDate放进同一次观察才是原子的。CSV 的StartToken格式与captureProcessStartToken()的格式逐字节一致这一约定由测试断言而非假设。collectDescendantIdentities()随后做自底向上的子树遍历叶子在前POSIX 分支用/procLinuxstat的 starttime 字段或ps -eo pid,ppid,lstartmacOSLC_ALLC固定 locale 防止本地化日期导致比对失败Windows 分支即上述 CIM 全表查询。问题三控制台窗口弹窗#1048与 Git Bash 兼容#1062windowsHide 作为 spawn 纪律Playbook 要求给 Windows 上所有exec/spawn调用加windowsHide: true。从源码看这条纪律已经渗透到全部平台敏感调用点例如ProcessManager.ts#L37-L41 的lookupBinaryInPath()Windows 分支用where bin、其他平台用which bin做 PATH 查找execSync带windowsHide: truekill-process-tree.ts 中taskkill、ps、powershell.exe的每一处execFileAsync都带windowsHide: trueprocess-identity.ts 的queryWindowsCreationDate()与 macOS 分支的ps -p pid -o lstart均带windowsHide: true且统一经sanitizeEnv()做 spawn 环境纪律。这条纪律有专门的回归测试守护windows-hide-regressions.test.ts 和 worker-wrapper-windows-hide.test.ts防止未来新增的调用点漏配。Windows 分支的额外适配除弹窗问题外Windows 分支还有两处源码级适配值得了解超时时钟差异ProcessManager.ts#L181-L184 提供getPlatformTimeout()Windows 下对基础超时统一乘 2.0——Windows 上进程启动与 CIM 查询显著更慢单次查询 100–300ms。daemon 启动的引号地狱ProcessManager.ts#L360-L415 的buildWindowsDaemonStartCommand()构造Start-Process -FilePath runtime -ArgumentList (scriptPath,--daemon) -WindowStyle Hidden并通过powershell -NoProfile -EncodedCommand base64(utf16le)传递。注释解释了为什么必须在单引号 PS 字符串内嵌字面双引号Windows PowerShell 5.1 拼接-ArgumentList元素时用裸空格且不自动加引号%USERPROFILE%路径中的空格会把脚本路径拆成多个 argv导致 bun 立即以 Module not found 退出Issue #3195。-FilePath参数作为单字符串参数不经过该拼接可安全裸传。Git Bash 兼容#1062则是上述 WQL-Filter改动的附带收益进程查询不再经过含$_的 PowerShell 管道改用始终在 PATH 中的tasklist.exe/taskkill.exe二进制与 WQL 过滤Git Bash 不再有机会把$_解释成自己的环境变量。问题四FTS5 在 Windows Bun 上的运行时探测与搜索降级#791Playbook 的修复策略是启动时探测 FTS5 是否可用不可用时跳过 FTS 建表搜索降级为 LIKE 结构化查询 ChromaDB 向量检索——FTS5 只是全量文本搜索的加速层缺失不应让搜索功能整体瘫痪。SessionSearch.ts 中的运行时探针实现了一个建临时表再删的活性检测private isFts5Available(): boolean { // 探测尝试创建临时 FTS5 虚拟表 this.db.run(CREATE VIRTUAL TABLE _fts5_probe USING fts5(test_column)); // ... 成功后删除并返回 true失败则返回 false }构造时执行一次this._fts5Available this.isFts5Available()后续所有 FTS5 建表observations_fts、session_summaries_fts在ensureFTSTables()中先检查该标志不可用则静默跳过。Playbook 同时要求在迁移路径上补防御migrations.tsmigration006、migrations/runner.ts与 SessionStore.ts其中user_prompts_fts等 FTS5 表创建都包了 try/catch 守卫保证老库升级时在无 FTS5 环境下迁移不中断。降级后的搜索路径仍然完整文本全文检索由 ChromaDB 向量搜索承担结构化过滤走LIKE查询如 SessionStore.ts#L861 的concepts LIKE %:% AND json_valid(concepts)这类 JSON 过滤两者均不依赖 FTS5。验证测试矩阵与结果该阶段修复的验证结果记录在 Playbook 末尾并与仓库测试文件一一对应进程管理69 个 ProcessManager/进程树相关测试全部通过。对应测试包括 kill-process-tree-identity.test.tsstart token 格式跨平台一致性断言、kill-process-tree-pid-reuse.test.tsPID 复用不杀错进程、kill-process-tree-cross-platform.test.ts、kill-process-tree-modes.test.tsgraceful/immediate 两种信号模式、process-registry.test.ts 等SQLite/搜索151 个 SQLite 与搜索测试全部通过覆盖 SessionStore 迁移、FTS5 建表守卫与 LIKE 降级路径对应tests/sqlite/、tests/services/sqlite/下各套件已知的既有失败logger-usage-standards.test.ts中关于src/services/transcripts/cli.ts使用console.log的一条失败经确认在改动前的干净分支上同样失败属于与本阶段无关的存量问题。此外针对 Windows 平台纪律还有专项守护测试windows-hide-regressions.test.tswindowsHide 回归、worker-wrapper-windows-hide.test.tswrapper 隐藏窗口、codex-transcript-watcher-windows.test.ts 与 npm-install-windows-hide.test.ts。小结一套可复用的 Windows 平台工程范式claude-mem 的 Phase 06 修复给出了一条清晰的跨平台进程/存储工程路线任何在 Windows 上跑常驻进程 子进程链 SQLite 的项目都可以对照借鉴永远不用 WMIC进程列表用tasklist /FO CSV /NH杀进程用taskkill /PID pid /T /F需要命令行/父 PID 过滤tasklist做不到时用Get-CimInstance WQL-Filter服务端过滤既避开$_管道语法又天然兼容 Git BashPID 必须配 start token快照与击杀之间任何 PID 都可能被复用击杀前用启动时间 token 重新认证且认证读取必须绕过缓存.cmdshim 不能靠 spawn 解析MCP SDK 无 shell 选项时解析绝对路径直接 spawn 原生可执行文件uvx.exe并警惕 cmd.exe 包装会劫持/参数windowsHide: true是纪律不是可选项每一处exec/spawn/execFile都要带并用回归测试防漏配可选扩展要探测 降级FTS5 这类锦上添花能力用临时表探测可用性建表路径全部加守卫查询路径准备好 LIKE 向量检索的替代方案。以上所有实现均可在仓库对应文件中进一步查证建议从 kill-process-tree.ts 与 process-identity.ts 的头部注释读起——两处注释完整保留了每次设计决策的问题背景关联 Issue 编号是理解这套 Windows 平台防御体系最直接的入口。【免费下载链接】claude-memPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode More项目地址: https://gitcode.com/GitHub_Trending/cl/claude-mem创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表