@aiyiran/myclaw 1.0.5 → 1.0.6
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/README.md +126 -0
- package/create_agent.js +272 -0
- package/index.js +87 -57
- package/package.json +1 -1
- package/publish.sh +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# MyClaw - 学生友好的 OpenClaw 工具
|
|
2
|
+
|
|
3
|
+
一个简化 OpenClaw 日常操作的命令行工具,专为教学环境设计。
|
|
4
|
+
|
|
5
|
+
## 跨平台要求 ⚠️
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
╔══════════════════════════════════════════════════════════════════════╗
|
|
9
|
+
║ 跨平台兼容性说明 ║
|
|
10
|
+
╠══════════════════════════════════════════════════════════════════════╣
|
|
11
|
+
║ ║
|
|
12
|
+
║ 支持系统: ║
|
|
13
|
+
║ ✅ macOS - 完全支持,包括颜色和 Emoji ║
|
|
14
|
+
║ ✅ Linux - 完全支持,包括颜色和 Emoji ║
|
|
15
|
+
║ ✅ Windows 10/11 - 基本支持,推荐使用 Windows Terminal ║
|
|
16
|
+
║ ⚠️ Windows 7/8 - 支持,但 Emoji 可能显示为方块 ║
|
|
17
|
+
║ ║
|
|
18
|
+
║ Windows 用户建议: ║
|
|
19
|
+
║ • 安装 Windows Terminal (Microsoft Store 免费下载) ║
|
|
20
|
+
║ • 或使用 PowerShell 7+ (https://aka.ms/powershell) ║
|
|
21
|
+
║ ║
|
|
22
|
+
║ 颜色说明: ║
|
|
23
|
+
║ • macOS/Linux: 正常显示 ANSI 颜色 ║
|
|
24
|
+
║ • Windows: 自动禁用颜色输出,避免乱码 ║
|
|
25
|
+
║ ║
|
|
26
|
+
╚══════════════════════════════════════════════════════════════════════╝
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 安装
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 方式一: 直接运行
|
|
33
|
+
node myclaw/index.js <command>
|
|
34
|
+
|
|
35
|
+
# 方式二: 添加到 PATH (macOS/Linux)
|
|
36
|
+
ln -s /path/to/myclaw/index.js /usr/local/bin/myclaw
|
|
37
|
+
chmod +x /usr/local/bin/myclaw
|
|
38
|
+
|
|
39
|
+
# 方式三: Windows PowerShell
|
|
40
|
+
# 将 myclaw/index.js 路径添加到系统 PATH
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 使用方法
|
|
44
|
+
|
|
45
|
+
### 查看状态
|
|
46
|
+
```bash
|
|
47
|
+
myclaw status
|
|
48
|
+
```
|
|
49
|
+
简化版的 OpenClaw 状态面板,一眼看清 Gateway、Agents、Sessions 状态。
|
|
50
|
+
|
|
51
|
+
### 创建新 Agent
|
|
52
|
+
```bash
|
|
53
|
+
myclaw new <agent名称>
|
|
54
|
+
```
|
|
55
|
+
快速创建一个新的 OpenClaw Agent,自动完成:
|
|
56
|
+
- 创建 workspace 目录
|
|
57
|
+
- 配置 agent 文件
|
|
58
|
+
- 发送出生消息
|
|
59
|
+
|
|
60
|
+
示例:
|
|
61
|
+
```bash
|
|
62
|
+
myclaw new helper # 创建名为 helper 的 Agent
|
|
63
|
+
myclaw new testbot # 创建名为 testbot 的 Agent
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 安装 OpenClaw
|
|
67
|
+
```bash
|
|
68
|
+
myclaw install
|
|
69
|
+
```
|
|
70
|
+
自动检测操作系统并执行对应的安装命令。
|
|
71
|
+
|
|
72
|
+
### 帮助
|
|
73
|
+
```bash
|
|
74
|
+
myclaw help
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 文件结构
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
myclaw/
|
|
81
|
+
├── index.js # 主入口,命令解析和输出
|
|
82
|
+
├── create_agent.js # Agent 创建逻辑模块
|
|
83
|
+
└── README.md # 本文件
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 模块说明
|
|
87
|
+
|
|
88
|
+
| 文件 | 职责 |
|
|
89
|
+
|------|------|
|
|
90
|
+
| `index.js` | 主入口,解析命令、颜色输出、调用模块 |
|
|
91
|
+
| `create_agent.js` | Agent 创建的完整逻辑,可独立使用 |
|
|
92
|
+
|
|
93
|
+
## 开发说明
|
|
94
|
+
|
|
95
|
+
### 代码规范
|
|
96
|
+
|
|
97
|
+
1. **跨平台兼容性** - 必须考虑 Windows 用户体验
|
|
98
|
+
- 使用 `os.platform()` 检测系统
|
|
99
|
+
- Windows 下禁用 ANSI 颜色输出
|
|
100
|
+
- 避免使用只在 Unix 系统有效的命令
|
|
101
|
+
|
|
102
|
+
2. **错误处理**
|
|
103
|
+
- 所有 `execSync` 调用必须使用 `try-catch`
|
|
104
|
+
- 失败时提供清晰的错误信息和解决方案
|
|
105
|
+
|
|
106
|
+
3. **模块化**
|
|
107
|
+
- 业务逻辑放入独立模块
|
|
108
|
+
- 主入口只做命令解析和输出
|
|
109
|
+
|
|
110
|
+
### 测试清单
|
|
111
|
+
|
|
112
|
+
发布前请在以下环境测试:
|
|
113
|
+
- [ ] macOS (Terminal)
|
|
114
|
+
- [ ] Linux (bash)
|
|
115
|
+
- [ ] Windows 10/11 (PowerShell)
|
|
116
|
+
- [ ] Windows 10/11 (CMD)
|
|
117
|
+
- [ ] Windows Terminal (如果可用)
|
|
118
|
+
|
|
119
|
+
## 依赖
|
|
120
|
+
|
|
121
|
+
- Node.js 14+
|
|
122
|
+
- OpenClaw CLI (用于实际命令执行)
|
|
123
|
+
|
|
124
|
+
## 许可证
|
|
125
|
+
|
|
126
|
+
内部教学工具
|
package/create_agent.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* MyClaw - Create Agent 模块
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* 创建 OpenClaw Agent 的完整逻辑
|
|
7
|
+
*
|
|
8
|
+
* 功能:
|
|
9
|
+
* - 标准化 agent ID
|
|
10
|
+
* - 检查重复
|
|
11
|
+
* - 创建工作空间目录和默认文件
|
|
12
|
+
* - 更新 OpenClaw 配置文件
|
|
13
|
+
* - 发送出生消息
|
|
14
|
+
*
|
|
15
|
+
* ============================================================================
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// 路径工具
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
function normalizePath(p) {
|
|
28
|
+
return p.replace(/\\/g, '/');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function ensureDir(dirPath) {
|
|
32
|
+
if (!fs.existsSync(dirPath)) {
|
|
33
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function writeIfAbsent(filePath, content) {
|
|
38
|
+
if (!fs.existsSync(filePath)) {
|
|
39
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// 工具函数
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
function fail(msg, code = 1) {
|
|
48
|
+
console.error('[错误] ' + msg);
|
|
49
|
+
process.exit(code);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 标准化 agent ID
|
|
54
|
+
* - 转小写
|
|
55
|
+
* - 非法字符替换为连字符
|
|
56
|
+
* - 去除多余连字符
|
|
57
|
+
*/
|
|
58
|
+
function normalizeAgentId(raw) {
|
|
59
|
+
let value = raw.trim().toLowerCase();
|
|
60
|
+
value = value.replace(/[^a-z0-9-]/g, '-');
|
|
61
|
+
value = value.replace(/-{2,}/g, '-').replace(/^-|-$/g, '');
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 验证 agent ID
|
|
67
|
+
*/
|
|
68
|
+
function validateAgentId(agentId) {
|
|
69
|
+
if (!agentId) {
|
|
70
|
+
fail('Agent 名称标准化后为空,请检查输入。');
|
|
71
|
+
}
|
|
72
|
+
if (agentId.length > 64) {
|
|
73
|
+
fail('Agent ID 太长,请保持在 64 个字符以内。');
|
|
74
|
+
}
|
|
75
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentId)) {
|
|
76
|
+
fail('Agent ID 只能包含小写字母、数字和连字符(不能以连字符开头或结尾)。');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 生成北京时间出生消息
|
|
82
|
+
*/
|
|
83
|
+
function buildBirthMessage() {
|
|
84
|
+
const nowUtc = new Date();
|
|
85
|
+
const nowBj = new Date(nowUtc.getTime() + 8 * 60 * 60 * 1000);
|
|
86
|
+
const y = nowBj.getUTCFullYear();
|
|
87
|
+
const m = nowBj.getUTCMonth() + 1;
|
|
88
|
+
const d = nowBj.getUTCDate();
|
|
89
|
+
const h = String(nowBj.getUTCHours()).padStart(2, '0');
|
|
90
|
+
const min = String(nowBj.getUTCMinutes()).padStart(2, '0');
|
|
91
|
+
const ts = `${y}年${m}月${d}日${h}:${min}`;
|
|
92
|
+
return (
|
|
93
|
+
`你好,你的生日是北京时间${ts},请记录这个信息。\n` +
|
|
94
|
+
'欢迎你来到这个世界,我是你的造物主,我们是伙伴,我叫做孙依然,' +
|
|
95
|
+
'你可以叫我依然,请多多指教,共同成长。'
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 默认工作空间文件内容
|
|
101
|
+
*/
|
|
102
|
+
function defaultWorkspaceFiles(agentId) {
|
|
103
|
+
return {
|
|
104
|
+
'AGENTS.md': (
|
|
105
|
+
`# AGENTS.md - ${agentId}\n\n` +
|
|
106
|
+
`This workspace belongs to the \`${agentId}\` agent.\n\n` +
|
|
107
|
+
'## Startup\n' +
|
|
108
|
+
'- Read `SOUL.md`\n' +
|
|
109
|
+
'- Read `USER.md`\n' +
|
|
110
|
+
'- Read recent memory if available\n\n' +
|
|
111
|
+
'## Rules\n' +
|
|
112
|
+
'- Be helpful, careful, and concise.\n' +
|
|
113
|
+
'- Prefer using the existing workspace and defaults.\n' +
|
|
114
|
+
'- Ask before destructive or external actions.\n'
|
|
115
|
+
),
|
|
116
|
+
'SOUL.md': (
|
|
117
|
+
`# SOUL.md\n\n` +
|
|
118
|
+
`You are \`${agentId}\`.\n\n` +
|
|
119
|
+
'Be useful, calm, direct, and trustworthy.\n' +
|
|
120
|
+
'Use the default OpenClaw behavior unless the user asks for something special.\n'
|
|
121
|
+
),
|
|
122
|
+
'USER.md': (
|
|
123
|
+
'# USER.md\n\n' +
|
|
124
|
+
'- Name: 孙依然\n' +
|
|
125
|
+
'- What to call them: 依然\n' +
|
|
126
|
+
'- Timezone: Asia/Shanghai\n\n' +
|
|
127
|
+
'Build understanding gradually and respectfully.\n'
|
|
128
|
+
),
|
|
129
|
+
'IDENTITY.md': (
|
|
130
|
+
'# IDENTITY.md\n\n' +
|
|
131
|
+
`- Name: ${agentId}\n` +
|
|
132
|
+
'- Role: OpenClaw agent\n' +
|
|
133
|
+
'- Vibe: practical, reliable, clear\n'
|
|
134
|
+
),
|
|
135
|
+
'HEARTBEAT.md': (
|
|
136
|
+
'# HEARTBEAT.md\n\n' +
|
|
137
|
+
'# Keep empty unless periodic checks are needed.\n'
|
|
138
|
+
),
|
|
139
|
+
'BOOTSTRAP.md': (
|
|
140
|
+
`# BOOTSTRAP.md\n\n` +
|
|
141
|
+
`You are a newly created OpenClaw agent named \`${agentId}\`.\n\n` +
|
|
142
|
+
'On first runs, learn your workspace files and begin helping.\n'
|
|
143
|
+
),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// 主函数
|
|
149
|
+
// ============================================================================
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 创建新的 OpenClaw Agent
|
|
153
|
+
*
|
|
154
|
+
* @param {string} rawName - 原始名称
|
|
155
|
+
* @returns {object} 创建结果
|
|
156
|
+
*/
|
|
157
|
+
function createAgent(rawName) {
|
|
158
|
+
// 标准化 & 验证名称
|
|
159
|
+
const agentId = normalizeAgentId(rawName);
|
|
160
|
+
validateAgentId(agentId);
|
|
161
|
+
|
|
162
|
+
// 确定 OpenClaw 配置目录
|
|
163
|
+
const homeDir = os.homedir();
|
|
164
|
+
const openclawDir = path.join(homeDir, '.openclaw');
|
|
165
|
+
const configPath = path.join(openclawDir, 'openclaw.json');
|
|
166
|
+
const agentsDir = path.join(openclawDir, 'agents');
|
|
167
|
+
const workspaceDir = path.join(openclawDir, 'workspace-' + agentId);
|
|
168
|
+
const agentDir = path.join(agentsDir, agentId, 'agent');
|
|
169
|
+
|
|
170
|
+
// 检查配置是否存在
|
|
171
|
+
if (!fs.existsSync(configPath)) {
|
|
172
|
+
fail('配置文件不存在: ' + normalizePath(configPath) + '\n请先运行 openclaw onboard 完成初始化。');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 加载配置
|
|
176
|
+
let configData;
|
|
177
|
+
try {
|
|
178
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
179
|
+
configData = JSON.parse(raw);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
fail('配置文件读取失败: ' + err.message);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 确保 agents 结构存在
|
|
185
|
+
if (!configData.agents) {
|
|
186
|
+
configData.agents = {};
|
|
187
|
+
}
|
|
188
|
+
if (!Array.isArray(configData.agents.list)) {
|
|
189
|
+
configData.agents.list = [];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 检查重复 ID
|
|
193
|
+
const existingIds = new Set(
|
|
194
|
+
configData.agents.list
|
|
195
|
+
.filter(e => e && typeof e === 'object')
|
|
196
|
+
.map(e => e.id)
|
|
197
|
+
);
|
|
198
|
+
if (existingIds.has(agentId)) {
|
|
199
|
+
fail('Agent "' + agentId + '" 已存在,请使用其他名称。');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 检查目录冲突
|
|
203
|
+
if (fs.existsSync(workspaceDir) || fs.existsSync(agentDir)) {
|
|
204
|
+
fail(
|
|
205
|
+
'工作空间或 Agent 目录已存在,请检查是否已有同名 Agent。\n' +
|
|
206
|
+
'workspace=' + normalizePath(workspaceDir) + '\n' +
|
|
207
|
+
'agentDir=' + normalizePath(agentDir)
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 创建目录结构
|
|
212
|
+
ensureDir(workspaceDir);
|
|
213
|
+
ensureDir(agentDir);
|
|
214
|
+
ensureDir(path.join(agentsDir, agentId, 'sessions'));
|
|
215
|
+
|
|
216
|
+
// 创建默认工作空间文件
|
|
217
|
+
const files = defaultWorkspaceFiles(agentId);
|
|
218
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
219
|
+
writeIfAbsent(path.join(workspaceDir, filename), content);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 备份配置
|
|
223
|
+
const backupPath = configPath + '.bak.agent-birth.' +
|
|
224
|
+
new Date().toISOString().replace(/[:.]/g, '-').slice(0, 26) + 'Z';
|
|
225
|
+
fs.copyFileSync(configPath, backupPath);
|
|
226
|
+
|
|
227
|
+
// 添加 Agent 条目
|
|
228
|
+
configData.agents.list.push({
|
|
229
|
+
id: agentId,
|
|
230
|
+
name: agentId,
|
|
231
|
+
workspace: workspaceDir,
|
|
232
|
+
agentDir: agentDir,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// 写入配置
|
|
236
|
+
try {
|
|
237
|
+
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf8');
|
|
238
|
+
} catch (err) {
|
|
239
|
+
fail('配置文件写入失败: ' + err.message + '\n备份文件: ' + normalizePath(backupPath));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 发送出生消息
|
|
243
|
+
const birthMessage = buildBirthMessage();
|
|
244
|
+
let firstMessageSent = false;
|
|
245
|
+
let firstMessageError = null;
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
execSync(
|
|
249
|
+
'openclaw agent --agent ' + agentId + ' --message ' + JSON.stringify(birthMessage) + ' --json 2>&1',
|
|
250
|
+
{ encoding: 'utf8', timeout: 30000 }
|
|
251
|
+
);
|
|
252
|
+
firstMessageSent = true;
|
|
253
|
+
} catch (err) {
|
|
254
|
+
firstMessageSent = false;
|
|
255
|
+
firstMessageError = err.message;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 返回结果
|
|
259
|
+
return {
|
|
260
|
+
ok: true,
|
|
261
|
+
agentId: agentId,
|
|
262
|
+
sessionKey: 'agent:' + agentId + ':main',
|
|
263
|
+
workspace: normalizePath(workspaceDir),
|
|
264
|
+
agentDir: normalizePath(agentDir),
|
|
265
|
+
configBackup: normalizePath(backupPath),
|
|
266
|
+
birthMessage: birthMessage,
|
|
267
|
+
firstMessageSent: firstMessageSent,
|
|
268
|
+
firstMessageError: firstMessageError,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = { createAgent, normalizeAgentId, validateAgentId };
|
package/index.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
const { execSync } = require('child_process');
|
|
27
27
|
const os = require('os');
|
|
28
|
+
const { createAgent } = require('./create_agent');
|
|
28
29
|
|
|
29
30
|
const args = process.argv.slice(2);
|
|
30
31
|
const command = args[0];
|
|
@@ -46,22 +47,10 @@ const isWindows = detectPlatform() === 'windows';
|
|
|
46
47
|
// 跨平台颜色输出
|
|
47
48
|
// ============================================================================
|
|
48
49
|
|
|
49
|
-
/**
|
|
50
|
-
* 颜色输出函数 - 自动兼容 Windows
|
|
51
|
-
* Windows 旧版本会 stripped ANSI 颜色代码,避免乱码
|
|
52
|
-
*/
|
|
53
50
|
function makeColors() {
|
|
54
51
|
if (isWindows) {
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
red: '',
|
|
58
|
-
green: '',
|
|
59
|
-
yellow: '',
|
|
60
|
-
blue: '',
|
|
61
|
-
nc: ''
|
|
62
|
-
};
|
|
52
|
+
return { red: '', green: '', yellow: '', blue: '', nc: '' };
|
|
63
53
|
}
|
|
64
|
-
// macOS/Linux: 正常 ANSI 颜色
|
|
65
54
|
return {
|
|
66
55
|
red: '\x1b[31m',
|
|
67
56
|
green: '\x1b[32m',
|
|
@@ -189,86 +178,124 @@ function runStatus() {
|
|
|
189
178
|
// ============================================================================
|
|
190
179
|
|
|
191
180
|
function runNew() {
|
|
192
|
-
const
|
|
181
|
+
const rawName = args[1];
|
|
193
182
|
|
|
194
|
-
if (!
|
|
183
|
+
if (!rawName) {
|
|
195
184
|
console.error('[' + colors.red + '错误' + colors.nc + '] 请提供 Agent 名称');
|
|
196
185
|
console.log('');
|
|
197
186
|
console.log('用法: myclaw new <agent名称>');
|
|
198
187
|
console.log('');
|
|
199
188
|
console.log('示例:');
|
|
200
189
|
console.log(' myclaw new helper # 创建名为 helper 的 Agent');
|
|
201
|
-
console.log(' myclaw new testbot
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// 验证名称格式
|
|
206
|
-
if (!/^[a-z0-9-]+$/.test(agentName)) {
|
|
207
|
-
console.error('[' + colors.red + '错误' + colors.nc + '] Agent 名称只能包含小写字母、数字和连字符(-)');
|
|
208
|
-
console.log('');
|
|
209
|
-
console.log('示例:');
|
|
210
|
-
console.log(' myclaw new helper');
|
|
211
|
-
console.log(' myclaw new my-bot');
|
|
190
|
+
console.log(' myclaw new testbot # 创建名为 testbot 的 Agent');
|
|
212
191
|
process.exit(1);
|
|
213
192
|
}
|
|
214
193
|
|
|
215
194
|
const bar = '----------------------------------------';
|
|
216
195
|
|
|
217
196
|
console.log('');
|
|
218
|
-
console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + '创建新 Agent
|
|
197
|
+
console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + '创建新 Agent' + colors.nc);
|
|
219
198
|
console.log(bar);
|
|
220
199
|
console.log('');
|
|
221
|
-
|
|
222
|
-
// 检查是否已存在
|
|
223
|
-
try {
|
|
224
|
-
const agentsOutput = execSync('openclaw agents list 2>/dev/null', { encoding: 'utf8' });
|
|
225
|
-
if (agentsOutput.includes(`agent:${agentName}:`)) {
|
|
226
|
-
console.error('[' + colors.red + '错误' + colors.nc + '] Agent "' + agentName + '" 已存在');
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
} catch (e) {
|
|
230
|
-
// 继续创建
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// 查找 yiran-agent-birth 脚本
|
|
234
|
-
const birthScript = '/Users/yiran/.openclaw/workspace/skills/yiran-agent-birth/scripts/create_agent.py';
|
|
235
|
-
|
|
236
200
|
console.log('[创建中] 正在创建 Agent...');
|
|
237
|
-
|
|
201
|
+
console.log('');
|
|
202
|
+
|
|
238
203
|
try {
|
|
239
|
-
const result =
|
|
240
|
-
const jsonResult = JSON.parse(result);
|
|
204
|
+
const result = createAgent(rawName);
|
|
241
205
|
|
|
242
|
-
console.log('');
|
|
243
206
|
console.log('[' + colors.green + '成功' + colors.nc + '] Agent 创建成功!');
|
|
244
207
|
console.log('');
|
|
245
|
-
console.log(' 名称:
|
|
246
|
-
console.log(' Session:
|
|
247
|
-
console.log(' Workspace: ' +
|
|
208
|
+
console.log(' 名称: ' + result.agentId);
|
|
209
|
+
console.log(' Session: ' + result.sessionKey);
|
|
210
|
+
console.log(' Workspace: ' + result.workspace);
|
|
211
|
+
console.log(' 备份: ' + result.configBackup);
|
|
248
212
|
console.log('');
|
|
249
213
|
|
|
250
|
-
if (
|
|
214
|
+
if (result.firstMessageSent) {
|
|
251
215
|
console.log('[' + colors.green + 'OK' + colors.nc + '] 出生消息已发送');
|
|
252
216
|
} else {
|
|
253
|
-
console.log('[' + colors.yellow + '警告' + colors.nc + ']
|
|
217
|
+
console.log('[' + colors.yellow + '警告' + colors.nc + '] 出生消息发送失败');
|
|
218
|
+
if (result.firstMessageError) {
|
|
219
|
+
console.log(' 错误: ' + result.firstMessageError);
|
|
220
|
+
}
|
|
221
|
+
console.log(' 手动重试: ' + colors.yellow + 'openclaw agent --agent ' + result.agentId + ' --message "你好"' + colors.nc);
|
|
254
222
|
}
|
|
255
223
|
|
|
256
224
|
console.log('');
|
|
257
225
|
console.log(bar);
|
|
258
|
-
console.log('下一步: 运行 ' + colors.yellow +
|
|
226
|
+
console.log('下一步: 运行 ' + colors.yellow + 'openclaw agent --agent ' + result.agentId + ' --message "你好"' + colors.nc + ' 与它对话');
|
|
259
227
|
console.log('');
|
|
260
228
|
|
|
261
229
|
} catch (err) {
|
|
262
|
-
|
|
230
|
+
// create_agent.js 已经有错误信息输出
|
|
231
|
+
console.log('');
|
|
232
|
+
console.log('[' + colors.red + '失败' + colors.nc + '] Agent 创建失败');
|
|
263
233
|
console.log('');
|
|
264
|
-
console.log('常见问题:');
|
|
265
|
-
console.log(' - Agent 名称已存在');
|
|
266
|
-
console.log(' - 权限不足');
|
|
267
|
-
console.log(' - OpenClaw 未运行');
|
|
268
234
|
process.exit(1);
|
|
269
235
|
}
|
|
270
236
|
}
|
|
271
237
|
|
|
238
|
+
// ============================================================================
|
|
239
|
+
// 安装/修复 WSL2
|
|
240
|
+
// ============================================================================
|
|
241
|
+
|
|
242
|
+
function runWsl2() {
|
|
243
|
+
if (!isWindows) {
|
|
244
|
+
console.error('[' + colors.red + '提示' + colors.nc + '] 本命令主要用于 Windows 系统。在 Mac/Linux 下不需要安装 WSL2。');
|
|
245
|
+
process.exit(0);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const bar = '----------------------------------------';
|
|
249
|
+
console.log('');
|
|
250
|
+
console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + '修复/安装 Windows WSL2 环境' + colors.nc);
|
|
251
|
+
console.log(bar);
|
|
252
|
+
console.log('');
|
|
253
|
+
console.log('即将申请管理员权限以启用 Windows WSL2 和 虚拟机平台功能...');
|
|
254
|
+
console.log('这使用的是兼容性最好的"手动打补丁"底层方法,用来解决直接安装失败的问题。');
|
|
255
|
+
console.log('[' + colors.yellow + '注意' + colors.nc + '] 请在稍后弹出的 UAC 授权窗口中选【是】。');
|
|
256
|
+
console.log('');
|
|
257
|
+
|
|
258
|
+
const psCommand = `
|
|
259
|
+
Write-Host "============================";
|
|
260
|
+
Write-Host " MyClaw - WSL2 环境底座修复";
|
|
261
|
+
Write-Host "============================";
|
|
262
|
+
Write-Host "";
|
|
263
|
+
Write-Host "步骤 1/3: 正在启用 Windows Subsystem for Linux...";
|
|
264
|
+
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart;
|
|
265
|
+
Write-Host "";
|
|
266
|
+
Write-Host "步骤 2/3: 正在启用 虚拟机平台...";
|
|
267
|
+
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart;
|
|
268
|
+
Write-Host "";
|
|
269
|
+
Write-Host "步骤 3/3: 尝试设置 WSL2 为默认版本...";
|
|
270
|
+
try { wsl --set-default-version 2 2>$null } catch {}
|
|
271
|
+
Write-Host "";
|
|
272
|
+
Write-Host "============================";
|
|
273
|
+
Write-Host " 操作执行完毕!";
|
|
274
|
+
Write-Host " 注意:必须 [重新启动电脑] 才能生效!";
|
|
275
|
+
Write-Host "============================";
|
|
276
|
+
Write-Host " -> 若重启后运行 wsl 提示需要内核更新,";
|
|
277
|
+
Write-Host " -> 请浏览器访问下载并安装: https://aka.ms/wsl2kernel";
|
|
278
|
+
Write-Host " -> 最后去 Microsoft Store 搜索 Ubuntu 并安装即可。";
|
|
279
|
+
Write-Host "";
|
|
280
|
+
Write-Host "按任意键退出当前窗口...";
|
|
281
|
+
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
|
|
282
|
+
`;
|
|
283
|
+
|
|
284
|
+
// 为了跨 PowerShell 调用避免引号转移错乱,转为 Base64 执行 (UTF-16LE 编码)
|
|
285
|
+
const b64Cmd = Buffer.from(psCommand, 'utf16le').toString('base64');
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
execSync(`powershell -Command "Start-Process powershell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -EncodedCommand ${b64Cmd}' -Verb RunAs"`, { stdio: 'inherit' });
|
|
289
|
+
console.log('[' + colors.green + '成功' + colors.nc + '] 修复命令已下发,请查看新弹出的蓝色 PowerShell 窗口。');
|
|
290
|
+
console.log('');
|
|
291
|
+
console.log('执行完后记得 ' + colors.yellow + '重启电脑' + colors.nc + ' 哦!');
|
|
292
|
+
console.log('');
|
|
293
|
+
} catch (err) {
|
|
294
|
+
console.error('[' + colors.red + '错误' + colors.nc + '] 执行提权脚本失败:', err.message);
|
|
295
|
+
console.log('建议右键点击终端,选择【以管理员身份运行】再重试。');
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
272
299
|
// ============================================================================
|
|
273
300
|
// 帮助信息
|
|
274
301
|
// ============================================================================
|
|
@@ -285,6 +312,7 @@ function showHelp() {
|
|
|
285
312
|
console.log(' install 安装 OpenClaw 服务');
|
|
286
313
|
console.log(' status 简化版状态查看(学生友好)');
|
|
287
314
|
console.log(' new 创建新的 Agent(学生练习用)');
|
|
315
|
+
console.log(' wsl2 修复 Windows 下 WSL2 安装失败的问题 (仅限 Windows)');
|
|
288
316
|
console.log(' help 显示帮助信息');
|
|
289
317
|
console.log('');
|
|
290
318
|
console.log('示例:');
|
|
@@ -308,6 +336,8 @@ if (!command || command === 'help' || command === '--help' || command === '-h')
|
|
|
308
336
|
runStatus();
|
|
309
337
|
} else if (command === 'new') {
|
|
310
338
|
runNew();
|
|
339
|
+
} else if (command === 'wsl2') {
|
|
340
|
+
runWsl2();
|
|
311
341
|
} else {
|
|
312
342
|
console.error('[' + colors.red + '错误' + colors.nc + '] 未知命令: ' + command);
|
|
313
343
|
showHelp();
|
package/package.json
CHANGED
package/publish.sh
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e # 遇到错误即停止
|
|
3
|
+
|
|
4
|
+
echo "📦 准备发布新版本..."
|
|
5
|
+
|
|
6
|
+
# 1. 添加所有变动
|
|
7
|
+
git add .
|
|
8
|
+
|
|
9
|
+
# 2. 检查是否有未提交的代码,如果有则先提交
|
|
10
|
+
if ! git diff-index --quiet HEAD; then
|
|
11
|
+
echo "📝 发现有修改的内容,正在自动提交..."
|
|
12
|
+
git commit -m "chore: auto update before publish"
|
|
13
|
+
else
|
|
14
|
+
echo "✅ 工作区很干净,不需要额外提交代码。"
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# 3. 自动更新最小版本号 (npm version patch 会自动再做一个改 package.json 的 commit 并且打上 Tag)
|
|
18
|
+
echo "📈 增加 Patch 版本号..."
|
|
19
|
+
npm version patch
|
|
20
|
+
|
|
21
|
+
# 4. 推送代码和 Tag 到 GitHub
|
|
22
|
+
echo "☁️ 推送代码和版本 Tag 到 GitHub..."
|
|
23
|
+
git push origin main
|
|
24
|
+
git push origin --tags
|
|
25
|
+
|
|
26
|
+
# 5. 发布到 npm
|
|
27
|
+
echo "🚀 发布到 npm 仓库..."
|
|
28
|
+
npm publish
|
|
29
|
+
|
|
30
|
+
echo "🎉 发布流执行完成!"
|