Pārlūkot izejas kodu

feat(pack): 新增文件类型白名单校验,不合规直接中止打包

白名单: .md/.json/.js/.mjs/.cjs/.ts/.py/.sh/.html/.htm/.css/.txt/.yaml/.yml/.svg 及常见图片
不合规即中止并给处理建议,避免上传后才发现被 SkillHub 拒绝。
liuyuyang 1 nedēļu atpakaļ
vecāks
revīzija
7780fd3729

+ 1 - 1
dist/skills-index.json

@@ -1,7 +1,7 @@
 {
   "name": "fmode-skills",
   "version": "1.2.0",
-  "builtAt": "2026-10-31T03:00:32.873Z",
+  "builtAt": "2026-10-31T03:21:55.534Z",
   "skills": [
     {
       "name": "fmode-storage",

+ 1 - 1
dist/skills/fmode-video-lapian/README.md

@@ -64,7 +64,7 @@ scripts/
   build_report.py         # 生成HTML报告(内置mini-Jinja, 无第三方依赖)
   publish.py              # S3上传+公开URL+逐产物校验
 templates/
-  report.html.j2          # 报告模板(暗色/手机自适应/相对路径)
+  report.template.html     # 报告模板(暗色/手机自适应/相对路径,Jinja2 语法)
 ```
 
 ## 报告示例

+ 1 - 1
dist/skills/fmode-video-lapian/scripts/build_report.py

@@ -23,7 +23,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
 from common import e as esc, fmt_ts, get_api_token  # noqa: E402
 
 ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-TEMPLATE = os.path.join(ROOT, "templates", "report.html.j2")
+TEMPLATE = os.path.join(ROOT, "templates", "report.template.html")
 TEXT_MODEL = os.environ.get("FEME_TEXT_MODEL", "deepseek-v4-flash")
 API_BASE = os.environ.get("FEME_API_BASE", "https://api.fmode.cn/v1")
 

+ 0 - 0
dist/skills/fmode-video-lapian/templates/report.html.j2 → dist/skills/fmode-video-lapian/templates/report.template.html


+ 26 - 1
scripts/pack-release.mjs

@@ -138,7 +138,32 @@ for (const f of files) {
   }
 }
 
-// 6. 打 zip
+// 6. 文件类型白名单校验(SkillHub 有严格限制,提前拦住)
+const ALLOWED_EXT = new Set([
+  '.md', '.json', '.js', '.mjs', '.cjs', '.ts', '.py', '.sh',
+  '.html', '.htm', '.css', '.txt', '.yaml', '.yml',
+  '.svg', '.png', '.jpg', '.jpeg', '.webp', '.gif',
+]);
+const badExt = [];
+(function scan(d, rel = '') {
+  for (const e of fs.readdirSync(d, { withFileTypes: true })) {
+    const p = path.join(d, e.name);
+    if (e.isDirectory()) { scan(p, `${rel}${e.name}/`); continue; }
+    const ext = path.extname(e.name).toLowerCase();
+    if (!ext || !ALLOWED_EXT.has(ext)) badExt.push(`${rel}${e.name}`);
+  }
+})(stageDir);
+
+if (badExt.length) {
+  console.log('\n✗ 发现 SkillHub 不支持的文件类型,已中止打包:');
+  for (const f of badExt) console.log(`   ${f}`);
+  console.log('\n处理建议:');
+  console.log('  .j2 → .template.html   (Jinja2 模板改扩展名,同步改引用)');
+  console.log('  LICENSE(无扩展名)→ LICENSE.md');
+  process.exit(1);
+}
+
+// 7. 打 zip
 const zipName = `${pkg.name || 'fmode-harness'}-${stamp}.zip`;
 const zipPath = path.join(RELEASE, zipName);
 fs.rmSync(zipPath, { force: true });