agent-configs 1.0.0
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 +223 -0
- package/agents/architect.md +211 -0
- package/agents/code-reviewer.md +104 -0
- package/agents/planner.md +119 -0
- package/agents/refactor-cleaner.md +306 -0
- package/agents/security-reviewer.md +545 -0
- package/agents/tdd-guide.md +280 -0
- package/bundles/bk-chat-bundle/README.md +48 -0
- package/bundles/bk-chat-bundle/manifest.json +10 -0
- package/bundles/continuous-learning/.claude/commands/evolve.md +190 -0
- package/bundles/continuous-learning/.claude/commands/instinct-status.md +64 -0
- package/bundles/continuous-learning/.claude/commands/learn.md +83 -0
- package/bundles/continuous-learning/.claude/hooks/learning-end.js +85 -0
- package/bundles/continuous-learning/.claude/hooks/observe.js +131 -0
- package/bundles/continuous-learning/.claude/lib/learning.js +559 -0
- package/bundles/continuous-learning/.claude/lib/utils.js +312 -0
- package/bundles/continuous-learning/.claude/skills/continuous-learning/SKILL.md +200 -0
- package/bundles/continuous-learning/.cursor/hooks/learning-end.js +102 -0
- package/bundles/continuous-learning/.cursor/rules/continuous-learning.mdc +34 -0
- package/bundles/continuous-learning/.cursor/skills/continuous-learning/SKILL.md +77 -0
- package/bundles/continuous-learning/README.md +159 -0
- package/bundles/continuous-learning/manifest.json +51 -0
- package/bundles/planning-bundle/README.md +34 -0
- package/bundles/planning-bundle/manifest.json +10 -0
- package/bundles/review-bundle/README.md +43 -0
- package/bundles/review-bundle/manifest.json +11 -0
- package/bundles/shared-memory/.claude/commands/list-sessions.md +124 -0
- package/bundles/shared-memory/.claude/commands/load-session.md +169 -0
- package/bundles/shared-memory/.claude/commands/save-session.md +137 -0
- package/bundles/shared-memory/.claude/hooks/memory-compact.js +43 -0
- package/bundles/shared-memory/.claude/hooks/memory-end.js +42 -0
- package/bundles/shared-memory/.claude/hooks/memory-start.js +59 -0
- package/bundles/shared-memory/.claude/lib/memory.js +416 -0
- package/bundles/shared-memory/.claude/lib/utils.js +209 -0
- package/bundles/shared-memory/.claude/skills/shared-memory/SKILL.md +183 -0
- package/bundles/shared-memory/.cursor/hooks/memory-start.js +42 -0
- package/bundles/shared-memory/.cursor/rules/shared-memory.mdc +37 -0
- package/bundles/shared-memory/.cursor/skills/shared-memory/SKILL.md +183 -0
- package/bundles/tdd-bundle/README.md +33 -0
- package/bundles/tdd-bundle/manifest.json +10 -0
- package/cli.js +978 -0
- package/commands/build-fix.md +29 -0
- package/commands/code-review.md +40 -0
- package/commands/e2e.md +363 -0
- package/commands/learn.md +114 -0
- package/commands/plan.md +113 -0
- package/commands/refactor-clean.md +28 -0
- package/commands/tdd.md +326 -0
- package/commands/test-coverage.md +27 -0
- package/commands/update-codemaps.md +17 -0
- package/commands/update-docs.md +31 -0
- package/configs.json +158 -0
- package/hooks/hooks.json +101 -0
- package/package.json +58 -0
- package/rules/agents.md +49 -0
- package/rules/coding-style.md +70 -0
- package/rules/git-workflow.md +45 -0
- package/rules/hooks.md +46 -0
- package/rules/patterns.md +55 -0
- package/rules/performance.md +47 -0
- package/rules/security.md +36 -0
- package/rules/testing.md +30 -0
- package/skills/ai-config-architect/SKILL.md +59 -0
- package/skills/ai-config-architect/references/agents.md +77 -0
- package/skills/ai-config-architect/references/commands.md +66 -0
- package/skills/ai-config-architect/references/hooks.md +70 -0
- package/skills/ai-config-architect/references/patterns.md +66 -0
- package/skills/ai-config-architect/references/platforms.md +82 -0
- package/skills/ai-config-architect/references/rules.md +66 -0
- package/skills/ai-config-architect/references/skills.md +67 -0
- package/skills/bk-chat-helper/SKILL.md +398 -0
- package/skills/bk-chat-helper/references/api-reference.md +606 -0
- package/skills/bk-chat-helper/references/examples.md +789 -0
- package/skills/bk-chat-helper/references/integration-guide.md +583 -0
- package/skills/bk-chat-x/SKILL.md +400 -0
- package/skills/bk-chat-x/references/components-api.md +340 -0
- package/skills/bk-chat-x/references/examples.md +386 -0
- package/skills/bk-chat-x/references/shortcuts-guide.md +375 -0
- package/skills/coding-standards/SKILL.md +523 -0
- package/skills/security-review/SKILL.md +497 -0
- package/skills/security-review/references/cloud-infrastructure-security.md +361 -0
- package/skills/strategic-compact/SKILL.md +66 -0
- package/skills/strategic-compact/scripts/suggest-compact.sh +52 -0
- package/skills/tdd-workflow/SKILL.md +412 -0
- package/skills/verification-loop/SKILL.md +128 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous Learning - 核心学习模块
|
|
3
|
+
*
|
|
4
|
+
* 提供 patterns/skills/instincts 的存储、检索、管理功能
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const {
|
|
10
|
+
ensureDir,
|
|
11
|
+
findFiles,
|
|
12
|
+
readFile,
|
|
13
|
+
writeFile,
|
|
14
|
+
appendJsonl,
|
|
15
|
+
readJsonl,
|
|
16
|
+
getFileSizeMB,
|
|
17
|
+
getDateString,
|
|
18
|
+
getTimestamp,
|
|
19
|
+
getWorkspaceRoot,
|
|
20
|
+
getHomeDir,
|
|
21
|
+
expandPath,
|
|
22
|
+
toSafeFilename
|
|
23
|
+
} = require('./utils');
|
|
24
|
+
|
|
25
|
+
// ============== 默认配置 ==============
|
|
26
|
+
|
|
27
|
+
const DEFAULT_CONFIG = {
|
|
28
|
+
// v1 配置 - 简单版 (Stop hook)
|
|
29
|
+
v1: {
|
|
30
|
+
min_session_length: 10,
|
|
31
|
+
extraction_threshold: 'medium',
|
|
32
|
+
auto_approve: false,
|
|
33
|
+
learned_skills_path: '~/.claude/skills/learned/',
|
|
34
|
+
patterns_to_detect: [
|
|
35
|
+
'error_resolution',
|
|
36
|
+
'user_corrections',
|
|
37
|
+
'workarounds',
|
|
38
|
+
'debugging_techniques',
|
|
39
|
+
'project_specific'
|
|
40
|
+
],
|
|
41
|
+
ignore_patterns: [
|
|
42
|
+
'simple_typos',
|
|
43
|
+
'one_time_fixes',
|
|
44
|
+
'external_api_issues'
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// v2 配置 - 高级版 (PreToolUse/PostToolUse hooks)
|
|
49
|
+
v2: {
|
|
50
|
+
observation: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
store_path: '~/.claude/homunculus/observations.jsonl',
|
|
53
|
+
max_file_size_mb: 10,
|
|
54
|
+
archive_after_days: 7,
|
|
55
|
+
capture_tools: ['Edit', 'Write', 'Bash', 'Read', 'Grep', 'Glob'],
|
|
56
|
+
ignore_tools: ['TodoWrite']
|
|
57
|
+
},
|
|
58
|
+
instincts: {
|
|
59
|
+
personal_path: '~/.claude/homunculus/instincts/personal/',
|
|
60
|
+
inherited_path: '~/.claude/homunculus/instincts/inherited/',
|
|
61
|
+
min_confidence: 0.3,
|
|
62
|
+
auto_approve_threshold: 0.7,
|
|
63
|
+
confidence_decay_rate: 0.02,
|
|
64
|
+
max_instincts: 100
|
|
65
|
+
},
|
|
66
|
+
evolution: {
|
|
67
|
+
cluster_threshold: 3,
|
|
68
|
+
evolved_path: '~/.claude/homunculus/evolved/',
|
|
69
|
+
auto_evolve: false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// ============== 路径管理 ==============
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取 learned skills 目录
|
|
78
|
+
*/
|
|
79
|
+
function getLearnedSkillsDir(config = DEFAULT_CONFIG.v1) {
|
|
80
|
+
return expandPath(config.learned_skills_path);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 获取 homunculus 根目录 (v2)
|
|
85
|
+
*/
|
|
86
|
+
function getHomunculusDir() {
|
|
87
|
+
return expandPath('~/.claude/homunculus');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 获取 observations 文件路径 (v2)
|
|
92
|
+
*/
|
|
93
|
+
function getObservationsPath(config = DEFAULT_CONFIG.v2) {
|
|
94
|
+
return expandPath(config.observation.store_path);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 获取 instincts 目录 (v2)
|
|
99
|
+
*/
|
|
100
|
+
function getInstinctsDir(type = 'personal', config = DEFAULT_CONFIG.v2) {
|
|
101
|
+
if (type === 'inherited') {
|
|
102
|
+
return expandPath(config.instincts.inherited_path);
|
|
103
|
+
}
|
|
104
|
+
return expandPath(config.instincts.personal_path);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 获取 evolved 目录 (v2)
|
|
109
|
+
*/
|
|
110
|
+
function getEvolvedDir(type, config = DEFAULT_CONFIG.v2) {
|
|
111
|
+
const base = expandPath(config.evolution.evolved_path);
|
|
112
|
+
if (type) {
|
|
113
|
+
return path.join(base, type);
|
|
114
|
+
}
|
|
115
|
+
return base;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 确保所有学习目录存在
|
|
120
|
+
*/
|
|
121
|
+
function ensureLearningDirs(config = DEFAULT_CONFIG) {
|
|
122
|
+
// v1 目录
|
|
123
|
+
ensureDir(getLearnedSkillsDir(config.v1));
|
|
124
|
+
|
|
125
|
+
// v2 目录
|
|
126
|
+
ensureDir(getHomunculusDir());
|
|
127
|
+
ensureDir(getInstinctsDir('personal', config.v2));
|
|
128
|
+
ensureDir(getInstinctsDir('inherited', config.v2));
|
|
129
|
+
ensureDir(getEvolvedDir('skills', config.v2));
|
|
130
|
+
ensureDir(getEvolvedDir('commands', config.v2));
|
|
131
|
+
ensureDir(getEvolvedDir('agents', config.v2));
|
|
132
|
+
ensureDir(path.dirname(getObservationsPath(config.v2)));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ============== Learned Skills (v1) ==============
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 生成 learned skill 文件名
|
|
139
|
+
*/
|
|
140
|
+
function generateSkillFilename(name) {
|
|
141
|
+
return `${toSafeFilename(name)}.md`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 生成 learned skill 内容
|
|
146
|
+
*/
|
|
147
|
+
function generateSkillContent(data) {
|
|
148
|
+
const {
|
|
149
|
+
name,
|
|
150
|
+
context = '',
|
|
151
|
+
problem = '',
|
|
152
|
+
solution = '',
|
|
153
|
+
example = '',
|
|
154
|
+
triggers = []
|
|
155
|
+
} = data;
|
|
156
|
+
|
|
157
|
+
const date = getDateString();
|
|
158
|
+
|
|
159
|
+
return `# ${name}
|
|
160
|
+
|
|
161
|
+
**Extracted:** ${date}
|
|
162
|
+
**Context:** ${context}
|
|
163
|
+
|
|
164
|
+
## Problem
|
|
165
|
+
${problem}
|
|
166
|
+
|
|
167
|
+
## Solution
|
|
168
|
+
${solution}
|
|
169
|
+
|
|
170
|
+
## Example
|
|
171
|
+
${example || '(No example provided)'}
|
|
172
|
+
|
|
173
|
+
## When to Use
|
|
174
|
+
${triggers.length > 0 ? triggers.map(t => `- ${t}`).join('\n') : '(Trigger conditions not specified)'}
|
|
175
|
+
`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 保存 learned skill
|
|
180
|
+
*/
|
|
181
|
+
function saveLearnedSkill(data, config = DEFAULT_CONFIG.v1) {
|
|
182
|
+
try {
|
|
183
|
+
const skillsDir = getLearnedSkillsDir(config);
|
|
184
|
+
ensureDir(skillsDir);
|
|
185
|
+
|
|
186
|
+
const filename = generateSkillFilename(data.name);
|
|
187
|
+
const filePath = path.join(skillsDir, filename);
|
|
188
|
+
const content = generateSkillContent(data);
|
|
189
|
+
|
|
190
|
+
writeFile(filePath, content);
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
success: true,
|
|
194
|
+
path: filePath,
|
|
195
|
+
filename
|
|
196
|
+
};
|
|
197
|
+
} catch (err) {
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: err.message
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 列出所有 learned skills
|
|
207
|
+
*/
|
|
208
|
+
function listLearnedSkills(config = DEFAULT_CONFIG.v1) {
|
|
209
|
+
const skillsDir = getLearnedSkillsDir(config);
|
|
210
|
+
const files = findFiles(skillsDir, '*.md');
|
|
211
|
+
|
|
212
|
+
return files.map(file => {
|
|
213
|
+
const content = readFile(file.path);
|
|
214
|
+
const nameMatch = content?.match(/^#\s+(.+)$/m);
|
|
215
|
+
const contextMatch = content?.match(/\*\*Context:\*\*\s*(.+)$/m);
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
path: file.path,
|
|
219
|
+
filename: path.basename(file.path),
|
|
220
|
+
name: nameMatch ? nameMatch[1] : path.basename(file.path, '.md'),
|
|
221
|
+
context: contextMatch ? contextMatch[1] : '',
|
|
222
|
+
mtime: file.mtime
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ============== Observations (v2) ==============
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* 记录观察
|
|
231
|
+
*/
|
|
232
|
+
function recordObservation(data, config = DEFAULT_CONFIG.v2) {
|
|
233
|
+
const obsPath = getObservationsPath(config);
|
|
234
|
+
|
|
235
|
+
// 检查文件大小,必要时归档
|
|
236
|
+
const sizeMB = getFileSizeMB(obsPath);
|
|
237
|
+
if (sizeMB >= config.observation.max_file_size_mb) {
|
|
238
|
+
archiveObservations(config);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const observation = {
|
|
242
|
+
timestamp: getTimestamp(),
|
|
243
|
+
...data
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
appendJsonl(obsPath, observation);
|
|
247
|
+
return observation;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* 归档旧的 observations
|
|
252
|
+
*/
|
|
253
|
+
function archiveObservations(config = DEFAULT_CONFIG.v2) {
|
|
254
|
+
const obsPath = getObservationsPath(config);
|
|
255
|
+
if (!fs.existsSync(obsPath)) return;
|
|
256
|
+
|
|
257
|
+
const archiveDir = path.join(getHomunculusDir(), 'observations.archive');
|
|
258
|
+
ensureDir(archiveDir);
|
|
259
|
+
|
|
260
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
261
|
+
const archivePath = path.join(archiveDir, `observations-${timestamp}.jsonl`);
|
|
262
|
+
|
|
263
|
+
fs.renameSync(obsPath, archivePath);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 读取近期 observations
|
|
268
|
+
*/
|
|
269
|
+
function getRecentObservations(limit = 100, config = DEFAULT_CONFIG.v2) {
|
|
270
|
+
const obsPath = getObservationsPath(config);
|
|
271
|
+
const observations = readJsonl(obsPath);
|
|
272
|
+
|
|
273
|
+
return observations.slice(-limit);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ============== Instincts (v2) ==============
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 生成 instinct 文件名
|
|
280
|
+
*/
|
|
281
|
+
function generateInstinctFilename(id) {
|
|
282
|
+
return `${toSafeFilename(id)}.md`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* 生成 instinct 内容
|
|
287
|
+
*/
|
|
288
|
+
function generateInstinctContent(data) {
|
|
289
|
+
const {
|
|
290
|
+
id,
|
|
291
|
+
trigger = '',
|
|
292
|
+
confidence = 0.5,
|
|
293
|
+
domain = 'general',
|
|
294
|
+
source = 'session-observation',
|
|
295
|
+
action = '',
|
|
296
|
+
evidence = []
|
|
297
|
+
} = data;
|
|
298
|
+
|
|
299
|
+
return `---
|
|
300
|
+
id: ${id}
|
|
301
|
+
trigger: "${trigger}"
|
|
302
|
+
confidence: ${confidence}
|
|
303
|
+
domain: "${domain}"
|
|
304
|
+
source: "${source}"
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
# ${id.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}
|
|
308
|
+
|
|
309
|
+
## Action
|
|
310
|
+
${action}
|
|
311
|
+
|
|
312
|
+
## Evidence
|
|
313
|
+
${evidence.length > 0 ? evidence.map(e => `- ${e}`).join('\n') : '- Initial observation'}
|
|
314
|
+
`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* 保存 instinct
|
|
319
|
+
*/
|
|
320
|
+
function saveInstinct(data, config = DEFAULT_CONFIG.v2) {
|
|
321
|
+
try {
|
|
322
|
+
const instinctsDir = getInstinctsDir('personal', config);
|
|
323
|
+
ensureDir(instinctsDir);
|
|
324
|
+
|
|
325
|
+
const filename = generateInstinctFilename(data.id);
|
|
326
|
+
const filePath = path.join(instinctsDir, filename);
|
|
327
|
+
const content = generateInstinctContent(data);
|
|
328
|
+
|
|
329
|
+
writeFile(filePath, content);
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
success: true,
|
|
333
|
+
path: filePath,
|
|
334
|
+
filename
|
|
335
|
+
};
|
|
336
|
+
} catch (err) {
|
|
337
|
+
return {
|
|
338
|
+
success: false,
|
|
339
|
+
error: err.message
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* 解析 instinct 文件
|
|
346
|
+
*/
|
|
347
|
+
function parseInstinctFile(filePath) {
|
|
348
|
+
const content = readFile(filePath);
|
|
349
|
+
if (!content) return null;
|
|
350
|
+
|
|
351
|
+
const instinct = {
|
|
352
|
+
path: filePath,
|
|
353
|
+
filename: path.basename(filePath)
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// 解析 frontmatter
|
|
357
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
358
|
+
if (frontmatterMatch) {
|
|
359
|
+
const frontmatter = frontmatterMatch[1];
|
|
360
|
+
|
|
361
|
+
const idMatch = frontmatter.match(/^id:\s*(.+)$/m);
|
|
362
|
+
const triggerMatch = frontmatter.match(/^trigger:\s*"?(.+?)"?$/m);
|
|
363
|
+
const confidenceMatch = frontmatter.match(/^confidence:\s*(.+)$/m);
|
|
364
|
+
const domainMatch = frontmatter.match(/^domain:\s*"?(.+?)"?$/m);
|
|
365
|
+
const sourceMatch = frontmatter.match(/^source:\s*"?(.+?)"?$/m);
|
|
366
|
+
|
|
367
|
+
if (idMatch) instinct.id = idMatch[1];
|
|
368
|
+
if (triggerMatch) instinct.trigger = triggerMatch[1];
|
|
369
|
+
if (confidenceMatch) instinct.confidence = parseFloat(confidenceMatch[1]);
|
|
370
|
+
if (domainMatch) instinct.domain = domainMatch[1];
|
|
371
|
+
if (sourceMatch) instinct.source = sourceMatch[1];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// 解析 action
|
|
375
|
+
const actionMatch = content.match(/## Action\n([\s\S]*?)(?=\n## |$)/);
|
|
376
|
+
if (actionMatch) {
|
|
377
|
+
instinct.action = actionMatch[1].trim();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// 解析 evidence
|
|
381
|
+
const evidenceMatch = content.match(/## Evidence\n([\s\S]*?)(?=\n## |$)/);
|
|
382
|
+
if (evidenceMatch) {
|
|
383
|
+
instinct.evidence = evidenceMatch[1]
|
|
384
|
+
.split('\n')
|
|
385
|
+
.filter(l => l.startsWith('- '))
|
|
386
|
+
.map(l => l.slice(2).trim());
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return instinct;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* 列出所有 instincts
|
|
394
|
+
*/
|
|
395
|
+
function listInstincts(config = DEFAULT_CONFIG.v2) {
|
|
396
|
+
const personalDir = getInstinctsDir('personal', config);
|
|
397
|
+
const inheritedDir = getInstinctsDir('inherited', config);
|
|
398
|
+
|
|
399
|
+
const personal = findFiles(personalDir, '*.md').map(f => ({
|
|
400
|
+
...parseInstinctFile(f.path),
|
|
401
|
+
type: 'personal',
|
|
402
|
+
mtime: f.mtime
|
|
403
|
+
}));
|
|
404
|
+
|
|
405
|
+
const inherited = findFiles(inheritedDir, '*.md').map(f => ({
|
|
406
|
+
...parseInstinctFile(f.path),
|
|
407
|
+
type: 'inherited',
|
|
408
|
+
mtime: f.mtime
|
|
409
|
+
}));
|
|
410
|
+
|
|
411
|
+
return [...personal, ...inherited].filter(Boolean);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* 更新 instinct 置信度
|
|
416
|
+
*/
|
|
417
|
+
function updateInstinctConfidence(id, delta, config = DEFAULT_CONFIG.v2) {
|
|
418
|
+
const instinctsDir = getInstinctsDir('personal', config);
|
|
419
|
+
const filePath = path.join(instinctsDir, generateInstinctFilename(id));
|
|
420
|
+
|
|
421
|
+
const instinct = parseInstinctFile(filePath);
|
|
422
|
+
if (!instinct) return null;
|
|
423
|
+
|
|
424
|
+
const newConfidence = Math.max(0, Math.min(1, instinct.confidence + delta));
|
|
425
|
+
instinct.confidence = newConfidence;
|
|
426
|
+
|
|
427
|
+
const content = generateInstinctContent(instinct);
|
|
428
|
+
writeFile(filePath, content);
|
|
429
|
+
|
|
430
|
+
return instinct;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ============== Evolution (v2) ==============
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* 按 domain 分组 instincts
|
|
437
|
+
*/
|
|
438
|
+
function groupInstinctsByDomain(instincts) {
|
|
439
|
+
const groups = {};
|
|
440
|
+
|
|
441
|
+
for (const instinct of instincts) {
|
|
442
|
+
const domain = instinct.domain || 'general';
|
|
443
|
+
if (!groups[domain]) {
|
|
444
|
+
groups[domain] = [];
|
|
445
|
+
}
|
|
446
|
+
groups[domain].push(instinct);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return groups;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* 查找可进化的 instinct 集群
|
|
454
|
+
*/
|
|
455
|
+
function findEvolvableClusters(instincts, config = DEFAULT_CONFIG.v2) {
|
|
456
|
+
const threshold = config.evolution.cluster_threshold;
|
|
457
|
+
const groups = groupInstinctsByDomain(instincts);
|
|
458
|
+
const clusters = [];
|
|
459
|
+
|
|
460
|
+
for (const [domain, domainInstincts] of Object.entries(groups)) {
|
|
461
|
+
if (domainInstincts.length >= threshold) {
|
|
462
|
+
// 计算平均置信度
|
|
463
|
+
const avgConfidence = domainInstincts.reduce((sum, i) => sum + (i.confidence || 0.5), 0) / domainInstincts.length;
|
|
464
|
+
|
|
465
|
+
// 确定进化类型
|
|
466
|
+
let evolutionType = 'skill';
|
|
467
|
+
const triggers = domainInstincts.map(i => i.trigger || '').join(' ');
|
|
468
|
+
|
|
469
|
+
if (triggers.includes('user asks') || triggers.includes('when creating')) {
|
|
470
|
+
evolutionType = 'command';
|
|
471
|
+
} else if (domainInstincts.length >= 4 && avgConfidence >= 0.7) {
|
|
472
|
+
evolutionType = 'agent';
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
clusters.push({
|
|
476
|
+
domain,
|
|
477
|
+
instincts: domainInstincts,
|
|
478
|
+
count: domainInstincts.length,
|
|
479
|
+
avgConfidence,
|
|
480
|
+
evolutionType,
|
|
481
|
+
suggestedName: `${domain}-${evolutionType}`
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return clusters;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// ============== 会话评估 ==============
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* 检查会话是否值得评估
|
|
493
|
+
*/
|
|
494
|
+
function shouldEvaluateSession(messageCount, config = DEFAULT_CONFIG.v1) {
|
|
495
|
+
return messageCount >= config.min_session_length;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 获取学习状态摘要
|
|
500
|
+
*/
|
|
501
|
+
function getLearningStatus(config = DEFAULT_CONFIG) {
|
|
502
|
+
const learnedSkills = listLearnedSkills(config.v1);
|
|
503
|
+
const instincts = listInstincts(config.v2);
|
|
504
|
+
const observations = getRecentObservations(100, config.v2);
|
|
505
|
+
const clusters = findEvolvableClusters(instincts, config.v2);
|
|
506
|
+
|
|
507
|
+
return {
|
|
508
|
+
v1: {
|
|
509
|
+
learnedSkillsCount: learnedSkills.length,
|
|
510
|
+
skills: learnedSkills
|
|
511
|
+
},
|
|
512
|
+
v2: {
|
|
513
|
+
instinctsCount: instincts.length,
|
|
514
|
+
instincts,
|
|
515
|
+
recentObservationsCount: observations.length,
|
|
516
|
+
evolvableClusters: clusters
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
module.exports = {
|
|
522
|
+
// 配置
|
|
523
|
+
DEFAULT_CONFIG,
|
|
524
|
+
|
|
525
|
+
// 路径
|
|
526
|
+
getLearnedSkillsDir,
|
|
527
|
+
getHomunculusDir,
|
|
528
|
+
getObservationsPath,
|
|
529
|
+
getInstinctsDir,
|
|
530
|
+
getEvolvedDir,
|
|
531
|
+
ensureLearningDirs,
|
|
532
|
+
|
|
533
|
+
// Learned Skills (v1)
|
|
534
|
+
generateSkillFilename,
|
|
535
|
+
generateSkillContent,
|
|
536
|
+
saveLearnedSkill,
|
|
537
|
+
listLearnedSkills,
|
|
538
|
+
|
|
539
|
+
// Observations (v2)
|
|
540
|
+
recordObservation,
|
|
541
|
+
archiveObservations,
|
|
542
|
+
getRecentObservations,
|
|
543
|
+
|
|
544
|
+
// Instincts (v2)
|
|
545
|
+
generateInstinctFilename,
|
|
546
|
+
generateInstinctContent,
|
|
547
|
+
saveInstinct,
|
|
548
|
+
parseInstinctFile,
|
|
549
|
+
listInstincts,
|
|
550
|
+
updateInstinctConfidence,
|
|
551
|
+
|
|
552
|
+
// Evolution (v2)
|
|
553
|
+
groupInstinctsByDomain,
|
|
554
|
+
findEvolvableClusters,
|
|
555
|
+
|
|
556
|
+
// 评估
|
|
557
|
+
shouldEvaluateSession,
|
|
558
|
+
getLearningStatus
|
|
559
|
+
};
|