searxng: a search tool — tools-only, a stateless search has nothing to observe. icecast: status tool, emits stream.started/.stopped by diffing live mountpoints. photos: status/albums/recent tools, emits item.added (immich-shaped API, coded defensively since the stub ships a placeholder image — flagged in the code). Typecheck; manifests parse.
38 lines
1.5 KiB
TypeScript
38 lines
1.5 KiB
TypeScript
// searxng's tools (novox/hq ADR 0044), importing searxng's own client. A stateless metasearch: one
|
|
// query in, merged results out — genuinely useful, and with nothing to observe over time it stays
|
|
// tools-only (no events, no broker).
|
|
|
|
import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools";
|
|
import { SearxngClient } from "../client.js";
|
|
|
|
export function getSearxngTools(searxng: SearxngClient): ToolDefinition[] {
|
|
return [
|
|
{
|
|
name: "searxng_search",
|
|
description: "Search the web through SearXNG's privacy-respecting metasearch — merged results from many engines.",
|
|
input: {
|
|
query: { type: "string", description: "the search query" },
|
|
categories: { type: "string", description: "comma-separated categories, e.g. 'general', 'news', 'images'" },
|
|
language: { type: "string", description: "language code, e.g. 'en' or 'en-US'" },
|
|
},
|
|
run: async (args) => {
|
|
const found = await searxng.search(String(args.query), {
|
|
categories: args.categories ? String(args.categories) : undefined,
|
|
language: args.language ? String(args.language) : undefined,
|
|
});
|
|
return found;
|
|
},
|
|
},
|
|
];
|
|
}
|
|
|
|
// A URL always resolves (it defaults), so this normally contributes its tool; the try/catch keeps a
|
|
// misconfiguration from taking the whole runtime down.
|
|
registerModuleTools("searxng", (env) => {
|
|
try {
|
|
return getSearxngTools(SearxngClient.fromEnv(env));
|
|
} catch {
|
|
return [];
|
|
}
|
|
});
|