/** DSH `tool_search` definition backed by the live tool registry. @module dsh-tool-retriever/retrieval/tool-search */ import { defineTool, type ToolRuntime } from '@deepseek-ai/dsh-tools' import type { ResolvedConfig } from '../config.ts' import { buildToolDocument } from './document.ts' import { retrieveTools } from './bm25f.ts' /** Stable model-facing name registered by this package. */ export const TOOL_SEARCH_NAME = 'tool_search' /** * Build the package's generic-rendered search tool. * @param registry - Live DSH registry read at execution time. * @param config - Resolved lexical retrieval configuration. * @returns A registry-ready, read-only tool definition. */ export function createToolSearch(registry: Pick, config: ResolvedConfig) { return defineTool({ name: TOOL_SEARCH_NAME, description: 'Search the tools currently available to this agent. Pass the capability you need in the user\'s original language and preserve specific identifiers. This alpha performs lexical retrieval only and does not translate the query.', parameters: { query: { type: 'string', required: true, description: 'The capability or operation to find, expressed in the user\'s original language.', }, }, output: { schema: { type: 'object', additionalProperties: false, properties: { query: { type: 'string', required: true }, catalogSize: { type: 'integer', required: true }, results: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: { name: { type: 'string', required: true }, description: { type: 'string', required: true }, rank: { type: 'integer', required: true }, score: { type: 'number', required: true }, exact: { type: 'boolean', required: true }, bm25: { type: 'number', required: true }, matchedFields: { type: 'array', required: true, items: { type: 'string', enum: ['name', 'description', 'parameterName', 'parameterDescription'], }, }, }, }, }, }, }, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }], }, isConcurrencySafe: () => true, async execute({ query }, exec) { exec.signal.throwIfAborted() const trimmedQuery = query.trim() if (!trimmedQuery) throw new Error('tool_search query must not be empty') const schemas = registry.schemas(exec.agent) .filter(schema => schema.name !== TOOL_SEARCH_NAME) const documents = schemas.map(buildToolDocument) const results = retrieveTools(trimmedQuery, documents, config) exec.signal.throwIfAborted() return { query: trimmedQuery, catalogSize: documents.length, results } }, }) }