Initial commit: Agentic OS troubleshooting platform
Self-hosted, Docker-based agentic troubleshooting platform: FastAPI backend + LangGraph agent, Next.js UI, tiered LLM routing (local Ollama -> Gemini -> DeepSeek -> OpenRouter), MCP server manager, encrypted device credentials, RBAC, audit log, project-memory + Obsidian integrations, and editable troubleshooting decision rules tuned for the GeneseasX vessel stack. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
84
backend/app/agent/asterisk_profiles.py
Normal file
84
backend/app/agent/asterisk_profiles.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""Asterisk deployment profiles and connect playbooks."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shlex
|
||||
|
||||
from app.agent.device_connect import ssh_connect_args
|
||||
|
||||
# Only one Asterisk slot allowed per vessel.
|
||||
ASTERISK_CATALOG_KEYS = frozenset({"asterisk", "asterisk_geneseasx", "asterisk_satbox"})
|
||||
|
||||
GENESEASX_KEYS = frozenset({"asterisk", "asterisk_geneseasx"})
|
||||
SATBOX_KEYS = frozenset({"asterisk_satbox"})
|
||||
|
||||
|
||||
def asterisk_container_name(catalog_key: str | None) -> str:
|
||||
"""Docker container name for GeneseasX Asterisk (default: voip)."""
|
||||
if catalog_key not in GENESEASX_KEYS:
|
||||
return ""
|
||||
return (
|
||||
os.environ.get("DEVICE_ASTERISK_GENESEASX_CONTAINER", "").strip()
|
||||
or os.environ.get("DEVICE_ASTERISK_CONTAINER", "").strip()
|
||||
or "voip"
|
||||
)
|
||||
|
||||
|
||||
def _ssh_connect(ctx: dict) -> dict:
|
||||
port = ctx.get("port")
|
||||
if port is None:
|
||||
port_raw = os.environ.get("DEVICE_ASTERISK_GENESEASX_PORT", "").strip()
|
||||
port = int(port_raw) if port_raw.isdigit() else 6022
|
||||
return ssh_connect_args({**ctx, "port": port})
|
||||
|
||||
|
||||
def _docker_asterisk(command: str):
|
||||
def builder(c: dict) -> dict:
|
||||
container = c.get("asterisk_container") or asterisk_container_name(c.get("catalog_key")) or "voip"
|
||||
return {"command": f"docker exec {container} asterisk -rx {shlex.quote(command)}"}
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def _asterisk_cli(command: str):
|
||||
return lambda c: {"command": f'asterisk -rx "{command}"'}
|
||||
|
||||
|
||||
# Native Debian host diagnostics (TMGeneseas / satbox) via SSH.
|
||||
SATBOX_ASTERISK_DIAGNOSTICS = [
|
||||
("ssh_run", _asterisk_cli("pjsip show registrations")),
|
||||
("ssh_run", _asterisk_cli("pjsip show endpoints")),
|
||||
("ssh_run", _asterisk_cli("core show channels")),
|
||||
("ssh_run", lambda c: {"command": "tail -n 100 /var/log/asterisk/full 2>/dev/null || journalctl -u asterisk -n 100 --no-pager 2>/dev/null || true"}),
|
||||
]
|
||||
|
||||
# GeneseasX: SSH to Docker VM, docker exec into voip (password auth via ssh-generic-mcp).
|
||||
GENESEASX_ASTERISK_DIAGNOSTICS = [
|
||||
("ssh_run", _docker_asterisk("pjsip show registrations")),
|
||||
("ssh_run", _docker_asterisk("pjsip show endpoints")),
|
||||
("ssh_run", _docker_asterisk("core show channels")),
|
||||
("ssh_run", lambda c: {
|
||||
"command": (
|
||||
f"docker logs --tail 100 {shlex.quote(c.get('asterisk_container') or 'voip')} 2>&1 | tail -100"
|
||||
)
|
||||
}),
|
||||
]
|
||||
|
||||
ASTERISK_PLAYBOOKS: dict[str, dict] = {
|
||||
"asterisk_geneseasx": {
|
||||
"mcp_server": "ssh-generic-mcp",
|
||||
"connect": ("ssh_connect", _ssh_connect),
|
||||
"diagnostics": GENESEASX_ASTERISK_DIAGNOSTICS,
|
||||
},
|
||||
# Legacy catalog key — same as GeneseasX
|
||||
"asterisk": {
|
||||
"mcp_server": "ssh-generic-mcp",
|
||||
"connect": ("ssh_connect", _ssh_connect),
|
||||
"diagnostics": GENESEASX_ASTERISK_DIAGNOSTICS,
|
||||
},
|
||||
"asterisk_satbox": {
|
||||
"mcp_server": "ssh-generic-mcp",
|
||||
"connect": ("ssh_connect", _ssh_connect),
|
||||
"diagnostics": SATBOX_ASTERISK_DIAGNOSTICS,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user