mcp-resend 1.0.0-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +257 -0
  3. package/data/embeddings.json +245241 -0
  4. package/dist/config/environment.d.ts +152 -0
  5. package/dist/config/environment.d.ts.map +1 -0
  6. package/dist/config/environment.js +217 -0
  7. package/dist/config/environment.js.map +1 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +119 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/services/rate-limiter.d.ts +90 -0
  13. package/dist/services/rate-limiter.d.ts.map +1 -0
  14. package/dist/services/rate-limiter.js +267 -0
  15. package/dist/services/rate-limiter.js.map +1 -0
  16. package/dist/services/tool-registry.d.ts +219 -0
  17. package/dist/services/tool-registry.d.ts.map +1 -0
  18. package/dist/services/tool-registry.js +459 -0
  19. package/dist/services/tool-registry.js.map +1 -0
  20. package/dist/tools/docs/embeddings-loader.d.ts +69 -0
  21. package/dist/tools/docs/embeddings-loader.d.ts.map +1 -0
  22. package/dist/tools/docs/embeddings-loader.js +218 -0
  23. package/dist/tools/docs/embeddings-loader.js.map +1 -0
  24. package/dist/tools/docs/errors.d.ts +75 -0
  25. package/dist/tools/docs/errors.d.ts.map +1 -0
  26. package/dist/tools/docs/errors.js +145 -0
  27. package/dist/tools/docs/errors.js.map +1 -0
  28. package/dist/tools/docs/index.d.ts +11 -0
  29. package/dist/tools/docs/index.d.ts.map +1 -0
  30. package/dist/tools/docs/index.js +14 -0
  31. package/dist/tools/docs/index.js.map +1 -0
  32. package/dist/tools/docs/metrics.d.ts +94 -0
  33. package/dist/tools/docs/metrics.d.ts.map +1 -0
  34. package/dist/tools/docs/metrics.js +174 -0
  35. package/dist/tools/docs/metrics.js.map +1 -0
  36. package/dist/tools/docs/search-docs-tool.d.ts +54 -0
  37. package/dist/tools/docs/search-docs-tool.d.ts.map +1 -0
  38. package/dist/tools/docs/search-docs-tool.js +231 -0
  39. package/dist/tools/docs/search-docs-tool.js.map +1 -0
  40. package/dist/tools/docs/types.d.ts +70 -0
  41. package/dist/tools/docs/types.d.ts.map +1 -0
  42. package/dist/tools/docs/types.js +7 -0
  43. package/dist/tools/docs/types.js.map +1 -0
  44. package/dist/tools/docs/vector-search.d.ts +80 -0
  45. package/dist/tools/docs/vector-search.d.ts.map +1 -0
  46. package/dist/tools/docs/vector-search.js +297 -0
  47. package/dist/tools/docs/vector-search.js.map +1 -0
  48. package/dist/tools/index.d.ts +27 -0
  49. package/dist/tools/index.d.ts.map +1 -0
  50. package/dist/tools/index.js +3413 -0
  51. package/dist/tools/index.js.map +1 -0
  52. package/dist/utils/mcp-errors.d.ts +109 -0
  53. package/dist/utils/mcp-errors.d.ts.map +1 -0
  54. package/dist/utils/mcp-errors.js +306 -0
  55. package/dist/utils/mcp-errors.js.map +1 -0
  56. package/package.json +77 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Metrics tracking for documentation search.
