// nextcloud's tools — importing nextcloud's own client (novox/hq ADR 0039). occ runs inside the // container; shares come over OCS. They return structured data; the mesh serves them through the // sdk's tool harness. import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools"; import { NextcloudClient } from "../client.js"; export function getNextcloudTools(nextcloud: NextcloudClient): ToolDefinition[] { return [ { name: "nextcloud_users", description: "List Nextcloud user accounts — uid and display name — via occ.", input: {}, run: async () => { const users = nextcloud.listUsers(); return { count: users.length, users }; }, }, { name: "nextcloud_shares", description: "List Nextcloud shares — path, type, who it is shared with — via the OCS API.", input: {}, run: async () => { const shares = await nextcloud.listShares(); return { count: shares.length, shares }; }, }, { name: "nextcloud_apps", description: "List Nextcloud apps, split into enabled and disabled, via occ.", input: {}, run: async () => nextcloud.listApps(), }, { name: "nextcloud_occ", description: "Run an arbitrary occ admin command, e.g. status, 'config:system:get trusted_domains', " + "user:list. occ is Nextcloud's CLI inside the container, run as the web user.", input: { args: { type: "array", description: 'occ arguments, e.g. ["config:system:get","trusted_domains"]' } }, run: async (args) => { const occArgs = (args.args ?? []) as unknown[]; if (!Array.isArray(occArgs) || occArgs.length === 0) throw new Error('args must be a non-empty array, e.g. ["status"]'); return { output: nextcloud.occ(occArgs.map(String)) || "(no output)" }; }, }, ]; } // The tools exist only when the admin password can be resolved; without it, nextcloud contributes // none rather than failing the whole tool runtime. registerModuleTools("nextcloud", (env) => { try { return getNextcloudTools(NextcloudClient.fromEnv(env)); } catch { return []; } });