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.
Files changed (79) hide show
  1. skill_seekers/__init__.py +22 -0
  2. skill_seekers/cli/__init__.py +39 -0
  3. skill_seekers/cli/adaptors/__init__.py +120 -0
  4. skill_seekers/cli/adaptors/base.py +221 -0
  5. skill_seekers/cli/adaptors/claude.py +485 -0
  6. skill_seekers/cli/adaptors/gemini.py +453 -0
  7. skill_seekers/cli/adaptors/markdown.py +269 -0
  8. skill_seekers/cli/adaptors/openai.py +503 -0
  9. skill_seekers/cli/ai_enhancer.py +310 -0
  10. skill_seekers/cli/api_reference_builder.py +373 -0
  11. skill_seekers/cli/architectural_pattern_detector.py +525 -0
  12. skill_seekers/cli/code_analyzer.py +1462 -0
  13. skill_seekers/cli/codebase_scraper.py +1225 -0
  14. skill_seekers/cli/config_command.py +563 -0
  15. skill_seekers/cli/config_enhancer.py +431 -0
  16. skill_seekers/cli/config_extractor.py +871 -0
  17. skill_seekers/cli/config_manager.py +452 -0
  18. skill_seekers/cli/config_validator.py +394 -0
  19. skill_seekers/cli/conflict_detector.py +528 -0
  20. skill_seekers/cli/constants.py +72 -0
  21. skill_seekers/cli/dependency_analyzer.py +757 -0
  22. skill_seekers/cli/doc_scraper.py +2332 -0
  23. skill_seekers/cli/enhance_skill.py +488 -0
  24. skill_seekers/cli/enhance_skill_local.py +1096 -0
  25. skill_seekers/cli/enhance_status.py +194 -0
  26. skill_seekers/cli/estimate_pages.py +433 -0
  27. skill_seekers/cli/generate_router.py +1209 -0
  28. skill_seekers/cli/github_fetcher.py +534 -0
  29. skill_seekers/cli/github_scraper.py +1466 -0
  30. skill_seekers/cli/guide_enhancer.py +723 -0
  31. skill_seekers/cli/how_to_guide_builder.py +1267 -0
  32. skill_seekers/cli/install_agent.py +461 -0
  33. skill_seekers/cli/install_skill.py +178 -0
  34. skill_seekers/cli/language_detector.py +614 -0
  35. skill_seekers/cli/llms_txt_detector.py +60 -0
  36. skill_seekers/cli/llms_txt_downloader.py +104 -0
  37. skill_seekers/cli/llms_txt_parser.py +150 -0
  38. skill_seekers/cli/main.py +558 -0
  39. skill_seekers/cli/markdown_cleaner.py +132 -0
  40. skill_seekers/cli/merge_sources.py +806 -0
  41. skill_seekers/cli/package_multi.py +77 -0
  42. skill_seekers/cli/package_skill.py +241 -0
  43. skill_seekers/cli/pattern_recognizer.py +1825 -0
  44. skill_seekers/cli/pdf_extractor_poc.py +1166 -0
  45. skill_seekers/cli/pdf_scraper.py +617 -0
  46. skill_seekers/cli/quality_checker.py +519 -0
  47. skill_seekers/cli/rate_limit_handler.py +438 -0
  48. skill_seekers/cli/resume_command.py +160 -0
  49. skill_seekers/cli/run_tests.py +230 -0
  50. skill_seekers/cli/setup_wizard.py +93 -0
  51. skill_seekers/cli/split_config.py +390 -0
  52. skill_seekers/cli/swift_patterns.py +560 -0
  53. skill_seekers/cli/test_example_extractor.py +1081 -0
  54. skill_seekers/cli/test_unified_simple.py +179 -0
  55. skill_seekers/cli/unified_codebase_analyzer.py +572 -0
  56. skill_seekers/cli/unified_scraper.py +932 -0
  57. skill_seekers/cli/unified_skill_builder.py +1605 -0
  58. skill_seekers/cli/upload_skill.py +162 -0
  59. skill_seekers/cli/utils.py +432 -0
  60. skill_seekers/mcp/__init__.py +33 -0
  61. skill_seekers/mcp/agent_detector.py +316 -0
  62. skill_seekers/mcp/git_repo.py +273 -0
  63. skill_seekers/mcp/server.py +231 -0
  64. skill_seekers/mcp/server_fastmcp.py +1249 -0
  65. skill_seekers/mcp/server_legacy.py +2302 -0
  66. skill_seekers/mcp/source_manager.py +285 -0
  67. skill_seekers/mcp/tools/__init__.py +115 -0
  68. skill_seekers/mcp/tools/config_tools.py +251 -0
  69. skill_seekers/mcp/tools/packaging_tools.py +826 -0
  70. skill_seekers/mcp/tools/scraping_tools.py +842 -0
  71. skill_seekers/mcp/tools/source_tools.py +828 -0
  72. skill_seekers/mcp/tools/splitting_tools.py +212 -0
  73. skill_seekers/py.typed +0 -0
  74. skill_seekers-2.7.3.dist-info/METADATA +2027 -0
  75. skill_seekers-2.7.3.dist-info/RECORD +79 -0
  76. skill_seekers-2.7.3.dist-info/WHEEL +5 -0
  77. skill_seekers-2.7.3.dist-info/entry_points.txt +19 -0
  78. skill_seekers-2.7.3.dist-info/licenses/LICENSE +21 -0
  79. 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