(req: Request, res: Response)
| 342 | // ==================== Messages API ==================== |
| 343 | |
| 344 | export async function handleMessages(req: Request, res: Response): Promise<void> { |
| 345 | const body = req.body as AnthropicRequest; |
| 346 | |
| 347 | const systemStr = typeof body.system === 'string' ? body.system : Array.isArray(body.system) ? body.system.map((b: any) => b.text || '').join('') : ''; |
| 348 | const log = createRequestLogger({ |
| 349 | method: req.method, |
| 350 | path: req.path, |
| 351 | model: body.model, |
| 352 | stream: !!body.stream, |
| 353 | hasTools: (body.tools?.length ?? 0) > 0, |
| 354 | toolCount: body.tools?.length ?? 0, |
| 355 | messageCount: body.messages?.length ?? 0, |
| 356 | apiFormat: 'anthropic', |
| 357 | systemPromptLength: systemStr.length, |
| 358 | }); |
| 359 | |
| 360 | log.startPhase('receive', '接收请求'); |
| 361 | log.recordOriginalRequest(body); |
| 362 | log.info('Handler', 'receive', `收到 Anthropic Messages 请求`, { |
| 363 | model: body.model, |
| 364 | messageCount: body.messages?.length, |
| 365 | stream: body.stream, |
| 366 | toolCount: body.tools?.length ?? 0, |
| 367 | maxTokens: body.max_tokens, |
| 368 | hasSystem: !!body.system, |
| 369 | thinking: body.thinking?.type, |
| 370 | }); |
| 371 | |
| 372 | try { |
| 373 | if (isIdentityProbe(body)) { |
| 374 | log.intercepted('身份探针拦截 → 返回模拟响应'); |
| 375 | if (body.stream) { |
| 376 | return await handleMockIdentityStream(res, body); |
| 377 | } else { |
| 378 | return await handleMockIdentityNonStream(res, body); |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | // 转换为 Cursor 请求 |
| 383 | log.startPhase('convert', '格式转换'); |
| 384 | log.info('Handler', 'convert', '开始转换为 Cursor 请求格式'); |
| 385 | // ★ 区分客户端 thinking 模式: |
| 386 | // - enabled: GUI 插件,支持渲染 thinking content block |
| 387 | // - adaptive: Claude Code,需要密码学 signature 验证,无法伪造 → 保留标签在正文中 |
| 388 | const thinkingConfig = getConfig().thinking; |
| 389 | // ★ config.yaml thinking 开关优先级最高 |
| 390 | // enabled=true: 强制注入 thinking(即使客户端没请求) |
| 391 | // enabled=false: 强制关闭 thinking |
| 392 | // 未配置: 跟随客户端请求(不自动补上) |
| 393 | if (thinkingConfig) { |
| 394 | if (!thinkingConfig.enabled) { |
| 395 | delete body.thinking; |
| 396 | } else if (!body.thinking) { |
| 397 | body.thinking = { type: 'enabled' }; |
| 398 | } |
| 399 | } |
| 400 | const clientRequestedThinking = body.thinking?.type === 'enabled'; |
| 401 | const cursorReq = await convertToCursorRequest(body); |
nothing calls this directly
no test coverage detected