diff --git a/app/pkg/agent/agent.go b/app/pkg/agent/agent.go index 0614567..ce6dec5 100644 --- a/app/pkg/agent/agent.go +++ b/app/pkg/agent/agent.go @@ -244,6 +244,11 @@ func (a *Agent) StreamGenerate(ctx context.Context, stream *connect.BidiStream[v return } + if dropResponse(response) { + log.V(logs.Debug).Info("Dropping response", zap.Object("response", response)) + continue + } + log.V(logs.Debug).Info("Sending response", zap.Object("response", response)) if err := stream.Send(response); err != nil { log.Error(err, "Failed to send response") @@ -564,6 +569,11 @@ func postProcessBlocks(blocks []*v1alpha1.Block) ([]*v1alpha1.Block, error) { if isOutputTag(block.Contents) { continue } + + // If the block is empty filter it out. + if strings.TrimSpace(block.Contents) == "" { + continue + } results = append(results, block) return results, nil } @@ -607,3 +617,17 @@ func shouldTrigger(doc *v1alpha1.Doc, selectedIndex int32) bool { selectedCell := doc.Blocks[selectedIndex] return selectedCell.GetKind() == v1alpha1.BlockKind_MARKUP } + +// dropResponse returns true if the response should be dropped rather than being sent to the client. +// The reason for doing this is because if a previous generation generated a "good" response we don't want +// to overwrite it with this one +func dropResponse(response *v1alpha1.StreamGenerateResponse) bool { + if response == nil { + return true + } + // We don't want to send empty cells because that will cause the client to remove any previously suggested cells + if len(response.Cells) == 0 { + return true + } + return false +} diff --git a/app/pkg/agent/agent_test.go b/app/pkg/agent/agent_test.go index 90585df..173da82 100644 --- a/app/pkg/agent/agent_test.go +++ b/app/pkg/agent/agent_test.go @@ -361,6 +361,16 @@ func Test_PostProcessBlocks(t *testing.T) { }, expected: []*v1alpha1.Block{}, }, + { + name: "whitespace-only-block", + blocks: []*v1alpha1.Block{ + { + Kind: v1alpha1.BlockKind_CODE, + Contents: " ", + }, + }, + expected: []*v1alpha1.Block{}, + }, } for _, c := range cases { @@ -375,3 +385,42 @@ func Test_PostProcessBlocks(t *testing.T) { }) } } + +func Test_dropResponse(t *testing.T) { + type testCase struct { + name string + response *v1alpha1.StreamGenerateResponse + expected bool + } + + cases := []testCase{ + { + name: "basic", + response: &v1alpha1.StreamGenerateResponse{ + Cells: []*parserv1.Cell{ + { + Kind: parserv1.CellKind_CELL_KIND_CODE, + Value: "print('Hello, World!')", + }, + }, + }, + expected: false, + }, + { + name: "empty", + response: &v1alpha1.StreamGenerateResponse{ + Cells: []*parserv1.Cell{}, + }, + expected: true, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + result := dropResponse(c.response) + if result != c.expected { + t.Errorf("Expected %v; got %v", c.expected, result) + } + }) + } +}