Skip to content

[Bug]: opencode-go provider streaming — API calls complete on provider side but gateway never receives stream termination signal#93708

Closed
zhangguiping-xydt wants to merge 1 commit into
openclaw:mainfrom
zhangguiping-xydt:fix/issue-93610
Closed

[Bug]: opencode-go provider streaming — API calls complete on provider side but gateway never receives stream termination signal#93708
zhangguiping-xydt wants to merge 1 commit into
openclaw:mainfrom
zhangguiping-xydt:fix/issue-93610

Conversation

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor

Summary

  • Fix classification: root-cause provider streaming compatibility fix for opencode-go OpenAI Chat Completions streams.
  • Maintainer-ready confidence: high; the transport and legacy stream consumers now have focused regression coverage for terminal finish reasons, trailing usage-only chunks, and request-level abort on terminal usage grace expiry.
  • Root cause: the OpenAI-compatible stream lifecycle contract only treated natural async iterator close as the completion source, so an opencode-go terminal finish_reason mapped to no OpenClaw completion state when the SSE socket stayed open.
  • Why this is root-cause fix: the patch adds an explicit provider compat contract for terminal finish_reason stream completion, preserves trailing usage chunks when configured, and aborts the underlying SDK request when the configured terminal usage grace expires.
  • What did NOT change: scope boundary is unchanged for existing providers; no unrelated provider receives terminal-finish completion or a terminal usage cutoff unless its compat config opts into finishReasonTerminatesStream and terminalUsageGraceMs.

Linked context

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: opencode-go OpenAI-compatible streams now complete after a terminal finish_reason even when the socket stays open, continue through trailing usage-only chunks when present, and abort the request-level stream when the configured terminal usage grace expires without usage.
  • Real environment tested: OpenClaw test runtime exercising the real OpenAI-compatible transport/parser code paths and opencode-go extension metadata in this patch; provider network access was not used.
  • Exact steps or command run after this patch: pnpm test src/llm/providers/openai-completions.test.ts; pnpm test src/agents/openai-transport-stream.test.ts; pnpm --filter @openclaw/model-catalog-core test model-catalog-normalize.test.ts; pnpm test src/config/zod-schema.models.test.ts src/config/config-misc.test.ts -t compat; pnpm test extensions/opencode-go/index.test.ts.
  • Evidence after fix (terminal capture):
$ pnpm test src/llm/providers/openai-completions.test.ts
Exit code: 0
Test Files  1 passed (1)
Tests  30 passed (30)

$ pnpm test src/agents/openai-transport-stream.test.ts
Exit code: 0
Test Files  1 passed (1)
Tests  275 passed (275)

$ pnpm --filter @openclaw/model-catalog-core test model-catalog-normalize.test.ts
Exit code: 0

$ pnpm test src/config/zod-schema.models.test.ts src/config/config-misc.test.ts -t compat
Exit code: 0
Test Files  2 passed (2)
Tests  5 passed | 86 skipped (91)

$ pnpm test extensions/opencode-go/index.test.ts
Exit code: 0
Test Files  1 passed (1)
Tests  12 passed (12)
  • Observed result after fix: the regression suite now covers the reported stuck-stream shape, verifies the stream finalizes after terminal finish signals, verifies trailing usage-only chunks are retained, verifies timeout cleanup aborts the request-level signal, and verifies opencode-go DeepSeek metadata carries the opt-in compat settings.
  • What was not tested: live opencode-go or DeepSeek provider network calls were not run because the issue-specific stream behavior is reproduced with deterministic OpenAI-compatible stream fixtures.

Gateway startup, /readyz, /healthz, listener, or generic status output is setup/smoke evidence only. Unless the linked issue is specifically a startup/readiness/health/liveness bug, this section must exercise the issue-specific runtime path and show the corrected post-fix behavior.

Tests and validation

  • Commands run: pnpm test src/llm/providers/openai-completions.test.ts; pnpm test src/agents/openai-transport-stream.test.ts; pnpm --filter @openclaw/model-catalog-core test model-catalog-normalize.test.ts; pnpm test src/config/zod-schema.models.test.ts src/config/config-misc.test.ts -t compat; pnpm test extensions/opencode-go/index.test.ts.
  • Regression coverage added or updated: transport and legacy OpenAI-compatible stream tests for terminal finish on a hanging socket, trailing usage-only chunks after stop/tool-call finish, and request-level abort when terminal usage grace expires.
  • Extension-specific test lane: pnpm test extensions/opencode-go/index.test.ts verifies the bundled opencode-go extension exposes the DeepSeek compat fields.
  • Contract test coverage: pnpm --filter @openclaw/model-catalog-core test model-catalog-normalize.test.ts and config compat schema tests cover the shared model catalog/config contract for the new compat fields.
  • What failed before this fix, if known: a stream with terminal finish_reason and no socket close could remain pending indefinitely; a terminal usage grace timeout could finish locally without aborting the already-pending SDK stream read.
  • If no test was added, why not: tests were added for the production behavior and compat metadata paths changed here.

Risk checklist

  • Did user-visible behavior change? Yes; opencode-go DeepSeek streams can now finish when a terminal provider finish signal arrives even if the SSE socket remains open.
  • Did config, environment, or migration behavior change? Yes; new optional compat fields were added to the model/config/catalog schema, with opencode-go DeepSeek models opting in.
  • Did security, auth, secrets, network, or tool execution behavior change? Yes; terminal usage grace expiry now aborts the request-level SDK stream signal instead of only closing the iterator.
  • Highest-risk area: OpenAI-compatible provider stream completion semantics and usage accounting.
  • How is that risk mitigated: the behavior is opt-in per provider, delayed usage-only chunks remain supported, providers without terminalUsageGraceMs do not receive a new implicit cutoff, and both stream implementations have regression coverage.
  • Plugin/shared surface boundary: this changes bundled extension metadata and shared compat schema only; no plugin runtime dependency or SDK import boundary changed.

Current review state

  • Next action: submit the PR and wait for the remote CI and mergeability verdict.
  • What is still waiting on author, maintainer, CI, or external proof: no known code review finding is open; remote CI and maintainer review are pending after PR creation.
  • Which bot or reviewer comments were addressed: Codex diff review findings about trailing usage, legacy stream behavior, configurable terminal usage grace, iterator cleanup, and request-level abort on timeout were addressed; the latest Codex diff review found no blocking regression.

Treat configured terminal finish reasons as stream completion while preserving trailing usage chunks so opencode-go DeepSeek streams cannot hang after the provider has completed.
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling extensions: opencode-go size: L proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 16, 2026
@clawsweeper

clawsweeper Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper review: did not complete due to Codex infrastructure failure. Reviewed June 16, 2026, 1:06 PM ET / 17:06 UTC.

Summary
Review failed before ClawSweeper could summarize the requested change.

PR surface: Source +202, Tests +412. Total +614 across 15 files.

Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/agents/sessions/model-registry.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Not assessed.
Failure reason: invalid structured output.

This is a ClawSweeper/Codex infrastructure failure, not a PR readiness or patch-quality verdict.
Keep any merge decision on the normal maintainer review path until ClawSweeper can complete a fresh review.

Risk before merge

  • [P1] No close action taken because the review did not complete.

Maintainer options:

  1. Decide the mitigation before merge
    Retry the Codex review after fixing the execution failure.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • Review did not complete, so no work-lane recommendation was made.
Review details

Best possible solution:

Retry the Codex review after fixing the execution failure.

Do we have a high-confidence way to reproduce the issue?

Unclear. The review failed before ClawSweeper could establish a reproduction path.

Is this the best way to solve the issue?

Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction.

AGENTS.md: unclear because the file could not be read completely.

Codex review notes: model internal, reasoning high; reviewed against 617f97d4b984.

Evidence reviewed

PR surface:

Source +202, Tests +412. Total +614 across 15 files.

View PR surface stats
Area Files Added Removed Net
Source 10 209 7 +202
Tests 5 425 13 +412
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 15 634 20 +614

What I checked:

  • failure reason: invalid structured output.
  • codex failure detail: Codex review failed for this PR with exit 0 and wrote invalid JSON or schema-invalid output to /home/runner/work/clawsweeper/clawsweeper/artifacts/event/codex/93708.json: decision.rootCauseCluster.currentItemRelationship fixed_by_candidate requires a canonical PR.
  • codex stderr: No stderr captured.
  • codex stdout: ","requiresNewFeature":false,"requiresNewConfigOption":true,"requiresProductDecision":true,"reproductionAssessment":"Yes, source-level: current main waits for the OpenAI-compatible stream iterator to close, while the linked report shows provider completion without gateway stream termination. I did not run a live opencode-go provider repro, and the PR's supplied proof is deterministic test output rather than a real provider call.","solutionAssessment":"No, not as submitted. The schema-driven provider opt-in is a maintainable fix shape, but the PR needs CI repairs, docs for the new config surface, and live provider proof before it is the best mergeable solution.","visionFit":"not_applicable","visionFitReason":"Pull request review; VISION.md product-fit classification is not applicable.","visionFitEvidence":[],"implementationComplexity":"not_applicable","autoImplementationCandidate":"none","rootCa.

Likely related people:

  • unknown: Codex failed before it could trace repository history. (role: review did not complete; confidence: low)
How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@vincentkoc

Copy link
Copy Markdown
Member

Closing this implementation, while keeping #93610 open for the provider failure. The report may be real, but this patch is not the best mergeable fix: it adds two shared model/config/catalog compatibility fields, changes both OpenAI-compatible streaming implementations, has failing required lint/test-type checks, and has no live opencode-go/DeepSeek reproduction proving the proposed terminal signal and 50 ms grace window match the provider contract.

The next fix should start provider-owned and include live provider proof. A generic shared seam is reconsiderable only if live evidence shows the behavior is a reusable provider-family contract, with docs and all required checks green.

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

Labels

agents Agent runtime and tooling extensions: opencode-go proof: supplied External PR includes structured after-fix real behavior proof. size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: opencode-go provider streaming — API calls complete on provider side but gateway never receives stream termination signal

2 participants