ChatGPT 本地知识库维护链路故障排查

按本地 MCP、Tunnel 控制面、ChatGPT App、Skill、Workspace Agent 和合并校验分层定位知识库维护链路故障。

#type / debug #status / growing #tech / ai #discipline / obsidian #resource / chatgpt #resource / mcp #platform / windows

[!abstract] 快速原则 从最靠近数据的本地层向外检查:MCP 测试 → Tunnel access/doctor → daemon → App 工具快照 → Agent 挂载与审批 → 具体提案校验。不要看到 404 就直接重建全部配置。

[!info] related notes

ChatGPT 本地知识库维护链路故障排查

现象

常见症状:

  • Tunnel API 返回 404;
  • doctor 失败或 tunnel-client 不在线;
  • ChatGPT 创建 App 时看不到 Tunnel;
  • App 只发现 11 个旧工具;
  • 只读工具被标成 WRITE/DESTRUCTIVE;
  • Workspace Agent 找不到 App 或 Skill;
  • Agent 跳过第一次/第二次确认;
  • 提案存在但合并被拒绝;
  • 已合并但搜索仍返回旧索引。
  • 自启动注册报 `tunnel-client not found on PATH`;
  • 自启动注册报 `MSFT_TaskLogonTrigger is not a valid value for the Trigger variable`;
  • 修正脚本后注册计划任务仍报“拒绝访问”。

快速分层

flowchart TD
    A[故障] --> B{npm run kb:mcp:test}
    B -- 失败 --> L[修本地 Server]
    B -- 通过 --> C{tunnel access/doctor}
    C -- 失败 --> T[查 ID/组织/RBAC/网络]
    C -- 通过 --> D{daemon ready}
    D -- 否 --> R[重启单实例 tunnel-client]
    D -- 是 --> E{普通聊天 App 只读调用}
    E -- 失败 --> P[查 App/Tunnel/工具快照]
    E -- 成功 --> F{Draft Agent Preview}
    F -- 失败 --> G[查 App/Skill/审批/指令]
    F -- 成功 --> H{提案或合并失败}
    H -- 是 --> I[查 proposal hash/base hash/path]

排查过程

第一层:本地 MCP

Set-Location D:\home\thought-forest
npx tsc --noEmit --pretty false
npm run kb:mcp:test
npm run kb:inbox:list

如果这里失败,Tunnel 和 ChatGPT 不可能修复它。先处理工具 schema、路径、索引或测试问题。

第二层:Tunnel 身份和权限

npm run kb:mcp:tunnel:access
npm run kb:mcp:tunnel:doctor

`404 Tunnel not found` 有多种可能:

  1. Tunnel ID 抄错;
  2. key 属于另一个 Platform Organization;
  3. principal 缺 Read/Use,控制面隐藏资源;
  4. Tunnel 已删除或重建;
  5. 本机 profile 与 `.env` 使用不同 ID。

先逐字符核对 ID,再查组织和权限。不要仅凭“我是管理员”推断当前 runtime key 具备 Tunnel 权限;ChatGPT Workspace Admin、Project Owner 和 Platform Organization Owner 是不同角色边界。

记录响应中的 request ID,必要时提交给 OpenAI Support。

第三层:daemon 与网络

检查:

  • 是否只运行一个目标 tunnel-client;
  • healthz 是否 live;
  • readyz 是否 ready;
  • 日志是否持续 polling;
  • 代理、自定义 CA 或 mTLS 是否阻断;
  • 任务计划是否以正确用户和工作目录运行。

Doctor 成功但 daemon 未常驻,ChatGPT 仍会在实际调用时失败。

Windows 登录自启动的三类失败

1. `tunnel-client not found on PATH`

先区分“程序不存在”和“按名称找不到”。`PATH` 只是 Windows 搜索可执行文件的目录列表;如果 `run-tunnel.cmd` 使用 `D:\tools\tunnel-client\tunnel-client.exe` 绝对路径,手动启动可以成功,而仅执行 `Get-Command tunnel-client` 的注册前检查仍会失败。

修复原则是让注册检查与实际 launcher 使用同一个安装事实。当前脚本同时接受 PATH 中的命令和已知安装路径,不需要把 runtime key 写入计划任务参数。

2. `MSFT_TaskLogonTrigger` 无法赋给 `Trigger`

PowerShell 变量名不区分大小写。脚本参数 `$Trigger` 带有 `ValidateSet(‘LogOn’, ‘Startup’)` 时,局部变量 `$trigger = New-ScheduledTaskTrigger …` 实际是在给同一个变量赋一个 CIM 对象,因此参数验证器拒绝 `MSFT_TaskLogonTrigger`。

