feat: migrate rag commands from CLI
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
4c741992dc
commit
2a8d8b0820
7 changed files with 465 additions and 0 deletions
86
cmd/rag/cmd_collections.go
Normal file
86
cmd/rag/cmd_collections.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package rag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/go-rag"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
listCollections bool
|
||||
showStats bool
|
||||
deleteCollection string
|
||||
)
|
||||
|
||||
var collectionsCmd = &cobra.Command{
|
||||
Use: "collections",
|
||||
Short: i18n.T("cmd.rag.collections.short"),
|
||||
Long: i18n.T("cmd.rag.collections.long"),
|
||||
RunE: runCollections,
|
||||
}
|
||||
|
||||
func runCollections(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
// Connect to Qdrant
|
||||
qdrantClient, err := rag.NewQdrantClient(rag.QdrantConfig{
|
||||
Host: qdrantHost,
|
||||
Port: qdrantPort,
|
||||
UseTLS: false,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to Qdrant: %w", err)
|
||||
}
|
||||
defer func() { _ = qdrantClient.Close() }()
|
||||
|
||||
// Handle delete
|
||||
if deleteCollection != "" {
|
||||
exists, err := qdrantClient.CollectionExists(ctx, deleteCollection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("collection not found: %s", deleteCollection)
|
||||
}
|
||||
if err := qdrantClient.DeleteCollection(ctx, deleteCollection); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted collection: %s\n", deleteCollection)
|
||||
return nil
|
||||
}
|
||||
|
||||
// List collections
|
||||
collections, err := qdrantClient.ListCollections(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(collections) == 0 {
|
||||
fmt.Println("No collections found.")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n\n", cli.TitleStyle.Render("Collections"))
|
||||
|
||||
for _, name := range collections {
|
||||
if showStats {
|
||||
info, err := qdrantClient.CollectionInfo(ctx, name)
|
||||
if err != nil {
|
||||
fmt.Printf(" %s (error: %v)\n", name, err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" %s\n", cli.ValueStyle.Render(name))
|
||||
fmt.Printf(" Points: %d\n", info.PointCount)
|
||||
fmt.Printf(" Status: %s\n", info.Status)
|
||||
fmt.Println()
|
||||
} else {
|
||||
fmt.Printf(" %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
21
cmd/rag/cmd_commands.go
Normal file
21
cmd/rag/cmd_commands.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Package rag provides RAG (Retrieval Augmented Generation) commands.
|
||||
//
|
||||
// Commands:
|
||||
// - core ai rag ingest: Ingest markdown files into Qdrant
|
||||
// - core ai rag query: Query the vector database
|
||||
// - core ai rag collections: List and manage collections
|
||||
package rag
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// AddRAGSubcommands registers the 'rag' command as a subcommand of parent.
|
||||
// Called from the ai command package to mount under "core ai rag".
|
||||
func AddRAGSubcommands(parent *cobra.Command) {
|
||||
initFlags()
|
||||
ragCmd.AddCommand(ingestCmd)
|
||||
ragCmd.AddCommand(queryCmd)
|
||||
ragCmd.AddCommand(collectionsCmd)
|
||||
parent.AddCommand(ragCmd)
|
||||
}
|
||||
117
cmd/rag/cmd_ingest.go
Normal file
117
cmd/rag/cmd_ingest.go
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package rag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/go-rag"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
collection string
|
||||
recreate bool
|
||||
chunkSize int
|
||||
chunkOverlap int
|
||||
)
|
||||
|
||||
var ingestCmd = &cobra.Command{
|
||||
Use: "ingest [directory]",
|
||||
Short: i18n.T("cmd.rag.ingest.short"),
|
||||
Long: i18n.T("cmd.rag.ingest.long"),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: runIngest,
|
||||
}
|
||||
|
||||
func runIngest(cmd *cobra.Command, args []string) error {
|
||||
directory := "."
|
||||
if len(args) > 0 {
|
||||
directory = args[0]
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Connect to Qdrant
|
||||
fmt.Printf("Connecting to Qdrant at %s:%d...\n", qdrantHost, qdrantPort)
|
||||
qdrantClient, err := rag.NewQdrantClient(rag.QdrantConfig{
|
||||
Host: qdrantHost,
|
||||
Port: qdrantPort,
|
||||
UseTLS: false,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to Qdrant: %w", err)
|
||||
}
|
||||
defer func() { _ = qdrantClient.Close() }()
|
||||
|
||||
if err := qdrantClient.HealthCheck(ctx); err != nil {
|
||||
return fmt.Errorf("qdrant health check failed: %w", err)
|
||||
}
|
||||
|
||||
// Connect to Ollama
|
||||
fmt.Printf("Using embedding model: %s (via %s:%d)\n", model, ollamaHost, ollamaPort)
|
||||
ollamaClient, err := rag.NewOllamaClient(rag.OllamaConfig{
|
||||
Host: ollamaHost,
|
||||
Port: ollamaPort,
|
||||
Model: model,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to Ollama: %w", err)
|
||||
}
|
||||
|
||||
if err := ollamaClient.VerifyModel(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Configure ingestion
|
||||
if chunkSize <= 0 {
|
||||
return fmt.Errorf("chunk-size must be > 0")
|
||||
}
|
||||
if chunkOverlap < 0 || chunkOverlap >= chunkSize {
|
||||
return fmt.Errorf("chunk-overlap must be >= 0 and < chunk-size")
|
||||
}
|
||||
|
||||
cfg := rag.IngestConfig{
|
||||
Directory: directory,
|
||||
Collection: collection,
|
||||
Recreate: recreate,
|
||||
Verbose: verbose,
|
||||
BatchSize: 100,
|
||||
Chunk: rag.ChunkConfig{
|
||||
Size: chunkSize,
|
||||
Overlap: chunkOverlap,
|
||||
},
|
||||
}
|
||||
|
||||
// Progress callback
|
||||
progress := func(file string, chunks int, total int) {
|
||||
if verbose {
|
||||
fmt.Printf(" Processed: %s (%d chunks total)\n", file, chunks)
|
||||
} else {
|
||||
fmt.Printf("\r %s (%d chunks) ", cli.DimStyle.Render(file), chunks)
|
||||
}
|
||||
}
|
||||
|
||||
// Run ingestion
|
||||
fmt.Printf("\nIngesting from: %s\n", directory)
|
||||
if recreate {
|
||||
fmt.Printf(" (recreating collection: %s)\n", collection)
|
||||
}
|
||||
|
||||
stats, err := rag.Ingest(ctx, qdrantClient, ollamaClient, cfg, progress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Summary
|
||||
fmt.Printf("\n\n%s\n", cli.TitleStyle.Render("Ingestion complete!"))
|
||||
fmt.Printf(" Files processed: %d\n", stats.Files)
|
||||
fmt.Printf(" Chunks created: %d\n", stats.Chunks)
|
||||
if stats.Errors > 0 {
|
||||
fmt.Printf(" Errors: %s\n", cli.ErrorStyle.Render(fmt.Sprintf("%d", stats.Errors)))
|
||||
}
|
||||
fmt.Printf(" Collection: %s\n", collection)
|
||||
|
||||
return nil
|
||||
}
|
||||
81
cmd/rag/cmd_query.go
Normal file
81
cmd/rag/cmd_query.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package rag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/go-rag"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
queryCollection string
|
||||
limit int
|
||||
threshold float32
|
||||
category string
|
||||
format string
|
||||
)
|
||||
|
||||
var queryCmd = &cobra.Command{
|
||||
Use: "query [question]",
|
||||
Short: i18n.T("cmd.rag.query.short"),
|
||||
Long: i18n.T("cmd.rag.query.long"),
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runQuery,
|
||||
}
|
||||
|
||||
func runQuery(cmd *cobra.Command, args []string) error {
|
||||
question := args[0]
|
||||
ctx := context.Background()
|
||||
|
||||
// Connect to Qdrant
|
||||
qdrantClient, err := rag.NewQdrantClient(rag.QdrantConfig{
|
||||
Host: qdrantHost,
|
||||
Port: qdrantPort,
|
||||
UseTLS: false,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to Qdrant: %w", err)
|
||||
}
|
||||
defer func() { _ = qdrantClient.Close() }()
|
||||
|
||||
// Connect to Ollama
|
||||
ollamaClient, err := rag.NewOllamaClient(rag.OllamaConfig{
|
||||
Host: ollamaHost,
|
||||
Port: ollamaPort,
|
||||
Model: model,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to Ollama: %w", err)
|
||||
}
|
||||
|
||||
// Configure query
|
||||
if limit < 0 {
|
||||
limit = 0
|
||||
}
|
||||
cfg := rag.QueryConfig{
|
||||
Collection: queryCollection,
|
||||
Limit: uint64(limit),
|
||||
Threshold: threshold,
|
||||
Category: category,
|
||||
}
|
||||
|
||||
// Run query
|
||||
results, err := rag.Query(ctx, qdrantClient, ollamaClient, question, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Format output
|
||||
switch format {
|
||||
case "json":
|
||||
fmt.Println(rag.FormatResultsJSON(results))
|
||||
case "context":
|
||||
fmt.Println(rag.FormatResultsContext(results))
|
||||
default:
|
||||
fmt.Println(rag.FormatResultsText(results))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
84
cmd/rag/cmd_rag.go
Normal file
84
cmd/rag/cmd_rag.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package rag
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Shared flags
|
||||
var (
|
||||
qdrantHost string
|
||||
qdrantPort int
|
||||
ollamaHost string
|
||||
ollamaPort int
|
||||
model string
|
||||
verbose bool
|
||||
)
|
||||
|
||||
var ragCmd = &cobra.Command{
|
||||
Use: "rag",
|
||||
Short: i18n.T("cmd.rag.short"),
|
||||
Long: i18n.T("cmd.rag.long"),
|
||||
}
|
||||
|
||||
func initFlags() {
|
||||
// Qdrant connection flags (persistent) - defaults to localhost for local development
|
||||
qHost := "localhost"
|
||||
if v := os.Getenv("QDRANT_HOST"); v != "" {
|
||||
qHost = v
|
||||
}
|
||||
ragCmd.PersistentFlags().StringVar(&qdrantHost, "qdrant-host", qHost, i18n.T("cmd.rag.flag.qdrant_host"))
|
||||
|
||||
qPort := 6334
|
||||
if v := os.Getenv("QDRANT_PORT"); v != "" {
|
||||
if p, err := strconv.Atoi(v); err == nil {
|
||||
qPort = p
|
||||
}
|
||||
}
|
||||
ragCmd.PersistentFlags().IntVar(&qdrantPort, "qdrant-port", qPort, i18n.T("cmd.rag.flag.qdrant_port"))
|
||||
|
||||
// Ollama connection flags (persistent) - defaults to localhost for local development
|
||||
oHost := "localhost"
|
||||
if v := os.Getenv("OLLAMA_HOST"); v != "" {
|
||||
oHost = v
|
||||
}
|
||||
ragCmd.PersistentFlags().StringVar(&ollamaHost, "ollama-host", oHost, i18n.T("cmd.rag.flag.ollama_host"))
|
||||
|
||||
oPort := 11434
|
||||
if v := os.Getenv("OLLAMA_PORT"); v != "" {
|
||||
if p, err := strconv.Atoi(v); err == nil {
|
||||
oPort = p
|
||||
}
|
||||
}
|
||||
ragCmd.PersistentFlags().IntVar(&ollamaPort, "ollama-port", oPort, i18n.T("cmd.rag.flag.ollama_port"))
|
||||
|
||||
m := "nomic-embed-text"
|
||||
if v := os.Getenv("EMBEDDING_MODEL"); v != "" {
|
||||
m = v
|
||||
}
|
||||
ragCmd.PersistentFlags().StringVar(&model, "model", m, i18n.T("cmd.rag.flag.model"))
|
||||
|
||||
// Verbose flag (persistent)
|
||||
ragCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, i18n.T("common.flag.verbose"))
|
||||
|
||||
// Ingest command flags
|
||||
ingestCmd.Flags().StringVar(&collection, "collection", "hostuk-docs", i18n.T("cmd.rag.ingest.flag.collection"))
|
||||
ingestCmd.Flags().BoolVar(&recreate, "recreate", false, i18n.T("cmd.rag.ingest.flag.recreate"))
|
||||
ingestCmd.Flags().IntVar(&chunkSize, "chunk-size", 500, i18n.T("cmd.rag.ingest.flag.chunk_size"))
|
||||
ingestCmd.Flags().IntVar(&chunkOverlap, "chunk-overlap", 50, i18n.T("cmd.rag.ingest.flag.chunk_overlap"))
|
||||
|
||||
// Query command flags
|
||||
queryCmd.Flags().StringVar(&queryCollection, "collection", "hostuk-docs", i18n.T("cmd.rag.query.flag.collection"))
|
||||
queryCmd.Flags().IntVar(&limit, "top", 5, i18n.T("cmd.rag.query.flag.top"))
|
||||
queryCmd.Flags().Float32Var(&threshold, "threshold", 0.5, i18n.T("cmd.rag.query.flag.threshold"))
|
||||
queryCmd.Flags().StringVar(&category, "category", "", i18n.T("cmd.rag.query.flag.category"))
|
||||
queryCmd.Flags().StringVar(&format, "format", "text", i18n.T("cmd.rag.query.flag.format"))
|
||||
|
||||
// Collections command flags
|
||||
collectionsCmd.Flags().BoolVar(&listCollections, "list", false, i18n.T("cmd.rag.collections.flag.list"))
|
||||
collectionsCmd.Flags().BoolVar(&showStats, "stats", false, i18n.T("cmd.rag.collections.flag.stats"))
|
||||
collectionsCmd.Flags().StringVar(&deleteCollection, "delete", "", i18n.T("cmd.rag.collections.flag.delete"))
|
||||
}
|
||||
21
go.mod
21
go.mod
|
|
@ -6,21 +6,42 @@ require (
|
|||
forge.lthn.ai/core/go v0.0.0-20260221191103-d091fa62023f
|
||||
github.com/ollama/ollama v0.16.1
|
||||
github.com/qdrant/go-client v1.16.2
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/charmbracelet/bubbletea v1.3.10 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/term v0.40.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/grpc v1.79.1 // indirect
|
||||
|
|
|
|||
55
go.sum
55
go.sum
|
|
@ -1,14 +1,37 @@
|
|||
forge.lthn.ai/core/go v0.0.0-20260221191103-d091fa62023f h1:CcSh/FFY93K5m0vADHLxwxKn2pTIM8HzYX1eGa4WZf4=
|
||||
forge.lthn.ai/core/go v0.0.0-20260221191103-d091fa62023f/go.mod h1:WCPJVEZm/6mTcJimHV0uX8ZhnKEF3dN0rQp13ByaSPg=
|
||||
forge.lthn.ai/core/go-crypt v0.0.0-20260221190941-9585da8e6649 h1:Rs3bfSU8u1wkzYeL21asL7IcJIBVwOhtRidcEVj/PkA=
|
||||
forge.lthn.ai/core/go-crypt v0.0.0-20260221190941-9585da8e6649/go.mod h1:RS+sz5lChrbc1AEmzzOULsTiMv3bwcwVtwbZi+c/Yjk=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
|
|
@ -19,12 +42,28 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
github.com/ollama/ollama v0.16.1 h1:DIxnLdS0om3hb7HheJqj6+ZnPCCMWmy/vyUxiQgRYoI=
|
||||
github.com/ollama/ollama v0.16.1/go.mod h1:FEk95NbAJJZk+t7cLh+bPGTul72j1O3PLLlYNV3FVZ0=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
|
|
@ -32,13 +71,24 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/qdrant/go-client v1.16.2 h1:UUMJJfvXTByhwhH1DwWdbkhZ2cTdvSqVkXSIfBrVWSg=
|
||||
github.com/qdrant/go-client v1.16.2/go.mod h1:I+EL3h4HRoRTeHtbfOd/4kDXwCukZfkd41j/9wryGkw=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||
|
|
@ -51,10 +101,15 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2W
|
|||
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
|
||||
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05ST2uO1exVfZPVqRC5o=
|
||||
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue