import { Type } from "typebox"; import { formatSearchResults, formatAuthError, formatBillingError, formatUnavailableError, formatGenericError, formatApiKeyMissingError, formatRateLimitError } from "../format"; export function makeSearchTool(store) { return { name: "alchemyst_context_search", label: "Alchemyst Context Search", description: "Search AlchemystAI's Context Layer for previously captured decisions, docs, or reference material relevant to a query. Use before answering questions about prior team decisions, specs, or conventions that might already be documented.", parameters: Type.Object({ query: Type.String({ description: "Natural language search query" }), scope: Type.Optional( Type.Union([ Type.Literal("internal"), Type.Literal("external"), ]) ), similarity_threshold: Type.Optional(Type.Number({ description: "Maximum similarity threshold (0-1)" })), minimum_similarity_threshold: Type.Optional( Type.Number({ description: "Minimum similarity threshold (0-1)" }) ), mode: Type.Optional( Type.Union([Type.Literal("fast"), Type.Literal("standard")]) ), limit: Type.Optional(Type.Number({ description: "Maximum number of results to return" })), }), async execute(_toolCallId, params) { if (!store.client) { return { content: [{ type: "text" as const, text: formatApiKeyMissingError() }], details: {}, }; } const result = await store.client.search( { query: params.query, similarity_threshold: params.similarity_threshold ?? 0.8, minimum_similarity_threshold: params.minimum_similarity_threshold ?? 0.5, scope: params.scope ?? "internal", }, params.mode ?? "standard", ); if (!result.ok) { if (result.status === 401 || result.status === 403) return { content: [{ type: "text" as const, text: formatAuthError() }], details: {}, }; if (result.status === 402) return { content: [{ type: "text" as const, text: formatBillingError() }], details: {}, }; if (result.status === 429) return { content: [{ type: "text" as const, text: formatRateLimitError() }], details: {}, }; if (result.status && result.status >= 500) return { content: [{ type: "text" as const, text: formatUnavailableError() }], details: {}, }; return { content: [{ type: "text" as const, text: formatGenericError(result.error) }], details: {}, }; } return { content: [ { type: "text" as const, text: formatSearchResults(result.data.contexts, params.limit ?? 8), }, ], details: { count: result.data.contexts.length }, }; }, }; }