@aiyiran/myclaw 1.0.50 → 1.0.52

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 CHANGED
@@ -581,16 +581,22 @@ function runOpen() {
581
581
 
582
582
  function runPatch() {
583
583
  const { patch, status: patchStatus } = require('./patch');
584
+ const { patchSkills } = require('./patch-skill');
584
585
  const bar = '----------------------------------------';
585
586
 
586
587
  console.log('');
587
- console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + 'UI 注入' + colors.nc);
588
+ console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + 'Patch (UI + Skills)' + colors.nc);
588
589
  console.log(bar);
589
590
  console.log('');
590
591
 
591
- const result = patch();
592
+ // 1. UI 注入
593
+ const uiResult = patch();
592
594
 
593
- if (result.success) {
595
+ // 2. Skill 注入
596
+ console.log('');
597
+ const skillResult = patchSkills();
598
+
599
+ if (uiResult.success || skillResult.success) {
594
600
  console.log('');
595
601
  console.log(bar);
596
602
  console.log('下一步: 运行 ' + colors.yellow + 'myclaw restart' + colors.nc + ' 重启 Gateway 使注入生效');
@@ -728,6 +734,7 @@ function showHelp() {
728
734
  console.log(' bat 在桌面生成一键启动脚本 (仅限 Windows)');
729
735
  console.log(' patch 注入 MyClaw UI 扩展到 WebChat');
730
736
  console.log(' unpatch 回滚 UI 注入(恢复原版)');
737
+ console.log(' minimax 注入 MiniMax 模型配置 (可选: --key sk-xxx)');
731
738
  console.log(' restart 重启 OpenClaw Gateway');
732
739
  console.log(' help 显示帮助信息');
733
740
  console.log('');
@@ -781,6 +788,13 @@ if (!command || command === 'help' || command === '--help' || command === '-h')
781
788
  runUnpatch();
782
789
  } else if (command === 'restart') {
783
790
  runRestart();
791
+ } else if (command === 'minimax') {
792
+ const minimax = require('./inject-minimax');
793
+ minimax.run(args.slice(1));
794
+ // 注入完成后自动重启 Gateway
795
+ console.log('🔄 正在重启 Gateway 使配置生效...');
796
+ console.log('');
797
+ runRestart();
784
798
  } else {
785
799
  console.error('[' + colors.red + '错误' + colors.nc + '] 未知命令: ' + command);
786
800
  showHelp();
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * inject-minimax.js
5
+ *
6
+ * 将 openclaw.json 中的模型配置清空,注入为唯一的 MiniMax 模型。
7
+ * 自动查找 ~/.openclaw/openclaw.json
8
+ *
9
+ * 入口: myclaw minimax [--key sk-xxx]
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const os = require('os');
15
+
16
+ function run(cliArgs) {
17
+ // 解析 --key 参数
18
+ let apiKey = null;
19
+ for (let i = 0; i < cliArgs.length; i++) {
20
+ if (cliArgs[i] === '--key' && cliArgs[i + 1]) {
21
+ apiKey = cliArgs[i + 1];
22
+ i++;
23
+ }
24
+ }
25
+
26
+ // 自动查找 openclaw.json
27
+ const openclawDir = path.join(os.homedir(), '.openclaw');
28
+ const targetPath = path.join(openclawDir, 'openclaw.json');
29
+
30
+ if (!fs.existsSync(targetPath)) {
31
+ console.error('❌ 未找到 openclaw.json');
32
+ console.error(' 期望路径: ' + targetPath);
33
+ console.error(' 请先安装 OpenClaw: myclaw install');
34
+ process.exit(1);
35
+ }
36
+
37
+ console.log('📍 找到配置: ' + targetPath);
38
+
39
+ // 读取并修改
40
+ const config = JSON.parse(fs.readFileSync(targetPath, 'utf8'));
41
+
42
+ // 1. auth.profiles → 只保留 minimax
43
+ config.auth = {
44
+ profiles: {
45
+ "minimax:cn": {
46
+ provider: "minimax",
47
+ mode: "api_key"
48
+ }
49
+ }
50
+ };
51
+
52
+ // 2. models.providers → 只保留 minimax
53
+ config.models = {
54
+ mode: "merge",
55
+ providers: {
56
+ minimax: {
57
+ baseUrl: "https://api.minimaxi.com/anthropic",
58
+ api: "anthropic-messages",
59
+ authHeader: true,
60
+ headers: {
61
+ "Authorization": "Bearer ${env:MINIMAX_API_KEY}"
62
+ },
63
+ models: [
64
+ {
65
+ id: "MiniMax-M2.7",
66
+ name: "MiniMax M2.7",
67
+ reasoning: true,
68
+ input: ["text"],
69
+ cost: {
70
+ input: 0.3,
71
+ output: 1.2,
72
+ cacheRead: 0.06,
73
+ cacheWrite: 0.375
74
+ },
75
+ contextWindow: 204800,
76
+ maxTokens: 131072
77
+ }
78
+ ]
79
+ }
80
+ }
81
+ };
82
+
83
+ // 3. agents.defaults → 使用 minimax 模型
84
+ if (!config.agents) config.agents = {};
85
+ if (!config.agents.defaults) config.agents.defaults = {};
86
+
87
+ config.agents.defaults.model = {
88
+ primary: "minimax/MiniMax-M2.7-highspeed"
89
+ };
90
+
91
+ config.agents.defaults.imageGenerationModel = {
92
+ primary: "minimax/image-01"
93
+ };
94
+
95
+ config.agents.defaults.models = {
96
+ "minimax/MiniMax-M2.7-highspeed": {}
97
+ };
98
+
99
+ // 写回文件
100
+ const output = JSON.stringify(config, null, 2) + '\n';
101
+ fs.writeFileSync(targetPath, output, 'utf8');
102
+
103
+ console.log('✅ MiniMax 模型配置已注入');
104
+ console.log('');
105
+ console.log(' auth.profiles → minimax:cn');
106
+ console.log(' models.providers → minimax (MiniMax-M2.7)');
107
+ console.log(' agents.defaults → minimax/MiniMax-M2.7-highspeed');
108
+
109
+ // 4. 如果传了 --key,写入环境变量
110
+ if (apiKey) {
111
+ console.log('');
112
+ console.log('🔑 设置 MINIMAX_API_KEY 环境变量...');
113
+
114
+ const platform = os.platform();
115
+
116
+ if (platform === 'win32') {
117
+ try {
118
+ const { execSync } = require('child_process');
119
+ execSync('setx MINIMAX_API_KEY "' + apiKey + '"', { stdio: 'pipe' });
120
+ console.log(' ✅ 已通过 setx 写入 Windows 用户环境变量');
121
+ } catch (err) {
122
+ console.log(' ❌ setx 写入失败: ' + err.message);
123
+ }
124
+ } else {
125
+ const shell = process.env.SHELL || '/bin/bash';
126
+ let rcFiles = [];
127
+ if (shell.includes('zsh')) {
128
+ rcFiles = [path.join(os.homedir(), '.zshrc')];
129
+ } else {
130
+ rcFiles = [path.join(os.homedir(), '.bashrc')];
131
+ }
132
+ const profilePath = path.join(os.homedir(), '.profile');
133
+ if (fs.existsSync(profilePath) && !rcFiles.includes(profilePath)) {
134
+ rcFiles.push(profilePath);
135
+ }
136
+
137
+ const exportLine = 'export MINIMAX_API_KEY="' + apiKey + '"';
138
+
139
+ for (const rcFile of rcFiles) {
140
+ let content = '';
141
+ try { content = fs.readFileSync(rcFile, 'utf8'); } catch {}
142
+
143
+ if (content.includes('MINIMAX_API_KEY')) {
144
+ content = content.replace(/^export MINIMAX_API_KEY=.*$/m, exportLine);
145
+ fs.writeFileSync(rcFile, content, 'utf8');
146
+ console.log(' ✅ 已更新: ' + rcFile);
147
+ } else {
148
+ fs.appendFileSync(rcFile, '\n# MiniMax API Key (by myclaw minimax)\n' + exportLine + '\n');
149
+ console.log(' ✅ 已追加: ' + rcFile);
150
+ }
151
+ }
152
+
153
+ process.env.MINIMAX_API_KEY = apiKey;
154
+ console.log(' ✅ 当前进程已设置 MINIMAX_API_KEY');
155
+ }
156
+ } else {
157
+ console.log('');
158
+ console.log('💡 未传入 --key,API Key 将使用环境变量 MINIMAX_API_KEY');
159
+ console.log(' 设置方法: myclaw minimax --key sk-xxx');
160
+ }
161
+
162
+ console.log('');
163
+ }
164
+
165
+ module.exports = { run };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
package/patch-skill.js ADDED
@@ -0,0 +1,171 @@
1
+ /**
2
+ * ============================================================================
3
+ * MyClaw Patch Skill Engine
4
+ * ============================================================================
5
+ *
6
+ * 功能:
7
+ * 1. 探测 OpenClaw 安装路径下的 skills/ 目录
8
+ * 2. 将 myclaw 自带的 skill 复制到 openclaw/skills/ 下
9
+ * 3. 幂等:重复执行覆盖更新
10
+ *
11
+ * 使用:
12
+ * const { patchSkills, listSkills } = require('./patch-skill');
13
+ * patchSkills(); // 注入所有 skill
14
+ * listSkills(); // 列出已注入的 skill
15
+ * ============================================================================
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ /**
22
+ * 探测 OpenClaw 的 skills 目录
23
+ */
24
+ function findSkillsDir() {
25
+ const candidates = [];
26
+
27
+ // 全局 node_modules 路径
28
+ const globalPaths = [
29
+ '/usr/lib/node_modules',
30
+ '/usr/local/lib/node_modules',
31
+ ];
32
+
33
+ try {
34
+ const { execSync } = require('child_process');
35
+ const prefix = execSync('npm config get prefix 2>/dev/null', { encoding: 'utf8' }).trim();
36
+ if (prefix) {
37
+ globalPaths.push(path.join(prefix, 'lib', 'node_modules'));
38
+ }
39
+ } catch {}
40
+
41
+ for (const globalPath of globalPaths) {
42
+ candidates.push(path.join(globalPath, 'openclaw', 'skills'));
43
+ }
44
+
45
+ // 通过 which openclaw 推断
46
+ try {
47
+ const { execSync } = require('child_process');
48
+ const bin = execSync('which openclaw 2>/dev/null', { encoding: 'utf8' }).trim();
49
+ if (bin) {
50
+ const real = fs.realpathSync(bin);
51
+ const pkgRoot = path.dirname(real);
52
+ candidates.push(path.join(pkgRoot, 'skills'));
53
+ candidates.push(path.join(path.dirname(pkgRoot), 'skills'));
54
+ }
55
+ } catch {}
56
+
57
+ // 找到第一个存在的
58
+ for (const dir of candidates) {
59
+ try {
60
+ if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
61
+ return dir;
62
+ }
63
+ } catch {}
64
+ }
65
+
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * 递归复制目录
71
+ */
72
+ function copyDirSync(src, dest) {
73
+ if (!fs.existsSync(dest)) {
74
+ fs.mkdirSync(dest, { recursive: true });
75
+ }
76
+
77
+ const entries = fs.readdirSync(src, { withFileTypes: true });
78
+ for (const entry of entries) {
79
+ const srcPath = path.join(src, entry.name);
80
+ const destPath = path.join(dest, entry.name);
81
+
82
+ if (entry.isDirectory()) {
83
+ copyDirSync(srcPath, destPath);
84
+ } else {
85
+ fs.copyFileSync(srcPath, destPath);
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * 注入所有 myclaw skills
92
+ */
93
+ function patchSkills() {
94
+ const skillsDir = findSkillsDir();
95
+ if (!skillsDir) {
96
+ console.log('[myclaw-skill] ❌ 未找到 OpenClaw skills 目录');
97
+ console.log('[myclaw-skill] 提示: 确保 openclaw 已全局安装');
98
+ return { success: false, reason: 'skills-dir-not-found' };
99
+ }
100
+
101
+ console.log('[myclaw-skill] 📍 找到 skills 目录: ' + skillsDir);
102
+
103
+ // myclaw 自带的 skills 源目录
104
+ const myclawSkillsDir = path.join(__dirname, 'skills');
105
+
106
+ if (!fs.existsSync(myclawSkillsDir)) {
107
+ console.log('[myclaw-skill] ⚠️ 无 skill 可注入 (skills/ 目录不存在)');
108
+ return { success: true, count: 0 };
109
+ }
110
+
111
+ // 遍历 skills/ 目录下的每个子目录 = 一个 skill
112
+ const skillDirs = fs.readdirSync(myclawSkillsDir, { withFileTypes: true })
113
+ .filter(d => d.isDirectory());
114
+
115
+ if (skillDirs.length === 0) {
116
+ console.log('[myclaw-skill] ⚠️ 无 skill 可注入 (skills/ 目录为空)');
117
+ return { success: true, count: 0 };
118
+ }
119
+
120
+ let count = 0;
121
+ for (const skillDir of skillDirs) {
122
+ const srcDir = path.join(myclawSkillsDir, skillDir.name);
123
+ const destDir = path.join(skillsDir, skillDir.name);
124
+
125
+ // 检查是否有 SKILL.md(必须有才是合法 skill)
126
+ if (!fs.existsSync(path.join(srcDir, 'SKILL.md'))) {
127
+ console.log('[myclaw-skill] ⚠️ 跳过 ' + skillDir.name + ' (缺少 SKILL.md)');
128
+ continue;
129
+ }
130
+
131
+ copyDirSync(srcDir, destDir);
132
+ count++;
133
+ console.log('[myclaw-skill] ✅ 已注入: ' + skillDir.name);
134
+ }
135
+
136
+ console.log('[myclaw-skill] 🎉 共注入 ' + count + ' 个 skill');
137
+ return { success: true, count };
138
+ }
139
+
140
+ /**
141
+ * 列出已注入的 myclaw skills
142
+ */
143
+ function listSkills() {
144
+ const skillsDir = findSkillsDir();
145
+ if (!skillsDir) {
146
+ console.log('[myclaw-skill] ❌ 未找到 OpenClaw skills 目录');
147
+ return [];
148
+ }
149
+
150
+ const myclawSkillsDir = path.join(__dirname, 'skills');
151
+ if (!fs.existsSync(myclawSkillsDir)) {
152
+ return [];
153
+ }
154
+
155
+ const mySkillNames = fs.readdirSync(myclawSkillsDir, { withFileTypes: true })
156
+ .filter(d => d.isDirectory())
157
+ .map(d => d.name);
158
+
159
+ const installed = [];
160
+ for (const name of mySkillNames) {
161
+ const destDir = path.join(skillsDir, name);
162
+ installed.push({
163
+ name,
164
+ installed: fs.existsSync(destDir),
165
+ });
166
+ }
167
+
168
+ return installed;
169
+ }
170
+
171
+ module.exports = { patchSkills, listSkills, findSkillsDir };
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: minimax-inject
3
+ description: 将 OpenClaw 的模型配置替换为 MiniMax M2.7,并可选设置 API Key。执行后自动重启 Gateway。
4
+ ---
5
+
6
+ # MiniMax 模型注入
7
+
8
+ 将 OpenClaw 的模型配置清空,替换为唯一的 MiniMax M2.7 模型。
9
+
10
+ ## 使用方法
11
+
12
+ ```bash
13
+ # 只注入模型配置(API Key 使用环境变量 MINIMAX_API_KEY)
14
+ node scripts/inject.js
15
+
16
+ # 注入模型 + 设置 API Key
17
+ node scripts/inject.js --key sk-你的key
18
+ ```
19
+
20
+ ## 注入内容
21
+
22
+ | 字段 | 值 |
23
+ |------|-----|
24
+ | auth.profiles | minimax:cn |
25
+ | models.providers | minimax (MiniMax-M2.7) |
26
+ | agents.defaults.model | minimax/MiniMax-M2.7-highspeed |
27
+ | imageGenerationModel | minimax/image-01 |
28
+
29
+ ## 执行后
30
+
31
+ - 自动修改 `~/.openclaw/openclaw.json`
32
+ - 自动重启 Gateway 使配置生效
33
+ - 如果传了 `--key`,会将 MINIMAX_API_KEY 写入 shell 配置文件
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MiniMax 模型注入脚本
5
+ *
6
+ * 独立运行,不依赖 myclaw CLI。
7
+ * OpenClaw agent 可直接调用此脚本。
8
+ *
9
+ * 用法:
10
+ * node inject.js # 注入模型配置
11
+ * node inject.js --key sk-xxx # 注入模型 + 设置 API Key
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const os = require('os');
17
+ const { execSync } = require('child_process');
18
+
19
+ // ============================================================================
20
+ // 解析参数
21
+ // ============================================================================
22
+
23
+ let apiKey = null;
24
+ const args = process.argv.slice(2);
25
+ for (let i = 0; i < args.length; i++) {
26
+ if (args[i] === '--key' && args[i + 1]) {
27
+ apiKey = args[i + 1];
28
+ i++;
29
+ }
30
+ }
31
+
32
+ // ============================================================================
33
+ // 查找 openclaw.json
34
+ // ============================================================================
35
+
36
+ const openclawDir = path.join(os.homedir(), '.openclaw');
37
+ const targetPath = path.join(openclawDir, 'openclaw.json');
38
+
39
+ if (!fs.existsSync(targetPath)) {
40
+ console.error('❌ 未找到 openclaw.json: ' + targetPath);
41
+ process.exit(1);
42
+ }
43
+
44
+ console.log('📍 找到配置: ' + targetPath);
45
+
46
+ // ============================================================================
47
+ // 注入模型配置
48
+ // ============================================================================
49
+
50
+ const config = JSON.parse(fs.readFileSync(targetPath, 'utf8'));
51
+
52
+ config.auth = {
53
+ profiles: {
54
+ "minimax:cn": {
55
+ provider: "minimax",
56
+ mode: "api_key"
57
+ }
58
+ }
59
+ };
60
+
61
+ config.models = {
62
+ mode: "merge",
63
+ providers: {
64
+ minimax: {
65
+ baseUrl: "https://api.minimaxi.com/anthropic",
66
+ api: "anthropic-messages",
67
+ authHeader: true,
68
+ headers: {
69
+ "Authorization": "Bearer ${env:MINIMAX_API_KEY}"
70
+ },
71
+ models: [
72
+ {
73
+ id: "MiniMax-M2.7",
74
+ name: "MiniMax M2.7",
75
+ reasoning: true,
76
+ input: ["text"],
77
+ cost: {
78
+ input: 0.3,
79
+ output: 1.2,
80
+ cacheRead: 0.06,
81
+ cacheWrite: 0.375
82
+ },
83
+ contextWindow: 204800,
84
+ maxTokens: 131072
85
+ }
86
+ ]
87
+ }
88
+ }
89
+ };
90
+
91
+ if (!config.agents) config.agents = {};
92
+ if (!config.agents.defaults) config.agents.defaults = {};
93
+
94
+ config.agents.defaults.model = {
95
+ primary: "minimax/MiniMax-M2.7-highspeed"
96
+ };
97
+
98
+ config.agents.defaults.imageGenerationModel = {
99
+ primary: "minimax/image-01"
100
+ };
101
+
102
+ config.agents.defaults.models = {
103
+ "minimax/MiniMax-M2.7-highspeed": {}
104
+ };
105
+
106
+ fs.writeFileSync(targetPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
107
+
108
+ console.log('✅ MiniMax 模型配置已注入');
109
+ console.log(' auth.profiles → minimax:cn');
110
+ console.log(' models.providers → minimax (MiniMax-M2.7)');
111
+ console.log(' agents.defaults → minimax/MiniMax-M2.7-highspeed');
112
+
113
+ // ============================================================================
114
+ // 设置 API Key(如果传了 --key)
115
+ // ============================================================================
116
+
117
+ if (apiKey) {
118
+ console.log('');
119
+ console.log('🔑 设置 MINIMAX_API_KEY...');
120
+
121
+ if (os.platform() === 'win32') {
122
+ try {
123
+ execSync('setx MINIMAX_API_KEY "' + apiKey + '"', { stdio: 'pipe' });
124
+ console.log(' ✅ 已写入 Windows 用户环境变量');
125
+ } catch (err) {
126
+ console.log(' ❌ setx 失败: ' + err.message);
127
+ }
128
+ } else {
129
+ const shell = process.env.SHELL || '/bin/bash';
130
+ const rcFile = shell.includes('zsh')
131
+ ? path.join(os.homedir(), '.zshrc')
132
+ : path.join(os.homedir(), '.bashrc');
133
+
134
+ const exportLine = 'export MINIMAX_API_KEY="' + apiKey + '"';
135
+ let content = '';
136
+ try { content = fs.readFileSync(rcFile, 'utf8'); } catch {}
137
+
138
+ if (content.includes('MINIMAX_API_KEY')) {
139
+ content = content.replace(/^export MINIMAX_API_KEY=.*$/m, exportLine);
140
+ fs.writeFileSync(rcFile, content, 'utf8');
141
+ console.log(' ✅ 已更新: ' + rcFile);
142
+ } else {
143
+ fs.appendFileSync(rcFile, '\n# MiniMax API Key\n' + exportLine + '\n');
144
+ console.log(' ✅ 已追加: ' + rcFile);
145
+ }
146
+
147
+ // 同时设到当前进程,确保重启的 gateway 能继承
148
+ process.env.MINIMAX_API_KEY = apiKey;
149
+ console.log(' ✅ 当前进程已设置');
150
+ }
151
+ } else {
152
+ console.log('');
153
+ console.log('💡 未传入 --key,将使用环境变量 MINIMAX_API_KEY');
154
+ }
155
+
156
+ // ============================================================================
157
+ // 重启 Gateway(不依赖 myclaw)
158
+ // ============================================================================
159
+
160
+ console.log('');
161
+ console.log('🔄 重启 Gateway...');
162
+
163
+ try {
164
+ execSync('openclaw gateway stop', { stdio: 'pipe', timeout: 10000 });
165
+ console.log(' Gateway 已停止');
166
+ } catch {
167
+ console.log(' Gateway 未在运行');
168
+ }
169
+
170
+ try {
171
+ execSync('nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &', {
172
+ stdio: 'ignore',
173
+ shell: true,
174
+ });
175
+ execSync('sleep 2', { stdio: 'ignore' });
176
+
177
+ try {
178
+ execSync('openclaw health', { stdio: 'pipe', timeout: 5000 });
179
+ console.log(' ✅ Gateway 启动成功');
180
+ } catch {
181
+ console.log(' ⏳ Gateway 启动中...');
182
+ }
183
+ } catch (err) {
184
+ console.error(' ❌ 启动失败: ' + err.message);
185
+ }
186
+
187
+ console.log('');