diff --git a/CHANGES.md b/CHANGES.md
index 9192c92..44503cf 100755
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,353 @@
# AI-LSC Changelog
+## v3.1.1b — taxonomy re-org: Routing restored (11 layers), canonical 24-dir /mnt/AI layout
+
+Restores the Routing layer that was lost when the 13-layer model was
+compressed to 10 (both "L6 AI Endpoints" and "L11 Intelligent Routing"
+had been folded into Orchestrators), fixes the mis-categorized tools,
+and aligns the backend to the revised canonical `/mnt/AI/` directory
+tree. No tool count change (185 tools); validator still reports 0 errors.
+
+### New layer ladder (10 → 11)
+
+```
+L1 Host Platform L7 Security
+L2 Development Env L8 Observability
+L3 GPU Runtimes L9 User Interfaces
+L4 Engines L10 DevOps
+L5 Routing (restored) L11 Knowledge Management
+L6 Orchestrators
+```
+
+`NAV_LAYER_ORDER` inserts Routing between Engines and Orchestrators —
+engines serve weights, routing proxies/load-balances/meshes them into
+one OpenAI-compat endpoint, orchestrators build agent workflows on top.
+
+### Tool moves (18 tools, all layers/levels updated)
+
+| tool_id | Old | New |
+|---------|-----|-----|
+| `litellm` | L5 Orchestrators (Proxy / API Gateway) | **L5 Routing** |
+| `9router_proxy` | L5 Orchestrators (LLM Router) | **L5 Routing** |
+| `meshllm` | L5 Orchestrators (LLM Mesh) | **L5 Routing** |
+| `dify` | L5 Orchestrators (Pipeline) | **L5 Routing** |
+| `picode` | L5 Orchestrators (AI Coding Agent) | **L5 Routing** (category → `Mesh Client`) |
+| `vllm` | L5 Orchestrators (Scaling) | **L4 Engines** (role → Engine; ADR-001 always listed vLLM under Inference Engines) |
+| `sglang` | L5 Orchestrators (Scaling) | **L4 Engines** (role → Engine) |
+| `eagle_eye` | L5 Orchestrators (category literally "Observability") | **L8 Observability** |
+| `dma` | L5 Orchestrators (Build Monitoring) | **L8 Observability** |
+| `aider`, `claude_code`, `codex`, `openhands`, `opencode`, `gemini_cli`, `qwen_code`, `goose`, `zcoder` | L5 Orchestrators (AI Coding Agent) | **L10 DevOps** — matches the DB editor's `AI Coding Agent → DevOps` mapping, which previously conflicted with the registry |
+
+Remaining tools in the affected layers were renumbered (+1): 38 stay in
+Orchestrators (L6), Security L7, Observability L8, User Interfaces L9,
+DevOps L10, Knowledge Management L11. Per-layer level uniformity
+verified. `picode`'s category changed `AI Coding Agent` → `Mesh Client`
+so the category cascade cannot silently flip it back to DevOps.
+
+### Tool DB editor (`CATEGORY_MAP`)
+
+- All entries renumbered to the new ladder; map is now fully consistent
+ with the live registry (0 layer/level mismatches).
+- 13 new categories so every registry category auto-fills correctly:
+ `LLM Mesh`, `Mesh Client` (Routing); `Observability` (Observability);
+ `Build`, `Debugging`, `Shell`, `Claude Code Skill`, `Container Ops`,
+ `Infrastructure`, `Memory System`, `Model Surgery`, `Networking`,
+ `Virtualization` (previously missing entirely).
+- Fixed conflicts: `AI Coding Agent` → DevOps/L10 (role `Coding Agent`,
+ was `Autonomous Coder` at L9), `Build Monitoring` → Observability/L8,
+ `LLM Serving` → Engines/L4, `LLM Router` / `Proxy` / `Pipeline` →
+ Routing/L5.
+
+### STACK_WIRINGS (`stack/connections.py`)
+
+- 29 wiring `layer=` labels synced to the registry: the 13 moved tools
+ with wirings, plus `deep_eye`/`luxtts` (UI tools mislabeled
+ Orchestrators) and 14 pre-existing drifts (`heretic`, `unsloth`,
+ `parakeet`, `fabric`, `n8n`, `nightshift`, `hivemind`, `hermes_agent`,
+ `agno`, `hermes_dashboard_page`, `mnemo_cortex`, `everos_memory`,
+ `langflow`, `opensandbox`). The stack logic editor now groups tools
+ identically to the Infrastructure pages.
+- Stale section comments annotated: `L6: AI Endpoints` → the restored
+ Routing layer; `L10: Intelligent Routing` → folded into Orchestrators.
+
+### Canonical `/mnt/AI/` layout (26 → 24 dirs)
+
+`REQUIRED_DIRS` now matches the target tree exactly:
+
+- **Added `configs/`** — app configs templated for native runtime plus
+ app state. `main_window.config_root` moves from legacy `config/` to
+ `configs/`, taking `pipeline_state.json`, `pipeline.json`,
+ `license_approvals.json` with it; `controller_config.json` moves off
+ the `/mnt/AI/` root into `configs/`. A one-time
+ `_migrate_legacy_state_files()` pass moves old files on startup
+ (newer copies win; emptied legacy dirs are removed).
+- **Dropped from the skeleton**: `bootstraps/ai-lsc`, `staging`,
+ `registry/manifests`. `registry/` remains as app-internal storage for
+ `ecosystem.json` and manifests — auto-created on demand by
+ `RegistryManager`, no longer part of the canonical tree.
+- `paths.py`: `configs_root` added; `staging_root` / `bootstraps_root`
+ removed; the deprecated `config_root → runtime` alias now points at
+ `configs/`. Per-tool config subdirs (`configs//`) are still
+ created on demand by `InstallerManager`.
+- `license_gate.py` / `licenses.py` doc references updated to
+ `configs/license_approvals.json`.
+
+Existing installs pick up all taxonomy changes automatically:
+`RegistryManager._sync_with_upstream()` re-syncs structural fields
+(layer, level, role, category) from the layer files on every start.
+
+## v3.1.1a — registry validator fixes (5 errors → 0)
+
+Fixes all 5 `validate_registry()` errors plus latent bugs surfaced
+during the fix pass. No tool count change (185 tools).
+
+### Installer fixes (validator errors)
+
+All five failed the "script installer cmd should reference
+{tools_root}" check — they installed into system dirs or the cwd:
+
+| tool_id | Before | After |
+|---------|--------|-------|
+| `firecracker` | extracted into `/usr/local/bin/` (and silently broken: versioned tarball dirs never landed on PATH) | extracts into `{tools_root}/firecracker/`, symlinks `firecracker` + `jailer` into `{tools_root}/bin/` |
+| `cloudflared` | downloaded to `/usr/local/bin/cloudflared` | downloads to `{tools_root}/bin/cloudflared` |
+| `llamafile` | downloaded to cwd (mismatched launcher, which already expected `{tools_root}/bin/llamafile`) | downloads to `{tools_root}/bin/llamafile` |
+| `meilisearch` | `curl \| sh` dropped binary in cwd | runs installer inside `{tools_root}/bin/` (official installer places the binary in the cwd) |
+| `grafana_alloy` | `install.sh \| sh` — **URL dead (404): upstream dropped the script** | direct release asset `alloy-linux-amd64.zip`, extracted via `python3 -m zipfile` (no unzip dependency) |
+
+### Launcher fixes (latent bugs)
+
+- `firecracker`, `cloudflared`, `grafana_alloy` launchers now use
+ absolute `{tools_root}/bin/` paths. Rationale: `tools_root/bin`
+ is on PATH at install time (`installer._env()`) but **not** at launch
+ time (`enriched_env()` builds PATH from `base_bin_dir` = uv/npm bins
+ only), so bare-name launcher cmds would pass preflight then fail
+ with "command not found". Absolute paths are immune to the gap.
+- firecracker version discovery uses the Location header
+ (`curl -sIL … | grep -i '^location:'`) instead of
+ `-w '%{url_effective}'` — launcher/installer cmds are rendered with
+ `str.format()`, and the `{url_effective}` braces would raise
+ `KeyError` at render time.
+
+### Dependency fixes (phantom missing-dep warnings)
+
+- `dify` deps: `node` → `nodejs` (the actual registry tool_id).
+- `RegistryManager.check_dependencies()` now allows system-level deps
+ (`kubectl`, `java`) via a `SYSTEM_DEPS` frozenset, mirroring the
+ existing `_system_deps` pattern in `stack/connections.py`. Previously
+ `crossplane` (kubectl) and `keycloak` (java) produced permanent
+ "missing dependency" warnings that could never be satisfied.
+
+### Not fixed (observations, no behavior change)
+
+- 9 duplicate `default_port` defaults across tools (e.g. 3000 shared
+ by grafana/opik/openhands/flowise). These are overridable per
+ service row; leaving as-is unless the stack compiler should
+ auto-assign.
+- `TODO.md`'s `open_webui`/`openwebui` split no longer reproduces:
+ only `openwebui` exists in both the registry and `STACK_WIRINGS`.
+
+## v3.1.1 — local-coder-mesh integration (this build)
+
+Adds 4 new tools, corrects 1 existing tool, adds 4 new `STACK_WIRINGS`
+entries (and rewires 1), adds 1 new stack template, and aligns all
+hardcoded `/mnt/AI/` paths to the canonical 26-directory layout. No
+containers in the dev path — every tool installs natively. ai-lsc's
+Podman/Docker/LXC/Firecracker export is reserved for total-stack
+deployment exports only, as before.
+
+### New tools (181 → 185)
+
+| tool_id | Layer | What | Install |
+|---------|-------|------|---------|
+| `picode` | L5 Orchestrators | PiCode (jasonjmcghee/picode) — local code-tinker agent | git clone |
+| `meshllm` | L5 Orchestrators | MeshLLM (Mesh-LLM/mesh-llm) — native binary, pools GPUs/memory across machines, exposes OpenAI-compat API at :9337, web console at :3131. NOT a LiteLLM derivative. | script (official curl installer) |
+| `zcoder` | L5 Orchestrators | Zhipu AI Z-Coder CLI coding agent | npm `zcoder-cli` |
+| `hermes_webui` | L8 User Interfaces | Hermes-themed Open-WebUI instance on :8081 with its own data volume; backend points at `hermes_agent` (:17051) instead of Ollama direct | uv `open-webui` |
+
+### Corrected tool
+
+`graphify` was already in the registry but had wrong metadata. Fixed in place:
+
+| Field | Old | New |
+|-------|-----|-----|
+| `role` | `Graph Builder` | `Knowledge Graph Builder` |
+| `category` | `AI Agent` | `Claude Code Skill` |
+| `installer` | `git: nicely-done/graphify` | `uv: graphifyy` (PyPI; CLI is `graphify`) |
+| `license` | `Proprietary` | `MIT` (verified from pyproject.toml) |
+| `flags.has_web` | `False` | `True` (graph.html output) |
+| `flags.is_mcp` | `False` | `True` (`graphify --mcp` stdio server) |
+| `description` | 1 line generic | 10 lines accurate (CLI + Claude Code skill + MCP server + LLM backend options) |
+
+Graphify's wiring also changed — see below.
+
+### New `STACK_WIRINGS` entries (133 → 137)
+
+| tool_id | Exposes | Consumes |
+|---------|---------|----------|
+| `picode` | (none — CLI agent) | `meshllm` (primary), `litellm` (fallback), `ollama` (direct fallback) |
+| `meshllm` | `openai_api` (:9337) + `mesh_web_console` (:3131) | `ollama` (optional, for `mesh-llm client --auto` mode) |
+| `zcoder` | (none — CLI agent) | `meshllm` (primary), `litellm` (fallback), `ollama` (direct fallback) |
+| `hermes_webui` | `hermes_webui_http` (:8081) | `hermes_agent` (required, primary backend), `ollama` (optional, for RAG embeddings) |
+
+### Rewired entry
+
+`graphify` removed from the L8 passive/CLI list and given a proper
+`_reg(StackWiring(...))` block:
+
+- **Exposes**: `graphify_mcp` (stdio MCP server, no port) — start with
+ `graphify --mcp`. Other MCP-aware agents can query the knowledge graph.
+- **Consumes** (all optional, fallback chain for the extraction LLM):
+ `meshllm` (:9337/v1), `litellm` (:4000/v1), `ollama` (:11434/v1).
+ Graphify defaults to Claude (Anthropic API) but can be configured for
+ fully-local extraction by setting `OPENAI_API_BASE` to any of the
+ above.
+
+### New stack template (13 → 14)
+
+`local-coder-mesh.json` — "Local Coder Mesh — All-Ollama Coding Stack".
+17 tools: ollama, litellm, meshllm, picode, aider, odysseus, opencode,
+zcoder, graphify, hermes, hermes_agent, hermes_webui, hermes_desktop,
+openwebui, ripgrep, fd, tree_sitter.
+
+Topology: coding agents prefer MeshLLM (:9337) for mesh-pooled inference,
+fall back to LiteLLM (:4000) for proxy routing, then Ollama direct
+(:11434). Graphify builds knowledge graphs from the codebase and exposes
+an MCP server that the coding agents query. Hermes WebUI talks to
+hermes_agent (NOT Ollama direct) so every Hermes conversation flows
+through the agent runtime's tool-use layer. OpenWebUI talks to Ollama
+direct. ripgrep + fd + tree_sitter are passive filesystem tools used by
+the coding agents for repo-map / symbol navigation.
+
+Recommended models: `qwen2.5-coder:7b` (fast coding),
+`qwen2.5-coder:32b` (heavy coding), `hermes3:8b` (Hermes stack),
+`nomic-embed-text` (openwebui RAG, corpus indexing, graphify embeddings).
+MeshLLM auto-downloads a suitable model on first `serve --auto` if none
+is specified.
+
+### Path alignment to canonical `/mnt/AI/` layout
+
+Three files updated so ai-lsc's hardcoded paths match the 26-directory
+canonical layout:
+
+- **`src/ai_lsc/constants.py`** — `REQUIRED_DIRS` replaced with the 26
+ canonical entries (`bootstraps/ai-lsc`, `staging`, `backends`,
+ `distfiles`, `runtime`, `models/hot`, `models/cold`, `corpus/hot`,
+ `corpus/cold`, `datasets/wordlists`, `datasets/huggingface`,
+ `datasets/github`, `pipelines`, `registry/manifests`, `agents`,
+ `skills`, `projects/active`, `projects/labs`, `projects/vault`,
+ `blueprints`, `workspaces`, `dashboards`, `tools`, `exports/oci-images`,
+ `scripts`, `logs`). Old layout dirs (`config`, `cache`, `data`,
+ `containers`, `bin`, `tmp`, `backups`, `models/ollama`, `models/chroma`,
+ `datasets/raw`, `workspaces/hermes`, `workspaces/openwebui`,
+ `workspaces/n8n`) are NOT removed — they just become orphans. Clean
+ them up manually if desired.
+- **`src/ai_lsc/utils/paths.py`** — `build_path_tree()` expanded from 10
+ keys to 24 keys. Old keys kept and repointed at canonical subdirs.
+ New keys added: `runtime_root`, `models_hot`, `models_cold`,
+ `corpus_root`, `pipelines_root`, `agents_root`, `projects_root`,
+ `blueprints_root`, `dashboards_root`, `scripts_root`, `backends_root`,
+ `distfiles_root`, `staging_root`, `bootstraps_root`. The `config_root`
+ key is kept as a deprecated alias pointing at `/mnt/AI/runtime/` so
+ existing callers don't break — new code should use
+ `tools_root / / "config"` or `runtime_root / ` explicitly.
+- **`src/ai_lsc/agents/litellm_config.py`** and
+ **`src/ai_lsc/agents/librechat_config.py`** — hardcoded save paths
+ moved from `/mnt/AI/config/litellm_config.yaml` and
+ `/mnt/AI/tools/librechat/librechat.yaml` to
+ `/mnt/AI/runtime/litellm/config.yaml` and
+ `/mnt/AI/runtime/librechat/config.yaml` respectively. Per-tool configs
+ for long-running services belong under `runtime//` next to their
+ venv / cloned repo, since the spec has no top-level `/mnt/AI/config/`.
+
+### Backfill script path fixes
+
+Three helper scripts in `scripts/` had stale hardcoded absolute paths to
+`/home/z/my-project/workspace/ai-lsc` (a developer machine path that
+leaked into the v3.1 release). Replaced with
+`Path(__file__).resolve().parent.parent` so they resolve to the project
+root regardless of where the tarball is extracted:
+
+- `scripts/backfill_default_licenses.py`
+- `scripts/backfill_layer_flags.py`
+- `scripts/backfill_tool_licenses.py`
+
+### Verification (run against this build)
+
+```
+Registry: 185 tools (was 181)
+Wirings: 137 entries (was 133)
+Wiring validation errors: 0
+Registry validation errors: 5 (all pre-existing in upstream v3.1 —
+ firecracker, cloudflared, llamafile, meilisearch, grafana_alloy —
+ none introduced by this build)
+meshllm installer: uses {tools_root}/meshllm/bin (passes validator)
+Templates: 14 (was 13) — local-coder-mesh added
+Template tool resolution: 17/17 tools resolve in registry
+build_path_tree() keys: 24 (was 10)
+REQUIRED_DIRS entries: 26 (was 22)
+graphify installer: uv:graphifyy (was git:nicely-done/graphify)
+graphify license: MIT (was Proprietary)
+graphify is_mcp flag: True (was False)
+meshllm interfaces: ['openai_api' on :9337, 'mesh_web_console' on :3131]
+graphify interfaces: ['graphify_mcp' stdio]
+```
+
+### Native-only install policy
+
+Every tool in the new `local-coder-mesh` template installs natively into
+`/mnt/AI/runtime//` (venv via uv/pipx) or via pacman/AUR/curl-script.
+ai-lsc's container export feature (Podman / Docker / LXC / Firecracker)
+is intentionally NOT used at install time — it's reserved for total-stack
+deployment exports via the Stack Editor, exactly as in v3.1.
+
+### Rollback
+
+To revert this entire build to upstream v3.1, restore from git or
+re-extract the original tarball. There is no separate "patch pack" to
+unapply — this is the integrated project.
+
+---
+
+## v3.1 — registry expansion: 2026-era coding agents, serving, and runtimes
+
+Adds 11 tools to the layer registry (170 → 181) and 10 `STACK_WIRINGS` entries (123 → 133), and backfills 6 missing OSI licenses into the catalog. All facts (npm/PyPI package names, default ports, licenses) were verified against current upstream docs.
+
+### New tools
+
+| tool_id | Layer | What | Install |
+|---------|-------|------|---------|
+| `deno` | L2 Development | JavaScript/TypeScript/WASM runtime; runs many MCP servers via `deno run` | pacman `deno` |
+| `uv` | L2 Development | Astral's Python package/project manager (AI-LSC's own install backend) | pacman `uv` |
+| `tinygrad` | L3 GPU Runtimes | Minimalist autograd tensor library (CUDA/AMD/CPU backends) | uv `tinygrad` |
+| `opencode` | L5 Orchestrators | SST's open-source terminal AI coding agent (TUI, LSP, 75+ providers) | npm `opencode-ai` |
+| `gemini_cli` | L5 Orchestrators | Google's open-source terminal AI agent | npm `@google/gemini-cli` |
+| `qwen_code` | L5 Orchestrators | Qwen's agentic terminal coding tool (Gemini CLI fork) | npm `@qwen-code/qwen-code` |
+| `goose` | L5 Orchestrators | Block's extensible AI agent with MCP extensions | manual (opens releases page) |
+| `letta` | L5 Orchestrators | Stateful agent framework (MemGPT) with persistent memory; `letta server` on :8283 | uv `letta` |
+| `sglang` | L5 Orchestrators | Fast LLM serving with RadixAttention; OpenAI-compat API on :30000 | uv `sglang` |
+| `jan` | L8 User Interfaces | Offline ChatGPT-alternative desktop app; OpenAI-compat local API on :1337 | npm `@janhq/jan` |
+| `mem0` | L10 Knowledge Mgmt | Memory layer for AI apps/agents; pluggable vector backends | uv `mem0ai` |
+
+`goose` uses installer type `custom` deliberately: its official install path is a `curl | sh` one-liner, which conflicts with the v3.1 no-remote-code-execution policy. The `custom` installer opens the GitHub releases page for a manual, download-first install instead. `deno` and `uv` are intentionally left unwired (language runtimes, consistent with `nodejs`/`python`).
+
+### Wiring topology (Pipeline Ticker)
+
+- **Terminal coding agents wired**: `opencode`, `gemini_cli`, `qwen_code`, `goose`, and the pre-existing `codex` each gained connections to Ollama (direct) and LiteLLM (proxied) — staging either backend now prevents orphan-flagging. `codex` had been an orphan since v3.1 because it had no `STACK_WIRINGS` entry.
+- **`sglang`** mirrors the vLLM wiring: exposes `openai_api` on :30000, consumes `cuda_driver`.
+- **`letta`** exposes its REST API on :8283 and optionally consumes PostgreSQL (`LETTA_PG_URI`) + Ollama.
+- **`jan`** exposes `openai_api` on :1337 (bundled llama.cpp engine).
+- **`mem0`** optionally consumes Ollama (LLM + embeddings) and Qdrant (vector storage).
+- **`tinygrad`** optionally consumes `cuda_driver` (it also runs on CPU/AMD).
+- `validate_wiring()` reports 0 errors across all 133 wirings.
+
+### License catalog backfill (fixes 8 pre-existing validator errors)
+
+The following SPDX IDs were referenced by layer files but missing from `registry/licenses.py`, producing `license is not in the license catalog` validation errors: `LGPL-2.1` (strace, lxc, libvirt), `GPL-1.0` (perl), `PHP-3.01` (php), `Ruby` (ruby), `MirOS` (mksh), `MIT/Apache-2.0` (rust). All six are OSI-approved and are now catalog entries (auto-approvable). The merged registry validates with **0 errors** — the only remaining messages are the 5 documented `script installer cmd should reference {{tools_root}}` warnings tied to the curl|sh policy decision (llamafile, meilisearch, grafana_alloy + the newer firecracker, cloudflared).
+
+### Docs
+
+README tool counts and the layer table were refreshed to the real merged-registry numbers (they had been stale since the DevOps→Orchestrators reorg moved the coding agents).
+
## v3.1 — 2026-07-07
Codename: **Ankh of Jah** (continuation)
diff --git a/README.md b/README.md
index 6b5e5a6..055f495 100755
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
AI - Local Stack Control
- v3.1 — Codename: Ankh of Jah
+ v3.1.1 — Codename: Ankh of Jah (local-coder-mesh build)
+
+
This build includes the local-coder-mesh integration — see CHANGES.md for the full list of changes vs upstream v3.1.
http://dcos.net
@@ -13,7 +15,7 @@
A PySide6 desktop application for orchestrating local AI/ML tool stacks across a 10-layer architecture.
-AI Local Stack Control (AI-LSC) provides a unified interface to discover, configure, launch, and manage 140 tools spanning the entire AI software stack — from GPU runtimes and inference engines to agent frameworks, security tooling, and knowledge management.
+AI Local Stack Control (AI-LSC) provides a unified interface to discover, configure, launch, and manage 181 tools spanning the entire AI software stack — from GPU runtimes and inference engines to agent frameworks, security tooling, and knowledge management.

