tools-cc 1.0.6 → 1.0.8
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/CHANGELOG.md +31 -0
- package/CHANGELOG_en.md +31 -0
- package/README.md +10 -4
- package/README_en.md +56 -4
- package/dist/commands/help.js +31 -4
- package/dist/commands/template.d.ts +18 -0
- package/dist/commands/template.js +154 -0
- package/dist/commands/use.d.ts +2 -2
- package/dist/commands/use.js +40 -35
- package/dist/core/template.d.ts +17 -0
- package/dist/core/template.js +74 -0
- package/dist/index.js +32 -0
- package/dist/types/config.d.ts +10 -0
- package/dist/utils/path.d.ts +2 -0
- package/dist/utils/path.js +6 -1
- package/package.json +3 -3
- package/src/commands/help.ts +31 -4
- package/src/commands/template.ts +160 -0
- package/src/commands/use.ts +12 -6
- package/src/core/template.ts +91 -0
- package/src/index.ts +48 -11
- package/src/types/config.ts +112 -101
- package/src/utils/path.ts +23 -18
- package/tests/commands/export.test.ts +120 -0
- package/tests/commands/use.test.ts +326 -0
- package/tests/core/config.test.ts +37 -0
- package/tests/core/manifest.test.ts +37 -0
- package/tests/core/project.test.ts +317 -0
- package/tests/core/source.test.ts +75 -0
- package/tests/core/symlink.test.ts +39 -0
- package/tests/core/template.test.ts +103 -0
- package/tests/types/config.test.ts +232 -0
- package/tests/utils/parsePath.test.ts +235 -0
package/dist/commands/use.js
CHANGED
|
@@ -11,6 +11,7 @@ exports.handleProjectUpdate = handleProjectUpdate;
|
|
|
11
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
12
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
13
13
|
const project_1 = require("../core/project");
|
|
14
|
+
const config_1 = require("../types/config");
|
|
14
15
|
const source_1 = require("../core/source");
|
|
15
16
|
const manifest_1 = require("../core/manifest");
|
|
16
17
|
const symlink_1 = require("../core/symlink");
|
|
@@ -28,12 +29,12 @@ const SUPPORTED_TOOLS = {
|
|
|
28
29
|
/**
|
|
29
30
|
* 处理 use 命令
|
|
30
31
|
*
|
|
31
|
-
*
|
|
32
|
+
* 支持多种模式:
|
|
32
33
|
* 1. 配置导入模式: tools-cc use -c config.json
|
|
33
34
|
* 2. 交互选择模式: tools-cc use my-source --ls
|
|
34
35
|
* 3. 路径语法模式: tools-cc use my-source/skills/a-skill
|
|
35
36
|
* 4. 整体导入模式: tools-cc use my-source
|
|
36
|
-
* 5.
|
|
37
|
+
* 5. 点模式: tools-cc use . (使用已配置源)
|
|
37
38
|
*/
|
|
38
39
|
async function handleUse(sourceSpecs, options) {
|
|
39
40
|
const projectDir = process.cwd();
|
|
@@ -44,7 +45,7 @@ async function handleUse(sourceSpecs, options) {
|
|
|
44
45
|
await handleConfigImportMode(options.config, projectDir, options.projects);
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
47
|
-
// 2.
|
|
48
|
+
// 2. 点模式:使用当前项目已配置的源
|
|
48
49
|
if (sourceSpecs.length === 1 && sourceSpecs[0] === '.') {
|
|
49
50
|
await handleDotMode(projectDir, toolsccDir, configFile, options.projects);
|
|
50
51
|
return;
|
|
@@ -52,7 +53,7 @@ async function handleUse(sourceSpecs, options) {
|
|
|
52
53
|
// 3. 交互选择模式:单个源 + --ls 选项
|
|
53
54
|
if (options.ls && sourceSpecs.length === 1) {
|
|
54
55
|
const parsed = (0, parsePath_1.parseSourcePath)(sourceSpecs[0]);
|
|
55
|
-
//
|
|
56
|
+
// 只有源名称时才进入交互模式
|
|
56
57
|
if (!parsed.type && parsed.sourceName) {
|
|
57
58
|
await handleInteractiveMode(parsed.sourceName, projectDir, options.projects);
|
|
58
59
|
return;
|
|
@@ -68,17 +69,17 @@ async function handleUse(sourceSpecs, options) {
|
|
|
68
69
|
}
|
|
69
70
|
// 5. 解析路径语法并构建选择配置
|
|
70
71
|
const selectionMap = (0, parsePath_1.buildSelectionFromPaths)(sourceSpecs);
|
|
71
|
-
//
|
|
72
|
+
// 初始化项目
|
|
72
73
|
await (0, project_1.initProject)(projectDir);
|
|
73
74
|
// 应用每个源的选择配置
|
|
74
75
|
for (const [sourceName, selection] of Object.entries(selectionMap)) {
|
|
75
76
|
try {
|
|
76
77
|
const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
|
|
77
78
|
await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
|
|
78
|
-
console.log(chalk_1.default.green(
|
|
79
|
+
console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
|
|
79
80
|
}
|
|
80
81
|
catch (error) {
|
|
81
|
-
console.log(chalk_1.default.red(
|
|
82
|
+
console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
// 创建符号链接
|
|
@@ -93,18 +94,18 @@ async function handleConfigImportMode(configPath, projectDir, projects) {
|
|
|
93
94
|
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
94
95
|
// 解析配置文件路径
|
|
95
96
|
const resolvedPath = path_2.default.resolve(configPath);
|
|
96
|
-
//
|
|
97
|
+
// 定义源路径解析函数
|
|
97
98
|
const resolveSourcePath = async (sourceName) => {
|
|
98
99
|
return await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
|
|
99
100
|
};
|
|
100
101
|
// 导入配置
|
|
101
102
|
await (0, project_1.importProjectConfig)(resolvedPath, projectDir, resolveSourcePath);
|
|
102
|
-
console.log(chalk_1.default.green(
|
|
103
|
+
console.log(chalk_1.default.green(`✓ Imported config from: ${resolvedPath}`));
|
|
103
104
|
// 创建符号链接
|
|
104
105
|
await createToolLinks(projectDir, toolsccDir, configFile, projects);
|
|
105
106
|
}
|
|
106
107
|
catch (error) {
|
|
107
|
-
console.log(chalk_1.default.red(
|
|
108
|
+
console.log(chalk_1.default.red(`✗ Failed to import config: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
/**
|
|
@@ -125,7 +126,7 @@ async function handleDotMode(projectDir, toolsccDir, configFile, projects) {
|
|
|
125
126
|
await createToolLinks(projectDir, toolsccDir, configFile, projects);
|
|
126
127
|
}
|
|
127
128
|
/**
|
|
128
|
-
*
|
|
129
|
+
* 交互选择模式:显示技能/命令/代理选择列表
|
|
129
130
|
*/
|
|
130
131
|
async function handleInteractiveMode(sourceName, projectDir, projects) {
|
|
131
132
|
try {
|
|
@@ -134,21 +135,21 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
|
|
|
134
135
|
// 构建选项列表
|
|
135
136
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
137
|
const choices = [];
|
|
137
|
-
// Skills
|
|
138
|
+
// Skills 区
|
|
138
139
|
if (manifest.skills && manifest.skills.length > 0) {
|
|
139
140
|
choices.push(new inquirer_1.default.Separator(`--- Skills (${manifest.skills.length}) ---`));
|
|
140
141
|
for (const skill of manifest.skills) {
|
|
141
142
|
choices.push({ name: skill, value: `skills/${skill}` });
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
|
-
// Commands
|
|
145
|
+
// Commands 区
|
|
145
146
|
if (manifest.commands && manifest.commands.length > 0) {
|
|
146
147
|
choices.push(new inquirer_1.default.Separator(`--- Commands (${manifest.commands.length}) ---`));
|
|
147
148
|
for (const cmd of manifest.commands) {
|
|
148
149
|
choices.push({ name: cmd, value: `commands/${cmd}` });
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
|
-
// Agents
|
|
152
|
+
// Agents 区
|
|
152
153
|
if (manifest.agents && manifest.agents.length > 0) {
|
|
153
154
|
choices.push(new inquirer_1.default.Separator(`--- Agents (${manifest.agents.length}) ---`));
|
|
154
155
|
for (const agent of manifest.agents) {
|
|
@@ -173,7 +174,7 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
|
|
|
173
174
|
console.log(chalk_1.default.gray('No items selected.'));
|
|
174
175
|
return;
|
|
175
176
|
}
|
|
176
|
-
//
|
|
177
|
+
// 将选择转换为 SourceSelection
|
|
177
178
|
const selection = {
|
|
178
179
|
skills: [],
|
|
179
180
|
commands: [],
|
|
@@ -191,14 +192,14 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
|
|
|
191
192
|
// 初始化项目并应用选择
|
|
192
193
|
await (0, project_1.initProject)(projectDir);
|
|
193
194
|
await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
|
|
194
|
-
console.log(chalk_1.default.green(
|
|
195
|
+
console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
|
|
195
196
|
// 创建符号链接
|
|
196
197
|
const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
|
|
197
198
|
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
198
199
|
await createToolLinks(projectDir, toolsccDir, configFile, projects);
|
|
199
200
|
}
|
|
200
201
|
catch (error) {
|
|
201
|
-
console.log(chalk_1.default.red(
|
|
202
|
+
console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
202
203
|
}
|
|
203
204
|
}
|
|
204
205
|
/**
|
|
@@ -235,10 +236,10 @@ async function createToolLinks(projectDir, toolsccDir, configFile, projects) {
|
|
|
235
236
|
const linkPath = path_2.default.join(projectDir, linkName);
|
|
236
237
|
try {
|
|
237
238
|
await (0, symlink_1.createSymlink)(toolsccDir, linkPath, true);
|
|
238
|
-
console.log(chalk_1.default.green(
|
|
239
|
+
console.log(chalk_1.default.green(`✓ Linked: ${linkName} -> .toolscc`));
|
|
239
240
|
}
|
|
240
241
|
catch (error) {
|
|
241
|
-
console.log(chalk_1.default.red(
|
|
242
|
+
console.log(chalk_1.default.red(`✗ Failed to link ${linkName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
// 更新项目配置
|
|
@@ -263,10 +264,10 @@ async function handleRemove(sourceName) {
|
|
|
263
264
|
const projectDir = process.cwd();
|
|
264
265
|
try {
|
|
265
266
|
await (0, project_1.unuseSource)(sourceName, projectDir);
|
|
266
|
-
console.log(chalk_1.default.green(
|
|
267
|
+
console.log(chalk_1.default.green(`✓ Removed source: ${sourceName}`));
|
|
267
268
|
}
|
|
268
269
|
catch (error) {
|
|
269
|
-
console.log(chalk_1.default.red(
|
|
270
|
+
console.log(chalk_1.default.red(`✗ ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
270
271
|
}
|
|
271
272
|
}
|
|
272
273
|
async function handleStatus() {
|
|
@@ -274,12 +275,12 @@ async function handleStatus() {
|
|
|
274
275
|
const sources = await (0, project_1.listUsedSources)(projectDir);
|
|
275
276
|
console.log(chalk_1.default.bold('\nProject Status:'));
|
|
276
277
|
console.log(chalk_1.default.gray(` Directory: ${projectDir}`));
|
|
277
|
-
//
|
|
278
|
+
// 检查 .toolscc
|
|
278
279
|
const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
|
|
279
280
|
console.log(` .toolscc: ${await fs_extra_1.default.pathExists(toolsccDir) ? chalk_1.default.green('exists') : chalk_1.default.red('not found')}`);
|
|
280
|
-
//
|
|
281
|
+
// 检查 sources
|
|
281
282
|
console.log(` Sources: ${sources.length > 0 ? sources.map(s => chalk_1.default.cyan(s)).join(', ') : chalk_1.default.gray('none')}`);
|
|
282
|
-
//
|
|
283
|
+
// 检查 links
|
|
283
284
|
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
284
285
|
if (await fs_extra_1.default.pathExists(configFile)) {
|
|
285
286
|
const config = await fs_extra_1.default.readJson(configFile);
|
|
@@ -298,40 +299,44 @@ async function handleStatus() {
|
|
|
298
299
|
async function handleProjectUpdate(sourceNames) {
|
|
299
300
|
const projectDir = process.cwd();
|
|
300
301
|
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
301
|
-
//
|
|
302
|
+
// 检查项目是否已初始化
|
|
302
303
|
if (!(await fs_extra_1.default.pathExists(configFile))) {
|
|
303
304
|
console.log(chalk_1.default.yellow('Project not initialized. Run `tools-cc use <source>` first.'));
|
|
304
305
|
return;
|
|
305
306
|
}
|
|
306
|
-
const
|
|
307
|
+
const rawConfig = await fs_extra_1.default.readJson(configFile);
|
|
308
|
+
// 使用 normalizeProjectConfig 处理旧版(数组)和新版(对象)格式
|
|
309
|
+
const config = (0, config_1.normalizeProjectConfig)(rawConfig);
|
|
307
310
|
const configuredSources = Object.keys(config.sources || {});
|
|
308
|
-
|
|
309
|
-
|
|
311
|
+
// 过滤掉无效的源名称(如数字字符串),这些可能是 Commander.js 解析错误产生的
|
|
312
|
+
const validSourceNames = sourceNames?.filter(s => isNaN(Number(s))) || [];
|
|
313
|
+
let sourcesToUpdate = validSourceNames.length > 0
|
|
314
|
+
? validSourceNames
|
|
310
315
|
: configuredSources;
|
|
311
316
|
if (sourcesToUpdate.length === 0) {
|
|
312
317
|
console.log(chalk_1.default.gray('No sources to update.'));
|
|
313
318
|
return;
|
|
314
319
|
}
|
|
315
|
-
//
|
|
316
|
-
if (
|
|
317
|
-
const invalidSources =
|
|
320
|
+
// 验证指定的源是否存在于项目配置中(仅当用户明确指定了有效源名称时)
|
|
321
|
+
if (validSourceNames.length > 0) {
|
|
322
|
+
const invalidSources = validSourceNames.filter((s) => !configuredSources.includes(s));
|
|
318
323
|
if (invalidSources.length > 0) {
|
|
319
324
|
console.log(chalk_1.default.yellow(`Sources not in project: ${invalidSources.join(', ')}`));
|
|
320
325
|
}
|
|
321
326
|
sourcesToUpdate = sourcesToUpdate.filter((s) => configuredSources.includes(s));
|
|
322
327
|
}
|
|
323
|
-
//
|
|
328
|
+
// 更新每个配置源
|
|
324
329
|
for (const sourceName of sourcesToUpdate) {
|
|
325
330
|
try {
|
|
326
331
|
const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
|
|
327
332
|
// 使用保存的选择配置进行更新
|
|
328
333
|
const selection = config.sources[sourceName];
|
|
329
334
|
await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
|
|
330
|
-
console.log(chalk_1.default.green(
|
|
335
|
+
console.log(chalk_1.default.green(`✓ Updated source: ${sourceName}`));
|
|
331
336
|
}
|
|
332
337
|
catch (error) {
|
|
333
|
-
console.log(chalk_1.default.red(
|
|
338
|
+
console.log(chalk_1.default.red(`✗ Failed to update ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
334
339
|
}
|
|
335
340
|
}
|
|
336
|
-
console.log(chalk_1.default.green(`\n
|
|
341
|
+
console.log(chalk_1.default.green(`\n✓ Project update complete`));
|
|
337
342
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TemplateConfig, ProjectConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 保存项目配置为模板
|
|
4
|
+
*/
|
|
5
|
+
export declare function saveTemplate(name: string, sourceProject: string, config: ProjectConfig, templatesDir: string): Promise<TemplateConfig>;
|
|
6
|
+
/**
|
|
7
|
+
* 列出所有模板
|
|
8
|
+
*/
|
|
9
|
+
export declare function listTemplates(templatesDir: string): Promise<TemplateConfig[]>;
|
|
10
|
+
/**
|
|
11
|
+
* 获取指定模板
|
|
12
|
+
*/
|
|
13
|
+
export declare function getTemplate(name: string, templatesDir: string): Promise<TemplateConfig | null>;
|
|
14
|
+
/**
|
|
15
|
+
* 删除模板
|
|
16
|
+
*/
|
|
17
|
+
export declare function removeTemplate(name: string, templatesDir: string): Promise<void>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.saveTemplate = saveTemplate;
|
|
7
|
+
exports.listTemplates = listTemplates;
|
|
8
|
+
exports.getTemplate = getTemplate;
|
|
9
|
+
exports.removeTemplate = removeTemplate;
|
|
10
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
/**
|
|
13
|
+
* 保存项目配置为模板
|
|
14
|
+
*/
|
|
15
|
+
async function saveTemplate(name, sourceProject, config, templatesDir) {
|
|
16
|
+
if (!name || !name.trim()) {
|
|
17
|
+
throw new Error('Template name is required');
|
|
18
|
+
}
|
|
19
|
+
await fs_extra_1.default.ensureDir(templatesDir);
|
|
20
|
+
const template = {
|
|
21
|
+
version: '1.0',
|
|
22
|
+
name,
|
|
23
|
+
sourceProject,
|
|
24
|
+
savedAt: new Date().toISOString(),
|
|
25
|
+
config
|
|
26
|
+
};
|
|
27
|
+
const templatePath = path_1.default.join(templatesDir, `${name}.json`);
|
|
28
|
+
await fs_extra_1.default.writeJson(templatePath, template, { spaces: 2 });
|
|
29
|
+
return template;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 列出所有模板
|
|
33
|
+
*/
|
|
34
|
+
async function listTemplates(templatesDir) {
|
|
35
|
+
if (!(await fs_extra_1.default.pathExists(templatesDir))) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const files = await fs_extra_1.default.readdir(templatesDir);
|
|
39
|
+
const templates = [];
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
if (file.endsWith('.json')) {
|
|
42
|
+
try {
|
|
43
|
+
const template = await fs_extra_1.default.readJson(path_1.default.join(templatesDir, file));
|
|
44
|
+
if (template.version && template.name && template.config) {
|
|
45
|
+
templates.push(template);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Skip invalid files
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return templates.sort((a, b) => b.savedAt.localeCompare(a.savedAt));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 获取指定模板
|
|
57
|
+
*/
|
|
58
|
+
async function getTemplate(name, templatesDir) {
|
|
59
|
+
const templatePath = path_1.default.join(templatesDir, `${name}.json`);
|
|
60
|
+
if (!(await fs_extra_1.default.pathExists(templatePath))) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return await fs_extra_1.default.readJson(templatePath);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 删除模板
|
|
67
|
+
*/
|
|
68
|
+
async function removeTemplate(name, templatesDir) {
|
|
69
|
+
const templatePath = path_1.default.join(templatesDir, `${name}.json`);
|
|
70
|
+
if (!(await fs_extra_1.default.pathExists(templatePath))) {
|
|
71
|
+
throw new Error(`Template not found: ${name}`);
|
|
72
|
+
}
|
|
73
|
+
await fs_extra_1.default.remove(templatePath);
|
|
74
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const config_1 = require("./commands/config");
|
|
|
6
6
|
const source_1 = require("./commands/source");
|
|
7
7
|
const use_1 = require("./commands/use");
|
|
8
8
|
const export_1 = require("./commands/export");
|
|
9
|
+
const template_1 = require("./commands/template");
|
|
9
10
|
const help_1 = require("./commands/help");
|
|
10
11
|
const program = new commander_1.Command();
|
|
11
12
|
program
|
|
@@ -76,6 +77,37 @@ configCmd
|
|
|
76
77
|
.action(async () => {
|
|
77
78
|
await (0, config_1.handleConfigList)();
|
|
78
79
|
});
|
|
80
|
+
// Template commands
|
|
81
|
+
const templateCmd = program
|
|
82
|
+
.command('template')
|
|
83
|
+
.description('Template management')
|
|
84
|
+
.alias('tpl');
|
|
85
|
+
templateCmd
|
|
86
|
+
.command('save')
|
|
87
|
+
.description('Save current project config as template')
|
|
88
|
+
.option('-n, --name <name>', 'Template name (default: project directory name)')
|
|
89
|
+
.action(async (options) => {
|
|
90
|
+
await (0, template_1.handleTemplateSave)(options);
|
|
91
|
+
});
|
|
92
|
+
templateCmd
|
|
93
|
+
.command('list')
|
|
94
|
+
.alias('ls')
|
|
95
|
+
.description('List all saved templates')
|
|
96
|
+
.action(async () => {
|
|
97
|
+
await (0, template_1.handleTemplateList)();
|
|
98
|
+
});
|
|
99
|
+
templateCmd
|
|
100
|
+
.command('rm <name>')
|
|
101
|
+
.description('Remove a template')
|
|
102
|
+
.action(async (name) => {
|
|
103
|
+
await (0, template_1.handleTemplateRemove)(name);
|
|
104
|
+
});
|
|
105
|
+
templateCmd
|
|
106
|
+
.command('use [name]')
|
|
107
|
+
.description('Apply a template to current project')
|
|
108
|
+
.action(async (name) => {
|
|
109
|
+
await (0, template_1.handleTemplateUse)(name);
|
|
110
|
+
});
|
|
79
111
|
// Project commands
|
|
80
112
|
program
|
|
81
113
|
.command('use [sources...]')
|
package/dist/types/config.d.ts
CHANGED
|
@@ -66,3 +66,13 @@ export interface GlobalExportConfig {
|
|
|
66
66
|
config: GlobalConfig;
|
|
67
67
|
exportedAt: string;
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* 模板配置格式
|
|
71
|
+
*/
|
|
72
|
+
export interface TemplateConfig {
|
|
73
|
+
version: string;
|
|
74
|
+
name: string;
|
|
75
|
+
sourceProject: string;
|
|
76
|
+
savedAt: string;
|
|
77
|
+
config: ProjectConfig;
|
|
78
|
+
}
|
package/dist/utils/path.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export declare const GLOBAL_CONFIG_DIR: string;
|
|
2
2
|
export declare const GLOBAL_CONFIG_FILE: string;
|
|
3
|
+
export declare const TEMPLATES_DIR: string;
|
|
3
4
|
export declare const DEFAULT_CONFIG: {
|
|
4
5
|
sourcesDir: string;
|
|
5
6
|
sources: {};
|
|
6
7
|
};
|
|
8
|
+
export declare function getTemplatePath(templateName: string): string;
|
|
7
9
|
export declare function getToolsccDir(projectDir: string): string;
|
|
8
10
|
export declare function getProjectConfigPath(projectDir: string): string;
|
package/dist/utils/path.js
CHANGED
|
@@ -3,17 +3,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DEFAULT_CONFIG = exports.GLOBAL_CONFIG_FILE = exports.GLOBAL_CONFIG_DIR = void 0;
|
|
6
|
+
exports.DEFAULT_CONFIG = exports.TEMPLATES_DIR = exports.GLOBAL_CONFIG_FILE = exports.GLOBAL_CONFIG_DIR = void 0;
|
|
7
|
+
exports.getTemplatePath = getTemplatePath;
|
|
7
8
|
exports.getToolsccDir = getToolsccDir;
|
|
8
9
|
exports.getProjectConfigPath = getProjectConfigPath;
|
|
9
10
|
const os_1 = __importDefault(require("os"));
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
11
12
|
exports.GLOBAL_CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.tools-cc');
|
|
12
13
|
exports.GLOBAL_CONFIG_FILE = path_1.default.join(exports.GLOBAL_CONFIG_DIR, 'config.json');
|
|
14
|
+
exports.TEMPLATES_DIR = path_1.default.join(exports.GLOBAL_CONFIG_DIR, 'templates');
|
|
13
15
|
exports.DEFAULT_CONFIG = {
|
|
14
16
|
sourcesDir: path_1.default.join(exports.GLOBAL_CONFIG_DIR, 'sources'),
|
|
15
17
|
sources: {}
|
|
16
18
|
};
|
|
19
|
+
function getTemplatePath(templateName) {
|
|
20
|
+
return path_1.default.join(exports.TEMPLATES_DIR, `${templateName}.json`);
|
|
21
|
+
}
|
|
17
22
|
function getToolsccDir(projectDir) {
|
|
18
23
|
return path_1.default.join(projectDir, '.toolscc');
|
|
19
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tools-cc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "tools-cc [options] <command> [args]",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"release": "npm run tag:create && npm run publish:npm && npm run release:gh"
|
|
19
19
|
},
|
|
20
20
|
"bin": {
|
|
21
|
-
"tools-cc": "
|
|
21
|
+
"tools-cc": "dist/index.js"
|
|
22
22
|
},
|
|
23
23
|
"keywords": [],
|
|
24
24
|
"author": "",
|
|
25
25
|
"license": "ISC",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/q759410559/tools-cc.git"
|
|
28
|
+
"url": "git+https://github.com/q759410559/tools-cc.git"
|
|
29
29
|
},
|
|
30
30
|
"bugs": {
|
|
31
31
|
"url": "https://github.com/q759410559/tools-cc/issues"
|
package/src/commands/help.ts
CHANGED
|
@@ -23,7 +23,8 @@ ${chalk.bold('COMMANDS / 命令')}
|
|
|
23
23
|
tools-cc sources add <name> <path-or-url> Add a source / 添加配置源
|
|
24
24
|
tools-cc sources list, ls List all sources / 列出所有配置源
|
|
25
25
|
tools-cc sources remove, rm <name> Remove a source / 移除配置源
|
|
26
|
-
tools-cc sources update, up [name]
|
|
26
|
+
tools-cc sources update, up [name] git pull update / 更新源代码
|
|
27
|
+
tools-cc sources scan Scan dir for sources / 扫描发现新源
|
|
27
28
|
|
|
28
29
|
${chalk.gray('Shortcut: -s')} e.g., tools-cc -s add my-skills https://github.com/user/skills.git
|
|
29
30
|
|
|
@@ -35,16 +36,27 @@ ${chalk.bold('COMMANDS / 命令')}
|
|
|
35
36
|
${chalk.gray('Shortcut: -c')} e.g., tools-cc -c set sourcesDir D:/skills
|
|
36
37
|
|
|
37
38
|
${chalk.cyan('Project Commands / 项目命令')}
|
|
38
|
-
tools-cc use [sources...] [
|
|
39
|
+
tools-cc use [sources...] [options] Use sources in project / 在项目中启用配置源
|
|
40
|
+
tools-cc update [sources...] Sync source content to project / 同步内容到项目
|
|
39
41
|
tools-cc list List used sources / 列出已启用的配置源
|
|
40
42
|
tools-cc rm <source> Remove source from project / 禁用配置源
|
|
41
43
|
tools-cc status Show project status / 显示项目状态
|
|
44
|
+
tools-cc export [options] Export config / 导出配置
|
|
42
45
|
|
|
43
46
|
${chalk.cyan('Help / 帮助')}
|
|
44
47
|
tools-cc help Show this help / 显示此帮助信息
|
|
45
48
|
tools-cc --help, -h Show command help / 显示命令帮助
|
|
46
49
|
tools-cc --version, -V Show version / 显示版本号
|
|
47
50
|
|
|
51
|
+
${chalk.bold('USE OPTIONS / use 命令选项')}
|
|
52
|
+
-p, --tools <tools...> Target tools (iflow, claude, etc.) / 目标工具
|
|
53
|
+
--ls Interactive selection / 交互式选择内容
|
|
54
|
+
-c, --config <file> Import from config file / 从配置文件导入
|
|
55
|
+
|
|
56
|
+
${chalk.bold('EXPORT OPTIONS / export 命令选项')}
|
|
57
|
+
-o, --output <file> Output file path / 输出文件路径
|
|
58
|
+
--global Export global config / 导出全局配置
|
|
59
|
+
|
|
48
60
|
${chalk.bold('SUPPORTED TOOLS / 支持的工具')}
|
|
49
61
|
iflow → .iflow
|
|
50
62
|
claude → .claude
|
|
@@ -59,21 +71,36 @@ ${chalk.bold('EXAMPLES / 示例')}
|
|
|
59
71
|
${chalk.gray('# Add a local source / 添加本地配置源')}
|
|
60
72
|
tools-cc sources add local-skills D:/path/to/local-skills
|
|
61
73
|
|
|
74
|
+
${chalk.gray('# Scan for sources / 扫描发现配置源')}
|
|
75
|
+
tools-cc sources scan
|
|
76
|
+
|
|
62
77
|
${chalk.gray('# List all sources / 列出所有配置源')}
|
|
63
78
|
tools-cc sources list
|
|
64
79
|
|
|
65
80
|
${chalk.gray('# Use sources in project / 在项目中启用配置源')}
|
|
66
81
|
tools-cc use my-skills -p iflow claude codex
|
|
67
82
|
|
|
83
|
+
${chalk.gray('# Interactive selection / 交互式选择内容')}
|
|
84
|
+
tools-cc use my-skills --ls
|
|
85
|
+
|
|
86
|
+
${chalk.gray('# Import from config file / 从配置文件导入')}
|
|
87
|
+
tools-cc use -c project-config.json
|
|
88
|
+
|
|
89
|
+
${chalk.gray('# Sync source content to project / 同步源内容到项目')}
|
|
90
|
+
tools-cc update my-skills
|
|
91
|
+
|
|
68
92
|
${chalk.gray('# Check project status / 检查项目状态')}
|
|
69
93
|
tools-cc status
|
|
70
94
|
|
|
95
|
+
${chalk.gray('# Export project config / 导出项目配置')}
|
|
96
|
+
tools-cc export -o my-config.json
|
|
97
|
+
|
|
71
98
|
${chalk.gray('# Show full configuration / 显示完整配置')}
|
|
72
99
|
tools-cc config list
|
|
73
100
|
|
|
74
101
|
${chalk.bold('MORE INFO / 更多信息')}
|
|
75
|
-
GitHub: https://github.com/
|
|
76
|
-
Docs: https://github.com/
|
|
102
|
+
GitHub: https://github.com/q759410559/tools-cc
|
|
103
|
+
Docs: https://github.com/q759410559/tools-cc#readme
|
|
77
104
|
|
|
78
105
|
${chalk.bold.cyan('═══════════════════════════════════════════════════════════════════════════')}
|
|
79
106
|
`);
|