修复是把对象变量改成语义不同的名称,例如 `$taskTrigger`:

$taskTrigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser
Register-ScheduledTask -Trigger $taskTrigger

3. `Register-ScheduledTask: 拒绝访问`

不要立即把任务升级为 SYSTEM 或最高权限。先显式创建当前用户、交互式登录、最低权限的 principal,并让 Logon trigger 绑定同一用户:

$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$principal = New-ScheduledTaskPrincipal `
  -UserId $currentUser `
  -LogonType Interactive `
  -RunLevel Limited

$taskTrigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser
Register-ScheduledTask `
  -TaskName ThoughtForestKbTunnel `
  -Action $action `
  -Trigger $taskTrigger `
  -Principal $principal `
  -Settings $settings

这个配置与知识库的用户级路径、用户配置和登录后运行模型一致。只有确实需要“无人登录也运行”时,才应评估 Windows Service 或系统级 Startup trigger,以及随之而来的凭据存储与权限问题。

第四层:ChatGPT App

普通新聊天中只启用 App,发送只读概况请求。若失败:

  • App 是否指向正确 Tunnel;
  • 是否误选 `Thought Forest KB (legacy)`;
  • App 的连接是否仍有效;
  • 工具快照是否为 12 个;
  • 工具标注是否与当前 Server 一致;
  • 工作区是否允许自定义 MCP。

服务端新增工具后,已发布 App 不一定自动更新。根据套餐使用 Refresh/重新审核,或新建 App 并明确标记旧版。

第五层:Skill 与 Workspace Agent

App 普通聊天可用而 Agent 不可用时,检查 Draft config:

  • connector ID 是否为新版 App;
  • allowed tools 是否包含完整 12 个;
  • Skill 是否出现在 `skills`;
  • 三个写工具是否 Always ask;
  • Agent 指令是否明确两次停止;
  • Preview 是否运行当前 Draft;
  • Agent 是否错误地使用已发布旧版本。

“Add skill”按钮存在不代表没有挂载;应寻找已挂载 Skill 卡片或读取 Draft config。

第六层:提案合并

按错误类型处理:

错误根因处理
proposal not foundID 错误、已消费或归档调用 `list_proposals`,不要猜 ID
proposal hash mismatch提案正文被修改重新生成提案
target already exists新建期间出现同名文件查重后改为 patch 或选择新边界
base hash mismatch目标在提案后被修改重新读取目标并生成 patch
target outside z路径不在批准目录修正知识架构,不扩大白名单
symlink/path traversal rejected真实路径逃逸保持拒绝,检查输入和文件结构
index failed after apply写入已成功,索引失败只运行 `npm run kb:index`

典型误诊:404 被当成纯 RBAC

如果同一个账号在网页中是 Owner,但脚本返回 404,不应立即断言是 RBAC。最小证据链:

  1. 从 Tunnel 管理页复制真实 ID;
  2. 与 `.env` 和 profile 逐字符比较;
  3. 使用 runtime key 发起精确 GET;
  4. 确认组织;
  5. 最后再检查角色权限。

Thought Forest 的实际案例中,根因是 Tunnel ID 中多个字符抄错,而不是缺权限。这个案例说明错误码只能缩小范围,不能替代输入核对。

解决方案

遵循“只修当前失败层”:

  • 本地测试失败:修 Server;
  • access 失败:修 ID、组织或 key;
  • doctor 失败:修 profile、命令或网络;
  • App 失败:修连接或工具快照;
  • Agent 失败:修挂载、指令或审批;
  • proposal 失败:重新生成精确提案;
  • index 失败:重建索引。

不要同时重建 Tunnel、App、Skill 和 Agent,否则会丢失诊断对照。

回归验证

修复后从失败层向外重新验证:

  • MCP tests
  • Tunnel access
  • Tunnel doctor
  • daemon health/ready
  • 普通聊天只读 App
  • Draft Agent 只读 Preview
  • 第一次批准只暂存
  • 第二次批准合并
  • 拒绝/冲突路径
  • `ThoughtForestKbTunnel` 为 Enabled,principal 是当前用户且 RunLevel 为 Limited
  • 重新登录后只出现一个 tunnel-client,`healthz` 和 `readyz` 均返回 200

预防

  • ID 复制后用脚本验证,不手工重输;
  • profile、`.env` 和文档使用占位符或单一来源;
  • 旧 App 重命名为 `legacy`;
  • 服务端版本和工具数量进入 smoke test;
  • Skill 源目录与生成 ZIP 做 hash 比较;
  • Agent 发布前固定运行四个验收场景;
  • 日志不输出 key、token 或完整敏感 header。
创建于 2026/8/8 更新于 2026/8/8