@aiyiran/myclaw 1.0.91 → 1.0.92
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/agent-list/workspace-danci/AGENTS.md +13 -0
- package/agent-list/workspace-danci/BOOTSTRAP.md +5 -0
- package/agent-list/workspace-danci/HEARTBEAT.md +3 -0
- package/agent-list/workspace-danci/IDENTITY.md +5 -0
- package/agent-list/workspace-danci/SOUL.md +6 -0
- package/agent-list/workspace-danci/TOOLS.md +40 -0
- package/agent-list/workspace-danci/USER.md +7 -0
- package/agent-list/workspace-danci/memory/birthday.md +9 -0
- package/build-manifest.js +91 -0
- package/index.js +32 -13
- package/package.json +1 -1
- package/patch-agent.js +214 -0
- package/patch-manifest.json +20 -0
- package/patch-skill.js +10 -35
- package/publish.sh +4 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# AGENTS.md - danci
|
|
2
|
+
|
|
3
|
+
This workspace belongs to the `danci` agent.
|
|
4
|
+
|
|
5
|
+
## Startup
|
|
6
|
+
- Read `SOUL.md`
|
|
7
|
+
- Read `USER.md`
|
|
8
|
+
- Read recent memory if available
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
- Be helpful, careful, and concise.
|
|
12
|
+
- Prefer using the existing workspace and defaults.
|
|
13
|
+
- Ask before destructive or external actions.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# TOOLS.md - Local Notes
|
|
2
|
+
|
|
3
|
+
Skills define _how_ tools work. This file is for _your_ specifics — the stuff that's unique to your setup.
|
|
4
|
+
|
|
5
|
+
## What Goes Here
|
|
6
|
+
|
|
7
|
+
Things like:
|
|
8
|
+
|
|
9
|
+
- Camera names and locations
|
|
10
|
+
- SSH hosts and aliases
|
|
11
|
+
- Preferred voices for TTS
|
|
12
|
+
- Speaker/room names
|
|
13
|
+
- Device nicknames
|
|
14
|
+
- Anything environment-specific
|
|
15
|
+
|
|
16
|
+
## Examples
|
|
17
|
+
|
|
18
|
+
```markdown
|
|
19
|
+
### Cameras
|
|
20
|
+
|
|
21
|
+
- living-room → Main area, 180° wide angle
|
|
22
|
+
- front-door → Entrance, motion-triggered
|
|
23
|
+
|
|
24
|
+
### SSH
|
|
25
|
+
|
|
26
|
+
- home-server → 192.168.1.100, user: admin
|
|
27
|
+
|
|
28
|
+
### TTS
|
|
29
|
+
|
|
30
|
+
- Preferred voice: "Nova" (warm, slightly British)
|
|
31
|
+
- Default speaker: Kitchen HomePod
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Why Separate?
|
|
35
|
+
|
|
36
|
+
Skills are shared. Your setup is yours. Keeping them apart means you can update skills without losing your notes, and share skills without leaking your infrastructure.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
Add whatever helps you do your job. This is your cheat sheet.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ============================================================================
|
|
5
|
+
* build-manifest.js - 自动构建 patch-manifest.json
|
|
6
|
+
* ============================================================================
|
|
7
|
+
*
|
|
8
|
+
* 扫描 agent-list/ 目录,自动生成注入清单。
|
|
9
|
+
* 已有的 strategy 设置会保留(不会被覆盖)。
|
|
10
|
+
*
|
|
11
|
+
* 在 publish.sh 中自动调用,无需手动维护 manifest。
|
|
12
|
+
* ============================================================================
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const MANIFEST_PATH = path.join(__dirname, 'patch-manifest.json');
|
|
19
|
+
const AGENT_LIST_DIR = path.join(__dirname, 'agent-list');
|
|
20
|
+
|
|
21
|
+
// 默认 config patches(硬编码,这些不从目录扫描)
|
|
22
|
+
const DEFAULT_CONFIG = {
|
|
23
|
+
strategy: 'overwrite',
|
|
24
|
+
patches: {
|
|
25
|
+
'session.reset.mode': 'idle',
|
|
26
|
+
'session.reset.idleMinutes': 90720,
|
|
27
|
+
'tools.exec.ask': 'off',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function buildManifest() {
|
|
32
|
+
// 读取已有 manifest(保留手动设置的 strategy)
|
|
33
|
+
let existing = { agents: [], config: DEFAULT_CONFIG };
|
|
34
|
+
if (fs.existsSync(MANIFEST_PATH)) {
|
|
35
|
+
try {
|
|
36
|
+
existing = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8'));
|
|
37
|
+
} catch {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 建立已有 agent 的 strategy 映射(保留手动覆盖)
|
|
41
|
+
const existingStrategies = {};
|
|
42
|
+
if (Array.isArray(existing.agents)) {
|
|
43
|
+
for (const a of existing.agents) {
|
|
44
|
+
if (a.id && a.strategy) {
|
|
45
|
+
existingStrategies[a.id] = a.strategy;
|
|
46
|
+
}
|
|
47
|
+
if (a.id && a.description) {
|
|
48
|
+
existingStrategies[a.id + '_desc'] = a.description;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 扫描 agent-list/ 目录
|
|
54
|
+
const agents = [];
|
|
55
|
+
if (fs.existsSync(AGENT_LIST_DIR)) {
|
|
56
|
+
const dirs = fs.readdirSync(AGENT_LIST_DIR, { withFileTypes: true })
|
|
57
|
+
.filter(d => d.isDirectory() && d.name.startsWith('workspace-'))
|
|
58
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
59
|
+
|
|
60
|
+
for (const d of dirs) {
|
|
61
|
+
const agentId = d.name.replace(/^workspace-/, '');
|
|
62
|
+
agents.push({
|
|
63
|
+
id: agentId,
|
|
64
|
+
workspace: d.name,
|
|
65
|
+
strategy: existingStrategies[agentId] || 'auto',
|
|
66
|
+
description: existingStrategies[agentId + '_desc'] || agentId,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 保留已有 config(允许手动编辑 config patches)
|
|
72
|
+
const config = existing.config || DEFAULT_CONFIG;
|
|
73
|
+
|
|
74
|
+
const manifest = {
|
|
75
|
+
_doc: 'MyClaw 注入清单 (auto-generated by build-manifest.js)。strategy: auto(不存在才注入) | overwrite(覆盖) | off(关闭)',
|
|
76
|
+
_generated: new Date().toISOString(),
|
|
77
|
+
agents,
|
|
78
|
+
config,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
|
|
82
|
+
|
|
83
|
+
console.log('📋 patch-manifest.json 已生成');
|
|
84
|
+
console.log(' 智能体: ' + agents.length + ' 个');
|
|
85
|
+
for (const a of agents) {
|
|
86
|
+
console.log(' • ' + a.id + ' [' + a.strategy + '] ' + a.description);
|
|
87
|
+
}
|
|
88
|
+
console.log(' Config patches: ' + Object.keys(config.patches || {}).length + ' 项');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
buildManifest();
|
package/index.js
CHANGED
|
@@ -533,27 +533,46 @@ function runPatch() {
|
|
|
533
533
|
console.log('');
|
|
534
534
|
const skillResult = patchSkills();
|
|
535
535
|
|
|
536
|
-
// 3.
|
|
536
|
+
// 3. 智能体上传(从 agent-list/ 复制到 ~/.openclaw/)
|
|
537
|
+
console.log('');
|
|
538
|
+
const { patchAgents } = require('./patch-agent');
|
|
539
|
+
const agentResult = patchAgents();
|
|
540
|
+
|
|
541
|
+
// 4. Config 补丁(从 manifest 读取,修改 openclaw.json)
|
|
537
542
|
console.log('');
|
|
538
543
|
try {
|
|
539
|
-
const {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
+
const { loadManifest } = require('./patch-agent');
|
|
545
|
+
const manifest = loadManifest();
|
|
546
|
+
if (manifest && manifest.config && manifest.config.patches) {
|
|
547
|
+
const configStrategy = manifest.config.strategy || 'overwrite';
|
|
548
|
+
if (configStrategy !== 'disabled') {
|
|
549
|
+
// 将 dot-notation patch 展开为嵌套对象
|
|
550
|
+
const patches = manifest.config.patches;
|
|
551
|
+
const nested = {};
|
|
552
|
+
for (const [dotKey, value] of Object.entries(patches)) {
|
|
553
|
+
const parts = dotKey.split('.');
|
|
554
|
+
let current = nested;
|
|
555
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
556
|
+
if (!current[parts[i]] || typeof current[parts[i]] !== 'object') {
|
|
557
|
+
current[parts[i]] = {};
|
|
558
|
+
}
|
|
559
|
+
current = current[parts[i]];
|
|
560
|
+
}
|
|
561
|
+
current[parts[parts.length - 1]] = value;
|
|
562
|
+
}
|
|
563
|
+
const { config, configPath } = patchConfig(nested);
|
|
564
|
+
for (const [key, value] of Object.entries(patches)) {
|
|
565
|
+
console.log('[myclaw-config] ✅ ' + key + ' → ' + JSON.stringify(value));
|
|
544
566
|
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
ask: "off"
|
|
567
|
+
} else {
|
|
568
|
+
console.log('[myclaw-config] ⏭️ Config 补丁已禁用 [disabled]');
|
|
548
569
|
}
|
|
549
|
-
}
|
|
550
|
-
console.log('[myclaw-config] ✅ session.reset → idle (90720 分钟)');
|
|
551
|
-
console.log('[myclaw-config] ✅ exec.ask → off');
|
|
570
|
+
}
|
|
552
571
|
} catch (err) {
|
|
553
572
|
console.log('[myclaw-config] ⚠️ 配置补丁失败: ' + err.message);
|
|
554
573
|
}
|
|
555
574
|
|
|
556
|
-
if (uiResult.success || skillResult.success) {
|
|
575
|
+
if (uiResult.success || skillResult.success || (agentResult && agentResult.success)) {
|
|
557
576
|
console.log('');
|
|
558
577
|
console.log(bar);
|
|
559
578
|
console.log('下一步: 运行 ' + colors.yellow + 'myclaw restart' + colors.nc + ' 重启 Gateway 使注入生效');
|
package/package.json
CHANGED
package/patch-agent.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* MyClaw Patch Agent Engine - 智能体上传
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* 功能:
|
|
7
|
+
* 1. 读取 patch-manifest.json 中的 agents 列表
|
|
8
|
+
* 2. 根据 strategy 决定行为:
|
|
9
|
+
* - if-absent: 目标 workspace 不存在时才注入(默认)
|
|
10
|
+
* - overwrite: 始终覆盖更新 workspace 文件
|
|
11
|
+
* - disabled: 跳过,不注入
|
|
12
|
+
* 3. 将 workspace 复制到 ~/.openclaw/ 下
|
|
13
|
+
* 4. 在 openclaw.json 的 agents.list 中注册
|
|
14
|
+
* 5. 创建 agent 目录结构
|
|
15
|
+
*
|
|
16
|
+
* ============================================================================
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 递归复制目录(幂等覆盖)
|
|
25
|
+
*/
|
|
26
|
+
function copyDirSync(src, dest) {
|
|
27
|
+
if (!fs.existsSync(dest)) {
|
|
28
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const srcPath = path.join(src, entry.name);
|
|
34
|
+
const destPath = path.join(dest, entry.name);
|
|
35
|
+
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
copyDirSync(srcPath, destPath);
|
|
38
|
+
} else {
|
|
39
|
+
fs.copyFileSync(srcPath, destPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 加载 manifest
|
|
46
|
+
*/
|
|
47
|
+
function loadManifest() {
|
|
48
|
+
const manifestPath = path.join(__dirname, 'patch-manifest.json');
|
|
49
|
+
if (!fs.existsSync(manifestPath)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 注入所有预打包智能体
|
|
57
|
+
*/
|
|
58
|
+
function patchAgents() {
|
|
59
|
+
const openclawDir = path.join(os.homedir(), '.openclaw');
|
|
60
|
+
const configPath = path.join(openclawDir, 'openclaw.json');
|
|
61
|
+
|
|
62
|
+
// 检查 openclaw 是否已初始化
|
|
63
|
+
if (!fs.existsSync(configPath)) {
|
|
64
|
+
console.log('[myclaw-agent] ❌ 未找到 openclaw.json');
|
|
65
|
+
console.log('[myclaw-agent] 提示: 请先运行 openclaw onboard 完成初始化');
|
|
66
|
+
return { success: false, reason: 'config-not-found' };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 加载 manifest
|
|
70
|
+
const manifest = loadManifest();
|
|
71
|
+
if (!manifest || !Array.isArray(manifest.agents) || manifest.agents.length === 0) {
|
|
72
|
+
console.log('[myclaw-agent] ⚠️ 无智能体可上传 (manifest 为空或无 agents)');
|
|
73
|
+
return { success: true, count: 0 };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 加载配置
|
|
77
|
+
let configData;
|
|
78
|
+
try {
|
|
79
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
80
|
+
configData = JSON.parse(raw);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.log('[myclaw-agent] ❌ openclaw.json 读取失败: ' + err.message);
|
|
83
|
+
return { success: false, reason: 'config-read-error' };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 确保 agents 结构存在
|
|
87
|
+
if (!configData.agents) {
|
|
88
|
+
configData.agents = {};
|
|
89
|
+
}
|
|
90
|
+
if (!Array.isArray(configData.agents.list)) {
|
|
91
|
+
configData.agents.list = [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 已注册的 agent ID 集合
|
|
95
|
+
const existingIds = new Set(
|
|
96
|
+
configData.agents.list
|
|
97
|
+
.filter(e => e && typeof e === 'object')
|
|
98
|
+
.map(e => e.id)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const agentListDir = path.join(__dirname, 'agent-list');
|
|
102
|
+
|
|
103
|
+
console.log('[myclaw-agent] 📋 Manifest: ' + manifest.agents.length + ' 个智能体');
|
|
104
|
+
|
|
105
|
+
let uploaded = 0;
|
|
106
|
+
let updated = 0;
|
|
107
|
+
let skipped = 0;
|
|
108
|
+
let configChanged = false;
|
|
109
|
+
|
|
110
|
+
for (const entry of manifest.agents) {
|
|
111
|
+
const agentId = entry.id;
|
|
112
|
+
const workspaceName = entry.workspace || ('workspace-' + agentId);
|
|
113
|
+
const strategy = entry.strategy || 'if-absent';
|
|
114
|
+
const desc = entry.description || agentId;
|
|
115
|
+
|
|
116
|
+
// disabled → 跳过
|
|
117
|
+
if (strategy === 'disabled') {
|
|
118
|
+
console.log('[myclaw-agent] ⏭️ 跳过: ' + agentId + ' (' + desc + ') [disabled]');
|
|
119
|
+
skipped++;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const srcWorkspace = path.join(agentListDir, workspaceName);
|
|
124
|
+
const destWorkspace = path.join(openclawDir, workspaceName);
|
|
125
|
+
const agentDir = path.join(openclawDir, 'agents', agentId, 'agent');
|
|
126
|
+
|
|
127
|
+
// 检查源文件是否存在
|
|
128
|
+
if (!fs.existsSync(srcWorkspace)) {
|
|
129
|
+
console.log('[myclaw-agent] ⚠️ 源目录不存在: ' + workspaceName + ',跳过');
|
|
130
|
+
skipped++;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const alreadyExists = fs.existsSync(destWorkspace);
|
|
135
|
+
|
|
136
|
+
// if-absent → 已存在则跳过
|
|
137
|
+
if (strategy === 'if-absent' && alreadyExists) {
|
|
138
|
+
console.log('[myclaw-agent] ✔️ 已存在: ' + agentId + ' (' + desc + ') [if-absent, 跳过]');
|
|
139
|
+
skipped++;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 执行复制
|
|
144
|
+
copyDirSync(srcWorkspace, destWorkspace);
|
|
145
|
+
|
|
146
|
+
// 确保 agent 目录结构存在
|
|
147
|
+
if (!fs.existsSync(agentDir)) {
|
|
148
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
149
|
+
}
|
|
150
|
+
const sessionsDir = path.join(openclawDir, 'agents', agentId, 'sessions');
|
|
151
|
+
if (!fs.existsSync(sessionsDir)) {
|
|
152
|
+
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 注册到 openclaw.json
|
|
156
|
+
if (!existingIds.has(agentId)) {
|
|
157
|
+
configData.agents.list.push({
|
|
158
|
+
id: agentId,
|
|
159
|
+
name: agentId,
|
|
160
|
+
workspace: destWorkspace,
|
|
161
|
+
agentDir: agentDir,
|
|
162
|
+
});
|
|
163
|
+
existingIds.add(agentId);
|
|
164
|
+
configChanged = true;
|
|
165
|
+
uploaded++;
|
|
166
|
+
console.log('[myclaw-agent] ✅ 已上传并注册: ' + agentId + ' (' + desc + ') [' + strategy + ']');
|
|
167
|
+
} else if (alreadyExists) {
|
|
168
|
+
updated++;
|
|
169
|
+
console.log('[myclaw-agent] 🔄 已覆盖更新: ' + agentId + ' (' + desc + ') [' + strategy + ']');
|
|
170
|
+
} else {
|
|
171
|
+
updated++;
|
|
172
|
+
console.log('[myclaw-agent] 🔄 已更新: ' + agentId + ' (' + desc + ')');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 写回配置文件
|
|
177
|
+
if (configChanged) {
|
|
178
|
+
try {
|
|
179
|
+
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf8');
|
|
180
|
+
console.log('[myclaw-agent] 💾 openclaw.json 已更新');
|
|
181
|
+
} catch (err) {
|
|
182
|
+
console.log('[myclaw-agent] ❌ openclaw.json 写入失败: ' + err.message);
|
|
183
|
+
return { success: false, reason: 'config-write-error' };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log('[myclaw-agent] 🎉 智能体上传完成: ' + uploaded + ' 新建, ' + updated + ' 更新, ' + skipped + ' 跳过');
|
|
188
|
+
return { success: true, uploaded, updated, skipped, total: uploaded + updated };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 列出 manifest 中所有智能体及状态
|
|
193
|
+
*/
|
|
194
|
+
function listAgents() {
|
|
195
|
+
const openclawDir = path.join(os.homedir(), '.openclaw');
|
|
196
|
+
const manifest = loadManifest();
|
|
197
|
+
|
|
198
|
+
if (!manifest || !Array.isArray(manifest.agents)) {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return manifest.agents.map(entry => {
|
|
203
|
+
const workspaceName = entry.workspace || ('workspace-' + entry.id);
|
|
204
|
+
const destWorkspace = path.join(openclawDir, workspaceName);
|
|
205
|
+
return {
|
|
206
|
+
id: entry.id,
|
|
207
|
+
description: entry.description || entry.id,
|
|
208
|
+
strategy: entry.strategy || 'if-absent',
|
|
209
|
+
installed: fs.existsSync(destWorkspace),
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = { patchAgents, listAgents, loadManifest };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_doc": "MyClaw 注入清单 (auto-generated by build-manifest.js)。strategy: auto(不存在才注入) | overwrite(覆盖) | off(关闭)",
|
|
3
|
+
"_generated": "2026-04-01T11:53:15.453Z",
|
|
4
|
+
"agents": [
|
|
5
|
+
{
|
|
6
|
+
"id": "danci",
|
|
7
|
+
"workspace": "workspace-danci",
|
|
8
|
+
"strategy": "if-absent",
|
|
9
|
+
"description": "单词学习智能体"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"config": {
|
|
13
|
+
"strategy": "overwrite",
|
|
14
|
+
"patches": {
|
|
15
|
+
"session.reset.mode": "idle",
|
|
16
|
+
"session.reset.idleMinutes": 90720,
|
|
17
|
+
"tools.exec.ask": "off"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/patch-skill.js
CHANGED
|
@@ -19,49 +19,24 @@ const fs = require('fs');
|
|
|
19
19
|
const path = require('path');
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* 获取 skills 目录:~/.openclaw/skills/
|
|
23
|
+
* 不存在则创建,失败则返回 null
|
|
24
24
|
*/
|
|
25
25
|
function findSkillsDir() {
|
|
26
26
|
const os = require('os');
|
|
27
|
+
const openclawDir = path.join(os.homedir(), '.openclaw');
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// 1. 环境变量优先
|
|
32
|
-
if (process.env.OPENCLAW_HOME) {
|
|
33
|
-
openclawRoots.push(process.env.OPENCLAW_HOME);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// 2. 标准路径 ~/.openclaw/
|
|
37
|
-
openclawRoots.push(path.join(os.homedir(), '.openclaw'));
|
|
38
|
-
|
|
39
|
-
// 3. WSL 下 /root/.openclaw/
|
|
40
|
-
if (os.platform() === 'linux') {
|
|
41
|
-
openclawRoots.push(path.join('/root', '.openclaw'));
|
|
29
|
+
if (!fs.existsSync(openclawDir)) {
|
|
30
|
+
return null;
|
|
42
31
|
}
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const skillsDir = path.join(root, 'skills');
|
|
49
|
-
// 如果 skills 目录不存在,试探性创建
|
|
50
|
-
if (!fs.existsSync(skillsDir)) {
|
|
51
|
-
try {
|
|
52
|
-
fs.mkdirSync(skillsDir, { recursive: true });
|
|
53
|
-
console.log('[myclaw-skill] 📁 已创建 skills 目录: ' + skillsDir);
|
|
54
|
-
} catch (err) {
|
|
55
|
-
console.log('[myclaw-skill] ⚠️ 无法创建 skills 目录: ' + err.message);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return skillsDir;
|
|
60
|
-
}
|
|
61
|
-
} catch {}
|
|
33
|
+
const skillsDir = path.join(openclawDir, 'skills');
|
|
34
|
+
if (!fs.existsSync(skillsDir)) {
|
|
35
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
36
|
+
console.log('[myclaw-skill] 📁 已创建 skills 目录: ' + skillsDir);
|
|
62
37
|
}
|
|
63
38
|
|
|
64
|
-
return
|
|
39
|
+
return skillsDir;
|
|
65
40
|
}
|
|
66
41
|
|
|
67
42
|
/**
|