diff --git a/README.md b/README.md index 50b4b66..c31c13e 100644 --- a/README.md +++ b/README.md @@ -30,21 +30,22 @@ The market currently contains: - `2` Agents: `desirecore`, `dingtalk-workspace` - `1` Team: `contract-review-team` -- `34` local built-in skills with `SKILL.md` +- `40` local built-in skills with `SKILL.md` - `29` external skill entries with `entry.json` -- `63` publishable skills in total (`SKILL.md` + `entry.json`) +- `69` publishable skills in total (`SKILL.md` + `entry.json`) ## Skill Sources Local built-in skills are installable from this repository and must be listed in `builtin-skills.json`: ```text -code-intelligence, configuring-compute, create-agent, dashscope-image-gen, delete-agent, +baidu-poi-search, ccgp-gov-procurement, clone-agent, cnipa-patent-search, code-intelligence, +configuring-compute, create-agent, creditchina-query, dashscope-image-gen, delete-agent, dev-environment-setup, discover-agent, docx, frontend-design, guizang-ppt, image-to-image, mail-operations, manage-skills, manage-teams, markdown, -minimax-music-gen, minimax-video-gen, nodejs-runtime, pdf, pptx, +minimax-music-gen, minimax-video-gen, multi-source-sentiment, nodejs-runtime, pdf, pptx, presentation-forge, python-runtime, registering-services, s3-storage-operations, skill-creator, -tech-diagram, update-agent, using-services, web-access, workflow, workforce-optimization, +tech-diagram, tianyancha-risk, update-agent, using-services, web-access, workflow, workforce-optimization, xiaomi-tts, xlsx ``` diff --git a/builtin-skills.json b/builtin-skills.json index 8c89341..2d217c7 100644 --- a/builtin-skills.json +++ b/builtin-skills.json @@ -1,9 +1,13 @@ { "skills": [ + "baidu-poi-search", + "ccgp-gov-procurement", "clone-agent", + "cnipa-patent-search", "code-intelligence", "configuring-compute", "create-agent", + "creditchina-query", "dashscope-image-gen", "delete-agent", "dev-environment-setup", @@ -18,6 +22,7 @@ "markdown", "minimax-music-gen", "minimax-video-gen", + "multi-source-sentiment", "nodejs-runtime", "pdf", "pptx", @@ -27,6 +32,7 @@ "s3-storage-operations", "skill-creator", "tech-diagram", + "tianyancha-risk", "update-agent", "using-services", "web-access", diff --git a/manifest.json b/manifest.json index 5e46687..6ec0c59 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,10 @@ "name": "DesireCore Official Market", "version": "1.5.0", "schemaVersion": "1.1.0", - "supportedLocales": ["zh-CN", "en-US"], + "supportedLocales": [ + "zh-CN", + "en-US" + ], "defaultLocale": "en-US", "i18n": { "default_locale": "en-US", @@ -28,8 +31,8 @@ "stats": { "totalAgents": 2, "totalTeams": 1, - "totalSkills": 63, - "lastUpdated": "2026-09-01" + "totalSkills": 69, + "lastUpdated": "2026-09-03" }, "features": [ "curated-index", diff --git a/skills/baidu-poi-search/SKILL.md b/skills/baidu-poi-search/SKILL.md new file mode 100644 index 0000000..8b71656 --- /dev/null +++ b/skills/baidu-poi-search/SKILL.md @@ -0,0 +1,152 @@ +--- +name: baidu-poi-search +description: >- + 百度地图企业 POI 搜索——输入企业名称,返回 POI 名称/地址/经纬度/分支机构。Use when 用户提到"查企业地址"、"查公司位置"、"POI搜索"、"企业地图"、"经纬度"、"查分支机构"、"百度地图"、"企业网点"、"周边企业"。 +version: 1.0.0 +type: procedural +risk_level: low +status: enabled +tags: + - due-diligence + - baidu-map + - poi + - geolocation +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 百度地图POI搜索 + short_desc: 输入企业名称,返回 POI 名称/地址/经纬度/分支机构 + description: >- + 百度地图企业 POI 搜索——输入企业名称,返回 POI 名称/地址/经纬度/分支机构。Use when 用户提到"查企业地址"、"查公司位置"、"POI搜索"、"企业地图"、"经纬度"、"查分支机构"、"百度地图"、"企业网点"、"周边企业"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:24e98eab4d4e0f04 + translated_by: human + en-US: + name: Baidu Map POI Search + short_desc: Enterprise POI lookup by company name — name, address, coordinates, branches + description: >- + Baidu Map enterprise POI search — input a company name and return POI name, address, latitude/longitude, and branch listings. Use when the user asks to look up a company address, location, POI, enterprise map, coordinates, branches, or nearby companies. + body: ./SKILL.md + source_hash: sha256:24e98eab4d4e0f04 + translated_by: human +market: + icon: >- + + category: data + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# Baidu Map POI Search + +## L0: One-Sentence Summary + +Input a company name, call the Baidu Map Place Search API, and return normalized POI data (name / address / coordinates / province & city). + +## L1: Overview + +- **Data source**: Baidu Map Open Platform Place Search API v2 +- **Auth**: AK (free quota for individual developers) +- **Invocation**: HTTP GET (curl / HttpRequest tool) +- **Prerequisites**: no browser, no extra dependencies — pure REST API + +## Credential Setup + +This skill requires a Baidu Map AK (access key): + +1. Register a developer account at the [Baidu Map Open Platform](https://lbsyun.baidu.com/) +2. Console → App Management → Create an app (enable the "Place Search" service; choose the empty-whitelist `0.0.0.0/0` AK type) +3. Export the AK as the environment variable `BAIDU_MAP_AK`, or replace the `{BAIDU_MAP_AK}` placeholder in the commands below + +> If the local DesireCore service catalog already registers the Baidu Map service (endpoint `https://api.map.baidu.com`), prefer calling it through the catalog so credentials are managed centrally. + +## L2: Procedure + +### 1. Build the request + +```bash +curl -s --max-time 15 --ssl-no-revoke \ + "https://api.map.baidu.com/place/v2/search?query={company-name-URL-encoded}®ion={city-or-nationwide}&output=json&page_size=20&ak=${BAIDU_MAP_AK}" +``` + +**Parameters**: + +| Param | Value | Notes | +|---|---|---| +| query | Company name (URL-encoded) | e.g. `华为技术有限公司` → `%E5%8D%8E%E4%B8%BA%E6%8A%80%E6%9C%AF%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8` | +| region | City name or `全国` (nationwide) | Scope; use nationwide when unsure | +| output | json | Fixed | +| page_size | 20 | Max 20 per page | +| ak | `{BAIDU_MAP_AK}` | Baidu Map AK (free for individual developers) | + +### 2. Interpret the response + +- `status == 0`: success, extract `results[]` +- `status != 0`: failure, check `message` (101 = AK missing, 200 = AK disabled, 302 = quota exceeded) + +### 3. Normalized mapping + +Map each entry in `results[]` to: + +```json +{ + "source": "baidu-poi", + "company_name": "{user input}", + "poi_name": "{result.name}", + "address": "{result.address}", + "latitude": "{result.location.lat}", + "longitude": "{result.location.lng}", + "province": "{result.province}", + "city": "{result.city}" +} +``` + +### 4. Homonym filtering (due-diligence scenario) + +POI results may contain same-name noise (e.g. "南岗华为公司" is not "华为技术有限公司"). Filtering suggestion: + +- Exact match: `result.name` equals the full company name → `match=exact` +- Partial match: `result.name` contains the full name or its short name → `match=partial` +- Otherwise → `match=related`, listed separately in due-diligence reports + +### 5. Output format + +```json +{ + "query_status": "success", + "source": "baidu-poi", + "total": 5, + "results": [ + { "poi_name": "华为技术有限公司", "address": "广东省深圳市龙岗区...", "latitude": "22.656137", "longitude": "114.066131", "match": "exact" } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +## Known Limitations + +- Free quota: QPS (~3/s) and daily caps (~100 place-search calls/day) for individual developers, per console quota management +- POI ≠ registered business address: results are map annotations and may differ from the registered address (note the distinction in due diligence) +- Homonyms: short names of famous companies hit many non-target POIs — prefer the full company name + +## Troubleshooting + +| Code | Meaning | Fix | +|---|---|---| +| 0 | Success | — | +| 101 | AK param missing | Check the ak parameter | +| 200 | AK disabled | Check app status in the Baidu console | +| 201 | AK/SN check failed | This recipe uses an empty-whitelist `0.0.0.0/0` AK; no SN needed | +| 302 | Quota exceeded | Wait for the daily reset or upgrade the quota | +| 240 | API service invalid | The AK has not enabled "Place Search" — fix the app in the console | diff --git a/skills/baidu-poi-search/SKILL.zh-CN.md b/skills/baidu-poi-search/SKILL.zh-CN.md new file mode 100644 index 0000000..dadd423 --- /dev/null +++ b/skills/baidu-poi-search/SKILL.zh-CN.md @@ -0,0 +1,102 @@ +# 百度地图 POI 搜索 + +## L0 + +输入企业名称,调用百度地图地点检索 API,返回标准化 POI 数据(名称/地址/经纬度/省市)。 + +## L1 概述 + +- **数据源**:百度地图开放平台地点检索 API v2 +- **认证**:AK(个人开发者免费配额) +- **调用方式**:HTTP GET(curl / HttpRequest 工具) +- **前置条件**:无浏览器依赖、无额外依赖——纯 REST API + +## 凭证获取 + +本技能需要百度地图 AK(访问令牌): + +1. 访问 [百度地图开放平台](https://lbsyun.baidu.com/) 注册开发者账号 +2. 控制台 → 应用管理 → 创建应用(启用"地点检索"服务,AK 类型选"浏览器白名单"并将白名单留空 `0.0.0.0/0`) +3. 将 AK 配置为环境变量 `BAIDU_MAP_AK`,或替换下文命令中的 `{BAIDU_MAP_AK}` 占位符 + +> 若本机 DesireCore 服务目录已注册百度地图服务(端点 `https://api.map.baidu.com`),优先通过服务目录调用,凭证由服务配置统一管理。 + +## L2 操作步骤 + +### 1. 构造请求 + +```bash +curl -s --max-time 15 --ssl-no-revoke \ + "https://api.map.baidu.com/place/v2/search?query={企业名称URL编码}®ion={城市或全国}&output=json&page_size=20&ak=${BAIDU_MAP_AK}" +``` + +**参数说明**: + +| 参数 | 值 | 说明 | +|---|---|---| +| query | 企业名称(URL 编码) | 如"华为技术有限公司"→ `%E5%8D%8E%E4%B8%BA%E6%8A%80%E6%9C%AF%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8` | +| region | 城市名或"全国" | 限定检索范围;不确定时用"全国" | +| output | json | 固定 | +| page_size | 20 | 每页条数(最大 20) | +| ak | `{BAIDU_MAP_AK}` | 百度地图 AK(个人开发者免费申请) | + +### 2. 判断响应 + +- `status == 0`:成功,提取 `results[]` +- `status != 0`:失败,查看 `message`(如 101=AK参数不存在,200=AK被禁用,302=配额超限) + +### 3. 标准化映射 + +对 `results[]` 中每条记录映射为: + +```json +{ + "source": "baidu-poi", + "company_name": "{用户输入的企业名称}", + "poi_name": "{result.name}", + "address": "{result.address}", + "latitude": "{result.location.lat}", + "longitude": "{result.location.lng}", + "province": "{result.province}", + "city": "{result.city}" +} +``` + +### 4. 同名词过滤(尽调场景) + +POI 结果可能包含同名词干扰(如"南岗华为公司"不是"华为技术有限公司")。过滤建议: + +- 精确匹配:`result.name` 与企业全名一致 → 标记 `match=exact` +- 包含匹配:`result.name` 包含企业全名或其简称 → 标记 `match=partial` +- 其他 → 标记 `match=related`,尽调报告单独归类 + +### 5. 输出格式 + +```json +{ + "query_status": "success", + "source": "baidu-poi", + "total": 5, + "results": [ + { "poi_name": "华为技术有限公司", "address": "广东省深圳市龙岗区...", "latitude": "22.656137", "longitude": "114.066131", "match": "exact" } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +## 已知限制 + +- 免费配额:个人开发者有 QPS(约 3 次/秒)与日量上限(地点检索约 100 次/日,以控制台额度管理为准) +- POI ≠ 工商注册地址:返回的是地图标注地址,可能与工商注册地址不同(尽调时注意区分) +- 同名词:知名企业简称(如"华为")会命中大量非目标 POI,建议输入企业全名 + +## 故障排查 + +| 错误码 | 含义 | 处理 | +|---|---|---| +| 0 | 成功 | — | +| 101 | AK 参数不存在 | 检查 ak 参数是否正确传递 | +| 200 | AK 被禁用 | 到百度地图开放平台控制台检查应用状态 | +| 201 | AK 校验失败 / SN 校验失败 | 本方案使用白名单 0.0.0.0/0 类型 AK,无需 SN | +| 302 | 配额超限 | 查看控制台额度管理,等待次日或升级配额 | +| 240 | API 服务无效 | AK 未勾选"地点检索"服务——到控制台修改应用勾选 | diff --git a/skills/baidu-poi-search/catalog-metadata.v1.json b/skills/baidu-poi-search/catalog-metadata.v1.json new file mode 100644 index 0000000..25fbe8d --- /dev/null +++ b/skills/baidu-poi-search/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "baidu-poi-search" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "百度地图POI搜索", + "summary": "输入企业名称,返回 POI 名称/地址/经纬度/分支机构", + "description": "百度地图企业 POI 搜索——输入企业名称,返回 POI 名称/地址/经纬度/分支机构。Use when 用户提到\"查企业地址\"、\"查公司位置\"、\"POI搜索\"、\"企业地图\"、\"经纬度\"、\"查分支机构\"、\"百度地图\"、\"企业网点\"、\"周边企业\"。" + }, + "en-US": { + "name": "Baidu Map POI Search", + "summary": "Enterprise POI lookup by company name — name, address, coordinates, branches", + "description": "Baidu Map enterprise POI search — input a company name and return POI name, address, latitude/longitude, and branch listings. Use when the user asks to look up a company address, location, POI, enterprise map, coordinates, branches, or nearby companies." + } + }, + "category": "data", + "tags": [ + "due-diligence", + "baidu-map", + "poi", + "geolocation" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "low" + } +} diff --git a/skills/ccgp-gov-procurement/SKILL.md b/skills/ccgp-gov-procurement/SKILL.md new file mode 100644 index 0000000..2a8b661 --- /dev/null +++ b/skills/ccgp-gov-procurement/SKILL.md @@ -0,0 +1,203 @@ +--- +name: ccgp-gov-procurement +description: >- + 中国政府采购网招标公告查询——输入企业名称(或简称),搜索该企业参与的采购公告,返回公告列表(标题/链接/日期)并可深度提取详情字段(项目编号/采购人/代理机构/更正内容/联系人)。Use when 用户提到"查招投标"、"政府采购"、"采购公告"、"中标公告"、"招标信息"、"ccgp"、"企业中标"。 +version: 1.0.0 +type: procedural +risk_level: medium +status: enabled +tags: + - due-diligence + - procurement + - government + - bidding +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 政府采购网招标查询 + short_desc: 输入企业名称(建议简称),返回采购公告列表与详情字段 + description: >- + 中国政府采购网招标公告查询——输入企业名称(或简称),搜索该企业参与的采购公告,返回公告列表(标题/链接/日期)并可深度提取详情字段(项目编号/采购人/代理机构/更正内容/联系人)。Use when 用户提到"查招投标"、"政府采购"、"采购公告"、"中标公告"、"招标信息"、"ccgp"、"企业中标"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:b5c84bd5f84eeb34 + translated_by: human + en-US: + name: CCGP Procurement Search + short_desc: Search China Government Procurement announcements by company name + description: >- + China Government Procurement (ccgp.gov.cn) announcement search — input a company name (short name recommended) and return procurement announcements (title / link / date), with optional deep extraction of detail fields (project number / purchaser / agency / corrections / contacts). Use when the user asks about tenders, procurement announcements, winning bids, or ccgp. + body: ./SKILL.md + source_hash: sha256:b5c84bd5f84eeb34 + translated_by: human +market: + icon: >- + + category: business + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# CCGP Government Procurement Search + +## L0: One-Sentence Summary + +Input a company name (short name recommended, e.g. "华为" instead of the full legal name), search ccgp.gov.cn via Kimi WebBridge browser automation, and return a structured list of procurement announcements. + +## L1: Overview + +- **Data source**: China Government Procurement search (`search.ccgp.gov.cn`) +- **Auth**: none (public search) +- **Invocation**: Kimi WebBridge browser automation (navigate + evaluate) +- **Prerequisites**: Kimi WebBridge daemon running (`127.0.0.1:10086`) + browser extension connected +- **Key advantage**: a browser session naturally avoids the IP throttling applied to direct curl calls + +## L2: Procedure + +### 1. Check the WebBridge daemon + +```bash +curl -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + -d '{"action":"list_tabs","session":"ccgp-query"}' --max-time 10 +``` + +If unreachable, start the daemon: + +```bash +~/.kimi-webbridge/bin/kimi-webbridge.exe start +``` + +### 2. Navigate to the search results page + +**Windows approach** (write JSON to a temp file to avoid encoding issues): + +Write `C:\tmp\ccgp-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://search.ccgp.gov.cn/bxsearch?searchtype=1&page_index=1&bidSort=0&pinMu=0&bidType=0&dbselect=bidx&kw={company-short-name-URL-encoded}", + "newTab": true, + "group_title": "政府采购网查询" + }, + "session": "ccgp-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\ccgp-nav.json" --max-time 30 +``` + +Wait 5 seconds before continuing. + +### 3. Extract the announcement list + +Write `C:\tmp\ccgp-extract.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var txt=document.body.innerText||'';var total=(txt.match(/共找到\\s*(\\d+)\\s*条/)||[])[1]||'?';var items=[];document.querySelectorAll('a').forEach(function(a){var t=(a.innerText||'').replace(/\\s+/g,' ').trim();if(t.includes('{company-keyword}')&&t.length>10){var li=a.closest('li')||a.closest('div');var date='';if(li){var m=(li.innerText||'').match(/\\d{4}[-:]\\d{2}[-:]\\d{2}/);if(m)date=m[0];}items.push({title:t.slice(0,80),href:(a.href||'').slice(0,100),date:date});}});return JSON.stringify({total:total,count:items.length,items:items.slice(0,10)});})()" + }, + "session": "ccgp-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\ccgp-extract.json" --max-time 40 +``` + +### 4. Deep extraction from detail pages (optional) + +Navigate to each announcement's detail page and extract structured fields: + +```json +{ + "action": "navigate", + "args": { "url": "{announcement-detail-URL}" }, + "session": "ccgp-query" +} +``` + +Wait 5 seconds, then extract: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var txt=document.body.innerText||'';var lines=txt.split('\\n').map(function(s){return s.trim();}).filter(function(s){return s.length>0;});var fields={};for(var i=0;i 10, change `page_index=2` in the URL and repeat steps 2-3. Keep ≥5-second intervals. + +### 7. Close the session + +```json +{ + "action": "close_session", + "session": "ccgp-query" +} +``` + +## Known Limitations + +- **Default time window is about one week**: results may be 0 — add `start_time` and `end_time` to the URL (e.g. `start_time=2026:01:01&end_time=2026:08:31`) or click the page's time filter +- **Title-keyword search**: matching happens on announcement titles, not a supplier dimension — full legal names rarely hit; use the short name +- **Polite pacing**: even browser sessions should keep ≥5 s between requests; do not hammer pagination +- **HTML coupling**: redesigns may break selectors — if extraction is empty, fall back to reading `document.body.innerText` + +## Troubleshooting + +| Problem | Cause | Fix | +|---|---|---| +| navigate fails | daemon down / extension disconnected | restart via `kimi-webbridge.exe start` | +| "频繁访问" (frequent-access) | IP throttling | browser sessions usually avoid it; wait 60 s and retry | +| Empty extraction | 0 results / selectors broken | check the keyword; fall back to `evaluate` reading `body.innerText` | +| Empty detail fields | async content not loaded | retry after 5 s | diff --git a/skills/ccgp-gov-procurement/SKILL.zh-CN.md b/skills/ccgp-gov-procurement/SKILL.zh-CN.md new file mode 100644 index 0000000..1f4385f --- /dev/null +++ b/skills/ccgp-gov-procurement/SKILL.zh-CN.md @@ -0,0 +1,153 @@ +# 中国政府采购网招标公告查询 + +## L0 + +输入企业名称(建议用简称而非全名,如"华为"而非"华为技术有限公司"),通过 Kimi WebBridge 浏览器自动化搜索政府采购网,返回结构化招标公告列表。 + +## L1 概述 + +- **数据源**:中国政府采购网搜索系统(`search.ccgp.gov.cn`) +- **认证**:无(公开搜索) +- **调用方式**:Kimi WebBridge 浏览器自动化(navigate + evaluate) +- **前置条件**:Kimi WebBridge daemon 运行中(`127.0.0.1:10086`)+ 浏览器扩展已连接 +- **核心优势**:浏览器会话天然规避 curl 直连的 IP 限流 + +## L2 操作步骤 + +### 1. 检查 WebBridge daemon + +```bash +curl -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + -d '{"action":"list_tabs","session":"ccgp-query"}' --max-time 10 +``` + +若连接失败,启动 daemon: + +```bash +~/.kimi-webbridge/bin/kimi-webbridge.exe start +``` + +### 2. 导航搜索结果页 + +**Windows 方式**(JSON 写入临时文件避免编码问题): + +写入 `C:\tmp\ccgp-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://search.ccgp.gov.cn/bxsearch?searchtype=1&page_index=1&bidSort=0&pinMu=0&bidType=0&dbselect=bidx&kw={企业简称URL编码}", + "newTab": true, + "group_title": "政府采购网查询" + }, + "session": "ccgp-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\ccgp-nav.json" --max-time 30 +``` + +等待 5 秒后继续。 + +### 3. 提取公告列表 + +写入 `C:\tmp\ccgp-extract.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var txt=document.body.innerText||'';var total=(txt.match(/共找到\\s*(\\d+)\\s*条/)||[])[1]||'?';var items=[];document.querySelectorAll('a').forEach(function(a){var t=(a.innerText||'').replace(/\\s+/g,' ').trim();if(t.includes('{企业名称关键字}')&&t.length>10){var li=a.closest('li')||a.closest('div');var date='';if(li){var m=(li.innerText||'').match(/\\d{4}[-:]\\d{2}[-:]\\d{2}/);if(m)date=m[0];}items.push({title:t.slice(0,80),href:(a.href||'').slice(0,100),date:date});}});return JSON.stringify({total:total,count:items.length,items:items.slice(0,10)});})()" + }, + "session": "ccgp-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\ccgp-extract.json" --max-time 40 +``` + +### 4. 深度提取详情页(可选) + +对列表中每条公告,导航到详情页并提取结构化字段: + +```json +{ + "action": "navigate", + "args": { "url": "{公告详情URL}" }, + "session": "ccgp-query" +} +``` + +等待 5 秒后提取: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var txt=document.body.innerText||'';var lines=txt.split('\\n').map(function(s){return s.trim();}).filter(function(s){return s.length>0;});var fields={};for(var i=0;i 10,修改 URL 中 `page_index=2` 重复步骤 2-3。保持 ≥5 秒间隔。 + +### 7. 关闭会话 + +```json +{ + "action": "close_session", + "session": "ccgp-query" +} +``` + +## 已知限制 + +- **默认时间范围仅近一周**:搜索结果可能为 0——需在 URL 中加 `start_time` 和 `end_time` 参数放宽(如 `start_time=2026:01:01&end_time=2026:08:31`),或点击页面"近半年"筛选 +- **标题检索模式**:搜索匹配公告标题中的关键词,非供应商维度——企业全名命中率低,建议用简称(如"华为"而非"华为技术有限公司") +- **礼貌间隔**:浏览器会话虽规避了 curl 限流,但仍应保持 ≥5 秒/次的间隔,不要高频翻页 +- **HTML 结构依赖**:页面改版可能导致选择器失效——若提取为空,改用 `document.body.innerText` 全文读取 + +## 故障排查 + +| 问题 | 原因 | 处理 | +|---|---|---| +| navigate 失败 | daemon 未运行 / 扩展断开 | `kimi-webbridge.exe start` 重启 daemon | +| "频繁访问" | IP 限流 | 浏览器会话一般不触发;若触发等 60 秒重试 | +| 提取列表为空 | 搜索结果为 0 / 选择器失效 | 检查 keyword 是否正确;改用 `evaluate` 读 `body.innerText` | +| 详情页字段为空 | 页面异步加载未完成 | 等 5 秒后重试提取 | diff --git a/skills/ccgp-gov-procurement/catalog-metadata.v1.json b/skills/ccgp-gov-procurement/catalog-metadata.v1.json new file mode 100644 index 0000000..9980125 --- /dev/null +++ b/skills/ccgp-gov-procurement/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "ccgp-gov-procurement" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "政府采购网招标查询", + "summary": "输入企业名称(建议简称),返回采购公告列表与详情字段", + "description": "中国政府采购网招标公告查询——输入企业名称(或简称),搜索该企业参与的采购公告,返回公告列表(标题/链接/日期)并可深度提取详情字段(项目编号/采购人/代理机构/更正内容/联系人)。Use when 用户提到\"查招投标\"、\"政府采购\"、\"采购公告\"、\"中标公告\"、\"招标信息\"、\"ccgp\"、\"企业中标\"。" + }, + "en-US": { + "name": "CCGP Procurement Search", + "summary": "Search China Government Procurement announcements by company name", + "description": "China Government Procurement (ccgp.gov.cn) announcement search — input a company name (short name recommended) and return procurement announcements (title / link / date), with optional deep extraction of detail fields (project number / purchaser / agency / corrections / contacts). Use when the user asks about tenders, procurement announcements, winning bids, or ccgp." + } + }, + "category": "business", + "tags": [ + "due-diligence", + "procurement", + "government", + "bidding" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "medium" + } +} diff --git a/skills/cnipa-patent-search/SKILL.md b/skills/cnipa-patent-search/SKILL.md new file mode 100644 index 0000000..8a3e016 --- /dev/null +++ b/skills/cnipa-patent-search/SKILL.md @@ -0,0 +1,228 @@ +--- +name: cnipa-patent-search +description: >- + 国家知识产权局专利检索——输入企业名称(作为申请人),返回专利列表(申请号/申请日/发明名称/专利类型/专利状态/主分类号/申请人/发明人/公开号/公开日/代理机构)。Use when 用户提到"查专利"、"知识产权"、"专利检索"、"专利申请"、"cnipa"、"pss-system"、"发明"、"实用新型"、"外观设计"、"专利状态"。 +version: 1.0.0 +type: procedural +risk_level: medium +status: enabled +tags: + - due-diligence + - patent + - cnipa + - intellectual-property +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 知识产权局专利检索 + short_desc: 登录态检索 pss-system,返回企业专利列表(申请号/类型/状态等) + description: >- + 国家知识产权局专利检索——输入企业名称(作为申请人),返回专利列表(申请号/申请日/发明名称/专利类型/专利状态/主分类号/申请人/发明人/公开号/公开日/代理机构)。Use when 用户提到"查专利"、"知识产权"、"专利检索"、"专利申请"、"cnipa"、"pss-system"、"发明"、"实用新型"、"外观设计"、"专利状态"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:08c8cb6ca63c6dd9 + translated_by: human + en-US: + name: CNIPA Patent Search + short_desc: Logged-in pss-system patent search by applicant company name + description: >- + CNIPA patent search — input a company name (as applicant) and return a patent list (application number / date / title / type / status / main class / applicant / inventors / publication). Use when the user asks about patents, intellectual property, patent applications, cnipa, pss-system, inventions, utility models, or designs. + body: ./SKILL.md + source_hash: sha256:08c8cb6ca63c6dd9 + translated_by: human +market: + icon: >- + + category: business + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# CNIPA Patent Search + +## L0: One-Sentence Summary + +Input a company name, drive the CNIPA pss-system patent search via Kimi WebBridge browser automation, and return a structured patent list. + +## L1: Overview + +- **Data source**: CNIPA Patent Search and Analysis System (`pss-system.cponline.cnipa.gov.cn`) +- **Auth**: logged-in account (**registration required** — anonymous search redirects to login) +- **Invocation**: Kimi WebBridge browser automation (navigate + evaluate + CDP insertText) +- **Prerequisites**: + - Kimi WebBridge daemon running + - the user has **logged into pss-system** in the browser (login persists; log in once and reuse) + +## Account Registration + +pss-system requires real-name registration (phone + SMS): + +1. Open `https://pss-system.cponline.cnipa.gov.cn/` in the browser +2. Click "注册" and complete real-name registration +3. Log in once — the browser keeps the session for later automation + +## L2: Procedure + +### 1. Check the WebBridge daemon + +```bash +~/.kimi-webbridge/bin/kimi-webbridge.exe status +``` + +If down or disconnected, start it: `kimi-webbridge.exe start`. + +### 2. Navigate to pss-system + +Write `C:\tmp\cnipa-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://pss-system.cponline.cnipa.gov.cn/", + "newTab": true, + "group_title": "专利检索" + }, + "session": "cnipa-patent" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cnipa-nav.json" --max-time 30 +``` + +Wait 5 seconds. + +### 3. Confirm login, accept the disclaimer, enter search + +Write `C:\tmp\cnipa-agree.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(async function(){var txt=document.body.innerText||'';var hasLogout=txt.includes('退出');if(txt.includes('免责声明')){var btns=document.querySelectorAll('button.el-button--primary');for(var b of btns){if((b.innerText||'').replace(/\\s+/g,'')==='同意'){b.click();break;}}await new Promise(function(r){setTimeout(r,4000);});}txt=document.body.innerText||'';return JSON.stringify({url:location.href.slice(0,80),isSearch:txt.includes('常规检索'),inputs:document.querySelectorAll('input').length,hasLogout:hasLogout});})()" + }, + "session": "cnipa-patent" +} +``` + +**Login check**: if `hasLogout=false`, the user must log into pss-system in the browser first. + +### 4. Focus the search box + CDP input + +Write `C:\tmp\cnipa-focus.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){for(var i of document.querySelectorAll('input')){if((i.placeholder||'').includes('请输入关键词')){i.value='';i.dispatchEvent(new Event('input',{bubbles:true}));i.focus();return 'focused';}}return 'not-found';})()" + }, + "session": "cnipa-patent" +} +``` + +Then write `C:\tmp\cnipa-insert.json` (CDP real input, Vue-compatible): + +```json +{ + "action": "cdp", + "args": { + "method": "Input.insertText", + "params": { "text": "{company name}" } + }, + "session": "cnipa-patent" +} +``` + +### 5. Click search + wait for results + +Write `C:\tmp\cnipa-click.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(async function(){var clicked=false;for(var el of document.querySelectorAll('div.btn')){if((el.innerText||'').replace(/\\s+/g,'')==='检索'){el.click();clicked=true;break;}}await new Promise(function(r){setTimeout(r,8000);});var tables=document.querySelectorAll('table').length;var rows=document.querySelectorAll('table tr').length;var hits=(document.body.innerText.match(/共[\\d,]+[条篇]/)||[])[0]||'';return JSON.stringify({clicked:clicked,url:location.href.slice(0,80),tables:tables,rows:rows,hits:hits});})()" + }, + "session": "cnipa-patent" +} +``` + +### 6. Extract the result table + +Write `C:\tmp\cnipa-table.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var table=document.querySelector('table');if(!table)return JSON.stringify({err:'no-table'});var headers=[];table.querySelectorAll('thead th').forEach(function(th){headers.push((th.innerText||'').trim())});var rows=[];table.querySelectorAll('tbody tr').forEach(function(tr){var cells=[];tr.querySelectorAll('td').forEach(function(td){cells.push((td.innerText||'').trim().slice(0,60))});rows.push(cells)});return JSON.stringify({headers:headers,rowCount:rows.length,rows:rows});})()" + }, + "session": "cnipa-patent" +} +``` + +### 7. Normalized mapping + +```json +{ + "query_status": "success", + "source": "cnipa", + "company_name": "{company name}", + "total_found": 1, + "patents": [ + { + "patent_number": "202310104843.5", + "application_date": "2023.01.16", + "patent_name": "一种通信方法及装置", + "patent_type": "发明", + "patent_status": "实质审查的生效", + "main_class_code": "H04W72/54", + "applicant": "华为技术有限公司", + "applicant_address": "广东省深圳市", + "publication_number": "CN117834529A", + "publication_date": "2024.04.05" + } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 8. Close the session + +```json +{ + "action": "close_session", + "session": "cnipa-patent" +} +``` + +## Known Limitations + +- **Login required**: anonymous searches redirect to login or silently fail (unstable behavior); logged-in sessions return results reliably +- **Session persistence**: browser cookies keep the login valid for a long time, but re-login may be needed after long idle periods +- **Vue compatibility**: real input must go through CDP `Input.insertText` (not DOM setters), otherwise the Vue autocomplete ignores the text +- **Pagination**: when results exceed 10, click the pager and extract each page + +## Troubleshooting + +| Problem | Cause | Fix | +|---|---|---| +| Search click redirects to login | not logged in | log into pss-system in the browser | +| Search click does nothing | Vue event not triggered | confirm CDP insertText was used; check the login state | +| Table empty | async results loading | retry extraction after 8 s | +| Stuck on the disclaimer | agree button not clicked | re-run the evaluate that clicks 同意 | diff --git a/skills/cnipa-patent-search/SKILL.zh-CN.md b/skills/cnipa-patent-search/SKILL.zh-CN.md new file mode 100644 index 0000000..fb2ba7c --- /dev/null +++ b/skills/cnipa-patent-search/SKILL.zh-CN.md @@ -0,0 +1,178 @@ +# 国家知识产权局专利检索 + +## L0 + +输入企业名称,通过 Kimi WebBridge 浏览器自动化操作 pss-system 专利检索系统,返回结构化专利列表。 + +## L1 概述 + +- **数据源**:国家知识产权局专利检索及分析系统(`pss-system.cponline.cnipa.gov.cn`) +- **认证**:账号登录态(**必须先注册登录**——匿名检索会跳转登录页) +- **调用方式**:Kimi WebBridge 浏览器自动化(navigate + evaluate + CDP insertText) +- **前置条件**: + - Kimi WebBridge daemon 运行中 + - 用户已在浏览器中**登录 pss-system 账号**(登录态长期有效,登录一次即可复用) + +## 账号注册 + +pss-system 需实名注册(手机号 + 短信验证): + +1. 浏览器访问 `https://pss-system.cponline.cnipa.gov.cn/` +2. 点击"注册"完成实名注册 +3. 登录一次——登录态由浏览器保存,后续自动化复用 + +## L2 操作步骤 + +### 1. 检查 WebBridge daemon + +```bash +~/.kimi-webbridge/bin/kimi-webbridge.exe status +``` + +若 daemon 未运行或扩展断开,启动:`kimi-webbridge.exe start`。 + +### 2. 导航 pss-system + +写入 `C:\tmp\cnipa-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://pss-system.cponline.cnipa.gov.cn/", + "newTab": true, + "group_title": "专利检索" + }, + "session": "cnipa-patent" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cnipa-nav.json" --max-time 30 +``` + +等待 5 秒。 + +### 3. 确认登录态 + 同意声明 + 进入检索页 + +写入 `C:\tmp\cnipa-agree.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(async function(){var txt=document.body.innerText||'';var hasLogout=txt.includes('退出');if(txt.includes('免责声明')){var btns=document.querySelectorAll('button.el-button--primary');for(var b of btns){if((b.innerText||'').replace(/\\s+/g,'')==='同意'){b.click();break;}}await new Promise(function(r){setTimeout(r,4000);});}txt=document.body.innerText||'';return JSON.stringify({url:location.href.slice(0,80),isSearch:txt.includes('常规检索'),inputs:document.querySelectorAll('input').length,hasLogout:hasLogout});})()" + }, + "session": "cnipa-patent" +} +``` + +**登录态判断**:若 `hasLogout=false`,说明未登录——需用户在浏览器中登录 pss-system 后重试。 + +### 4. 聚焦检索框 + CDP 真实输入 + +写入 `C:\tmp\cnipa-focus.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){for(var i of document.querySelectorAll('input')){if((i.placeholder||'').includes('请输入关键词')){i.value='';i.dispatchEvent(new Event('input',{bubbles:true}));i.focus();return 'focused';}}return 'not-found';})()" + }, + "session": "cnipa-patent" +} +``` + +执行后,写入 `C:\tmp\cnipa-insert.json`(CDP 真实输入,Vue 组件兼容): + +```json +{ + "action": "cdp", + "args": { + "method": "Input.insertText", + "params": { "text": "{企业名称}" } + }, + "session": "cnipa-patent" +} +``` + +### 5. 点击检索 + 等待结果 + +写入 `C:\tmp\cnipa-click.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(async function(){var clicked=false;for(var el of document.querySelectorAll('div.btn')){if((el.innerText||'').replace(/\\s+/g,'')==='检索'){el.click();clicked=true;break;}}await new Promise(function(r){setTimeout(r,8000);});var tables=document.querySelectorAll('table').length;var rows=document.querySelectorAll('table tr').length;var hits=(document.body.innerText.match(/共[\\d,]+[条篇]/)||[])[0]||'';return JSON.stringify({clicked:clicked,url:location.href.slice(0,80),tables:tables,rows:rows,hits:hits});})()" + }, + "session": "cnipa-patent" +} +``` + +### 6. 提取表格数据 + +写入 `C:\tmp\cnipa-table.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var table=document.querySelector('table');if(!table)return JSON.stringify({err:'no-table'});var headers=[];table.querySelectorAll('thead th').forEach(function(th){headers.push((th.innerText||'').trim())});var rows=[];table.querySelectorAll('tbody tr').forEach(function(tr){var cells=[];tr.querySelectorAll('td').forEach(function(td){cells.push((td.innerText||'').trim().slice(0,60))});rows.push(cells)});return JSON.stringify({headers:headers,rowCount:rows.length,rows:rows});})()" + }, + "session": "cnipa-patent" +} +``` + +### 7. 标准化映射 + +```json +{ + "query_status": "success", + "source": "cnipa", + "company_name": "{企业名称}", + "total_found": 1, + "patents": [ + { + "patent_number": "202310104843.5", + "application_date": "2023.01.16", + "patent_name": "一种通信方法及装置", + "patent_type": "发明", + "patent_status": "实质审查的生效", + "main_class_code": "H04W72/54", + "applicant": "华为技术有限公司", + "applicant_address": "广东省深圳市", + "publication_number": "CN117834529A", + "publication_date": "2024.04.05" + } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 8. 关闭会话 + +```json +{ + "action": "close_session", + "session": "cnipa-patent" +} +``` + +## 已知限制 + +- **必须登录态**:匿名状态下点击检索会跳转 login 页或静默无响应(行为不稳定);登录态下检索正常返回结果 +- **登录态会话保持**:浏览器登录 pss-system 后 cookie 长期有效,WebBridge 会话可复用——但长时间未操作后可能需要重新登录 +- **Vue 组件兼容性**:必须用 CDP `Input.insertText` 真实输入(非 DOM setter),否则 Vue 下拉联想组件不接收文本 +- **翻页**:结果超过 10 条时,点击页面分页按钮翻页,提取每页表格数据 + +## 故障排查 + +| 问题 | 原因 | 处理 | +|---|---|---| +| 点击检索后 URL 跳转到 login | 未登录 | 用户在浏览器中登录 pss-system | +| 点击检索后无响应 | Vue 事件未触发 | 确认用 CDP insertText 输入了检索词;检查登录态是否有效 | +| 表格为空 | 结果异步加载中 | 等待 8 秒后重新提取表格 | +| "免责声明"页卡住 | 同意按钮未点击成功 | 重新执行 evaluate 点击同意按钮 | diff --git a/skills/cnipa-patent-search/catalog-metadata.v1.json b/skills/cnipa-patent-search/catalog-metadata.v1.json new file mode 100644 index 0000000..9578f2d --- /dev/null +++ b/skills/cnipa-patent-search/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "cnipa-patent-search" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "知识产权局专利检索", + "summary": "登录态检索 pss-system,返回企业专利列表(申请号/类型/状态等)", + "description": "国家知识产权局专利检索——输入企业名称(作为申请人),返回专利列表(申请号/申请日/发明名称/专利类型/专利状态/主分类号/申请人/发明人/公开号/公开日/代理机构)。Use when 用户提到\"查专利\"、\"知识产权\"、\"专利检索\"、\"专利申请\"、\"cnipa\"、\"pss-system\"、\"发明\"、\"实用新型\"、\"外观设计\"、\"专利状态\"。" + }, + "en-US": { + "name": "CNIPA Patent Search", + "summary": "Logged-in pss-system patent search by applicant company name", + "description": "CNIPA patent search — input a company name (as applicant) and return a patent list (application number / date / title / type / status / main class / applicant / inventors / publication). Use when the user asks about patents, intellectual property, patent applications, cnipa, pss-system, inventions, utility models, or designs." + } + }, + "category": "business", + "tags": [ + "due-diligence", + "patent", + "cnipa", + "intellectual-property" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "medium" + } +} diff --git a/skills/creditchina-query/SKILL.md b/skills/creditchina-query/SKILL.md new file mode 100644 index 0000000..266c247 --- /dev/null +++ b/skills/creditchina-query/SKILL.md @@ -0,0 +1,279 @@ +--- +name: creditchina-query +description: >- + 信用中国企业信用信息查询——输入企业名称,自动通过图形验证码(ddddocr 本地 OCR 100ms),返回信用信息(行政处罚/失信被执行/行政许可)。Use when 用户提到"查信用"、"信用中国"、"行政处罚"、"失信企业"、"企业信用"、"失信被执行人"、"行政许可"、"creditchina"。 +version: 1.0.0 +type: procedural +risk_level: high +status: enabled +tags: + - due-diligence + - credit + - creditchina + - compliance +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 信用中国查询 + short_desc: 浏览器自动化 + ddddocr 本地过验证码,返回企业信用信息 + description: >- + 信用中国企业信用信息查询——输入企业名称,自动通过图形验证码(ddddocr 本地 OCR 100ms),返回信用信息(行政处罚/失信被执行/行政许可)。Use when 用户提到"查信用"、"信用中国"、"行政处罚"、"失信企业"、"企业信用"、"失信被执行人"、"行政许可"、"creditchina"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:ae28ca7a89d99438 + translated_by: human + en-US: + name: Credit China Query + short_desc: Browser automation with local ddddocr captcha solving for enterprise credit records + description: >- + Credit China (creditchina.gov.cn) enterprise credit query — input a company name, automatically pass the graphic captcha (ddddocr local OCR, ~100 ms), and return credit records (administrative penalties / dishonest debtors / administrative licenses). Use when the user asks about enterprise credit, administrative penalties, dishonest-debtor lists, or creditchina. + body: ./SKILL.md + source_hash: sha256:ae28ca7a89d99438 + translated_by: human +market: + icon: >- + + category: business + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# Credit China Query + +## L0: One-Sentence Summary + +Input a company name, pass the graphic captcha automatically via Kimi WebBridge plus ddddocr local OCR, and return the enterprise's credit records. + +## L1: Overview + +- **Data source**: Credit China (`creditchina.gov.cn`, guided by NDRC) +- **Auth**: graphic captcha (solved locally by ddddocr, ~100 ms) +- **Invocation**: Kimi WebBridge + CDP screenshot + ddddocr Python OCR +- **Prerequisites**: + - Kimi WebBridge daemon running + - Python with `ddddocr` (`pip install ddddocr`) + - Python with `Pillow` (`pip install pillow`) + +## L2: Procedure + +### 1. Navigate to the search page + +Write `C:\tmp\cc-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://www.creditchina.gov.cn/xinyongxinxi/?keyword={company-name-URL-encoded}&scenesVal=default&tableName=credit_xyzx_tyshxydm", + "newTab": true, + "group_title": "信用中国查询" + }, + "session": "creditchina-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cc-nav.json" --max-time 30 +``` + +Wait 6 seconds. + +### 2. Confirm the captcha overlay + +Write `C:\tmp\cc-check.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var v=document.getElementById('vcode');var i=document.getElementById('vcodeimg');return JSON.stringify({vcode:v?v.getBoundingClientRect().width>0:false,vimg:i?i.getBoundingClientRect().width>0:false});})()" + }, + "session": "creditchina-query" +} +``` + +If `vcode=true` and `vimg=true`, the captcha overlay is visible — continue. + +### 3. Get the captcha image coordinates + +Write `C:\tmp\cc-coord.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var img=document.getElementById('vcodeimg');if(!img)return 'no-img';var r=img.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x),y:Math.round(r.y),w:Math.round(r.width),h:Math.round(r.height),dpr:window.devicePixelRatio});})()" + }, + "session": "creditchina-query" +} +``` + +Record `x` / `y` / `w` / `h`. + +### 4. CDP screenshot of the captcha region + +> **Note**: the WebBridge screenshot action fails intermittently on this site (HTTP 000/400) — **always use CDP `Page.captureScreenshot` with the clip parameter**. + +Write `C:\tmp\cc-shot.json` (replace `{x}` / `{y}` / `{w}` / `{h}`): + +```json +{ + "action": "cdp", + "args": { + "method": "Page.captureScreenshot", + "params": { + "format": "png", + "clip": { "x": {x}, "y": {y}, "width": {w}, "height": {h}, "scale": 1 } + } + }, + "session": "creditchina-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cc-shot.json" --max-time 40 -o "C:/tmp/cc-cdp-resp.json" +``` + +Decode the base64 payload and save the image: + +```python +import json, base64 +d = json.load(open(r'C:\tmp\cc-cdp-resp.json', encoding='utf-8')) +b64 = d.get('data', {}).get('data', '') +open(r'C:\tmp\cc-captcha.png', 'wb').write(base64.b64decode(b64)) +``` + +### 5. ddddocr recognition (~100 ms) + +```python +import ddddocr, sys, time +sys.stdout.reconfigure(encoding='utf-8') +ocr = ddddocr.DdddOcr(show_ad=False) +t0 = time.time() +with open(r'C:\tmp\cc-captcha.png', 'rb') as f: + code = ocr.classification(f.read()) +print(f'验证码: {code} ({(time.time()-t0)*1000:.0f}ms)') +open(r'C:\tmp\cc-code.txt', 'w').write(code) +``` + +### 6. Fill and submit the captcha + +Write `C:\tmp\cc-submit.json` (replace `{code}`): + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var inp=document.getElementById('vcode');if(!inp)return 'no-input';var s=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,'value').set;s.call(inp,'{code}');inp.dispatchEvent(new Event('input',{bubbles:true}));inp.dispatchEvent(new Event('change',{bubbles:true}));for(var el of document.querySelectorAll('button, a, input[type=button]')){if((el.innerText||el.value||'').trim()==='验证'){el.click();break;}}return 'submitted';})()" + }, + "session": "creditchina-query" +} +``` + +Wait 5 seconds. + +### 7. Check the verification result + +Write `C:\tmp\cc-result.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var t=document.body.innerText||'';if(t.includes('验证码错误'))return '验证码错误';if(t.includes('失效'))return '验证码已失效';return JSON.stringify({hasResult:t.includes('共')||t.includes('条'),textSample:t.slice(0,500)});})()" + }, + "session": "creditchina-query" +} +``` + +**Three outcomes**: + +- `"验证码错误"` / `"验证码已失效"` → retry from step 3 (click 换一张 to refresh) +- `hasResult=true` with data → success, go to step 8 +- `textSample` contains "很抱歉,没有找到您搜索的数据" → captcha passed but the keyword has no match — retry with the full name or a short name + +### 8. Read the search results + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){return document.body.innerText.slice(0,1500);})()" + }, + "session": "creditchina-query" +} +``` + +### 9. Normalized mapping + +```json +{ + "query_status": "success", + "source": "creditchina", + "company_name": "{company name}", + "captcha_solved": true, + "search_result": "有结果 | 无匹配", + "credit_info": [ + { + "event_type": "行政处罚 | 行政许可 | 失信被执行 | 守信激励", + "event_title": "...", + "event_date": "...", + "source_url": "...", + "summary": "..." + } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 10. Close the session + +```json +{ + "action": "close_session", + "session": "creditchina-query" +} +``` + +## Retry Strategy + +On captcha failure (wrong/expired), retry automatically up to 3 rounds: + +1. Click 换一张 to refresh the captcha via `evaluate` +2. Wait 2 seconds for the new image +3. Repeat steps 3-6 (screenshot → recognize → submit) + +After 3 failed rounds: ask the user to solve the captcha manually once in the browser, then resume — once verified, the browser remembers the state and subsequent queries skip the captcha. + +## Known Limitations + +- **Very short captcha TTL**: screenshot-to-submit must stay under ~15 s — **use ddddocr locally (~100 ms); cloud OCR (10-30 s round trips) always times out** +- **CDP screenshot required**: the WebBridge screenshot action fails intermittently here; use CDP `Page.captureScreenshot` with clip +- **Verification caching**: once passed, subsequent searches (navigating to new keyword URLs) return results without another captcha +- **CORS**: `fetch+FileReader` or `canvas.toDataURL` cannot capture the image (cross-origin taint) — CDP screenshots only +- **Keyword advice**: exact full names may return "no data" (the database only covers entities with credit records) — try the full name first, then the short name + +## Troubleshooting + +| Problem | Cause | Fix | +|---|---|---| +| 412 on direct HTTP | WAF blocks non-browser calls | always go through WebBridge | +| Captcha overlay missing | keyword param not triggered | check the keyword in the URL | +| Empty CDP screenshot | wrong coordinates / scrolled page | re-read `vcodeimg` bounding rect | +| ddddocr returns empty | broken image / recognition failure | refresh and retry; confirm screenshot bytes > 3000 | +| Wrong/expired captcha | misread / timeout | refresh (up to 3 rounds); fall back to manual | +| "没有找到您搜索的数据" | no credit records / keyword mismatch | retry with the short name | diff --git a/skills/creditchina-query/SKILL.zh-CN.md b/skills/creditchina-query/SKILL.zh-CN.md new file mode 100644 index 0000000..3856226 --- /dev/null +++ b/skills/creditchina-query/SKILL.zh-CN.md @@ -0,0 +1,229 @@ +# 信用中国查询 + +## L0 + +输入企业名称,通过 Kimi WebBridge 浏览器自动化 + ddddocr 本地 OCR 自动过图形验证码,返回企业信用信息。 + +## L1 概述 + +- **数据源**:信用中国(`creditchina.gov.cn`,国家发改委指导) +- **认证**:图形验证码(ddddocr 本地 OCR 自动识别,~100ms) +- **调用方式**:Kimi WebBridge + CDP 截图 + ddddocr Python OCR +- **前置条件**: + - Kimi WebBridge daemon 运行中 + - Python 已安装 `ddddocr`(`pip install ddddocr`) + - Python 已安装 `Pillow`(`pip install pillow`) + +## L2 操作步骤 + +### 1. 导航搜索页 + +写入 `C:\tmp\cc-nav.json`: + +```json +{ + "action": "navigate", + "args": { + "url": "https://www.creditchina.gov.cn/xinyongxinxi/?keyword={企业名称URL编码}&scenesVal=default&tableName=credit_xyzx_tyshxydm", + "newTab": true, + "group_title": "信用中国查询" + }, + "session": "creditchina-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cc-nav.json" --max-time 30 +``` + +等待 6 秒。 + +### 2. 确认验证码弹层 + +写入 `C:\tmp\cc-check.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var v=document.getElementById('vcode');var i=document.getElementById('vcodeimg');return JSON.stringify({vcode:v?v.getBoundingClientRect().width>0:false,vimg:i?i.getBoundingClientRect().width>0:false});})()" + }, + "session": "creditchina-query" +} +``` + +若 `vcode=true` 且 `vimg=true`,验证码弹层已出现,继续下一步。 + +### 3. 获取验证码图坐标 + +写入 `C:\tmp\cc-coord.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var img=document.getElementById('vcodeimg');if(!img)return 'no-img';var r=img.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x),y:Math.round(r.y),w:Math.round(r.width),h:Math.round(r.height),dpr:window.devicePixelRatio});})()" + }, + "session": "creditchina-query" +} +``` + +记录返回的 `x` / `y` / `w` / `h`。 + +### 4. CDP 截图验证码区域 + +> **注意**:WebBridge 的 screenshot 工具对此页面存在间歇性失败(HTTP 000/400),**必须用 CDP `Page.captureScreenshot` 的 clip 参数**。 + +写入 `C:\tmp\cc-shot.json`(替换 `{x}` / `{y}` / `{w}` / `{h}` 为上一步返回值): + +```json +{ + "action": "cdp", + "args": { + "method": "Page.captureScreenshot", + "params": { + "format": "png", + "clip": { "x": {x}, "y": {y}, "width": {w}, "height": {h}, "scale": 1 } + } + }, + "session": "creditchina-query" +} +``` + +```bash +curl.exe -s -X POST "http://127.0.0.1:10086/command" \ + -H "Content-Type: application/json" \ + --data-binary "@C:\tmp\cc-shot.json" --max-time 40 -o "C:/tmp/cc-cdp-resp.json" +``` + +解码 base64 并保存为图片: + +```python +import json, base64 +d = json.load(open(r'C:\tmp\cc-cdp-resp.json', encoding='utf-8')) +b64 = d.get('data', {}).get('data', '') +open(r'C:\tmp\cc-captcha.png', 'wb').write(base64.b64decode(b64)) +``` + +### 5. ddddocr 识别(~100ms) + +```python +import ddddocr, sys, time +sys.stdout.reconfigure(encoding='utf-8') +ocr = ddddocr.DdddOcr(show_ad=False) +t0 = time.time() +with open(r'C:\tmp\cc-captcha.png', 'rb') as f: + code = ocr.classification(f.read()) +print(f'验证码: {code} ({(time.time()-t0)*1000:.0f}ms)') +open(r'C:\tmp\cc-code.txt', 'w').write(code) +``` + +### 6. 填入验证码 + 点击验证 + +写入 `C:\tmp\cc-submit.json`(替换 `{code}` 为识别结果): + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var inp=document.getElementById('vcode');if(!inp)return 'no-input';var s=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,'value').set;s.call(inp,'{code}');inp.dispatchEvent(new Event('input',{bubbles:true}));inp.dispatchEvent(new Event('change',{bubbles:true}));for(var el of document.querySelectorAll('button, a, input[type=button]')){if((el.innerText||el.value||'').trim()==='验证'){el.click();break;}}return 'submitted';})()" + }, + "session": "creditchina-query" +} +``` + +等待 5 秒。 + +### 7. 检查验证结果 + +写入 `C:\tmp\cc-result.json`: + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){var t=document.body.innerText||'';if(t.includes('验证码错误'))return '验证码错误';if(t.includes('失效'))return '验证码已失效';return JSON.stringify({hasResult:t.includes('共')||t.includes('条'),textSample:t.slice(0,500)});})()" + }, + "session": "creditchina-query" +} +``` + +**三种结果**: + +- `"验证码错误"` / `"验证码已失效"` → 返回步骤 3 重试(点"换一张"刷新验证码) +- `hasResult=true` 且返回搜索数据 → 成功,继续步骤 8 +- `textSample` 含"很抱歉,没有找到您搜索的数据" → 验证码已通过,但搜索词无匹配(非技术错误)——建议换企业全名或简称重试 + +### 8. 读取搜索结果 + +```json +{ + "action": "evaluate", + "args": { + "code": "(function(){return document.body.innerText.slice(0,1500);})()" + }, + "session": "creditchina-query" +} +``` + +### 9. 标准化映射 + +```json +{ + "query_status": "success", + "source": "creditchina", + "company_name": "{企业名称}", + "captcha_solved": true, + "search_result": "有结果 | 无匹配", + "credit_info": [ + { + "event_type": "行政处罚 | 行政许可 | 失信被执行 | 守信激励", + "event_title": "...", + "event_date": "...", + "source_url": "...", + "summary": "..." + } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 10. 关闭会话 + +```json +{ + "action": "close_session", + "session": "creditchina-query" +} +``` + +## 重试策略 + +验证码识别失败(错误/失效)时自动重试,最多 3 轮: + +1. 点击"换一张"刷新验证码:`evaluate` 点击文本含"换一张"的元素 +2. 等 2 秒(新图加载) +3. 重复步骤 3-6(重新截图→识别→提交) + +3 轮失败后:报告用户,请人工在浏览器中手动过一次验证码,然后智能体接管继续(验证通过后浏览器记住验证态,后续查询免验证码)。 + +## 已知限制 + +- **验证码时效极短**:从截图到提交需 <15 秒——**必须用 ddddocr 本地识别(~100ms),禁用云端 OCR(10~30 秒往返必超时)** +- **CDP 截图替代 screenshot**:WebBridge screenshot 工具对此页面间歇性失败(HTTP 000/400),必须用 CDP `Page.captureScreenshot` 的 clip 参数 +- **验证态缓存**:一次验证通过后,浏览器记住验证态——后续搜索(导航到新 keyword URL)不再需要验证码,直接返回结果 +- **CORS 限制**:不能通过 `fetch+FileReader` 或 `canvas.toDataURL` 取图(跨子域 tainted)——只能用 CDP 截图 +- **搜索词建议**:精确企业全名可能"没有找到您搜索的数据"(信用库只收录有信用记录的主体)——先试全名,无结果再试简称 + +## 故障排查 + +| 问题 | 原因 | 处理 | +|---|---|---| +| 412(直连被 WAF 拦截) | 未用浏览器 | 必须通过 WebBridge 浏览器访问 | +| 验证码弹层未出现 | keyword 参数未触发 | 检查 URL 中的 keyword 参数 | +| CDP 截图返回空 | 坐标错误 / 页面滚动 | 重新获取 vcodeimg 的 getBoundingClientRect | +| ddddocr 识别为空 | 图片损坏 / 识别失败 | 刷新验证码重试;确认 CDP 截图 bytes > 3000 | +| 验证码错误/失效 | 识别错 / 超时 | 点"换一张"重试(最多 3 轮);仍失败转人工 | +| "没有找到您搜索的数据" | 企业无信用记录 / 词不匹配 | 换简称重试;确认企业有信用记录 | diff --git a/skills/creditchina-query/catalog-metadata.v1.json b/skills/creditchina-query/catalog-metadata.v1.json new file mode 100644 index 0000000..170904f --- /dev/null +++ b/skills/creditchina-query/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "creditchina-query" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "信用中国查询", + "summary": "浏览器自动化 + ddddocr 本地过验证码,返回企业信用信息", + "description": "信用中国企业信用信息查询——输入企业名称,自动通过图形验证码(ddddocr 本地 OCR 100ms),返回信用信息(行政处罚/失信被执行/行政许可)。Use when 用户提到\"查信用\"、\"信用中国\"、\"行政处罚\"、\"失信企业\"、\"企业信用\"、\"失信被执行人\"、\"行政许可\"、\"creditchina\"。" + }, + "en-US": { + "name": "Credit China Query", + "summary": "Browser automation with local ddddocr captcha solving for enterprise credit records", + "description": "Credit China (creditchina.gov.cn) enterprise credit query — input a company name, automatically pass the graphic captcha (ddddocr local OCR, ~100 ms), and return credit records (administrative penalties / dishonest debtors / administrative licenses). Use when the user asks about enterprise credit, administrative penalties, dishonest-debtor lists, or creditchina." + } + }, + "category": "business", + "tags": [ + "due-diligence", + "credit", + "creditchina", + "compliance" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "high" + } +} diff --git a/skills/multi-source-sentiment/SKILL.md b/skills/multi-source-sentiment/SKILL.md new file mode 100644 index 0000000..5a36fc9 --- /dev/null +++ b/skills/multi-source-sentiment/SKILL.md @@ -0,0 +1,229 @@ +--- +name: multi-source-sentiment +description: >- + 企业尽调舆情采集——通过抖音指数、抖音精选、WebSearch 三大数据源采集企业舆情,分析负面风险(诉讼/处罚/质量/高管/劳资),输出尽调舆情报告。Use when 用户提到"查舆情"、"企业舆情"、"负面新闻"、"舆论风险"、"尽调舆情"、"企业口碑"、"舆情分析"、"网络口碑"。 +version: 1.0.0 +type: procedural +risk_level: medium +status: enabled +tags: + - due-diligence + - sentiment + - public-opinion + - douyin +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 企业尽调舆情采集 + short_desc: 抖音指数+抖音精选+WebSearch 三渠道采集,输出尽调舆情报告 + description: >- + 企业尽调舆情采集——通过抖音指数、抖音精选、WebSearch 三大数据源采集企业舆情,分析负面风险(诉讼/处罚/质量/高管/劳资),输出尽调舆情报告。Use when 用户提到"查舆情"、"企业舆情"、"负面新闻"、"舆论风险"、"尽调舆情"、"企业口碑"、"舆情分析"、"网络口碑"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:e102f3139e03fcd5 + translated_by: human + en-US: + name: Multi-Source Sentiment + short_desc: Due-diligence sentiment via Douyin Index, Douyin Featured, and WebSearch + description: >- + Due-diligence sentiment collection — gather enterprise public opinion via three channels (Douyin Index, Douyin Featured, WebSearch), analyze negative risks (litigation / penalties / quality / executives / labor), and output a due-diligence sentiment report. Use when the user asks about enterprise sentiment, negative news, reputation risk, or public opinion. + body: ./SKILL.md + source_hash: sha256:e102f3139e03fcd5 + translated_by: human +market: + icon: >- + + category: research + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# Multi-Source Sentiment (Due Diligence) + +## L0: One-Sentence Summary + +Input a company name, collect public opinion via Douyin Index (trend) + Douyin Featured (negative material) + WebSearch (web-wide news), and output a due-diligence sentiment report (negative-risk list / positive highlights / sentiment overview / overall judgment). + +## L1: Overview + +- **Purpose**: answer the core due-diligence questions — any negative publicity? litigation/penalty coverage? product-quality issues? executive misconduct? overall reputation? +- **Channel split**: + +| Channel | Due-diligence use | Collection | +|---|---|---| +| **Douyin Index** | Quantified heat trend (is something fermenting recently?) | Kimi WebBridge visiting Oceanengine Trends | +| **Douyin Featured** | Concrete negative material (complaint/expose videos) | Kimi WebBridge searching Douyin | +| **WebSearch** | Web-wide negative news / court notices / penalties / complaints | DesireCore built-in WebSearch | + +- **Prerequisites**: Kimi WebBridge daemon running (`127.0.0.1:10086`) + browser extension connected + +## L2: Procedure + +### Source 1: Douyin Index (heat trend) + +#### Access Method + +``` +URL: https://trendinsight.oceanengine.com/arithmetic-index/analysis/keyword?keyword={company-short-name}&appName=aweme +Method: Kimi WebBridge opens the URL and extracts page content +Note: URL-parameterized access avoids captchas. Do not type into the search box. +``` + +#### Keyword Strategy + +| Dimension | Keyword | +|---|---| +| Overall heat | `{short name}` | +| Negative heat | `{short name} 负面` | +| Complaint heat | `{short name} 投诉` | + +#### Interpretation + +- **Sudden spike** (MoM > 200%) → a negative event may be fermenting; investigate +- **Flat trend** → low reputation risk +- **Persistently high** → normal for famous companies; judge by content + +### Source 2: Douyin Featured (negative material) + +#### Access Method + +``` +URL: https://www.douyin.com/search/{company-short-name}?type=video +Method: Kimi WebBridge searches Douyin, extracts title / author / likes / comments +Note: search by short name (full names rarely hit); prioritize high-engagement videos. +``` + +#### Collected Fields + +Collected fields: video title (negative signals: complaint / rights-protection / exposure / quality / scam / runaway), likes & comments (reach = impact), author (personal vent vs media report vs competitor smear), publish date (recent vs historical). + +#### Signal Grading + +| Signals | Risk | +|---|---| +| 投诉 / 维权 / 欺骗 / 诈骗 / 跑路 | 🔴 high | +| 质量 / 召回 / 不合格 / 假货 | 🔴 high | +| 欠薪 / 辞退 / 仲裁 | 🟡 medium | +| 吐槽 / 差评 / 不满 | 🟡 medium | +| positive / awards / innovation | 🟢 positive | + +### Source 3: WebSearch (web-wide) + +#### Search Keyword Groups + +```python +# High priority (always) +search_queries_high = [ + "{company} 负面 OR 投诉 OR 维权 OR 欺骗 OR 跑路", + "{company} 起诉 OR 法院 OR 被告 OR 被执行 OR 失信", + "{company} 处罚 OR 违规 OR 罚款 OR 整改 OR 通报批评", +] + +# Medium priority (recommended) +search_queries_mid = [ + "{company} 质量 OR 召回 OR 不合格 OR 安全事故", + "{company} 老板 OR 法人 OR 总经理 丑闻 OR 被查 OR 被抓", + "{company} 欠薪 OR 辞退 OR 劳动仲裁 OR 工伤", +] + +# Low priority (positive control) +search_queries_low = [ + "{company} 获奖 OR 创新 OR 认定 OR 排名", +] +``` + +#### Collected Fields + +Collected fields: title / source site / date / summary / URL. **Note**: distinguish the company as **plaintiff** (enforcement, not a negative signal) vs **defendant** (negative signal). + +### Step 1: Run the three channels + +1. **WebSearch** first (highest information density): run high/medium/low query groups and collect results +2. **Douyin Index**: check the heat trend for signs of recent fermentation +3. **Douyin Featured**: search videos and filter by negative signal words + +### Step 2: LLM post-processing + +| Step | Description | +|---|---| +| Sentiment classification | tag each item positive / neutral / negative | +| Risk grading | negative → high (defendant / penalty / runaway / safety accident) / medium (complaints / quality gripes / labor) / low (generic bad reviews) | +| Event merging | merge duplicate coverage of one event (keep the earliest) | +| Plaintiff/defendant split | litigation where the company is plaintiff is **not** a negative risk | +| Recency | mark "recent" (≤3 months) vs "historical" | + +### Step 3: Output the report + +```json +{ + "query_status": "success", + "source": "multi-source-sentiment", + "company_name": "{company}", + "sentiment_overview": { + "overall_assessment": "正面 | 中性偏正 | 中性 | 中性偏负 | 负面 | 高风险", + "negative_ratio": "15%", + "neutral_ratio": "60%", + "positive_ratio": "25%", + "trend": "稳定 | 近期发酵 | 持续负面" + }, + "negative_risks": [ + { + "risk_type": "诉讼报道(被告) | 行政处罚 | 产品质量 | 高管负面 | 劳资纠纷 | 消费者投诉 | 经营异常", + "event_title": "……", + "event_date": "YYYY-MM-DD", + "recency": "近期 | 历史", + "source_url": "https://……", + "severity": "高 | 中 | 低", + "summary": "1-2 sentence summary" + } + ], + "controversies": [], + "positive_highlights": [], + "sentiment_summary": "3-5 sentence judgment: overall reputation, main negatives and severity, fermentation status, due-diligence advice", + "data_sources_used": ["websearch", "douyin-index", "douyin-featured"], + "collection_time": "ISO8601" +} +``` + +## Quality Standards + +- **Authenticity**: all content must come from actual collection (WebSearch results / Douyin pages); never fabricate +- **Traceability**: every negative risk carries a source_url +- **Plaintiff/defendant**: litigation where the company is plaintiff goes to "litigation updates", not negative risks +- **Recency**: every negative item is marked recent (≤3 months) or historical +- **No absolute conclusions**: sentiment is one auxiliary signal; the report must note it should be combined with business-registration, judicial, and financial data + +## Error Handling + +| Scenario | Handling | +|---|---| +| Douyin Index unreachable | skip; supplement with WebSearch + Featured; note "heat data missing" in the report | +| Douyin search requires login | skip; WebSearch `{company} 抖音 负面` instead | +| WebSearch returns nothing | mark "no negative found" — a positive signal | +| Too many negatives | keep the top 10 by severity; count the rest | + +## Known Limitations + +- **Not real-time**: depends on search-engine indexing and Douyin pages; hour-to-day latency (7×24 monitoring requires commercial sentiment APIs) +- **LLM-based sentiment**: no dedicated sentiment model; ~85-90% accuracy, edge cases may misjudge +- **Douyin coverage**: WeChat/Weibo/Xiaohongshu content is only covered indirectly via WebSearch +- **Full vs short name**: WebSearch uses the full name (precision), Douyin the short name (recall); results may differ + +## Troubleshooting + +| Problem | Cause | Fix | +|---|---|---| +| WebBridge daemon unreachable | daemon down | `~/.kimi-webbridge/bin/kimi-webbridge.exe start` | +| Trends page blank | JS not rendered | wait 5 s, then evaluate innerText | +| Douyin search empty | login required / name mismatch | skip; supplement via WebSearch | +| WebSearch results all positive | weak negative keywords | use concrete terms (e.g. "被处罚" instead of "处罚") | diff --git a/skills/multi-source-sentiment/SKILL.zh-CN.md b/skills/multi-source-sentiment/SKILL.zh-CN.md new file mode 100644 index 0000000..e8a230b --- /dev/null +++ b/skills/multi-source-sentiment/SKILL.zh-CN.md @@ -0,0 +1,193 @@ +# 企业尽调舆情采集 + +## L0 + +输入企业名称,通过抖音指数(热度趋势)+ 抖音精选(负面素材)+ WebSearch(全网新闻)三渠道采集舆情,输出尽调舆情报告(负面风险清单/正面亮点/情感概览/综合判断)。 + +## L1 概述 + +- **目的**:回答尽调核心问题——有没有负面舆情?有没有诉讼/处罚报道?产品质量有没有问题?高管有没有负面?舆论形象如何? +- **三渠道分工**: + +| 渠道 | 尽调用途 | 采集方式 | +|---|---|---| +| **抖音指数** | 舆论热度量化(时间序列,看是否近期发酵) | Kimi WebBridge 访问巨量算数 | +| **抖音精选** | 具体负面内容素材(投诉视频/维权曝光/质量吐槽) | Kimi WebBridge 搜索抖音 | +| **WebSearch** | 全网负面新闻/法院公告/监管处罚/消费者投诉 | DesireCore 内置 WebSearch | + +- **前置依赖**:Kimi WebBridge daemon 运行中(`127.0.0.1:10086`)+ 浏览器扩展已连接 + +## L2 详细操作 + +### 数据源一:抖音指数(企业名热度趋势) + +#### 访问方式 + +``` +URL: https://trendinsight.oceanengine.com/arithmetic-index/analysis/keyword?keyword={企业简称}&appName=aweme +方法: Kimi WebBridge 浏览器自动访问页面并提取内容 +注意: URL 参数化访问,不触发验证码。不要尝试在搜索框输入文字。 +``` + +#### 尽调关键词策略 + +| 尽调维度 | 搜索关键词 | +|---|---| +| 舆论整体热度 | `{企业简称}` | +| 负面热度 | `{企业简称} 负面` | +| 投诉热度 | `{企业简称} 投诉` | + +#### 尽调判断要点 + +- **热度骤升**:近期热度陡增(环比 >200%)→ 可能存在负面事件发酵,需重点排查 +- **热度平稳**:无异常波动 → 舆论风险较低 +- **长期高热**:知名企业的常态,需结合内容素材判断正负 + +### 数据源二:抖音精选(负面内容素材) + +#### 访问方式 + +``` +URL: https://www.douyin.com/search/{企业简称}?type=video +方法: Kimi WebBridge 搜索抖音,提取视频标题/作者/点赞数/评论数 +注意: 用企业简称搜索(全名命中率低);优先看点赞/评论高的视频(传播广=影响大)。 +``` + +#### 尽调采集字段 + +- 视频标题(判断是否负面:投诉/维权/曝光/质量/欺骗/跑路) +- 点赞数 / 评论数(传播广度 = 负面影响程度) +- 作者昵称(个人吐槽 vs 媒体报道 vs 竞品抹黑) +- 发布时间(近期 vs 历史) + +#### 负面视频筛选标准 + +| 信号词 | 风险等级 | +|---|---| +| 投诉 / 维权 / 欺骗 / 诈骗 / 跑路 | 🔴 高 | +| 质量 / 召回 / 不合格 / 假货 | 🔴 高 | +| 欠薪 / 辞退 / 仲裁 | 🟡 中 | +| 吐槽 / 差评 / 不满 | 🟡 中 | +| 正面宣传 / 获奖 / 创新 | 🟢 正面 | + +### 数据源三:WebSearch(全网尽调舆情) + +#### 搜索关键词组合(按尽调维度) + +```python +# 高优先级(必查) +search_queries_high = [ + "{企业名} 负面 OR 投诉 OR 维权 OR 欺骗 OR 跑路", + "{企业名} 起诉 OR 法院 OR 被告 OR 被执行 OR 失信", + "{企业名} 处罚 OR 违规 OR 罚款 OR 整改 OR 通报批评", +] + +# 中优先级(建议查) +search_queries_mid = [ + "{企业名} 质量 OR 召回 OR 不合格 OR 安全事故", + "{企业名} 老板 OR 法人 OR 总经理 丑闻 OR 被查 OR 被抓", + "{企业名} 欠薪 OR 辞退 OR 劳动仲裁 OR 工伤", +] + +# 低优先级(正面对照) +search_queries_low = [ + "{企业名} 获奖 OR 创新 OR 认定 OR 排名", +] +``` + +#### 采集字段 + +- 新闻标题 / 来源网站 / 发布时间 / 摘要 / 原文链接 +- **注意**:区分企业作为**原告**(维权,非负面信号)vs **被告**(被诉,负面信号) + +### Step 1:三渠道采集执行 + +1. **WebSearch 尽调搜索**(先执行,信息量最大):按高/中/低优先级逐组搜索,收集新闻标题+来源+日期+摘要 +2. **抖音指数热度**:访问巨量算数查企业简称热度趋势,判断是否近期发酵 +3. **抖音精选内容**:搜索抖音视频,按负面信号词筛选高互动视频 + +### Step 2:LLM 后处理(情感分析 + 风险分级) + +对采集到的原始内容执行: + +| 分析步骤 | 说明 | +|---|---| +| **情感分类** | 每条标注:正面 / 中性 / 负面 | +| **风险分级** | 负面内容分:高(诉讼被告/处罚/跑路/安全事故)/ 中(投诉/质量吐槽/劳资)/ 低(一般差评) | +| **事件归并** | 同一事件的多条报道归并为一条(以最早报道为准) | +| **原被告区分** | 企业作为原告的维权诉讼**不是**负面风险信号 | +| **时效判断** | 近 3 个月的负面标记"近期",更早的标记"历史" | + +### Step 3:输出尽调舆情报告 + +```json +{ + "query_status": "success", + "source": "multi-source-sentiment", + "company_name": "{企业名}", + "sentiment_overview": { + "overall_assessment": "正面 | 中性偏正 | 中性 | 中性偏负 | 负面 | 高风险", + "negative_ratio": "15%", + "neutral_ratio": "60%", + "positive_ratio": "25%", + "trend": "稳定 | 近期发酵 | 持续负面" + }, + "negative_risks": [ + { + "risk_type": "诉讼报道(被告) | 行政处罚 | 产品质量 | 高管负面 | 劳资纠纷 | 消费者投诉 | 经营异常", + "event_title": "……", + "event_date": "YYYY-MM-DD", + "recency": "近期 | 历史", + "source_url": "https://……", + "severity": "高 | 中 | 低", + "summary": "1-2 句事件摘要" + } + ], + "controversies": [ + { + "event_title": "……", + "description": "争议双方与焦点", + "status": "发酵中 | 已平息 | 官方已回应" + } + ], + "positive_highlights": [ + "获奖/创新/贡献等正面事件(一句话)" + ], + "sentiment_summary": "3-5 句舆情综合判断:整体舆论形象、主要负面及严重程度、是否近期发酵、尽调建议", + "data_sources_used": ["websearch", "douyin-index", "douyin-featured"], + "collection_time": "ISO8601" +} +``` + +## 质量标准 + +- **数据真实性**:所有舆情内容必须来自实际采集(WebSearch 结果 / 抖音页面),绝不编造 +- **来源可溯**:每条负面风险必须附 source_url +- **原被告区分**:企业作为原告的诉讼报道不列入负面风险(单独归类为"涉诉动态") +- **时效标注**:每条负面标注"近期"(3 个月内)或"历史" +- **不做绝对结论**:舆情是辅助信号,报告末尾注明"舆情仅为尽调参考维度之一,需结合工商/司法/财务数据综合判断" + +## 错误处理 + +| 场景 | 处理方式 | +|---|---| +| 抖音指数页面无法访问 | 跳过该源,用 WebSearch + 抖音精选补充,报告中注明"热度数据缺失" | +| 抖音搜索需登录 | 跳过该源,WebSearch 补充搜索 `{企业名} 抖音 负面` | +| WebSearch 无结果 | 该维度标注"未检索到相关负面",属正面信号 | +| 负面信息量极大 | 只取前 10 条高严重度条目,其余归入计数 | + +## 已知限制 + +- **非实时**:依赖搜索引擎收录与抖音页面展示,存在小时级~天级延迟(非 7×24 实时监测——持续监测需商业舆情 API) +- **情感分析靠 LLM**:无专用情感模型,由 LLM 后处理推断(准确率约 85-90%,边界案例可能误判) +- **抖音覆盖**:微信公众号/微博/小红书等平台内容仅能通过 WebSearch 间接覆盖(非全平台直达) +- **企业全名 vs 简称**:WebSearch 用全名(精确),抖音用简称(命中率);两者结果可能有差异 + +## 故障排查 + +| 问题 | 原因 | 处理 | +|---|---|---| +| WebBridge daemon 不可达 | daemon 未运行 | `~/.kimi-webbridge/bin/kimi-webbridge.exe start` | +| 巨量算数页面空白 | JS 渲染未完成 | 等 5 秒后 evaluate 读 innerText | +| 抖音搜索页无结果 | 需登录 / 简称不匹配 | 跳过,WebSearch 补充 | +| WebSearch 结果全是正面 | 负面词组合不当 | 换用具体负面词(如"被处罚"而非"处罚") | diff --git a/skills/multi-source-sentiment/catalog-metadata.v1.json b/skills/multi-source-sentiment/catalog-metadata.v1.json new file mode 100644 index 0000000..d5eed4a --- /dev/null +++ b/skills/multi-source-sentiment/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "multi-source-sentiment" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "企业尽调舆情采集", + "summary": "抖音指数+抖音精选+WebSearch 三渠道采集,输出尽调舆情报告", + "description": "企业尽调舆情采集——通过抖音指数、抖音精选、WebSearch 三大数据源采集企业舆情,分析负面风险(诉讼/处罚/质量/高管/劳资),输出尽调舆情报告。Use when 用户提到\"查舆情\"、\"企业舆情\"、\"负面新闻\"、\"舆论风险\"、\"尽调舆情\"、\"企业口碑\"、\"舆情分析\"、\"网络口碑\"。" + }, + "en-US": { + "name": "Multi-Source Sentiment", + "summary": "Due-diligence sentiment via Douyin Index, Douyin Featured, and WebSearch", + "description": "Due-diligence sentiment collection — gather enterprise public opinion via three channels (Douyin Index, Douyin Featured, WebSearch), analyze negative risks (litigation / penalties / quality / executives / labor), and output a due-diligence sentiment report. Use when the user asks about enterprise sentiment, negative news, reputation risk, or public opinion." + } + }, + "category": "research", + "tags": [ + "due-diligence", + "sentiment", + "public-opinion", + "douyin" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "medium" + } +} diff --git a/skills/tianyancha-risk/SKILL.md b/skills/tianyancha-risk/SKILL.md new file mode 100644 index 0000000..3f96eb6 --- /dev/null +++ b/skills/tianyancha-risk/SKILL.md @@ -0,0 +1,154 @@ +--- +name: tianyancha-risk +description: >- + 天眼查企业风险查询——输入企业名称,返回风险画像(自身风险/周边风险/历史风险/预警提醒,含分类统计与明细)。Use when 用户提到"查风险"、"企业风险"、"风险画像"、"司法风险"、"经营风险"、"开庭公告"、"裁判文书"、"被执行人"、"天眼查"。 +version: 1.0.0 +type: procedural +risk_level: low +status: enabled +tags: + - due-diligence + - risk + - tianyancha + - corporate +metadata: + author: desirecore + updated_at: '2026-09-03' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 天眼查企业风险查询 + short_desc: 输入企业名称,返回自身/周边/历史/预警四类风险画像 + description: >- + 天眼查企业风险查询——输入企业名称,返回风险画像(自身风险/周边风险/历史风险/预警提醒,含分类统计与明细)。Use when 用户提到"查风险"、"企业风险"、"风险画像"、"司法风险"、"经营风险"、"开庭公告"、"裁判文书"、"被执行人"、"天眼查"。 + body: ./SKILL.zh-CN.md + source_hash: sha256:b58091c7ef9e968e + translated_by: human + en-US: + name: Tianyancha Risk Query + short_desc: Enterprise risk profile by company name — self/related/historical/warning risk + description: >- + Tianyancha enterprise risk query — input a company name and return a structured risk profile (self risk / related-party risk / historical risk / early warnings, with category counts and details). Use when the user asks about enterprise risk, judicial risk, litigation announcements, court rulings, dishonest debtors, or Tianyancha. + body: ./SKILL.md + source_hash: sha256:b58091c7ef9e968e + translated_by: human +market: + icon: >- + + category: business + maintainer: + name: DesireCore Official + verified: true + compatible_agents: [] + channel: latest + required_client_version: 10.0.115 +--- + +# Tianyancha Risk Query + +## L0: One-Sentence Summary + +Input a company name, call the Tianyancha risk-info API, and return a structured risk profile (self / related-party / historical / warning, four categories). + +## L1: Overview + +- **Data source**: Tianyancha Open Platform `risk/riskInfo/2.0` +- **Auth**: Token (`Authorization` header, **without** the `Bearer` prefix) +- **Invocation**: HTTP GET (curl / HttpRequest tool) +- **Prerequisites**: a valid Token with the risk API enabled + +## Credential Setup + +This skill requires a Tianyancha Open Platform Token: + +1. Register an enterprise account at the [Tianyancha Open Platform](https://open.tianyancha.com/) +2. Purchase/enable an API package (`risk/riskInfo/2.0` is authorized per package tier) +3. Export the token as the environment variable `TIANYANCHA_TOKEN`, or replace the `{TIANYANCHA_TOKEN}` placeholder below + +## L2: Procedure + +### 1. Build the request + +```bash +curl -s --max-time 30 --ssl-no-revoke \ + "https://open.api.tianyancha.com/services/open/risk/riskInfo/2.0?keyword={company-name-URL-encoded}" \ + -H "Authorization: ${TIANYANCHA_TOKEN}" +``` + +**Parameters**: + +| Param | Value | Notes | +|---|---|---| +| keyword | Company name (URL-encoded) | e.g. `华为技术有限公司` | +| Authorization | `{TIANYANCHA_TOKEN}` | **Token in header, no `Bearer` prefix** (adding one returns 300009) | + +### 2. Interpret the response + +- `error_code == 0` and `reason == "ok"`: success, extract `result.riskList[]` +- `error_code == 300009`: account error — wrong token or a `Bearer` prefix was added +- `error_code == 300005`: no permission for this API — the token does not cover it +- `error_code == 300008`: missing parameter — check keyword + +### 3. Response structure + +`result` contains: + +- `riskLevel`: overall risk level +- `riskList[]`: four risk categories (each with name / count / type / list[]) + +| Category | type | Meaning | +|---|---|---| +| Self risk | 1 | The company's own judicial/business risks (court hearings / rulings / case filings / court announcements / judicial auctions) | +| Related-party risk | 2 | Risks of shareholders, executives, invested companies | +| Historical risk | 3 | Closed historical risks (historical filings / hearings / dishonest-debtor history) | +| Early warnings | 0 | Business-registration changes (investor / key-personnel / registered-capital / legal-representative changes, bankruptcy cases) | + +Each category's `list[]` holds sub-items with `title` (e.g. "开庭公告") / `total` / `tag` (warning / high-risk / info) / `list[]` (top details with id / title / desc / riskCount). + +### 4. Normalized mapping + +```json +{ + "query_status": "success", + "source": "tianyancha", + "company_name": "{company name}", + "risk_level": "{result.riskLevel}", + "summary": { + "self_risk_count": 3127, + "related_risk_count": 1505, + "history_risk_count": 9113, + "warning_count": 815 + }, + "self_risks": [ + { "risk_type": "开庭公告", "count": 1501, "level": "警示", "title": "该公司起诉他人或公司的开庭公告", "detail_count": 1096 } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 5. Due-diligence highlights + +Prioritize as follows when composing the report: + +1. **High-risk entries** (tag=高风险): e.g. "被执行人", "清算信息", "失信被执行人" — list as major risk items +2. **Large warning counts** (total > 100): e.g. 1,501 hearing announcements — list as judicial-activity indicators +3. **Change warnings**: recent investor / legal-representative / capital changes — list as business dynamics + +## Known Limitations + +- **Tiered token authorization**: APIs are authorized per package; unauthorized APIs return 300005 — full-dimension packages unlock business/shareholder/IP endpoints +- **QPS throttling**: rate limits depend on the package; keep ≥1 s between calls +- **Large responses**: big companies can return 98KB+ — extract summaries plus top-N details to keep context small + +## Troubleshooting + +| Code | Meaning | Fix | +|---|---|---| +| 0 | Success | — | +| 300005 | No permission for this API | Confirm the endpoint is covered by your package | +| 300008 | Missing parameter | Check the keyword parameter | +| 300009 | Account error | Wrong token / Bearer prefix / expired token — remove the prefix and retry; if still failing, update the token | diff --git a/skills/tianyancha-risk/SKILL.zh-CN.md b/skills/tianyancha-risk/SKILL.zh-CN.md new file mode 100644 index 0000000..51a1511 --- /dev/null +++ b/skills/tianyancha-risk/SKILL.zh-CN.md @@ -0,0 +1,106 @@ +# 天眼查企业风险查询 + +## L0 + +输入企业名称,调用天眼查风险信息 API,返回结构化风险画像(自身/周边/历史/预警四类)。 + +## L1 概述 + +- **数据源**:天眼查开放平台 `risk/riskInfo/2.0` +- **认证**:Token(`Authorization` Header,**不带 `Bearer` 前缀**) +- **调用方式**:HTTP GET(curl / HttpRequest 工具) +- **前置条件**:Token 有效(需在天眼查开放平台开通对应接口权限) + +## 凭证获取 + +本技能需要天眼查开放平台 Token: + +1. 访问 [天眼查开放平台](https://open.tianyancha.com/) 注册企业账号 +2. 购买/开通接口套餐(风险信息接口 `risk/riskInfo/2.0` 按套餐分级授权) +3. 将 Token 配置为环境变量 `TIANYANCHA_TOKEN`,或替换下文命令中的 `{TIANYANCHA_TOKEN}` 占位符 + +## L2 操作步骤 + +### 1. 构造请求 + +```bash +curl -s --max-time 30 --ssl-no-revoke \ + "https://open.api.tianyancha.com/services/open/risk/riskInfo/2.0?keyword={企业名称URL编码}" \ + -H "Authorization: ${TIANYANCHA_TOKEN}" +``` + +**参数说明**: + +| 参数 | 值 | 说明 | +|---|---|---| +| keyword | 企业名称(URL 编码) | 如"华为技术有限公司" | +| Authorization | `{TIANYANCHA_TOKEN}` | **Header 传 Token,不带 `Bearer` 前缀**(带前缀返回 300009) | + +### 2. 判断响应 + +- `error_code == 0` 且 `reason == "ok"`:成功,提取 `result.riskList[]` +- `error_code == 300009`:账号信息有误——Token 错误或加了 Bearer 前缀 +- `error_code == 300005`:无权限访问此 API——当前 Token 未授权该接口 +- `error_code == 300008`:缺少必要参数——检查 keyword + +### 3. 响应结构解析 + +`result` 包含两个字段: + +- `riskLevel`:整体风险等级 +- `riskList[]`:四类风险(每类含 name / count / type / list[]) + +四类风险: + +| 类型 | type | 含义 | +|---|---|---| +| 自身风险 | 1 | 该企业自身的司法/经营风险(开庭公告/裁判文书/立案信息/法院公告/司法拍卖等) | +| 周边风险 | 2 | 关联方(股东/高管/投资企业)的风险 | +| 历史风险 | 3 | 已了结的历史风险(历史立案/历史开庭/被执行人_历史等) | +| 预警提醒 | 0 | 工商变更提醒(投资人变更/主要人员变更/注册资本变更/法定代表人变更/破产案件等) | + +每类下 `list[]` 为子项,每子项含 `title`(如"开庭公告")/ `total`(条数)/ `tag`(警示/高风险/提示信息)/ `list[]`(前几条明细,含 id / title / desc / riskCount)。 + +### 4. 标准化映射 + +```json +{ + "query_status": "success", + "source": "tianyancha", + "company_name": "{企业名称}", + "risk_level": "{result.riskLevel}", + "summary": { + "self_risk_count": 3127, + "related_risk_count": 1505, + "history_risk_count": 9113, + "warning_count": 815 + }, + "self_risks": [ + { "risk_type": "开庭公告", "count": 1501, "level": "警示", "title": "该公司起诉他人或公司的开庭公告", "detail_count": 1096 } + ], + "timestamp": "2026-08-31T21:00:00+08:00" +} +``` + +### 5. 尽调要点提炼 + +输出报告时按以下优先级提炼: + +1. **高风险条目**(tag=高风险):如"被执行人"、"清算信息"、"失信被执行人"——直接列为重大风险项 +2. **警示条目大额计数**(total > 100):如开庭公告 1501 条——列为司法活跃度指标 +3. **预警变更**:近期投资人/法定代表人/注册资本变更——列为经营动态 + +## 已知限制 + +- **Token 分级授权**:接口按套餐授权,未授权接口返回 300005——购买全维度套餐后可扩展工商/股权/知产等接口 +- **QPS 限流**:天眼查 API 按套餐有 QPS 限制,连续调用注意间隔(建议 ≥1 秒) +- **响应体量大**:大企业响应可达 98KB+,解析时注意内存与上下文压缩(只提取汇总+前 N 条明细) + +## 故障排查 + +| 错误码 | 含义 | 处理 | +|---|---|---| +| 0 | 成功 | — | +| 300005 | 无权限访问此 API | 当前 Token 未授权该接口;确认调用的接口在授权范围内 | +| 300008 | 缺少必要参数 | 检查 keyword 参数 | +| 300009 | 账号信息有误 | Token 错误 / 加了 Bearer 前缀 / Token 过期——去掉前缀重试,仍失败则更新 Token | diff --git a/skills/tianyancha-risk/catalog-metadata.v1.json b/skills/tianyancha-risk/catalog-metadata.v1.json new file mode 100644 index 0000000..c8809de --- /dev/null +++ b/skills/tianyancha-risk/catalog-metadata.v1.json @@ -0,0 +1,74 @@ +{ + "$schema": "../../schemas/catalog-metadata.v1.schema.json", + "schemaVersion": 1, + "identity": { + "kind": "skill", + "id": "tianyancha-risk" + }, + "presentation": { + "defaultLocale": "en-US", + "i18n": { + "zh-CN": { + "name": "天眼查企业风险查询", + "summary": "输入企业名称,返回自身/周边/历史/预警四类风险画像", + "description": "天眼查企业风险查询——输入企业名称,返回风险画像(自身风险/周边风险/历史风险/预警提醒,含分类统计与明细)。Use when 用户提到\"查风险\"、\"企业风险\"、\"风险画像\"、\"司法风险\"、\"经营风险\"、\"开庭公告\"、\"裁判文书\"、\"被执行人\"、\"天眼查\"。" + }, + "en-US": { + "name": "Tianyancha Risk Query", + "summary": "Enterprise risk profile by company name — self/related/historical/warning risk", + "description": "Tianyancha enterprise risk query — input a company name and return a structured risk profile (self risk / related-party risk / historical risk / early warnings, with category counts and details). Use when the user asks about enterprise risk, judicial risk, litigation announcements, court rulings, dishonest debtors, or Tianyancha." + } + }, + "category": "business", + "tags": [ + "due-diligence", + "risk", + "tianyancha", + "corporate" + ] + }, + "release": { + "state": "known", + "version": "1.0.0", + "versionScheme": "semver" + }, + "timestamps": { + "catalogUpdatedAt": { + "state": "known", + "value": "2026-09-03T05:45:00Z", + "precision": "second" + }, + "releasePublishedAt": { + "state": "unknown" + }, + "reviewedAt": { + "state": "unknown" + }, + "upstreamObservedAt": { + "state": "unknown" + } + }, + "provenance": {}, + "governance": { + "stewardship": "official", + "availability": "installable", + "license": { + "state": "unknown" + }, + "redistribution": "verify-package-terms", + "listingMaintainer": { + "name": "DesireCore Official", + "verified": true + } + }, + "compatibility": { + "platforms": { + "state": "unknown" + }, + "requiredClientVersion": "10.0.115" + }, + "spec": { + "kind": "skill", + "riskLevel": "low" + } +}