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
18 changes: 11 additions & 7 deletions cmd/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cmd

import (
"fmt"
"os"
"log/slog"

"github.com/RandomCodeSpace/docsgraphcontext/internal/llm"
"github.com/RandomCodeSpace/docsgraphcontext/internal/pipeline"
Expand Down Expand Up @@ -39,11 +39,12 @@ var indexCmd = &cobra.Command{
return fmt.Errorf("llm provider: %w", err)
}
pl := pipeline.New(st, prov, cfg)
fmt.Fprintln(os.Stderr, "Running Phase 3-4: community detection + summaries...")
slog.Info("running Phase 3-4: community detection + summaries")
if err := pl.Finalize(cmd.Context(), indexVerbose); err != nil {
slog.Error("finalization failed", "err", err)
return err
}
fmt.Fprintln(os.Stderr, "Finalization complete.")
slog.Info("finalization complete")
return nil
}

Expand All @@ -62,23 +63,26 @@ var indexCmd = &cobra.Command{
}

if indexURL != "" {
fmt.Fprintf(os.Stderr, "Crawling %s (workers=%d)...\n", indexURL, indexWorkers)
slog.Info("crawling documentation site", "url", indexURL, "workers", indexWorkers,
"max_pages", indexMaxPages, "max_depth", indexMaxDepth)
if err := pl.IndexURL(cmd.Context(), indexURL, opts); err != nil {
slog.Error("web indexing failed", "url", indexURL, "err", err)
return err
}
fmt.Fprintln(os.Stderr, "Web indexing complete.")
slog.Info("web indexing complete", "url", indexURL)
return nil
}

if len(args) == 0 {
return fmt.Errorf("path or --url required (or use --finalize)")
}

fmt.Fprintf(os.Stderr, "Indexing %s (workers=%d)...\n", args[0], indexWorkers)
slog.Info("indexing path", "path", args[0], "workers", indexWorkers, "force", indexForce)
if err := pl.IndexPath(cmd.Context(), args[0], opts); err != nil {
slog.Error("indexing failed", "path", args[0], "err", err)
return err
}
fmt.Fprintln(os.Stderr, "Indexing complete.")
slog.Info("indexing complete", "path", args[0])
return nil
},
}
Expand Down
25 changes: 21 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package cmd

import (
"fmt"
"log/slog"
"os"

"github.com/RandomCodeSpace/docsgraphcontext/internal/config"
"github.com/spf13/cobra"
)

var (
cfgFile string
cfg *config.Config
cfgFile string
cfg *config.Config
logLevel string
)

var rootCmd = &cobra.Command{
Expand All @@ -32,17 +34,32 @@ func Execute() {
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default ~/.docsgraph/config.yaml)")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn, error")
}

func initConfig() {
// Set up structured logger
var level slog.Level
switch logLevel {
case "debug":
level = slog.LevelDebug
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
default:
level = slog.LevelInfo
}
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level})))

var err error
cfg, err = config.Load(cfgFile)
if err != nil {
fmt.Fprintln(os.Stderr, "config error:", err)
slog.Error("config error", "err", err)
os.Exit(1)
}
if err := os.MkdirAll(cfg.DataDir, 0755); err != nil {
fmt.Fprintln(os.Stderr, "mkdir error:", err)
slog.Error("failed to create data directory", "path", cfg.DataDir, "err", err)
os.Exit(1)
}
}
27 changes: 17 additions & 10 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"context"
"fmt"
"log/slog"
"net"
"net/http"
"os"
Expand All @@ -26,7 +27,6 @@ var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start MCP + Web UI server",
RunE: func(cmd *cobra.Command, args []string) error {
// Override config with CLI flags
if serveHost != "" {
cfg.Server.Host = serveHost
}
Expand All @@ -39,11 +39,13 @@ var serveCmd = &cobra.Command{
return fmt.Errorf("open store: %w", err)
}
defer st.Close()
slog.Info("store opened", "path", cfg.DBPath())

prov, err := llm.NewProvider(&cfg.LLM)
if err != nil {
return fmt.Errorf("llm provider: %w", err)
}
slog.Info("LLM provider initialised", "provider", prov.Name(), "model", prov.ModelID())

emb := embedder.New(prov, cfg.Indexing.BatchSize)
router := api.NewRouter(st, prov, emb, cfg)
Expand All @@ -56,27 +58,32 @@ var serveCmd = &cobra.Command{

srv := &http.Server{Handler: router, ReadTimeout: 60 * time.Second, WriteTimeout: 120 * time.Second}

fmt.Fprintf(os.Stderr, "DocsGraphContext server running on http://%s\n", addr)
fmt.Fprintf(os.Stderr, " Web UI: http://%s/\n", addr)
fmt.Fprintf(os.Stderr, " MCP: http://%s/mcp\n", addr)
fmt.Fprintf(os.Stderr, " API: http://%s/api/\n", addr)
fmt.Fprintf(os.Stderr, " LLM: %s (%s)\n", prov.Name(), prov.ModelID())
slog.Info("server started",
"addr", "http://"+addr,
"ui", "http://"+addr+"/",
"mcp", "http://"+addr+"/mcp",
"api", "http://"+addr+"/api/",
)

// Graceful shutdown
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

go func() {
if err := srv.Serve(ln); err != nil && err != http.ErrServerClosed {
fmt.Fprintln(os.Stderr, "server error:", err)
slog.Error("server error", "err", err)
}
}()

<-ctx.Done()
fmt.Fprintln(os.Stderr, "\nShutting down...")
slog.Info("shutting down...")
shutCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return srv.Shutdown(shutCtx)
if err := srv.Shutdown(shutCtx); err != nil {
slog.Error("shutdown error", "err", err)
return err
}
slog.Info("shutdown complete")
return nil
},
}

Expand Down
Loading
Loading