Skip to content

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

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

feat(diagnostics): hint for 3rd-party relay SSE truncation (#180)#181
hqhq1025 merged 1 commit into
mainfrom
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

@github-actions github-actions Bot 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.

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

@github-actions github-actions Bot 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.

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

1 participant