* Responses API 非流式处理
(
res: Response,
cursorReq: CursorChatRequest,
body: Record<string, unknown>,
anthropicReq: AnthropicRequest,
log: RequestLogger,
)
| 1773 | * Responses API 非流式处理 |
| 1774 | */ |
| 1775 | async function handleResponsesNonStream( |
| 1776 | res: Response, |
| 1777 | cursorReq: CursorChatRequest, |
| 1778 | body: Record<string, unknown>, |
| 1779 | anthropicReq: AnthropicRequest, |
| 1780 | log: RequestLogger, |
| 1781 | ): Promise<void> { |
| 1782 | let activeCursorReq = cursorReq; |
| 1783 | let fullText = (await sendCursorRequestFull(activeCursorReq)).text; |
| 1784 | const hasTools = (anthropicReq.tools?.length ?? 0) > 0; |
| 1785 | |
| 1786 | // Thinking 提取 |
| 1787 | if (hasLeadingThinking(fullText)) { |
| 1788 | fullText = extractThinking(fullText).strippedText; |
| 1789 | } |
| 1790 | |
| 1791 | // 拒绝检测 + 重试 |
| 1792 | const shouldRetry = () => isRefusal(fullText) && !(hasTools && hasToolCalls(fullText)); |
| 1793 | if (shouldRetry()) { |
| 1794 | for (let attempt = 0; attempt < MAX_REFUSAL_RETRIES; attempt++) { |
| 1795 | const retryBody = buildRetryRequest(anthropicReq, attempt); |
| 1796 | const retryCursorReq = await convertToCursorRequest(retryBody); |
| 1797 | activeCursorReq = retryCursorReq; |
| 1798 | fullText = (await sendCursorRequestFull(activeCursorReq)).text; |
| 1799 | if (hasLeadingThinking(fullText)) { |
| 1800 | fullText = extractThinking(fullText).strippedText; |
| 1801 | } |
| 1802 | if (!shouldRetry()) break; |
| 1803 | } |
| 1804 | if (shouldRetry()) { |
| 1805 | if (isToolCapabilityQuestion(anthropicReq)) { |
| 1806 | fullText = CLAUDE_TOOLS_RESPONSE; |
| 1807 | } else { |
| 1808 | fullText = CLAUDE_IDENTITY_RESPONSE; |
| 1809 | } |
| 1810 | } |
| 1811 | } |
| 1812 | |
| 1813 | if (hasTools) { |
| 1814 | fullText = await autoContinueCursorToolResponseFull(activeCursorReq, fullText, hasTools); |
| 1815 | } |
| 1816 | |
| 1817 | fullText = sanitizeResponse(fullText); |
| 1818 | |
| 1819 | const respId = responsesId(); |
| 1820 | const model = (body.model as string) || 'gpt-4'; |
| 1821 | const inputTokens = estimateInputTokens(anthropicReq); |
| 1822 | const outputTokens = Math.ceil(fullText.length / 3); |
| 1823 | const usage = { input_tokens: inputTokens, output_tokens: outputTokens, total_tokens: inputTokens + outputTokens }; |
| 1824 | |
| 1825 | const output: Record<string, unknown>[] = []; |
| 1826 | let toolCallsDetected = 0; |
| 1827 | |
| 1828 | if (hasTools && hasToolCalls(fullText)) { |
| 1829 | const { toolCalls, cleanText } = parseToolCalls(fullText); |
| 1830 | toolCallsDetected = toolCalls.length; |
| 1831 | log.recordToolCalls(toolCalls); |
| 1832 | log.updateSummary({ toolCallsDetected: toolCalls.length }); |
no test coverage detected