Skip to content

feat(providers): 供应商级流式重试策略——default/off/custom 三态反转到设置层 - #597

Open
AlphaCatMeow wants to merge 3 commits into
Stack-Cairn:mainfrom
AlphaCatMeow:feat-llm-retry-policy
Open

feat(providers): 供应商级流式重试策略——default/off/custom 三态反转到设置层#597
AlphaCatMeow wants to merge 3 commits into
Stack-Cairn:mainfrom
AlphaCatMeow:feat-llm-retry-policy

Conversation

@AlphaCatMeow

@AlphaCatMeow AlphaCatMeow commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Closes #596

Depends-On: #594
Stack-Root: #590

改动说明

把流内重试策略的归属权从全局常量反转到供应商配置(stack 第 3 层,PR-2/5)。未配置任何 retryPolicy 时行为与 main 严格等价

共享真源(agent-ui settings)

  • CustomProvider.retryPolicy?{ mode: "off" }{ mode: "custom", maxRetries }maxRetries首次请求失败后的重试次数(不含首次请求,钳位 1..10),与重试状态提示"正在重试 (n/m)"的 m 同一口径
  • normalizeProviderRetryPolicy:default 态不落字段,非法输入(未知 mode、custom 无有效次数)一律落 default——旧配置零迁移
  • Gateway 设置同步派生自 Omit<CustomProvider, "apiKey">,新字段自动纳入,无需额外改动

