(
res: Response,
cursorReq: CursorChatRequest,
body: OpenAIChatRequest,
anthropicReq: AnthropicRequest,
log: RequestLogger,
)
| 1132 | // ==================== 非流式处理 ==================== |
| 1133 | |
| 1134 | async function handleOpenAINonStream( |
| 1135 | res: Response, |
| 1136 | cursorReq: CursorChatRequest, |
| 1137 | body: OpenAIChatRequest, |
| 1138 | anthropicReq: AnthropicRequest, |
| 1139 | log: RequestLogger, |
| 1140 | ): Promise<void> { |
| 1141 | let activeCursorReq = cursorReq; |
| 1142 | let fullText = (await sendCursorRequestFull(activeCursorReq)).text; |
| 1143 | const hasTools = (body.tools?.length ?? 0) > 0; |
| 1144 | |
| 1145 | // 日志记录在详细日志中 |
| 1146 | |
| 1147 | // ★ Thinking 提取必须在拒绝检测之前 — 否则 thinking 内容中的关键词会触发 isRefusal 误判 |
| 1148 | const thinkingEnabled = anthropicReq.thinking?.type === 'enabled'; |
| 1149 | let reasoningContent: string | undefined; |
| 1150 | if (hasLeadingThinking(fullText)) { |
| 1151 | const { thinkingContent: extracted, strippedText } = extractThinking(fullText); |
| 1152 | if (extracted) { |
| 1153 | if (thinkingEnabled) { |
| 1154 | reasoningContent = extracted; |
| 1155 | } |
| 1156 | // thinking 剥离记录 |
| 1157 | fullText = strippedText; |
| 1158 | } |
| 1159 | } |
| 1160 | |
| 1161 | // 拒绝检测 + 自动重试(在 thinking 提取之后,只检测实际输出内容) |
| 1162 | const shouldRetry = () => isRefusal(fullText) && !(hasTools && hasToolCalls(fullText)); |
| 1163 | |
| 1164 | if (shouldRetry()) { |
| 1165 | for (let attempt = 0; attempt < MAX_REFUSAL_RETRIES; attempt++) { |
| 1166 | // 重试记录 |
| 1167 | const retryBody = buildRetryRequest(anthropicReq, attempt); |
| 1168 | const retryCursorReq = await convertToCursorRequest(retryBody); |
| 1169 | activeCursorReq = retryCursorReq; |
| 1170 | fullText = (await sendCursorRequestFull(activeCursorReq)).text; |
| 1171 | // 重试响应也需要先剥离 thinking |
| 1172 | if (hasLeadingThinking(fullText)) { |
| 1173 | fullText = extractThinking(fullText).strippedText; |
| 1174 | } |
| 1175 | if (!shouldRetry()) break; |
| 1176 | } |
| 1177 | if (shouldRetry()) { |
| 1178 | if (hasTools) { |
| 1179 | // 记录在详细日志 |
| 1180 | fullText = 'I understand the request. Let me analyze the information and proceed with the appropriate action.'; |
| 1181 | } else if (isToolCapabilityQuestion(anthropicReq)) { |
| 1182 | // 记录在详细日志 |
| 1183 | fullText = CLAUDE_TOOLS_RESPONSE; |
| 1184 | } else { |
| 1185 | // 记录在详细日志 |
| 1186 | fullText = CLAUDE_IDENTITY_RESPONSE; |
| 1187 | } |
| 1188 | } |
| 1189 | } |
| 1190 | |
| 1191 | if (hasTools) { |
no test coverage detected