@aiyiran/myclaw 1.0.200 → 1.0.202
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/index.js +113 -25
- package/{inject-clear-models.js → injects/inject-clear-models.js} +1 -1
- package/{inject-image.js → injects/inject-image.js} +1 -1
- package/{inject-minimax.js → injects/inject-minimax.js} +1 -1
- package/{inject-search.js → injects/inject-search.js} +1 -1
- package/{inject-token.js → injects/inject-token.js} +1 -1
- package/injects/inject-tooldeny.js +50 -0
- package/{inject-zai.js → injects/inject-zai.js} +2 -2
- package/package.json +1 -1
- package/{patch-manifest.json → patches/patch-manifest.json} +15 -5
- package/{patch-reset.js → patches/patch-reset.js} +1 -1
- package/{patch-skill.js → patches/patch-skill.js} +6 -1
- package/pull.js +1 -1
- package/skills/vapi-image-gen-1.0.1/README.md +92 -0
- package/skills/vapi-image-gen-1.0.1/SKILL.md +75 -0
- package/skills/vapi-image-gen-1.0.1/_meta.json +6 -0
- package/skills/vapi-image-gen-1.0.1/scripts/gen.py +259 -0
- package/skills/yiran-skill-media/SKILL.md +74 -0
- package/skills/yiran-skill-media/config.json +26 -0
- package/skills/yiran-skill-media/references/image-api.md +88 -0
- package/skills/yiran-skill-media/references/music-api.md +120 -0
- package/skills/yiran-skill-media/scripts/generate.py +165 -0
- package/skills/yiran-skill-media/scripts/generation_log.json +20 -0
- package/skills/yiran-skill-media/scripts/image.sh +43 -0
- package/skills/yiran-skill-media/scripts/music.sh +46 -0
- package/skills/yiran-skill-media/scripts/providers/__init__.py +15 -0
- package/skills/yiran-skill-media/scripts/providers/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_image.cpython-311.pyc +0 -0
- package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_music.cpython-311.pyc +0 -0
- package/skills/yiran-skill-media/scripts/providers/__pycache__/vapi_image.cpython-311.pyc +0 -0
- package/skills/yiran-skill-media/scripts/providers/minimax_image.py +75 -0
- package/skills/yiran-skill-media/scripts/providers/minimax_music.py +61 -0
- package/skills/yiran-skill-media/scripts/providers/vapi_image.py +63 -0
- package/skills/yiran-skill-media/scripts/registry.py +133 -0
- /package/{inject-workspaceAndSoul.js → injects/inject-workspaceAndSoul.js} +0 -0
- /package/{patch-agent.js → patches/patch-agent.js} +0 -0
- /package/{patch.js → patches/patch.js} +0 -0
package/index.js
CHANGED
|
@@ -682,8 +682,8 @@ function runOpen() {
|
|
|
682
682
|
// ============================================================================
|
|
683
683
|
|
|
684
684
|
function runPatch() {
|
|
685
|
-
const { patch, status: patchStatus } = require('./patch');
|
|
686
|
-
const { patchSkills } = require('./patch-skill');
|
|
685
|
+
const { patch, status: patchStatus } = require('./patches/patch');
|
|
686
|
+
const { patchSkills } = require('./patches/patch-skill');
|
|
687
687
|
const { patchConfig } = require('./find-config');
|
|
688
688
|
const bar = '----------------------------------------';
|
|
689
689
|
|
|
@@ -701,13 +701,13 @@ function runPatch() {
|
|
|
701
701
|
|
|
702
702
|
// 3. 智能体上传(从 agent-list/ 复制到 ~/.openclaw/)
|
|
703
703
|
console.log('');
|
|
704
|
-
const { patchAgents } = require('./patch-agent');
|
|
704
|
+
const { patchAgents } = require('./patches/patch-agent');
|
|
705
705
|
const agentResult = patchAgents();
|
|
706
706
|
|
|
707
707
|
// 4. Config 补丁(从 manifest 读取,修改 openclaw.json)
|
|
708
708
|
console.log('');
|
|
709
709
|
try {
|
|
710
|
-
const { loadManifest } = require('./patch-agent');
|
|
710
|
+
const { loadManifest } = require('./patches/patch-agent');
|
|
711
711
|
const manifest = loadManifest();
|
|
712
712
|
if (manifest && manifest.config && manifest.config.patches) {
|
|
713
713
|
const configStrategy = manifest.config.strategy || 'on';
|
|
@@ -757,7 +757,7 @@ function runPatch() {
|
|
|
757
757
|
// 通过修改 manifest 即可控制额外脚本(如 inject-image, inject-search)是否跟随 patch 自动执行,
|
|
758
758
|
// 从而避免硬编码具体要注入哪些模块。
|
|
759
759
|
try {
|
|
760
|
-
const { loadManifest } = require('./patch-agent');
|
|
760
|
+
const { loadManifest } = require('./patches/patch-agent');
|
|
761
761
|
const m = loadManifest();
|
|
762
762
|
if (m && Array.isArray(m.run) && m.run.length > 0) {
|
|
763
763
|
console.log('');
|
|
@@ -791,7 +791,7 @@ function runPatch() {
|
|
|
791
791
|
}
|
|
792
792
|
|
|
793
793
|
function runUnpatch() {
|
|
794
|
-
const { unpatch } = require('./patch');
|
|
794
|
+
const { unpatch } = require('./patches/patch');
|
|
795
795
|
const bar = '----------------------------------------';
|
|
796
796
|
|
|
797
797
|
console.log('');
|
|
@@ -959,7 +959,7 @@ function runUpdate() {
|
|
|
959
959
|
// ============================================================================
|
|
960
960
|
|
|
961
961
|
function runList() {
|
|
962
|
-
const { loadManifest } = require('./patch-agent');
|
|
962
|
+
const { loadManifest } = require('./patches/patch-agent');
|
|
963
963
|
const bar = '----------------------------------------';
|
|
964
964
|
|
|
965
965
|
console.log('');
|
|
@@ -1166,6 +1166,84 @@ function runInteractiveMenu() {
|
|
|
1166
1166
|
// 帮助信息
|
|
1167
1167
|
// ============================================================================
|
|
1168
1168
|
|
|
1169
|
+
// ============================================================================
|
|
1170
|
+
// inject 交互菜单
|
|
1171
|
+
// ============================================================================
|
|
1172
|
+
|
|
1173
|
+
const INJECT_MENU = [
|
|
1174
|
+
{ key: '1', cmd: 'inject-minimax', desc: '注入 MiniMax 模型配置' },
|
|
1175
|
+
{ key: '2', cmd: 'inject-zai', desc: '注入智谱 GLM 模型配置' },
|
|
1176
|
+
{ key: '3', cmd: 'inject-image', desc: '注入图像生成模型配置 (vveai)' },
|
|
1177
|
+
{ key: '4', cmd: 'inject-search', desc: '注入 Tavily 搜索插件配置' },
|
|
1178
|
+
{ key: '5', cmd: 'inject-token', desc: '设置 Gateway Token 为 aiyiran' },
|
|
1179
|
+
{ key: '6', cmd: 'inject-workspaceAndSoul', desc: '替换默认 workspace 的 SOUL.md' },
|
|
1180
|
+
{ key: '7', cmd: 'inject-tooldeny', desc: 'deny image_generate + music_generate 内置工具' },
|
|
1181
|
+
{ key: 'a', cmd: 'all', desc: '执行以上全部注入' },
|
|
1182
|
+
];
|
|
1183
|
+
|
|
1184
|
+
function runInjectCommand(cmd, extraArgs) {
|
|
1185
|
+
const modules = {
|
|
1186
|
+
'inject-minimax': './inject-minimax',
|
|
1187
|
+
'inject-zai': './inject-zai',
|
|
1188
|
+
'inject-image': './inject-image',
|
|
1189
|
+
'inject-search': './inject-search',
|
|
1190
|
+
'inject-token': './inject-token',
|
|
1191
|
+
'inject-workspaceAndSoul': './inject-workspaceAndSoul',
|
|
1192
|
+
'inject-tooldeny': './inject-tooldeny',
|
|
1193
|
+
};
|
|
1194
|
+
const mod = require(modules[cmd]);
|
|
1195
|
+
mod.run(extraArgs || []);
|
|
1196
|
+
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1197
|
+
console.log('');
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
function showInjectMenu() {
|
|
1201
|
+
console.log('');
|
|
1202
|
+
console.log(colors.blue + '📦 注入脚本选择' + colors.nc);
|
|
1203
|
+
console.log('----------------------------------------');
|
|
1204
|
+
console.log('');
|
|
1205
|
+
for (const item of INJECT_MENU) {
|
|
1206
|
+
console.log(' ' + colors.cyan + item.key + colors.nc + ') ' + item.desc);
|
|
1207
|
+
}
|
|
1208
|
+
console.log(' ' + colors.cyan + '0' + colors.nc + ') 返回');
|
|
1209
|
+
console.log('');
|
|
1210
|
+
|
|
1211
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1212
|
+
rl.question('请选择 [0-' + INJECT_MENU.length + '/a]: ', function (answer) {
|
|
1213
|
+
rl.close();
|
|
1214
|
+
const choice = answer.trim().toLowerCase();
|
|
1215
|
+
|
|
1216
|
+
if (choice === '0' || choice === '') {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
if (choice === 'a') {
|
|
1221
|
+
for (const item of INJECT_MENU) {
|
|
1222
|
+
if (item.cmd !== 'all') {
|
|
1223
|
+
try {
|
|
1224
|
+
console.log('');
|
|
1225
|
+
console.log('→ ' + item.desc + '...');
|
|
1226
|
+
runInjectCommand(item.cmd);
|
|
1227
|
+
} catch (err) {
|
|
1228
|
+
console.log(' ❌ 失败: ' + err.message);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
runRestart();
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
const found = INJECT_MENU.find(m => m.key === choice);
|
|
1237
|
+
if (!found) {
|
|
1238
|
+
console.log('[' + colors.red + '错误' + colors.nc + '] 无效选择: ' + choice);
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
runInjectCommand(found.cmd, args.slice(1));
|
|
1243
|
+
runRestart();
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1169
1247
|
function showHelp() {
|
|
1170
1248
|
console.log('');
|
|
1171
1249
|
console.log('MyClaw - 学生友好的 OpenClaw 工具');
|
|
@@ -1197,12 +1275,14 @@ function showHelp() {
|
|
|
1197
1275
|
console.log(' pull 从 ~/.openclaw 拉取最新资源到源目录(开发用)');
|
|
1198
1276
|
console.log(' patch 注入 MyClaw UI + 技能 + 智能体 + 配置');
|
|
1199
1277
|
console.log(' unpatch 回滚 UI 注入(恢复原版)');
|
|
1200
|
-
console.log('
|
|
1201
|
-
console.log('
|
|
1202
|
-
console.log('
|
|
1203
|
-
console.log('
|
|
1204
|
-
console.log('
|
|
1205
|
-
console.log('
|
|
1278
|
+
console.log(' inject 交互选择要执行的注入脚本');
|
|
1279
|
+
console.log(' inject-minimax 注入 MiniMax 模型配置 (可选: --key sk-xxx, -f 强制清理其他模型)');
|
|
1280
|
+
console.log(' inject-zai 注入智谱 GLM 模型配置 (可选: --key xxx, -f 强制清理其他模型)');
|
|
1281
|
+
console.log(' inject-image 注入图像生成模型配置 (基于 vveai)');
|
|
1282
|
+
console.log(' inject-token 设置 Gateway Token 为 aiyiran');
|
|
1283
|
+
console.log(' inject-search 注入 Tavily 搜索插件配置');
|
|
1284
|
+
console.log(' inject-workspaceAndSoul 替换默认 workspace 的 SOUL.md 提示词');
|
|
1285
|
+
console.log(' inject-tooldeny deny image_generate + music_generate 内置工具');
|
|
1206
1286
|
console.log(' restart 重启 OpenClaw Gateway');
|
|
1207
1287
|
console.log(' help 显示帮助信息');
|
|
1208
1288
|
console.log('');
|
|
@@ -1286,43 +1366,51 @@ if (!command) {
|
|
|
1286
1366
|
runUninstall();
|
|
1287
1367
|
} else if (command === 'restart') {
|
|
1288
1368
|
runRestart();
|
|
1289
|
-
} else if (command === '
|
|
1290
|
-
|
|
1369
|
+
} else if (command === 'inject') {
|
|
1370
|
+
showInjectMenu();
|
|
1371
|
+
} else if (command === 'inject-minimax') {
|
|
1372
|
+
const minimax = require('./injects/inject-minimax');
|
|
1291
1373
|
minimax.run(args.slice(1));
|
|
1292
1374
|
// 注入完成后自动重启 Gateway
|
|
1293
1375
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1294
1376
|
console.log('');
|
|
1295
1377
|
runRestart();
|
|
1296
|
-
} else if (command === 'zai') {
|
|
1297
|
-
const zai = require('./inject-zai');
|
|
1378
|
+
} else if (command === 'inject-zai') {
|
|
1379
|
+
const zai = require('./injects/inject-zai');
|
|
1298
1380
|
zai.run(args.slice(1));
|
|
1299
1381
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1300
1382
|
console.log('');
|
|
1301
1383
|
runRestart();
|
|
1302
|
-
} else if (command === 'image') {
|
|
1303
|
-
const image = require('./inject-image');
|
|
1384
|
+
} else if (command === 'inject-image') {
|
|
1385
|
+
const image = require('./injects/inject-image');
|
|
1304
1386
|
image.run(args.slice(1));
|
|
1305
1387
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1306
1388
|
console.log('');
|
|
1307
1389
|
runRestart();
|
|
1308
|
-
} else if (command === 'token') {
|
|
1309
|
-
const token = require('./inject-token');
|
|
1390
|
+
} else if (command === 'inject-token') {
|
|
1391
|
+
const token = require('./injects/inject-token');
|
|
1310
1392
|
token.run(args.slice(1));
|
|
1311
1393
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1312
1394
|
console.log('');
|
|
1313
1395
|
runRestart();
|
|
1314
|
-
} else if (command === '
|
|
1315
|
-
const search = require('./inject-search');
|
|
1396
|
+
} else if (command === 'inject-search') {
|
|
1397
|
+
const search = require('./injects/inject-search');
|
|
1316
1398
|
search.run(args.slice(1));
|
|
1317
1399
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1318
1400
|
console.log('');
|
|
1319
1401
|
runRestart();
|
|
1320
|
-
} else if (command === '
|
|
1321
|
-
const soul = require('./inject-workspaceAndSoul');
|
|
1402
|
+
} else if (command === 'inject-workspaceAndSoul') {
|
|
1403
|
+
const soul = require('./injects/inject-workspaceAndSoul');
|
|
1322
1404
|
soul.run();
|
|
1323
1405
|
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1324
1406
|
console.log('');
|
|
1325
1407
|
runRestart();
|
|
1408
|
+
} else if (command === 'inject-tooldeny') {
|
|
1409
|
+
const tooldeny = require('./injects/inject-tooldeny');
|
|
1410
|
+
media.run(args.slice(1));
|
|
1411
|
+
console.log('🔄 正在重启 Gateway 使配置生效...');
|
|
1412
|
+
console.log('');
|
|
1413
|
+
runRestart();
|
|
1326
1414
|
} else {
|
|
1327
1415
|
console.error('[' + colors.red + '错误' + colors.nc + '] 未知命令: ' + command);
|
|
1328
1416
|
showHelp();
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 入口: myclaw minimax [--key sk-xxx]
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
const { readConfig, writeConfig } = require('
|
|
17
|
+
const { readConfig, writeConfig } = require('../find-config');
|
|
18
18
|
|
|
19
19
|
// ============================================================
|
|
20
20
|
// 请在这里填写默认的 MiniMax API Key
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* inject-rewriteMedia.js
|
|
5
|
+
*
|
|
6
|
+
* deny image_generate 工具,使智能体优先使用 yiran-skill-media skill。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { readConfig, writeConfig } = require('../find-config');
|
|
10
|
+
|
|
11
|
+
function run() {
|
|
12
|
+
let configPath;
|
|
13
|
+
try {
|
|
14
|
+
({ configPath } = readConfig());
|
|
15
|
+
} catch (err) {
|
|
16
|
+
console.error('❌ ' + err.message);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
console.log('📍 找到配置: ' + configPath);
|
|
21
|
+
console.log('');
|
|
22
|
+
|
|
23
|
+
const { config } = readConfig();
|
|
24
|
+
|
|
25
|
+
// ── deny image_generate 工具 ──
|
|
26
|
+
if (!config.tools) config.tools = {};
|
|
27
|
+
if (!config.tools.deny) config.tools.deny = [];
|
|
28
|
+
for (const tool of ['image_generate', 'music_generate']) {
|
|
29
|
+
if (!config.tools.deny.includes(tool)) {
|
|
30
|
+
config.tools.deny.push(tool);
|
|
31
|
+
console.log(' ✓ 已添加 tools.deny["' + tool + '"]');
|
|
32
|
+
} else {
|
|
33
|
+
console.log(' ○ tools.deny 已包含 ' + tool + ',跳过');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
writeConfig(config, configPath);
|
|
38
|
+
|
|
39
|
+
// ── 验证 ──
|
|
40
|
+
const verify = readConfig();
|
|
41
|
+
const deniedTools = verify.config.tools?.deny || [];
|
|
42
|
+
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log('✅ rewriteMedia 注入完成');
|
|
45
|
+
console.log(' [验证] tools.deny image_generate: ' + deniedTools.includes('image_generate'));
|
|
46
|
+
console.log(' [验证] tools.deny music_generate: ' + deniedTools.includes('music_generate'));
|
|
47
|
+
console.log('');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { run };
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 入口: myclaw zai [--key xxx]
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
const { readConfig, writeConfig } = require('
|
|
16
|
+
const { readConfig, writeConfig } = require('../find-config');
|
|
17
17
|
const fs = require('fs');
|
|
18
18
|
const path = require('path');
|
|
19
19
|
const os = require('os');
|
|
@@ -21,7 +21,7 @@ const os = require('os');
|
|
|
21
21
|
// ============================================================
|
|
22
22
|
// 默认智谱 API Key
|
|
23
23
|
// ============================================================
|
|
24
|
-
const DEFAULT_ZAI_KEY = "
|
|
24
|
+
const DEFAULT_ZAI_KEY = "122435800204471f83045b53aaf5c54e.StwsrQVMlYXkLcJ1";
|
|
25
25
|
|
|
26
26
|
// 智谱模型列表
|
|
27
27
|
const ZAI_MODELS = [
|
package/package.json
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"name": "tavily-search",
|
|
13
13
|
"strategy": "off",
|
|
14
14
|
"description": "tavily-search (Tavily 搜索技能包)"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "yiran-skill-media",
|
|
18
|
+
"strategy": "on",
|
|
19
|
+
"description": "统一多媒体生成 skill(图片+音乐,主备切换)"
|
|
15
20
|
}
|
|
16
21
|
],
|
|
17
22
|
"_doc_agents": "Step 3: 将 agent-list/ 下的智能体分发到 ~/.openclaw/ 并注册到 openclaw.json",
|
|
@@ -43,29 +48,34 @@
|
|
|
43
48
|
"_doc_run": "Step 5: 按顺序 require(module).run([]) 执行自定义脚本,不触发 Gateway 重启",
|
|
44
49
|
"run": [
|
|
45
50
|
{
|
|
46
|
-
"module": "./inject-search",
|
|
51
|
+
"module": "./injects/inject-search",
|
|
47
52
|
"strategy": "auto",
|
|
48
53
|
"description": "搜索配置注入 (Tavily)"
|
|
49
54
|
},
|
|
50
55
|
{
|
|
51
|
-
"module": "./inject-minimax",
|
|
56
|
+
"module": "./injects/inject-minimax",
|
|
52
57
|
"strategy": "auto",
|
|
53
58
|
"description": "MiniMax 模型注入"
|
|
54
59
|
},
|
|
55
60
|
{
|
|
56
|
-
"module": "./inject-image",
|
|
61
|
+
"module": "./injects/inject-image",
|
|
57
62
|
"strategy": "auto",
|
|
58
63
|
"description": "图片模型注入 (vveai)"
|
|
59
64
|
},
|
|
60
65
|
{
|
|
61
|
-
"module": "./inject-workspaceAndSoul",
|
|
66
|
+
"module": "./injects/inject-workspaceAndSoul",
|
|
62
67
|
"strategy": "on",
|
|
63
68
|
"description": "替换默认 workspace 的 SOUL.md 提示词"
|
|
64
69
|
},
|
|
65
70
|
{
|
|
66
|
-
"module": "./inject-token",
|
|
71
|
+
"module": "./injects/inject-token",
|
|
67
72
|
"strategy": "auto",
|
|
68
73
|
"description": "Gateway Token 设置为 aiyiran"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"module": "./injects/inject-tooldeny",
|
|
77
|
+
"strategy": "on",
|
|
78
|
+
"description": "deny image_generate + music_generate 内置工具"
|
|
69
79
|
}
|
|
70
80
|
]
|
|
71
81
|
}
|
|
@@ -120,7 +120,12 @@ function patchSkills() {
|
|
|
120
120
|
for (const skillDir of skillDirs) {
|
|
121
121
|
const srcDir = path.join(myclawSkillsDir, skillDir.name);
|
|
122
122
|
const destDir = path.join(skillsDir, skillDir.name);
|
|
123
|
-
const strategy = skillStrategyMap[skillDir.name]
|
|
123
|
+
const strategy = skillStrategyMap[skillDir.name];
|
|
124
|
+
|
|
125
|
+
if (!strategy) {
|
|
126
|
+
console.log('[myclaw-skill] ⊘ 跳过: ' + skillDir.name + ' [未配置,跳过]');
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
124
129
|
|
|
125
130
|
if (strategy === 'off') {
|
|
126
131
|
console.log('[myclaw-skill] ⊘ 跳过: ' + skillDir.name + ' [off]');
|
package/pull.js
CHANGED
|
@@ -21,7 +21,7 @@ const os = require('os');
|
|
|
21
21
|
const OPENCLAW_DIR = path.join(os.homedir(), '.openclaw');
|
|
22
22
|
const AGENT_LIST_DIR = path.join(__dirname, 'agent-list');
|
|
23
23
|
const SKILLS_DIR = path.join(__dirname, 'skills');
|
|
24
|
-
const MANIFEST_PATH = path.join(__dirname, 'patch-manifest.json');
|
|
24
|
+
const MANIFEST_PATH = path.join(__dirname, 'patches/patch-manifest.json');
|
|
25
25
|
|
|
26
26
|
// 不应拉取的 workspace(排除列表)
|
|
27
27
|
const WORKSPACE_IGNORE = new Set([
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# 🎨 vapi-image-gen
|
|
2
|
+
|
|
3
|
+
Generate images with AI via VAPI's OpenAI-compatible Images API.
|
|
4
|
+
通过 VAPI 的 OpenAI 兼容图像 API,让你的 AI 助手学会画画。
|
|
5
|
+
|
|
6
|
+
Supports **nano-banana** and **gpt-image** model series. Fast, flexible, works out of the box once configured.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ✅ Requirements / 前置条件
|
|
11
|
+
|
|
12
|
+
- Python 3
|
|
13
|
+
- A [VAPI API Key](https://api.v3.cm) (`VAPI_API_KEY`)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ⚙️ Configuration / 配置
|
|
18
|
+
|
|
19
|
+
Set in `.env` or `~/.openclaw/openclaw.json`:
|
|
20
|
+
- `VAPI_API_KEY` — your VAPI API key **(required)**
|
|
21
|
+
- `VAPI_BASE_URL` — base URL with /v1 suffix **(required)**; defaults to `https://api.v3.cm/v1` if not set
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 💬 Example Prompts / 示例提示词
|
|
26
|
+
|
|
27
|
+
Once configured, just tell your AI assistant what you want:
|
|
28
|
+
|
|
29
|
+
配置好后,直接用自然语言告诉 AI 你想要什么:
|
|
30
|
+
|
|
31
|
+
### 🖼️ Basic Generation / 基础生图
|
|
32
|
+
|
|
33
|
+
| English | 中文 |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Draw a sunset over the ocean | 画一张海上日落的风景 |
|
|
36
|
+
| Generate a cyberpunk city at night | 生成一张赛博朋克风格的城市夜景 |
|
|
37
|
+
| Create a cute cartoon cat illustration | 画一只可爱的卡通猫咪插画 |
|
|
38
|
+
|
|
39
|
+
### 📐 With Aspect Ratio / 指定比例
|
|
40
|
+
|
|
41
|
+
| English | 中文 |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Generate a 16:9 wallpaper of a starry sky | 生成一张 16:9 的星空壁纸 |
|
|
44
|
+
| Draw a 2:3 portrait of a fantasy warrior | 画一张 2:3 竖版奇幻战士肖像 |
|
|
45
|
+
| Create a 1:1 square avatar of a fox in a suit | 画一个穿西装的狐狸头像,1:1 方形 |
|
|
46
|
+
|
|
47
|
+
### 💾 Save to Local / 保存到本地
|
|
48
|
+
|
|
49
|
+
| English | 中文 |
|
|
50
|
+
|---|---|
|
|
51
|
+
| Generate a forest scene and save it | 生成一张森林场景的图片,保存到本地 |
|
|
52
|
+
| Draw 3 variations of a mountain landscape and save | 画 3 张山景图,保存到本地 |
|
|
53
|
+
|
|
54
|
+
### 🔍 High Resolution / 高清生图
|
|
55
|
+
|
|
56
|
+
| English | 中文 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Generate a high-res 4K illustration of a dragon | 用高清 4K 模型画一条龙的插画 |
|
|
59
|
+
| Create a 2K detailed city map illustration | 生成一张 2K 高清城市地图插画 |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🤖 Supported Models / 支持的模型
|
|
64
|
+
|
|
65
|
+
| Model | Quality | Output |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `nano-banana` | Standard | URL |
|
|
68
|
+
| `nano-banana-pro` ⭐ | Better — **Default** | URL |
|
|
69
|
+
| `nano-banana-2` | Gen 2 | URL |
|
|
70
|
+
| `nano-banana-pro-2k` | High-res 2K | URL |
|
|
71
|
+
| `nano-banana-pro-4k` | Ultra 4K | URL |
|
|
72
|
+
| `gpt-image-1` | High quality | Saved file |
|
|
73
|
+
| `gpt-image-1.5` | Higher quality | Saved file |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 📁 Save Behavior / 图片保存说明
|
|
78
|
+
|
|
79
|
+
| Flag | Behavior |
|
|
80
|
+
|---|---|
|
|
81
|
+
| *(default)* | Returns image URL only, no local file |
|
|
82
|
+
| `--save` | Saves to `~/.openclaw/media/` |
|
|
83
|
+
| `--oss` | Saves to `~/.openclaw/oss/` |
|
|
84
|
+
| `gpt-image` models | Always saved (API returns base64 only) |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 🔗 Links
|
|
89
|
+
|
|
90
|
+
- VAPI API: [api.v3.cm](https://api.v3.cm)
|
|
91
|
+
- OpenClaw: [openclaw.ai](https://openclaw.ai)
|
|
92
|
+
- ClawHub: [clawhub.ai](https://clawhub.ai)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vapi-image-gen
|
|
3
|
+
description: Generate images via VAPI's OpenAI-compatible Images API. Supports nano-banana and gpt-image model series. Default model is nano-banana-pro. Images are NOT saved locally by default (URL only). Use --save flag when the user wants to keep the image.
|
|
4
|
+
homepage: https://api.v3.cm
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
{
|
|
8
|
+
"openclaw":
|
|
9
|
+
{
|
|
10
|
+
"emoji": "🎨",
|
|
11
|
+
"requires": { "bins": ["python3"], "env": ["VAPI_API_KEY", "VAPI_BASE_URL"] },
|
|
12
|
+
"primaryEnv": "VAPI_API_KEY",
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# VAPI Image Gen
|
|
18
|
+
|
|
19
|
+
Generate images via VAPI's OpenAI-compatible Images API (`/images/generations`).
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
python3 {baseDir}/scripts/gen.py --prompt "your prompt here"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Options
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Specify model (default: nano-banana-pro)
|
|
31
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --model nano-banana-pro
|
|
32
|
+
|
|
33
|
+
# Higher resolution (append -2k or -4k to model name)
|
|
34
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --model nano-banana-pro-2k
|
|
35
|
+
|
|
36
|
+
# Save image locally (default: NO save, URL only)
|
|
37
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --save
|
|
38
|
+
|
|
39
|
+
# Save to OSS directory (~/.openclaw/oss/)
|
|
40
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --oss
|
|
41
|
+
|
|
42
|
+
# Save to custom directory
|
|
43
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --save --out-dir /path/to/dir
|
|
44
|
+
|
|
45
|
+
# Aspect ratio
|
|
46
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --aspect-ratio 16:9
|
|
47
|
+
|
|
48
|
+
# Image count
|
|
49
|
+
python3 {baseDir}/scripts/gen.py --prompt "..." --count 2
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Supported Models
|
|
53
|
+
|
|
54
|
+
nano-banana series (returns URL, fast):
|
|
55
|
+
- nano-banana
|
|
56
|
+
- nano-banana-pro ← default
|
|
57
|
+
- nano-banana-2
|
|
58
|
+
- nano-banana-pro-2k / nano-banana-pro-4k (high res)
|
|
59
|
+
|
|
60
|
+
gpt-image series (returns base64, always saved):
|
|
61
|
+
- gpt-image-1
|
|
62
|
+
- gpt-image-1.5
|
|
63
|
+
|
|
64
|
+
## Config
|
|
65
|
+
|
|
66
|
+
Set in `.env` or `~/.openclaw/openclaw.json`:
|
|
67
|
+
- `VAPI_API_KEY` — your VAPI API key **(required)**
|
|
68
|
+
- `VAPI_BASE_URL` — base URL with /v1 suffix **(required)**; defaults to `https://api.v3.cm/v1` if not set
|
|
69
|
+
|
|
70
|
+
## Save Behavior
|
|
71
|
+
|
|
72
|
+
- Default: no local file, output `MEDIA:<url>` directly
|
|
73
|
+
- `--save`: save to `~/.openclaw/media/`
|
|
74
|
+
- `--oss`: save to `~/.openclaw/oss/`
|
|
75
|
+
- gpt-image models always save to media/ (API returns base64 only)
|