yuanflow-cli 0.1.0 → 0.1.2
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/LICENSE +1 -1
- package/README.md +34 -50
- package/bin/yuanflow-cli.js +26 -0
- package/bin/yuanflow-skill.cjs +334 -0
- package/generated/registry.json +24641 -0
- package/lib/skill-installer/agents.cjs +203 -0
- package/lib/skill-installer/discover-skills.cjs +79 -0
- package/lib/skill-installer/installer.cjs +300 -0
- package/lib/skill-installer/publish.cjs +53 -0
- package/lib/skill-installer/repo-source.cjs +162 -0
- package/package.json +57 -6
- package/scripts/generate-registry.js +174 -0
- package/skills/yuanflow-skill/SKILL.md +60 -0
- package/skills/yuanflow-skill/yuanflow-cli/SKILL.md +207 -0
- package/src/agent-protocol.js +169 -0
- package/src/cli.js +382 -0
- package/src/config.js +31 -0
- package/src/registry.js +45 -0
- package/src/request.js +97 -0
- package/src/shortcuts.js +346 -0
- package/cli.js +0 -3
- package/src/ycloud/cli.js +0 -29
- package/src/ycloud/commands/analysis.js +0 -82
- package/src/ycloud/commands/auth.js +0 -191
- package/src/ycloud/commands/commands.js +0 -262
- package/src/ycloud/commands/compliance.js +0 -146
- package/src/ycloud/commands/config.js +0 -103
- package/src/ycloud/commands/health.js +0 -35
- package/src/ycloud/commands/index.js +0 -381
- package/src/ycloud/commands/kb.js +0 -82
- package/src/ycloud/commands/schema.js +0 -229
- package/src/ycloud/commands/shared.js +0 -30
- package/src/ycloud/commands/tool-registry.js +0 -209
- package/src/ycloud/commands/tool-runner.js +0 -226
- package/src/ycloud/commands/tool.js +0 -178
- package/src/ycloud/commands/version.js +0 -84
- package/src/ycloud/core/config.js +0 -78
- package/src/ycloud/core/http.js +0 -133
- package/src/ycloud/core/token.js +0 -30
- package/src/ycloud/resources/.gitkeep +0 -1
- package/src/ycloud/resources/tool_catalog_full.json +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,77 +1,61 @@
|
|
|
1
1
|
# yuanflow-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
YuanFlow 的 npm 包,包含两个命令入口:
|
|
4
|
+
|
|
5
|
+
- `yuanflow-cli`:社媒 API 转 CLI,覆盖完整 registry、快捷命令、schema、dry-run 和 agent-json 输出。
|
|
6
|
+
- `yuanflow-skill`:把 `YuanFlow-skill` 注入到本机支持的 AI Agent skills 目录。
|
|
4
7
|
|
|
5
8
|
## 安装
|
|
6
9
|
|
|
10
|
+
需要 Node.js 20 或更高版本。
|
|
11
|
+
|
|
7
12
|
```bash
|
|
8
13
|
npm install -g yuanflow-cli
|
|
9
14
|
```
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
推荐直接写入本地配置:
|
|
16
|
+
安装后可用:
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
|
-
|
|
19
|
+
yuanflow-cli --help
|
|
20
|
+
yuanflow-skill list-agents
|
|
17
21
|
```
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
## API CLI
|
|
20
24
|
|
|
21
25
|
```bash
|
|
22
|
-
|
|
26
|
+
yuanflow-cli config set-token <你的令牌>
|
|
27
|
+
yuanflow-cli config set-base-url https://open.yuanchuangai.com
|
|
28
|
+
yuanflow-cli douyin video-detail "https://v.douyin.com/xxx/" --format agent-json
|
|
29
|
+
yuanflow-cli shortcuts douyin
|
|
30
|
+
yuanflow-cli commands list
|
|
31
|
+
yuanflow-cli schema douyin.video-detail
|
|
32
|
+
yuanflow-cli list douyin
|
|
23
33
|
```
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
环境变量:
|
|
26
36
|
|
|
27
|
-
```
|
|
28
|
-
|
|
37
|
+
```bash
|
|
38
|
+
YUANFLOW_TOKEN=<你的令牌>
|
|
29
39
|
```
|
|
30
40
|
|
|
31
|
-
##
|
|
41
|
+
## Skill 安装器
|
|
32
42
|
|
|
33
43
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
yuanflow-skill list-agents
|
|
45
|
+
yuanflow-skill list-skills
|
|
46
|
+
yuanflow-skill install
|
|
47
|
+
yuanflow-skill install --agent codex,cursor
|
|
48
|
+
yuanflow-skill install --project
|
|
49
|
+
yuanflow-skill install --dry-run
|
|
50
|
+
yuanflow-skill uninstall --agent codex
|
|
38
51
|
```
|
|
39
52
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
发布包由仓库内独立的 NPM 封装目录维护,不直接在业务源码根目录做发包逻辑。
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
下面内容面向仓库维护者。
|
|
47
|
-
|
|
48
|
-
## 目录职责
|
|
49
|
-
|
|
50
|
-
- 独立维护 NPM 发布所需的 `package.json`
|
|
51
|
-
- 生成可发布的 `dist/` 目录
|
|
52
|
-
- 放安装说明、打包脚本、发布收口逻辑
|
|
53
|
+
安装器会自动发现 `YuanFlow-skill` 根目录和一级子目录中的 `SKILL.md`,并以 `yuanflow-skill` bundle 形式注入到目标 Agent。
|
|
53
54
|
|
|
54
|
-
##
|
|
55
|
+
## 开发检查
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
打包脚本会把这部分源码复制到:
|
|
61
|
-
|
|
62
|
-
- `./dist/src/ycloud`
|
|
63
|
-
|
|
64
|
-
这样做的目的很简单:
|
|
65
|
-
|
|
66
|
-
- NPM 封装逻辑和 CLI 主源码分离
|
|
67
|
-
- 后续调整发布逻辑时,不容易和 CLI 开发逻辑冲突
|
|
68
|
-
|
|
69
|
-
## 常用命令
|
|
70
|
-
|
|
71
|
-
```powershell
|
|
72
|
-
npm run build
|
|
73
|
-
npm run check:version-sync
|
|
74
|
-
npm run check:publish
|
|
75
|
-
npm run pack:dry-run
|
|
76
|
-
npm run pack
|
|
57
|
+
```bash
|
|
58
|
+
npm test
|
|
59
|
+
npm run pack:check
|
|
60
|
+
npm run release:check
|
|
77
61
|
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { main } from '../src/cli.js';
|
|
4
|
+
import { createAgentError } from '../src/agent-protocol.js';
|
|
5
|
+
|
|
6
|
+
function parseFormat(argv) {
|
|
7
|
+
const index = argv.indexOf('--format');
|
|
8
|
+
if (index === -1) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
return argv[index + 1] || '';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
main(process.argv).catch((error) => {
|
|
15
|
+
if (parseFormat(process.argv.slice(2)) === 'agent-json') {
|
|
16
|
+
const { payload, exitCode } = createAgentError(
|
|
17
|
+
process.argv.slice(2, 4).filter((item) => !item.startsWith('--')).join(' '),
|
|
18
|
+
error,
|
|
19
|
+
);
|
|
20
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
21
|
+
process.exitCode = exitCode;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
console.error(error?.message || error);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
});
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { execFileSync } = require('node:child_process');
|
|
6
|
+
|
|
7
|
+
const { getSupportedAgents, detectInstalledAgents, getAgentConfig } = require('../lib/skill-installer/agents.cjs');
|
|
8
|
+
const { discoverSkills } = require('../lib/skill-installer/discover-skills.cjs');
|
|
9
|
+
const { installSkills, uninstallSkills } = require('../lib/skill-installer/installer.cjs');
|
|
10
|
+
const { buildReleaseChecklist } = require('../lib/skill-installer/publish.cjs');
|
|
11
|
+
const { prepareSkillSource, readRepositoryConfig } = require('../lib/skill-installer/repo-source.cjs');
|
|
12
|
+
|
|
13
|
+
function print(message = '') {
|
|
14
|
+
process.stdout.write(`${message}\n`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function printError(message) {
|
|
18
|
+
process.stderr.write(`${message}\n`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
const args = { _: [] };
|
|
23
|
+
|
|
24
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
25
|
+
const current = argv[index];
|
|
26
|
+
|
|
27
|
+
if (current === '--agent') {
|
|
28
|
+
args.agent = (argv[index + 1] || '')
|
|
29
|
+
.split(',')
|
|
30
|
+
.map((item) => item.trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
index += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (current === '--mode') {
|
|
37
|
+
args.mode = argv[index + 1] || 'symlink';
|
|
38
|
+
index += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (current === '--scope') {
|
|
43
|
+
args.scope = argv[index + 1] || 'global';
|
|
44
|
+
index += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (current === '--skill') {
|
|
49
|
+
args.skill = (argv[index + 1] || '')
|
|
50
|
+
.split(',')
|
|
51
|
+
.map((item) => item.trim())
|
|
52
|
+
.filter(Boolean);
|
|
53
|
+
index += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (current === '--dry-run') {
|
|
58
|
+
args.dryRun = true;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (current === '--project') {
|
|
63
|
+
args.scope = 'project';
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (current === '--global') {
|
|
68
|
+
args.scope = 'global';
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (current === '--postinstall') {
|
|
73
|
+
args.postinstall = true;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
args._.push(current);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return args;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function shouldSkipPostinstall() {
|
|
84
|
+
if (process.env.YUANFLOW_SKILL_SKIP_POSTINSTALL === '1') {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const isGlobalInstall =
|
|
89
|
+
process.env.npm_config_global === 'true' || process.env.npm_config_location === 'global';
|
|
90
|
+
|
|
91
|
+
return !isGlobalInstall;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getPackageRoot() {
|
|
95
|
+
return path.resolve(__dirname, '..');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function listAgents() {
|
|
99
|
+
const supportedAgents = getSupportedAgents();
|
|
100
|
+
const detectedAgents = detectInstalledAgents();
|
|
101
|
+
|
|
102
|
+
print('Supported agents:');
|
|
103
|
+
for (const agentName of supportedAgents) {
|
|
104
|
+
const marker = detectedAgents.includes(agentName) ? '[detected]' : '[not detected]';
|
|
105
|
+
print(`- ${agentName} ${marker}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function withSkillSource(run) {
|
|
110
|
+
const packageRoot = getPackageRoot();
|
|
111
|
+
const prepared = await prepareSkillSource({ packageRoot });
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
return await run(prepared.sourceRoot);
|
|
115
|
+
} finally {
|
|
116
|
+
prepared.cleanup();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function listSkills() {
|
|
121
|
+
const skills = await withSkillSource((sourceRoot) => discoverSkills(sourceRoot));
|
|
122
|
+
|
|
123
|
+
print('Discovered skills:');
|
|
124
|
+
for (const skill of skills) {
|
|
125
|
+
print(`- ${skill.name} -> ${skill.sourceDir}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function resolveAgents(requestedAgents) {
|
|
130
|
+
if (requestedAgents && requestedAgents.length > 0) {
|
|
131
|
+
return requestedAgents.map((agentName) => getAgentConfig(agentName));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return detectInstalledAgents().map((agentName) => getAgentConfig(agentName));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function resolveSkills(sourceRoot, requestedSkillNames) {
|
|
138
|
+
const skills = discoverSkills(sourceRoot);
|
|
139
|
+
|
|
140
|
+
if (!requestedSkillNames || requestedSkillNames.length === 0) {
|
|
141
|
+
return skills;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const requested = new Set(requestedSkillNames.map((item) => item.toLowerCase()));
|
|
145
|
+
return skills.filter((skill) => requested.has(skill.name.toLowerCase()));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function printInstallResults(results) {
|
|
149
|
+
for (const result of results) {
|
|
150
|
+
const actionLabel = result.dryRun ? 'Would install' : 'Installed';
|
|
151
|
+
const overwriteLabel =
|
|
152
|
+
result.overwriteCanonical || result.overwriteTarget ? ' overwrite' : '';
|
|
153
|
+
print(
|
|
154
|
+
`${actionLabel} ${result.skillName} -> ${result.agentName} (${result.installedBy}, ${result.scope}${overwriteLabel})`
|
|
155
|
+
);
|
|
156
|
+
print(` ${result.targetDir}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function printUninstallResults(results) {
|
|
161
|
+
for (const result of results) {
|
|
162
|
+
const actionLabel = result.dryRun ? 'Would remove' : 'Removed';
|
|
163
|
+
print(`${actionLabel} ${result.skillName} -> ${result.agentName} (${result.scope})`);
|
|
164
|
+
print(` ${result.targetDir}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function runInstall(options = {}) {
|
|
169
|
+
const packageRoot = getPackageRoot();
|
|
170
|
+
const agents = resolveAgents(options.agent);
|
|
171
|
+
|
|
172
|
+
if (agents.length === 0) {
|
|
173
|
+
print('No supported agent installation was detected. Nothing to install.');
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const results = await withSkillSource((sourceRoot) => {
|
|
178
|
+
const skills = resolveSkills(sourceRoot, options.skill);
|
|
179
|
+
|
|
180
|
+
if (skills.length === 0) {
|
|
181
|
+
print('No matching skills were found in the skill repository.');
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return installSkills({
|
|
186
|
+
packageRoot,
|
|
187
|
+
skills,
|
|
188
|
+
targetAgents: agents,
|
|
189
|
+
mode: options.mode || 'symlink',
|
|
190
|
+
scope: options.scope || 'global',
|
|
191
|
+
cwd: process.cwd(),
|
|
192
|
+
dryRun: Boolean(options.dryRun),
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
if (typeof results === 'number') {
|
|
197
|
+
return results;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
printInstallResults(results);
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function runUpdate(options = {}) {
|
|
205
|
+
return runInstall(options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function runUninstall(options = {}) {
|
|
209
|
+
const agents = resolveAgents(options.agent);
|
|
210
|
+
|
|
211
|
+
if (agents.length === 0) {
|
|
212
|
+
print('No supported agent installation was detected. Nothing to remove.');
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const results = await withSkillSource((sourceRoot) => {
|
|
217
|
+
const skills = resolveSkills(sourceRoot, options.skill);
|
|
218
|
+
|
|
219
|
+
if (skills.length === 0) {
|
|
220
|
+
print('No matching skills were found in the skill repository.');
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return uninstallSkills({
|
|
225
|
+
bundleName: skills.find((skill) => skill.rootSkill)?.name || 'yuanflow-skill',
|
|
226
|
+
targetAgents: agents,
|
|
227
|
+
scope: options.scope || 'global',
|
|
228
|
+
cwd: process.cwd(),
|
|
229
|
+
dryRun: Boolean(options.dryRun),
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (typeof results === 'number') {
|
|
234
|
+
return results;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
printUninstallResults(results);
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function runReleaseCheck() {
|
|
242
|
+
const packageRoot = getPackageRoot();
|
|
243
|
+
const packageJson = JSON.parse(
|
|
244
|
+
fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')
|
|
245
|
+
);
|
|
246
|
+
const repoConfig = readRepositoryConfig(packageRoot);
|
|
247
|
+
const checklist = buildReleaseChecklist({
|
|
248
|
+
packageJson,
|
|
249
|
+
packageRoot,
|
|
250
|
+
repoConfig,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
print('Release checklist:');
|
|
254
|
+
for (const item of checklist.items) {
|
|
255
|
+
print(`- ${item.ok ? 'OK' : 'FAIL'} ${item.label}`);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
const output = execFileSync('npm', ['view', packageJson.name, 'version', '--json'], {
|
|
260
|
+
cwd: packageRoot,
|
|
261
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
262
|
+
encoding: 'utf8',
|
|
263
|
+
}).trim();
|
|
264
|
+
if (output) {
|
|
265
|
+
print(`- INFO package name exists on npm: ${packageJson.name}`);
|
|
266
|
+
print(` latest published version: ${output.replace(/^"|"$/g, '')}`);
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
print(`- INFO package name not found on npm or registry query failed: ${packageJson.name}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return checklist.ok ? 0 : 1;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function runPublishHelp() {
|
|
276
|
+
print('Publish flow for the npm installer package:');
|
|
277
|
+
print('1. npm test');
|
|
278
|
+
print('2. npm run pack:check');
|
|
279
|
+
print('3. npm run release:check');
|
|
280
|
+
print('4. npm publish --access public');
|
|
281
|
+
return 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async function main() {
|
|
285
|
+
const args = parseArgs(process.argv.slice(2));
|
|
286
|
+
const command = args._[0] || 'install';
|
|
287
|
+
|
|
288
|
+
if (args.postinstall && shouldSkipPostinstall()) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (command === 'list-agents') {
|
|
293
|
+
listAgents();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (command === 'list-skills') {
|
|
298
|
+
await listSkills();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (command === 'install') {
|
|
303
|
+
process.exitCode = await runInstall(args);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (command === 'update') {
|
|
308
|
+
process.exitCode = await runUpdate(args);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (command === 'uninstall' || command === 'remove') {
|
|
313
|
+
process.exitCode = await runUninstall(args);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (command === 'release-check') {
|
|
318
|
+
process.exitCode = runReleaseCheck();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (command === 'publish-help') {
|
|
323
|
+
process.exitCode = runPublishHelp();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
printError(`Unsupported command: ${command}`);
|
|
328
|
+
process.exitCode = 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
main().catch((error) => {
|
|
332
|
+
printError(error instanceof Error ? error.message : String(error));
|
|
333
|
+
process.exitCode = 1;
|
|
334
|
+
});
|