// grafana's tools — moved here from the shared hal sdk (novox/hq ADR 0039), importing grafana's own // client. They return structured data; the mesh serves them through the sdk's tool harness. import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools"; import { GrafanaClient } from "../client.js"; export function getGrafanaTools(grafana: GrafanaClient): ToolDefinition[] { return [ { name: "grafana_status", description: "Grafana server health — database state, version, build commit.", input: {}, run: async () => grafana.health(), }, { name: "grafana_list_datasources", description: "List Grafana data sources — name, type, backing URL, which is default.", input: {}, run: async () => { const datasources = await grafana.listDatasources(); return { count: datasources.length, datasources }; }, }, { name: "grafana_list_dashboards", description: "List Grafana dashboards, optionally filtered by a name query.", input: { query: { type: "string", description: "filter dashboards by name (optional)" } }, run: async (args) => { const query = args.query ? String(args.query) : undefined; const dashboards = await grafana.listDashboards(query); return { count: dashboards.length, dashboards }; }, }, { name: "grafana_alerts", description: "Active Grafana alert instances and their state (Alerting, Pending, Normal).", input: {}, run: async () => { const alerts = await grafana.listAlerts(); const firing = alerts.filter((a) => a.state.toLowerCase() === "alerting"); return { count: alerts.length, firing: firing.length, alerts }; }, }, ]; } // The tools exist only when Grafana auth can be resolved; without it, grafana contributes none // rather than failing the whole tool runtime. registerModuleTools("grafana", (env) => { try { return getGrafanaTools(GrafanaClient.fromEnv(env)); } catch { return []; } });