Skip to content

fix: preserve SDK behavior while closing runtime resources - #395

Closed
WH-2099 wants to merge 9 commits into
mainfrom
fix/sdk-contract-regressions
Closed

WH-2099 wants to merge 9 commits into
mainfrom
fix/sdk-contract-regressions

Conversation

@WH-2099

@WH-2099 WH-2099 commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

SDK calls could leave response resources open, interleave TCP frames, or leave CLI readers blocked after process exit.
This change fixes those lifecycle paths and expands regression coverage while preserving existing SDK behavior against main at 86e81e72.

Closes #394.

Changes

  • Close HTTP responses, response callbacks, provider generators, request subscriptions and process resources on completion, failure and cancellation.
  • Serialize TCP writes and reconnect safely after partial-frame cancellation, while retaining existing retry and ordinary write-error behavior.
  • Stop the launched Serverless HTTP service when its reader closes, and cancel work when its response is closed.
  • Drain CLI stderr, handle partial pipe writes and clean up failed startup, process exit and concurrent shutdown.
  • Register the existing tool runtime-parameter action and support separately declared trigger constructors while retaining provider-module precedence.
  • Support standard SSE events alongside existing response encodings, raw JSON, custom delimiters and EOF behavior.
  • Allow tool and model manifest validation to be retried after the original input would previously have been consumed; preserve nested shared-object behavior.
  • Fix missing position-file handling, numeric tool-schema enum tokenization, short-module error reporting and schema documentation traversal.

The tests cover all 37 public dispatch actions, actual local HTTP/TLS services, sockets, subprocess pipes, cancellation and an installed SDK wheel.
Dispatch assertions inspect the arguments received by plugin implementations, including credentials and user/session context.
CLI assertions cover complete request envelopes and the daemon's error format.
The test guide records upstream source revisions and fixture limitations; controlled mutations were used to check that key assertions detect incorrect behavior.

Development dependencies add pytest-httpserver, pytest-timeout, pytest-socket, Hypothesis and trustme.
TLS certificates are generated in memory, with temporary files where Python TLS APIs require paths.
The private-key check retains its default configuration.
just coverage combines parent and subprocess coverage and writes JUnit, JSON and XML reports under reports/.
Separate SDK, runtime and HTTP coverage gates remain enforced.

Compatibility

The target is main, with existing behavior pinned to 86e81e72.
Package version remains 0.11.0; runtime dependencies and the supported Python version range are unchanged.
The review checks public signatures and provider extension hooks against the baseline.

Compatibility regressions cover:

  • Blocking LLM string results, original model metadata and usage aggregation, four-argument response-handler hooks and existing error mapping.
  • Rerank min/max normalization for every batch, embedding response order, parameter acceptance, numeric boolean defaults and OAuth expiry conversion.
  • Regular-expression stop matching, structured-output processor selection and existing updates to prompts, stop lists and model parameters.
  • Shared blob metadata, repeated tool blob emission, Agent usage accumulation and YAML aliases across credential schemas.
  • Original WAV bytes and streaming, datasource/Agent blob messages, tool chunk framing and file redirect errors.
  • Stream completion, timeout and Serverless idle policies, storage acknowledgements, CLI hooks and HTTP header handling.

Existing limitations are retained deliberately.
For example, a 4 MiB datasource or Agent blob can exceed the daemon's default 5 MiB JSON line limit after base64 encoding.
Changing that transport or the model scoring policy requires a separate compatible design.

The test guide describes compatibility coverage and protocol evidence.
The regression map links behavior to its tests.

Validation

  • Python 3.12: just coverage, 1,470 passed, with no failed or skipped tests.
  • Python 3.13: 1,470 passed, with no failed or skipped tests.
  • SDK coverage: statements 96.87%, branches 93.22%.
  • Runtime coverage: statements 97.12%, branches 93.01%; HTTP coverage: statements 96.18%, branches 92.86%.
  • just check, just build, just docs, all prek hooks and git diff --check passed.
  • Independent compatibility review compared successful outputs against the baseline, including shared objects, provider overrides and existing protocol fixtures.

Tests use local services and the actual SDK wheel.
The matrix used fresh pytest temporary roots because gevent 26.9.0 can exhaust file descriptors when removing large historical temporary directories.
A running Dify deployment, the released Go CLI, external model APIs and sustained load were not tested.

Pull Request Checklist

Compatibility Check

  • I have checked whether this change affects the backward compatibility of the plugin declared in README.md
  • I have checked whether this change affects the forward compatibility of the plugin declared in README.md
  • If this change introduces a breaking change, I have discussed it with the project maintainer and specified the release version in the README.md — not applicable: existing behavior is preserved against the baseline above.
  • I have described the compatibility impact and the corresponding version number in the PR description
  • I have checked whether the plugin version is updated in the README.md

Available Checks

  • just build has passed
  • Relevant documentation has been updated (if necessary)

@WH-2099 WH-2099 self-assigned this Oct 13, 2026
@WH-2099
WH-2099 marked this pull request as ready for review October 13, 2026 15:51
@WH-2099 WH-2099 changed the title fix: restore SDK contracts and cover runtime boundaries fix: preserve SDK behavior while closing runtime resources Oct 13, 2026
@WH-2099
WH-2099 changed the base branch from fix/preserve-opaque-invocations to main October 13, 2026 19:20
@WH-2099 WH-2099 closed this Oct 13, 2026
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: resolve SDK protocol and lifecycle regressions

1 participant