Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
52e3db3
feat(server): 新增Blade服务器核心功能及API路由
echoVic Jan 24, 2026
55540e5
feat(web): 添加完整的Web UI界面
echoVic Jan 24, 2026
9b2682c
feat: 实现聊天会话管理和消息流式处理功能
echoVic Jan 24, 2026
c85cff9
feat: 添加模型管理和会话功能
echoVic Jan 25, 2026
4c598e9
feat(会话): 实现临时会话功能并增强侧边栏
echoVic Jan 25, 2026
37831e3
feat(web): 添加终端功能及UI改进
echoVic Jan 25, 2026
5b83127
feat(消息): 添加权限模式支持并优化侧边栏样式
echoVic Jan 25, 2026
11b3b4d
refactor(权限模式): 统一使用 PermissionMode 枚举类型
echoVic Jan 25, 2026
de2fe52
feat: 添加多语言支持并优化UI主题配置
echoVic Jan 25, 2026
67a4dab
refactor(server): 移除事件总线并重构会话和权限处理
echoVic Jan 25, 2026
18d75a5
refactor(会话): 重构会话管理及事件处理机制
echoVic Jan 25, 2026
ff2cde1
feat(terminal): 支持Node.js环境的终端WebSocket连接
Jan 27, 2026
785bd56
refactor(session): 重构会话存储结构,将状态管理拆分为多个切片
Jan 28, 2026
e6fe25e
refactor(session): 重构会话存储结构,移除工具切片并优化事件处理
Jan 28, 2026
05e579a
refactor(chat): 重构消息组件和状态管理逻辑
Jan 28, 2026
f3716a8
Update package version
Jan 28, 2026
d5b5b67
feat: 移除pino日志库并实现自定义日志系统
Jan 29, 2026
a96ac69
feat(文件预览): 支持展示所有变更文件并允许展开/折叠差异
Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
only-built-dependencies=@vscode/ripgrep esbuild
only-built-dependencies=@vscode/ripgrep esbuild node-pty
195 changes: 195 additions & 0 deletions .trae/documents/Claude 子代理独立 JSONL 文件设计实现.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
## 目标

将子代理(Task/Subagent)的对话流写到独立 JSONL 文件 `agent_<id>.jsonl`,主会话 JSONL 只保留"调用记录 + 关联信息 + 摘要"。

---

## 一、类型定义扩展

### 1.1 扩展 `BladeJSONLEntry`(src/context/types.ts)

```typescript
export interface BladeJSONLEntry {
// ... 现有字段 ...

// === 子代理关联字段(新增) ===
/** 父会话 ID(子代理 JSONL 必带,用于回链主会话) */
parentSessionId?: string;
/** 是否为侧链/子代理会话(Claude 概念兼容) */
isSidechain?: boolean;

// === 主会话中的子代理引用字段(新增) ===
/** 关联的子代理会话 ID */
subagentSessionId?: string;
/** 子代理类型 */
subagentType?: string;
/** 子代理状态 */
subagentStatus?: 'running' | 'completed' | 'failed' | 'cancelled';
/** 子代理结果摘要(避免重复全文) */
subagentSummary?: string;
}
```

---

## 二、存储层改造

### 2.1 新增 `SubagentPersistentStore`(src/context/storage/SubagentPersistentStore.ts)

专门处理子代理 JSONL 文件的写入,复用现有 `JSONLStore` 和 `pathUtils`。

**核心功能:**
- `getSubagentFilePath(projectPath, agentId)` → `~/.blade/projects/{escaped-path}/agent_<id>.jsonl`
- `saveMessage(agentId, ...)` - 追加消息到子代理 JSONL
- `saveToolUse(agentId, ...)` - 追加工具调用
- `saveToolResult(agentId, ...)` - 追加工具结果
- `readAll(agentId)` - 读取子代理完整对话流

**关键设计:**
- 每条 entry 必带 `sessionId = agent_<id>`、`parentSessionId`、`isSidechain = true`
- 复用 `BladeJSONLEntry` 结构,保持与主会话格式一致

### 2.2 扩展 `pathUtils.ts`

新增函数:
```typescript
export function getSubagentFilePath(projectPath: string, agentId: string): string {
const storagePath = getProjectStoragePath(projectPath);
const safeId = agentId.replace(/[^a-zA-Z0-9_-]/g, '_');
return path.join(storagePath, `${safeId}.jsonl`);
}
```

---

## 三、子代理执行器改造

### 3.1 修改 `SubagentExecutor`(src/agent/subagents/SubagentExecutor.ts)

**改动点:**
1. 构造函数接收 `projectPath` 参数
2. 创建 `SubagentPersistentStore` 实例
3. 在 `execute()` 中:
- 生成 `agent_<id>` 作为 sessionId
- 通过 `runAgenticLoop` 的回调或后处理,将消息写入独立 JSONL
- 返回结果时包含 `agentId` 供主会话引用

### 3.2 修改 `BackgroundAgentManager`(src/agent/subagents/BackgroundAgentManager.ts)

