Files
obsidian-rag/src/tools/index.ts
Santhosh Janardhanan da1cf8bb60 feat: wire all 4 obsidian_rag tools to OpenClaw via AnyAgentTool factory
- Replace TypeBox + AgentToolResult with native OpenClaw AnyAgentTool pattern
- Add id, openclaw, main fields to openclaw.plugin.json manifest
- registerTools() now uses factory helpers returning typed AnyAgentTool objects
- toAgentResult() adapter bridges search/index/status/memory results to AgentToolResult shape
- Build clean — pi-agent-core peer dep not needed, openclaw exports all types
- Task list updated: Phase 4 tools + plugin registration marked complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 14:12:22 -04:00

113 lines
4.5 KiB
TypeScript

/** 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<string, unknown>,
};
}
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<string, unknown>) {
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<string, unknown>) {
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<string, unknown>) {
return toAgentResult(await memoryStoreTool(params as any));
},
} as AnyAgentTool;
}