feat: Unified create command + consolidated enhancement flags

This commit includes two major improvements:

## 1. Unified Create Command (v3.0.0 feature)
- Auto-detects source type (web, GitHub, local, PDF, config)
- Three-tier argument organization (universal, source-specific, advanced)
- Routes to existing scrapers (100% backward compatible)
- Progressive disclosure: 15 universal flags in default help

**New files:**
- src/skill_seekers/cli/source_detector.py - Auto-detection logic
- src/skill_seekers/cli/arguments/create.py - Argument definitions
- src/skill_seekers/cli/create_command.py - Main orchestrator
- src/skill_seekers/cli/parsers/create_parser.py - Parser integration

**Tests:**
- tests/test_source_detector.py (35 tests)
- tests/test_create_arguments.py (30 tests)
- tests/test_create_integration_basic.py (10 tests)

## 2. Enhanced Flag Consolidation (Phase 1)
- Consolidated 3 flags (--enhance, --enhance-local, --enhance-level) → 1 flag
- --enhance-level 0-3 with auto-detection of API vs LOCAL mode
- Default: --enhance-level 2 (balanced enhancement)

**Modified files:**
- arguments/{common,create,scrape,github,analyze}.py - Added enhance_level
- {doc_scraper,github_scraper,config_extractor,main}.py - Updated logic
- create_command.py - Uses consolidated flag

**Auto-detection:**
- If ANTHROPIC_API_KEY set → API mode
- Else → LOCAL mode (Claude Code)

## 3. PresetManager Bug Fix
- Fixed module naming conflict (presets.py vs presets/ directory)
- Moved presets.py → presets/manager.py
- Updated __init__.py exports

**Test Results:**
- All 160+ tests passing
- Zero regressions
- 100% backward compatible

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
yusyus
2026-02-15 14:29:19 +03:00
parent aa952aff81
commit ba1670a220
53 changed files with 10144 additions and 589 deletions

View File

