grafana, tautulli, nextcloud, nodered: full nox modules (ADR 0044/0046)
grafana: status/datasources/dashboards/alerts tools, emits alert.firing. tautulli: activity/history/stats tools, emits watch.recorded. nextcloud: users/shares/apps/occ tools (occ via docker exec, shares over OCS), emits user.created/share.created. nodered: flows/nodes/deploy tools, emits flows.deployed inline from the deploy tool. All typecheck; manifests parse.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// grafana's tools — moved here from the shared hal sdk (novox/hq ADR 0044), 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 [];
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user