From 5bd179a36ed8653ce653ea80ea9a89d4f9b1a450 Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Fri, 8 May 2026 14:27:11 +0300 Subject: [PATCH 1/2] fix(cursor): remove user_info, system_reminder, and user_query tags --- .../list/cursor/cursor-sessions.provider.ts | 81 +++++++++++++++++-- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/server/modules/providers/list/cursor/cursor-sessions.provider.ts b/server/modules/providers/list/cursor/cursor-sessions.provider.ts index e276ba8c..2a5ac39a 100644 --- a/server/modules/providers/list/cursor/cursor-sessions.provider.ts +++ b/server/modules/providers/list/cursor/cursor-sessions.provider.ts @@ -25,6 +25,47 @@ type CursorMessageBlob = { content: AnyRecord; }; +function isInternalCursorText(value: unknown): boolean { + if (typeof value !== 'string') { + return false; + } + + const normalized = value.trim(); + return normalized.startsWith('') || normalized.startsWith(''); +} + +function isInternalCursorPart(part: unknown): boolean { + if (!part || typeof part !== 'object') { + return false; + } + + const record = part as AnyRecord; + const type = typeof record.type === 'string' ? record.type : ''; + if (type === 'user_info' || type === 'system_reminder') { + return true; + } + + return isInternalCursorText(record.text); +} + +function unwrapUserQueryText(value: string, role: 'user' | 'assistant'): string { + if (role !== 'user') { + return value; + } + + const normalized = value.trimStart(); + const openTag = ''; + const closeTag = ''; + if (!normalized.startsWith(openTag)) { + return value; + } + + const afterOpen = normalized.slice(openTag.length); + const closeIndex = afterOpen.lastIndexOf(closeTag); + const inner = closeIndex >= 0 ? afterOpen.slice(0, closeIndex) : afterOpen; + return inner.trim(); +} + function sanitizeCursorSessionId(sessionId: string): string { const normalized = sessionId.trim(); if (!normalized) { @@ -192,6 +233,7 @@ export class CursorSessionsProvider implements IProviderSessions { */ normalizeMessage(rawMessage: unknown, sessionId: string | null): NormalizedMessage[] { const raw = readObjectRecord(rawMessage); + console.log('Normalizing Cursor message:', raw); if (raw?.type === 'assistant' && raw.message?.content?.[0]?.text) { return [createNormalizedMessage({ kind: 'stream_delta', @@ -274,6 +316,7 @@ export class CursorSessionsProvider implements IProviderSessions { const baseId = blob.id || generateMessageId('cursor'); try { + console.log('Normalizing Cursor blob content:', content); if (!content?.role || !content?.content) { if (content?.message?.role && content?.message?.content) { if (content.message.role === 'system') { @@ -283,11 +326,24 @@ export class CursorSessionsProvider implements IProviderSessions { let text = ''; if (Array.isArray(content.message.content)) { text = content.message.content - .map((part: string | AnyRecord) => typeof part === 'string' ? part : part?.text || '') + .map((part: string | AnyRecord) => { + if (typeof part === 'string') { + if (isInternalCursorText(part)) { + return ''; + } + return unwrapUserQueryText(part, role); + } + if (isInternalCursorPart(part)) { + return ''; + } + return unwrapUserQueryText(part?.text || '', role); + }) .filter(Boolean) .join('\n'); } else if (typeof content.message.content === 'string') { - text = content.message.content; + if (!isInternalCursorText(content.message.content)) { + text = unwrapUserQueryText(content.message.content, role); + } } if (text?.trim()) { messages.push(createNormalizedMessage({ @@ -336,8 +392,15 @@ export class CursorSessionsProvider implements IProviderSessions { if (Array.isArray(content.content)) { for (let partIdx = 0; partIdx < content.content.length; partIdx++) { const part = content.content[partIdx]; + if (isInternalCursorPart(part)) { + continue; + } if (part?.type === 'text' && part?.text) { + const normalizedPartText = unwrapUserQueryText(part.text, role); + if (!normalizedPartText) { + continue; + } messages.push(createNormalizedMessage({ id: `${baseId}_${partIdx}`, sessionId, @@ -345,7 +408,7 @@ export class CursorSessionsProvider implements IProviderSessions { provider: PROVIDER, kind: 'text', role, - content: part.text, + content: normalizedPartText, sequence: blob.sequence, rowid: blob.rowid, })); @@ -376,7 +439,15 @@ export class CursorSessionsProvider implements IProviderSessions { toolUseMap.set(toolId, message); } } - } else if (typeof content.content === 'string' && content.content.trim()) { + } else if ( + typeof content.content === 'string' + && content.content.trim() + && !isInternalCursorText(content.content) + ) { + const normalizedText = unwrapUserQueryText(content.content, role); + if (!normalizedText) { + continue; + } messages.push(createNormalizedMessage({ id: baseId, sessionId, @@ -384,7 +455,7 @@ export class CursorSessionsProvider implements IProviderSessions { provider: PROVIDER, kind: 'text', role, - content: content.content, + content: normalizedText, sequence: blob.sequence, rowid: blob.rowid, })); From c9413815a437526ec161428e09f47ce5d18a6aab Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Fri, 8 May 2026 14:27:44 +0300 Subject: [PATCH 2/2] fix(cursor): attach write tool outputs correctly --- .../list/cursor/cursor-sessions.provider.ts | 142 +++++++++++++++++- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/server/modules/providers/list/cursor/cursor-sessions.provider.ts b/server/modules/providers/list/cursor/cursor-sessions.provider.ts index 2a5ac39a..8f896bb9 100644 --- a/server/modules/providers/list/cursor/cursor-sessions.provider.ts +++ b/server/modules/providers/list/cursor/cursor-sessions.provider.ts @@ -66,6 +66,126 @@ function unwrapUserQueryText(value: string, role: 'user' | 'assistant'): string return inner.trim(); } +function normalizeToolId(value: unknown): string | null { + if (typeof value !== 'string') { + return null; + } + + const normalized = value.trim(); + return normalized ? normalized : null; +} + +function extractCursorToolResultContent(item: AnyRecord): string { + if (typeof item.result === 'string' && item.result.trim()) { + return item.result; + } + + if (typeof item.output === 'string' && item.output.trim()) { + return item.output; + } + + if (Array.isArray(item.experimental_content)) { + const experimentalText = item.experimental_content + .map((part: unknown) => { + if (typeof part === 'string') { + return part; + } + if (part && typeof part === 'object') { + const record = part as AnyRecord; + if (typeof record.text === 'string') { + return record.text; + } + } + return ''; + }) + .filter(Boolean) + .join('\n'); + + if (experimentalText.trim()) { + return experimentalText; + } + } + + return typeof item.result === 'string' ? item.result : ''; +} + +function parseCursorToolInput(rawInput: unknown): unknown { + if (typeof rawInput !== 'string') { + return rawInput; + } + + const trimmed = rawInput.trim(); + if (!trimmed) { + return rawInput; + } + + try { + return JSON.parse(trimmed); + } catch { + return rawInput; + } +} + +function normalizeCursorToolInput(toolName: string, rawInput: unknown): unknown { + const parsed = parseCursorToolInput(rawInput); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + return parsed; + } + + const input = parsed as AnyRecord; + const normalized: AnyRecord = { ...input }; + + const filePath = input.file_path + ?? input.filePath + ?? input.path + ?? input.file + ?? input.filename; + if (typeof filePath === 'string' && filePath.trim()) { + normalized.file_path = filePath; + } + + if (toolName === 'Write') { + const content = input.content + ?? input.text + ?? input.value + ?? input.contents + ?? input.fileContent + ?? input.new_string + ?? input.newString; + if (typeof content === 'string') { + normalized.content = content; + } + } + + if (toolName === 'Edit') { + const oldString = input.old_string + ?? input.oldString + ?? input.old + ?? ''; + const newString = input.new_string + ?? input.newString + ?? input.new + ?? input.content + ?? ''; + + if (typeof oldString === 'string') { + normalized.old_string = oldString; + } + if (typeof newString === 'string') { + normalized.new_string = newString; + } + } + + if (toolName === 'ApplyPatch') { + const patch = input.patch ?? input.diff ?? input.content; + if (typeof patch === 'string' && !normalized.patch) { + normalized.patch = patch; + } + } + + return normalized; +} + function sanitizeCursorSessionId(sessionId: string): string { const normalized = sessionId.trim(); if (!normalized) { @@ -372,7 +492,14 @@ export class CursorSessionsProvider implements IProviderSessions { if (item?.type !== 'tool-result') { continue; } - const toolCallId = item.toolCallId || content.id; + const cursorOptions = content.providerOptions?.cursor as AnyRecord | undefined; + const highLevelToolCallResult = cursorOptions?.highLevelToolCallResult; + const toolCallId = normalizeToolId(item.toolCallId) + || normalizeToolId(item.tool_call_id) + || normalizeToolId(highLevelToolCallResult?.toolCallId) + || normalizeToolId(highLevelToolCallResult?.tool_call_id) + || normalizeToolId(content.id) + || ''; messages.push(createNormalizedMessage({ id: `${baseId}_tr`, sessionId, @@ -380,8 +507,9 @@ export class CursorSessionsProvider implements IProviderSessions { provider: PROVIDER, kind: 'tool_result', toolId: toolCallId, - content: item.result || '', - isError: false, + content: extractCursorToolResultContent(item), + isError: Boolean(item.isError || item.is_error), + toolUseResult: highLevelToolCallResult, })); } continue; @@ -424,7 +552,10 @@ export class CursorSessionsProvider implements IProviderSessions { } else if (part?.type === 'tool-call' || part?.type === 'tool_use') { const rawToolName = part.toolName || part.name || 'Unknown Tool'; const toolName = rawToolName === 'ApplyPatch' ? 'Edit' : rawToolName; - const toolId = part.toolCallId || part.id || `tool_${i}_${partIdx}`; + const toolId = normalizeToolId(part.toolCallId) + || normalizeToolId(part.tool_call_id) + || normalizeToolId(part.id) + || `tool_${i}_${partIdx}`; const message = createNormalizedMessage({ id: `${baseId}_${partIdx}`, sessionId, @@ -432,7 +563,7 @@ export class CursorSessionsProvider implements IProviderSessions { provider: PROVIDER, kind: 'tool_use', toolName, - toolInput: part.args || part.input, + toolInput: normalizeCursorToolInput(toolName, part.args ?? part.input), toolId, }); messages.push(message); @@ -472,6 +603,7 @@ export class CursorSessionsProvider implements IProviderSessions { toolUse.toolResult = { content: msg.content, isError: msg.isError, + toolUseResult: msg.toolUseResult, }; } }