Skip to content

feat(diagnostics): hint for 3rd-party relay SSE truncation (#180)#181

Merged
hqhq1025 merged 1 commit intomainfrom
worktree-agent-a7a20322
Apr 23, 2026
Merged

feat(diagnostics): hint for 3rd-party relay SSE truncation (#180)#181
hqhq1025 merged 1 commit intomainfrom
worktree-agent-a7a20322

Conversation

@hqhq1025
Copy link
Copy Markdown
Collaborator

Summary

Fix #180 (implementation of #167): give users an actionable diagnostic when a third-party relay (older sub2api / claude2api / anyrouter builds) mishandles OpenAI Responses API SSE events and cuts the stream short with no HTTP status.

What changed

  • packages/shared/src/diagnostics.ts — new relayStreamingBug hypothesis in diagnoseGenerateFailure(). Triggers when:
    • wire === 'openai-responses'
    • baseUrl host is not *.openai.com
    • No HTTP status is attached (transport-level failure, not a 4xx/5xx)
    • Message matches a truncated-stream shape: stream ended, premature close, terminated, ECONNRESET, aborted
  • packages/i18n/src/locales/en.json + zh-CN.jsondiagnostics.cause.relayStreamingBug + diagnostics.fix.relayStreamingBug.
  • packages/shared/src/diagnostics.test.ts — 6 new tests covering positive + negative cases:
    • openai-responses + custom baseUrl + "terminated" → triggers
    • openai-responses + api.openai.com + "terminated" → does NOT trigger (official endpoint isn't the culprit)
    • openai-responses + custom baseUrl + 500 status → does NOT trigger (routes to serverError)
    • anthropic wire + "terminated" → does NOT trigger (wrong wire)
    • "premature close" + "ECONNRESET" message shapes both matched

Detection signal used: (b) from the task spec — pattern-matching on baseUrl + wire + message, since the existing error path (packages/providers/src/codex/client.ts, retry.ts) does not yet attach a "stream closed without response.completed" context field.

Stacked on #165

This PR builds on the diagnoseGenerateFailure() function introduced in #165 (branch worktree-agent-a75d65c7). Merge #165 first, then this PR. Rebasing onto main after #165 lands will be a no-op.

Four-principle check

  • Compatibility: green — pure addition, no signature changes
  • Upgradeability: green — hypothesis code-path is additive, falls through to existing serverError / unknown when signals don't match
  • No bloat: green — ~25 LOC + 2 i18n strings per locale
  • Elegance: green — same shape as existing hypotheses, reuses the DiagnosticHypothesis surface

Test plan

  • pnpm --filter @open-codesign/shared test — 174 passed (8 files)
  • pnpm typecheck — 10 packages green
  • pnpm lint — biome clean (360 files)
  • Manual: reproduce with a gateway that truncates response.* SSE events, confirm the diagnostic panel renders the new cause + fix strings

Refs #167, closes #180.

@github-actions github-actions Bot added docs Documentation area:desktop apps/desktop (Electron shell, renderer) labels Apr 23, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • No high-confidence issues found in added/modified lines.

Summary

  • Review mode: initial
  • No issues identified in the latest diff.
  • Residual risk/testing gap: automated tests were not run in this environment (pnpm not found), so behavioral validation depends on CI.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation): pnpm unavailable in runner environment.

open-codesign Bot

Some gateways (older sub2api / claude2api / anyrouter builds) mishandle
OpenAI Responses API SSE events and treat `response.output_text.delta`
/ `response.completed` as `[DONE]`, cutting the stream short with no
HTTP status — the error surfaces as a transport-level "terminated" /
"premature close" / ECONNRESET.

diagnoseGenerateFailure() now recognises this pattern and returns a
`relayStreamingBug` hypothesis with actionable fix copy (upgrade the
relay, switch wire to openai-chat, or use api.openai.com directly).

Detection signal (b): wire=openai-responses AND baseUrl host is not
*.openai.com AND no HTTP status attached AND the message matches a
truncated-stream shape. HTTP-status errors still route to the existing
gatewayIncompatible / serverError / keyInvalid paths.

Refs #167.

Stacked on #165 (introduces diagnoseGenerateFailure).

Signed-off-by: hqhq1025 <1506751656@qq.com>
@hqhq1025 hqhq1025 force-pushed the worktree-agent-a7a20322 branch from 1e80a69 to 95d26bb Compare April 23, 2026 02:58
@github-actions github-actions Bot removed docs Documentation area:desktop apps/desktop (Electron shell, renderer) labels Apr 23, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • No high-confidence issues found in added/modified lines.

Summary

  • Review mode: follow-up after new commits
  • No issues identified in the latest PR diff.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.
  • Residual risk/testing gap: heuristic matching for truncated streams is covered by unit tests in packages/shared/src/diagnostics.test.ts, but integration behavior remains dependent on CI/runtime paths.

Testing

  • Not run (automation)

open-codesign Bot

@hqhq1025 hqhq1025 merged commit a245761 into main Apr 23, 2026
7 checks passed
@hqhq1025 hqhq1025 deleted the worktree-agent-a7a20322 branch April 23, 2026 03:01
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.

feat(diagnostics): add hint for 3rd-party relay SSE truncation on OpenAI Responses API (#167 follow-up)

1 participant