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. ![Overview](docs/screenshots/overview.png) @@ -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 | ![Infrastructure Layers](docs/screenshots/infrastructure-layers.png) 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", }