@yulailai/openclaw-plugin-self-growth 3.1.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/LICENSE +21 -0
- package/PERSONALITY.md +60 -0
- package/README.md +19 -0
- package/dist/anti-tamper.js +55 -0
- package/dist/auth-client.js +80 -0
- package/dist/chat-logger.js +86 -0
- package/dist/daily-review.js +311 -0
- package/dist/health-check.js +65 -0
- package/dist/index.js +721 -0
- package/dist/memory-manager.js +374 -0
- package/dist/payment.js +89 -0
- package/dist/preference-extractor.js +190 -0
- package/dist/setup-wizard.js +130 -0
- package/dist/skill-generator.js +259 -0
- package/dist/skill-optimizer.js +393 -0
- package/dist/sync-client.js +220 -0
- package/dist/task-tracker.js +215 -0
- package/dist/utils/logger.js +24 -0
- package/openclaw.plugin.json +85 -0
- package/package.json +376 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* 任务追踪器(融合版 + 关联 + 防抖)
|
|
5
|
+
*
|
|
6
|
+
* 功能一:实时状态追踪 — 监控任务执行状态(进行中/成功/失败)
|
|
7
|
+
* 功能二:长期流程记录 — 记录任务步骤、累计次数、触发 Skill 生成
|
|
8
|
+
* 功能三:维度关联 — 通过 runIds 关联实时状态与长期记录
|
|
9
|
+
* 功能四:防抖保存 — 减少高并发下的文件 I/O 压力
|
|
10
|
+
*/
|
|
11
|
+
export class TaskTracker {
|
|
12
|
+
// ========== 实时状态追踪 ==========
|
|
13
|
+
activeTasks = new Map();
|
|
14
|
+
completedTasks = [];
|
|
15
|
+
// ========== 长期流程记录 ==========
|
|
16
|
+
trackerFile;
|
|
17
|
+
tasks;
|
|
18
|
+
// ========== 防抖保存 ==========
|
|
19
|
+
saveTimer = null;
|
|
20
|
+
saveDelay = 500; // 500ms 防抖间隔
|
|
21
|
+
constructor(storageDir = './memory') {
|
|
22
|
+
this.trackerFile = path.join(storageDir, 'task_tracker.json');
|
|
23
|
+
this.tasks = new Map();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 初始化:从文件加载已有的任务记录
|
|
27
|
+
*/
|
|
28
|
+
async init() {
|
|
29
|
+
try {
|
|
30
|
+
await fs.mkdir(path.dirname(this.trackerFile), { recursive: true });
|
|
31
|
+
const data = await fs.readFile(this.trackerFile, 'utf-8');
|
|
32
|
+
const parsed = JSON.parse(data);
|
|
33
|
+
this.tasks = new Map(Object.entries(parsed));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
this.tasks = new Map();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// ========== 实时状态 API ==========
|
|
40
|
+
/**
|
|
41
|
+
* 标记一个任务开始执行
|
|
42
|
+
*/
|
|
43
|
+
startTask(taskId, taskName) {
|
|
44
|
+
this.activeTasks.set(taskId, taskName);
|
|
45
|
+
console.log(`[TaskTracker] ▶️ 任务开始 [${taskId}]: ${taskName}`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 标记一个任务执行成功
|
|
49
|
+
*/
|
|
50
|
+
completeTask(taskId) {
|
|
51
|
+
const taskName = this.activeTasks.get(taskId);
|
|
52
|
+
if (taskName) {
|
|
53
|
+
this.recordCompletion(taskId, taskName, 'success');
|
|
54
|
+
console.log(`[TaskTracker] ✅ 任务成功 [${taskId}]: ${taskName}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 标记一个任务执行失败
|
|
59
|
+
*/
|
|
60
|
+
failTask(taskId, error) {
|
|
61
|
+
const taskName = this.activeTasks.get(taskId);
|
|
62
|
+
if (taskName) {
|
|
63
|
+
this.recordCompletion(taskId, taskName, 'failed');
|
|
64
|
+
console.warn(`[TaskTracker] ❌ 任务失败 [${taskId}]: ${taskName}${error ? ` - ${error}` : ''}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 获取当前所有正在执行的任务
|
|
69
|
+
*/
|
|
70
|
+
getActiveTasks() {
|
|
71
|
+
return new Map(this.activeTasks);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 获取最近完成的任务列表
|
|
75
|
+
*/
|
|
76
|
+
getRecentCompletedTasks(limit = 10) {
|
|
77
|
+
return this.completedTasks.slice(-limit);
|
|
78
|
+
}
|
|
79
|
+
// ========== 长期流程记录 API ==========
|
|
80
|
+
/**
|
|
81
|
+
* 记录一次任务执行(流程步骤追踪)
|
|
82
|
+
* 会自动关联当前所有活跃的 taskId,建立维度关联。
|
|
83
|
+
*
|
|
84
|
+
* @param taskName 任务名称,例如 "周报生成"
|
|
85
|
+
* @param steps 步骤列表
|
|
86
|
+
* @param category 任务类别
|
|
87
|
+
* @returns 本次记录后的任务信息
|
|
88
|
+
*/
|
|
89
|
+
async addTask(taskName, steps, category = 'general') {
|
|
90
|
+
if (!this.tasks.has(taskName)) {
|
|
91
|
+
this.tasks.set(taskName, {
|
|
92
|
+
name: taskName,
|
|
93
|
+
category,
|
|
94
|
+
count: 0,
|
|
95
|
+
steps,
|
|
96
|
+
history: [],
|
|
97
|
+
readyForSkill: false,
|
|
98
|
+
runIds: []
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const task = this.tasks.get(taskName);
|
|
102
|
+
task.count += 1;
|
|
103
|
+
task.steps = steps;
|
|
104
|
+
task.history.push({
|
|
105
|
+
time: new Date().toISOString(),
|
|
106
|
+
steps
|
|
107
|
+
});
|
|
108
|
+
// 关联当前所有活跃的 taskId
|
|
109
|
+
const activeIds = Array.from(this.activeTasks.keys());
|
|
110
|
+
task.runIds.push(...activeIds);
|
|
111
|
+
if (task.count >= 3) {
|
|
112
|
+
task.readyForSkill = true;
|
|
113
|
+
}
|
|
114
|
+
// 防抖保存:500ms 内的多次调用只触发一次文件写入
|
|
115
|
+
this.debouncedSave();
|
|
116
|
+
return task;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 获取某个任务的完整信息
|
|
120
|
+
*/
|
|
121
|
+
getTask(taskName) {
|
|
122
|
+
return this.tasks.get(taskName);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 获取某个任务的执行次数
|
|
126
|
+
*/
|
|
127
|
+
getTaskCount(taskName) {
|
|
128
|
+
const task = this.tasks.get(taskName);
|
|
129
|
+
return task ? task.count : 0;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 获取所有可生成 Skill 的任务
|
|
133
|
+
*/
|
|
134
|
+
getReadyTasks() {
|
|
135
|
+
return Array.from(this.tasks.values()).filter(task => task.readyForSkill);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 列出所有已追踪的任务名称
|
|
139
|
+
*/
|
|
140
|
+
listAllTasks() {
|
|
141
|
+
return Array.from(this.tasks.keys());
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* 检查某个任务是否达到了生成 Skill 的阈值(3 次)
|
|
145
|
+
*/
|
|
146
|
+
isReadyForSkill(taskName) {
|
|
147
|
+
const task = this.tasks.get(taskName);
|
|
148
|
+
return task ? task.readyForSkill : false;
|
|
149
|
+
}
|
|
150
|
+
// ========== 通用 API ==========
|
|
151
|
+
/**
|
|
152
|
+
* 重置实时追踪状态(长期记录保留)
|
|
153
|
+
*/
|
|
154
|
+
reset() {
|
|
155
|
+
this.activeTasks.clear();
|
|
156
|
+
this.completedTasks = [];
|
|
157
|
+
console.log('[TaskTracker] 🧹 已重置追踪状态(长期记录保留)');
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 完全清空所有数据(包括长期记录)
|
|
161
|
+
* 会取消待处理的防抖保存,立即写入空数据
|
|
162
|
+
*/
|
|
163
|
+
async clearAll() {
|
|
164
|
+
this.activeTasks.clear();
|
|
165
|
+
this.completedTasks = [];
|
|
166
|
+
this.tasks.clear();
|
|
167
|
+
if (this.saveTimer) {
|
|
168
|
+
clearTimeout(this.saveTimer);
|
|
169
|
+
this.saveTimer = null;
|
|
170
|
+
}
|
|
171
|
+
await this.saveImmediate();
|
|
172
|
+
console.log('[TaskTracker] 🧹 已清空所有追踪数据');
|
|
173
|
+
}
|
|
174
|
+
// ========== 私有方法 ==========
|
|
175
|
+
/**
|
|
176
|
+
* 记录任务完成并清理活跃任务列表
|
|
177
|
+
*/
|
|
178
|
+
recordCompletion(taskId, taskName, status) {
|
|
179
|
+
this.completedTasks.push({
|
|
180
|
+
id: taskId,
|
|
181
|
+
name: taskName,
|
|
182
|
+
status,
|
|
183
|
+
time: new Date().toISOString()
|
|
184
|
+
});
|
|
185
|
+
this.activeTasks.delete(taskId);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 防抖保存:延迟 500ms 写入文件。
|
|
189
|
+
* 如果在延迟期间又有新数据,取消前一次计时器,重新计时。
|
|
190
|
+
* 这样高并发下的多次调用只触发一次实际的文件 I/O。
|
|
191
|
+
*/
|
|
192
|
+
debouncedSave() {
|
|
193
|
+
if (this.saveTimer) {
|
|
194
|
+
clearTimeout(this.saveTimer);
|
|
195
|
+
}
|
|
196
|
+
this.saveTimer = setTimeout(() => {
|
|
197
|
+
this.saveImmediate();
|
|
198
|
+
this.saveTimer = null;
|
|
199
|
+
}, this.saveDelay);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 立即保存长期任务数据到文件(不经过防抖)
|
|
203
|
+
*/
|
|
204
|
+
async saveImmediate() {
|
|
205
|
+
try {
|
|
206
|
+
await fs.mkdir(path.dirname(this.trackerFile), { recursive: true });
|
|
207
|
+
const data = Object.fromEntries(this.tasks);
|
|
208
|
+
await fs.writeFile(this.trackerFile, JSON.stringify(data, null, 2), 'utf-8');
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error('[TaskTracker] ❌ 保存任务数据失败:', error);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=task-tracker.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2
|
+
const currentLevel = process.env.YUNLAILAI_LOG_LEVEL || 'info';
|
|
3
|
+
function log(level, message, meta) {
|
|
4
|
+
if (LOG_LEVELS[level] < LOG_LEVELS[currentLevel])
|
|
5
|
+
return;
|
|
6
|
+
const timestamp = new Date().toISOString();
|
|
7
|
+
const prefix = `[yunlailai] ${timestamp} [${level.toUpperCase()}]`;
|
|
8
|
+
if (level === 'error') {
|
|
9
|
+
console.error(prefix, message, meta || '');
|
|
10
|
+
}
|
|
11
|
+
else if (level === 'warn') {
|
|
12
|
+
console.warn(prefix, message, meta || '');
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
console.log(prefix, message, meta || '');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export const logger = {
|
|
19
|
+
debug: (msg, meta) => log('debug', msg, meta),
|
|
20
|
+
info: (msg, meta) => log('info', msg, meta),
|
|
21
|
+
warn: (msg, meta) => log('warn', msg, meta),
|
|
22
|
+
error: (msg, meta) => log('error', msg, meta),
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "@yulailai/openclaw-plugin-self-growth",
|
|
3
|
+
"name": "Self Growth Engine",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"description": "让 Agent 具备自我成长、复盘与技能进化能力的插件。支持对话日志、偏好提取与注入、双引擎反思、技能自动生成与生命周期管理、每日复盘、技能评分与自动清理。",
|
|
6
|
+
"author": "lailai",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"activation": {
|
|
9
|
+
"onStartup": true
|
|
10
|
+
},
|
|
11
|
+
"capability": {
|
|
12
|
+
"hooks": ["session_start", "before_prompt_build", "agent_end","before_compaction"]
|
|
13
|
+
},
|
|
14
|
+
"contracts": {
|
|
15
|
+
"tools": [
|
|
16
|
+
"daily_analyze_tool",
|
|
17
|
+
"record_session_insight",
|
|
18
|
+
"manage_interrupted_task"
|
|
19
|
+
],
|
|
20
|
+
"hooks": [
|
|
21
|
+
"session_start",
|
|
22
|
+
"before_prompt_build",
|
|
23
|
+
"agent_end",
|
|
24
|
+
"before_compaction"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"outputHooks": [
|
|
28
|
+
"session_start",
|
|
29
|
+
"before_prompt_build",
|
|
30
|
+
"agent_end",
|
|
31
|
+
"before_compaction"
|
|
32
|
+
],
|
|
33
|
+
"toolMetadata": {
|
|
34
|
+
"daily_analyze_tool": {
|
|
35
|
+
"optional": true
|
|
36
|
+
},
|
|
37
|
+
"record_session_insight": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"manage_interrupted_task": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"install": {
|
|
45
|
+
"ignore": [
|
|
46
|
+
"memory",
|
|
47
|
+
"chat_logs",
|
|
48
|
+
"skills"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"skills": [
|
|
52
|
+
"./skills"
|
|
53
|
+
],
|
|
54
|
+
"configSchema": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"properties": {
|
|
58
|
+
"enableDailyReview": {
|
|
59
|
+
"type": "boolean",
|
|
60
|
+
"default": true,
|
|
61
|
+
"description": "是否开启每日自动复盘功能"
|
|
62
|
+
},
|
|
63
|
+
"logRetentionDays": {
|
|
64
|
+
"type": "integer",
|
|
65
|
+
"default": 30,
|
|
66
|
+
"description": "对话日志的保留天数"
|
|
67
|
+
},
|
|
68
|
+
"memoryPath": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"default": "./memory",
|
|
71
|
+
"description": "长期记忆文件的存储路径"
|
|
72
|
+
},
|
|
73
|
+
"autoOptimizeSkills": {
|
|
74
|
+
"type": "boolean",
|
|
75
|
+
"default": false,
|
|
76
|
+
"description": "是否允许插件自动优化已有的技能"
|
|
77
|
+
},
|
|
78
|
+
"skillsOutputDir": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"default": "./skills",
|
|
81
|
+
"description": "技能文件输出目录"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|