mio-agent-runtime 0.5.3 → 0.5.5
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 +296 -86
- package/package.json +1 -1
- package/server/mio-intelligence-mcp/index.js +86 -80
package/README.md
CHANGED
|
@@ -1,102 +1,312 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Mio Agent Runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> 让所有 AI Agent 共享记忆、观察行为、积累经验——安装一次,无感增强。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Mio 是 **Agent Control Plane**:不替代任何 Agent,而是为它们提供统一的智能层。
|
|
6
|
+
安装到 Codex、OpenCode、Hermes、WorkBuddy 后,所有 Agent 的决策、错误和结果自动进入共享记忆,跨 Agent 复用经验。
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
```
|
|
9
|
+
┌─────────────────────────────────────────────┐
|
|
10
|
+
│ 用户的日常工具 │
|
|
11
|
+
│ Codex · OpenCode · Hermes · WorkBuddy │
|
|
12
|
+
└──────────────────┬──────────────────────────┘
|
|
13
|
+
│ MCP
|
|
14
|
+
┌─────────┴─────────┐
|
|
15
|
+
│ Mio Intelligence │
|
|
16
|
+
│ │
|
|
17
|
+
│ Memory │ 决策、上下文、问题记录
|
|
18
|
+
│ Observer │ 被动观察 Agent 行为
|
|
19
|
+
│ Policy │ 高风险操作拦截
|
|
20
|
+
│ Experience │ 跨 Agent 经验复用
|
|
21
|
+
│ Ideas │ 记忆驱动的创意生成
|
|
22
|
+
│ Evolution │ 生态级优化建议
|
|
23
|
+
└───────────────────┘
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 快速开始
|
|
8
29
|
|
|
9
30
|
```bash
|
|
31
|
+
# 1. 全局安装
|
|
10
32
|
npm install -g mio-agent-runtime
|
|
33
|
+
|
|
34
|
+
# 2. 初始化
|
|
35
|
+
mio init
|
|
36
|
+
|
|
37
|
+
# 3. 接入你使用的 Agent(可多选)
|
|
38
|
+
mio install codex # Codex Desktop / CLI
|
|
39
|
+
mio install opencode # OpenCode
|
|
40
|
+
mio install hermes # Hermes (Nous)
|
|
41
|
+
mio install workbuddy # WorkBuddy
|
|
42
|
+
|
|
43
|
+
# 4. 查看状态
|
|
44
|
+
mio status
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
安装完成后**重启对应 Agent**,Mio 即自动生效。无需改变任何使用习惯。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 核心能力
|
|
52
|
+
|
|
53
|
+
### 记忆 — `mio.memory.*`
|
|
54
|
+
|
|
55
|
+
| 工具 | 功能 |
|
|
56
|
+
|------|------|
|
|
57
|
+
| `mio.memory.record` | 记录决策、上下文、问题、笔记 |
|
|
58
|
+
| `mio.memory.query` | 按关键词/标签/类型检索历史记忆 |
|
|
59
|
+
| `mio.memory.analyze` | 分析记忆质量:类型分布、重复检测、低质量记录 |
|
|
60
|
+
| `mio.memory.archive` | 归档不再需要的记忆(可恢复) |
|
|
61
|
+
| `mio.memory.migrate` | 在项目级和全局级之间迁移记忆 |
|
|
62
|
+
|
|
63
|
+
### 观察 — `mio.observer.*`
|
|
64
|
+
|
|
65
|
+
| 工具 | 功能 |
|
|
66
|
+
|------|------|
|
|
67
|
+
| `mio.observer.ingest` | 上报 Agent 事件:工具调用、错误、重试、任务结果 |
|
|
68
|
+
| `mio.observer.subscribe` | 订阅特定项目/事件类型的实时通知 |
|
|
69
|
+
| `mio.observer.digest` | 拉取自上次以来的新事件 |
|
|
70
|
+
|
|
71
|
+
### 策略 — `mio.policy.*`
|
|
72
|
+
|
|
73
|
+
| 工具 | 功能 |
|
|
74
|
+
|------|------|
|
|
75
|
+
| `mio.policy.check` | 执行高风险操作前检查历史失败率和风险等级 |
|
|
76
|
+
|
|
77
|
+
### 经验 — `mio.experience.*`
|
|
78
|
+
|
|
79
|
+
| 工具 | 功能 |
|
|
80
|
+
|------|------|
|
|
81
|
+
| `mio.experience.reuse` | 记录一次跨 Agent 经验复用(来源→目标→是否改善结果) |
|
|
82
|
+
| `mio.experience.confirm` | 人工确认自动声明的复用记录 |
|
|
83
|
+
| `mio.experience.list` | 查询复用证据,按状态/Agent 过滤 |
|
|
84
|
+
|
|
85
|
+
### 任务 — `mio.task.*`
|
|
86
|
+
|
|
87
|
+
| 工具 | 功能 |
|
|
88
|
+
|------|------|
|
|
89
|
+
| `mio.task.route` | 根据历史经验为任务推荐最佳 Agent |
|
|
90
|
+
| `mio.task.record_outcome` | 记录任务执行结果(成功/失败/中止) |
|
|
91
|
+
|
|
92
|
+
### Agent — `mio.agent.*`
|
|
93
|
+
|
|
94
|
+
| 工具 | 功能 |
|
|
95
|
+
|------|------|
|
|
96
|
+
| `mio.agent.register` | 注册 Agent 元数据(名称、能力、宿主) |
|
|
97
|
+
| `mio.agent.list` | 列出已注册的 Agent |
|
|
98
|
+
| `mio.agent.report` | 查询指定 Agent 的能力报告和行为摘要 |
|
|
99
|
+
|
|
100
|
+
### 创意 — `mio.idea.*`
|
|
101
|
+
|
|
102
|
+
| 工具 | 功能 |
|
|
103
|
+
|------|------|
|
|
104
|
+
| `mio.idea.generate` | 基于记忆库,用 SCAMPER / 类比 / 第一性原理 / 随机刺激 / 约束反转 五种策略生成创意 |
|
|
105
|
+
| `mio.idea.list` | 查询已保存的创意,按目标/策略/时间段过滤 |
|
|
106
|
+
|
|
107
|
+
### 进化 — `mio.evolution.*`
|
|
108
|
+
|
|
109
|
+
| 工具 | 功能 |
|
|
110
|
+
|------|------|
|
|
111
|
+
| `mio.evolution.report` | 生成生态系统分析报告 |
|
|
112
|
+
| `mio.evolution.suggest` | 输出可执行的优化建议(带 nextAction 和 impact) |
|
|
113
|
+
|
|
114
|
+
### 验证 — `mio.phase0.*`
|
|
115
|
+
|
|
116
|
+
| 工具 | 功能 |
|
|
117
|
+
|------|------|
|
|
118
|
+
| `mio.phase0.report` | 生成 Phase 0 跨 Agent 验证报告(JSON / Markdown) |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 支持的 Agent 宿主
|
|
123
|
+
|
|
124
|
+
### Codex (OpenAI)
|
|
125
|
+
|
|
126
|
+
- **接入方式**:修改 `~/.codex/config.json`,注入 `mcpServers.mio`
|
|
127
|
+
- **工作流增强**:AGENTS.md 规则注入 → Agent 自动在决策前后调用 Mio
|
|
128
|
+
- **被动观察**:不依赖,Codex 默认主动调用 MCP 工具
|
|
129
|
+
|
|
130
|
+
### OpenCode
|
|
131
|
+
|
|
132
|
+
- **接入方式**:修改 `~/.config/opencode/opencode.json`(MCP)+ `~/.config/opencode/AGENTS.md`(规则)
|
|
133
|
+
- **被动观察**:`mio observe` 通过 `opencode db` 增量读取会话数据库,自动提取任务结果和工具错误,写回 `<workspace>/AGENTS.md` 的 `MIO_CONTEXT` 块
|
|
134
|
+
- **增量机制**:按 `part` 表的 `rowid` 游标,只传输 `text` / `tool` 类型,首次只回填 24h 内数据
|
|
135
|
+
|
|
136
|
+
### Hermes (Nous)
|
|
137
|
+
|
|
138
|
+
- **接入方式**:`hermes mcp add mio-intelligence --command node --args <server>`
|
|
139
|
+
- **被动观察**:增量读取 `<LocalAppData>/hermes/state.db`(`messages.id` 自增游标),无需调用 hermes CLI
|
|
140
|
+
- **写回策略**:仅当会话发生在真实 git 仓库时写回 `AGENTS.md`,避免污染用户主目录
|
|
141
|
+
|
|
142
|
+
### WorkBuddy
|
|
143
|
+
|
|
144
|
+
- **接入方式**:写入 `~/.workbuddy/mcp.json` + `~/.workbuddy/mcp-approvals.json`
|
|
145
|
+
- **规则注入**:写入 `~/.workbuddy/CODEBUDDY.md`(用户级)+ `<workspace>/AGENTS.md`(项目级)
|
|
146
|
+
- **被动观察**:监听 `~/.workbuddy/projects/**/*.jsonl`,自动提取任务结果,写回 `<workspace>/.workbuddy/memory/YYYY-MM-DD.md`
|
|
147
|
+
|
|
148
|
+
> 所有宿主的被动观察器共享同一套 schema,数据统一存入 `MIO_HOME`,实现跨 Agent 经验复用。
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 被动观察器
|
|
153
|
+
|
|
154
|
+
被动观察器是 Mio 的核心差异化能力:**不依赖 Agent 主动调用,自动采集行为数据。**
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
Agent 会话日志
|
|
158
|
+
↓
|
|
159
|
+
mio observe
|
|
160
|
+
↓
|
|
161
|
+
┌──────────────────┐
|
|
162
|
+
│ 提取 task_outcome │
|
|
163
|
+
│ 提取 tool error │
|
|
164
|
+
│ 生成任务摘要 │
|
|
165
|
+
└────────┬─────────┘
|
|
166
|
+
↓
|
|
167
|
+
MIO_HOME/traces.jsonl ← 统一行为数据
|
|
168
|
+
MIO_HOME/memory.jsonl ← 自动记忆
|
|
169
|
+
↓
|
|
170
|
+
写回 Agent 原生记忆文件 ← 单 Agent 闭环
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 后台守护进程
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
mio observe --start # 启动后台守护
|
|
177
|
+
mio observe --stop # 停止
|
|
178
|
+
mio observe --status # 查看状态
|
|
179
|
+
mio observe --once # 执行一次采集周期
|
|
180
|
+
mio observe # 前台持续监听(Ctrl+C 停止)
|
|
11
181
|
```
|
|
12
182
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
183
|
+
### 增量与去重
|
|
184
|
+
|
|
185
|
+
- 已处理的文件偏移记录在 `MIO_HOME/observe-state.json`,不会重复写入
|
|
186
|
+
- 只回填最近 24h 内更新的会话,避免历史灌入
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## CLI 命令
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
mio init 初始化 MIO_HOME 目录结构
|
|
194
|
+
mio mcp 启动 MCP Server(stdio 模式,供 Agent 调用)
|
|
195
|
+
mio install <host> 接入指定 Agent(codex|opencode|workbuddy|hermes)
|
|
196
|
+
mio status 显示运行时状态和所有 Adapter 状态
|
|
197
|
+
mio agents 列出已安装的 Agent
|
|
198
|
+
mio observe 观察器管理(见上方)
|
|
199
|
+
mio --json status 机器可读的状态输出
|
|
200
|
+
mio --json agents 机器可读的 Agent 列表
|
|
201
|
+
```
|
|
16
202
|
|
|
17
|
-
|
|
203
|
+
### `mio install` 做了什么
|
|
18
204
|
|
|
19
205
|
```text
|
|
20
|
-
mio
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mio observe --start|--stop|--status|--once Manage the background observer daemon
|
|
27
|
-
mio --json status Machine-readable status
|
|
28
|
-
mio --json agents Machine-readable agents
|
|
206
|
+
mio install codex
|
|
207
|
+
│
|
|
208
|
+
├── 修改 ~/.codex/config.json → 添加 mio MCP Server
|
|
209
|
+
├── 注入 AGENTS.md 规则 → Agent 自动调用 Mio
|
|
210
|
+
├── 执行一次历史回填 → 被动观察已有会话
|
|
211
|
+
└── 启动后台观察器 → 持续采集
|
|
29
212
|
```
|
|
30
213
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
calls Mio memory/observer/policy automatically. If OpenCode is already
|
|
37
|
-
running, restart it once so it reloads both files. `mio observe` also
|
|
38
|
-
passively tails the OpenCode session database (`opencode db`) without
|
|
39
|
-
requiring the model to call Mio tools.
|
|
40
|
-
- Hermes uses `hermes mcp add mio-intelligence --command node --args <server>`
|
|
41
|
-
to register the Mio MCP server. Hermes has native memory and reads
|
|
42
|
-
AGENTS.md Context Files, so retrieval works without Mio rule injection.
|
|
43
|
-
- WorkBuddy uses `~/.workbuddy/mcp.json` and requires each custom MCP server to
|
|
44
|
-
be approved in `~/.workbuddy/mcp-approvals.json`. `mio install workbuddy`
|
|
45
|
-
writes both files and injects Mio usage rules into
|
|
46
|
-
`~/.workbuddy/CODEBUDDY.md` (user-level memory rules, auto-loaded by
|
|
47
|
-
WorkBuddy into every session; the CLI hardcodes the CodeBuddy product name, so the file is CODEBUDDY.md not WORKBUDDY.md) plus `<workspace>/AGENTS.md` (project-level).
|
|
48
|
-
If WorkBuddy is already running, restart it once so it reloads the approval
|
|
49
|
-
and memory rule files.
|
|
50
|
-
|
|
51
|
-
## Passive observer (`mio observe`)
|
|
52
|
-
|
|
53
|
-
WorkBuddy 的默认模型不一定会主动调用 Mio MCP 工具,即使规则已注入
|
|
54
|
-
(`CODEBUDDY.md` / `AGENTS.md`)。`mio observe` 是一个不依赖模型自觉的
|
|
55
|
-
兜底:它持续监听 `~/.workbuddy/projects/**/*.jsonl` 会话记录,把每个任务的
|
|
56
|
-
结果(`task_outcome`)、工具调用错误(`error`)以及完成任务的摘要自动写入
|
|
57
|
-
`MIO_HOME/traces.jsonl` 和 `MIO_HOME/memory.jsonl`(与 MCP 服务同一套
|
|
58
|
-
schema,`source=workbuddy-observer`)。
|
|
59
|
-
|
|
60
|
-
- `mio install <host>` 会自动执行一次回填并启动后台观察器。
|
|
61
|
-
|
|
62
|
-
- 除了写入 `MIO_HOME`,观察器还会把任务摘要**写回 WorkBuddy 自己的记忆文件**
|
|
63
|
-
(`<workspace>/.workbuddy/memory/YYYY-MM-DD.md`,标为 `## Mio 自动摘要`)。
|
|
64
|
-
WorkBuddy 的系统提示要求模型每次会话维护并阅读这些文件,所以下一次会话
|
|
65
|
-
WorkBuddy 会**被动取到** Mio 记录的内容——单 Agent 的「存 + 取」闭环不依赖
|
|
66
|
-
模型调用 Mio 工具。
|
|
67
|
-
- 已处理的文件偏移记录在 `MIO_HOME/observe-state.json`,不会重复写入。
|
|
68
|
-
- 只回填最近 24h 内更新的会话,避免把历史记录灌入记忆库。
|
|
69
|
-
|
|
70
|
-
OpenCode 会话不依赖模型自觉:`mio observe` 通过 `opencode db` 增量读取
|
|
71
|
-
`~/.local/share/opencode/opencode.db`(Windows 下该文件被 OpenCode 独占锁定,
|
|
72
|
-
必须经 opencode 自带 CLI 读取),按 `part` 表的 rowid 做增量游标,只传输
|
|
73
|
-
`text`/`tool` 两种 part,把每个用户回合的 `task_outcome` 与工具错误写入
|
|
74
|
-
`MIO_HOME/traces.jsonl` / `memory.jsonl`(`source=opencode-observer`),并同样
|
|
75
|
-
把摘要写回 `<workspace>/AGENTS.md` 的 `MIO_CONTEXT` 块,供 OpenCode 下一会话
|
|
76
|
-
被动取用。首次启动只回填最近 24h 的 part,避免历史会话灌入记忆库。
|
|
77
|
-
|
|
78
|
-
Hermes(Nous hermes-agent)同理:`mio observe` 以只读方式增量读取
|
|
79
|
-
`<LocalAppData>/hermes/state.db`(`messages.id` 自增游标,无需调用 hermes CLI),
|
|
80
|
-
把每个用户回合的 `task_outcome` 写入 `MIO_HOME`(`source=hermes-observer`)。
|
|
81
|
-
Hermes 本身有原生记忆,Mio 只负责让 Hermes 经验进入跨 Agent 生态;仅当会话
|
|
82
|
-
发生在真实 git 仓库时才写回该仓库的 `AGENTS.md`,避免污染用户主目录。
|
|
83
|
-
|
|
84
|
-
## MIO_HOME
|
|
85
|
-
|
|
86
|
-
默认 `~/.mio-intelligence`,可通过环境变量 `MIO_HOME` 覆盖。
|
|
87
|
-
|
|
88
|
-
## Package layout
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## MIO_HOME 目录结构
|
|
217
|
+
|
|
218
|
+
默认 `~/.mio-intelligence`,可通过 `MIO_HOME` 环境变量覆盖。
|
|
89
219
|
|
|
90
220
|
```text
|
|
91
|
-
|
|
92
|
-
├──
|
|
93
|
-
├──
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
├──
|
|
98
|
-
|
|
99
|
-
├──
|
|
100
|
-
|
|
101
|
-
└── package.json
|
|
221
|
+
~/.mio-intelligence/
|
|
222
|
+
├── config.json 运行时配置(已安装的 Agent 列表)
|
|
223
|
+
├── memory.jsonl 记忆存储(决策、上下文、问题)
|
|
224
|
+
├── traces.jsonl 行为追踪(任务结果、工具调用)
|
|
225
|
+
├── experience-reuse.jsonl 跨 Agent 经验复用记录
|
|
226
|
+
├── ideas.jsonl 生成的创意想法
|
|
227
|
+
├── suggestions.jsonl 进化建议
|
|
228
|
+
├── observe-state.json 观察器增量游标
|
|
229
|
+
├── observe.pid 后台观察器进程 ID
|
|
230
|
+
└── logs/ 运行日志
|
|
102
231
|
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 架构定位
|
|
236
|
+
|
|
237
|
+
Mio 不是又一个 AI 助手,而是 **Agent 的控制平面**。
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
传统模式(每个 Agent 独立):
|
|
241
|
+
|
|
242
|
+
Codex OpenCode Hermes WorkBuddy
|
|
243
|
+
(各自记忆) (各自记忆) (各自记忆) (各自记忆)
|
|
244
|
+
|
|
245
|
+
Mio 模式(统一智能层):
|
|
246
|
+
|
|
247
|
+
Codex OpenCode Hermes WorkBuddy
|
|
248
|
+
\ | / /
|
|
249
|
+
└───────┴────────┴──────────┘
|
|
250
|
+
|
|
|
251
|
+
Mio Intelligence
|
|
252
|
+
┌──────┴──────┐
|
|
253
|
+
│ Memory │ 跨 Agent 共享
|
|
254
|
+
│ Observer │ 行为自动采集
|
|
255
|
+
│ Policy │ 风险统一管理
|
|
256
|
+
│ Experience │ 复用证据链
|
|
257
|
+
│ Ideas │ 记忆驱动创意
|
|
258
|
+
│ Evolution │ 生态优化
|
|
259
|
+
└─────────────┘
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 核心差异
|
|
263
|
+
|
|
264
|
+
| 维度 | Agent Memory | Mio Control Plane |
|
|
265
|
+
|------|-------------|-------------------|
|
|
266
|
+
| 作用域 | 单 Agent | 多 Agent 生态 |
|
|
267
|
+
| 数据采集 | 依赖 Agent 主动调用 | 被动观察 + 主动调用 |
|
|
268
|
+
| 经验流动 | 无 | 跨 Agent 复用 + 证据验证 |
|
|
269
|
+
| 风险管理 | 无 | 统一策略检查 |
|
|
270
|
+
| 优化对象 | 单个 Agent 的记忆 | 整个 Agent 生态的质量和效率 |
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## 版本要求
|
|
275
|
+
|
|
276
|
+
| 版本 | 能力 |
|
|
277
|
+
|------|------|
|
|
278
|
+
| `< 0.3.6` | 仅主动 MCP 规则注入 |
|
|
279
|
+
| `≥ 0.3.6` | 被动观察 + 无感存取 |
|
|
280
|
+
| `≥ 0.5.0` | 创意生成 + 进化建议 |
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
npm install -g mio-agent-runtime@latest
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 开发
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
git clone https://github.com/your-org/akemi-mio.git
|
|
292
|
+
cd akemi-mio
|
|
293
|
+
node --check server/mio-intelligence-mcp/index.js # 语法检查
|
|
294
|
+
npm run check # 全量检查
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 发布流程
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# 1. 编辑 server/mio-intelligence-mcp/index.js
|
|
301
|
+
# 2. 复制到 npm 包目录
|
|
302
|
+
cp server/mio-intelligence-mcp/index.js tmp/mio-agent-runtime/package/server/mio-intelligence-mcp/index.js
|
|
303
|
+
# 3. 更新版本号
|
|
304
|
+
# 4. 发布
|
|
305
|
+
cd tmp/mio-agent-runtime/package && npm publish
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## License
|
|
311
|
+
|
|
312
|
+
MIT
|
package/package.json
CHANGED
|
@@ -20,7 +20,8 @@ const queryPath = path.join(dataDir, 'queries.jsonl')
|
|
|
20
20
|
const agentsPath = path.join(dataDir, 'agents.jsonl')
|
|
21
21
|
const subscriptionPath = path.join(dataDir, 'subscriptions.jsonl')
|
|
22
22
|
const digestStatePath = path.join(dataDir, 'digest_state.json')
|
|
23
|
-
const ideasPath = path.join(dataDir, 'ideas.jsonl')
|
|
23
|
+
const ideasPath = path.join(dataDir, 'ideas.jsonl')
|
|
24
|
+
const suggestionsPath = path.join(dataDir, 'suggestions.jsonl')
|
|
24
25
|
fs.mkdirSync(dataDir, { recursive: true })
|
|
25
26
|
|
|
26
27
|
const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
|
|
@@ -1649,9 +1650,39 @@ const TOOLS = [
|
|
|
1649
1650
|
}
|
|
1650
1651
|
},
|
|
1651
1652
|
},
|
|
1652
|
-
|
|
1653
|
+
{
|
|
1654
|
+
name: 'mio.evolution.suggest',
|
|
1655
|
+
description: 'Analyze ecosystem data and produce prioritized improvement suggestions with next actions and expected impact.',
|
|
1656
|
+
inputSchema: {
|
|
1657
|
+
type: 'object',
|
|
1658
|
+
properties: {
|
|
1659
|
+
project: { type: 'string', description: 'Project name filter. Defaults to current repository.' }
|
|
1660
|
+
}
|
|
1661
|
+
},
|
|
1662
|
+
},
|
|
1653
1663
|
]
|
|
1654
1664
|
|
|
1665
|
+
function listIdeas(args = {}) {
|
|
1666
|
+
if (!fs.existsSync(ideasPath)) return { ideas: [], count: 0, total: 0 }
|
|
1667
|
+
const now = Date.now()
|
|
1668
|
+
const period = String(args.period || 'all').trim()
|
|
1669
|
+
const periodMs = period === '24h' ? 86400000 : period === '7d' ? 604800000 : period === '30d' ? 2592000000 : Infinity
|
|
1670
|
+
const cutoff = periodMs === Infinity ? 0 : now - periodMs
|
|
1671
|
+
const goalFilter = args.goal ? String(args.goal).toLowerCase() : null
|
|
1672
|
+
const strategyFilter = args.strategy ? String(args.strategy).trim().toLowerCase() : null
|
|
1673
|
+
const limit = Math.min(Math.max(Number(args.limit) || 10, 1), 50)
|
|
1674
|
+
const all = fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(line => {
|
|
1675
|
+
try { return JSON.parse(line) } catch (_) { return null }
|
|
1676
|
+
}).filter(Boolean)
|
|
1677
|
+
const filtered = all.filter(idea => {
|
|
1678
|
+
if (cutoff && new Date(idea.generatedAt).getTime() < cutoff) return false
|
|
1679
|
+
if (goalFilter && !String(idea.goal || '').toLowerCase().includes(goalFilter)) return false
|
|
1680
|
+
if (strategyFilter && String(idea.provenance?.strategy || '').toLowerCase() !== strategyFilter) return false
|
|
1681
|
+
return true
|
|
1682
|
+
})
|
|
1683
|
+
return { ideas: filtered.slice(-limit), count: filtered.length, total: all.length }
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1655
1686
|
async function callTool(name, args = {}) {
|
|
1656
1687
|
switch (name) {
|
|
1657
1688
|
case 'mio.memory.query':
|
|
@@ -1696,6 +1727,8 @@ async function callTool(name, args = {}) {
|
|
|
1696
1727
|
return handleIdeaGenerate(args)
|
|
1697
1728
|
case 'mio.idea.list':
|
|
1698
1729
|
return listIdeas(args)
|
|
1730
|
+
case 'mio.evolution.suggest':
|
|
1731
|
+
return evolutionSuggest(args)
|
|
1699
1732
|
default:
|
|
1700
1733
|
throw new Error(`Unknown tool: ${name}`)
|
|
1701
1734
|
}
|
|
@@ -2016,91 +2049,64 @@ function recordTaskOutcome(args = {}) {
|
|
|
2016
2049
|
}
|
|
2017
2050
|
|
|
2018
2051
|
|
|
2019
|
-
function
|
|
2020
|
-
|
|
2052
|
+
function evolutionSuggest(args = {}) {
|
|
2053
|
+
const project = args.project || projectName()
|
|
2021
2054
|
const now = Date.now()
|
|
2022
|
-
const
|
|
2023
|
-
const
|
|
2024
|
-
const
|
|
2025
|
-
const
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
const
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
const
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2055
|
+
const memories = readJsonl(memoryPath)
|
|
2056
|
+
const traces = readJsonl(tracePath)
|
|
2057
|
+
const reuses = readJsonl(experienceReusePath)
|
|
2058
|
+
const ideas = fs.existsSync(ideasPath)
|
|
2059
|
+
? fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(l => { try { return JSON.parse(l) } catch (_) { return null } }).filter(Boolean)
|
|
2060
|
+
: []
|
|
2061
|
+
const agentIds = new Set()
|
|
2062
|
+
traces.forEach((t) => { if (t.agent) agentIds.add(t.agent) })
|
|
2063
|
+
const outcomes = traces.filter((t) => t.event_type === 'task_outcome')
|
|
2064
|
+
const successes = outcomes.filter((t) => t.outcome === 'success').length
|
|
2065
|
+
const successRate = outcomes.length > 0 ? Math.round((successes / outcomes.length) * 100) : 0
|
|
2066
|
+
const verifiedReuses = reuses.filter((r) => r.confirmed && r.reuse && r.behaviorChanged && r.outcomeImproved)
|
|
2067
|
+
const pendingReuses = reuses.filter((r) => r.source === 'auto_claim' && !r.confirmed)
|
|
2068
|
+
const decisions = memories.filter((m) => m.kind === 'decision')
|
|
2069
|
+
const problems = memories.filter((m) => m.kind === 'problem')
|
|
2070
|
+
const shortMemories = memories.filter((m) => String(m.content || '').trim().length < 20)
|
|
2071
|
+
const ideasWithoutMemory = ideas.filter((i) => !i.provenance?.relatedMemoryIds?.length)
|
|
2072
|
+
const suggestions = []
|
|
2039
2073
|
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2074
|
+
if (agentIds.size >= 2) {
|
|
2075
|
+
const agentStats = []
|
|
2076
|
+
for (const id of agentIds) {
|
|
2077
|
+
const ao = outcomes.filter((t) => t.agent === id)
|
|
2078
|
+
const as = ao.filter((t) => t.outcome === 'success').length
|
|
2079
|
+
agentStats.push({ id, total: ao.length, success: as, rate: ao.length > 0 ? Math.round(as / ao.length * 100) : 0 })
|
|
2080
|
+
}
|
|
2081
|
+
agentStats.sort((a, b) => b.rate - a.rate)
|
|
2082
|
+
const best = agentStats[0], worst = agentStats[agentStats.length - 1]
|
|
2083
|
+
if (best.total >= 5 && worst.total >= 5 && best.rate - worst.rate >= 15) {
|
|
2084
|
+
suggestions.push({ category: 'routing', priority: 'high', title: 'Route tasks to ' + best.id, description: best.id + ' has ' + best.rate + '% success rate vs ' + worst.id + ' at ' + worst.rate + '%.', nextAction: 'Update task routing rules to prefer ' + best.id, impact: 'Could improve overall success rate by ~' + Math.round((best.rate - worst.rate) * 0.3) + '%', basedOn: 'task_outcome comparison' })
|
|
2085
|
+
}
|
|
2050
2086
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
.
|
|
2056
|
-
|
|
2057
|
-
// Generation strategies give diversity without exposing the mechanism to callers.
|
|
2058
|
-
const strategies = [
|
|
2059
|
-
'SCAMPER',
|
|
2060
|
-
'Analogy',
|
|
2061
|
-
'First-Principles',
|
|
2062
|
-
'Random-Stimulus',
|
|
2063
|
-
'Constraint-Inversion'
|
|
2064
|
-
]
|
|
2065
|
-
|
|
2066
|
-
const ideas = []
|
|
2067
|
-
for (let i = 0; i < numIdeas; i++) {
|
|
2068
|
-
const strategy = strategies[i % strategies.length]
|
|
2069
|
-
const blocks = [
|
|
2070
|
-
'Goal: ' + goal,
|
|
2071
|
-
'Strategy: ' + strategy,
|
|
2072
|
-
context ? 'Context: ' + context : '',
|
|
2073
|
-
constraints.length ? 'Constraints: ' + constraints.join(', ') : '',
|
|
2074
|
-
related.length
|
|
2075
|
-
? 'Related Mio memory:\n' + grounding
|
|
2076
|
-
: 'No related Mio memory found yet; record outcomes to grow the experience base.',
|
|
2077
|
-
'Suggestion: Consider prototyping the idea and measuring its impact against prior decisions.'
|
|
2078
|
-
].filter(Boolean)
|
|
2079
|
-
ideas.push({
|
|
2080
|
-
id: 'idea_' + Date.now() + '_' + i,
|
|
2081
|
-
title: 'Idea #' + (i + 1) + ' (' + strategy + '): ' + goal,
|
|
2082
|
-
description: blocks.join('\n\n'),
|
|
2083
|
-
provenance: {
|
|
2084
|
-
strategy: strategy,
|
|
2085
|
-
relatedMemoryIds: relatedIds
|
|
2086
|
-
}
|
|
2087
|
-
})
|
|
2087
|
+
if (shortMemories.length > 5 && memories.length > 10) {
|
|
2088
|
+
suggestions.push({ category: 'memory', priority: 'medium', title: 'Enrich ' + shortMemories.length + ' short memory records', description: Math.round(shortMemories.length / memories.length * 100) + '% of memories have content < 20 chars.', nextAction: 'Review and expand short memory records, or archive irrelevant ones.', impact: 'Improves memory.query recall precision', basedOn: 'memory.jsonl analysis' })
|
|
2089
|
+
}
|
|
2090
|
+
if (pendingReuses.length >= 5) {
|
|
2091
|
+
suggestions.push({ category: 'evidence', priority: 'medium', title: 'Confirm ' + pendingReuses.length + ' pending auto-claims', description: pendingReuses.length + ' auto-claimed reuses await confirmation.', nextAction: 'Call mio.experience.confirm on each auto_claim id.', impact: 'Increases verified reuse count toward Phase 0 threshold', basedOn: 'experience_reuse.jsonl' })
|
|
2088
2092
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
} catch (_) {}
|
|
2093
|
+
const crossAgent = verifiedReuses.filter((r) => r.sourceAgent !== r.targetAgent)
|
|
2094
|
+
if (agentIds.size >= 2 && crossAgent.length === 0) {
|
|
2095
|
+
suggestions.push({ category: 'interop', priority: 'high', title: 'Enable cross-agent experience sharing', description: 'Multiple agents exist but no cross-agent reuse detected.', nextAction: 'Ensure all agents query shared memory before designing solutions.', impact: 'Unlocks core Agent Control Plane value', basedOn: 'experience_reuse.jsonl' })
|
|
2093
2096
|
}
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
fs.appendFileSync(ideasPath, JSON.stringify({ id: idea.id, title: idea.title, description: idea.description, provenance: idea.provenance, goal, context: context || null, constraints, generatedAt: idea.generatedAt }) + '\n')
|
|
2097
|
-
} catch (_) {}
|
|
2097
|
+
if (ideas.length > 0 && ideasWithoutMemory.length > ideas.length * 0.5) {
|
|
2098
|
+
suggestions.push({ category: 'creativity', priority: 'low', title: 'Improve idea grounding (' + ideasWithoutMemory.length + ' ungrounded)', description: Math.round(ideasWithoutMemory.length / ideas.length * 100) + '% of ideas lack related memory context.', nextAction: 'Record more decision/problem memories to enrich the idea pipeline.', impact: 'Higher-quality, more context-aware ideas', basedOn: 'ideas.jsonl provenance' })
|
|
2098
2099
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2100
|
+
if (problems.length >= 3) {
|
|
2101
|
+
const recent = problems.filter((p) => (now - new Date(p.timestamp).getTime()) < 7 * 86400000)
|
|
2102
|
+
if (recent.length >= 2) {
|
|
2103
|
+
suggestions.push({ category: 'health', priority: 'high', title: recent.length + ' problems in last 7 days', description: 'Recurring problems may indicate systemic issues.', nextAction: 'Review recent problems, identify root causes, create decision records.', impact: 'Prevents problem accumulation', basedOn: 'memory.jsonl recent problems' })
|
|
2104
|
+
}
|
|
2103
2105
|
}
|
|
2106
|
+
suggestions.sort((a, b) => ({ high: 0, medium: 1, low: 2 }[a.priority] || 2) - ({ high: 0, medium: 1, low: 2 }[b.priority] || 2))
|
|
2107
|
+
const record = { id: 'evo_' + Date.now(), timestamp: new Date().toISOString(), project, metrics: { agents: agentIds.size, tasks: outcomes.length, successRate, memories: memories.length, decisions: decisions.length, problems: problems.length, verifiedReuses: verifiedReuses.length, pendingReuses: pendingReuses.length, ideas: ideas.length }, suggestions }
|
|
2108
|
+
try { fs.appendFileSync(suggestionsPath, JSON.stringify(record) + '\n') } catch (_) {}
|
|
2109
|
+
return record
|
|
2104
2110
|
}
|
|
2105
2111
|
|
|
2106
2112
|
module.exports = { TOOLS, callTool, handleMessage, readJsonl, appendJsonl, rl }
|