运行时(agent-gui)

  • ProviderRuntimeConfig.retryPolicy 经唯一构造点 createProviderRuntimeConfig 透传
  • 新增 resolveStreamRetryConfig:缺省 → {}(落全局默认 DEFAULT_STREAM_RETRY_MAX_ATTEMPTS);off → { disabled: true };custom → { maxAttempts: maxRetries + 1 }(用户口径 → withStreamRetry 总尝试数)
  • agentRunnertextOnlyRuntime 两个 streamRetry 注入点展开合并策略;onRetry/onRetryRecovered 回调与 buffer-until-commit 语义逐行不变
  • failover 逐候选使用各自 runtime 的策略(textOnly 回退路径全部经 buildTextOnlyStreamOptions,天然按候选解析)
  • streamRetry.ts 与协议适配器零改动;全 diff 不含 src-tauri/**(设置 JSON 对 Rust 透传)

设置 UI(GUI 与 WebUI 镜像同源)

  • ProviderModal/ProviderModalView 请求面板新增「流式重试」三态控件(默认/关闭/自定义次数),自定义态显示重试次数输入(1..10,blur 钳位)
  • UI 展示镜像常量 PROVIDER_RETRY_DEFAULT_MAX_RETRIES = 5 与运行时真源(DEFAULT_STREAM_RETRY_MAX_ATTEMPTS - 1)的一致性由单测锁定

验证结果

  • 新增 test/providers/provider-retry-policy.test.mjs(13 用例):归一化矩阵、构造点透传、消费方合并语义三种 mode、failover 候选策略独立、口径换算(maxRetries+1)、镜像常量一致性 — 13/13 通过
  • PR-0 golden 两套件(13 用例)与既有 stream-retry.test.mjs(13 用例)零修改通过;PR-1 seam 套件 8/8
  • pnpm --dir crates/agent-gui build ✅ / test:frontend(269 个测试文件)✅
  • pnpm --dir crates/agent-gateway/web build ✅ / test(83 个测试文件)✅
  • 任务文件 biome lint 零错;git diff --check
  • node scripts/check-ui-boundaries.mjs:仅既有 3 个文件不合规(与 upstream/main 逐字节一致,非本 PR 引入)
  • WebUI 仓库级 lint:预置格式基线失败(本 PR 未触碰 gateway 目录,git diff 取证为零交集)

未运行项

  • Rust/Go 后端测试(本 PR 无后端改动)

人工验收结果

Windows Tauri 调试客户端(start-tauri-dev.bat,分支 HEAD)人工验收通过:

  • 控件口径与外观:三态胶囊 + 自定义重试次数输入(默认填 5)✅
  • 默认(未配置)行为与旧版一致 ✅
  • 自定义 2 次:断网后提示 (1/2)、(2/2),共 3 次请求后报错 ✅
  • 关闭:断网直接报错,无重试提示 ✅
  • 配置持久化:重开弹窗保留所选态与次数 ✅

自动化专用用例(UI 无法直接触发,已附命令与结果):node --test test/providers/provider-retry-policy.test.mjs → 13/13 通过(非法输入归一化矩阵、failover 逐候选独立解析、口径换算与镜像常量一致性)。

Screenshots / preview

17-32-27 17-33-25 17-35-33

为 LLM seam 改造提供行为等价判定基准:
- wire-payload-golden:anthropic-messages / openai-completions /
  openai-responses / google-generative-ai / deepseek-responses 五协议
  固定输入下的完整请求体逐字段锁定(thinking 档位、工具、缓存断点、
  text-only 双形态),走真实 pi-ai stream() 与全部 payload 中间件,
  onPayload 链尾截获后中断,零网络。
- transport-golden:prepareProviderRequest 完整输出快照(反代 URL、
  全量头集、base64 覆盖包解码断言、鉴权头排除、full URL 模式、
  useSystemProxy 开关),并锁定 failover 逐候选传输配置独立性
  (主选走代理+备选直连互不泄漏,双向拓扑)。

零生产代码改动。
将 streamByApi.ts 的五协议 switch 原样搬移为 service/ 下的双适配器
(piAiAdapter 承接 4 条 pi-ai 协议,deepSeekAdapter 承接 deepseek 原生),
经 api→adapter 注册表分发;新增统一流式入口 llm.stream(),携带仅 dev
构建生效的请求信封冻结与一次性分发不变量。streamByApi.ts 收缩为保留
原签名的兼容壳(分发针孔),agentRunner 与 textOnlyRuntime 共 5 处调用
换用统一入口。行为严格等价:PR-0 两个 golden 套件(13 用例)零修改
通过;新增 seam 单测 8 用例覆盖注册表分发、错误文案逐字等价、dev
冻结开关与双入口 wire payload 等价。零 Rust 改动、零镜像文件改动。
将流内重试策略的归属权从全局常量反转到供应商配置(PR-2,stack 第 3 层):

- 共享真源 agent-ui settings 新增 CustomProvider.retryPolicy?(off |
  custom+maxRetries),maxRetries 为首次失败后的重试次数(不含首次请求,
  钳位 1..10)。normalizeProviderRetryPolicy 保证非法/缺省一律落 default
  且不落字段,旧配置零迁移;default 态在持久层不存在。
- agent-gui 运行时经 ProviderRuntimeConfig 唯一构造点透传策略,新增
  resolveStreamRetryConfig 把策略解析为 withStreamRetry 选项(off →
  disabled,custom → maxAttempts=maxRetries+1,缺省 → 空对象落全局默认)。
  agentRunner 与 textOnlyRuntime 两个 streamRetry 注入点展开合并,回调
  语义与 buffer-until-commit 不变;failover 逐候选使用各自 runtime 的
  策略。streamRetry.ts 与协议适配器零改动,
  DEFAULT_STREAM_RETRY_MAX_ATTEMPTS 降级为未配置时的默认值。
- 共享 settings UI(ProviderModal/ProviderModalView)请求面板新增
  流式重试三态控件(默认/关闭/自定义次数),GUI 与 WebUI 镜像同源;
  UI 展示镜像常量 PROVIDER_RETRY_DEFAULT_MAX_RETRIES 与运行时真源的
  一致性由单测锁定。
- 新增 provider-retry-policy.test.mjs(13 用例):归一化矩阵、构造点
  透传、消费方合并语义三种 mode、failover 候选策略独立、口径换算。
  PR-0 golden 两套件与既有 stream-retry 套件零修改通过。
@StackCairn
StackCairn marked this pull request as draft August 22, 2026 10:03
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

PR governance checks passed. Awaiting human review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

供应商级流式重试策略:default/off/custom 三态可配置

1 participant