feat: central graphify brain (merged cross-project knowledge graph)
- brain/graph/: build-central.sh (code graph + merge linked projects), link-project.sh (register a project graph into the brain), serve-brain.sh (HTTP MCP :8090), README.md - server.py: mount /brain-graph so the brain is browsable from the dashboard - venv: graphify [mcp] extra installed so HTTP MCP serve works - hourly rebuild cron (agentic-os-brain-rebuild) Topology: each project keeps its own graph; they roll up into one central-graph.json that agents query over MCP. Memory notes become queryable later via an LLM key (graphify . without --code-only).
This commit is contained in:
parent
fe65acc405
commit
0a28ef0389
|
|
@ -0,0 +1,31 @@
|
|||
# Central Brain — Graphify knowledge graph
|
||||
|
||||
One central, queryable brain that project graphs roll up into.
|
||||
|
||||
## Topology
|
||||
- `agentic-os.json` — this project's own code graph (built from `graphify . --code-only`).
|
||||
- `projects/<name>.json` — each linked project's graph (registered via `link-project.sh`).
|
||||
- `central-graph.json` — the MERGED cross-repo brain (union of all the above). This is the artifact everything queries.
|
||||
- `serve-brain.sh` — serves `central-graph.json` over HTTP MCP at `http://127.0.0.1:8090/mcp`.
|
||||
- Dashboard: the brain directory is mounted at `http://127.0.0.1:8080/brain-graph/`.
|
||||
|
||||
## Commands
|
||||
```
|
||||
bash brain/graph/build-central.sh # rebuild central brain (code graph + merge linked projects)
|
||||
bash brain/graph/link-project.sh <name> <graph.json> # register a project's graph into the brain
|
||||
bash brain/graph/serve-brain.sh # serve central brain over HTTP MCP (:8090)
|
||||
```
|
||||
Set `CENTRAL_BRAIN_PORT` to override the serve port (default 8090).
|
||||
|
||||
## What it contains today
|
||||
- Code symbols of agentic-os as nodes (functions/classes/modules), with call/import edges.
|
||||
- Linked projects (added via `link-project.sh`).
|
||||
- Memory NOTES (markdown under `brain/`) are NOT yet graph nodes. To make them
|
||||
queryable, set an LLM key (GEMINI_API_KEY / OPENAI_API_KEY / etc.) and run
|
||||
`graphify .` (no `--code-only`) so notes are semantically extracted. Until
|
||||
then, notes remain the write path; the graph indexes code structure.
|
||||
|
||||
## Notes
|
||||
- `graphify`'s MCP HTTP serve requires the extra: `pip install "graphifyy[mcp]"` (done in the venv).
|
||||
- The write path for memory is still `brain/*.md` + `audit` + `data/`; graphify reads those, never writes them.
|
||||
- Rebuild is scheduled hourly by the `agentic-os-brain-rebuild` cron.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build the CENTRAL Agentic-OS brain graph.
|
||||
#
|
||||
# Strategy (works WITHOUT an LLM key):
|
||||
# 1. Build this project's CODE graph (graphify . --code-only) into
|
||||
# brain/graph/agentic-os.json (nodes = code symbols, edges = relations).
|
||||
# 2. Merge in every linked project graph under brain/graph/projects/ -> central-graph.json
|
||||
# (cross-repo union = the unified brain).
|
||||
#
|
||||
# The central brain is the single queryable artifact. Per-project graphs stay
|
||||
# independent; they are rolled up here via `graphify merge-graphs`.
|
||||
#
|
||||
# To make MEMORY NOTES queryable too, set an LLM key (GEMINI_API_KEY etc.)
|
||||
# and run `graphify . ` (no --code-only) — that adds markdown notes as nodes.
|
||||
# Until then, notes live as linked files and the code graph indexes structure.
|
||||
|
||||
set -u
|
||||
DIR="/home/austin/agentic-os"
|
||||
VENV="$DIR/venv"
|
||||
GF="$VENV/bin/graphify"
|
||||
OUT="$DIR/brain/graph"
|
||||
PORT="${CENTRAL_BRAIN_PORT:-8090}"
|
||||
|
||||
cd "$DIR" || { echo "FATAL: cannot cd $DIR"; exit 1; }
|
||||
|
||||
echo "==> [1/2] building Agentic-OS code graph"
|
||||
"$GF" . --code-only --no-viz 2>&1 | tail -2 || {
|
||||
echo "WARN: code graph build failed; using existing graphify-out/graph.json if present"
|
||||
}
|
||||
# graphify always writes to graphify-out/graph.json relative to the scanned root
|
||||
[ -f "$DIR/graphify-out/graph.json" ] && cp "$DIR/graphify-out/graph.json" "$OUT/agentic-os.json" && echo " copied -> $OUT/agentic-os.json"
|
||||
|
||||
echo "==> [2/2] merging linked project graphs into central brain"
|
||||
MAPS=()
|
||||
[ -f "$OUT/agentic-os.json" ] && MAPS+=("$OUT/agentic-os.json")
|
||||
for g in "$OUT"/projects/*.json; do
|
||||
[ -f "$g" ] && MAPS+=("$g")
|
||||
done
|
||||
|
||||
if [ "${#MAPS[@]}" -eq 0 ]; then
|
||||
echo "ERROR: no graph.json found to merge"; exit 1
|
||||
elif [ "${#MAPS[@]}" -eq 1 ]; then
|
||||
# only the agentic-os graph so far — central brain = that graph (no merge needed)
|
||||
cp "${MAPS[0]}" "$OUT/central-graph.json" && echo " (single source -> central brain)"
|
||||
else
|
||||
"$GF" merge-graphs "${MAPS[@]}" --out "$OUT/central-graph.json" 2>&1 | tail -3
|
||||
fi
|
||||
echo "==> central brain written: $OUT/central-graph.json"
|
||||
"$VENV/bin/python" -c "import json;d=json.load(open('$OUT/central-graph.json'));n=d.get('nodes',d.get('graph',{}).get('nodes',[]));print(' nodes:',len(n) if isinstance(n,list) else '?')" 2>/dev/null || true
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env bash
|
||||
# Link a project's graphify graph into the CENTRAL brain.
|
||||
#
|
||||
# Usage:
|
||||
# ./brain/graph/link-project.sh <project-name> <path-to-graph.json>
|
||||
#
|
||||
# Copies the project's graph.json into brain/graph/projects/<name>.json and
|
||||
# records it in brain/graph/projects/registry.json, then rebuilds the central
|
||||
# brain. The central brain is a merged cross-repo graph, so projects stay
|
||||
# independent on disk but roll up into one queryable brain.
|
||||
set -eu
|
||||
DIR="/home/austin/agentic-os"
|
||||
OUT="$DIR/brain/graph"
|
||||
REG="$OUT/projects/registry.json"
|
||||
|
||||
NAME="${1:-}"
|
||||
SRC="${2:-}"
|
||||
if [ -z "$NAME" ] || [ -z "$SRC" ]; then
|
||||
echo "Usage: $0 <project-name> <path-to-graph.json>" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$SRC" ]; then
|
||||
echo "ERROR: graph not found: $SRC" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$OUT/projects"
|
||||
cp "$SRC" "$OUT/projects/$NAME.json"
|
||||
echo "linked $NAME -> $OUT/projects/$NAME.json"
|
||||
|
||||
# update registry
|
||||
python3 - "$REG" "$NAME" "$OUT/projects/$NAME.json" <<'PY'
|
||||
import json, sys
|
||||
reg, name, path = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
data = {}
|
||||
if __import__('os').path.exists(reg):
|
||||
try: data = json.load(open(reg))
|
||||
except Exception: data = {}
|
||||
data[name] = {"graph": path, "linked": __import__('datetime').datetime.now().isoformat()}
|
||||
json.dump(data, open(reg, "w"), indent=2)
|
||||
PY
|
||||
|
||||
echo "rebuild central brain..."
|
||||
bash "$OUT/build-central.sh"
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
# Serve the CENTRAL brain graph over HTTP MCP so agents/tools can query it.
|
||||
#
|
||||
# Endpoints: http://127.0.0.1:8090/mcp (Streamable HTTP MCP)
|
||||
# Requires the graphify [mcp] extra (pip install "graphifyy[mcp]").
|
||||
#
|
||||
# The central brain is the single memory/code query surface for all projects.
|
||||
set -u
|
||||
DIR="/home/austin/agentic-os"
|
||||
VENV="$DIR/venv"
|
||||
GF="$VENV/bin/python"
|
||||
GRAPH="$DIR/brain/graph/central-graph.json"
|
||||
PORT="${CENTRAL_BRAIN_PORT:-8090}"
|
||||
|
||||
cd "$DIR" || exit 1
|
||||
if [ ! -f "$GRAPH" ]; then
|
||||
echo "central brain missing ($GRAPH). Run: bash brain/graph/build-central.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Serving central brain on http://127.0.0.1:$PORT/mcp"
|
||||
exec "$GF" -m graphify.serve "$GRAPH" --transport http --host 127.0.0.1 --port "$PORT"
|
||||
|
|
@ -2534,6 +2534,12 @@ graphify_dir = BASE_DIR / "graphify-out"
|
|||
if graphify_dir.exists():
|
||||
app.mount("/graphify-out", StaticFiles(directory=str(graphify_dir)), name="graphify-out")
|
||||
|
||||
# Central Agentic-OS brain graph (merged cross-project knowledge graph).
|
||||
# Built by brain/graph/build-central.sh; queryable live via brain/graph/serve-brain.sh (MCP :8090).
|
||||
central_brain_dir = BASE_DIR / "brain" / "graph"
|
||||
if central_brain_dir.exists():
|
||||
app.mount("/brain-graph", StaticFiles(directory=str(central_brain_dir)), name="brain-graph")
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
def index():
|
||||
html_file = BASE_DIR / "dashboard" / "index.html"
|
||||
|
|
|
|||
Loading…
Reference in New Issue