snow-ai 0.3.35 → 0.3.37

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 (92) hide show
  1. package/dist/agents/codebaseIndexAgent.js +1 -0
  2. package/dist/agents/codebaseReviewAgent.d.ts +61 -0
  3. package/dist/agents/codebaseReviewAgent.js +301 -0
  4. package/dist/api/anthropic.js +1 -0
  5. package/dist/api/chat.js +1 -0
  6. package/dist/api/embedding.js +1 -0
  7. package/dist/api/gemini.js +2 -1
  8. package/dist/api/responses.js +1 -0
  9. package/dist/api/systemPrompt.d.ts +1 -5
  10. package/dist/api/systemPrompt.js +198 -141
  11. package/dist/app.js +14 -6
  12. package/dist/cli.js +1 -1
  13. package/dist/hooks/useCommandPanel.js +48 -46
  14. package/dist/hooks/useConversation.d.ts +2 -1
  15. package/dist/hooks/useConversation.js +110 -28
  16. package/dist/hooks/useGlobalExit.js +4 -2
  17. package/dist/hooks/useKeyboardInput.js +132 -26
  18. package/dist/hooks/useStreamingState.d.ts +9 -0
  19. package/dist/hooks/useStreamingState.js +3 -0
  20. package/dist/i18n/I18nContext.d.ts +14 -0
  21. package/dist/i18n/I18nContext.js +24 -0
  22. package/dist/i18n/index.d.ts +3 -0
  23. package/dist/i18n/index.js +2 -0
  24. package/dist/i18n/lang/en.d.ts +2 -0
  25. package/dist/i18n/lang/en.js +481 -0
  26. package/dist/i18n/lang/es.d.ts +2 -0
  27. package/dist/i18n/lang/es.js +481 -0
  28. package/dist/i18n/lang/ja.d.ts +2 -0
  29. package/dist/i18n/lang/ja.js +481 -0
  30. package/dist/i18n/lang/ko.d.ts +2 -0
  31. package/dist/i18n/lang/ko.js +481 -0
  32. package/dist/i18n/lang/zh-TW.d.ts +2 -0
  33. package/dist/i18n/lang/zh-TW.js +481 -0
  34. package/dist/i18n/lang/zh.d.ts +2 -0
  35. package/dist/i18n/lang/zh.js +481 -0
  36. package/dist/i18n/translations.d.ts +2 -0
  37. package/dist/i18n/translations.js +14 -0
  38. package/dist/i18n/types.d.ts +457 -0
  39. package/dist/i18n/types.js +1 -0
  40. package/dist/mcp/aceCodeSearch.d.ts +23 -48
  41. package/dist/mcp/aceCodeSearch.js +154 -144
  42. package/dist/mcp/codebaseSearch.d.ts +1 -1
  43. package/dist/mcp/codebaseSearch.js +159 -30
  44. package/dist/mcp/filesystem.d.ts +3 -80
  45. package/dist/mcp/filesystem.js +7 -92
  46. package/dist/mcp/subagent.d.ts +2 -1
  47. package/dist/mcp/subagent.js +54 -5
  48. package/dist/ui/components/ChatInput.js +39 -50
  49. package/dist/ui/components/CommandPanel.d.ts +1 -1
  50. package/dist/ui/components/CommandPanel.js +20 -13
  51. package/dist/ui/components/HelpPanel.js +47 -21
  52. package/dist/ui/components/Menu.js +6 -2
  53. package/dist/ui/components/MessageList.d.ts +6 -0
  54. package/dist/ui/components/MessageList.js +1 -1
  55. package/dist/ui/components/ToolConfirmation.d.ts +4 -1
  56. package/dist/ui/components/ToolConfirmation.js +28 -2
  57. package/dist/ui/components/ToolResultPreview.d.ts +2 -1
  58. package/dist/ui/components/ToolResultPreview.js +26 -22
  59. package/dist/ui/pages/ChatScreen.js +126 -49
  60. package/dist/ui/pages/CodeBaseConfigScreen.js +54 -30
  61. package/dist/ui/pages/ConfigScreen.js +102 -98
  62. package/dist/ui/pages/CustomHeadersScreen.js +75 -69
  63. package/dist/ui/pages/LanguageSettingsScreen.d.ts +7 -0
  64. package/dist/ui/pages/LanguageSettingsScreen.js +89 -0
  65. package/dist/ui/pages/ProxyConfigScreen.js +27 -23
  66. package/dist/ui/pages/SensitiveCommandConfigScreen.js +32 -25
  67. package/dist/ui/pages/SubAgentConfigScreen.js +88 -75
  68. package/dist/ui/pages/SystemPromptConfigScreen.js +31 -26
  69. package/dist/ui/pages/WelcomeScreen.js +40 -26
  70. package/dist/utils/codebaseConfig.d.ts +1 -5
  71. package/dist/utils/codebaseConfig.js +2 -10
  72. package/dist/utils/codebaseSearchEvents.d.ts +16 -0
  73. package/dist/utils/codebaseSearchEvents.js +13 -0
  74. package/dist/utils/commands/agent.js +2 -2
  75. package/dist/utils/commands/init.js +1 -1
  76. package/dist/utils/configManager.js +26 -5
  77. package/dist/utils/contextCompressor.js +1 -1
  78. package/dist/utils/languageConfig.d.ts +21 -0
  79. package/dist/utils/languageConfig.js +61 -0
  80. package/dist/utils/mcpToolsManager.js +0 -9
  81. package/dist/utils/notebookManager.js +11 -4
  82. package/dist/utils/sessionConverter.js +13 -3
  83. package/dist/utils/subAgentConfig.d.ts +10 -5
  84. package/dist/utils/subAgentConfig.js +112 -19
  85. package/dist/utils/subAgentExecutor.d.ts +9 -1
  86. package/dist/utils/subAgentExecutor.js +122 -9
  87. package/dist/utils/textBuffer.d.ts +1 -0
  88. package/dist/utils/textBuffer.js +69 -4
  89. package/dist/utils/toolExecutor.d.ts +2 -1
  90. package/dist/utils/toolExecutor.js +1 -2
  91. package/dist/utils/usageLogger.js +18 -3
  92. package/package.json +1 -1
