Skip to content

[Bug] 3.18.2 升级后,外部 ACP 客户端拉起的 headless app-server 无法通过 OS 加密凭证认证,请求 bigmodel 恒定 401 #1502

Open

Description

@flywithrain

环境

  • OS:Windows 11(10.0.26200 x64)
  • ZCode Desktop:3.18.2.10443(2026-11-13 16:44 自动升级,升级前版本正常)
  • 外部 ACP 客户端:hifox,通过 node zcode.cjs app-server --stdio 拉起 headless 会话
  • 模型通道:account:bigmodel-individual-coding-plan → https://open.bigmodel.cn/api/anthropic(SSE)

一句话结论

升级把凭证存储切换为 OS 凭据库加密(enc:v2 / credential-source: os)后,桌面端进程能解密、一切正常;外部客户端用裸 node 拉起的 headless app-server 解不出凭证,请求不带有效 token 出网 → 服务端恒定 401 auth_failed,token 刷新通道同样失败,表现为一发即死、不重试。同一份凭证文件、同一端点,桌面端在故障窗口内正常工作,可证明凭证本身有效。

复现步骤

  1. ZCode Desktop 升级到 3.18.2.10443(2026-11-13 16:44)
  2. 外部 ACP 客户端按常规方式拉起 headless app-server 并触发一次对话
  3. 观察模型请求 → 401;同时在桌面端发起新对话 → 正常

时间线(2026-11-13,本地时间 UTC+8)

时间 事件
16:44 升级安装:~/.zcode/v2/credential-source 重写为 os
17:07–17:08 桌面端重启;~/.zcode/v2/credentials.json 全量重写为 enc:v2: 加密条目
17:10:36 headless/ACP 路径首次出现 401(当天此前 0 次)
17:10–17:53 hifox 会话持续 401(84 条失败记录);桌面端同时段正常
17:53:51 hifox 新建会话,headless app-server 全新进程拉起
17:53:57 / 17:53:59 新进程两次 401(读的就是 17:08 重写后的新凭证文件)
17:37 / 全天 桌面端同端点成功流式 3316 次

证据

A. 同端点、同凭证:桌面端成功,headless 401(时间窗重叠)

  • 401 全部来自 https://open.bigmodel.cn/api/anthropic,与桌面端成功请求的端点完全相同
  • 401 窗口(17:10:36–17:53:59)内,桌面端完成 18 次成功补全(首条 17:37:59、末条 17:45:32,均为 ttft.model.completed)
  • 401 窗口结束后,桌面端 18:04:08 继续正常补全——凭证在整个故障期内有效

B. 排除"旧进程持有旧 token":全新进程仍然 401

17:53:51 由 hifox 全新拉起的 headless 进程(启动仅 6 秒,读取的是 17:08 重写后的新凭证文件),17:53:57 即 401:

{"timestamp":"2026-11-13T09:53:57.865Z","event":"model.request.failed",
 "context":{"providerId":"account:bigmodel-individual-coding-plan","modelId":"GLM-5.3",
            "attempt":1,"maxAttempts":11,"transport":"sse","reason":"auth_failed",
            "retryable":false,"statusCode":401,"statusMessage":"Provider authentication failed."}}

C. 凭证刷新通道同样不可用

{"timestamp":"2026-11-13T09:53:57.868Z","event":"model.retry.delay.resolved",
 "context":{"reason":"auth_failed","retryReason":"auth_refresh","statusCode":401}}

retryable: false + 刷新立即失败 → headless 无法通过刷新获得新 token,与"无法解密存储中的 refresh token"一致。

D. 两种 app-server 的启动拓扑差异(疑点所在)

桌面端(正常) headless/ACP(401)
拉起方式 ZCode.exe → zcode-runtime-host.exe(命名管道宿主)→ zcode.cjs app-server --stdio --surface desktop hifox daemon → zcode-acp.cjs server → 裸 node.exe 直接运行 zcode.cjs app-server --stdio(无 runtime-host)
结果 全天正常 全部 401

E. 升级前无此问题

  • 2026-11-12 全天日志:0 条 401;ACP 路径仅有一次无关错误码(IDENTITY_VERIFICATION_REQUIRED)
  • 401 起点(17:10:36)= 升级 + 凭证重加密完成(17:08)之后 ACP 的第一次对话

F. 凭证存储形态(升级引入的变化)

  • credential-source 内容:os(16:44 写入)
  • credentials.json 所有条目为 enc:v2:... 形态(17:08 重写),键含 zcodejwttoken、oauth:zai_cn:access_token、oauth:linked_bigmodel 等
  • 桌面端可正常使用这些凭证发起请求,说明凭证内容有效;headless 侧表现为"有存储但用不了"

推测的根因

OS 凭据库作用域的加密凭证(enc:v2 / credential-source: os)在 Electron 主进程之外不可解密(或解密/刷新通道依赖 runtime-host),headless app-server 读到密文后无法还原,也未走"回退到其他凭证源"的路径,导致不带有效 Authorization 出网。

期望行为

headless / ACP 拉起的 app-server 应与桌面端一致地解密(或刷新)凭证;若无法解密,应给出明确错误(如"凭证解密失败")而非让请求裸发出网拿到 401。

当前 workaround(已验证思路)

为 headless 场景配置 API key 型 provider(绕开 OS 加密凭证)后 ACP 可用;但官方对 OAuth 凭证在 headless 下的支持仍期望修复。

附注

  • 以上日志行号(如 model.request.failed 位于 zcode-2026-11-13.jsonl 第 27791 行)对应本地日志文件,需要完整片段可提供
  • 已排查并排除的方向:provider ID 映射错误(升级后已正确映射到新 ID)、模型权限(GLM-5.3 与 GLM-5.3-Flash 在故障窗口前后均有成功记录)、端点差异(两条路径端点相同)、凭证过期(桌面端同时段正常)

Activity

  1. github-actions commented on Nov 13, 2026

    @github-actions

    👋 感谢你的反馈,我们已经收到。

    • 维护者看到后会尽快回复你。
    • 状态保持为 status: 待评估,你可以随时补充信息。
    • 信息不全时我们会打上 needs: 更多信息 标签并 @ 你。

    👋 Thanks — we've received your issue.

    • A maintainer will get back to you as soon as we can.
    • Status stays at status: 待评估 (Triage); feel free to add context.
    • If we need more details, we'll add needs: 更多信息 and ping you.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions