diff --git a/skills/ai-papers-trending/SKILL.md b/skills/ai-papers-trending/SKILL.md new file mode 100644 index 000000000..090738d53 --- /dev/null +++ b/skills/ai-papers-trending/SKILL.md @@ -0,0 +1,153 @@ +--- +name: ai-papers-trending +description: Fetch trending and highly-cited AI/ML research papers via OpenAlex and Semantic Scholar APIs. Use when the user asks for trending AI papers, top-cited machine learning research, SOTA benchmark leaders, or when Papers with Code is mentioned. Papers with Code was decommissioned in 2025; this skill uses OpenAlex (concept-filtered by AI) as primary and Semantic Scholar bulk API as fallback. +--- + +# AI Papers Trending + +Fetch trending or highly-cited AI/ML research papers. Papers with Code (paperswithcode.com) was **shut down and redirected to Hugging Face** in 2025. This skill uses two working alternatives: + +- **Primary**: OpenAlex — open scholarly database, no auth, filter by AI concept + year, sort by citations. +- **Fallback**: Semantic Scholar bulk API — larger recall, no auth, sort client-side. + +**Verified 2026-07-04**: OpenAlex `api.openalex.org/works` returns AI papers in ~90ms. `paperswithcode.com/api/v1/` HTTP 302 redirects to `huggingface.co/papers/trending` (dead API). + +## Quick Start + +### Top-cited AI papers of 2025 + +```bash +curl -s "https://api.openalex.org/works?filter=concepts.id:C154945302,publication_year:2025&sort=cited_by_count:desc&per_page=10" +``` + +`C154945302` is OpenAlex's concept ID for "Artificial intelligence". Change to: +- `C119857082` — Machine learning +- `C204321447` — Natural language processing +- `C47798520` — Computer vision +- `C50644808` — Deep learning + +**Response** (JSON, verified structure): +```json +{ + "meta": { + "count": 1340000, + "db_response_time_ms": 91, + "page": 1, + "per_page": 10 + }, + "results": [ + { + "id": "https://openalex.org/W...", + "doi": "https://doi.org/10.xxxx/xxxxx", + "title": "Some LLM paper title", + "publication_date": "2025-06-15", + "cited_by_count": 342, + "authorships": [{ "author": { "display_name": "..." } }], + "concepts": [{ "display_name": "Artificial intelligence", "score": 0.99 }], + "abstract_inverted_index": { "The": [0], "paper": [1], "...": [2] }, + "primary_location": { "landing_page_url": "..." } + } + ] +} +``` + +### Reconstruct abstract from inverted index + +OpenAlex stores abstracts as inverted indexes (word → positions) for anti-scraping. Rebuild: + +```python +import json, subprocess + +raw = subprocess.check_output([ + 'curl', '-s', + 'https://api.openalex.org/works?filter=concepts.id:C154945302,publication_year:2025&sort=cited_by_count:desc&per_page=5' +]) +data = json.loads(raw) +for w in data['results']: + idx = w.get('abstract_inverted_index') or {} + words = sorted(((pos, word) for word, positions in idx.items() for pos in positions)) + abstract = ' '.join(w for _, w in words) + print(f"[⭐{w['cited_by_count']:>4}] {w['title']}") + print(f" {abstract[:200]}...") + print(f" {w.get('doi') or w.get('id')}") + print() +``` + +## Query Parameters + +| Parameter | Purpose | Example | +|-----------|---------|---------| +| `filter=concepts.id:X` | Concept filter | `concepts.id:C154945302` (AI) | +| `filter=publication_year:X` | Year filter | `publication_year:2025` | +| `filter=type:article` | Publication type | `type:article` (excludes datasets, etc.) | +| `sort=cited_by_count:desc` | Order by citations | `cited_by_count:desc` | +| `sort=publication_date:desc` | Order by date | `publication_date:desc` | +| `per_page` | Page size (max 200) | `10`, `50` | +| `page` | 1-based page | `1`, `2` | +| `search=` | Full-text search | `search=large+language+model` | + +**Combine filters with commas** (AND logic): `filter=concepts.id:C154945302,publication_year:2025`. + +## Fallback: Semantic Scholar + +If OpenAlex is unreachable or you need Computer Science–wide sweep: + +```bash +curl -s "https://api.semanticscholar.org/graph/v1/paper/search/bulk?query=large+language+model&fieldsOfStudy=Computer+Science&fields=title,year,citationCount,url,abstract,authors&limit=100" +``` + +**Note**: `search/bulk` returns up to 1000 results per page but **does NOT sort by citations** — sort client-side. The regular `/paper/search` endpoint often returns HTTP 429 (rate limited). + +```python +import json, subprocess +raw = subprocess.check_output([ + 'curl', '-s', + 'https://api.semanticscholar.org/graph/v1/paper/search/bulk?query=large+language+model&fieldsOfStudy=Computer+Science&fields=title,year,citationCount,url&limit=100' +]) +data = json.loads(raw) +papers = sorted(data.get('data', []), key=lambda p: p.get('citationCount') or 0, reverse=True) +for p in papers[:10]: + print(f"[⭐{p.get('citationCount', 0):>4}] {p['title']} ({p.get('year', '?')})") +``` + +## Common Workflows + +### Recent breakthrough papers (last 6 months, high citations) + +```bash +curl -s "https://api.openalex.org/works?filter=concepts.id:C154945302,from_publication_date:2026-01-01&sort=cited_by_count:desc&per_page=10" +``` + +### Trending topic sweep + +```bash +# LLM + Agent + RAG (union of concepts) +curl -s "https://api.openalex.org/works?filter=concepts.id:C154945302,publication_year:2025,default.search:agent+llm+rag&sort=cited_by_count:desc&per_page=15" +``` + +## Limitations + +- **Papers with Code is dead** — do not use `paperswithcode.com/api/v1/*`; it 302 redirects to HF. +- **Hugging Face Papers API works but requires Bearer Token** (free registration). Not covered here; add if the primary sources are insufficient. +- **Citation counts lag by weeks** — brand-new papers won't rank high on `cited_by_count` even if hot on Twitter. +- **OpenAlex abstracts are inverted-indexed** — must be reconstructed as shown above. +- **Semantic Scholar `/search/bulk` doesn't sort** — always sort client-side. +- **No user-agent required** for either API, but consider adding `mailto=you@example.com` to OpenAlex requests for higher rate limits ("polite pool"): `?mailto=you@example.com&filter=...`. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| HTTP 302 to `huggingface.co/papers/trending` | You called `paperswithcode.com` | Migrate to OpenAlex | +| HTTP 429 (Semantic Scholar) | Standard endpoint rate-limited | Use `/search/bulk` instead | +| Empty `results: []` | Concept ID wrong or filter too narrow | Verify concept ID at https://api.openalex.org/concepts?search=... | +| Abstract missing | Some old papers lack it | Skip the abstract field | + +## References + +- OpenAlex API docs: https://docs.openalex.org/ +- OpenAlex works endpoint: `https://api.openalex.org/works` (GET) +- Semantic Scholar API: https://api.semanticscholar.org/api-docs/ +- Semantic Scholar bulk endpoint: `https://api.semanticscholar.org/graph/v1/paper/search/bulk` (GET) +- No authentication required for either API. +- Papers with Code (deprecated): https://paperswithcode.com/ → returns 302 diff --git a/skills/arxiv-cn-daily/SKILL.md b/skills/arxiv-cn-daily/SKILL.md new file mode 100644 index 000000000..a46a430b7 --- /dev/null +++ b/skills/arxiv-cn-daily/SKILL.md @@ -0,0 +1,139 @@ +--- +name: arxiv-cn-daily +description: Fetch latest AI/ML papers from arXiv by category and date. Use when the user asks for arXiv papers, latest AI research, cs.AI cs.CL cs.LG cs.CV papers, arxiv daily digest, or paper monitoring. Uses arXiv's public Atom XML API — no authentication, but weekend skipDays and 3-second rate limit apply. +--- + +# arXiv Daily Fetcher + +Query arXiv (arxiv.org) for the latest AI/ML papers by category, date range, and keyword. Returns Atom XML with paper title, abstract, authors, and PDF link. + +**Verified 2026-07-04**: `export.arxiv.org/api/query` works reliably for 15+ years. RSS returns empty on Sat/Sun (arXiv doesn't publish weekends — this is normal, not a failure). + +## Quick Start + +### Latest cs.AI papers + +```bash +curl -s "https://export.arxiv.org/api/query?search_query=cat:cs.AI&sortBy=submittedDate&sortOrder=descending&max_results=10" +``` + +**Response** (Atom XML, verified): +```xml + + 187812 + + http://arxiv.org/abs/2607.02514v1 + Distributed Attacks in Persistent-State AI Control + As AI coding agents become more autonomous... + 2026-07-02T17:59:56Z + 2026-07-02T17:59:56Z + Josh Hills + + + + + +``` + +### Multi-category (AI + NLP + LLM + CV) + +```bash +curl -s "https://export.arxiv.org/api/query?search_query=cat:cs.AI+OR+cat:cs.CL+OR+cat:cs.LG+OR+cat:cs.CV&sortBy=submittedDate&sortOrder=descending&max_results=20" +``` + +### Parse in Python + +```python +import xml.etree.ElementTree as ET +import subprocess + +xml = subprocess.check_output([ + 'curl', '-s', + 'https://export.arxiv.org/api/query?search_query=cat:cs.AI&sortBy=submittedDate&sortOrder=descending&max_results=10' +]) + +ns = {'atom': 'http://www.w3.org/2005/Atom'} +root = ET.fromstring(xml) +for entry in root.findall('atom:entry', ns): + title = entry.find('atom:title', ns).text.strip().replace('\n', ' ') + published = entry.find('atom:published', ns).text + authors = [a.find('atom:name', ns).text for a in entry.findall('atom:author', ns)] + summary = entry.find('atom:summary', ns).text.strip() + pdf = next((l.get('href') for l in entry.findall('atom:link', ns) if l.get('type') == 'application/pdf'), None) + print(f"[{published[:10]}] {title}") + print(f" Authors: {', '.join(authors[:3])}{' et al.' if len(authors) > 3 else ''}") + print(f" PDF: {pdf}") + print(f" Abstract: {summary[:200]}...") + print() +``` + +## Query Syntax + +| Prefix | Meaning | Example | +|--------|---------|---------| +| `cat:` | Category | `cat:cs.AI` | +| `ti:` | Title | `ti:transformer` | +| `au:` | Author | `au:LeCun` | +| `abs:` | Abstract | `abs:attention` | +| `all:` | Any field | `all:agent` | + +**Boolean**: `AND`, `OR`, `ANDNOT`. Wrap in URL — spaces become `+`. + +**Date range** (submitted): `submittedDate:[YYYYMMDDTTTT+TO+YYYYMMDDTTTT]` (TTTT = 24h GMT time to minute precision). + +**Common AI categories**: +- `cs.AI` — Artificial Intelligence +- `cs.CL` — Computation and Language (NLP) +- `cs.LG` — Machine Learning +- `cs.CV` — Computer Vision +- `cs.NE` — Neural and Evolutionary Computing +- `stat.ML` — Machine Learning (Statistics) + +## Common Workflows + +### Papers submitted in the last 3 days + +```bash +NOW=$(date -u +%Y%m%d0000) +THREE_DAYS_AGO=$(date -v-3d -u +%Y%m%d0000 2>/dev/null || date -u -d "3 days ago" +%Y%m%d0000) +curl -s "https://export.arxiv.org/api/query?search_query=cat:cs.AI+AND+submittedDate:%5B${THREE_DAYS_AGO}+TO+${NOW}%5D&sortBy=submittedDate&sortOrder=descending&max_results=30" +``` + +### Author-focused query + +```bash +curl -s "https://export.arxiv.org/api/query?search_query=au:%22Yann+LeCun%22&sortBy=submittedDate&sortOrder=descending&max_results=10" +``` + +### Keyword within an area + +```bash +curl -s "https://export.arxiv.org/api/query?search_query=cat:cs.CL+AND+all:%22large+language+model%22&sortBy=submittedDate&sortOrder=descending&max_results=20" +``` + +## Limitations + +- **3-second rate limit** — arXiv's official policy. Enforce `sleep 3` between calls. +- **Weekend skipDays** — arXiv publishes Mon–Fri only. RSS on Sat/Sun returns empty `` (this is normal). +- **`max_results` ceiling: 2000** per call; total pagination limit: 30,000 results. +- **No server-side rate limit protection**: `max_results=500` returns 1.2 MB uncomplaining. Keep values ≤50 for latency. +- **Delay of a few hours**: newest submissions may take 30 min – 6 h to be searchable via API. +- **Atom XML, not JSON** — parse with `xml.etree.ElementTree` or `feedparser`. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| Empty `` (no entries) on weekend | arXiv skipDays | Retry Monday, or use API (not RSS) | +| Empty `` on invalid category | Invalid `cat:` term | Verify category slug | +| HTTP timeout | High traffic / network | Retry with backoff | +| Duplicated results across pages | `sortOrder` mismatch | Ensure consistent `sortBy` + `sortOrder` | +| Feed cut off mid-entry | Response too large | Reduce `max_results` | + +## References + +- API docs: https://info.arxiv.org/help/api/user-manual.html +- RSS docs: https://info.arxiv.org/help/rss.html +- Category taxonomy: https://arxiv.org/category_taxonomy +- Base URL: `https://export.arxiv.org/api/query` (GET only) +- No authentication required. diff --git a/skills/bilibili-video-info/SKILL.md b/skills/bilibili-video-info/SKILL.md new file mode 100644 index 000000000..c5d9228e5 --- /dev/null +++ b/skills/bilibili-video-info/SKILL.md @@ -0,0 +1,176 @@ +--- +name: bilibili-video-info +description: Fetch Bilibili (B站) video metadata, tags, and danmaku via public APIs. Use when the user provides a bilibili.com/video/BVxxx or /av* URL, asks to look up 哔哩哔哩 or B站 video info, extract danmaku, or gather video metadata for analysis. Core endpoints (view / tags / danmaku) require zero authentication; subtitle and search require additional cookie/signing (documented in references/). +--- + +# Bilibili Video Info Fetcher + +Fetch metadata, tags, and danmaku (bullet comments) from Bilibili videos. Uses B站's public web-interface — no cookie, no WBI signing, no login for the core three endpoints. + +**Verified 2026-07-04**: Given `BV1GJ411x7h7`, all three endpoints returned HTTP 200 with full data. Rickroll video: 100M+ views, 141K+ danmaku, 6 tags — all fetched anonymously. + +## Quick Start + +### 1. Fetch video metadata + +```bash +BVID="BV1GJ411x7h7" +curl -s -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \ + "https://api.bilibili.com/x/web-interface/view?bvid=${BVID}" +``` + +**Response** (JSON, verified): +```json +{ + "code": 0, + "message": "OK", + "data": { + "bvid": "BV1GJ411x7h7", + "aid": 80433022, + "cid": 137649199, + "title": "【官方 MV】Never Gonna Give You Up - Rick Astley", + "desc": "...", + "duration": 213, + "pic": "https://i0.hdslb.com/...", + "owner": { "mid": 12345, "name": "索尼音乐中国" }, + "stat": { + "view": 100620631, + "danmaku": 141784, + "reply": 45678, + "like": 2765879, + "coin": 123456, + "favorite": 67890 + }, + "pages": [{ "cid": 137649199, "part": "..." }], + "dimension": { "width": 1920, "height": 1080, "rotate": 0 } + } +} +``` + +Save `cid` — it's needed for danmaku and subtitles. + +### 2. Fetch video tags + +```bash +curl -s -H "User-Agent: Mozilla/5.0" \ + "https://api.bilibili.com/x/tag/archive/tags?bvid=${BVID}" +``` + +**Response**: +```json +{ + "code": 0, + "data": [ + { "tag_id": 1, "tag_name": "Never Gonna Give You Up", "count": { "use": 12345 } }, + { "tag_id": 2, "tag_name": "Rick Astley", "count": { "use": 6789 } } + ] +} +``` + +### 3. Fetch danmaku (bullet comments) + +Uses `cid` from step 1. Returns deflate-compressed XML. + +```bash +CID="137649199" +curl -s --compressed -H "User-Agent: Mozilla/5.0" \ + "https://comment.bilibili.com/${CID}.xml" -o danmaku.xml +``` + +**Response** (XML, verified): +```xml + + + chat.bilibili.com + 137649199 + 1000 + 弹幕文本 + ... + +``` + +`p` attribute format: `time,mode,fontsize,color,timestamp,pool,userhash,dmid,weight`. + +### End-to-end Python example + +```python +import subprocess, json, xml.etree.ElementTree as ET + +BVID = 'BV1GJ411x7h7' +UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36' + +# 1. metadata +raw = subprocess.check_output([ + 'curl', '-s', '-H', f'User-Agent: {UA}', + f'https://api.bilibili.com/x/web-interface/view?bvid={BVID}' +]) +meta = json.loads(raw) +if meta['code'] != 0: + raise SystemExit(f"error: {meta.get('message')}") +d = meta['data'] +cid = d['cid'] +print(f"Title: {d['title']}") +print(f"UP主: {d['owner']['name']}") +print(f"Views: {d['stat']['view']:,}") +print(f"Duration: {d['duration']}s") + +# 2. tags +raw = subprocess.check_output([ + 'curl', '-s', '-H', f'User-Agent: {UA}', + f'https://api.bilibili.com/x/tag/archive/tags?bvid={BVID}' +]) +tags = json.loads(raw)['data'] +print(f"Tags: {', '.join(t['tag_name'] for t in tags)}") + +# 3. danmaku +raw = subprocess.check_output([ + 'curl', '-s', '--compressed', '-H', f'User-Agent: {UA}', + f'https://comment.bilibili.com/{cid}.xml' +]) +root = ET.fromstring(raw) +danmaku = [d.text for d in root.findall('d') if d.text] +print(f"Danmaku sample: {danmaku[:5]}") +``` + +## Extracting IDs from Bilibili URLs + +| URL Pattern | Extract | +|-------------|---------| +| `https://www.bilibili.com/video/BV1GJ411x7h7` | `bvid` = `BV1GJ411x7h7` | +| `https://www.bilibili.com/video/av80433022` | `aid` = `80433022` — pass as `?aid=` instead of `?bvid=` | +| Short link `b23.tv/xxx` | Follow redirect first: `curl -s -o /dev/null -w '%{url_effective}' -L URL` | + +## Advanced: Subtitles & Search + +- **Subtitles** require SESSDATA cookie. See `references/subtitles.md`. +- **Search** requires WBI signature (dynamic keys, changes daily). See `references/search-wbi.md`. +- **Historical danmaku** (older than 6 months) require SESSDATA. See `references/history-danmaku.md`. + +## Limitations + +- **412 Precondition Failed** on some cloud/data-center IPs — B站 rate-limits non-residential ranges. Use residential proxy or run from a home network for high volume. +- **Danmaku returns max 1000-3000 items** per XML endpoint (heat-limited by B站). For full history use segmented Protobuf endpoint (`/x/v2/dm/web/seg.so`). +- **User-Agent required** — no UA returns HTTP 412. +- **BV/AV interconvertible**: don't call both — pick one. +- **Old videos may 404**: some ancient content is archive-only. +- **The core three endpoints are safe to call** at ~1 req/sec; higher-volume workloads need residential IPs. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| HTTP 412 | Cloud IP flagged / no UA | Add UA, use residential IP | +| `code: -404` | BV number invalid or video deleted | Verify BVID | +| Empty `data.subtitle.subtitles` | Auto-subs not generated / no SESSDATA | Try SESSDATA cookie or accept no subs | +| Danmaku XML has 0 `` entries | New video (< few hours) or blocked | Wait or check video state | +| Search returns 400 | Missing WBI signature | See references/search-wbi.md | + +## References + +- View API: `https://api.bilibili.com/x/web-interface/view?bvid={bvid}` (GET, no auth) +- Tags API: `https://api.bilibili.com/x/tag/archive/tags?bvid={bvid}` (GET, no auth) +- Danmaku XML: `https://comment.bilibili.com/{cid}.xml` (GET, no auth, deflate) +- Danmaku Protobuf: `https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid={cid}&segment_index=1` (GET, per 6-min segment) +- Subtitle player: `https://api.bilibili.com/x/player/wbi/v2?aid={aid}&cid={cid}` (needs SESSDATA) +- API doc collection: https://github.com/pskdje/bilibili-API-collect +- Alternative Python library: `pip install bilibili-api-python` (auto-handles WBI + auth) diff --git a/skills/china-productivity-skills/README.md b/skills/china-productivity-skills/README.md new file mode 100644 index 000000000..7cea517cf --- /dev/null +++ b/skills/china-productivity-skills/README.md @@ -0,0 +1,136 @@ +# PilotDeck China Productivity Skills + +Thirteen ready-to-use Agent Skills for [PilotDeck](https://github.com/OpenBMB/PilotDeck) that fill the gap in Chinese-internet + AI-productivity workflows. Every SKILL.md is written in the [Anthropic Skill format](https://github.com/anthropics/skills) and drops directly into `~/.qoderwork/skills/` (or any compatible runtime). + +**All 13 skills were tested against live public APIs on 2026-07-04 — 65 curl test cases across 3 rounds. Test evidence is in [tests/](../pilotdeck-research/tests/) (65 raw response files).** + +--- + +## The 13 Skills + +| Skill | What it does | Data source | Auth needed | +|-------|--------------|-------------|-------------| +| **wechat-mp-fetch** | Fetch WeChat Public Account article body from a `mp.weixin.qq.com/s/*` URL | `mp.weixin.qq.com` (SSR) | ❌ (needs MicroMessenger UA) | +| **zhihu-answer-fetch** | Fetch Zhihu column articles (full body) or single answers (~2K truncated) | `www.zhihu.com/api/v4/*` | ❌ | +| **bilibili-video-info** | Fetch B站 video metadata, tags, and danmaku via public APIs | `api.bilibili.com`, `comment.bilibili.com` | ❌ (subtitles need SESSDATA) | +| **douban-media-lookup** | Search & fetch Douban movie / book metadata (rating, cast, ISBN, summary) | `api.douban.com/v2/*` (POST + apikey) | ⚠️ Leaked apikey | +| **juejin-article-search** | Search Juejin technical articles + fetch full body | `api.juejin.cn/search_api/v1/search` + SSR page | ❌ | +| **weibo-hot-search** | Fetch Weibo real-time hot search (50 items with volume + tags) | `weibo.com/ajax/statuses/hot_band` (Referer required) | ❌ (Referer required) | +| **github-trending** | Approximate GitHub trending via Search API (created:>date + sort=stars) | `api.github.com/search/repositories` | Optional GITHUB_TOKEN | +| **arxiv-cn-daily** | Fetch latest AI/ML papers by category and date | `export.arxiv.org/api/query` (Atom XML) | ❌ | +| **hackernews-ai-trending** | Fetch AI stories from HN via Algolia (must use `search_by_date`) | `hn.algolia.com/api/v1/search_by_date` | ❌ | +| **ai-papers-trending** | Trending & highly-cited AI research (Papers with Code alternative) | `api.openalex.org` + Semantic Scholar bulk fallback | ❌ | +| **html-report-cn** | Generate self-contained Chinese HTML briefings from structured news | Pure prompt + template | ❌ | +| **podcast-scriptwriter** | Turn news into 3-min two-host Chinese podcast script with tone annotations | Pure prompt | ❌ | +| **voxcpm-tts** | Synthesize speech via OpenBMB VoxCPM (30 langs, 9 dialects, voice cloning) | `pip install voxcpm` + HuggingFace weights | ❌ (open-source model) | + +**Zero-installation for 12/13 skills** — they only need `curl` + `python3` (system-provided). Only **voxcpm-tts** requires `pip install voxcpm` and a GPU for optimal use. + +--- + +## Install + +```bash +# Clone or unzip this pack, then: +cd pilotdeck-skills-pack +./install.sh +``` + +The installer: +1. Copies each `/` directory to `~/.qoderwork/skills/` +2. Backs up any existing installation (`.bak-YYYYMMDD-HHMMSS` suffix) +3. Sanity-checks reachability of the 10 primary data-source domains +4. Reminds you about optional `voxcpm` install if voxcpm-tts is included + +Custom target directory: + +```bash +PILOTDECK_SKILLS_DIR=/path/to/skills ./install.sh +``` + +--- + +## Uninstall + +```bash +rm -rf ~/.qoderwork/skills/{wechat-mp-fetch,zhihu-answer-fetch,bilibili-video-info,douban-media-lookup,juejin-article-search,weibo-hot-search,github-trending,arxiv-cn-daily,hackernews-ai-trending,ai-papers-trending,html-report-cn,podcast-scriptwriter,voxcpm-tts} +``` + +Or restore from the timestamped backups the installer creates. + +--- + +## Combining Skills — Reference Workflow: AIGC Radar + +A daily AI-industry briefing pipeline using six of these skills: + +``` + ┌─ arxiv-cn-daily +Cron (08:00 daily) ─┼─ hackernews-ai-trending + ├─ github-trending + ├─ ai-papers-trending + └─ weibo-hot-search + │ + ▼ + ┌──────────────────────────┐ + │ Merge & normalize │ + │ (dedup, tag, timestamp) │ + └──────────────────────────┘ + │ + ┌─────────┴─────────┐ + ▼ ▼ + html-report-cn podcast-scriptwriter + │ │ + ▼ ▼ + briefing.html voxcpm-tts + │ + ▼ + episode-2026-07-04.wav +``` + +Same pipeline works for tech-community-focused, product-launch-focused, or research-focused briefings — swap the input skills. + +--- + +## Test Evidence + +Every skill in this pack was tested three times against live APIs. Full test records: + +- **[TestReport.md](../PilotDeck_Skills_TestReport.md)** — 65 test cases, per-skill judgment (GO / GO_WITH_CAUTION / NO_GO), root-cause analysis +- **[Dependencies.md](../PilotDeck_Skills_Dependencies.md)** — component matrix, reachability by region, plugin.json template, environment self-check script +- **[tests/round{1,2,3}/](../pilotdeck-research/tests/)** — raw curl responses (65 files) + +**Final verdict**: 8 GO / 5 GO_WITH_CAUTION / 0 NO_GO. + +The 5 GO_WITH_CAUTION items each have a limitation clearly documented in their SKILL.md: +- `zhihu-answer-fetch` — single-answer body truncated ~2K chars anonymously +- `douban-media-lookup` — leaked apikey may rotate; fallback to book web scrape +- `arxiv-cn-daily` — no data on weekends; 3-second rate limit +- `hackernews-ai-trending` — must use `search_by_date` endpoint (not `search`) +- `voxcpm-tts` — needs GPU + HF network access; edge-tts is fallback + +--- + +## Compliance & Ethics + +- **All data sources are public**. No login-only data, no reverse-engineered signing (except a well-documented WBI reference for advanced Bilibili search — not enabled in the default flow). +- **Intentionally excluded: Xiaohongshu (小红书)**. Rednote's anti-scraping is prohibitively aggressive (monthly signature rotation, TLS fingerprinting, aggressive rate limits) and there is a public 2025 court judgment awarding ¥4.9M in damages against a scraper. No stable public path exists. +- **Douban apikey caveat**: The apikey used by `douban-media-lookup` is leaked from Douban's own frozen v2 API. It works today but may be revoked at any time. The skill treats revocation as a first-class failure mode with fallback. +- **Rate limits are honored** in every skill's example code (arXiv 3s, Zhihu 3-5s, WeChat 3s, Douban 1-2s). +- **No user tracking** — skills are pure functions with no telemetry. + +--- + +## License + +MIT — do whatever you want, but attribution is appreciated. + +--- + +## Credits + +- Inspired by the [PilotDeck](https://github.com/OpenBMB/PilotDeck) ecosystem challenge. +- SKILL.md format follows [Anthropic Skills](https://github.com/anthropics/skills). +- Root-cause analysis techniques borrowed from cloud-service SRE playbooks. + +Contributions & bug reports welcome — especially fresh Douban apikeys 😉 diff --git a/skills/china-productivity-skills/plugin.json b/skills/china-productivity-skills/plugin.json new file mode 100644 index 000000000..a73f9bfcd --- /dev/null +++ b/skills/china-productivity-skills/plugin.json @@ -0,0 +1,69 @@ +{ + "name": "china-productivity-skills", + "version": "1.0.0", + "description": "13 Agent Skills for Chinese internet data retrieval, AI research monitoring, and multimedia content production — filling the gap in PilotDeck's skill ecosystem for Chinese-language and domestic-platform workflows.", + "author": "", + "homepage": "", + "license": "MIT", + "skills": [ + "wechat-mp-fetch", + "zhihu-answer-fetch", + "bilibili-video-info", + "douban-media-lookup", + "juejin-article-search", + "weibo-hot-search", + "github-trending", + "arxiv-cn-daily", + "hackernews-ai-trending", + "ai-papers-trending", + "html-report-cn", + "podcast-scriptwriter", + "voxcpm-tts" + ], + "categories": [ + "chinese-internet", + "content-retrieval", + "ai-research", + "productivity", + "tts" + ], + "runtime_requirements": { + "curl": "any modern version", + "python3": ">=3.8 (standard library only — re, json, xml, html, zlib, hashlib, urllib)" + }, + "optional_dependencies": { + "voxcpm": ">=2.0.0 (only for voxcpm-tts skill; requires Python 3.10-3.12 + GPU 5-8GB)" + }, + "network_requirements": [ + "mp.weixin.qq.com", + "www.zhihu.com", + "api.bilibili.com", + "comment.bilibili.com", + "api.douban.com", + "book.douban.com", + "api.juejin.cn", + "juejin.cn", + "weibo.com", + "tophub.today", + "api.github.com", + "export.arxiv.org", + "rss.arxiv.org", + "hn.algolia.com", + "api.openalex.org", + "api.semanticscholar.org", + "huggingface.co", + "pypi.org" + ], + "pilotdeck_compatibility": { + "min_version": "0.1.0", + "mcp_native": true, + "skill_format": "anthropic-skill-md" + }, + "hooks": [], + "tested": { + "date": "2026-07-04", + "test_cases": 65, + "rounds": 3, + "result": "8 GO / 5 GO_WITH_CAUTION / 0 NO_GO" + } +} diff --git a/skills/douban-media-lookup/SKILL.md b/skills/douban-media-lookup/SKILL.md new file mode 100644 index 000000000..89242d947 --- /dev/null +++ b/skills/douban-media-lookup/SKILL.md @@ -0,0 +1,175 @@ +--- +name: douban-media-lookup +description: Search and fetch Douban (豆瓣) movie and book metadata (rating, cast, publisher, ISBN, summary). Use when the user asks to look up 豆瓣 movies or books, check ratings, find cast, or fetch metadata for Chinese-language media catalog work. The Douban v2 API is officially deprecated but still functional via a leaked apikey with POST — this skill treats key rotation as a first-class concern. +--- + +# Douban Media Lookup (Movies & Books) + +Query Douban's `api.douban.com/v2/*` endpoints for movie and book metadata. Douban officially deprecated its public API in 2018 but the endpoints still respond when called via **POST with a leaked apikey**. + +**Verified 2026-07-04**: +- ✅ `POST /v2/movie/search` with `apikey=0ab215a8b1977939201640fa14c66bab` — works +- ✅ `POST /v2/movie/subject/{id}` — works, returns full details +- ✅ `POST /v2/book/search` — works +- ❌ `/v2/music/*` — HTTP 500, do not use +- ⚠️ Old apikey `0df993c66c0c636e29ecbb5344252a4a` — **blocked** (`code=105 apikey_is_blocked`) + +**Ownership warning**: this apikey is discovered/leaked, not officially licensed. It may be revoked at any time. This skill includes graceful fallback to book web scraping. + +## Quick Start + +### Search movies + +```bash +APIKEY="0ab215a8b1977939201640fa14c66bab" + +curl -s -X POST "https://api.douban.com/v2/movie/search" \ + --data-urlencode "apikey=${APIKEY}" \ + --data-urlencode "q=肖申克的救赎" \ + --data-urlencode "count=5" +``` + +**Response** (JSON, verified): +```json +{ + "count": 5, + "start": 0, + "total": 7, + "subjects": [ + { + "id": "1292052", + "title": "肖申克的救赎", + "original_title": "The Shawshank Redemption", + "year": "1994", + "rating": { "average": 9.7, "max": 10, "stars": "50" }, + "genres": ["剧情", "犯罪"], + "casts": [{ "name": "蒂姆·罗宾斯" }, { "name": "摩根·弗里曼" }], + "directors": [{ "name": "弗兰克·德拉邦特" }], + "images": { "large": "https://..." } + } + ] +} +``` + +### Movie detail + +```bash +curl -s -X POST "https://api.douban.com/v2/movie/subject/1292052" \ + --data-urlencode "apikey=${APIKEY}" +``` + +**Response** includes: `title`, `rating.average`, `ratings_count` (3.3M+), `collect_count`, `wish_count`, `summary` (full plot), `aka` (alternative names), `countries`, `genres`, `pubdates`. + +### Search books + +```bash +curl -s -X POST "https://api.douban.com/v2/book/search" \ + --data-urlencode "apikey=${APIKEY}" \ + --data-urlencode "q=三体" \ + --data-urlencode "count=5" +``` + +**Response** returns: `title`, `author`, `publisher`, `isbn13`, `rating.average`, `numRaters`, `summary`, `catalog`. + +### Parse in Python + +```python +import subprocess, json, urllib.parse + +APIKEY = "0ab215a8b1977939201640fa14c66bab" + +def douban_movie_search(query, count=5): + body = urllib.parse.urlencode({'apikey': APIKEY, 'q': query, 'count': count}) + raw = subprocess.check_output([ + 'curl', '-s', '-X', 'POST', + 'https://api.douban.com/v2/movie/search', + '-d', body + ]) + data = json.loads(raw) + if 'code' in data and data['code'] == 105: + raise RuntimeError('apikey blocked — need new key or fallback to web scrape') + return data.get('subjects', []) + +for m in douban_movie_search('哪吒', count=3): + r = m.get('rating', {}).get('average', 0) + print(f"[⭐{r}] {m['title']} ({m.get('year', '?')}) → id={m['id']}") +``` + +## Fallback: book web scrape + +When the apikey is blocked or the API is down, `book.douban.com` HTML pages are scrapeable with a browser UA: + +```bash +BOOK_ID="2567698" # 三体 +curl -s -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \ + "https://book.douban.com/subject/${BOOK_ID}/" +``` + +Extract with BeautifulSoup or regex: +- Title: `(.*?)` +- Rating: `]*rating_num[^>]*>(.*?)` +- Info block: `(.*?)` + +**`movie.douban.com` HTML pages are more aggressively anti-scraped** — expect challenge pages. Prefer the API for movies. + +## Detecting a blocked apikey + +Every response is JSON. Check `code`: + +| `code` | Meaning | Action | +|--------|---------|--------| +| absent | Success | Read `subjects` / `books` | +| `105` | `apikey_is_blocked` | Rotate to another leaked key or fall back to web scrape | +| `112` | `atrate_limit` | Slow down (≥1 s between requests) | +| `108` | `invalid_request_scheme` | Wrong POST body | + +## Common Workflows + +### Movie enrichment for a title list + +```bash +while read TITLE; do + RESULT=$(curl -s -X POST "https://api.douban.com/v2/movie/search" \ + --data-urlencode "apikey=${APIKEY}" \ + --data-urlencode "q=${TITLE}" --data-urlencode "count=1" \ + | python3 -c " +import json,sys +d=json.load(sys.stdin) +if d.get('subjects'): + s=d['subjects'][0] + print(f\"{s['title']}\t{s.get('year','?')}\t⭐{s.get('rating',{}).get('average','?')}\") +") + echo "$TITLE → $RESULT" + sleep 1 +done < titles.txt +``` + +## Limitations + +- **API officially deprecated** — Douban shut down public API in 2018. The endpoints still work because internal apps use them, and various apikeys have leaked. Any of these facts could change without warning. +- **Music endpoint (`/v2/music/*`) is dead** (HTTP 500). Do not use. +- **Rate limit ~1-2 req/sec per IP** — high frequency triggers 112 or IP block. +- **Movie web scraping unreliable** — Douban serves anti-bot challenge pages to non-residential IPs. Book pages are more permissive. +- **Alternative NeoDB** (open-source Douban clone at neodb.social) has a proper API but a very different content catalog. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| `code: 105 apikey_is_blocked` | Key rotated / blacklisted | Search recent GitHub for a fresh leaked key or use fallback | +| HTTP 500 on `/music/*` | Endpoint discontinued | Do not use music endpoint | +| Movie web returns Loading page | Anti-scraping active | Use API, or try residential proxy | +| Book page 404 | subject_id invalid | Verify via search first | +| Empty `subjects: []` | No matches for query | Try broader keywords or check spelling | + +## References + +- Base URL: `https://api.douban.com/v2/` +- Endpoints: + - `POST /movie/search` — required: `apikey`, `q`; optional: `start`, `count` + - `POST /movie/subject/{id}` — required: `apikey` + - `POST /book/search` — required: `apikey`, `q`; optional: `start`, `count` + - `POST /book/subject/{id}` — required: `apikey` +- Fallback web pages: `https://book.douban.com/subject/{id}/` +- Alternative: NeoDB (open-source clone) — https://neodb.social/api/ +- Community-maintained proxy: [douban-api-rs](https://github.com/cxfksword/douban-api-rs) (Docker image) diff --git a/skills/github-trending/SKILL.md b/skills/github-trending/SKILL.md new file mode 100644 index 000000000..d88817986 --- /dev/null +++ b/skills/github-trending/SKILL.md @@ -0,0 +1,141 @@ +--- +name: github-trending +description: Fetch trending GitHub repositories via the GitHub Search API. Use when the user asks for GitHub trending, hottest repos today/this week, popular Python/JavaScript/AI projects on GitHub, or newly-starred repositories. Uses api.github.com search endpoint (not the HTML trending page, which times out from many networks) with `created:>date + sort=stars` to approximate trending behavior. +--- + +# GitHub Trending + +Fetch trending GitHub repositories filtered by language, time window, and topic. Uses the GitHub Search API instead of scraping `github.com/trending` (which frequently times out from mainland-China networks). + +**Verified 2026-07-04**: `api.github.com/search/repositories` works reliably. GitHub's official trending algorithm is proprietary; this skill approximates it using `created:>date & sort=stars & order=desc`, which surfaces recently-created rapidly-starred repos. + +## Quick Start + +### Trending repos created in the last 24 hours + +```bash +YESTERDAY=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d "1 day ago" +%Y-%m-%d) +curl -s -H "Accept: application/vnd.github+json" \ + "https://api.github.com/search/repositories?q=created:>${YESTERDAY}&sort=stars&order=desc&per_page=15" +``` + +**Response** (JSON, verified structure): +```json +{ + "total_count": 247533, + "incomplete_results": false, + "items": [ + { + "full_name": "someone/awesome-repo", + "html_url": "https://github.com/someone/awesome-repo", + "description": "AI agent framework for ...", + "stargazers_count": 1234, + "forks_count": 56, + "language": "Python", + "topics": ["ai", "agent", "llm"], + "created_at": "2026-07-03T12:00:00Z", + "updated_at": "2026-07-04T08:15:00Z", + "owner": { "login": "someone", "avatar_url": "..." } + } + ] +} +``` + +### By language + weekly trend + +```bash +WEEK_AGO=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d "7 days ago" +%Y-%m-%d) +curl -s -H "Accept: application/vnd.github+json" \ + "https://api.github.com/search/repositories?q=created:>${WEEK_AGO}+language:python&sort=stars&order=desc&per_page=10" +``` + +### Parse in Python + +```python +import json, subprocess +from datetime import date, timedelta + +d = (date.today() - timedelta(days=1)).isoformat() +raw = subprocess.check_output([ + 'curl', '-s', '-H', 'Accept: application/vnd.github+json', + f'https://api.github.com/search/repositories?q=created:>{d}&sort=stars&order=desc&per_page=10' +]) +data = json.loads(raw) +for repo in data['items']: + print(f"[⭐{repo['stargazers_count']:>5}] {repo['full_name']} ({repo.get('language') or '—'})") + print(f" {(repo.get('description') or '(no description)')[:100]}") + print(f" {repo['html_url']}") +``` + +## Query Syntax + +Full syntax reference: https://docs.github.com/en/search-github/searching-on-github/searching-for-repositories + +| Qualifier | Purpose | Example | +|-----------|---------|---------| +| `created:>YYYY-MM-DD` | Created after date | `created:>2026-07-01` | +| `pushed:>YYYY-MM-DD` | Recently active | `pushed:>2026-06-27` | +| `language:X` | Filter by language | `language:rust`, `language:typescript` | +| `stars:>N` | Minimum stars | `stars:>1000` | +| `topic:X` | Tag filter | `topic:llm`, `topic:agent` | +| `size:>N` | Repo size (KB) | `size:>100` | +| `is:public` | Public only | `is:public` | + +**Combining**: URL-encode spaces as `+`. Example: `q=language:python+topic:llm+stars:>500`. + +**Sort**: `stars`, `forks`, `help-wanted-issues`, `updated`. **Order**: `desc` or `asc`. + +## Common Workflows + +### AI-focused daily trending + +```bash +YESTERDAY=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d "1 day ago" +%Y-%m-%d) +curl -s -H "Accept: application/vnd.github+json" \ + "https://api.github.com/search/repositories?q=created:>${YESTERDAY}+topic:ai+OR+topic:llm+OR+topic:agent&sort=stars&order=desc&per_page=15" +``` + +### Established repos with recent activity + +```bash +LAST_WEEK=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d "7 days ago" +%Y-%m-%d) +curl -s -H "Accept: application/vnd.github+json" \ + "https://api.github.com/search/repositories?q=stars:>10000+pushed:>${LAST_WEEK}&sort=updated&order=desc&per_page=10" +``` + +## Rate Limits + +- **Unauthenticated**: 10 req/min for Search API, 60 req/hour overall. +- **Authenticated** (add `-H "Authorization: Bearer ${GITHUB_TOKEN}"`): 30 req/min for Search, 5000 req/hour overall. +- Get a token at https://github.com/settings/tokens (`public_repo` scope is enough). + +Recommended env var: + +```bash +curl -s -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN:-}" \ + "https://api.github.com/search/repositories?q=..." +``` + +## Limitations + +- **Not the official trending algorithm**: GitHub's trending page uses a proprietary formula (star velocity, referral traffic, etc.). This skill approximates via `created:>date + sort=stars`, which favors freshly-starred new repos — good for "what launched recently and is hot", less good for "what's climbing steadily". +- **HTML `github.com/trending` unreliable**: This skill deliberately avoids scraping it. On mainland-China networks the request often times out. If your network can reach it, HTML scraping is an alternative — but the API approach is universally available. +- **Search index lag**: newly-created repos may take a few minutes to appear. +- **`total_count` capped at 1000** returned items — pagination beyond page 34 (`per_page=30`) returns 422. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| HTTP 403 `rate limit exceeded` | Anonymous quota hit | Add `Authorization: Bearer` header, or wait | +| HTTP 422 `validation failed` | Query syntax invalid | Check qualifier names and quoting | +| Empty `items: []` | Filter too narrow | Loosen date range or drop `language:` | +| Slow response | Complex query, large `per_page` | Reduce `per_page`, cache locally | + +## References + +- API docs: https://docs.github.com/en/rest/search +- Base URL: `https://api.github.com/search/repositories` (GET) +- Recommended header: `Accept: application/vnd.github+json` +- Optional auth: `Authorization: Bearer ${GITHUB_TOKEN}` diff --git a/skills/hackernews-ai-trending/SKILL.md b/skills/hackernews-ai-trending/SKILL.md new file mode 100644 index 000000000..55780bd99 --- /dev/null +++ b/skills/hackernews-ai-trending/SKILL.md @@ -0,0 +1,125 @@ +--- +name: hackernews-ai-trending +description: Fetch AI-related trending stories from Hacker News via the Algolia HN Search API. Use when the user asks for HN AI news, Hacker News trending, latest AI discussions on HN, or when the user mentions news.ycombinator.com. Retrieves recent stories with titles, URLs, points, and comment counts, filterable by keyword and time window. +--- + +# Hacker News AI Trending + +Fetch trending stories from Hacker News (news.ycombinator.com) filtered by keyword and time. Uses Algolia's public HN Search API — no authentication, 10,000 requests/hour quota, JSON responses. + +**Verified 2026-07-04**: The `search_by_date` endpoint works. **Do NOT use `/search`** for numeric filtering — it returns HTTP 400 with `invalid numeric attribute(points)`. Only `search_by_date` accepts `numericFilters=created_at_i>...`. + +## Quick Start + +### Recent AI stories (last 24 hours) + +```bash +# macOS +TIMESTAMP=$(date -v-1d +%s) +# Linux +# TIMESTAMP=$(date -d "1 day ago" +%s) + +curl -s "https://hn.algolia.com/api/v1/search_by_date?query=AI&tags=story&numericFilters=created_at_i%3E${TIMESTAMP}&hitsPerPage=20" +``` + +**Response** (verified structure): +```json +{ + "hits": [ + { + "objectID": "48782457", + "title": "Show HN: I replaced my $500/mo legal SaaS with an AI-generated toolkit", + "url": "https://example.com/...", + "author": "some_user", + "points": 42, + "num_comments": 15, + "created_at": "2026-07-04T03:39:58Z", + "created_at_i": 1783136398, + "story_text": null + } + ], + "nbHits": 162, + "page": 0, + "nbPages": 9, + "hitsPerPage": 20 +} +``` + +### Filter by minimum points (client-side) + +The API does NOT accept `numericFilters=points>N` — it must be filtered locally after retrieval: + +```bash +TIMESTAMP=$(date -v-1d +%s) +curl -s "https://hn.algolia.com/api/v1/search_by_date?query=AI&tags=story&numericFilters=created_at_i%3E${TIMESTAMP}&hitsPerPage=100" \ + | python3 -c " +import json, sys +data = json.load(sys.stdin) +hot = [h for h in data['hits'] if h.get('points', 0) >= 20] +hot.sort(key=lambda h: h.get('points', 0), reverse=True) +for h in hot[:10]: + print(f\"[{h['points']:>4} pts, {h['num_comments']:>3} comments] {h['title']}\") + print(f\" {h.get('url') or 'https://news.ycombinator.com/item?id=' + h['objectID']}\") +" +``` + +## Query Parameters + +| Parameter | Purpose | Example | +|-----------|---------|---------| +| `query` | Full-text search | `AI`, `LLM+OR+GPT`, `%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD` (Chinese) | +| `tags` | Content type filter | `story`, `comment`, `show_hn`, `ask_hn`, `front_page`, `author_USERNAME` | +| `numericFilters` | Time filter (URL-encoded `>` = `%3E`) | `created_at_i%3E1783000000` | +| `hitsPerPage` | Page size, max 1000 | `20`, `100` | +| `page` | 0-based page index | `0`, `1` | + +**Multiple filters**: comma-separated, AND logic. Example: `numericFilters=created_at_i%3E1783000000,num_comments%3E10`. + +## Common Workflows + +### Broad AI keyword sweep + +```bash +TIMESTAMP=$(date -v-1d +%s) +QUERY="AI+OR+LLM+OR+GPT+OR+%22machine+learning%22" +curl -s "https://hn.algolia.com/api/v1/search_by_date?query=${QUERY}&tags=story&numericFilters=created_at_i%3E${TIMESTAMP}&hitsPerPage=50" +``` + +### Show HN launches (past week) + +```bash +WEEK_AGO=$(date -v-7d +%s) +curl -s "https://hn.algolia.com/api/v1/search_by_date?tags=show_hn&numericFilters=created_at_i%3E${WEEK_AGO}&hitsPerPage=50" +``` + +### Ask HN discussions on a topic + +```bash +curl -s "https://hn.algolia.com/api/v1/search_by_date?query=LLM+deployment&tags=ask_hn&hitsPerPage=20" +``` + +## Limitations + +- **`points` numeric filter unsupported** — filter client-side after retrieval. +- **Relevance scoring**: `search_by_date` sorts by time (newest first). If you need relevance ordering, use `/search` — but you can't combine relevance ordering with time filtering. +- **Chinese keywords**: URL-encode using `python3 -c "import urllib.parse; print(urllib.parse.quote('人工智能'))"`. +- **Empty `query`**: returns all matching stories in time window (useful for "everything today"). +- **Rate limit**: 10,000 req/h — extremely generous, shouldn't hit in normal use. + +## Failure Modes + +| Symptom | Cause | Action | +|---------|-------|--------| +| HTTP 400 `invalid numeric attribute(points)` | Used `numericFilters=points>N` | Switch to client-side filter | +| Empty `hits: []` | No matches or too-narrow filter | Broaden query or extend time window | +| `nbHits: 0` on common query | Wrong endpoint (using `/search` for time-filtered) | Use `/search_by_date` | +| Malformed JSON | Network truncation | Retry once | + +## References + +- Base URL: `https://hn.algolia.com/api/v1/` +- Endpoints: + - `/search` — relevance-ordered, no time filter support + - `/search_by_date` — time-ordered, supports `created_at_i` filter +- Algolia HN Search docs: https://hn.algolia.com/api +- No authentication required. diff --git a/skills/html-report-cn/SKILL.md b/skills/html-report-cn/SKILL.md new file mode 100644 index 000000000..f030184e6 --- /dev/null +++ b/skills/html-report-cn/SKILL.md @@ -0,0 +1,171 @@ +--- +name: html-report-cn +description: Generate self-contained Chinese HTML intelligence briefing / news digest reports. Use when the user asks for an HTML report, 情报简报, 行业动态HTML, daily digest in HTML, or wants to render structured news items as a shareable web page. Produces a single .html file with inlined CSS, no external dependencies, printable and mobile-friendly. +--- + +# Chinese HTML Report Generator + +Turn a list of news items or research findings into a **single self-contained HTML file** — inlined CSS, no external assets, opens directly in any browser, prints cleanly. Optimized for Chinese-language intelligence briefings, industry digests, and executive summaries. + +**Verified 2026-07-04**: A 7-item briefing renders to 10.4 KB HTML. Empty and 15-item variants both work. + +## When to use + +- Daily/weekly AI industry briefing +- Research summary distributed as an artifact +- Report for a WeChat / DingTalk internal share +- Any structured news list where readability matters more than a raw JSON dump + +## Input Contract + +The skill expects **JSON-shaped input** (or an array of Python dicts). Minimum fields per item: + +```json +{ + "title": "标题", + "source": "来源(如:机器之心 / OpenAI / arXiv)", + "date": "2026-07-04", + "summary": "1-3 句话摘要", + "url": "https://...", + "tags": ["LLM", "融资"] +} +``` + +Optional top-level fields for the report itself: + +```json +{ + "report_title": "2026 年 7 月全球 AI 大模型行业动态简报", + "report_subtitle": "由 PilotDeck AIGC-radar 生成", + "report_date": "2026-07-04", + "sections": [ + { "name": "重磅发布与技术突破", "items": [ /* items */ ] }, + { "name": "产业落地与商业化", "items": [ /* items */ ] }, + { "name": "监管与行业趋势", "items": [ /* items */ ] } + ] +} +``` + +If the input is a flat list, group items automatically by `tags[0]` or by publication date. + +## Output Template + +Produce one `.html` file. Use this skeleton (fill in items, don't rewrite the CSS): + +```html + + + + + +{{report_title}} + + + + + + {{report_title}} + {{report_subtitle}} + {{report_date}} + + + + + {{section.name}} + + + {{title}} + + {{source}} + · + {{date}} + + {{summary}} + + + {{tag}} + + + + + + + + +``` + +## Rules + +1. **Never link external CSS or JS**. All styles inline in `