Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions internal/ollama/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (c *Client) StreamChatWithModel(ctx context.Context, model string, messages
if err != nil {
return fmt.Errorf("request ollama: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
payload, readErr := io.ReadAll(io.LimitReader(resp.Body, 4096))
Expand Down Expand Up @@ -138,7 +138,7 @@ func (c *Client) doModelOnlyRequest(ctx context.Context, endpoint string, body [
if err != nil {
return fmt.Errorf("request ollama preload: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
payload, readErr := io.ReadAll(io.LimitReader(resp.Body, 4096))
Expand Down Expand Up @@ -237,7 +237,7 @@ func (c *Client) doEmbedRequest(ctx context.Context, endpoint string, body []byt
if err != nil {
return embedResponse{}, 0, fmt.Errorf("request ollama embeddings: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
payload, readErr := io.ReadAll(io.LimitReader(resp.Body, 4096))
Expand Down
2 changes: 1 addition & 1 deletion internal/ollama/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestStreamChatWithModelIncludesDefaultOptions(t *testing.T) {
t.Fatalf("request path = %q, want /api/chat", r.URL.Path)
}

defer r.Body.Close()
defer func() { _ = r.Body.Close() }()

var payload chatRequest
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
Expand Down
27 changes: 6 additions & 21 deletions internal/search/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ type labeledSearchQuery struct {
type fetchedDocument struct {
document Document
sourceMD string
include bool
processed bool
}

Expand Down Expand Up @@ -1476,7 +1475,7 @@ func (s *Service) searchVariant(ctx context.Context, rewrittenQuery string, quer
if err != nil {
return nil, fmt.Errorf("request searxng: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
payload, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
Expand Down Expand Up @@ -1603,20 +1602,6 @@ func shouldSkipSearchURL(rawURL string) bool {
}
}

func isTrustedSearchHost(host string) bool {
normalized := strings.ToLower(strings.TrimSpace(host))
if normalized == "" {
return false
}
trustedHosts := []string{"github.com", "stackoverflow.com", "developer.mozilla.org"}
for _, candidate := range trustedHosts {
if normalized == candidate || strings.HasSuffix(normalized, "."+candidate) {
return true
}
}
return strings.HasPrefix(normalized, "docs.") || strings.HasPrefix(normalized, "developer.") || strings.HasSuffix(normalized, ".gov") || strings.HasSuffix(normalized, ".edu")
}

func isVideoResult(rawURL string) bool {
parsed, err := url.Parse(strings.TrimSpace(rawURL))
if err != nil {
Expand Down Expand Up @@ -1758,7 +1743,7 @@ func (s *Service) fetchDocument(ctx context.Context, result Result, onActivity f
}
return failedFetchResult(progressKey, result.URL, onProgress), nil
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
notifyActivity(onActivity)

if resp.StatusCode != http.StatusOK {
Expand Down Expand Up @@ -1976,7 +1961,7 @@ func buildSummaryPrompt(originalQuery string, searchQuery string, documents []Do
}
builder.WriteString("Fuentes extraídas:\n")
for i, document := range documents {
builder.WriteString(fmt.Sprintf("\n[%d] %s\n", i+1, safeTitle(document.Title)))
_, _ = fmt.Fprintf(&builder, "\n[%d] %s\n", i+1, safeTitle(document.Title))
builder.WriteString("URL: ")
builder.WriteString(document.URL)
builder.WriteString("\n")
Expand All @@ -1992,7 +1977,7 @@ func buildSummaryPrompt(originalQuery string, searchQuery string, documents []Do

builder.WriteString("\nFuentes:\n")
for index, document := range documents {
builder.WriteString(fmt.Sprintf("- [%d] ", index+1))
_, _ = fmt.Fprintf(&builder, "- [%d] ", index+1)
builder.WriteString(document.URL)
builder.WriteString("\n")
}
Expand Down Expand Up @@ -2334,7 +2319,7 @@ func buildFinalSummaryPrompt(query string, summaries []SourceSummary) string {
builder.WriteString("\n\n")
builder.WriteString("Resúmenes por fuente:\n")
for index, summary := range summaries {
builder.WriteString(fmt.Sprintf("\n[%d] %s\n", index+1, safeTitle(summary.Title)))
_, _ = fmt.Fprintf(&builder, "\n[%d] %s\n", index+1, safeTitle(summary.Title))
builder.WriteString("URL: ")
builder.WriteString(summary.URL)
builder.WriteString("\n")
Expand All @@ -2345,7 +2330,7 @@ func buildFinalSummaryPrompt(query string, summaries []SourceSummary) string {

builder.WriteString("\nFuentes:\n")
for index, summary := range summaries {
builder.WriteString(fmt.Sprintf("- [%d] ", index+1))
_, _ = fmt.Fprintf(&builder, "- [%d] ", index+1)
builder.WriteString(summary.URL)
builder.WriteString("\n")
}
Expand Down
68 changes: 34 additions & 34 deletions internal/search/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ func TestPrepareFallsBackToWebSearchWhenSemanticCacheMisses(t *testing.T) {
if got := r.URL.Query().Get("q"); got != "consulta optimizada" {
t.Fatalf("search query = %q, want rewritten fallback query", got)
}
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -471,19 +471,19 @@ func TestPrepareIncludesAllSearchVariantsInDownloadProgress(t *testing.T) {
query := r.URL.Query().Get("q")
switch query {
case "instalar ollama":
fmt.Fprintf(w, `{"results":[{"title":"A1","url":"%s/a1","content":"snippet a1","score":0.91},{"title":"A2","url":"%s/a2","content":"snippet a2","score":0.81},{"title":"A3","url":"%s/a3","content":"snippet a3","score":0.71}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A1","url":"%s/a1","content":"snippet a1","score":0.91},{"title":"A2","url":"%s/a2","content":"snippet a2","score":0.81},{"title":"A3","url":"%s/a3","content":"snippet a3","score":0.71}]}`,
baseURL,
baseURL,
baseURL,
)
case installOllamaQuery:
fmt.Fprintf(w, `{"results":[{"title":"B1","url":"%s/b1","content":"snippet b1","score":0.89},{"title":"B2","url":"%s/b2","content":"snippet b2","score":0.79},{"title":"B3","url":"%s/b3","content":"snippet b3","score":0.69}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"B1","url":"%s/b1","content":"snippet b1","score":0.89},{"title":"B2","url":"%s/b2","content":"snippet b2","score":0.79},{"title":"B3","url":"%s/b3","content":"snippet b3","score":0.69}]}`,
baseURL,
baseURL,
baseURL,
)
case "ollama":
fmt.Fprintf(w, `{"results":[{"title":"C1","url":"%s/c1","content":"snippet c1","score":0.87},{"title":"C2","url":"%s/c2","content":"snippet c2","score":0.77},{"title":"C3","url":"%s/c3","content":"snippet c3","score":0.67}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"C1","url":"%s/c1","content":"snippet c1","score":0.87},{"title":"C2","url":"%s/c2","content":"snippet c2","score":0.77},{"title":"C3","url":"%s/c3","content":"snippet c3","score":0.67}]}`,
baseURL,
baseURL,
baseURL,
Expand All @@ -492,9 +492,9 @@ func TestPrepareIncludesAllSearchVariantsInDownloadProgress(t *testing.T) {
t.Fatalf("unexpected search query: %q", query)
}
case "/a1", "/a2", "/a3", "/b1", "/b2", "/b3", "/c1", "/c2", "/c3":
fmt.Fprint(w, strings.TrimPrefix(r.URL.Path, "/"))
_, _ = fmt.Fprint(w, strings.TrimPrefix(r.URL.Path, "/"))
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -526,19 +526,19 @@ func TestPrepareUsesTopThreeResultsPerVariantAsSources(t *testing.T) {
case searchPath:
switch r.URL.Query().Get("q") {
case primaryVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"A1","url":"%s/a1","content":"snippet a1","score":0.92},{"title":"A2","url":"%s/a2","content":"snippet a2","score":0.82},{"title":"A3","url":"%s/a3","content":"snippet a3","score":0.72}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A1","url":"%s/a1","content":"snippet a1","score":0.92},{"title":"A2","url":"%s/a2","content":"snippet a2","score":0.82},{"title":"A3","url":"%s/a3","content":"snippet a3","score":0.72}]}`,
baseURL,
baseURL,
baseURL,
)
case longVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"B1","url":"%s/b1","content":"snippet b1","score":0.91},{"title":"B2","url":"%s/b2","content":"snippet b2","score":0.81},{"title":"B3","url":"%s/b3","content":"snippet b3","score":0.71}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"B1","url":"%s/b1","content":"snippet b1","score":0.91},{"title":"B2","url":"%s/b2","content":"snippet b2","score":0.81},{"title":"B3","url":"%s/b3","content":"snippet b3","score":0.71}]}`,
baseURL,
baseURL,
baseURL,
)
case technicalVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"C1","url":"%s/c1","content":"snippet c1","score":0.90},{"title":"C2","url":"%s/c2","content":"snippet c2","score":0.80},{"title":"C3","url":"%s/c3","content":"snippet c3","score":0.70}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"C1","url":"%s/c1","content":"snippet c1","score":0.90},{"title":"C2","url":"%s/c2","content":"snippet c2","score":0.80},{"title":"C3","url":"%s/c3","content":"snippet c3","score":0.70}]}`,
baseURL,
baseURL,
baseURL,
Expand All @@ -547,7 +547,7 @@ func TestPrepareUsesTopThreeResultsPerVariantAsSources(t *testing.T) {
t.Fatalf("unexpected search query: %q", r.URL.Query().Get("q"))
}
case "/a1", "/a2", "/a3", "/b1", "/b2", "/b3", "/c1", "/c2", "/c3":
fmt.Fprint(w, strings.TrimPrefix(r.URL.Path, "/"))
_, _ = fmt.Fprint(w, strings.TrimPrefix(r.URL.Path, "/"))
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -638,7 +638,7 @@ func TestFetchSourceBuildsReadableMarkdown(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -750,9 +750,9 @@ func TestPrepareWaitsForPendingSemanticCacheIngestBeforeRepeatingWebSearch(t *te
searchMu.Lock()
searchRequests++
searchMu.Unlock()
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -818,9 +818,9 @@ func TestPrepareFallsBackToWebSearchWhenSemanticCacheEntryExpired(t *testing.T)
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case searchPath:
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.8}]}`, baseURL)
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -854,9 +854,9 @@ func TestPrepareReturnsErrorWhenNoSourcesCanBeProcessed(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case searchPath:
fmt.Fprintf(w, `{"results":[{"title":"Fallback","url":"%s/article","content":"search snippet","score":1}]}`, baseURL)
_, _ = fmt.Fprintf(w, `{"results":[{"title":"Fallback","url":"%s/article","content":"search snippet","score":1}]}`, baseURL)
case "/article":
fmt.Fprint(w, "broken body")
_, _ = fmt.Fprint(w, "broken body")
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -884,7 +884,7 @@ func TestPrepareUsesBackupSourcesWhenPrimaryDownloadsFail(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case searchPath:
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":8},{"title":"B","url":"%s/b","content":"snippet b","score":7},{"title":"C","url":"%s/c","content":"snippet c","score":6},{"title":"D","url":"%s/d","content":"snippet d","score":5},{"title":"E","url":"%s/e","content":"snippet e","score":4},{"title":"F","url":"%s/f","content":"snippet f","score":3},{"title":"Video","url":"https://www.youtube.com/watch?v=abc","content":"video snippet","score":99}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":8},{"title":"B","url":"%s/b","content":"snippet b","score":7},{"title":"C","url":"%s/c","content":"snippet c","score":6},{"title":"D","url":"%s/d","content":"snippet d","score":5},{"title":"E","url":"%s/e","content":"snippet e","score":4},{"title":"F","url":"%s/f","content":"snippet f","score":3},{"title":"Video","url":"https://www.youtube.com/watch?v=abc","content":"video snippet","score":99}]}`,
baseURL,
baseURL,
baseURL,
Expand All @@ -893,18 +893,18 @@ func TestPrepareUsesBackupSourcesWhenPrimaryDownloadsFail(t *testing.T) {
baseURL,
)
case "/b":
fmt.Fprint(w, "page/b")
_, _ = fmt.Fprint(w, "page/b")
case "/c":
fmt.Fprint(w, "page/c")
_, _ = fmt.Fprint(w, "page/c")
case "/d":
fmt.Fprint(w, "page/d")
_, _ = fmt.Fprint(w, "page/d")
case "/e":
fmt.Fprint(w, "page/e")
_, _ = fmt.Fprint(w, "page/e")
case "/f":
fmt.Fprint(w, "page/f")
_, _ = fmt.Fprint(w, "page/f")
case "/a":
w.WriteHeader(http.StatusBadGateway)
fmt.Fprint(w, "upstream error")
_, _ = fmt.Fprint(w, "upstream error")
default:
http.NotFound(w, r)
}
Expand Down Expand Up @@ -943,13 +943,13 @@ func newMultiplexedSearchHandler(t *testing.T, baseURL *string) http.HandlerFunc
case searchPath:
serveMultiplexedSearchResults(t, w, r, *baseURL)
case "/a":
fmt.Fprint(w, pageAContent)
_, _ = fmt.Fprint(w, pageAContent)
case sharedPath:
fmt.Fprint(w, sharedPageContent)
_, _ = fmt.Fprint(w, sharedPageContent)
case "/docs":
fmt.Fprint(w, "page/docs")
_, _ = fmt.Fprint(w, "page/docs")
case "/c":
fmt.Fprint(w, "page/c")
_, _ = fmt.Fprint(w, "page/c")
default:
http.NotFound(w, r)
}
Expand All @@ -960,17 +960,17 @@ func serveMultiplexedSearchResults(t *testing.T, w http.ResponseWriter, r *http.
t.Helper()
switch r.URL.Query().Get("q") {
case primaryVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.9},{"title":"B","url":"%s/shared","content":"snippet shared","score":0.8}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.9},{"title":"B","url":"%s/shared","content":"snippet shared","score":0.8}]}`,
baseURL,
baseURL,
)
case longVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"Shared alt","url":"%s/shared","content":"snippet shared alt","score":0.95},{"title":"C","url":"%s/c","content":"snippet c","score":0.7}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"Shared alt","url":"%s/shared","content":"snippet shared alt","score":0.95},{"title":"C","url":"%s/c","content":"snippet c","score":0.7}]}`,
baseURL,
baseURL,
)
case technicalVariantQuery:
fmt.Fprintf(w, `{"results":[{"title":"Docs","url":"%s/docs","content":"docs","score":0.6}]}`, baseURL)
_, _ = fmt.Fprintf(w, `{"results":[{"title":"Docs","url":"%s/docs","content":"docs","score":0.6}]}`, baseURL)
default:
t.Fatalf("unexpected multiplexed query: %q", r.URL.Query().Get("q"))
}
Expand Down Expand Up @@ -1170,15 +1170,15 @@ func (f *rewriteSearchFixture) handleRewriteSearch(t *testing.T) func(http.Respo
if got := r.URL.Query().Get("q"); got != rewrittenSudoQuery {
t.Fatalf("search query = %q, want rewritten query", got)
}
fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.4},{"title":"B","url":"%s/b","content":"snippet b","score":0.9}]}`,
_, _ = fmt.Fprintf(w, `{"results":[{"title":"A","url":"%s/a","content":"snippet a","score":0.4},{"title":"B","url":"%s/b","content":"snippet b","score":0.9}]}`,
f.baseURL,
f.baseURL,
)
case "/a", "/b":
f.mu.Lock()
f.pageRequests = append(f.pageRequests, r.URL.Path)
f.mu.Unlock()
fmt.Fprintf(w, "page%s", r.URL.Path)
_, _ = fmt.Fprintf(w, "page%s", r.URL.Path)
default:
http.NotFound(w, r)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/tui/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func editInExternalEditor(localizer *i18n.Localizer, editor, content string) tea
cmd.Stderr = os.Stderr

return tea.ExecProcess(cmd, func(runErr error) tea.Msg {
defer os.Remove(path)
defer func() { _ = os.Remove(path) }()
if runErr != nil {
return editorDoneMsg{err: fmt.Errorf(localizer.Get("editor.open_failed"), label, runErr)}
}
Expand Down
Loading
Loading