MCPcopy
hub / github.com/7836246/cursor2api / handleStream

Function handleStream

src/handler.ts:1143–1814  ·  view source on GitHub ↗
(res: Response, cursorReq: CursorChatRequest, body: AnthropicRequest, log: RequestLogger, clientRequestedThinking: boolean = false)

Source from the content-addressed store, hash-verified

1141// ==================== 流式处理 ====================
1142
1143async function handleStream(res: Response, cursorReq: CursorChatRequest, body: AnthropicRequest, log: RequestLogger, clientRequestedThinking: boolean = false): Promise<void> {
1144 // 设置 SSE headers
1145 res.writeHead(200, {
1146 'Content-Type': 'text/event-stream',
1147 'Cache-Control': 'no-cache',
1148 'Connection': 'keep-alive',
1149 'X-Accel-Buffering': 'no',
1150 });
1151
1152 const id = msgId();
1153 const model = body.model;
1154 const hasTools = (body.tools?.length ?? 0) > 0;
1155
1156 // 发送 message_start
1157 writeSSE(res, 'message_start', {
1158 type: 'message_start',
1159 message: {
1160 id, type: 'message', role: 'assistant', content: [],
1161 model, stop_reason: null, stop_sequence: null,
1162 usage: { input_tokens: estimateInputTokens(body), output_tokens: 0 },
1163 },
1164 });
1165
1166 // ★ 流式保活 — 注意:无工具的增量流式路径(handleDirectTextStream)有自己的 keepalive
1167 // 这里的 keepalive 仅用于工具模式下的缓冲/续写期间
1168 let keepaliveInterval: ReturnType<typeof setInterval> | undefined;
1169
1170 let fullResponse = '';
1171 let sentText = '';
1172 let blockIndex = 0;
1173 let textBlockStarted = false;
1174 let thinkingBlockEmitted = false;
1175 let cursorUsage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
1176
1177 // 无工具模式:先缓冲全部响应再检测拒绝,如果是拒绝则重试
1178 let activeCursorReq = cursorReq;
1179 let retryCount = 0;
1180
1181 const executeStream = async (detectRefusalEarly = false, onTextDelta?: (delta: string) => void): Promise<{ earlyAborted: boolean }> => {
1182 fullResponse = '';
1183 const apiStart = Date.now();
1184 let firstChunk = true;
1185 let earlyAborted = false;
1186 log.startPhase('send', '发送到 Cursor');
1187
1188 // ★ 早期中止支持:检测到拒绝后立即中断流,不等完整响应
1189 const abortController = detectRefusalEarly ? new AbortController() : undefined;
1190
1191 try {
1192 await sendCursorRequest(activeCursorReq, (event: CursorSSEEvent) => {
1193 if (event.type === 'finish') {
1194 if (event.messageMetadata?.usage) cursorUsage = event.messageMetadata.usage;
1195 return;
1196 }
1197 if (event.type !== 'text-delta' || !event.delta) return;
1198 if (firstChunk) { log.recordTTFT(); log.endPhase(); log.startPhase('response', '接收响应'); firstChunk = false; }
1199 fullResponse += event.delta;
1200 onTextDelta?.(event.delta);

Callers 1

handleMessagesFunction · 0.85

Calls 15

isRefusalFunction · 0.90
getConfigFunction · 0.90
parseToolCallsFunction · 0.90
msgIdFunction · 0.85
writeSSEFunction · 0.85
estimateInputTokensFunction · 0.85
handleDirectTextStreamFunction · 0.85
writeAnthropicTextDeltaFunction · 0.85
hasLeadingThinkingFunction · 0.85

Tested by

no test coverage detected