/** Tool registration — wires all 4 obsidian_rag_* tools into OpenClaw. */ import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk"; import type { ObsidianRagConfig } from "../utils/config.js"; import type { HealthState } from "../services/health.js"; import { searchTool } from "./search.js"; import { runIndexTool } from "./index-tool.js"; import { statusTool } from "./status.js"; import { memoryStoreTool } from "./memory.js"; export function registerTools( api: OpenClawPluginApi, config: ObsidianRagConfig, health: { get: () => { state: HealthState }; setActiveJob: (job: { id: string; mode: string; progress: number } | null) => void }, ): void { api.registerTool(makeSearchTool(config)); api.registerTool(makeIndexTool(config, health)); api.registerTool(makeStatusTool(config)); api.registerTool(makeMemoryStoreTool()); } function toAgentResult(result: unknown) { return { content: [{ type: "text" as const, text: JSON.stringify(result) }], details: result as Record, }; } function makeSearchTool(config: ObsidianRagConfig): AnyAgentTool { return { name: "obsidian_rag_search", description: "Primary semantic search tool for querying the Obsidian vault. Use for natural language questions about journal entries, financial records, health data, project ideas, and more.", label: "Obsidian RAG Search", parameters: { type: "object", properties: { query: { type: "string", description: "Natural language question or topic to search for" }, max_results: { type: "integer", description: "Maximum number of chunks to return (default: 5, range: 1-50)", default: 5, minimum: 1, maximum: 50 }, directory_filter: { type: "array", description: "Limit search to specific subdirectories", items: { type: "string" } }, date_range: { type: "object", properties: { from: { type: "string" }, to: { type: "string" } }, }, tags: { type: "array", description: "Filter by hashtags", items: { type: "string" } }, }, required: ["query"], }, // eslint-disable-next-line @typescript-eslint/no-explicit-any async execute(_toolCallId: string, params: Record) { return toAgentResult(await searchTool(config, params as any)); }, } as AnyAgentTool; } function makeIndexTool( config: ObsidianRagConfig, health: { get: () => { state: HealthState }; setActiveJob: (job: { id: string; mode: string; progress: number } | null) => void }, ): AnyAgentTool { return { name: "obsidian_rag_index", description: "Trigger indexing of the Obsidian vault. Use 'full' for initial index, 'sync' for incremental updates, 'reindex' to force full rebuild.", label: "Obsidian RAG Index", parameters: { type: "object", properties: { mode: { type: "string", enum: ["full", "sync", "reindex"], description: "Indexing mode" }, }, required: ["mode"], }, // eslint-disable-next-line @typescript-eslint/no-explicit-any async execute(_toolCallId: string, params: Record) { return toAgentResult(await runIndexTool(config, health, params as any)); }, } as AnyAgentTool; } function makeStatusTool(config: ObsidianRagConfig): AnyAgentTool { return { name: "obsidian_rag_status", description: "Check the health of the Obsidian RAG plugin: index statistics, last sync time, Ollama status, and active indexing job.", label: "Obsidian RAG Status", parameters: { type: "object", properties: {} }, async execute(_toolCallId: string) { return toAgentResult(await statusTool(config)); }, } as AnyAgentTool; } function makeMemoryStoreTool(): AnyAgentTool { return { name: "obsidian_rag_memory_store", description: "Commit important facts from search results to OpenClaw's memory for faster future retrieval. Auto-suggested when search detects financial, health, or commitment content.", label: "Obsidian RAG Memory Store", parameters: { type: "object", properties: { key: { type: "string", description: "Identifier for the fact (e.g. 'debt_to_sreenivas')" }, value: { type: "string", description: "The fact to remember" }, source: { type: "string", description: "Source file path in the vault" }, }, required: ["key", "value", "source"], }, // eslint-disable-next-line @typescript-eslint/no-explicit-any async execute(_toolCallId: string, params: Record) { return toAgentResult(await memoryStoreTool(params as any)); }, } as AnyAgentTool; }