bluera-knowledge 0.9.37 → 0.9.39

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.
@@ -9,6 +9,7 @@ import type {
9
9
  SearchQuery,
10
10
  SearchResponse,
11
11
  SearchResult,
12
+ SearchConfidence,
12
13
  DetailLevel,
13
14
  CodeUnit,
14
15
  } from '../types/search.js';
@@ -246,6 +247,19 @@ export class SearchService {
246
247
  return result;
247
248
  }
248
249
 
250
+ /**
251
+ * Calculate confidence level based on max raw vector similarity score.
252
+ * Configurable via environment variables.
253
+ */
254
+ private calculateConfidence(maxRawScore: number): SearchConfidence {
255
+ const highThreshold = parseFloat(process.env['SEARCH_CONFIDENCE_HIGH'] ?? '0.5');
256
+ const mediumThreshold = parseFloat(process.env['SEARCH_CONFIDENCE_MEDIUM'] ?? '0.3');
257
+
258
+ if (maxRawScore >= highThreshold) return 'high';
259
+ if (maxRawScore >= mediumThreshold) return 'medium';
260
+ return 'low';
261
+ }
262
+
249
263
  async search(query: SearchQuery): Promise<SearchResponse> {
250
264
  const startTime = Date.now();
251
265
  const mode = query.mode ?? 'hybrid';
@@ -264,22 +278,61 @@ export class SearchService {
264
278
  detail,
265
279
  intent: primaryIntent,
266
280
  intents,
281
+ minRelevance: query.minRelevance,
267
282
  },
268
283
  'Search query received'
269
284
  );
270
285
 
271
286
  let allResults: SearchResult[] = [];
287
+ let maxRawScore = 0;
272
288
 
273
289
  // Fetch more results than needed to allow for deduplication
274
290
  const fetchLimit = limit * 3;
275
291
 
276
292
  if (mode === 'vector') {
293
+ // For vector mode, get raw scores first for confidence calculation
294
+ const rawResults = await this.vectorSearchRaw(query.query, stores, fetchLimit);
295
+ maxRawScore = rawResults.length > 0 ? (rawResults[0]?.score ?? 0) : 0;
277
296
  allResults = await this.vectorSearch(query.query, stores, fetchLimit, query.threshold);
278
297
  } else if (mode === 'fts') {
298
+ // FTS mode doesn't have vector similarity, so no confidence calculation
279
299
  allResults = await this.ftsSearch(query.query, stores, fetchLimit);
280
300
  } else {
281
- // Hybrid: combine vector and FTS with RRF
282
- allResults = await this.hybridSearch(query.query, stores, fetchLimit, query.threshold);
301
+ // Hybrid: combine vector and FTS with RRF, get maxRawScore for confidence
302
+ const hybridResult = await this.hybridSearchWithMetadata(
303
+ query.query,
304
+ stores,
305
+ fetchLimit,
306
+ query.threshold
307
+ );
308
+ allResults = hybridResult.results;
309
+ maxRawScore = hybridResult.maxRawScore;
310
+ }
311
+
312
+ // Apply minRelevance filter - if max raw score is below threshold, return empty
313
+ if (query.minRelevance !== undefined && maxRawScore < query.minRelevance) {
314
+ const timeMs = Date.now() - startTime;
315
+ logger.info(
316
+ {
317
+ query: query.query,
318
+ mode,
319
+ maxRawScore,
320
+ minRelevance: query.minRelevance,
321
+ timeMs,
322
+ },
323
+ 'Search filtered by minRelevance - no sufficiently relevant results'
324
+ );
325
+
326
+ return {
327
+ query: query.query,
328
+ mode,
329
+ stores,
330
+ results: [],
331
+ totalResults: 0,
332
+ timeMs,
333
+ confidence: this.calculateConfidence(maxRawScore),
334
+ maxRawScore,
335
+ };
283
336
  }
284
337
 
285
338
  // Deduplicate by source file - keep best chunk per source (considers query relevance)
@@ -302,6 +355,7 @@ export class SearchService {
302
355
  });
303
356
 
304
357
  const timeMs = Date.now() - startTime;
358
+ const confidence = mode !== 'fts' ? this.calculateConfidence(maxRawScore) : undefined;
305
359
 
