@su-record/vibe 0.1.2 → 0.1.4

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 (59) hide show
  1. package/README.md +13 -6
  2. package/bin/vibe +20 -2
  3. package/package.json +5 -6
  4. package/scripts/install-mcp.js +31 -5
  5. package/mcp/dist/__tests__/complexity.test.js +0 -126
  6. package/mcp/dist/__tests__/memory.test.js +0 -120
  7. package/mcp/dist/__tests__/python-dart-complexity.test.js +0 -146
  8. package/mcp/dist/index.js +0 -230
  9. package/mcp/dist/lib/ContextCompressor.js +0 -305
  10. package/mcp/dist/lib/MemoryManager.js +0 -334
  11. package/mcp/dist/lib/ProjectCache.js +0 -126
  12. package/mcp/dist/lib/PythonParser.js +0 -241
  13. package/mcp/dist/tools/browser/browserPool.js +0 -76
  14. package/mcp/dist/tools/browser/browserUtils.js +0 -135
  15. package/mcp/dist/tools/browser/inspectNetworkRequests.js +0 -140
  16. package/mcp/dist/tools/browser/monitorConsoleLogs.js +0 -97
  17. package/mcp/dist/tools/convention/analyzeComplexity.js +0 -248
  18. package/mcp/dist/tools/convention/applyQualityRules.js +0 -102
  19. package/mcp/dist/tools/convention/checkCouplingCohesion.js +0 -233
  20. package/mcp/dist/tools/convention/complexityMetrics.js +0 -133
  21. package/mcp/dist/tools/convention/dartComplexity.js +0 -117
  22. package/mcp/dist/tools/convention/getCodingGuide.js +0 -64
  23. package/mcp/dist/tools/convention/languageDetector.js +0 -50
  24. package/mcp/dist/tools/convention/pythonComplexity.js +0 -109
  25. package/mcp/dist/tools/convention/suggestImprovements.js +0 -257
  26. package/mcp/dist/tools/convention/validateCodeQuality.js +0 -177
  27. package/mcp/dist/tools/memory/autoSaveContext.js +0 -79
  28. package/mcp/dist/tools/memory/database.js +0 -123
  29. package/mcp/dist/tools/memory/deleteMemory.js +0 -39
  30. package/mcp/dist/tools/memory/listMemories.js +0 -38
  31. package/mcp/dist/tools/memory/memoryConfig.js +0 -27
  32. package/mcp/dist/tools/memory/memorySQLite.js +0 -138
  33. package/mcp/dist/tools/memory/memoryUtils.js +0 -34
  34. package/mcp/dist/tools/memory/migrate.js +0 -113
  35. package/mcp/dist/tools/memory/prioritizeMemory.js +0 -109
  36. package/mcp/dist/tools/memory/recallMemory.js +0 -40
  37. package/mcp/dist/tools/memory/restoreSessionContext.js +0 -69
  38. package/mcp/dist/tools/memory/saveMemory.js +0 -34
  39. package/mcp/dist/tools/memory/searchMemories.js +0 -37
  40. package/mcp/dist/tools/memory/startSession.js +0 -100
  41. package/mcp/dist/tools/memory/updateMemory.js +0 -46
  42. package/mcp/dist/tools/planning/analyzeRequirements.js +0 -166
  43. package/mcp/dist/tools/planning/createUserStories.js +0 -119
  44. package/mcp/dist/tools/planning/featureRoadmap.js +0 -202
  45. package/mcp/dist/tools/planning/generatePrd.js +0 -156
  46. package/mcp/dist/tools/prompt/analyzePrompt.js +0 -145
  47. package/mcp/dist/tools/prompt/enhancePrompt.js +0 -105
  48. package/mcp/dist/tools/semantic/findReferences.js +0 -195
  49. package/mcp/dist/tools/semantic/findSymbol.js +0 -200
  50. package/mcp/dist/tools/thinking/analyzeProblem.js +0 -50
  51. package/mcp/dist/tools/thinking/breakDownProblem.js +0 -140
  52. package/mcp/dist/tools/thinking/createThinkingChain.js +0 -39
  53. package/mcp/dist/tools/thinking/formatAsPlan.js +0 -73
  54. package/mcp/dist/tools/thinking/stepByStepAnalysis.js +0 -58
  55. package/mcp/dist/tools/thinking/thinkAloudProcess.js +0 -75
  56. package/mcp/dist/tools/time/getCurrentTime.js +0 -61
  57. package/mcp/dist/tools/ui/previewUiAscii.js +0 -232
  58. package/mcp/dist/types/tool.js +0 -2
  59. package/mcp/package.json +0 -53
