Skip to content

Commit 34439ac

Browse files
authored
Merge pull request #7 from echoVic/refactor/remove-bus-layer
Refactor/remove bus layer
2 parents 93fdb99 + a96ac69 commit 34439ac

123 files changed

Lines changed: 17838 additions & 533 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.npmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
only-built-dependencies=@vscode/ripgrep esbuild
1+
only-built-dependencies=@vscode/ripgrep esbuild node-pty
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
## 目标
2+
3+
将子代理(Task/Subagent)的对话流写到独立 JSONL 文件 `agent_<id>.jsonl`,主会话 JSONL 只保留"调用记录 + 关联信息 + 摘要"。
4+
5+
---
6+
7+
## 一、类型定义扩展
8+
9+
### 1.1 扩展 `BladeJSONLEntry`(src/context/types.ts)
10+
11+
```typescript
12+
export interface BladeJSONLEntry {
13+
// ... 现有字段 ...
14+
15+
// === 子代理关联字段(新增) ===
16+
/** 父会话 ID(子代理 JSONL 必带,用于回链主会话) */
17+
parentSessionId?: string;
18+
/** 是否为侧链/子代理会话(Claude 概念兼容) */
19+
isSidechain?: boolean;
20+
21+
// === 主会话中的子代理引用字段(新增) ===
22+
/** 关联的子代理会话 ID */
23+
subagentSessionId?: string;
24+
/** 子代理类型 */
25+
subagentType?: string;
26+
/** 子代理状态 */
27+
subagentStatus?: 'running' | 'completed' | 'failed' | 'cancelled';
28+
/** 子代理结果摘要(避免重复全文) */
29+
subagentSummary?: string;
30+
}
31+
```
32+
33+
---
34+
35+
## 二、存储层改造
36+
37+
### 2.1 新增 `SubagentPersistentStore`(src/context/storage/SubagentPersistentStore.ts)
38+
39+
专门处理子代理 JSONL 文件的写入,复用现有 `JSONLStore``pathUtils`
40+
41+
**核心功能:**
42+
- `getSubagentFilePath(projectPath, agentId)``~/.blade/projects/{escaped-path}/agent_<id>.jsonl`
43+
- `saveMessage(agentId, ...)` - 追加消息到子代理 JSONL
44+
- `saveToolUse(agentId, ...)` - 追加工具调用
45+
- `saveToolResult(agentId, ...)` - 追加工具结果
46+
- `readAll(agentId)` - 读取子代理完整对话流
47+
48+
**关键设计:**
49+
- 每条 entry 必带 `sessionId = agent_<id>``parentSessionId``isSidechain = true`
50+
- 复用 `BladeJSONLEntry` 结构,保持与主会话格式一致
51+
52+
### 2.2 扩展 `pathUtils.ts`
53+
54+
新增函数:
55+
```typescript
56+
export function getSubagentFilePath(projectPath: string, agentId: string): string {
57+
const storagePath = getProjectStoragePath(projectPath);
58+
const safeId = agentId.replace(/[^a-zA-Z0-9_-]/g, '_');
59+
return path.join(storagePath, `${safeId}.jsonl`);
60+
}
61+
```
62+
63+
---
64+
65+
## 三、子代理执行器改造
66+
67+
### 3.1 修改 `SubagentExecutor`(src/agent/subagents/SubagentExecutor.ts)
68+
69+
**改动点:**
70+
1. 构造函数接收 `projectPath` 参数
71+
2. 创建 `SubagentPersistentStore` 实例
72+
3.`execute()` 中:
73+
- 生成 `agent_<id>` 作为 sessionId
74+
- 通过 `runAgenticLoop` 的回调或后处理,将消息写入独立 JSONL
75+
- 返回结果时包含 `agentId` 供主会话引用
76+
77+
### 3.2 修改 `BackgroundAgentManager`(src/agent/subagents/BackgroundAgentManager.ts)
78+
79+
**改动点:**
80+
1. `executeAgent()` 中使用 `SubagentPersistentStore` 写入 JSONL
81+
2. 保留 `AgentSessionStore` 的 JSON 存储作为元数据索引(状态、统计信息)
82+
3. 消息历史从 JSON 迁移到 JSONL(JSON 只存 metadata,不存 messages)
83+
84+
---
85+
86+
## 四、主会话引用节点
87+
88+
### 4.1 修改 Task 工具(src/tools/builtin/task/task.ts)
89+
90+
在返回结果时,添加子代理关联信息到 metadata:
91+
92+
```typescript
93+
return {
94+
success: true,
95+
llmContent: result.message,
96+
metadata: {
97+
subagentSessionId: agentId, // 新增
98+
subagentType: subagent_type,
99+
subagentStatus: 'completed', // 新增
100+
subagentSummary: result.message.slice(0, 500), // 新增
101+
// ... 其他字段
102+
},
103+
};
104+
```
105+
106+
### 4.2 修改 `PersistentStore.saveToolResult()`
107+
108+
支持写入子代理关联字段:
109+
110+
```typescript
111+
async saveToolResult(
112+
sessionId: string,
113+
toolId: string,
114+
toolOutput: JsonValue,
115+
parentUuid: string | null = null,
116+
error?: string,
117+
subagentInfo?: { // 新增参数
118+
subagentSessionId: string;
119+
subagentType: string;
120+
subagentStatus: string;
121+
subagentSummary?: string;
122+
}
123+
): Promise<string>
124+
```
125+
126+
---
127+
128+
## 五、文件结构变更
129+
130+
```
131+
src/
132+
├── context/
133+
│ ├── types.ts # 扩展 BladeJSONLEntry
134+
│ └── storage/
135+
│ ├── pathUtils.ts # 新增 getSubagentFilePath
136+
│ ├── PersistentStore.ts # 扩展 saveToolResult
137+
│ └── SubagentPersistentStore.ts # 【新建】子代理 JSONL 存储
138+
├── agent/subagents/
139+
│ ├── SubagentExecutor.ts # 集成 SubagentPersistentStore
140+
│ ├── BackgroundAgentManager.ts # 集成 SubagentPersistentStore
141+
│ └── AgentSessionStore.ts # 简化:只存 metadata,不存 messages
142+
└── tools/builtin/task/
143+
└── task.ts # 返回子代理关联信息
144+
```
145+
146+
---
147+
148+
## 六、实现步骤
149+
150+
| 步骤 | 文件 | 改动内容 |
151+
|------|------|----------|
152+
| 1 | `src/context/types.ts` | 扩展 `BladeJSONLEntry` 添加子代理字段 |
153+
| 2 | `src/context/storage/pathUtils.ts` | 新增 `getSubagentFilePath` 函数 |
154+
| 3 | `src/context/storage/SubagentPersistentStore.ts` | 【新建】子代理 JSONL 存储类 |
155+
| 4 | `src/agent/subagents/SubagentExecutor.ts` | 集成 JSONL 写入 |
156+
| 5 | `src/agent/subagents/BackgroundAgentManager.ts` | 集成 JSONL 写入 |
157+
| 6 | `src/agent/subagents/AgentSessionStore.ts` | 移除 messages 字段,只保留 metadata |
158+
| 7 | `src/context/storage/PersistentStore.ts` | 扩展 `saveToolResult` 支持子代理字段 |
159+
| 8 | `src/tools/builtin/task/task.ts` | 返回结果时添加子代理关联信息 |
160+
161+
---
162+
163+
## 七、数据流示意
164+
165+
```
166+
用户请求 → 主会话 JSONL
167+
168+
Task Tool 调用
169+
170+
┌─────────────────────┐
171+
│ SubagentExecutor │
172+
│ 或 BackgroundAgent │
173+
└─────────────────────┘
174+
175+
子代理 JSONL (agent_<id>.jsonl)
176+
- sessionId: agent_<id>
177+
- parentSessionId: 主会话 ID
178+
- isSidechain: true
179+
- 完整对话流(user/assistant/tool_use/tool_result)
180+
181+
主会话 JSONL 写入引用节点
182+
- type: tool_result
183+
- subagentSessionId: agent_<id>
184+
- subagentType: Explore
185+
- subagentStatus: completed
186+
- subagentSummary: "..."
187+
```
188+
189+
---
190+
191+
## 八、预估改动量
192+
193+
- **新建文件**:1 个(`SubagentPersistentStore.ts`,约 150 行)
194+
- **修改文件**:7 个
195+
- **总代码变更**:约 300-400 行

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
],
1616
"scripts": {
1717
"dev": "bun --watch src/blade.tsx",
18+
"dev:serve": "bun --watch src/blade.tsx serve --port 4097",
1819
"build": "rm -rf dist && bun run scripts/build.ts",
1920
"start": "bun run dist/blade.js",
2021
"test": "node scripts/test.js",
@@ -103,7 +104,9 @@
103104
"vitest": "^3.0.0"
104105
},
105106
"optionalDependencies": {
106-
"@vscode/ripgrep": "^1.17.0"
107+
"@vscode/ripgrep": "^1.17.0",
108+
"bun-pty": "^0.4.8",
109+
"node-pty": "1.0.0"
107110
},
108111
"dependencies": {
109112
"@agentclientprotocol/sdk": "^0.12.0",
@@ -128,6 +131,7 @@
128131
"fast-glob": "^3.3.3",
129132
"fuse.js": "^7.1.0",
130133
"gray-matter": "^4.0.3",
134+
"hono": "^4.7.10",
131135
"ink": "npm:@jrichman/ink@6.4.6",
132136
"ink-big-text": "^2.0.0",
133137
"ink-gradient": "^3.0.0",
@@ -139,10 +143,9 @@
139143
"lowlight": "^3.3.0",
140144
"lru-cache": "^11.2.4",
141145
"nanoid": "^5.1.6",
146+
"open": "^10.1.2",
142147
"openai": "^6.2.0",
143148
"picomatch": "^4.0.3",
144-
"pino": "^10.1.0",
145-
"pino-pretty": "^13.1.3",
146149
"react": "^19.1.1",
147150
"react-dom": "^19.1.1",
148151
"semver": "^7.7.3",

0 commit comments

Comments
 (0)