@@ -7,6 +7,7 @@ function to create them.
from .base import SubcommandParser
# Import all parser classes
from .create_parser import CreateParser # NEW: Unified create command
from .config_parser import ConfigParser
from .scrape_parser import ScrapeParser
from .github_parser import GitHubParser
@@ -30,6 +31,7 @@ from .quality_parser import QualityParser
# Registry of all parsers (in order of usage frequency)
PARSERS = [
CreateParser(), # NEW: Unified create command (placed first for prominence)
ConfigParser(),
ScrapeParser(),
GitHubParser(),

View File

@@ -1,6 +1,13 @@
"""Analyze subcommand parser."""
"""Analyze subcommand parser.
Uses shared argument definitions from arguments.analyze to ensure
consistency with the standalone codebase_scraper module.
Includes preset system support (Issue #268).
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.analyze import add_analyze_arguments
class AnalyzeParser(SubcommandParser):
@@ -16,69 +23,14 @@ class AnalyzeParser(SubcommandParser):
@property
def description(self) -> str:
return "Standalone codebase analysis with C3.x features (patterns, tests, guides)"
return "Standalone codebase analysis with patterns, tests, and guides"
def add_arguments(self, parser):
"""Add analyze-specific arguments."""
parser.add_argument("--directory", required=True, help="Directory to analyze")
parser.add_argument(
"--output",
default="output/codebase/",
help="Output directory (default: output/codebase/)",
)
# Preset selection (NEW - recommended way)
parser.add_argument(
"--preset",
choices=["quick", "standard", "comprehensive"],
help="Analysis preset: quick (1-2 min), standard (5-10 min, DEFAULT), comprehensive (20-60 min)",
)
parser.add_argument(
"--preset-list", action="store_true", help="Show available presets and exit"
)
# Legacy preset flags (kept for backward compatibility)
parser.add_argument(
"--quick",
action="store_true",
help="[DEPRECATED] Quick analysis - use '--preset quick' instead",
)
parser.add_argument(
"--comprehensive",
action="store_true",
help="[DEPRECATED] Comprehensive analysis - use '--preset comprehensive' instead",
)
# Deprecated depth flag
parser.add_argument(
"--depth",
choices=["surface", "deep", "full"],
help="[DEPRECATED] Analysis depth - use --preset instead",
)
parser.add_argument(
"--languages", help="Comma-separated languages (e.g., Python,JavaScript,C++)"
)
parser.add_argument("--file-patterns", help="Comma-separated file patterns")
parser.add_argument(
"--enhance",
action="store_true",
help="Enable AI enhancement (default level 1 = SKILL.md only)",
)
parser.add_argument(
"--enhance-level",
type=int,
choices=[0, 1, 2, 3],
default=None,
help="AI enhancement level: 0=off, 1=SKILL.md only (default), 2=+Architecture+Config, 3=full",
)
parser.add_argument("--skip-api-reference", action="store_true", help="Skip API docs")
parser.add_argument("--skip-dependency-graph", action="store_true", help="Skip dep graph")
parser.add_argument("--skip-patterns", action="store_true", help="Skip pattern detection")
parser.add_argument("--skip-test-examples", action="store_true", help="Skip test examples")
parser.add_argument("--skip-how-to-guides", action="store_true", help="Skip guides")
parser.add_argument("--skip-config-patterns", action="store_true", help="Skip config")
parser.add_argument(
"--skip-docs", action="store_true", help="Skip project docs (README, docs/)"
)
parser.add_argument("--no-comments", action="store_true", help="Skip comments")
parser.add_argument("--verbose", action="store_true", help="Verbose logging")
"""Add analyze-specific arguments.
Uses shared argument definitions to ensure consistency
with codebase_scraper.py (standalone scraper).
Includes preset system for simplified UX.
"""
add_analyze_arguments(parser)

View File

@@ -0,0 +1,103 @@
"""Create subcommand parser with multi-mode help support.
Implements progressive disclosure:
- Default help: Universal arguments only (15 flags)
- Source-specific help: --help-web, --help-github, --help-local, --help-pdf
- Advanced help: --help-advanced
- Complete help: --help-all
Follows existing SubcommandParser pattern for consistency.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.create import add_create_arguments
class CreateParser(SubcommandParser):
"""Parser for create subcommand with multi-mode help."""
@property
def name(self) -> str:
return "create"
@property
def help(self) -> str:
return "Create skill from any source (auto-detects type)"
@property
def description(self) -> str:
return """Create skill from web docs, GitHub repos, local code, PDFs, or config files.
Source type is auto-detected from the input:
- Web: https://docs.react.dev/ or docs.react.dev
- GitHub: facebook/react or github.com/facebook/react
- Local: ./my-project or /path/to/repo
- PDF: tutorial.pdf
- Config: configs/react.json
Examples:
skill-seekers create https://docs.react.dev/ --preset quick
skill-seekers create facebook/react --preset standard
skill-seekers create ./my-project --preset comprehensive
skill-seekers create tutorial.pdf --ocr
skill-seekers create configs/react.json
For source-specific options, use:
--help-web Show web scraping options
--help-github Show GitHub repository options
--help-local Show local codebase options
--help-pdf Show PDF extraction options
--help-advanced Show advanced/rare options
--help-all Show all 120+ options
"""
def add_arguments(self, parser):
"""Add create-specific arguments.
Uses shared argument definitions with progressive disclosure.
Default mode shows only universal arguments (15 flags).
Multi-mode help handled via custom flags detected in argument parsing.
"""
# Add all arguments in 'default' mode (universal only)
# This keeps help text clean and focused
add_create_arguments(parser, mode='default')
# Add hidden help mode flags
# These won't show in default help but can be used to get source-specific help
parser.add_argument(
'--help-web',
action='store_true',
help='Show web scraping specific options',
dest='_help_web'
)
parser.add_argument(
'--help-github',
action='store_true',
help='Show GitHub repository specific options',
dest='_help_github'
)
parser.add_argument(
'--help-local',
action='store_true',
help='Show local codebase specific options',
dest='_help_local'
)
parser.add_argument(
'--help-pdf',
action='store_true',
help='Show PDF extraction specific options',
dest='_help_pdf'
)
parser.add_argument(
'--help-advanced',
action='store_true',
help='Show advanced/rare options',
dest='_help_advanced'
)
parser.add_argument(
'--help-all',
action='store_true',
help='Show all available options (120+ flags)',
dest='_help_all'
)

View File

@@ -1,6 +1,11 @@
"""Enhance subcommand parser."""
"""Enhance subcommand parser.
Uses shared argument definitions from arguments.enhance to ensure
consistency with the standalone enhance_skill_local module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.enhance import add_enhance_arguments
class EnhanceParser(SubcommandParser):
@@ -19,20 +24,9 @@ class EnhanceParser(SubcommandParser):
return "Enhance SKILL.md using a local coding agent"
def add_arguments(self, parser):
"""Add enhance-specific arguments."""
parser.add_argument("skill_directory", help="Skill directory path")
parser.add_argument(
"--agent",
choices=["claude", "codex", "copilot", "opencode", "custom"],
help="Local coding agent to use (default: claude or SKILL_SEEKER_AGENT)",
)
parser.add_argument(
"--agent-cmd",
help="Override agent command template (use {prompt_file} or stdin).",
)
parser.add_argument("--background", action="store_true", help="Run in background")
parser.add_argument("--daemon", action="store_true", help="Run as daemon")
parser.add_argument(
"--no-force", action="store_true", help="Disable force mode (enable confirmations)"
)
parser.add_argument("--timeout", type=int, default=600, help="Timeout in seconds")
"""Add enhance-specific arguments.
Uses shared argument definitions to ensure consistency
with enhance_skill_local.py (standalone enhancer).
"""
add_enhance_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""GitHub subcommand parser."""
"""GitHub subcommand parser.
Uses shared argument definitions from arguments.github to ensure
consistency with the standalone github_scraper module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.github import add_github_arguments
class GitHubParser(SubcommandParser):
@@ -19,17 +24,12 @@ class GitHubParser(SubcommandParser):
return "Scrape GitHub repository and generate skill"
def add_arguments(self, parser):
"""Add github-specific arguments."""
parser.add_argument("--config", help="Config JSON file")
parser.add_argument("--repo", help="GitHub repo (owner/repo)")
parser.add_argument("--name", help="Skill name")
parser.add_argument("--description", help="Skill description")
parser.add_argument("--enhance", action="store_true", help="AI enhancement (API)")
parser.add_argument("--enhance-local", action="store_true", help="AI enhancement (local)")
parser.add_argument("--api-key", type=str, help="Anthropic API key for --enhance")
parser.add_argument(
"--non-interactive",
action="store_true",
help="Non-interactive mode (fail fast on rate limits)",
)
parser.add_argument("--profile", type=str, help="GitHub profile name from config")
"""Add github-specific arguments.
Uses shared argument definitions to ensure consistency
with github_scraper.py (standalone scraper).
"""
# Add all github arguments from shared definitions
# This ensures the unified CLI has exactly the same arguments
# as the standalone scraper - they CANNOT drift out of sync
add_github_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""Package subcommand parser."""
"""Package subcommand parser.
Uses shared argument definitions from arguments.package to ensure
consistency with the standalone package_skill module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.package import add_package_arguments
class PackageParser(SubcommandParser):
@@ -19,74 +24,9 @@ class PackageParser(SubcommandParser):
return "Package skill directory into uploadable format for various LLM platforms"
def add_arguments(self, parser):
"""Add package-specific arguments."""
parser.add_argument("skill_directory", help="Skill directory path (e.g., output/react/)")
parser.add_argument(
"--no-open", action="store_true", help="Don't open output folder after packaging"
)
parser.add_argument(
"--skip-quality-check", action="store_true", help="Skip quality checks before packaging"
)
parser.add_argument(
"--target",
choices=[
"claude",
"gemini",
"openai",
"markdown",
"langchain",
"llama-index",
"haystack",
"weaviate",
"chroma",
"faiss",
"qdrant",
],
default="claude",
help="Target LLM platform (default: claude)",
)
parser.add_argument(
"--upload",
action="store_true",
help="Automatically upload after packaging (requires platform API key)",
)
# Streaming options
parser.add_argument(
"--streaming",
action="store_true",
help="Use streaming ingestion for large docs (memory-efficient)",
)
parser.add_argument(
"--chunk-size",
type=int,
default=4000,
help="Maximum characters per chunk (streaming mode, default: 4000)",
)
parser.add_argument(
"--chunk-overlap",
type=int,
default=200,
help="Overlap between chunks (streaming mode, default: 200)",
)
parser.add_argument(
"--batch-size",
type=int,
default=100,
help="Number of chunks per batch (streaming mode, default: 100)",
)
# RAG chunking options
parser.add_argument(
"--chunk",
action="store_true",
help="Enable intelligent chunking for RAG platforms (auto-enabled for RAG adaptors)",
)
parser.add_argument(
"--chunk-tokens", type=int, default=512, help="Maximum tokens per chunk (default: 512)"
)
parser.add_argument(
"--no-preserve-code",
action="store_true",
help="Allow code block splitting (default: code blocks preserved)",
)
"""Add package-specific arguments.
Uses shared argument definitions to ensure consistency
with package_skill.py (standalone packager).
"""
add_package_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""PDF subcommand parser."""
"""PDF subcommand parser.
Uses shared argument definitions from arguments.pdf to ensure
consistency with the standalone pdf_scraper module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.pdf import add_pdf_arguments
class PDFParser(SubcommandParser):
@@ -19,9 +24,9 @@ class PDFParser(SubcommandParser):
return "Extract content from PDF and generate skill"
def add_arguments(self, parser):
"""Add pdf-specific arguments."""
parser.add_argument("--config", help="Config JSON file")
parser.add_argument("--pdf", help="PDF file path")
parser.add_argument("--name", help="Skill name")
parser.add_argument("--description", help="Skill description")
parser.add_argument("--from-json", help="Build from extracted JSON")
"""Add pdf-specific arguments.
Uses shared argument definitions to ensure consistency
with pdf_scraper.py (standalone scraper).
"""
add_pdf_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""Scrape subcommand parser."""
"""Scrape subcommand parser.
Uses shared argument definitions from arguments.scrape to ensure
consistency with the standalone doc_scraper module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.scrape import add_scrape_arguments
class ScrapeParser(SubcommandParser):
@@ -19,24 +24,12 @@ class ScrapeParser(SubcommandParser):
return "Scrape documentation website and generate skill"
def add_arguments(self, parser):
"""Add scrape-specific arguments."""
parser.add_argument("url", nargs="?", help="Documentation URL (positional argument)")
parser.add_argument("--config", help="Config JSON file")
parser.add_argument("--name", help="Skill name")
parser.add_argument("--description", help="Skill description")
parser.add_argument(
"--max-pages",
type=int,
dest="max_pages",
help="Maximum pages to scrape (override config)",
)
parser.add_argument(
"--skip-scrape", action="store_true", help="Skip scraping, use cached data"
)
parser.add_argument("--enhance", action="store_true", help="AI enhancement (API)")
parser.add_argument("--enhance-local", action="store_true", help="AI enhancement (local)")
parser.add_argument("--dry-run", action="store_true", help="Dry run mode")
parser.add_argument(
"--async", dest="async_mode", action="store_true", help="Use async scraping"
)
parser.add_argument("--workers", type=int, help="Number of async workers")
"""Add scrape-specific arguments.
Uses shared argument definitions to ensure consistency
with doc_scraper.py (standalone scraper).
"""
# Add all scrape arguments from shared definitions
# This ensures the unified CLI has exactly the same arguments
# as the standalone scraper - they CANNOT drift out of sync
add_scrape_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""Unified subcommand parser."""
"""Unified subcommand parser.
Uses shared argument definitions from arguments.unified to ensure
consistency with the standalone unified_scraper module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.unified import add_unified_arguments
class UnifiedParser(SubcommandParser):
@@ -19,10 +24,9 @@ class UnifiedParser(SubcommandParser):
return "Combine multiple sources into one skill"
def add_arguments(self, parser):
"""Add unified-specific arguments."""
parser.add_argument("--config", required=True, help="Unified config JSON file")
parser.add_argument("--merge-mode", help="Merge mode (rule-based, claude-enhanced)")
parser.add_argument(
"--fresh", action="store_true", help="Clear existing data and start fresh"
)
parser.add_argument("--dry-run", action="store_true", help="Dry run mode")
"""Add unified-specific arguments.
Uses shared argument definitions to ensure consistency
with unified_scraper.py (standalone scraper).
"""
add_unified_arguments(parser)

View File

@@ -1,6 +1,11 @@
"""Upload subcommand parser."""
"""Upload subcommand parser.
Uses shared argument definitions from arguments.upload to ensure
consistency with the standalone upload_skill module.
"""
from .base import SubcommandParser
from skill_seekers.cli.arguments.upload import add_upload_arguments
class UploadParser(SubcommandParser):
@@ -19,51 +24,9 @@ class UploadParser(SubcommandParser):
return "Upload skill package to Claude, Gemini, OpenAI, ChromaDB, or Weaviate"
def add_arguments(self, parser):
"""Add upload-specific arguments."""
parser.add_argument(
"package_file", help="Path to skill package file (e.g., output/react.zip)"
)
parser.add_argument(
"--target",
choices=["claude", "gemini", "openai", "chroma", "weaviate"],
default="claude",
help="Target platform (default: claude)",
)
parser.add_argument("--api-key", help="Platform API key (or set environment variable)")
# ChromaDB upload options
parser.add_argument(
"--chroma-url",
help="ChromaDB URL (default: http://localhost:8000 for HTTP, or use --persist-directory for local)",
)
parser.add_argument(
"--persist-directory",
help="Local directory for persistent ChromaDB storage (default: ./chroma_db)",
)
# Embedding options
parser.add_argument(
"--embedding-function",
choices=["openai", "sentence-transformers", "none"],
help="Embedding function for ChromaDB/Weaviate (default: platform default)",
)
parser.add_argument(
"--openai-api-key", help="OpenAI API key for embeddings (or set OPENAI_API_KEY env var)"
)
# Weaviate upload options
parser.add_argument(
"--weaviate-url",
default="http://localhost:8080",
help="Weaviate URL (default: http://localhost:8080)",
)
parser.add_argument(
"--use-cloud",
action="store_true",
help="Use Weaviate Cloud (requires --api-key and --cluster-url)",
)
parser.add_argument(
"--cluster-url", help="Weaviate Cloud cluster URL (e.g., https://xxx.weaviate.network)"
)
"""Add upload-specific arguments.
Uses shared argument definitions to ensure consistency
with upload_skill.py (standalone uploader).
"""
add_upload_arguments(parser)