From 45e265c69c9a0e888d0daf252837ca555937896c Mon Sep 17 00:00:00 2001 From: code2gold Date: Wed, 11 Feb 2026 15:31:56 +0900 Subject: [PATCH] fix: generate UUID for request confirmation events generateRequestConfirmationEvent() creates Event structs without setting the ID field, resulting in empty string IDs. When persisted to a database with a composite primary key that includes ID, the second confirmation event causes a duplicate key violation. Set ID via uuid.NewString() to match session.NewEvent() behavior. --- internal/llminternal/base_flow_test.go | 45 ++++++++++++++++++++++++++ internal/llminternal/functions.go | 2 ++ 2 files changed, 47 insertions(+) diff --git a/internal/llminternal/base_flow_test.go b/internal/llminternal/base_flow_test.go index 9a8f2ec64..787d71167 100644 --- a/internal/llminternal/base_flow_test.go +++ b/internal/llminternal/base_flow_test.go @@ -21,11 +21,13 @@ import ( "github.com/google/go-cmp/cmp" "google.golang.org/genai" + "google.golang.org/adk/agent" icontext "google.golang.org/adk/internal/context" "google.golang.org/adk/internal/toolinternal" "google.golang.org/adk/model" "google.golang.org/adk/session" "google.golang.org/adk/tool" + "google.golang.org/adk/tool/toolconfirmation" ) type mockFunctionTool struct { @@ -403,6 +405,49 @@ func TestCallTool(t *testing.T) { } } +func TestGenerateRequestConfirmationEvent_SetsEventID(t *testing.T) { + agnt, err := agent.New(agent.Config{Name: "testAgent"}) + if err != nil { + t.Fatalf("failed to create agent: %v", err) + } + ctx := icontext.NewInvocationContext(t.Context(), icontext.InvocationContextParams{Agent: agnt}) + + functionCallEvent := &session.Event{ + LLMResponse: model.LLMResponse{ + Content: &genai.Content{ + Parts: []*genai.Part{ + {FunctionCall: &genai.FunctionCall{Name: "my_tool", ID: "fc-1", Args: map[string]any{"k": "v"}}}, + }, + }, + }, + } + + functionResponseEvent := &session.Event{ + Actions: session.EventActions{ + RequestedToolConfirmations: map[string]toolconfirmation.ToolConfirmation{ + "fc-1": {Hint: "confirm?"}, + }, + }, + } + + event := generateRequestConfirmationEvent(ctx, functionCallEvent, functionResponseEvent) + if event == nil { + t.Fatal("expected non-nil event") + } + if event.ID == "" { + t.Error("expected event ID to be set, got empty string") + } + + // Verify uniqueness: calling again should produce a different ID. + event2 := generateRequestConfirmationEvent(ctx, functionCallEvent, functionResponseEvent) + if event2 == nil { + t.Fatal("expected non-nil second event") + } + if event.ID == event2.ID { + t.Errorf("expected unique IDs, got same ID %q twice", event.ID) + } +} + func TestMergeEventActions(t *testing.T) { tests := []struct { name string diff --git a/internal/llminternal/functions.go b/internal/llminternal/functions.go index 4eaaedceb..2ec50e1ed 100644 --- a/internal/llminternal/functions.go +++ b/internal/llminternal/functions.go @@ -17,6 +17,7 @@ package llminternal import ( "time" + "github.com/google/uuid" "google.golang.org/genai" "google.golang.org/adk/agent" @@ -84,6 +85,7 @@ func generateRequestConfirmationEvent( utils.PopulateClientFunctionCallID(content) return &session.Event{ + ID: uuid.NewString(), InvocationID: invocationContext.InvocationID(), Author: invocationContext.Agent().Name(), Branch: invocationContext.Branch(),