Fix double-pipe DSML variant and promote on Responses API.

Parse <||DSML||> markup, add DSML recovery to openai_responses transport, and avoid persisting raw DSML as plain assistant text when promotion fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-27 16:42:29 +08:00
parent 43f6a792eb
commit c31e6ad4b7
5 changed files with 118 additions and 38 deletions

View file

@ -18,8 +18,8 @@ from svc.llm.transports.base import (
)
from runtime.dsml_tool_parse import (
DeepSeekTextFilter,
dsml_text_tools_enabled,
try_parse_dsml_tool_calls_from_fields,
promote_dsml_tool_calls_in_response,
should_recover_dsml_tool_calls,
)
from svc.persistence.assistant_store import get_assistant_store
@ -461,13 +461,11 @@ def _should_recover_dsml_tool_calls(
*,
thinking_mode_enabled: bool = False,
) -> bool:
if dsml_text_tools_enabled(base_url=str(base_url or ""), model_id=str(model or "")):
return True
if thinking_mode_enabled:
mid = str(model or "").strip().lower()
if mid.startswith("deepseek-") or "deepseek" in mid:
return True
return False
return should_recover_dsml_tool_calls(
model_id=str(model or ""),
base_url=str(base_url or ""),
thinking_mode_enabled=thinking_mode_enabled,
)
def _promote_dsml_in_llm_response(
@ -475,15 +473,7 @@ def _promote_dsml_in_llm_response(
reasoning: str,
tool_calls: list[LLMToolCall],
) -> tuple[str, str, list[LLMToolCall]]:
if tool_calls:
return content, reasoning, tool_calls
parsed, clean_content, clean_reasoning = try_parse_dsml_tool_calls_from_fields(
content=content,
reasoning_content=reasoning,
)
if parsed is not None:
return clean_content, clean_reasoning, parsed
return content, reasoning, tool_calls
return promote_dsml_tool_calls_in_response(content, reasoning, tool_calls)
class OpenAIChatModel(ChatModel):

View file

@ -9,6 +9,7 @@ from typing import Any, Optional
from collections.abc import Callable, Iterable
from svc.llm.transports.base import ChatModel, LLMResponse, LLMToolCall, normalize_image_b64_payload
from runtime.dsml_tool_parse import promote_dsml_tool_calls_in_response, should_recover_dsml_tool_calls
logger = logging.getLogger(__name__)
@ -340,6 +341,18 @@ class OpenAIResponsesModel(ChatModel):
kw["base_url"] = self.base_url
self._client = OpenAI(**kw)
def _finalize_response(self, content: str, tool_calls: list[LLMToolCall], reasoning: str) -> LLMResponse:
text = str(content or "")
reasoning_text = str(reasoning or "")
calls = list(tool_calls or [])
if should_recover_dsml_tool_calls(
model_id=str(self.model or ""),
base_url=str(self.base_url or ""),
thinking_mode_enabled=bool(getattr(self, "thinking_mode_enabled", False)),
):
text, reasoning_text, calls = promote_dsml_tool_calls_in_response(text, reasoning_text, calls)
return LLMResponse(content=text, tool_calls=calls, reasoning_content=reasoning_text.strip())
@staticmethod
def _strip_leading_system_messages(messages: list[dict[str, Any]]) -> tuple[str, list[dict[str, Any]]]:
"""Separate leading ``role=system`` rows for ``instructions=` (Responses API expects user-shaped ``input.messages``)."""
@ -692,7 +705,7 @@ class OpenAIResponsesModel(ChatModel):
on_token(text)
if cand_label != input_candidates[0][0]:
logger.info("openai_responses: succeeded with input variant %s", cand_label)
return LLMResponse(content=text, tool_calls=tool_calls, reasoning_content=reasoning_text)
return self._finalize_response(text, tool_calls, reasoning_text)
except Exception as exc:
emsg = str(exc)
# Fallback: provider thinking-mode replay contract.
@ -721,7 +734,7 @@ class OpenAIResponsesModel(ChatModel):
on_token(text)
if cand_label != input_candidates[0][0]:
logger.info("openai_responses: succeeded with input variant %s", cand_label)
return LLMResponse(content=text, tool_calls=tool_calls, reasoning_content=reasoning_text)
return self._finalize_response(text, tool_calls, reasoning_text)
except Exception:
pass
if _env_truthy("AIA_RESPONSES_LOG_API_ERROR_DETAIL"):
@ -759,7 +772,7 @@ class OpenAIResponsesModel(ChatModel):
on_token(text)
if cand_label != input_candidates[0][0]:
logger.info("openai_responses non-stream: succeeded with input variant %s", cand_label)
return LLMResponse(content=text, tool_calls=tool_calls, reasoning_content=reasoning_text)
return self._finalize_response(text, tool_calls, reasoning_text)
except Exception as e2:
emsg2 = str(e2)
if "reasoning_content" in emsg2 and "thinking mode" in emsg2 and "must be passed back" in emsg2:
@ -787,7 +800,7 @@ class OpenAIResponsesModel(ChatModel):
"openai_responses non-stream: succeeded with input variant %s",
cand_label,
)
return LLMResponse(content=text, tool_calls=tool_calls, reasoning_content=reasoning_text)
return self._finalize_response(text, tool_calls, reasoning_text)
except Exception:
pass
if _env_truthy("AIA_RESPONSES_LOG_API_ERROR_DETAIL"):