Skip to content

fix(llm)!: preserve complete messages and final usage - #390

Merged
WH-2099 merged 7 commits into
mainfrom
fix/preserve-opaque-invocations
Oct 28, 2026
Merged

WH-2099 merged 7 commits into
mainfrom
fix/preserve-opaque-invocations

Conversation

@WH-2099

@WH-2099 WH-2099 commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Blocking model invocations lose provider replay state and content blocks, and streaming collectors can overwrite earlier tool calls or count cumulative usage more than once.
Preserve complete assistant messages through ordinary and structured output invocations, append complete tool calls in order, and retain the final non-None usage snapshot.
Agent usage totals copy the first response before adding later responses so saved per-response usage remains intact.

Closes #389.

Compatibility

This targets SDK 0.11.0 (unreleased).
Providers must assemble each complete tool call before emitting it exactly once, either in separate batches or a final list.
IDs must be nonempty and unique within a response; invalid batches fail before changing the collected result.
Arguments retain their original string representation.
Usage updates are cumulative snapshots for one response, while Agent totals add across responses.

Blocking content can be an ordered list of content blocks.
Display consumers should use message.get_text_content(), and Agent loops should preserve the complete message, including falsy opaque_body values.

The coordinated upgrade includes daemon #828, provider and Agent changes #4034, OpenAI and endpoint #4035, and Dify #44502.
Its Graphon candidate is published for reproducible dependency installation.
Final release versions and minimum Dify versions still need to be selected together.

Validation

  • just test: 1,650 passed.
  • just check, just build, and git diff --check passed.
  • Regressions cover both invocation modes, ordered content, falsy replay state, multiple batches of complete calls, exact argument strings, invalid IDs, final zero usage, and immutable per-response usage.
  • Eight controlled Vertex/OpenAI cases exercised provider clients, Graphon, Dify backwards invocation and serialization, real SDK Session HTTP transport, and Function Calling/Self Refine in both modes.
    Each executed both tools once, retained replay data, and reported 131 tokens for responses of 120 and 11 tokens.

Vendor HTTP and daemon HTTP were controlled test endpoints.
Live vendor signature acceptance and production deployment remain untested.

Pull Request Checklist

Compatibility Check

  • Documented the coordinated breaking change and SDK version in README.md.
  • Updated affected official providers and Agent consumers in the linked changes.
  • Select and publish the coordinated release versions before production rollout.

Available Checks

  • just build passed.
  • Relevant documentation was updated.

@WH-2099
WH-2099 force-pushed the fix/preserve-opaque-invocations branch from 5d5799e to 1447e0a Compare October 12, 2026 17:38
@WH-2099 WH-2099 changed the title fix(llm): preserve replay state and agent output budgets fix(llm): preserve replay state in blocking invocations Oct 13, 2026
@WH-2099
WH-2099 marked this pull request as ready for review October 13, 2026 13:20
Copilot AI balanced review requested due to automatic review settings October 13, 2026 13:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation satisfies the documented replay-preservation requirements with focused regression coverage.

0 open findings

What changed in this PR

Preserves replay state and ordered content blocks in blocking LLM invocations.

Changes:

  • Adds shared chunk aggregation for ordinary and structured-output invocations.
  • Preserves falsy opaque snapshots, mixed content, tool calls, and usage.
  • Adds comprehensive regression coverage.
File Description
src/​dify_plugin/​entities/​model/​message.py Treats replay state and tool calls as nonempty.
src/​dify_plugin/​invocations/​model/​llm.py Adds shared replay-aware chunk merging.
src/​dify_plugin/​invocations/​model/​llm_structured_output.py Reuses shared chunk merging.
tests/​invocations/​test_llm.py Covers replay state, content ordering, and invocation isolation.

🧠 Review effort: Balanced


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

Copilot AI balanced review requested due to automatic review settings October 21, 2026 05:23
@WH-2099 WH-2099 changed the title fix(llm): preserve replay state in blocking invocations fix(llm)!: preserve replay state in blocking invocations Oct 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No blocking issues remain in the scoped SDK changes; coordinated downstream deployment remains separate.

No open issues 🎉

Review effort: Balanced

QuantumGhost
QuantumGhost previously approved these changes Oct 21, 2026
Copilot AI balanced review requested due to automatic review settings October 21, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The intentional blocking-result shape change still requires maintainer compatibility review and coordinated downstream validation.

No open issues 🎉

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 05:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

@WH-2099 WH-2099 changed the title fix(llm)!: preserve replay state in blocking invocations fix(llm)!: preserve complete messages and final usage Oct 28, 2026
@WH-2099
WH-2099 merged commit 3652576 into main Oct 28, 2026
11 of 12 checks passed
@WH-2099
WH-2099 deleted the fix/preserve-opaque-invocations branch October 28, 2026 06:48
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.

fix(llm): preserve opaque snapshots and content blocks in blocking invocation

3 participants