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,488 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SKILL.md Enhancement Script
4
+ Uses platform AI APIs to improve SKILL.md by analyzing reference documentation.
5
+
6
+ Usage:
7
+ # Claude (default)
8
+ skill-seekers enhance output/react/
9
+ skill-seekers enhance output/react/ --api-key sk-ant-...
10
+
11
+ # Gemini
12
+ skill-seekers enhance output/react/ --target gemini --api-key AIzaSy...
13
+
14
+ # OpenAI
15
+ skill-seekers enhance output/react/ --target openai --api-key sk-proj-...
16
+ """
17
+
18
+ import argparse
19
+ import os
20
+ import sys
21
+ from pathlib import Path
22
+
23
+ # Add parent directory to path for imports when run as script
24
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
25
+
26
+ from skill_seekers.cli.constants import API_CONTENT_LIMIT, API_PREVIEW_LIMIT
27
+ from skill_seekers.cli.utils import read_reference_files
28
+
29
+ try:
30
+ import anthropic
31
+ except ImportError:
32
+ print("āŒ Error: anthropic package not installed")
33
+ print("Install with: pip3 install anthropic")
34
+ sys.exit(1)
35
+
36
+
37
+ class SkillEnhancer:
38
+ def __init__(self, skill_dir, api_key=None):
39
+ self.skill_dir = Path(skill_dir)
40
+ self.references_dir = self.skill_dir / "references"
41
+ self.skill_md_path = self.skill_dir / "SKILL.md"
42
+
43
+ # Get API key - support both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN
44
+ self.api_key = (
45
+ api_key or os.environ.get("ANTHROPIC_API_KEY") or os.environ.get("ANTHROPIC_AUTH_TOKEN")
46
+ )
47
+ if not self.api_key:
48
+ raise ValueError(
49
+ "No API key provided. Set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN "
50
+ "environment variable or use --api-key argument"
51
+ )
52
+
53
+ # Support custom base URL for alternative API endpoints
54
+ base_url = os.environ.get("ANTHROPIC_BASE_URL")
55
+ client_kwargs = {"api_key": self.api_key}
56
+ if base_url:
57
+ client_kwargs["base_url"] = base_url
58
+ print(f"ā„¹ļø Using custom API base URL: {base_url}")
59
+
60
+ self.client = anthropic.Anthropic(**client_kwargs)
61
+
62
+ def read_current_skill_md(self):
63
+ """Read existing SKILL.md"""
64
+ if not self.skill_md_path.exists():
65
+ return None
66
+ return self.skill_md_path.read_text(encoding="utf-8")
67
+
68
+ def enhance_skill_md(self, references, current_skill_md):
69
+ """Use Claude to enhance SKILL.md"""
70
+
71
+ # Build prompt
72
+ prompt = self._build_enhancement_prompt(references, current_skill_md)
73
+
74
+ print("\nšŸ¤– Asking Claude to enhance SKILL.md...")
75
+ print(f" Input: {len(prompt):,} characters")
76
+
77
+ try:
78
+ message = self.client.messages.create(
79
+ model="claude-sonnet-4-20250514",
80
+ max_tokens=4096,
81
+ temperature=0.3,
82
+ messages=[{"role": "user", "content": prompt}],
83
+ )
84
+
85
+ # Handle response content - newer SDK versions may include ThinkingBlock
86
+ # Find the TextBlock containing the actual response
87
+ enhanced_content = None
88
+ for block in message.content:
89
+ if hasattr(block, "text"):
90
+ enhanced_content = block.text
91
+ break
92
+
93
+ if not enhanced_content:
94
+ print("āŒ Error: No text content found in API response")
95
+ return None
96
+
97
+ return enhanced_content
98
+
99
+ except Exception as e:
100
+ print(f"āŒ Error calling Claude API: {e}")
101
+ return None
102
+
103
+ def _build_enhancement_prompt(self, references, current_skill_md):
104
+ """Build the prompt for Claude with multi-source awareness"""
105
+
106
+ # Extract skill name and description
107
+ skill_name = self.skill_dir.name
108
+
109
+ # Analyze sources
110
+ sources_found = set()
111
+ for metadata in references.values():
112
+ sources_found.add(metadata["source"])
113
+
114
+ # Analyze conflicts if present
115
+ has_conflicts = any("conflicts" in meta["path"] for meta in references.values())
116
+
117
+ prompt = f"""You are enhancing a Claude skill's SKILL.md file. This skill is about: {skill_name}
118
+
119
+ I've scraped documentation from multiple sources and organized it into reference files. Your job is to create an EXCELLENT SKILL.md that synthesizes knowledge from these sources.
120
+
121
+ SKILL OVERVIEW:
122
+ - Name: {skill_name}
123
+ - Source Types: {", ".join(sorted(sources_found))}
124
+ - Multi-Source: {"Yes" if len(sources_found) > 1 else "No"}
125
+ - Conflicts Detected: {"Yes - see conflicts.md in references" if has_conflicts else "No"}
126
+
127
+ CURRENT SKILL.MD:
128
+ {"```markdown" if current_skill_md else "(none - create from scratch)"}
129
+ {current_skill_md or "No existing SKILL.md"}
130
+ {"```" if current_skill_md else ""}
131
+
132
+ SOURCE ANALYSIS:
133
+ This skill combines knowledge from {len(sources_found)} source type(s):
134
+
135
+ """
136
+
137
+ # Group references by (source_type, repo_id) for multi-source support
138
+ by_source = {}
139
+ for filename, metadata in references.items():
140
+ source = metadata["source"]
141
+ repo_id = metadata.get("repo_id") # None for single-source
142
+ key = (source, repo_id) if repo_id else (source, None)
143
+
144
+ if key not in by_source:
145
+ by_source[key] = []
146
+ by_source[key].append((filename, metadata))
147
+
148
+ # Add source breakdown with repo identity
149
+ for source, repo_id in sorted(by_source.keys()):
150
+ files = by_source[(source, repo_id)]
151
+ if repo_id:
152
+ prompt += f"\n**{source.upper()} - {repo_id} ({len(files)} file(s))**\n"
153
+ else:
154
+ prompt += f"\n**{source.upper()} ({len(files)} file(s))**\n"
155
+ for filename, metadata in files[:5]: # Top 5 per source
156
+ prompt += f"- {filename} (confidence: {metadata['confidence']}, {metadata['size']:,} chars)\n"
157
+ if len(files) > 5:
158
+ prompt += f"- ... and {len(files) - 5} more\n"
159
+
160
+ prompt += "\n\nREFERENCE DOCUMENTATION:\n"
161
+
162
+ # Add references grouped by (source, repo_id) with metadata
163
+ for source, repo_id in sorted(by_source.keys()):
164
+ if repo_id:
165
+ prompt += f"\n### {source.upper()} SOURCES - {repo_id}\n\n"
166
+ else:
167
+ prompt += f"\n### {source.upper()} SOURCES\n\n"
168
+
169
+ for filename, metadata in by_source[(source, repo_id)]:
170
+ content = metadata["content"]
171
+ # Limit per-file to 30K
172
+ if len(content) > 30000:
173
+ content = content[:30000] + "\n\n[Content truncated for size...]"
174
+
175
+ prompt += f"\n#### {filename}\n"
176
+ if repo_id:
177
+ prompt += f"*Source: {metadata['source']} ({repo_id}), Confidence: {metadata['confidence']}*\n\n"
178
+ else:
179
+ prompt += (
180
+ f"*Source: {metadata['source']}, Confidence: {metadata['confidence']}*\n\n"
181
+ )
182
+ prompt += f"```markdown\n{content}\n```\n"
183
+
184
+ prompt += """
185
+
186
+ REFERENCE PRIORITY (when sources differ):
187
+ 1. **Code patterns (codebase_analysis)**: Ground truth - what the code actually does
188
+ 2. **Official documentation**: Intended API and usage patterns
189
+ 3. **GitHub issues**: Real-world usage and known problems
190
+ 4. **PDF documentation**: Additional context and tutorials
191
+
192
+ MULTI-REPOSITORY HANDLING:
193
+ """
194
+
195
+ # Detect multiple repos from same source type
196
+ repo_ids = set()
197
+ for metadata in references.values():
198
+ if metadata.get("repo_id"):
199
+ repo_ids.add(metadata["repo_id"])
200
+
201
+ if len(repo_ids) > 1:
202
+ prompt += f"""
203
+ āš ļø MULTIPLE REPOSITORIES DETECTED: {", ".join(sorted(repo_ids))}
204
+
205
+ This skill combines codebase analysis from {len(repo_ids)} different repositories.
206
+ Each repo has its own ARCHITECTURE.md, patterns, examples, and configuration.
207
+
208
+ When synthesizing:
209
+ - Clearly identify which content comes from which repo
210
+ - Compare and contrast patterns across repos (e.g., "httpx uses Strategy pattern 50 times, httpcore uses it 32 times")
211
+ - Highlight relationships (e.g., "httpx is a client library built on top of httpcore")
212
+ - Present examples from BOTH repos to show different use cases
213
+ - If repos serve different purposes, explain when to use each
214
+ """
215
+ else:
216
+ prompt += "\nSingle repository - standard synthesis applies.\n"
217
+
218
+ prompt += """
219
+
220
+ YOUR TASK:
221
+ Create an enhanced SKILL.md that synthesizes knowledge from multiple sources:
222
+
223
+ 1. **Multi-Source Synthesis**
224
+ - Acknowledge that this skill combines multiple sources
225
+ - Highlight agreements between sources (builds confidence)
226
+ - Note discrepancies transparently (if present)
227
+ - Use source priority when synthesizing conflicting information
228
+
229
+ 2. **Clear "When to Use This Skill" section**
230
+ - Be SPECIFIC about trigger conditions
231
+ - List concrete use cases
232
+ - Include perspective from both docs AND real-world usage (if GitHub/codebase data available)
233
+
234
+ 3. **Excellent Quick Reference section**
235
+ - Extract 5-10 of the BEST, most practical code examples
236
+ - Prefer examples from HIGH CONFIDENCE sources first
237
+ - If code examples exist from codebase analysis, prioritize those (real usage)
238
+ - If docs examples exist, include those too (official patterns)
239
+ - Choose SHORT, clear examples (5-20 lines max)
240
+ - Use proper language tags (cpp, python, javascript, json, etc.)
241
+ - Add clear descriptions noting the source (e.g., "From official docs" or "From codebase")
242
+
243
+ 4. **Detailed Reference Files description**
244
+ - Explain what's in each reference file
245
+ - Note the source type and confidence level
246
+ - Help users navigate multi-source documentation
247
+
248
+ 5. **Practical "Working with This Skill" section**
249
+ - Clear guidance for beginners, intermediate, and advanced users
250
+ - Navigation tips for multi-source references
251
+ - How to resolve conflicts if present
252
+
253
+ 6. **Key Concepts section** (if applicable)
254
+ - Explain core concepts
255
+ - Define important terminology
256
+ - Reconcile differences between sources if needed
257
+
258
+ 7. **Conflict Handling** (if conflicts detected)
259
+ - Add a "Known Discrepancies" section
260
+ - Explain major conflicts transparently
261
+ - Provide guidance on which source to trust in each case
262
+
263
+ 8. **Keep the frontmatter** (---\nname: ...\n---) intact
264
+
265
+ IMPORTANT:
266
+ - Extract REAL examples from the reference docs, don't make them up
267
+ - Prioritize HIGH CONFIDENCE sources when synthesizing
268
+ - Note source attribution when helpful (e.g., "Official docs say X, but codebase shows Y")
269
+ - Make discrepancies transparent, not hidden
270
+ - Prioritize SHORT, clear examples (5-20 lines max)
271
+ - Make it actionable and practical
272
+ - Don't be too verbose - be concise but useful
273
+ - Maintain the markdown structure for Claude skills
274
+ - Keep code examples properly formatted with language tags
275
+
276
+ OUTPUT:
277
+ Return ONLY the complete SKILL.md content, starting with the frontmatter (---).
278
+ """
279
+
280
+ return prompt
281
+
282
+ def save_enhanced_skill_md(self, content):
283
+ """Save the enhanced SKILL.md"""
284
+ # Backup original
285
+ if self.skill_md_path.exists():
286
+ backup_path = self.skill_md_path.with_suffix(".md.backup")
287
+ self.skill_md_path.rename(backup_path)
288
+ print(f" šŸ’¾ Backed up original to: {backup_path.name}")
289
+
290
+ # Save enhanced version
291
+ self.skill_md_path.write_text(content, encoding="utf-8")
292
+ print(" āœ… Saved enhanced SKILL.md")
293
+
294
+ def run(self):
295
+ """Main enhancement workflow"""
296
+ print(f"\n{'=' * 60}")
297
+ print(f"ENHANCING SKILL: {self.skill_dir.name}")
298
+ print(f"{'=' * 60}\n")
299
+
300
+ # Read reference files
301
+ print("šŸ“– Reading reference documentation...")
302
+ references = read_reference_files(
303
+ self.skill_dir, max_chars=API_CONTENT_LIMIT, preview_limit=API_PREVIEW_LIMIT
304
+ )
305
+
306
+ if not references:
307
+ print("āŒ No reference files found to analyze")
308
+ return False
309
+
310
+ # Analyze sources
311
+ sources_found = set()
312
+ for metadata in references.values():
313
+ sources_found.add(metadata["source"])
314
+
315
+ print(f" āœ“ Read {len(references)} reference files")
316
+ print(f" āœ“ Sources: {', '.join(sorted(sources_found))}")
317
+ total_size = sum(meta["size"] for meta in references.values())
318
+ print(f" āœ“ Total size: {total_size:,} characters\n")
319
+
320
+ # Read current SKILL.md
321
+ current_skill_md = self.read_current_skill_md()
322
+ if current_skill_md:
323
+ print(f" ℹ Found existing SKILL.md ({len(current_skill_md)} chars)")
324
+ else:
325
+ print(" ℹ No existing SKILL.md, will create new one")
326
+
327
+ # Enhance with Claude
328
+ enhanced = self.enhance_skill_md(references, current_skill_md)
329
+
330
+ if not enhanced:
331
+ print("āŒ Enhancement failed")
332
+ return False
333
+
334
+ print(f" āœ“ Generated enhanced SKILL.md ({len(enhanced)} chars)\n")
335
+
336
+ # Save
337
+ print("šŸ’¾ Saving enhanced SKILL.md...")
338
+ self.save_enhanced_skill_md(enhanced)
339
+
340
+ print("\nāœ… Enhancement complete!")
341
+ print("\nNext steps:")
342
+ print(f" 1. Review: {self.skill_md_path}")
343
+ print(
344
+ f" 2. If you don't like it, restore backup: {self.skill_md_path.with_suffix('.md.backup')}"
345
+ )
346
+ print(" 3. Package your skill:")
347
+ print(f" skill-seekers package {self.skill_dir}/")
348
+
349
+ return True
350
+
351
+
352
+ def main():
353
+ parser = argparse.ArgumentParser(
354
+ description="Enhance SKILL.md using platform AI APIs",
355
+ formatter_class=argparse.RawDescriptionHelpFormatter,
356
+ epilog="""
357
+ Examples:
358
+ # Claude (default)
359
+ export ANTHROPIC_API_KEY=sk-ant-...
360
+ skill-seekers enhance output/react/
361
+
362
+ # Gemini
363
+ export GOOGLE_API_KEY=AIzaSy...
364
+ skill-seekers enhance output/react/ --target gemini
365
+
366
+ # OpenAI
367
+ export OPENAI_API_KEY=sk-proj-...
368
+ skill-seekers enhance output/react/ --target openai
369
+
370
+ # With explicit API key
371
+ skill-seekers enhance output/react/ --api-key sk-ant-...
372
+
373
+ # Dry run
374
+ skill-seekers enhance output/godot/ --dry-run
375
+ """,
376
+ )
377
+
378
+ parser.add_argument(
379
+ "skill_dir", type=str, help="Path to skill directory (e.g., output/steam-inventory/)"
380
+ )
381
+ parser.add_argument(
382
+ "--api-key", type=str, help="Platform API key (or set environment variable)"
383
+ )
384
+ parser.add_argument(
385
+ "--target",
386
+ choices=["claude", "gemini", "openai"],
387
+ default="claude",
388
+ help="Target LLM platform (default: claude)",
389
+ )
390
+ parser.add_argument(
391
+ "--dry-run", action="store_true", help="Show what would be done without calling API"
392
+ )
393
+
394
+ args = parser.parse_args()
395
+
396
+ # Validate skill directory
397
+ skill_dir = Path(args.skill_dir)
398
+ if not skill_dir.exists():
399
+ print(f"āŒ Error: Directory not found: {skill_dir}")
400
+ sys.exit(1)
401
+
402
+ if not skill_dir.is_dir():
403
+ print(f"āŒ Error: Not a directory: {skill_dir}")
404
+ sys.exit(1)
405
+
406
+ # Dry run mode
407
+ if args.dry_run:
408
+ print("šŸ” DRY RUN MODE")
409
+ print(f" Would enhance: {skill_dir}")
410
+ print(f" References: {skill_dir / 'references'}")
411
+ print(f" SKILL.md: {skill_dir / 'SKILL.md'}")
412
+
413
+ refs_dir = skill_dir / "references"
414
+ if refs_dir.exists():
415
+ ref_files = list(refs_dir.glob("*.md"))
416
+ print(f" Found {len(ref_files)} reference files:")
417
+ for rf in ref_files:
418
+ size = rf.stat().st_size
419
+ print(f" - {rf.name} ({size:,} bytes)")
420
+
421
+ print("\nTo actually run enhancement:")
422
+ print(f" skill-seekers enhance {skill_dir}")
423
+ return
424
+
425
+ # Check if platform supports enhancement
426
+ try:
427
+ from skill_seekers.cli.adaptors import get_adaptor
428
+
429
+ adaptor = get_adaptor(args.target)
430
+
431
+ if not adaptor.supports_enhancement():
432
+ print(f"āŒ Error: {adaptor.PLATFORM_NAME} does not support AI enhancement")
433
+ print("\nSupported platforms for enhancement:")
434
+ print(" - Claude AI (Anthropic)")
435
+ print(" - Google Gemini")
436
+ print(" - OpenAI ChatGPT")
437
+ sys.exit(1)
438
+
439
+ # Get API key
440
+ api_key = args.api_key
441
+ if not api_key:
442
+ api_key = os.environ.get(adaptor.get_env_var_name(), "").strip()
443
+
444
+ if not api_key:
445
+ print(f"āŒ Error: {adaptor.get_env_var_name()} not set")
446
+ print(f"\nSet your API key for {adaptor.PLATFORM_NAME}:")
447
+ print(f" export {adaptor.get_env_var_name()}=...")
448
+ print("Or provide it directly:")
449
+ print(f" skill-seekers enhance {skill_dir} --target {args.target} --api-key ...")
450
+ sys.exit(1)
451
+
452
+ # Run enhancement using adaptor
453
+ print(f"\n{'=' * 60}")
454
+ print(f"ENHANCING SKILL: {skill_dir}")
455
+ print(f"Platform: {adaptor.PLATFORM_NAME}")
456
+ print(f"{'=' * 60}\n")
457
+
458
+ success = adaptor.enhance(Path(skill_dir), api_key)
459
+
460
+ if success:
461
+ print("\nāœ… Enhancement complete!")
462
+ print("\nNext steps:")
463
+ print(f" 1. Review: {Path(skill_dir) / 'SKILL.md'}")
464
+ print(
465
+ f" 2. If you don't like it, restore backup: {Path(skill_dir) / 'SKILL.md.backup'}"
466
+ )
467
+ print(" 3. Package your skill:")
468
+ print(f" skill-seekers package {skill_dir}/ --target {args.target}")
469
+
470
+ sys.exit(0 if success else 1)
471
+
472
+ except ImportError as e:
473
+ print(f"āŒ Error: {e}")
474
+ print("\nAdaptor system not available. Reinstall skill-seekers.")
475
+ sys.exit(1)
476
+ except ValueError as e:
477
+ print(f"āŒ Error: {e}")
478
+ sys.exit(1)
479
+ except Exception as e:
480
+ print(f"āŒ Unexpected error: {e}")
481
+ import traceback
482
+
483
+ traceback.print_exc()
484
+ sys.exit(1)
485
+
486
+
487
+ if __name__ == "__main__":
488
+ main()