@@ -1,156 +0,0 @@
1
- // Planning tool - completely independent
2
- export const generatePrdDefinition = {
3
- name: 'generate_prd',
4
- description: 'PRD|요구사항 문서|제품 요구사항|product requirements|requirements document|spec document - Generate Product Requirements Document',
5
- inputSchema: {
6
- type: 'object',
7
- properties: {
8
- productName: { type: 'string', description: 'Name of the product/feature' },
9
- productVision: { type: 'string', description: 'High-level vision and goals' },
10
- targetAudience: { type: 'string', description: 'Target users and stakeholders' },
11
- businessObjectives: { type: 'string', description: 'Business goals and success metrics' },
12
- functionalRequirements: { type: 'string', description: 'Key features and functionality' },
13
- constraints: { type: 'string', description: 'Technical/business constraints' }
14
- },
15
- required: ['productName', 'productVision']
16
- },
17
- annotations: {
18
- title: 'Generate PRD',
19
- audience: ['user', 'assistant']
20
- }
21
- };
22
- export async function generatePrd(args) {
23
- const { productName, productVision, targetAudience = 'General users', businessObjectives = 'Improve user experience and business value', functionalRequirements = 'Core functionality to be defined', constraints = 'Standard technical and budget constraints' } = args;
24
- const prd = {
25
- action: 'generate_prd',
26
- product: productName,
27
- document: {
28
- title: `Product Requirements Document: ${productName}`,
29
- version: '1.0',
30
- date: new Date().toISOString().split('T')[0],
31
- sections: {
32
- executiveSummary: {
33
- title: 'Executive Summary',
34
- content: `${productName} is designed to ${productVision}. This document outlines the requirements, scope, and implementation strategy for delivering value to ${targetAudience}.`
35
- },
36
- productOverview: {
37
- title: 'Product Overview',
38
- vision: productVision,
39
- objectives: businessObjectives,
40
- targetUsers: targetAudience,
41
- successMetrics: [
42
- 'User adoption rate',
43
- 'Feature usage metrics',
44
- 'User satisfaction score',
45
- 'Business impact measurement'
46
- ]
47
- },
48
- functionalRequirements: {
49
- title: 'Functional Requirements',
50
- description: functionalRequirements,
51
- coreFeatures: [
52
- 'User authentication and management',
53
- 'Core functionality implementation',
54
- 'Data processing and storage',
55
- 'User interface and experience',
56
- 'Integration capabilities'
57
- ],
58
- userFlows: [
59
- 'User onboarding process',
60
- 'Main feature usage flow',
61
- 'Error handling and recovery',
62
- 'Administrative functions'
63
- ]
64
- },
65
- nonFunctionalRequirements: {
66
- title: 'Non-Functional Requirements',
67
- performance: 'Fast response times (<2s), high availability (99.9%)',
68
- security: 'Data encryption, secure authentication, privacy compliance',
69
- scalability: 'Support growing user base and data volume',
70
- usability: 'Intuitive interface, accessibility standards',
71
- compatibility: 'Cross-platform support, browser compatibility'
72
- },
73
- constraints: {
74
- title: 'Constraints and Assumptions',
75
- technical: constraints,
76
- timeline: 'Development timeline to be defined based on scope',
77
- budget: 'Budget allocation for development and infrastructure',
78
- resources: 'Team capacity and skill requirements'
79
- },
80
- implementationPlan: {
81
- title: 'Implementation Strategy',
82
- phases: [
83
- 'Phase 1: Core functionality development',
84
- 'Phase 2: Advanced features and integrations',
85
- 'Phase 3: Performance optimization and scaling',
86
- 'Phase 4: Launch and post-launch improvements'
87
- ],
88
- riskMitigation: [
89
- 'Technical risk assessment and mitigation',
90
- 'Resource and timeline risk management',
91
- 'Market and user acceptance risks',
92
- 'Compliance and security considerations'
93
- ]
94
- }
95
- }
96
- },
97
- recommendations: [
98
- 'Conduct user research to validate assumptions',
99
- 'Create detailed wireframes and prototypes',
100
- 'Define detailed acceptance criteria for each feature',
101
- 'Set up monitoring and analytics for success metrics',
102
- 'Plan for iterative development and feedback loops'
103
- ],
104
- status: 'success'
105
- };
106
- const formattedPrd = `# ${prd.document.title}
107
-
108
- **Version:** ${prd.document.version}
109
- **Date:** ${prd.document.date}
110
-
111
- ## ${prd.document.sections.executiveSummary.title}
112
- ${prd.document.sections.executiveSummary.content}
113
-
114
- ## ${prd.document.sections.productOverview.title}
115
- **Vision:** ${prd.document.sections.productOverview.vision}
116
- **Objectives:** ${prd.document.sections.productOverview.objectives}
117
- **Target Users:** ${prd.document.sections.productOverview.targetUsers}
118
-
119
- **Success Metrics:**
120
- ${prd.document.sections.productOverview.successMetrics.map(metric => `- ${metric}`).join('\n')}
121
-
122
- ## ${prd.document.sections.functionalRequirements.title}
123
- ${prd.document.sections.functionalRequirements.description}
124
-
125
- **Core Features:**
126
- ${prd.document.sections.functionalRequirements.coreFeatures.map(feature => `- ${feature}`).join('\n')}
127
-
128
- **User Flows:**
129
- ${prd.document.sections.functionalRequirements.userFlows.map(flow => `- ${flow}`).join('\n')}
130
-
131
- ## ${prd.document.sections.nonFunctionalRequirements.title}
132
- - **Performance:** ${prd.document.sections.nonFunctionalRequirements.performance}
133
- - **Security:** ${prd.document.sections.nonFunctionalRequirements.security}
134
- - **Scalability:** ${prd.document.sections.nonFunctionalRequirements.scalability}
135
- - **Usability:** ${prd.document.sections.nonFunctionalRequirements.usability}
136
- - **Compatibility:** ${prd.document.sections.nonFunctionalRequirements.compatibility}
137
-
138
- ## ${prd.document.sections.constraints.title}
139
- - **Technical:** ${prd.document.sections.constraints.technical}
140
- - **Timeline:** ${prd.document.sections.constraints.timeline}
141
- - **Budget:** ${prd.document.sections.constraints.budget}
142
- - **Resources:** ${prd.document.sections.constraints.resources}
143
-
144
- ## ${prd.document.sections.implementationPlan.title}
145
- **Development Phases:**
146
- ${prd.document.sections.implementationPlan.phases.map(phase => `- ${phase}`).join('\n')}
147
-
148
- **Risk Mitigation:**
149
- ${prd.document.sections.implementationPlan.riskMitigation.map(risk => `- ${risk}`).join('\n')}
150
-
151
- ## Recommendations
152
- ${prd.recommendations.map(rec => `- ${rec}`).join('\n')}`;
153
- return {
154
- content: [{ type: 'text', text: formattedPrd }]
155
- };
156
- }
@@ -1,145 +0,0 @@
1
- // Prompt analysis tool - completely independent
2
- export const analyzePromptDefinition = {
3
- name: 'analyze_prompt',
4
- description: '프롬프트 분석|평가|점수|얼마나 좋은지|analyze prompt|rate this|score|how good|prompt quality - Analyze prompt quality',
5
- inputSchema: {
6
- type: 'object',
7
- properties: {
8
- prompt: { type: 'string', description: 'Prompt to analyze' },
9
- criteria: {
10
- type: 'array',
11
- items: { type: 'string' },
12
- description: 'Specific criteria to evaluate (default: all)'
13
- }
14
- },
15
- required: ['prompt']
16
- },
17
- annotations: {
18
- title: 'Analyze Prompt',
19
- audience: ['user', 'assistant']
20
- }
21
- };
22
- export async function analyzePrompt(args) {
23
- const { prompt, criteria = ['clarity', 'specificity', 'context', 'structure'] } = args;
24
- // Initialize scores with explicit types
25
- const scores = {};
26
- const feedback = {};
27
- // Analyze clarity (0-10)
28
- if (criteria.includes('clarity')) {
29
- let clarityScore = 5.0;
30
- const clarityFeedback = [];
31
- if (prompt.length < 20) {
32
- clarityScore -= 2.0;
33
- clarityFeedback.push('프롬프트가 너무 짧습니다');
34
- }
35
- if (prompt.includes('?') || /\b(해주세요|부탁|요청)\b/.test(prompt)) {
36
- clarityScore += 2.0;
37
- clarityFeedback.push('명확한 요청 형태 ✓');
38
- }
39
- if (prompt.split(',').length > 5 || prompt.split('.').length > 10) {
40
- clarityScore -= 1.0;
41
- clarityFeedback.push('문장이 너무 복잡합니다');
42
- }
43
- scores.clarity = Math.max(0, Math.min(10, clarityScore));
44
- feedback.clarity = clarityFeedback;
45
- }
46
- // Analyze specificity (0-10)
47
- if (criteria.includes('specificity')) {
48
- let specificityScore = 5.0;
49
- const specificityFeedback = [];
50
- const specificKeywords = ['구체적', '정확히', '예시', '예를 들어'];
51
- const hasSpecificWords = specificKeywords.some(word => prompt.includes(word));
52
- if (hasSpecificWords) {
53
- specificityScore += 2.0;
54
- specificityFeedback.push('구체적인 표현 사용 ✓');
55
- }
56
- const techTerms = /\b(JavaScript|Python|React|Node\.js|API|데이터베이스)\b/i;
57
- if (techTerms.test(prompt)) {
58
- specificityScore += 2.0;
59
- specificityFeedback.push('기술 용어 포함 ✓');
60
- }
61
- if (!prompt.match(/\d+/) && prompt.length > 50) {
62
- specificityScore -= 1.0;
63
- specificityFeedback.push('수치나 구체적 데이터 부족');
64
- }
65
- scores.specificity = Math.max(0, Math.min(10, specificityScore));
66
- feedback.specificity = specificityFeedback;
67
- }
68
- // Analyze context (0-10)
69
- if (criteria.includes('context')) {
70
- let contextScore = 5.0;
71
- const contextFeedback = [];
72
- const contextKeywords = ['배경', '목적', '이유', '상황', '현재', '문제'];
73
- const contextCount = contextKeywords.filter(word => prompt.includes(word)).length;
74
- contextScore += contextCount * 1.5;
75
- if (contextCount > 0) {
76
- contextFeedback.push(`배경 정보 포함 (${contextCount}개 키워드) ✓`);
77
- }
78
- else {
79
- contextFeedback.push('배경 정보 부족');
80
- }
81
- if (prompt.split('\n').length > 2) {
82
- contextScore += 1.0;
83
- contextFeedback.push('구조화된 설명 ✓');
84
- }
85
- scores.context = Math.max(0, Math.min(10, contextScore));
86
- feedback.context = contextFeedback;
87
- }
88
- // Analyze structure (0-10)
89
- if (criteria.includes('structure')) {
90
- let structureScore = 5.0;
91
- const structureFeedback = [];
92
- if (prompt.includes('\n')) {
93
- structureScore += 2.0;
94
- structureFeedback.push('줄바꿈 사용 ✓');
95
- }
96
- if (/[1-9]\.|[-•]/.test(prompt)) {
97
- structureScore += 2.0;
98
- structureFeedback.push('목록 형식 사용 ✓');
99
- }
100
- if (prompt.includes('**') || prompt.includes('##')) {
101
- structureScore += 1.0;
102
- structureFeedback.push('마크다운 형식 사용 ✓');
103
- }
104
- scores.structure = Math.max(0, Math.min(10, structureScore));
105
- feedback.structure = structureFeedback;
106
- }
107
- // Calculate total score
108
- const totalScore = Object.values(scores).reduce((a, b) => a + b, 0) / Object.keys(scores).length;
109
- // Generate recommendations
110
- const recommendations = [];
111
- if (scores.clarity < 6) {
112
- recommendations.push('💡 질문이나 요청을 더 명확하게 표현하세요');
113
- }
114
- if (scores.specificity < 6) {
115
- recommendations.push('💡 구체적인 예시나 기술 사양을 추가하세요');
116
- }
117
- if (scores.context < 6) {
118
- recommendations.push('💡 작업의 배경과 목적을 설명하세요');
119
- }
120
- if (scores.structure < 6) {
121
- recommendations.push('💡 번호나 불릿 포인트로 구조화하세요');
122
- }
123
- // Identify strengths and weaknesses
124
- const strengths = Object.entries(scores)
125
- .filter(([_, score]) => score >= 7)
126
- .map(([category, score]) => `✨ ${category}: 우수함 (${score.toFixed(1)}/10)`);
127
- const weaknesses = Object.entries(scores)
128
- .filter(([_, score]) => score < 5)
129
- .map(([category, score]) => `⚠️ ${category}: 개선 필요 (${score.toFixed(1)}/10)`);
130
- const analysis = {
131
- action: 'analyze_prompt',
132
- prompt,
133
- totalScore: parseFloat(totalScore.toFixed(1)),
134
- scores: Object.fromEntries(Object.entries(scores).map(([k, v]) => [k, parseFloat(v.toFixed(1))])),
135
- feedback,
136
- strengths,
137
- weaknesses,
138
- recommendations,
139
- grade: totalScore >= 8 ? 'A' : totalScore >= 6 ? 'B' : totalScore >= 4 ? 'C' : 'D',
140
- status: 'success'
141
- };
142
- return {
143
- content: [{ type: 'text', text: `Score: ${analysis.totalScore}/10 (Grade: ${analysis.grade})\n\nScores:\n${Object.entries(analysis.scores).map(([k, v]) => `- ${k}: ${v}/10`).join('\n')}\n\nStrengths:\n${analysis.strengths.length > 0 ? analysis.strengths.join('\n') : 'None identified'}\n\nWeaknesses:\n${analysis.weaknesses.length > 0 ? analysis.weaknesses.join('\n') : 'None identified'}\n\nRecommendations:\n${analysis.recommendations.map(r => `- ${r}`).join('\n')}` }]
144
- };
145
- }
@@ -1,105 +0,0 @@
1
- // Prompt enhancement tool - completely independent
2
- export const enhancePromptDefinition = {
3
- name: 'enhance_prompt',
4
- description: '구체적으로|자세히|명확하게|더 구체적으로|be specific|more detail|clarify|elaborate|vague - Transform vague requests',
5
- inputSchema: {
6
- type: 'object',
7
- properties: {
8
- prompt: { type: 'string', description: 'Original prompt to enhance' },
9
- context: { type: 'string', description: 'Additional context or project information' },
10
- enhancement_type: {
11
- type: 'string',
12
- enum: ['clarity', 'specificity', 'context', 'all'],
13
- description: 'Type of enhancement (default: all)'
14
- }
15
- },
16
- required: ['prompt']
17
- },
18
- annotations: {
19
- title: 'Enhance Prompt',
20
- audience: ['user', 'assistant']
21
- }
22
- };
23
- export async function enhancePrompt(args) {
24
- const { prompt, context = '', enhancement_type = 'all' } = args;
25
- // Enhancement logic
26
- const enhancements = {
27
- clarity: [],
28
- specificity: [],
29
- context: [],
30
- structure: []
31
- };
32
- // Analyze original prompt
33
- const promptLength = prompt.length;
34
- const hasQuestion = prompt.includes('?');
35
- const hasSpecificTerms = /\b(구현|개발|수정|분석|디버그|리팩토링)\b/i.test(prompt);
36
- // Apply enhancements based on type
37
- if (enhancement_type === 'clarity' || enhancement_type === 'all') {
38
- if (promptLength < 20) {
39
- enhancements.clarity.push('더 구체적인 설명 추가');
40
- }
41
- if (!hasQuestion && !hasSpecificTerms) {
42
- enhancements.clarity.push('명확한 요청이나 질문 형태로 변환');
43
- }
44
- }
45
- if (enhancement_type === 'specificity' || enhancement_type === 'all') {
46
- if (!prompt.match(/\b(언어|프레임워크|라이브러리|버전)\b/)) {
47
- enhancements.specificity.push('기술 스택 명시');
48
- }
49
- if (!prompt.match(/\b(입력|출력|결과|형식)\b/)) {
50
- enhancements.specificity.push('예상 입출력 정의');
51
- }
52
- }
53
- if (enhancement_type === 'context' || enhancement_type === 'all') {
54
- if (!prompt.match(/\b(목적|이유|배경|상황)\b/)) {
55
- enhancements.context.push('작업 목적과 배경 추가');
56
- }
57
- if (context) {
58
- enhancements.context.push('제공된 컨텍스트 통합');
59
- }
60
- }
61
- // Generate enhanced prompt
62
- let enhancedPrompt = prompt;
63
- // Build enhanced version
64
- const components = [];
65
- // Add objective
66
- components.push(`**목표**: ${prompt}`);
67
- // Add context if provided
68
- if (context) {
69
- components.push(`**배경**: ${context}`);
70
- }
71
- // Add specific requirements based on analysis
72
- const requirements = [];
73
- if (enhancements.specificity.includes('기술 스택 명시')) {
74
- requirements.push('- 사용할 언어/프레임워크를 명시해주세요');
75
- }
76
- if (enhancements.specificity.includes('예상 입출력 정의')) {
77
- requirements.push('- 예상되는 입력과 출력 형식을 설명해주세요');
78
- }
79
- if (requirements.length > 0) {
80
- components.push(`**요구사항**:\n${requirements.join('\n')}`);
81
- }
82
- // Add quality considerations
83
- const quality = [
84
- '- 에러 처리 포함',
85
- '- 테스트 가능한 구조',
86
- '- 확장 가능한 설계'
87
- ];
88
- components.push(`**품질 기준**:\n${quality.join('\n')}`);
89
- enhancedPrompt = components.join('\n\n');
90
- const result = {
91
- action: 'enhance_prompt',
92
- original: prompt,
93
- enhanced: enhancedPrompt,
94
- enhancements,
95
- improvements: [
96
- enhancements.clarity.length > 0 ? `명확성 개선 (${enhancements.clarity.length}개)` : null,
97
- enhancements.specificity.length > 0 ? `구체성 추가 (${enhancements.specificity.length}개)` : null,
98
- enhancements.context.length > 0 ? `맥락 보강 (${enhancements.context.length}개)` : null
99
- ].filter(Boolean),
100
- status: 'success'
101
- };
102
- return {
103
- content: [{ type: 'text', text: `Original: ${prompt}\n\nEnhanced:\n${enhancedPrompt}\n\nImprovements: ${result.improvements.join(', ')}` }]
104
- };
105
- }
@@ -1,195 +0,0 @@
1
- // Semantic code analysis tool - Find References (v1.3)
2
- // With ProjectCache for 25x performance improvement
3
- import { Node } from 'ts-morph';
4
- import * as path from 'path';
5
- import { ProjectCache } from '../../lib/ProjectCache.js';
6
- import { readFile } from 'fs/promises';
7
- export const findReferencesDefinition = {
8
- name: 'find_references',
9
- description: '어디서 쓰|참조|사용처|find usage|references|where used - Find symbol references',
10
- inputSchema: {
11
- type: 'object',
12
- properties: {
13
- symbolName: { type: 'string', description: 'Name of the symbol to find references for' },
14
- filePath: { type: 'string', description: 'File path where the symbol is defined' },
15
- line: { type: 'number', description: 'Line number of the symbol definition' },
16
- projectPath: { type: 'string', description: 'Project directory path' }
17
- },
18
- required: ['symbolName', 'projectPath']
19
- },
20
- annotations: {
21
- title: 'Find References',
22
- audience: ['user', 'assistant']
23
- }
24
- };
25
- export async function findReferences(args) {
26
- const { symbolName, filePath, line, projectPath } = args;
27
- try {
28
- // Use cached project for performance
29
- const projectCache = ProjectCache.getInstance();
30
- const project = projectCache.getOrCreate(projectPath);
31
- const allReferences = [];
32
- // Check for Python files
33
- const glob = await import('glob');
34
- const pythonFiles = glob.globSync(path.join(projectPath, '**/*.py'), {
35
- ignore: ['**/node_modules/**', '**/.git/**', '**/venv/**', '**/__pycache__/**']
36
- });
37
- // Parse Python files for references
38
- for (const pyFile of pythonFiles) {
39
- try {
40
- const content = await readFile(pyFile, 'utf-8');
41
- const lines = content.split('\n');
42
- lines.forEach((line, index) => {
43
- if (line.includes(symbolName)) {
44
- const column = line.indexOf(symbolName);
45
- allReferences.push({
46
- filePath: pyFile,
47
- line: index + 1,
48
- column: column,
49
- text: line.trim().substring(0, 100),
50
- isDefinition: /^(def|class)\s/.test(line.trim())
51
- });
52
- }
53
- });
54
- }
55
- catch (error) {
56
- console.error(`Error parsing Python file ${pyFile}:`, error);
57
- }
58
- }
59
- // If specific file and line provided, use precise reference finding
60
- if (filePath && line) {
61
- const sourceFile = project.getSourceFile(filePath);
62
- if (sourceFile) {
63
- const position = sourceFile.compilerNode.getPositionOfLineAndCharacter(line - 1, 0);
64
- const node = sourceFile.getDescendantAtPos(position);
65
- if (node) {
66
- const symbol = node.getSymbol();
67
- if (symbol) {
68
- const references = project.getLanguageService().findReferencesAtPosition(sourceFile, position);
69
- if (references) {
70
- for (const ref of references) {
71
- for (const reference of ref.getReferences()) {
72
- const refSourceFile = reference.getSourceFile();
73
- const refNode = reference.getNode();
74
- const start = refNode.getStartLinePos();
75
- const pos = refSourceFile.getLineAndColumnAtPos(start);
76
- allReferences.push({
77
- filePath: refSourceFile.getFilePath(),
78
- line: pos.line,
79
- column: pos.column,
80
- text: refNode.getParent()?.getText().substring(0, 100) || refNode.getText(),
81
- isDefinition: reference.isDefinition() || false
82
- });
83
- }
84
- }
85
- }
86
- }
87
- }
88
- }
89
- }
90
- else {
91
- // Fallback: search by name across all files
92
- for (const sourceFile of project.getSourceFiles()) {
93
- const filePath = sourceFile.getFilePath();
94
- // Skip node_modules and other irrelevant paths
95
- if (filePath.includes('node_modules') || filePath.includes('.git')) {
96
- continue;
97
- }
98
- // Find all identifiers matching the symbol name
99
- sourceFile.forEachDescendant((node) => {
100
- if (Node.isIdentifier(node) && node.getText() === symbolName) {
101
- const start = node.getStartLinePos();
102
- const pos = sourceFile.getLineAndColumnAtPos(start);
103
- const parent = node.getParent();
104
- // Determine if this is a definition
105
- const isDefinition = isSymbolDefinition(node);
106
- allReferences.push({
107
- filePath: filePath,
108
- line: pos.line,
109
- column: pos.column,
110
- text: parent?.getText().substring(0, 100) || node.getText(),
111
- isDefinition
112
- });
113
- }
114
- });
115
- }
116
- }
117
- const definitions = allReferences.filter(r => r.isDefinition);
118
- const usages = allReferences.filter(r => !r.isDefinition);
119
- return {
120
- content: [{
121
- type: 'text',
122
- text: `Found ${allReferences.length} references (${definitions.length} defs, ${usages.length} uses):\n${allReferences.slice(0, 20).map(r => `${r.isDefinition ? 'DEF' : 'USE'}: ${r.filePath}:${r.line}`).join('\n')}`
123
- }]
124
- };
125
- }
126
- catch (error) {
127
- return {
128
- content: [{
129
- type: 'text',
130
- text: `Error finding references: ${error instanceof Error ? error.message : 'Unknown error'}`
131
- }]
132
- };
133
- }
134
- }
135
- function isSymbolDefinition(node) {
136
- const parent = node.getParent();
137
- if (!parent)
138
- return false;
139
- // Check if this is a declaration
140
- return Node.isFunctionDeclaration(parent) ||
141
- Node.isClassDeclaration(parent) ||
142
- Node.isInterfaceDeclaration(parent) ||
143
- Node.isTypeAliasDeclaration(parent) ||
144
- Node.isVariableDeclaration(parent) ||
145
- Node.isMethodDeclaration(parent) ||
146
- Node.isPropertyDeclaration(parent) ||
147
- Node.isParameterDeclaration(parent);
148
- }
149
- function groupReferencesByFile(references) {
150
- const grouped = {};
151
- for (const ref of references) {
152
- if (!grouped[ref.filePath]) {
153
- grouped[ref.filePath] = [];
154
- }
155
- grouped[ref.filePath].push(ref);
156
- }
157
- // Sort references within each file by line number
158
- for (const filePath in grouped) {
159
- grouped[filePath].sort((a, b) => a.line - b.line);
160
- }
161
- return grouped;
162
- }
163
- function formatReferenceResults(result) {
164
- let output = `# Reference Search Results\n\n`;
165
- output += `**Symbol:** ${result.symbol}\n`;
166
- output += `**Total References:** ${result.totalReferences}\n`;
167
- output += `**Files:** ${result.filesCount}\n`;
168
- output += `**Definitions:** ${result.definitions.length}\n`;
169
- output += `**Usages:** ${result.usages.length}\n\n`;
170
- if (result.totalReferences === 0) {
171
- output += `No references found for "${result.symbol}".\n`;
172
- return output;
173
- }
174
- // Show definitions first
175
- if (result.definitions.length > 0) {
176
- output += `## Definitions\n\n`;
177
- result.definitions.forEach((def, index) => {
178
- output += `${index + 1}. **${def.filePath}:${def.line}:${def.column}**\n`;
179
- output += ` \`\`\`typescript\n ${def.text}\n \`\`\`\n\n`;
180
- });
181
- }
182
- // Show usages grouped by file
183
- output += `## Usages by File\n\n`;
184
- for (const [filePath, refs] of Object.entries(result.references)) {
185
- const usages = refs.filter(r => !r.isDefinition);
186
- if (usages.length === 0)
187
- continue;
188
- output += `### ${filePath} (${usages.length} usages)\n\n`;
189
- usages.forEach((ref) => {
190
- output += `- **Line ${ref.line}:** \`${ref.text.substring(0, 60)}...\`\n`;
191
- });
192
- output += `\n`;
193
- }
194
- return output;
195
- }