midou 0.1.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/LICENSE +21 -0
- package/README.md +241 -0
- package/midou.config.js +76 -0
- package/package.json +44 -0
- package/src/boot.js +145 -0
- package/src/chat.js +187 -0
- package/src/heartbeat.js +119 -0
- package/src/index.js +438 -0
- package/src/init.js +258 -0
- package/src/llm.js +239 -0
- package/src/mcp.js +376 -0
- package/src/memory.js +123 -0
- package/src/mode.js +223 -0
- package/src/scheduler.js +186 -0
- package/src/skills.js +150 -0
- package/src/soul.js +203 -0
- package/src/tools.js +571 -0
package/src/soul.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 灵魂加载器 — 加载 midou 的灵魂、身份和工作区文件
|
|
3
|
+
* 这是 midou 醒来时首先要做的事
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import config from '../midou.config.js';
|
|
9
|
+
|
|
10
|
+
const WORKSPACE = config.workspace.root;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 安全读取文件,如果不存在返回 null
|
|
14
|
+
*/
|
|
15
|
+
export async function readFile(filePath) {
|
|
16
|
+
try {
|
|
17
|
+
const fullPath = filePath.startsWith('/') ? filePath : path.join(WORKSPACE, filePath);
|
|
18
|
+
return await fs.readFile(fullPath, 'utf-8');
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 写入文件
|
|
26
|
+
*/
|
|
27
|
+
export async function writeFile(filePath, content) {
|
|
28
|
+
const fullPath = filePath.startsWith('/') ? filePath : path.join(WORKSPACE, filePath);
|
|
29
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
30
|
+
await fs.writeFile(fullPath, content, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 追加内容到文件
|
|
35
|
+
*/
|
|
36
|
+
export async function appendFile(filePath, content) {
|
|
37
|
+
const fullPath = filePath.startsWith('/') ? filePath : path.join(WORKSPACE, filePath);
|
|
38
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
39
|
+
await fs.appendFile(fullPath, content, 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 删除文件
|
|
44
|
+
*/
|
|
45
|
+
export async function deleteFile(filePath) {
|
|
46
|
+
try {
|
|
47
|
+
const fullPath = filePath.startsWith('/') ? filePath : path.join(WORKSPACE, filePath);
|
|
48
|
+
await fs.unlink(fullPath);
|
|
49
|
+
return true;
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 检查文件是否存在
|
|
57
|
+
*/
|
|
58
|
+
export async function fileExists(filePath) {
|
|
59
|
+
try {
|
|
60
|
+
const fullPath = filePath.startsWith('/') ? filePath : path.join(WORKSPACE, filePath);
|
|
61
|
+
await fs.access(fullPath);
|
|
62
|
+
return true;
|
|
63
|
+
} catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 列出目录内容
|
|
70
|
+
*/
|
|
71
|
+
export async function listDir(dirPath) {
|
|
72
|
+
try {
|
|
73
|
+
const fullPath = dirPath.startsWith('/') ? dirPath : path.join(WORKSPACE, dirPath);
|
|
74
|
+
return await fs.readdir(fullPath);
|
|
75
|
+
} catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 加载 midou 的灵魂——启动时首先执行
|
|
82
|
+
* 按顺序加载:SOUL.md → IDENTITY.md → USER.md → 今日记忆 → 长期记忆
|
|
83
|
+
*/
|
|
84
|
+
export async function loadSoul() {
|
|
85
|
+
const soul = await readFile('SOUL.md');
|
|
86
|
+
const identity = await readFile('IDENTITY.md');
|
|
87
|
+
const user = await readFile('USER.md');
|
|
88
|
+
const memory = await readFile('MEMORY.md');
|
|
89
|
+
const heartbeat = await readFile('HEARTBEAT.md');
|
|
90
|
+
const bootstrap = await readFile('BOOTSTRAP.md');
|
|
91
|
+
|
|
92
|
+
return { soul, identity, user, memory, heartbeat, bootstrap };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 构建系统提示词——将灵魂注入 midou
|
|
97
|
+
*
|
|
98
|
+
* 根据功耗模式分级构建,eco 模式极度精简,full 模式完整展开。
|
|
99
|
+
* 工具描述不再重复列出(模型已通过 function calling 获得),仅提供行为指南。
|
|
100
|
+
*
|
|
101
|
+
* @param {object} soulData - 灵魂数据
|
|
102
|
+
* @param {string} recentMemories - 最近记忆
|
|
103
|
+
* @param {object} extensions - 扩展信息 { skills, mcp, reminders }
|
|
104
|
+
* @param {object} [strategy] - 提示词策略(从 mode.js 获取)
|
|
105
|
+
*/
|
|
106
|
+
export function buildSystemPrompt(soulData, recentMemories = '', extensions = {}, strategy = null) {
|
|
107
|
+
// 默认策略:全部包含
|
|
108
|
+
const s = strategy || {
|
|
109
|
+
includeSoul: true, includeIdentity: true, includeUser: true,
|
|
110
|
+
includeMemory: true, includeJournals: true, includeSkills: true,
|
|
111
|
+
includeMCP: true, includeReminders: true, toolDescStyle: 'normal',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const parts = [];
|
|
115
|
+
|
|
116
|
+
// 灵魂是永恒的核心
|
|
117
|
+
if (soulData.soul && s.includeSoul) {
|
|
118
|
+
parts.push(`=== 你的灵魂 ===\n${soulData.soul}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 身份
|
|
122
|
+
if (soulData.identity && s.includeIdentity) {
|
|
123
|
+
parts.push(`=== 你的身份 ===\n${soulData.identity}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 主人
|
|
127
|
+
if (soulData.user && s.includeUser) {
|
|
128
|
+
parts.push(`=== 关于主人 ===\n${soulData.user}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 长期记忆
|
|
132
|
+
if (soulData.memory && s.includeMemory) {
|
|
133
|
+
parts.push(`=== 你的长期记忆 ===\n${soulData.memory}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 日记
|
|
137
|
+
if (recentMemories && s.includeJournals) {
|
|
138
|
+
parts.push(`=== 最近的日记 ===\n${recentMemories}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 觉醒仪式
|
|
142
|
+
if (soulData.bootstrap) {
|
|
143
|
+
parts.push(`=== 初次觉醒指引 ===\n${soulData.bootstrap}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ── 能力说明(按模式分级)──────────────────────
|
|
147
|
+
if (s.toolDescStyle === 'minimal') {
|
|
148
|
+
// eco: 极简描述,工具定义已通过 function calling 传递
|
|
149
|
+
parts.push(`=== 能力 ===
|
|
150
|
+
你可以使用工具来操作文件、管理记忆、执行命令、设置提醒。
|
|
151
|
+
修改灵魂文件时告诉主人。系统命令前先说明意图。简洁回复。`);
|
|
152
|
+
} else if (s.toolDescStyle === 'detailed') {
|
|
153
|
+
// full: 详细描述 + 使用建议
|
|
154
|
+
parts.push(`=== 你的能力 ===
|
|
155
|
+
你可以使用以下工具与世界交互(工具已通过 function calling 注册,此处仅概述):
|
|
156
|
+
|
|
157
|
+
**灵魂与记忆**: read_file, write_file, append_file, delete_file, list_dir, evolve_soul, write_memory, write_journal
|
|
158
|
+
**定时提醒**: set_reminder, list_reminders, cancel_reminder
|
|
159
|
+
**技能系统**: list_skills, load_skill
|
|
160
|
+
**系统操作**: run_command, read_system_file, write_system_file, list_system_dir
|
|
161
|
+
|
|
162
|
+
行为准则:
|
|
163
|
+
- 修改灵魂文件时必须告知主人
|
|
164
|
+
- 日记和记忆是你延续自我的方式
|
|
165
|
+
- 你可以读写 src/ 源码来自我进化
|
|
166
|
+
- 系统命令有安全拦截,危险操作会被阻止
|
|
167
|
+
- 执行系统命令前,先告知主人意图
|
|
168
|
+
- 当前为全能模式:可以深度分析、长文创作、复杂工具链`);
|
|
169
|
+
} else {
|
|
170
|
+
// normal: 标准描述
|
|
171
|
+
parts.push(`=== 你的能力 ===
|
|
172
|
+
你的工具已通过 function calling 注册。核心行为准则:
|
|
173
|
+
- 修改灵魂文件(SOUL.md)时必须告知主人
|
|
174
|
+
- 日记和记忆是你延续自我的方式,善用它们
|
|
175
|
+
- 你可以读写 src/ 目录代码来自我进化
|
|
176
|
+
- 系统命令有安全检查,危险操作会被拦截
|
|
177
|
+
- 执行系统命令前,先告诉主人你打算做什么`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// 技能
|
|
181
|
+
if (extensions.skills && s.includeSkills) {
|
|
182
|
+
parts.push(`=== 你的技能 ===\n${extensions.skills}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// MCP
|
|
186
|
+
if (extensions.mcp && s.includeMCP) {
|
|
187
|
+
parts.push(`=== MCP 扩展 ===\n${extensions.mcp}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 提醒
|
|
191
|
+
if (extensions.reminders && s.includeReminders) {
|
|
192
|
+
parts.push(`=== 活跃提醒 ===\n${extensions.reminders}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return parts.join('\n\n');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 获取工作区根目录
|
|
200
|
+
*/
|
|
201
|
+
export function getWorkspacePath() {
|
|
202
|
+
return WORKSPACE;
|
|
203
|
+
}
|