fix: force Agent mode in Cursor protobuf when User-Agent contains Claude Code (closes #643) (#692)

This commit is contained in:
Anurag Saxena
2026-04-21 23:24:58 -04:00
committed by GitHub
parent 95841f9a48
commit 37f7e97348
3 changed files with 13 additions and 8 deletions

View File

@@ -132,7 +132,10 @@ export class CursorExecutor extends BaseExecutor {
const messages = body.messages || []; const messages = body.messages || [];
const tools = body.tools || []; const tools = body.tools || [];
const reasoningEffort = body.reasoning_effort || null; const reasoningEffort = body.reasoning_effort || null;
return generateCursorBody(messages, model, tools, reasoningEffort); // Detect Claude Code UA to force Agent mode (issue #643)
const ua = credentials?.rawHeaders?.["user-agent"] || "";
const forceAgentMode = ua.includes("claude-cli") || ua.includes("claude-code") || ua.includes("Claude Code");
return generateCursorBody(messages, model, tools, reasoningEffort, forceAgentMode);
} }
async makeFetchRequest(url, headers, body, signal, proxyOptions = null) { async makeFetchRequest(url, headers, body, signal, proxyOptions = null) {

View File

@@ -169,8 +169,10 @@ function convertMessages(messages) {
export function buildCursorRequest(model, body, stream, credentials) { export function buildCursorRequest(model, body, stream, credentials) {
const messages = convertMessages(body.messages || []); const messages = convertMessages(body.messages || []);
// Strip fields irrelevant to Cursor (OpenAI/Anthropic-specific) // Strip fields irrelevant to Cursor (OpenAI/Anthropic-specific)
const { user, metadata, tool_choice, stream_options, system, ...rest } = body; const { user, metadata, tool_choice, stream_options, system, ...rest } = body;
return { return {
...rest, ...rest,
messages, messages,

View File

@@ -447,9 +447,9 @@ export function encodeMcpTool(tool) {
// ==================== REQUEST BUILDING ==================== // ==================== REQUEST BUILDING ====================
export function encodeRequest(messages, modelName, tools = [], reasoningEffort = null) { export function encodeRequest(messages, modelName, tools = [], reasoningEffort = null, forceAgentMode = false) {
const hasTools = tools?.length > 0; const hasTools = tools?.length > 0;
const isAgentic = hasTools; const isAgentic = hasTools || forceAgentMode;
const formattedMessages = []; const formattedMessages = [];
const messageIds = []; const messageIds = [];
const normalizedMessages = []; const normalizedMessages = [];
@@ -583,8 +583,8 @@ export function encodeRequest(messages, modelName, tools = [], reasoningEffort =
); );
} }
export function buildChatRequest(messages, modelName, tools = [], reasoningEffort = null) { export function buildChatRequest(messages, modelName, tools = [], reasoningEffort = null, forceAgentMode = false) {
return encodeField(FIELD.REQUEST, WIRE_TYPE.LEN, encodeRequest(messages, modelName, tools, reasoningEffort)); return encodeField(FIELD.REQUEST, WIRE_TYPE.LEN, encodeRequest(messages, modelName, tools, reasoningEffort, forceAgentMode));
} }
/** /**
@@ -646,10 +646,10 @@ export function wrapConnectRPCFrame(payload, compress = false) {
return frame; return frame;
} }
export function generateCursorBody(messages, modelName, tools = [], reasoningEffort = null) { export function generateCursorBody(messages, modelName, tools = [], reasoningEffort = null, forceAgentMode = false) {
log("BODY", `Generating: ${messages.length} msgs, model=${modelName}, tools=${tools.length}, reasoning=${reasoningEffort || "none"}`); log("BODY", `Generating: ${messages.length} msgs, model=${modelName}, tools=${tools.length}, reasoning=${reasoningEffort || "none"}, forceAgentMode=${forceAgentMode}`);
const protobuf = buildChatRequest(messages, modelName, tools, reasoningEffort); const protobuf = buildChatRequest(messages, modelName, tools, reasoningEffort, forceAgentMode);
const framed = wrapConnectRPCFrame(protobuf, false); // Cursor doesn't support compressed requests const framed = wrapConnectRPCFrame(protobuf, false); // Cursor doesn't support compressed requests
log("BODY", `Protobuf=${protobuf.length}B, Framed=${framed.length}B`); log("BODY", `Protobuf=${protobuf.length}B, Framed=${framed.length}B`);