#!/usr/bin/env node /** * sync-version.js — 从 stats-compiled.json 同步版本号到 boot 仓库文件 * * 用法: node sync-version.js [--dry-run] * * 替换规则: * {N} Skills → 从 stats.summary.skills * {N} Agents → 从 stats.summary.agents * {N} Hooks → 从 stats.summary.hooks (settings.json 注册的总数) */ 'use strict'; const fs = require('fs'); const path = require('path'); const DRY_RUN = process.argv.includes('--dry-run'); const BOOT_DIR = __dirname; const STATS_PATH = path.join(process.env.HOME || process.env.USERPROFILE, '.claude', 'stats-compiled.json'); // 读取 stats let stats; try { stats = JSON.parse(fs.readFileSync(STATS_PATH, 'utf8')); } catch (e) { console.error(` [FAIL] 无法读取 ${STATS_PATH}: ${e.message}`); process.exit(1); } const skills = stats.summary.skills; const agents = stats.summary.agents; const hooks = stats.summary.hooks; const version = stats.summary?.version || stats.version || 'v6.5.1'; console.log(` sync-version: ${skills} Skills / ${agents} Agents / ${hooks} Hooks (${version})`); // 需要更新的文件 (相对于 boot 仓库) const FILES = [ 'Bookworm-Setup.sh', 'Bookworm-Setup.bat', 'Bookworm-OneClick.bat', 'Bookworm-OneClick-Win10.bat', 'Bookworm-OneClick-Mac.sh', 'install.ps1', 'guide.html', 'guide-mac.html', 'quick-start.html', 'quick-reference.txt', ]; // 替换模式: 匹配 "数字 Skills"、"数字 Agents"、"数字 Hooks" // 支持多种分隔格式: "92 Skills"、"92 个 Skills"、"92 Skills" const REPLACEMENTS = [ // 纯文本格式: "92 Skills"、"92 个 Skills" { pattern: /\b\d+ Skills/g, replacement: `${skills} Skills` }, { pattern: /\b\d+ Agents/g, replacement: `${agents} Agents` }, { pattern: /\b\d+ Hooks/g, replacement: `${hooks} Hooks` }, { pattern: /\b\d+ 个 Skills/g, replacement: `${skills} 个 Skills` }, // HTML badge 格式: 92 Skills { pattern: /\d+<\/strong> Skills/g, replacement: `${skills} Skills` }, { pattern: /\d+<\/strong> Agents/g, replacement: `${agents} Agents` }, { pattern: /\d+<\/strong> Hooks/g, replacement: `${hooks} Hooks` }, // PS1 格式: "92 Skills / 18 Agents / 34 Hooks" { pattern: /\b\d+ Skills \/ \d+ Agents \/ \d+ Hooks/g, replacement: `${skills} Skills / ${agents} Agents / ${hooks} Hooks` }, // bat 格式: "92 Skills / 18 Agents" { pattern: /\b\d+ Skills \/ \d+ Agents/g, replacement: `${skills} Skills / ${agents} Agents` }, // "Bookworm (92 Skills)" / "Bookworm - 92 Skills" { pattern: /Bookworm \(\d+ Skills\)/g, replacement: `Bookworm (${skills} Skills)` }, { pattern: /Bookworm - \d+ Skills/g, replacement: `Bookworm - ${skills} Skills` }, ]; let totalChanged = 0; for (const file of FILES) { const filePath = path.join(BOOT_DIR, file); if (!fs.existsSync(filePath)) continue; let content = fs.readFileSync(filePath, 'utf8'); const original = content; for (const { pattern, replacement } of REPLACEMENTS) { content = content.replace(pattern, replacement); } if (content !== original) { if (!DRY_RUN) { fs.writeFileSync(filePath, content, 'utf8'); } totalChanged++; console.log(` ${DRY_RUN ? '[DRY] ' : ''}更新: ${file}`); } } console.log(` 同步完成: ${totalChanged}/${FILES.length} 个文件更新`); if (DRY_RUN) console.log(' [DRY RUN] 未实际写入');