(
cursorReq: CursorChatRequest,
initialText: string,
hasTools: boolean,
)
| 743 | } |
| 744 | |
| 745 | export async function autoContinueCursorToolResponseFull( |
| 746 | cursorReq: CursorChatRequest, |
| 747 | initialText: string, |
| 748 | hasTools: boolean, |
| 749 | ): Promise<string> { |
| 750 | let fullText = initialText; |
| 751 | // Keep non-stream OpenAI-compatible tool responses aligned with the stream helper: |
| 752 | // always allow at least one internal continuation for truncated tool payloads. |
| 753 | const MAX_AUTO_CONTINUE = Math.max(getConfig().maxAutoContinue, 1); |
| 754 | let continueCount = 0; |
| 755 | let consecutiveSmallAdds = 0; |
| 756 | |
| 757 | while (MAX_AUTO_CONTINUE > 0 && shouldAutoContinueTruncatedToolResponse(fullText, hasTools) && continueCount < MAX_AUTO_CONTINUE) { |
| 758 | continueCount++; |
| 759 | |
| 760 | const anchorLength = Math.min(300, fullText.length); |
| 761 | const anchorText = fullText.slice(-anchorLength); |
| 762 | const continuationPrompt = `Your previous response was cut off mid-output. The last part of your output was: |
| 763 | |
| 764 | \`\`\` |
| 765 | ...${anchorText} |
| 766 | \`\`\` |
| 767 | |
| 768 | Continue EXACTLY from where you stopped. DO NOT repeat any content already generated. DO NOT restart the response. Output ONLY the remaining content, starting immediately from the cut-off point.`; |
| 769 | |
| 770 | const assistantContext = closeUnclosedThinking( |
| 771 | fullText.length > 2000 |
| 772 | ? '...\n' + fullText.slice(-2000) |
| 773 | : fullText, |
| 774 | ); |
| 775 | |
| 776 | const continuationReq: CursorChatRequest = { |
| 777 | ...cursorReq, |
| 778 | messages: [ |
| 779 | // ★ 续写优化:丢弃所有工具定义和历史消息 |
| 780 | { |
| 781 | parts: [{ type: 'text', text: assistantContext }], |
| 782 | id: uuidv4(), |
| 783 | role: 'assistant', |
| 784 | }, |
| 785 | { |
| 786 | parts: [{ type: 'text', text: continuationPrompt }], |
| 787 | id: uuidv4(), |
| 788 | role: 'user', |
| 789 | }, |
| 790 | ], |
| 791 | }; |
| 792 | |
| 793 | const { text: continuationResponse } = await sendCursorRequestFull(continuationReq); |
| 794 | if (continuationResponse.trim().length === 0) break; |
| 795 | |
| 796 | const deduped = deduplicateContinuation(fullText, continuationResponse); |
| 797 | fullText += deduped; |
| 798 | |
| 799 | if (deduped.trim().length === 0) break; |
| 800 | if (deduped.trim().length < 100) break; |
| 801 | |
| 802 | if (deduped.trim().length < 500) { |
no test coverage detected