306
360
  logger.info(
307
361
  {
@@ -310,6 +364,8 @@ export class SearchService {
310
364
  resultCount: enhancedResults.length,
311
365
  dedupedFrom: allResults.length,
312
366
  intents: intents.map((i) => `${i.intent}(${i.confidence.toFixed(2)})`),
367
+ maxRawScore: mode !== 'fts' ? maxRawScore : undefined,
368
+ confidence,
313
369
  timeMs,
314
370
  },
315
371
  'Search complete'
@@ -322,6 +378,8 @@ export class SearchService {
322
378
  results: enhancedResults,
323
379
  totalResults: enhancedResults.length,
324
380
  timeMs,
381
+ confidence,
382
+ maxRawScore: mode !== 'fts' ? maxRawScore : undefined,
325
383
  };
326
384
  }
327
385
 
@@ -412,27 +470,41 @@ export class SearchService {
412
470
  return normalized;
413
471
  }
414
472
 
415
- private async vectorSearch(
473
+ /**
474
+ * Fetch raw vector search results without normalization.
475
+ * Returns results with raw cosine similarity scores [0-1].
476
+ */
477
+ private async vectorSearchRaw(
416
478
  query: string,
417
479
  stores: readonly StoreId[],
418
- limit: number,
419
- threshold?: number
480
+ limit: number
420
481
  ): Promise<SearchResult[]> {
421
482
  const queryVector = await this.embeddingEngine.embed(query);
422
483
  const results: SearchResult[] = [];
423
484
 
424
485
  for (const storeId of stores) {
425
- const hits = await this.lanceStore.search(storeId, queryVector, limit, threshold);
486
+ const hits = await this.lanceStore.search(storeId, queryVector, limit);
426
487
  results.push(
427
488
  ...hits.map((r) => ({
428
489
  id: r.id,
429
- score: r.score,
490
+ score: r.score, // Raw cosine similarity (1 - distance)
430
491
  content: r.content,
431
492
  metadata: r.metadata,
432
493
  }))
433
494
  );
434
495
  }
435
496
 
497
+ return results.sort((a, b) => b.score - a.score).slice(0, limit);
498
+ }
499
+
500
+ private async vectorSearch(
501
+ query: string,
502
+ stores: readonly StoreId[],
503
+ limit: number,
504
+ threshold?: number
505
+ ): Promise<SearchResult[]> {
506
+ const results = await this.vectorSearchRaw(query, stores, limit);
507
+
436
508
  // Normalize scores and apply threshold filter
437
509
  const normalized = this.normalizeAndFilterScores(results, threshold);
438
510
  return normalized.slice(0, limit);
@@ -460,20 +532,37 @@ export class SearchService {
460
532
  return results.sort((a, b) => b.score - a.score).slice(0, limit);
461
533
  }
462
534
 
463
- private async hybridSearch(
535
+ /**
536
+ * Internal hybrid search result with additional metadata for confidence calculation.
537
+ */
538
+ private async hybridSearchWithMetadata(
464
539
  query: string,
465
540
  stores: readonly StoreId[],
466
541
  limit: number,
467
542
  threshold?: number
468
- ): Promise<SearchResult[]> {
543
+ ): Promise<{ results: SearchResult[]; maxRawScore: number }> {
469
544
  // Classify query intents for context-aware ranking (supports multiple intents)
470
545
  const intents = classifyQueryIntents(query);
471
546
 
472
- // Get both result sets (don't pass threshold - apply after RRF normalization)
473
- const [vectorResults, ftsResults] = await Promise.all([
474
- this.vectorSearch(query, stores, limit * 2),
475
- this.ftsSearch(query, stores, limit * 2),
476
- ]);
547
+ // Get raw vector results (unnormalized) to track raw cosine similarity
548
+ // We use these for both raw score tracking and as the basis for normalized vector results
549
+ const rawVectorResults = await this.vectorSearchRaw(query, stores, limit * 2);
550
+
551
+ // Build map of raw vector scores by document ID
552
+ const rawVectorScores = new Map<string, number>();
553
+ rawVectorResults.forEach((r) => {
554
+ rawVectorScores.set(r.id, r.score);
555
+ });
556
+
557
+ // Track max raw score for confidence calculation
558
+ const maxRawScore = rawVectorResults.length > 0 ? (rawVectorResults[0]?.score ?? 0) : 0;
559
+
560
+ // Normalize raw vector results directly (avoids duplicate embedding call)
561
+ // Don't apply threshold here - it's applied to final RRF-normalized scores at the end
562
+ const vectorResults = this.normalizeAndFilterScores(rawVectorResults);
563
+
564
+ // Get FTS results in parallel (only one call needed now)
565
+ const ftsResults = await this.ftsSearch(query, stores, limit * 2);
477
566
 
478
567
  // Build rank maps
479
568
  const vectorRanks = new Map<string, number>();
@@ -497,6 +586,7 @@ export class SearchService {
497
586
  id: string;
498
587
  score: number;
499
588
  result: SearchResult;
589
+ rawVectorScore: number | undefined;
500
590
  metadata: {
501
591
  vectorRank?: number;
502
592
  ftsRank?: number;
@@ -506,6 +596,7 @@ export class SearchService {
506
596
  frameworkBoost: number;
507
597
  urlKeywordBoost: number;
508
598
  pathKeywordBoost: number;
599
+ rawVectorScore?: number;
509
600
  };
510
601
  }> = [];
511
602
 
@@ -516,6 +607,7 @@ export class SearchService {
516
607
  for (const [id, result] of allDocs) {
517
608
  const vectorRank = vectorRanks.get(id) ?? Infinity;
518
609
  const ftsRank = ftsRanks.get(id) ?? Infinity;
610
+ const rawVectorScore = rawVectorScores.get(id);
519
611
 
520
612
  const vectorRRF = vectorRank !== Infinity ? vectorWeight / (k + vectorRank) : 0;
521
613
  const ftsRRF = ftsRank !== Infinity ? ftsWeight / (k + ftsRank) : 0;
@@ -545,6 +637,7 @@ export class SearchService {
545
637
  frameworkBoost: number;
546
638
  urlKeywordBoost: number;
547
639
  pathKeywordBoost: number;
640
+ rawVectorScore?: number;
548
641
  } = {
549
642
  vectorRRF,
550
643
  ftsRRF,
@@ -560,6 +653,9 @@ export class SearchService {
560
653
  if (ftsRank !== Infinity) {
561
654
  metadata.ftsRank = ftsRank;
562
655
  }
656
+ if (rawVectorScore !== undefined) {
657
+ metadata.rawVectorScore = rawVectorScore;
658
+ }
563
659
 
564
660
  rrfScores.push({
565
661
  id,
@@ -570,6 +666,7 @@ export class SearchService {
570
666
  urlKeywordBoost *
571
667
  pathKeywordBoost,
572
668
  result,
669
+ rawVectorScore,
573
670
  metadata,
574
671
  });
575
672
  }
@@ -616,10 +713,10 @@ export class SearchService {
616
713
 
617
714
  // Apply threshold filter on normalized scores (UX consistency)
618
715
  if (threshold !== undefined) {
619
- return normalizedResults.filter((r) => r.score >= threshold);
716
+ normalizedResults = normalizedResults.filter((r) => r.score >= threshold);
620
717
  }
621
718
 
622
- return normalizedResults;
719
+ return { results: normalizedResults, maxRawScore };
623
720
  }
624
721
 
625
722
  async searchAllStores(query: SearchQuery, storeIds: StoreId[]): Promise<SearchResponse> {
@@ -655,7 +752,7 @@ export class SearchService {
655
752
  baseBoost = 0.75; // Internal implementation files (not too harsh)
656
753
  break;
657
754
  case 'test':
658
- baseBoost = 0.7; // Tests significantly lower
755
+ baseBoost = parseFloat(process.env['SEARCH_TEST_FILE_BOOST'] ?? '0.5'); // Tests strongly penalized
659
756
  break;
660
757
  case 'config':
661
758
  baseBoost = 0.5; // Config files rarely answer questions
@@ -676,8 +773,14 @@ export class SearchService {
676
773
  }
677
774
 
678
775
  const blendedMultiplier = totalConfidence > 0 ? weightedMultiplier / totalConfidence : 1.0;
776
+ const finalBoost = baseBoost * blendedMultiplier;
777
+
778
+ // Cap test file boost to prevent intent multipliers from overriding the penalty
779
+ if (fileType === 'test') {
780
+ return Math.min(finalBoost, 0.6);
781
+ }
679
782
 
680
- return baseBoost * blendedMultiplier;
783
+ return finalBoost;
681
784
  }
682
785
 
683
786
  /**
@@ -51,6 +51,7 @@ export interface SearchQuery {
51
51
  readonly mode?: SearchMode | undefined;
52
52
  readonly limit?: number | undefined;
53
53
  readonly threshold?: number | undefined;
54
+ readonly minRelevance?: number | undefined; // Minimum raw cosine similarity [0-1] to include results
54
55
  readonly filter?: Record<string, unknown> | undefined;
55
56
  readonly includeContent?: boolean | undefined;
56
57
  readonly contextLines?: number | undefined;
@@ -83,10 +84,15 @@ export interface SearchResult {
83
84
  readonly ftsRRF: number; // FTS contribution to RRF score
84
85
  readonly fileTypeBoost: number; // File type multiplier applied
85
86
  readonly frameworkBoost: number; // Framework context multiplier
87
+ readonly urlKeywordBoost: number; // URL keyword matching multiplier
88
+ readonly pathKeywordBoost: number; // File path keyword matching multiplier
89
+ readonly rawVectorScore?: number; // Raw cosine similarity [0-1] before RRF/normalization
86
90
  }
87
91
  | undefined;
88
92
  }
89
93
 
94
+ export type SearchConfidence = 'high' | 'medium' | 'low';
95
+
90
96
  export interface SearchResponse {
91
97
  readonly query: string;
92
98
  readonly mode: SearchMode;
@@ -94,4 +100,6 @@ export interface SearchResponse {
94
100
  readonly results: readonly SearchResult[];
95
101
  readonly totalResults: number;
96
102
  readonly timeMs: number;
103
+ readonly confidence?: SearchConfidence | undefined; // Based on max raw vector similarity
104
+ readonly maxRawScore?: number | undefined; // Highest raw cosine similarity found
97
105
  }
@@ -27,6 +27,7 @@ describe('BackgroundWorker', () => {
27
27
  lanceStore = {
28
28
  initialize: vi.fn().mockResolvedValue(undefined),
29
29
  addDocuments: vi.fn().mockResolvedValue(undefined),
30
+ createFtsIndex: vi.fn().mockResolvedValue(undefined),
30
31
  } as unknown as LanceStore;
31
32
  embeddingEngine = {
32
33
  embed: vi.fn().mockResolvedValue(new Array(384).fill(0)),
@@ -296,6 +296,8 @@ export class BackgroundWorker {
296
296
  });
297
297
 
298
298
  await this.lanceStore.addDocuments(store.id, docs);
299
+ // Create FTS index for full-text search
300
+ await this.lanceStore.createFtsIndex(store.id);
299
301
  }
300
302
 
301
303
  this.jobService.updateJob(job.id, {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/server.ts","../src/mcp/commands/job.commands.ts","../src/mcp/schemas/index.ts","../src/mcp/handlers/job.handler.ts","../src/mcp/commands/meta.commands.ts","../src/mcp/commands/registry.ts","../src/mcp/commands/store.commands.ts","../src/mcp/handlers/store.handler.ts","../src/workers/spawn-worker.ts","../src/mcp/commands/index.ts","../src/mcp/handlers/execute.handler.ts","../src/services/token.service.ts","../src/mcp/cache.ts","../src/mcp/handlers/search.handler.ts","../src/mcp/handlers/index.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { createServices } from '../services/index.js';\nimport { handleExecute } from './handlers/execute.handler.js';\nimport { tools } from './handlers/index.js';\nimport { ExecuteArgsSchema } from './schemas/index.js';\nimport { createLogger } from '../logging/index.js';\nimport type { MCPServerOptions } from './types.js';\n\nconst logger = createLogger('mcp-server');\n\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport function createMCPServer(options: MCPServerOptions): Server {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n const server = new Server(\n {\n name: 'bluera-knowledge',\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // List available tools - consolidated from 10 tools to 3 for reduced context overhead\n server.setRequestHandler(ListToolsRequestSchema, () => {\n return Promise.resolve({\n tools: [\n // Native search tool with full schema (most used, benefits from detailed params)\n {\n name: 'search',\n description:\n 'Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description:\n 'Search query (can include type signatures, constraints, or natural language)',\n },\n intent: {\n type: 'string',\n enum: [\n 'find-pattern',\n 'find-implementation',\n 'find-usage',\n 'find-definition',\n 'find-documentation',\n ],\n description: 'Search intent for better ranking',\n },\n detail: {\n type: 'string',\n enum: ['minimal', 'contextual', 'full'],\n default: 'minimal',\n description:\n 'Context detail level: minimal (summary only), contextual (+ imports/types), full (+ complete code)',\n },\n limit: {\n type: 'number',\n default: 10,\n description: 'Maximum number of results',\n },\n stores: {\n type: 'array',\n items: { type: 'string' },\n description: 'Specific store IDs to search (optional)',\n },\n },\n required: ['query'],\n },\n },\n // Native get_full_context tool (frequently used after search)\n {\n name: 'get_full_context',\n description:\n 'Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.',\n inputSchema: {\n type: 'object',\n properties: {\n resultId: {\n type: 'string',\n description: 'Result ID from previous search',\n },\n },\n required: ['resultId'],\n },\n },\n // Meta-tool for store and job management (consolidates 8 tools into 1)\n {\n name: 'execute',\n description:\n 'Execute store/job management commands. Commands: stores, store:info, store:create, store:index, store:delete, jobs, job:status, job:cancel, help, commands',\n inputSchema: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'Command to execute (e.g., \"stores\", \"store:create\", \"jobs\", \"help\")',\n },\n args: {\n type: 'object',\n description: 'Command arguments (e.g., {store: \"mystore\"} for store:info)',\n },\n },\n required: ['command'],\n },\n },\n ],\n });\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n const startTime = Date.now();\n\n logger.info({ tool: name, args: JSON.stringify(args) }, 'Tool invoked');\n\n // Create services once (needed by all handlers)\n const services = await createServices(options.config, options.dataDir, options.projectRoot);\n const context = { services, options };\n\n try {\n let result;\n\n // Handle execute meta-tool\n if (name === 'execute') {\n const validated = ExecuteArgsSchema.parse(args ?? {});\n result = await handleExecute(validated, context);\n } else {\n // Find handler in registry for native tools (search, get_full_context)\n const tool = tools.find((t) => t.name === name);\n if (tool === undefined) {\n throw new Error(`Unknown tool: ${name}`);\n }\n\n // Validate arguments with Zod\n const validated = tool.schema.parse(args ?? {});\n\n // Execute handler with context\n result = await tool.handler(validated, context);\n }\n\n const durationMs = Date.now() - startTime;\n logger.info({ tool: name, durationMs }, 'Tool completed');\n\n return result;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n logger.error(\n {\n tool: name,\n durationMs,\n error: error instanceof Error ? error.message : String(error),\n },\n 'Tool execution failed'\n );\n throw error;\n }\n });\n\n return server;\n}\n\nexport async function runMCPServer(options: MCPServerOptions): Promise<void> {\n logger.info(\n {\n dataDir: options.dataDir,\n projectRoot: options.projectRoot,\n },\n 'MCP server starting'\n );\n\n const server = createMCPServer(options);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n logger.info('MCP server connected to stdio transport');\n}\n\n// Run the server only when this file is executed directly (not imported by CLI)\n// Check if we're running as the mcp/server entry point vs being imported by index.js\nconst scriptPath = process.argv[1] ?? '';\nconst isMCPServerEntry = scriptPath.endsWith('mcp/server.js') || scriptPath.endsWith('mcp/server');\n\nif (isMCPServerEntry) {\n runMCPServer({\n dataDir: process.env['DATA_DIR'],\n config: process.env['CONFIG_PATH'],\n projectRoot: process.env['PROJECT_ROOT'] ?? process.env['PWD'],\n }).catch((error: unknown) => {\n logger.error(\n { error: error instanceof Error ? error.message : String(error) },\n 'Failed to start MCP server'\n );\n process.exit(1);\n });\n}\n","import { z } from 'zod';\nimport { handleCheckJobStatus, handleListJobs, handleCancelJob } from '../handlers/job.handler.js';\nimport type { CommandDefinition } from './registry.js';\nimport type { CheckJobStatusArgs, ListJobsArgs, CancelJobArgs } from '../schemas/index.js';\n\n/**\n * Job management commands for the execute meta-tool\n *\n * These commands wrap the existing job handlers, providing\n * a unified interface through the execute command.\n *\n * Note: Type assertions are necessary here because CommandHandler uses\n * Record<string, unknown> for generic command args, while handlers expect\n * specific typed args. Zod validates at runtime before the cast.\n */\n/* eslint-disable @typescript-eslint/consistent-type-assertions */\nexport const jobCommands: CommandDefinition[] = [\n {\n name: 'jobs',\n description: 'List all background jobs',\n argsSchema: z.object({\n activeOnly: z.boolean().optional().describe('Only show active jobs'),\n status: z\n .enum(['pending', 'running', 'completed', 'failed', 'cancelled'])\n .optional()\n .describe('Filter by job status'),\n }),\n handler: (args, context) => handleListJobs(args as unknown as ListJobsArgs, context),\n },\n {\n name: 'job:status',\n description: 'Check the status of a specific background job',\n argsSchema: z.object({\n jobId: z.string().min(1).describe('Job ID to check'),\n }),\n handler: (args, context) =>\n handleCheckJobStatus(args as unknown as CheckJobStatusArgs, context),\n },\n {\n name: 'job:cancel',\n description: 'Cancel a running or pending background job',\n argsSchema: z.object({\n jobId: z.string().min(1).describe('Job ID to cancel'),\n }),\n handler: (args, context) => handleCancelJob(args as unknown as CancelJobArgs, context),\n },\n];\n/* eslint-enable @typescript-eslint/consistent-type-assertions */\n","import { z } from 'zod';\n\n/**\n * Validation schemas for all MCP tool inputs\n *\n * These schemas provide runtime type validation and better error messages\n * compared to manual type assertions.\n */\n\n// ============================================================================\n// Search Tool Schemas\n// ============================================================================\n\n/**\n * Schema for search tool arguments\n */\nexport const SearchArgsSchema = z.object({\n query: z.string().min(1, 'Query must be a non-empty string'),\n intent: z\n .enum([\n 'find-pattern',\n 'find-implementation',\n 'find-usage',\n 'find-definition',\n 'find-documentation',\n ])\n .optional(),\n detail: z.enum(['minimal', 'contextual', 'full']).default('minimal'),\n limit: z.number().int().positive().default(10),\n stores: z.array(z.string()).optional(),\n});\n\nexport type SearchArgs = z.infer<typeof SearchArgsSchema>;\n\n/**\n * Schema for get_full_context tool arguments\n */\nexport const GetFullContextArgsSchema = z.object({\n resultId: z.string().min(1, 'Result ID must be a non-empty string'),\n});\n\nexport type GetFullContextArgs = z.infer<typeof GetFullContextArgsSchema>;\n\n// ============================================================================\n// Store Tool Schemas\n// ============================================================================\n\n/**\n * Schema for list_stores tool arguments\n */\nexport const ListStoresArgsSchema = z.object({\n type: z.enum(['file', 'repo', 'web']).optional(),\n});\n\nexport type ListStoresArgs = z.infer<typeof ListStoresArgsSchema>;\n\n/**\n * Schema for get_store_info tool arguments\n */\nexport const GetStoreInfoArgsSchema = z.object({\n store: z.string().min(1, 'Store name or ID must be a non-empty string'),\n});\n\nexport type GetStoreInfoArgs = z.infer<typeof GetStoreInfoArgsSchema>;\n\n/**\n * Schema for create_store tool arguments\n */\nexport const CreateStoreArgsSchema = z.object({\n name: z.string().min(1, 'Store name must be a non-empty string'),\n type: z.enum(['file', 'repo']),\n source: z.string().min(1, 'Source path or URL must be a non-empty string'),\n branch: z.string().optional(),\n description: z.string().optional(),\n});\n\nexport type CreateStoreArgs = z.infer<typeof CreateStoreArgsSchema>;\n\n/**\n * Schema for index_store tool arguments\n */\nexport const IndexStoreArgsSchema = z.object({\n store: z.string().min(1, 'Store name or ID must be a non-empty string'),\n});\n\nexport type IndexStoreArgs = z.infer<typeof IndexStoreArgsSchema>;\n\n/**\n * Schema for delete_store tool arguments\n */\nexport const DeleteStoreArgsSchema = z.object({\n store: z.string().min(1, 'Store name or ID must be a non-empty string'),\n});\n\nexport type DeleteStoreArgs = z.infer<typeof DeleteStoreArgsSchema>;\n\n// ============================================================================\n// Job Tool Schemas\n// ============================================================================\n\n/**\n * Schema for check_job_status tool arguments\n */\nexport const CheckJobStatusArgsSchema = z.object({\n jobId: z.string().min(1, 'Job ID must be a non-empty string'),\n});\n\nexport type CheckJobStatusArgs = z.infer<typeof CheckJobStatusArgsSchema>;\n\n/**\n * Schema for list_jobs tool arguments\n */\nexport const ListJobsArgsSchema = z.object({\n activeOnly: z.boolean().optional(),\n status: z.enum(['pending', 'running', 'completed', 'failed', 'cancelled']).optional(),\n});\n\nexport type ListJobsArgs = z.infer<typeof ListJobsArgsSchema>;\n\n/**\n * Schema for cancel_job tool arguments\n */\nexport const CancelJobArgsSchema = z.object({\n jobId: z.string().min(1, 'Job ID must be a non-empty string'),\n});\n\nexport type CancelJobArgs = z.infer<typeof CancelJobArgsSchema>;\n\n// ============================================================================\n// Execute Meta-Tool Schema\n// ============================================================================\n\n/**\n * Schema for execute meta-tool arguments\n *\n * The execute tool consolidates store and job management commands\n * into a single tool, reducing context overhead.\n */\nexport const ExecuteArgsSchema = z.object({\n command: z.string().min(1, 'Command name is required'),\n args: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type ExecuteArgs = z.infer<typeof ExecuteArgsSchema>;\n","import { JobService } from '../../services/job.service.js';\nimport {\n CheckJobStatusArgsSchema,\n ListJobsArgsSchema,\n CancelJobArgsSchema,\n} from '../schemas/index.js';\nimport type { CheckJobStatusArgs, ListJobsArgs, CancelJobArgs } from '../schemas/index.js';\nimport type { ToolHandler, ToolResponse } from '../types.js';\n\n/**\n * Handle check_job_status requests\n *\n * Retrieves the current status of a background job.\n */\nexport const handleCheckJobStatus: ToolHandler<CheckJobStatusArgs> = (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = CheckJobStatusArgsSchema.parse(args);\n\n const { options } = context;\n\n const jobService = new JobService(options.dataDir);\n const job = jobService.getJob(validated.jobId);\n\n if (!job) {\n throw new Error(`Job not found: ${validated.jobId}`);\n }\n\n return Promise.resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify(job, null, 2),\n },\n ],\n });\n};\n\n/**\n * Handle list_jobs requests\n *\n * Lists all jobs with optional filtering by status or active status.\n */\nexport const handleListJobs: ToolHandler<ListJobsArgs> = (args, context): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = ListJobsArgsSchema.parse(args);\n\n const { options } = context;\n\n const jobService = new JobService(options.dataDir);\n\n let jobs;\n if (validated.activeOnly === true) {\n jobs = jobService.listActiveJobs();\n } else if (validated.status !== undefined) {\n jobs = jobService.listJobs(validated.status);\n } else {\n jobs = jobService.listJobs();\n }\n\n return Promise.resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({ jobs }, null, 2),\n },\n ],\n });\n};\n\n/**\n * Handle cancel_job requests\n *\n * Cancels a running or pending background job.\n * Kills the worker process if it exists.\n */\nexport const handleCancelJob: ToolHandler<CancelJobArgs> = (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = CancelJobArgsSchema.parse(args);\n\n const { options } = context;\n\n const jobService = new JobService(options.dataDir);\n const result = jobService.cancelJob(validated.jobId);\n\n if (!result.success) {\n throw new Error(result.error.message);\n }\n\n const job = jobService.getJob(validated.jobId);\n\n return Promise.resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: true,\n job,\n message: 'Job cancelled successfully',\n },\n null,\n 2\n ),\n },\n ],\n });\n};\n","import { z } from 'zod';\nimport { commandRegistry, generateHelp } from './registry.js';\nimport type { CommandDefinition } from './registry.js';\nimport type { ToolResponse } from '../types.js';\n\n/**\n * Meta commands for introspection and help\n *\n * These commands provide self-documentation for the execute tool,\n * allowing users to discover available commands and their usage.\n */\nexport const metaCommands: CommandDefinition[] = [\n {\n name: 'commands',\n description: 'List all available commands',\n handler: (): Promise<ToolResponse> => {\n const commands = commandRegistry.all();\n const commandList = commands.map((cmd) => ({\n name: cmd.name,\n description: cmd.description,\n }));\n\n return Promise.resolve({\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ commands: commandList }, null, 2),\n },\n ],\n });\n },\n },\n {\n name: 'help',\n description: 'Show help for a specific command or list all commands',\n argsSchema: z.object({\n command: z.string().optional().describe('Command name to get help for'),\n }),\n handler: (args: Record<string, unknown>): Promise<ToolResponse> => {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const commandName = args['command'] as string | undefined;\n const helpText = generateHelp(commandName);\n\n return Promise.resolve({\n content: [\n {\n type: 'text' as const,\n text: helpText,\n },\n ],\n });\n },\n },\n];\n","import { z } from 'zod';\nimport type { HandlerContext, ToolResponse } from '../types.js';\n\n/**\n * Command definition for the execute meta-tool\n *\n * Each command has a name, description, optional args schema, and handler.\n * Commands are registered in the registry and invoked via execute(command, args).\n */\nexport interface CommandDefinition {\n /** Command name (e.g., 'stores', 'store:info', 'job:status') */\n name: string;\n /** Human-readable description shown in help output */\n description: string;\n /** Optional Zod schema for argument validation */\n argsSchema?: z.ZodType;\n /** Handler function that executes the command */\n handler: CommandHandler;\n}\n\n/**\n * Command handler function signature\n *\n * @param args - Validated command arguments (or empty object if no args)\n * @param context - Handler context with services and options\n * @returns Promise resolving to tool response\n */\nexport type CommandHandler = (\n args: Record<string, unknown>,\n context: HandlerContext\n) => Promise<ToolResponse>;\n\n/**\n * Command registry - singleton that holds all registered commands\n */\nclass CommandRegistry {\n private readonly commands = new Map<string, CommandDefinition>();\n\n /**\n * Register a command\n */\n register(command: CommandDefinition): void {\n if (this.commands.has(command.name)) {\n throw new Error(`Command already registered: ${command.name}`);\n }\n this.commands.set(command.name, command);\n }\n\n /**\n * Register multiple commands at once\n */\n registerAll(commands: CommandDefinition[]): void {\n for (const command of commands) {\n this.register(command);\n }\n }\n\n /**\n * Get a command by name\n */\n get(name: string): CommandDefinition | undefined {\n return this.commands.get(name);\n }\n\n /**\n * Check if a command exists\n */\n has(name: string): boolean {\n return this.commands.has(name);\n }\n\n /**\n * Get all registered commands\n */\n all(): CommandDefinition[] {\n return Array.from(this.commands.values());\n }\n\n /**\n * Get commands grouped by category (prefix before colon)\n */\n grouped(): Map<string, CommandDefinition[]> {\n const groups = new Map<string, CommandDefinition[]>();\n\n for (const cmd of this.commands.values()) {\n const colonIndex = cmd.name.indexOf(':');\n const category = colonIndex === -1 ? 'general' : cmd.name.slice(0, colonIndex);\n\n const existing = groups.get(category) ?? [];\n existing.push(cmd);\n groups.set(category, existing);\n }\n\n return groups;\n }\n}\n\n/** Global command registry instance */\nexport const commandRegistry = new CommandRegistry();\n\n/**\n * Execute a command by name\n *\n * @param commandName - The command to execute\n * @param args - Arguments to pass to the command\n * @param context - Handler context\n * @returns Promise resolving to tool response\n */\nexport async function executeCommand(\n commandName: string,\n args: Record<string, unknown>,\n context: HandlerContext\n): Promise<ToolResponse> {\n const command = commandRegistry.get(commandName);\n\n if (command === undefined) {\n throw new Error(\n `Unknown command: ${commandName}. Use execute(\"commands\") to list available commands.`\n );\n }\n\n // Validate args if schema provided (Zod parse returns unknown, safe to cast after validation)\n /* eslint-disable @typescript-eslint/consistent-type-assertions */\n const validatedArgs: Record<string, unknown> =\n command.argsSchema !== undefined\n ? (command.argsSchema.parse(args) as Record<string, unknown>)\n : args;\n /* eslint-enable @typescript-eslint/consistent-type-assertions */\n\n return command.handler(validatedArgs, context);\n}\n\n/**\n * Generate help text for a command or all commands\n */\nexport function generateHelp(commandName?: string): string {\n if (commandName !== undefined) {\n const command = commandRegistry.get(commandName);\n if (command === undefined) {\n throw new Error(`Unknown command: ${commandName}`);\n }\n\n const lines = [`Command: ${command.name}`, `Description: ${command.description}`, ''];\n\n if (command.argsSchema !== undefined) {\n lines.push('Arguments:');\n // Extract schema shape for documentation\n const schema = command.argsSchema;\n if (schema instanceof z.ZodObject) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const shape = schema.shape as Record<string, z.ZodType>;\n for (const [key, fieldSchema] of Object.entries(shape)) {\n const isOptional = fieldSchema.safeParse(undefined).success;\n const desc = fieldSchema.description ?? '';\n lines.push(` ${key}${isOptional ? ' (optional)' : ''}: ${desc}`);\n }\n }\n } else {\n lines.push('Arguments: none');\n }\n\n return lines.join('\\n');\n }\n\n // Generate help for all commands\n const groups = commandRegistry.grouped();\n const lines = ['Available commands:', ''];\n\n for (const [category, commands] of groups) {\n lines.push(`${category}:`);\n for (const cmd of commands) {\n lines.push(` ${cmd.name} - ${cmd.description}`);\n }\n lines.push('');\n }\n\n lines.push('Use execute(\"help\", {command: \"name\"}) for detailed command help.');\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport {\n handleListStores,\n handleGetStoreInfo,\n handleCreateStore,\n handleIndexStore,\n handleDeleteStore,\n} from '../handlers/store.handler.js';\nimport type { CommandDefinition } from './registry.js';\nimport type {\n ListStoresArgs,\n GetStoreInfoArgs,\n CreateStoreArgs,\n IndexStoreArgs,\n DeleteStoreArgs,\n} from '../schemas/index.js';\n\n/**\n * Store management commands for the execute meta-tool\n *\n * These commands wrap the existing store handlers, providing\n * a unified interface through the execute command.\n *\n * Note: Type assertions are necessary here because CommandHandler uses\n * Record<string, unknown> for generic command args, while handlers expect\n * specific typed args. Zod validates at runtime before the cast.\n */\n/* eslint-disable @typescript-eslint/consistent-type-assertions */\nexport const storeCommands: CommandDefinition[] = [\n {\n name: 'stores',\n description: 'List all indexed knowledge stores',\n argsSchema: z.object({\n type: z.enum(['file', 'repo', 'web']).optional().describe('Filter by store type'),\n }),\n handler: (args, context) => handleListStores(args as unknown as ListStoresArgs, context),\n },\n {\n name: 'store:info',\n description: 'Get detailed information about a specific store',\n argsSchema: z.object({\n store: z.string().min(1).describe('Store name or ID'),\n }),\n handler: (args, context) => handleGetStoreInfo(args as unknown as GetStoreInfoArgs, context),\n },\n {\n name: 'store:create',\n description: 'Create a new knowledge store from git URL or local path',\n argsSchema: z.object({\n name: z.string().min(1).describe('Store name'),\n type: z.enum(['file', 'repo']).describe('Store type'),\n source: z.string().min(1).describe('Git URL or local path'),\n branch: z.string().optional().describe('Git branch (for repo type)'),\n description: z.string().optional().describe('Store description'),\n }),\n handler: (args, context) => handleCreateStore(args as unknown as CreateStoreArgs, context),\n },\n {\n name: 'store:index',\n description: 'Re-index a knowledge store to update search data',\n argsSchema: z.object({\n store: z.string().min(1).describe('Store name or ID'),\n }),\n handler: (args, context) => handleIndexStore(args as unknown as IndexStoreArgs, context),\n },\n {\n name: 'store:delete',\n description: 'Delete a knowledge store and all associated data',\n argsSchema: z.object({\n store: z.string().min(1).describe('Store name or ID'),\n }),\n handler: (args, context) => handleDeleteStore(args as unknown as DeleteStoreArgs, context),\n },\n];\n/* eslint-enable @typescript-eslint/consistent-type-assertions */\n","import { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { JobService } from '../../services/job.service.js';\nimport { createStoreId } from '../../types/brands.js';\nimport { spawnBackgroundWorker } from '../../workers/spawn-worker.js';\nimport {\n ListStoresArgsSchema,\n GetStoreInfoArgsSchema,\n CreateStoreArgsSchema,\n IndexStoreArgsSchema,\n DeleteStoreArgsSchema,\n} from '../schemas/index.js';\nimport type {\n ListStoresArgs,\n GetStoreInfoArgs,\n CreateStoreArgs,\n IndexStoreArgs,\n DeleteStoreArgs,\n} from '../schemas/index.js';\nimport type { ToolHandler, ToolResponse } from '../types.js';\n\n/**\n * Handle list_stores requests\n *\n * Lists all knowledge stores with optional type filtering.\n */\nexport const handleListStores: ToolHandler<ListStoresArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = ListStoresArgsSchema.parse(args);\n\n const { services } = context;\n\n const stores = await services.store.list();\n const filtered =\n validated.type !== undefined ? stores.filter((s) => s.type === validated.type) : stores;\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n stores: filtered.map((s) => ({\n id: s.id,\n name: s.name,\n type: s.type,\n path: 'path' in s ? s.path : undefined,\n url: 'url' in s && s.url !== undefined ? s.url : undefined,\n description: s.description,\n createdAt: s.createdAt.toISOString(),\n })),\n },\n null,\n 2\n ),\n },\n ],\n };\n};\n\n/**\n * Handle get_store_info requests\n *\n * Retrieves detailed information about a specific store.\n */\nexport const handleGetStoreInfo: ToolHandler<GetStoreInfoArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = GetStoreInfoArgsSchema.parse(args);\n\n const { services } = context;\n\n const store = await services.store.getByIdOrName(createStoreId(validated.store));\n\n if (store === undefined) {\n throw new Error(`Store not found: ${validated.store}`);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n id: store.id,\n name: store.name,\n type: store.type,\n path: 'path' in store ? store.path : undefined,\n url: 'url' in store && store.url !== undefined ? store.url : undefined,\n branch: 'branch' in store ? store.branch : undefined,\n description: store.description,\n status: store.status,\n createdAt: store.createdAt.toISOString(),\n updatedAt: store.updatedAt.toISOString(),\n },\n null,\n 2\n ),\n },\n ],\n };\n};\n\n/**\n * Handle create_store requests\n *\n * Creates a new knowledge store and starts background indexing.\n * Returns store info and job ID for tracking progress.\n */\nexport const handleCreateStore: ToolHandler<CreateStoreArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = CreateStoreArgsSchema.parse(args);\n\n const { services, options } = context;\n\n // Determine if source is a URL or path\n const isUrl =\n validated.source.startsWith('http://') ||\n validated.source.startsWith('https://') ||\n validated.source.startsWith('git@');\n\n const result = await services.store.create({\n name: validated.name,\n type: validated.type,\n ...(isUrl ? { url: validated.source } : { path: validated.source }),\n ...(validated.branch !== undefined ? { branch: validated.branch } : {}),\n ...(validated.description !== undefined ? { description: validated.description } : {}),\n });\n\n if (!result.success) {\n throw new Error(result.error.message);\n }\n\n // Create background job for indexing\n const jobService = new JobService(options.dataDir);\n const jobDetails: Record<string, unknown> = {\n storeName: result.data.name,\n storeId: result.data.id,\n };\n if (isUrl) {\n jobDetails['url'] = validated.source;\n }\n if ('path' in result.data && result.data.path) {\n jobDetails['path'] = result.data.path;\n }\n const job = jobService.createJob({\n type: validated.type === 'repo' && isUrl ? 'clone' : 'index',\n details: jobDetails,\n message: `Indexing ${result.data.name}...`,\n });\n\n // Spawn background worker (dataDir defaults to project-local .bluera if undefined)\n spawnBackgroundWorker(job.id, options.dataDir ?? '');\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n store: {\n id: result.data.id,\n name: result.data.name,\n type: result.data.type,\n path: 'path' in result.data ? result.data.path : undefined,\n },\n job: {\n id: job.id,\n status: job.status,\n message: job.message,\n },\n message: `Store created. Indexing started in background (Job ID: ${job.id})`,\n },\n null,\n 2\n ),\n },\n ],\n };\n};\n\n/**\n * Handle index_store requests\n *\n * Re-indexes an existing store in the background.\n * Returns job ID for tracking progress.\n */\nexport const handleIndexStore: ToolHandler<IndexStoreArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = IndexStoreArgsSchema.parse(args);\n\n const { services, options } = context;\n\n const store = await services.store.getByIdOrName(createStoreId(validated.store));\n\n if (store === undefined) {\n throw new Error(`Store not found: ${validated.store}`);\n }\n\n // Create background job for indexing\n const jobService = new JobService(options.dataDir);\n const jobDetails: Record<string, unknown> = {\n storeName: store.name,\n storeId: store.id,\n };\n if ('path' in store && store.path) {\n jobDetails['path'] = store.path;\n }\n const job = jobService.createJob({\n type: 'index',\n details: jobDetails,\n message: `Re-indexing ${store.name}...`,\n });\n\n // Spawn background worker (dataDir defaults to project-local .bluera if undefined)\n spawnBackgroundWorker(job.id, options.dataDir ?? '');\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n store: {\n id: store.id,\n name: store.name,\n },\n job: {\n id: job.id,\n status: job.status,\n message: job.message,\n },\n message: `Indexing started in background (Job ID: ${job.id})`,\n },\n null,\n 2\n ),\n },\n ],\n };\n};\n\n/**\n * Handle delete_store requests\n *\n * Deletes a store and all associated data:\n * - Removes from store registry\n * - Drops LanceDB table\n * - For repo stores with URL, removes cloned files\n */\nexport const handleDeleteStore: ToolHandler<DeleteStoreArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = DeleteStoreArgsSchema.parse(args);\n\n const { services, options } = context;\n\n const store = await services.store.getByIdOrName(createStoreId(validated.store));\n\n if (store === undefined) {\n throw new Error(`Store not found: ${validated.store}`);\n }\n\n // Delete LanceDB table\n await services.lance.deleteStore(store.id);\n\n // For repo stores cloned from URL, remove the cloned directory\n if (store.type === 'repo' && 'url' in store && store.url !== undefined) {\n if (options.dataDir === undefined) {\n throw new Error('dataDir is required to delete cloned repository files');\n }\n const repoPath = join(options.dataDir, 'repos', store.id);\n await rm(repoPath, { recursive: true, force: true });\n }\n\n // Delete from registry\n const result = await services.store.delete(store.id);\n if (!result.success) {\n throw new Error(result.error.message);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n deleted: true,\n store: {\n id: store.id,\n name: store.name,\n type: store.type,\n },\n message: `Successfully deleted store: ${store.name}`,\n },\n null,\n 2\n ),\n },\n ],\n };\n};\n","import { spawn } from 'child_process';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * Spawn a background worker process to execute a job\n *\n * The worker runs detached from the parent process, allowing the\n * parent to exit while the worker continues running.\n *\n * @param jobId - The ID of the job to execute\n */\nexport function spawnBackgroundWorker(jobId: string, dataDir: string): void {\n // Determine the worker script path\n // In production, this will be the compiled dist file\n // In development, we need to use tsx to run TypeScript\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n // Check if we're running from dist (production) or src (development)\n const isProduction = __dirname.includes('/dist/');\n\n let command: string;\n let args: string[];\n\n if (isProduction) {\n // Production: Use Node.js directly with compiled file\n const workerScript = path.join(__dirname, 'background-worker-cli.js');\n command = process.execPath; // Use the same Node.js binary\n args = [workerScript, jobId];\n } else {\n // Development: Use tsx to run TypeScript directly\n const workerScript = path.join(__dirname, 'background-worker-cli.ts');\n command = 'npx';\n args = ['tsx', workerScript, jobId];\n }\n\n // Spawn the worker process\n const worker = spawn(command, args, {\n detached: true, // Detach from parent process\n stdio: 'ignore', // Don't pipe stdio (fully independent)\n env: {\n ...process.env, // Inherit environment variables\n BLUERA_DATA_DIR: dataDir, // Pass dataDir to worker\n },\n });\n\n // Unref the worker so the parent can exit\n worker.unref();\n}\n","/**\n * Command registration for the execute meta-tool\n *\n * This module registers all commands with the command registry.\n * Import this module to ensure all commands are available.\n */\n\nimport { jobCommands } from './job.commands.js';\nimport { metaCommands } from './meta.commands.js';\nimport { commandRegistry } from './registry.js';\nimport { storeCommands } from './store.commands.js';\n\n// Register all commands\ncommandRegistry.registerAll(storeCommands);\ncommandRegistry.registerAll(jobCommands);\ncommandRegistry.registerAll(metaCommands);\n\n// Re-export for convenience\nexport { commandRegistry, executeCommand, generateHelp } from './registry.js';\nexport type { CommandDefinition, CommandHandler } from './registry.js';\n","// Import commands module - side effect registers all commands, then use executeCommand\nimport { executeCommand } from '../commands/index.js';\nimport { ExecuteArgsSchema } from '../schemas/index.js';\nimport type { ExecuteArgs } from '../schemas/index.js';\nimport type { ToolHandler, ToolResponse } from '../types.js';\n\n/**\n * Handle execute requests\n *\n * This is the meta-tool handler that routes to registered commands.\n * It consolidates store and job management into a single tool surface.\n */\nexport const handleExecute: ToolHandler<ExecuteArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = ExecuteArgsSchema.parse(args);\n\n const commandArgs = validated.args ?? {};\n\n return executeCommand(validated.command, commandArgs, context);\n};\n","/**\n * Token estimation service using Anthropic's recommended heuristic.\n * For Claude 3+ models, Anthropic recommends ~3.5 characters per token\n * for English text. This varies by language.\n *\n * Note: The official @anthropic-ai/tokenizer package only works for\n * pre-Claude 3 models. For accurate counts on Claude 3+, use the\n * Token Count API. This heuristic is suitable for display purposes.\n */\n\nconst CHARS_PER_TOKEN = 3.5;\n\n/**\n * Estimate token count for a string using character-based heuristic.\n * @param text - The text to estimate tokens for\n * @returns Estimated token count (rounded up)\n */\nexport function estimateTokens(text: string): number {\n if (!text) return 0;\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n/**\n * Format token count for display with appropriate suffix.\n * @param tokens - Token count\n * @returns Formatted string like \"~1.2k\" or \"~847\"\n */\nexport function formatTokenCount(tokens: number): string {\n if (tokens >= 1000) {\n return `~${(tokens / 1000).toFixed(1)}k`;\n }\n return `~${String(tokens)}`;\n}\n","/**\n * LRU (Least Recently Used) Cache implementation\n *\n * Maintains a cache with a maximum size, evicting the oldest (least recently used)\n * items when the capacity is exceeded. This prevents unbounded memory growth.\n *\n * Items are automatically moved to the end of the cache when accessed (via get),\n * making them the most recently used.\n */\nexport class LRUCache<K, V> {\n private readonly cache = new Map<K, V>();\n private readonly maxSize: number;\n\n /**\n * Create a new LRU cache\n *\n * @param maxSize - Maximum number of items to store (default: 1000)\n */\n constructor(maxSize: number = 1000) {\n this.maxSize = maxSize;\n }\n\n /**\n * Store a value in the cache\n *\n * If the key already exists, it will be moved to the end (most recent).\n * If the cache is at capacity, the oldest item will be evicted.\n *\n * @param key - The cache key\n * @param value - The value to store\n */\n set(key: K, value: V): void {\n // If key exists, delete it first to move it to the end\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Add the new/updated entry\n this.cache.set(key, value);\n\n // Evict oldest entry if over capacity\n if (this.cache.size > this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n }\n\n /**\n * Retrieve a value from the cache\n *\n * If the key exists, it will be moved to the end (most recent).\n *\n * @param key - The cache key\n * @returns The cached value, or undefined if not found\n */\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n\n if (value !== undefined) {\n // Move to end (most recent) by deleting and re-adding\n this.cache.delete(key);\n this.cache.set(key, value);\n }\n\n return value;\n }\n\n /**\n * Check if a key exists in the cache\n *\n * @param key - The cache key\n * @returns True if the key exists\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Remove a specific key from the cache\n *\n * @param key - The cache key\n * @returns True if the key was removed, false if it didn't exist\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries from the cache\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the current number of items in the cache\n */\n get size(): number {\n return this.cache.size;\n }\n}\n","import { createLogger, summarizePayload } from '../../logging/index.js';\nimport { estimateTokens, formatTokenCount } from '../../services/token.service.js';\nimport { LRUCache } from '../cache.js';\nimport { SearchArgsSchema, GetFullContextArgsSchema } from '../schemas/index.js';\nimport type { SearchQuery, DocumentId, StoreId } from '../../types/index.js';\nimport type { SearchResult } from '../../types/search.js';\nimport type { SearchArgs, GetFullContextArgs } from '../schemas/index.js';\nimport type { ToolHandler, ToolResponse } from '../types.js';\n\nconst logger = createLogger('mcp-search');\n\n// Create result cache for get_full_context\n// Uses LRU cache to prevent memory leaks (max 1000 items)\nexport const resultCache = new LRUCache<DocumentId, SearchResult>(1000);\n\n/**\n * Handle search requests\n *\n * Searches across specified stores (or all stores if none specified) using\n * hybrid vector + FTS search. Results are cached for get_full_context retrieval.\n */\nexport const handleSearch: ToolHandler<SearchArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = SearchArgsSchema.parse(args);\n\n logger.info(\n {\n query: validated.query,\n stores: validated.stores,\n detail: validated.detail,\n limit: validated.limit,\n intent: validated.intent,\n },\n 'Search started'\n );\n\n const { services } = context;\n\n // Get all stores if none specified, resolve store names to IDs\n const storeIds: StoreId[] =\n validated.stores !== undefined\n ? await Promise.all(\n validated.stores.map(async (s) => {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const store = await services.store.getByIdOrName(s as StoreId);\n if (!store) {\n throw new Error(`Store not found: ${s}`);\n }\n return store.id;\n })\n )\n : (await services.store.list()).map((s) => s.id);\n\n // Initialize stores with error handling\n try {\n for (const storeId of storeIds) {\n await services.lance.initialize(storeId);\n }\n } catch (error) {\n throw new Error(\n `Failed to initialize vector stores: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n // Perform search\n const searchQuery: SearchQuery = {\n query: validated.query,\n stores: storeIds,\n mode: 'hybrid',\n limit: validated.limit,\n detail: validated.detail,\n };\n\n const results = await services.search.search(searchQuery);\n\n // Cache results for get_full_context (with LRU eviction)\n for (const result of results.results) {\n resultCache.set(result.id, result);\n }\n\n // Add repoRoot to results for cloned repos\n const enhancedResults = await Promise.all(\n results.results.map(async (r) => {\n const storeId = r.metadata.storeId;\n const store = await services.store.getByIdOrName(storeId);\n\n return {\n id: r.id,\n score: r.score,\n summary: {\n ...r.summary,\n storeName: store?.name,\n repoRoot: store?.type === 'repo' ? store.path : undefined,\n },\n context: r.context,\n full: r.full,\n };\n })\n );\n\n const responseJson = JSON.stringify(\n {\n results: enhancedResults,\n totalResults: results.totalResults,\n mode: results.mode,\n timeMs: results.timeMs,\n },\n null,\n 2\n );\n\n // Calculate actual token estimate based on response content\n const responseTokens = estimateTokens(responseJson);\n\n // Create visible header with token usage\n const header = `Search: \"${validated.query}\" | Results: ${String(results.totalResults)} | ${formatTokenCount(responseTokens)} tokens | ${String(results.timeMs)}ms\\n\\n`;\n\n // Log the complete MCP response that will be sent to Claude Code\n logger.info(\n {\n query: validated.query,\n totalResults: results.totalResults,\n responseTokens,\n timeMs: results.timeMs,\n ...summarizePayload(responseJson, 'mcp-response', validated.query),\n },\n 'Search complete - context sent to Claude Code'\n );\n\n return {\n content: [\n {\n type: 'text',\n text: header + responseJson,\n },\n ],\n };\n};\n\n/**\n * Handle get_full_context requests\n *\n * Retrieves full context for a previously cached search result.\n * If the result isn't already full, re-queries with full detail level.\n */\nexport const handleGetFullContext: ToolHandler<GetFullContextArgs> = async (\n args,\n context\n): Promise<ToolResponse> => {\n // Validate arguments with Zod\n const validated = GetFullContextArgsSchema.parse(args);\n\n logger.info({ resultId: validated.resultId }, 'Get full context requested');\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const resultId = validated.resultId as DocumentId;\n\n // Check cache for result\n const cachedResult = resultCache.get(resultId);\n\n if (!cachedResult) {\n throw new Error(`Result not found in cache: ${resultId}. Run a search first to cache results.`);\n }\n\n // If result already has full context, return it\n if (cachedResult.full) {\n const responseJson = JSON.stringify(\n {\n id: cachedResult.id,\n score: cachedResult.score,\n summary: cachedResult.summary,\n context: cachedResult.context,\n full: cachedResult.full,\n },\n null,\n 2\n );\n\n logger.info(\n {\n resultId,\n cached: true,\n hasFullContext: true,\n ...summarizePayload(responseJson, 'mcp-full-context', resultId),\n },\n 'Full context retrieved from cache'\n );\n\n return {\n content: [\n {\n type: 'text',\n text: responseJson,\n },\n ],\n };\n }\n\n // Otherwise, re-query with full detail\n const { services } = context;\n const store = await services.store.getByIdOrName(cachedResult.metadata.storeId);\n\n if (!store) {\n throw new Error(`Store not found: ${cachedResult.metadata.storeId}`);\n }\n\n await services.lance.initialize(store.id);\n\n const searchQuery: SearchQuery = {\n query: cachedResult.content.substring(0, 100), // Use snippet of content as query\n stores: [store.id],\n mode: 'hybrid',\n limit: 1,\n detail: 'full',\n };\n\n const results = await services.search.search(searchQuery);\n\n // Find matching result by ID\n const fullResult = results.results.find((r) => r.id === resultId);\n\n if (!fullResult) {\n // Return cached result even if we couldn't get full detail\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n id: cachedResult.id,\n score: cachedResult.score,\n summary: cachedResult.summary,\n context: cachedResult.context,\n warning: 'Could not retrieve full context, returning cached minimal result',\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // Update cache with full result\n resultCache.set(resultId, fullResult);\n\n const responseJson = JSON.stringify(\n {\n id: fullResult.id,\n score: fullResult.score,\n summary: fullResult.summary,\n context: fullResult.context,\n full: fullResult.full,\n },\n null,\n 2\n );\n\n logger.info(\n {\n resultId,\n cached: false,\n hasFullContext: true,\n ...summarizePayload(responseJson, 'mcp-full-context', resultId),\n },\n 'Full context retrieved via re-query'\n );\n\n return {\n content: [\n {\n type: 'text',\n text: responseJson,\n },\n ],\n };\n};\n","import { z } from 'zod';\nimport { handleSearch, handleGetFullContext } from './search.handler.js';\nimport { SearchArgsSchema, GetFullContextArgsSchema } from '../schemas/index.js';\nimport type { ToolHandler } from '../types.js';\n\n/**\n * Tool definition with schema and handler\n */\nexport interface ToolDefinition {\n name: string;\n description: string;\n schema: z.ZodType;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- heterogeneous tool registry requires any; schema provides runtime type safety via Zod validation\n handler: ToolHandler<any>;\n}\n\n/**\n * Registry of native MCP tools\n *\n * Only search and get_full_context are native tools with full schemas.\n * Store and job management is consolidated into the execute meta-tool\n * (see commands/ directory and execute.handler.ts).\n */\nexport const tools: ToolDefinition[] = [\n {\n name: 'search',\n description:\n 'Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.',\n schema: SearchArgsSchema,\n handler: handleSearch,\n },\n {\n name: 'get_full_context',\n description:\n 'Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.',\n schema: GetFullContextArgsSchema,\n handler: handleGetFullContext,\n },\n];\n"],"mappings":"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","names":["z","z","z","z","lines","z","z","__dirname","z","responseJson","logger"]}