package cmd import ( "fmt" "github.com/kb-search/kb/internal/api" "github.com/kb-search/kb/internal/output" "github.com/spf13/cobra" ) var findCmd = &cobra.Command{ Use: "find ", Short: "Find documents by their indexed content", Args: cobra.ExactArgs(1), RunE: runFind, } func init() { findCmd.Flags().IntP("top", "n", 10, "number of documents to return") findCmd.Flags().String("tags", "", "filter by tags (comma-separated)") findCmd.Flags().String("type", "", "filter by document type") rootCmd.AddCommand(findCmd) } func runFind(cmd *cobra.Command, args []string) error { top, _ := cmd.Flags().GetInt("top") tags, _ := cmd.Flags().GetString("tags") docType, _ := cmd.Flags().GetString("type") body := map[string]interface{}{"query": args[0], "top": top} if tags != "" { body["tags"] = splitTags(tags) } if docType != "" { body["doc_type"] = docType } resp, err := api.NewClient().Post("/api/v1/documents/find", body) if err != nil { return err } if err := api.CheckError(resp); err != nil { return err } if output.IsJSON() { var raw interface{} if err := api.DecodeJSON(resp, &raw); err != nil { return fmt.Errorf("failed to decode response: %w", err) } output.PrintJSON(raw) return nil } var docs []struct { DocumentID int `json:"document_id"` Title string `json:"title"` Filename string `json:"original_filename"` Type string `json:"doc_type"` Score float64 `json:"score"` HitCount int `json:"hit_count"` TopChunk string `json:"top_chunk"` } if err := api.DecodeJSON(resp, &docs); err != nil { return fmt.Errorf("failed to decode response: %w", err) } if len(docs) == 0 { fmt.Println("No documents found.") return nil } for i, doc := range docs { preview := doc.TopChunk if len(preview) > 200 { preview = preview[:200] + "..." } fmt.Printf("\n%d. [%.4f] %s (doc:%d, hits:%d)\n", i+1, doc.Score, doc.Title, doc.DocumentID, doc.HitCount) if doc.Filename != "" { fmt.Printf(" Filename: %s\n", doc.Filename) } if doc.Type != "" { fmt.Printf(" Type: %s\n", doc.Type) } fmt.Printf(" %s\n", preview) } fmt.Println() return nil }