feat(graph): wire graphsync into MCP write/ingest/tunnel handlers
Commit 2 of Track A. Service stays a no-op until BRAIN_GRAPH_ENABLED= true; flipping it on creates the schema (idempotent), starts indexing every successful write, and optionally backfills the existing brain dir. - internal/graphsync: best-effort wrapper around graph.Extract + graphstore. IndexDoc reads docPath under brainDir, parses, upserts entity + replaces edges. BackfillFromBrainDir walks wiki/ + knowledge/. Both are no-ops on nil store so callers wire unconditionally. - mcp.Server gains WithGraph builder + graphsync.Store field. brain_write, brain_ingest, brain_ingest_raw, brain_tunnel call indexInGraph after success — failures slog.Warn but never propagate (graph is augmentation, not correctness). - cmd/server gates the wiring on BRAIN_GRAPH_ENABLED=true (default off so first rollout doesn't surprise). BRAIN_GRAPH_BACKFILL=true triggers a one-shot walk of the brain dir on boot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,9 +15,11 @@ import (
|
||||
chassisauth "gitea.d-ma.be/mathias/mcp-chassis/auth"
|
||||
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/api"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/embed"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/graphstore"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/graphsync"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/llm"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/mcp"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/embed"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/metrics"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/oauth"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/pipeline"
|
||||
@@ -142,6 +144,32 @@ func main() {
|
||||
logger.Info("brain hybrid retrieval enabled",
|
||||
"pg", redactDSN(pgDSN),
|
||||
"embed_url", embedURL, "embed_model", embedModel)
|
||||
|
||||
// Graph store shares the same postgres18 DSN as the vector
|
||||
// store and is opt-in via BRAIN_GRAPH_ENABLED=true. Defaults
|
||||
// to off so first rollout doesn't surprise — flip on after
|
||||
// the migration completes and the backfill finishes.
|
||||
if envOr("BRAIN_GRAPH_ENABLED", "false") == "true" {
|
||||
gstore, gerr := graphstore.New(context.Background(), pgDSN)
|
||||
if gerr != nil {
|
||||
logger.Error("graph store init", "err", gerr)
|
||||
os.Exit(1)
|
||||
}
|
||||
if gerr := gstore.Init(context.Background()); gerr != nil {
|
||||
logger.Error("graph store migrate", "err", gerr)
|
||||
os.Exit(1)
|
||||
}
|
||||
mcpSrv = mcpSrv.WithGraph(gstore)
|
||||
if envOr("BRAIN_GRAPH_BACKFILL", "false") == "true" {
|
||||
n, berr := graphsync.BackfillFromBrainDir(context.Background(), gstore, brainDir)
|
||||
if berr != nil {
|
||||
logger.Warn("graph backfill incomplete", "indexed", n, "err", berr)
|
||||
} else {
|
||||
logger.Info("graph backfill complete", "indexed", n)
|
||||
}
|
||||
}
|
||||
logger.Info("brain graph enabled", "pg", redactDSN(pgDSN))
|
||||
}
|
||||
case pgDSN == "" && embedURL == "":
|
||||
// disabled — fine
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user