Repository: google/adk-go
File: internal/llminternal/contents_processor.go (Go)

Code before:
	req.Contents = append(req.Contents, contents...)
	return nil
}

// buildContentsDefault returns the contents for the LLM request by applying
// filtering, rearrangement, and content processing to the given events.
func buildContentsDefault(agentName, invocationBranch string, events []*session.Event) ([]*genai.Content, error) {
	// parse the events, leaving the contents and the function calls and responses from the current agent.
	var filtered []*session.Event
	for _, ev := range events {
		content := utils.Content(ev)
		// Skip events without content or generated neither by user nor
		// by model.
		// e.g. events purely for mutating session states.
		if content == nil || content.Role == "" || len(content.Parts) == 0 {
			// TODO: log a bad event with content but no Role is skipped
			// Note: python checks here if content.Parts[0] is an empty string and skip if so.
			// But unlike python that distinguishes None vs empty string, two cases are indistinguishable in Go.
			continue
		}
		// Skip events that do not belong to the current branch.
		// TODO: can we use a richier type for branch (e.g. []string) instead of using string prefix test?
		// We use dot to delimit branch nodes. To avoid simple prefix match
		// (e.g. agent_0 unexpectedly matching agent_00), require either perfect branch
		// match, or match prefix with an additional explicit '.'
		if invocationBranch != "" && (ev.Branch != invocationBranch && !strings.HasPrefix(invocationBranch, ev.Branch+".")) {
			continue
		}
		if isAuthEvent(ev) {
			continue
		}
		if isOtherAgentReply(agentName, ev) {
			filtered = append(filtered, ConvertForeignEvent(ev))
		} else {
			filtered = append(filtered, ev)
		}
	}

	//  src/google/adk/flows/llm_flows/contents.py
	// 	 - _rearrange_events_for_async_function_response
	filtered, err := rearrangeEventsForLatestFunctionResponse(filtered)
	if err != nil {
		return nil, err
	}
	//   - _rearrange_events_for_async_function_responses_in_history
	filtered, err = rearrangeEventsForFunctionResponsesInHistory(filtered)
	if err != nil {
		return nil, err
	}

	var contents []*genai.Content

Review comment (refactor):
WDYT if we move the condition out to a func to simplify reading code?

`if !sameInvocationBranch(invocationBranch, ev.Branch) {`

Code after:
	req.Contents = append(req.Contents, contents...)
	return nil
}

// buildContentsDefault returns the contents for the LLM request by applying
// filtering, rearrangement, and content processing to the given events.
func buildContentsDefault(agentName, invocationBranch string, events []*session.Event) ([]*genai.Content, error) {
	// parse the events, leaving the contents and the function calls and responses from the current agent.
	var filtered []*session.Event
	for _, ev := range events {
		content := utils.Content(ev)
		// Skip events without content or generated neither by user nor
		// by model.
		// e.g. events purely for mutating session states.
		if content == nil || content.Role == "" || len(content.Parts) == 0 {
			// TODO: log a bad event with content but no Role is skipped
			// Note: python checks here if content.Parts[0] is an empty string and skip if so.
			// But unlike python that distinguishes None vs empty string, two cases are indistinguishable in Go.
			continue
		}
		// Skip events that do not belong to the current branch.
		// TODO: can we use a richier type for branch (e.g. []string) instead of using string prefix test?
		if !eventBelongsToBranch(invocationBranch, ev) {
			continue
		}
		if isAuthEvent(ev) {
			continue
		}
		if isOtherAgentReply(agentName, ev) {
			filtered = append(filtered, ConvertForeignEvent(ev))
		} else {
			filtered = append(filtered, ev)
		}
	}

	//  src/google/adk/flows/llm_flows/contents.py
	// 	 - _rearrange_events_for_async_function_response
	filtered, err := rearrangeEventsForLatestFunctionResponse(filtered)
	if err != nil {
		return nil, err
	}
	//   - _rearrange_events_for_async_function_responses_in_history
	filtered, err = rearrangeEventsForFunctionResponsesInHistory(filtered)
	if err != nil {
		return nil, err
	}

	var contents []*genai.Content
	for _, ev := range filtered {
		content := clone(utils.Content(ev))
		if content == nil {