skill-seekers 2.7.3__py3-none-any.whl
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.
- skill_seekers/__init__.py +22 -0
- skill_seekers/cli/__init__.py +39 -0
- skill_seekers/cli/adaptors/__init__.py +120 -0
- skill_seekers/cli/adaptors/base.py +221 -0
- skill_seekers/cli/adaptors/claude.py +485 -0
- skill_seekers/cli/adaptors/gemini.py +453 -0
- skill_seekers/cli/adaptors/markdown.py +269 -0
- skill_seekers/cli/adaptors/openai.py +503 -0
- skill_seekers/cli/ai_enhancer.py +310 -0
- skill_seekers/cli/api_reference_builder.py +373 -0
- skill_seekers/cli/architectural_pattern_detector.py +525 -0
- skill_seekers/cli/code_analyzer.py +1462 -0
- skill_seekers/cli/codebase_scraper.py +1225 -0
- skill_seekers/cli/config_command.py +563 -0
- skill_seekers/cli/config_enhancer.py +431 -0
- skill_seekers/cli/config_extractor.py +871 -0
- skill_seekers/cli/config_manager.py +452 -0
- skill_seekers/cli/config_validator.py +394 -0
- skill_seekers/cli/conflict_detector.py +528 -0
- skill_seekers/cli/constants.py +72 -0
- skill_seekers/cli/dependency_analyzer.py +757 -0
- skill_seekers/cli/doc_scraper.py +2332 -0
- skill_seekers/cli/enhance_skill.py +488 -0
- skill_seekers/cli/enhance_skill_local.py +1096 -0
- skill_seekers/cli/enhance_status.py +194 -0
- skill_seekers/cli/estimate_pages.py +433 -0
- skill_seekers/cli/generate_router.py +1209 -0
- skill_seekers/cli/github_fetcher.py +534 -0
- skill_seekers/cli/github_scraper.py +1466 -0
- skill_seekers/cli/guide_enhancer.py +723 -0
- skill_seekers/cli/how_to_guide_builder.py +1267 -0
- skill_seekers/cli/install_agent.py +461 -0
- skill_seekers/cli/install_skill.py +178 -0
- skill_seekers/cli/language_detector.py +614 -0
- skill_seekers/cli/llms_txt_detector.py +60 -0
- skill_seekers/cli/llms_txt_downloader.py +104 -0
- skill_seekers/cli/llms_txt_parser.py +150 -0
- skill_seekers/cli/main.py +558 -0
- skill_seekers/cli/markdown_cleaner.py +132 -0
- skill_seekers/cli/merge_sources.py +806 -0
- skill_seekers/cli/package_multi.py +77 -0
- skill_seekers/cli/package_skill.py +241 -0
- skill_seekers/cli/pattern_recognizer.py +1825 -0
- skill_seekers/cli/pdf_extractor_poc.py +1166 -0
- skill_seekers/cli/pdf_scraper.py +617 -0
- skill_seekers/cli/quality_checker.py +519 -0
- skill_seekers/cli/rate_limit_handler.py +438 -0
- skill_seekers/cli/resume_command.py +160 -0
- skill_seekers/cli/run_tests.py +230 -0
- skill_seekers/cli/setup_wizard.py +93 -0
- skill_seekers/cli/split_config.py +390 -0
- skill_seekers/cli/swift_patterns.py +560 -0
- skill_seekers/cli/test_example_extractor.py +1081 -0
- skill_seekers/cli/test_unified_simple.py +179 -0
- skill_seekers/cli/unified_codebase_analyzer.py +572 -0
- skill_seekers/cli/unified_scraper.py +932 -0
- skill_seekers/cli/unified_skill_builder.py +1605 -0
- skill_seekers/cli/upload_skill.py +162 -0
- skill_seekers/cli/utils.py +432 -0
- skill_seekers/mcp/__init__.py +33 -0
- skill_seekers/mcp/agent_detector.py +316 -0
- skill_seekers/mcp/git_repo.py +273 -0
- skill_seekers/mcp/server.py +231 -0
- skill_seekers/mcp/server_fastmcp.py +1249 -0
- skill_seekers/mcp/server_legacy.py +2302 -0
- skill_seekers/mcp/source_manager.py +285 -0
- skill_seekers/mcp/tools/__init__.py +115 -0
- skill_seekers/mcp/tools/config_tools.py +251 -0
- skill_seekers/mcp/tools/packaging_tools.py +826 -0
- skill_seekers/mcp/tools/scraping_tools.py +842 -0
- skill_seekers/mcp/tools/source_tools.py +828 -0
- skill_seekers/mcp/tools/splitting_tools.py +212 -0
- skill_seekers/py.typed +0 -0
- skill_seekers-2.7.3.dist-info/METADATA +2027 -0
- skill_seekers-2.7.3.dist-info/RECORD +79 -0
- skill_seekers-2.7.3.dist-info/WHEEL +5 -0
- skill_seekers-2.7.3.dist-info/entry_points.txt +19 -0
- skill_seekers-2.7.3.dist-info/licenses/LICENSE +21 -0
- skill_seekers-2.7.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test Runner for Skill Seeker
|
|
4
|
+
Runs all test suites and generates a comprehensive test report
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import unittest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ColoredTextTestResult(unittest.TextTestResult):
|
|
12
|
+
"""Custom test result class with colored output"""
|
|
13
|
+
|
|
14
|
+
# ANSI color codes
|
|
15
|
+
GREEN = "\033[92m"
|
|
16
|
+
RED = "\033[91m"
|
|
17
|
+
YELLOW = "\033[93m"
|
|
18
|
+
BLUE = "\033[94m"
|
|
19
|
+
RESET = "\033[0m"
|
|
20
|
+
BOLD = "\033[1m"
|
|
21
|
+
|
|
22
|
+
def __init__(self, *args, **kwargs):
|
|
23
|
+
super().__init__(*args, **kwargs)
|
|
24
|
+
self.test_results = []
|
|
25
|
+
|
|
26
|
+
def addSuccess(self, test):
|
|
27
|
+
super().addSuccess(test)
|
|
28
|
+
self.test_results.append(("PASS", test))
|
|
29
|
+
if self.showAll:
|
|
30
|
+
self.stream.write(f"{self.GREEN}✓ PASS{self.RESET}\n")
|
|
31
|
+
elif self.dots:
|
|
32
|
+
self.stream.write(f"{self.GREEN}.{self.RESET}")
|
|
33
|
+
self.stream.flush()
|
|
34
|
+
|
|
35
|
+
def addError(self, test, err):
|
|
36
|
+
super().addError(test, err)
|
|
37
|
+
self.test_results.append(("ERROR", test))
|
|
38
|
+
if self.showAll:
|
|
39
|
+
self.stream.write(f"{self.RED}✗ ERROR{self.RESET}\n")
|
|
40
|
+
elif self.dots:
|
|
41
|
+
self.stream.write(f"{self.RED}E{self.RESET}")
|
|
42
|
+
self.stream.flush()
|
|
43
|
+
|
|
44
|
+
def addFailure(self, test, err):
|
|
45
|
+
super().addFailure(test, err)
|
|
46
|
+
self.test_results.append(("FAIL", test))
|
|
47
|
+
if self.showAll:
|
|
48
|
+
self.stream.write(f"{self.RED}✗ FAIL{self.RESET}\n")
|
|
49
|
+
elif self.dots:
|
|
50
|
+
self.stream.write(f"{self.RED}F{self.RESET}")
|
|
51
|
+
self.stream.flush()
|
|
52
|
+
|
|
53
|
+
def addSkip(self, test, reason):
|
|
54
|
+
super().addSkip(test, reason)
|
|
55
|
+
self.test_results.append(("SKIP", test))
|
|
56
|
+
if self.showAll:
|
|
57
|
+
self.stream.write(f"{self.YELLOW}⊘ SKIP{self.RESET}\n")
|
|
58
|
+
elif self.dots:
|
|
59
|
+
self.stream.write(f"{self.YELLOW}s{self.RESET}")
|
|
60
|
+
self.stream.flush()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ColoredTextTestRunner(unittest.TextTestRunner):
|
|
64
|
+
"""Custom test runner with colored output"""
|
|
65
|
+
|
|
66
|
+
resultclass = ColoredTextTestResult
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def discover_tests(test_dir="tests"):
|
|
70
|
+
"""Discover all test files in the tests directory"""
|
|
71
|
+
loader = unittest.TestLoader()
|
|
72
|
+
start_dir = test_dir
|
|
73
|
+
pattern = "test_*.py"
|
|
74
|
+
|
|
75
|
+
suite = loader.discover(start_dir, pattern=pattern)
|
|
76
|
+
return suite
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def run_specific_suite(suite_name):
|
|
80
|
+
"""Run a specific test suite"""
|
|
81
|
+
loader = unittest.TestLoader()
|
|
82
|
+
|
|
83
|
+
suite_map = {
|
|
84
|
+
"config": "tests.test_config_validation",
|
|
85
|
+
"features": "tests.test_scraper_features",
|
|
86
|
+
"integration": "tests.test_integration",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if suite_name not in suite_map:
|
|
90
|
+
print(f"Unknown test suite: {suite_name}")
|
|
91
|
+
print(f"Available suites: {', '.join(suite_map.keys())}")
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
module_name = suite_map[suite_name]
|
|
95
|
+
try:
|
|
96
|
+
suite = loader.loadTestsFromName(module_name)
|
|
97
|
+
return suite
|
|
98
|
+
except Exception as e:
|
|
99
|
+
print(f"Error loading test suite '{suite_name}': {e}")
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def print_summary(result):
|
|
104
|
+
"""Print a detailed test summary"""
|
|
105
|
+
total = result.testsRun
|
|
106
|
+
passed = total - len(result.failures) - len(result.errors) - len(result.skipped)
|
|
107
|
+
failed = len(result.failures)
|
|
108
|
+
errors = len(result.errors)
|
|
109
|
+
skipped = len(result.skipped)
|
|
110
|
+
|
|
111
|
+
print("\n" + "=" * 70)
|
|
112
|
+
print("TEST SUMMARY")
|
|
113
|
+
print("=" * 70)
|
|
114
|
+
|
|
115
|
+
# Overall stats
|
|
116
|
+
print(f"\n{ColoredTextTestResult.BOLD}Total Tests:{ColoredTextTestResult.RESET} {total}")
|
|
117
|
+
print(f"{ColoredTextTestResult.GREEN}✓ Passed:{ColoredTextTestResult.RESET} {passed}")
|
|
118
|
+
if failed > 0:
|
|
119
|
+
print(f"{ColoredTextTestResult.RED}✗ Failed:{ColoredTextTestResult.RESET} {failed}")
|
|
120
|
+
if errors > 0:
|
|
121
|
+
print(f"{ColoredTextTestResult.RED}✗ Errors:{ColoredTextTestResult.RESET} {errors}")
|
|
122
|
+
if skipped > 0:
|
|
123
|
+
print(f"{ColoredTextTestResult.YELLOW}⊘ Skipped:{ColoredTextTestResult.RESET} {skipped}")
|
|
124
|
+
|
|
125
|
+
# Success rate
|
|
126
|
+
if total > 0:
|
|
127
|
+
success_rate = (passed / total) * 100
|
|
128
|
+
color = (
|
|
129
|
+
ColoredTextTestResult.GREEN
|
|
130
|
+
if success_rate == 100
|
|
131
|
+
else ColoredTextTestResult.YELLOW
|
|
132
|
+
if success_rate >= 80
|
|
133
|
+
else ColoredTextTestResult.RED
|
|
134
|
+
)
|
|
135
|
+
print(f"\n{color}Success Rate: {success_rate:.1f}%{ColoredTextTestResult.RESET}")
|
|
136
|
+
|
|
137
|
+
# Category breakdown
|
|
138
|
+
if hasattr(result, "test_results"):
|
|
139
|
+
print(
|
|
140
|
+
f"\n{ColoredTextTestResult.BOLD}Test Breakdown by Category:{ColoredTextTestResult.RESET}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
categories = {}
|
|
144
|
+
for status, test in result.test_results:
|
|
145
|
+
test_name = str(test)
|
|
146
|
+
# Extract test class name
|
|
147
|
+
if "." in test_name:
|
|
148
|
+
class_name = test_name.split(".")[0].split()[-1]
|
|
149
|
+
if class_name not in categories:
|
|
150
|
+
categories[class_name] = {"PASS": 0, "FAIL": 0, "ERROR": 0, "SKIP": 0}
|
|
151
|
+
categories[class_name][status] += 1
|
|
152
|
+
|
|
153
|
+
for category, stats in sorted(categories.items()):
|
|
154
|
+
total_cat = sum(stats.values())
|
|
155
|
+
passed_cat = stats["PASS"]
|
|
156
|
+
print(f" {category}: {passed_cat}/{total_cat} passed")
|
|
157
|
+
|
|
158
|
+
print("\n" + "=" * 70)
|
|
159
|
+
|
|
160
|
+
# Return status
|
|
161
|
+
return failed == 0 and errors == 0
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def main():
|
|
165
|
+
"""Main test runner"""
|
|
166
|
+
import argparse
|
|
167
|
+
|
|
168
|
+
parser = argparse.ArgumentParser(
|
|
169
|
+
description="Run tests for Skill Seeker",
|
|
170
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
parser.add_argument(
|
|
174
|
+
"--suite", "-s", type=str, help="Run specific test suite (config, features, integration)"
|
|
175
|
+
)
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"--verbose", "-v", action="store_true", help="Verbose output (show each test)"
|
|
178
|
+
)
|
|
179
|
+
parser.add_argument("--quiet", "-q", action="store_true", help="Quiet output (minimal output)")
|
|
180
|
+
parser.add_argument("--failfast", "-f", action="store_true", help="Stop on first failure")
|
|
181
|
+
parser.add_argument("--list", "-l", action="store_true", help="List all available tests")
|
|
182
|
+
|
|
183
|
+
args = parser.parse_args()
|
|
184
|
+
|
|
185
|
+
# Set verbosity
|
|
186
|
+
verbosity = 1
|
|
187
|
+
if args.verbose:
|
|
188
|
+
verbosity = 2
|
|
189
|
+
elif args.quiet:
|
|
190
|
+
verbosity = 0
|
|
191
|
+
|
|
192
|
+
print(f"\n{ColoredTextTestResult.BOLD}{'=' * 70}{ColoredTextTestResult.RESET}")
|
|
193
|
+
print(f"{ColoredTextTestResult.BOLD}SKILL SEEKER TEST SUITE{ColoredTextTestResult.RESET}")
|
|
194
|
+
print(f"{ColoredTextTestResult.BOLD}{'=' * 70}{ColoredTextTestResult.RESET}\n")
|
|
195
|
+
|
|
196
|
+
# Discover or load specific suite
|
|
197
|
+
if args.suite:
|
|
198
|
+
print(
|
|
199
|
+
f"Running test suite: {ColoredTextTestResult.BLUE}{args.suite}{ColoredTextTestResult.RESET}\n"
|
|
200
|
+
)
|
|
201
|
+
suite = run_specific_suite(args.suite)
|
|
202
|
+
if suite is None:
|
|
203
|
+
return 1
|
|
204
|
+
else:
|
|
205
|
+
print(f"Running {ColoredTextTestResult.BLUE}all tests{ColoredTextTestResult.RESET}\n")
|
|
206
|
+
suite = discover_tests()
|
|
207
|
+
|
|
208
|
+
# List tests
|
|
209
|
+
if args.list:
|
|
210
|
+
print("\nAvailable tests:\n")
|
|
211
|
+
for test_group in suite:
|
|
212
|
+
for test in test_group:
|
|
213
|
+
print(f" - {test}")
|
|
214
|
+
print()
|
|
215
|
+
return 0
|
|
216
|
+
|
|
217
|
+
# Run tests
|
|
218
|
+
runner = ColoredTextTestRunner(verbosity=verbosity, failfast=args.failfast)
|
|
219
|
+
|
|
220
|
+
result = runner.run(suite)
|
|
221
|
+
|
|
222
|
+
# Print summary
|
|
223
|
+
success = print_summary(result)
|
|
224
|
+
|
|
225
|
+
# Return appropriate exit code
|
|
226
|
+
return 0 if success else 1
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
sys.exit(main())
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Interactive Setup Wizard for Skill Seekers
|
|
3
|
+
|
|
4
|
+
Guides users through installation options on first run.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def show_installation_guide():
|
|
11
|
+
"""Show installation options"""
|
|
12
|
+
print("""
|
|
13
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
14
|
+
║ ║
|
|
15
|
+
║ Skill Seekers Setup Guide ║
|
|
16
|
+
║ ║
|
|
17
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
18
|
+
|
|
19
|
+
Choose your installation profile:
|
|
20
|
+
|
|
21
|
+
1️⃣ CLI Only (Skill Generation)
|
|
22
|
+
pip install skill-seekers
|
|
23
|
+
|
|
24
|
+
Features:
|
|
25
|
+
• Scrape documentation websites
|
|
26
|
+
• Analyze GitHub repositories
|
|
27
|
+
• Extract from PDFs
|
|
28
|
+
• Package skills for all platforms
|
|
29
|
+
|
|
30
|
+
2️⃣ MCP Integration (Claude Code, Cursor, Windsurf)
|
|
31
|
+
pip install skill-seekers[mcp]
|
|
32
|
+
|
|
33
|
+
Features:
|
|
34
|
+
• Everything from CLI Only
|
|
35
|
+
• MCP server for Claude Code
|
|
36
|
+
• One-command skill installation
|
|
37
|
+
• HTTP/stdio transport modes
|
|
38
|
+
|
|
39
|
+
3️⃣ Multi-LLM Support (Gemini, OpenAI)
|
|
40
|
+
pip install skill-seekers[all-llms]
|
|
41
|
+
|
|
42
|
+
Features:
|
|
43
|
+
• Everything from CLI Only
|
|
44
|
+
• Google Gemini support
|
|
45
|
+
• OpenAI ChatGPT support
|
|
46
|
+
• Enhanced AI features
|
|
47
|
+
|
|
48
|
+
4️⃣ Everything
|
|
49
|
+
pip install skill-seekers[all]
|
|
50
|
+
|
|
51
|
+
Features:
|
|
52
|
+
• All features enabled
|
|
53
|
+
• Maximum flexibility
|
|
54
|
+
|
|
55
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
56
|
+
|
|
57
|
+
Current installation: pip install skill-seekers
|
|
58
|
+
Upgrade with: pip install -U skill-seekers[mcp]
|
|
59
|
+
|
|
60
|
+
For configuration wizard:
|
|
61
|
+
skill-seekers config
|
|
62
|
+
|
|
63
|
+
For help:
|
|
64
|
+
skill-seekers --help
|
|
65
|
+
|
|
66
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
67
|
+
""")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def check_first_run():
|
|
71
|
+
"""Check if this is first run"""
|
|
72
|
+
flag_file = Path.home() / ".config" / "skill-seekers" / ".setup_shown"
|
|
73
|
+
|
|
74
|
+
if not flag_file.exists():
|
|
75
|
+
show_installation_guide()
|
|
76
|
+
|
|
77
|
+
# Create flag to not show again
|
|
78
|
+
flag_file.parent.mkdir(parents=True, exist_ok=True)
|
|
79
|
+
flag_file.touch()
|
|
80
|
+
|
|
81
|
+
input("\nPress Enter to continue...")
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def main():
|
|
88
|
+
"""Show wizard"""
|
|
89
|
+
show_installation_guide()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
main()
|