byteplan-cli 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -3
- package/skills/byteplan-analysis/SKILL.md +1078 -0
- package/skills/byteplan-api/API_REFERENCE.md +249 -0
- package/skills/byteplan-api/SKILL.md +96 -0
- package/skills/byteplan-api/package.json +16 -0
- package/skills/byteplan-api/scripts/api.js +973 -0
- package/skills/byteplan-excel/SKILL.md +212 -0
- package/skills/byteplan-excel/examples/margin-analysis.json +40 -0
- package/skills/byteplan-excel/package.json +12 -0
- package/skills/byteplan-excel/pnpm-lock.yaml +68 -0
- package/skills/byteplan-excel/scripts/generate_excel.js +156 -0
- package/skills/byteplan-html/SKILL.md +490 -0
- package/skills/byteplan-html/examples/example-output.html +184 -0
- package/skills/byteplan-html/examples/generate-ppt-style-html.js +611 -0
- package/skills/byteplan-html/examples/margin-contribution-analysis.json +152 -0
- package/skills/byteplan-html/package.json +18 -0
- package/skills/byteplan-html/scripts/generate_html.js +517 -0
- package/skills/byteplan-ppt/SKILL.md +394 -0
- package/skills/byteplan-ppt/examples/margin-contribution-analysis.json +152 -0
- package/skills/byteplan-ppt/package.json +16 -0
- package/skills/byteplan-ppt/pnpm-lock.yaml +138 -0
- package/skills/byteplan-ppt/scripts/check_ppt_overlap.js +318 -0
- package/skills/byteplan-ppt/scripts/generate_ppt.js +680 -0
- package/skills/byteplan-video/SKILL.md +606 -0
- package/skills/byteplan-video/examples/sample-video-data.json +82 -0
- package/skills/byteplan-video/remotion-project/package.json +22 -0
- package/skills/byteplan-video/remotion-project/pnpm-lock.yaml +1646 -0
- package/skills/byteplan-video/remotion-project/remotion.config.ts +6 -0
- package/skills/byteplan-video/remotion-project/scene_durations.json +32 -0
- package/skills/byteplan-video/remotion-project/scripts/generate_audio.js +279 -0
- package/skills/byteplan-video/remotion-project/src/DynamicReport.tsx +172 -0
- package/skills/byteplan-video/remotion-project/src/Root.tsx +51 -0
- package/skills/byteplan-video/remotion-project/src/SalesReport.tsx +107 -0
- package/skills/byteplan-video/remotion-project/src/index.tsx +4 -0
- package/skills/byteplan-video/remotion-project/src/scenes/ChartSlide.tsx +201 -0
- package/skills/byteplan-video/remotion-project/src/scenes/CoverSlide.tsx +61 -0
- package/skills/byteplan-video/remotion-project/src/scenes/EndSlide.tsx +60 -0
- package/skills/byteplan-video/remotion-project/src/scenes/InsightSlide.tsx +101 -0
- package/skills/byteplan-video/remotion-project/src/scenes/KpiSlide.tsx +84 -0
- package/skills/byteplan-video/remotion-project/src/scenes/RecommendationSlide.tsx +100 -0
- package/skills/byteplan-video/remotion-project/tsconfig.json +13 -0
- package/skills/byteplan-video/remotion-project/video_data.json +76 -0
- package/skills/byteplan-video/scripts/generate_video.js +270 -0
- package/skills/byteplan-video/templates/package.json +31 -0
- package/skills/byteplan-video/templates/pnpm-lock.yaml +2200 -0
- package/skills/byteplan-video/templates/remotion.config.ts +9 -0
- package/skills/byteplan-video/templates/scripts/generate-audio.ts +55 -0
- package/skills/byteplan-video/templates/src/components/BarChartScene.tsx +153 -0
- package/skills/byteplan-video/templates/src/components/InsightScene.tsx +135 -0
- package/skills/byteplan-video/templates/src/components/LineChartScene.tsx +214 -0
- package/skills/byteplan-video/templates/src/components/SceneFactory.tsx +34 -0
- package/skills/byteplan-video/templates/src/components/SummaryScene.tsx +155 -0
- package/skills/byteplan-video/templates/src/components/TitleScene.tsx +130 -0
- package/skills/byteplan-video/templates/src/compositions/AnalysisVideo.tsx +39 -0
- package/skills/byteplan-video/templates/src/index.tsx +28 -0
- package/skills/byteplan-video/templates/src/register-root.tsx +4 -0
- package/skills/byteplan-video/templates/src/storyboard/types.ts +46 -0
- package/skills/byteplan-video/templates/tsconfig.json +17 -0
- package/skills/byteplan-video/templates/tsconfig.scripts.json +13 -0
- package/skills/byteplan-word/SKILL.md +233 -0
- package/skills/byteplan-word/package.json +12 -0
- package/skills/byteplan-word/pnpm-lock.yaml +120 -0
- package/skills/byteplan-word/scripts/generate_word.js +548 -0
- package/src/cli.js +4 -0
- package/src/commands/skills.js +279 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Skills management commands for BytePlan CLI
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { existsSync, mkdirSync, readdirSync, cpSync, readFileSync } from 'fs';
|
|
11
|
+
import { createRequire } from 'module';
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
// Skills 源目录(在 npm 包中)
|
|
16
|
+
const getSkillsSourceDir = () => {
|
|
17
|
+
// 获取当前模块所在目录,然后向上找到项目根目录
|
|
18
|
+
const currentDir = path.dirname(new URL(import.meta.url).pathname);
|
|
19
|
+
// 从 src/commands/skills.js -> src -> 项目根目录 -> skills
|
|
20
|
+
return path.join(currentDir, '..', '..', 'skills');
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Skills 默认目标目录(仅用于提示)
|
|
24
|
+
const getDefaultSkillsTargetDir = () => {
|
|
25
|
+
return path.join(homedir(), '.claude', 'skills');
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function printJSON(data) {
|
|
29
|
+
console.log(JSON.stringify(data, null, 2));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function printError(error) {
|
|
33
|
+
printJSON({ error: true, message: error.message });
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 获取 skill 信息
|
|
38
|
+
function getSkillInfo(skillPath) {
|
|
39
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
40
|
+
if (!existsSync(skillMdPath)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const content = readFileSync(skillMdPath, 'utf-8');
|
|
45
|
+
|
|
46
|
+
// 解析 frontmatter
|
|
47
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
48
|
+
if (!frontmatterMatch) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const frontmatter = frontmatterMatch[1];
|
|
53
|
+
const nameMatch = frontmatter.match(/name:\s*(.+)/);
|
|
54
|
+
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
name: nameMatch ? nameMatch[1].trim() : path.basename(skillPath),
|
|
58
|
+
description: descMatch ? descMatch[1].trim() : '',
|
|
59
|
+
path: skillPath,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 获取所有可用 skills
|
|
64
|
+
function getAvailableSkills() {
|
|
65
|
+
const sourceDir = getSkillsSourceDir();
|
|
66
|
+
if (!existsSync(sourceDir)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const skills = [];
|
|
71
|
+
const dirs = readdirSync(sourceDir, { withFileTypes: true });
|
|
72
|
+
|
|
73
|
+
for (const dir of dirs) {
|
|
74
|
+
if (dir.isDirectory()) {
|
|
75
|
+
const skillPath = path.join(sourceDir, dir.name);
|
|
76
|
+
const info = getSkillInfo(skillPath);
|
|
77
|
+
if (info) {
|
|
78
|
+
skills.push(info);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return skills;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 获取已安装的 skills(支持自定义目录)
|
|
87
|
+
function getInstalledSkills(targetDir) {
|
|
88
|
+
if (!existsSync(targetDir)) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const skills = [];
|
|
93
|
+
const dirs = readdirSync(targetDir, { withFileTypes: true });
|
|
94
|
+
|
|
95
|
+
for (const dir of dirs) {
|
|
96
|
+
if (dir.isDirectory() && dir.name.startsWith('byteplan-')) {
|
|
97
|
+
const skillPath = path.join(targetDir, dir.name);
|
|
98
|
+
const info = getSkillInfo(skillPath);
|
|
99
|
+
if (info) {
|
|
100
|
+
skills.push(info);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return skills;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Skills 命令
|
|
109
|
+
const skillsCmd = new Command('skills')
|
|
110
|
+
.description('Manage BytePlan Claude Code skills')
|
|
111
|
+
.requiredOption('-d, --dir <directory>', 'Target installation directory (required)')
|
|
112
|
+
.addHelpText('after', `
|
|
113
|
+
Commands:
|
|
114
|
+
skills list List all available skills
|
|
115
|
+
skills installed List installed skills (requires -d)
|
|
116
|
+
skills install [names] Install skills to target directory (requires -d)
|
|
117
|
+
skills install-all Install all BytePlan skills (requires -d)
|
|
118
|
+
|
|
119
|
+
Examples:
|
|
120
|
+
$ byteplan skills list
|
|
121
|
+
$ byteplan skills installed -d ~/.claude/skills
|
|
122
|
+
$ byteplan skills install byteplan-api byteplan-analysis -d ~/.claude/skills
|
|
123
|
+
$ byteplan skills install-all -d ~/.claude/skills
|
|
124
|
+
$ byteplan skills install-all -d /custom/path/skills
|
|
125
|
+
`);
|
|
126
|
+
|
|
127
|
+
// skills list 子命令
|
|
128
|
+
skillsCmd
|
|
129
|
+
.command('list')
|
|
130
|
+
.description('List all available BytePlan skills')
|
|
131
|
+
.action(() => {
|
|
132
|
+
try {
|
|
133
|
+
const skills = getAvailableSkills();
|
|
134
|
+
|
|
135
|
+
printJSON({
|
|
136
|
+
skills: skills.map(s => ({
|
|
137
|
+
name: s.name,
|
|
138
|
+
description: s.description,
|
|
139
|
+
})),
|
|
140
|
+
total: skills.length,
|
|
141
|
+
sourceDir: getSkillsSourceDir(),
|
|
142
|
+
});
|
|
143
|
+
} catch (error) {
|
|
144
|
+
printError(error);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// skills installed 子命令
|
|
149
|
+
skillsCmd
|
|
150
|
+
.command('installed')
|
|
151
|
+
.description('List installed BytePlan skills in target directory')
|
|
152
|
+
.action(() => {
|
|
153
|
+
try {
|
|
154
|
+
// 获取父命令的 -d 选项(requiredOption 已确保必传)
|
|
155
|
+
const parentOptions = skillsCmd.opts();
|
|
156
|
+
const targetDir = parentOptions.dir;
|
|
157
|
+
const skills = getInstalledSkills(targetDir);
|
|
158
|
+
|
|
159
|
+
printJSON({
|
|
160
|
+
skills: skills.map(s => ({
|
|
161
|
+
name: s.name,
|
|
162
|
+
description: s.description,
|
|
163
|
+
})),
|
|
164
|
+
total: skills.length,
|
|
165
|
+
targetDir: targetDir,
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
printError(error);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// skills install 子命令
|
|
173
|
+
skillsCmd
|
|
174
|
+
.command('install [names...]')
|
|
175
|
+
.description('Install specified skills to target directory')
|
|
176
|
+
.option('-a, --all', 'Install all BytePlan skills', false)
|
|
177
|
+
.addHelpText('after', `
|
|
178
|
+
Examples:
|
|
179
|
+
$ byteplan skills install byteplan-api byteplan-analysis -d ~/.claude/skills
|
|
180
|
+
$ byteplan skills install --all -d ~/.claude/skills
|
|
181
|
+
$ byteplan skills install byteplan-api -d /custom/path/skills
|
|
182
|
+
`)
|
|
183
|
+
.action(async (names, options) => {
|
|
184
|
+
try {
|
|
185
|
+
// 获取父命令的 -d 选项(requiredOption 已确保必传)
|
|
186
|
+
const parentOptions = skillsCmd.opts();
|
|
187
|
+
const targetDir = parentOptions.dir;
|
|
188
|
+
const sourceDir = getSkillsSourceDir();
|
|
189
|
+
|
|
190
|
+
// 确保目标目录存在
|
|
191
|
+
if (!existsSync(targetDir)) {
|
|
192
|
+
mkdirSync(targetDir, { recursive: true });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 获取要安装的 skills
|
|
196
|
+
let toInstall = names || [];
|
|
197
|
+
if (options.all || toInstall.length === 0) {
|
|
198
|
+
const available = getAvailableSkills();
|
|
199
|
+
toInstall = available.map(s => s.name);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 验证 skills 存在
|
|
203
|
+
const availableSkills = getAvailableSkills();
|
|
204
|
+
const availableNames = availableSkills.map(s => s.name);
|
|
205
|
+
|
|
206
|
+
const invalid = toInstall.filter(n => !availableNames.includes(n));
|
|
207
|
+
if (invalid.length > 0) {
|
|
208
|
+
printJSON({
|
|
209
|
+
error: true,
|
|
210
|
+
message: `Unknown skills: ${invalid.join(', ')}`,
|
|
211
|
+
available: availableNames,
|
|
212
|
+
});
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 安装 skills
|
|
217
|
+
const installed = [];
|
|
218
|
+
for (const skillName of toInstall) {
|
|
219
|
+
const skillSourcePath = path.join(sourceDir, skillName);
|
|
220
|
+
const skillTargetPath = path.join(targetDir, skillName);
|
|
221
|
+
|
|
222
|
+
// 复制 skill 目录
|
|
223
|
+
cpSync(skillSourcePath, skillTargetPath, { recursive: true });
|
|
224
|
+
installed.push(skillName);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
printJSON({
|
|
228
|
+
success: true,
|
|
229
|
+
installed: installed,
|
|
230
|
+
total: installed.length,
|
|
231
|
+
targetDir: targetDir,
|
|
232
|
+
});
|
|
233
|
+
} catch (error) {
|
|
234
|
+
printError(error);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// skills install-all 子命令(快捷方式)
|
|
239
|
+
skillsCmd
|
|
240
|
+
.command('install-all')
|
|
241
|
+
.description('Install all BytePlan skills to target directory')
|
|
242
|
+
.action(async () => {
|
|
243
|
+
try {
|
|
244
|
+
// 获取父命令的 -d 选项(requiredOption 已确保必传)
|
|
245
|
+
const parentOptions = skillsCmd.opts();
|
|
246
|
+
const targetDir = parentOptions.dir;
|
|
247
|
+
const sourceDir = getSkillsSourceDir();
|
|
248
|
+
|
|
249
|
+
// 确保目标目录存在
|
|
250
|
+
if (!existsSync(targetDir)) {
|
|
251
|
+
mkdirSync(targetDir, { recursive: true });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 获取所有 skills
|
|
255
|
+
const availableSkills = getAvailableSkills();
|
|
256
|
+
|
|
257
|
+
// 安装所有 skills
|
|
258
|
+
const installed = [];
|
|
259
|
+
for (const skill of availableSkills) {
|
|
260
|
+
const skillSourcePath = path.join(sourceDir, skill.name);
|
|
261
|
+
const skillTargetPath = path.join(targetDir, skill.name);
|
|
262
|
+
|
|
263
|
+
// 复制 skill 目录
|
|
264
|
+
cpSync(skillSourcePath, skillTargetPath, { recursive: true });
|
|
265
|
+
installed.push(skill.name);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
printJSON({
|
|
269
|
+
success: true,
|
|
270
|
+
installed: installed,
|
|
271
|
+
total: installed.length,
|
|
272
|
+
targetDir: targetDir,
|
|
273
|
+
});
|
|
274
|
+
} catch (error) {
|
|
275
|
+
printError(error);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
export { skillsCmd };
|