@@ -25,16 +27,16 @@ Every tool in the registry is classified within a 10-layer taxonomy, giving you
| Layer | Tools | Examples |
|-------|-------|---------|
-| L1 — Host Platform | 9 | PostgreSQL, MariaDB, Redis, SQLite3, DuckDB, Podman, Docker, Tmux, Git |
-| L2 — Development Environment | 7 | Python Environment, CuPy, ripgrep, fd, tree-sitter, SST, Unsloth |
-| L3 — GPU Runtimes | 3 | CUDA Toolkit, NVIDIA Apex, Heretic |
-| L4 — Engines | 7 | Ollama, llama.cpp, KoboldCPP, Llamafile, TurboLLM, AirLLM, Locally-Uncensored |
-| L5 — Orchestrators | 26 | vLLM, Ray, LiteLLM Proxy, 9Router Proxy, LangChain, LangFlow, Dify, CrewAI, AutoGen, Wayland AI, +17 more |
+| L1 — Host Platform | 16 | PostgreSQL, MariaDB, Redis, SQLite3, DuckDB, Podman, Docker, Tmux, Git |
+| L2 — Development Environment | 33 | Python Environment, Deno, uv, Node.js, CuPy, ripgrep, fd, tree-sitter, SST, Unsloth |
+| L3 — GPU Runtimes | 3 | CUDA Toolkit, NVIDIA Apex, tinygrad |
+| L4 — Engines | 8 | Ollama, llama.cpp, KoboldCPP, Llamafile, TurboLLM, AirLLM, Locally-Uncensored |
+| L5 — Orchestrators | 53 | vLLM, SGLang, LiteLLM Proxy, 9Router Proxy, LangChain, LangFlow, Dify, CrewAI, AutoGen, Letta, OpenCode, Gemini CLI, Qwen Code, goose, Codex, +38 more |
| L6 — Security | 6 | Keycloak, HashiCorp Vault, Trivy, Fail2Ban, ClamAV, Open Policy Agent |
| L7 — Observability | 8 | Btop, Glances, Prometheus, Grafana, Grafana Alloy, Opik, Pulse AI, Latitude |
-| L8 — User Interfaces | 16 | Open WebUI, AnythingLLM, LibreChat, Flowise, InvokeAI, Forge (A1111), ComfyUI, Dashy, Obsidian, +7 more |
-| L9 — DevOps | 33 | Terraform, Ansible, Puppet, Pulumi, OpenTofu, AWS CDK, Crossplane, n8n, Aider, Claude Code, OpenHands, +23 more |
-| L10 — Knowledge Management | 25 | Zotero, Calibre, Paperless-ngx, Logseq, Joplin, ChromaDB, LanceDB, Qdrant, LlamaIndex, +16 more |
+| L8 — User Interfaces | 17 | Open WebUI, AnythingLLM, LibreChat, Flowise, Jan, InvokeAI, Forge (A1111), ComfyUI, Dashy, Obsidian, +7 more |
+| L9 — DevOps | 11 | Terraform, Ansible, Puppet, Pulumi, OpenTofu, AWS CDK, Crossplane, Terragrunt |
+| L10 — Knowledge Management | 26 | Zotero, Calibre, Paperless-ngx, Logseq, Joplin, Mem0, ChromaDB, LanceDB, Qdrant, LlamaIndex, +16 more |

