@aiyiran/myclaw 1.0.96 → 1.0.98
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 +17 -55
- package/launch.js +3 -19
- package/package.json +1 -1
- package/patch-manifest.json +2 -2
- package/prepare.js +6 -9
- package/wizards/configs/new-agent/index.config.json +116 -0
- package/wizards/index.js +6 -1
- package/wizards/scripts/create_agent_steps.js +178 -0
package/index.js
CHANGED
|
@@ -181,60 +181,8 @@ function runStatus() {
|
|
|
181
181
|
// ============================================================================
|
|
182
182
|
|
|
183
183
|
function runNew() {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
if (!rawName) {
|
|
187
|
-
console.error('[' + colors.red + '错误' + colors.nc + '] 请提供 Agent 名称');
|
|
188
|
-
console.log('');
|
|
189
|
-
console.log('用法: myclaw new <agent名称>');
|
|
190
|
-
console.log('');
|
|
191
|
-
console.log('示例:');
|
|
192
|
-
console.log(' myclaw new helper # 创建名为 helper 的 Agent');
|
|
193
|
-
console.log(' myclaw new testbot # 创建名为 testbot 的 Agent');
|
|
194
|
-
process.exit(1);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const bar = '----------------------------------------';
|
|
198
|
-
|
|
199
|
-
console.log('');
|
|
200
|
-
console.log('[' + colors.blue + 'MyClaw' + colors.nc + '] ' + colors.blue + '创建新 Agent' + colors.nc);
|
|
201
|
-
console.log(bar);
|
|
202
|
-
console.log('');
|
|
203
|
-
console.log('[创建中] 正在创建 Agent...');
|
|
204
|
-
console.log('');
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
const result = createAgent(rawName);
|
|
208
|
-
|
|
209
|
-
console.log('[' + colors.green + '成功' + colors.nc + '] Agent 创建成功!');
|
|
210
|
-
console.log('');
|
|
211
|
-
console.log(' 名称: ' + result.agentId);
|
|
212
|
-
console.log(' Session: ' + result.sessionKey);
|
|
213
|
-
console.log(' Workspace: ' + result.workspace);
|
|
214
|
-
console.log(' 备份: ' + result.configBackup);
|
|
215
|
-
console.log('');
|
|
216
|
-
|
|
217
|
-
if (result.firstMessageSent) {
|
|
218
|
-
console.log('[' + colors.green + 'OK' + colors.nc + '] 出生消息已发送');
|
|
219
|
-
} else {
|
|
220
|
-
console.log('[' + colors.yellow + '警告' + colors.nc + '] 出生消息发送失败');
|
|
221
|
-
if (result.firstMessageError) {
|
|
222
|
-
console.log(' 错误: ' + result.firstMessageError);
|
|
223
|
-
}
|
|
224
|
-
console.log(' 手动重试: ' + colors.yellow + 'openclaw agent --agent ' + result.agentId + ' --message "你好"' + colors.nc);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
console.log('');
|
|
228
|
-
console.log(bar);
|
|
229
|
-
console.log('下一步: 运行 ' + colors.yellow + 'openclaw agent --agent ' + result.agentId + ' --message "你好"' + colors.nc + ' 与它对话');
|
|
230
|
-
console.log('');
|
|
231
|
-
|
|
232
|
-
} catch (err) {
|
|
233
|
-
console.log('');
|
|
234
|
-
console.log('[' + colors.red + '失败' + colors.nc + '] Agent 创建失败');
|
|
235
|
-
console.log('');
|
|
236
|
-
process.exit(1);
|
|
237
|
-
}
|
|
184
|
+
const { runNewAgent } = require('./wizards/index');
|
|
185
|
+
runNewAgent();
|
|
238
186
|
}
|
|
239
187
|
|
|
240
188
|
// ============================================================================
|
|
@@ -561,6 +509,20 @@ function runPatch() {
|
|
|
561
509
|
current[parts[parts.length - 1]] = value;
|
|
562
510
|
}
|
|
563
511
|
const { config, configPath } = patchConfig(nested);
|
|
512
|
+
|
|
513
|
+
// 【关键修复】深度合并不会删除错误的历史残留配置,这里主动帮学生清理掉遗留在顶层的 "exec"
|
|
514
|
+
let requireSave = false;
|
|
515
|
+
if (config && config.exec) {
|
|
516
|
+
delete config.exec;
|
|
517
|
+
requireSave = true;
|
|
518
|
+
console.log('[myclaw-config] 🧹 已清理历史遗留的错误顶层 "exec" 常驻配置');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (requireSave) {
|
|
522
|
+
const { writeConfig } = require('./find-config');
|
|
523
|
+
writeConfig(config, configPath);
|
|
524
|
+
}
|
|
525
|
+
|
|
564
526
|
for (const [key, value] of Object.entries(patches)) {
|
|
565
527
|
console.log('[myclaw-config] ✅ ' + key + ' → ' + JSON.stringify(value));
|
|
566
528
|
}
|
|
@@ -814,6 +776,7 @@ function showHelp() {
|
|
|
814
776
|
console.log('');
|
|
815
777
|
console.log('向导 (交互式):');
|
|
816
778
|
console.log(' prepare 智能初始化(环境检测 + 安装 + Patch)');
|
|
779
|
+
console.log(' new 创建新 Agent(分步理解生命周期)');
|
|
817
780
|
console.log(' weixin 微信接入向导(步骤引导 + 教学说明)');
|
|
818
781
|
console.log(' rebind 微信换绑向导(清空、扫码、换Agent)');
|
|
819
782
|
console.log('');
|
|
@@ -821,7 +784,6 @@ function showHelp() {
|
|
|
821
784
|
console.log(' start 智能启动(图标 & 命令行通用入口)');
|
|
822
785
|
console.log(' install 安装 OpenClaw 服务');
|
|
823
786
|
console.log(' status 简化版状态查看(学生友好)');
|
|
824
|
-
console.log(' new 创建新的 Agent(学生练习用)');
|
|
825
787
|
console.log(' update 自动升级 MyClaw 到最新版本');
|
|
826
788
|
console.log(' up 升级 + 刷新桌面快捷方式 (= update + bat)');
|
|
827
789
|
console.log(' open 打开浏览器控制台(自动带 token)');
|
package/launch.js
CHANGED
|
@@ -66,29 +66,13 @@ function stepUpdate() {
|
|
|
66
66
|
|
|
67
67
|
function stepPatch() {
|
|
68
68
|
console.log('[2/4] Patch...');
|
|
69
|
-
|
|
70
69
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const { patchConfig } = require('./find-config');
|
|
74
|
-
|
|
75
|
-
patch();
|
|
76
|
-
patchSkills();
|
|
77
|
-
patchConfig({
|
|
78
|
-
session: {
|
|
79
|
-
reset: {
|
|
80
|
-
mode: 'idle',
|
|
81
|
-
idleMinutes: 90720,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
exec: {
|
|
85
|
-
ask: 'off',
|
|
86
|
-
},
|
|
70
|
+
execSync('node "' + path.join(__dirname, 'index.js') + '" patch', {
|
|
71
|
+
stdio: 'inherit',
|
|
87
72
|
});
|
|
88
|
-
|
|
89
73
|
console.log(' ' + C.g + '[OK]' + C.nc);
|
|
90
74
|
} catch (err) {
|
|
91
|
-
console.log(' ' + C.y + '[跳过]' + C.nc + ' ' + err.message);
|
|
75
|
+
console.log(' ' + C.y + '[跳过]' + C.nc + ' 注入失败: ' + err.message);
|
|
92
76
|
}
|
|
93
77
|
console.log('');
|
|
94
78
|
}
|
package/package.json
CHANGED
package/patch-manifest.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_doc": "MyClaw 注入清单 (auto-generated)。strategy: auto | on | off",
|
|
3
|
-
"_generated": "2026-04-
|
|
3
|
+
"_generated": "2026-04-01T15:56:26.709Z",
|
|
4
4
|
"agents": [
|
|
5
5
|
{
|
|
6
6
|
"id": "danci",
|
|
7
7
|
"workspace": "workspace-danci",
|
|
8
|
-
"strategy": "
|
|
8
|
+
"strategy": "auto",
|
|
9
9
|
"description": "danci"
|
|
10
10
|
}
|
|
11
11
|
],
|
package/prepare.js
CHANGED
|
@@ -291,16 +291,13 @@ function runPatchStep(env) {
|
|
|
291
291
|
log('Step 4', '执行 MyClaw Patch...');
|
|
292
292
|
|
|
293
293
|
try {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
logWarn('Patch 跳过: ' + (result.reason || '未知原因'));
|
|
300
|
-
}
|
|
301
|
-
return result.success;
|
|
294
|
+
execSync('node "' + path.join(__dirname, 'index.js') + '" patch', {
|
|
295
|
+
stdio: 'inherit',
|
|
296
|
+
});
|
|
297
|
+
logOK('Patch 注入成功');
|
|
298
|
+
return true;
|
|
302
299
|
} catch (err) {
|
|
303
|
-
logWarn('Patch
|
|
300
|
+
logWarn('Patch 跳过或失败: ' + err.message);
|
|
304
301
|
return false;
|
|
305
302
|
}
|
|
306
303
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "new-agent-wizard",
|
|
3
|
+
"title": "新建 Agent 生长向导",
|
|
4
|
+
"subtitle": "一步步了解一个数字生命是如何在本地诞生的",
|
|
5
|
+
"steps": [
|
|
6
|
+
{
|
|
7
|
+
"id": "input-name",
|
|
8
|
+
"icon": "📝",
|
|
9
|
+
"label": "第一步:给 Agent 起个名字",
|
|
10
|
+
"type": "input",
|
|
11
|
+
"command": {
|
|
12
|
+
"template": "node {scripts_dir}/create_agent_steps.js init {{agent_name}}",
|
|
13
|
+
"display": "node create_agent_steps.js init {{agent_name}}"
|
|
14
|
+
},
|
|
15
|
+
"inputs": [
|
|
16
|
+
{
|
|
17
|
+
"key": "agent_name",
|
|
18
|
+
"label": "新 Agent 名称",
|
|
19
|
+
"hint": "只能包含小写字母、数字和连字符,作为文件目录名",
|
|
20
|
+
"placeholder": "例如: tutor、helper"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"teach": {
|
|
24
|
+
"title": "为什么要先起名?",
|
|
25
|
+
"description": "这是给 Agent 上户口。\n你起的名字(如 helper)将会被标准化成小写,并且只能用连字符连接。\n它将作为内部唯一的身份标识符(Agent ID)。\n\n我们会把它存在一个临时文件中供后续步骤使用。",
|
|
26
|
+
"look_for": "输出「✅ Agent ID 已确定」",
|
|
27
|
+
"tip": "💡 想个好听又简短的名字吧。"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "check-env",
|
|
32
|
+
"icon": "🔍",
|
|
33
|
+
"label": "第二步:环境验证与查重",
|
|
34
|
+
"type": "action",
|
|
35
|
+
"requires": ["input-name"],
|
|
36
|
+
"command": {
|
|
37
|
+
"exec": "node {scripts_dir}/create_agent_steps.js check",
|
|
38
|
+
"display": "node create_agent_steps.js check"
|
|
39
|
+
},
|
|
40
|
+
"teach": {
|
|
41
|
+
"title": "确保小房间没被占",
|
|
42
|
+
"description": "在真正创建之前,系统必须:\n 1. 读取这台电脑上的配置文件 openclaw.json,检查之前是不是建过同名的。\n 2. 检查硬盘上是不是残留了同名的文件夹。\n\n严格的环境校验,是为了防止数据被错误覆盖。",
|
|
43
|
+
"look_for": "输出「名称检查通过,目录无冲突」",
|
|
44
|
+
"tip": "⚠️ 这个步骤没有任何修改,只是检查。"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "scaffold-files",
|
|
49
|
+
"icon": "🏠",
|
|
50
|
+
"label": "第三步:为它筑个巢(创建核心文件)",
|
|
51
|
+
"type": "action",
|
|
52
|
+
"requires": ["check-env"],
|
|
53
|
+
"command": {
|
|
54
|
+
"exec": "node {scripts_dir}/create_agent_steps.js scaffold",
|
|
55
|
+
"display": "node create_agent_steps.js scaffold"
|
|
56
|
+
},
|
|
57
|
+
"teach": {
|
|
58
|
+
"title": "注入灵魂要素:工作空间",
|
|
59
|
+
"description": "这一步将在 ~/.openclaw/ 下建两个文件夹并写入几个 Markdown 文件:\n - SOUL.md:Agent 的底层性格与灵魂。\n - USER.md:记录了你的身份(造物主:孙依然,时区)。\n - AGENTS.md:最高行为守则。\n\n系统底层实现是通过原生 Node.js 的 fs 模块创建文件。这些文件决定了这台数字生命的初步人格。",
|
|
60
|
+
"look_for": "输出「工作空间创建完毕」及核心文件列表",
|
|
61
|
+
"tip": "💡 诞生后你可以自己去修改 SOUL.md,它的性格就随之改变。"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "register-agent",
|
|
66
|
+
"icon": "📝",
|
|
67
|
+
"label": "第四步:在系统中挂号",
|
|
68
|
+
"type": "action",
|
|
69
|
+
"requires": ["scaffold-files"],
|
|
70
|
+
"command": {
|
|
71
|
+
"exec": "node {scripts_dir}/create_agent_steps.js register",
|
|
72
|
+
"display": "node create_agent_steps.js register"
|
|
73
|
+
},
|
|
74
|
+
"teach": {
|
|
75
|
+
"title": "核心配置关联",
|
|
76
|
+
"description": "光有文件夹还不行,OpenClaw 大总管系统得知道。\n这一步把 Agent 的目录路径(workspace 目录和 agent 状态目录)写进了系统核心的 openclaw.json 的 agents.list 数组里。\n\n写入前这步底层会自动备份老配置文件,安全第一。",
|
|
77
|
+
"look_for": "输出「配置文件更新成功」及系统备份位置",
|
|
78
|
+
"tip": "🔒 备份机制保证我们不会搞坏系统。"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "awaken-ping",
|
|
83
|
+
"icon": "⚡",
|
|
84
|
+
"label": "第五步:赋予第一声啼哭(唤醒)",
|
|
85
|
+
"type": "action",
|
|
86
|
+
"requires": ["register-agent"],
|
|
87
|
+
"command": {
|
|
88
|
+
"exec": "node {scripts_dir}/create_agent_steps.js awaken",
|
|
89
|
+
"display": "node create_agent_steps.js awaken"
|
|
90
|
+
},
|
|
91
|
+
"teach": {
|
|
92
|
+
"title": "建立 First Session,睁眼看世界",
|
|
93
|
+
"description": "作为造物主,系统将以你的名义发去一段设定好的出生文案(北京时间生日等)给你的新 Agent。\n\n这一步实际上在底层执行了以下指令:\n\u001b[32m$ openclaw agent --agent <你在第一步起的名字> --message \"你好,你的生日是...\" --json\u001b[0m\n\n这条指令将调用底层大模型 API:系统将把它拉取到内存中思考,并创建它生命里的第一条对话记录(Session)。这也是第一次让 Agent 服务拉起环境。",
|
|
94
|
+
"look_for": "输出「✅ 唤醒成功!第一次思考已完成」",
|
|
95
|
+
"tip": "⏳ 这一步要真正去云端调大模型接口,一般需要等几秒至十几秒。"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "verify-creation",
|
|
100
|
+
"icon": "✅",
|
|
101
|
+
"label": "第六步:验证出生",
|
|
102
|
+
"type": "check",
|
|
103
|
+
"requires": ["awaken-ping"],
|
|
104
|
+
"command": {
|
|
105
|
+
"exec": "openclaw agents list",
|
|
106
|
+
"display": "openclaw agents list"
|
|
107
|
+
},
|
|
108
|
+
"teach": {
|
|
109
|
+
"title": "查看系统登记的 Agent 名单",
|
|
110
|
+
"description": "终于诞生了!我们通过调用 OpenClaw 的内建指令来确认大名单:\n\n\u001b[32m$ openclaw agents list\u001b[0m\n\n这条指令会去读取刚刚你在第四步重写的 openclaw.json,把它打印成人类可读的列表给你。\n\n你应该能在列表中看到你起的名字,并且它已经处于准备就绪可以交谈的状态。",
|
|
111
|
+
"look_for": "找找你起的 Agent ID 是否出现在列表中",
|
|
112
|
+
"tip": "🎉 看到名字就意味着完美的数字生命诞生啦!"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
package/wizards/index.js
CHANGED
|
@@ -29,9 +29,14 @@ function runRebind() {
|
|
|
29
29
|
startWizard(path.join(__dirname, 'configs/rebind/index.config.json'));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function runNewAgent() {
|
|
33
|
+
startWizard(path.join(__dirname, 'configs/new-agent/index.config.json'));
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
// 未来扩展示例:
|
|
37
|
+
|
|
33
38
|
// function runGateway() { startWizard(path.join(__dirname, 'configs/gateway/index.config.json')); }
|
|
34
39
|
// function runAgent() { startWizard(path.join(__dirname, 'configs/agent/index.config.json')); }
|
|
35
40
|
|
|
36
|
-
module.exports = { runWeixin, runRebind };
|
|
41
|
+
module.exports = { runWeixin, runRebind, runNewAgent };
|
|
37
42
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 分步版 Agent 创建脚本,支持从临时文件暂存状态。
|
|
4
|
+
* 供 myclaw new-agent 向导调用。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// 工具方法
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
function normalizePath(p) { return p.replace(/\\/g, '/'); }
|
|
17
|
+
function ensureDir(dirPath) { if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }); }
|
|
18
|
+
function writeIfAbsent(filePath, content) { if (!fs.existsSync(filePath)) fs.writeFileSync(filePath, content, 'utf8'); }
|
|
19
|
+
function normalizeAgentId(raw) {
|
|
20
|
+
let value = raw.trim().toLowerCase();
|
|
21
|
+
value = value.replace(/[^a-z0-9-]/g, '-');
|
|
22
|
+
value = value.replace(/-{2,}/g, '-').replace(/^-|-$/g, '');
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function validateAgentId(agentId) {
|
|
26
|
+
if (!agentId) fail('Agent 名称标准化后为空,请检查输入。');
|
|
27
|
+
if (agentId.length > 64) fail('Agent ID 太长,请保持在 64 个字符以内。');
|
|
28
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentId)) fail('Agent ID 只能包含字母、数字和连字符。');
|
|
29
|
+
}
|
|
30
|
+
function fail(msg, code = 1) { console.error('❌ ' + msg); process.exit(code); }
|
|
31
|
+
function success(msg) { console.log('✅ ' + msg); }
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// 状态管理
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
const homeDir = os.homedir();
|
|
38
|
+
const openclawDir = path.join(homeDir, '.openclaw');
|
|
39
|
+
const STATE_FILE = path.join(os.tmpdir(), 'myclaw-new-agent-state.json');
|
|
40
|
+
|
|
41
|
+
function saveState(state) { fs.writeFileSync(STATE_FILE, JSON.stringify(state), 'utf8'); }
|
|
42
|
+
function loadState() {
|
|
43
|
+
if (!fs.existsSync(STATE_FILE)) fail('找不到创建状态,请先执行第一步输入名称。');
|
|
44
|
+
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// 各个步骤逻辑
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
const action = process.argv[2];
|
|
52
|
+
|
|
53
|
+
if (!fs.existsSync(path.join(openclawDir, 'openclaw.json'))) {
|
|
54
|
+
fail('配置文件不存在。请先运行 openclaw onboard 完成初始化。');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
switch (action) {
|
|
58
|
+
case 'init': {
|
|
59
|
+
// 步骤 1:格式化名称并保存状态
|
|
60
|
+
const rawName = process.argv[3] || '';
|
|
61
|
+
const agentId = normalizeAgentId(rawName);
|
|
62
|
+
validateAgentId(agentId);
|
|
63
|
+
saveState({ agentId });
|
|
64
|
+
success('Agent ID 已确定: ' + agentId);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
case 'check': {
|
|
69
|
+
// 步骤 2:环境与名字查重
|
|
70
|
+
const state = loadState();
|
|
71
|
+
const configPath = path.join(openclawDir, 'openclaw.json');
|
|
72
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
73
|
+
const configData = JSON.parse(raw);
|
|
74
|
+
|
|
75
|
+
if (configData.agents && configData.agents.list) {
|
|
76
|
+
const existing = configData.agents.list.find(a => a.id === state.agentId);
|
|
77
|
+
if (existing) fail('Agent "' + state.agentId + '" 已存在于 openclaw.json,请换个名字。');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const agentsDir = path.join(openclawDir, 'agents');
|
|
81
|
+
const workspaceDir = path.join(openclawDir, 'workspace-' + state.agentId);
|
|
82
|
+
const agentDir = path.join(agentsDir, state.agentId, 'agent');
|
|
83
|
+
|
|
84
|
+
if (fs.existsSync(workspaceDir) || fs.existsSync(agentDir)) {
|
|
85
|
+
fail('工作空间或 Agent 目录已存在,可能是残留文件:\n ' + workspaceDir + '\n ' + agentDir);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
success('名称检查通过,目录无冲突,可以创建。');
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case 'scaffold': {
|
|
93
|
+
// 步骤 3:创建文件和文件夹
|
|
94
|
+
const state = loadState();
|
|
95
|
+
const agentId = state.agentId;
|
|
96
|
+
const workspaceDir = path.join(openclawDir, 'workspace-' + agentId);
|
|
97
|
+
const agentDir = path.join(openclawDir, 'agents', agentId, 'agent');
|
|
98
|
+
const sessionsDir = path.join(openclawDir, 'agents', agentId, 'sessions');
|
|
99
|
+
|
|
100
|
+
ensureDir(workspaceDir);
|
|
101
|
+
ensureDir(agentDir);
|
|
102
|
+
ensureDir(sessionsDir);
|
|
103
|
+
|
|
104
|
+
const files = {
|
|
105
|
+
'AGENTS.md': `# AGENTS.md - ${agentId}\n\nThis workspace belongs to the \`${agentId}\` agent.\n\n## Startup\n- Read \`SOUL.md\`\n- Read \`USER.md\`\n- Read recent memory if available\n\n## Rules\n- Be helpful, careful, and concise.\n- Prefer using the existing workspace and defaults.\n- Ask before destructive or external actions.\n`,
|
|
106
|
+
'SOUL.md': `# SOUL.md\n\nYou are \`${agentId}\`.\n\nBe useful, calm, direct, and trustworthy.\nUse the default OpenClaw behavior unless the user asks for something special.\n`,
|
|
107
|
+
'USER.md': `# USER.md\n\n- Name: 孙依然\n- What to call them: 依然\n- Timezone: Asia/Shanghai\n\nBuild understanding gradually and respectfully.\n`,
|
|
108
|
+
'IDENTITY.md': `# IDENTITY.md\n\n- Name: ${agentId}\n- Role: OpenClaw agent\n- Vibe: practical, reliable, clear\n`,
|
|
109
|
+
'HEARTBEAT.md': `# HEARTBEAT.md\n\n# Keep empty unless periodic checks are needed.\n`,
|
|
110
|
+
'BOOTSTRAP.md': `# BOOTSTRAP.md\n\nYou are a newly created OpenClaw agent named \`${agentId}\`.\n\nOn first runs, learn your workspace files and begin helping.\n`
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
114
|
+
writeIfAbsent(path.join(workspaceDir, filename), content);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
success(`工作空间创建完毕:\n - 📂 ${workspaceDir}\n - 📄 SOUL.md, AGENTS.md 等基础性格文件已就绪。`);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
case 'register': {
|
|
122
|
+
// 步骤 4:注册到系统 JSON
|
|
123
|
+
const state = loadState();
|
|
124
|
+
const agentId = state.agentId;
|
|
125
|
+
const configPath = path.join(openclawDir, 'openclaw.json');
|
|
126
|
+
|
|
127
|
+
let configData = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
128
|
+
if (!configData.agents) configData.agents = {};
|
|
129
|
+
if (!Array.isArray(configData.agents.list)) configData.agents.list = [];
|
|
130
|
+
|
|
131
|
+
const workspaceDir = path.join(openclawDir, 'workspace-' + agentId);
|
|
132
|
+
const agentDir = path.join(openclawDir, 'agents', agentId, 'agent');
|
|
133
|
+
|
|
134
|
+
// 备份
|
|
135
|
+
const backupPath = configPath + '.bak.agent-birth.' + new Date().toISOString().replace(/[:.]/g, '-').slice(0, 26) + 'Z';
|
|
136
|
+
fs.copyFileSync(configPath, backupPath);
|
|
137
|
+
|
|
138
|
+
configData.agents.list.push({
|
|
139
|
+
id: agentId,
|
|
140
|
+
name: agentId,
|
|
141
|
+
workspace: normalizePath(workspaceDir),
|
|
142
|
+
agentDir: normalizePath(agentDir),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
console.log('\n\x1b[32m(底层动作:修改 ' + configPath + ' ,写入 agents.list)\x1b[0m\n');
|
|
146
|
+
|
|
147
|
+
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf8');
|
|
148
|
+
success('配置文件更新成功,系统已承认它的存在。\n 备份: ' + backupPath);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
case 'awaken': {
|
|
153
|
+
// 步骤 5:发第一条消息激活
|
|
154
|
+
const state = loadState();
|
|
155
|
+
const agentId = state.agentId;
|
|
156
|
+
|
|
157
|
+
const nowUtc = new Date();
|
|
158
|
+
const nowBj = new Date(nowUtc.getTime() + 8 * 60 * 60 * 1000);
|
|
159
|
+
const ts = `${nowBj.getUTCFullYear()}年${nowBj.getUTCMonth() + 1}月${nowBj.getUTCDate()}日${String(nowBj.getUTCHours()).padStart(2, '0')}:${String(nowBj.getUTCMinutes()).padStart(2, '0')}`;
|
|
160
|
+
|
|
161
|
+
const cmd = `openclaw agent --agent ${agentId} --message ${JSON.stringify(birthMessage)} --json 2>&1`;
|
|
162
|
+
console.log('\n\x1b[32m$ openclaw agent --agent ' + agentId + ' --message "你好,你的生日..."\x1b[0m\n');
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
execSync(cmd, { encoding: 'utf8', timeout: 45000 });
|
|
166
|
+
success('唤醒成功!第一次思考(session 初始化)已完成。');
|
|
167
|
+
} catch (err) {
|
|
168
|
+
fail('唤醒遇到错误,可能需要去浏览器 Console 手动激活。\n' + err.message);
|
|
169
|
+
}
|
|
170
|
+
// 清除状态文件
|
|
171
|
+
if (fs.existsSync(STATE_FILE)) fs.unlinkSync(STATE_FILE);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
default:
|
|
176
|
+
console.error('Usage: create_agent_steps.js <init|check|scaffold|register|awaken> [args]');
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|