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:
2026-06-14 22:11:07 +03:00
commit 6185b9b85a
126 changed files with 14565 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
export const ACTIVE_STATUSES = ["running", "queued", "waiting_approval"] as const;
export type TaskStatus =
| "queued"
| "running"
| "waiting_approval"
| "succeeded"
| "failed"
| "cancelled";
export type TaskEvent = {
id?: number;
kind: string;
message: string | null;
payload?: Record<string, any> | null;
ts?: string;
created_at?: string;
replay?: boolean;
};
export type TaskOverview = {
id: number;
title: string;
issue: string;
status: TaskStatus;
vessel_id: number | null;
vessel_name?: string | null;
summary?: string | null;
key_finding?: string | null;
devices_checked: string[];
resolved?: boolean | null;
memory_id?: string | null;
obsidian_path?: string | null;
obsidian_push_error?: string | null;
run_cost_usd?: number | null;
created_at: string;
updated_at: string;
};
export type TaskPreview = {
vessel_id: number;
vessel_name?: string | null;
devices: { catalog_key: string; name: string; label: string; checks: string[] }[];
rule_id?: string | null;
rule_name?: string | null;
severity?: string | null;
hints: string[];
warning?: string | null;
};
export function isActiveStatus(status: string) {
return ACTIVE_STATUSES.includes(status as (typeof ACTIVE_STATUSES)[number]);
}
export function taskPhaseLabel(status: string, events: TaskEvent[] = []) {
if (status === "queued") return "Waiting in queue";
if (status === "waiting_approval") return "Waiting for approval";
if (status === "succeeded") return "Report complete";
if (status === "failed") return "Failed";
if (status === "cancelled") return "Stopped";
const last = [...events].reverse().find((e) => e.kind !== "log");
if (!last) return "Starting";
if (last.kind === "context") return "Gathering context";
if (last.kind === "triage" || last.kind === "rule") return "Planning checks";
if (last.kind === "connect") return "Connecting to devices";
if (last.kind === "tool_start" || last.kind === "tool_call" || last.kind === "diagnose") {
const device = last.payload?.device;
const tool = humanToolName(String(last.payload?.tool || ""));
return [device, tool].filter(Boolean).join(": ") || "Running diagnostics";
}
if (last.kind === "reason") return "Analyzing findings";
if (last.kind === "report") return "Writing report";
return last.message || "Running";
}
export function humanToolName(tool: string) {
const known: Record<string, string> = {
pfsense_get_system_status: "pfSense system status",
pfsense_list_interfaces: "pfSense interfaces",
pfsense_list_gateways: "pfSense gateways",
pfsense_get_gateway_status: "pfSense gateway status",
pfsense_list_firewall_rules: "pfSense firewall rules",
pfsense_list_port_forwards: "pfSense port forwards",
pfsense_list_outbound_nat_mappings: "pfSense outbound NAT",
proxmox_list_nodes: "Proxmox nodes",
proxmox_list_qemu: "Proxmox VMs",
proxmox_list_lxc: "Proxmox LXCs",
proxmox_get_qemu_status: "VM status",
proxmox_get_qemu_config: "VM config",
ssh_run: "SSH command",
};
return known[tool] || tool.replace(/_/g, " ");
}