diff --git a/bootstrap.sh b/bootstrap.sh
index ed9e324..661c51b 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────
-# AI Local Stack Control v3.1.0 — Ankh of Jah
+# AI Local Stack Control v3.1.1 — Ankh of Jah
# Bootstrap Script
#
# Fully portable: works wherever the tarball lands.
@@ -46,7 +46,7 @@ export AI_LSC_BASE_DIR="$AI_BASE"
echo ""
echo -e "${BOLD}╔══════════════════════════════════════════════════════╗${NC}"
-echo -e "${BOLD}║ AI Local Stack Control v3.1.0 — Ankh of Jah ║${NC}"
+echo -e "${BOLD}║ AI Local Stack Control v3.1.1 — Ankh of Jah ║${NC}"
echo -e "${BOLD}╚══════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN} Project root : ${SCRIPT_DIR}${NC}"
diff --git a/docs/screenshots/ai-lsc-about.png b/docs/screenshots/ai-lsc-about.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-centralized-git-repos-manager.png b/docs/screenshots/ai-lsc-centralized-git-repos-manager.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-chat.png b/docs/screenshots/ai-lsc-chat.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-deployment-targets.png b/docs/screenshots/ai-lsc-deployment-targets.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-infrastructure-is-the-tools-seen-by-ai-lsc.png b/docs/screenshots/ai-lsc-infrastructure-is-the-tools-seen-by-ai-lsc.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-install-verification-of-tool.png b/docs/screenshots/ai-lsc-install-verification-of-tool.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-monitor-active-workstation.png b/docs/screenshots/ai-lsc-monitor-active-workstation.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-settings.png b/docs/screenshots/ai-lsc-settings.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-skills-manager.png b/docs/screenshots/ai-lsc-skills-manager.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-stack-logic-editor.png b/docs/screenshots/ai-lsc-stack-logic-editor.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-tool-db-editor.png b/docs/screenshots/ai-lsc-tool-db-editor.png
old mode 100644
new mode 100755
diff --git a/docs/screenshots/ai-lsc-workspaces.png b/docs/screenshots/ai-lsc-workspaces.png
old mode 100644
new mode 100755
diff --git a/pyproject.toml b/pyproject.toml
index b825794..d3fab71 100755
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "ai-lsc"
-version = "3.1.0"
+version = "3.1.1"
description = "AI Local Stack Control — PySide6 desktop app for orchestrating local AI/ML tool stacks"
readme = "README.md"
license = {text = "AGPL-3.0-or-later"}
diff --git a/scripts/backfill_default_licenses.py b/scripts/backfill_default_licenses.py
index 3895190..8abe508 100755
--- a/scripts/backfill_default_licenses.py
+++ b/scripts/backfill_default_licenses.py
@@ -15,7 +15,7 @@ import re
import sys
from pathlib import Path
-ROOT = Path("/home/z/my-project/workspace/ai-lsc")
+ROOT = Path(__file__).resolve().parent.parent
LAYER_DIR = ROOT / "src/ai_lsc/registry/layers"
DEFAULTS_PATH = ROOT / "src/ai_lsc/registry/defaults.py"
diff --git a/scripts/backfill_layer_flags.py b/scripts/backfill_layer_flags.py
index d23dae7..8e21f2e 100755
--- a/scripts/backfill_layer_flags.py
+++ b/scripts/backfill_layer_flags.py
@@ -14,7 +14,7 @@ import re
import sys
from pathlib import Path
-LAYER_DIR = Path("/home/z/my-project/workspace/ai-lsc/src/ai_lsc/registry/layers")
+LAYER_DIR = Path(__file__).resolve().parent.parent / "src/ai_lsc/registry/layers"
REQUIRED_KEYS = [
"has_cli",
"has_gui",
diff --git a/scripts/backfill_tool_licenses.py b/scripts/backfill_tool_licenses.py
index 95a6246..0b4a0b4 100755
--- a/scripts/backfill_tool_licenses.py
+++ b/scripts/backfill_tool_licenses.py
@@ -18,7 +18,7 @@ import re
import sys
from pathlib import Path
-ROOT = Path("/home/z/my-project/workspace/ai-lsc")
+ROOT = Path(__file__).resolve().parent.parent
LAYER_DIR = ROOT / "src/ai_lsc/registry/layers"
DEFAULTS_PATH = ROOT / "src/ai_lsc/registry/defaults.py"
diff --git a/src/ai_lsc/agents/librechat_config.py b/src/ai_lsc/agents/librechat_config.py
index f523548..7bbdc5b 100755
--- a/src/ai_lsc/agents/librechat_config.py
+++ b/src/ai_lsc/agents/librechat_config.py
@@ -15,7 +15,7 @@ Usage
config.set_ollama_endpoint(ollama_port=11434)
config.set_litellm_endpoint(litellm_port=4000)
config.set_tool_schemas(tool_schemas)
- config.save("/mnt/AI/tools/librechat/librechat.yaml")
+ config.save("/mnt/AI/runtime/librechat/config.yaml")
"""
from __future__ import annotations
diff --git a/src/ai_lsc/agents/litellm_config.py b/src/ai_lsc/agents/litellm_config.py
index b2c6cba..6be40eb 100755
--- a/src/ai_lsc/agents/litellm_config.py
+++ b/src/ai_lsc/agents/litellm_config.py
@@ -16,7 +16,7 @@ Usage
config = LiteLLMConfigGenerator()
config.add_ollama_models(ollama_port=11434)
yaml_str = config.generate_yaml()
- config.save("/mnt/AI/config/litellm_config.yaml")
+ config.save("/mnt/AI/runtime/litellm/config.yaml")
"""
from __future__ import annotations
diff --git a/src/ai_lsc/constants.py b/src/ai_lsc/constants.py
index d678f3c..0d8ddce 100755
--- a/src/ai_lsc/constants.py
+++ b/src/ai_lsc/constants.py
@@ -19,7 +19,7 @@ BASE_DIR: str = os.environ.get("AI_LSC_BASE_DIR", "/mnt/AI")
CANONICAL_BASE_DIR: str = BASE_DIR
# ── Filenames ────────────────────────────────────────────────────────────
-APP_VERSION: str = "3.1.0"
+APP_VERSION: str = "3.1.1"
APP_CODENAME: str = "Ankh of Jah"
APP_DISPLAY_NAME: str = f"AI - Local Stack Control v{APP_VERSION} - http://dcos.net"
CONFIG_FILE: str = "controller_config.json"
@@ -31,29 +31,41 @@ MANIFEST_FILE_NAME: str = ".ai-lsc-project.json"
JCL_FILE_NAME: str = ".ai-lsc-jobs.json"
# ── Required sub-directories under BASE_DIR ────────────────────
+# The canonical /mnt/AI/ folder layout (v3.1.1b, 24 dirs). Per-tool
+# subdirs (runtime//, configs//, dashboards//) are
+# created on demand by InstallerManager; only top-level layout dirs are
+# listed here so a fresh install has the full skeleton.
+#
+# App-internal storage that is NOT part of the canonical layout:
+# registry/ — ecosystem.json tool DB (RegistryManager mkdirs it)
+# registry/manifests — SHA256 hashes, build logs, chunking records
+# bootstraps/ — legacy minimal bootstrap scripts (no longer created)
+# staging/ — legacy quarantine zone (no longer created)
REQUIRED_DIRS: list[str] = [
- "bin",
- "tools",
- "registry",
- "config",
- "cache",
- "runtime",
- "logs",
- "skills",
- "datasets/raw",
- "models/ollama",
- "models/chroma",
- "workspaces/hermes",
- "workspaces/openwebui",
- "workspaces/n8n",
- "tmp",
- "exports",
- "data",
- "containers",
- "configs",
- "pipelines",
- "dashboards",
- "backups",
+ "backends", # S3/MinIO/Ceph connection profiles + topology
+ "distfiles", # permanent mirror of raw source tarballs + installers
+ "runtime", # native compiled binaries (Ollama, llama.cpp, MinIO…)
+ "models/hot", # active weights; loaded or VRAM-ready (SSD)
+ "models/cold", # archived weights; offline / long-term retention (HDD)
+ "corpus/hot", # active text indexed in Vector DBs, used by agents
+ "corpus/cold", # raw, uningested, or unprocessed text archives
+ "datasets/wordlists", # fuzzing lists, dictionaries, tokenization test strings
+ "datasets/huggingface", # downloaded bulk datasets from Hugging Face
+ "datasets/github", # scraped or exported repository data
+ "pipelines", # ETL, chunking, and routing scripts (backends <-> DBs)
+ "configs", # app configs templated for native runtime + app state
+ "agents", # configs and chains for autonomous AI actors
+ "skills", # 3rd-party skill files (QA and MoE templates, …)
+ "projects/active", # primary focus; actively developed codebases
+ "projects/labs", # experimental, beta, or throwaway POC code
+ "projects/vault", # archived masters, cloned refs, strict git histories
+ "blueprints", # Dockerfiles and build contexts for Podman exports
+ "workspaces", # interactive execution envs (Jupyter, OpenNotebook…)
+ "dashboards", # web UIs and landing pages (Dashy, Open-WebUI, …)
+ "tools", # standalone compiles (built from distfiles)
+ "exports/oci-images", # finalized Podman .tar snapshots (-> MinIO registry)
+ "scripts", # system admin / maintenance automation for the stack
+ "logs", # system, runtime, and pipeline service logs
]
# ── Default ports for every known tool ───────────────────────────────────
@@ -123,7 +135,7 @@ TREE_SKIP_PATTERNS: set[str] = {".", "__pycache__", "node_modules", "vendor"}
# ── Navigation layer order for the sidebar rack diagram ───────────────
NAV_LAYER_ORDER: list[str] = [
"Host Platform", "Development Environment", "GPU Runtimes",
- "Engines", "Orchestrators", "Security",
+ "Engines", "Routing", "Orchestrators", "Security",
"Observability", "User Interfaces", "DevOps",
"Knowledge Management",
]
diff --git a/src/ai_lsc/registry/layers/development.py b/src/ai_lsc/registry/layers/development.py
index e9521ac..308a1dd 100755
--- a/src/ai_lsc/registry/layers/development.py
+++ b/src/ai_lsc/registry/layers/development.py
@@ -3,7 +3,7 @@
Each entry follows the standard registry schema:
- ``name``: human-readable tool name
-- ``level``: 10-layer taxonomy level (1-10)
+- ``level``: 11-layer taxonomy level (1-11)
- ``layer``: this layer name
- ``role``: role within the layer
- ``category``: functional category
@@ -890,4 +890,64 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'deno': {
+ "name": "Deno",
+ "level": 2,
+ "layer": "Development Environment",
+ "role": "Language",
+ "category": "Runtime",
+ "installer": {
+ "type": "pacman",
+ "pkg": "deno"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "deno --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "JavaScript/TypeScript/WASM runtime with secure-by-default "
+ "permissions and native TypeScript. Many MCP servers are "
+ "distributed as `deno run` one-liners.",
+ "license": "MIT",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+ },
+ 'uv': {
+ "name": "uv",
+ "level": 2,
+ "layer": "Development Environment",
+ "role": "Package Manager",
+ "category": "Build",
+ "installer": {
+ "type": "pacman",
+ "pkg": "uv"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "uv --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Astral's ultra-fast Python package and project manager. "
+ "Replaces pip/pipx/virtualenv workflows and is the "
+ "installer backend for AI-LSC's Python tool installs.",
+ "license": "MIT/Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+ },
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/devops.py b/src/ai_lsc/registry/layers/devops.py
index 06c566b..b124760 100755
--- a/src/ai_lsc/registry/layers/devops.py
+++ b/src/ai_lsc/registry/layers/devops.py
@@ -1,7 +1,9 @@
-"""Registry entries for the DevOps layer (L9).
+"""Registry entries for the DevOps layer (L10).
Contains Infrastructure as Code tools, configuration management, OCI
-runtime packaging, and provisioning tools.
+runtime packaging, provisioning tools, and AI coding agents
+(aider, claude_code, codex, openhands, opencode, gemini_cli,
+qwen_code, goose, zcoder).
This module is consumed by
:mod:`ai_lsc.registry.loader`.
@@ -10,7 +12,7 @@ This module is consumed by
TOOLS: dict[str, dict] = {
'terraform': {
"name": "Terraform",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC",
@@ -38,7 +40,7 @@ TOOLS: dict[str, dict] = {
},
'ansible': {
"name": "Ansible",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Configuration Management",
"category": "Config Management",
@@ -66,7 +68,7 @@ TOOLS: dict[str, dict] = {
},
'puppet': {
"name": "Puppet",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Configuration Management",
"category": "Config Management",
@@ -94,7 +96,7 @@ TOOLS: dict[str, dict] = {
},
'pulumi': {
"name": "Pulumi",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC",
@@ -122,7 +124,7 @@ TOOLS: dict[str, dict] = {
},
'bicep': {
"name": "Bicep",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC",
@@ -150,7 +152,7 @@ TOOLS: dict[str, dict] = {
},
'opentofu': {
"name": "OpenTofu",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC",
@@ -178,7 +180,7 @@ TOOLS: dict[str, dict] = {
},
'aws_cdk': {
"name": "AWS CDK",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC",
@@ -206,7 +208,7 @@ TOOLS: dict[str, dict] = {
},
'crossplane': {
"name": "Crossplane",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC Control Plane",
@@ -236,7 +238,7 @@ TOOLS: dict[str, dict] = {
},
'terragrunt': {
"name": "Terragrunt",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Infrastructure as Code",
"category": "IaC Wrapper",
@@ -266,7 +268,7 @@ TOOLS: dict[str, dict] = {
},
'stack_exporter': {
"name": "Stack Container Packager",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Runtime Packaging",
"category": "OCI Export",
@@ -294,7 +296,7 @@ TOOLS: dict[str, dict] = {
},
'homelab': {
"name": "Homelab",
- "level": 9,
+ "level": 10,
"layer": "DevOps",
"role": "Provisioning",
"category": "Provisioning",
@@ -321,4 +323,281 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'aider': {
+ "name": "Aider",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "uv",
+ "pkg": "aider-chat"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "aider --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "AI pair programming assistant that works in your terminal.",
+ "license": 'Apache-2.0',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'claude_code': {
+ "name": "Claude Code",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "@anthropic-ai/claude-code"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "claude --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Anthropic's CLI-based AI coding agent powered by Claude.",
+ "license": 'Proprietary',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'codex': {
+ "name": "Codex",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "@openai/codex"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "codex --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "OpenAI's CLI-based AI coding agent powered by GPT.",
+ "license": 'Proprietary',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'openhands': {
+ "name": "OpenHands",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "uv",
+ "pkg": "openhands-ai"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "openhands serve --port {port}",
+ "default_port": 3000
+ },
+ "deps": [],
+ "description": "Open-source AI coding agent platform with web UI for autonomous software engineering.",
+ "license": 'MIT',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'opencode': {
+ "name": "OpenCode",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "opencode-ai"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "opencode --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Open-source terminal AI coding agent from the SST team. "
+ "Native TUI, LSP integration, shareable sessions, and "
+ "75+ model providers including local Ollama.",
+ "license": "MIT",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'gemini_cli': {
+ "name": "Gemini CLI",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "@google/gemini-cli"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "gemini --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Google's open-source terminal AI agent. Supports "
+ "OpenAI-compatible local endpoints via OPENAI_BASE_URL, "
+ "MCP servers, and multi-turn agentic workflows.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'qwen_code': {
+ "name": "Qwen Code",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "@qwen-code/qwen-code"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "qwen --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Qwen's terminal-based agentic coding tool (Gemini CLI "
+ "fork) optimized for Qwen models, with subagents, MCP "
+ "support, and OpenAI-compatible local endpoints.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'goose': {
+ "name": "codename goose",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "custom",
+ "pkg": "https://github.com/block/goose"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "goose --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Block's open-source extensible AI agent. Runs MCP "
+ "extensions for coding, research, and automation; supports "
+ "local LLM backends including Ollama.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+# ---- zcoder -----------------------------------------------------------------
+ 'zcoder': {
+ "name": "ZCoder",
+ "level": 10,
+ "layer": "DevOps",
+ "role": "Coding Agent",
+ "category": "AI Coding Agent",
+ "installer": {
+ "type": "npm",
+ "pkg": "zcoder-cli"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "zcoder --version",
+ "default_port": None
+ },
+ "deps": [
+ "ollama"
+ ],
+ "description": "Zhipu AI Z-Coder CLI coding agent. Speaks OpenAI-compat "
+ "— point OPENAI_API_BASE at MeshLLM (localhost:9337/v1), "
+ "LiteLLM (localhost:4000/v1), or Ollama direct "
+ "(localhost:11434/v1). If the upstream package name "
+ "differs in your region, override installer.pkg in "
+ "your local registry.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/gpu.py b/src/ai_lsc/registry/layers/gpu.py
index 00da8bc..d229d51 100755
--- a/src/ai_lsc/registry/layers/gpu.py
+++ b/src/ai_lsc/registry/layers/gpu.py
@@ -3,7 +3,7 @@
Each entry follows the standard registry schema:
- ``name``: human-readable tool name
-- ``level``: 10-layer taxonomy level (1-10)
+- ``level``: 11-layer taxonomy level (1-11)
- ``layer``: this layer name
- ``role``: role within the layer
- ``category``: functional category
@@ -75,5 +75,35 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
+},
+ 'tinygrad': {
+ "name": "tinygrad",
+ "level": 3,
+ "layer": "GPU Runtimes",
+ "role": "GPU Acceleration",
+ "category": "GPU Computing",
+ "installer": {
+ "type": "uv",
+ "pkg": "tinygrad"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "python3 -c \"from tinygrad import Tensor; print(Tensor([1,2,3]).sum().item())\"",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Minimalist autograd tensor library with a PyTorch-like API "
+ "targeting CUDA, AMD, and CPU backends. Powers tinybox "
+ "inference serving.",
+ "license": "MIT",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": True,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
},
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/host_platform.py b/src/ai_lsc/registry/layers/host_platform.py
index d78fb98..52ebbf6 100755
--- a/src/ai_lsc/registry/layers/host_platform.py
+++ b/src/ai_lsc/registry/layers/host_platform.py
@@ -3,7 +3,7 @@
Each entry follows the standard registry schema:
- ``name``: human-readable tool name
-- ``level``: 10-layer taxonomy level (1-10)
+- ``level``: 11-layer taxonomy level (1-11)
- ``layer``: this layer name
- ``role``: role within the layer
- ``category``: functional category
@@ -306,11 +306,11 @@ TOOLS: dict[str, dict] = {
"category": "Virtualization",
"installer": {
"type": "script",
- "cmd": "curl -fsSL https://github.com/firecracker-microvm/firecracker/releases/latest/download/firecracker-v$(curl -s https://api.github.com/repos/firecracker-microvm/firecracker/releases/latest | grep tag_name | cut -d'\"' -f4)-x86_64.tgz | tar xz -C /usr/local/bin/"
+ "cmd": "mkdir -p {tools_root}/bin {tools_root}/firecracker && FC_VER=$(curl -sIL https://github.com/firecracker-microvm/firecracker/releases/latest | grep -i '^location:' | tail -1 | sed 's|.*/tag/||' | tr -d '\r') && curl -fsSL 'https://github.com/firecracker-microvm/firecracker/releases/download/$FC_VER/firecracker-$FC_VER-x86_64.tgz' | tar xz -C {tools_root}/firecracker --strip-components=1 && ln -sf {tools_root}/firecracker/firecracker-$FC_VER-x86_64 {tools_root}/bin/firecracker && ln -sf {tools_root}/firecracker/jailer-$FC_VER-x86_64 {tools_root}/bin/jailer"
},
"launcher": {
"type": "desktop",
- "cmd": "firecracker --version",
+ "cmd": "{tools_root}/bin/firecracker --version",
"default_port": None
},
"deps": [],
@@ -390,11 +390,11 @@ TOOLS: dict[str, dict] = {
"category": "Networking",
"installer": {
"type": "script",
- "cmd": "curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared"
+ "cmd": "mkdir -p {tools_root}/bin && curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o {tools_root}/bin/cloudflared && chmod +x {tools_root}/bin/cloudflared"
},
"launcher": {
"type": "tmux",
- "cmd": "cloudflared tunnel --url http://localhost:{port}",
+ "cmd": "{tools_root}/bin/cloudflared tunnel --url http://localhost:{port}",
"default_port": 8080
},
"deps": [],
diff --git a/src/ai_lsc/registry/layers/inference.py b/src/ai_lsc/registry/layers/inference.py
index 0b2120e..9283483 100755
--- a/src/ai_lsc/registry/layers/inference.py
+++ b/src/ai_lsc/registry/layers/inference.py
@@ -3,7 +3,7 @@
Each entry follows the standard registry schema:
- ``name``: human-readable tool name
-- ``level``: 10-layer taxonomy level (1-10)
+- ``level``: 11-layer taxonomy level (1-11)
- ``layer``: this layer name
- ``role``: role within the layer
- ``category``: functional category
@@ -110,7 +110,7 @@ TOOLS: dict[str, dict] = {
"category": "Single-File LLM",
"installer": {
"type": "script",
- "cmd": "curl -LO https://github.com/Mozilla-Ocho/llamafile/releases/latest/download/llamafile && chmod +x llamafile"
+ "cmd": "mkdir -p {tools_root}/bin && curl -L https://github.com/Mozilla-Ocho/llamafile/releases/latest/download/llamafile -o {tools_root}/bin/llamafile && chmod +x {tools_root}/bin/llamafile"
},
"launcher": {
"type": "desktop",
@@ -251,4 +251,68 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'vllm': {
+ "name": "vLLM",
+ "level": 4,
+ "layer": "Engines",
+ "role": "Engine",
+ "category": "LLM Serving",
+ "installer": {
+ "type": "uv",
+ "pkg": "vllm"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "python -m vllm.entrypoints.openai.api_server --port {port}",
+ "default_port": 8000
+ },
+ "deps": [
+ "cuda"
+ ],
+ "description": "High-throughput and memory-efficient LLM serving.",
+ "license": 'Apache-2.0',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'sglang': {
+ "name": "SGLang",
+ "level": 4,
+ "layer": "Engines",
+ "role": "Engine",
+ "category": "LLM Serving",
+ "installer": {
+ "type": "uv",
+ "pkg": "sglang"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "python -m sglang.launch_server --port {port}",
+ "default_port": 30000
+ },
+ "deps": [
+ "cuda"
+ ],
+ "description": "Fast LLM serving engine with RadixAttention prefix "
+ "caching, structured generation, and an OpenAI-compatible "
+ "API.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/knowledge_management.py b/src/ai_lsc/registry/layers/knowledge_management.py
index f068704..74e3048 100755
--- a/src/ai_lsc/registry/layers/knowledge_management.py
+++ b/src/ai_lsc/registry/layers/knowledge_management.py
@@ -1,4 +1,4 @@
-"""Registry entries for the Knowledge Management layer (L10).
+"""Registry entries for the Knowledge Management layer (L11).
Contains vector stores, graph databases, search engines, document parsers,
data pipelines, memory systems, and knowledge management tools.
@@ -10,7 +10,7 @@ This module is consumed by
TOOLS: dict[str, dict] = {
'zotero': {
"name": "Zotero",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Reference Manager",
"category": "Academic References",
@@ -38,7 +38,7 @@ TOOLS: dict[str, dict] = {
},
'calibre': {
"name": "Calibre",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Library Manager",
"category": "Ebook Library",
@@ -66,7 +66,7 @@ TOOLS: dict[str, dict] = {
},
'paperlessngx': {
"name": "Paperless-ngx",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Document Archive",
"category": "Document Management",
@@ -97,7 +97,7 @@ TOOLS: dict[str, dict] = {
},
'logseq': {
"name": "Logseq",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Knowledge Graph",
"category": "Outliner",
@@ -125,7 +125,7 @@ TOOLS: dict[str, dict] = {
},
'joplin': {
"name": "Joplin",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Note Taking",
"category": "Notes",
@@ -153,7 +153,7 @@ TOOLS: dict[str, dict] = {
},
'chromadb': {
"name": "ChromaDB",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Vector Store",
@@ -181,7 +181,7 @@ TOOLS: dict[str, dict] = {
},
'lancedb': {
"name": "LanceDB",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Vector Store",
@@ -209,7 +209,7 @@ TOOLS: dict[str, dict] = {
},
'qdrant': {
"name": "Qdrant",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Vector Store",
@@ -242,7 +242,7 @@ TOOLS: dict[str, dict] = {
},
'neo4j': {
"name": "Neo4j",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Graph Database",
@@ -270,7 +270,7 @@ TOOLS: dict[str, dict] = {
},
'elasticsearch': {
"name": "Elasticsearch",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Search Engine",
@@ -298,13 +298,13 @@ TOOLS: dict[str, dict] = {
},
'meilisearch': {
"name": "Meilisearch",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Search Engine",
"installer": {
"type": "script",
- "cmd": "curl -L https://install.meilisearch.com | sh"
+ "cmd": "mkdir -p {tools_root}/bin && cd {tools_root}/bin && curl -L https://install.meilisearch.com | sh"
},
"launcher": {
"type": "tmux",
@@ -326,7 +326,7 @@ TOOLS: dict[str, dict] = {
},
'graphrag': {
"name": "GraphRAG",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Knowledge Synthesis",
"category": "Graph RAG",
@@ -354,7 +354,7 @@ TOOLS: dict[str, dict] = {
},
'turbovec': {
"name": "TurboVec",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Embedding",
"category": "Vector Engine",
@@ -384,7 +384,7 @@ TOOLS: dict[str, dict] = {
},
'airweave': {
"name": "Airweave",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Integration",
"category": "Data Sync",
@@ -412,7 +412,7 @@ TOOLS: dict[str, dict] = {
},
'crawl4ai': {
"name": "Crawl4AI",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Data Harvesting",
"category": "Web Crawler",
@@ -440,7 +440,7 @@ TOOLS: dict[str, dict] = {
},
'docling': {
"name": "Docling",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "File Parsing",
@@ -468,7 +468,7 @@ TOOLS: dict[str, dict] = {
},
'markitdown': {
"name": "MarkItDown",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "File Parsing",
"category": "Document Converter",
@@ -496,7 +496,7 @@ TOOLS: dict[str, dict] = {
},
'opendataloader': {
"name": "OpenDataLoader",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Ingestion",
"category": "Data Pipeline",
@@ -524,7 +524,7 @@ TOOLS: dict[str, dict] = {
},
'whisper': {
"name": "Whisper",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Audio Parsing",
@@ -552,7 +552,7 @@ TOOLS: dict[str, dict] = {
},
'mnemosyne': {
"name": "Mnemosyne",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Spaced Repetition",
@@ -580,7 +580,7 @@ TOOLS: dict[str, dict] = {
},
'mnemo_cortex': {
"name": "Mnemo Cortex",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Cortex Memory",
@@ -610,7 +610,7 @@ TOOLS: dict[str, dict] = {
},
'everos_memory': {
"name": "EverOS Memory",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Memory",
"category": "Persistent Memory",
@@ -638,7 +638,7 @@ TOOLS: dict[str, dict] = {
},
'mirofish': {
"name": "Mirofish",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Transform",
"category": "Data Pipeline",
@@ -666,7 +666,7 @@ TOOLS: dict[str, dict] = {
},
'opendataloader_pdf': {
"name": "OpenDataLoader PDF",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Extraction",
"category": "PDF Pipeline",
@@ -694,7 +694,7 @@ TOOLS: dict[str, dict] = {
},
'understand_anything': {
"name": "Understand Anything",
- "level": 10,
+ "level": 11,
"layer": "Knowledge Management",
"role": "Comprehension",
"category": "Document Understanding",
@@ -721,5 +721,35 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
+},
+ 'mem0': {
+ "name": "Mem0",
+ "level": 11,
+ "layer": "Knowledge Management",
+ "role": "Memory",
+ "category": "Memory System",
+ "installer": {
+ "type": "uv",
+ "pkg": "mem0ai"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "python3 -c \"import mem0; print('ok')\"",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Memory layer for AI applications and agents — extracts, "
+ "stores, and retrieves long-term user/agent memories across "
+ "sessions, backed by pluggable vector stores.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": True,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
},
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/observability.py b/src/ai_lsc/registry/layers/observability.py
index 5f4a808..64649e5 100755
--- a/src/ai_lsc/registry/layers/observability.py
+++ b/src/ai_lsc/registry/layers/observability.py
@@ -1,6 +1,7 @@
-"""Registry entries for the Observability layer (L7).
+"""Registry entries for the Observability layer (L8).
-Contains metrics, dashboards, tracing, AI monitoring, and LLM evaluation tools.
+Contains metrics, dashboards, tracing, AI monitoring, LLM
+evaluation, and build/system monitoring tools.
This module is consumed by
:mod:`ai_lsc.registry.loader`.
@@ -9,7 +10,7 @@ This module is consumed by
TOOLS: dict[str, dict] = {
'btop': {
"name": "Btop",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Dashboard",
"category": "Metrics",
@@ -37,7 +38,7 @@ TOOLS: dict[str, dict] = {
},
'glances': {
"name": "Glances",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Dashboard",
"category": "Metrics",
@@ -65,7 +66,7 @@ TOOLS: dict[str, dict] = {
},
'prometheus': {
"name": "Prometheus",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Metrics Collector",
"category": "Metrics",
@@ -93,7 +94,7 @@ TOOLS: dict[str, dict] = {
},
'grafana': {
"name": "Grafana",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Dashboard",
"category": "Visualization",
@@ -121,17 +122,17 @@ TOOLS: dict[str, dict] = {
},
'grafana_alloy': {
"name": "Grafana Alloy",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Collector",
"category": "Telemetry",
"installer": {
"type": "script",
- "cmd": "curl -fsSL https://raw.githubusercontent.com/grafana/alloy/main/install.sh | sh"
+ "cmd": "mkdir -p {tools_root}/bin {tools_root}/alloy && curl -fsSL https://github.com/grafana/alloy/releases/latest/download/alloy-linux-amd64.zip -o {tools_root}/alloy/alloy.zip && python3 -m zipfile -e {tools_root}/alloy/alloy.zip {tools_root}/alloy && mv {tools_root}/alloy/alloy-linux-amd64 {tools_root}/bin/alloy && chmod +x {tools_root}/bin/alloy"
},
"launcher": {
"type": "tmux",
- "cmd": "alloy run --server.http.listen-port={port}",
+ "cmd": "{tools_root}/bin/alloy run --server.http.listen-port={port}",
"default_port": 12345
},
"deps": [
@@ -151,7 +152,7 @@ TOOLS: dict[str, dict] = {
},
'opik': {
"name": "Opik",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "LLM Tracing",
"category": "AI Observability",
@@ -179,7 +180,7 @@ TOOLS: dict[str, dict] = {
},
'pulse_ai': {
"name": "Pulse AI",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Health Monitor",
"category": "AI Monitoring",
@@ -207,7 +208,7 @@ TOOLS: dict[str, dict] = {
},
'latitude': {
"name": "Latitude",
- "level": 7,
+ "level": 8,
"layer": "Observability",
"role": "Evaluation",
"category": "LLM Evaluation",
@@ -235,4 +236,64 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'eagle_eye': {
+ "name": "Eagle Eye",
+ "level": 8,
+ "layer": "Observability",
+ "role": "Monitoring",
+ "category": "Observability",
+ "installer": {
+ "type": "git",
+ "pkg": "https://github.com/nicely-done/eagle_eye"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "eagle_eye --version",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "AI-powered observability and monitoring agent.",
+ "license": 'Proprietary',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'dma': {
+ "name": "DMA (Distcc Monitor Agent)",
+ "level": 8,
+ "layer": "Observability",
+ "role": "Monitoring",
+ "category": "Build Monitoring",
+ "installer": {
+ "type": "git",
+ "pkg": "https://github.com/distcc/dma"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "dma --version",
+ "default_port": None
+ },
+ "deps": [
+ "distcc"
+ ],
+ "description": "Monitor for distributed compilation with distcc.",
+ "license": 'Proprietary',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/orchestrators.py b/src/ai_lsc/registry/layers/orchestrators.py
index a9b9f44..b683fa1 100755
--- a/src/ai_lsc/registry/layers/orchestrators.py
+++ b/src/ai_lsc/registry/layers/orchestrators.py
@@ -1,46 +1,18 @@
-"""Registry entries for the Orchestrators layer (L5).
+"""Registry entries for the Orchestrators layer (L6).
-Contains distributed compute, LLM serving, agent orchestration,
-workflow routing, pipeline coordination, and multi-agent frameworks.
+Contains distributed compute, agent orchestration, workflow
+engines, pipeline coordination, and multi-agent frameworks.
+(LLM serving moved to Engines; routing/gateways to Routing;
+coding agents to DevOps in the 11-layer taxonomy.)
This module is consumed by
:mod:`ai_lsc.registry.loader`.
"""
TOOLS: dict[str, dict] = {
- 'vllm': {
- "name": "vLLM",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Scaling",
- "category": "LLM Serving",
- "installer": {
- "type": "uv",
- "pkg": "vllm"
- },
- "launcher": {
- "type": "tmux",
- "cmd": "python -m vllm.entrypoints.openai.api_server --port {port}",
- "default_port": 8000
- },
- "deps": [
- "cuda"
- ],
- "description": "High-throughput and memory-efficient LLM serving.",
- "license": 'Apache-2.0',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": True,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
-},
'distcc': {
"name": "DistCC",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Distribution",
"category": "Distributed Compilation",
@@ -65,40 +37,10 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
-},
- 'dma': {
- "name": "DMA (Distcc Monitor Agent)",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Monitoring",
- "category": "Build Monitoring",
- "installer": {
- "type": "git",
- "pkg": "https://github.com/distcc/dma"
- },
- "launcher": {
- "type": "desktop",
- "cmd": "dma --version",
- "default_port": None
- },
- "deps": [
- "distcc"
- ],
- "description": "Monitor for distributed compilation with distcc.",
- "license": 'Proprietary',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": False,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
},
'ray': {
"name": "Ray",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Scaling",
"category": "Distributed Compute",
@@ -126,7 +68,7 @@ TOOLS: dict[str, dict] = {
},
'pssh': {
"name": "PSSH (Parallel SSH)",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Coordination",
"category": "Cluster SSH",
@@ -151,68 +93,10 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
-},
- 'litellm': {
- "name": "LiteLLM Proxy",
- "level": 5,
- "layer": "Orchestrators",
- "role": "API Gateway",
- "category": "Proxy",
- "installer": {
- "type": "uv",
- "pkg": "litellm"
- },
- "launcher": {
- "type": "tmux",
- "cmd": "litellm --port {port}",
- "default_port": 4000
- },
- "deps": [],
- "description": "Call 100+ LLMs using the OpenAI format.",
- "license": 'MIT',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": True,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
-},
- '9router_proxy': {
- "name": "9Router Proxy",
- "level": 5,
- "layer": "Orchestrators",
- "role": "API Gateway",
- "category": "LLM Router",
- "installer": {
- "type": "git",
- "pkg": "https://github.com/nicely-done/9router"
- },
- "launcher": {
- "type": "tmux",
- "cmd": "cd {tools_root}/9router && python3 main.py --port {port}",
- "default_port": 4001
- },
- "deps": [
- "ollama"
- ],
- "description": "Intelligent LLM request router and load balancer.",
- "license": 'MIT',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": True,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
},
'langchain': {
"name": "LangChain",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Orchestration",
"category": "LLM Framework",
@@ -240,7 +124,7 @@ TOOLS: dict[str, dict] = {
},
'langflow': {
"name": "LangFlow",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Visual Builder",
"category": "Workflow",
@@ -268,7 +152,7 @@ TOOLS: dict[str, dict] = {
},
'crewai': {
"name": "CrewAI",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Brain",
"category": "Agent Workflow",
@@ -296,7 +180,7 @@ TOOLS: dict[str, dict] = {
},
'autogen': {
"name": "AutoGen",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Brain",
"category": "Agent Workflow",
@@ -324,7 +208,7 @@ TOOLS: dict[str, dict] = {
},
'openai_swarm': {
"name": "OpenAI Swarm",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Multi-Agent",
"category": "Agent Framework",
@@ -352,7 +236,7 @@ TOOLS: dict[str, dict] = {
},
'agno': {
"name": "Agno",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Agent Framework",
"category": "AI Agent",
@@ -380,7 +264,7 @@ TOOLS: dict[str, dict] = {
},
'nvidia_agent_skills': {
"name": "NVIDIA Agent Skills",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Tool Integration",
"category": "Agent Toolkit",
@@ -410,7 +294,7 @@ TOOLS: dict[str, dict] = {
},
'openbrain': {
"name": "OpenBrain",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Brain",
"category": "Reasoning Engine",
@@ -440,7 +324,7 @@ TOOLS: dict[str, dict] = {
},
'odysseus': {
"name": "Odysseus",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Reasoning",
"category": "Agent Workflow",
@@ -467,43 +351,10 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
-},
- 'dify': {
- "name": "Dify",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Pipeline Orchestrator",
- "category": "Pipeline",
- "installer": {
- "type": "git",
- "pkg": "https://github.com/langgenius/dify.git"
- },
- "launcher": {
- "type": "tmux",
- "cmd": "cd {tools_root}/dify/api && poetry run flask run --host 0.0.0.0 --port={port}",
- "default_port": 5001
- },
- "deps": [
- "postgresql",
- "redis",
- "python",
- "node"
- ],
- "description": "LLM application development platform (native install). Requires Poetry, Node.js 18+, FFmpeg. Backend (Flask) + Celery worker + Next.js frontend run as separate services.",
- "license": 'Dify-OSL',
- "flags": {
- "has_cli": False,
- "has_gui": False,
- "has_web": True,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
},
'n8n': {
"name": "n8n",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Workflow Orchestrator",
"category": "Workflow Automation",
@@ -534,7 +385,7 @@ TOOLS: dict[str, dict] = {
},
'fabric': {
"name": "Fabric",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Curation",
"category": "AI Augmentation",
@@ -564,7 +415,7 @@ TOOLS: dict[str, dict] = {
},
'synapscli': {
"name": "SynapsCLI",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Agent",
"category": "AI Agent",
@@ -593,7 +444,7 @@ TOOLS: dict[str, dict] = {
},
'hivemind': {
"name": "HiveMind",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Coordination",
"category": "Multi-Agent",
@@ -623,7 +474,7 @@ TOOLS: dict[str, dict] = {
},
'hermes_agent': {
"name": "Hermes Agent",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Agent",
"category": "AI Agent",
@@ -653,7 +504,7 @@ TOOLS: dict[str, dict] = {
},
'agentic_os': {
"name": "Agentic OS",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Hands",
"category": "Agent OS",
@@ -683,7 +534,7 @@ TOOLS: dict[str, dict] = {
},
'mcp_drift_state_tracker': {
"name": "MCP Drift State Tracker",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Code Audit",
"category": "MCP Server",
@@ -713,7 +564,7 @@ TOOLS: dict[str, dict] = {
},
'glassmind': {
"name": "GlassMind",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Reasoning",
"category": "Reasoning Engine",
@@ -740,122 +591,10 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
-},
- 'aider': {
- "name": "Aider",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Coding Agent",
- "category": "AI Coding Agent",
- "installer": {
- "type": "uv",
- "pkg": "aider-chat"
- },
- "launcher": {
- "type": "desktop",
- "cmd": "aider --version",
- "default_port": None
- },
- "deps": [],
- "description": "AI pair programming assistant that works in your terminal.",
- "license": 'Apache-2.0',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": False,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
-},
- 'claude_code': {
- "name": "Claude Code",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Coding Agent",
- "category": "AI Coding Agent",
- "installer": {
- "type": "npm",
- "pkg": "@anthropic-ai/claude-code"
- },
- "launcher": {
- "type": "desktop",
- "cmd": "claude --version",
- "default_port": None
- },
- "deps": [],
- "description": "Anthropic's CLI-based AI coding agent powered by Claude.",
- "license": 'Proprietary',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": False,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
-},
- 'codex': {
- "name": "Codex",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Coding Agent",
- "category": "AI Coding Agent",
- "installer": {
- "type": "npm",
- "pkg": "@openai/codex"
- },
- "launcher": {
- "type": "desktop",
- "cmd": "codex --version",
- "default_port": None
- },
- "deps": [],
- "description": "OpenAI's CLI-based AI coding agent powered by GPT.",
- "license": 'Proprietary',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": False,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
-},
- 'openhands': {
- "name": "OpenHands",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Coding Agent",
- "category": "AI Coding Agent",
- "installer": {
- "type": "uv",
- "pkg": "openhands-ai"
- },
- "launcher": {
- "type": "tmux",
- "cmd": "openhands serve --port {port}",
- "default_port": 3000
- },
- "deps": [],
- "description": "Open-source AI coding agent platform with web UI for autonomous software engineering.",
- "license": 'MIT',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": True,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
},
'honcho': {
"name": "Honcho",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Process Manager",
"category": "Workflow Automation",
@@ -880,44 +619,16 @@ TOOLS: dict[str, dict] = {
"is_mcp": False,
"is_skills_collection": False
}
-},
- 'eagle_eye': {
- "name": "Eagle Eye",
- "level": 5,
- "layer": "Orchestrators",
- "role": "Monitoring",
- "category": "Observability",
- "installer": {
- "type": "git",
- "pkg": "https://github.com/nicely-done/eagle_eye"
- },
- "launcher": {
- "type": "desktop",
- "cmd": "eagle_eye --version",
- "default_port": None
- },
- "deps": [],
- "description": "AI-powered observability and monitoring agent.",
- "license": 'Proprietary',
- "flags": {
- "has_cli": True,
- "has_gui": False,
- "has_web": False,
- "is_ollama": False,
- "is_passive": False,
- "is_mcp": False,
- "is_skills_collection": False
- }
},
'graphify': {
"name": "Graphify",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
- "role": "Graph Builder",
- "category": "AI Agent",
+ "role": "Knowledge Graph Builder",
+ "category": "Claude Code Skill",
"installer": {
- "type": "git",
- "pkg": "https://github.com/nicely-done/graphify"
+ "type": "uv",
+ "pkg": "graphifyy"
},
"launcher": {
"type": "desktop",
@@ -925,21 +636,31 @@ TOOLS: dict[str, dict] = {
"default_port": None
},
"deps": [],
- "description": "Graph-based knowledge and workflow visualization agent.",
- "license": 'Proprietary',
+ "description": "Knowledge graph builder for code, docs, PDFs, and "
+ "images. Installs as a Claude Code skill (type "
+ "`/graphify .` in Claude Code) or runs standalone "
+ "via CLI. Builds interactive graph.html, Obsidian "
+ "vault, Wikipedia-style wiki, and persistent "
+ "graph.json from any folder. MCP stdio server mode "
+ "(`graphify --mcp`) lets other agents query the "
+ "graph. Uses Claude vision by default; can be "
+ "configured to use any OpenAI-compat endpoint "
+ "(MeshLLM, LiteLLM, Ollama) for extraction. PyPI "
+ "package is `graphifyy` (CLI is `graphify`).",
+ "license": "MIT",
"flags": {
"has_cli": True,
"has_gui": False,
- "has_web": False,
+ "has_web": True,
"is_ollama": False,
"is_passive": False,
- "is_mcp": False,
+ "is_mcp": True,
"is_skills_collection": False
}
},
'headroom': {
"name": "Headroom",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Resource Manager",
"category": "Infrastructure",
@@ -967,7 +688,7 @@ TOOLS: dict[str, dict] = {
},
'loop_engineering': {
"name": "Loop Engineering",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Engineering Loop",
"category": "Workflow Automation",
@@ -995,7 +716,7 @@ TOOLS: dict[str, dict] = {
},
'nightshift': {
"name": "Nightshift",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Night Ops",
"category": "Workflow Automation",
@@ -1023,7 +744,7 @@ TOOLS: dict[str, dict] = {
},
'opensandbox': {
"name": "OpenSandbox",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Sandbox",
"category": "Container Ops",
@@ -1051,7 +772,7 @@ TOOLS: dict[str, dict] = {
},
'ponytail': {
"name": "Ponytail",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "CI/CD",
"category": "Workflow Automation",
@@ -1079,7 +800,7 @@ TOOLS: dict[str, dict] = {
},
'promptops': {
"name": "PromptOps",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Prompt Ops",
"category": "AI Agent",
@@ -1107,7 +828,7 @@ TOOLS: dict[str, dict] = {
},
'agent_reach': {
"name": "Agent Reach",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Agent Discovery",
"category": "Multi-Agent",
@@ -1135,7 +856,7 @@ TOOLS: dict[str, dict] = {
},
'algory': {
"name": "Algory",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Algorithm",
"category": "AI Agent",
@@ -1163,7 +884,7 @@ TOOLS: dict[str, dict] = {
},
'atlas_os': {
"name": "Atlas OS",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "OS Framework",
"category": "Agent OS",
@@ -1191,7 +912,7 @@ TOOLS: dict[str, dict] = {
},
'career_ops': {
"name": "Career Ops",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Career Ops",
"category": "Workflow Automation",
@@ -1219,7 +940,7 @@ TOOLS: dict[str, dict] = {
},
'container_tool': {
"name": "Container Tool",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Containerization",
"category": "Container Ops",
@@ -1247,7 +968,7 @@ TOOLS: dict[str, dict] = {
},
'pm_skills': {
"name": "PM Skills",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Project Management",
"category": "Workflow Automation",
@@ -1275,7 +996,7 @@ TOOLS: dict[str, dict] = {
},
'skillspector': {
"name": "Skillspector",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Skill Inspector",
"category": "AI Agent",
@@ -1303,7 +1024,7 @@ TOOLS: dict[str, dict] = {
},
'spec_kit': {
"name": "Spec Kit",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Specification",
"category": "AI Agent",
@@ -1331,7 +1052,7 @@ TOOLS: dict[str, dict] = {
},
'wayland_ai': {
"name": "Wayland AI",
- "level": 5,
+ "level": 6,
"layer": "Orchestrators",
"role": "Agent Orchestrator",
"category": "AI Agent",
@@ -1358,4 +1079,35 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'letta': {
+ "name": "Letta",
+ "level": 6,
+ "layer": "Orchestrators",
+ "role": "Agent Framework",
+ "category": "Agent Framework",
+ "installer": {
+ "type": "uv",
+ "pkg": "letta"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "letta server --port {port}",
+ "default_port": 8283
+ },
+ "deps": [],
+ "description": "Stateful agent framework (MemGPT) with persistent memory, "
+ "self-editing agents, and a REST API server for agent "
+ "management.",
+ "license": "Apache-2.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/layers/routing.py b/src/ai_lsc/registry/layers/routing.py
new file mode 100644
index 0000000..66cd2dd
--- /dev/null
+++ b/src/ai_lsc/registry/layers/routing.py
@@ -0,0 +1,187 @@
+"""Registry entries for the Routing layer (L5).
+
+Restored layer (v3.1.1b): model gateways, LLM proxies, request routers,
+mesh transport, and the model-routing tier that sits between the Engines
+(who serve weights) and the Orchestrators (who build agent workflows on
+top of a single OpenAI-compatible endpoint). This re-unites the old
+13-layer model's "AI Endpoints" tier (LiteLLM, model routers, API
+gateways) that had been folded into Orchestrators during the 13-to-10
+reorg, plus the mesh-aware clients that ride on it.
+
+This module is consumed by :mod:`ai_lsc.registry.loader`.
+"""
+
+TOOLS: dict[str, dict] = {
+ 'litellm': {
+ "name": "LiteLLM Proxy",
+ "level": 5,
+ "layer": "Routing",
+ "role": "API Gateway",
+ "category": "Proxy",
+ "installer": {
+ "type": "uv",
+ "pkg": "litellm"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "litellm --port {port}",
+ "default_port": 4000
+ },
+ "deps": [],
+ "description": "Call 100+ LLMs using the OpenAI format.",
+ "license": 'MIT',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ '9router_proxy': {
+ "name": "9Router Proxy",
+ "level": 5,
+ "layer": "Routing",
+ "role": "API Gateway",
+ "category": "LLM Router",
+ "installer": {
+ "type": "git",
+ "pkg": "https://github.com/nicely-done/9router"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "cd {tools_root}/9router && python3 main.py --port {port}",
+ "default_port": 4001
+ },
+ "deps": [
+ "ollama"
+ ],
+ "description": "Intelligent LLM request router and load balancer.",
+ "license": 'MIT',
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+# ---- meshllm ----------------------------------------------------------------
+# MeshLLM is its own native binary — NOT a LiteLLM re-skin. It pools GPUs
+# and memory across machines, exposes one OpenAI-compat API at :9337, and
+# has a web console at :3131. Install via the official curl installer.
+ 'meshllm': {
+ "name": "MeshLLM",
+ "level": 5,
+ "layer": "Routing",
+ "role": "API Gateway",
+ "category": "LLM Mesh",
+ "installer": {
+ "type": "script",
+ "cmd": "mkdir -p {tools_root}/meshllm/bin && curl -fsSL https://raw.githubusercontent.com/Mesh-LLM/mesh-llm/main/install.sh | MESH_LLM_INSTALL_DIR={tools_root}/meshllm/bin bash"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "mesh-llm serve --auto --port {port}",
+ "default_port": 9337
+ },
+ "deps": [],
+ "description": "Native binary that pools GPUs and memory across "
+ "machines and exposes the result as one OpenAI-"
+ "compatible API at http://localhost:9337/v1. Start "
+ "one node, add more nodes later — the mesh decides "
+ "whether a model runs locally, routes to a peer, or "
+ "uses Skippy stage splits for models too large for "
+ "one box. Web console on :3131. Has subcommands "
+ "(`mesh-llm goose`, `mesh-llm opencode`, `mesh-llm "
+ "claude`, `mesh-llm pi`) that wrap other coding agents "
+ "to use the mesh. QUIC-encrypted peer transport via "
+ "Iroh relays. NOT a LiteLLM derivative — distinct "
+ "project at https://github.com/Mesh-LLM/mesh-llm.",
+ "license": "MIT",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+ 'dify': {
+ "name": "Dify",
+ "level": 5,
+ "layer": "Routing",
+ "role": "Pipeline Orchestrator",
+ "category": "Pipeline",
+ "installer": {
+ "type": "git",
+ "pkg": "https://github.com/langgenius/dify.git"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "cd {tools_root}/dify/api && poetry run flask run --host 0.0.0.0 --port={port}",
+ "default_port": 5001
+ },
+ "deps": [
+ "postgresql",
+ "redis",
+ "python",
+ "nodejs"
+ ],
+ "description": "LLM application development platform (native install). Requires Poetry, Node.js 18+, FFmpeg. Backend (Flask) + Celery worker + Next.js frontend run as separate services.",
+ "license": 'Dify-OSL',
+ "flags": {
+ "has_cli": False,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+'picode': {
+ "name": "PiCode",
+ "level": 5,
+ "layer": "Routing",
+ "role": "Coding Agent",
+ "category": "Mesh Client",
+ "installer": {
+ "type": "git",
+ "pkg": "https://github.com/jasonjmcghee/picode.git"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "picode --version",
+ "default_port": None
+ },
+ "deps": [
+ "ollama"
+ ],
+ "description": "Local code-tinker agent. Speaks OpenAI-compat — point "
+ "OPENAI_API_BASE at the mesh (localhost:9337 for MeshLLM, "
+ "localhost:4000 for LiteLLM) or directly at Ollama "
+ "(localhost:11434/v1).",
+ "license": "MIT",
+ "flags": {
+ "has_cli": True,
+ "has_gui": False,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
+}
diff --git a/src/ai_lsc/registry/layers/security.py b/src/ai_lsc/registry/layers/security.py
index 2550a55..68c2992 100755
--- a/src/ai_lsc/registry/layers/security.py
+++ b/src/ai_lsc/registry/layers/security.py
@@ -1,4 +1,4 @@
-"""Registry entries for the Security layer (L6).
+"""Registry entries for the Security layer (L7).
Contains identity management, secrets management, container scanning,
intrusion prevention, antivirus, and policy enforcement tools for
@@ -11,7 +11,7 @@ This module is consumed by
TOOLS: dict[str, dict] = {
'keycloak': {
"name": "Keycloak",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "Identity",
"category": "Auth",
@@ -39,7 +39,7 @@ TOOLS: dict[str, dict] = {
},
'vault': {
"name": "HashiCorp Vault",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "Secrets",
"category": "Secrets Management",
@@ -67,7 +67,7 @@ TOOLS: dict[str, dict] = {
},
'trivy': {
"name": "Trivy",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "Scanner",
"category": "Container Security",
@@ -95,7 +95,7 @@ TOOLS: dict[str, dict] = {
},
'fail2ban': {
"name": "Fail2Ban",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "IDS",
"category": "Intrusion Prevention",
@@ -123,7 +123,7 @@ TOOLS: dict[str, dict] = {
},
'clamav': {
"name": "ClamAV",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "Scanner",
"category": "Antivirus",
@@ -151,7 +151,7 @@ TOOLS: dict[str, dict] = {
},
'opa': {
"name": "Open Policy Agent",
- "level": 6,
+ "level": 7,
"layer": "Security",
"role": "Policy",
"category": "Policy Engine",
diff --git a/src/ai_lsc/registry/layers/user_interfaces.py b/src/ai_lsc/registry/layers/user_interfaces.py
index c3d5407..b0e18bf 100755
--- a/src/ai_lsc/registry/layers/user_interfaces.py
+++ b/src/ai_lsc/registry/layers/user_interfaces.py
@@ -1,4 +1,4 @@
-"""Registry entries for the User Interfaces layer (L8).
+"""Registry entries for the User Interfaces layer (L9).
Contains frontends, dashboards, chat UIs, image generation interfaces,
sensory interfaces (vision, speech, voice), and knowledge graph tools.
@@ -10,7 +10,7 @@ This module is consumed by
TOOLS: dict[str, dict] = {
'openwebui': {
"name": "Open WebUI",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Chat Frontend",
@@ -40,7 +40,7 @@ TOOLS: dict[str, dict] = {
},
'anythingllm': {
"name": "AnythingLLM",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Chat",
@@ -68,7 +68,7 @@ TOOLS: dict[str, dict] = {
},
'librechat': {
"name": "LibreChat",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Chat Agent Platform",
@@ -105,7 +105,7 @@ TOOLS: dict[str, dict] = {
},
'flowise': {
"name": "Flowise",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Workflow",
@@ -133,7 +133,7 @@ TOOLS: dict[str, dict] = {
},
'invokeai': {
"name": "InvokeAI",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Image Generation",
@@ -163,7 +163,7 @@ TOOLS: dict[str, dict] = {
},
'forge': {
"name": "Forge (A1111)",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Image Generation",
@@ -193,7 +193,7 @@ TOOLS: dict[str, dict] = {
},
'dashy': {
"name": "Dashy",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Homepage",
@@ -221,7 +221,7 @@ TOOLS: dict[str, dict] = {
},
'obsidian': {
"name": "Obsidian",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Knowledge Graph Notes",
@@ -249,7 +249,7 @@ TOOLS: dict[str, dict] = {
},
'hermes': {
"name": "Hermes",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Ecosystem Dashboard",
@@ -279,7 +279,7 @@ TOOLS: dict[str, dict] = {
},
'hermes_desktop': {
"name": "Hermes Desktop",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Desktop Agent",
@@ -309,7 +309,7 @@ TOOLS: dict[str, dict] = {
},
'hermes_dashboard_page': {
"name": "Hermes Dashboard",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "Dashboard",
@@ -339,7 +339,7 @@ TOOLS: dict[str, dict] = {
},
'local_llm_launcher': {
"name": "Local LLM Launcher",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Face",
"category": "LLM GUI",
@@ -369,7 +369,7 @@ TOOLS: dict[str, dict] = {
},
'openjarvis': {
"name": "OpenJarvis",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Central Intelligence",
"category": "AI Assistant Platform",
@@ -408,7 +408,7 @@ TOOLS: dict[str, dict] = {
},
'deep_eye': {
"name": "Deep Eye",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Vision",
"category": "Computer Vision",
@@ -438,7 +438,7 @@ TOOLS: dict[str, dict] = {
},
'parakeet': {
"name": "Parakeet.cpp",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Senses",
"category": "Speech Recognition",
@@ -468,7 +468,7 @@ TOOLS: dict[str, dict] = {
},
'luxtts': {
"name": "LuxTTS",
- "level": 8,
+ "level": 9,
"layer": "User Interfaces",
"role": "Voice",
"category": "Text-to-Speech",
@@ -494,4 +494,71 @@ TOOLS: dict[str, dict] = {
"is_skills_collection": False
}
},
+ 'jan': {
+ "name": "Jan",
+ "level": 9,
+ "layer": "User Interfaces",
+ "role": "Face",
+ "category": "LLM GUI",
+ "installer": {
+ "type": "npm",
+ "pkg": "@janhq/jan"
+ },
+ "launcher": {
+ "type": "desktop",
+ "cmd": "jan",
+ "default_port": None
+ },
+ "deps": [],
+ "description": "Offline-capable ChatGPT-alternative desktop app with a "
+ "built-in llama.cpp engine and an OpenAI-compatible local "
+ "API server at 127.0.0.1:1337.",
+ "license": "AGPL-3.0",
+ "flags": {
+ "has_cli": True,
+ "has_gui": True,
+ "has_web": False,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+'hermes_webui': {
+ "name": "Hermes WebUI",
+ "level": 9,
+ "layer": "User Interfaces",
+ "role": "Face",
+ "category": "Chat Frontend",
+ "installer": {
+ "type": "uv",
+ "pkg": "open-webui"
+ },
+ "launcher": {
+ "type": "tmux",
+ "cmd": "open-webui serve --port {port} --data-dir {workspaces_root}/hermes-webui --env OLLAMA_BASE_URL=http://localhost:17051",
+ "default_port": 8081
+ },
+ "deps": [
+ "hermes_agent",
+ "ollama"
+ ],
+ "description": "Hermes-themed Open-WebUI instance running on a "
+ "separate port (8081) with its own data volume so "
+ "users, prompts, and RAG corpus don't collide with "
+ "the general openwebui instance. Backend points at "
+ "hermes_agent (17051) instead of Ollama direct, so "
+ "every conversation goes through the Hermes runtime.",
+ "license": "MIT",
+ "flags": {
+ "has_cli": False,
+ "has_gui": False,
+ "has_web": True,
+ "is_ollama": False,
+ "is_passive": False,
+ "is_mcp": False,
+ "is_skills_collection": False
+ }
+},
+
}
\ No newline at end of file
diff --git a/src/ai_lsc/registry/license_gate.py b/src/ai_lsc/registry/license_gate.py
index 164ba88..99277ab 100755
--- a/src/ai_lsc/registry/license_gate.py
+++ b/src/ai_lsc/registry/license_gate.py
@@ -8,7 +8,7 @@ tool's ``license`` SPDX ID against three sources:
tool_id is blocked, raise :class:`LicenseBlocked` immediately. No
dialog, no acceptance, no install.
-2. **Auto-approval registry** (``config/license_approvals.json``) — a
+2. **Auto-approval registry** (``configs/license_approvals.json``) — a
user-editable list of OSI-approved SPDX IDs that have been
pre-approved. If the tool's license is in this list, install
proceeds without a dialog. Only OSI-approved licenses can appear
@@ -28,7 +28,7 @@ the install.
Files managed
-------------
-* ``config/license_approvals.json`` — ``{"licenses": ["MIT", "Apache-2.0"], "updated_at": "..."}``
+* ``configs/license_approvals.json`` — ``{"licenses": ["MIT", "Apache-2.0"], "updated_at": "..."}``
* ``config/license_acceptances.json`` — ``{"ollama": {"spdx": "MIT", "accepted_at": "...", "via": "auto-approved"}, ...}``
"""
diff --git a/src/ai_lsc/registry/licenses.py b/src/ai_lsc/registry/licenses.py
index 5beda5d..88e7c60 100755
--- a/src/ai_lsc/registry/licenses.py
+++ b/src/ai_lsc/registry/licenses.py
@@ -20,7 +20,7 @@ Defines the three license categories the AI-LSC license gate recognizes:
a prominent disclaimer warning about ToS restrictions before
install. Example: Claude Code (Anthropic ToS).
-The license-approvals registry (``config/license_approvals.json``) is
+The license-approvals registry (``configs/license_approvals.json``) is
a user-editable list of SPDX IDs that have been pre-approved. Only
OSI-approved licenses can appear in this list — the
:func:`LicenseGate.add_auto_approval` method rejects attempts to
@@ -224,6 +224,71 @@ CATALOG: dict[str, LicenseInfo] = {
"commercial use and modification."
),
),
+ "LGPL-2.1": LicenseInfo(
+ spdx="LGPL-2.1",
+ name="GNU Lesser General Public License v2.1",
+ category=Category.OSI,
+ url="https://opensource.org/licenses/LGPL-2.1",
+ summary=(
+ "Weak copyleft license allowing linking from proprietary "
+ "software, but modifications to the LGPL-licensed code itself "
+ "must be shared under LGPL. Used by strace, LXC, libvirt."
+ ),
+ ),
+ "GPL-1.0": LicenseInfo(
+ spdx="GPL-1.0",
+ name="GNU General Public License v1.0",
+ category=Category.OSI,
+ url="https://opensource.org/licenses/GPL-1.0",
+ summary=(
+ "The original 1989 GNU copyleft license. Superseded by "
+ "GPL-2.0/GPL-3.0 but still applied by some legacy packages "
+ "(e.g. Perl)."
+ ),
+ ),
+ "PHP-3.01": LicenseInfo(
+ spdx="PHP-3.01",
+ name="PHP License v3.01",
+ category=Category.OSI,
+ url="https://opensource.org/licenses/PHP-3.01",
+ summary=(
+ "Permissive, PHP-specific license governing the PHP "
+ "interpreter. Allows commercial use and modification with "
+ "copyright notice; not derivatively-named redistribution."
+ ),
+ ),
+ "Ruby": LicenseInfo(
+ spdx="Ruby",
+ name="Ruby License",
+ category=Category.OSI,
+ url="https://www.ruby-lang.org/en/about/license.txt",
+ summary=(
+ "Permissive dual license (Ruby's own terms or BSD-2-Clause) "
+ "governing the Ruby interpreter and standard library."
+ ),
+ ),
+ "MirOS": LicenseInfo(
+ spdx="MirOS",
+ name="MirOS License",
+ category=Category.OSI,
+ url="https://opensource.org/licenses/MirOS",
+ summary=(
+ "Permissive BSD-style license with attribution requirement, "
+ "used by MirBSD and mksh."
+ ),
+ ),
+ "MIT/Apache-2.0": LicenseInfo(
+ spdx="MIT/Apache-2.0",
+ name="MIT OR Apache-2.0 (dual license)",
+ category=Category.OSI,
+ url="https://opensource.org/licenses/Apache-2.0",
+ summary=(
+ "Dual licensing under MIT OR Apache-2.0 at the recipient's "
+ "choice — the standard convention for Rust crates (and tools "
+ "like uv). Either grant applies; Apache-2.0 adds a patent "
+ "grant."
+ ),
+ ),
# ── Source-available / fair-code (NOT auto-approvable) ───────────
"BSL-1.1": LicenseInfo(
diff --git a/src/ai_lsc/registry/manager.py b/src/ai_lsc/registry/manager.py
index 550a19a..9a35b73 100755
--- a/src/ai_lsc/registry/manager.py
+++ b/src/ai_lsc/registry/manager.py
@@ -133,6 +133,10 @@ class RegistryManager:
).append((t_id, meta))
return dict(sorted(layers.items()))
+ # Host-level prerequisites referenced in deps but not managed as
+ # registry tools (mirrors _system_deps in stack/connections.py).
+ SYSTEM_DEPS: frozenset[str] = frozenset({"kubectl", "java"})
+
def check_dependencies(
self, selected: list[str],
) -> list[str]:
@@ -142,4 +146,7 @@ class RegistryManager:
for t in selected
if not t.startswith("skill:")
))
- return list({d for d in all_deps if d not in selected})
\ No newline at end of file
+ return list({
+ d for d in all_deps
+ if d not in selected and d not in self.SYSTEM_DEPS
+ })
\ No newline at end of file
diff --git a/src/ai_lsc/registry/stack_templates/local-coder-mesh.json b/src/ai_lsc/registry/stack_templates/local-coder-mesh.json
new file mode 100644
index 0000000..22baaf2
--- /dev/null
+++ b/src/ai_lsc/registry/stack_templates/local-coder-mesh.json
@@ -0,0 +1,48 @@
+{
+ "id": "local-coder-mesh",
+ "name": "Local Coder Mesh — All-Ollama Coding Stack",
+ "description": "Every coding agent in this stack speaks OpenAI-compat and points at localhost Ollama, MeshLLM, or LiteLLM. Includes the four tools missing from the existing hermes-ai-coder-stack template: PiCode, MeshLLM (the native GPU-pooling mesh binary from Mesh-LLM/mesh-llm, NOT a LiteLLM re-skin), Hermes WebUI, ZCoder. Also includes Graphify for knowledge-graph-aware coding. Use this template when you want the complete local coding-agent fleet wired to one Ollama instance with no cloud calls.",
+ "version": "1.1",
+ "author": "ai-lsc-template-pack",
+ "tags": ["coding", "agent", "local-first", "ollama", "mesh", "hermes", "native", "knowledge-graph"],
+ "endpoints": {
+ "ollama_base": "http://localhost:11434/v1",
+ "litellm_base": "http://localhost:4000",
+ "meshllm_api": "http://localhost:9337/v1",
+ "meshllm_console": "http://localhost:3131",
+ "openwebui": "http://localhost:3000",
+ "hermes_webui": "http://localhost:8081",
+ "hermes_agent": "http://localhost:17051",
+ "hermes_dashboard": "http://localhost:17050"
+ },
+ "tools": [
+ "ollama",
+ "litellm",
+ "meshllm",
+ "picode",
+ "aider",
+ "odysseus",
+ "opencode",
+ "zcoder",
+ "graphify",
+ "hermes",
+ "hermes_agent",
+ "hermes_webui",
+ "hermes_desktop",
+ "openwebui",
+ "ripgrep",
+ "fd",
+ "tree_sitter"
+ ],
+ "notes": {
+ "philosophy": "One Ollama, one mesh (MeshLLM for multi-node pooling, LiteLLM for proxy routing), every coding agent speaks OpenAI-compat to localhost. No cloud calls, no containers in the dev path — ai-lsc's Podman/Docker/LXC/Firecracker export is reserved for total-stack export only.",
+ "meshllm_clarification": "MeshLLM is the native binary from https://github.com/Mesh-LLM/mesh-llm. It pools GPUs and memory across machines, exposes one OpenAI-compat API at :9337, and has a web console at :3131. It is NOT a LiteLLM re-skin — the two tools coexist in this template: MeshLLM for mesh-pooled multi-node inference, LiteLLM for proxy routing to multiple backends. Coding agents prefer MeshLLM (:9337) first, fall back to LiteLLM (:4000), then Ollama direct (:11434).",
+ "graphify_role": "Graphify (https://github.com/Graphify-Labs/graphify) builds knowledge graphs from code, docs, PDFs, and images. It runs as a CLI (pip install graphifyy), a Claude Code skill (/graphify .), or an MCP stdio server (graphify --mcp). Other agents in this stack can query graphify's MCP server to navigate the codebase graph without re-reading source files — 71.5x fewer tokens per query vs reading raw files. Uses Claude vision by default but can be configured to use MeshLLM/LiteLLM/Ollama for fully-local extraction.",
+ "topology": "ollama (11434) <- litellm (4000, proxy mesh) + meshllm (9337, native mesh) <- {picode, aider, odysseus, opencode, zcoder}. graphify builds graphs from the codebase and exposes an MCP server that the coding agents query. hermes_webui + hermes_desktop talk to hermes (17050) -> hermes_agent (17051) -> ollama. openwebui talks to ollama directly. ripgrep + fd + tree_sitter are passive filesystem tools used by the coding agents for repo-map / symbol navigation.",
+ "recommended_models": "qwen2.5-coder:7b (fast coding), qwen2.5-coder:32b (heavy coding), hermes3:8b (Hermes stack), nomic-embed-text (openwebui RAG, corpus indexing, graphify embeddings). MeshLLM auto-downloads a suitable model on first `serve --auto` if none specified.",
+ "install_order": "1) ollama (already running). 2) litellm (proxy mesh) + meshllm (native mesh binary via curl installer). 3) hermes_agent -> hermes -> hermes_webui + hermes_desktop. 4) aider, picode, odysseus, opencode, zcoder (CLI agents, all native venvs/uv/npm). 5) graphify (uv install graphifyy). 6) openwebui (native uv). 7) ripgrep, fd, tree_sitter (pacman).",
+ "native_only_policy": "Every tool in this template installs natively into /mnt/AI/runtime// (venv/uv) or via pacman/AUR/curl-script. ai-lsc's container export feature is intentionally not used at install time — it's reserved for total-stack deployment exports via the Stack Editor.",
+ "non_destructive_policy": "Applying this template never removes existing installs. ai-lsc's InstallerManager.preflight() detects existing installs and skips them unless force=True.",
+ "missing_tools_added_by_template_pack": "picode, meshllm, hermes_webui, zcoder — these four require the registry + wirings patches in this template pack before the template will compile. graphify already exists in the registry but needs the graphify-update.diff and graphify-wiring-update.diff patches to fix its URL (Graphify-Labs/graphify), license (MIT), role (Knowledge Graph Builder), installer (uv graphifyy), and wiring (MCP server + LLM backend connections). See MERGE-GUIDE.md."
+ }
+}
diff --git a/src/ai_lsc/stack/connections.py b/src/ai_lsc/stack/connections.py
index ed8e98d..2cc5871 100755
--- a/src/ai_lsc/stack/connections.py
+++ b/src/ai_lsc/stack/connections.py
@@ -632,7 +632,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="heretic",
- layer="GPU Runtimes",
+ layer="Engines",
interfaces=[],
connections=[
Connection(
@@ -656,7 +656,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="unsloth",
- layer="GPU Runtimes",
+ layer="Development Environment",
interfaces=[],
connections=[
Connection(
@@ -771,7 +771,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="vllm",
- layer="Orchestrators",
+ layer="Engines",
interfaces=[
ToolInterface(
interface_id="openai_api",
@@ -931,12 +931,12 @@ _reg(StackWiring(
# ──────────────────────────────────────────────────────────────────
-# L6: AI Endpoints
+# L6: AI Endpoints (→ the restored "Routing" layer in the 11-layer taxonomy)
# ──────────────────────────────────────────────────────────────────
_reg(StackWiring(
tool_id="litellm",
- layer="Orchestrators",
+ layer="Routing",
interfaces=[
ToolInterface(
interface_id="openai_api",
@@ -1015,7 +1015,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="9router_proxy",
- layer="Orchestrators",
+ layer="Routing",
interfaces=[
ToolInterface(
interface_id="router_api",
@@ -1041,7 +1041,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="deep_eye",
- layer="Orchestrators",
+ layer="User Interfaces",
interfaces=[
ToolInterface(
interface_id="deep_eye_api",
@@ -1066,7 +1066,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="luxtts",
- layer="Orchestrators",
+ layer="User Interfaces",
interfaces=[
ToolInterface(
interface_id="tts_api",
@@ -1234,7 +1234,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="parakeet",
- layer="Knowledge Management",
+ layer="User Interfaces",
interfaces=[
ToolInterface(
interface_id="parakeet_api",
@@ -1306,7 +1306,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="fabric",
- layer="Knowledge Management",
+ layer="Orchestrators",
interfaces=[],
connections=[],
context=EngineeringContext(
@@ -1408,7 +1408,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="n8n",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="n8n_api",
@@ -1454,7 +1454,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="nightshift",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="nightshift_api",
@@ -1470,7 +1470,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="hivemind",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="hivemind_api",
@@ -1495,7 +1495,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="hermes_agent",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="hermes_agent_api",
@@ -1546,7 +1546,7 @@ _reg(StackWiring(
# Passive / CLI-only tools in L8 — no interfaces or network connections
for _tid in [
"agent_reach", "agentic_os", "aider", "algory", "atlas_os",
- "claude_code", "eagle_eye", "graphify", "headroom", "honcho",
+ "claude_code", "eagle_eye", "headroom", "honcho",
"loop_engineering", "mcp_drift_state_tracker", "nvidia_agent_skills",
"ponytail", "promptops", "skillspector", "spec_kit", "synapscli",
"wayland_ai",
@@ -1595,7 +1595,7 @@ for _tid in [
# agno has a web interface but no deps in defaults
_reg(StackWiring(
tool_id="agno",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="agno_web",
@@ -1787,7 +1787,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="hermes_dashboard_page",
- layer="Observability",
+ layer="User Interfaces",
interfaces=[
ToolInterface(
interface_id="dashboard_api",
@@ -1837,7 +1837,7 @@ _reg(StackWiring(
# ──────────────────────────────────────────────────────────────────
-# L10: Intelligent Routing
+# L10: Intelligent Routing (folded into "Orchestrators" in the 11-layer taxonomy)
# ──────────────────────────────────────────────────────────────────
_reg(StackWiring(
@@ -1892,7 +1892,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="mnemo_cortex",
- layer="Orchestrators",
+ layer="Knowledge Management",
interfaces=[
ToolInterface(
interface_id="mnemo_cortex_api",
@@ -1942,7 +1942,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="everos_memory",
- layer="Orchestrators",
+ layer="Knowledge Management",
interfaces=[
ToolInterface(
interface_id="everos_memory_api",
@@ -2049,7 +2049,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="dify",
- layer="User Interfaces",
+ layer="Routing",
interfaces=[
ToolInterface(
interface_id="dify_web",
@@ -2271,7 +2271,7 @@ _reg(StackWiring(
_reg(StackWiring(
tool_id="langflow",
- layer="User Interfaces",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="langflow_web",
@@ -2381,7 +2381,7 @@ for _tid in ["hermes_desktop", "local_llm_launcher"]:
_reg(StackWiring(
tool_id="opensandbox",
- layer="DevOps",
+ layer="Orchestrators",
interfaces=[
ToolInterface(
interface_id="opensandbox_web",
@@ -2529,6 +2529,378 @@ for _tid in [
))
+# ──────────────────────────────────────────────────────────────────
+# L5 additions: terminal coding agents (registry expansion pass)
+# (coding agents now live in DevOps L10; meshllm/picode in Routing L5)
+# opencode / gemini_cli / qwen_code / goose / codex — all multi-provider
+# CLI agents that consume an OpenAI-compatible endpoint. Wired to both
+# Ollama (direct) and LiteLLM (proxied) so staging either backend
+# prevents orphan-flagging in the Pipeline Ticker.
+# ──────────────────────────────────────────────────────────────────
+
+_CODING_AGENT_CTX = EngineeringContext(
+ decision="Terminal coding agents consume an OpenAI-compatible "
+ "chat endpoint for LLM inference.",
+ observation="Every modern coding agent (opencode, Gemini CLI, "
+ "Qwen Code, goose, Codex) speaks the OpenAI wire "
+ "format for at least one provider slot.",
+ alternatives="Native provider SDKs (Anthropic, Google) or a "
+ "custom proxy.",
+ constraints="The endpoint must be reachable and expose "
+ "/v1/chat/completions.",
+ reasoning="OpenAI-compat is the de-facto agent ↔ LLM contract; "
+ "pointing the agents at localhost keeps inference "
+ "local per AI-LSC policy.",
+ verification="Set the agent's base-URL env var to "
+ "http://127.0.0.1:11434/v1 and list models.",
+ lineage="Mirrors the OpenAI API spec; adopted by Ollama, vLLM, "
+ "SGLang, LiteLLM.",
+ assumptions="At least one model is served by the target backend.",
+)
+
+_reg(StackWiring(
+ tool_id="opencode",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Local LLM inference for terminal coding sessions.",
+ config_key="OPENAI_BASE_URL (ollama provider, opencode.json)",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Multi-model routing via LiteLLM proxy.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="gemini_cli",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Local LLM inference via the openai-compat provider.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Multi-model routing via LiteLLM proxy.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="qwen_code",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Local Qwen model inference via openai-compat provider.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Multi-model routing via LiteLLM proxy.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="goose",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Local LLM backend for goose sessions and MCP extensions.",
+ config_key="GOOSE_PROVIDER / OPENAI_BASE_URL",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Multi-model routing via LiteLLM proxy.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ ],
+))
+
+# codex existed in the registry since v3.1 but had no STACK_WIRINGS
+# entry, so it was flagged as an orphan by the Pipeline Ticker whenever
+# it was staged. This wiring closes that gap.
+_reg(StackWiring(
+ tool_id="codex",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Local LLM inference for terminal coding sessions.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Multi-model routing via LiteLLM proxy.",
+ config_key="OPENAI_BASE_URL",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="letta",
+ layer="Orchestrators",
+ interfaces=[
+ ToolInterface(
+ interface_id="http_api",
+ protocol="HTTP",
+ api_format="REST",
+ port=8283,
+ auth="Optional password (LETTA_SERVER_PASSWORD)",
+ description="Letta agent server REST API — create/state/"
+ "message agents with persistent memory.",
+ context=EngineeringContext(
+ decision="Expose the Letta server REST API as its "
+ "primary interface.",
+ observation="Letta (formerly MemGPT) manages stateful "
+ "agents whose memory/context survives across "
+ "sessions; the REST API is the management "
+ "surface.",
+ alternatives="Python SDK in-process, or Letta Cloud "
+ "(SaaS — excluded by policy).",
+ constraints="Requires a database — SQLite by default, "
+ "PostgreSQL recommended for persistence.",
+ reasoning="A local agent-memory server complements "
+ "stateless coding agents in the stack.",
+ verification="curl http://localhost:8283/v1/agents",
+ lineage="Letta — https://docs.letta.com/",
+ ),
+ ),
+ ],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="LLM inference for agent reasoning and memory operations.",
+ config_key="LETTA_INFERENCE_BASE_URL / model config",
+ required=False,
+ context=_OLLAMA_CONSUMER_CTX,
+ ),
+ Connection(
+ target_tool="postgresql",
+ interface_id="postgresql",
+ purpose="Persistent agent/state storage (SQLite fallback).",
+ config_key="LETTA_PG_URI",
+ required=False,
+ context=EngineeringContext(
+ decision="PostgreSQL as the optional durable backend for "
+ "Letta's state store.",
+ observation="Letta defaults to SQLite; PostgreSQL is "
+ "recommended for multi-user / long-lived "
+ "deployments.",
+ alternatives="Built-in SQLite (zero-config).",
+ reasoning="Sharing one PostgreSQL instance with other "
+ "stack tools keeps state management uniform.",
+ verification="letta server with LETTA_PG_URI set; "
+ "inspect created tables.",
+ lineage="Letta — https://docs.letta.com/",
+ ),
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="sglang",
+ layer="Engines",
+ interfaces=[
+ ToolInterface(
+ interface_id="openai_api",
+ protocol="HTTP",
+ api_format="OpenAI",
+ port=30000,
+ base_path="/v1",
+ auth="None (or API key if configured)",
+ description="SGLang OpenAI-compatible API: /v1/chat/completions, "
+ "/v1/models, /v1/embeddings. High-throughput serving "
+ "with RadixAttention prefix caching.",
+ context=EngineeringContext(
+ decision="Expose SGLang's OpenAI-compatible API as its "
+ "primary interface.",
+ observation="SGLang rivals vLLM on throughput for "
+ "many-workload serving, and prefix caching "
+ "benefits agentic loops that resend context.",
+ alternatives="vLLM (port 8000), Ollama, llama.cpp server.",
+ constraints="Requires a CUDA GPU with sufficient VRAM for "
+ "the target model.",
+ reasoning="OpenAI API compatibility lets every consumer in "
+ "the stack use SGLang without code changes.",
+ verification="curl http://localhost:30000/v1/models",
+ lineage="SGLang — https://docs.sglang.ai/",
+ ),
+ ),
+ ],
+ connections=[
+ Connection(
+ target_tool="cuda",
+ interface_id="cuda_driver",
+ purpose="GPU-accelerated inference kernels.",
+ config_key="CUDA_VISIBLE_DEVICES",
+ required=True,
+ context=EngineeringContext(
+ decision="SGLang requires CUDA for its serving kernels.",
+ observation="SGLang's throughput comes from custom CUDA "
+ "kernels and RadixAttention.",
+ reasoning="SGLang without a GPU has no advantage over "
+ "llama.cpp on CPU.",
+ verification="nvidia-smi confirms driver and GPU availability.",
+ lineage="SGLang — https://docs.sglang.ai/",
+ ),
+ ),
+ ],
+))
+
+# ──────────────────────────────────────────────────────────────────
+# L8 / L10 / L3 additions: jan, mem0, tinygrad
+# ──────────────────────────────────────────────────────────────────
+
+_reg(StackWiring(
+ tool_id="jan",
+ layer="User Interfaces",
+ interfaces=[
+ ToolInterface(
+ interface_id="openai_api",
+ protocol="HTTP",
+ api_format="OpenAI",
+ port=1337,
+ base_path="/v1",
+ auth="None (local only)",
+ description="Jan's built-in OpenAI-compatible local API server "
+ "powered by its bundled llama.cpp engine — a "
+ "drop-in replacement for cloud APIs.",
+ context=EngineeringContext(
+ decision="Expose Jan's local API server as its wiring "
+ "interface.",
+ observation="Jan is a self-contained desktop app: engine, "
+ "model manager, and API server in one; the API "
+ "server listens on 127.0.0.1:1337.",
+ alternatives="Ollama as the engine with a separate chat UI.",
+ constraints="The API server toggle must be enabled in Jan's "
+ "settings; Electron desktop UI is not "
+ "web-embeddable.",
+ reasoning="A GUI chat app that also serves an "
+ "OpenAI-compatible endpoint doubles as an "
+ "inference provider for other stack tools.",
+ verification="curl http://127.0.0.1:1337/v1/models",
+ lineage="Jan — https://jan.ai/docs/desktop/api-server",
+ assumptions="API server enabled (default on recent builds).",
+ ),
+ ),
+ ],
+ connections=[],
+))
+
+_reg(StackWiring(
+ tool_id="mem0",
+ layer="Knowledge Management",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="LLM inference for memory extraction/summarisation "
+ "and embeddings for memory vectors.",
+ config_key="OPENAI_BASE_URL / embedding model config",
+ required=False,
+ context=_OLLAMA_CONSUMER_CTX,
+ ),
+ Connection(
+ target_tool="qdrant",
+ interface_id="http_api",
+ purpose="Vector storage for long-term memories.",
+ config_key="QDRANT_HOST",
+ required=False,
+ context=EngineeringContext(
+ decision="Qdrant as an optional external vector backend "
+ "for stored memories.",
+ observation="Mem0 ships with an embedded vector store by "
+ "default and supports pluggable backends "
+ "(Qdrant, Chroma, pgvector).",
+ alternatives="Mem0's built-in store, or ChromaDB.",
+ reasoning="Sharing one Qdrant instance across knowledge "
+ "tools keeps embeddings co-located.",
+ verification="Configure vector_store.provider=qdrant in "
+ "mem0 config; run a memory add + search.",
+ lineage="Mem0 — https://docs.mem0.ai/",
+ ),
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="tinygrad",
+ layer="GPU Runtimes",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="cuda",
+ interface_id="cuda_driver",
+ purpose="GPU-accelerated tensor ops on NVIDIA backends.",
+ config_key="CUDA_VISIBLE_DEVICES",
+ required=False,
+ context=EngineeringContext(
+ decision="CUDA is optional — tinygrad also runs on CPU and "
+ "AMD backends.",
+ observation="tinygrad's lazy execution compiles kernels per "
+ "backend at runtime; the NVIDIA backend needs "
+ "the CUDA driver.",
+ alternatives="CuPy for NumPy-compat GPU arrays; PyTorch for "
+ "a full training stack.",
+ reasoning="Wiring CUDA (optionally) surfaces tinygrad in "
+ "the ticker when a GPU stack is staged, without "
+ "forcing it on CPU-only hosts.",
+ verification="python3 -c \"from tinygrad import Tensor; "
+ "print(Tensor([1,2,3]).sum().item())\"",
+ lineage="tinygrad — https://github.com/tinygrad/tinygrad",
+ ),
+ ),
+ ],
+))
+
+
# ══════════════════════════════════════════════════════════════════
# Topology query helpers
# ══════════════════════════════════════════════════════════════════
@@ -2636,4 +3008,392 @@ def validate_wiring() -> list[str]:
f"target '{conn.target_tool}' "
f"(available: {sorted(target_iface_ids) or 'none'})"
)
- return errors
\ No newline at end of file
+ return errors
+
+# ──────────────────────────────────────────────────────────────────
+# Graphify — knowledge graph builder + MCP server (rewired from passive)
+# Removed from the L8 passive/CLI list above and given a proper wiring
+# since graphify is both a CLI tool and an MCP stdio server.
+# ──────────────────────────────────────────────────────────────────
+_reg(StackWiring(
+ tool_id="graphify",
+ layer="Orchestrators",
+ interfaces=[
+ ToolInterface(
+ interface_id="graphify_mcp",
+ protocol="stdio",
+ api_format="MCP",
+ port=None,
+ base_path="",
+ auth="None (local stdio)",
+ description="Graphify MCP stdio server. Start with "
+ "`graphify --mcp`. Other MCP-aware agents "
+ "(Claude Code, opencode with MCP support, "
+ "etc.) can query the knowledge graph via the "
+ "standard MCP protocol. Exposes tools for "
+ "graph query, path finding, and concept "
+ "explanation.",
+ context=EngineeringContext(
+ decision="Expose graphify as an MCP server so other "
+ "agents can query its knowledge graph.",
+ observation="Graphify's --mcp mode runs a stdio MCP "
+ "server. Any MCP-aware agent can call "
+ "graphify's query/path/explain tools to "
+ "navigate the codebase graph without "
+ "re-reading source files.",
+ alternatives="CLI-only mode (graphify query '...') "
+ "or direct graph.json consumption.",
+ constraints="Graph must be built first via "
+ "`graphify .` before the MCP server can "
+ "answer queries.",
+ reasoning="MCP is the standard agent-to-tool protocol. "
+ "Exposing graphify via MCP lets every coding "
+ "agent in the stack benefit from the "
+ "knowledge graph without each one needing "
+ "a custom graphify integration.",
+ verification="Start `graphify --mcp` and send an MCP "
+ "initialize request on stdin.",
+ lineage="Graphify — https://github.com/Graphify-Labs/graphify",
+ assumptions="graphify installed (uv tool graphifyy) and "
+ "a graph has been built in the working "
+ "directory.",
+ ),
+ ),
+ ],
+ connections=[
+ Connection(
+ target_tool="meshllm",
+ interface_id="openai_api",
+ purpose="Optional LLM backend for graphify's vision/extraction "
+ "pass. Graphify defaults to Claude (Anthropic API); "
+ "users who want fully-local extraction can configure "
+ "it to use MeshLLM (:9337/v1) instead.",
+ config_key="OPENAI_API_BASE (set to http://localhost:9337/v1 "
+ "to route extraction through the mesh)",
+ required=False,
+ context=EngineeringContext(
+ decision="Graphify can use MeshLLM as its extraction "
+ "backend instead of Claude.",
+ observation="Graphify uses an LLM to extract concepts "
+ "and relationships from files. The default "
+ "is Claude (Anthropic), but it speaks "
+ "OpenAI-compat so any OpenAI-format endpoint "
+ "works.",
+ reasoning="For a fully-local stack, route graphify's "
+ "extraction through MeshLLM or Ollama direct. "
+ "Claude gives better vision results for "
+ "images/diagrams, so the connection is "
+ "optional — users choose.",
+ lineage="Graphify docs — https://github.com/Graphify-Labs/graphify",
+ assumptions="MeshLLM has a vision-capable model if the "
+ "corpus contains images.",
+ ),
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Fallback LLM backend (general LiteLLM proxy on :4000).",
+ config_key="OPENAI_API_BASE",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Direct Ollama fallback for extraction (bypass both "
+ "meshes). Useful for single-node setups without "
+ "MeshLLM.",
+ config_key="OPENAI_API_BASE (set to http://localhost:11434/v1)",
+ required=False,
+ context=EngineeringContext(
+ decision="Ollama direct as a third extraction option.",
+ observation="Same OpenAI-compat contract as MeshLLM "
+ "and LiteLLM.",
+ reasoning="Single-node users who don't need mesh "
+ "pooling can point graphify straight at "
+ "Ollama for the extraction LLM calls.",
+ ),
+ ),
+ ],
+))
+
+_reg(StackWiring(
+ tool_id="meshllm",
+ layer="Routing",
+ interfaces=[
+ ToolInterface(
+ interface_id="openai_api",
+ protocol="HTTP",
+ api_format="OpenAI",
+ port=9337,
+ base_path="/v1",
+ auth="API key (MESH_LLM_KEY, optional — local mesh is open by default)",
+ description="MeshLLM unified API. Exposes a single "
+ "OpenAI-compatible endpoint that routes requests "
+ "across pooled GPUs/memory. Supports "
+ "/v1/chat/completions, /v1/models, "
+ "/v1/embeddings. The mesh decides whether a "
+ "model runs locally, routes to a peer node, or "
+ "uses Skippy stage splits for models too large "
+ "for one box. Use model='mesh' to fan out one "
+ "prompt to every model in the mesh (MoA gateway).",
+ context=EngineeringContext(
+ decision="MeshLLM as the mesh-pooling LLM gateway for "
+ "multi-node inference.",
+ observation="MeshLLM pools GPUs and memory across "
+ "machines. Every node exposes the same /v1 "
+ "API. Requests are routed by the 'model' "
+ "field to the peer that can serve that "
+ "model. QUIC end-to-end encrypts peer "
+ "traffic via Iroh relays.",
+ alternatives="LiteLLM (proxy only, no mesh pooling), "
+ "vLLM (single-node high-throughput), "
+ "direct Ollama (single-node).",
+ constraints="mesh-llm setup must be run before first "
+ "serve. Multi-node mesh requires peers to "
+ "be discoverable via Nostr (public mesh) "
+ "or invite token (private mesh).",
+ reasoning="MeshLLM is the only tool in the stack that "
+ "can split a model too large for one GPU "
+ "across multiple nodes (Skippy stage splits). "
+ "For single-node workloads, Ollama or LiteLLM "
+ "are simpler; MeshLLM shines when you add a "
+ "second machine.",
+ verification="curl http://localhost:9337/v1/models",
+ lineage="MeshLLM — https://github.com/Mesh-LLM/mesh-llm",
+ assumptions="mesh-llm binary installed and `mesh-llm "
+ "setup` completed. At least one model is "
+ "available (auto-downloaded by `serve --auto` "
+ "or specified via --model).",
+ ),
+ ),
+ ToolInterface(
+ interface_id="mesh_web_console",
+ protocol="HTTP",
+ api_format="REST",
+ port=3131,
+ base_path="",
+ auth="None (local only)",
+ description="MeshLLM web console. Browser UI for mesh "
+ "management, node inventory, model routing, "
+ "and peer discovery. Use `mesh-llm serve "
+ "--headless` to hide the console while "
+ "keeping the management API.",
+ context=EngineeringContext(
+ decision="Expose a separate web console port for mesh "
+ "management.",
+ observation="The console is a browser UI distinct from "
+ "the OpenAI-compat API. Operators use it "
+ "to monitor mesh health, add peers, and "
+ "configure model routing.",
+ reasoning="Separating management UI from inference API "
+ "lets operators lock down :9337 (inference) "
+ "while keeping :3131 (console) accessible "
+ "only on the LAN.",
+ verification="curl http://localhost:3131/",
+ lineage="MeshLLM console — https://github.com/Mesh-LLM/mesh-llm",
+ assumptions="MeshLLM was started without --headless.",
+ ),
+ ),
+ ],
+ connections=[
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Optional: use Ollama as a local-model backend via "
+ "`mesh-llm client --auto` (API-only client mode). "
+ "When configured, MeshLLM routes to Ollama for "
+ "models not served by the mesh itself.",
+ config_key="mesh-llm client --auto (reads OLLAMA_BASE_URL)",
+ required=False,
+ context=EngineeringContext(
+ decision="Ollama is an OPTIONAL backend for MeshLLM, "
+ "not a required one.",
+ observation="MeshLLM can load GGUF models directly "
+ "(--model /path/to/model.gguf) without "
+ "Ollama. The `mesh-llm client --auto` "
+ "subcommand turns MeshLLM into a pure "
+ "client that routes to other meshes or "
+ "Ollama-compatible backends.",
+ reasoning="In the local-coder-mesh stack, most users "
+ "will run MeshLLM standalone (it auto-"
+ "downloads a suitable model). The Ollama "
+ "connection is for users who want to expose "
+ "their existing Ollama model fleet through "
+ "the mesh routing layer.",
+ ),
+ ),
+ ],
+))
+
+# ──────────────────────────────────────────────────────────────────
+# PiCode — coding agent, consumes mesh first, falls back to LiteLLM + Ollama
+# ──────────────────────────────────────────────────────────────────
+_reg(StackWiring(
+ tool_id="picode",
+ layer="Routing",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="meshllm",
+ interface_id="openai_api",
+ purpose="Primary LLM route for PiCode — mesh-pooled inference "
+ "across all available nodes.",
+ config_key="OPENAI_API_BASE (set to http://localhost:9337/v1)",
+ required=False,
+ context=EngineeringContext(
+ decision="PiCode points at MeshLLM first.",
+ observation="MeshLLM's :9337 endpoint gives PiCode "
+ "access to every model in the mesh via "
+ "one URL.",
+ alternatives="LiteLLM proxy (localhost:4000) or direct "
+ "Ollama (localhost:11434).",
+ reasoning="Mesh-pooled inference is preferable when "
+ "available — it can serve models larger than "
+ "any single GPU via Skippy stage splits.",
+ verification="Set OPENAI_API_BASE=http://localhost:9337/v1 "
+ "and list models.",
+ lineage="PiCode — https://github.com/jasonjmcghee/picode",
+ assumptions="MeshLLM is running and has at least one "
+ "model available.",
+ ),
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Fallback mesh (general LiteLLM proxy on :4000).",
+ config_key="OPENAI_API_BASE",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Direct Ollama fallback (bypass both meshes).",
+ config_key="OPENAI_API_BASE",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ ],
+))
+
+# ──────────────────────────────────────────────────────────────────
+# ZCoder — coding agent, same consumer pattern as PiCode
+# ──────────────────────────────────────────────────────────────────
+_reg(StackWiring(
+ tool_id="zcoder",
+ layer="DevOps",
+ interfaces=[],
+ connections=[
+ Connection(
+ target_tool="meshllm",
+ interface_id="openai_api",
+ purpose="Primary LLM route for ZCoder — mesh-pooled inference.",
+ config_key="OPENAI_API_BASE (set to http://localhost:9337/v1)",
+ required=False,
+ context=EngineeringContext(
+ decision="ZCoder points at MeshLLM first.",
+ observation="Same OpenAI-compat contract as PiCode.",
+ reasoning="Consistent routing across all coding agents "
+ "in the stack — they all prefer the mesh.",
+ lineage="ZCoder (Zhipu AI)",
+ assumptions="MeshLLM is running.",
+ ),
+ ),
+ Connection(
+ target_tool="litellm",
+ interface_id="openai_api",
+ purpose="Fallback mesh (general LiteLLM proxy).",
+ config_key="OPENAI_API_BASE",
+ required=False,
+ context=_LITELLM_CONSUMER_CTX,
+ ),
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Direct Ollama fallback (bypass both meshes).",
+ config_key="OPENAI_API_BASE",
+ required=False,
+ context=_CODING_AGENT_CTX,
+ ),
+ ],
+))
+
+# ──────────────────────────────────────────────────────────────────
+# Hermes WebUI — web frontend, backend is hermes_agent (NOT ollama direct)
+# ──────────────────────────────────────────────────────────────────
+_reg(StackWiring(
+ tool_id="hermes_webui",
+ layer="User Interfaces",
+ interfaces=[
+ ToolInterface(
+ interface_id="hermes_webui_http",
+ protocol="HTTP",
+ api_format="REST",
+ port=8081,
+ base_path="",
+ auth="WebUI auth (first-run admin signup)",
+ description="Hermes-themed Open-WebUI instance. Separate "
+ "port (8081) and data volume from the general "
+ "openwebui instance so user accounts and RAG "
+ "corpus don't collide.",
+ context=EngineeringContext(
+ decision="Run a second Open-WebUI instance dedicated "
+ "to the Hermes stack.",
+ observation="Open-WebUI supports multiple instances "
+ "with separate data-dir flags. The general "
+ "openwebui tool already occupies :3000 with "
+ "Ollama direct as backend.",
+ alternatives="Use a single Open-WebUI instance with "
+ "model name prefixes (hermes/*).",
+ constraints="Must run on a different port (8081) and "
+ "data-dir than the general openwebui.",
+ reasoning="Dedicated Hermes UI keeps the Hermes agent "
+ "runtime as the single backend, so every "
+ "Hermes WebUI conversation flows through "
+ "hermes_agent's tool-use / function-calling "
+ "layer instead of raw Ollama.",
+ verification="curl http://localhost:8081/health",
+ lineage="Open-WebUI — https://github.com/open-webui/open-webui",
+ assumptions="hermes_agent is running on :17051.",
+ ),
+ ),
+ ],
+ connections=[
+ Connection(
+ target_tool="hermes_agent",
+ interface_id="hermes_agent_api",
+ purpose="Primary backend — every chat goes through the "
+ "Hermes agent runtime (tool use, function calling).",
+ config_key="OLLAMA_BASE_URL (set to http://localhost:17051)",
+ required=True,
+ context=EngineeringContext(
+ decision="Hermes WebUI talks to hermes_agent, NOT "
+ "Ollama direct.",
+ observation="hermes_agent exposes an OpenAI-compat "
+ "endpoint on :17051 that wraps Ollama with "
+ "Hermes function-calling logic.",
+ reasoning="Routing through hermes_agent gives the "
+ "WebUI access to Hermes tool use without "
+ "requiring the user to wire it manually.",
+ ),
+ ),
+ Connection(
+ target_tool="ollama",
+ interface_id="openai_api",
+ purpose="Embedding model for RAG (nomic-embed-text). "
+ "Embeddings bypass hermes_agent for speed.",
+ config_key="OLLAMA_BASE_URL (RAG_EMBEDDING_ENGINE=ollama)",
+ required=False,
+ context=EngineeringContext(
+ decision="Use Ollama direct for embeddings, "
+ "hermes_agent for chat.",
+ observation="Embeddings don't need Hermes function "
+ "calling — direct Ollama is faster.",
+ reasoning="Splitting chat vs. embedding traffic "
+ "keeps hermes_agent focused on tool-use "
+ "calls.",
+ ),
+ ),
+ ],
+))
diff --git a/src/ai_lsc/ui/main_window.py b/src/ai_lsc/ui/main_window.py
index 89586b0..a0790bb 100755
--- a/src/ai_lsc/ui/main_window.py
+++ b/src/ai_lsc/ui/main_window.py
@@ -210,13 +210,14 @@ if _HAS_QT:
self.logs_root: str = os.path.join(self.base_dir, "logs")
self.skills_root: str = os.path.join(self.base_dir, "skills")
self.datasets_root: str = os.path.join(self.base_dir, "datasets")
- self.config_root: str = os.path.join(self.base_dir, "config")
+ self.config_root: str = os.path.join(self.base_dir, "configs")
self.workspaces_root: str = os.path.join(
self.base_dir, "workspaces"
)
self.exports_root: str = os.path.join(self.base_dir, "exports")
self._setup_environment_hierarchy()
+ self._migrate_legacy_state_files()
self.dtach_bin: str | None = find_binary("dtach-ng", "dtach")
# License gate — checks every tool's license before the
@@ -291,6 +292,62 @@ if _HAS_QT:
# Environment setup
# ───────────────────────────────────────────────────────────────
+ def _migrate_legacy_state_files(self) -> None:
+ """One-time migration to the canonical configs/ directory.
+
+ v3.1.1b moved app state into /configs/. Older
+ installs kept files in three legacy locations:
+ * /config/ (pipeline_state.json, license_approvals.json)
+ * /controller_config.json (config persisted at the root)
+ Files are moved only when no newer copy exists in configs/;
+ emptied legacy dirs are removed. Never raises.
+ """
+ import shutil
+
+ legacy_dir = os.path.join(self.base_dir, "config")
+ candidates: list[tuple[str, str]] = []
+ if os.path.isdir(legacy_dir):
+ for fname in os.listdir(legacy_dir):
+ if fname.endswith(".json"):
+ candidates.append(
+ (os.path.join(legacy_dir, fname), fname)
+ )
+ root_cfg = os.path.join(self.base_dir, CONFIG_FILE)
+ if os.path.isfile(root_cfg):
+ candidates.append((root_cfg, CONFIG_FILE))
+
+ moved: list[str] = []
+ for src_path, fname in candidates:
+ dst_path = os.path.join(self.config_root, fname)
+ try:
+ if not os.path.exists(dst_path):
+ shutil.move(src_path, dst_path)
+ moved.append(fname)
+ elif os.path.getmtime(src_path) > os.path.getmtime(dst_path):
+ # legacy copy is newer — keep it, drop the old one
+ shutil.move(
+ src_path, dst_path + ".legacy.bak"
+ )
+ moved.append(fname + " (kept as .legacy.bak)")
+ else:
+ os.remove(src_path)
+ except OSError:
+ continue
+
+ # remove the legacy config/ dir when it is now empty
+ try:
+ if os.path.isdir(legacy_dir) and not os.listdir(legacy_dir):
+ os.rmdir(legacy_dir)
+ except OSError:
+ pass
+
+ if moved:
+ from ai_lsc.utils.logging import get_logger
+ get_logger(__name__).info(
+ "Migrated legacy state files to %s: %s",
+ self.config_root, ", ".join(moved),
+ )
+
def _setup_environment_hierarchy(self) -> None:
for d in REQUIRED_DIRS:
os.makedirs(
@@ -1480,7 +1537,7 @@ if _HAS_QT:
def _load_config(self) -> dict:
# H-02: resolve config relative to BASE_DIR (not the cwd the
# app was launched from).
- config_path = os.path.join(self.base_dir, CONFIG_FILE)
+ config_path = os.path.join(self.config_root, CONFIG_FILE)
if os.path.exists(config_path):
try:
with open(config_path, encoding="utf-8") as f:
@@ -1507,7 +1564,10 @@ if _HAS_QT:
"services": services_data,
}
# H-02 + H-03: write under base_dir atomically.
- _atomic_write_json(os.path.join(self.base_dir, CONFIG_FILE), config)
+ os.makedirs(self.config_root, exist_ok=True)
+ _atomic_write_json(
+ os.path.join(self.config_root, CONFIG_FILE), config
+ )
def closeEvent(self, event) -> None:
self.save_config()
diff --git a/src/ai_lsc/ui/pages/db_manager.py b/src/ai_lsc/ui/pages/db_manager.py
index 641133e..82c8221 100755
--- a/src/ai_lsc/ui/pages/db_manager.py
+++ b/src/ai_lsc/ui/pages/db_manager.py
@@ -46,120 +46,136 @@ except ImportError:
_HAS_QT = False
# ── Category → default Layer / Level / Role mapping ──────────────────
-# Derived from the canonical registry. When the user picks a category
-# these fields auto-fill; the user can still override afterwards.
+# Derived from the canonical registry (11-layer taxonomy, v3.1.1b:
+# Routing=L5, Orchestrators=L6, Security=L7, Observability=L8,
+# User Interfaces=L9, DevOps=L10, Knowledge Management=L11).
+# When the user picks a category these fields auto-fill; the user can
+# still override afterwards.
CATEGORY_MAP: dict[str, dict[str, object]] = {
- "AI Agent": {"layer": "Orchestrators", "level": 5, "role": "Sensory Bridge"},
- "AI Assistant Platform": {"layer": "User Interfaces", "level": 8, "role": "Central Intelligence"},
- "AI Augmentation": {"layer": "Orchestrators", "level": 5, "role": "Curation"},
- "AI Coding Agent": {"layer": "DevOps", "level": 9, "role": "Autonomous Coder"},
- "AI Monitoring": {"layer": "Observability", "level": 7, "role": "Health Monitor"},
- "AI Observability": {"layer": "Observability", "level": 7, "role": "LLM Tracing"},
- "AI Operating System": {"layer": "DevOps", "level": 9, "role": "OS Integration"},
- "Academic References": {"layer": "Knowledge Management", "level": 10, "role": "Reference Manager"},
- "Agent Framework": {"layer": "Orchestrators", "level": 5, "role": "Multi-Agent"},
- "Agent Network": {"layer": "DevOps", "level": 9, "role": "Discovery"},
- "Agent OS": {"layer": "Orchestrators", "level": 5, "role": "Hands"},
- "Agent Toolkit": {"layer": "Orchestrators", "level": 5, "role": "Tool Integration"},
- "Agent Workflow": {"layer": "Orchestrators", "level": 5, "role": "Reasoning"},
- "Algorithm Toolkit": {"layer": "DevOps", "level": 9, "role": "Hands"},
+ "AI Agent": {"layer": "Orchestrators", "level": 6, "role": "Sensory Bridge"},
+ "AI Assistant Platform": {"layer": "User Interfaces", "level": 9, "role": "Central Intelligence"},
+ "AI Augmentation": {"layer": "Orchestrators", "level": 6, "role": "Curation"},
+ "AI Coding Agent": {"layer": "DevOps", "level": 10, "role": "Coding Agent"},
+ "AI Monitoring": {"layer": "Observability", "level": 8, "role": "Health Monitor"},
+ "AI Observability": {"layer": "Observability", "level": 8, "role": "LLM Tracing"},
+ "AI Operating System": {"layer": "DevOps", "level": 10, "role": "OS Integration"},
+ "Academic References": {"layer": "Knowledge Management", "level": 11, "role": "Reference Manager"},
+ "Agent Framework": {"layer": "Orchestrators", "level": 6, "role": "Multi-Agent"},
+ "Agent Network": {"layer": "DevOps", "level": 10, "role": "Discovery"},
+ "Agent OS": {"layer": "Orchestrators", "level": 6, "role": "Hands"},
+ "Agent Toolkit": {"layer": "Orchestrators", "level": 6, "role": "Tool Integration"},
+ "Agent Workflow": {"layer": "Orchestrators", "level": 6, "role": "Reasoning"},
+ "Algorithm Toolkit": {"layer": "DevOps", "level": 10, "role": "Hands"},
"Analytical Database": {"layer": "Host Platform", "level": 1, "role": "Foundation"},
- "Antivirus": {"layer": "Security", "level": 6, "role": "Scanner"},
- "Audio Parsing": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Auth": {"layer": "Security", "level": 6, "role": "Identity"},
- "Build Monitoring": {"layer": "Orchestrators", "level": 5, "role": "Monitoring"},
+ "Antivirus": {"layer": "Security", "level": 7, "role": "Scanner"},
+ "Build": {"layer": "Development Environment", "level": 2, "role": "Build Tool"},
+ "Audio Parsing": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Auth": {"layer": "Security", "level": 7, "role": "Identity"},
+ "Build Monitoring": {"layer": "Observability", "level": 8, "role": "Monitoring"},
"Cache": {"layer": "Host Platform", "level": 1, "role": "Foundation"},
- "Chat": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Chat Agent Platform": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Chat Frontend": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Cluster SSH": {"layer": "Orchestrators", "level": 5, "role": "Coordination"},
- "Code Analysis": {"layer": "DevOps", "level": 9, "role": "Inspector"},
- "Code Generation": {"layer": "DevOps", "level": 9, "role": "Hands"},
- "Computer Vision": {"layer": "User Interfaces", "level": 8, "role": "Vision"},
- "Config Management": {"layer": "DevOps", "level": 9, "role": "Configuration Management"},
- "Container Security": {"layer": "Security", "level": 6, "role": "Scanner"},
+ "Chat": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Chat Agent Platform": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Chat Frontend": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Claude Code Skill": {"layer": "Orchestrators", "level": 6, "role": "Knowledge Graph Builder"},
+ "Cluster SSH": {"layer": "Orchestrators", "level": 6, "role": "Coordination"},
+ "Code Analysis": {"layer": "DevOps", "level": 10, "role": "Inspector"},
+ "Code Generation": {"layer": "DevOps", "level": 10, "role": "Hands"},
+ "Computer Vision": {"layer": "User Interfaces", "level": 9, "role": "Vision"},
+ "Config Management": {"layer": "DevOps", "level": 10, "role": "Configuration Management"},
+ "Container Ops": {"layer": "Orchestrators", "level": 6, "role": "Sandbox"},
+ "Container Security": {"layer": "Security", "level": 7, "role": "Scanner"},
"Containers": {"layer": "Host Platform", "level": 1, "role": "Container Runtime"},
- "Context Manager": {"layer": "DevOps", "level": 9, "role": "Context"},
- "Cortex Memory": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Dashboard": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Data Pipeline": {"layer": "Knowledge Management", "level": 10, "role": "Ingestion"},
- "Data Sync": {"layer": "Knowledge Management", "level": 10, "role": "Integration"},
+ "Context Manager": {"layer": "DevOps", "level": 10, "role": "Context"},
+ "Cortex Memory": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Dashboard": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Data Pipeline": {"layer": "Knowledge Management", "level": 11, "role": "Ingestion"},
+ "Data Sync": {"layer": "Knowledge Management", "level": 11, "role": "Integration"},
+ "Debugging": {"layer": "Development Environment", "level": 2, "role": "Profiling"},
"Database": {"layer": "Host Platform", "level": 1, "role": "Foundation"},
- "Desktop Agent": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Dev Automation": {"layer": "DevOps", "level": 9, "role": "Hands"},
- "Development": {"layer": "DevOps", "level": 9, "role": "Hands"},
- "Distributed Compilation": {"layer": "Orchestrators", "level": 5, "role": "Distribution"},
- "Distributed Compute": {"layer": "Orchestrators", "level": 5, "role": "Scaling"},
- "Document Converter": {"layer": "Knowledge Management", "level": 10, "role": "File Parsing"},
- "Document Management": {"layer": "Knowledge Management", "level": 10, "role": "Document Archive"},
- "Document Understanding": {"layer": "Knowledge Management", "level": 10, "role": "Comprehension"},
- "Ebook Library": {"layer": "Knowledge Management", "level": 10, "role": "Library Manager"},
- "Ecosystem Dashboard": {"layer": "User Interfaces", "level": 8, "role": "Face"},
+ "Desktop Agent": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Dev Automation": {"layer": "DevOps", "level": 10, "role": "Hands"},
+ "Development": {"layer": "DevOps", "level": 10, "role": "Hands"},
+ "Distributed Compilation": {"layer": "Orchestrators", "level": 6, "role": "Distribution"},
+ "Distributed Compute": {"layer": "Orchestrators", "level": 6, "role": "Scaling"},
+ "Document Converter": {"layer": "Knowledge Management", "level": 11, "role": "File Parsing"},
+ "Document Management": {"layer": "Knowledge Management", "level": 11, "role": "Document Archive"},
+ "Document Understanding": {"layer": "Knowledge Management", "level": 11, "role": "Comprehension"},
+ "Ebook Library": {"layer": "Knowledge Management", "level": 11, "role": "Library Manager"},
+ "Ecosystem Dashboard": {"layer": "User Interfaces", "level": 9, "role": "Face"},
"Efficient LLM": {"layer": "Engines", "level": 4, "role": "Engine"},
- "File Parsing": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
+ "File Parsing": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
"Find Tool": {"layer": "Development Environment", "level": 2, "role": "Search"},
"GPU": {"layer": "GPU Runtimes", "level": 3, "role": "Acceleration"},
"GPU Computing": {"layer": "Development Environment", "level": 2, "role": "GPU Acceleration"},
- "Graph Database": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Graph RAG": {"layer": "Knowledge Management", "level": 10, "role": "Knowledge Synthesis"},
- "Homepage": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "IaC": {"layer": "DevOps", "level": 9, "role": "Infrastructure as Code"},
- "IaC Control Plane": {"layer": "DevOps", "level": 9, "role": "Infrastructure as Code"},
- "IaC Wrapper": {"layer": "DevOps", "level": 9, "role": "Infrastructure as Code"},
- "Image Generation": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "Intrusion Prevention": {"layer": "Security", "level": 6, "role": "IDS"},
- "Knowledge Graph": {"layer": "DevOps", "level": 9, "role": "Graph Builder"},
- "Knowledge Graph Notes": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "LLM Evaluation": {"layer": "Observability", "level": 7, "role": "Evaluation"},
+ "Graph Database": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Graph RAG": {"layer": "Knowledge Management", "level": 11, "role": "Knowledge Synthesis"},
+ "Homepage": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "IaC": {"layer": "DevOps", "level": 10, "role": "Infrastructure as Code"},
+ "IaC Control Plane": {"layer": "DevOps", "level": 10, "role": "Infrastructure as Code"},
+ "IaC Wrapper": {"layer": "DevOps", "level": 10, "role": "Infrastructure as Code"},
+ "Image Generation": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "Infrastructure": {"layer": "Orchestrators", "level": 6, "role": "Resource Manager"},
+ "Intrusion Prevention": {"layer": "Security", "level": 7, "role": "IDS"},
+ "Knowledge Graph": {"layer": "DevOps", "level": 10, "role": "Graph Builder"},
+ "Knowledge Graph Notes": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "LLM Evaluation": {"layer": "Observability", "level": 8, "role": "Evaluation"},
+ "Memory System": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
"LLM Fine-tuning": {"layer": "GPU Runtimes", "level": 3, "role": "Abliteration"},
- "LLM Framework": {"layer": "Orchestrators", "level": 5, "role": "Orchestration"},
- "LLM GUI": {"layer": "User Interfaces", "level": 8, "role": "Face"},
- "LLM Router": {"layer": "Orchestrators", "level": 5, "role": "API Gateway"},
+ "LLM Framework": {"layer": "Orchestrators", "level": 6, "role": "Orchestration"},
+ "LLM GUI": {"layer": "User Interfaces", "level": 9, "role": "Face"},
+ "LLM Mesh": {"layer": "Routing", "level": 5, "role": "API Gateway"},
+ "LLM Router": {"layer": "Routing", "level": 5, "role": "API Gateway"},
"LLM Runtime": {"layer": "Engines", "level": 4, "role": "Engine"},
- "LLM Serving": {"layer": "Orchestrators", "level": 5, "role": "Scaling"},
- "MCP Server": {"layer": "Orchestrators", "level": 5, "role": "Code Audit"},
- "Metrics": {"layer": "Observability", "level": 7, "role": "Metrics Collector"},
+ "LLM Serving": {"layer": "Engines", "level": 4, "role": "Engine"},
+ "MCP Server": {"layer": "Orchestrators", "level": 6, "role": "Code Audit"},
+ "Metrics": {"layer": "Observability", "level": 8, "role": "Metrics Collector"},
+ "Mesh Client": {"layer": "Routing", "level": 5, "role": "Coding Agent"},
"Mixed Precision": {"layer": "GPU Runtimes", "level": 3, "role": "Optimization"},
+ "Model Surgery": {"layer": "Engines", "level": 4, "role": "Abliteration"},
"Model Training": {"layer": "Development Environment", "level": 2, "role": "Training"},
- "Multi-Agent": {"layer": "Orchestrators", "level": 5, "role": "Coordination"},
- "Notes": {"layer": "Knowledge Management", "level": 10, "role": "Note Taking"},
- "OCI Export": {"layer": "DevOps", "level": 9, "role": "Runtime Packaging"},
- "Outliner": {"layer": "Knowledge Management", "level": 10, "role": "Knowledge Graph"},
- "PDF Pipeline": {"layer": "Knowledge Management", "level": 10, "role": "Extraction"},
+ "Multi-Agent": {"layer": "Orchestrators", "level": 6, "role": "Coordination"},
+ "Networking": {"layer": "Host Platform", "level": 1, "role": "Tunnel"},
+ "Notes": {"layer": "Knowledge Management", "level": 11, "role": "Note Taking"},
+ "OCI Export": {"layer": "DevOps", "level": 10, "role": "Runtime Packaging"},
+ "Observability": {"layer": "Observability", "level": 8, "role": "Monitoring"},
+ "Outliner": {"layer": "Knowledge Management", "level": 11, "role": "Knowledge Graph"},
+ "PDF Pipeline": {"layer": "Knowledge Management", "level": 11, "role": "Extraction"},
"Parser": {"layer": "Development Environment", "level": 2, "role": "Parsing"},
- "Persistent Memory": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Pipeline": {"layer": "Orchestrators", "level": 5, "role": "Pipeline Orchestrator"},
- "Policy Engine": {"layer": "Security", "level": 6, "role": "Policy"},
- "Procfile Runner": {"layer": "DevOps", "level": 9, "role": "Process Manager"},
- "Project Management": {"layer": "DevOps", "level": 9, "role": "Management"},
- "Prompt Tooling": {"layer": "DevOps", "level": 9, "role": "Prompt Management"},
- "Provisioning": {"layer": "DevOps", "level": 9, "role": "Provisioning"},
- "Proxy": {"layer": "Orchestrators", "level": 5, "role": "API Gateway"},
- "Reasoning Engine": {"layer": "Orchestrators", "level": 5, "role": "Brain"},
+ "Persistent Memory": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Pipeline": {"layer": "Routing", "level": 5, "role": "Pipeline Orchestrator"},
+ "Policy Engine": {"layer": "Security", "level": 7, "role": "Policy"},
+ "Procfile Runner": {"layer": "DevOps", "level": 10, "role": "Process Manager"},
+ "Project Management": {"layer": "DevOps", "level": 10, "role": "Management"},
+ "Prompt Tooling": {"layer": "DevOps", "level": 10, "role": "Prompt Management"},
+ "Provisioning": {"layer": "DevOps", "level": 10, "role": "Provisioning"},
+ "Proxy": {"layer": "Routing", "level": 5, "role": "API Gateway"},
+ "Reasoning Engine": {"layer": "Orchestrators", "level": 6, "role": "Brain"},
"Runtime": {"layer": "Development Environment", "level": 2, "role": "Build System"},
- "Sandbox": {"layer": "DevOps", "level": 9, "role": "Isolation"},
- "Search Engine": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
+ "Sandbox": {"layer": "DevOps", "level": 10, "role": "Isolation"},
+ "Search Engine": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
"Search Tool": {"layer": "Development Environment", "level": 2, "role": "Search"},
- "Secrets Management": {"layer": "Security", "level": 6, "role": "Secrets"},
+ "Shell": {"layer": "Development Environment", "level": 2, "role": "Shell"},
+ "Secrets Management": {"layer": "Security", "level": 7, "role": "Secrets"},
"Serverless Framework": {"layer": "Development Environment", "level": 2, "role": "Full-Stack Framework"},
"Single-File LLM": {"layer": "Engines", "level": 4, "role": "Engine"},
- "Skill Analysis": {"layer": "DevOps", "level": 9, "role": "Assessment"},
- "Skill Inspection": {"layer": "DevOps", "level": 9, "role": "Analysis"},
- "Spaced Repetition": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Spec Writer": {"layer": "DevOps", "level": 9, "role": "Documentation"},
- "Speech Recognition": {"layer": "User Interfaces", "level": 8, "role": "Senses"},
- "Task Runner": {"layer": "DevOps", "level": 9, "role": "Scheduler"},
- "Telemetry": {"layer": "Observability", "level": 7, "role": "Collector"},
+ "Skill Analysis": {"layer": "DevOps", "level": 10, "role": "Assessment"},
+ "Skill Inspection": {"layer": "DevOps", "level": 10, "role": "Analysis"},
+ "Spaced Repetition": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Spec Writer": {"layer": "DevOps", "level": 10, "role": "Documentation"},
+ "Speech Recognition": {"layer": "User Interfaces", "level": 9, "role": "Senses"},
+ "Task Runner": {"layer": "DevOps", "level": 10, "role": "Scheduler"},
+ "Telemetry": {"layer": "Observability", "level": 8, "role": "Collector"},
"Terminal": {"layer": "Host Platform", "level": 1, "role": "Multiplexer"},
- "Text-to-Speech": {"layer": "User Interfaces", "level": 8, "role": "Voice"},
+ "Text-to-Speech": {"layer": "User Interfaces", "level": 9, "role": "Voice"},
"Uncensored Models": {"layer": "Engines", "level": 4, "role": "Engine"},
"VCS": {"layer": "Host Platform", "level": 1, "role": "Version Control"},
- "Vector Engine": {"layer": "Knowledge Management", "level": 10, "role": "Embedding"},
- "Vector Store": {"layer": "Knowledge Management", "level": 10, "role": "Memory"},
- "Visualization": {"layer": "Observability", "level": 7, "role": "Dashboard"},
- "Web Crawler": {"layer": "Knowledge Management", "level": 10, "role": "Data Harvesting"},
- "Workflow": {"layer": "Orchestrators", "level": 5, "role": "Visual Builder"},
- "Workflow Automation": {"layer": "Orchestrators", "level": 5, "role": "Workflow Orchestrator"},
+ "Vector Engine": {"layer": "Knowledge Management", "level": 11, "role": "Embedding"},
+ "Vector Store": {"layer": "Knowledge Management", "level": 11, "role": "Memory"},
+ "Visualization": {"layer": "Observability", "level": 8, "role": "Dashboard"},
+ "Virtualization": {"layer": "Host Platform", "level": 1, "role": "MicroVM"},
+ "Web Crawler": {"layer": "Knowledge Management", "level": 11, "role": "Data Harvesting"},
+ "Workflow": {"layer": "Orchestrators", "level": 6, "role": "Visual Builder"},
+ "Workflow Automation": {"layer": "Orchestrators", "level": 6, "role": "Workflow Orchestrator"},
}
# ── Field-constant lookups (populated once on first use) ─────────────
diff --git a/src/ai_lsc/utils/paths.py b/src/ai_lsc/utils/paths.py
index 2a90787..68ff70f 100755
--- a/src/ai_lsc/utils/paths.py
+++ b/src/ai_lsc/utils/paths.py
@@ -31,30 +31,61 @@ def build_path_tree(base_dir: str | Path | None = None) -> dict[str, Path]:
Example::
{
- "base_dir": Path("/mnt/AI"),
- "tools_root": Path("/mnt/AI/tools"),
- "models_root": Path("/mnt/AI/models"),
- "logs_root": Path("/mnt/AI/logs"),
- "skills_root": Path("/mnt/AI/skills"),
- "datasets_root": Path("/mnt/AI/datasets"),
- "config_root": Path("/mnt/AI/config"),
- "workspaces_root": Path("/mnt/AI/workspaces"),
- "exports_root": Path("/mnt/AI/exports"),
- "registry_root": Path("/mnt/AI/registry"),
+ "base_dir": Path("/mnt/AI"),
+ "tools_root": Path("/mnt/AI/tools"), # standalone CLI utilities
+ "runtime_root": Path("/mnt/AI/runtime"), # native binaries + per-tool venvs
+ "models_root": Path("/mnt/AI/models"), # parent of hot/ and cold/
+ "models_hot": Path("/mnt/AI/models/hot"), # active weights (SSD)
+ "models_cold": Path("/mnt/AI/models/cold"), # archived weights (HDD)
+ "corpus_root": Path("/mnt/AI/corpus"), # parent of hot/ and cold/
+ "datasets_root": Path("/mnt/AI/datasets"), # parent of wordlists/, huggingface/, github/
+ "pipelines_root": Path("/mnt/AI/pipelines"), # ETL / chunking / routing scripts
+ "configs_root": Path("/mnt/AI/configs"), # app state + templated configs
+ "registry_root": Path("/mnt/AI/registry"), # app-internal: ecosystem.json + manifests/
+ "agents_root": Path("/mnt/AI/agents"), # configs and chains for autonomous actors
+ "skills_root": Path("/mnt/AI/skills"), # 3rd-party integrations and tool wrappers
+ "projects_root": Path("/mnt/AI/projects"), # parent of active/, labs/, vault/
+ "blueprints_root": Path("/mnt/AI/blueprints"), # Dockerfiles / build contexts for Podman exports
+ "workspaces_root": Path("/mnt/AI/workspaces"), # Jupyter, OpenNotebook, etc.
+ "dashboards_root": Path("/mnt/AI/dashboards"), # web UIs (Dashy, Open-WebUI, Hermes WebUI, etc.)
+ "exports_root": Path("/mnt/AI/exports"), # parent of oci-images/
+ "scripts_root": Path("/mnt/AI/scripts"), # system admin / maintenance automation
+ "logs_root": Path("/mnt/AI/logs"),
+ "backends_root": Path("/mnt/AI/backends"), # S3/MinIO/Ceph connection profiles
+ "distfiles_root": Path("/mnt/AI/distfiles"), # permanent local mirror of source tarballs
+ "config_root": Path("/mnt/AI/configs"), # app state + templated configs
}
"""
root = Path(base_dir) if base_dir is not None else Path(BASE_DIR)
return {
"base_dir": root,
"tools_root": root / "tools",
+ "runtime_root": root / "runtime",
"models_root": root / "models",
- "logs_root": root / "logs",
- "skills_root": root / "skills",
+ "models_hot": root / "models" / "hot",
+ "models_cold": root / "models" / "cold",
+ "corpus_root": root / "corpus",
"datasets_root": root / "datasets",
- "config_root": root / "config",
- "workspaces_root": root / "workspaces",
- "exports_root": root / "exports",
+ "pipelines_root": root / "pipelines",
"registry_root": root / "registry",
+ "agents_root": root / "agents",
+ "skills_root": root / "skills",
+ "projects_root": root / "projects",
+ "blueprints_root": root / "blueprints",
+ "workspaces_root": root / "workspaces",
+ "dashboards_root": root / "dashboards",
+ "exports_root": root / "exports",
+ "scripts_root": root / "scripts",
+ "logs_root": root / "logs",
+ "backends_root": root / "backends",
+ "distfiles_root": root / "distfiles",
+ "configs_root": root / "configs",
+ # App-state + templated app configs (controller_config.json,
+ # pipeline_state.json, license_approvals.json). Per-tool config
+ # subdirs (configs//) are created on demand by
+ # InstallerManager. Legacy installs used base_dir/config or
+ # base_dir root — main_window migrates those on startup.
+ "config_root": root / "configs",
}