@@ -7,7 +7,7 @@ import { processManager } from '../utils/processManager.js';
7
7
  import { detectLanguage } from './utils/aceCodeSearch/language.utils.js';
8
8
  import { loadExclusionPatterns, shouldExcludeDirectory, readFileWithCache, } from './utils/aceCodeSearch/filesystem.utils.js';
9
9
  import { parseFileSymbols, getContext, } from './utils/aceCodeSearch/symbol.utils.js';
10
- import { isCommandAvailable, parseGrepOutput, globToRegex, } from './utils/aceCodeSearch/search.utils.js';
10
+ import { isCommandAvailable, parseGrepOutput, } from './utils/aceCodeSearch/search.utils.js';
11
11
  export class ACECodeSearchService {
12
12
  constructor(basePath = process.cwd()) {
13
13
  Object.defineProperty(this, "basePath", {
@@ -196,10 +196,11 @@ export class ACECodeSearchService {
196
196
  await fs.access(cachedPath);
197
197
  }
198
198
  catch {
199
- // File no longer exists, remove from cache
199
+ // File no longer exists, remove from all caches
200
200
  this.indexCache.delete(cachedPath);
201
201
  this.fileModTimes.delete(cachedPath);
202
202
  this.allIndexedFiles.delete(cachedPath);
203
+ this.fileContentCache.delete(cachedPath);
203
204
  }
204
205
  }
205
206
  this.lastIndexTime = now;
@@ -372,6 +373,10 @@ export class ACECodeSearchService {
372
373
  */
373
374
  async findReferences(symbolName, maxResults = 100) {
374
375
  const references = [];
376
+ // Load exclusion patterns
377
+ await this.loadExclusionPatterns();
378
+ // Escape special regex characters to prevent ReDoS
379
+ const escapedSymbol = symbolName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
375
380
  const searchInDirectory = async (dirPath) => {
376
381
  try {
377
382
  const entries = await fs.readdir(dirPath, { withFileTypes: true });
@@ -380,11 +385,8 @@ export class ACECodeSearchService {
380
385
  break;
381
386
  const fullPath = path.join(dirPath, entry.name);
382
387
  if (entry.isDirectory()) {
383
- if (entry.name === 'node_modules' ||
384
- entry.name === '.git' ||
385
- entry.name === 'dist' ||
386
- entry.name === 'build' ||
387
- entry.name.startsWith('.')) {
388
+ // Use configurable exclusion check
389
+ if (shouldExcludeDirectory(entry.name, fullPath, this.basePath, this.customExcludes, this.regexCache)) {
388
390
  continue;
389
391
  }
390
392
  await searchInDirectory(fullPath);
@@ -395,12 +397,14 @@ export class ACECodeSearchService {
395
397
  try {
396
398
  const content = await fs.readFile(fullPath, 'utf-8');
397
399
  const lines = content.split('\n');
398
- // Search for symbol usage
400
+ // Search for symbol usage with escaped symbol name
401
+ const regex = new RegExp(`\\b${escapedSymbol}\\b`, 'g');
399
402
  for (let i = 0; i < lines.length; i++) {
400
403
  const line = lines[i];
401
404
  if (!line)
402
405
  continue;
403
- const regex = new RegExp(`\\b${symbolName}\\b`, 'g');
406
+ // Reset regex for each line
407
+ regex.lastIndex = 0;
404
408
  let match;
405
409
  while ((match = regex.exec(line)) !== null) {
406
410
  if (references.length >= maxResults)
@@ -410,7 +414,7 @@ export class ACECodeSearchService {
410
414
  if (line.includes('import') && line.includes(symbolName)) {
411
415
  referenceType = 'import';
412
416
  }
413
- else if (line.match(new RegExp(`(?:function|class|const|let|var)\\s+${symbolName}`))) {
417
+ else if (new RegExp(`(?:function|class|const|let|var)\\s+${escapedSymbol}`).test(line)) {
414
418
  referenceType = 'definition';
415
419
  }
416
420
  else if (line.includes(':') &&
@@ -491,19 +495,24 @@ export class ACECodeSearchService {
491
495
  /**
492
496
  * Strategy 1: Use git grep for fast searching in Git repositories
493
497
  */
494
- async gitGrepSearch(pattern, fileGlob, maxResults = 100) {
498
+ async gitGrepSearch(pattern, fileGlob, maxResults = 100, isRegex = false) {
495
499
  return new Promise((resolve, reject) => {
496
- const args = [
497
- 'grep',
498
- '--untracked',
499
- '-n',
500
- '-E',
501
- '--ignore-case',
502
- pattern,
503
- ];
500
+ const args = ['grep', '--untracked', '-n', '--ignore-case'];
501
+ // Use fixed-strings for literal search, extended regex for pattern search
502
+ if (isRegex) {
503
+ args.push('-E'); // Extended regex
504
+ }
505
+ else {
506
+ args.push('--fixed-strings'); // Literal string matching
507
+ }
508
+ args.push(pattern);
504
509
  if (fileGlob) {
505
- // Expand glob patterns with braces (e.g., "source/**/*.{ts,tsx}" -> ["source/**/*.ts", "source/**/*.tsx"])
506
- const expandedGlobs = this.expandGlobBraces(fileGlob);
510
+ // Normalize path separators for Windows compatibility
511
+ let gitGlob = fileGlob.replace(/\\/g, '/');
512
+ // Convert ** to * as git grep has limited ** support
513
+ gitGlob = gitGlob.replace(/\*\*/g, '*');
514
+ // Expand glob patterns with braces (e.g., "source/*.{ts,tsx}" -> ["source/*.ts", "source/*.tsx"])
515
+ const expandedGlobs = this.expandGlobBraces(gitGlob);
507
516
  args.push('--', ...expandedGlobs);
508
517
  }
509
518
  const child = spawn('git', args, {
@@ -563,14 +572,22 @@ export class ACECodeSearchService {
563
572
  // Ripgrep uses --glob for filtering
564
573
  excludeDirs.forEach(dir => args.push('--glob', `!${dir}/`));
565
574
  if (fileGlob) {
566
- args.push('--glob', fileGlob);
575
+ // Normalize path separators for Windows compatibility
576
+ const normalizedGlob = fileGlob.replace(/\\/g, '/');
577
+ // Expand glob patterns with braces
578
+ const expandedGlobs = this.expandGlobBraces(normalizedGlob);
579
+ expandedGlobs.forEach(glob => args.push('--glob', glob));
567
580
  }
568
581
  }
569
582
  else {
570
583
  // System grep uses --exclude-dir
571
584
  excludeDirs.forEach(dir => args.push(`--exclude-dir=${dir}`));
572
585
  if (fileGlob) {
573
- args.push(`--include=${fileGlob}`);
586
+ // Normalize path separators for Windows compatibility
587
+ const normalizedGlob = fileGlob.replace(/\\/g, '/');
588
+ // Expand glob patterns with braces
589
+ const expandedGlobs = this.expandGlobBraces(normalizedGlob);
590
+ expandedGlobs.forEach(glob => args.push(`--include=${glob}`));
574
591
  }
575
592
  args.push(pattern, '.');
576
593
  }
@@ -615,11 +632,35 @@ export class ACECodeSearchService {
615
632
  });
616
633
  });
617
634
  }
635
+ /**
636
+ * Convert a glob pattern to a RegExp that matches full paths
637
+ * Supports: *, **, ?, {a,b}, [abc]
638
+ */
639
+ globPatternToRegex(globPattern) {
640
+ // Normalize path separators
641
+ const normalizedGlob = globPattern.replace(/\\/g, '/');
642
+ // First, temporarily replace glob special patterns with placeholders
643
+ // to prevent them from being escaped
644
+ let regexStr = normalizedGlob
645
+ .replace(/\*\*/g, '\x00DOUBLESTAR\x00') // ** -> placeholder
646
+ .replace(/\*/g, '\x00STAR\x00') // * -> placeholder
647
+ .replace(/\?/g, '\x00QUESTION\x00'); // ? -> placeholder
648
+ // Now escape all special regex characters
649
+ regexStr = regexStr.replace(/[.+^${}()|[\]\\]/g, '\\$&');
650
+ // Replace placeholders with actual regex patterns
651
+ regexStr = regexStr
652
+ .replace(/\x00DOUBLESTAR\x00/g, '.*') // ** -> .* (match any path segments)
653
+ .replace(/\x00STAR\x00/g, '[^/]*') // * -> [^/]* (match within single segment)
654
+ .replace(/\x00QUESTION\x00/g, '.'); // ? -> . (match single character)
655
+ return new RegExp(regexStr, 'i');
656
+ }
618
657
  /**
619
658
  * Strategy 3: Pure JavaScript fallback search
620
659
  */
621
660
  async jsTextSearch(pattern, fileGlob, isRegex = false, maxResults = 100) {
622
661
  const results = [];
662
+ // Load exclusion patterns
663
+ await this.loadExclusionPatterns();
623
664
  // Compile search pattern
624
665
  let searchRegex;
625
666
  try {
@@ -635,8 +676,42 @@ export class ACECodeSearchService {
635
676
  catch (error) {
636
677
  throw new Error(`Invalid regex pattern: ${pattern}`);
637
678
  }
638
- // Parse glob pattern if provided
639
- const globRegex = fileGlob ? globToRegex(fileGlob) : null;
679
+ // Parse glob pattern if provided using improved glob parser
680
+ const globRegex = fileGlob ? this.globPatternToRegex(fileGlob) : null;
681
+ // Binary file extensions (using Set for O(1) lookup)
682
+ const binaryExts = new Set([
683
+ '.jpg',
684
+ '.jpeg',
685
+ '.png',
686
+ '.gif',
687
+ '.bmp',
688
+ '.ico',
689
+ '.svg',
690
+ '.pdf',
691
+ '.zip',
692
+ '.tar',
693
+ '.gz',
694
+ '.rar',
695
+ '.7z',
696
+ '.exe',
697
+ '.dll',
698
+ '.so',
699
+ '.dylib',
700
+ '.mp3',
701
+ '.mp4',
702
+ '.avi',
703
+ '.mov',
704
+ '.woff',
705
+ '.woff2',
706
+ '.ttf',
707
+ '.eot',
708
+ '.class',
709
+ '.jar',
710
+ '.war',
711
+ '.o',
712
+ '.a',
713
+ '.lib',
714
+ ]);
640
715
  // Search recursively
641
716
  const searchInDirectory = async (dirPath) => {
642
717
  if (results.length >= maxResults)
@@ -648,62 +723,26 @@ export class ACECodeSearchService {
648
723
  break;
649
724
  const fullPath = path.join(dirPath, entry.name);
650
725
  if (entry.isDirectory()) {
651
- // Skip ignored directories
652
- if (entry.name === 'node_modules' ||
653
- entry.name === '.git' ||
654
- entry.name === 'dist' ||
655
- entry.name === 'build' ||
656
- entry.name === '__pycache__' ||
657
- entry.name === 'target' ||
658
- entry.name === '.next' ||
659
- entry.name === '.nuxt' ||
660
- entry.name === 'coverage' ||
661
- entry.name.startsWith('.')) {
726
+ // Use configurable exclusion check
727
+ if (shouldExcludeDirectory(entry.name, fullPath, this.basePath, this.customExcludes, this.regexCache)) {
662
728
  continue;
663
729
  }
664
730
  await searchInDirectory(fullPath);
665
731
  }
666
732
  else if (entry.isFile()) {
667
733
  // Filter by glob if specified
668
- if (globRegex && !globRegex.test(fullPath)) {
669
- continue;
734
+ if (globRegex) {
735
+ // Use relative path from basePath for glob matching
736
+ const relativePath = path
737
+ .relative(this.basePath, fullPath)
738
+ .replace(/\\/g, '/');
739
+ if (!globRegex.test(relativePath)) {
740
+ continue;
741
+ }
670
742
  }
671
- // Skip binary files
743
+ // Skip binary files (using Set for fast lookup)
672
744
  const ext = path.extname(entry.name).toLowerCase();
673
- const binaryExts = [
674
- '.jpg',
675
- '.jpeg',
676
- '.png',
677
- '.gif',
678
- '.bmp',
679
- '.ico',
680
- '.svg',
681
- '.pdf',
682
- '.zip',
683
- '.tar',
684
- '.gz',
685
- '.rar',
686
- '.7z',
687
- '.exe',
688
- '.dll',
689
- '.so',
690
- '.dylib',
691
- '.mp3',
692
- '.mp4',
693
- '.avi',
694
- '.mov',
695
- '.woff',
696
- '.woff2',
697
- '.ttf',
698
- '.eot',
699
- '.class',
700
- '.jar',
701
- '.war',
702
- '.o',
703
- '.a',
704
- '.lib',
705
- ];
706
- if (binaryExts.includes(ext)) {
745
+ if (binaryExts.has(ext)) {
707
746
  continue;
708
747
  }
709
748
  try {
@@ -754,10 +793,8 @@ export class ACECodeSearchService {
754
793
  try {
755
794
  const gitAvailable = await isCommandAvailable('git');
756
795
  if (gitAvailable) {
757
- const results = await this.gitGrepSearch(pattern, fileGlob, maxResults);
758
- if (results.length > 0 || !isRegex) {
759
- // git grep doesn't support all regex features,
760
- // fall back if pattern is complex regex and no results
796
+ const results = await this.gitGrepSearch(pattern, fileGlob, maxResults, isRegex);
797
+ if (results.length > 0) {
761
798
  return await this.sortResultsByRecency(results);
762
799
  }
763
800
  }
@@ -786,27 +823,32 @@ export class ACECodeSearchService {
786
823
  /**
787
824
  * Sort search results by file modification time (recent files first)
788
825
  * Files modified within last 24 hours are prioritized
826
+ * Uses parallel stat calls for better performance
789
827
  */
790
828
  async sortResultsByRecency(results) {
791
829
  if (results.length === 0)
792
830
  return results;
793
831
  const now = Date.now();
794
832
  const recentThreshold = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
795
- // Get file modification times
833
+ // Get unique file paths
834
+ const uniqueFiles = Array.from(new Set(results.map(r => r.filePath)));
835
+ // Fetch file modification times in parallel using Promise.allSettled
836
+ const statResults = await Promise.allSettled(uniqueFiles.map(async (filePath) => {
837
+ const fullPath = path.resolve(this.basePath, filePath);
838
+ const stats = await fs.stat(fullPath);
839
+ return { filePath, mtimeMs: stats.mtimeMs };
840
+ }));
841
+ // Build map of file modification times
796
842
  const fileModTimes = new Map();
797
- for (const result of results) {
798
- if (fileModTimes.has(result.filePath))
799
- continue;
800
- try {
801
- const fullPath = path.resolve(this.basePath, result.filePath);
802
- const stats = await fs.stat(fullPath);
803
- fileModTimes.set(result.filePath, stats.mtimeMs);
843
+ statResults.forEach((result, index) => {
844
+ if (result.status === 'fulfilled') {
845
+ fileModTimes.set(result.value.filePath, result.value.mtimeMs);
804
846
  }
805
- catch {
847
+ else {
806
848
  // If we can't get stats, treat as old file
807
- fileModTimes.set(result.filePath, 0);
849
+ fileModTimes.set(uniqueFiles[index], 0);
808
850
  }
809
- }
851
+ });
810
852
  // Sort results: recent files first, then by original order
811
853
  return results.sort((a, b) => {
812
854
  const aMtime = fileModTimes.get(a.filePath) || 0;
@@ -841,10 +883,10 @@ export class ACECodeSearchService {
841
883
  /**
842
884
  * Search with language-specific context (cross-reference search)
843
885
  */
844
- async semanticSearch(query, searchType = 'all', language, maxResults = 50) {
886
+ async semanticSearch(query, searchType = 'all', language, symbolType, maxResults = 50) {
845
887
  const startTime = Date.now();
846
888
  // Get symbol search results
847
- const symbolResults = await this.searchSymbols(query, undefined, language, maxResults);
889
+ const symbolResults = await this.searchSymbols(query, symbolType, language, maxResults);
848
890
  // Get reference results if needed
849
891
  let references = [];
850
892
  if (searchType === 'usage' || searchType === 'all') {
@@ -880,54 +922,6 @@ export class ACECodeSearchService {
880
922
  export const aceCodeSearchService = new ACECodeSearchService();
881
923
  // MCP Tool definitions for integration
882
924
  export const mcpTools = [
883
- {
884
- name: 'ace-search_symbols',
885
- description: 'ACE Code Search: Intelligent symbol search across the codebase. Finds functions, classes, variables, and other code symbols with fuzzy matching. Supports multiple programming languages (TypeScript, JavaScript, Python, Go, Rust, Java, C#). Returns precise file locations with line numbers and context.',
886
- inputSchema: {
887
- type: 'object',
888
- properties: {
889
- query: {
890
- type: 'string',
891
- description: 'Symbol name to search for (supports fuzzy matching, e.g., "gfc" can match "getFileContent")',
892
- },
893
- symbolType: {
894
- type: 'string',
895
- enum: [
896
- 'function',
897
- 'class',
898
- 'method',
899
- 'variable',
900
- 'constant',
901
- 'interface',
902
- 'type',
903
- 'enum',
904
- 'import',
905
- 'export',
906
- ],
907
- description: 'Filter by specific symbol type (optional)',
908
- },
909
- language: {
910
- type: 'string',
911
- enum: [
912
- 'typescript',
913
- 'javascript',
914
- 'python',
915
- 'go',
916
- 'rust',
917
- 'java',
918
- 'csharp',
919
- ],
920
- description: 'Filter by programming language (optional)',
921
- },
922
- maxResults: {
923
- type: 'number',
924
- description: 'Maximum number of results to return (default: 100)',
925
- default: 100,
926
- },
927
- },
928
- required: ['query'],
929
- },
930
- },
931
925
  {
932
926
  name: 'ace-find_definition',
933
927
  description: 'ACE Code Search: Find the definition of a symbol (Go to Definition). Locates where a function, class, or variable is defined in the codebase. Returns precise location with full signature and context.',
@@ -967,20 +961,36 @@ export const mcpTools = [
967
961
  },
968
962
  {
969
963
  name: 'ace-semantic_search',
970
- description: 'ACE Code Search: Advanced semantic search with context understanding. Searches for symbols with intelligent filtering by search type (definition, usage, implementation, all). Combines symbol search with cross-reference analysis.',
964
+ description: 'ACE Code Search: 智能符号搜索与语义分析。支持多种搜索模式:(1) definition - 查找符号定义(函数/类/接口);(2) usage - 查找符号引用位置;(3) implementation - 查找具体实现;(4) all - 综合搜索。支持模糊匹配、按语言和符号类型过滤。💡 提示:如果只需要查看单个文件的符号大纲,使用 ace-file_outline 更快。',
971
965
  inputSchema: {
972
966
  type: 'object',
973
967
  properties: {
974
968
  query: {
975
969
  type: 'string',
976
- description: 'Search query (symbol name or pattern)',
970
+ description: '搜索查询 (符号名称或模式,支持模糊匹配如 "gfc" 匹配 "getFileContent")',
977
971
  },
978
972
  searchType: {
979
973
  type: 'string',
980
974
  enum: ['definition', 'usage', 'implementation', 'all'],
981
- description: 'Type of search: definition (find declarations), usage (find usages), implementation (find implementations), all (comprehensive search)',
975
+ description: '搜索类型:definition (查找声明)usage (查找使用)implementation (查找实现)all (全面搜索)',
982
976
  default: 'all',
983
977
  },
978
+ symbolType: {
979
+ type: 'string',
980
+ enum: [
981
+ 'function',
982
+ 'class',
983
+ 'method',
984
+ 'variable',
985
+ 'constant',
986
+ 'interface',
987
+ 'type',
988
+ 'enum',
989
+ 'import',
990
+ 'export',
991
+ ],
992
+ description: '可选:按符号类型筛选 (function, class, variable等)',
993
+ },
984
994
  language: {
985
995
  type: 'string',
986
996
  enum: [
@@ -992,11 +1002,11 @@ export const mcpTools = [
992
1002
  'java',
993
1003
  'csharp',
994
1004
  ],
995
- description: 'Filter by programming language (optional)',
1005
+ description: '可选:按编程语言筛选',
996
1006
  },
997
1007
  maxResults: {
998
1008
  type: 'number',
999
- description: 'Maximum number of results to return (default: 50)',
1009
+ description: '最大返回结果数 (默认: 50)',
1000
1010
  default: 50,
1001
1011
  },
1002
1012
  },
@@ -1019,7 +1029,7 @@ export const mcpTools = [
1019
1029
  },
1020
1030
  {
1021
1031
  name: 'ace-text_search',
1022
- description: 'ACE Code Search: Fast text search across the entire codebase using Node.js built-in features (no external dependencies required). Search for exact patterns or regex across all files. Useful for finding strings, comments, TODOs, or any text patterns. Supports glob filtering.',
1032
+ description: 'ACE Code Search: Literal text/regex pattern matching (grep-style search). Best for finding exact strings: TODOs, comments, log messages, error strings, string constants. NOT recommended for code understanding or exploring functionality - use semantic search tools for that. Use when you know the exact text pattern you are looking for.',
1023
1033
  inputSchema: {
1024
1034
  type: 'object',
1025
1035
  properties: {
@@ -12,7 +12,7 @@ declare class CodebaseSearchService {
12
12
  */
13
13
  private cosineSimilarity;
14
14
  /**
15
- * Search codebase using semantic similarity
15
+ * Search codebase using semantic similarity with retry logic
16
16
  */
17
17
  search(query: string, topN?: number): Promise<any>;
18
18
  }