3
+ * Collects search performance metrics and outputs them as JSON lines to stderr.
4
+ */
5
+ /** Rolling window of recent searches (max 100) */
6
+ const searchHistory = [];
7
+ /** Maximum entries in rolling window */
8
+ const MAX_HISTORY_SIZE = 100;
9
+ /** Flag to track if embeddings were loaded from cache */
10
+ let embeddingsCacheHit = false;
11
+ /**
12
+ * Output a metric as a JSON line to stderr.
13
+ *
14
+ * @param metric - The metric to output
15
+ */
16
+ function emitMetric(metric) {
17
+ console.error(JSON.stringify(metric));
18
+ }
19
+ /**
20
+ * Record a successful search and emit metric.
21
+ *
22
+ * @param latencyMs - Search latency in milliseconds
23
+ * @param resultCount - Number of results returned
24
+ * @param searchType - Type of search performed
25
+ * @param cacheHit - Whether embeddings were cached
26
+ */
27
+ export function recordSearch(latencyMs, resultCount, searchType, cacheHit) {
28
+ const entry = {
29
+ timestamp: Date.now(),
30
+ latencyMs,
31
+ resultCount,
32
+ searchType,
33
+ cacheHit,
34
+ success: true,
35
+ };
36
+ // Add to rolling window
37
+ searchHistory.push(entry);
38
+ if (searchHistory.length > MAX_HISTORY_SIZE) {
39
+ searchHistory.shift();
40
+ }
41
+ // Emit metric
42
+ emitMetric({
43
+ _type: "metric",
44
+ name: "search_completed",
45
+ timestamp: new Date().toISOString(),
46
+ search_latency_ms: latencyMs,
47
+ result_count: resultCount,
48
+ search_type: searchType,
49
+ cache_hit: cacheHit,
50
+ });
51
+ }
52
+ /**
53
+ * Record a search error and emit metric.
54
+ *
55
+ * @param latencyMs - Time until error in milliseconds
56
+ * @param errorCode - Error code from DocsErrorCode
57
+ * @param context - Additional error context
58
+ */
59
+ export function recordSearchError(latencyMs, errorCode, context) {
60
+ const entry = {
61
+ timestamp: Date.now(),
62
+ latencyMs,
63
+ resultCount: 0,
64
+ searchType: "semantic",
65
+ cacheHit: embeddingsCacheHit,
66
+ success: false,
67
+ };
68
+ // Add to rolling window
69
+ searchHistory.push(entry);
70
+ if (searchHistory.length > MAX_HISTORY_SIZE) {
71
+ searchHistory.shift();
72
+ }
73
+ // Emit metric
74
+ emitMetric({
75
+ _type: "metric",
76
+ name: "search_error",
77
+ timestamp: new Date().toISOString(),
78
+ search_latency_ms: latencyMs,
79
+ error_code: errorCode,
80
+ context,
81
+ });
82
+ }
83
+ /**
84
+ * Record model loaded event.
85
+ *
86
+ * @param latencyMs - Model load time in milliseconds
87
+ */
88
+ export function recordModelLoaded(latencyMs) {
89
+ emitMetric({
90
+ _type: "metric",
91
+ name: "model_loaded",
92
+ timestamp: new Date().toISOString(),
93
+ search_latency_ms: latencyMs,
94
+ });
95
+ }
96
+ /**
97
+ * Record embeddings loaded event.
98
+ *
99
+ * @param latencyMs - Embeddings load time in milliseconds
100
+ * @param cacheHit - Whether loaded from cache
101
+ * @param chunkCount - Number of chunks loaded
102
+ */
103
+ export function recordEmbeddingsLoaded(latencyMs, cacheHit, chunkCount) {
104
+ embeddingsCacheHit = cacheHit;
105
+ emitMetric({
106
+ _type: "metric",
107
+ name: "embeddings_loaded",
108
+ timestamp: new Date().toISOString(),
109
+ search_latency_ms: latencyMs,
110
+ cache_hit: cacheHit,
111
+ context: { chunk_count: chunkCount },
112
+ });
113
+ }
114
+ /**
115
+ * Check if embeddings are cached (for cache_hit metric).
116
+ *
117
+ * @param isCached - Whether embeddings are currently cached
118
+ */
119
+ export function setEmbeddingsCacheStatus(isCached) {
120
+ embeddingsCacheHit = isCached;
121
+ }
122
+ /**
123
+ * Get aggregated statistics from the rolling window.
124
+ *
125
+ * @returns Statistics object with averages and counts
126
+ */
127
+ export function getSearchStats() {
128
+ if (searchHistory.length === 0) {
129
+ return {
130
+ totalSearches: 0,
131
+ successfulSearches: 0,
132
+ failedSearches: 0,
133
+ averageLatencyMs: 0,
134
+ averageResultCount: 0,
135
+ searchTypeDistribution: {},
136
+ cacheHitRate: 0,
137
+ };
138
+ }
139
+ const successful = searchHistory.filter((e) => e.success);
140
+ const failed = searchHistory.filter((e) => !e.success);
141
+ const cacheHits = searchHistory.filter((e) => e.cacheHit);
142
+ const totalLatency = searchHistory.reduce((sum, e) => sum + e.latencyMs, 0);
143
+ const totalResults = successful.reduce((sum, e) => sum + e.resultCount, 0);
144
+ const typeDistribution = {};
145
+ for (const entry of searchHistory) {
146
+ typeDistribution[entry.searchType] = (typeDistribution[entry.searchType] || 0) + 1;
147
+ }
148
+ return {
149
+ totalSearches: searchHistory.length,
150
+ successfulSearches: successful.length,
151
+ failedSearches: failed.length,
152
+ averageLatencyMs: Math.round(totalLatency / searchHistory.length),
153
+ averageResultCount: successful.length > 0 ? Math.round((totalResults / successful.length) * 10) / 10 : 0,
154
+ searchTypeDistribution: typeDistribution,
155
+ cacheHitRate: Math.round((cacheHits.length / searchHistory.length) * 100) / 100,
156
+ };
157
+ }
158
+ /**
159
+ * Clear metrics history.
160
+ * Primarily for testing purposes.
161
+ */
162
+ export function clearMetricsHistory() {
163
+ searchHistory.length = 0;
164
+ embeddingsCacheHit = false;
165
+ }
166
+ /**
167
+ * Get the current rolling window size.
168
+ *
169
+ * @returns Number of entries in the rolling window
170
+ */
171
+ export function getHistorySize() {
172
+ return searchHistory.length;
173
+ }
174
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/tools/docs/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * MCP Tool implementation for searching Resend documentation.
3
+ * Provides semantic search with keyword fallback for documentation queries.
4
+ */
5
+ /**
6
+ * Get the MCP tool definition for search_resend_documentation.
7
+ * Includes annotations for tool behavior hints.
8
+ *
9
+ * @returns Tool definition object
10
+ */
11
+ export declare function getDefinition(): {
12
+ name: string;
13
+ description: string;
14
+ inputSchema: {
15
+ type: "object";
16
+ properties: {
17
+ query: {
18
+ type: string;
19
+ description: string;
20
+ minLength: number;
21
+ maxLength: number;
22
+ };
23
+ limit: {
24
+ type: string;
25
+ description: string;
26
+ minimum: number;
27
+ maximum: number;
28
+ default: number;
29
+ };
30
+ };
31
+ required: string[];
32
+ };
33
+ annotations: {
34
+ title: string;
35
+ readOnlyHint: boolean;
36
+ destructiveHint: boolean;
37
+ idempotentHint: boolean;
38
+ openWorldHint: boolean;
39
+ };
40
+ };
41
+ /**
42
+ * Execute a documentation search.
43
+ *
44
+ * @param args - Raw arguments from MCP call
45
+ * @returns MCP tool response with search results or error
46
+ */
47
+ export declare function execute(args: unknown): Promise<{
48
+ content: Array<{
49
+ type: "text";
50
+ text: string;
51
+ }>;
52
+ isError?: boolean;
53
+ }>;
54
+ //# sourceMappingURL=search-docs-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-docs-tool.d.ts","sourceRoot":"","sources":["../../../src/tools/docs/search-docs-tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkDH;;;;;GAKG;AACH,wBAAgB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoC5B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACpD,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC,CA0ID"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * MCP Tool implementation for searching Resend documentation.
3
+ * Provides semantic search with keyword fallback for documentation queries.
4
+ */
5
+ import { z } from "zod";
6
+ import { semanticSearch, keywordSearch, truncateToTokenBudget } from "./vector-search.js";
7
+ import { isEmbeddingsLoaded, getFreshnessWarning } from "./embeddings-loader.js";
8
+ import { toDocsError, formatErrorResponse } from "./errors.js";
9
+ import { recordSearch, recordSearchError, setEmbeddingsCacheStatus } from "./metrics.js";
10
+ // NOTE: Use console.error for logging - stdout is reserved for MCP protocol
11
+ const log = (message) => console.error(`[docs-search] ${message}`);
12
+ /** Minimum relevance threshold for semantic search results */
13
+ const SEMANTIC_RELEVANCE_THRESHOLD = 0.3;
14
+ /** Maximum total tokens across all results */
15
+ const MAX_TOTAL_TOKENS = 2800;
16
+ /** Default number of results to return */
17
+ const DEFAULT_LIMIT = 3;
18
+ /** Minimum query length */
19
+ const MIN_QUERY_LENGTH = 3;
20
+ /** Maximum query length */
21
+ const MAX_QUERY_LENGTH = 500;
22
+ /** Maximum results allowed */
23
+ const MAX_LIMIT = 10;
24
+ /**
25
+ * Zod schema for input validation.
26
+ */
27
+ const inputSchema = z.object({
28
+ query: z
29
+ .string()
30
+ .min(MIN_QUERY_LENGTH, `Query must be at least ${MIN_QUERY_LENGTH} characters`)
31
+ .max(MAX_QUERY_LENGTH, `Query must be at most ${MAX_QUERY_LENGTH} characters`)
32
+ .describe("Search query or question about Resend API usage"),
33
+ limit: z
34
+ .number()
35
+ .int()
36
+ .min(1, "Limit must be at least 1")
37
+ .max(MAX_LIMIT, `Limit must be at most ${MAX_LIMIT}`)
38
+ .default(DEFAULT_LIMIT)
39
+ .describe("Maximum number of results to return (1-10, default: 3)"),
40
+ });
41
+ /**
42
+ * Get the MCP tool definition for search_resend_documentation.
43
+ * Includes annotations for tool behavior hints.
44
+ *
45
+ * @returns Tool definition object
46
+ */
47
+ export function getDefinition() {
48
+ return {
49
+ name: "search_resend_documentation",
50
+ description: "Search Resend API documentation using semantic search. Returns relevant documentation " +
51
+ "excerpts for API usage, code examples, error handling, and best practices. Use this " +
52
+ "when you need information about sending emails, managing domains, contacts, audiences, " +
53
+ "templates, or any other Resend API features.",
54
+ inputSchema: {
55
+ type: "object",
56
+ properties: {
57
+ query: {
58
+ type: "string",
59
+ description: "Search query or question about Resend API usage",
60
+ minLength: MIN_QUERY_LENGTH,
61
+ maxLength: MAX_QUERY_LENGTH,
62
+ },
63
+ limit: {
64
+ type: "integer",
65
+ description: "Maximum number of results to return (1-10, default: 3)",
66
+ minimum: 1,
67
+ maximum: MAX_LIMIT,
68
+ default: DEFAULT_LIMIT,
69
+ },
70
+ },
71
+ required: ["query"],
72
+ },
73
+ annotations: {
74
+ // Tool behavior hints for MCP clients
75
+ title: "Search Resend Documentation",
76
+ readOnlyHint: true,
77
+ destructiveHint: false,
78
+ idempotentHint: true,
79
+ openWorldHint: false,
80
+ },
81
+ };
82
+ }
83
+ /**
84
+ * Execute a documentation search.
85
+ *
86
+ * @param args - Raw arguments from MCP call
87
+ * @returns MCP tool response with search results or error
88
+ */
89
+ export async function execute(args) {
90
+ const startTime = Date.now();
91
+ // Validate input
92
+ const parseResult = inputSchema.safeParse(args);
93
+ if (!parseResult.success) {
94
+ const errorMessage = parseResult.error.errors
95
+ .map((e) => `${e.path.join(".")}: ${e.message}`)
96
+ .join("; ");
97
+ const latencyMs = Date.now() - startTime;
98
+ recordSearchError(latencyMs, "VALIDATION_ERROR", { errors: parseResult.error.errors });
99
+ return {
100
+ content: [
101
+ {
102
+ type: "text",
103
+ text: JSON.stringify({
104
+ error: true,
105
+ code: "VALIDATION_ERROR",
106
+ message: `Invalid input: ${errorMessage}`,
107
+ hint: "Provide a 'query' string (3-500 chars) and optional 'limit' (1-10)",
108
+ recoverable: false,
109
+ }, null, 2),
110
+ },
111
+ ],
112
+ isError: true,
113
+ };
114
+ }
115
+ const input = parseResult.data;
116
+ log(`Searching documentation: "${input.query}" (limit: ${input.limit})`);
117
+ // Track cache status for metrics
118
+ const wasCached = isEmbeddingsLoaded();
119
+ setEmbeddingsCacheStatus(wasCached);
120
+ try {
121
+ // Try semantic search first
122
+ let results = await semanticSearch(input.query, input.limit);
123
+ let searchType = "semantic";
124
+ // Check if best semantic result meets quality threshold
125
+ // Fall back to keyword search if no results OR best result is below threshold
126
+ const bestScore = results[0]?.score ?? 0;
127
+ if (results.length === 0 || bestScore < SEMANTIC_RELEVANCE_THRESHOLD) {
128
+ // Fall back to keyword search
129
+ log(`Semantic search returned low relevance results (best: ${bestScore.toFixed(3)}), falling back to keyword search`);
130
+ const keywordResults = await keywordSearch(input.query, input.limit);
131
+ if (keywordResults.length > 0) {
132
+ // Use keyword results, mark as keyword search type
133
+ results = keywordResults;
134
+ searchType = "keyword";
135
+ }
136
+ else if (results.length === 0) {
137
+ // No results from either search
138
+ const latencyMs = Date.now() - startTime;
139
+ recordSearch(latencyMs, 0, "keyword", wasCached);
140
+ const noResultsResponse = {
141
+ query: input.query,
142
+ searchType: "keyword",
143
+ resultCount: 0,
144
+ totalTokens: 0,
145
+ results: [],
146
+ };
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: JSON.stringify(noResultsResponse, null, 2),
152
+ },
153
+ ],
154
+ };
155
+ }
156
+ // If keyword search returned nothing but we have some semantic results,
157
+ // keep the semantic results even if below threshold
158
+ }
159
+ // Apply token budget
160
+ const searchResults = applyTokenBudget(results, MAX_TOTAL_TOKENS);
161
+ // Calculate total tokens
162
+ const totalTokens = searchResults.reduce((sum, r) => sum + r.tokenCount, 0);
163
+ // Record successful search metrics
164
+ const latencyMs = Date.now() - startTime;
165
+ recordSearch(latencyMs, searchResults.length, searchType, wasCached);
166
+ // Check for freshness warning
167
+ const freshnessWarning = getFreshnessWarning();
168
+ // Build response
169
+ const response = {
170
+ query: input.query,
171
+ searchType,
172
+ resultCount: searchResults.length,
173
+ totalTokens,
174
+ results: searchResults,
175
+ };
176
+ // Add freshness warning if present
177
+ if (freshnessWarning) {
178
+ response.warning = freshnessWarning;
179
+ }
180
+ log(`Search complete: ${searchResults.length} results, ${totalTokens} tokens, type: ${searchType}, latency: ${latencyMs}ms`);
181
+ return {
182
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
183
+ };
184
+ }
185
+ catch (error) {
186
+ const latencyMs = Date.now() - startTime;
187
+ // Convert to structured DocsError
188
+ const docsError = toDocsError(error);
189
+ log(`Search error [${docsError.code}]: ${docsError.message}`);
190
+ // Record error metrics
191
+ recordSearchError(latencyMs, docsError.code, { message: docsError.message });
192
+ return {
193
+ content: [{ type: "text", text: JSON.stringify(formatErrorResponse(docsError), null, 2) }],
194
+ isError: true,
195
+ };
196
+ }
197
+ }
198
+ /**
199
+ * Apply token budget to search results.
200
+ * Truncates results to fit within the total token limit.
201
+ *
202
+ * @param results - Scored chunks from search
203
+ * @param maxTotalTokens - Maximum total tokens allowed
204
+ * @returns Array of SearchResult objects within budget
205
+ */
206
+ function applyTokenBudget(results, maxTotalTokens) {
207
+ const searchResults = [];
208
+ let remainingTokens = maxTotalTokens;
209
+ for (const result of results) {
210
+ if (remainingTokens <= 0) {
211
+ break;
212
+ }
213
+ let excerpt = result.content;
214
+ let tokenCount = result.tokenCount;
215
+ // Truncate if needed to fit remaining budget
216
+ if (tokenCount > remainingTokens) {
217
+ excerpt = truncateToTokenBudget(excerpt, remainingTokens);
218
+ tokenCount = remainingTokens;
219
+ }
220
+ searchResults.push({
221
+ section: result.section,
222
+ excerpt,
223
+ relevance: Math.round(result.score * 1000) / 1000, // Round to 3 decimal places
224
+ tokenCount,
225
+ sourceUrl: result.sourceUrl,
226
+ });
227
+ remainingTokens -= tokenCount;
228
+ }
229
+ return searchResults;
230
+ }
231
+ //# sourceMappingURL=search-docs-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-docs-tool.js","sourceRoot":"","sources":["../../../src/tools/docs/search-docs-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Runtime types for the documentation search tool.
3
+ * These types are used during search execution, distinct from the build-time types
4
+ * in scripts/types.ts used for embedding generation.
5
+ */
6
+ /**
7
+ * A search result returned to the user.
8
+ * Contains the relevant excerpt and metadata about the match.
9
+ */
10
+ export interface SearchResult {
11
+ /** Section header or title of the matched documentation */
12
+ section: string;
13
+ /** Relevant excerpt from the documentation (may be truncated) */
14
+ excerpt: string;
15
+ /** Relevance score (0-1 for semantic, simple match for keyword) */
16
+ relevance: number;
17
+ /** Estimated token count of the excerpt */
18
+ tokenCount: number;
19
+ /** Optional source URL for the documentation */
20
+ sourceUrl?: string;
21
+ }
22
+ /**
23
+ * Internal representation of a chunk with its similarity score.
24
+ * Used during search ranking before transforming to SearchResult.
25
+ */
26
+ export interface ScoredChunk {
27
+ /** Unique identifier for the chunk */
28
+ id: string;
29
+ /** Section header or title */
30
+ section: string;
31
+ /** Full content of the chunk */
32
+ content: string;
33
+ /** Token count of the chunk */
34
+ tokenCount: number;
35
+ /** Similarity score (cosine similarity for semantic search) */
36
+ score: number;
37
+ /** Optional source URL */
38
+ sourceUrl?: string;
39
+ }
40
+ /**
41
+ * Successful search response structure.
42
+ */
43
+ export interface SearchResponse {
44
+ /** The search query that was executed */
45
+ query: string;
46
+ /** Type of search performed */
47
+ searchType: "semantic" | "keyword" | "hybrid";
48
+ /** Number of results returned */
49
+ resultCount: number;
50
+ /** Total tokens across all results */
51
+ totalTokens: number;
52
+ /** The search results */
53
+ results: SearchResult[];
54
+ }
55
+ /**
56
+ * Error response structure for search failures.
57
+ */
58
+ export interface SearchErrorResponse {
59
+ /** Error indicator */
60
+ error: true;
61
+ /** Error message */
62
+ message: string;
63
+ /** Optional hint for resolving the error */
64
+ hint?: string;
65
+ }
66
+ /**
67
+ * Union type for search responses.
68
+ */
69
+ export type SearchResponseType = SearchResponse | SearchErrorResponse;
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/docs/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9C,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,KAAK,EAAE,IAAI,CAAC;IACZ,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Runtime types for the documentation search tool.
3
+ * These types are used during search execution, distinct from the build-time types
4
+ * in scripts/types.ts used for embedding generation.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/tools/docs/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Core vector search functionality for documentation.
3
+ * Provides semantic search using embeddings and keyword search as fallback.
4
+ */
5
+ import type { ScoredChunk } from "./types.js";
6
+ /**
7
+ * Type definition for the transformer pipeline.
8
+ * We use dynamic import to load @xenova/transformers.
9
+ */
10
+ type Pipeline = (texts: string[], options?: {
11
+ pooling: string;
12
+ normalize: boolean;
13
+ }) => Promise<{
14
+ data: Float32Array;
15
+ }>;
16
+ /**
17
+ * Load the embedding model (Xenova/all-MiniLM-L6-v2).
18
+ * Lazy loads on first call and caches for subsequent use.
19
+ * Includes timeout and retry logic for robustness.
20
+ *
21
+ * @returns Promise resolving to the embedding pipeline function
22
+ */
23
+ export declare function loadEmbedder(): Promise<Pipeline>;
24
+ /**
25
+ * Generate embedding vector for a query string.
26
+ *
27
+ * @param query - The text to embed
28
+ * @returns Promise resolving to 384-dimensional embedding vector
29
+ */
30
+ export declare function embedQuery(query: string): Promise<number[]>;
31
+ /**
32
+ * Compute cosine similarity between two vectors.
33
+ * Assumes vectors are already normalized (which they are from the model).
34
+ *
35
+ * @param a - First vector
36
+ * @param b - Second vector
37
+ * @returns Cosine similarity score between -1 and 1
38
+ */
39
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
40
+ /**
41
+ * Perform semantic search using vector embeddings.
42
+ *
43
+ * @param query - The search query
44
+ * @param limit - Maximum number of results to return
45
+ * @param maxTokensPerResult - Optional max tokens per result for truncation
46
+ * @returns Promise resolving to array of scored chunks
47
+ */
48
+ export declare function semanticSearch(query: string, limit: number, maxTokensPerResult?: number): Promise<ScoredChunk[]>;
49
+ /**
50
+ * Perform keyword-based search as fallback.
51
+ * Uses simple case-insensitive substring matching with basic relevance scoring.
52
+ *
53
+ * @param query - The search query
54
+ * @param limit - Maximum number of results to return
55
+ * @returns Promise resolving to array of scored chunks
56
+ */
57
+ export declare function keywordSearch(query: string, limit: number): Promise<ScoredChunk[]>;
58
+ /**
59
+ * Truncate content to fit within a token budget.
60
+ * Uses approximate token estimation (4 chars per token).
61
+ *
62
+ * @param content - The content to truncate
63
+ * @param maxTokens - Maximum tokens allowed
64
+ * @returns Truncated content with ellipsis if needed
65
+ */
66
+ export declare function truncateToTokenBudget(content: string, maxTokens: number): string;
67
+ /**
68
+ * Get statistics about the loaded embeddings.
69
+ * Useful for debugging and status reporting.
70
+ *
71
+ * @returns Object with embeddings statistics, or null if not loaded
72
+ */
73
+ export declare function getEmbeddingsStats(): Promise<{
74
+ chunkCount: number;
75
+ dimensions: number;
76
+ model: string;
77
+ generatedAt: string;
78
+ } | null>;
79
+ export {};
80
+ //# sourceMappingURL=vector-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../../src/tools/docs/vector-search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgB9C;;;GAGG;AACH,KAAK,QAAQ,GAAG,CACd,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,KAC9C,OAAO,CAAC;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAuDrC;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAkEtD;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUjE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAejE;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CAqCxB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,EAAE,CAAC,CAgExB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAyBhF;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,IAAI,CAAC,CAYR"}