octocode-mcp 1.1.0 → 2.2.0
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.
- package/build/index.js +3496 -769
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -14,7 +14,6 @@ const TOOL_NAMES = {
|
|
|
14
14
|
GITHUB_SEARCH_COMMITS: 'github_search_commits',
|
|
15
15
|
GITHUB_SEARCH_ISSUES: 'github_search_issues',
|
|
16
16
|
GITHUB_SEARCH_PULL_REQUESTS: 'github_search_pull_requests',
|
|
17
|
-
GITHUB_SEARCH_DISCUSSIONS: 'github_search_discussions',
|
|
18
17
|
GITHUB_SEARCH_TOPICS: 'github_search_topics',
|
|
19
18
|
GITHUB_SEARCH_USERS: 'github_search_users',
|
|
20
19
|
// GitHub Repository API (/repos/*)
|
|
@@ -23,180 +22,447 @@ const TOOL_NAMES = {
|
|
|
23
22
|
GITHUB_GET_FILE_CONTENT: 'github_get_file_content',
|
|
24
23
|
// GitHub Users API (/user/*)
|
|
25
24
|
GITHUB_GET_USER_ORGS: 'github_get_user_organizations',
|
|
26
|
-
//
|
|
25
|
+
// System & API Status
|
|
26
|
+
API_STATUS_CHECK: 'api_status_check',
|
|
27
|
+
// npm Registry API - Comprehensive
|
|
27
28
|
NPM_SEARCH_PACKAGES: 'npm_search_packages',
|
|
28
29
|
NPM_GET_PACKAGE: 'npm_get_package',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
**
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
**
|
|
30
|
+
NPM_ANALYZE_DEPENDENCIES: 'npm_analyze_dependencies',
|
|
31
|
+
// npm Registry API - Focused (minimal token usage)
|
|
32
|
+
NPM_GET_REPOSITORY: 'npm_get_repository',
|
|
33
|
+
NPM_GET_DEPENDENCIES: 'npm_get_dependencies',
|
|
34
|
+
NPM_GET_BUGS: 'npm_get_bugs',
|
|
35
|
+
NPM_GET_README: 'npm_get_readme',
|
|
36
|
+
NPM_GET_VERSIONS: 'npm_get_versions',
|
|
37
|
+
NPM_GET_AUTHOR: 'npm_get_author',
|
|
38
|
+
NPM_GET_LICENSE: 'npm_get_license',
|
|
39
|
+
NPM_GET_HOMEPAGE: 'npm_get_homepage',
|
|
40
|
+
NPM_GET_ID: 'npm_get_id',
|
|
41
|
+
NPM_GET_RELEASES: 'npm_get_releases',
|
|
42
|
+
NPM_GET_ENGINES: 'npm_get_engines',
|
|
43
|
+
NPM_GET_EXPORTS: 'npm_get_exports'};
|
|
44
|
+
|
|
45
|
+
const PROMPT_SYSTEM_PROMPT = `**Universal Research Intelligence Engine** - Comprehensive discovery, analysis, and insights across all domains of knowledge.
|
|
46
|
+
|
|
47
|
+
## 🛠️ CRITICAL: API STATUS VERIFICATION FIRST
|
|
48
|
+
|
|
49
|
+
**MANDATORY FIRST STEP:** Always begin research sessions with ${TOOL_NAMES.API_STATUS_CHECK} to:
|
|
50
|
+
- Verify GitHub CLI authentication (gh auth status)
|
|
51
|
+
- Confirm NPM registry connectivity (npm ping)
|
|
52
|
+
- Analyze real-time GitHub API rate limits across all endpoints
|
|
53
|
+
- Get intelligent research strategy recommendations based on current API capacity
|
|
54
|
+
|
|
55
|
+
**RESEARCH STRATEGY ADAPTATION:**
|
|
56
|
+
- **READY Status**: Proceed with comprehensive multi-tool research
|
|
57
|
+
- **LIMITED Status**: Use targeted searches, avoid broad exploration
|
|
58
|
+
- **NOT_READY Status**: Guide user through authentication/connectivity setup
|
|
59
|
+
|
|
60
|
+
**API-AWARE RESEARCH PLANNING:**
|
|
61
|
+
- Code Search < 5 remaining → Use repository browsing instead
|
|
62
|
+
- Search API < 20 remaining → Focus on specific repositories
|
|
63
|
+
- Core API < 200 remaining → Minimize repository exploration
|
|
64
|
+
- NPM disconnected → GitHub-only research mode
|
|
65
|
+
|
|
66
|
+
## ADAPTIVE RESEARCH METHODOLOGY
|
|
67
|
+
|
|
68
|
+
### SEMANTIC TOPIC DETECTION & ADAPTATION
|
|
69
|
+
Automatically detect query intent and adapt research strategy:
|
|
70
|
+
|
|
71
|
+
**TECHNOLOGY & SOFTWARE** → NPM packages, GitHub repositories, code implementations, documentation
|
|
72
|
+
**ACADEMIC & RESEARCH** → GitHub topics, research repositories, academic projects, papers
|
|
73
|
+
**BUSINESS & ORGANIZATIONS** → Company repositories, organizational projects, business tools
|
|
74
|
+
**CREATIVE & MEDIA** → Creative coding, media projects, artistic repositories, design systems
|
|
75
|
+
**EDUCATION & LEARNING** → Educational resources, tutorials, learning materials, course content
|
|
76
|
+
**SCIENCE & DATA** → Data science projects, scientific computing, research datasets, analysis tools
|
|
77
|
+
**GENERAL KNOWLEDGE** → Any topic through GitHub's vast ecosystem of projects and discussions
|
|
78
|
+
|
|
79
|
+
### UNIVERSAL RESEARCH DIMENSIONS
|
|
80
|
+
Every query requires investigation across multiple dimensions:
|
|
81
|
+
|
|
82
|
+
**1. DISCOVERY & EXPLORATION**
|
|
83
|
+
- Find relevant projects, packages, and implementations
|
|
84
|
+
- Identify multiple approaches and methodologies
|
|
85
|
+
- Locate official vs community resources
|
|
86
|
+
- Discover edge cases and alternative solutions
|
|
87
|
+
|
|
88
|
+
**2. ECOSYSTEM ANALYSIS**
|
|
89
|
+
- Understand relationships and dependencies
|
|
90
|
+
- Analyze community adoption and trends
|
|
91
|
+
- Evaluate maintenance and support status
|
|
92
|
+
- Assess quality and reliability indicators
|
|
93
|
+
|
|
94
|
+
**3. QUALITY & CREDIBILITY ASSESSMENT**
|
|
95
|
+
- Project quality and architecture evaluation
|
|
96
|
+
- Performance characteristics and benchmarks
|
|
97
|
+
- Documentation completeness and clarity
|
|
98
|
+
- Community engagement and activity levels
|
|
99
|
+
|
|
100
|
+
**4. CONTEXTUAL INTELLIGENCE**
|
|
101
|
+
- Trade-offs vs alternative approaches
|
|
102
|
+
- Scalability and practical considerations
|
|
103
|
+
- Integration complexity and requirements
|
|
104
|
+
- Learning curve and accessibility
|
|
105
|
+
|
|
106
|
+
**5. STRATEGIC INSIGHTS**
|
|
107
|
+
- Future trends and evolution patterns
|
|
108
|
+
- Community momentum and backing
|
|
109
|
+
- Suitability for different use cases
|
|
110
|
+
- Migration paths and compatibility
|
|
111
|
+
|
|
112
|
+
## INTELLIGENT TOOL SELECTION STRATEGY
|
|
113
|
+
|
|
114
|
+
### SEMANTIC QUERY ANALYSIS
|
|
115
|
+
Analyze query semantics to determine optimal tool combination:
|
|
116
|
+
|
|
117
|
+
**PACKAGE/LIBRARY QUERIES** → NPM-first approach
|
|
118
|
+
**PROJECT/REPOSITORY QUERIES** → GitHub repository search
|
|
119
|
+
**TOPIC/CONCEPT QUERIES** → GitHub topics exploration
|
|
120
|
+
**IMPLEMENTATION QUERIES** → Code search and file extraction
|
|
121
|
+
**PROBLEM/SOLUTION QUERIES** → Issues and discussions search
|
|
122
|
+
**PEOPLE/EXPERTISE QUERIES** → User and organization discovery
|
|
123
|
+
|
|
124
|
+
### ADAPTIVE SEARCH PATTERNS
|
|
125
|
+
|
|
126
|
+
**FOR TECHNOLOGY TOPICS:**
|
|
127
|
+
- ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → Package ecosystem discovery
|
|
128
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} → Technology landscape mapping
|
|
129
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_CODE} → Implementation patterns
|
|
130
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_REPOS} → Project repositories
|
|
131
|
+
|
|
132
|
+
**FOR RESEARCH/ACADEMIC TOPICS:**
|
|
133
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} → Research area exploration
|
|
134
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_REPOS} → Academic projects and papers
|
|
135
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_CODE} → Research implementations
|
|
136
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_USERS} → Researcher discovery
|
|
137
|
+
|
|
138
|
+
**FOR BUSINESS/ORGANIZATIONAL TOPICS:**
|
|
139
|
+
- ${TOOL_NAMES.GITHUB_GET_USER_ORGS} → Organization discovery
|
|
140
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_REPOS} → Company projects
|
|
141
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_CODE} → Internal implementations
|
|
142
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} → Business discussions
|
|
143
|
+
|
|
144
|
+
**FOR CREATIVE/MEDIA TOPICS:**
|
|
145
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} → Creative technology trends
|
|
146
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_REPOS} → Creative projects and tools
|
|
147
|
+
- ${TOOL_NAMES.GITHUB_SEARCH_CODE} → Creative implementations
|
|
148
|
+
- ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → Creative libraries and tools
|
|
149
|
+
|
|
150
|
+
## UNIVERSAL BOOLEAN SEARCH INTELLIGENCE
|
|
151
|
+
|
|
152
|
+
### SEMANTIC EXPANSION PATTERNS
|
|
153
|
+
Automatically enhance queries with domain-appropriate boolean operators:
|
|
154
|
+
|
|
155
|
+
**UNIVERSAL DOMAIN PATTERNS:**
|
|
156
|
+
- **Core Concepts**: "primary_term OR synonym OR variation OR abbreviation"
|
|
157
|
+
- **Quality Focus**: "concept OR approach OR method OR technique NOT test NOT demo"
|
|
158
|
+
- **Comprehensive Coverage**: "topic OR field OR domain OR area OR discipline"
|
|
159
|
+
- **Implementation Focus**: "solution OR tool OR system OR framework OR platform"
|
|
160
|
+
|
|
161
|
+
**ADAPTIVE SEMANTIC ENHANCEMENT:**
|
|
162
|
+
- **Academic/Research**: "research OR study OR analysis OR investigation OR methodology"
|
|
163
|
+
- **Creative/Artistic**: "creative OR artistic OR design OR visual OR aesthetic OR expression"
|
|
164
|
+
- **Business/Professional**: "business OR professional OR commercial OR enterprise OR industry"
|
|
165
|
+
- **Educational/Learning**: "education OR learning OR tutorial OR guide OR instruction OR knowledge"
|
|
166
|
+
- **Technical/Scientific**: "technical OR scientific OR systematic OR analytical OR computational"
|
|
167
|
+
- **Social/Community**: "social OR community OR collaborative OR public OR collective"
|
|
168
|
+
|
|
169
|
+
**CONTEXTUAL BOOLEAN PATTERNS:**
|
|
170
|
+
- **Problem-Solving**: "solution OR approach OR method OR strategy OR technique"
|
|
171
|
+
- **Tool Discovery**: "tool OR utility OR application OR platform OR system OR framework"
|
|
172
|
+
- **Knowledge Seeking**: "guide OR tutorial OR documentation OR resource OR reference"
|
|
173
|
+
- **Community Building**: "community OR collaboration OR network OR group OR organization"
|
|
174
|
+
- **Innovation Exploration**: "innovation OR experimental OR cutting-edge OR emerging OR novel"
|
|
175
|
+
|
|
176
|
+
## ADAPTIVE RESEARCH WORKFLOWS
|
|
177
|
+
|
|
178
|
+
### DISCOVERY INTENT DETECTION
|
|
179
|
+
Automatically route based on query patterns:
|
|
180
|
+
|
|
181
|
+
**"Find [topic] tools/resources"** → Package + Topic + Repository Discovery
|
|
182
|
+
**"How to [accomplish/solve]"** → Content search + Community discussions + Documentation
|
|
183
|
+
**"Who works on [topic]"** → User + Organization + Contributor Discovery
|
|
184
|
+
**"What's trending in [domain]"** → Topic + Popular projects + Recent activity
|
|
185
|
+
**"Compare [A] vs [B]"** → Multi-target analysis + Community discussions
|
|
186
|
+
**"Learn about [concept]"** → Educational resources + Documentation + Examples
|
|
187
|
+
**"Research [topic]"** → Academic projects + Data + Methodology discovery
|
|
188
|
+
**"Create [something]"** → Tools + Frameworks + Creative resources
|
|
189
|
+
**"Analyze [subject]"** → Data tools + Visualization + Analytics resources
|
|
190
|
+
|
|
191
|
+
### CONTEXTUAL WORKFLOW ADAPTATION
|
|
192
|
+
|
|
193
|
+
**DISCOVERY QUERIES:**
|
|
194
|
+
1. Topic landscape mapping (${TOOL_NAMES.GITHUB_SEARCH_TOPICS})
|
|
195
|
+
2. Resource discovery (${TOOL_NAMES.NPM_SEARCH_PACKAGES})
|
|
196
|
+
3. Project exploration (${TOOL_NAMES.GITHUB_SEARCH_REPOS})
|
|
197
|
+
4. Content analysis (${TOOL_NAMES.GITHUB_SEARCH_CODE})
|
|
198
|
+
|
|
199
|
+
**RESEARCH QUERIES:**
|
|
200
|
+
1. Domain exploration (${TOOL_NAMES.GITHUB_SEARCH_TOPICS})
|
|
201
|
+
2. Academic project discovery (${TOOL_NAMES.GITHUB_SEARCH_REPOS})
|
|
202
|
+
3. Methodology analysis (${TOOL_NAMES.GITHUB_SEARCH_CODE})
|
|
203
|
+
4. Expert network discovery (${TOOL_NAMES.GITHUB_SEARCH_USERS})
|
|
204
|
+
|
|
205
|
+
**SOLUTION QUERIES:**
|
|
206
|
+
1. Resource identification (${TOOL_NAMES.NPM_SEARCH_PACKAGES})
|
|
207
|
+
2. Project discovery (${TOOL_NAMES.GITHUB_SEARCH_REPOS})
|
|
208
|
+
3. Implementation analysis (${TOOL_NAMES.GITHUB_SEARCH_CODE})
|
|
209
|
+
4. Community support (${TOOL_NAMES.GITHUB_SEARCH_ISSUES})
|
|
210
|
+
|
|
211
|
+
## SEMANTIC PROPOSITION FRAMEWORK
|
|
212
|
+
|
|
213
|
+
### DYNAMIC GUIDANCE SYSTEM
|
|
214
|
+
Provide context-aware recommendations based on detected domain:
|
|
215
|
+
|
|
216
|
+
**UNIVERSAL PROPOSITIONS:**
|
|
217
|
+
- "Consider quality indicators and community engagement"
|
|
218
|
+
- "Evaluate approach diversity and methodological rigor"
|
|
219
|
+
- "Assess resource accessibility and learning curve"
|
|
220
|
+
- "Review documentation completeness and clarity"
|
|
221
|
+
|
|
222
|
+
**RESEARCH PROPOSITIONS:**
|
|
223
|
+
- "Examine methodology and experimental design"
|
|
224
|
+
- "Evaluate data quality and reproducibility"
|
|
225
|
+
- "Consider peer validation and citation patterns"
|
|
226
|
+
- "Assess theoretical foundations and practical applications"
|
|
227
|
+
|
|
228
|
+
**CREATIVE PROPOSITIONS:**
|
|
229
|
+
- "Explore artistic expression and creative possibilities"
|
|
230
|
+
- "Consider aesthetic principles and design philosophy"
|
|
231
|
+
- "Evaluate creative tools and workflow integration"
|
|
232
|
+
- "Assess community engagement and inspiration sources"
|
|
233
|
+
|
|
234
|
+
**BUSINESS PROPOSITIONS:**
|
|
235
|
+
- "Analyze market adoption and practical viability"
|
|
236
|
+
- "Evaluate cost-benefit and resource requirements"
|
|
237
|
+
- "Consider scalability and implementation complexity"
|
|
238
|
+
- "Assess competitive landscape and differentiation"
|
|
239
|
+
|
|
240
|
+
**EDUCATIONAL PROPOSITIONS:**
|
|
241
|
+
- "Examine learning pathways and skill progression"
|
|
242
|
+
- "Evaluate pedagogical approach and accessibility"
|
|
243
|
+
- "Consider prerequisite knowledge and learning curve"
|
|
244
|
+
- "Assess practical application and real-world relevance"
|
|
245
|
+
|
|
246
|
+
**COMMUNITY PROPOSITIONS:**
|
|
247
|
+
- "Explore collaboration opportunities and network effects"
|
|
248
|
+
- "Evaluate community health and engagement patterns"
|
|
249
|
+
- "Consider contribution pathways and skill development"
|
|
250
|
+
- "Assess social impact and collective benefit"
|
|
251
|
+
|
|
252
|
+
## UNIVERSAL ANTI-HALLUCINATION SAFEGUARDS
|
|
253
|
+
|
|
254
|
+
### DOMAIN-AGNOSTIC VALIDATION
|
|
255
|
+
- **Existence Verification**: Confirm resources exist before deep analysis
|
|
256
|
+
- **Cross-Reference Validation**: Verify findings across multiple sources
|
|
257
|
+
- **Community Consensus**: Check for widespread adoption vs niche experiments
|
|
258
|
+
- **Recency Assessment**: Evaluate currency and maintenance status
|
|
259
|
+
- **Authority Validation**: Assess source credibility and expertise
|
|
260
|
+
|
|
261
|
+
### PROGRESSIVE REFINEMENT STRATEGY
|
|
262
|
+
- **Broad Discovery**: Start with general terms and concepts
|
|
263
|
+
- **Semantic Expansion**: Add related terms and variations
|
|
264
|
+
- **Context Filtering**: Apply domain-specific filters and exclusions
|
|
265
|
+
- **Quality Assessment**: Evaluate results for relevance and quality
|
|
266
|
+
- **Deep Analysis**: Extract detailed insights from validated sources
|
|
267
|
+
|
|
268
|
+
## INTELLIGENT RESULT SYNTHESIS
|
|
269
|
+
|
|
270
|
+
### MULTI-DIMENSIONAL ANALYSIS
|
|
271
|
+
For every comprehensive answer, provide:
|
|
272
|
+
|
|
273
|
+
**LANDSCAPE OVERVIEW**
|
|
274
|
+
- Current state of the domain/topic
|
|
275
|
+
- Key players and influential projects
|
|
276
|
+
- Trending approaches and methodologies
|
|
277
|
+
- Community dynamics and adoption patterns
|
|
278
|
+
|
|
279
|
+
**PRACTICAL INSIGHTS**
|
|
280
|
+
- Actionable recommendations with rationale
|
|
281
|
+
- Common challenges and solution approaches
|
|
282
|
+
- Best practices and proven patterns
|
|
283
|
+
- Learning resources and next steps
|
|
284
|
+
|
|
285
|
+
**STRATEGIC CONTEXT**
|
|
286
|
+
- Future trends and evolution directions
|
|
287
|
+
- Trade-offs and decision frameworks
|
|
288
|
+
- Suitability for different use cases
|
|
289
|
+
- Risk assessment and mitigation strategies
|
|
290
|
+
|
|
291
|
+
**COMMUNITY INTELLIGENCE**
|
|
292
|
+
- Expert contributors and thought leaders
|
|
293
|
+
- Active discussions and debates
|
|
294
|
+
- Collaborative opportunities and networks
|
|
295
|
+
- Knowledge gaps and research opportunities
|
|
296
|
+
|
|
297
|
+
## ADAPTIVE ERROR RECOVERY
|
|
298
|
+
|
|
299
|
+
### SEMANTIC FALLBACK STRATEGIES
|
|
300
|
+
When primary searches fail, automatically adapt:
|
|
301
|
+
|
|
302
|
+
**TERM EXPANSION**: Broaden to related concepts and synonyms
|
|
303
|
+
**DOMAIN SHIFTING**: Explore adjacent fields and applications
|
|
304
|
+
**ABSTRACTION LEVELS**: Move between specific and general concepts
|
|
305
|
+
**TEMPORAL ADJUSTMENT**: Consider historical vs cutting-edge approaches
|
|
306
|
+
**COMMUNITY PIVOTING**: Shift from technical to social/community aspects
|
|
307
|
+
|
|
308
|
+
### INTELLIGENT GUIDANCE
|
|
309
|
+
Provide domain-appropriate suggestions for:
|
|
310
|
+
- Alternative search strategies
|
|
311
|
+
- Related topics worth exploring
|
|
312
|
+
- Community resources and experts
|
|
313
|
+
- Learning pathways and next steps
|
|
314
|
+
|
|
315
|
+
**OUTPUT GOAL**: Comprehensive, accurate, and actionable insights across any domain of knowledge, leveraging GitHub's vast ecosystem of human knowledge and collaboration.`;
|
|
159
316
|
|
|
160
317
|
const TOOL_DESCRIPTIONS = {
|
|
161
|
-
[TOOL_NAMES.NPM_SEARCH_PACKAGES]: `**
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
**
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
**
|
|
171
|
-
|
|
172
|
-
**
|
|
173
|
-
|
|
174
|
-
**
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
**
|
|
180
|
-
|
|
181
|
-
**
|
|
182
|
-
|
|
183
|
-
|
|
318
|
+
[TOOL_NAMES.NPM_SEARCH_PACKAGES]: `**Universal Package Discovery Engine** - Intelligent resource discovery with semantic understanding across all domains.
|
|
319
|
+
|
|
320
|
+
**🧠 SEMANTIC PACKAGE INTELLIGENCE:**
|
|
321
|
+
- **DOMAIN-ADAPTIVE SEARCH**: Automatically detects query intent and adapts search strategy
|
|
322
|
+
- **UNIVERSAL RESOURCE DISCOVERY**: Finds packages, tools, libraries, frameworks across any field
|
|
323
|
+
- **INTELLIGENT CATEGORIZATION**: Understands technology, creative, business, educational, scientific packages
|
|
324
|
+
- **CONTEXTUAL RECOMMENDATIONS**: Provides domain-specific guidance and alternatives
|
|
325
|
+
|
|
326
|
+
**🎯 ADAPTIVE SEARCH STRATEGIES:**
|
|
327
|
+
- **TECHNOLOGY PACKAGES** → Development tools, frameworks, libraries, utilities
|
|
328
|
+
- **CREATIVE PACKAGES** → Design tools, media processing, artistic frameworks, generators
|
|
329
|
+
- **BUSINESS PACKAGES** → Analytics, automation, productivity, management tools
|
|
330
|
+
- **EDUCATIONAL PACKAGES** → Learning resources, documentation generators, tutorial tools
|
|
331
|
+
- **SCIENTIFIC PACKAGES** → Data analysis, visualization, computation, research tools
|
|
332
|
+
- **UTILITY PACKAGES** → General-purpose tools, helpers, converters, processors
|
|
333
|
+
|
|
334
|
+
**🚀 INTELLIGENT QUERY OPTIMIZATION:**
|
|
335
|
+
1. **Single Terms**: "visualization", "automation", "analysis", "design"
|
|
336
|
+
2. **Combined Concepts**: "data-visualization", "workflow-automation", "content-management"
|
|
337
|
+
3. **Domain Bridging**: Technical terms → accessible language, specific → general
|
|
338
|
+
4. **Semantic Expansion**: Core concept → related terms → ecosystem discovery
|
|
339
|
+
|
|
340
|
+
**💡 UNIVERSAL SEARCH PATTERNS:**
|
|
341
|
+
- **"data visualization"** → Charts, graphs, dashboards, plotting tools
|
|
342
|
+
- **"content management"** → CMS, publishing, editorial, workflow tools
|
|
343
|
+
- **"image processing"** → Graphics, filters, conversion, manipulation tools
|
|
344
|
+
- **"workflow automation"** → Task runners, schedulers, pipeline tools
|
|
345
|
+
- **"learning resources"** → Educational, tutorial, documentation tools
|
|
346
|
+
|
|
347
|
+
**🌍 CROSS-DOMAIN EXAMPLES:**
|
|
348
|
+
- **CREATIVE DOMAIN**: "design OR graphics OR visual OR creative OR artistic"
|
|
349
|
+
- **BUSINESS DOMAIN**: "management OR analytics OR productivity OR automation"
|
|
350
|
+
- **RESEARCH DOMAIN**: "analysis OR data OR research OR scientific OR academic"
|
|
351
|
+
- **EDUCATIONAL DOMAIN**: "learning OR tutorial OR education OR documentation"
|
|
352
|
+
- **UTILITY DOMAIN**: "tool OR utility OR helper OR converter OR processor"
|
|
353
|
+
|
|
354
|
+
**🔧 ORGANIZATIONAL INTELLIGENCE:**
|
|
355
|
+
- **@organization/** packages → Triggers private/enterprise discovery workflow
|
|
356
|
+
- **Internal/Private** indicators → Activates organizational context search
|
|
357
|
+
- **Enterprise** patterns → Suggests organizational repository exploration
|
|
358
|
+
|
|
359
|
+
**⚡ SEARCH OPTIMIZATION:**
|
|
360
|
+
- **0 results** → Broader terms, ecosystem exploration, alternative approaches
|
|
361
|
+
- **1-20 results** → IDEAL scope for detailed analysis and comparison
|
|
362
|
+
- **100+ results** → More specific terms, domain filters, focused refinement
|
|
363
|
+
- **Organizational scope** → Private package discovery, enterprise workflows
|
|
364
|
+
|
|
365
|
+
**🔄 INTELLIGENT FALLBACK STRATEGIES:**
|
|
366
|
+
When package search yields insufficient results:
|
|
367
|
+
1. **Ecosystem Exploration** → Related technology/domain discovery
|
|
368
|
+
2. **Repository Search** → Direct project/tool discovery
|
|
369
|
+
3. **Topic Analysis** → Domain terminology and trend identification
|
|
370
|
+
4. **Community Discovery** → Expert and organization identification
|
|
371
|
+
5. **Content Search** → Implementation and usage pattern analysis
|
|
372
|
+
6. **Discussion Mining** → Problem-solving and solution discovery
|
|
373
|
+
|
|
374
|
+
**🎨 DOMAIN-SPECIFIC INTELLIGENCE:**
|
|
375
|
+
- **Creative Tools**: Design, media, art, visualization, creative coding
|
|
376
|
+
- **Business Solutions**: Analytics, automation, management, productivity
|
|
377
|
+
- **Research Instruments**: Data analysis, computation, visualization, modeling
|
|
378
|
+
- **Educational Resources**: Learning, documentation, tutorials, guides
|
|
379
|
+
- **Utility Collections**: Helpers, converters, processors, generators
|
|
380
|
+
|
|
381
|
+
**INPUT**: Any concept, tool, or resource need across any domain
|
|
382
|
+
**OUTPUT**: Comprehensive package ecosystem with domain-adapted insights and alternatives`,
|
|
184
383
|
[TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES]: `**CRITICAL: Package security analysis** - Essential for package evaluation and organizational detection.
|
|
185
384
|
|
|
186
|
-
**WHEN TO USE:** ALWAYS after ${TOOL_NAMES.
|
|
385
|
+
**WHEN TO USE:** ALWAYS after ${TOOL_NAMES.NPM_SEARCH_PACKAGES} for complete assessment.
|
|
187
386
|
|
|
188
387
|
**ANALYSIS:** Security vulnerabilities, dependency tree, license compatibility, bundle impact, organization detection (@company/).
|
|
189
388
|
|
|
190
|
-
**ORGANIZATIONAL CONTEXT:** Private packages → Check ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
**
|
|
198
|
-
|
|
199
|
-
**
|
|
389
|
+
**ORGANIZATIONAL CONTEXT:** Private packages → Check ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access
|
|
390
|
+
|
|
391
|
+
**KNOWN LIMITATION:** Some NPM audit failures may occur (package-specific). Bundle analysis and dependency tree remain reliable.`,
|
|
392
|
+
[TOOL_NAMES.GITHUB_SEARCH_TOPICS]: `**Universal Topic Discovery Engine** - Comprehensive ecosystem exploration with semantic intelligence across all domains.
|
|
393
|
+
|
|
394
|
+
**🧠 SEMANTIC TOPIC INTELLIGENCE:**
|
|
395
|
+
- **DOMAIN-AGNOSTIC DISCOVERY**: Explores any field, discipline, or area of interest
|
|
396
|
+
- **ECOSYSTEM MAPPING**: Reveals relationships, trends, and communities across topics
|
|
397
|
+
- **CONTEXTUAL UNDERSTANDING**: Adapts recommendations based on query domain and intent
|
|
398
|
+
- **CROSS-POLLINATION**: Discovers unexpected connections between different fields
|
|
399
|
+
|
|
400
|
+
**🎯 UNIVERSAL EXPLORATION PATTERNS:**
|
|
401
|
+
- **SINGLE TERMS**: "sustainability", "automation", "creativity", "wellness", "education"
|
|
402
|
+
- **COMPOUND CONCEPTS**: "machine-learning", "user-experience", "data-science", "digital-art"
|
|
403
|
+
- **DOMAIN BRIDGING**: Technical ↔ Creative ↔ Business ↔ Academic ↔ Social
|
|
404
|
+
|
|
405
|
+
**🌍 CROSS-DOMAIN TOPIC DISCOVERY:**
|
|
406
|
+
- **TECHNOLOGY DOMAINS**: "ai", "blockchain", "iot", "cybersecurity", "cloud-computing"
|
|
407
|
+
- **CREATIVE DOMAINS**: "design", "art", "music", "writing", "photography", "animation"
|
|
408
|
+
- **BUSINESS DOMAINS**: "entrepreneurship", "marketing", "finance", "management", "strategy"
|
|
409
|
+
- **ACADEMIC DOMAINS**: "research", "education", "science", "mathematics", "psychology"
|
|
410
|
+
- **SOCIAL DOMAINS**: "community", "activism", "sustainability", "health", "culture"
|
|
411
|
+
- **LIFESTYLE DOMAINS**: "fitness", "cooking", "travel", "productivity", "mindfulness"
|
|
412
|
+
|
|
413
|
+
**🚀 INTELLIGENT SEARCH STRATEGIES:**
|
|
414
|
+
1. **Broad Discovery**: Start with core concepts to map the landscape
|
|
415
|
+
2. **Semantic Expansion**: Related terms, synonyms, and variations
|
|
416
|
+
3. **Community Identification**: Active projects, contributors, and organizations
|
|
417
|
+
4. **Trend Analysis**: Emerging topics, popular projects, and growth patterns
|
|
418
|
+
5. **Cross-Domain Connections**: Unexpected intersections and collaborations
|
|
419
|
+
|
|
420
|
+
**💡 ADAPTIVE TOPIC PATTERNS:**
|
|
421
|
+
- **"sustainability"** → Environmental, green-tech, renewable, climate, conservation
|
|
422
|
+
- **"creativity"** → Art, design, innovation, expression, generative, artistic
|
|
423
|
+
- **"wellness"** → Health, fitness, mental-health, mindfulness, nutrition
|
|
424
|
+
- **"automation"** → Workflow, productivity, efficiency, tools, processes
|
|
425
|
+
- **"learning"** → Education, tutorial, knowledge, skill-development, training
|
|
426
|
+
|
|
427
|
+
**🔍 DISCOVERY METHODOLOGIES:**
|
|
428
|
+
- **ECOSYSTEM EXPLORATION**: Map entire domains and their sub-communities
|
|
429
|
+
- **TREND IDENTIFICATION**: Spot emerging topics and growing communities
|
|
430
|
+
- **COMMUNITY MAPPING**: Find active contributors and thought leaders
|
|
431
|
+
- **RESOURCE DISCOVERY**: Locate tools, frameworks, and learning materials
|
|
432
|
+
- **COLLABORATION OPPORTUNITIES**: Identify potential partnerships and projects
|
|
433
|
+
|
|
434
|
+
**⚡ SEARCH OPTIMIZATION STRATEGIES:**
|
|
435
|
+
- **1-10 TOPICS**: Perfect scope for deep domain analysis
|
|
436
|
+
- **10+ TOPICS**: Rich ecosystem with multiple exploration paths
|
|
437
|
+
- **Featured/Curated**: High-quality, community-validated topics
|
|
438
|
+
- **Repository Count**: Indicates community size and activity level
|
|
439
|
+
|
|
440
|
+
**🎨 DOMAIN-SPECIFIC INTELLIGENCE:**
|
|
441
|
+
- **CREATIVE EXPLORATION**: Art, design, media, expression, aesthetics
|
|
442
|
+
- **BUSINESS INTELLIGENCE**: Strategy, operations, innovation, market trends
|
|
443
|
+
- **RESEARCH DISCOVERY**: Academic, scientific, experimental, methodological
|
|
444
|
+
- **EDUCATIONAL RESOURCES**: Learning, teaching, knowledge transfer, skill building
|
|
445
|
+
- **SOCIAL IMPACT**: Community, activism, sustainability, social good
|
|
446
|
+
- **PERSONAL DEVELOPMENT**: Wellness, productivity, skills, lifestyle, growth
|
|
447
|
+
|
|
448
|
+
**🔄 PROGRESSIVE DISCOVERY WORKFLOW:**
|
|
449
|
+
1. **Core Topic Exploration** → Understand the fundamental landscape
|
|
450
|
+
2. **Related Topic Discovery** → Find adjacent and complementary areas
|
|
451
|
+
3. **Community Identification** → Locate active contributors and projects
|
|
452
|
+
4. **Resource Mapping** → Discover tools, frameworks, and materials
|
|
453
|
+
5. **Trend Analysis** → Identify emerging patterns and opportunities
|
|
454
|
+
6. **Cross-Domain Bridging** → Find unexpected connections and innovations
|
|
455
|
+
|
|
456
|
+
**🌟 UNIVERSAL APPLICATIONS:**
|
|
457
|
+
- **Research Planning**: Explore academic and scientific domains
|
|
458
|
+
- **Business Strategy**: Identify market trends and opportunities
|
|
459
|
+
- **Creative Inspiration**: Discover artistic and design communities
|
|
460
|
+
- **Learning Pathways**: Find educational resources and skill development
|
|
461
|
+
- **Community Building**: Locate like-minded individuals and organizations
|
|
462
|
+
- **Innovation Discovery**: Spot emerging technologies and methodologies
|
|
463
|
+
|
|
464
|
+
**INPUT**: Any topic, concept, interest, or domain of inquiry
|
|
465
|
+
**OUTPUT**: Comprehensive ecosystem map with community insights, trends, and exploration pathways`,
|
|
200
466
|
[TOOL_NAMES.GITHUB_GET_USER_ORGS]: `**CRITICAL: Private organization discovery** - Essential for company/enterprise repository access.
|
|
201
467
|
|
|
202
468
|
**AUTO-TRIGGERS:** @wix/, @company/, "I work at [Company]", "internal code", "enterprise setup"
|
|
@@ -204,31 +470,102 @@ const TOOL_DESCRIPTIONS = {
|
|
|
204
470
|
**WORKFLOW:** IMMEDIATE call when organizational context detected → Match company to organizations → Use as 'owner' parameter → Enable private repository access
|
|
205
471
|
|
|
206
472
|
**INTEGRATION:** MANDATORY first step when private access likely needed`,
|
|
207
|
-
[TOOL_NAMES.GITHUB_GET_REPOSITORY]: `**CRITICAL FIRST STEP** - Required before all GitHub file operations.
|
|
473
|
+
[TOOL_NAMES.GITHUB_GET_REPOSITORY]: `**CRITICAL FIRST STEP** - Required before all GitHub file operations, but ONLY after discovery.
|
|
208
474
|
|
|
209
475
|
**PURPOSE:** Discover default branch and repository metadata to prevent tool failures.
|
|
210
476
|
|
|
211
|
-
**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
**KEY FEATURES:** Every search includes "repo:owner/repository", smart boolean logic, organizational context.
|
|
477
|
+
**MANDATORY PREREQUISITES:** Repository owner/name MUST be discovered first through:
|
|
478
|
+
1. ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → ${TOOL_NAMES.NPM_GET_PACKAGE} (for packages)
|
|
479
|
+
2. ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} (for ecosystem discovery)
|
|
480
|
+
3. ${TOOL_NAMES.GITHUB_SEARCH_REPOS} (last resort)
|
|
217
481
|
|
|
218
|
-
**
|
|
219
|
-
|
|
220
|
-
**PATH WARNING:** React uses path:packages (NOT path:src). Using path:src on repositories without top-level src returns zero results.
|
|
221
|
-
|
|
222
|
-
**RESULT OPTIMIZATION:** 1-10 IDEAL, 100+ TOO BROAD
|
|
482
|
+
**REQUIRED BEFORE:** ${TOOL_NAMES.GITHUB_SEARCH_CODE}, ${TOOL_NAMES.GITHUB_GET_CONTENTS}, ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT}
|
|
223
483
|
|
|
224
|
-
**
|
|
484
|
+
**CRITICAL:** NEVER call with guessed repository names. ALWAYS use discovery workflow first.`,
|
|
485
|
+
[TOOL_NAMES.GITHUB_SEARCH_CODE]: `**Universal Content Discovery Engine** - Intelligent search with automatic domain adaptation and semantic understanding.
|
|
486
|
+
|
|
487
|
+
**🧠 SEMANTIC QUERY INTELLIGENCE - ADAPTS TO ANY DOMAIN:**
|
|
488
|
+
- **AUTOMATIC DOMAIN DETECTION**: Analyzes query intent and adapts search strategy accordingly
|
|
489
|
+
- **UNIVERSAL BOOLEAN ENHANCEMENT**: Converts any query into optimal boolean patterns for maximum efficiency
|
|
490
|
+
- **CROSS-DOMAIN EXPERTISE**: Handles technology, research, business, creative, educational, scientific topics
|
|
491
|
+
- **CONTEXTUAL INTELLIGENCE**: Provides domain-specific guidance based on query semantics
|
|
492
|
+
|
|
493
|
+
**🎯 ADAPTIVE SEMANTIC PATTERNS:**
|
|
494
|
+
- **TECHNOLOGY QUERIES** → "framework OR library OR tool OR implementation NOT tutorial"
|
|
495
|
+
- **RESEARCH QUERIES** → "study OR analysis OR research OR investigation NOT example"
|
|
496
|
+
- **BUSINESS QUERIES** → "solution OR strategy OR management OR process NOT demo"
|
|
497
|
+
- **CREATIVE QUERIES** → "design OR art OR creative OR visual NOT template"
|
|
498
|
+
- **EDUCATIONAL QUERIES** → "learning OR education OR tutorial OR guide NOT test"
|
|
499
|
+
- **SCIENTIFIC QUERIES** → "data OR analysis OR algorithm OR method NOT mock"
|
|
500
|
+
|
|
501
|
+
**🚀 INTELLIGENT QUERY OPTIMIZATION:**
|
|
502
|
+
- **Semantic Expansion**: Automatically adds synonyms and variations based on domain
|
|
503
|
+
- **Context Enrichment**: Suggests related terms specific to the detected topic area
|
|
504
|
+
- **Quality Filtering**: Adds appropriate exclusions (NOT test, NOT example, NOT demo)
|
|
505
|
+
- **Progressive Refinement**: Starts broad, then narrows based on results
|
|
506
|
+
|
|
507
|
+
**🔧 UNIVERSAL BOOLEAN INTELLIGENCE:**
|
|
508
|
+
- **COVERAGE PATTERNS**: "primary_term OR synonym OR variation OR abbreviation"
|
|
509
|
+
- **PRECISION PATTERNS**: "specific_concept AND context AND domain NOT noise"
|
|
510
|
+
- **QUALITY PATTERNS**: "topic NOT test NOT example NOT demo NOT tutorial"
|
|
511
|
+
- **DOMAIN PATTERNS**: "core_concept OR related_field OR application_area"
|
|
512
|
+
|
|
513
|
+
**💡 SEMANTIC DOMAIN EXAMPLES:**
|
|
514
|
+
- **"machine learning"** → "ml OR ai OR algorithm OR model OR neural NOT tutorial"
|
|
515
|
+
- **"climate change"** → "climate OR environment OR warming OR carbon NOT simulation"
|
|
516
|
+
- **"marketing strategy"** → "marketing OR strategy OR campaign OR brand NOT template"
|
|
517
|
+
- **"data visualization"** → "visualization OR chart OR graph OR dashboard NOT example"
|
|
518
|
+
- **"user experience"** → "ux OR ui OR design OR usability OR interface NOT mockup"
|
|
519
|
+
|
|
520
|
+
**🎨 CREATIVE DOMAIN INTELLIGENCE:**
|
|
521
|
+
- **Art & Design**: "creative OR artistic OR visual OR aesthetic OR design"
|
|
522
|
+
- **Music & Audio**: "music OR audio OR sound OR composition OR production"
|
|
523
|
+
- **Writing & Content**: "writing OR content OR narrative OR storytelling OR editorial"
|
|
524
|
+
- **Media & Video**: "video OR media OR film OR animation OR production"
|
|
525
|
+
|
|
526
|
+
**🔬 ACADEMIC DOMAIN INTELLIGENCE:**
|
|
527
|
+
- **Research**: "research OR study OR analysis OR investigation OR methodology"
|
|
528
|
+
- **Science**: "scientific OR experiment OR hypothesis OR data OR evidence"
|
|
529
|
+
- **Mathematics**: "mathematical OR algorithm OR computation OR formula OR proof"
|
|
530
|
+
- **Social Sciences**: "social OR behavioral OR psychological OR cultural OR demographic"
|
|
531
|
+
|
|
532
|
+
**🏢 BUSINESS DOMAIN INTELLIGENCE:**
|
|
533
|
+
- **Management**: "management OR leadership OR strategy OR operations OR planning"
|
|
534
|
+
- **Finance**: "financial OR economic OR investment OR budget OR revenue"
|
|
535
|
+
- **Marketing**: "marketing OR advertising OR branding OR promotion OR customer"
|
|
536
|
+
- **Analytics**: "analytics OR metrics OR performance OR tracking OR insights"
|
|
537
|
+
|
|
538
|
+
**🌍 UNIVERSAL FALLBACK STRATEGIES:**
|
|
539
|
+
- **Term Simplification**: Complex phrases → core concepts
|
|
540
|
+
- **Semantic Broadening**: Specific terms → general categories
|
|
541
|
+
- **Cross-Domain Bridging**: Technical terms → common language
|
|
542
|
+
- **Progressive Refinement**: General → specific based on results
|
|
543
|
+
|
|
544
|
+
**⚡ EFFICIENCY GUARANTEES:**
|
|
545
|
+
- **3-5x Performance**: Boolean queries consistently outperform simple text
|
|
546
|
+
- **Automatic Enhancement**: Every query gets optimized for maximum results
|
|
547
|
+
- **Smart Fallbacks**: Multiple strategies ensure you always get insights
|
|
548
|
+
- **Domain Adaptation**: Recommendations tailored to your specific field
|
|
549
|
+
|
|
550
|
+
**🔍 ANTI-HALLUCINATION SAFEGUARDS:**
|
|
551
|
+
- **Existence Verification**: Confirms content exists before deep analysis
|
|
552
|
+
- **Semantic Validation**: Checks query makes sense in detected domain
|
|
553
|
+
- **Progressive Discovery**: Starts broad, narrows based on actual results
|
|
554
|
+
- **Cross-Reference**: Validates findings across multiple sources
|
|
555
|
+
|
|
556
|
+
**INPUT**: Any query in any domain - technology, research, business, creative, educational, scientific
|
|
557
|
+
**OUTPUT**: Comprehensive, domain-adapted search results with intelligent insights and next steps`,
|
|
225
558
|
[TOOL_NAMES.GITHUB_GET_FILE_CONTENT]: `**Complete code extraction** - Fetch full working implementations.
|
|
226
559
|
|
|
227
|
-
**CRITICAL WORKFLOW:** MANDATORY ${TOOL_NAMES.GITHUB_GET_REPOSITORY}
|
|
560
|
+
**CRITICAL WORKFLOW:** MANDATORY discovery → ${TOOL_NAMES.GITHUB_GET_REPOSITORY} → Find files with ${TOOL_NAMES.GITHUB_SEARCH_CODE} or ${TOOL_NAMES.GITHUB_GET_CONTENTS} → Extract with this tool
|
|
228
561
|
|
|
229
562
|
**AUTO-RECOVERY:** Specified branch → main → master → develop → trunk → try without ref
|
|
230
563
|
|
|
231
|
-
**
|
|
564
|
+
**ENHANCED ERROR HANDLING:** Provides detailed guidance when files don't exist, with alternative discovery methods
|
|
565
|
+
|
|
566
|
+
**ORGANIZATIONAL CONTEXT:** Private repositories → Use ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access
|
|
567
|
+
|
|
568
|
+
**CRITICAL:** NEVER guess file paths. Use structure exploration or code search first.`,
|
|
232
569
|
[TOOL_NAMES.GITHUB_GET_CONTENTS]: `**Repository structure exploration** - Strategic directory navigation.
|
|
233
570
|
|
|
234
571
|
**CRITICAL:** MANDATORY ${TOOL_NAMES.GITHUB_GET_REPOSITORY} FIRST for branch discovery.
|
|
@@ -240,8 +577,14 @@ const TOOL_DESCRIPTIONS = {
|
|
|
240
577
|
|
|
241
578
|
**SEARCH STRATEGY:** Single keywords ("bug", "feature"), then combine ("bug fix"), never complex.
|
|
242
579
|
|
|
580
|
+
**SEARCH MODES:**
|
|
581
|
+
- Global search (no owner): Searches issues across all GitHub repositories
|
|
582
|
+
- Scoped search (with owner): Targeted search within specific organization/user
|
|
583
|
+
|
|
243
584
|
**PROBLEM HIERARCHY:** "React auth JWT error" → "authentication" → "React" → "token expired" → "JWT"
|
|
244
585
|
|
|
586
|
+
**PAGINATION LIMITATION:** GitHub CLI limited to --limit parameter only (no page navigation).
|
|
587
|
+
|
|
245
588
|
**RESULT TARGETS:** 0 → broader terms, 1-20 IDEAL, 100+ → add specific terms/filters`,
|
|
246
589
|
[TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS]: `**Implementation analysis** - PR search for patterns and repository status.
|
|
247
590
|
|
|
@@ -249,48 +592,247 @@ const TOOL_DESCRIPTIONS = {
|
|
|
249
592
|
|
|
250
593
|
**KEY FILTERS:** State (open/closed), draft (false for completed), author/reviewer, language
|
|
251
594
|
|
|
595
|
+
**PAGINATION LIMITATION:** GitHub CLI limited to --limit parameter only (no page navigation).
|
|
596
|
+
|
|
252
597
|
**QUALITY FOCUS:** Use review-related filters for thoroughly vetted code examples`,
|
|
253
598
|
[TOOL_NAMES.GITHUB_SEARCH_COMMITS]: `**Development history** - Track code evolution and repository status.
|
|
254
599
|
|
|
255
600
|
**SEARCH STRATEGY:** Start minimal ("fix", "feature", "update") with owner/repo, progressive expansion.
|
|
256
601
|
|
|
257
|
-
**LIMITATIONS:** Large organizations may return org-wide results, requires text terms.
|
|
602
|
+
**LIMITATIONS:** Large organizations may return org-wide results, requires text terms. GitHub CLI limited to --limit parameter only (no page navigation).
|
|
258
603
|
|
|
259
604
|
**ERROR HANDLING:** "Search text required" → Use minimal keywords ("fix", "update")`,
|
|
260
|
-
[TOOL_NAMES.GITHUB_SEARCH_DISCUSSIONS]: `**Community knowledge** - Access discussions for tutorials and solutions.
|
|
261
|
-
|
|
262
|
-
**DISCOVERY WORKFLOW:** ${TOOL_NAMES.NPM_GET_PACKAGE} → get repo URL → Search discussions
|
|
263
|
-
|
|
264
|
-
**SEARCH STRATEGY:** Start simple ("help", "tutorial"), build complexity ("help deployment"), avoid full phrases.
|
|
265
|
-
|
|
266
|
-
**KEY FILTERS:** Answered: true for validated solutions, category filters, maintainer participation`,
|
|
267
605
|
[TOOL_NAMES.GITHUB_SEARCH_USERS]: `**Developer discovery** - Find experts and community leaders.
|
|
268
606
|
|
|
269
607
|
**SEARCH METHODOLOGY:** Technology terms ("react", "python") → add context (location, experience) → specialized search.
|
|
270
608
|
|
|
609
|
+
**SEARCH MODES:**
|
|
610
|
+
- Global search (no owner): Searches users/orgs across all GitHub
|
|
611
|
+
- Scoped search (with owner): Targeted search within specific organization context
|
|
612
|
+
|
|
271
613
|
**KEY FILTERS:** Type (user/org), location, language, followers (">100" influential), repos (">10" active)
|
|
272
614
|
|
|
273
615
|
**DISCOVERY PATTERNS:** Technology experts, local developers, open source contributors, industry leaders`,
|
|
274
|
-
[TOOL_NAMES.GITHUB_SEARCH_REPOS]: `**
|
|
616
|
+
[TOOL_NAMES.GITHUB_SEARCH_REPOS]: `**Universal Project Discovery Engine** - Intelligent repository search with semantic understanding across all domains and disciplines.
|
|
617
|
+
|
|
618
|
+
**🧠 SEMANTIC PROJECT INTELLIGENCE:**
|
|
619
|
+
- **DOMAIN-ADAPTIVE DISCOVERY**: Automatically detects query intent and adapts search strategy
|
|
620
|
+
- **UNIVERSAL PROJECT TYPES**: Finds software, research, creative, educational, business, and community projects
|
|
621
|
+
- **CONTEXTUAL UNDERSTANDING**: Provides domain-specific insights and recommendations
|
|
622
|
+
- **CROSS-DISCIPLINARY EXPLORATION**: Discovers projects spanning multiple fields and interests
|
|
623
|
+
|
|
624
|
+
**🎯 ADAPTIVE PROJECT DISCOVERY:**
|
|
625
|
+
- **TECHNOLOGY PROJECTS** → Software, tools, frameworks, applications, systems
|
|
626
|
+
- **RESEARCH PROJECTS** → Academic studies, experiments, data analysis, methodologies
|
|
627
|
+
- **CREATIVE PROJECTS** → Art, design, media, content, artistic expressions
|
|
628
|
+
- **EDUCATIONAL PROJECTS** → Learning resources, tutorials, courses, documentation
|
|
629
|
+
- **BUSINESS PROJECTS** → Solutions, automation, analytics, productivity tools
|
|
630
|
+
- **COMMUNITY PROJECTS** → Open source, collaboration, social impact, activism
|
|
631
|
+
|
|
632
|
+
**🚀 INTELLIGENT SEARCH STRATEGIES:**
|
|
633
|
+
1. **Single Terms**: "visualization", "sustainability", "automation", "creativity"
|
|
634
|
+
2. **Domain-Specific**: Add context filters based on detected field
|
|
635
|
+
3. **Quality Indicators**: Star count, activity level, community engagement
|
|
636
|
+
4. **Scope Management**: Global discovery vs. targeted organizational search
|
|
637
|
+
|
|
638
|
+
**💡 UNIVERSAL PROJECT PATTERNS:**
|
|
639
|
+
- **"data visualization"** → Charts, dashboards, plotting, analytics projects
|
|
640
|
+
- **"sustainability"** → Environmental, green-tech, climate, conservation projects
|
|
641
|
+
- **"education"** → Learning platforms, tutorials, courses, knowledge sharing
|
|
642
|
+
- **"automation"** → Workflow tools, productivity, efficiency, process optimization
|
|
643
|
+
- **"creativity"** → Art tools, design systems, creative coding, expression platforms
|
|
644
|
+
|
|
645
|
+
**🌍 CROSS-DOMAIN PROJECT TYPES:**
|
|
646
|
+
- **RESEARCH REPOSITORIES**: Academic papers, datasets, experiments, methodologies
|
|
647
|
+
- **CREATIVE PORTFOLIOS**: Art projects, design systems, media collections
|
|
648
|
+
- **BUSINESS SOLUTIONS**: Analytics tools, automation scripts, productivity apps
|
|
649
|
+
- **EDUCATIONAL RESOURCES**: Learning materials, tutorials, course content
|
|
650
|
+
- **COMMUNITY INITIATIVES**: Open source projects, social impact, collaboration
|
|
651
|
+
- **PERSONAL PROJECTS**: Individual explorations, experiments, learning journeys
|
|
652
|
+
|
|
653
|
+
**⚡ SEARCH OPTIMIZATION STRATEGIES:**
|
|
654
|
+
- **0 results** → Broader terms, alternative approaches, ecosystem exploration
|
|
655
|
+
- **1-20 results** → IDEAL scope for detailed analysis and comparison
|
|
656
|
+
- **100+ results** → Add filters, narrow scope, focus on quality indicators
|
|
657
|
+
- **Organizational scope** → Private/enterprise project discovery
|
|
658
|
+
|
|
659
|
+
**🔧 INTELLIGENT FILTERING:**
|
|
660
|
+
- **Quality Indicators**: Star count (>100 established, >10 active)
|
|
661
|
+
- **Activity Level**: Recent updates, community engagement
|
|
662
|
+
- **Project Maturity**: Development stage, documentation quality
|
|
663
|
+
- **Domain Relevance**: Topic tags, description matching, content analysis
|
|
664
|
+
|
|
665
|
+
**🔄 PROGRESSIVE DISCOVERY WORKFLOW:**
|
|
666
|
+
1. **Broad Exploration** → Map the project landscape in your domain
|
|
667
|
+
2. **Quality Filtering** → Focus on well-maintained, active projects
|
|
668
|
+
3. **Community Analysis** → Identify key contributors and organizations
|
|
669
|
+
4. **Feature Comparison** → Analyze capabilities and approaches
|
|
670
|
+
5. **Ecosystem Understanding** → See how projects relate and complement
|
|
671
|
+
6. **Selection Criteria** → Choose based on needs, quality, and fit
|
|
672
|
+
|
|
673
|
+
**🎨 DOMAIN-SPECIFIC PROJECT DISCOVERY:**
|
|
674
|
+
- **CREATIVE DOMAIN**: Art tools, design systems, media processing, creative coding
|
|
675
|
+
- **BUSINESS DOMAIN**: Analytics, automation, productivity, management tools
|
|
676
|
+
- **RESEARCH DOMAIN**: Data analysis, visualization, computation, methodology
|
|
677
|
+
- **EDUCATIONAL DOMAIN**: Learning platforms, tutorials, knowledge sharing
|
|
678
|
+
- **SOCIAL DOMAIN**: Community tools, activism, social impact, collaboration
|
|
679
|
+
- **PERSONAL DOMAIN**: Productivity, wellness, lifestyle, skill development
|
|
680
|
+
|
|
681
|
+
**🌟 UNIVERSAL APPLICATIONS:**
|
|
682
|
+
- **Solution Discovery**: Find tools and projects for specific needs
|
|
683
|
+
- **Research Exploration**: Locate academic and experimental projects
|
|
684
|
+
- **Learning Resources**: Discover educational and tutorial projects
|
|
685
|
+
- **Community Building**: Find collaborative and open source initiatives
|
|
686
|
+
- **Innovation Inspiration**: Explore cutting-edge and experimental work
|
|
687
|
+
- **Quality Assessment**: Compare approaches, features, and implementations
|
|
688
|
+
|
|
689
|
+
**🔍 FALLBACK STRATEGIES:**
|
|
690
|
+
When repository search yields insufficient results:
|
|
691
|
+
1. **Package Discovery** → Find related tools and libraries
|
|
692
|
+
2. **Topic Exploration** → Understand domain terminology and trends
|
|
693
|
+
3. **Content Search** → Look for implementations and usage patterns
|
|
694
|
+
4. **Community Discovery** → Find experts and organizations
|
|
695
|
+
5. **Discussion Mining** → Explore problems and solutions
|
|
696
|
+
6. **Cross-Domain Bridging** → Look in adjacent fields and applications
|
|
697
|
+
|
|
698
|
+
**INPUT**: Any project need, concept, or area of interest across any domain
|
|
699
|
+
**OUTPUT**: Comprehensive project landscape with quality insights and recommendations`,
|
|
700
|
+
// Focused NPM tools for minimal token usage
|
|
701
|
+
[TOOL_NAMES.NPM_GET_REPOSITORY]: `**Repository discovery** - Extract GitHub repository URL and project description.
|
|
702
|
+
|
|
703
|
+
**MINIMAL OUTPUT:** Package name, description, repository URL, homepage - optimized for token efficiency.
|
|
704
|
+
|
|
705
|
+
**WHEN TO USE:** When you only need repository location for GitHub operations.
|
|
706
|
+
|
|
707
|
+
**INTEGRATION:** Perfect first step → ${TOOL_NAMES.GITHUB_GET_REPOSITORY} → Code exploration`,
|
|
708
|
+
[TOOL_NAMES.NPM_GET_DEPENDENCIES]: `**Dependency analysis** - Extract package dependencies tree.
|
|
709
|
+
|
|
710
|
+
**MINIMAL OUTPUT:** Dependencies, devDependencies, resolutions - focused dependency data only.
|
|
711
|
+
|
|
712
|
+
**WHEN TO USE:** When analyzing package ecosystem and compatibility.
|
|
713
|
+
|
|
714
|
+
**INTEGRATION:** Combine with ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} for security audit`,
|
|
715
|
+
[TOOL_NAMES.NPM_GET_BUGS]: `**Issue tracking** - Extract bug reporting information.
|
|
716
|
+
|
|
717
|
+
**MINIMAL OUTPUT:** Package name and bugs URL - direct access to issue tracker.
|
|
718
|
+
|
|
719
|
+
**WHEN TO USE:** When users need to report issues or check known problems.
|
|
720
|
+
|
|
721
|
+
**INTEGRATION:** Links to ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} for problem discovery`,
|
|
722
|
+
[TOOL_NAMES.NPM_GET_README]: `**Documentation access** - Extract README filename information.
|
|
723
|
+
|
|
724
|
+
**MINIMAL OUTPUT:** Package name and readme filename - efficient documentation lookup.
|
|
725
|
+
|
|
726
|
+
**WHEN TO USE:** When users need documentation without full package metadata.
|
|
727
|
+
|
|
728
|
+
**INTEGRATION:** Combine with ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT} for full README content`,
|
|
729
|
+
[TOOL_NAMES.NPM_GET_VERSIONS]: `**Official version tracking** - Extract production-ready semantic versions only.
|
|
730
|
+
|
|
731
|
+
**MINIMAL OUTPUT:** Official versions (major.minor.patch format), latest version, count - excludes alpha/beta/rc versions.
|
|
732
|
+
|
|
733
|
+
**WHEN TO USE:** Find stable versions for production deployment, analyze release cadence of stable releases.
|
|
734
|
+
|
|
735
|
+
**INTEGRATION:** Perfect for production planning - filters out experimental versions for reliable deployment decisions`,
|
|
736
|
+
[TOOL_NAMES.NPM_GET_AUTHOR]: `**Maintainer information** - Extract author and maintainer details.
|
|
737
|
+
|
|
738
|
+
**MINIMAL OUTPUT:** Author and maintainers list - focused ownership data.
|
|
739
|
+
|
|
740
|
+
**WHEN TO USE:** When users need to contact maintainers or assess project ownership.
|
|
741
|
+
|
|
742
|
+
**INTEGRATION:** Links to ${TOOL_NAMES.GITHUB_SEARCH_USERS} for developer discovery`,
|
|
743
|
+
[TOOL_NAMES.NPM_GET_LICENSE]: `**License compliance** - Extract package license information.
|
|
744
|
+
|
|
745
|
+
**MINIMAL OUTPUT:** Package name and license - essential legal compliance data.
|
|
746
|
+
|
|
747
|
+
**WHEN TO USE:** When users need quick license verification for legal compliance.
|
|
748
|
+
|
|
749
|
+
**INTEGRATION:** Essential for enterprise package evaluation workflows`,
|
|
750
|
+
[TOOL_NAMES.NPM_GET_HOMEPAGE]: `**Official documentation gateway** - Extract package homepage for comprehensive project resources.
|
|
275
751
|
|
|
276
|
-
**
|
|
752
|
+
**MINIMAL OUTPUT:** Package name and homepage URL - direct access to live documentation, tutorials, and demos.
|
|
277
753
|
|
|
278
|
-
**
|
|
754
|
+
**WHEN TO USE:** Access official docs, interactive examples, getting started guides, and project showcases.
|
|
279
755
|
|
|
280
|
-
**
|
|
756
|
+
**INTEGRATION:** Complements ${TOOL_NAMES.NPM_GET_REPOSITORY} - homepage often contains better docs than README`,
|
|
757
|
+
[TOOL_NAMES.NPM_GET_ID]: `**Precise package targeting** - Extract exact name@version for dependency management.
|
|
281
758
|
|
|
282
|
-
**
|
|
759
|
+
**MINIMAL OUTPUT:** Package name and _id (name@latestVersion format) - canonical package identifier for lockfiles.
|
|
283
760
|
|
|
284
|
-
**
|
|
285
|
-
[TOOL_NAMES.NPM_GET_PACKAGE_STATS]: `**Package maturity analysis** - Lifecycle assessment for package evaluation.
|
|
761
|
+
**WHEN TO USE:** Pin exact versions, resolve dependency conflicts, generate package-lock entries, version compatibility checks.
|
|
286
762
|
|
|
287
|
-
**
|
|
763
|
+
**INTEGRATION:** Critical for CI/CD pipelines, dependency auditing, and reproducible builds`,
|
|
764
|
+
[TOOL_NAMES.NPM_GET_RELEASES]: `**Recent releases tracker** - Get latest release activity and timeline data.
|
|
288
765
|
|
|
289
|
-
**
|
|
766
|
+
**MINIMAL OUTPUT:** Last modified, created date, version count, and last 10 releases - focused release intelligence.
|
|
290
767
|
|
|
291
|
-
**
|
|
768
|
+
**WHEN TO USE:** Track recent package activity, analyze release frequency, check latest versions and release dates.
|
|
292
769
|
|
|
293
|
-
**INTEGRATION:**
|
|
770
|
+
**INTEGRATION:** Essential for monitoring package updates - combine with ${TOOL_NAMES.NPM_GET_VERSIONS} for comprehensive version analysis`,
|
|
771
|
+
[TOOL_NAMES.NPM_GET_ENGINES]: `**Environment compatibility validator** - Prevent runtime conflicts before installation.
|
|
772
|
+
|
|
773
|
+
**MINIMAL OUTPUT:** Node.js version requirements, npm constraints - environment compatibility matrix.
|
|
774
|
+
|
|
775
|
+
**WHEN TO USE:** Pre-deployment validation, Docker image planning, Node.js upgrade decisions, CI/CD environment setup.
|
|
776
|
+
|
|
777
|
+
**INTEGRATION:** Prevents deployment failures - use before installation in production environments`,
|
|
778
|
+
[TOOL_NAMES.NPM_GET_EXPORTS]: `**Import path intelligence** - Discover available modules and import strategies.
|
|
779
|
+
|
|
780
|
+
**MINIMAL OUTPUT:** Export mappings, entry points, submodule paths - complete import guide for developers.
|
|
781
|
+
|
|
782
|
+
**WHEN TO USE:** Learn correct import syntax, discover tree-shakable exports, find submodules, optimize bundle size.
|
|
783
|
+
|
|
784
|
+
**INTEGRATION:** CRITICAL for ${TOOL_NAMES.GITHUB_SEARCH_CODE} - enables precise code search with accurate import paths`,
|
|
785
|
+
[TOOL_NAMES.API_STATUS_CHECK]: `**🛠️ CRITICAL FIRST STEP** - Comprehensive API readiness verification before research operations.
|
|
786
|
+
|
|
787
|
+
**ESSENTIAL PRE-RESEARCH VALIDATION:**
|
|
788
|
+
- **GitHub CLI Authentication**: Verifies user is logged in (gh auth status)
|
|
789
|
+
- **NPM Registry Connectivity**: Confirms npm ping successful
|
|
790
|
+
- **GitHub API Rate Limits**: Real-time quota analysis across all endpoints
|
|
791
|
+
|
|
792
|
+
**🔍 COMPREHENSIVE HEALTH CHECK:**
|
|
793
|
+
- **Authentication Status**: GitHub CLI login verification with username detection
|
|
794
|
+
- **Network Connectivity**: NPM registry accessibility and response validation
|
|
795
|
+
- **API Quota Analysis**: Core API, Search API, and Code Search remaining limits
|
|
796
|
+
- **Reset Time Tracking**: When exhausted APIs will restore quota
|
|
797
|
+
- **Usage Percentage**: Current consumption across all GitHub endpoints
|
|
798
|
+
|
|
799
|
+
**⚡ INTELLIGENT RESEARCH STRATEGY:**
|
|
800
|
+
- **Ready Status**: All systems operational for comprehensive research
|
|
801
|
+
- **Limited Status**: Reduced capacity - targeted searches recommended
|
|
802
|
+
- **Not Ready Status**: Authentication/quota issues require resolution
|
|
803
|
+
|
|
804
|
+
**🎯 RESEARCH GUIDANCE BASED ON API LIMITS:**
|
|
805
|
+
- **Code Search < 5**: Critical - use repository browsing instead of code search
|
|
806
|
+
- **Search API < 20**: Limited - focus on specific repositories vs broad searches
|
|
807
|
+
- **Core API < 200**: Constrained - minimize repository exploration operations
|
|
808
|
+
- **NPM Disconnected**: GitHub-only research mode activated
|
|
809
|
+
|
|
810
|
+
**🚀 SMART FALLBACK RECOMMENDATIONS:**
|
|
811
|
+
- **Authentication Issues**: Step-by-step gh auth login guidance
|
|
812
|
+
- **NPM Problems**: Alternative research paths using GitHub discovery
|
|
813
|
+
- **Rate Limit Exhaustion**: Wait times and alternative approaches
|
|
814
|
+
- **Network Issues**: Diagnostic commands and troubleshooting steps
|
|
815
|
+
|
|
816
|
+
**📊 REAL-TIME API INTELLIGENCE:**
|
|
817
|
+
- **Primary API**: Repository operations, issues, PRs, users (5000/hour)
|
|
818
|
+
- **Search API**: Repository/user/topic searches (30/minute)
|
|
819
|
+
- **Code Search**: Code content searches (10/minute) - most restrictive
|
|
820
|
+
- **Reset Schedules**: Precise timestamps for quota restoration
|
|
821
|
+
|
|
822
|
+
**✅ RESEARCH READINESS MATRIX:**
|
|
823
|
+
- **READY**: GitHub authenticated + NPM connected + healthy API limits
|
|
824
|
+
- **LIMITED**: Some constraints but research possible with guidance
|
|
825
|
+
- **NOT_READY**: Critical issues blocking research operations
|
|
826
|
+
|
|
827
|
+
**💡 PROACTIVE OPTIMIZATION:**
|
|
828
|
+
- **API Usage Prediction**: Warns before hitting limits during extensive research
|
|
829
|
+
- **Strategy Adaptation**: Automatically suggests efficient research patterns
|
|
830
|
+
- **Resource Conservation**: Identifies when to use cached vs live data
|
|
831
|
+
- **Batch Operation Planning**: Optimal timing for bulk research tasks
|
|
832
|
+
|
|
833
|
+
**WHEN TO USE:** ALWAYS call first before starting any research session to ensure optimal tool usage and prevent operation failures.
|
|
834
|
+
|
|
835
|
+
**INTEGRATION:** Sets research strategy for all subsequent GitHub and NPM tools based on current system status.`,
|
|
294
836
|
};
|
|
295
837
|
|
|
296
838
|
const cache = new NodeCache({
|
|
@@ -463,6 +1005,17 @@ async function executeGitHubCommand(command, args = [], options = {}) {
|
|
|
463
1005
|
return executeCommand();
|
|
464
1006
|
}
|
|
465
1007
|
|
|
1008
|
+
/**
|
|
1009
|
+
* Search GitHub code with organizational fallback strategy
|
|
1010
|
+
*
|
|
1011
|
+
* For internal company projects (like "Astra Nova" at Wix):
|
|
1012
|
+
* 1. Try direct code search first
|
|
1013
|
+
* 2. If no results, the calling code should implement fallback chain:
|
|
1014
|
+
* - searchGitHubCommits() for commit message references
|
|
1015
|
+
* - searchGitHubPullRequests() for PR mentions
|
|
1016
|
+
* - searchGitHubIssues() for issue discussions
|
|
1017
|
+
* 3. Extract repository info from any successful results
|
|
1018
|
+
*/
|
|
466
1019
|
async function searchGitHubCode(params) {
|
|
467
1020
|
const cacheKey = generateCacheKey('gh-code', params);
|
|
468
1021
|
return withCache(cacheKey, async () => {
|
|
@@ -541,6 +1094,18 @@ async function searchGitHubCode(params) {
|
|
|
541
1094
|
topMatches: analysis.topMatches.slice(0, 5),
|
|
542
1095
|
},
|
|
543
1096
|
};
|
|
1097
|
+
// Add organizational fallback guidance for zero results
|
|
1098
|
+
if (analysis.totalFound === 0 && params.owner) {
|
|
1099
|
+
searchResult.organizationalFallback = {
|
|
1100
|
+
suggestion: `No code matches found for "${params.query}" in ${params.owner}. Try organizational fallback strategy:`,
|
|
1101
|
+
fallbackSteps: [
|
|
1102
|
+
`Search commits: "${params.query}" with owner:${params.owner}`,
|
|
1103
|
+
`Search pull requests: "${params.query}" with owner:${params.owner}`,
|
|
1104
|
+
`Search issues: "${params.query}" with owner:${params.owner}`,
|
|
1105
|
+
'Extract repository references from any successful results',
|
|
1106
|
+
],
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
544
1109
|
return createSuccessResult$1(searchResult);
|
|
545
1110
|
}
|
|
546
1111
|
catch (parseError) {
|
|
@@ -686,84 +1251,387 @@ function buildGitHubCodeSearchCommand(params) {
|
|
|
686
1251
|
return { command: 'search', args };
|
|
687
1252
|
}
|
|
688
1253
|
|
|
689
|
-
//
|
|
1254
|
+
// Enhanced search pattern analysis with MANDATORY boolean operator suggestions
|
|
690
1255
|
function analyzeSearchPattern(args) {
|
|
691
1256
|
const suggestions = [];
|
|
692
1257
|
const warnings = [];
|
|
1258
|
+
const booleanRecommendations = [];
|
|
1259
|
+
const contextEnrichment = [];
|
|
693
1260
|
let patternType = 'basic';
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
1261
|
+
const query = args.query.toLowerCase();
|
|
1262
|
+
const hasBoolean = /\b(OR|AND|NOT)\b/i.test(args.query);
|
|
1263
|
+
// CRITICAL: Always recommend boolean operators if not present
|
|
1264
|
+
if (!hasBoolean) {
|
|
1265
|
+
warnings.push('CRITICAL: Query lacks boolean operators - efficiency reduced by 3-5x without them');
|
|
1266
|
+
warnings.push('MANDATORY: Add boolean operators (OR, AND, NOT) for maximum search efficiency');
|
|
1267
|
+
patternType = 'needs-boolean-enhancement';
|
|
698
1268
|
}
|
|
699
|
-
//
|
|
700
|
-
if (args.query.includes('
|
|
701
|
-
|
|
702
|
-
|
|
1269
|
+
// CRITICAL: Check for unsupported parentheses
|
|
1270
|
+
if (args.query.includes('(') || args.query.includes(')')) {
|
|
1271
|
+
warnings.push('CRITICAL: GitHub API does not support parentheses () in search queries');
|
|
1272
|
+
warnings.push('SOLUTION: Remove parentheses and use boolean operators: "term1 OR term2 AND term3"');
|
|
1273
|
+
patternType = 'unsupported-syntax';
|
|
1274
|
+
}
|
|
1275
|
+
// Check for overly complex queries
|
|
1276
|
+
const booleanOperatorCount = (args.query.match(/\b(OR|AND|NOT)\b/gi) || [])
|
|
1277
|
+
.length;
|
|
1278
|
+
const termCount = args.query.split(/\s+/).length;
|
|
1279
|
+
if (booleanOperatorCount > 3 || termCount > 8) {
|
|
1280
|
+
warnings.push('COMPLEXITY WARNING: Query may exceed GitHub API limits');
|
|
1281
|
+
warnings.push('RECOMMENDATION: Simplify to essential boolean operators (max 3-4 per query)');
|
|
1282
|
+
patternType = 'overly-complex';
|
|
1283
|
+
}
|
|
1284
|
+
// Enhanced Function signature patterns with MANDATORY boolean operators
|
|
1285
|
+
if (query.includes('function') || query.includes('export')) {
|
|
1286
|
+
patternType = 'function-discovery';
|
|
1287
|
+
suggestions.push('PROVEN BOOLEAN: "export OR function OR method OR class" → Comprehensive function discovery');
|
|
1288
|
+
booleanRecommendations.push('MANDATORY BOOLEAN: "export AND function OR method OR procedure" - captures all function types');
|
|
1289
|
+
booleanRecommendations.push('MANDATORY EXCLUSION: "function OR method NOT test NOT spec NOT mock" - production code only');
|
|
1290
|
+
booleanRecommendations.push('MANDATORY ASYNC: "async AND (function OR method) OR promise NOT example" - async patterns');
|
|
1291
|
+
contextEnrichment.push('BOOLEAN CONTEXT: "arrow OR lambda OR callback OR closure" for function variations');
|
|
703
1292
|
}
|
|
704
|
-
//
|
|
705
|
-
if (
|
|
1293
|
+
// Enhanced React/Component patterns with MANDATORY boolean operators
|
|
1294
|
+
if (query.includes('react') ||
|
|
1295
|
+
query.includes('component') ||
|
|
1296
|
+
query.includes('jsx')) {
|
|
706
1297
|
patternType = 'component-discovery';
|
|
707
|
-
suggestions.push('PROVEN: "
|
|
1298
|
+
suggestions.push('PROVEN BOOLEAN: "react AND (hooks OR components OR jsx) NOT test" → React ecosystem discovery');
|
|
1299
|
+
booleanRecommendations.push('MANDATORY HOOKS: "useState OR useEffect OR useContext OR useReducer" - comprehensive hook coverage');
|
|
1300
|
+
booleanRecommendations.push('MANDATORY COMPONENTS: "component OR jsx OR tsx OR react NOT test NOT story" - component patterns');
|
|
1301
|
+
booleanRecommendations.push('MANDATORY LIFECYCLE: "componentDidMount OR useEffect OR lifecycle NOT mock" - lifecycle methods');
|
|
1302
|
+
contextEnrichment.push('BOOLEAN CONTEXT: "props OR state OR render OR mount" for React-specific patterns');
|
|
1303
|
+
}
|
|
1304
|
+
// Authentication/Security patterns with MANDATORY boolean operators
|
|
1305
|
+
if (query.includes('auth') ||
|
|
1306
|
+
query.includes('login') ||
|
|
1307
|
+
query.includes('password') ||
|
|
1308
|
+
query.includes('token')) {
|
|
1309
|
+
patternType = 'security-discovery';
|
|
1310
|
+
booleanRecommendations.push('MANDATORY AUTH: "authentication OR auth OR login OR signin OR oauth" - comprehensive auth coverage');
|
|
1311
|
+
booleanRecommendations.push('MANDATORY TOKENS: "jwt OR token OR bearer OR session OR cookie" - token handling patterns');
|
|
1312
|
+
booleanRecommendations.push('MANDATORY SECURITY: "password OR hash OR encrypt OR decrypt NOT test NOT mock" - security implementations');
|
|
1313
|
+
contextEnrichment.push('BOOLEAN SECURITY: "middleware OR guard OR interceptor OR validation OR sanitize" for auth context');
|
|
1314
|
+
}
|
|
1315
|
+
// API/HTTP patterns with MANDATORY boolean operators
|
|
1316
|
+
if (query.includes('api') ||
|
|
1317
|
+
query.includes('http') ||
|
|
1318
|
+
query.includes('request') ||
|
|
1319
|
+
query.includes('fetch')) {
|
|
1320
|
+
patternType = 'api-discovery';
|
|
1321
|
+
booleanRecommendations.push('MANDATORY HTTP: "fetch OR axios OR request OR http OR api" - HTTP client coverage');
|
|
1322
|
+
booleanRecommendations.push('MANDATORY ENDPOINTS: "endpoint OR route OR handler OR controller NOT test" - API structure');
|
|
1323
|
+
booleanRecommendations.push('MANDATORY METHODS: "get OR post OR put OR delete OR patch" - HTTP methods');
|
|
1324
|
+
contextEnrichment.push('BOOLEAN API: "cors OR middleware OR validation OR serialization OR response" for API context');
|
|
1325
|
+
}
|
|
1326
|
+
// Database/Storage patterns with MANDATORY boolean operators
|
|
1327
|
+
if (query.includes('database') ||
|
|
1328
|
+
query.includes('db') ||
|
|
1329
|
+
query.includes('sql') ||
|
|
1330
|
+
query.includes('query')) {
|
|
1331
|
+
patternType = 'database-discovery';
|
|
1332
|
+
booleanRecommendations.push('MANDATORY CRUD: "insert OR update OR delete OR select OR create" - database operations');
|
|
1333
|
+
booleanRecommendations.push('MANDATORY DATABASES: "mongodb OR postgresql OR mysql OR sqlite OR redis" - database types');
|
|
1334
|
+
booleanRecommendations.push('MANDATORY ORM: "sequelize OR typeorm OR prisma OR mongoose OR knex" - ORM frameworks');
|
|
1335
|
+
}
|
|
1336
|
+
// Error handling patterns with MANDATORY boolean operators
|
|
1337
|
+
if (query.includes('error') ||
|
|
1338
|
+
query.includes('exception') ||
|
|
1339
|
+
query.includes('try') ||
|
|
1340
|
+
query.includes('catch')) {
|
|
1341
|
+
patternType = 'error-handling';
|
|
1342
|
+
booleanRecommendations.push('MANDATORY ERROR: "error OR exception OR catch OR throw OR reject" - error handling coverage');
|
|
1343
|
+
booleanRecommendations.push('MANDATORY PATTERNS: "try OR catch OR finally OR async OR await" - error patterns');
|
|
1344
|
+
booleanRecommendations.push('MANDATORY HANDLING: "handling OR recovery OR retry OR fallback NOT test" - error management');
|
|
1345
|
+
}
|
|
1346
|
+
// Testing patterns - suggest boolean exclusion
|
|
1347
|
+
if (query.includes('test') ||
|
|
1348
|
+
query.includes('spec') ||
|
|
1349
|
+
query.includes('mock')) {
|
|
1350
|
+
if (!query.includes('NOT')) {
|
|
1351
|
+
booleanRecommendations.push('MANDATORY EXCLUSION: Add "NOT test NOT spec NOT mock" to focus on production code');
|
|
1352
|
+
booleanRecommendations.push('BOOLEAN ALTERNATIVE: Use "production OR live OR deploy NOT test" for real implementations');
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
// Generic single-term queries - MANDATORY boolean enhancement
|
|
1356
|
+
const words = query.split(/\s+/).filter(w => w.length > 2);
|
|
1357
|
+
if (words.length === 1 && !hasBoolean && words[0].length > 3) {
|
|
1358
|
+
booleanRecommendations.push(`MANDATORY VARIATIONS: "${words[0]} OR ${words[0]}s OR ${words[0]}ing" - capture all variations`);
|
|
1359
|
+
booleanRecommendations.push(`MANDATORY EXCLUSION: "${words[0]} NOT test NOT spec NOT example" - production focus`);
|
|
1360
|
+
booleanRecommendations.push(`MANDATORY CONTEXT: "${words[0]} OR related_term OR synonym" - comprehensive coverage`);
|
|
1361
|
+
}
|
|
1362
|
+
// Boolean operator patterns (existing logic enhanced)
|
|
1363
|
+
if (hasBoolean) {
|
|
1364
|
+
patternType = 'boolean-search';
|
|
1365
|
+
suggestions.push('EXCELLENT: Boolean operators detected - proven 3-5x more efficient than simple text');
|
|
1366
|
+
suggestions.push('PROVEN PATTERNS: "useState OR useEffect" ✅, "function NOT test" ✅, "async AND await" ✅');
|
|
708
1367
|
}
|
|
709
|
-
// Path filter validation (
|
|
1368
|
+
// Path filter validation (enhanced with boolean recommendations)
|
|
710
1369
|
if (args.path === 'src' && !args.repo) {
|
|
711
1370
|
warnings.push('CRITICAL: path:src may fail - many repos use path:packages, path:lib instead');
|
|
712
|
-
suggestions.push('PROVEN PATHS:
|
|
1371
|
+
suggestions.push('PROVEN BOOLEAN PATHS: "react AND hooks" with path:packages, NOT path:src');
|
|
1372
|
+
contextEnrichment.push('BOOLEAN PATH ALTERNATIVES: Try boolean queries without path filters first');
|
|
1373
|
+
}
|
|
1374
|
+
// Language-specific boolean enhancements
|
|
1375
|
+
if (args.language) {
|
|
1376
|
+
const lang = args.language.toLowerCase();
|
|
1377
|
+
if (lang === 'typescript' || lang === 'javascript') {
|
|
1378
|
+
contextEnrichment.push('BOOLEAN JS/TS: "interface OR type OR class OR function OR const OR let" for comprehensive coverage');
|
|
1379
|
+
}
|
|
1380
|
+
else if (lang === 'python') {
|
|
1381
|
+
contextEnrichment.push('BOOLEAN PYTHON: "def OR class OR import OR async OR lambda" for Python patterns');
|
|
1382
|
+
}
|
|
1383
|
+
else if (lang === 'java') {
|
|
1384
|
+
contextEnrichment.push('BOOLEAN JAVA: "public OR private OR class OR interface OR method" for Java patterns');
|
|
1385
|
+
}
|
|
713
1386
|
}
|
|
714
|
-
// Cross-repository patterns (
|
|
1387
|
+
// Cross-repository patterns (enhanced with boolean emphasis)
|
|
715
1388
|
if (!args.owner && !args.repo && args.query.includes('async')) {
|
|
716
1389
|
patternType = 'cross-repo-discovery';
|
|
717
|
-
suggestions.push('PROVEN: "async function
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
.
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
.
|
|
729
|
-
.
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
.
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
.
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
.
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
.
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1390
|
+
suggestions.push('PROVEN BOOLEAN GLOBAL: "async AND (function OR method) OR promise" finds comprehensive async patterns');
|
|
1391
|
+
contextEnrichment.push('BOOLEAN CROSS-REPO: Global boolean searches excel for common patterns like "error OR exception"');
|
|
1392
|
+
}
|
|
1393
|
+
// Zero results prediction with boolean solutions
|
|
1394
|
+
if (query.length > 50 || query.split(' ').length > 8) {
|
|
1395
|
+
warnings.push('COMPLEXITY WARNING: Very long/complex queries often return 0 results');
|
|
1396
|
+
booleanRecommendations.push('MANDATORY SIMPLIFICATION: Break into essential boolean terms: "term1 OR term2 NOT test"');
|
|
1397
|
+
booleanRecommendations.push('BOOLEAN STRATEGY: Use progressive boolean refinement instead of complex phrases');
|
|
1398
|
+
}
|
|
1399
|
+
// ALWAYS add mandatory boolean recommendations if none exist
|
|
1400
|
+
if (booleanRecommendations.length === 0) {
|
|
1401
|
+
booleanRecommendations.push('MANDATORY: Add boolean operators for 3-5x better efficiency: "term1 OR term2 NOT test"');
|
|
1402
|
+
booleanRecommendations.push('PROVEN PATTERN: Use "primary_term OR synonym OR variation NOT noise" structure');
|
|
1403
|
+
}
|
|
1404
|
+
return {
|
|
1405
|
+
patternType,
|
|
1406
|
+
suggestions,
|
|
1407
|
+
warnings,
|
|
1408
|
+
booleanRecommendations,
|
|
1409
|
+
contextEnrichment,
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
// NEW: Smart query simplification for GitHub API compatibility
|
|
1413
|
+
function simplifyComplexQuery(query) {
|
|
1414
|
+
const fallbackQueries = [];
|
|
1415
|
+
// Remove parentheses - GitHub doesn't support them
|
|
1416
|
+
const simplified = query.replace(/[()]/g, '');
|
|
1417
|
+
// If query has parentheses, create simplified version
|
|
1418
|
+
if (query.includes('(') || query.includes(')')) {
|
|
1419
|
+
fallbackQueries.push(simplified);
|
|
1420
|
+
}
|
|
1421
|
+
// Extract main terms and create progressive simplifications
|
|
1422
|
+
const terms = simplified
|
|
1423
|
+
.split(/\s+/)
|
|
1424
|
+
.filter(term => !['AND', 'OR', 'NOT'].includes(term.toUpperCase()));
|
|
1425
|
+
// Strategy 1: Keep only OR operations (most permissive)
|
|
1426
|
+
const orTerms = [];
|
|
1427
|
+
const parts = simplified.split(/\s+/);
|
|
1428
|
+
for (let i = 0; i < parts.length; i++) {
|
|
1429
|
+
if (parts[i].toUpperCase() === 'OR' && i > 0 && i < parts.length - 1) {
|
|
1430
|
+
orTerms.push(parts[i - 1], 'OR', parts[i + 1]);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
if (orTerms.length > 0) {
|
|
1434
|
+
fallbackQueries.push(orTerms.join(' '));
|
|
1435
|
+
}
|
|
1436
|
+
// Strategy 2: Take first 2-3 most important terms
|
|
1437
|
+
if (terms.length >= 2) {
|
|
1438
|
+
fallbackQueries.push(`${terms[0]} OR ${terms[1]}`);
|
|
1439
|
+
}
|
|
1440
|
+
// Strategy 3: Single most specific term
|
|
1441
|
+
const specificTerms = terms.filter(term => term.length > 4 &&
|
|
1442
|
+
!['function', 'class', 'import', 'export'].includes(term.toLowerCase()));
|
|
1443
|
+
if (specificTerms.length > 0) {
|
|
1444
|
+
fallbackQueries.push(specificTerms[0]);
|
|
1445
|
+
}
|
|
1446
|
+
// Strategy 4: Fallback to first term
|
|
1447
|
+
if (terms.length > 0) {
|
|
1448
|
+
fallbackQueries.push(terms[0]);
|
|
1449
|
+
}
|
|
1450
|
+
// Remove duplicates and return unique fallbacks
|
|
1451
|
+
return [...new Set(fallbackQueries)];
|
|
1452
|
+
}
|
|
1453
|
+
// NEW: Safe JSON parsing with error recovery
|
|
1454
|
+
function safeParseJSON(text) {
|
|
1455
|
+
try {
|
|
1456
|
+
const parsed = JSON.parse(text);
|
|
1457
|
+
return { success: true, data: parsed };
|
|
1458
|
+
}
|
|
1459
|
+
catch (error) {
|
|
1460
|
+
try {
|
|
1461
|
+
// Try parsing as double-encoded JSON
|
|
1462
|
+
const doubleParsed = JSON.parse(JSON.parse(text));
|
|
1463
|
+
return { success: true, data: doubleParsed };
|
|
1464
|
+
}
|
|
1465
|
+
catch (secondError) {
|
|
1466
|
+
return {
|
|
1467
|
+
success: false,
|
|
1468
|
+
error: error instanceof Error ? error.message : 'JSON parsing failed',
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
// Enhanced query optimization for better results - BOOLEAN OPERATORS ALWAYS REQUIRED
|
|
1474
|
+
function optimizeQuery(args) {
|
|
1475
|
+
const original = args.query;
|
|
1476
|
+
const optimized = [];
|
|
1477
|
+
const rationale = [];
|
|
1478
|
+
const fallbackQueries = [];
|
|
1479
|
+
// Check for unsupported syntax first
|
|
1480
|
+
if (original.includes('(') || original.includes(')')) {
|
|
1481
|
+
const simplified = simplifyComplexQuery(original);
|
|
1482
|
+
fallbackQueries.push(...simplified);
|
|
1483
|
+
rationale.push('Removed unsupported parentheses and created boolean fallback queries');
|
|
1484
|
+
}
|
|
1485
|
+
// MANDATORY: Always ensure boolean operators are used for maximum efficiency
|
|
1486
|
+
const hasBoolean = /\b(OR|AND|NOT)\b/i.test(original);
|
|
1487
|
+
if (!hasBoolean) {
|
|
1488
|
+
// CRITICAL: Inject boolean operators for maximum efficiency
|
|
1489
|
+
const words = original
|
|
1490
|
+
.trim()
|
|
1491
|
+
.split(/\s+/)
|
|
1492
|
+
.filter(w => w.length > 2);
|
|
1493
|
+
if (words.length === 1) {
|
|
1494
|
+
const word = words[0];
|
|
1495
|
+
// Always create boolean variations for single terms
|
|
1496
|
+
optimized.push(`${word} OR ${word}s OR ${word}ing`);
|
|
1497
|
+
rationale.push('MANDATORY: Added boolean variations for comprehensive coverage (3-5x more efficient)');
|
|
1498
|
+
optimized.push(`${word} NOT test NOT spec NOT mock`);
|
|
1499
|
+
rationale.push('MANDATORY: Added boolean exclusions to focus on production code');
|
|
1500
|
+
// Add semantic boolean expansions based on common patterns
|
|
1501
|
+
if (word.toLowerCase().includes('react')) {
|
|
1502
|
+
optimized.push(`${word} OR reactjs OR react.js NOT example`);
|
|
1503
|
+
rationale.push('MANDATORY: Added React-specific boolean variations');
|
|
1504
|
+
}
|
|
1505
|
+
else if (word.toLowerCase().includes('auth')) {
|
|
1506
|
+
optimized.push(`${word} OR authentication OR login OR signin NOT test`);
|
|
1507
|
+
rationale.push('MANDATORY: Added authentication boolean variations');
|
|
1508
|
+
}
|
|
1509
|
+
else if (word.toLowerCase().includes('function')) {
|
|
1510
|
+
optimized.push(`${word} OR method OR procedure OR class NOT test`);
|
|
1511
|
+
rationale.push('MANDATORY: Added function-related boolean variations');
|
|
1512
|
+
}
|
|
1513
|
+
else if (word.toLowerCase().includes('error')) {
|
|
1514
|
+
optimized.push(`${word} OR exception OR catch OR handling NOT mock`);
|
|
1515
|
+
rationale.push('MANDATORY: Added error-handling boolean variations');
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
else if (words.length >= 2 && words.length <= 4) {
|
|
1519
|
+
// MANDATORY: Convert multi-word queries to boolean
|
|
1520
|
+
optimized.push(words.join(' OR '));
|
|
1521
|
+
rationale.push('MANDATORY: Converted to OR boolean for comprehensive coverage (proven 3-5x more efficient)');
|
|
1522
|
+
optimized.push(`${words.join(' AND ')} NOT test NOT spec`);
|
|
1523
|
+
rationale.push('MANDATORY: Added AND boolean with exclusions for precise targeting');
|
|
1524
|
+
// Create semantic boolean combinations
|
|
1525
|
+
if (words.some(w => w.toLowerCase().includes('react'))) {
|
|
1526
|
+
const reactTerms = words.filter(w => !w.toLowerCase().includes('react'));
|
|
1527
|
+
optimized.push(`react AND (${reactTerms.join(' OR ')}) NOT example NOT tutorial`);
|
|
1528
|
+
rationale.push('MANDATORY: Created React-specific boolean combination');
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
else if (words.length > 4) {
|
|
1532
|
+
// MANDATORY: Simplify complex queries with boolean operators
|
|
1533
|
+
const primaryTerms = words.slice(0, 3);
|
|
1534
|
+
optimized.push(`${primaryTerms.join(' OR ')} NOT test`);
|
|
1535
|
+
rationale.push('MANDATORY: Simplified to essential boolean terms (complex queries often fail)');
|
|
1536
|
+
optimized.push(`${primaryTerms[0]} AND ${primaryTerms[1]} NOT mock NOT spec`);
|
|
1537
|
+
rationale.push('MANDATORY: Created focused boolean combination from key terms');
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
else {
|
|
1541
|
+
// Query already has boolean operators - validate and enhance
|
|
1542
|
+
const booleanCount = (original.match(/\b(OR|AND|NOT)\b/gi) || []).length;
|
|
1543
|
+
if (booleanCount > 3) {
|
|
1544
|
+
const simplified = simplifyComplexQuery(original);
|
|
1545
|
+
fallbackQueries.push(...simplified);
|
|
1546
|
+
rationale.push('MANDATORY: Boolean query too complex - created simplified boolean fallbacks');
|
|
1547
|
+
}
|
|
1548
|
+
else {
|
|
1549
|
+
optimized.push(original);
|
|
1550
|
+
rationale.push('MANDATORY: Boolean complexity acceptable - using optimized boolean query');
|
|
1551
|
+
// Always add enhanced boolean variations even for existing boolean queries
|
|
1552
|
+
const words = original
|
|
1553
|
+
.split(/\s+/)
|
|
1554
|
+
.filter(w => w.length > 3 && !['AND', 'OR', 'NOT'].includes(w.toUpperCase()));
|
|
1555
|
+
if (words.length >= 2) {
|
|
1556
|
+
// Add alternative boolean combinations
|
|
1557
|
+
optimized.push(`${words[0]} OR ${words[1]} NOT test NOT example`);
|
|
1558
|
+
rationale.push('MANDATORY: Added alternative boolean combination for broader coverage');
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
// MANDATORY: Always ensure we have boolean fallbacks
|
|
1563
|
+
if (optimized.length === 0 && fallbackQueries.length === 0) {
|
|
1564
|
+
const words = original.split(/\s+/).filter(w => w.length > 2);
|
|
1565
|
+
if (words.length > 0) {
|
|
1566
|
+
optimized.push(`${words[0]} OR ${words[0]}s NOT test`);
|
|
1567
|
+
rationale.push('MANDATORY: Created essential boolean query as fallback');
|
|
1568
|
+
}
|
|
1569
|
+
else {
|
|
1570
|
+
optimized.push(original);
|
|
1571
|
+
rationale.push('MANDATORY: Preserved original query (boolean enhancement not possible)');
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
return {
|
|
1575
|
+
originalQuery: original,
|
|
1576
|
+
optimizedQueries: optimized,
|
|
1577
|
+
rationale,
|
|
1578
|
+
fallbackQueries,
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
765
1581
|
function registerGitHubSearchCodeTool(server) {
|
|
766
|
-
server.tool(TOOL_NAMES.GITHUB_SEARCH_CODE, TOOL_DESCRIPTIONS[TOOL_NAMES.GITHUB_SEARCH_CODE],
|
|
1582
|
+
server.tool(TOOL_NAMES.GITHUB_SEARCH_CODE, TOOL_DESCRIPTIONS[TOOL_NAMES.GITHUB_SEARCH_CODE], {
|
|
1583
|
+
query: z
|
|
1584
|
+
.string()
|
|
1585
|
+
.min(1, 'Query cannot be empty')
|
|
1586
|
+
.describe('Search query for code. Use GitHub search syntax like repo:owner/name, language:javascript, path:*.js, or simple keywords. Boolean operators (OR, AND, NOT) are highly recommended for better results.'),
|
|
1587
|
+
owner: z
|
|
1588
|
+
.string()
|
|
1589
|
+
.optional()
|
|
1590
|
+
.describe('Repository owner/organization (e.g., "facebook", "microsoft"). Leave empty for global searches.'),
|
|
1591
|
+
repo: z
|
|
1592
|
+
.array(z.string())
|
|
1593
|
+
.optional()
|
|
1594
|
+
.describe('Repository names (e.g., ["react", "vscode"]). Requires owner parameter.'),
|
|
1595
|
+
extension: z
|
|
1596
|
+
.string()
|
|
1597
|
+
.optional()
|
|
1598
|
+
.describe('File extension to filter by (e.g., "js", "ts", "py").'),
|
|
1599
|
+
filename: z
|
|
1600
|
+
.string()
|
|
1601
|
+
.optional()
|
|
1602
|
+
.describe('Exact filename to search for (e.g., "package.json", "README.md").'),
|
|
1603
|
+
language: z
|
|
1604
|
+
.string()
|
|
1605
|
+
.optional()
|
|
1606
|
+
.describe('Programming language to filter by (e.g., "javascript", "typescript", "python").'),
|
|
1607
|
+
path: z
|
|
1608
|
+
.string()
|
|
1609
|
+
.optional()
|
|
1610
|
+
.describe('Path pattern to filter by (e.g., "src", "lib", "*.js", "/src/**/*.ts").'),
|
|
1611
|
+
limit: z
|
|
1612
|
+
.number()
|
|
1613
|
+
.int()
|
|
1614
|
+
.min(1)
|
|
1615
|
+
.max(100)
|
|
1616
|
+
.optional()
|
|
1617
|
+
.default(30)
|
|
1618
|
+
.describe('Maximum number of results to return (default: 30, max: 100).'),
|
|
1619
|
+
match: z.enum(['file', 'path']).optional().describe('Search scope'),
|
|
1620
|
+
branch: z
|
|
1621
|
+
.string()
|
|
1622
|
+
.optional()
|
|
1623
|
+
.describe('Branch for workflow documentation (required but not used by CLI)'),
|
|
1624
|
+
size: z
|
|
1625
|
+
.string()
|
|
1626
|
+
.optional()
|
|
1627
|
+
.describe('Filter on file size range, in kilobytes (e.g., ">1", "<50")'),
|
|
1628
|
+
// New parameter for query optimization
|
|
1629
|
+
enableQueryOptimization: z
|
|
1630
|
+
.boolean()
|
|
1631
|
+
.optional()
|
|
1632
|
+
.default(true)
|
|
1633
|
+
.describe('Enable automatic query optimization with boolean operators for better results (default: true)'),
|
|
1634
|
+
}, {
|
|
767
1635
|
title: 'GitHub Code Search',
|
|
768
1636
|
readOnlyHint: true,
|
|
769
1637
|
destructiveHint: false,
|
|
@@ -771,7 +1639,7 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
771
1639
|
openWorldHint: true,
|
|
772
1640
|
}, async (args) => {
|
|
773
1641
|
try {
|
|
774
|
-
//
|
|
1642
|
+
// Enhanced validation
|
|
775
1643
|
if (args.repo && !args.owner) {
|
|
776
1644
|
return {
|
|
777
1645
|
content: [
|
|
@@ -783,19 +1651,177 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
783
1651
|
isError: true,
|
|
784
1652
|
};
|
|
785
1653
|
}
|
|
786
|
-
//
|
|
1654
|
+
// Enhanced pattern analysis
|
|
787
1655
|
const patternAnalysis = analyzeSearchPattern(args);
|
|
788
|
-
|
|
789
|
-
|
|
1656
|
+
// Query optimization with fallbacks
|
|
1657
|
+
const queryOptimization = optimizeQuery(args);
|
|
1658
|
+
let result = null;
|
|
1659
|
+
let usedOptimizedQuery = false;
|
|
1660
|
+
let usedFallbackQuery = false;
|
|
1661
|
+
let finalQuery = args.query;
|
|
1662
|
+
const attemptedQueries = [];
|
|
1663
|
+
// Strategy 1: Try original query first (unless it has known issues)
|
|
1664
|
+
const hasUnsupportedSyntax = args.query.includes('(') || args.query.includes(')');
|
|
1665
|
+
const isOverlyComplex = (args.query.match(/\b(OR|AND|NOT)\b/gi) || []).length > 3;
|
|
1666
|
+
if (!hasUnsupportedSyntax && !isOverlyComplex) {
|
|
1667
|
+
try {
|
|
1668
|
+
result = await searchGitHubCode(args);
|
|
1669
|
+
attemptedQueries.push(args.query);
|
|
1670
|
+
// Validate result with safe JSON parsing
|
|
1671
|
+
if (result.content && result.content[0]) {
|
|
1672
|
+
const parseResult = safeParseJSON(result.content[0].text);
|
|
1673
|
+
if (!parseResult.success) {
|
|
1674
|
+
throw new Error(`JSON parsing failed: ${parseResult.error}`);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
catch (error) {
|
|
1679
|
+
console.warn(`Original query failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1680
|
+
result = null; // Will trigger fallback
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
// Strategy 2: Try optimized queries if original failed or returned minimal results
|
|
1684
|
+
if (!result &&
|
|
1685
|
+
args.enableQueryOptimization !== false &&
|
|
1686
|
+
queryOptimization.optimizedQueries.length > 0) {
|
|
1687
|
+
for (const optimizedQuery of queryOptimization.optimizedQueries) {
|
|
1688
|
+
if (optimizedQuery === args.query)
|
|
1689
|
+
continue; // Skip if same as original
|
|
1690
|
+
try {
|
|
1691
|
+
const optimizedArgs = { ...args, query: optimizedQuery };
|
|
1692
|
+
const optimizedResult = await searchGitHubCode(optimizedArgs);
|
|
1693
|
+
attemptedQueries.push(optimizedQuery);
|
|
1694
|
+
if (optimizedResult.content && optimizedResult.content[0]) {
|
|
1695
|
+
const parseResult = safeParseJSON(optimizedResult.content[0].text);
|
|
1696
|
+
if (parseResult.success) {
|
|
1697
|
+
result = optimizedResult;
|
|
1698
|
+
usedOptimizedQuery = true;
|
|
1699
|
+
finalQuery = optimizedQuery;
|
|
1700
|
+
break;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
catch (error) {
|
|
1705
|
+
console.warn(`Optimized query failed: ${optimizedQuery} - ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1706
|
+
continue;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
// Strategy 3: Try fallback queries for complex/unsupported syntax
|
|
1711
|
+
if (!result && queryOptimization.fallbackQueries.length > 0) {
|
|
1712
|
+
for (const fallbackQuery of queryOptimization.fallbackQueries) {
|
|
1713
|
+
try {
|
|
1714
|
+
const fallbackArgs = { ...args, query: fallbackQuery };
|
|
1715
|
+
const fallbackResult = await searchGitHubCode(fallbackArgs);
|
|
1716
|
+
attemptedQueries.push(fallbackQuery);
|
|
1717
|
+
if (fallbackResult.content && fallbackResult.content[0]) {
|
|
1718
|
+
const parseResult = safeParseJSON(fallbackResult.content[0].text);
|
|
1719
|
+
if (parseResult.success) {
|
|
1720
|
+
result = fallbackResult;
|
|
1721
|
+
usedFallbackQuery = true;
|
|
1722
|
+
finalQuery = fallbackQuery;
|
|
1723
|
+
break;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
catch (error) {
|
|
1728
|
+
console.warn(`Fallback query failed: ${fallbackQuery} - ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
// Strategy 4: Last resort - try single term from original query
|
|
1734
|
+
if (!result) {
|
|
1735
|
+
const terms = args.query
|
|
1736
|
+
.split(/\s+/)
|
|
1737
|
+
.filter(term => term.length > 3 &&
|
|
1738
|
+
!['AND', 'OR', 'NOT'].includes(term.toUpperCase()));
|
|
1739
|
+
if (terms.length > 0) {
|
|
1740
|
+
try {
|
|
1741
|
+
const lastResortArgs = { ...args, query: terms[0] };
|
|
1742
|
+
const lastResortResult = await searchGitHubCode(lastResortArgs);
|
|
1743
|
+
attemptedQueries.push(terms[0]);
|
|
1744
|
+
if (lastResortResult.content && lastResortResult.content[0]) {
|
|
1745
|
+
const parseResult = safeParseJSON(lastResortResult.content[0].text);
|
|
1746
|
+
if (parseResult.success) {
|
|
1747
|
+
result = lastResortResult;
|
|
1748
|
+
usedFallbackQuery = true;
|
|
1749
|
+
finalQuery = terms[0];
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
catch (error) {
|
|
1754
|
+
console.warn(`Last resort query failed: ${terms[0]} - ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
// If we still don't have a result, return comprehensive error
|
|
1759
|
+
if (!result) {
|
|
1760
|
+
return {
|
|
1761
|
+
content: [
|
|
1762
|
+
{
|
|
1763
|
+
type: 'text',
|
|
1764
|
+
text: `🚨 ALL QUERY STRATEGIES FAILED
|
|
1765
|
+
|
|
1766
|
+
📋 ATTEMPTED QUERIES:
|
|
1767
|
+
${attemptedQueries.map(q => `• "${q}"`).join('\n')}
|
|
1768
|
+
|
|
1769
|
+
🔧 INTELLIGENT FALLBACK RECOMMENDATIONS:
|
|
1770
|
+
• SIMPLIFY: Try single keywords like "useState", "function", "class"
|
|
1771
|
+
• REMOVE SYNTAX: Avoid parentheses () - GitHub API doesn't support them
|
|
1772
|
+
• REDUCE COMPLEXITY: Use max 2-3 boolean operators (OR, AND, NOT)
|
|
1773
|
+
• SPECIFIC TERMS: Use concrete terms instead of abstract concepts
|
|
1774
|
+
• REPOSITORY SCOPE: Add owner/repo parameters to narrow search
|
|
1775
|
+
|
|
1776
|
+
💡 PROVEN WORKING PATTERNS:
|
|
1777
|
+
• "useState OR useEffect" ✅
|
|
1778
|
+
• "function NOT test" ✅
|
|
1779
|
+
• "async function" ✅
|
|
1780
|
+
• "export default" ✅
|
|
1781
|
+
|
|
1782
|
+
⚠️ AVOID THESE PATTERNS:
|
|
1783
|
+
• "(term1 OR term2) AND term3" ❌ (parentheses not supported)
|
|
1784
|
+
• Complex nested boolean logic ❌
|
|
1785
|
+
• Very long queries (>50 characters) ❌`,
|
|
1786
|
+
},
|
|
1787
|
+
],
|
|
1788
|
+
isError: true,
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
// Enhance successful result with comprehensive insights
|
|
790
1792
|
if (result.content && result.content[0]) {
|
|
791
1793
|
let responseText = result.content[0].text;
|
|
1794
|
+
// Add query transformation info
|
|
1795
|
+
if (usedOptimizedQuery || usedFallbackQuery) {
|
|
1796
|
+
responseText += `\n\n🔄 QUERY TRANSFORMATION APPLIED:`;
|
|
1797
|
+
responseText += `\n• Original: "${args.query}"`;
|
|
1798
|
+
responseText += `\n• Used: "${finalQuery}"`;
|
|
1799
|
+
responseText += `\n• Strategy: ${usedFallbackQuery ? 'Fallback (syntax/complexity issues)' : 'Optimization'}`;
|
|
1800
|
+
if (attemptedQueries.length > 1) {
|
|
1801
|
+
responseText += `\n• Attempts: ${attemptedQueries.length} queries tried`;
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
792
1804
|
// Add pattern-specific insights
|
|
793
1805
|
if (patternAnalysis.suggestions.length > 0) {
|
|
794
|
-
responseText += `\n\n🎯
|
|
1806
|
+
responseText += `\n\n🎯 PATTERN INSIGHTS (${patternAnalysis.patternType.toUpperCase()}):`;
|
|
795
1807
|
patternAnalysis.suggestions.forEach(suggestion => {
|
|
796
1808
|
responseText += `\n• ${suggestion}`;
|
|
797
1809
|
});
|
|
798
1810
|
}
|
|
1811
|
+
// Add boolean operator recommendations
|
|
1812
|
+
if (patternAnalysis.booleanRecommendations.length > 0) {
|
|
1813
|
+
responseText += `\n\n🔍 BOOLEAN OPERATOR RECOMMENDATIONS:`;
|
|
1814
|
+
patternAnalysis.booleanRecommendations.forEach(rec => {
|
|
1815
|
+
responseText += `\n• ${rec}`;
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
// Add context enrichment suggestions
|
|
1819
|
+
if (patternAnalysis.contextEnrichment.length > 0) {
|
|
1820
|
+
responseText += `\n\n💡 CONTEXT ENRICHMENT SUGGESTIONS:`;
|
|
1821
|
+
patternAnalysis.contextEnrichment.forEach(context => {
|
|
1822
|
+
responseText += `\n• ${context}`;
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
799
1825
|
// Add critical warnings
|
|
800
1826
|
if (patternAnalysis.warnings.length > 0) {
|
|
801
1827
|
responseText += `\n\n⚠️ CRITICAL WARNINGS:`;
|
|
@@ -803,14 +1829,24 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
803
1829
|
responseText += `\n• ${warning}`;
|
|
804
1830
|
});
|
|
805
1831
|
}
|
|
806
|
-
//
|
|
807
|
-
responseText += `\n\n📋
|
|
808
|
-
responseText += `\n•
|
|
809
|
-
responseText += `\n•
|
|
810
|
-
responseText += `\n•
|
|
811
|
-
responseText += `\n•
|
|
1832
|
+
// Enhanced best practices with GitHub API limitations
|
|
1833
|
+
responseText += `\n\n📋 GITHUB API SEARCH BEST PRACTICES:`;
|
|
1834
|
+
responseText += `\n• ✅ SUPPORTED: "useState OR useEffect", "function NOT test"`;
|
|
1835
|
+
responseText += `\n• ❌ NOT SUPPORTED: "(useState OR useEffect) AND typescript" (parentheses)`;
|
|
1836
|
+
responseText += `\n• ⚠️ COMPLEXITY LIMIT: Max 3-4 boolean operators per query`;
|
|
1837
|
+
responseText += `\n• 🎯 PATTERN MATCHING: "async function" vs "function.*async"`;
|
|
1838
|
+
responseText += `\n• 🚫 EXCLUDE NOISE: "auth NOT mock NOT test" for production code`;
|
|
1839
|
+
responseText += `\n• 🔄 VARIATION COVERAGE: "login OR signin OR authenticate"`;
|
|
812
1840
|
if (!args.owner && !args.repo) {
|
|
813
|
-
responseText += `\n•
|
|
1841
|
+
responseText += `\n• 🌐 GLOBAL SEARCH: Works well for common patterns across repositories`;
|
|
1842
|
+
}
|
|
1843
|
+
// Add alternative query suggestions
|
|
1844
|
+
if (queryOptimization.fallbackQueries.length > 0 &&
|
|
1845
|
+
!usedFallbackQuery) {
|
|
1846
|
+
responseText += `\n\n🔄 ALTERNATIVE QUERY SUGGESTIONS:`;
|
|
1847
|
+
queryOptimization.fallbackQueries.forEach(query => {
|
|
1848
|
+
responseText += `\n• "${query}" - Simplified version for better compatibility`;
|
|
1849
|
+
});
|
|
814
1850
|
}
|
|
815
1851
|
return {
|
|
816
1852
|
content: [
|
|
@@ -825,20 +1861,65 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
825
1861
|
return result;
|
|
826
1862
|
}
|
|
827
1863
|
catch (error) {
|
|
828
|
-
// Enhanced error handling with
|
|
1864
|
+
// Enhanced error handling with intelligent suggestions
|
|
829
1865
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1866
|
+
// Detect specific error types
|
|
1867
|
+
let errorType = 'general';
|
|
1868
|
+
let specificSuggestions = '';
|
|
1869
|
+
if (errorMessage.includes('JSON') || errorMessage.includes('parse')) {
|
|
1870
|
+
errorType = 'json-parsing';
|
|
1871
|
+
specificSuggestions = `
|
|
1872
|
+
🔧 JSON PARSING ERROR SOLUTIONS:
|
|
1873
|
+
• QUERY SIMPLIFICATION: Remove complex boolean logic
|
|
1874
|
+
• SYNTAX CHECK: Avoid parentheses () in queries
|
|
1875
|
+
• RETRY STRATEGY: Try single keywords instead of complex queries`;
|
|
1876
|
+
}
|
|
1877
|
+
else if (errorMessage.includes('API') ||
|
|
1878
|
+
errorMessage.includes('rate')) {
|
|
1879
|
+
errorType = 'api-limit';
|
|
1880
|
+
specificSuggestions = `
|
|
1881
|
+
🔧 API LIMIT SOLUTIONS:
|
|
1882
|
+
• REDUCE FREQUENCY: Wait before retrying
|
|
1883
|
+
• SIMPLIFY QUERIES: Use fewer boolean operators
|
|
1884
|
+
• SCOPE NARROWING: Add owner/repo parameters`;
|
|
1885
|
+
}
|
|
1886
|
+
else if (errorMessage.includes('syntax') ||
|
|
1887
|
+
errorMessage.includes('invalid')) {
|
|
1888
|
+
errorType = 'syntax-error';
|
|
1889
|
+
specificSuggestions = `
|
|
1890
|
+
🔧 SYNTAX ERROR SOLUTIONS:
|
|
1891
|
+
• REMOVE PARENTHESES: GitHub API doesn't support () grouping
|
|
1892
|
+
• SIMPLIFY BOOLEAN: Use "term1 OR term2" not "(term1 OR term2)"
|
|
1893
|
+
• CHECK OPERATORS: Only AND, OR, NOT are supported`;
|
|
1894
|
+
}
|
|
1895
|
+
let fallbackSuggestions = `
|
|
1896
|
+
🔄 INTELLIGENT FALLBACK STRATEGIES:
|
|
1897
|
+
• PROGRESSIVE SIMPLIFICATION: Start with single terms, add complexity gradually
|
|
1898
|
+
• BOOLEAN BASICS: "term1 OR term2" works, "(term1 OR term2) AND term3" doesn't
|
|
1899
|
+
• EXCLUDE NOISE: Add "NOT test NOT spec NOT mock" to focus on production code
|
|
1900
|
+
• REMOVE FILTERS: Try without path/language filters first
|
|
1901
|
+
• REPOSITORY TARGETING: Use owner/repo for focused searches${specificSuggestions}`;
|
|
1902
|
+
// Add pattern-specific fallback suggestions
|
|
1903
|
+
const query = args.query.toLowerCase();
|
|
1904
|
+
if (query.includes('react')) {
|
|
1905
|
+
fallbackSuggestions += `\n• REACT SPECIFIC: Try "useState OR useEffect", avoid complex hook combinations`;
|
|
1906
|
+
}
|
|
1907
|
+
if (query.includes('auth')) {
|
|
1908
|
+
fallbackSuggestions += `\n• AUTH SPECIFIC: Try "login OR authenticate OR signin NOT test"`;
|
|
1909
|
+
}
|
|
1910
|
+
if (query.includes('api')) {
|
|
1911
|
+
fallbackSuggestions += `\n• API SPECIFIC: Try "fetch OR axios OR request NOT mock"`;
|
|
1912
|
+
}
|
|
1913
|
+
// Add the attempted queries for debugging
|
|
1914
|
+
fallbackSuggestions += `\n\n🔍 DEBUGGING INFO:
|
|
1915
|
+
• Original Query: "${args.query}"
|
|
1916
|
+
• Error Type: ${errorType}
|
|
1917
|
+
• Error Message: ${errorMessage}`;
|
|
837
1918
|
return {
|
|
838
1919
|
content: [
|
|
839
1920
|
{
|
|
840
1921
|
type: 'text',
|
|
841
|
-
text:
|
|
1922
|
+
text: `🚨 GitHub Code Search Failed: ${errorMessage}${fallbackSuggestions}`,
|
|
842
1923
|
},
|
|
843
1924
|
],
|
|
844
1925
|
isError: true,
|
|
@@ -859,31 +1940,127 @@ async function fetchGitHubFileContent(params) {
|
|
|
859
1940
|
const args = [apiPath, '--jq', '.content'];
|
|
860
1941
|
const result = await executeGitHubCommand('api', args, { cache: false });
|
|
861
1942
|
if (result.isError) {
|
|
862
|
-
|
|
1943
|
+
// Parse the error message to provide better context
|
|
1944
|
+
const errorMsg = result.content[0].text;
|
|
1945
|
+
// Handle common GitHub API errors
|
|
1946
|
+
if (errorMsg.includes('404') || errorMsg.includes('Not Found')) {
|
|
1947
|
+
return createErrorResult$1(`File not found: ${params.filePath}`, new Error(`
|
|
1948
|
+
❌ FILE NOT FOUND: The file '${params.filePath}' does not exist in ${params.owner}/${params.repo}${params.branch ? ` on branch '${params.branch}'` : ''}.
|
|
1949
|
+
|
|
1950
|
+
🔍 COMMON CAUSES:
|
|
1951
|
+
• File path is incorrect or has changed
|
|
1952
|
+
• Branch '${params.branch || 'default'}' doesn't contain this file
|
|
1953
|
+
• File may exist in a different directory
|
|
1954
|
+
|
|
1955
|
+
💡 RECOMMENDED ACTIONS:
|
|
1956
|
+
1. Use 'github_get_contents' to explore repository structure first
|
|
1957
|
+
2. Use 'github_search_code' to find files by name or pattern
|
|
1958
|
+
3. Verify the branch contains the expected files
|
|
1959
|
+
|
|
1960
|
+
📍 SEARCH ALTERNATIVES:
|
|
1961
|
+
• Search for filename: query="${params.filePath.split('/').pop()}"
|
|
1962
|
+
• Search in repository: repo:${params.owner}/${params.repo}
|
|
1963
|
+
• Explore repository structure starting from root`));
|
|
1964
|
+
}
|
|
1965
|
+
if (errorMsg.includes('403') || errorMsg.includes('Forbidden')) {
|
|
1966
|
+
return createErrorResult$1(`Access denied to file: ${params.filePath}`, new Error(`
|
|
1967
|
+
🔒 ACCESS DENIED: You don't have permission to access '${params.filePath}' in ${params.owner}/${params.repo}.
|
|
1968
|
+
|
|
1969
|
+
🔍 POSSIBLE CAUSES:
|
|
1970
|
+
• Repository is private and you lack access
|
|
1971
|
+
• File is in a protected branch
|
|
1972
|
+
• Organization restrictions apply
|
|
1973
|
+
|
|
1974
|
+
💡 RECOMMENDED ACTIONS:
|
|
1975
|
+
1. Check if you're authenticated: gh auth status
|
|
1976
|
+
2. Request repository access from owner
|
|
1977
|
+
3. Use 'github_get_user_organizations' if this is your organization`));
|
|
1978
|
+
}
|
|
1979
|
+
// Handle rate limiting
|
|
1980
|
+
if (errorMsg.includes('rate limit') || errorMsg.includes('429')) {
|
|
1981
|
+
return createErrorResult$1('GitHub API rate limit exceeded', new Error(`
|
|
1982
|
+
⏱️ RATE LIMIT: GitHub API rate limit has been exceeded.
|
|
1983
|
+
|
|
1984
|
+
💡 RECOMMENDED ACTIONS:
|
|
1985
|
+
1. Wait a few minutes before trying again
|
|
1986
|
+
2. Use authentication to increase rate limits: gh auth login
|
|
1987
|
+
3. Try searching for content instead of direct file access`));
|
|
1988
|
+
}
|
|
1989
|
+
// Generic error fallback
|
|
1990
|
+
return createErrorResult$1(`Failed to fetch file content: ${params.filePath}`, new Error(`GitHub API Error: ${errorMsg}
|
|
1991
|
+
|
|
1992
|
+
🔧 TROUBLESHOOTING:
|
|
1993
|
+
• Verify repository exists: ${params.owner}/${params.repo}
|
|
1994
|
+
• Check file path: ${params.filePath}
|
|
1995
|
+
• Confirm branch: ${params.branch || 'default'}
|
|
1996
|
+
• Use repository exploration tools first`));
|
|
863
1997
|
}
|
|
864
1998
|
// Extract the actual content from the exec result
|
|
865
1999
|
const execResult = JSON.parse(result.content[0].text);
|
|
866
2000
|
const base64Content = execResult.result.trim().replace(/\n/g, '');
|
|
2001
|
+
// Validate base64 content
|
|
2002
|
+
if (!base64Content || base64Content === 'null') {
|
|
2003
|
+
return createErrorResult$1(`Empty or invalid file content: ${params.filePath}`, new Error(`
|
|
2004
|
+
📄 EMPTY FILE: The file '${params.filePath}' exists but contains no content or returned invalid data.
|
|
2005
|
+
|
|
2006
|
+
🔍 POSSIBLE CAUSES:
|
|
2007
|
+
• File is empty or binary
|
|
2008
|
+
• API returned null content
|
|
2009
|
+
• File is too large for API response
|
|
2010
|
+
|
|
2011
|
+
💡 ALTERNATIVES:
|
|
2012
|
+
• Use 'github_search_code' to find content by pattern
|
|
2013
|
+
• Check file in GitHub web interface
|
|
2014
|
+
• Try accessing a different file in the same directory`));
|
|
2015
|
+
}
|
|
867
2016
|
// Decode base64 content using Node.js Buffer
|
|
868
2017
|
let decodedContent;
|
|
869
2018
|
try {
|
|
870
2019
|
decodedContent = Buffer.from(base64Content, 'base64').toString('utf-8');
|
|
871
2020
|
}
|
|
872
2021
|
catch (decodeError) {
|
|
873
|
-
|
|
2022
|
+
return createErrorResult$1(`Failed to decode file content: ${params.filePath}`, new Error(`
|
|
2023
|
+
🔧 DECODE ERROR: Unable to decode base64 content from GitHub API.
|
|
2024
|
+
|
|
2025
|
+
📋 DETAILS: ${decodeError.message}
|
|
2026
|
+
|
|
2027
|
+
💡 POSSIBLE CAUSES:
|
|
2028
|
+
• File contains binary data
|
|
2029
|
+
• Corrupted response from API
|
|
2030
|
+
• Encoding mismatch
|
|
2031
|
+
|
|
2032
|
+
🔍 ALTERNATIVES:
|
|
2033
|
+
• Use 'github_search_code' to find text-based content
|
|
2034
|
+
• Check if file is binary (images, executables, etc.)
|
|
2035
|
+
• Try accessing a different version of the file`));
|
|
874
2036
|
}
|
|
875
|
-
return {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
};
|
|
2037
|
+
return createSuccessResult$1({
|
|
2038
|
+
filePath: params.filePath,
|
|
2039
|
+
owner: params.owner,
|
|
2040
|
+
repo: params.repo,
|
|
2041
|
+
branch: params.branch,
|
|
2042
|
+
content: decodedContent,
|
|
2043
|
+
size: decodedContent.length,
|
|
2044
|
+
encoding: 'utf-8',
|
|
2045
|
+
});
|
|
884
2046
|
}
|
|
885
2047
|
catch (error) {
|
|
886
|
-
return createErrorResult$1(
|
|
2048
|
+
return createErrorResult$1(`Unexpected error fetching file content: ${params.filePath}`, new Error(`
|
|
2049
|
+
❌ UNEXPECTED ERROR: ${error.message}
|
|
2050
|
+
|
|
2051
|
+
📍 FILE DETAILS:
|
|
2052
|
+
• Repository: ${params.owner}/${params.repo}
|
|
2053
|
+
• File: ${params.filePath}
|
|
2054
|
+
• Branch: ${params.branch || 'default'}
|
|
2055
|
+
|
|
2056
|
+
🔧 TROUBLESHOOTING STEPS:
|
|
2057
|
+
1. Verify repository exists with 'github_get_repository'
|
|
2058
|
+
2. Explore structure with 'github_get_contents'
|
|
2059
|
+
3. Search for file with 'github_search_code'
|
|
2060
|
+
4. Check GitHub authentication: gh auth status
|
|
2061
|
+
|
|
2062
|
+
💡 WORKFLOW RECOMMENDATION:
|
|
2063
|
+
github_get_repository → github_get_contents → github_search_code → github_get_file_content`));
|
|
887
2064
|
}
|
|
888
2065
|
});
|
|
889
2066
|
}
|
|
@@ -932,25 +2109,434 @@ async function viewGitHubRepositoryInfo(params) {
|
|
|
932
2109
|
const args = ['view', `${owner}/${params.repo}`];
|
|
933
2110
|
const result = await executeGitHubCommand('repo', args, { cache: false });
|
|
934
2111
|
if (result.isError) {
|
|
935
|
-
|
|
2112
|
+
// Parse the error message to provide better context
|
|
2113
|
+
const errorMsg = result.content[0].text;
|
|
2114
|
+
// Handle repository not found
|
|
2115
|
+
if (errorMsg.includes('404') ||
|
|
2116
|
+
errorMsg.includes('Not Found') ||
|
|
2117
|
+
errorMsg.includes('could not resolve to a Repository')) {
|
|
2118
|
+
return createErrorResult$1(`Repository not found: ${owner}/${params.repo}`, new Error(`
|
|
2119
|
+
❌ REPOSITORY NOT FOUND: The repository '${owner}/${params.repo}' does not exist or is not accessible.
|
|
2120
|
+
|
|
2121
|
+
🔍 COMMON CAUSES:
|
|
2122
|
+
• Repository name is incorrect
|
|
2123
|
+
• Repository is private and you lack access
|
|
2124
|
+
• Owner/organization name is wrong
|
|
2125
|
+
• Repository has been deleted or moved
|
|
2126
|
+
|
|
2127
|
+
🎯 RECOMMENDED DISCOVERY WORKFLOW (in this order):
|
|
2128
|
+
|
|
2129
|
+
1️⃣ **NPM PACKAGE DISCOVERY** (if this is a package):
|
|
2130
|
+
• Use 'npm_search_packages' with keywords: "${params.repo}"
|
|
2131
|
+
• Then 'npm_get_package' to find the GitHub repository URL
|
|
2132
|
+
• This automatically discovers the correct owner/repo
|
|
2133
|
+
|
|
2134
|
+
2️⃣ **GITHUB TOPICS SEARCH** (for broader discovery):
|
|
2135
|
+
• Use 'github_search_topics' with terms: "${params.repo}"
|
|
2136
|
+
• Discover related repositories and ecosystems
|
|
2137
|
+
• Find the correct repository among similar projects
|
|
2138
|
+
|
|
2139
|
+
3️⃣ **REPOSITORY SEARCH** (last resort):
|
|
2140
|
+
• Use 'github_search_repositories' with query: "${params.repo}"
|
|
2141
|
+
• Add filters like language, stars, etc.
|
|
2142
|
+
• Manual selection from search results
|
|
2143
|
+
|
|
2144
|
+
💡 ORGANIZATION ACCESS:
|
|
2145
|
+
If this should be a private repository, try:
|
|
2146
|
+
• 'github_get_user_organizations' to see your available orgs
|
|
2147
|
+
• Use the correct organization name as owner
|
|
2148
|
+
|
|
2149
|
+
🔧 VERIFICATION:
|
|
2150
|
+
• Check repository exists at: https://github.com/${owner}/${params.repo}
|
|
2151
|
+
• Verify spelling and case sensitivity`));
|
|
2152
|
+
}
|
|
2153
|
+
// Handle access denied
|
|
2154
|
+
if (errorMsg.includes('403') || errorMsg.includes('Forbidden')) {
|
|
2155
|
+
return createErrorResult$1(`Access denied to repository: ${owner}/${params.repo}`, new Error(`
|
|
2156
|
+
🔒 ACCESS DENIED: You don't have permission to access '${owner}/${params.repo}'.
|
|
2157
|
+
|
|
2158
|
+
🔍 POSSIBLE CAUSES:
|
|
2159
|
+
• Repository is private
|
|
2160
|
+
• Organization restrictions
|
|
2161
|
+
• Invalid authentication
|
|
2162
|
+
|
|
2163
|
+
💡 RECOMMENDED ACTIONS:
|
|
2164
|
+
1. Check authentication: gh auth status
|
|
2165
|
+
2. Request repository access from owner: ${owner}
|
|
2166
|
+
3. Use 'github_get_user_organizations' if this is your org
|
|
2167
|
+
4. Verify you're logged into the correct GitHub account
|
|
2168
|
+
|
|
2169
|
+
🎯 ALTERNATIVE DISCOVERY:
|
|
2170
|
+
If you're looking for similar repositories, try:
|
|
2171
|
+
• 'npm_search_packages' for packages
|
|
2172
|
+
• 'github_search_topics' for general discovery
|
|
2173
|
+
• 'github_search_repositories' with broader terms`));
|
|
2174
|
+
}
|
|
2175
|
+
// Handle rate limiting
|
|
2176
|
+
if (errorMsg.includes('rate limit') || errorMsg.includes('429')) {
|
|
2177
|
+
return createErrorResult$1('GitHub API rate limit exceeded', new Error(`
|
|
2178
|
+
⏱️ RATE LIMIT: GitHub API rate limit has been exceeded.
|
|
2179
|
+
|
|
2180
|
+
💡 RECOMMENDED ACTIONS:
|
|
2181
|
+
1. Wait a few minutes before trying again
|
|
2182
|
+
2. Use authentication to increase rate limits: gh auth login
|
|
2183
|
+
3. Try discovery tools instead: npm_search_packages or github_search_topics`));
|
|
2184
|
+
}
|
|
2185
|
+
// Generic error fallback
|
|
2186
|
+
return createErrorResult$1(`Failed to access repository: ${owner}/${params.repo}`, new Error(`GitHub CLI Error: ${errorMsg}
|
|
2187
|
+
|
|
2188
|
+
🔧 TROUBLESHOOTING:
|
|
2189
|
+
• Verify repository exists: https://github.com/${owner}/${params.repo}
|
|
2190
|
+
• Check spelling and case sensitivity
|
|
2191
|
+
• Confirm authentication: gh auth status
|
|
2192
|
+
|
|
2193
|
+
🎯 DISCOVERY WORKFLOW:
|
|
2194
|
+
1. npm_search_packages → npm_get_package
|
|
2195
|
+
2. github_search_topics
|
|
2196
|
+
3. github_search_repositories
|
|
2197
|
+
4. github_get_repository (current step)`));
|
|
936
2198
|
}
|
|
937
2199
|
// Extract the actual content from the exec result
|
|
938
2200
|
const execResult = JSON.parse(result.content[0].text);
|
|
939
2201
|
const content = execResult.result;
|
|
2202
|
+
// Parse repository info to extract key details
|
|
940
2203
|
const viewResult = {
|
|
941
2204
|
owner,
|
|
942
2205
|
repo: params.repo,
|
|
943
2206
|
repositoryInfo: content,
|
|
944
2207
|
rawOutput: content,
|
|
945
2208
|
};
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
2209
|
+
// Try to extract branch information from the output
|
|
2210
|
+
let defaultBranch = 'main'; // fallback
|
|
2211
|
+
try {
|
|
2212
|
+
// The content is usually YAML-like output from gh repo view
|
|
2213
|
+
const lines = content.split('\n');
|
|
2214
|
+
for (const line of lines) {
|
|
2215
|
+
if (line.includes('default branch:') ||
|
|
2216
|
+
line.includes('Default branch:')) {
|
|
2217
|
+
const branchMatch = line.split(':')[1]?.trim();
|
|
2218
|
+
if (branchMatch) {
|
|
2219
|
+
defaultBranch = branchMatch;
|
|
2220
|
+
break;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
catch (parseError) {
|
|
2226
|
+
// If we can't parse the branch, keep the fallback
|
|
2227
|
+
}
|
|
2228
|
+
return createSuccessResult$1({
|
|
2229
|
+
...viewResult,
|
|
2230
|
+
defaultBranch,
|
|
2231
|
+
success: true,
|
|
2232
|
+
message: `✅ Repository found: ${owner}/${params.repo}
|
|
2233
|
+
|
|
2234
|
+
📋 REPOSITORY DETAILS:
|
|
2235
|
+
• Default branch: ${defaultBranch}
|
|
2236
|
+
• Ready for file operations
|
|
2237
|
+
|
|
2238
|
+
🔄 NEXT RECOMMENDED STEPS:
|
|
2239
|
+
1. Explore structure: github_get_contents
|
|
2240
|
+
2. Search for code: github_search_code
|
|
2241
|
+
3. Fetch specific files: github_get_file_content
|
|
2242
|
+
|
|
2243
|
+
⚠️ IMPORTANT: Use branch '${defaultBranch}' in subsequent file operations.`,
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
catch (error) {
|
|
2247
|
+
return createErrorResult$1(`Unexpected error accessing repository: ${params.owner}/${params.repo}`, new Error(`
|
|
2248
|
+
❌ UNEXPECTED ERROR: ${error.message}
|
|
2249
|
+
|
|
2250
|
+
📍 REPOSITORY DETAILS:
|
|
2251
|
+
• Owner: ${params.owner}
|
|
2252
|
+
• Repository: ${params.repo}
|
|
2253
|
+
|
|
2254
|
+
🔧 TROUBLESHOOTING STEPS:
|
|
2255
|
+
1. Verify GitHub CLI is installed and authenticated
|
|
2256
|
+
2. Check network connectivity
|
|
2257
|
+
3. Try discovery workflow instead:
|
|
2258
|
+
|
|
2259
|
+
🎯 DISCOVERY WORKFLOW:
|
|
2260
|
+
1. npm_search_packages "${params.repo}"
|
|
2261
|
+
2. github_search_topics "${params.repo}"
|
|
2262
|
+
3. github_search_repositories query="${params.repo}" owner="${params.owner}"
|
|
2263
|
+
4. github_get_repository (retry after discovery)
|
|
2264
|
+
|
|
2265
|
+
💡 This ensures you have the correct owner/repo before attempting direct access.`));
|
|
2266
|
+
}
|
|
951
2267
|
});
|
|
952
2268
|
}
|
|
953
2269
|
|
|
2270
|
+
// Cross-Tool Orchestration Chains
|
|
2271
|
+
const TOOL_FALLBACK_CHAINS = {
|
|
2272
|
+
'package-discovery': [
|
|
2273
|
+
{ tool: TOOL_NAMES.NPM_SEARCH_PACKAGES, reason: 'Primary package search' },
|
|
2274
|
+
{
|
|
2275
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_TOPICS,
|
|
2276
|
+
reason: 'Ecosystem terminology discovery',
|
|
2277
|
+
},
|
|
2278
|
+
{
|
|
2279
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_REPOS,
|
|
2280
|
+
reason: 'Repository-based discovery',
|
|
2281
|
+
},
|
|
2282
|
+
{
|
|
2283
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_CODE,
|
|
2284
|
+
reason: 'Code implementation search',
|
|
2285
|
+
},
|
|
2286
|
+
],
|
|
2287
|
+
'code-discovery': [
|
|
2288
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_CODE, reason: 'Direct code search' },
|
|
2289
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_REPOS, reason: 'Project-level discovery' },
|
|
2290
|
+
{ tool: TOOL_NAMES.NPM_SEARCH_PACKAGES, reason: 'Package-based solutions' },
|
|
2291
|
+
{
|
|
2292
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_ISSUES,
|
|
2293
|
+
reason: 'Problem discussion search',
|
|
2294
|
+
},
|
|
2295
|
+
],
|
|
2296
|
+
'repository-discovery': [
|
|
2297
|
+
{ tool: TOOL_NAMES.NPM_GET_REPOSITORY, reason: 'Package-to-repo mapping' },
|
|
2298
|
+
{
|
|
2299
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_REPOS,
|
|
2300
|
+
reason: 'Direct repository search',
|
|
2301
|
+
},
|
|
2302
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_TOPICS, reason: 'Topic-based discovery' },
|
|
2303
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_USERS, reason: 'Organization discovery' },
|
|
2304
|
+
],
|
|
2305
|
+
'issue-discovery': [
|
|
2306
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_ISSUES, reason: 'Primary issue search' },
|
|
2307
|
+
{
|
|
2308
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS,
|
|
2309
|
+
reason: 'Solution implementation search',
|
|
2310
|
+
},
|
|
2311
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_CODE, reason: 'Code example search' },
|
|
2312
|
+
{
|
|
2313
|
+
tool: TOOL_NAMES.GITHUB_SEARCH_REPOS,
|
|
2314
|
+
reason: 'Related project discovery',
|
|
2315
|
+
},
|
|
2316
|
+
],
|
|
2317
|
+
'user-discovery': [
|
|
2318
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_USERS, reason: 'Primary user search' },
|
|
2319
|
+
{
|
|
2320
|
+
tool: TOOL_NAMES.GITHUB_GET_USER_ORGS,
|
|
2321
|
+
reason: 'Organization membership discovery',
|
|
2322
|
+
},
|
|
2323
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_REPOS, reason: 'User project discovery' },
|
|
2324
|
+
{ tool: TOOL_NAMES.GITHUB_SEARCH_CODE, reason: 'Contribution analysis' },
|
|
2325
|
+
],
|
|
2326
|
+
};
|
|
2327
|
+
// Query Simplification Utilities
|
|
2328
|
+
class QueryOptimizer {
|
|
2329
|
+
static getProgressiveQueries(originalQuery) {
|
|
2330
|
+
const queries = [];
|
|
2331
|
+
// Original query
|
|
2332
|
+
queries.push(originalQuery);
|
|
2333
|
+
// Remove special characters and clean up
|
|
2334
|
+
const cleaned = originalQuery.replace(/[^\w\s-]/g, ' ').trim();
|
|
2335
|
+
if (cleaned !== originalQuery) {
|
|
2336
|
+
queries.push(cleaned);
|
|
2337
|
+
}
|
|
2338
|
+
// Extract key terms (remove common words)
|
|
2339
|
+
const stopWords = [
|
|
2340
|
+
'the',
|
|
2341
|
+
'a',
|
|
2342
|
+
'an',
|
|
2343
|
+
'and',
|
|
2344
|
+
'or',
|
|
2345
|
+
'but',
|
|
2346
|
+
'in',
|
|
2347
|
+
'on',
|
|
2348
|
+
'at',
|
|
2349
|
+
'to',
|
|
2350
|
+
'for',
|
|
2351
|
+
'of',
|
|
2352
|
+
'with',
|
|
2353
|
+
'by',
|
|
2354
|
+
];
|
|
2355
|
+
const terms = cleaned
|
|
2356
|
+
.split(/\s+/)
|
|
2357
|
+
.filter(term => term.length > 2 && !stopWords.includes(term.toLowerCase()));
|
|
2358
|
+
// Multiple key terms
|
|
2359
|
+
if (terms.length >= 2) {
|
|
2360
|
+
queries.push(terms.slice(0, 2).join(' '));
|
|
2361
|
+
}
|
|
2362
|
+
// Single most important term
|
|
2363
|
+
if (terms.length >= 1) {
|
|
2364
|
+
queries.push(terms[0]);
|
|
2365
|
+
}
|
|
2366
|
+
// Remove duplicates and return
|
|
2367
|
+
return [...new Set(queries)];
|
|
2368
|
+
}
|
|
2369
|
+
static simplifyPackageName(packageName) {
|
|
2370
|
+
const variations = [packageName];
|
|
2371
|
+
// Remove scope if present
|
|
2372
|
+
if (packageName.startsWith('@')) {
|
|
2373
|
+
const withoutScope = packageName.split('/')[1];
|
|
2374
|
+
if (withoutScope) {
|
|
2375
|
+
variations.push(withoutScope);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
// Remove common suffixes
|
|
2379
|
+
const suffixes = ['-js', '-node', '-lib', '-tool', '-cli', '-api'];
|
|
2380
|
+
suffixes.forEach(suffix => {
|
|
2381
|
+
if (packageName.endsWith(suffix)) {
|
|
2382
|
+
variations.push(packageName.slice(0, -suffix.length));
|
|
2383
|
+
}
|
|
2384
|
+
});
|
|
2385
|
+
return [...new Set(variations)];
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
// Context Analysis
|
|
2389
|
+
class ContextAnalyzer {
|
|
2390
|
+
static analyzeQuery(query) {
|
|
2391
|
+
const lowerQuery = query.toLowerCase();
|
|
2392
|
+
const keywords = query.split(/\s+/).filter(term => term.length > 2);
|
|
2393
|
+
// Determine query type
|
|
2394
|
+
let type = 'general';
|
|
2395
|
+
if (lowerQuery.includes('npm') ||
|
|
2396
|
+
lowerQuery.includes('package') ||
|
|
2397
|
+
lowerQuery.includes('install')) {
|
|
2398
|
+
type = 'package';
|
|
2399
|
+
}
|
|
2400
|
+
else if (lowerQuery.includes('function') ||
|
|
2401
|
+
lowerQuery.includes('class') ||
|
|
2402
|
+
lowerQuery.includes('import')) {
|
|
2403
|
+
type = 'code';
|
|
2404
|
+
}
|
|
2405
|
+
else if (lowerQuery.includes('repo') ||
|
|
2406
|
+
lowerQuery.includes('project') ||
|
|
2407
|
+
lowerQuery.includes('github')) {
|
|
2408
|
+
type = 'repository';
|
|
2409
|
+
}
|
|
2410
|
+
else if (lowerQuery.includes('bug') ||
|
|
2411
|
+
lowerQuery.includes('issue') ||
|
|
2412
|
+
lowerQuery.includes('problem')) {
|
|
2413
|
+
type = 'issue';
|
|
2414
|
+
}
|
|
2415
|
+
else if (lowerQuery.includes('user') ||
|
|
2416
|
+
lowerQuery.includes('developer') ||
|
|
2417
|
+
lowerQuery.includes('maintainer')) {
|
|
2418
|
+
type = 'user';
|
|
2419
|
+
}
|
|
2420
|
+
// Determine complexity
|
|
2421
|
+
const complexity = keywords.length <= 1
|
|
2422
|
+
? 'simple'
|
|
2423
|
+
: keywords.length <= 3
|
|
2424
|
+
? 'medium'
|
|
2425
|
+
: 'complex';
|
|
2426
|
+
// Generate suggestions
|
|
2427
|
+
const suggestions = [];
|
|
2428
|
+
if (complexity === 'complex') {
|
|
2429
|
+
suggestions.push('Try breaking down into simpler terms');
|
|
2430
|
+
suggestions.push('Use 1-2 key words instead of full phrases');
|
|
2431
|
+
}
|
|
2432
|
+
return { type, keywords, complexity, suggestions };
|
|
2433
|
+
}
|
|
2434
|
+
static getToolChain(queryType) {
|
|
2435
|
+
const chainKey = `${queryType}-discovery`;
|
|
2436
|
+
return (TOOL_FALLBACK_CHAINS[chainKey] ||
|
|
2437
|
+
TOOL_FALLBACK_CHAINS['package-discovery']);
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
// Enhanced Error Recovery
|
|
2441
|
+
function generateSmartRecovery(options) {
|
|
2442
|
+
const { tool, query, packageName, resultCount, error } = options;
|
|
2443
|
+
const queryAnalysis = query ? ContextAnalyzer.analyzeQuery(query) : null;
|
|
2444
|
+
const simplifiedQueries = query
|
|
2445
|
+
? QueryOptimizer.getProgressiveQueries(query)
|
|
2446
|
+
: [];
|
|
2447
|
+
const packageVariations = packageName
|
|
2448
|
+
? QueryOptimizer.simplifyPackageName(packageName)
|
|
2449
|
+
: [];
|
|
2450
|
+
// Determine appropriate tool chain
|
|
2451
|
+
const toolChain = queryAnalysis
|
|
2452
|
+
? ContextAnalyzer.getToolChain(queryAnalysis.type)
|
|
2453
|
+
: TOOL_FALLBACK_CHAINS['package-discovery'];
|
|
2454
|
+
// Build comprehensive recovery message
|
|
2455
|
+
let recoveryText = `${tool} failed: ${error.message}`;
|
|
2456
|
+
// Context-specific analysis
|
|
2457
|
+
if (queryAnalysis) {
|
|
2458
|
+
recoveryText += `
|
|
2459
|
+
|
|
2460
|
+
🔍 QUERY ANALYSIS:
|
|
2461
|
+
• Type: ${queryAnalysis.type.toUpperCase()} search
|
|
2462
|
+
• Complexity: ${queryAnalysis.complexity.toUpperCase()}
|
|
2463
|
+
• Keywords: ${queryAnalysis.keywords.join(', ')}`;
|
|
2464
|
+
if (queryAnalysis.suggestions.length > 0) {
|
|
2465
|
+
recoveryText += `
|
|
2466
|
+
• Suggestions: ${queryAnalysis.suggestions.join(', ')}`;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
// Query simplification suggestions
|
|
2470
|
+
if (simplifiedQueries.length > 1) {
|
|
2471
|
+
recoveryText += `
|
|
2472
|
+
|
|
2473
|
+
🔄 SIMPLIFIED QUERY OPTIONS:
|
|
2474
|
+
${simplifiedQueries
|
|
2475
|
+
.slice(1)
|
|
2476
|
+
.map((q, i) => `${i + 1}. "${q}"`)
|
|
2477
|
+
.join('\n')}`;
|
|
2478
|
+
}
|
|
2479
|
+
// Package name variations
|
|
2480
|
+
if (packageVariations.length > 1) {
|
|
2481
|
+
recoveryText += `
|
|
2482
|
+
|
|
2483
|
+
📦 PACKAGE NAME VARIATIONS:
|
|
2484
|
+
${packageVariations
|
|
2485
|
+
.slice(1)
|
|
2486
|
+
.map((v, i) => `${i + 1}. "${v}"`)
|
|
2487
|
+
.join('\n')}`;
|
|
2488
|
+
}
|
|
2489
|
+
// Cross-tool recommendations
|
|
2490
|
+
recoveryText += `
|
|
2491
|
+
|
|
2492
|
+
🔗 ALTERNATIVE TOOL CHAIN:
|
|
2493
|
+
${toolChain.map((t, i) => `${i + 1}. ${t.tool} - ${t.reason}`).join('\n')}`;
|
|
2494
|
+
// Specific error type handling
|
|
2495
|
+
if (error.message.includes('404') || error.message.includes('not found')) {
|
|
2496
|
+
recoveryText += `
|
|
2497
|
+
|
|
2498
|
+
💡 NOT FOUND RECOVERY:
|
|
2499
|
+
• Check spelling and exact names
|
|
2500
|
+
• Try search tools instead of direct access
|
|
2501
|
+
• Use broader discovery methods first`;
|
|
2502
|
+
}
|
|
2503
|
+
if (error.message.includes('API') || error.message.includes('rate limit')) {
|
|
2504
|
+
recoveryText += `
|
|
2505
|
+
|
|
2506
|
+
⏱️ API LIMIT RECOVERY:
|
|
2507
|
+
• Wait a moment before retrying
|
|
2508
|
+
• Use simpler queries to reduce API usage
|
|
2509
|
+
• Try different tools that may use different API endpoints`;
|
|
2510
|
+
}
|
|
2511
|
+
// General best practices
|
|
2512
|
+
recoveryText += `
|
|
2513
|
+
|
|
2514
|
+
📋 PROVEN RECOVERY WORKFLOW:
|
|
2515
|
+
1. Start with search tools (npm_search_packages, github_search_repos)
|
|
2516
|
+
2. Use discovery results to guide specific tool usage
|
|
2517
|
+
3. Progressively simplify queries if needed
|
|
2518
|
+
4. Try alternative tool chains for different perspectives`;
|
|
2519
|
+
// Context-specific recommendations
|
|
2520
|
+
if (resultCount === 0) {
|
|
2521
|
+
recoveryText += `
|
|
2522
|
+
|
|
2523
|
+
🎯 ZERO RESULTS STRATEGY:
|
|
2524
|
+
• Broaden search terms
|
|
2525
|
+
• Remove restrictive filters
|
|
2526
|
+
• Try ecosystem discovery tools
|
|
2527
|
+
• Use single keywords instead of phrases`;
|
|
2528
|
+
}
|
|
2529
|
+
return {
|
|
2530
|
+
content: [
|
|
2531
|
+
{
|
|
2532
|
+
type: 'text',
|
|
2533
|
+
text: recoveryText,
|
|
2534
|
+
},
|
|
2535
|
+
],
|
|
2536
|
+
isError: true,
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
|
|
954
2540
|
function registerViewRepositoryTool(server) {
|
|
955
2541
|
server.tool(TOOL_NAMES.GITHUB_GET_REPOSITORY, TOOL_DESCRIPTIONS[TOOL_NAMES.GITHUB_GET_REPOSITORY], {
|
|
956
2542
|
owner: z
|
|
@@ -970,88 +2556,12 @@ function registerViewRepositoryTool(server) {
|
|
|
970
2556
|
return await viewGitHubRepositoryInfo(args);
|
|
971
2557
|
}
|
|
972
2558
|
catch (error) {
|
|
973
|
-
return {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
},
|
|
979
|
-
],
|
|
980
|
-
isError: true,
|
|
981
|
-
};
|
|
982
|
-
}
|
|
983
|
-
});
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
async function npmView(packageName) {
|
|
987
|
-
const cacheKey = generateCacheKey('npm-view', { packageName });
|
|
988
|
-
return withCache(cacheKey, async () => {
|
|
989
|
-
try {
|
|
990
|
-
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
991
|
-
cache: true,
|
|
2559
|
+
return generateSmartRecovery({
|
|
2560
|
+
tool: 'GitHub Repository View',
|
|
2561
|
+
owner: args.owner,
|
|
2562
|
+
repo: args.repo,
|
|
2563
|
+
error: error,
|
|
992
2564
|
});
|
|
993
|
-
if (result.isError) {
|
|
994
|
-
return result;
|
|
995
|
-
}
|
|
996
|
-
// Parse the result from the executed command
|
|
997
|
-
const commandOutput = JSON.parse(result.content[0].text);
|
|
998
|
-
const npmData = commandOutput.result;
|
|
999
|
-
let popularityData = '';
|
|
1000
|
-
try {
|
|
1001
|
-
// Get version count as popularity indicator
|
|
1002
|
-
const versionsResult = await executeNpmCommand('view', [
|
|
1003
|
-
packageName,
|
|
1004
|
-
'time',
|
|
1005
|
-
'--json',
|
|
1006
|
-
]);
|
|
1007
|
-
if (!versionsResult.isError) {
|
|
1008
|
-
const versionsOutput = JSON.parse(versionsResult.content[0].text);
|
|
1009
|
-
const timeData = versionsOutput.result;
|
|
1010
|
-
const versionCount = Object.keys(timeData).length - 2; // Subtract 'created' and 'modified'
|
|
1011
|
-
popularityData = `Package versions released: ${versionCount}`;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
catch {
|
|
1015
|
-
// Popularity data is optional
|
|
1016
|
-
}
|
|
1017
|
-
const enhancedResult = {
|
|
1018
|
-
npmData: JSON.parse(JSON.stringify(npmData)),
|
|
1019
|
-
popularityInfo: popularityData,
|
|
1020
|
-
lastAnalyzed: new Date().toISOString(),
|
|
1021
|
-
};
|
|
1022
|
-
return createSuccessResult$1(enhancedResult);
|
|
1023
|
-
}
|
|
1024
|
-
catch (error) {
|
|
1025
|
-
return createErrorResult$1('Failed to get npm repository information', error);
|
|
1026
|
-
}
|
|
1027
|
-
});
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
function registerNpmViewTool(server) {
|
|
1031
|
-
server.tool(TOOL_NAMES.NPM_GET_PACKAGE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_PACKAGE], {
|
|
1032
|
-
packageName: z
|
|
1033
|
-
.string()
|
|
1034
|
-
.describe("The name of the npm package to analyze (e.g., 'react', '@types/node', 'lodash')"),
|
|
1035
|
-
}, {
|
|
1036
|
-
title: 'View NPM Package',
|
|
1037
|
-
readOnlyHint: true,
|
|
1038
|
-
destructiveHint: false,
|
|
1039
|
-
idempotentHint: true,
|
|
1040
|
-
openWorldHint: true,
|
|
1041
|
-
}, async (args) => {
|
|
1042
|
-
try {
|
|
1043
|
-
return await npmView(args.packageName);
|
|
1044
|
-
}
|
|
1045
|
-
catch (error) {
|
|
1046
|
-
return {
|
|
1047
|
-
content: [
|
|
1048
|
-
{
|
|
1049
|
-
type: 'text',
|
|
1050
|
-
text: `Failed to get npm package info: ${error.message}`,
|
|
1051
|
-
},
|
|
1052
|
-
],
|
|
1053
|
-
isError: true,
|
|
1054
|
-
};
|
|
1055
2565
|
}
|
|
1056
2566
|
});
|
|
1057
2567
|
}
|
|
@@ -1184,8 +2694,8 @@ function buildGitHubReposSearchCommand(params) {
|
|
|
1184
2694
|
args.push(`--include-forks=${params.includeForks}`);
|
|
1185
2695
|
if (params.language)
|
|
1186
2696
|
args.push(`--language=${params.language}`);
|
|
1187
|
-
if (params.license)
|
|
1188
|
-
args.push(`--license=${params.license}`);
|
|
2697
|
+
if (params.license && params.license.length > 0)
|
|
2698
|
+
args.push(`--license=${params.license.join(',')}`);
|
|
1189
2699
|
if (params.limit)
|
|
1190
2700
|
args.push(`--limit=${params.limit}`);
|
|
1191
2701
|
if (params.match)
|
|
@@ -1196,15 +2706,15 @@ function buildGitHubReposSearchCommand(params) {
|
|
|
1196
2706
|
args.push(`--order=${params.order}`);
|
|
1197
2707
|
if (params.size)
|
|
1198
2708
|
args.push(`--size="${params.size}"`);
|
|
1199
|
-
//
|
|
1200
|
-
const sortBy = params.sort || '
|
|
2709
|
+
// Use best-match as default, only specify sort if different from default
|
|
2710
|
+
const sortBy = params.sort || 'best-match';
|
|
1201
2711
|
if (sortBy !== 'best-match') {
|
|
1202
2712
|
args.push(`--sort=${sortBy}`);
|
|
1203
2713
|
}
|
|
1204
2714
|
if (params.stars !== undefined)
|
|
1205
|
-
args.push(`--stars
|
|
1206
|
-
if (params.topic)
|
|
1207
|
-
args.push(`--topic=${params.topic}`);
|
|
2715
|
+
args.push(`--stars="${params.stars}"`);
|
|
2716
|
+
if (params.topic && params.topic.length > 0)
|
|
2717
|
+
args.push(`--topic=${params.topic.join(',')}`);
|
|
1208
2718
|
if (params.updated)
|
|
1209
2719
|
args.push(`--updated="${params.updated}"`);
|
|
1210
2720
|
if (params.visibility)
|
|
@@ -1264,7 +2774,13 @@ function validateFilterCombinations(args) {
|
|
|
1264
2774
|
suggestion: 'PROVEN: owner=facebook + query=react without language filter → React (236K⭐), React Native (119K⭐), Create React App',
|
|
1265
2775
|
},
|
|
1266
2776
|
{
|
|
1267
|
-
condition: args.language &&
|
|
2777
|
+
condition: args.language &&
|
|
2778
|
+
args.stars &&
|
|
2779
|
+
((args.stars.includes('>') &&
|
|
2780
|
+
parseInt(args.stars.replace(/[><]/g, '')) > 10000) ||
|
|
2781
|
+
(!args.stars.includes('>') &&
|
|
2782
|
+
!args.stars.includes('<') &&
|
|
2783
|
+
parseInt(args.stars) > 10000)),
|
|
1268
2784
|
warning: 'High star threshold with specific language may be too restrictive (TESTING-VALIDATED)',
|
|
1269
2785
|
suggestion: 'PROVEN: Use >1000 stars for established projects, >100 for active ones. Language filters often miss major projects.',
|
|
1270
2786
|
},
|
|
@@ -1298,8 +2814,8 @@ function validateFilterCombinations(args) {
|
|
|
1298
2814
|
if (args.limit && (args.limit < 1 || args.limit > 100)) {
|
|
1299
2815
|
warnings.push('Limit must be between 1 and 100');
|
|
1300
2816
|
}
|
|
1301
|
-
if (args.stars
|
|
1302
|
-
warnings.push('Stars filter must be
|
|
2817
|
+
if (args.stars && !/^[><]=?\d+$|^\d+$|^\d+\.\.\d+$/.test(args.stars)) {
|
|
2818
|
+
warnings.push('Stars filter must be in format ">100", ">=500", "<1000", "<=200", "50..200" or a simple number');
|
|
1303
2819
|
}
|
|
1304
2820
|
if (args.forks !== undefined && args.forks < 0) {
|
|
1305
2821
|
warnings.push('Forks filter must be non-negative');
|
|
@@ -1338,8 +2854,9 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1338
2854
|
.describe('Search query for repositories. PRODUCTION TIP: Single terms work best (e.g., "react", "typescript"). Multi-term queries will be auto-decomposed with suggestions.'),
|
|
1339
2855
|
owner: z
|
|
1340
2856
|
.string()
|
|
1341
|
-
.min(1
|
|
1342
|
-
.
|
|
2857
|
+
.min(1)
|
|
2858
|
+
.optional()
|
|
2859
|
+
.describe('Repository owner/organization (e.g., "facebook", "microsoft"). OPTIONAL: Leave empty for global searches across all of GitHub. Recommended for scoped, reliable results.'),
|
|
1343
2860
|
archived: z.boolean().optional().describe('Filter archived state'),
|
|
1344
2861
|
created: z
|
|
1345
2862
|
.string()
|
|
@@ -1363,7 +2880,10 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1363
2880
|
.string()
|
|
1364
2881
|
.optional()
|
|
1365
2882
|
.describe('Filter by programming language - WARNING: Can cause empty results with restrictive combinations'),
|
|
1366
|
-
license: z
|
|
2883
|
+
license: z
|
|
2884
|
+
.array(z.string())
|
|
2885
|
+
.optional()
|
|
2886
|
+
.describe('Filter based on license type (e.g., ["mit", "apache-2.0"])'),
|
|
1367
2887
|
limit: z
|
|
1368
2888
|
.number()
|
|
1369
2889
|
.optional()
|
|
@@ -1373,28 +2893,37 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1373
2893
|
.enum(['name', 'description', 'readme'])
|
|
1374
2894
|
.optional()
|
|
1375
2895
|
.describe('Search scope restriction'),
|
|
1376
|
-
numberTopics: z
|
|
2896
|
+
numberTopics: z
|
|
2897
|
+
.number()
|
|
2898
|
+
.optional()
|
|
2899
|
+
.describe('Filter on number of topics'),
|
|
1377
2900
|
order: z
|
|
1378
2901
|
.enum(['asc', 'desc'])
|
|
1379
2902
|
.optional()
|
|
1380
2903
|
.default('desc')
|
|
1381
2904
|
.describe('Result order (default: desc for newest first)'),
|
|
1382
|
-
size: z
|
|
2905
|
+
size: z
|
|
2906
|
+
.string()
|
|
2907
|
+
.optional()
|
|
2908
|
+
.describe('Filter on size range, in kilobytes (e.g., ">1000", "50..120")'),
|
|
1383
2909
|
sort: z
|
|
1384
2910
|
.enum(['forks', 'help-wanted-issues', 'stars', 'updated', 'best-match'])
|
|
1385
2911
|
.optional()
|
|
1386
|
-
.default('
|
|
1387
|
-
.describe('Sort
|
|
2912
|
+
.default('best-match')
|
|
2913
|
+
.describe('Sort fetched repositories (default: best-match)'),
|
|
1388
2914
|
stars: z
|
|
1389
|
-
.
|
|
2915
|
+
.string()
|
|
2916
|
+
.optional()
|
|
2917
|
+
.describe('Filter by stars count (e.g., ">100", "<1000", ">=500", "50..200" for range queries) - TIP: Use >100 for established projects, >10 for active ones'),
|
|
2918
|
+
topic: z
|
|
2919
|
+
.array(z.string())
|
|
1390
2920
|
.optional()
|
|
1391
|
-
.describe('Filter
|
|
1392
|
-
topic: z.string().optional().describe('Filter by topic/tag'),
|
|
2921
|
+
.describe('Filter on topic (e.g., ["react", "javascript"])'),
|
|
1393
2922
|
updated: z.string().optional().describe('Filter by last update date'),
|
|
1394
2923
|
visibility: z
|
|
1395
2924
|
.enum(['public', 'private', 'internal'])
|
|
1396
2925
|
.optional()
|
|
1397
|
-
.describe('Filter
|
|
2926
|
+
.describe('Filter based on repository visibility'),
|
|
1398
2927
|
}, {
|
|
1399
2928
|
title: 'Search GitHub Repositories',
|
|
1400
2929
|
readOnlyHint: true,
|
|
@@ -1420,8 +2949,26 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1420
2949
|
const result = await searchGitHubRepos(searchArgs);
|
|
1421
2950
|
// Check if we got empty results and provide helpful guidance
|
|
1422
2951
|
const resultText = result.content[0].text;
|
|
1423
|
-
|
|
1424
|
-
|
|
2952
|
+
// Handle non-JSON responses gracefully
|
|
2953
|
+
let parsedResults;
|
|
2954
|
+
let resultCount = 0;
|
|
2955
|
+
try {
|
|
2956
|
+
parsedResults = JSON.parse(resultText);
|
|
2957
|
+
if (parsedResults.rawOutput) {
|
|
2958
|
+
const rawData = JSON.parse(parsedResults.rawOutput);
|
|
2959
|
+
resultCount = Array.isArray(rawData) ? rawData.length : 0;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
catch (parseError) {
|
|
2963
|
+
// If parsing fails, it might be an error message from GitHub CLI
|
|
2964
|
+
if (resultText.includes('Failed to') ||
|
|
2965
|
+
resultText.includes('Error:')) {
|
|
2966
|
+
throw new Error(`GitHub CLI error: ${resultText}`);
|
|
2967
|
+
}
|
|
2968
|
+
// For other parsing issues, set reasonable defaults
|
|
2969
|
+
resultCount = 0;
|
|
2970
|
+
parsedResults = { rawOutput: '[]' };
|
|
2971
|
+
}
|
|
1425
2972
|
let responseText = resultText;
|
|
1426
2973
|
// Add guidance for multi-term queries
|
|
1427
2974
|
if (queryAnalysis.shouldDecompose) {
|
|
@@ -1462,6 +3009,10 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1462
3009
|
responseText += `\n• SCOPED SEARCH SUCCESS: owner + single term pattern proven effective`;
|
|
1463
3010
|
responseText += `\n• PROVEN EXAMPLES: microsoft+typescript→VSCode(173K⭐), facebook+react→React(236K⭐)`;
|
|
1464
3011
|
}
|
|
3012
|
+
else if (!args.owner) {
|
|
3013
|
+
responseText += `\n• GLOBAL SEARCH: Searching across all GitHub repositories`;
|
|
3014
|
+
responseText += `\n• TIP: Add owner filter for more targeted results if you know specific organizations`;
|
|
3015
|
+
}
|
|
1465
3016
|
// Add caching recommendations for testing-validated popular searches
|
|
1466
3017
|
const validatedPopularTerms = [
|
|
1467
3018
|
'react', // 236K⭐ confirmed
|
|
@@ -1494,11 +3045,12 @@ function registerSearchGitHubReposTool(server) {
|
|
|
1494
3045
|
🔄 RECOMMENDED FALLBACK WORKFLOW:
|
|
1495
3046
|
${fallbacks.map(f => `• ${f}`).join('\n')}
|
|
1496
3047
|
|
|
1497
|
-
💡 PRODUCTION NOTE:
|
|
3048
|
+
💡 PRODUCTION NOTE: For reliable discovery:
|
|
1498
3049
|
1. Start with npm_search_packages for package-based discovery
|
|
1499
3050
|
2. Use github_search_topics for ecosystem terminology
|
|
1500
3051
|
3. Use npm_get_package to extract repository URLs
|
|
1501
|
-
4.
|
|
3052
|
+
4. Use global repository search (without owner) for broad discovery
|
|
3053
|
+
5. Use scoped search (with owner) when you know specific organizations`;
|
|
1502
3054
|
return {
|
|
1503
3055
|
content: [
|
|
1504
3056
|
{
|
|
@@ -1856,18 +3408,69 @@ function registerSearchGitHubPullRequestsTool(server) {
|
|
|
1856
3408
|
openWorldHint: true,
|
|
1857
3409
|
}, async (args) => {
|
|
1858
3410
|
try {
|
|
1859
|
-
|
|
3411
|
+
const result = await searchGitHubPullRequests(args);
|
|
3412
|
+
// Check for empty results and enhance with smart suggestions
|
|
3413
|
+
if (result.content && result.content[0]) {
|
|
3414
|
+
let responseText = result.content[0].text;
|
|
3415
|
+
let resultCount = 0;
|
|
3416
|
+
try {
|
|
3417
|
+
const parsed = JSON.parse(responseText);
|
|
3418
|
+
if (parsed.rawOutput) {
|
|
3419
|
+
const rawData = JSON.parse(parsed.rawOutput);
|
|
3420
|
+
resultCount = Array.isArray(rawData) ? rawData.length : 0;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
catch {
|
|
3424
|
+
const lines = responseText.split('\n').filter(line => line.trim());
|
|
3425
|
+
resultCount = Math.max(0, lines.length - 5);
|
|
3426
|
+
}
|
|
3427
|
+
if (resultCount === 0) {
|
|
3428
|
+
responseText += `
|
|
3429
|
+
|
|
3430
|
+
🔄 NO RESULTS RECOVERY STRATEGY:
|
|
3431
|
+
• Try broader terms: "${args.query}" → "fix", "feature", "update"
|
|
3432
|
+
• Implementation search: github_search_code for actual code changes
|
|
3433
|
+
• Project discovery: github_search_repos for related projects
|
|
3434
|
+
• Issue tracking: github_search_issues for related problems
|
|
3435
|
+
|
|
3436
|
+
💡 PR SEARCH OPTIMIZATION:
|
|
3437
|
+
• Focus on action words: "implement", "add", "fix", "update"
|
|
3438
|
+
• Try state filters: state=open vs state=closed
|
|
3439
|
+
• Use review filters: draft=false for completed PRs
|
|
3440
|
+
|
|
3441
|
+
🔗 RECOMMENDED TOOL CHAIN:
|
|
3442
|
+
1. github_search_issues - Find problems that needed solutions
|
|
3443
|
+
2. github_search_code - See actual implementation patterns
|
|
3444
|
+
3. github_search_repos - Discover projects with similar features`;
|
|
3445
|
+
}
|
|
3446
|
+
else if (resultCount <= 5) {
|
|
3447
|
+
responseText += `
|
|
3448
|
+
|
|
3449
|
+
💡 FEW RESULTS ENHANCEMENT:
|
|
3450
|
+
• Found ${resultCount} PRs - try removing restrictive filters
|
|
3451
|
+
• Alternative: github_search_code for implementation examples
|
|
3452
|
+
• Cross-reference: github_search_issues for related discussions`;
|
|
3453
|
+
}
|
|
3454
|
+
return {
|
|
3455
|
+
content: [
|
|
3456
|
+
{
|
|
3457
|
+
type: 'text',
|
|
3458
|
+
text: responseText,
|
|
3459
|
+
},
|
|
3460
|
+
],
|
|
3461
|
+
isError: false,
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
return result;
|
|
1860
3465
|
}
|
|
1861
3466
|
catch (error) {
|
|
1862
|
-
return {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
isError: true,
|
|
1870
|
-
};
|
|
3467
|
+
return generateSmartRecovery({
|
|
3468
|
+
tool: 'GitHub Pull Requests Search',
|
|
3469
|
+
query: args.query,
|
|
3470
|
+
owner: args.owner,
|
|
3471
|
+
repo: args.repo,
|
|
3472
|
+
error: error,
|
|
3473
|
+
});
|
|
1871
3474
|
}
|
|
1872
3475
|
});
|
|
1873
3476
|
}
|
|
@@ -1999,6 +3602,39 @@ async function npmSearch(args) {
|
|
|
1999
3602
|
}
|
|
2000
3603
|
}
|
|
2001
3604
|
|
|
3605
|
+
// Analyze NPM search patterns and suggest fallbacks
|
|
3606
|
+
function analyzeNpmSearchPattern(args) {
|
|
3607
|
+
const suggestions = [];
|
|
3608
|
+
const fallbackStrategy = [];
|
|
3609
|
+
const organizationalHints = [];
|
|
3610
|
+
let patternType = 'basic';
|
|
3611
|
+
const query = args.query.toLowerCase();
|
|
3612
|
+
// Detect organizational packages
|
|
3613
|
+
if (query.includes('@') ||
|
|
3614
|
+
query.includes('internal') ||
|
|
3615
|
+
query.includes('private')) {
|
|
3616
|
+
patternType = 'organizational';
|
|
3617
|
+
organizationalHints.push('ORGANIZATIONAL PACKAGE DETECTED: Consider checking GitHub organizations first');
|
|
3618
|
+
fallbackStrategy.push(`Use ${TOOL_NAMES.GITHUB_GET_USER_ORGS} to discover private package access`);
|
|
3619
|
+
}
|
|
3620
|
+
// Complex search patterns
|
|
3621
|
+
if (query.split(' ').length > 2) {
|
|
3622
|
+
patternType = 'complex-multi-term';
|
|
3623
|
+
suggestions.push('PROVEN: Complex phrases often yield zero results - try single terms');
|
|
3624
|
+
fallbackStrategy.push('Break down into primary term → secondary filters');
|
|
3625
|
+
}
|
|
3626
|
+
// Technology-specific patterns
|
|
3627
|
+
if (query.includes('react') ||
|
|
3628
|
+
query.includes('vue') ||
|
|
3629
|
+
query.includes('angular')) {
|
|
3630
|
+
patternType = 'framework-specific';
|
|
3631
|
+
suggestions.push('FRAMEWORK DETECTED: Consider ecosystem-specific searches');
|
|
3632
|
+
fallbackStrategy.push(`Use ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} for framework ecosystem discovery`);
|
|
3633
|
+
}
|
|
3634
|
+
// Generic fallback strategy for all patterns
|
|
3635
|
+
fallbackStrategy.push(`1. ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} - Search ecosystem terms`, `2. ${TOOL_NAMES.GITHUB_SEARCH_REPOS} - Find repositories that might be packages`, `3. ${TOOL_NAMES.GITHUB_SEARCH_CODE} - Search package.json files`, `4. ${TOOL_NAMES.GITHUB_SEARCH_COMMITS} - Search package development history`, `5. ${TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS} - Search package mentions in PRs`, `6. ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} - Search package discussions`);
|
|
3636
|
+
return { patternType, suggestions, fallbackStrategy, organizationalHints };
|
|
3637
|
+
}
|
|
2002
3638
|
function registerNpmSearchTool(server) {
|
|
2003
3639
|
server.tool(TOOL_NAMES.NPM_SEARCH_PACKAGES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_SEARCH_PACKAGES], {
|
|
2004
3640
|
query: z
|
|
@@ -2022,14 +3658,106 @@ function registerNpmSearchTool(server) {
|
|
|
2022
3658
|
openWorldHint: true,
|
|
2023
3659
|
}, async (args) => {
|
|
2024
3660
|
try {
|
|
2025
|
-
|
|
3661
|
+
// Analyze search pattern for insights and fallbacks
|
|
3662
|
+
const patternAnalysis = analyzeNpmSearchPattern(args);
|
|
3663
|
+
const result = await npmSearch(args);
|
|
3664
|
+
// Check if we got poor results and enhance with fallback suggestions
|
|
3665
|
+
if (result.content && result.content[0]) {
|
|
3666
|
+
let responseText = result.content[0].text;
|
|
3667
|
+
// Parse result to check quality
|
|
3668
|
+
let resultCount = 0;
|
|
3669
|
+
try {
|
|
3670
|
+
const parsed = JSON.parse(responseText);
|
|
3671
|
+
if (parsed.results && Array.isArray(parsed.results)) {
|
|
3672
|
+
resultCount = parsed.results.length;
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
catch {
|
|
3676
|
+
// If not JSON, try to estimate from text
|
|
3677
|
+
const lines = responseText.split('\n').filter(line => line.trim());
|
|
3678
|
+
resultCount = Math.max(0, lines.length - 5); // Rough estimate
|
|
3679
|
+
}
|
|
3680
|
+
// Add organizational hints if detected
|
|
3681
|
+
if (patternAnalysis.organizationalHints.length > 0) {
|
|
3682
|
+
responseText += `\n\n🏢 ORGANIZATIONAL PACKAGE INSIGHTS:`;
|
|
3683
|
+
patternAnalysis.organizationalHints.forEach(hint => {
|
|
3684
|
+
responseText += `\n• ${hint}`;
|
|
3685
|
+
});
|
|
3686
|
+
}
|
|
3687
|
+
// Add pattern-specific suggestions
|
|
3688
|
+
if (patternAnalysis.suggestions.length > 0) {
|
|
3689
|
+
responseText += `\n\n💡 SEARCH PATTERN INSIGHTS (${patternAnalysis.patternType.toUpperCase()}):`;
|
|
3690
|
+
patternAnalysis.suggestions.forEach(suggestion => {
|
|
3691
|
+
responseText += `\n• ${suggestion}`;
|
|
3692
|
+
});
|
|
3693
|
+
}
|
|
3694
|
+
// Add fallback strategy if results are poor (< 5 results or specific patterns)
|
|
3695
|
+
if (resultCount < 5 || patternAnalysis.patternType !== 'basic') {
|
|
3696
|
+
responseText += `\n\n🔄 NPM SEARCH FALLBACK STRATEGY:`;
|
|
3697
|
+
responseText += `\nIf NPM search yields insufficient results, try this validated workflow:`;
|
|
3698
|
+
patternAnalysis.fallbackStrategy.forEach((step, index) => {
|
|
3699
|
+
responseText += `\n${index + 1}. ${step}`;
|
|
3700
|
+
});
|
|
3701
|
+
}
|
|
3702
|
+
// Add general best practices
|
|
3703
|
+
responseText += `\n\n📋 NPM SEARCH BEST PRACTICES:`;
|
|
3704
|
+
responseText += `\n• Single terms work best: "react", "auth", "cli"`;
|
|
3705
|
+
responseText += `\n• Combined terms: "react-hooks", "typescript-cli"`;
|
|
3706
|
+
responseText += `\n• Avoid complex phrases: Break "react auth jwt library" → "react" + "auth"`;
|
|
3707
|
+
responseText += `\n• Organizational packages: @company/ triggers private search workflow`;
|
|
3708
|
+
responseText += `\n• 0 results → broader terms, 1-20 IDEAL, 100+ → more specific`;
|
|
3709
|
+
return {
|
|
3710
|
+
content: [
|
|
3711
|
+
{
|
|
3712
|
+
type: 'text',
|
|
3713
|
+
text: responseText,
|
|
3714
|
+
},
|
|
3715
|
+
],
|
|
3716
|
+
isError: false,
|
|
3717
|
+
};
|
|
3718
|
+
}
|
|
3719
|
+
return result;
|
|
2026
3720
|
}
|
|
2027
3721
|
catch (error) {
|
|
3722
|
+
// Enhanced error handling with fallback suggestions
|
|
3723
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
3724
|
+
const fallbackSuggestions = `
|
|
3725
|
+
🔄 NPM SEARCH FALLBACK WORKFLOW:
|
|
3726
|
+
When NPM registry search fails, try this proven sequence:
|
|
3727
|
+
|
|
3728
|
+
1. ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} - Discover ecosystem terminology
|
|
3729
|
+
• Use broader terms: "authentication" instead of "jwt-auth-library"
|
|
3730
|
+
• Find related technologies and packages
|
|
3731
|
+
|
|
3732
|
+
2. ${TOOL_NAMES.GITHUB_SEARCH_REPOS} - Find package repositories
|
|
3733
|
+
• Search for repositories that might contain packages
|
|
3734
|
+
• Look for package.json indicators
|
|
3735
|
+
|
|
3736
|
+
3. ${TOOL_NAMES.GITHUB_SEARCH_CODE} - Search package manifests
|
|
3737
|
+
• Query: "package.json" + your terms
|
|
3738
|
+
• Find actual package definitions
|
|
3739
|
+
|
|
3740
|
+
4. ${TOOL_NAMES.GITHUB_SEARCH_COMMITS} - Development history
|
|
3741
|
+
• Search commit messages for package development
|
|
3742
|
+
• Find package creation/updates
|
|
3743
|
+
|
|
3744
|
+
5. ${TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS} - Package discussions
|
|
3745
|
+
• Find PRs mentioning package development
|
|
3746
|
+
• Discover package features and issues
|
|
3747
|
+
|
|
3748
|
+
6. ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} - Community discussions
|
|
3749
|
+
• Find issues discussing packages
|
|
3750
|
+
• Discover alternatives and recommendations
|
|
3751
|
+
|
|
3752
|
+
💡 PROVEN STRATEGIES:
|
|
3753
|
+
• Try simpler terms if complex search fails
|
|
3754
|
+
• Check organizational access for @company/ packages
|
|
3755
|
+
• Use GitHub ecosystem discovery when NPM fails`;
|
|
2028
3756
|
return {
|
|
2029
3757
|
content: [
|
|
2030
3758
|
{
|
|
2031
3759
|
type: 'text',
|
|
2032
|
-
text: `
|
|
3760
|
+
text: `NPM Search Failed: ${errorMessage}${fallbackSuggestions}`,
|
|
2033
3761
|
},
|
|
2034
3762
|
],
|
|
2035
3763
|
isError: true,
|
|
@@ -2291,8 +4019,9 @@ function registerSearchGitHubIssuesTool(server) {
|
|
|
2291
4019
|
.describe("The search query to find issues (e.g., 'bug fix', 'feature request', 'documentation')"),
|
|
2292
4020
|
owner: z
|
|
2293
4021
|
.string()
|
|
2294
|
-
.min(1
|
|
2295
|
-
.
|
|
4022
|
+
.min(1)
|
|
4023
|
+
.optional()
|
|
4024
|
+
.describe("Filter by repository owner/organization (e.g., 'example-org'). OPTIONAL: Leave empty for global searches across all of GitHub."),
|
|
2296
4025
|
repo: z
|
|
2297
4026
|
.string()
|
|
2298
4027
|
.optional()
|
|
@@ -2407,18 +4136,71 @@ function registerSearchGitHubIssuesTool(server) {
|
|
|
2407
4136
|
openWorldHint: true,
|
|
2408
4137
|
}, async (args) => {
|
|
2409
4138
|
try {
|
|
2410
|
-
|
|
4139
|
+
const result = await searchGitHubIssues(args);
|
|
4140
|
+
// Check for empty results and enhance with smart suggestions
|
|
4141
|
+
if (result.content && result.content[0]) {
|
|
4142
|
+
let responseText = result.content[0].text;
|
|
4143
|
+
let resultCount = 0;
|
|
4144
|
+
try {
|
|
4145
|
+
const parsed = JSON.parse(responseText);
|
|
4146
|
+
if (parsed.rawOutput) {
|
|
4147
|
+
const rawData = JSON.parse(parsed.rawOutput);
|
|
4148
|
+
resultCount = Array.isArray(rawData) ? rawData.length : 0;
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
catch {
|
|
4152
|
+
// If parsing fails, estimate from text
|
|
4153
|
+
const lines = responseText.split('\n').filter(line => line.trim());
|
|
4154
|
+
resultCount = Math.max(0, lines.length - 5);
|
|
4155
|
+
}
|
|
4156
|
+
// Add smart suggestions for empty or poor results
|
|
4157
|
+
if (resultCount === 0) {
|
|
4158
|
+
responseText += `
|
|
4159
|
+
|
|
4160
|
+
🔄 NO RESULTS RECOVERY STRATEGY:
|
|
4161
|
+
• Try broader terms: "${args.query}" → single keywords
|
|
4162
|
+
• Alternative discovery: github_search_repos for related projects
|
|
4163
|
+
• Problem context: github_search_code for implementation examples
|
|
4164
|
+
• Solution tracking: github_search_pull_requests for fixes
|
|
4165
|
+
|
|
4166
|
+
💡 QUERY SIMPLIFICATION:
|
|
4167
|
+
• Remove quotes and special characters
|
|
4168
|
+
• Use single keywords: "bug", "error", "feature"
|
|
4169
|
+
• Try related terms: "issue" → "problem", "bug" → "error"
|
|
4170
|
+
|
|
4171
|
+
🔗 RECOMMENDED TOOL CHAIN:
|
|
4172
|
+
1. github_search_repos - Find projects that might have similar issues
|
|
4173
|
+
2. github_search_code - Search for code patterns related to your problem
|
|
4174
|
+
3. npm_search_packages - Find packages that solve similar problems`;
|
|
4175
|
+
}
|
|
4176
|
+
else if (resultCount <= 5) {
|
|
4177
|
+
responseText += `
|
|
4178
|
+
|
|
4179
|
+
💡 FEW RESULTS ENHANCEMENT:
|
|
4180
|
+
• Found ${resultCount} issues - try broader search terms
|
|
4181
|
+
• Alternative: github_search_repos for project-level discovery
|
|
4182
|
+
• Cross-reference: github_search_code for implementation patterns`;
|
|
4183
|
+
}
|
|
4184
|
+
return {
|
|
4185
|
+
content: [
|
|
4186
|
+
{
|
|
4187
|
+
type: 'text',
|
|
4188
|
+
text: responseText,
|
|
4189
|
+
},
|
|
4190
|
+
],
|
|
4191
|
+
isError: false,
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
return result;
|
|
2411
4195
|
}
|
|
2412
4196
|
catch (error) {
|
|
2413
|
-
return {
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
isError: true,
|
|
2421
|
-
};
|
|
4197
|
+
return generateSmartRecovery({
|
|
4198
|
+
tool: 'GitHub Issues Search',
|
|
4199
|
+
query: args.query,
|
|
4200
|
+
owner: args.owner,
|
|
4201
|
+
repo: args.repo,
|
|
4202
|
+
error: error,
|
|
4203
|
+
});
|
|
2422
4204
|
}
|
|
2423
4205
|
});
|
|
2424
4206
|
}
|
|
@@ -2535,23 +4317,72 @@ function registerSearchGitHubTopicsTool(server) {
|
|
|
2535
4317
|
openWorldHint: true,
|
|
2536
4318
|
}, async (args) => {
|
|
2537
4319
|
try {
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
4320
|
+
const result = await searchGitHubTopics(args);
|
|
4321
|
+
// Check for empty results and enhance with smart suggestions
|
|
4322
|
+
if (result.content && result.content[0]) {
|
|
4323
|
+
let responseText = result.content[0].text;
|
|
4324
|
+
let resultCount = 0;
|
|
4325
|
+
try {
|
|
4326
|
+
const parsed = JSON.parse(responseText);
|
|
4327
|
+
if (parsed.rawOutput) {
|
|
4328
|
+
const rawData = JSON.parse(parsed.rawOutput);
|
|
4329
|
+
resultCount = Array.isArray(rawData) ? rawData.length : 0;
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
catch {
|
|
4333
|
+
const lines = responseText.split('\n').filter(line => line.trim());
|
|
4334
|
+
resultCount = Math.max(0, lines.length - 5);
|
|
4335
|
+
}
|
|
4336
|
+
if (resultCount === 0) {
|
|
4337
|
+
responseText += `
|
|
4338
|
+
|
|
4339
|
+
🔄 NO TOPICS FOUND RECOVERY:
|
|
4340
|
+
• Try simpler terms: "${args.query}" → single technology keywords
|
|
4341
|
+
• Ecosystem discovery: npm_search_packages for related packages
|
|
4342
|
+
• Repository search: github_search_repos for projects using these topics
|
|
4343
|
+
• User community: github_search_users for topic experts
|
|
4344
|
+
|
|
4345
|
+
💡 TOPIC SEARCH OPTIMIZATION:
|
|
4346
|
+
• Use popular technology terms: "react", "javascript", "python"
|
|
4347
|
+
• Try compound topics: "machine-learning", "web-development"
|
|
4348
|
+
• Focus on featured topics: featured=true
|
|
4349
|
+
|
|
4350
|
+
🔗 RECOMMENDED DISCOVERY CHAIN:
|
|
4351
|
+
1. npm_search_packages - Find packages in this domain
|
|
4352
|
+
2. github_search_repos - Discover projects using these topics
|
|
4353
|
+
3. github_search_code - Find implementations using topic technologies`;
|
|
4354
|
+
}
|
|
4355
|
+
else if (resultCount <= 3) {
|
|
4356
|
+
responseText += `
|
|
4357
|
+
|
|
4358
|
+
💡 LIMITED TOPICS ENHANCEMENT:
|
|
4359
|
+
• Found ${resultCount} topics - try broader or more popular terms
|
|
4360
|
+
• Ecosystem expansion: npm_search_packages for related technologies
|
|
4361
|
+
• Project discovery: github_search_repos for topic implementation`;
|
|
4362
|
+
}
|
|
4363
|
+
return {
|
|
4364
|
+
content: [
|
|
4365
|
+
{
|
|
4366
|
+
type: 'text',
|
|
4367
|
+
text: responseText,
|
|
4368
|
+
},
|
|
4369
|
+
],
|
|
4370
|
+
isError: false,
|
|
4371
|
+
};
|
|
4372
|
+
}
|
|
4373
|
+
return result;
|
|
4374
|
+
}
|
|
4375
|
+
catch (error) {
|
|
4376
|
+
return generateSmartRecovery({
|
|
4377
|
+
tool: 'GitHub Topics Search',
|
|
4378
|
+
query: args.query,
|
|
4379
|
+
error: error,
|
|
4380
|
+
});
|
|
4381
|
+
}
|
|
4382
|
+
});
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4385
|
+
async function searchGitHubUsers(params) {
|
|
2555
4386
|
const cacheKey = generateCacheKey('gh-users', params);
|
|
2556
4387
|
return withCache(cacheKey, async () => {
|
|
2557
4388
|
try {
|
|
@@ -2605,6 +4436,8 @@ function buildGitHubUsersAPICommand(params) {
|
|
|
2605
4436
|
// Add pagination parameters
|
|
2606
4437
|
const limit = params.limit || 30;
|
|
2607
4438
|
queryParams.push(`per_page=${limit}`);
|
|
4439
|
+
const page = params.page || 1;
|
|
4440
|
+
queryParams.push(`page=${page}`);
|
|
2608
4441
|
if (params.sort)
|
|
2609
4442
|
queryParams.push(`sort=${params.sort}`);
|
|
2610
4443
|
if (params.order)
|
|
@@ -2623,8 +4456,9 @@ function registerSearchGitHubUsersTool(server) {
|
|
|
2623
4456
|
.describe("The search query to find users/organizations (e.g., 'react developer', 'python', 'machine learning')"),
|
|
2624
4457
|
owner: z
|
|
2625
4458
|
.string()
|
|
2626
|
-
.min(1
|
|
2627
|
-
.
|
|
4459
|
+
.min(1)
|
|
4460
|
+
.optional()
|
|
4461
|
+
.describe("Filter by repository owner/organization (e.g., 'example-org'). OPTIONAL: Leave empty for global searches across all of GitHub."),
|
|
2628
4462
|
type: z
|
|
2629
4463
|
.enum(['user', 'org'])
|
|
2630
4464
|
.optional()
|
|
@@ -2663,6 +4497,11 @@ function registerSearchGitHubUsersTool(server) {
|
|
|
2663
4497
|
.optional()
|
|
2664
4498
|
.default(50)
|
|
2665
4499
|
.describe('Maximum number of users to return (default: 50)'),
|
|
4500
|
+
page: z
|
|
4501
|
+
.number()
|
|
4502
|
+
.optional()
|
|
4503
|
+
.default(1)
|
|
4504
|
+
.describe('The page number of the results to fetch (default: 1)'),
|
|
2666
4505
|
}, {
|
|
2667
4506
|
title: 'Search GitHub Users',
|
|
2668
4507
|
readOnlyHint: true,
|
|
@@ -2671,79 +4510,67 @@ function registerSearchGitHubUsersTool(server) {
|
|
|
2671
4510
|
openWorldHint: true,
|
|
2672
4511
|
}, async (args) => {
|
|
2673
4512
|
try {
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
: null,
|
|
2712
|
-
analyzedAt: new Date().toISOString(),
|
|
2713
|
-
};
|
|
2714
|
-
return createSuccessResult$1(stats);
|
|
2715
|
-
}
|
|
2716
|
-
catch (error) {
|
|
2717
|
-
return createErrorResult$1('Failed to get npm package statistics', error);
|
|
2718
|
-
}
|
|
2719
|
-
});
|
|
2720
|
-
}
|
|
4513
|
+
const result = await searchGitHubUsers(args);
|
|
4514
|
+
// Check for empty results and enhance with smart suggestions
|
|
4515
|
+
if (result.content && result.content[0]) {
|
|
4516
|
+
let responseText = result.content[0].text;
|
|
4517
|
+
let resultCount = 0;
|
|
4518
|
+
try {
|
|
4519
|
+
const parsed = JSON.parse(responseText);
|
|
4520
|
+
if (parsed.rawOutput) {
|
|
4521
|
+
const rawData = JSON.parse(parsed.rawOutput);
|
|
4522
|
+
resultCount = Array.isArray(rawData) ? rawData.length : 0;
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
catch {
|
|
4526
|
+
const lines = responseText.split('\n').filter(line => line.trim());
|
|
4527
|
+
resultCount = Math.max(0, lines.length - 5);
|
|
4528
|
+
}
|
|
4529
|
+
if (resultCount === 0) {
|
|
4530
|
+
responseText += `
|
|
4531
|
+
|
|
4532
|
+
🔄 NO RESULTS RECOVERY STRATEGY:
|
|
4533
|
+
• Try simpler terms: "${args.query}" → technology keywords only
|
|
4534
|
+
• Organization discovery: github_get_user_organizations for company access
|
|
4535
|
+
• Project-based search: github_search_repos to find user projects
|
|
4536
|
+
• Code contribution search: github_search_code for user activity
|
|
4537
|
+
|
|
4538
|
+
💡 USER SEARCH OPTIMIZATION:
|
|
4539
|
+
• Use technology terms: "react", "python", "javascript"
|
|
4540
|
+
• Try location filters: location="San Francisco", location="Remote"
|
|
4541
|
+
• Focus on active users: followers>10, repos>5
|
|
4542
|
+
|
|
4543
|
+
🔗 RECOMMENDED TOOL CHAIN:
|
|
4544
|
+
1. github_search_repos - Find projects by technology/topic
|
|
4545
|
+
2. github_get_user_organizations - Discover organizations
|
|
4546
|
+
3. npm_search_packages - Find package maintainers`;
|
|
4547
|
+
}
|
|
4548
|
+
else if (resultCount <= 5) {
|
|
4549
|
+
responseText += `
|
|
2721
4550
|
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
4551
|
+
💡 FEW RESULTS ENHANCEMENT:
|
|
4552
|
+
• Found ${resultCount} users - try broader location or technology terms
|
|
4553
|
+
• Alternative: github_search_repos for project discovery
|
|
4554
|
+
• Organization search: github_get_user_organizations`;
|
|
4555
|
+
}
|
|
4556
|
+
return {
|
|
4557
|
+
content: [
|
|
4558
|
+
{
|
|
4559
|
+
type: 'text',
|
|
4560
|
+
text: responseText,
|
|
4561
|
+
},
|
|
4562
|
+
],
|
|
4563
|
+
isError: false,
|
|
4564
|
+
};
|
|
4565
|
+
}
|
|
4566
|
+
return result;
|
|
2736
4567
|
}
|
|
2737
4568
|
catch (error) {
|
|
2738
|
-
return {
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
},
|
|
2744
|
-
],
|
|
2745
|
-
isError: true,
|
|
2746
|
-
};
|
|
4569
|
+
return generateSmartRecovery({
|
|
4570
|
+
tool: 'GitHub Users Search',
|
|
4571
|
+
query: args.query,
|
|
4572
|
+
error: error,
|
|
4573
|
+
});
|
|
2747
4574
|
}
|
|
2748
4575
|
});
|
|
2749
4576
|
}
|
|
@@ -2874,214 +4701,1153 @@ function registerNpmDependencyAnalysisTool(server) {
|
|
|
2874
4701
|
});
|
|
2875
4702
|
}
|
|
2876
4703
|
|
|
2877
|
-
function
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
1. **ALWAYS START**: \`search_github_topics\` - **NEVER SKIP** - Maps ecosystem terminology
|
|
2892
|
-
2. **PRIMARY DISCOVERY**: \`npm_search\` and \`npm_view\` - Minimizes GitHub API calls
|
|
2893
|
-
3. **TARGETED EXTRACTION**: \`search_github_code\` with owner/repo from NPM
|
|
2894
|
-
4. **LAST RESORT**: \`search_github_repos\` - Single terms only when NPM insufficient
|
|
2895
|
-
|
|
2896
|
-
## Core Workflow
|
|
2897
|
-
1. **Check Auth**: Read \`github://auth-status\` and \`github://rate-limits\`
|
|
2898
|
-
2. **MANDATORY**: \`search_github_topics\` for ecosystem mapping
|
|
2899
|
-
3. **NPM Discovery**: \`npm_search\` → \`npm_view\` → extract repository URLs
|
|
2900
|
-
4. **Extract**: Get complete implementations from discovered repositories
|
|
2901
|
-
5. **Validate**: Cross-reference multiple NPM packages
|
|
2902
|
-
|
|
2903
|
-
## Essential Tools (Priority Order)
|
|
2904
|
-
- **\`search_github_topics\`**: **MANDATORY FIRST STEP** - Find technology ecosystems
|
|
2905
|
-
- **\`npm_search\`**: **PRIMARY DISCOVERY** - Find packages by functionality
|
|
2906
|
-
- **\`npm_view\`**: **PRIMARY DISCOVERY** - Package metadata and repo links
|
|
2907
|
-
- **\`view_repository\`**: Get branch info (required before file operations!)
|
|
2908
|
-
- **\`search_github_code\`**: Find specific implementations in discovered repos
|
|
2909
|
-
- **\`fetch_github_file_content\`**: Extract complete code
|
|
2910
|
-
- **\`search_github_repos\`**: **LAST RESORT ONLY** - Single terms when NPM fails
|
|
2911
|
-
|
|
2912
|
-
## Search Strategy Rules
|
|
2913
|
-
- **Topics First**: Every workflow starts with \`search_github_topics\`
|
|
2914
|
-
- **NPM Primary**: Use NPM tools before GitHub repo search
|
|
2915
|
-
- **Single Terms Only**: NEVER multi-term searches in \`search_github_repos\`
|
|
2916
|
-
- **API Conservation**: NPM discovery reduces GitHub API usage by 60%
|
|
2917
|
-
|
|
2918
|
-
## Search Term Strategy
|
|
2919
|
-
- **✅ GOOD**: "react", "authentication", "typescript", "deployment"
|
|
2920
|
-
- **❌ BAD**: "react hooks", "full-stack app", "react angular auth"
|
|
2921
|
-
- **Decompose**: "react typescript auth" → ["react", "typescript", "authentication"]
|
|
2922
|
-
|
|
2923
|
-
## Quick Examples
|
|
2924
|
-
- **Package research**: \`search_github_topics\` → \`npm_search\` → \`npm_view\` → \`view_repository\` → \`search_github_code\`
|
|
2925
|
-
- **Problem solving**: \`search_github_topics\` → \`npm_search\` → \`search_github_issues\` → \`search_github_code\`
|
|
2926
|
-
- **Technology discovery**: \`search_github_topics\` → \`npm_search\` → \`npm_view\` → \`view_repository\` → \`fetch_github_file_content\`
|
|
2927
|
-
|
|
2928
|
-
## CRITICAL REMINDERS
|
|
2929
|
-
- **NEVER skip** \`search_github_topics\` - provides essential context
|
|
2930
|
-
- **NPM FIRST** - use NPM tools before GitHub repo search
|
|
2931
|
-
- **SINGLE TERMS** - never combine multiple concepts in repo searches
|
|
2932
|
-
- **REPOS LAST** - \`search_github_repos\` is lowest priority discovery tool
|
|
2933
|
-
|
|
2934
|
-
Generated: ${new Date().toISOString()}`,
|
|
2935
|
-
},
|
|
2936
|
-
],
|
|
2937
|
-
}));
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
|
-
// GitHub Authentication Status Resource
|
|
2941
|
-
function registerGithubStatusResource(server) {
|
|
2942
|
-
server.resource('github-auth-status', 'github://auth-status', async (uri) => {
|
|
2943
|
-
try {
|
|
2944
|
-
// For version, we'll use a workaround since --version is not a command
|
|
2945
|
-
// We can use 'help' command which shows version info, or skip detailed version check
|
|
2946
|
-
const ghVersion = 'Available (GitHub CLI detected)';
|
|
2947
|
-
let isAuthenticated = false;
|
|
2948
|
-
let authError = null;
|
|
2949
|
-
try {
|
|
2950
|
-
// Check auth status using safe command
|
|
2951
|
-
const authResult = await executeGitHubCommand('auth', ['status'], {
|
|
2952
|
-
timeout: 5000,
|
|
2953
|
-
cache: false,
|
|
2954
|
-
});
|
|
2955
|
-
if (!authResult.isError) {
|
|
2956
|
-
const content = String(authResult.content[0]?.text || '');
|
|
2957
|
-
if (content) {
|
|
2958
|
-
try {
|
|
2959
|
-
const parsed = JSON.parse(content);
|
|
2960
|
-
const output = parsed.result || content;
|
|
2961
|
-
// Only check if authenticated, don't expose user details
|
|
2962
|
-
isAuthenticated =
|
|
2963
|
-
String(output).includes('✓ Logged in') ||
|
|
2964
|
-
String(output).includes('Logged in');
|
|
2965
|
-
}
|
|
2966
|
-
catch {
|
|
2967
|
-
isAuthenticated =
|
|
2968
|
-
content.includes('✓ Logged in') ||
|
|
2969
|
-
content.includes('Logged in');
|
|
2970
|
-
}
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
else {
|
|
2974
|
-
// auth status command failed, check error content for auth info
|
|
2975
|
-
const errorContent = String(authResult.content[0]?.text || 'Authentication check failed');
|
|
2976
|
-
if (errorContent.includes('✓ Logged in') ||
|
|
2977
|
-
errorContent.includes('Logged in')) {
|
|
2978
|
-
isAuthenticated = true;
|
|
2979
|
-
}
|
|
2980
|
-
else {
|
|
2981
|
-
authError = 'Not authenticated';
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
catch (error) {
|
|
2986
|
-
authError = 'Unable to check authentication status';
|
|
4704
|
+
async function checkGitHubAuth() {
|
|
4705
|
+
try {
|
|
4706
|
+
const authResult = await executeGitHubCommand('auth', ['status'], {
|
|
4707
|
+
timeout: 10000,
|
|
4708
|
+
cache: false,
|
|
4709
|
+
});
|
|
4710
|
+
if (authResult.isError) {
|
|
4711
|
+
const errorText = String(authResult.content[0]?.text || '');
|
|
4712
|
+
if (errorText.includes('not logged into') ||
|
|
4713
|
+
errorText.includes('not authenticated')) {
|
|
4714
|
+
return {
|
|
4715
|
+
status: 'not_authenticated',
|
|
4716
|
+
message: 'Not logged into GitHub CLI. Please run: gh auth login',
|
|
4717
|
+
};
|
|
2987
4718
|
}
|
|
2988
4719
|
return {
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
uri: uri.href,
|
|
2992
|
-
mimeType: 'application/json',
|
|
2993
|
-
text: JSON.stringify({
|
|
2994
|
-
status: 'GitHub Authentication Status - LIVE STATUS',
|
|
2995
|
-
description: 'GitHub CLI authentication status and version information',
|
|
2996
|
-
gh_version: ghVersion,
|
|
2997
|
-
authenticated: isAuthenticated,
|
|
2998
|
-
auth_error: authError,
|
|
2999
|
-
setup_instructions: {
|
|
3000
|
-
not_authenticated: [
|
|
3001
|
-
'Run: gh auth login',
|
|
3002
|
-
'Follow the interactive prompts to authenticate',
|
|
3003
|
-
'Choose your preferred authentication method',
|
|
3004
|
-
],
|
|
3005
|
-
verification: [
|
|
3006
|
-
'Run: gh auth status',
|
|
3007
|
-
'Should show "✓ Logged in" if successful',
|
|
3008
|
-
],
|
|
3009
|
-
},
|
|
3010
|
-
timestamp: new Date().toISOString(),
|
|
3011
|
-
}, null, 2),
|
|
3012
|
-
},
|
|
3013
|
-
],
|
|
4720
|
+
status: 'error',
|
|
4721
|
+
message: `GitHub CLI error: ${errorText}`,
|
|
3014
4722
|
};
|
|
3015
4723
|
}
|
|
3016
|
-
|
|
4724
|
+
const statusText = String(authResult.content[0]?.text || '');
|
|
4725
|
+
// Extract username if present
|
|
4726
|
+
const userMatch = statusText.match(/Logged in to github\.com as ([^\s]+)/);
|
|
4727
|
+
const user = userMatch ? userMatch[1] : undefined;
|
|
4728
|
+
if (statusText.includes('Logged in to github.com')) {
|
|
3017
4729
|
return {
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
mimeType: 'application/json',
|
|
3022
|
-
text: JSON.stringify({
|
|
3023
|
-
status: 'GitHub Authentication Status - ERROR',
|
|
3024
|
-
error: error.message,
|
|
3025
|
-
message: 'GitHub CLI may not be installed or accessible',
|
|
3026
|
-
timestamp: new Date().toISOString(),
|
|
3027
|
-
}, null, 2),
|
|
3028
|
-
},
|
|
3029
|
-
],
|
|
4730
|
+
status: 'authenticated',
|
|
4731
|
+
user,
|
|
4732
|
+
message: user ? `Authenticated as ${user}` : 'Authenticated to GitHub',
|
|
3030
4733
|
};
|
|
3031
4734
|
}
|
|
3032
|
-
|
|
4735
|
+
return {
|
|
4736
|
+
status: 'not_authenticated',
|
|
4737
|
+
message: 'GitHub CLI authentication status unclear. Please run: gh auth login',
|
|
4738
|
+
};
|
|
4739
|
+
}
|
|
4740
|
+
catch (error) {
|
|
4741
|
+
return {
|
|
4742
|
+
status: 'error',
|
|
4743
|
+
message: `Failed to check GitHub auth: ${error.message}`,
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
3033
4746
|
}
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
if
|
|
3050
|
-
|
|
4747
|
+
async function checkNpmConnectivity() {
|
|
4748
|
+
try {
|
|
4749
|
+
const pingResult = await executeNpmCommand('ping', [], {
|
|
4750
|
+
timeout: 10000,
|
|
4751
|
+
cache: false,
|
|
4752
|
+
});
|
|
4753
|
+
if (pingResult.isError) {
|
|
4754
|
+
const errorText = String(pingResult.content[0]?.text || '');
|
|
4755
|
+
return {
|
|
4756
|
+
status: 'disconnected',
|
|
4757
|
+
message: `NPM registry unreachable: ${errorText}`,
|
|
4758
|
+
};
|
|
4759
|
+
}
|
|
4760
|
+
const pingText = String(pingResult.content[0]?.text || '');
|
|
4761
|
+
if (pingText.includes('npm ping ok') || pingText.includes('Ping success')) {
|
|
4762
|
+
// Extract registry if present
|
|
4763
|
+
const registryMatch = pingText.match(/registry: (.+)/);
|
|
4764
|
+
const registry = registryMatch
|
|
4765
|
+
? registryMatch[1]
|
|
4766
|
+
: 'https://registry.npmjs.org';
|
|
4767
|
+
return {
|
|
4768
|
+
status: 'connected',
|
|
4769
|
+
registry,
|
|
4770
|
+
message: `Connected to NPM registry: ${registry}`,
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4773
|
+
return {
|
|
4774
|
+
status: 'error',
|
|
4775
|
+
message: `NPM ping response unclear: ${pingText}`,
|
|
4776
|
+
};
|
|
4777
|
+
}
|
|
4778
|
+
catch (error) {
|
|
4779
|
+
return {
|
|
4780
|
+
status: 'error',
|
|
4781
|
+
message: `Failed to ping NPM registry: ${error.message}`,
|
|
4782
|
+
};
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
async function checkGitHubRateLimits() {
|
|
4786
|
+
try {
|
|
4787
|
+
const rateLimitResult = await executeGitHubCommand('api', ['rate_limit'], {
|
|
4788
|
+
timeout: 10000,
|
|
4789
|
+
cache: false,
|
|
4790
|
+
});
|
|
4791
|
+
if (rateLimitResult.isError) {
|
|
4792
|
+
const errorText = String(rateLimitResult.content[0]?.text || '');
|
|
4793
|
+
return {
|
|
4794
|
+
status: 'error',
|
|
4795
|
+
primary_api: {
|
|
4796
|
+
remaining: 0,
|
|
4797
|
+
limit: 0,
|
|
4798
|
+
reset_time: '',
|
|
4799
|
+
usage_percentage: 100,
|
|
4800
|
+
},
|
|
4801
|
+
search_api: {
|
|
4802
|
+
remaining: 0,
|
|
4803
|
+
limit: 0,
|
|
4804
|
+
reset_time: '',
|
|
4805
|
+
usage_percentage: 100,
|
|
4806
|
+
},
|
|
4807
|
+
code_search: {
|
|
4808
|
+
remaining: 0,
|
|
4809
|
+
limit: 0,
|
|
4810
|
+
reset_time: '',
|
|
4811
|
+
usage_percentage: 100,
|
|
4812
|
+
},
|
|
4813
|
+
message: `Failed to fetch rate limits: ${errorText}`,
|
|
4814
|
+
recommendations: [
|
|
4815
|
+
'GitHub authentication may be required',
|
|
4816
|
+
'Run: gh auth login',
|
|
4817
|
+
],
|
|
4818
|
+
};
|
|
4819
|
+
}
|
|
4820
|
+
const content = String(rateLimitResult.content[0]?.text || '');
|
|
4821
|
+
if (!content) {
|
|
4822
|
+
throw new Error('No rate limit data received');
|
|
4823
|
+
}
|
|
4824
|
+
let rateLimit;
|
|
4825
|
+
try {
|
|
4826
|
+
const parsed = JSON.parse(content);
|
|
4827
|
+
rateLimit = parsed.result || parsed;
|
|
4828
|
+
}
|
|
4829
|
+
catch {
|
|
4830
|
+
rateLimit = JSON.parse(content);
|
|
4831
|
+
}
|
|
4832
|
+
const formatResetTime = (reset) => new Date(reset * 1000).toISOString();
|
|
4833
|
+
const calculateUsage = (used, limit) => Math.round((used / limit) * 100);
|
|
4834
|
+
const core = rateLimit.resources.core;
|
|
4835
|
+
const search = rateLimit.resources.search;
|
|
4836
|
+
const codeSearch = rateLimit.resources.code_search;
|
|
4837
|
+
const primaryApi = {
|
|
4838
|
+
remaining: core.remaining,
|
|
4839
|
+
limit: core.limit,
|
|
4840
|
+
reset_time: formatResetTime(core.reset),
|
|
4841
|
+
usage_percentage: calculateUsage(core.used, core.limit),
|
|
4842
|
+
};
|
|
4843
|
+
const searchApi = {
|
|
4844
|
+
remaining: search.remaining,
|
|
4845
|
+
limit: search.limit,
|
|
4846
|
+
reset_time: formatResetTime(search.reset),
|
|
4847
|
+
usage_percentage: calculateUsage(search.used, search.limit),
|
|
4848
|
+
};
|
|
4849
|
+
const codeSearchApi = {
|
|
4850
|
+
remaining: codeSearch.remaining,
|
|
4851
|
+
limit: codeSearch.limit,
|
|
4852
|
+
reset_time: formatResetTime(codeSearch.reset),
|
|
4853
|
+
usage_percentage: calculateUsage(codeSearch.used, codeSearch.limit),
|
|
4854
|
+
};
|
|
4855
|
+
// Determine overall status
|
|
4856
|
+
const minRemaining = Math.min(core.remaining, search.remaining, codeSearch.remaining);
|
|
4857
|
+
let status;
|
|
4858
|
+
const recommendations = [];
|
|
4859
|
+
if (minRemaining === 0) {
|
|
4860
|
+
status = 'exhausted';
|
|
4861
|
+
recommendations.push('🚨 API limits exhausted - wait for reset or use alternative approaches');
|
|
4862
|
+
recommendations.push('Consider using cached data or reducing API calls');
|
|
4863
|
+
}
|
|
4864
|
+
else if (minRemaining < 10) {
|
|
4865
|
+
status = 'limited';
|
|
4866
|
+
recommendations.push('⚠️ API limits low - prioritize essential requests only');
|
|
4867
|
+
recommendations.push('Avoid extensive searches or bulk operations');
|
|
4868
|
+
}
|
|
4869
|
+
else {
|
|
4870
|
+
status = 'healthy';
|
|
4871
|
+
recommendations.push('✅ All APIs ready for normal operation');
|
|
4872
|
+
}
|
|
4873
|
+
// Add specific API recommendations
|
|
4874
|
+
if (codeSearch.remaining < 5) {
|
|
4875
|
+
recommendations.push('🔍 Code search severely limited - use repository-specific searches');
|
|
4876
|
+
}
|
|
4877
|
+
if (search.remaining < 10) {
|
|
4878
|
+
recommendations.push('🔎 Search API limited - reduce search complexity');
|
|
4879
|
+
}
|
|
4880
|
+
if (core.remaining < 100) {
|
|
4881
|
+
recommendations.push('🏠 Core API limited - avoid bulk repository operations');
|
|
4882
|
+
}
|
|
4883
|
+
return {
|
|
4884
|
+
status,
|
|
4885
|
+
primary_api: primaryApi,
|
|
4886
|
+
search_api: searchApi,
|
|
4887
|
+
code_search: codeSearchApi,
|
|
4888
|
+
message: `Rate limits checked - ${status}`,
|
|
4889
|
+
recommendations,
|
|
4890
|
+
};
|
|
4891
|
+
}
|
|
4892
|
+
catch (error) {
|
|
4893
|
+
return {
|
|
4894
|
+
status: 'error',
|
|
4895
|
+
primary_api: {
|
|
4896
|
+
remaining: 0,
|
|
4897
|
+
limit: 0,
|
|
4898
|
+
reset_time: '',
|
|
4899
|
+
usage_percentage: 100,
|
|
4900
|
+
},
|
|
4901
|
+
search_api: {
|
|
4902
|
+
remaining: 0,
|
|
4903
|
+
limit: 0,
|
|
4904
|
+
reset_time: '',
|
|
4905
|
+
usage_percentage: 100,
|
|
4906
|
+
},
|
|
4907
|
+
code_search: {
|
|
4908
|
+
remaining: 0,
|
|
4909
|
+
limit: 0,
|
|
4910
|
+
reset_time: '',
|
|
4911
|
+
usage_percentage: 100,
|
|
4912
|
+
},
|
|
4913
|
+
message: `Error checking rate limits: ${error.message}`,
|
|
4914
|
+
recommendations: [
|
|
4915
|
+
'Unable to determine API status',
|
|
4916
|
+
'Check GitHub authentication',
|
|
4917
|
+
],
|
|
4918
|
+
};
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4921
|
+
async function performApiStatusCheck() {
|
|
4922
|
+
try {
|
|
4923
|
+
console.log('🔍 Performing comprehensive API status check...');
|
|
4924
|
+
// Perform all checks in parallel for efficiency
|
|
4925
|
+
const [githubAuth, npmConnectivity, githubRateLimits] = await Promise.all([
|
|
4926
|
+
checkGitHubAuth(),
|
|
4927
|
+
checkNpmConnectivity(),
|
|
4928
|
+
checkGitHubRateLimits(),
|
|
4929
|
+
]);
|
|
4930
|
+
// Determine overall status
|
|
4931
|
+
let overallStatus;
|
|
4932
|
+
const researchRecommendations = [];
|
|
4933
|
+
if (githubAuth.status !== 'authenticated') {
|
|
4934
|
+
overallStatus = 'not_ready';
|
|
4935
|
+
researchRecommendations.push('❌ GitHub authentication required before research');
|
|
4936
|
+
researchRecommendations.push('Run: gh auth login');
|
|
4937
|
+
}
|
|
4938
|
+
else if (npmConnectivity.status !== 'connected') {
|
|
4939
|
+
overallStatus = 'limited';
|
|
4940
|
+
researchRecommendations.push('⚠️ NPM unavailable - GitHub research only');
|
|
4941
|
+
}
|
|
4942
|
+
else if (githubRateLimits.status === 'exhausted') {
|
|
4943
|
+
overallStatus = 'not_ready';
|
|
4944
|
+
researchRecommendations.push('❌ GitHub API exhausted - wait for reset');
|
|
4945
|
+
researchRecommendations.push(`Next reset: ${githubRateLimits.code_search.reset_time}`);
|
|
4946
|
+
}
|
|
4947
|
+
else if (githubRateLimits.status === 'limited') {
|
|
4948
|
+
overallStatus = 'limited';
|
|
4949
|
+
researchRecommendations.push('⚠️ Limited API quota - reduce research scope');
|
|
4950
|
+
researchRecommendations.push('Use targeted searches instead of broad exploration');
|
|
4951
|
+
}
|
|
4952
|
+
else {
|
|
4953
|
+
overallStatus = 'ready';
|
|
4954
|
+
researchRecommendations.push('✅ All systems ready for comprehensive research');
|
|
4955
|
+
researchRecommendations.push('NPM package discovery and GitHub analysis available');
|
|
4956
|
+
}
|
|
4957
|
+
// Add research strategy recommendations based on API limits
|
|
4958
|
+
if (githubRateLimits.code_search.remaining < 5) {
|
|
4959
|
+
researchRecommendations.push('🔍 Code search critical - use repository browsing instead');
|
|
4960
|
+
}
|
|
4961
|
+
if (githubRateLimits.search_api.remaining < 20) {
|
|
4962
|
+
researchRecommendations.push('🔎 Search API limited - focus on specific repositories');
|
|
4963
|
+
}
|
|
4964
|
+
if (githubRateLimits.primary_api.remaining < 200) {
|
|
4965
|
+
researchRecommendations.push('🏠 Core API limited - minimize repository exploration');
|
|
4966
|
+
}
|
|
4967
|
+
const result = {
|
|
4968
|
+
github_auth: githubAuth,
|
|
4969
|
+
npm_connectivity: npmConnectivity,
|
|
4970
|
+
github_rate_limits: githubRateLimits,
|
|
4971
|
+
overall_status: overallStatus,
|
|
4972
|
+
research_recommendations: researchRecommendations,
|
|
4973
|
+
timestamp: new Date().toISOString(),
|
|
4974
|
+
};
|
|
4975
|
+
return {
|
|
4976
|
+
content: [
|
|
4977
|
+
{
|
|
4978
|
+
type: 'text',
|
|
4979
|
+
text: JSON.stringify(result, null, 2),
|
|
4980
|
+
},
|
|
4981
|
+
],
|
|
4982
|
+
isError: false,
|
|
4983
|
+
};
|
|
4984
|
+
}
|
|
4985
|
+
catch (error) {
|
|
4986
|
+
return {
|
|
4987
|
+
content: [
|
|
4988
|
+
{
|
|
4989
|
+
type: 'text',
|
|
4990
|
+
text: `🚨 API Status Check Failed: ${error.message}
|
|
4991
|
+
|
|
4992
|
+
🔧 Troubleshooting Steps:
|
|
4993
|
+
1. Check GitHub CLI installation: gh --version
|
|
4994
|
+
2. Check NPM installation: npm --version
|
|
4995
|
+
3. Check network connectivity
|
|
4996
|
+
4. Try: gh auth login
|
|
4997
|
+
5. Try: npm ping
|
|
4998
|
+
|
|
4999
|
+
💡 Manual Verification:
|
|
5000
|
+
- GitHub Auth: gh auth status
|
|
5001
|
+
- NPM Registry: npm ping
|
|
5002
|
+
- GitHub API: gh api rate_limit`,
|
|
5003
|
+
},
|
|
5004
|
+
],
|
|
5005
|
+
isError: true,
|
|
5006
|
+
};
|
|
5007
|
+
}
|
|
5008
|
+
}
|
|
5009
|
+
function registerApiStatusCheckTool(server) {
|
|
5010
|
+
server.tool(TOOL_NAMES.API_STATUS_CHECK, TOOL_DESCRIPTIONS[TOOL_NAMES.API_STATUS_CHECK], {
|
|
5011
|
+
// No parameters needed for status check
|
|
5012
|
+
}, {
|
|
5013
|
+
title: 'API Status Check',
|
|
5014
|
+
readOnlyHint: true,
|
|
5015
|
+
destructiveHint: false,
|
|
5016
|
+
idempotentHint: true,
|
|
5017
|
+
openWorldHint: false,
|
|
5018
|
+
}, async () => {
|
|
5019
|
+
return await performApiStatusCheck();
|
|
5020
|
+
});
|
|
5021
|
+
}
|
|
5022
|
+
|
|
5023
|
+
async function npmGetRepository(packageName) {
|
|
5024
|
+
const cacheKey = generateCacheKey('npm-get-repository', { packageName });
|
|
5025
|
+
return withCache(cacheKey, async () => {
|
|
5026
|
+
try {
|
|
5027
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5028
|
+
cache: true,
|
|
5029
|
+
});
|
|
5030
|
+
if (result.isError) {
|
|
5031
|
+
return result;
|
|
5032
|
+
}
|
|
5033
|
+
// Parse the result from the executed command
|
|
5034
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5035
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5036
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5037
|
+
// Extract only repository-related data
|
|
5038
|
+
const repositoryResult = {
|
|
5039
|
+
packageName: npmData.name,
|
|
5040
|
+
description: npmData.description,
|
|
5041
|
+
repository: npmData.repository,
|
|
5042
|
+
homepage: npmData.homepage,
|
|
5043
|
+
};
|
|
5044
|
+
return createSuccessResult$1(repositoryResult);
|
|
5045
|
+
}
|
|
5046
|
+
catch (error) {
|
|
5047
|
+
return createErrorResult$1('Failed to get npm repository information', error);
|
|
5048
|
+
}
|
|
5049
|
+
});
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
function registerNpmGetRepositoryTool(server) {
|
|
5053
|
+
server.tool(TOOL_NAMES.NPM_GET_REPOSITORY, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_REPOSITORY], {
|
|
5054
|
+
packageName: z
|
|
5055
|
+
.string()
|
|
5056
|
+
.describe("The name of the npm package to get repository information for (e.g., 'react', 'express', 'lodash'). Returns minimal repository data: package name, description, repository URL, and homepage - optimized for token efficiency."),
|
|
5057
|
+
}, {
|
|
5058
|
+
title: 'NPM Repository Discovery - Extract GitHub Repository URL',
|
|
5059
|
+
readOnlyHint: true,
|
|
5060
|
+
destructiveHint: false,
|
|
5061
|
+
idempotentHint: true,
|
|
5062
|
+
openWorldHint: true,
|
|
5063
|
+
}, async (args) => {
|
|
5064
|
+
try {
|
|
5065
|
+
return await npmGetRepository(args.packageName);
|
|
5066
|
+
}
|
|
5067
|
+
catch (error) {
|
|
5068
|
+
const errorMessage = error.message;
|
|
5069
|
+
// Enhanced error handling for package not found
|
|
5070
|
+
if (errorMessage.includes('404') ||
|
|
5071
|
+
errorMessage.includes('not found')) {
|
|
5072
|
+
return generateSmartRecovery({
|
|
5073
|
+
tool: 'NPM Get Repository',
|
|
5074
|
+
packageName: args.packageName,
|
|
5075
|
+
error: error,
|
|
5076
|
+
});
|
|
5077
|
+
}
|
|
5078
|
+
// Generic enhanced error handling
|
|
5079
|
+
return generateSmartRecovery({
|
|
5080
|
+
tool: 'NPM Get Repository',
|
|
5081
|
+
packageName: args.packageName,
|
|
5082
|
+
error: error,
|
|
5083
|
+
});
|
|
5084
|
+
}
|
|
5085
|
+
});
|
|
5086
|
+
}
|
|
5087
|
+
|
|
5088
|
+
async function npmGetDependencies(packageName) {
|
|
5089
|
+
const cacheKey = generateCacheKey('npm-get-dependencies', { packageName });
|
|
5090
|
+
return withCache(cacheKey, async () => {
|
|
5091
|
+
try {
|
|
5092
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5093
|
+
cache: true,
|
|
5094
|
+
});
|
|
5095
|
+
if (result.isError) {
|
|
5096
|
+
return result;
|
|
5097
|
+
}
|
|
5098
|
+
// Parse the result from the executed command
|
|
5099
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5100
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5101
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5102
|
+
// Extract only dependencies data
|
|
5103
|
+
const dependenciesResult = {
|
|
5104
|
+
packageName: npmData.name,
|
|
5105
|
+
dependencies: npmData.dependencies || {},
|
|
5106
|
+
devDependencies: npmData.devDependencies || {},
|
|
5107
|
+
resolutions: npmData.resolutions || {},
|
|
5108
|
+
};
|
|
5109
|
+
return createSuccessResult$1(dependenciesResult);
|
|
5110
|
+
}
|
|
5111
|
+
catch (error) {
|
|
5112
|
+
return createErrorResult$1('Failed to get npm dependencies information', error);
|
|
5113
|
+
}
|
|
5114
|
+
});
|
|
5115
|
+
}
|
|
5116
|
+
|
|
5117
|
+
function registerNpmGetDependenciesTool(server) {
|
|
5118
|
+
server.tool(TOOL_NAMES.NPM_GET_DEPENDENCIES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_DEPENDENCIES], {
|
|
5119
|
+
packageName: z
|
|
5120
|
+
.string()
|
|
5121
|
+
.describe("The name of the npm package to analyze dependencies for (e.g., 'react', 'express', 'lodash'). Returns focused dependency data: dependencies, devDependencies, and resolutions - optimized for token efficiency."),
|
|
5122
|
+
}, {
|
|
5123
|
+
title: 'NPM Dependency Analysis - Extract Package Dependencies',
|
|
5124
|
+
readOnlyHint: true,
|
|
5125
|
+
destructiveHint: false,
|
|
5126
|
+
idempotentHint: true,
|
|
5127
|
+
openWorldHint: true,
|
|
5128
|
+
}, async (args) => {
|
|
5129
|
+
try {
|
|
5130
|
+
return await npmGetDependencies(args.packageName);
|
|
5131
|
+
}
|
|
5132
|
+
catch (error) {
|
|
5133
|
+
return generateSmartRecovery({
|
|
5134
|
+
tool: 'NPM Get Dependencies',
|
|
5135
|
+
packageName: args.packageName,
|
|
5136
|
+
error: error,
|
|
5137
|
+
});
|
|
5138
|
+
}
|
|
5139
|
+
});
|
|
5140
|
+
}
|
|
5141
|
+
|
|
5142
|
+
async function npmGetBugs(packageName) {
|
|
5143
|
+
const cacheKey = generateCacheKey('npm-get-bugs', { packageName });
|
|
5144
|
+
return withCache(cacheKey, async () => {
|
|
5145
|
+
try {
|
|
5146
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5147
|
+
cache: true,
|
|
5148
|
+
});
|
|
5149
|
+
if (result.isError) {
|
|
5150
|
+
return result;
|
|
5151
|
+
}
|
|
5152
|
+
// Parse the result from the executed command
|
|
5153
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5154
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5155
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5156
|
+
// Extract only bugs data
|
|
5157
|
+
const bugsResult = {
|
|
5158
|
+
packageName: npmData.name,
|
|
5159
|
+
bugs: npmData.bugs,
|
|
5160
|
+
};
|
|
5161
|
+
return createSuccessResult$1(bugsResult);
|
|
5162
|
+
}
|
|
5163
|
+
catch (error) {
|
|
5164
|
+
return createErrorResult$1('Failed to get npm bugs information', error);
|
|
5165
|
+
}
|
|
5166
|
+
});
|
|
5167
|
+
}
|
|
5168
|
+
|
|
5169
|
+
function registerNpmGetBugsTool(server) {
|
|
5170
|
+
server.tool(TOOL_NAMES.NPM_GET_BUGS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_BUGS], {
|
|
5171
|
+
packageName: z
|
|
5172
|
+
.string()
|
|
5173
|
+
.describe("The name of the npm package to get bug tracking information for (e.g., 'react', 'express', 'lodash'). Returns minimal bug data: package name and bugs URL - optimized for token efficiency."),
|
|
5174
|
+
}, {
|
|
5175
|
+
title: 'NPM Bug Tracking - Extract Issue Tracker URL',
|
|
5176
|
+
readOnlyHint: true,
|
|
5177
|
+
destructiveHint: false,
|
|
5178
|
+
idempotentHint: true,
|
|
5179
|
+
openWorldHint: true,
|
|
5180
|
+
}, async (args) => {
|
|
5181
|
+
try {
|
|
5182
|
+
return await npmGetBugs(args.packageName);
|
|
5183
|
+
}
|
|
5184
|
+
catch (error) {
|
|
5185
|
+
return {
|
|
5186
|
+
content: [
|
|
5187
|
+
{
|
|
5188
|
+
type: 'text',
|
|
5189
|
+
text: `Failed to get npm bugs info: ${error.message}`,
|
|
5190
|
+
},
|
|
5191
|
+
],
|
|
5192
|
+
isError: true,
|
|
5193
|
+
};
|
|
5194
|
+
}
|
|
5195
|
+
});
|
|
5196
|
+
}
|
|
5197
|
+
|
|
5198
|
+
async function npmGetReadme(packageName) {
|
|
5199
|
+
const cacheKey = generateCacheKey('npm-get-readme', { packageName });
|
|
5200
|
+
return withCache(cacheKey, async () => {
|
|
5201
|
+
try {
|
|
5202
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5203
|
+
cache: true,
|
|
5204
|
+
});
|
|
5205
|
+
if (result.isError) {
|
|
5206
|
+
return result;
|
|
5207
|
+
}
|
|
5208
|
+
// Parse the result from the executed command
|
|
5209
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5210
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5211
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5212
|
+
// Extract only readme data
|
|
5213
|
+
const readmeResult = {
|
|
5214
|
+
packageName: npmData.name,
|
|
5215
|
+
readmeFilename: npmData.readmeFilename,
|
|
5216
|
+
};
|
|
5217
|
+
return createSuccessResult$1(readmeResult);
|
|
5218
|
+
}
|
|
5219
|
+
catch (error) {
|
|
5220
|
+
return createErrorResult$1('Failed to get npm readme information', error);
|
|
5221
|
+
}
|
|
5222
|
+
});
|
|
5223
|
+
}
|
|
5224
|
+
|
|
5225
|
+
function registerNpmGetReadmeTool(server) {
|
|
5226
|
+
server.tool(TOOL_NAMES.NPM_GET_README, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_README], {
|
|
5227
|
+
packageName: z
|
|
5228
|
+
.string()
|
|
5229
|
+
.describe("The name of the npm package to get README information for (e.g., 'react', 'express', 'lodash'). Returns minimal README data: package name and readme filename - optimized for token efficiency."),
|
|
5230
|
+
}, {
|
|
5231
|
+
title: 'NPM Documentation Access - Extract README Filename',
|
|
5232
|
+
readOnlyHint: true,
|
|
5233
|
+
destructiveHint: false,
|
|
5234
|
+
idempotentHint: true,
|
|
5235
|
+
openWorldHint: true,
|
|
5236
|
+
}, async (args) => {
|
|
5237
|
+
try {
|
|
5238
|
+
return await npmGetReadme(args.packageName);
|
|
5239
|
+
}
|
|
5240
|
+
catch (error) {
|
|
5241
|
+
return {
|
|
5242
|
+
content: [
|
|
5243
|
+
{
|
|
5244
|
+
type: 'text',
|
|
5245
|
+
text: `Failed to get npm readme info: ${error.message}`,
|
|
5246
|
+
},
|
|
5247
|
+
],
|
|
5248
|
+
isError: true,
|
|
5249
|
+
};
|
|
5250
|
+
}
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
|
|
5254
|
+
async function npmGetVersions(packageName) {
|
|
5255
|
+
const cacheKey = generateCacheKey('npm-get-versions', { packageName });
|
|
5256
|
+
return withCache(cacheKey, async () => {
|
|
5257
|
+
try {
|
|
5258
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5259
|
+
cache: true,
|
|
5260
|
+
});
|
|
5261
|
+
if (result.isError) {
|
|
5262
|
+
return result;
|
|
5263
|
+
}
|
|
5264
|
+
// Parse the result from the executed command
|
|
5265
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5266
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5267
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5268
|
+
// Filter versions to include only official semantic versions (major.minor.patch)
|
|
5269
|
+
// Excludes pre-release versions like alpha, beta, rc, dev, experimental, etc.
|
|
5270
|
+
const semanticVersionRegex = /^\d+\.\d+\.\d+$/;
|
|
5271
|
+
const officialVersions = npmData.versions.filter(version => semanticVersionRegex.test(version));
|
|
5272
|
+
// Extract only versions data with filtered official versions
|
|
5273
|
+
const versionsResult = {
|
|
5274
|
+
packageName: npmData.name,
|
|
5275
|
+
versions: officialVersions,
|
|
5276
|
+
latestVersion: npmData['dist-tags'].latest,
|
|
5277
|
+
versionCount: officialVersions.length,
|
|
5278
|
+
};
|
|
5279
|
+
return createSuccessResult$1(versionsResult);
|
|
5280
|
+
}
|
|
5281
|
+
catch (error) {
|
|
5282
|
+
return createErrorResult$1('Failed to get npm versions information', error);
|
|
5283
|
+
}
|
|
5284
|
+
});
|
|
5285
|
+
}
|
|
5286
|
+
|
|
5287
|
+
function registerNpmGetVersionsTool(server) {
|
|
5288
|
+
server.tool(TOOL_NAMES.NPM_GET_VERSIONS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_VERSIONS], {
|
|
5289
|
+
packageName: z
|
|
5290
|
+
.string()
|
|
5291
|
+
.describe("The name of the npm package to get version information for (e.g., 'react', 'express', 'lodash'). Returns only official semantic versions (major.minor.patch format), excluding pre-release versions like alpha, beta, rc - optimized for production planning."),
|
|
5292
|
+
}, {
|
|
5293
|
+
title: 'NPM Version Tracking - Extract Package Versions',
|
|
5294
|
+
readOnlyHint: true,
|
|
5295
|
+
destructiveHint: false,
|
|
5296
|
+
idempotentHint: true,
|
|
5297
|
+
openWorldHint: true,
|
|
5298
|
+
}, async (args) => {
|
|
5299
|
+
try {
|
|
5300
|
+
return await npmGetVersions(args.packageName);
|
|
5301
|
+
}
|
|
5302
|
+
catch (error) {
|
|
5303
|
+
return {
|
|
5304
|
+
content: [
|
|
5305
|
+
{
|
|
5306
|
+
type: 'text',
|
|
5307
|
+
text: `Failed to get npm versions: ${error.message}`,
|
|
5308
|
+
},
|
|
5309
|
+
],
|
|
5310
|
+
isError: true,
|
|
5311
|
+
};
|
|
5312
|
+
}
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
5315
|
+
|
|
5316
|
+
async function npmGetAuthor(packageName) {
|
|
5317
|
+
const cacheKey = generateCacheKey('npm-get-author', { packageName });
|
|
5318
|
+
return withCache(cacheKey, async () => {
|
|
5319
|
+
try {
|
|
5320
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5321
|
+
cache: true,
|
|
5322
|
+
});
|
|
5323
|
+
if (result.isError) {
|
|
5324
|
+
return result;
|
|
5325
|
+
}
|
|
5326
|
+
// Parse the result from the executed command
|
|
5327
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5328
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5329
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5330
|
+
// Extract only author data
|
|
5331
|
+
const authorResult = {
|
|
5332
|
+
packageName: npmData.name,
|
|
5333
|
+
author: npmData.author,
|
|
5334
|
+
maintainers: npmData.maintainers,
|
|
5335
|
+
};
|
|
5336
|
+
return createSuccessResult$1(authorResult);
|
|
5337
|
+
}
|
|
5338
|
+
catch (error) {
|
|
5339
|
+
return createErrorResult$1('Failed to get npm author information', error);
|
|
5340
|
+
}
|
|
5341
|
+
});
|
|
5342
|
+
}
|
|
5343
|
+
|
|
5344
|
+
function registerNpmGetAuthorTool(server) {
|
|
5345
|
+
server.tool(TOOL_NAMES.NPM_GET_AUTHOR, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_AUTHOR], {
|
|
5346
|
+
packageName: z
|
|
5347
|
+
.string()
|
|
5348
|
+
.describe("The name of the npm package to get author information for (e.g., 'react', 'express', 'lodash'). Returns focused author data: author and maintainers list - optimized for token efficiency."),
|
|
5349
|
+
}, {
|
|
5350
|
+
title: 'NPM Maintainer Information - Extract Author and Maintainers',
|
|
5351
|
+
readOnlyHint: true,
|
|
5352
|
+
destructiveHint: false,
|
|
5353
|
+
idempotentHint: true,
|
|
5354
|
+
openWorldHint: true,
|
|
5355
|
+
}, async (args) => {
|
|
5356
|
+
try {
|
|
5357
|
+
return await npmGetAuthor(args.packageName);
|
|
5358
|
+
}
|
|
5359
|
+
catch (error) {
|
|
5360
|
+
return {
|
|
5361
|
+
content: [
|
|
5362
|
+
{
|
|
5363
|
+
type: 'text',
|
|
5364
|
+
text: `Failed to get npm author info: ${error.message}`,
|
|
5365
|
+
},
|
|
5366
|
+
],
|
|
5367
|
+
isError: true,
|
|
5368
|
+
};
|
|
5369
|
+
}
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
async function npmGetLicense(packageName) {
|
|
5374
|
+
const cacheKey = generateCacheKey('npm-get-license', { packageName });
|
|
5375
|
+
return withCache(cacheKey, async () => {
|
|
5376
|
+
try {
|
|
5377
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5378
|
+
cache: true,
|
|
5379
|
+
});
|
|
5380
|
+
if (result.isError) {
|
|
5381
|
+
return result;
|
|
5382
|
+
}
|
|
5383
|
+
// Parse the result from the executed command
|
|
5384
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5385
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5386
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5387
|
+
// Extract only license data
|
|
5388
|
+
const licenseResult = {
|
|
5389
|
+
packageName: npmData.name,
|
|
5390
|
+
license: npmData.license,
|
|
5391
|
+
};
|
|
5392
|
+
return createSuccessResult$1(licenseResult);
|
|
5393
|
+
}
|
|
5394
|
+
catch (error) {
|
|
5395
|
+
return createErrorResult$1('Failed to get npm license information', error);
|
|
5396
|
+
}
|
|
5397
|
+
});
|
|
5398
|
+
}
|
|
5399
|
+
|
|
5400
|
+
function registerNpmGetLicenseTool(server) {
|
|
5401
|
+
server.tool(TOOL_NAMES.NPM_GET_LICENSE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_LICENSE], {
|
|
5402
|
+
packageName: z
|
|
5403
|
+
.string()
|
|
5404
|
+
.describe("The name of the npm package to get license information for (e.g., 'react', 'express', 'lodash'). Returns minimal license data: package name and license - optimized for token efficiency."),
|
|
5405
|
+
}, {
|
|
5406
|
+
title: 'NPM License Compliance - Extract Package License',
|
|
5407
|
+
readOnlyHint: true,
|
|
5408
|
+
destructiveHint: false,
|
|
5409
|
+
idempotentHint: true,
|
|
5410
|
+
openWorldHint: true,
|
|
5411
|
+
}, async (args) => {
|
|
5412
|
+
try {
|
|
5413
|
+
return await npmGetLicense(args.packageName);
|
|
5414
|
+
}
|
|
5415
|
+
catch (error) {
|
|
5416
|
+
return {
|
|
5417
|
+
content: [
|
|
5418
|
+
{
|
|
5419
|
+
type: 'text',
|
|
5420
|
+
text: `Failed to get npm license info: ${error.message}`,
|
|
5421
|
+
},
|
|
5422
|
+
],
|
|
5423
|
+
isError: true,
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
});
|
|
5427
|
+
}
|
|
5428
|
+
|
|
5429
|
+
async function npmGetHomepage(packageName) {
|
|
5430
|
+
const cacheKey = generateCacheKey('npm-get-homepage', { packageName });
|
|
5431
|
+
return withCache(cacheKey, async () => {
|
|
5432
|
+
try {
|
|
5433
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5434
|
+
cache: true,
|
|
5435
|
+
});
|
|
5436
|
+
if (result.isError) {
|
|
5437
|
+
return result;
|
|
5438
|
+
}
|
|
5439
|
+
// Parse the result from the executed command
|
|
5440
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5441
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5442
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5443
|
+
// Extract only homepage data
|
|
5444
|
+
const homepageResult = {
|
|
5445
|
+
packageName: npmData.name,
|
|
5446
|
+
homepage: npmData.homepage,
|
|
5447
|
+
};
|
|
5448
|
+
return createSuccessResult$1(homepageResult);
|
|
5449
|
+
}
|
|
5450
|
+
catch (error) {
|
|
5451
|
+
return createErrorResult$1('Failed to get npm homepage information', error);
|
|
5452
|
+
}
|
|
5453
|
+
});
|
|
5454
|
+
}
|
|
5455
|
+
|
|
5456
|
+
function registerNpmGetHomepageTool(server) {
|
|
5457
|
+
server.tool(TOOL_NAMES.NPM_GET_HOMEPAGE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_HOMEPAGE], {
|
|
5458
|
+
packageName: z
|
|
5459
|
+
.string()
|
|
5460
|
+
.describe("The name of the npm package to get homepage information for (e.g., 'react', 'express', 'lodash'). Returns direct access to official documentation, interactive examples, and comprehensive project resources - optimized for token efficiency."),
|
|
5461
|
+
}, {
|
|
5462
|
+
title: 'NPM Homepage Discovery - Extract Project Website URL',
|
|
5463
|
+
readOnlyHint: true,
|
|
5464
|
+
destructiveHint: false,
|
|
5465
|
+
idempotentHint: true,
|
|
5466
|
+
openWorldHint: true,
|
|
5467
|
+
}, async (args) => {
|
|
5468
|
+
try {
|
|
5469
|
+
return await npmGetHomepage(args.packageName);
|
|
5470
|
+
}
|
|
5471
|
+
catch (error) {
|
|
5472
|
+
return {
|
|
5473
|
+
content: [
|
|
5474
|
+
{
|
|
5475
|
+
type: 'text',
|
|
5476
|
+
text: `Failed to get npm homepage info: ${error.message}`,
|
|
5477
|
+
},
|
|
5478
|
+
],
|
|
5479
|
+
isError: true,
|
|
5480
|
+
};
|
|
5481
|
+
}
|
|
5482
|
+
});
|
|
5483
|
+
}
|
|
5484
|
+
|
|
5485
|
+
async function npmGetId(packageName) {
|
|
5486
|
+
const cacheKey = generateCacheKey('npm-get-id', { packageName });
|
|
5487
|
+
return withCache(cacheKey, async () => {
|
|
5488
|
+
try {
|
|
5489
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5490
|
+
cache: true,
|
|
5491
|
+
});
|
|
5492
|
+
if (result.isError) {
|
|
5493
|
+
return result;
|
|
5494
|
+
}
|
|
5495
|
+
// Parse the result from the executed command
|
|
5496
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5497
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5498
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5499
|
+
// Extract only _id data (name@latestVersion format)
|
|
5500
|
+
const idResult = {
|
|
5501
|
+
packageName: npmData.name,
|
|
5502
|
+
id: npmData._id,
|
|
5503
|
+
};
|
|
5504
|
+
return createSuccessResult$1(idResult);
|
|
5505
|
+
}
|
|
5506
|
+
catch (error) {
|
|
5507
|
+
return createErrorResult$1('Failed to get npm ID information', error);
|
|
5508
|
+
}
|
|
5509
|
+
});
|
|
5510
|
+
}
|
|
5511
|
+
|
|
5512
|
+
function registerNpmGetIdTool(server) {
|
|
5513
|
+
server.tool(TOOL_NAMES.NPM_GET_ID, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_ID], {
|
|
5514
|
+
packageName: z
|
|
5515
|
+
.string()
|
|
5516
|
+
.describe("The name of the npm package to get ID information for (e.g., 'react', 'express', 'lodash'). Returns precise version identifier for dependency management, lockfiles, and reproducible builds - optimized for token efficiency."),
|
|
5517
|
+
}, {
|
|
5518
|
+
title: 'NPM Package Identification - Extract Name@Version ID',
|
|
5519
|
+
readOnlyHint: true,
|
|
5520
|
+
destructiveHint: false,
|
|
5521
|
+
idempotentHint: true,
|
|
5522
|
+
openWorldHint: true,
|
|
5523
|
+
}, async (args) => {
|
|
5524
|
+
try {
|
|
5525
|
+
return await npmGetId(args.packageName);
|
|
5526
|
+
}
|
|
5527
|
+
catch (error) {
|
|
5528
|
+
return {
|
|
5529
|
+
content: [
|
|
5530
|
+
{
|
|
5531
|
+
type: 'text',
|
|
5532
|
+
text: `Failed to get npm ID info: ${error.message}`,
|
|
5533
|
+
},
|
|
5534
|
+
],
|
|
5535
|
+
isError: true,
|
|
5536
|
+
};
|
|
5537
|
+
}
|
|
5538
|
+
});
|
|
5539
|
+
}
|
|
5540
|
+
|
|
5541
|
+
async function npmGetReleases(packageName) {
|
|
5542
|
+
const cacheKey = generateCacheKey('npm-get-releases', { packageName });
|
|
5543
|
+
return withCache(cacheKey, async () => {
|
|
5544
|
+
try {
|
|
5545
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5546
|
+
cache: true,
|
|
5547
|
+
});
|
|
5548
|
+
if (result.isError) {
|
|
5549
|
+
return result;
|
|
5550
|
+
}
|
|
5551
|
+
// Parse the result from the executed command
|
|
5552
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5553
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5554
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5555
|
+
// Extract only version entries (exclude 'created' and 'modified')
|
|
5556
|
+
const versionEntries = Object.entries(npmData.time).filter(([key]) => key !== 'created' && key !== 'modified');
|
|
5557
|
+
// Sort by release date (most recent first) and take last 10
|
|
5558
|
+
const sortedVersions = versionEntries
|
|
5559
|
+
.sort(([, dateA], [, dateB]) => new Date(dateB).getTime() - new Date(dateA).getTime())
|
|
5560
|
+
.slice(0, 10)
|
|
5561
|
+
.map(([version, releaseDate]) => ({ version, releaseDate }));
|
|
5562
|
+
// Create efficient result with only requested data
|
|
5563
|
+
const timeResult = {
|
|
5564
|
+
packageName: npmData.name,
|
|
5565
|
+
lastModified: npmData.time.modified,
|
|
5566
|
+
created: npmData.time.created,
|
|
5567
|
+
versionCount: versionEntries.length,
|
|
5568
|
+
last10Releases: sortedVersions,
|
|
5569
|
+
};
|
|
5570
|
+
return createSuccessResult$1(timeResult);
|
|
5571
|
+
}
|
|
5572
|
+
catch (error) {
|
|
5573
|
+
return createErrorResult$1('Failed to get npm time information', error);
|
|
5574
|
+
}
|
|
5575
|
+
});
|
|
5576
|
+
}
|
|
5577
|
+
|
|
5578
|
+
function registerNpmGetReleasesTool(server) {
|
|
5579
|
+
server.tool(TOOL_NAMES.NPM_GET_RELEASES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_RELEASES], {
|
|
5580
|
+
packageName: z
|
|
5581
|
+
.string()
|
|
5582
|
+
.describe("The name of the npm package to get release information for (e.g., 'react', 'express', 'lodash'). Returns focused release data: last modified, created date, version count, and last 10 releases - optimized for token efficiency."),
|
|
5583
|
+
}, {
|
|
5584
|
+
title: 'NPM Package Releases - Extract Recent Release Data',
|
|
5585
|
+
readOnlyHint: true,
|
|
5586
|
+
destructiveHint: false,
|
|
5587
|
+
idempotentHint: true,
|
|
5588
|
+
openWorldHint: true,
|
|
5589
|
+
}, async (args) => {
|
|
5590
|
+
try {
|
|
5591
|
+
return await npmGetReleases(args.packageName);
|
|
5592
|
+
}
|
|
5593
|
+
catch (error) {
|
|
5594
|
+
return {
|
|
5595
|
+
content: [
|
|
5596
|
+
{
|
|
5597
|
+
type: 'text',
|
|
5598
|
+
text: `Failed to get npm release info: ${error.message}`,
|
|
5599
|
+
},
|
|
5600
|
+
],
|
|
5601
|
+
isError: true,
|
|
5602
|
+
};
|
|
5603
|
+
}
|
|
5604
|
+
});
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5607
|
+
async function npmGetEngines(packageName) {
|
|
5608
|
+
const cacheKey = generateCacheKey('npm-get-engines', { packageName });
|
|
5609
|
+
return withCache(cacheKey, async () => {
|
|
5610
|
+
try {
|
|
5611
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5612
|
+
cache: true,
|
|
5613
|
+
});
|
|
5614
|
+
if (result.isError) {
|
|
5615
|
+
return result;
|
|
5616
|
+
}
|
|
5617
|
+
// Parse the result from the executed command
|
|
5618
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5619
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5620
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5621
|
+
// Extract only engines data
|
|
5622
|
+
const enginesResult = {
|
|
5623
|
+
packageName: npmData.name,
|
|
5624
|
+
engines: npmData.engines || {},
|
|
5625
|
+
};
|
|
5626
|
+
return createSuccessResult$1(enginesResult);
|
|
5627
|
+
}
|
|
5628
|
+
catch (error) {
|
|
5629
|
+
return createErrorResult$1('Failed to get npm engines information', error);
|
|
5630
|
+
}
|
|
5631
|
+
});
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5634
|
+
function registerNpmGetEnginesTool(server) {
|
|
5635
|
+
server.tool(TOOL_NAMES.NPM_GET_ENGINES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_ENGINES], {
|
|
5636
|
+
packageName: z
|
|
5637
|
+
.string()
|
|
5638
|
+
.describe("The name of the npm package to get engines information for (e.g., 'react', 'express', 'lodash'). Returns environment compatibility requirements to prevent deployment failures and runtime conflicts - optimized for token efficiency."),
|
|
5639
|
+
}, {
|
|
5640
|
+
title: 'NPM Runtime Compatibility - Extract Engine Requirements',
|
|
5641
|
+
readOnlyHint: true,
|
|
5642
|
+
destructiveHint: false,
|
|
5643
|
+
idempotentHint: true,
|
|
5644
|
+
openWorldHint: true,
|
|
5645
|
+
}, async (args) => {
|
|
5646
|
+
try {
|
|
5647
|
+
return await npmGetEngines(args.packageName);
|
|
5648
|
+
}
|
|
5649
|
+
catch (error) {
|
|
5650
|
+
return {
|
|
5651
|
+
content: [
|
|
5652
|
+
{
|
|
5653
|
+
type: 'text',
|
|
5654
|
+
text: `Failed to get npm engines info: ${error.message}`,
|
|
5655
|
+
},
|
|
5656
|
+
],
|
|
5657
|
+
isError: true,
|
|
5658
|
+
};
|
|
5659
|
+
}
|
|
5660
|
+
});
|
|
5661
|
+
}
|
|
5662
|
+
|
|
5663
|
+
async function npmGetExports(packageName) {
|
|
5664
|
+
const cacheKey = generateCacheKey('npm-get-exports', { packageName });
|
|
5665
|
+
return withCache(cacheKey, async () => {
|
|
5666
|
+
try {
|
|
5667
|
+
const result = await executeNpmCommand('view', [packageName, '--json'], {
|
|
5668
|
+
cache: true,
|
|
5669
|
+
});
|
|
5670
|
+
if (result.isError) {
|
|
5671
|
+
return result;
|
|
3051
5672
|
}
|
|
3052
|
-
|
|
5673
|
+
// Parse the result from the executed command
|
|
5674
|
+
const commandOutput = JSON.parse(result.content[0].text);
|
|
5675
|
+
// The result is a JSON string from npm that needs to be parsed again
|
|
5676
|
+
const npmData = JSON.parse(commandOutput.result);
|
|
5677
|
+
// Extract only exports data
|
|
5678
|
+
const exportsResult = {
|
|
5679
|
+
packageName: npmData.name,
|
|
5680
|
+
exports: npmData.exports || {},
|
|
5681
|
+
};
|
|
5682
|
+
return createSuccessResult$1(exportsResult);
|
|
5683
|
+
}
|
|
5684
|
+
catch (error) {
|
|
5685
|
+
return createErrorResult$1('Failed to get npm exports information', error);
|
|
5686
|
+
}
|
|
5687
|
+
});
|
|
5688
|
+
}
|
|
5689
|
+
|
|
5690
|
+
function registerNpmGetExportsTool(server) {
|
|
5691
|
+
server.tool(TOOL_NAMES.NPM_GET_EXPORTS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_EXPORTS], {
|
|
5692
|
+
packageName: z
|
|
5693
|
+
.string()
|
|
5694
|
+
.describe("The name of the npm package to get exports information for (e.g., 'react', 'express', 'lodash'). Returns import path intelligence: available modules, entry points, and tree-shakable exports for optimal code search - optimized for token efficiency."),
|
|
5695
|
+
}, {
|
|
5696
|
+
title: 'NPM Module Structure - Extract Package Export Mappings',
|
|
5697
|
+
readOnlyHint: true,
|
|
5698
|
+
destructiveHint: false,
|
|
5699
|
+
idempotentHint: true,
|
|
5700
|
+
openWorldHint: true,
|
|
5701
|
+
}, async (args) => {
|
|
5702
|
+
try {
|
|
5703
|
+
return await npmGetExports(args.packageName);
|
|
5704
|
+
}
|
|
5705
|
+
catch (error) {
|
|
5706
|
+
return {
|
|
5707
|
+
content: [
|
|
5708
|
+
{
|
|
5709
|
+
type: 'text',
|
|
5710
|
+
text: `Failed to get npm exports info: ${error.message}`,
|
|
5711
|
+
},
|
|
5712
|
+
],
|
|
5713
|
+
isError: true,
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5716
|
+
});
|
|
5717
|
+
}
|
|
5718
|
+
|
|
5719
|
+
function registerUsageGuideResource(server) {
|
|
5720
|
+
server.resource('usage-guide', 'help://usage', async (uri) => ({
|
|
5721
|
+
contents: [
|
|
5722
|
+
{
|
|
5723
|
+
uri: uri.href,
|
|
5724
|
+
mimeType: 'text/markdown',
|
|
5725
|
+
text: `# Octocode MCP Quick Start
|
|
5726
|
+
|
|
5727
|
+
## Setup (Required)
|
|
5728
|
+
\`\`\`bash
|
|
5729
|
+
gh auth login # GitHub CLI authentication
|
|
5730
|
+
\`\`\`
|
|
5731
|
+
|
|
5732
|
+
## MANDATORY SEARCH STRATEGY
|
|
5733
|
+
1. **ALWAYS START**: \`search_github_topics\` - **NEVER SKIP** - Maps ecosystem terminology
|
|
5734
|
+
2. **PRIMARY DISCOVERY**: \`npm_search\` and \`npm_view\` - Minimizes GitHub API calls
|
|
5735
|
+
3. **TARGETED EXTRACTION**: \`search_github_code\` with owner/repo from NPM
|
|
5736
|
+
4. **LAST RESORT**: \`search_github_repos\` - Single terms only when NPM insufficient
|
|
5737
|
+
|
|
5738
|
+
## Core Workflow
|
|
5739
|
+
1. **Check Auth**: Read \`github://auth-status\` and \`github://rate-limits\`
|
|
5740
|
+
2. **MANDATORY**: \`search_github_topics\` for ecosystem mapping
|
|
5741
|
+
3. **NPM Discovery**: \`npm_search\` → \`npm_view\` → extract repository URLs
|
|
5742
|
+
4. **Extract**: Get complete implementations from discovered repositories
|
|
5743
|
+
5. **Validate**: Cross-reference multiple NPM packages
|
|
5744
|
+
|
|
5745
|
+
## Essential Tools (Priority Order)
|
|
5746
|
+
- **\`search_github_topics\`**: **MANDATORY FIRST STEP** - Find technology ecosystems
|
|
5747
|
+
- **\`npm_search\`**: **PRIMARY DISCOVERY** - Find packages by functionality
|
|
5748
|
+
- **\`npm_view\`**: **PRIMARY DISCOVERY** - Package metadata and repo links
|
|
5749
|
+
- **\`view_repository\`**: Get branch info (required before file operations!)
|
|
5750
|
+
- **\`search_github_code\`**: Find specific implementations in discovered repos
|
|
5751
|
+
- **\`fetch_github_file_content\`**: Extract complete code
|
|
5752
|
+
- **\`search_github_repos\`**: **LAST RESORT ONLY** - Single terms when NPM fails
|
|
5753
|
+
|
|
5754
|
+
## Search Strategy Rules
|
|
5755
|
+
- **Topics First**: Every workflow starts with \`search_github_topics\`
|
|
5756
|
+
- **NPM Primary**: Use NPM tools before GitHub repo search
|
|
5757
|
+
- **Single Terms Only**: NEVER multi-term searches in \`search_github_repos\`
|
|
5758
|
+
- **API Conservation**: NPM discovery reduces GitHub API usage by 60%
|
|
5759
|
+
|
|
5760
|
+
## Search Term Strategy
|
|
5761
|
+
- **✅ GOOD**: "react", "authentication", "typescript", "deployment"
|
|
5762
|
+
- **❌ BAD**: "react hooks", "full-stack app", "react angular auth"
|
|
5763
|
+
- **Decompose**: "react typescript auth" → ["react", "typescript", "authentication"]
|
|
5764
|
+
|
|
5765
|
+
## Quick Examples
|
|
5766
|
+
- **Package research**: \`search_github_topics\` → \`npm_search\` → \`npm_view\` → \`view_repository\` → \`search_github_code\`
|
|
5767
|
+
- **Problem solving**: \`search_github_topics\` → \`npm_search\` → \`search_github_issues\` → \`search_github_code\`
|
|
5768
|
+
- **Technology discovery**: \`search_github_topics\` → \`npm_search\` → \`npm_view\` → \`view_repository\` → \`fetch_github_file_content\`
|
|
5769
|
+
|
|
5770
|
+
## CRITICAL REMINDERS
|
|
5771
|
+
- **NEVER skip** \`search_github_topics\` - provides essential context
|
|
5772
|
+
- **NPM FIRST** - use NPM tools before GitHub repo search
|
|
5773
|
+
- **SINGLE TERMS** - never combine multiple concepts in repo searches
|
|
5774
|
+
- **REPOS LAST** - \`search_github_repos\` is lowest priority discovery tool
|
|
5775
|
+
|
|
5776
|
+
Generated: ${new Date().toISOString()}`,
|
|
5777
|
+
},
|
|
5778
|
+
],
|
|
5779
|
+
}));
|
|
5780
|
+
}
|
|
5781
|
+
|
|
5782
|
+
// GitHub Authentication Status Resource
|
|
5783
|
+
function registerGithubStatusResource(server) {
|
|
5784
|
+
server.resource('github-auth-status', 'github://auth-status', async (uri) => {
|
|
5785
|
+
try {
|
|
5786
|
+
// For version, we'll use a workaround since --version is not a command
|
|
5787
|
+
// We can use 'help' command which shows version info, or skip detailed version check
|
|
5788
|
+
const ghVersion = 'Available (GitHub CLI detected)';
|
|
5789
|
+
let isAuthenticated = false;
|
|
5790
|
+
let authError = null;
|
|
3053
5791
|
try {
|
|
3054
|
-
|
|
3055
|
-
|
|
5792
|
+
// Check auth status using safe command
|
|
5793
|
+
const authResult = await executeGitHubCommand('auth', ['status'], {
|
|
5794
|
+
timeout: 5000,
|
|
5795
|
+
cache: false,
|
|
5796
|
+
});
|
|
5797
|
+
if (!authResult.isError) {
|
|
5798
|
+
const content = String(authResult.content[0]?.text || '');
|
|
5799
|
+
if (content) {
|
|
5800
|
+
try {
|
|
5801
|
+
const parsed = JSON.parse(content);
|
|
5802
|
+
const output = parsed.result || content;
|
|
5803
|
+
// Only check if authenticated, don't expose user details
|
|
5804
|
+
isAuthenticated =
|
|
5805
|
+
String(output).includes('✓ Logged in') ||
|
|
5806
|
+
String(output).includes('Logged in');
|
|
5807
|
+
}
|
|
5808
|
+
catch {
|
|
5809
|
+
isAuthenticated =
|
|
5810
|
+
content.includes('✓ Logged in') ||
|
|
5811
|
+
content.includes('Logged in');
|
|
5812
|
+
}
|
|
5813
|
+
}
|
|
5814
|
+
}
|
|
5815
|
+
else {
|
|
5816
|
+
// auth status command failed, check error content for auth info
|
|
5817
|
+
const errorContent = String(authResult.content[0]?.text || 'Authentication check failed');
|
|
5818
|
+
if (errorContent.includes('✓ Logged in') ||
|
|
5819
|
+
errorContent.includes('Logged in')) {
|
|
5820
|
+
isAuthenticated = true;
|
|
5821
|
+
}
|
|
5822
|
+
else {
|
|
5823
|
+
authError = 'Not authenticated';
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
3056
5826
|
}
|
|
3057
|
-
catch {
|
|
3058
|
-
|
|
5827
|
+
catch (error) {
|
|
5828
|
+
authError = 'Unable to check authentication status';
|
|
3059
5829
|
}
|
|
3060
|
-
const rateLimitInfo = processRateLimit(rateLimit);
|
|
3061
5830
|
return {
|
|
3062
5831
|
contents: [
|
|
3063
5832
|
{
|
|
3064
5833
|
uri: uri.href,
|
|
3065
5834
|
mimeType: 'application/json',
|
|
3066
5835
|
text: JSON.stringify({
|
|
3067
|
-
status: 'GitHub
|
|
3068
|
-
description: '
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
healthy: 'All APIs ready for use',
|
|
3083
|
-
limited: 'Consider prioritizing essential requests only',
|
|
3084
|
-
exhausted: 'Wait until reset time or use alternative approaches',
|
|
5836
|
+
status: 'GitHub Authentication Status - LIVE STATUS',
|
|
5837
|
+
description: 'GitHub CLI authentication status and version information',
|
|
5838
|
+
gh_version: ghVersion,
|
|
5839
|
+
authenticated: isAuthenticated,
|
|
5840
|
+
auth_error: authError,
|
|
5841
|
+
setup_instructions: {
|
|
5842
|
+
not_authenticated: [
|
|
5843
|
+
'Run: gh auth login',
|
|
5844
|
+
'Follow the interactive prompts to authenticate',
|
|
5845
|
+
'Choose your preferred authentication method',
|
|
5846
|
+
],
|
|
5847
|
+
verification: [
|
|
5848
|
+
'Run: gh auth status',
|
|
5849
|
+
'Should show "✓ Logged in" if successful',
|
|
5850
|
+
],
|
|
3085
5851
|
},
|
|
3086
5852
|
timestamp: new Date().toISOString(),
|
|
3087
5853
|
}, null, 2),
|
|
@@ -3096,9 +5862,9 @@ function registerGithubRateLimitResource(server) {
|
|
|
3096
5862
|
uri: uri.href,
|
|
3097
5863
|
mimeType: 'application/json',
|
|
3098
5864
|
text: JSON.stringify({
|
|
3099
|
-
status: 'GitHub
|
|
5865
|
+
status: 'GitHub Authentication Status - ERROR',
|
|
3100
5866
|
error: error.message,
|
|
3101
|
-
message: '
|
|
5867
|
+
message: 'GitHub CLI may not be installed or accessible',
|
|
3102
5868
|
timestamp: new Date().toISOString(),
|
|
3103
5869
|
}, null, 2),
|
|
3104
5870
|
},
|
|
@@ -3107,56 +5873,6 @@ function registerGithubRateLimitResource(server) {
|
|
|
3107
5873
|
}
|
|
3108
5874
|
});
|
|
3109
5875
|
}
|
|
3110
|
-
function processRateLimit(rateLimit) {
|
|
3111
|
-
const formatResetTime = (reset) => new Date(reset * 1000).toISOString();
|
|
3112
|
-
const calculateUsage = (used, limit) => Math.round((used / limit) * 100);
|
|
3113
|
-
const core = rateLimit.resources.core;
|
|
3114
|
-
const search = rateLimit.resources.search;
|
|
3115
|
-
const codeSearch = rateLimit.resources.code_search;
|
|
3116
|
-
const graphql = rateLimit.resources.graphql;
|
|
3117
|
-
// Determine overall status based on most restrictive API
|
|
3118
|
-
const minRemaining = Math.min(core.remaining, search.remaining, codeSearch.remaining, graphql.remaining);
|
|
3119
|
-
let status;
|
|
3120
|
-
if (minRemaining === 0) {
|
|
3121
|
-
status = 'exhausted';
|
|
3122
|
-
}
|
|
3123
|
-
else if (minRemaining < 10) {
|
|
3124
|
-
status = 'limited';
|
|
3125
|
-
}
|
|
3126
|
-
else {
|
|
3127
|
-
status = 'healthy';
|
|
3128
|
-
}
|
|
3129
|
-
// Find the earliest reset time
|
|
3130
|
-
const nextReset = Math.min(core.reset, search.reset, codeSearch.reset, graphql.reset);
|
|
3131
|
-
return {
|
|
3132
|
-
primary_api: {
|
|
3133
|
-
remaining: core.remaining,
|
|
3134
|
-
limit: core.limit,
|
|
3135
|
-
reset_time: formatResetTime(core.reset),
|
|
3136
|
-
usage_percentage: calculateUsage(core.used, core.limit),
|
|
3137
|
-
},
|
|
3138
|
-
search_api: {
|
|
3139
|
-
remaining: search.remaining,
|
|
3140
|
-
limit: search.limit,
|
|
3141
|
-
reset_time: formatResetTime(search.reset),
|
|
3142
|
-
usage_percentage: calculateUsage(search.used, search.limit),
|
|
3143
|
-
},
|
|
3144
|
-
code_search: {
|
|
3145
|
-
remaining: codeSearch.remaining,
|
|
3146
|
-
limit: codeSearch.limit,
|
|
3147
|
-
reset_time: formatResetTime(codeSearch.reset),
|
|
3148
|
-
usage_percentage: calculateUsage(codeSearch.used, codeSearch.limit),
|
|
3149
|
-
},
|
|
3150
|
-
graphql_api: {
|
|
3151
|
-
remaining: graphql.remaining,
|
|
3152
|
-
limit: graphql.limit,
|
|
3153
|
-
reset_time: formatResetTime(graphql.reset),
|
|
3154
|
-
usage_percentage: calculateUsage(graphql.used, graphql.limit),
|
|
3155
|
-
},
|
|
3156
|
-
status,
|
|
3157
|
-
next_reset: formatResetTime(nextReset),
|
|
3158
|
-
};
|
|
3159
|
-
}
|
|
3160
5876
|
|
|
3161
5877
|
// Sanitize output to remove potential tokens
|
|
3162
5878
|
function sanitizeOutput(output) {
|
|
@@ -3598,10 +6314,12 @@ process.stdin.on('close', async () => {
|
|
|
3598
6314
|
});
|
|
3599
6315
|
// Register all tools
|
|
3600
6316
|
function registerAllTools(server) {
|
|
6317
|
+
// System & API Status - CRITICAL FIRST STEP
|
|
6318
|
+
registerApiStatusCheckTool(server);
|
|
3601
6319
|
registerGitHubSearchCodeTool(server);
|
|
3602
6320
|
registerFetchGitHubFileContentTool(server);
|
|
3603
6321
|
registerViewRepositoryTool(server);
|
|
3604
|
-
registerNpmViewTool(server);
|
|
6322
|
+
//Tools.registerNpmViewTool(server);
|
|
3605
6323
|
registerSearchGitHubReposTool(server);
|
|
3606
6324
|
registerSearchGitHubCommitsTool(server);
|
|
3607
6325
|
registerSearchGitHubPullRequestsTool(server);
|
|
@@ -3609,18 +6327,27 @@ function registerAllTools(server) {
|
|
|
3609
6327
|
registerNpmSearchTool(server);
|
|
3610
6328
|
registerViewRepositoryStructureTool(server);
|
|
3611
6329
|
registerSearchGitHubIssuesTool(server);
|
|
3612
|
-
// TODO: add discussions tool after fixing API
|
|
3613
|
-
//Tools.registerSearchGitHubDiscussionsTool(server);
|
|
3614
6330
|
registerSearchGitHubTopicsTool(server);
|
|
3615
6331
|
registerSearchGitHubUsersTool(server);
|
|
3616
|
-
|
|
6332
|
+
// Focused NPM tools for minimal token usage
|
|
3617
6333
|
registerNpmDependencyAnalysisTool(server);
|
|
6334
|
+
registerNpmGetRepositoryTool(server);
|
|
6335
|
+
registerNpmGetDependenciesTool(server);
|
|
6336
|
+
registerNpmGetBugsTool(server);
|
|
6337
|
+
registerNpmGetReadmeTool(server);
|
|
6338
|
+
registerNpmGetVersionsTool(server);
|
|
6339
|
+
registerNpmGetAuthorTool(server);
|
|
6340
|
+
registerNpmGetLicenseTool(server);
|
|
6341
|
+
registerNpmGetHomepageTool(server);
|
|
6342
|
+
registerNpmGetIdTool(server);
|
|
6343
|
+
registerNpmGetReleasesTool(server);
|
|
6344
|
+
registerNpmGetEnginesTool(server);
|
|
6345
|
+
registerNpmGetExportsTool(server);
|
|
3618
6346
|
}
|
|
3619
6347
|
// Register all resources
|
|
3620
6348
|
function registerResources(server) {
|
|
3621
6349
|
registerUsageGuideResource(server);
|
|
3622
6350
|
registerGithubStatusResource(server);
|
|
3623
|
-
registerGithubRateLimitResource(server);
|
|
3624
6351
|
registerNpmStatusResource(server);
|
|
3625
6352
|
registerRepositoryIntelligenceResource(server);
|
|
3626
6353
|
}
|