fix(cursor): stop AgentService empty turns and silent tool hangs
Cursor-hosted models (cu/composer-2.5, cu/cursor-grok-*, cu/default) returned HTTP 200 with an empty turn, or hung, whenever a client sent tools. - Fold system prompts into the current user message. custom_system_prompt (RunRequest field 8) makes AgentService return an empty turn. - Send ModelDetails (field 3); thinking variants (Composer, Grok, *-thinking) return an empty turn when only requested_model (field 9) is set. - Route tool-call history and declared tool schemas through AgentService: encode OpenAI tools into mcp_tools (field 4), decode McpArgs and emit real tool_calls with finish_reason tool_calls. - Map Composer thinking / Grok thinking_delta (field 4) into visible content instead of dropping the answer with the unsigned reasoning. - Ack request_context without echoing MCP tools (double-advertise stalls the HTTP/2 stream) and ack kv_server_message so the run proceeds. - Reject IDE builtin execs instead of failing the turn, so the model can continue with MCP tools or a text answer. - Add google.protobuf.Value / MCP encoders and a FIXED64 branch to encodeField in cursorProtobuf.js. RTK now compresses the source-format body before translation for cursor only: its translator rewrites role:tool into user XML, so the post-translate pass missed those tool results. Every other provider keeps the post-translate pass unchanged.
This commit is contained in:
@@ -246,6 +246,15 @@ describe("Cursor AgentService executor helpers (cursor.js)", () => {
|
||||
const run = decodeMessage(clientMsg.get(1)[0].value);
|
||||
expect(run.has(2)).toBe(true); // action
|
||||
expect(run.has(9)).toBe(true); // requested_model
|
||||
// custom_system_prompt (field 8) makes AgentService return an empty turn.
|
||||
expect(run.has(8)).toBe(false);
|
||||
expect(run.has(3)).toBe(true); // ModelDetails — required for thinking variants
|
||||
const action = decodeMessage(run.get(2)[0].value);
|
||||
const userAction = decodeMessage(action.get(1)[0].value);
|
||||
const userMessage = decodeMessage(userAction.get(1)[0].value);
|
||||
const userText = Buffer.from(userMessage.get(1)[0].value).toString("utf8");
|
||||
expect(userText).toContain("be brief");
|
||||
expect(userText).toContain("hi");
|
||||
});
|
||||
|
||||
it("encodes mcp_tools (field 4) when tools are provided", () => {
|
||||
|
||||
Reference in New Issue
Block a user