openclaw - ✅(Solved) Fix Thinking-only LLM responses silently dropped (kimi-k2.5-thinking) [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#64570Fetched 2026-04-11 06:14:22
View on GitHub
Comments
1
Participants
2
Timeline
9
Reactions
0
Timeline (top)
referenced ×6cross-referenced ×2commented ×1

Error Message

  1. resolveIncompleteTurnPayloadText — only triggers on stopReason: "toolUse" | "error", misses stopReason: "stop" with empty assistant text

Root Cause

Two detection gates in src/agents/pi-embedded-runner/run/incomplete-turn.ts fail to catch this:

  1. resolveIncompleteTurnPayloadText — only triggers on stopReason: "toolUse" | "error", misses stopReason: "stop" with empty assistant text
  2. resolvePlanningOnlyRetryInstruction — only applies to openai/gpt-5 models

Fix Action

Fixed

PR fix notes

PR #64576: fix(agents): surface incomplete embedded Pi turn when stop leaves no visible reply

Description (problem / solution / changelog)

Summary

  • Problem: When the model finishes with stop or end_turn but there are no user-visible payloads (for example thinking-only content while reasoning is not shown), resolveIncompleteTurnPayloadText returned null and the run completed with no reply.
  • Why it matters: The user sees nothing and the message is effectively dropped (#64570).
  • What changed: Treat normal completion stop reasons with zero payloads like other incomplete turns, except when a reply was already sent via the messaging tool (same idea as the planning-only guard). Added unit coverage for stop, end_turn, messaging suppression, and other stop reasons.
  • Also in this PR (to keep pnpm check green): Codex dynamic-tool bridge now calls optional prepareArguments via a narrow cast; Discord model-picker test removes a redundant String() wrapper flagged by oxlint.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #64570
  • Related #64570
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: resolveIncompleteTurnPayloadText only treated toolUse-terminated empty turns or error as incomplete, not successful stop / end_turn with empty visible output.
  • Missing detection / guardrail: No branch for “finished cleanly” with zero outbound payloads.
  • Contributing context (if known): Thinking blocks are excluded from visible text unless reasoning is enabled; some models can return only thinking with a normal stop reason.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/pi-embedded-runner/run.incomplete-turn.test.ts
  • Scenario the test should lock in: resolveIncompleteTurnPayloadText returns the user-visible incomplete message for stop / end_turn with zero payloads; returns null when didSendViaMessagingTool and for maxTokens with empty payloads.
  • Why this is the smallest reliable guardrail: Exercises the resolver directly without a full embedded run harness.
  • Existing test that already covers this (if any): Partially covered via toolUse incomplete path; this adds the normal-stop path.
  • If no new test is added, why not: N/A — tests added.

User-visible / Behavior Changes

Users now see the standard incomplete-turn error string instead of silence when the model stops with no visible reply under the conditions above.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • New network endpoints or trust boundaries? No

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/codex/src/app-server/dynamic-tools.test.ts (modified, +27/-0)
  • extensions/codex/src/app-server/dynamic-tools.ts (modified, +10/-1)
  • extensions/discord/src/monitor/native-command.model-picker.test.ts (modified, +1/-1)
  • src/agents/pi-embedded-runner/run.incomplete-turn.test.ts (modified, +82/-0)
  • src/agents/pi-embedded-runner/run/incomplete-turn.ts (modified, +9/-1)

PR #64589: fix(agents): incomplete turn + Codex prepareArguments (#64570)

Description (problem / solution / changelog)

Summary

Single-commit replacement for #64576 (reviewer-friendly).

Changes

  • Embedded runner: Treat stop/end_turn with zero visible payloads as an incomplete-turn candidate when appropriate, but suppress the false error when message(send) ran and every non-empty assistant segment is silent-only (NO_REPLY / isSilentReplyPayloadText), matching payload stripping.
  • Codex dynamic tools: Fail closed if prepareArguments is present but not a function; call with tool as this.

Issue

Fixes #64570

Supersedes

Closes the review thread from #64576.

Made with Cursor

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/codex/src/app-server/dynamic-tools.test.ts (modified, +29/-0)
  • extensions/codex/src/app-server/dynamic-tools.ts (modified, +14/-2)
  • src/agents/pi-embedded-runner/run.incomplete-turn.test.ts (modified, +71/-0)
  • src/agents/pi-embedded-runner/run/incomplete-turn.ts (modified, +39/-1)
RAW_BUFFERClick to expand / collapse

Problem

When kimi-k2.5-thinking (or potentially other thinking models) returns a response containing only thinking content with stopReason: "stop", the agent treats this as a successful completion with 0 payloads — no text, no tool calls, no retry. The user's message gets silently dropped.

Root Cause

Two detection gates in src/agents/pi-embedded-runner/run/incomplete-turn.ts fail to catch this:

  1. resolveIncompleteTurnPayloadText — only triggers on stopReason: "toolUse" | "error", misses stopReason: "stop" with empty assistant text
  2. resolvePlanningOnlyRetryInstruction — only applies to openai/gpt-5 models

Proposed Fix

Extend resolveIncompleteTurnPayloadText to detect stopReason: "stop" with 0 assistant text blocks AND 0 tool calls. Extend resolvePlanningOnlyRetryInstruction to cover all thinking models.

Impact

Any user message triggering a thinking-only response is silently lost. Particularly likely on high-context sessions.

Related

  • #724

extent analysis

TL;DR

Extend the resolveIncompleteTurnPayloadText and resolvePlanningOnlyRetryInstruction functions to handle stopReason: "stop" with empty responses from thinking models like kimi-k2.5-thinking.

Guidance

  • Review the src/agents/pi-embedded-runner/run/incomplete-turn.ts file to understand the current implementation of resolveIncompleteTurnPayloadText and resolvePlanningOnlyRetryInstruction.
  • Modify resolveIncompleteTurnPayloadText to trigger on stopReason: "stop" when there are 0 assistant text blocks and 0 tool calls.
  • Update resolvePlanningOnlyRetryInstruction to apply to all thinking models, not just openai/gpt-5.
  • Test the changes with different thinking models and edge cases to ensure the fix works as expected.

Example

// Example of how resolveIncompleteTurnPayloadText could be extended
function resolveIncompleteTurnPayloadText(turn) {
  if (turn.stopReason === "stop" && turn.assistant.text_blocks.length === 0 && turn.tool_calls.length === 0) {
    // Handle the case where stopReason is "stop" with empty response
  }
  // Existing logic for other stopReason cases
}

Notes

The proposed fix assumes that the issue is solely due to the two detection gates missing the stopReason: "stop" case. Additional testing and verification may be necessary to ensure the fix works correctly in all scenarios.

Recommendation

Apply the workaround by extending the resolveIncompleteTurnPayloadText and resolvePlanningOnlyRetryInstruction functions as described, to prevent user messages from being silently dropped when a thinking model returns an empty response.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Thinking-only LLM responses silently dropped (kimi-k2.5-thinking) [2 pull requests, 1 comments, 2 participants]