2025-04-06 20:50:08 +00:00
/ * *
* Search Notes Tool
*
* This tool allows the LLM to search for notes using semantic search .
* /
import type { Tool , ToolHandler } from './tool_interfaces.js' ;
import log from '../../log.js' ;
import aiServiceManager from '../ai_service_manager.js' ;
/ * *
* Definition of the search notes tool
* /
export const searchNotesToolDefinition : Tool = {
type : 'function' ,
function : {
name : 'search_notes' ,
description : 'Search for notes in the database using semantic search. Returns notes most semantically related to the query.' ,
parameters : {
type : 'object' ,
properties : {
query : {
type : 'string' ,
description : 'The search query to find semantically related notes'
} ,
parentNoteId : {
type : 'string' ,
2025-04-17 16:25:39 +00:00
description : 'Optional system ID of the parent note to restrict search to a specific branch (not the title). This is a unique identifier like "abc123def456".'
2025-04-06 20:50:08 +00:00
} ,
maxResults : {
type : 'number' ,
description : 'Maximum number of results to return (default: 5)'
}
} ,
required : [ 'query' ]
}
}
} ;
2025-04-17 03:08:11 +00:00
/ * *
* Get or create the vector search tool dependency
* @returns The vector search tool or null if it couldn ' t be created
* /
async function getOrCreateVectorSearchTool ( ) : Promise < any > {
try {
// Try to get the existing vector search tool
let vectorSearchTool = aiServiceManager . getVectorSearchTool ( ) ;
if ( vectorSearchTool ) {
log . info ( ` Found existing vectorSearchTool ` ) ;
return vectorSearchTool ;
}
// No existing tool, try to initialize it
log . info ( ` VectorSearchTool not found, attempting initialization ` ) ;
// Get agent tools manager and initialize it
const agentTools = aiServiceManager . getAgentTools ( ) ;
if ( agentTools && typeof agentTools . initialize === 'function' ) {
log . info ( 'Initializing agent tools to create vectorSearchTool' ) ;
try {
// Force initialization to ensure it runs even if previously marked as initialized
await agentTools . initialize ( true ) ;
log . info ( 'Agent tools initialized successfully' ) ;
} catch ( initError : any ) {
log . error ( ` Failed to initialize agent tools: ${ initError . message } ` ) ;
return null ;
}
} else {
log . error ( 'Agent tools manager not available' ) ;
return null ;
}
// Try getting the vector search tool again after initialization
vectorSearchTool = aiServiceManager . getVectorSearchTool ( ) ;
if ( vectorSearchTool ) {
log . info ( 'Successfully created vectorSearchTool' ) ;
return vectorSearchTool ;
} else {
log . error ( 'Failed to create vectorSearchTool after initialization' ) ;
return null ;
}
} catch ( error : any ) {
log . error ( ` Error getting or creating vectorSearchTool: ${ error . message } ` ) ;
return null ;
}
}
2025-04-06 20:50:08 +00:00
/ * *
* Search notes tool implementation
* /
export class SearchNotesTool implements ToolHandler {
public definition : Tool = searchNotesToolDefinition ;
/ * *
* Execute the search notes tool
* /
public async execute ( args : { query : string , parentNoteId? : string , maxResults? : number } ) : Promise < string | object > {
try {
const { query , parentNoteId , maxResults = 5 } = args ;
log . info ( ` Executing search_notes tool - Query: " ${ query } ", ParentNoteId: ${ parentNoteId || 'not specified' } , MaxResults: ${ maxResults } ` ) ;
// Get the vector search tool from the AI service manager
2025-04-17 03:08:11 +00:00
const vectorSearchTool = await getOrCreateVectorSearchTool ( ) ;
if ( ! vectorSearchTool ) {
return ` Error: Vector search tool is not available. The system may still be initializing or there could be a configuration issue. ` ;
}
2025-04-06 20:50:08 +00:00
log . info ( ` Retrieved vector search tool from AI service manager ` ) ;
2025-04-17 03:08:11 +00:00
// Check if searchNotes method exists
if ( ! vectorSearchTool . searchNotes || typeof vectorSearchTool . searchNotes !== 'function' ) {
log . error ( ` Vector search tool is missing searchNotes method ` ) ;
return ` Error: Vector search tool is improperly configured (missing searchNotes method). ` ;
}
2025-04-06 20:50:08 +00:00
// Execute the search
log . info ( ` Performing semantic search for: " ${ query } " ` ) ;
const searchStartTime = Date . now ( ) ;
const results = await vectorSearchTool . searchNotes ( query , {
parentNoteId ,
maxResults
} ) ;
const searchDuration = Date . now ( ) - searchStartTime ;
log . info ( ` Search completed in ${ searchDuration } ms, found ${ results . length } matching notes ` ) ;
if ( results . length > 0 ) {
// Log top results
2025-04-17 03:08:11 +00:00
results . slice ( 0 , 3 ) . forEach ( ( result : any , index : number ) = > {
2025-04-06 20:50:08 +00:00
log . info ( ` Result ${ index + 1 } : " ${ result . title } " (similarity: ${ Math . round ( result . similarity * 100 ) } %) ` ) ;
} ) ;
} else {
log . info ( ` No matching notes found for query: " ${ query } " ` ) ;
}
// Format the results
return {
count : results.length ,
2025-04-17 03:08:11 +00:00
results : results.map ( ( result : any ) = > ( {
2025-04-06 20:50:08 +00:00
noteId : result.noteId ,
title : result.title ,
preview : result.contentPreview ,
similarity : Math.round ( result . similarity * 100 ) / 100 ,
parentId : result.parentId
2025-04-17 16:25:39 +00:00
} ) ) ,
message : "Note: Use the noteId (not the title) when performing operations on specific notes with other tools."
2025-04-06 20:50:08 +00:00
} ;
} catch ( error : any ) {
log . error ( ` Error executing search_notes tool: ${ error . message || String ( error ) } ` ) ;
return ` Error: ${ error . message || String ( error ) } ` ;
}
}
}