Skip to content

Commit b71c2d8

Browse files
committed
fix(integrations): address review comments — stale names and docs
- retry.go: update package-level doc from "Package gemini" to "Package ai" to match the declared package name - vdb_router.go: rename NewVDBRouterFromGemini → NewVDBRouterFromEmbedder and fix its stale doc comment - index.go: rename local variable geminiClient → embedder to match the provider-neutral *ai.Embedder type - gemini_test.go → prompts_test.go: rename test file to a provider-neutral name consistent with the package rename Relates to #68 Signed-off-by: Kavirubc <hapuarachchikaviru@gmail.com>
1 parent db21ccc commit b71c2d8

4 files changed

Lines changed: 162 additions & 7 deletions

File tree

cmd/simili/commands/index.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ func runIndex(cmd *cobra.Command, args []string) {
8989

9090
ghClient := similiGithub.NewClient(ctx, token)
9191

92-
geminiClient, err := ai.NewEmbedder(cfg.Embedding.APIKey, cfg.Embedding.Model)
92+
embedder, err := ai.NewEmbedder(cfg.Embedding.APIKey, cfg.Embedding.Model)
9393
if err != nil {
9494
log.Fatalf("Failed to init embedder: %v", err)
9595
}
96-
defer geminiClient.Close()
96+
defer embedder.Close()
9797
embeddingDimensions := cfg.Embedding.Dimensions
98-
if dim := geminiClient.Dimensions(); dim > 0 {
98+
if dim := embedder.Dimensions(); dim > 0 {
9999
embeddingDimensions = dim
100100
}
101101

@@ -144,7 +144,7 @@ func runIndex(cmd *cobra.Command, args []string) {
144144
go func(id int) {
145145
defer wg.Done()
146146
for job := range jobs {
147-
processIssue(ctx, id, job.Issue, ghClient, geminiClient, qdrantClient, splitter, cfg.Qdrant.Collection, org, repoName, indexDryRun)
147+
processIssue(ctx, id, job.Issue, ghClient, embedder, qdrantClient, splitter, cfg.Qdrant.Collection, org, repoName, indexDryRun)
148148
}
149149
}(i)
150150
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Author: Kaviru Hapuarachchi
2+
// GitHub: https://github.com/Kavirubc
3+
// Created: 2026-02-02
4+
// Last Modified: 2026-02-02
5+
6+
package ai
7+
8+
import (
9+
"strings"
10+
"testing"
11+
)
12+
13+
func TestBuildTriagePrompt(t *testing.T) {
14+
issue := &IssueInput{
15+
Title: "Bug: Application crashes on startup",
16+
Body: "When I start the application, it immediately crashes with error XYZ",
17+
Author: "testuser",
18+
Labels: []string{"bug", "needs-triage"},
19+
}
20+
21+
prompt := buildTriagePrompt(issue)
22+
23+
if prompt == "" {
24+
t.Error("Expected non-empty prompt")
25+
}
26+
27+
// Check that prompt contains key information
28+
if !strings.Contains(prompt, issue.Title) {
29+
t.Error("Prompt should contain issue title")
30+
}
31+
if !strings.Contains(prompt, issue.Author) {
32+
t.Error("Prompt should contain author")
33+
}
34+
}
35+
36+
func TestBuildResponsePrompt(t *testing.T) {
37+
similar := []SimilarIssueInput{
38+
{
39+
Number: 123,
40+
Title: "Similar issue",
41+
URL: "https://github.com/org/repo/issues/123",
42+
Similarity: 0.85,
43+
State: "closed",
44+
},
45+
{
46+
Number: 456,
47+
Title: "Another similar issue",
48+
URL: "https://github.com/org/repo/issues/456",
49+
Similarity: 0.75,
50+
State: "open",
51+
},
52+
}
53+
54+
prompt := buildResponsePrompt(similar)
55+
56+
if prompt == "" {
57+
t.Error("Expected non-empty prompt")
58+
}
59+
60+
// Check that prompt contains issue information
61+
if !strings.Contains(prompt, "#123") {
62+
t.Error("Prompt should contain first issue number")
63+
}
64+
if !strings.Contains(prompt, "#456") {
65+
t.Error("Prompt should contain second issue number")
66+
}
67+
}
68+
69+
func TestTruncate(t *testing.T) {
70+
tests := []struct {
71+
name string
72+
input string
73+
maxLen int
74+
expected string
75+
}{
76+
{
77+
name: "short string",
78+
input: "hello",
79+
maxLen: 10,
80+
expected: "hello",
81+
},
82+
{
83+
name: "exact length",
84+
input: "hello",
85+
maxLen: 5,
86+
expected: "hello",
87+
},
88+
{
89+
name: "long string",
90+
input: "hello world this is a long string",
91+
maxLen: 10,
92+
expected: "hello worl...",
93+
},
94+
}
95+
96+
for _, tt := range tests {
97+
t.Run(tt.name, func(t *testing.T) {
98+
result := truncate(tt.input, tt.maxLen)
99+
if result != tt.expected {
100+
t.Errorf("Expected %q, got %q", tt.expected, result)
101+
}
102+
})
103+
}
104+
}
105+
106+
func TestParseTriageResponse(t *testing.T) {
107+
tests := []struct {
108+
name string
109+
response string
110+
expectedQuality string
111+
expectedLabels int
112+
expectedDupe bool
113+
}{
114+
{
115+
name: "good quality bug",
116+
response: "Quality: good\nLabels: bug\nReasoning: Well described issue with clear steps",
117+
expectedQuality: "good",
118+
expectedLabels: 1,
119+
expectedDupe: false,
120+
},
121+
{
122+
name: "poor quality",
123+
response: "Quality: poor\nLabels: question\nReasoning: Vague description, no details",
124+
expectedQuality: "poor",
125+
expectedLabels: 1,
126+
expectedDupe: false,
127+
},
128+
{
129+
name: "duplicate detection",
130+
response: "Quality: good\nThis appears to be a duplicate of issue #123",
131+
expectedQuality: "good",
132+
expectedLabels: 0,
133+
expectedDupe: true,
134+
},
135+
}
136+
137+
for _, tt := range tests {
138+
t.Run(tt.name, func(t *testing.T) {
139+
result := parseTriageResponseLegacy(tt.response)
140+
141+
if result.Quality != tt.expectedQuality {
142+
t.Errorf("Expected quality %q, got %q", tt.expectedQuality, result.Quality)
143+
}
144+
145+
if len(result.SuggestedLabels) != tt.expectedLabels {
146+
t.Errorf("Expected %d labels, got %d", tt.expectedLabels, len(result.SuggestedLabels))
147+
}
148+
149+
if result.IsDuplicate != tt.expectedDupe {
150+
t.Errorf("Expected duplicate=%v, got %v", tt.expectedDupe, result.IsDuplicate)
151+
}
152+
})
153+
}
154+
}
155+

internal/integrations/ai/retry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Created: 2026-02-15
44
// Last Modified: 2026-02-17
55

6-
// Package gemini provides Gemini AI integration for embeddings and LLM.
6+
// Package ai provides provider-neutral AI integration for embeddings and LLM.
77
package ai
88

99
import (

internal/transfer/vdb_router.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func (r *VDBRouter) SuggestTransfer(ctx context.Context, issue *IssueInput, curr
137137
}, nil
138138
}
139139

140-
// VDBRouterWithGeminiEmbedder is a convenience constructor accepting *ai.Embedder directly.
141-
func NewVDBRouterFromGemini(embedder *ai.Embedder, store qdrant.VectorStore, collection string, maxResults int) *VDBRouter {
140+
// NewVDBRouterFromEmbedder is a convenience constructor accepting *ai.Embedder directly.
141+
func NewVDBRouterFromEmbedder(embedder *ai.Embedder, store qdrant.VectorStore, collection string, maxResults int) *VDBRouter {
142142
return NewVDBRouter(embedder, store, collection, maxResults)
143143
}

0 commit comments

Comments
 (0)