Răsfoiți Sursa

feat: upload-skills.js - add masterKey for Skill table creation, fix dot-in-keys issue, full 75 skills synced

gangvy 5 luni în urmă
părinte
comite
bc72e94773
3 a modificat fișierele cu 366 adăugiri și 14 ștergeri
  1. 0 0
      docs/1.md
  2. 62 14
      scripts/deploy/upload-skills.js
  3. 304 0
      scripts/skills-cdn-urls.json

+ 0 - 0
docs/1.md


+ 62 - 14
scripts/deploy/upload-skills.js

@@ -35,6 +35,7 @@ const CDN_PREFIX = 'x/openclaw-skills';
 // ============================================
 const PARSE_BASE = 'https://server.fmode.cn/parse';
 const APP_ID = 'ncloudmaster';
+const MASTER_KEY = process.env.PARSE_MASTER_KEY || 'SnkK12*&sunq2#@20!';
 
 // Skills 源目录(部署目录)
 const DEPLOYED_SKILLS_DIR = path.join(process.env.USERPROFILE || process.env.HOME, '.openclaw', 'skills');
@@ -103,13 +104,50 @@ function uploadBuffer(buffer, cdnKey) {
 // Parse REST API helpers
 // ============================================
 
+const PARSE_HEADERS = {
+    'X-Parse-Application-Id': APP_ID,
+    'X-Parse-Master-Key': MASTER_KEY,
+    'Content-Type': 'application/json'
+};
+
+async function ensureSkillClass() {
+    const resp = await fetch(`${PARSE_BASE}/schemas/Skill`, {
+        headers: PARSE_HEADERS
+    });
+    if (resp.ok) return;
+    // Class 不存在,创建
+    const createResp = await fetch(`${PARSE_BASE}/schemas/Skill`, {
+        method: 'POST',
+        headers: PARSE_HEADERS,
+        body: JSON.stringify({
+            className: 'Skill',
+            fields: {
+                name:        { type: 'String' },
+                displayName: { type: 'String' },
+                description: { type: 'String' },
+                category:    { type: 'String' },
+                version:     { type: 'String' },
+                author:      { type: 'String' },
+                cdnUrls:     { type: 'Object' },
+                cdnPrefix:   { type: 'String' }
+            }
+        })
+    });
+    const result = await createResp.json();
+    if (createResp.ok) {
+        console.log('  ✅ Skill 表已创建');
+    } else {
+        console.log('  ⚠️ 创建 Skill 表:', result.error || JSON.stringify(result));
+    }
+}
+
 async function parseQuery(className, where) {
     const qs = new URLSearchParams({
         where: JSON.stringify(where),
         limit: '1'
     });
     const resp = await fetch(`${PARSE_BASE}/classes/${className}?${qs}`, {
-        headers: { 'X-Parse-Application-Id': APP_ID }
+        headers: PARSE_HEADERS
     });
     const data = await resp.json();
     return data.results || [];
@@ -118,10 +156,7 @@ async function parseQuery(className, where) {
 async function parseCreate(className, body) {
     const resp = await fetch(`${PARSE_BASE}/classes/${className}`, {
         method: 'POST',
-        headers: {
-            'X-Parse-Application-Id': APP_ID,
-            'Content-Type': 'application/json'
-        },
+        headers: PARSE_HEADERS,
         body: JSON.stringify(body)
     });
     return resp.json();
@@ -130,10 +165,7 @@ async function parseCreate(className, body) {
 async function parseUpdate(className, objectId, body) {
     const resp = await fetch(`${PARSE_BASE}/classes/${className}/${objectId}`, {
         method: 'PUT',
-        headers: {
-            'X-Parse-Application-Id': APP_ID,
-            'Content-Type': 'application/json'
-        },
+        headers: PARSE_HEADERS,
         body: JSON.stringify(body)
     });
     return resp.json();
@@ -364,6 +396,7 @@ async function main() {
 
     // ── Step 2: 写入 Parse Skill 表 ──
     console.log('── Step 2: 同步到 Parse 数据库 (Skill 表) ──');
+    await ensureSkillClass();
     let dbSuccess = 0;
     let dbFail = 0;
 
@@ -371,6 +404,11 @@ async function main() {
         if (Object.keys(entry.cdnUrls).length === 0) continue;
         process.stdout.write(`  💾 ${entry.name} ... `);
         try {
+            // Parse 不允许嵌套 key 含 '.',将文件名中的 '.' 替换为 '_'
+            const safeCdnUrls = {};
+            for (const [k, v] of Object.entries(entry.cdnUrls)) {
+                safeCdnUrls[k.replace(/\./g, '_')] = v;
+            }
             const skillData = {
                 name: entry.meta.name,
                 displayName: entry.meta.displayName,
@@ -378,7 +416,7 @@ async function main() {
                 category: entry.meta.category,
                 version: entry.meta.version,
                 author: entry.meta.author,
-                cdnUrls: entry.cdnUrls,
+                cdnUrls: safeCdnUrls,
                 cdnPrefix: `${CDN_DOMAIN}/${CDN_PREFIX}/${entry.name}`
             };
             const result = await upsertSkill(skillData);
@@ -394,23 +432,33 @@ async function main() {
     console.log(`   数据库同步完成!成功: ${dbSuccess}  失败: ${dbFail}`);
     console.log('');
 
-    // ── Step 3: 生成 README.md 并上传 ──
+    // ── Step 3: 生成 README.md 并上传(包含在技能文件夹内)──
     console.log('── Step 3: 生成 README.md 并上传 ──');
+    let readmeUrl = '';
     try {
         const readme = generateReadme(results);
         const readmeKey = `${CDN_PREFIX}/README.md`;
         const readmeResult = await uploadBuffer(Buffer.from(readme, 'utf8'), readmeKey);
-        console.log(`  ✅ README.md 已上传: ${readmeResult.url}`);
+        readmeUrl = readmeResult.url;
+        console.log(`  ✅ README.md 已上传: ${readmeUrl}`);
     } catch (err) {
         console.log(`  ❌ README.md 上传失败: ${err.message}`);
     }
     console.log('');
 
-    // ── 输出 URL 汇总 ──
+    // ── 输出 URL 汇总(README 包含在内)──
     console.log('📋 CDN 下载地址列表:');
     console.log('');
 
     const urlMap = {};
+
+    // README 放在最前面
+    if (readmeUrl) {
+        urlMap['_README'] = { 'README.md': readmeUrl };
+        console.log(`  README.md`);
+        console.log(`    👉 ${readmeUrl}`);
+    }
+
     for (const entry of results) {
         if (Object.keys(entry.cdnUrls).length > 0) {
             urlMap[entry.name] = entry.cdnUrls;
@@ -429,7 +477,7 @@ async function main() {
     console.log('');
 
     console.log('==================================================');
-    console.log('📌 技能索引:');
+    console.log('📌 技能索引(README 已包含在文件夹内):');
     console.log(`  README: ${CDN_DOMAIN}/${CDN_PREFIX}/README.md`);
     console.log(`  CDN:    ${CDN_DOMAIN}/${CDN_PREFIX}/`);
     console.log('==================================================');

+ 304 - 0
scripts/skills-cdn-urls.json

@@ -0,0 +1,304 @@
+{
+  "_README": {
+    "README.md": "https://repos.fmode.cn/x/openclaw-skills/README.md"
+  },
+  "asin-reverse-keywords": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/asin-reverse-keywords/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/asin-reverse-keywords/api-config.json"
+  },
+  "asin-sales-volume": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/asin-sales-volume/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/asin-sales-volume/api-config.json"
+  },
+  "brand-context-builder": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/brand-context-builder/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/brand-context-builder/api-config.json"
+  },
+  "brand-profile": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/brand-profile/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/brand-profile/api-config.json"
+  },
+  "category-landscape": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/category-landscape/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/category-landscape/api-config.json"
+  },
+  "category-products": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/category-products/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/category-products/api-config.json"
+  },
+  "category-tree": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/category-tree/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/category-tree/api-config.json"
+  },
+  "competitor-bsr-tracking": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/competitor-bsr-tracking/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/competitor-bsr-tracking/api-config.json"
+  },
+  "competitor-discovery": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/competitor-discovery/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/competitor-discovery/api-config.json"
+  },
+  "competitor-pricing-analysis": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/competitor-pricing-analysis/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/competitor-pricing-analysis/api-config.json"
+  },
+  "competitor-product-comparison": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/competitor-product-comparison/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/competitor-product-comparison/api-config.json"
+  },
+  "douyin-comment-replies": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-comment-replies/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-comment-replies/api-config.json"
+  },
+  "douyin-general-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-general-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-general-search/api-config.json"
+  },
+  "douyin-hashtag-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-hashtag-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-hashtag-search/api-config.json"
+  },
+  "douyin-user-profile": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-user-profile/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-user-profile/api-config.json"
+  },
+  "douyin-user-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-user-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-user-search/api-config.json"
+  },
+  "douyin-video-comments": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-video-comments/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-video-comments/api-config.json"
+  },
+  "douyin-video-detail": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/douyin-video-detail/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/douyin-video-detail/api-config.json"
+  },
+  "html-report-generator": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/html-report-generator/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/html-report-generator/api-config.json"
+  },
+  "instagram-brand-voc": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/instagram-brand-voc/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/instagram-brand-voc/api-config.json"
+  },
+  "instagram-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/instagram-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/instagram-search/api-config.json"
+  },
+  "instagram-user-info": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/instagram-user-info/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/instagram-user-info/api-config.json"
+  },
+  "instagram-user-posts": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/instagram-user-posts/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/instagram-user-posts/api-config.json"
+  },
+  "jimeng-actor": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-actor/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-actor/api-config.json"
+  },
+  "jimeng-actor-v2": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-actor-v2/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-actor-v2/api-config.json"
+  },
+  "jimeng-clothes-v2": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-clothes-v2/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-clothes-v2/api-config.json"
+  },
+  "jimeng-img-v4": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4/api-config.json"
+  },
+  "jimeng-img-v4-goods": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4-goods/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4-goods/api-config.json"
+  },
+  "jimeng-img-v4-pod": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4-pod/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img-v4-pod/api-config.json"
+  },
+  "jimeng-img2img-v3": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img2img-v3/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-img2img-v3/api-config.json"
+  },
+  "jimeng-inpaint": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-inpaint/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-inpaint/api-config.json"
+  },
+  "jimeng-oh-detect": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-detect/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-detect/api-config.json"
+  },
+  "jimeng-oh-generate": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-generate/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-generate/api-config.json"
+  },
+  "jimeng-oh-identify": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-identify/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-identify/api-config.json"
+  },
+  "jimeng-oh-query": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-query/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-oh-query/api-config.json"
+  },
+  "jimeng-super-resolution": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-super-resolution/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-super-resolution/api-config.json"
+  },
+  "jimeng-task-query": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-task-query/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-task-query/api-config.json"
+  },
+  "jimeng-text2img-v3": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-text2img-v3/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-text2img-v3/api-config.json"
+  },
+  "jimeng-text2img-v31": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-text2img-v31/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-text2img-v31/api-config.json"
+  },
+  "jimeng-video-v3-1080p": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-1080p/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-1080p/api-config.json"
+  },
+  "jimeng-video-v3-720p": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-720p/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-720p/api-config.json"
+  },
+  "jimeng-video-v3-pro": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-pro/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-video-v3-pro/api-config.json"
+  },
+  "jimeng-work-result": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/jimeng-work-result/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/jimeng-work-result/api-config.json"
+  },
+  "keyword-product-ranking": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/keyword-product-ranking/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/keyword-product-ranking/api-config.json"
+  },
+  "keyword-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/keyword-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/keyword-search/api-config.json"
+  },
+  "keyword-search-trend": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/keyword-search-trend/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/keyword-search-trend/api-config.json"
+  },
+  "product-deep-analysis": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/product-deep-analysis/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/product-deep-analysis/api-config.json"
+  },
+  "product-detail-query": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/product-detail-query/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/product-detail-query/api-config.json"
+  },
+  "product-monitor": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/product-monitor/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/product-monitor/api-config.json"
+  },
+  "product-reviews-query": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/product-reviews-query/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/product-reviews-query/api-config.json"
+  },
+  "product-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/product-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/product-search/api-config.json"
+  },
+  "quickly-video-create": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-create/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-create/api-config.json"
+  },
+  "quickly-video-library": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-library/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-library/api-config.json"
+  },
+  "quickly-video-query": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-query/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/quickly-video-query/api-config.json"
+  },
+  "review-batch-collection": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/review-batch-collection/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/review-batch-collection/api-config.json"
+  },
+  "review-highlight-extraction": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/review-highlight-extraction/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/review-highlight-extraction/api-config.json"
+  },
+  "review-keyword-cloud": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/review-keyword-cloud/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/review-keyword-cloud/api-config.json"
+  },
+  "review-pain-point-extraction": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/review-pain-point-extraction/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/review-pain-point-extraction/api-config.json"
+  },
+  "review-sentiment-analysis": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/review-sentiment-analysis/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/review-sentiment-analysis/api-config.json"
+  },
+  "similar-products": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/similar-products/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/similar-products/api-config.json"
+  },
+  "social-trend-analysis": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/social-trend-analysis/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/social-trend-analysis/api-config.json"
+  },
+  "test-billing": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/test-billing/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/test-billing/api-config.json"
+  },
+  "test-skill": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/test-skill/SKILL.md"
+  },
+  "tiktok-brand-voc": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-brand-voc/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-brand-voc/api-config.json"
+  },
+  "tiktok-category-voc": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-category-voc/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-category-voc/api-config.json"
+  },
+  "tiktok-hashtag-detail": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-hashtag-detail/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-hashtag-detail/api-config.json"
+  },
+  "tiktok-hashtag-videos": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-hashtag-videos/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-hashtag-videos/api-config.json"
+  },
+  "tiktok-user-posts": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-posts/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-posts/api-config.json"
+  },
+  "tiktok-user-profile": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-profile/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-profile/api-config.json"
+  },
+  "tiktok-user-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-user-search/api-config.json"
+  },
+  "tiktok-video-comments": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-comments/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-comments/api-config.json"
+  },
+  "tiktok-video-detail": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-detail/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-detail/api-config.json"
+  },
+  "tiktok-video-search": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-search/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/tiktok-video-search/api-config.json"
+  },
+  "user-persona": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/user-persona/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/user-persona/api-config.json"
+  },
+  "voc-proposal": {
+    "SKILL.md": "https://repos.fmode.cn/x/openclaw-skills/voc-proposal/SKILL.md",
+    "api-config.json": "https://repos.fmode.cn/x/openclaw-skills/voc-proposal/api-config.json"
+  }
+}