From 0ecc29c7ceaf9d17c1ef5a14097b7a9ae79fe9f3 Mon Sep 17 00:00:00 2001 From: Yige Date: Thu, 16 Jul 2026 19:59:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(market):=20=E4=B8=BA=E5=A4=96=E9=83=A8?= =?UTF-8?q?=E6=8A=80=E8=83=BD=E8=A1=A5=E5=85=85=E5=9B=BE=E6=A0=87=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary / 摘要 Add inline SVG icons to all 20 external pointer skills, so their cards no longer fall back to an empty icon. The market catalog version is bumped from `1.2.8` to `1.2.9`. 为全部 20 个外部 pointer skill 补齐内联 SVG 图标,市场卡片不再显示为空;市场版本由 `1.2.8` 升至 `1.2.9`。 ## Compatibility / 兼容性 Depends on desirecore/desirecore#1177, which permits the `icon` field in strict pointer-entry validation and forwards it through the offline list/detail responses. That PR must merge first. ## Skill → icon screenshot / Skill 与图标截图 The preview labels every card with its display name and id. ![External skill icon preview](https://raw.githubusercontent.com/desirecore/market/feat/external-skill-icons/docs/assets/external-skill-icons-v1.2.9.svg) Covered skills: `agent-reach`, `ai-news-radar`, `amap-jsapi-skill`, `dingtalk-api`, `flyai-skill`, `follow-builders`, `ian-xiaohei-illustrations`, `karpathy-guidelines`, `khazix-skills`, `larksuite-cli`, `last30days`, `luckin-my-coffee`, `mattpocock-skills`, `minimax-image-gen`, `minimax-tts`, `mt-paotui-for-client`, `netease-skills`, `taste-skill`, `wechatpay-skills`, and `wecom-cli`. ## Validation / 验证 - `uv run scripts/i18n/validate-i18n.py` - `uv run scripts/i18n/translate.py --check` - Parsed all 20 `entry.json` icons as SVG XML - `git diff --check` - Rendered the committed preview asset locally --- README.md | 1 + docs/assets/external-skill-icons-v1.2.9.svg | 125 ++++++++++++++++++++ manifest.json | 4 +- scripts/i18n/validate-i18n.py | 18 ++- skills/agent-reach/entry.json | 1 + skills/ai-news-radar/entry.json | 1 + skills/amap-jsapi-skill/entry.json | 1 + skills/dingtalk-api/entry.json | 1 + skills/flyai-skill/entry.json | 1 + skills/follow-builders/entry.json | 1 + skills/ian-xiaohei-illustrations/entry.json | 1 + skills/karpathy-guidelines/entry.json | 1 + skills/khazix-skills/entry.json | 1 + skills/larksuite-cli/entry.json | 1 + skills/last30days/entry.json | 1 + skills/luckin-my-coffee/entry.json | 1 + skills/mattpocock-skills/entry.json | 1 + skills/minimax-image-gen/entry.json | 1 + skills/minimax-tts/entry.json | 1 + skills/mt-paotui-for-client/entry.json | 1 + skills/netease-skills/entry.json | 1 + skills/taste-skill/entry.json | 1 + skills/wechatpay-skills/entry.json | 1 + skills/wecom-cli/entry.json | 1 + 24 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 docs/assets/external-skill-icons-v1.2.9.svg diff --git a/README.md b/README.md index dbe5adb..6e956c9 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ External entries point to upstream packages or repositories. They are counted in "id": "example-skill", "name": "Example Skill", "category": "development", + "icon": "...", "tags": ["example"], "maintainer": { "name": "Example", diff --git a/docs/assets/external-skill-icons-v1.2.9.svg b/docs/assets/external-skill-icons-v1.2.9.svg new file mode 100644 index 0000000..5910870 --- /dev/null +++ b/docs/assets/external-skill-icons-v1.2.9.svg @@ -0,0 +1,125 @@ + + +External skill icon preview +20 pointer entries · DesireCore Market v1.2.9 + + + +Agent Reach +agent-reach +research + + + +AI News Radar +ai-news-radar +productivity + + + +AMap JSAPI Skill +amap-jsapi-skill +development + + + +DingTalk API Skill +dingtalk-api +communication + + + +FlyAI +flyai-skill +productivity + + + +Follow Builders +follow-builders +productivity + + + +Ian 小黑怪诞正文配图 +ian-xiaohei-illustrations +media + + + +Karpathy Guidelines +karpathy-guidelines +development + + + +卡兹克 Skills +khazix-skills +productivity + + + +Lark Suite CLI +larksuite-cli +communication + + + +Last 30 Days +last30days +research + + + +Luckin My Coffee +luckin-my-coffee +business + + + +Matt Pocock Skills +mattpocock-skills +development + + + +MiniMax 图像生成 +minimax-image-gen +media + + + +MiniMax 语音合成 +minimax-tts +media + + + +Meituan Paotui Client +mt-paotui-for-client +business + + + +NetEase Skills +netease-skills +productivity + + + +Taste Skill +taste-skill +creative + + + +WeChat Pay Skills +wechatpay-skills +business + + + +WeCom CLI +wecom-cli +communication + \ No newline at end of file diff --git a/manifest.json b/manifest.json index ad13091..6691634 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "DesireCore Official Market", - "version": "1.2.8", + "version": "1.2.9", "schemaVersion": "1.1.0", "supportedLocales": ["zh-CN", "en-US"], "defaultLocale": "en-US", @@ -28,7 +28,7 @@ "stats": { "totalAgents": 1, "totalSkills": 50, - "lastUpdated": "2026-07-11" + "lastUpdated": "2026-07-16" }, "features": [ "curated-index", diff --git a/scripts/i18n/validate-i18n.py b/scripts/i18n/validate-i18n.py index 4ea6926..5681cfe 100755 --- a/scripts/i18n/validate-i18n.py +++ b/scripts/i18n/validate-i18n.py @@ -17,7 +17,7 @@ Checks: 8. Top-level description is 1-1024 chars (spec); top-level name is 1-64 chars (spec). 9. Skill/Agent counts and builtin skill index match the repository contents. 10. Skill, Agent, and entry.json category references exist in categories.json. - 11. entry.json pointers have the required marketplace fields and safe source URLs. + 11. entry.json pointers have the required marketplace fields, valid inline SVG icons, and safe source URLs. 12. Market Skills set `disable-model-invocation` to true or omit it; false is prohibited. Exit codes: @@ -38,6 +38,7 @@ import json import re import ssl import sys +from xml.etree import ElementTree from dataclasses import dataclass, field from pathlib import Path from typing import Any, Iterable @@ -389,7 +390,7 @@ def validate_entry_json(report: Report, entry_file: Path, category_ids: set[str] if not entry: return - required = ("id", "name", "category", "maintainer", "stewardship", "license", "redistribution", "source") + required = ("id", "name", "category", "icon", "maintainer", "stewardship", "license", "redistribution", "source") for key in required: if key not in entry: report.add(Issue(rel, "entry-json", f"missing required field '{key}'")) @@ -401,6 +402,19 @@ def validate_entry_json(report: Report, entry_file: Path, category_ids: set[str] if not isinstance(category, str) or category not in category_ids: report.add(Issue(rel, "entry-json", f"category '{category}' is not declared in categories.json")) + icon = entry.get("icon") + if not isinstance(icon, str) or not icon.strip(): + report.add(Issue(rel, "entry-json", "icon must be a non-empty inline SVG string")) + else: + try: + root = ElementTree.fromstring(icon) + if root.tag != "{http://www.w3.org/2000/svg}svg": + report.add(Issue(rel, "entry-json", "icon root element must be svg in the SVG namespace")) + elif not root.get("viewBox"): + report.add(Issue(rel, "entry-json", "icon SVG must declare a viewBox")) + except ElementTree.ParseError as exc: + report.add(Issue(rel, "entry-json", f"icon must be valid SVG XML: {exc}")) + maintainer = entry.get("maintainer") if not isinstance(maintainer, dict) or not isinstance(maintainer.get("name"), str): report.add(Issue(rel, "entry-json", "maintainer.name is required")) diff --git a/skills/agent-reach/entry.json b/skills/agent-reach/entry.json index cdb4a05..31bcd29 100644 --- a/skills/agent-reach/entry.json +++ b/skills/agent-reach/entry.json @@ -2,6 +2,7 @@ "id": "agent-reach", "name": "Agent Reach", "category": "research", + "icon": "", "tags": ["research", "web-search", "social-media", "twitter", "reddit", "youtube", "bilibili", "xiaohongshu"], "maintainer": { "name": "Panniantong", diff --git a/skills/ai-news-radar/entry.json b/skills/ai-news-radar/entry.json index e61e00f..241df7b 100644 --- a/skills/ai-news-radar/entry.json +++ b/skills/ai-news-radar/entry.json @@ -2,6 +2,7 @@ "id": "ai-news-radar", "name": "AI News Radar", "category": "productivity", + "icon": "", "tags": [ "ai-news", "rss", diff --git a/skills/amap-jsapi-skill/entry.json b/skills/amap-jsapi-skill/entry.json index e3e6da9..0466675 100644 --- a/skills/amap-jsapi-skill/entry.json +++ b/skills/amap-jsapi-skill/entry.json @@ -2,6 +2,7 @@ "id": "amap-jsapi-skill", "name": "AMap JSAPI Skill", "category": "development", + "icon": "", "tags": [ "lbs-amap" ], diff --git a/skills/dingtalk-api/entry.json b/skills/dingtalk-api/entry.json index 6209384..e6661d8 100644 --- a/skills/dingtalk-api/entry.json +++ b/skills/dingtalk-api/entry.json @@ -2,6 +2,7 @@ "id": "dingtalk-api", "name": "DingTalk API Skill", "category": "communication", + "icon": "", "tags": [ "ogenes" ], diff --git a/skills/flyai-skill/entry.json b/skills/flyai-skill/entry.json index 621a09b..64e6cab 100644 --- a/skills/flyai-skill/entry.json +++ b/skills/flyai-skill/entry.json @@ -2,6 +2,7 @@ "id": "flyai-skill", "name": "FlyAI", "category": "productivity", + "icon": "", "tags": [ "alibaba-flyai" ], diff --git a/skills/follow-builders/entry.json b/skills/follow-builders/entry.json index be76fb8..5937e5a 100644 --- a/skills/follow-builders/entry.json +++ b/skills/follow-builders/entry.json @@ -2,6 +2,7 @@ "id": "follow-builders", "name": "Follow Builders", "category": "productivity", + "icon": "", "tags": [ "zarazhangrui" ], diff --git a/skills/ian-xiaohei-illustrations/entry.json b/skills/ian-xiaohei-illustrations/entry.json index d52a076..a851da6 100644 --- a/skills/ian-xiaohei-illustrations/entry.json +++ b/skills/ian-xiaohei-illustrations/entry.json @@ -2,6 +2,7 @@ "id": "ian-xiaohei-illustrations", "name": "Ian 小黑怪诞正文配图", "category": "media", + "icon": "", "tags": ["illustration", "image-generation", "xiaohei", "design"], "maintainer": { "name": "helloianneo", diff --git a/skills/karpathy-guidelines/entry.json b/skills/karpathy-guidelines/entry.json index 457ee16..5c2a9f1 100644 --- a/skills/karpathy-guidelines/entry.json +++ b/skills/karpathy-guidelines/entry.json @@ -2,6 +2,7 @@ "id": "karpathy-guidelines", "name": "Karpathy Guidelines", "category": "development", + "icon": "", "tags": [ "guidelines", "best-practices", diff --git a/skills/khazix-skills/entry.json b/skills/khazix-skills/entry.json index 1153afd..ecd4a58 100644 --- a/skills/khazix-skills/entry.json +++ b/skills/khazix-skills/entry.json @@ -2,6 +2,7 @@ "id": "khazix-skills", "name": "卡兹克 Skills", "category": "productivity", + "icon": "", "tags": ["khazix", "ai-news", "writing", "analysis"], "maintainer": { "name": "KKKKhazix", diff --git a/skills/larksuite-cli/entry.json b/skills/larksuite-cli/entry.json index 5369fbc..62f5213 100644 --- a/skills/larksuite-cli/entry.json +++ b/skills/larksuite-cli/entry.json @@ -2,6 +2,7 @@ "id": "larksuite-cli", "name": "Lark Suite CLI", "category": "communication", + "icon": "", "tags": [ "larksuite" ], diff --git a/skills/last30days/entry.json b/skills/last30days/entry.json index 6b09ad1..ef600ca 100644 --- a/skills/last30days/entry.json +++ b/skills/last30days/entry.json @@ -2,6 +2,7 @@ "id": "last30days", "name": "Last 30 Days", "category": "research", + "icon": "", "tags": [ "research", "trends", diff --git a/skills/luckin-my-coffee/entry.json b/skills/luckin-my-coffee/entry.json index 5df3450..358557a 100644 --- a/skills/luckin-my-coffee/entry.json +++ b/skills/luckin-my-coffee/entry.json @@ -2,6 +2,7 @@ "id": "luckin-my-coffee", "name": "Luckin My Coffee", "category": "business", + "icon": "", "tags": [ "luckin" ], diff --git a/skills/mattpocock-skills/entry.json b/skills/mattpocock-skills/entry.json index b51e506..6a8057c 100644 --- a/skills/mattpocock-skills/entry.json +++ b/skills/mattpocock-skills/entry.json @@ -2,6 +2,7 @@ "id": "mattpocock-skills", "name": "Matt Pocock Skills", "category": "development", + "icon": "", "tags": [ "engineering", "tdd", diff --git a/skills/minimax-image-gen/entry.json b/skills/minimax-image-gen/entry.json index 693eddb..8704860 100644 --- a/skills/minimax-image-gen/entry.json +++ b/skills/minimax-image-gen/entry.json @@ -2,6 +2,7 @@ "id": "minimax-image-gen", "name": "MiniMax 图像生成", "category": "media", + "icon": "", "tags": [ "minimax", "media" diff --git a/skills/minimax-tts/entry.json b/skills/minimax-tts/entry.json index f2a3ce6..ca7fb31 100644 --- a/skills/minimax-tts/entry.json +++ b/skills/minimax-tts/entry.json @@ -2,6 +2,7 @@ "id": "minimax-tts", "name": "MiniMax 语音合成", "category": "media", + "icon": "", "tags": [ "minimax", "media" diff --git a/skills/mt-paotui-for-client/entry.json b/skills/mt-paotui-for-client/entry.json index 6b09a21..22e4994 100644 --- a/skills/mt-paotui-for-client/entry.json +++ b/skills/mt-paotui-for-client/entry.json @@ -2,6 +2,7 @@ "id": "mt-paotui-for-client", "name": "Meituan Paotui Client", "category": "business", + "icon": "", "tags": [ "meituan" ], diff --git a/skills/netease-skills/entry.json b/skills/netease-skills/entry.json index 9fc3b07..7e61d2a 100644 --- a/skills/netease-skills/entry.json +++ b/skills/netease-skills/entry.json @@ -2,6 +2,7 @@ "id": "netease-skills", "name": "NetEase Skills", "category": "productivity", + "icon": "", "tags": [ "NetEase" ], diff --git a/skills/taste-skill/entry.json b/skills/taste-skill/entry.json index a8c6b8d..6f859da 100644 --- a/skills/taste-skill/entry.json +++ b/skills/taste-skill/entry.json @@ -2,6 +2,7 @@ "id": "taste-skill", "name": "Taste Skill", "category": "creative", + "icon": "", "tags": [ "taste", "design", diff --git a/skills/wechatpay-skills/entry.json b/skills/wechatpay-skills/entry.json index b16f997..f53c3dc 100644 --- a/skills/wechatpay-skills/entry.json +++ b/skills/wechatpay-skills/entry.json @@ -2,6 +2,7 @@ "id": "wechatpay-skills", "name": "WeChat Pay Skills", "category": "business", + "icon": "", "tags": [ "wechatpay-apiv3" ], diff --git a/skills/wecom-cli/entry.json b/skills/wecom-cli/entry.json index dd8bf1e..f1c8d00 100644 --- a/skills/wecom-cli/entry.json +++ b/skills/wecom-cli/entry.json @@ -2,6 +2,7 @@ "id": "wecom-cli", "name": "WeCom CLI", "category": "communication", + "icon": "", "tags": [ "WecomTeam" ],