**改动点:**
1. `executeAgent()` 中使用 `SubagentPersistentStore` 写入 JSONL
2. 保留 `AgentSessionStore` 的 JSON 存储作为元数据索引(状态、统计信息)
3. 消息历史从 JSON 迁移到 JSONL(JSON 只存 metadata,不存 messages)

---

## 四、主会话引用节点

### 4.1 修改 Task 工具(src/tools/builtin/task/task.ts)

在返回结果时,添加子代理关联信息到 metadata:

```typescript
return {
success: true,
llmContent: result.message,
metadata: {
subagentSessionId: agentId, // 新增
subagentType: subagent_type,
subagentStatus: 'completed', // 新增
subagentSummary: result.message.slice(0, 500), // 新增
// ... 其他字段
},
};
```

### 4.2 修改 `PersistentStore.saveToolResult()`

支持写入子代理关联字段:

```typescript
async saveToolResult(
sessionId: string,
toolId: string,
toolOutput: JsonValue,
parentUuid: string | null = null,
error?: string,
subagentInfo?: { // 新增参数
subagentSessionId: string;
subagentType: string;
subagentStatus: string;
subagentSummary?: string;
}
): Promise<string>
```

---

## 五、文件结构变更

```
src/
├── context/
│ ├── types.ts # 扩展 BladeJSONLEntry
│ └── storage/
│ ├── pathUtils.ts # 新增 getSubagentFilePath
│ ├── PersistentStore.ts # 扩展 saveToolResult
│ └── SubagentPersistentStore.ts # 【新建】子代理 JSONL 存储
├── agent/subagents/
│ ├── SubagentExecutor.ts # 集成 SubagentPersistentStore
│ ├── BackgroundAgentManager.ts # 集成 SubagentPersistentStore
│ └── AgentSessionStore.ts # 简化:只存 metadata,不存 messages
└── tools/builtin/task/
└── task.ts # 返回子代理关联信息
```

---

## 六、实现步骤

| 步骤 | 文件 | 改动内容 |
|------|------|----------|
| 1 | `src/context/types.ts` | 扩展 `BladeJSONLEntry` 添加子代理字段 |
| 2 | `src/context/storage/pathUtils.ts` | 新增 `getSubagentFilePath` 函数 |
| 3 | `src/context/storage/SubagentPersistentStore.ts` | 【新建】子代理 JSONL 存储类 |
| 4 | `src/agent/subagents/SubagentExecutor.ts` | 集成 JSONL 写入 |
| 5 | `src/agent/subagents/BackgroundAgentManager.ts` | 集成 JSONL 写入 |
| 6 | `src/agent/subagents/AgentSessionStore.ts` | 移除 messages 字段,只保留 metadata |
| 7 | `src/context/storage/PersistentStore.ts` | 扩展 `saveToolResult` 支持子代理字段 |
| 8 | `src/tools/builtin/task/task.ts` | 返回结果时添加子代理关联信息 |

---

## 七、数据流示意

```
用户请求 → 主会话 JSONL
Task Tool 调用
┌─────────────────────┐
│ SubagentExecutor │
│ 或 BackgroundAgent │
└─────────────────────┘
子代理 JSONL (agent_<id>.jsonl)
- sessionId: agent_<id>
- parentSessionId: 主会话 ID
- isSidechain: true
- 完整对话流(user/assistant/tool_use/tool_result)
主会话 JSONL 写入引用节点
- type: tool_result
- subagentSessionId: agent_<id>
- subagentType: Explore
- subagentStatus: completed
- subagentSummary: "..."
```

---

## 八、预估改动量

- **新建文件**:1 个(`SubagentPersistentStore.ts`,约 150 行)
- **修改文件**:7 个
- **总代码变更**:约 300-400 行
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
],
"scripts": {
"dev": "bun --watch src/blade.tsx",
"dev:serve": "bun --watch src/blade.tsx serve --port 4097",
"build": "rm -rf dist && bun run scripts/build.ts",
"start": "bun run dist/blade.js",
"test": "node scripts/test.js",
Expand Down Expand Up @@ -103,7 +104,9 @@
"vitest": "^3.0.0"
},
"optionalDependencies": {
"@vscode/ripgrep": "^1.17.0"
"@vscode/ripgrep": "^1.17.0",
"bun-pty": "^0.4.8",
"node-pty": "1.0.0"
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.12.0",
Expand All @@ -128,6 +131,7 @@
"fast-glob": "^3.3.3",
"fuse.js": "^7.1.0",
"gray-matter": "^4.0.3",
"hono": "^4.7.10",
"ink": "npm:@jrichman/ink@6.4.6",
"ink-big-text": "^2.0.0",
"ink-gradient": "^3.0.0",
Expand All @@ -139,10 +143,9 @@
"lowlight": "^3.3.0",
"lru-cache": "^11.2.4",
"nanoid": "^5.1.6",
"open": "^10.1.2",
"openai": "^6.2.0",
"picomatch": "^4.0.3",
"pino": "^10.1.0",
"pino-pretty": "^13.1.3",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"semver": "^7.7.3",
Expand Down
Loading
Loading