|
@@ -32,6 +32,7 @@ const CDN_PREFIX = 'x/openclaw-skills/packages';
|
|
|
const SKILLS_DIR = path.join(os.homedir(), '.openclaw', 'skills');
|
|
const SKILLS_DIR = path.join(os.homedir(), '.openclaw', 'skills');
|
|
|
const INSTALL_JS = path.join(__dirname, '..', '..', 'dist', 'install.js');
|
|
const INSTALL_JS = path.join(__dirname, '..', '..', 'dist', 'install.js');
|
|
|
const SET_VOC_TOKEN_JS = path.join(__dirname, '..', 'tools', 'set-voc-token.js');
|
|
const SET_VOC_TOKEN_JS = path.join(__dirname, '..', 'tools', 'set-voc-token.js');
|
|
|
|
|
+const VOC_TOKEN_PREFLIGHT_JS = path.join(__dirname, '..', 'tools', 'voc-token-preflight.js');
|
|
|
const INSTALL_WORKSHOP_JS = path.join(__dirname, 'install-workshop.js');
|
|
const INSTALL_WORKSHOP_JS = path.join(__dirname, 'install-workshop.js');
|
|
|
const INSTALL_ALL_JS = path.join(__dirname, 'install-all.js');
|
|
const INSTALL_ALL_JS = path.join(__dirname, 'install-all.js');
|
|
|
const CREDENTIALS_TEMPLATE = path.join(__dirname, '..', '..', '__config', 'voc-credentials.template.json');
|
|
const CREDENTIALS_TEMPLATE = path.join(__dirname, '..', '..', '__config', 'voc-credentials.template.json');
|
|
@@ -100,7 +101,7 @@ const PACKAGES = {
|
|
|
// social-voc
|
|
// social-voc
|
|
|
'instagram-brand-voc', 'social-trend-analysis', 'tiktok-brand-voc', 'tiktok-category-voc',
|
|
'instagram-brand-voc', 'social-trend-analysis', 'tiktok-brand-voc', 'tiktok-category-voc',
|
|
|
// workshop
|
|
// workshop
|
|
|
- 'brand-context-builder'
|
|
|
|
|
|
|
+ 'brand-context-builder', 'voc-token-preflight'
|
|
|
]
|
|
]
|
|
|
},
|
|
},
|
|
|
'social-media': {
|
|
'social-media': {
|
|
@@ -162,6 +163,11 @@ function buildPackage(pkgId, pkg) {
|
|
|
fs.copyFileSync(SET_VOC_TOKEN_JS, path.join(pkgDir, 'set-voc-token.js'));
|
|
fs.copyFileSync(SET_VOC_TOKEN_JS, path.join(pkgDir, 'set-voc-token.js'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 复制 voc-token-preflight.js(Token 预飞检测工具)
|
|
|
|
|
+ if (fs.existsSync(VOC_TOKEN_PREFLIGHT_JS)) {
|
|
|
|
|
+ fs.copyFileSync(VOC_TOKEN_PREFLIGHT_JS, path.join(pkgDir, 'voc-token-preflight.js'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 生成 README.txt
|
|
// 生成 README.txt
|
|
|
const readme = [
|
|
const readme = [
|
|
|
`OpenClaw ${pkg.label}`,
|
|
`OpenClaw ${pkg.label}`,
|
|
@@ -179,11 +185,12 @@ function buildPackage(pkgId, pkg) {
|
|
|
' 5. 重启 OpenClaw gateway',
|
|
' 5. 重启 OpenClaw gateway',
|
|
|
'',
|
|
'',
|
|
|
'其他命令:',
|
|
'其他命令:',
|
|
|
- ' node install.js --list # 列出所有技能',
|
|
|
|
|
- ' node install.js --dry-run # 预览模式',
|
|
|
|
|
- ' node install.js --only a,b,c # 只安装指定技能',
|
|
|
|
|
- ' node install.js --skip a,b,c # 跳过指定技能',
|
|
|
|
|
- ' node set-voc-token.js <token> # 设置/更新 VOC Token',
|
|
|
|
|
|
|
+ ' node install.js --list # 列出所有技能',
|
|
|
|
|
+ ' node install.js --dry-run # 预览模式',
|
|
|
|
|
+ ' node install.js --only a,b,c # 只安装指定技能',
|
|
|
|
|
+ ' node install.js --skip a,b,c # 跳过指定技能',
|
|
|
|
|
+ ' node set-voc-token.js <token> # 设置/更新 VOC Token',
|
|
|
|
|
+ ' node voc-token-preflight.js # 检测 Token 有效性和余额',
|
|
|
'',
|
|
'',
|
|
|
'技能列表:',
|
|
'技能列表:',
|
|
|
...pkg.skills.map(s => ` - ${s}`),
|
|
...pkg.skills.map(s => ` - ${s}`),
|
|
@@ -238,15 +245,30 @@ function buildPackage(pkgId, pkg) {
|
|
|
function buildWorkshopPackage() {
|
|
function buildWorkshopPackage() {
|
|
|
const pkgDir = path.join(TEMP_BASE, 'workshop');
|
|
const pkgDir = path.join(TEMP_BASE, 'workshop');
|
|
|
const memoryDir = path.join(pkgDir, 'memory-templates');
|
|
const memoryDir = path.join(pkgDir, 'memory-templates');
|
|
|
|
|
+ const skillsDir = path.join(pkgDir, 'skills');
|
|
|
|
|
|
|
|
if (fs.existsSync(pkgDir)) fs.rmSync(pkgDir, { recursive: true, force: true });
|
|
if (fs.existsSync(pkgDir)) fs.rmSync(pkgDir, { recursive: true, force: true });
|
|
|
fs.mkdirSync(memoryDir, { recursive: true });
|
|
fs.mkdirSync(memoryDir, { recursive: true });
|
|
|
|
|
+ fs.mkdirSync(skillsDir, { recursive: true });
|
|
|
|
|
|
|
|
// 复制安装脚本
|
|
// 复制安装脚本
|
|
|
if (fs.existsSync(INSTALL_WORKSHOP_JS)) {
|
|
if (fs.existsSync(INSTALL_WORKSHOP_JS)) {
|
|
|
fs.copyFileSync(INSTALL_WORKSHOP_JS, path.join(pkgDir, 'install-workshop.js'));
|
|
fs.copyFileSync(INSTALL_WORKSHOP_JS, path.join(pkgDir, 'install-workshop.js'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 复制 Token 工具(workshop 自足所需)
|
|
|
|
|
+ if (fs.existsSync(SET_VOC_TOKEN_JS)) {
|
|
|
|
|
+ fs.copyFileSync(SET_VOC_TOKEN_JS, path.join(pkgDir, 'set-voc-token.js'));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (fs.existsSync(VOC_TOKEN_PREFLIGHT_JS)) {
|
|
|
|
|
+ fs.copyFileSync(VOC_TOKEN_PREFLIGHT_JS, path.join(pkgDir, 'voc-token-preflight.js'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 复制凭证模板
|
|
|
|
|
+ if (fs.existsSync(CREDENTIALS_TEMPLATE)) {
|
|
|
|
|
+ fs.copyFileSync(CREDENTIALS_TEMPLATE, path.join(pkgDir, 'voc-credentials.template.json'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
let copied = 0;
|
|
let copied = 0;
|
|
|
|
|
|
|
|
// 复制 workshop 文件(仅白名单 playbooks)
|
|
// 复制 workshop 文件(仅白名单 playbooks)
|
|
@@ -271,38 +293,92 @@ function buildWorkshopPackage() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 复制 workshop 所需的全部 skills(复用 voc-core 列表,workshop 主线+侧线都依赖它们)
|
|
|
|
|
+ const workshopSkills = PACKAGES['voc-core'].skills;
|
|
|
|
|
+ let skillsCopied = 0;
|
|
|
|
|
+ let skillsMissing = 0;
|
|
|
|
|
+ for (const skillName of workshopSkills) {
|
|
|
|
|
+ const srcDir = path.join(SKILLS_DIR, skillName);
|
|
|
|
|
+ if (!fs.existsSync(srcDir)) {
|
|
|
|
|
+ skillsMissing++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ const destDir = path.join(skillsDir, skillName);
|
|
|
|
|
+ fs.mkdirSync(destDir, { recursive: true });
|
|
|
|
|
+ const files = fs.readdirSync(srcDir).filter(f => fs.statSync(path.join(srcDir, f)).isFile());
|
|
|
|
|
+ for (const f of files) {
|
|
|
|
|
+ fs.copyFileSync(path.join(srcDir, f), path.join(destDir, f));
|
|
|
|
|
+ }
|
|
|
|
|
+ skillsCopied++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 生成 README.txt
|
|
// 生成 README.txt
|
|
|
const readme = [
|
|
const readme = [
|
|
|
- 'OpenClaw 🦐 VOC虾工作坊 v4.1',
|
|
|
|
|
|
|
+ 'OpenClaw 🦐 VOC虾工作坊 v4.2(自足版)',
|
|
|
'==================================================',
|
|
'==================================================',
|
|
|
'',
|
|
'',
|
|
|
- 'VOC 工作坊完整流程文件(Side Quest 架构)',
|
|
|
|
|
|
|
+ '一个压缩包搞定所有!包含:',
|
|
|
|
|
+ ` 🔧 ${skillsCopied} 个 workshop 必需的 skills(品类/评论/竞品/合成/社媒VOC/工作坊)`,
|
|
|
|
|
+ ' 📘 11 份 playbook(入口+全局规则+6个Session+配套文档)',
|
|
|
|
|
+ ' 📄 9 份 memory templates(记忆模板)',
|
|
|
|
|
+ ' 🔑 2 个 Token 工具(set-voc-token.js + voc-token-preflight.js)',
|
|
|
|
|
+ ' 📝 1 份凭证模板(voc-credentials.template.json)',
|
|
|
'',
|
|
'',
|
|
|
'架构:6个Session + 17个Side Quest,主线感知 + 支线深耕',
|
|
'架构:6个Session + 17个Side Quest,主线感知 + 支线深耕',
|
|
|
'',
|
|
'',
|
|
|
- '安装方法:',
|
|
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ '📦 一键安装:',
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
' 1. 解压本压缩包',
|
|
' 1. 解压本压缩包',
|
|
|
- ' 2. 在解压目录运行: node install-workshop.js',
|
|
|
|
|
- ' 3. 重启 OpenClaw gateway',
|
|
|
|
|
|
|
+ ' 2. 运行: node install-workshop.js',
|
|
|
|
|
+ ' (自动安装 skills + playbooks + memory templates + tools + 凭证模板)',
|
|
|
|
|
+ ' 3. 设置 Token(首次使用):',
|
|
|
|
|
+ ' a. 打开 https://app.fmode.cn/dev/apig-pay/?apigid=7HwdQZk55B&fun_id=HOkkX72PMF',
|
|
|
|
|
+ ' b. 登录并充值(最低 ¥0.01 体验 1 次)',
|
|
|
|
|
+ ' c. 复制 session token(格式 r:xxxx...)',
|
|
|
|
|
+ ' d. 运行: node ~/.openclaw/tools/set-voc-token.js <your-token>',
|
|
|
|
|
+ ' 4. 重启 OpenClaw gateway',
|
|
|
|
|
+ ' 5. 对话框说"开始 VOC 工作坊",Agent 会自动进入 Session 0',
|
|
|
'',
|
|
'',
|
|
|
- '其他命令:',
|
|
|
|
|
- ' node install-workshop.js --dry-run # 预览模式',
|
|
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ '🔍 验证安装:',
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ ' node ~/.openclaw/tools/voc-token-preflight.js',
|
|
|
|
|
+ ' (期望看到: status=valid, 余额 >= 1)',
|
|
|
|
|
+ '',
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ '🛠 其他命令:',
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ ' node install-workshop.js --dry-run # 预览将要安装的文件',
|
|
|
|
|
+ ' node install-workshop.js --skills-only # 只装 skills',
|
|
|
|
|
+ ' node install-workshop.js --playbook-only # 只装 playbooks (旧行为)',
|
|
|
'',
|
|
'',
|
|
|
- '文件说明:',
|
|
|
|
|
- ' workshop-voc-playbook.md ← 入口路由',
|
|
|
|
|
- ' workshop-global-rules.md ← 全局规则 + Side Quest Protocol',
|
|
|
|
|
- ' workshop-session-0-intake.md ← Session 0: 品牌建档',
|
|
|
|
|
- ' workshop-session-1-category.md ← Session 1: 品类 + 4 Side Quests',
|
|
|
|
|
- ' workshop-session-2-brand.md ← Session 2: 品牌 + 3 Side Quests',
|
|
|
|
|
- ' workshop-session-3-voc.md ← Session 3: VOC + 3 Side Quests',
|
|
|
|
|
- ' workshop-session-4-deep.md ← Session 4: 深入 + 5 Side Quests',
|
|
|
|
|
- ' workshop-session-5-report.md ← Session 5: 报告 + 2 Side Quests',
|
|
|
|
|
- ' memory-templates/*.json ← 记忆模板(9个)',
|
|
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ '📂 文件结构:',
|
|
|
|
|
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
|
|
|
+ ' skills/ ← workshop 用到的 skills',
|
|
|
|
|
+ ' voc-token-preflight/ ← Session 0/1 的 Token 预飞闸门',
|
|
|
|
|
+ ' brand-context-builder/ ← Session 0 品牌建档',
|
|
|
|
|
+ ' category-landscape/ ← Session 1 品类全景',
|
|
|
|
|
+ ' keyword-search/, category-tree/, ... (其余 Amazon/VOC/合成 skills)',
|
|
|
|
|
+ ' workshop-voc-playbook.md ← 入口路由',
|
|
|
|
|
+ ' workshop-global-rules.md ← 全局规则 + Token 预飞协议',
|
|
|
|
|
+ ' workshop-session-0-intake.md ← Session 0: 品牌建档 + Token 预飞',
|
|
|
|
|
+ ' workshop-session-1-category.md ← Session 1: 品类 + 4 Side Quests',
|
|
|
|
|
+ ' workshop-session-2-brand.md ← Session 2: 品牌 + 3 Side Quests',
|
|
|
|
|
+ ' workshop-session-3-voc.md ← Session 3: VOC + 3 Side Quests',
|
|
|
|
|
+ ' workshop-session-4-deep.md ← Session 4: 深入 + 5 Side Quests',
|
|
|
|
|
+ ' workshop-session-5-report.md ← Session 5: 报告 + 2 Side Quests',
|
|
|
|
|
+ ' memory-templates/*.json ← 记忆模板(9个)',
|
|
|
|
|
+ ' set-voc-token.js ← Token 写入工具',
|
|
|
|
|
+ ' voc-token-preflight.js ← Token 预飞检测工具',
|
|
|
|
|
+ ' voc-credentials.template.json ← 凭证模板',
|
|
|
''
|
|
''
|
|
|
].join('\n');
|
|
].join('\n');
|
|
|
fs.writeFileSync(path.join(pkgDir, 'README.txt'), readme, 'utf8');
|
|
fs.writeFileSync(path.join(pkgDir, 'README.txt'), readme, 'utf8');
|
|
|
|
|
|
|
|
- console.log(` ✅ 复制 ${copied} 个文件`);
|
|
|
|
|
|
|
+ console.log(` ✅ 复制 ${copied} 个 playbook/template + ${skillsCopied} 个 skills` +
|
|
|
|
|
+ (skillsMissing > 0 ? ` (缺失 ${skillsMissing})` : ''));
|
|
|
|
|
|
|
|
// 压缩
|
|
// 压缩
|
|
|
const zipPath = path.join(DIST_DIR, 'workshop.zip');
|
|
const zipPath = path.join(DIST_DIR, 'workshop.zip');
|
|
@@ -342,6 +418,11 @@ function buildAllPackage() {
|
|
|
fs.copyFileSync(SET_VOC_TOKEN_JS, path.join(pkgDir, 'set-voc-token.js'));
|
|
fs.copyFileSync(SET_VOC_TOKEN_JS, path.join(pkgDir, 'set-voc-token.js'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 复制 voc-token-preflight.js
|
|
|
|
|
+ if (fs.existsSync(VOC_TOKEN_PREFLIGHT_JS)) {
|
|
|
|
|
+ fs.copyFileSync(VOC_TOKEN_PREFLIGHT_JS, path.join(pkgDir, 'voc-token-preflight.js'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 复制凭证模板
|
|
// 复制凭证模板
|
|
|
if (fs.existsSync(CREDENTIALS_TEMPLATE)) {
|
|
if (fs.existsSync(CREDENTIALS_TEMPLATE)) {
|
|
|
fs.copyFileSync(CREDENTIALS_TEMPLATE, path.join(pkgDir, 'voc-credentials.template.json'));
|
|
fs.copyFileSync(CREDENTIALS_TEMPLATE, path.join(pkgDir, 'voc-credentials.template.json'));
|
|
@@ -418,6 +499,7 @@ function buildAllPackage() {
|
|
|
' node install-all.js --skills-only # 只装 Skills',
|
|
' node install-all.js --skills-only # 只装 Skills',
|
|
|
' node install-all.js --workshop-only # 只装 Workshop',
|
|
' node install-all.js --workshop-only # 只装 Workshop',
|
|
|
' node set-voc-token.js <token> # 设置/更新 Token',
|
|
' node set-voc-token.js <token> # 设置/更新 Token',
|
|
|
|
|
+ ' node voc-token-preflight.js # 检测 Token 有效性和余额(Workshop 前置检查)',
|
|
|
''
|
|
''
|
|
|
].join('\n');
|
|
].join('\n');
|
|
|
fs.writeFileSync(path.join(pkgDir, 'README.txt'), readme, 'utf8');
|
|
fs.writeFileSync(path.join(pkgDir, 'README.txt'), readme, 'utf8');
|