package cmd import ( "context" "fmt" "net/url" "os" "strings" "github.com/spf13/cobra" "github.com/yourorg/devour/internal/scraper" "github.com/yourorg/devour/internal/search" "github.com/yourorg/devour/internal/storage" ) var pushCmd = &cobra.Command{ Use: "push ", Short: "Import local documents into Devour storage/index", Long: `Push local documents into your Devour local workspace. Current stable behavior: - local ingest into docs storage - local reindex for query/ask/status Remote push is experimental and not enabled by default. Examples: devour push ./docs devour push ./docs --project my-project`, Args: cobra.ExactArgs(1), RunE: runPush, } var ( pushServer string pushProject string ) func init() { pushCmd.Flags().StringVar(&pushServer, "server", "", "remote Devour server URL (experimental)") pushCmd.Flags().StringVarP(&pushProject, "project", "p", "", "project name label") } func runPush(cmd *cobra.Command, args []string) error { path := args[0] if _, err := os.Stat(path); err != nil { return fmt.Errorf("path does not exist: %s", path) } cfg, err := loadAppConfig() if err != nil { return fmt.Errorf("load app config for push command: %w", err) } server := strings.TrimSpace(pushServer) if server != "" && !isLocalServer(server) { return fmt.Errorf("remote push is experimental and not enabled in this build; use local push without --server") } projectName := strings.TrimSpace(pushProject) if projectName == "" { projectName = "local-push" } fmt.Printf("šŸ“¤ Ingesting local docs from: %s\n", path) fmt.Printf(" Project: %s\n", projectName) fmt.Printf(" Target docs dir: %s\n", cfg.Storage.DocsDir) s := scraper.NewScraper(scraper.SourceTypeLocal, toScraperConfig(cfg, 0)) if s == nil { return fmt.Errorf("local scraper not available") } docs, err := s.Scrape(context.Background(), &scraper.Source{ Name: projectName, Type: scraper.SourceTypeLocal, Path: path, Include: []string{`.*`}, }) if err != nil { return fmt.Errorf("local ingest failed: %w", err) } saved, err := storage.SaveDocuments(docs, storage.SaveOptions{ Format: "json", OutputDir: cfg.Storage.DocsDir, AllowEmpty: false, PrintWriter: nil, }) if err != nil { return fmt.Errorf("save docs failed: %w", err) } engine := search.NewEngine(cfg) stats, err := engine.Rebuild(context.Background()) if err != nil { return fmt.Errorf("reindex failed: %w", err) } fmt.Println("\nāœ“ Push complete") fmt.Printf(" Documents imported: %d\n", saved.Count) fmt.Printf(" Index docs: %d\n", stats.Documents) fmt.Printf(" Index path: %s\n", stats.IndexPath) return nil } func isLocalServer(raw string) bool { u, err := url.Parse(raw) if err != nil { return false } host := strings.ToLower(u.Hostname()) return host == "" || host == "localhost" || host == "127.0.0.1" }