41 lines
1.5 KiB
TypeScript
41 lines
1.5 KiB
TypeScript
import { z } from 'zod';
|
|
import type { ToolDef } from '../tools/types.js';
|
|
import { scanProjectMemory } from '../memory/scan.js';
|
|
import { rankByHybrid } from '../memory/recall.js';
|
|
|
|
const SearchMemoryInput = z.object({
|
|
query: z.string().min(1).describe('Search query to match against memory entries'),
|
|
});
|
|
|
|
type InputT = z.infer<typeof SearchMemoryInput>;
|
|
|
|
export const searchMemoryTool: ToolDef<InputT> = {
|
|
name: 'search_memory',
|
|
description: 'Search the .boocode/memory/ store for relevant entries. Returns ranked results matching the query. Use before asking about project conventions or preferences.',
|
|
inputSchema: SearchMemoryInput,
|
|
jsonSchema: {
|
|
type: 'function',
|
|
function: {
|
|
name: 'search_memory',
|
|
description: 'Search memory store for relevant entries',
|
|
parameters: {
|
|
type: 'object',
|
|
properties: {
|
|
query: { type: 'string', description: 'Search query' },
|
|
},
|
|
required: ['query'],
|
|
},
|
|
},
|
|
},
|
|
async execute(input: InputT, projectRoot: string): Promise<unknown> {
|
|
const entries = await scanProjectMemory(projectRoot);
|
|
if (entries.length === 0) return { result: 'No memory entries found.' };
|
|
|
|
const relevant = await rankByHybrid(input.query, entries);
|
|
if (relevant.length === 0) return { result: 'No matching memory entries.' };
|
|
|
|
const lines = relevant.map((e) => `[${e.topic}] ${e.title}: ${e.content}`);
|
|
return { result: `Found ${relevant.length} entry(ies):\n${lines.join('\n')}` };
|
|
},
|
|
};
|