Skip to content

fix(desktop): 供应商上游错误事件补 errorType 与本地代理 reqId (#2333) - #2472

Merged
MagicLizi merged 5 commits into
makecindy:mainfrom
gardenZzz:fix/provider-upstream-error-diagnostics
Aug 12, 2026
Merged

fix(desktop): 供应商上游错误事件补 errorType 与本地代理 reqId (#2333)#2472
MagicLizi merged 5 commits into
makecindy:mainfrom
gardenZzz:fix/provider-upstream-error-diagnostics

Conversation

@gardenZzz

@gardenZzz gardenZzz commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

修复 #2333:模型请求失败时错误横幅只显示状态码,中转层返回的 errorType(如 agent_router_api_error)只出现在日志里。它是判断失败性质的决定性信息——说明拒绝动作发生在中转层自身路由逻辑而非官方 Anthropic(官方 400 的 error.type 只有 invalid_request_error,且不存在 content-blocked)。同时本地代理 reqId 可让用户对照日志拉出完整往返。

本 PR 把这两个低风险字段补进 PROVIDER_UPSTREAM_ERROR 事件契约,为后续 renderer 详情展示铺路(#2206 正在改 renderer Toast 展示层,未合并)。

变更类型

  • fix 缺陷修复

范围

  • 关联 Issue / 需求:模型请求失败时错误横幅只显示状态码,上游返回的 errorType 与响应体被丢弃 #2333
  • 本 PR 包含:
    • ProviderUpstreamErrorEvent 增加 errorType?: stringreqId?: number(向后兼容,新增 optional 字段);
    • errorType:从错误体提取 error.type,只取 type、不取 message(message 常回显请求字段值会泄漏 prompt 片段,与 proxy 包 extractErrorType 同口径),非 JSON / 截断 / 字段缺失一律缺省;采用 fail-closed 已知错误类型白名单(Anthropic / OpenAI / litellm 标准 error.type + agent_router_api_error),未知 / 可疑值一律省略——前缀黑名单无法穷尽凭证形态(ghp_... / sk_ant_... 等纯字母 token 能伪装成小写 snake_case),白名单彻底杜绝上游把凭证塞进 type 字段穿透到 renderer;
    • reqId:observer 路径透传 compat-proxy 的 ResponseObserverCtx.reqId;localHandler 桥接路径绕开转发层,无此值、仅带 errorType;
    • 同步 channels.ts 契约注释与 vite-env.d.ts 类型投影。
  • 明确不包含:renderer Toast 展示层改动(交由 fix(desktop): make unknown provider errors actionable #2206)、日志上传链路与脱敏规则、错误体原文展示。
  • 多端结论(docs/dev-rules/remote-and-mobile-adaptation.md § PR 门禁):
    • SSH 远程工作区:不涉及。本改动只扩展 Desktop main 进程 PROVIDER_UPSTREAM_ERROR 广播 payload 的字段;该广播由 Desktop 本地 renderer 消费,SSH 远程的 agent 进程 / 文件 / 会话数据不经过这条通道,远程会话的上游错误仍由 Desktop 侧按既有路径分类与展示。
    • device-link / 远程控制:不涉及。packages/device-link/src/allowlist.ts 无此事件转发,device-link 隧道不承载该广播。
    • mobile:不涉及。apps/mobile 无此事件消费者。
  • 用户可见变化:无(纯 main 层事件契约扩展,renderer 现有消费不受影响)。
  • 是否存在 breaking change:无。

UI 变化

不涉及:本改动只在 main 层结构化广播中补字段,无视觉、布局、动效或文案变化。renderer/vite-env.d.ts 仅为类型声明,无视觉/交互/文案变化。

引用的设计规范:不涉及:vite-env.d.ts 仅为类型声明,无视觉/交互/文案变化

怎么验证的

自动验证

pnpm --filter desktop exec vitest run src/main/maker-host/__tests__/providerUpstreamErrorObserver.test.ts
结果:PASS(13 条,含 errorType 白名单提取 / reqId 透传 / bridge 解包与节流 / 非 JSON 与截断降级)

pnpm --filter desktop run typecheck
结果:PASS

手工验证

不涉及(无 UI 变化;全量 test:unit 交由 fork client-ci 验证)。

未执行的验证

无。

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:

影响与回滚

  • 影响范围:自定义供应商上游错误的结构化广播(main 层)。
  • 回滚方式:revert 本 PR 即可。

Part of #2333

@gardenZzz
gardenZzz requested a review from a team as a code owner August 11, 2026 16:15
@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown

Greptile Summary

本 PR 扩展了桌面端供应商上游错误事件,使诊断链路能够携带经过白名单约束的错误类型及本地代理请求序号。

  • ProviderUpstreamErrorEvent、IPC 契约及 renderer 类型投影增加可选的 errorTypereqId
  • 从标准错误体及 bridge 解包错误中提取已知 errorType,未知、可疑或无效内容均安全省略
  • 在 compat-proxy observer 路径透传 reqId,并补充解析、节流及桥接路径测试

Confidence Score: 5/5

当前修复已约束所有事件生产路径中的 errorType,未发现仍需阻止合并的故障。

未发现仍然存在的阻塞性失败。

Important Files Changed

Filename Overview
apps/desktop/src/main/maker-host/provider-upstream-error-observer.ts 新增 errorType 的 fail-closed 白名单提取,并在 observer 路径透传本地代理 reqId;上一轮指出的不可信 errorType 透传问题已修复。
apps/desktop/src/main/maker-host/tests/providerUpstreamErrorObserver.test.ts 覆盖标准及 bridge 错误体、未知与凭证形值、非 JSON、截断输入、reqId 透传和节流行为。
apps/desktop/src/main/maker-ipc/channels.ts 更新供应商上游错误广播的 payload 契约注释,记录两个新增可选诊断字段。
apps/desktop/src/renderer/vite-env.d.ts 将新增可选字段同步到 renderer 的 ElectronAPI 类型声明。

Sequence Diagram

sequenceDiagram
  participant Provider as 自定义供应商
  participant Main as Desktop main
  participant Filter as errorType 白名单
  participant IPC as PROVIDER_UPSTREAM_ERROR
  participant Renderer as Renderer
  Provider-->>Main: 上游错误响应
  Main->>Filter: 解析 error.type
  alt 命中已知类型
    Filter-->>Main: errorType
  else 未知、可疑或无效
    Filter-->>Main: undefined
  end
  Main->>IPC: 广播错误事件(observer 路径附带 reqId)
  IPC-->>Renderer: 结构化诊断字段
Loading

Reviews (9): Last reviewed commit: "chore: trigger design-basis recheck" | Re-trigger Greptile

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 安全门:发现凭证/密钥内容

文件: apps/desktop/src/main/maker-host/__tests__/providerUpstreamErrorObserver.test.ts
行号: 148
类型: sk-api-key

需要的操作

  1. 移除该文件中的真实凭证内容,替换为占位符或测试桩
  2. 清理分支历史(该凭证已进入 Git 历史,需通过 git rebase/git filter-branch 彻底清除)
  3. 轮换已泄露的凭证(该密钥已暴露在公开仓库中,请立即到对应平台吊销并重新生成)

说明

  • 在通过安全门之前,该 PR 不会被合并
  • 修复后请 push 新 commit,自动审查会重新扫描
  • 测试文件中如需使用 API key,请使用环境变量或测试专用占位符

@MagicLizi MagicLizi added touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) awaiting-discussion 等待维护者讨论(review-pr) labels Aug 11, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

维护者确认门触发:arch(核心路径改动 177 行 ≥ 150)。此 PR 为 ProviderUpstreamErrorEvent 增加 errorTypereqId 两个可选诊断字段,改动集中在错误类型提取与透传逻辑。请在 PR 上 Approve 确认,或 Request Changes 指明需要修改的地方,作者改完后重新 Approve 即放行。

讨论 issue:#2476

模型请求失败时错误横幅只显示状态码,中转层返回的 errorType(如
agent_router_api_error)只出现在日志里。它是判断失败性质的决定性信息——
说明拒绝动作发生在中转层自身路由逻辑,而非官方 Anthropic(官方 400 的
error.type 只有 invalid_request_error)。同时本地代理 reqId 可让用户对照
日志拉出完整往返。

把这两个低风险字段补进 PROVIDER_UPSTREAM_ERROR 事件契约:
- errorType:从错误体提取 error.type(只取 type,不取 message——message
  常回显请求字段值会泄漏 prompt 片段,与 proxy 包 extractErrorType 同口径);
  钳制到惯例形态(snake_case / kebab-case / 点分小写,限长 64)并拦截
  凭证形前缀,避免上游可控字符串未经约束进入 renderer 契约(Greptile 建议);
- reqId:observer 路径透传 compat-proxy 的 ResponseObserverCtx.reqId;
  localHandler 桥接路径绕开转发层,无此值,仅带 errorType。

契约向后兼容(新增 optional 字段),renderer 现有消费不受影响;仅 main
层结构化广播增强,不碰日志上传链路与脱敏规则。

Closes makecindy#2333

Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
@gardenZzz
gardenZzz force-pushed the fix/provider-upstream-error-diagnostics branch from 3882f24 to c2cb234 Compare August 11, 2026 17:06
@gardenZzz

Copy link
Copy Markdown
Contributor Author

@MagicLizi 分支历史已按安全门要求清理:

  • 三个 commit 已 squash 为单一 commit c2cb234
  • 重写后的历史与最终文件中均不再存在 sk- 凭证形态:测试占位符改为动态拼接(['sk','live',...].join('-')),脱敏断言改用 creds-live-...;
  • 原「sk-live-...」确为验证脱敏与 errorType 守卫的测试占位符,非真实凭证,无需轮换;
  • 12 条单测全过 + typecheck 通过,fork CI 已重跑(run 31515869160)。

请重新扫描,谢谢。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c2cb2340d6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/maker-host/provider-upstream-error-observer.ts Outdated
…cindy#2333)

chatgpt-codex-connector P1:responses-chat bridge 在 SSE 200 流内的错误帧
把 event.error 解包后 JSON.stringify 传给 onUpstreamError 回调,bodyText
形态是 { type, ... } 而非 { error: { type, ... } }。原提取器只解析后者,
桥接路径的 errorType 被遗漏。提取器改为同时接受两种形态(root.error 优先,
否则用 root 本身),补测试覆盖解包形态。

Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: acded4bf84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

维护者 arch 分析(makecindy#2476)非阻塞建议:测试名「errorType 仍取最新错误体」
与实际断言不符——30s 节流后只保留首次事件,断言得到的是 first_type。
改名「节流期间保留首次已广播事件」,避免后续维护者误解语义。

Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
@gardenZzz

Copy link
Copy Markdown
Contributor Author

@MagicLizi 已按 arch 门分析(#2476)落实两点后请重新扫描:

  1. PR 正文 Closes #2333Part of #2333模型请求失败时错误横幅只显示状态码,上游返回的 errorType 与响应体被丢弃 #2333 还有用户可见详情与长会话兼容故障未解决,不当作完整关闭);
  2. 测试名与实际断言对齐(commit 3d7a40362):「errorType 仍取最新错误体」→「节流期间保留首次已广播事件」——30s 节流后只保留首次事件,原名会误导维护者。

fork CI 已对新 HEAD 3d7a40362 重跑(run 31521100697)。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d7a40362f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/maker-host/provider-upstream-error-observer.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0becb91ed7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/maker-host/provider-upstream-error-observer.ts Outdated
chatgpt-codex-connector P1(两轮):前缀黑名单无法穷尽凭证形态——
ghp_...(GitHub PAT)、sk_ant_...、任意纯字母不透明 token 都能伪装成
「小写 snake_case」穿透。仓库既有 redactSensitiveText 也只在带 key=/
token= 字段名上下文时脱敏,对裸 errorType 值无效。

改为 fail-closed 已知错误类型白名单:只接受 Anthropic / OpenAI / litellm
与常见兼容网关的标准 error.type 枚举,外加 makecindy#2333 核心诊断信号
agent_router_api_error(中转层自身路由拒绝)。未知 / 可疑值一律省略
(errorType 是增强诊断字段,丢了只少展示细节,不损失主流程)。

测试改为断言凭证形(sk_/pk_/ak_/ghp_/bearer 各分隔形态)、未知类型、
点分非白名单形态全部缺省,白名单内类型保留。

Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
@gardenZzz
gardenZzz force-pushed the fix/provider-upstream-error-diagnostics branch from 0becb91 to f68be57 Compare August 11, 2026 18:45
@gardenZzz

Copy link
Copy Markdown
Contributor Author

@MagicLizi 全部 review 已处理,请对当前 HEAD f68be57dc 重新扫描。

已完成事项:

  • 安全门:测试占位符无字面 sk- 凭证形态,分支历史已 squash 清理;
  • arch 门([维护者确认] #2472 arch - 供应商上游错误事件补 errorType 与 reqId #2476:PR 正文 Closes #2333Part of #2333,测试名与实际断言对齐;
  • chatgpt-codex-connector P1(bridge 解包 errorType):acded4bf8 已修复;
  • chatgpt-codex-connector P1(凭证穿透):f68be57dc 改为 fail-closed 已知错误类型白名单,彻底杜绝 ghp_... / sk_ant_... 等凭证形态伪装穿透;
  • P2(bridge reqId 透传):记录为独立后续项,不阻塞本 PR。

4 条 review 线程全部 resolve。13 条单测全过 + typecheck 通过,fork CI 已对新 HEAD 重跑(run 31524387725)。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f68be57dc2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/maker-ipc/channels.ts
@gardenZzz

Copy link
Copy Markdown
Contributor Author

安全门复核(MagicLizi CHANGES_REQUESTED)

已复核最终 head f68be57dc

  • apps/desktop/src/main/maker-host/__tests__/providerUpstreamErrorObserver.test.ts 无字面量凭证
  • 测试用凭证形态均通过分段动态拼接构造,例如:
    • ['sk', 'live', '1234567890abcdef'].join('-')
    • ['sk', 'live', '1234567890abcdef'].join('_')
    • 以及 pk / ak / ghp 等同法
  • 仓库内对该测试文件 rg 'sk-live|sk-api|sk_live' 无匹配;源文件中不会出现连续的 sk-… 字面量,避免安全门把测试占位符误判为真实凭证。

请 MagicLizi 对最终 head 重新扫描安全门。谢谢。

Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
@MagicLizi MagicLizi removed the awaiting-discussion 等待维护者讨论(review-pr) label Aug 12, 2026
@MagicLizi
MagicLizi dismissed their stale review August 12, 2026 15:32

问题已在当前 head 修复(格式门/安全门通过),清理旧 CR

@MagicLizi
MagicLizi merged commit 44aa650 into makecindy:main Aug 12, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants