Skip to content

fix: handle empty OpenAI completions and Gemini history parts - #10215

Open
PeiPei233 wants to merge 5 commits into
AstrBotDevs:masterfrom
PeiPei233:fix/accept-empty-stop
Open

PeiPei233 wants to merge 5 commits into
AstrBotDevs:masterfrom
PeiPei233:fix/accept-empty-stop

Conversation

@PeiPei233

@PeiPei233 PeiPei233 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Models can finish successfully without another visible reply, for example after a message-sending tool has delivered the result. AstrBot rejects these empty turns, retries completed work and may unnecessarily switch providers. This affects both Chat Completions (finish_reason="stop") and Responses (status="completed"). Empty assistant history can also produce invalid Gemini text parts.

Related: #7409, #7044. This revisits closed, unmerged #7410; #7104 introduced dedicated empty-output retries.

Changes

  • Accept contentless Chat Completions only for normal stop without raw tool calls, legacy function calls or refusals.
  • Accept empty Responses turns only for completed without errors, incomplete details, unhandled output or unfinished output items. Preserve response ID, raw completion, token usage and encrypted reasoning state. Unparsed tool calls, empty refusals and unsupported output remain errors.
  • Normalize empty visible output and reasoning to None. Complete the agent without appending an empty assistant text message; retain existing tool history.
  • Omit empty Gemini assistant text parts while retaining calls and existing signature behavior. Signature-only content uses a space data field.

The Responses parser is shared by non-streaming and terminal streaming events. Streams without a terminal event still fail. This PR does not make thought signatures portable between different providers.

Validation

  • Full PR checkout: pytest -q tests/test_openai_responses_source.py tests/test_openai_source.py tests/test_tool_loop_agent_runner.py tests/test_gemini_source.py — 207 passed.
  • Responses tests against the patched running-container code — 25 passed.
  • Covers completed empty output, whitespace, encrypted reasoning retention, unfinished responses/streams, errors, refusals and unhandled calls/items; existing agent completion and Gemini history regression coverage retained.
  • Ruff formatting/lint and git diff --check passed.

Tests use mocked responses; no live model requests or group messages were sent.

Copilot AI lite review requested due to automatic review settings September 24, 2026 08:49

@sourcery-ai sourcery-ai 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Two moderate issues remain in empty-response parsing.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

This PR treats normally completed empty OpenAI responses as successful without retries, fallback, or empty assistant history entries.

Changes:

  • Accept empty stop completions without raw tool calls.
  • Preserve metadata, hooks, and tool history.
  • Add streaming and agent regression coverage.
File Summary
tests/​test_tool_loop_agent_runner.py Tests completion, retry, fallback, hooks, and history behavior.
tests/​test_openai_source.py Tests empty and streamed OpenAI response handling.
astrbot/​core/​provider/​sources/​openai_source.py Handles successful empty completions. Two moderate findings remain: legacy function_call handling and empty reasoning normalization.
astrbot/​core/​agent/​runners/​tool_loop_agent_runner.py Finalizes empty turns without invalid assistant history entries.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread astrbot/core/provider/sources/openai_source.py Outdated
Comment thread astrbot/core/provider/sources/openai_source.py

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues were identified.

Review effort: Lite
Findings: None

Resolved since last review (2)

@PeiPei233

Copy link
Copy Markdown
Contributor Author

@sourcery-ai review

@sourcery-ai sourcery-ai 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@PeiPei233 PeiPei233 changed the title fix: accept normally completed empty OpenAI responses fix: handle empty OpenAI completions and Gemini history parts Sep 26, 2026
@PeiPei233

Copy link
Copy Markdown
Contributor Author

@sourcery-ai review

@sourcery-ai sourcery-ai 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

This branch has not been deployed

No deployments
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.

2 participants