- Bookworm-Setup.sh: macOS Keychain 本日免密缓存(对标 Windows Credential Manager) - Bookworm-OneClick-Mac.sh: bw-update 补 config 仓库更新 - sync-version.js: 新建版本号同步脚本(从 stats-compiled.json 自动注入) - quick-start.html/quick-reference.txt: Hooks 29→34 修正 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
95 lines
3.4 KiB
JavaScript
95 lines
3.4 KiB
JavaScript
#!/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-mac.html',
|
|
'quick-start.html',
|
|
'quick-reference.txt',
|
|
];
|
|
|
|
// 替换模式: 匹配 "数字 Skills"、"数字 Agents"、"数字 Hooks"
|
|
// 支持多种分隔格式: "92 Skills"、"92 个 Skills"、"<strong>92</strong> 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 格式: <strong>92</strong> Skills
|
|
{ pattern: /<strong>\d+<\/strong> Skills/g, replacement: `<strong>${skills}</strong> Skills` },
|
|
{ pattern: /<strong>\d+<\/strong> Agents/g, replacement: `<strong>${agents}</strong> Agents` },
|
|
{ pattern: /<strong>\d+<\/strong> Hooks/g, replacement: `<strong>${hooks}</strong> 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] 未实际写入');
|