You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
[3.9.0] - 2026-07-29
Added
HTML parser fallback for broken markup (#96, task F1.4) — new parse_html() helper (cli/html_parsing.py) keeps html.parser as the primary parser (well-formed pages stay byte-identical) but retries with lxml (if installed) then html5lib when parsing raises or yields a tag-free tree for tag-bearing markup, so severely malformed pages no longer scrape as empty. Wired into all web-scraper parse sites (doc_scraper.py) and local HTML file parsing (html_scraper.py); html5lib added as a core dependency so the fallback always exists.
Doc scraper retries transient network failures (#97) — scrape_page/scrape_page_async now wrap fetches in retry_with_backoff, so a connection blip or 5xx no longer silently drops the page and ships an incomplete skill. Only transient faults retry (connect/timeout errors, 5xx); 4xx is a definitive answer and returns un-retried. Attempts configurable via the new max_retries config option (default 3; 1 disables retrying).
MCP fetch_config retries transient network failures (#92) — the registry list/detail/download GETs go through _get_with_retry (3 attempts, exponential backoff); 4xx like "config not found" still returns immediately.
Whisper transcription fallback (Tier 2) implemented (#420) — transcribe_with_whisper() was a placeholder that always raised, so local videos without subtitle files produced no transcript despite the documented 3-tier fallback. Now implemented with faster-whisper (device auto, --whisper-model size, language hint, per-segment confidence), and get_transcript() logs the actual transcription error instead of swallowing it.
MiniMax image OCR + registry-driven multimodal provider support (#423) — MiniMax joins the AI provider registry for text enhancement and vision OCR (MINIMAX_API_REGIONglobal_en/cn_zh, MINIMAX_API_PROTOCOLopenai/anthropic — China-issued keys no longer 401 against the global endpoint). API_PROVIDERS entries now declare wire protocol and supports_images, _call_api branches on protocol (not provider name), and AgentClient.call_with_image() serves all image-capable providers with SKILL_SEEKER_VISION_PROVIDER auto-detection for video_visual frame OCR.
word (docx) source in the scrape_generic MCP tool (#41) — the converter existed in CONVERTER_REGISTRY but the MCP surface never listed it, so MCP clients had no way to scrape .docx sources.
Changed
Token-lean GitHub issue defaults (#169) — GitHub-sourced skills no longer bundle a repo's full closed-issue history by default: issue_state defaults to "open" (was "all"), max_issues to 20 (was 100), and labels/milestones are emitted only with the new include_issue_labels/include_issue_milestones flags (default off). issues.md omits empty sections and no longer prints "No labels" stubs. All defaults overridable.
Fixed
Unified multi-source skip_scrape now rebuilds from cache — UnifiedScraper reloads each configured source from .skillseeker-cache/cached extraction files before conflict detection and build, so cached unified configs no longer re-scrape the network (#405).
Quality completeness checks no longer match inside code blocks (#229) — SkillQualityChecker._check_skill_completeness ran its workflow-step/prerequisites/error-handling regexes against raw SKILL.md, so a # Step 1: comment in a fenced example counted as workflow guidance. Fenced blocks and inline code are stripped before matching; prose detection unchanged.
Pattern-detector precision: getters are not factories, Java Singletons are detectable (#425) — FactoryDetector matched creation keywords as substrings, so a plain Java POJO scored Factory from its getters and a canonical getInstance() Singleton was misclassified as Factory. Creation verbs now match as word-boundary prefixes with accessor prefixes (get/set/is/has) excluded, and SingletonDetector recognizes class-named constructors (Java/C#/C++) and an overridden __new__. Also: dependency-graph node keys use as_posix() so Windows paths can't zero out import resolution, and a multi-file graph resolving zero edges now logs a warning.
Per-frame failures no longer abort visual extraction (#426) — one exception in the classify → OCR → track loop killed the whole video's --visual extraction; a failing frame now logs a warning and is skipped while the scan continues.
Two CPU-environment crashes in visual extraction (#419) — newer OpenCV builds return (N, 4) from HoughLinesP, crashing region classification (reshape(-1, 4) handles every layout); and EasyOCR's quantized backend SIGILLed on x86 CPUs without AVX2 (QEMU default model, homelab VMs) — AVX2 is now detected via /proc/cpuinfo and quantize=False passed when missing (slower fp32, but completes).
Kotlin analyzer is string-aware (#407) — brace counting and declaration extraction now mask strings and comments via a single offset-preserving C-style scanner, fixing dropped declarations from backtick-escaped identifiers, ${...} string-template interpolation, C++14 digit separators, and unterminated block comments.
Streaming-package consumer snippets handle the real package shape (#416) — the usage examples generated by the LangChain/LlamaIndex/Haystack adaptors assumed a bare JSON list, but streaming packages wrap content in {"documents": ...}/{"nodes": ...}; the snippets now handle both, and dead example classes were removed from streaming_adaptor.py.
Docker docs point at pullable images (#412) — all documented references now use the public Hub namespace yusyuss with the CLI (skill-seekers) vs MCP (skill-seekers-mcp) image used correctly per context; Helm values and the raw Kubernetes manifest no longer reference unpullable names.
Security
CORS origins are env-driven across all three servers (#422, #424) — the API, embedding, and MCP HTTP servers shipped allow_origins=["*"] with allow_credentials=True, a combination browsers reject. A shared resolve_cors_config() reads CORS_ORIGINS (comma-separated or *) and enables credentials only for a concrete origin list; a wildcard mixed into the list can't re-enable the rejected combo. Docker LABEL versions synced to pyproject and the stale MCP tool-count label corrected (35 → 40).