@qcluffy/agent-bootstrap 0.0.1
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/AGENTS.md +294 -0
- package/BOOTSTRAP.md +268 -0
- package/DEMO.md +103 -0
- package/HEARTBEAT.md +444 -0
- package/IDENTITY.md +239 -0
- package/LICENSE +21 -0
- package/MEMORY.md +324 -0
- package/README.md +582 -0
- package/SOUL.md +254 -0
- package/TOOLS.md +317 -0
- package/USER.md +274 -0
- package/bootstrap-system/HOOK.md +31 -0
- package/bootstrap-system/README.md +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/systems/bootstrap.d.ts.map +1 -0
- package/dist/systems/bootstrap.js +272 -0
- package/dist/systems/bootstrap.js.map +1 -0
- package/dist/systems/cognition.d.ts.map +1 -0
- package/dist/systems/cognition.js +254 -0
- package/dist/systems/cognition.js.map +1 -0
- package/dist/systems/emotion.d.ts.map +1 -0
- package/dist/systems/emotion.js +194 -0
- package/dist/systems/emotion.js.map +1 -0
- package/dist/systems/input.d.ts.map +1 -0
- package/dist/systems/input.js +161 -0
- package/dist/systems/input.js.map +1 -0
- package/dist/systems/output.d.ts.map +1 -0
- package/dist/systems/output.js +224 -0
- package/dist/systems/output.js.map +1 -0
- package/dist/test.js +54 -0
- package/emotion-system/README.md +195 -0
- package/hooks/agent-lifecycle/handler.js +109 -0
- package/hooks/auto-bootstrap/handler.js +145 -0
- package/hooks/bootstrap-system/HOOK.md +74 -0
- package/hooks/bootstrap-system/handler.js +220 -0
- package/hooks/cognition-system/HOOK.md +75 -0
- package/hooks/cognition-system/handler.js +186 -0
- package/hooks/emotion-system/HOOK.md +81 -0
- package/hooks/emotion-system/handler.js +239 -0
- package/hooks/heartbeat-system/HOOK.md +63 -0
- package/hooks/heartbeat-system/handler.js +121 -0
- package/hooks/input-system/HOOK.md +79 -0
- package/hooks/input-system/handler.js +181 -0
- package/hooks/memory-system/HOOK.md +43 -0
- package/hooks/memory-system/handler.js +213 -0
- package/hooks/output-system/HOOK.md +79 -0
- package/hooks/output-system/handler.js +195 -0
- package/memory-system/README.md +291 -0
- package/openclaw.plugin.json +51 -0
- package/package.json +30 -0
- package/requirements.txt +11 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: memory-system
|
|
3
|
+
description: "集成记忆系统,自动保存对话和加载历史上下文"
|
|
4
|
+
homepage: https://github.com/openclaw/openclaw
|
|
5
|
+
metadata:
|
|
6
|
+
{
|
|
7
|
+
"openclaw": {
|
|
8
|
+
"emoji": "🔗",
|
|
9
|
+
"events": ["command", "lifecycle", "session"],
|
|
10
|
+
"requires": { "config": ["workspace.dir"] },
|
|
11
|
+
"install": [{ "id": "workspace", "kind": "workspace", "label": "User workspace" }]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Memory System Hook
|
|
17
|
+
|
|
18
|
+
> 自动保存对话到记忆系统,并在会话开始时恢复上下文
|
|
19
|
+
|
|
20
|
+
## 概述
|
|
21
|
+
|
|
22
|
+
这个 Hook 会在以下时机触发:
|
|
23
|
+
|
|
24
|
+
- `session_start`: 会话开始时加载历史记忆
|
|
25
|
+
- `message_received`: 收到用户消息时处理输入
|
|
26
|
+
- `agent_end`: Agent 回复完成后保存对话
|
|
27
|
+
- `session_end`: 会话结束时保存最终状态
|
|
28
|
+
- `/new` 或 `/reset`: 命令时保存会话
|
|
29
|
+
|
|
30
|
+
## 功能
|
|
31
|
+
|
|
32
|
+
1. **会话开始时**:检索相关记忆,恢复上下文
|
|
33
|
+
2. **对话过程中**:实时保存关键对话到记忆系统
|
|
34
|
+
3. **会话结束时**:保存会话摘要,更新关系状态
|
|
35
|
+
|
|
36
|
+
## 配置
|
|
37
|
+
|
|
38
|
+
无需额外配置,Hook 会自动使用 workspace 目录下的 memory-system。
|
|
39
|
+
|
|
40
|
+
## 依赖
|
|
41
|
+
|
|
42
|
+
- Python 3.8+
|
|
43
|
+
- memory-system 模块(在 workspace/templates/ 目录下)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory System Hook Handler
|
|
3
|
+
*
|
|
4
|
+
* 集成 Python memory-system 到 OpenClaw
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs').promises;
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
// 配置
|
|
13
|
+
const CONFIG = {
|
|
14
|
+
memorySystemPath: 'templates/memory-system',
|
|
15
|
+
cliScript: 'cli.py',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 运行 Python memory-system CLI
|
|
20
|
+
*/
|
|
21
|
+
async function runPythonCli(args) {
|
|
22
|
+
const workspaceDir = process.env.OPENCLAW_WORKSPACE ||
|
|
23
|
+
path.join(os.homedir(), '.openclaw', 'workspace');
|
|
24
|
+
const pythonScript = path.join(workspaceDir, CONFIG.memorySystemPath, CONFIG.cliScript);
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
fs.access(pythonScript).then(() => {
|
|
28
|
+
const proc = spawn('python3', [pythonScript, ...args], {
|
|
29
|
+
cwd: workspaceDir,
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
OPENCLAW_WORKSPACE: workspaceDir,
|
|
33
|
+
PYTHONPATH: path.join(workspaceDir, CONFIG.memorySystemPath)
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
let output = '';
|
|
38
|
+
let error = '';
|
|
39
|
+
|
|
40
|
+
proc.stdout.on('data', (data) => { output += data.toString(); });
|
|
41
|
+
proc.stderr.on('data', (data) => { error += data.toString(); });
|
|
42
|
+
|
|
43
|
+
proc.on('close', (code) => {
|
|
44
|
+
try {
|
|
45
|
+
if (output) {
|
|
46
|
+
const result = JSON.parse(output);
|
|
47
|
+
resolve(result);
|
|
48
|
+
} else {
|
|
49
|
+
resolve({ success: false, error: 'No output' });
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
resolve({ success: false, error: error || 'Parse error' });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
proc.on('error', (err) => {
|
|
57
|
+
resolve({ success: false, error: err.message });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
resolve({ success: false, error: 'Memory system not found' });
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 从会话消息中提取文本内容
|
|
68
|
+
*/
|
|
69
|
+
function extractMessageText(message) {
|
|
70
|
+
if (!message || !message.content) return '';
|
|
71
|
+
|
|
72
|
+
if (typeof message.content === 'string') {
|
|
73
|
+
return message.content;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (Array.isArray(message.content)) {
|
|
77
|
+
return message.content
|
|
78
|
+
.filter((c) => c.type === 'text')
|
|
79
|
+
.map((c) => c.text || '')
|
|
80
|
+
.join('');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 生成上下文摘要
|
|
88
|
+
*/
|
|
89
|
+
function formatContextSummary(data) {
|
|
90
|
+
if (!data || !data.success || !data.context) return '';
|
|
91
|
+
|
|
92
|
+
const { context } = data;
|
|
93
|
+
const lines = [];
|
|
94
|
+
|
|
95
|
+
if (context.preferences) {
|
|
96
|
+
const p = context.preferences;
|
|
97
|
+
if (p.userName || p.agentName) {
|
|
98
|
+
lines.push(`【用户信息】名字: ${p.userName || p.agentName || '未知'}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (context.recent_memories && context.recent_memories.length > 0) {
|
|
103
|
+
lines.push('【近期记忆】');
|
|
104
|
+
context.recent_memories.slice(0, 3).forEach((m) => {
|
|
105
|
+
const content = m.content ? m.content.substring(0, 50) : '';
|
|
106
|
+
const date = m.created_at ? m.created_at.substring(0, 10) : '';
|
|
107
|
+
lines.push(` - [${date}] ${content}...`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return lines.length > 0 ? '\n' + lines.join('\n') : '';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 处理 session_start
|
|
116
|
+
*/
|
|
117
|
+
async function handleSessionStart(event) {
|
|
118
|
+
console.log('[memory-system] Session start, loading context...');
|
|
119
|
+
|
|
120
|
+
const context = event.context || {};
|
|
121
|
+
const result = await runPythonCli(['get_context']);
|
|
122
|
+
|
|
123
|
+
if (result.success && result.context) {
|
|
124
|
+
const summary = formatContextSummary(result);
|
|
125
|
+
if (summary) {
|
|
126
|
+
if (!context.prependContext) context.prependContext = '';
|
|
127
|
+
context.prependContext += '\n\n--- 记忆系统 ---\n' + summary;
|
|
128
|
+
console.log('[memory-system] Context injected successfully');
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
console.log('[memory-system] No context to load:', result.error);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
event.context = context;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 处理 agent_end
|
|
139
|
+
*/
|
|
140
|
+
async function handleAgentEnd(event) {
|
|
141
|
+
console.log('[memory-system] Agent end, saving conversation...');
|
|
142
|
+
|
|
143
|
+
const context = event.context || {};
|
|
144
|
+
const messages = context.messages || [];
|
|
145
|
+
|
|
146
|
+
if (messages.length === 0) return;
|
|
147
|
+
|
|
148
|
+
const reversed = [...messages].reverse();
|
|
149
|
+
const lastUserMsg = reversed.find((m) => m.role === 'user');
|
|
150
|
+
const lastAssistantMsg = reversed.find((m) => m.role === 'assistant');
|
|
151
|
+
|
|
152
|
+
if (lastUserMsg) {
|
|
153
|
+
const userText = extractMessageText(lastUserMsg);
|
|
154
|
+
const assistantText = lastAssistantMsg ? extractMessageText(lastAssistantMsg) : '';
|
|
155
|
+
|
|
156
|
+
if (userText && userText.length < 1000 && !userText.startsWith('/')) {
|
|
157
|
+
const content = `用户: ${userText}\n助手: ${assistantText}`;
|
|
158
|
+
const result = await runPythonCli(['save', content, 'episodic', '对话', '0.3']);
|
|
159
|
+
|
|
160
|
+
if (result.success) {
|
|
161
|
+
console.log('[memory-system] Conversation saved:', result.memory_id);
|
|
162
|
+
} else {
|
|
163
|
+
console.log('[memory-system] Save failed:', result.error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 主 handler
|
|
171
|
+
*/
|
|
172
|
+
async function handle(event) {
|
|
173
|
+
const type = event.type || event.event || '';
|
|
174
|
+
const action = event.action || '';
|
|
175
|
+
|
|
176
|
+
console.log(`[memory-system] Event: ${type}/${action}`);
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
if (type === 'command') {
|
|
180
|
+
if (action === 'new' || action === 'reset') {
|
|
181
|
+
await handleAgentEnd(event);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else if (type === 'lifecycle' || type === 'lifecycle:end') {
|
|
185
|
+
if (action === 'end' || action === '') {
|
|
186
|
+
await handleAgentEnd(event);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (type === 'session' || type === 'session:start') {
|
|
190
|
+
if (action === 'start' || action === '') {
|
|
191
|
+
await handleSessionStart(event);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (type === 'message' || type === 'message:received') {
|
|
195
|
+
await handleMessageReceived(event);
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error('[memory-system] Handler error:', error.message);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 默认导出
|
|
203
|
+
module.exports = handle;
|
|
204
|
+
module.exports.handle = handle;
|
|
205
|
+
module.exports.metadata = {
|
|
206
|
+
name: 'memory-system',
|
|
207
|
+
description: '集成记忆系统,自动保存对话和加载历史上下文',
|
|
208
|
+
events: ['command', 'lifecycle', 'session'],
|
|
209
|
+
version: '1.0.0',
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// 也导出 default 兼容
|
|
213
|
+
module.exports.default = handle;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: output-system
|
|
3
|
+
description: "输出执行系统,语言生成、行动执行、反馈收集、多模态输出"
|
|
4
|
+
homepage: https://github.com/openclaw/openclaw
|
|
5
|
+
metadata:
|
|
6
|
+
{
|
|
7
|
+
"openclaw": {
|
|
8
|
+
"emoji": "📤",
|
|
9
|
+
"events": ["agent", "lifecycle", "command"],
|
|
10
|
+
"requires": { "config": ["workspace.dir"] },
|
|
11
|
+
"install": [{ "id": "workspace", "kind": "workspace", "label": "User workspace" }]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Output System Hook
|
|
17
|
+
|
|
18
|
+
> 输出执行的"嘴巴"
|
|
19
|
+
|
|
20
|
+
## 概述
|
|
21
|
+
|
|
22
|
+
输出系统负责生成回复、执行行动、收集反馈。
|
|
23
|
+
|
|
24
|
+
## 功能
|
|
25
|
+
|
|
26
|
+
### 1. 回复生成器
|
|
27
|
+
不同风格的回复模板:
|
|
28
|
+
- direct: 直接简洁
|
|
29
|
+
- friendly: 友好亲切
|
|
30
|
+
- formal: 正式规范
|
|
31
|
+
- casual: 轻松随意
|
|
32
|
+
- technical: 技术专业
|
|
33
|
+
|
|
34
|
+
### 2. 行动执行器
|
|
35
|
+
执行各种行动:
|
|
36
|
+
- file.write / file.read / file.delete
|
|
37
|
+
- shell.run
|
|
38
|
+
- http.request
|
|
39
|
+
- search.web
|
|
40
|
+
|
|
41
|
+
### 3. 反馈收集器
|
|
42
|
+
- 确认问题
|
|
43
|
+
- 澄清问题
|
|
44
|
+
- 信息缺失提示
|
|
45
|
+
|
|
46
|
+
### 4. 格式化器
|
|
47
|
+
- 代码块
|
|
48
|
+
- 列表
|
|
49
|
+
- 表格
|
|
50
|
+
|
|
51
|
+
## 使用方法
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 生成回复
|
|
55
|
+
python3 templates/output-system/main.py --style friendly response "任务完成"
|
|
56
|
+
|
|
57
|
+
# 执行行动
|
|
58
|
+
python3 templates/output-system/main.py action file.read '{"path": "/tmp/test.txt"}'
|
|
59
|
+
|
|
60
|
+
# 格式化列表
|
|
61
|
+
python3 templates/output-system/main.py list "a,b,c" --numbered
|
|
62
|
+
|
|
63
|
+
# 查看状态
|
|
64
|
+
python3 templates/output-system/main.py status
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 工作流程
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
INPUT(意图识别) → COGNITION(推理规划) → OUTPUT(执行输出)
|
|
71
|
+
↓
|
|
72
|
+
回复生成 + 行动执行
|
|
73
|
+
↓
|
|
74
|
+
附加情感状态显示
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 依赖
|
|
78
|
+
|
|
79
|
+
- Python 3.8+
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output System Hook Handler
|
|
3
|
+
*
|
|
4
|
+
* 集成 Python output-system 到 OpenClaw
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs').promises;
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
// 配置
|
|
13
|
+
const CONFIG = {
|
|
14
|
+
outputSystemPath: 'templates/output-system',
|
|
15
|
+
mainScript: 'main.py',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 运行 Python output-system CLI
|
|
20
|
+
*/
|
|
21
|
+
async function runPythonCli(args = []) {
|
|
22
|
+
const workspaceDir = process.env.OPENCLAW_WORKSPACE ||
|
|
23
|
+
path.join(os.homedir(), '.openclaw', 'workspace');
|
|
24
|
+
const pythonScript = path.join(workspaceDir, CONFIG.outputSystemPath, CONFIG.mainScript);
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
fs.access(pythonScript).then(() => {
|
|
28
|
+
const proc = spawn('python3', [pythonScript, ...args], {
|
|
29
|
+
cwd: workspaceDir,
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
OPENCLAW_WORKSPACE: workspaceDir,
|
|
33
|
+
PYTHONPATH: path.join(workspaceDir, CONFIG.outputSystemPath)
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
let output = '';
|
|
38
|
+
let error = '';
|
|
39
|
+
|
|
40
|
+
proc.stdout.on('data', (data) => { output += data.toString(); });
|
|
41
|
+
proc.stderr.on('data', (data) => { error += data.toString(); });
|
|
42
|
+
|
|
43
|
+
proc.on('close', (code) => {
|
|
44
|
+
resolve({ success: code === 0, output, error });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
proc.on('error', (err) => {
|
|
48
|
+
resolve({ success: false, error: err.message });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
}).catch(() => {
|
|
52
|
+
resolve({ success: false, error: 'Output system not found' });
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 格式化输出
|
|
59
|
+
*/
|
|
60
|
+
function formatOutput(content, context) {
|
|
61
|
+
const style = context?.replyStrategy?.style || 'friendly';
|
|
62
|
+
const format = context?.replyStrategy?.format || 'text';
|
|
63
|
+
|
|
64
|
+
// 附加情感状态
|
|
65
|
+
let emotionLine = '';
|
|
66
|
+
if (context?.emotionState) {
|
|
67
|
+
const e = context.emotionState;
|
|
68
|
+
emotionLine = `\n${e.mood_emoji || '🧐'} Lv.${e.level} | ⚡${Math.round(e.energy*100)}% | 💕${Math.round(e.connection*100)}%`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return content + emotionLine;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 处理 agent_start - 准备输出
|
|
76
|
+
*/
|
|
77
|
+
async function handleAgentStart(event) {
|
|
78
|
+
console.log('[output-system] Preparing output...');
|
|
79
|
+
|
|
80
|
+
const context = event.context || {};
|
|
81
|
+
|
|
82
|
+
// 获取回复策略
|
|
83
|
+
const strategy = context.replyStrategy || {};
|
|
84
|
+
|
|
85
|
+
// 准备输出格式
|
|
86
|
+
context.outputConfig = {
|
|
87
|
+
style: strategy.style || 'friendly',
|
|
88
|
+
format: strategy.format || 'text',
|
|
89
|
+
includeEmotion: true,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return event;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 处理 agent_end - 生成输出
|
|
97
|
+
*/
|
|
98
|
+
async function handleAgentEnd(event) {
|
|
99
|
+
console.log('[output-system] Generating output...');
|
|
100
|
+
|
|
101
|
+
const context = event.context || {};
|
|
102
|
+
const messages = context.messages || [];
|
|
103
|
+
|
|
104
|
+
// 获取最后助手回复
|
|
105
|
+
const reversed = [...messages].reverse();
|
|
106
|
+
const lastAssistantMsg = reversed.find((m) => m.role === 'assistant');
|
|
107
|
+
|
|
108
|
+
if (lastAssistantMsg) {
|
|
109
|
+
// 获取内容
|
|
110
|
+
let content = '';
|
|
111
|
+
if (typeof lastAssistantMsg.content === 'string') {
|
|
112
|
+
content = lastAssistantMsg.content;
|
|
113
|
+
} else if (Array.isArray(lastAssistantMsg.content)) {
|
|
114
|
+
content = lastAssistantMsg.content
|
|
115
|
+
.filter((c) => c.type === 'text')
|
|
116
|
+
.map((c) => c.text || '')
|
|
117
|
+
.join('');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 格式化输出(附加情感状态)
|
|
121
|
+
const formattedContent = formatOutput(content, context);
|
|
122
|
+
|
|
123
|
+
// 更新消息
|
|
124
|
+
lastAssistantMsg.content = formattedContent;
|
|
125
|
+
|
|
126
|
+
console.log('[output-system] Output formatted with emotion state');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return event;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 执行行动
|
|
134
|
+
*/
|
|
135
|
+
async function handleExecuteAction(event) {
|
|
136
|
+
const action = event.action;
|
|
137
|
+
const params = event.params || {};
|
|
138
|
+
|
|
139
|
+
if (action) {
|
|
140
|
+
const result = await runPythonCli([
|
|
141
|
+
'action',
|
|
142
|
+
action,
|
|
143
|
+
JSON.stringify(params)
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
event.actionResult = result;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return event;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 主 handler
|
|
154
|
+
*/
|
|
155
|
+
async function handle(event) {
|
|
156
|
+
const type = event.type || event.event || '';
|
|
157
|
+
const action = event.action || '';
|
|
158
|
+
|
|
159
|
+
console.log(`[output-system] Event: ${type}/${action}`);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
if (type === 'agent' || type === 'agent_start') {
|
|
163
|
+
await handleAgentStart(event);
|
|
164
|
+
}
|
|
165
|
+
else if (type === 'lifecycle' || type === 'lifecycle:end' || type === 'agent_end') {
|
|
166
|
+
await handleAgentEnd(event);
|
|
167
|
+
}
|
|
168
|
+
else if (type === 'command') {
|
|
169
|
+
if (action === 'execute' || action === 'run') {
|
|
170
|
+
await handleExecuteAction(event);
|
|
171
|
+
}
|
|
172
|
+
else if (action === 'output' || action === 'status') {
|
|
173
|
+
const result = await runPythonCli(['status', '--json']);
|
|
174
|
+
if (result.success) {
|
|
175
|
+
event.response = result.output;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.error('[output-system] Handler error:', error.message);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return event;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports = handle;
|
|
187
|
+
module.exports.handle = handle;
|
|
188
|
+
module.exports.metadata = {
|
|
189
|
+
name: 'output-system',
|
|
190
|
+
description: '输出执行系统,语言生成、行动执行、反馈收集、多模态输出',
|
|
191
|
+
events: ['agent', 'lifecycle', 'command'],
|
|
192
|
+
version: '1.0.0',
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
module.exports.default = handle;
|