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,212 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Splitting tools for Skill Seeker MCP Server.
|
|
3
|
+
|
|
4
|
+
This module provides tools for splitting large documentation configs into multiple
|
|
5
|
+
focused skills and generating router/hub skills for managing split documentation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import glob
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from mcp.types import TextContent
|
|
14
|
+
except ImportError:
|
|
15
|
+
# Graceful degradation: Create a simple fallback class for testing
|
|
16
|
+
class TextContent:
|
|
17
|
+
"""Fallback TextContent for when MCP is not installed"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, type: str, text: str):
|
|
20
|
+
self.type = type
|
|
21
|
+
self.text = text
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Path to CLI tools
|
|
25
|
+
CLI_DIR = Path(__file__).parent.parent.parent / "cli"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Import subprocess helper from parent module
|
|
29
|
+
# We'll use a local import to avoid circular dependencies
|
|
30
|
+
def run_subprocess_with_streaming(cmd, timeout=None):
|
|
31
|
+
"""
|
|
32
|
+
Run subprocess with real-time output streaming.
|
|
33
|
+
Returns (stdout, stderr, returncode).
|
|
34
|
+
|
|
35
|
+
This solves the blocking issue where long-running processes (like scraping)
|
|
36
|
+
would cause MCP to appear frozen. Now we stream output as it comes.
|
|
37
|
+
"""
|
|
38
|
+
import subprocess
|
|
39
|
+
import time
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
process = subprocess.Popen(
|
|
43
|
+
cmd,
|
|
44
|
+
stdout=subprocess.PIPE,
|
|
45
|
+
stderr=subprocess.PIPE,
|
|
46
|
+
text=True,
|
|
47
|
+
bufsize=1, # Line buffered
|
|
48
|
+
universal_newlines=True,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
stdout_lines = []
|
|
52
|
+
stderr_lines = []
|
|
53
|
+
start_time = time.time()
|
|
54
|
+
|
|
55
|
+
# Read output line by line as it comes
|
|
56
|
+
while True:
|
|
57
|
+
# Check timeout
|
|
58
|
+
if timeout and (time.time() - start_time) > timeout:
|
|
59
|
+
process.kill()
|
|
60
|
+
stderr_lines.append(f"\n⚠️ Process killed after {timeout}s timeout")
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
# Check if process finished
|
|
64
|
+
if process.poll() is not None:
|
|
65
|
+
break
|
|
66
|
+
|
|
67
|
+
# Read available output (non-blocking)
|
|
68
|
+
try:
|
|
69
|
+
import select
|
|
70
|
+
|
|
71
|
+
readable, _, _ = select.select([process.stdout, process.stderr], [], [], 0.1)
|
|
72
|
+
|
|
73
|
+
if process.stdout in readable:
|
|
74
|
+
line = process.stdout.readline()
|
|
75
|
+
if line:
|
|
76
|
+
stdout_lines.append(line)
|
|
77
|
+
|
|
78
|
+
if process.stderr in readable:
|
|
79
|
+
line = process.stderr.readline()
|
|
80
|
+
if line:
|
|
81
|
+
stderr_lines.append(line)
|
|
82
|
+
except Exception:
|
|
83
|
+
# Fallback for Windows (no select)
|
|
84
|
+
time.sleep(0.1)
|
|
85
|
+
|
|
86
|
+
# Get any remaining output
|
|
87
|
+
remaining_stdout, remaining_stderr = process.communicate()
|
|
88
|
+
if remaining_stdout:
|
|
89
|
+
stdout_lines.append(remaining_stdout)
|
|
90
|
+
if remaining_stderr:
|
|
91
|
+
stderr_lines.append(remaining_stderr)
|
|
92
|
+
|
|
93
|
+
stdout = "".join(stdout_lines)
|
|
94
|
+
stderr = "".join(stderr_lines)
|
|
95
|
+
returncode = process.returncode
|
|
96
|
+
|
|
97
|
+
return stdout, stderr, returncode
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
return "", f"Error running subprocess: {str(e)}", 1
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
async def split_config(args: dict) -> list[TextContent]:
|
|
104
|
+
"""
|
|
105
|
+
Split large configs into multiple focused skills.
|
|
106
|
+
|
|
107
|
+
Supports both documentation and unified (multi-source) configs:
|
|
108
|
+
- Documentation configs: Split by categories, size, or create router skills
|
|
109
|
+
- Unified configs: Split by source type (documentation, github, pdf)
|
|
110
|
+
|
|
111
|
+
For large documentation sites (10K+ pages), this tool splits the config into
|
|
112
|
+
multiple smaller configs. For unified configs with multiple sources, splits
|
|
113
|
+
into separate configs per source type.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
args: Dictionary containing:
|
|
117
|
+
- config_path (str): Path to config JSON file (e.g., configs/godot.json or configs/react_unified.json)
|
|
118
|
+
- strategy (str, optional): Split strategy: auto, none, source, category, router, size (default: auto)
|
|
119
|
+
'source' strategy is for unified configs only
|
|
120
|
+
- target_pages (int, optional): Target pages per skill for doc configs (default: 5000)
|
|
121
|
+
- dry_run (bool, optional): Preview without saving files (default: False)
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
List[TextContent]: Split results showing created configs and recommendations,
|
|
125
|
+
or error message if split failed.
|
|
126
|
+
"""
|
|
127
|
+
config_path = args["config_path"]
|
|
128
|
+
strategy = args.get("strategy", "auto")
|
|
129
|
+
target_pages = args.get("target_pages", 5000)
|
|
130
|
+
dry_run = args.get("dry_run", False)
|
|
131
|
+
|
|
132
|
+
# Run split_config.py
|
|
133
|
+
cmd = [
|
|
134
|
+
sys.executable,
|
|
135
|
+
str(CLI_DIR / "split_config.py"),
|
|
136
|
+
config_path,
|
|
137
|
+
"--strategy",
|
|
138
|
+
strategy,
|
|
139
|
+
"--target-pages",
|
|
140
|
+
str(target_pages),
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
if dry_run:
|
|
144
|
+
cmd.append("--dry-run")
|
|
145
|
+
|
|
146
|
+
# Timeout: 5 minutes for config splitting
|
|
147
|
+
timeout = 300
|
|
148
|
+
|
|
149
|
+
progress_msg = "✂️ Splitting configuration...\n"
|
|
150
|
+
progress_msg += f"⏱️ Maximum time: {timeout // 60} minutes\n\n"
|
|
151
|
+
|
|
152
|
+
stdout, stderr, returncode = run_subprocess_with_streaming(cmd, timeout=timeout)
|
|
153
|
+
|
|
154
|
+
output = progress_msg + stdout
|
|
155
|
+
|
|
156
|
+
if returncode == 0:
|
|
157
|
+
return [TextContent(type="text", text=output)]
|
|
158
|
+
else:
|
|
159
|
+
return [TextContent(type="text", text=f"{output}\n\n❌ Error:\n{stderr}")]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
async def generate_router(args: dict) -> list[TextContent]:
|
|
163
|
+
"""
|
|
164
|
+
Generate router/hub skill for split documentation.
|
|
165
|
+
|
|
166
|
+
Creates an intelligent routing skill that helps users navigate between split
|
|
167
|
+
sub-skills. The router skill analyzes user queries and directs them to the
|
|
168
|
+
appropriate sub-skill based on content categories.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
args: Dictionary containing:
|
|
172
|
+
- config_pattern (str): Config pattern for sub-skills (e.g., 'configs/godot-*.json')
|
|
173
|
+
- router_name (str, optional): Router skill name (optional, inferred from configs)
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
List[TextContent]: Router skill creation results with usage instructions,
|
|
177
|
+
or error message if generation failed.
|
|
178
|
+
"""
|
|
179
|
+
config_pattern = args["config_pattern"]
|
|
180
|
+
router_name = args.get("router_name")
|
|
181
|
+
|
|
182
|
+
# Expand glob pattern
|
|
183
|
+
config_files = glob.glob(config_pattern)
|
|
184
|
+
|
|
185
|
+
if not config_files:
|
|
186
|
+
return [
|
|
187
|
+
TextContent(type="text", text=f"❌ No config files match pattern: {config_pattern}")
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
# Run generate_router.py
|
|
191
|
+
cmd = [
|
|
192
|
+
sys.executable,
|
|
193
|
+
str(CLI_DIR / "generate_router.py"),
|
|
194
|
+
] + config_files
|
|
195
|
+
|
|
196
|
+
if router_name:
|
|
197
|
+
cmd.extend(["--name", router_name])
|
|
198
|
+
|
|
199
|
+
# Timeout: 5 minutes for router generation
|
|
200
|
+
timeout = 300
|
|
201
|
+
|
|
202
|
+
progress_msg = "🧭 Generating router skill...\n"
|
|
203
|
+
progress_msg += f"⏱️ Maximum time: {timeout // 60} minutes\n\n"
|
|
204
|
+
|
|
205
|
+
stdout, stderr, returncode = run_subprocess_with_streaming(cmd, timeout=timeout)
|
|
206
|
+
|
|
207
|
+
output = progress_msg + stdout
|
|
208
|
+
|
|
209
|
+
if returncode == 0:
|
|
210
|
+
return [TextContent(type="text", text=output)]
|
|
211
|
+
else:
|
|
212
|
+
return [TextContent(type="text", text=f"{output}\n\n❌ Error:\n{stderr}")]
|
skill_seekers/py.typed
ADDED
|
File without changes
|