package claude import ( "ds2api/internal/assistantturn" "ds2api/internal/toolcall" "fmt" "time" "ds2api/internal/prompt" "ds2api/internal/util" ) func BuildMessageResponseFromTurn(messageID, model string, turn assistantturn.Turn, exposeThinking bool) map[string]any { content := make([]map[string]any, 0, 4) if exposeThinking && turn.Thinking != "" { content = append(content, map[string]any{"type": "thinking", "thinking": turn.Thinking}) } stopReason := "end_turn" if len(turn.ToolCalls) > 0 { stopReason = "tool_use" for i, tc := range turn.ToolCalls { content = append(content, map[string]any{ "type": "tool_use", "id": fmt.Sprintf("toolu_%d_%d", time.Now().Unix(), i), "name": tc.Name, "input": tc.Input, }) } } else { text := turn.Text if text == "" && exposeThinking { text = turn.Thinking } if text == "" { text = "抱歉,没有生成有效的响应内容。" } content = append(content, map[string]any{"type": "text", "text": text}) } return map[string]any{ "id": messageID, "type": "message", "role": "assistant", "model": model, "content": content, "stop_reason": stopReason, "stop_sequence": nil, "usage": map[string]any{ "input_tokens": turn.Usage.InputTokens, "output_tokens": turn.Usage.OutputTokens, }, } } func BuildMessageResponse(messageID, model string, normalizedMessages []any, finalThinking, finalText string, toolNames []string) map[string]any { detected := toolcall.ParseToolCalls(finalText, toolNames) if len(detected) == 0 && finalText == "" && finalThinking != "" { detected = toolcall.ParseToolCalls(finalThinking, toolNames) } content := make([]map[string]any, 0, 4) if finalThinking != "" { content = append(content, map[string]any{"type": "thinking", "thinking": finalThinking}) } stopReason := "end_turn" if len(detected) > 0 { stopReason = "tool_use" for i, tc := range detected { content = append(content, map[string]any{ "type": "tool_use", "id": fmt.Sprintf("toolu_%d_%d", time.Now().Unix(), i), "name": tc.Name, "input": tc.Input, }) } } else { if finalText == "" { finalText = "抱歉,没有生成有效的响应内容。" } content = append(content, map[string]any{"type": "text", "text": finalText}) } return map[string]any{ "id": messageID, "type": "message", "role": "assistant", "model": model, "content": content, "stop_reason": stopReason, "stop_sequence": nil, "usage": map[string]any{ "input_tokens": util.CountPromptTokens(prompt.MessagesPrepareWithThinking(claudeMessageMaps(normalizedMessages), false), model), "output_tokens": util.CountOutputTokens(finalThinking, model) + util.CountOutputTokens(finalText, model), }, } } func claudeMessageMaps(messages []any) []map[string]any { if len(messages) == 0 { return nil } out := make([]map[string]any, 0, len(messages)) for _, item := range messages { msg, ok := item.(map[string]any) if !ok { continue } out = append(out, msg) } return out }