Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
		if err := r.Completion(c.Request.Context(), llm.CompletionRequest{
			Prompt:  prompt,
			Images:  images,
			Format:  req.Format,
			Options: opts,
		}, func(r llm.CompletionResponse) {
			res := api.ChatResponse{
				Model:      req.Model,
				CreatedAt:  time.Now().UTC(),
				Message:    api.Message{Role: "assistant", Content: r.Content},
				Done:       r.Done,
				DoneReason: r.DoneReason,
				Metrics: api.Metrics{
					PromptEvalCount:    r.PromptEvalCount,
					PromptEvalDuration: r.PromptEvalDuration,
					EvalCount:          r.EvalCount,
					EvalDuration:       r.EvalDuration,
				},
			}

			if r.Done {
				res.TotalDuration = time.Since(checkpointStart)
				res.LoadDuration = checkpointLoaded.Sub(checkpointStart)
			}

			// Always return if not streaming - handling logic is outside
			if req.Stream != nil && !*req.Stream {
				res.Message.Content = r.Content
				ch <- res
				return
			}

			if len(req.Tools) > 0 {
				sb.WriteString(r.Content)
				if toolCalls, ok := m.parseToolCalls(sb.String()); ok {
					slog.Info("found tool call!")
					res.Message.ToolCalls = toolCalls
					res.Message.Content = ""
					sb.Reset()
					flushContent = true
				}
			}

			// Send response in three cases:
			// 1. Tool calls were found and parsed
			// 2. Regular streaming (no tools involved)
			// 3. Final response for tool requests
			shouldSend := len(req.Tools) > 0 && res.Message.ToolCalls != nil || // Tool calls found
				len(req.Tools) == 0 || // Regular streaming
				r.Done


Review comment (suggestion):
```suggestion
			// If not streaming, skip tool checks
```

Code after:
			Images:  images,
			Format:  req.Format,
			Options: opts,
		}, func(r llm.CompletionResponse) {
			res := api.ChatResponse{
				Model:      req.Model,
				CreatedAt:  time.Now().UTC(),
				Message:    api.Message{Role: "assistant", Content: r.Content},
				Done:       r.Done,
				DoneReason: r.DoneReason,
				Metrics: api.Metrics{
					PromptEvalCount:    r.PromptEvalCount,
					PromptEvalDuration: r.PromptEvalDuration,
					EvalCount:          r.EvalCount,
					EvalDuration:       r.EvalDuration,
				},
			}

			if r.Done {
				res.TotalDuration = time.Since(checkpointStart)
				res.LoadDuration = checkpointLoaded.Sub(checkpointStart)
			}

			// TODO: tool call checking and filtering should be moved outside of this callback once streaming
			// however this was a simple change for now without reworking streaming logic of this (and other)
			// handlers
			if req.Stream != nil && !*req.Stream || len(req.Tools) == 0 {
				ch <- res
				return
			}

			// Streaming tool calls:
			// If tools are recognized, use a flag to track the sending of a tool downstream
			// This ensures that content is cleared from the message on the last chunk sent
			sb.WriteString(r.Content)
			if toolCalls, ok := m.parseToolCalls(sb.String()); ok {
				res.Message.ToolCalls = toolCalls
				res.Message.Content = ""
				sb.Reset()
				hasToolCalls = true
				ch <- res
				return
			}

			if r.Done {
				// Send any remaining content if no tool calls were detected
				if !hasToolCalls {
					res.Message.Content = sb.String()
				}
				ch <- res
			}