Repository navigation
fix(deepseek-web): bind native DSML tool calls to the request nonce (policy change — please review) - #15448
Merged
diegosouzapw merged 11 commits intoOct 10, 2026
Conversation
Removes src/shared/contracts/openai.ts and its test — the module was never imported by any route/handler (verified via grep across open-sse/, src/, tests/), so it added maintenance surface with zero runtime effect. Fixes the two OPENAI_COMPATIBILITY.md doc-links that pointed at the removed test file to point at existing coverage instead (chat-completions-route-shape-gate.test.ts, audio-transcription-handler.test.ts, audio-speech-handler.test.ts). Also drops the src/app/api/v1/batches/route.ts sanitizeErrorMessage() hunk from this PR: it duplicates the same Hard Rule diegosouzapw#12 fix already proposed standalone in diegosouzapw#14115 and diegosouzapw#14145, so it is left for whichever of those lands first rather than triple-implemented here. The real fix in this PR — DSML tool-call normalization for DeepSeek-shaped web providers in webTools.ts/deepseekWebTools.ts — is unaffected and remains the mergeable core. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…ratchet
Fixes a real regression this PR's own DSML changes introduced against the
pre-existing tests/unit/deepseek-web-tools-salvage-leading-json.test.ts
suite: parseFullWidthDsmlCalls() treated the mere presence of a stray/
corrupted "||DSML||" delimiter fragment (e.g. trailing garbage after an
otherwise well-formed <tool>{json} block with no actual <invoke name="...">
tag) as "recognized", short-circuiting parseDeepSeekToolCalls() before the
canonical tag parser's JSON-salvage fallback ever ran. It now only reports
recognized:true when a structurally well-formed invoke tag was found
(matching the "malformed or unknown native markers remain content"
contract for genuinely well-formed-but-unresolvable invokes).
Also splits the new parseNativeDeepSeekCalls/parseFullWidthDsmlCalls
functions (deepseekWebTools.ts) and resolveImageBaseUrl (imageGeneration.ts)
into smaller helpers to clear the complexity/cognitive-complexity ratchet
this PR's diff newly crossed (verified via
scripts/check/check-complexity-ratchets.mjs --base-ref
origin/release/v3.8.51, now 0/0 new violations) — no behavior change beyond
the recognized-flag fix above.
Corrects the changelog fragment: it used the wrong format for
check:changelog-integrity (prose + "Closes #N" lines instead of a "- "
bullet) and, per review, overclaimed a "canonical contract" this PR does
not ship — rewritten to describe only what is actually wired.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
arashashrafii
marked this pull request as ready for review
October 3, 2026 20:56
diegosouzapw#14103 landed on the base as a squash; the 7 inherited commits now merge to the base content, leaving only this PR's own commit as the delta. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…inding comments hasMalformedDeepSeekToolMarkup required whitespace after the DSML marker, so an unbound <|DSML|invoke ...> reply yielded no calls and no repair signal and leaked as a 200 text reply. Accept \s*. Comments now state the real policy: single-pipe/full-width DSML is nonce-bound and schema-checked, the double-pipe dialect and the canonical <tool> envelope keep the shared diegosouzapw#9343 behavior (no schema validation there). Adds the changelog fragment for the 200 -> 502 contract change. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…dule deepseekWebTools.ts crossed the 1200-line cap for unfrozen files and deepseek-web.ts grew past its frozen size. Move nonce binding, schema validation and the malformed-envelope detectors to deepseekWebToolBinding.ts (re-exported), and share one 502 helper in the executor's repair branch. No behavior change. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw
merged commit Oct 10, 2026
f3a25e8
into
diegosouzapw:release/v3.8.52
28 of 51 checks passed
Owner
|
Thanks @arashashrafii — this is in the upcoming release. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this proposes
Native DeepSeek DSML replies (
<||DSML|| invoke>,<|DSML|invoke>, the WMAdapter▁-token form)were trusted on shape alone: any well-formed
<invoke>became a tool call, with no check that_noncematched the request binding, orA copied or hallucinated envelope therefore executed. The canonical
<tool>{json}</tool>path has hadboth checks since #9343; the DSML path had neither.
What it changes
finalizeParsedToolCallsfinalizeBoundCalls_nonce; upstream's nameless<tool><parameter>shape (no JSON body to bind) keeps workinghasMalformedDeepSeekToolMarkup/IntentThe policy question for review — please read before merging
Upstream explicitly documents the opposite:
This PR deliberately departs from that for DSML, on the argument that DSML bodies do carry a JSON
payload (and, in practice, a
_nonceparameter), so the guarantee the canonical path already makesshould extend to them.
Consequences to weigh:
200 + raw textto502(
tests/unit/deepseek-web-tool-call-retry.test.tsis updated here to assert the new contract).bound one; a test using single-pipe DSML was moved to that dialect so it exercises the fork path
rather than upstream's parser.
|DSML|,▁-token) are parsed by this fork; upstream'sdouble-pipe parser runs first and keeps ownership of its own inputs.
If you prefer to keep the "no nonce concept" policy, close this and #14103 stands alone — the
dialect coverage there is independent of this proposal.
Verification
262/262deepseek + web-tools teststypecheck:corecleanfix/openai-compatible-web-provider-contract(feat: complete OpenAI-compatible web-provider contracts #14103); the first commit here is thatbranch's tip.