fix: align agent payload semantics with VSCode tool flow

Force OpenAI tooling-context requests into agent mode and align Lingma ask payload fields for agent requests so server-side tool path matches VSCode semantics.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
GitHub Actions
2026-04-19 23:19:52 +08:00
parent e208025f35
commit c67a9c3d61
3 changed files with 9 additions and 7 deletions

View File

@@ -896,15 +896,15 @@ class LingmaGatewayClient:
is_reply: bool = False, is_reply: bool = False,
tool_config: dict[str, Any] | None = None, tool_config: dict[str, Any] | None = None,
): ):
session_type = "developer" if ask_mode == "agent" else "chat" session_type = "ask" if ask_mode == "agent" else "chat"
payload = { payload = {
"requestId": request_id, "requestId": request_id,
"sessionId": session_id, "sessionId": session_id,
"sessionType": session_type, "sessionType": session_type,
"chatTask": "FREE_INPUT", "chatTask": "chat" if ask_mode == "agent" else "FREE_INPUT",
"mode": ask_mode, "mode": ask_mode,
"stream": True, "stream": True,
"source": 1, "source": "vscode" if ask_mode == "agent" else 1,
"isReply": is_reply, "isReply": is_reply,
"taskDefinitionType": "system", "taskDefinitionType": "system",
"content": prompt, "content": prompt,

View File

@@ -504,13 +504,13 @@ async def v1_chat_completions(req: ChatCompletionsRequest, request: Request):
# 1. Reuse the upstream sessionId so Lingma/Qwen hits its KV cache. # 1. Reuse the upstream sessionId so Lingma/Qwen hits its KV cache.
# 2. Send only the new user message instead of the whole history. # 2. Send only the new user message instead of the whole history.
# 3. Stick the request to the pool instance that originally served it. # 3. Stick the request to the pool instance that originally served it.
ask_mode = settings.default_ask_mode
if req.model.lower() in {"lingma-agent", "agent"}:
ask_mode = "agent"
tool_config = _openai_tool_config(req) tool_config = _openai_tool_config(req)
has_tooling_context = _openai_has_tooling_context(req, messages_dump) has_tooling_context = _openai_has_tooling_context(req, messages_dump)
ask_mode = settings.default_ask_mode
if req.model.lower() in {"lingma-agent", "agent"} or has_tooling_context:
ask_mode = "agent"
reuse_eligible = ( reuse_eligible = (
session_cache.enabled session_cache.enabled
and ask_mode == "chat" and ask_mode == "chat"

View File

@@ -500,6 +500,7 @@ class ToolCallBridgeTests(unittest.IsolatedAsyncioTestCase):
self.assertEqual(cfg["provider"], "openai") self.assertEqual(cfg["provider"], "openai")
self.assertEqual(len(cfg["tools"]), 1) self.assertEqual(len(cfg["tools"]), 1)
self.assertIsInstance(cfg["tool_choice"], dict) self.assertIsInstance(cfg["tool_choice"], dict)
self.assertEqual(spy_client.last_complete_args[2], "agent")
async def test_openai_non_stream_does_not_forward_tool_config_when_disabled(self) -> None: async def test_openai_non_stream_does_not_forward_tool_config_when_disabled(self) -> None:
spy_client = _SpyClient(stream_events=[], complete_result={"text": "ok", "toolEvents": []}) spy_client = _SpyClient(stream_events=[], complete_result={"text": "ok", "toolEvents": []})
@@ -522,6 +523,7 @@ class ToolCallBridgeTests(unittest.IsolatedAsyncioTestCase):
self.assertIn("tool_config", spy_client.last_complete_kwargs) self.assertIn("tool_config", spy_client.last_complete_kwargs)
self.assertIsNone(spy_client.last_complete_kwargs["tool_config"]) self.assertIsNone(spy_client.last_complete_kwargs["tool_config"])
self.assertEqual(spy_client.last_complete_args[2], "agent")
async def test_openai_tooling_context_disables_session_reuse_cache(self) -> None: async def test_openai_tooling_context_disables_session_reuse_cache(self) -> None: