Files
2026-04-03 13:01:19 +08:00

692 lines
16 KiB
Markdown

# Swarm 系统
Claude Code 的 Swarm 系统是一个多智能体协作框架,支持团队模式、进程内队友和多种终端后端实现。
## 1. Swarm 系统概述
### 1.1 核心目录结构
**位置:** `/src/utils/swarm/`
```
swarm/
├── backends/
│ ├── types.ts # 后端类型定义
│ ├── registry.ts # 后端注册表
│ ├── detection.ts # 环境检测
│ ├── TmuxBackend.ts # Tmux 后端
│ ├── ITermBackend.ts # iTerm2 后端
│ ├── InProcessBackend.ts # 进程内后端
│ ├── PaneBackendExecutor.ts # 面板执行器
│ └── teammateModeSnapshot.ts # 团队模式快照
├── teamHelpers.ts # 团队辅助函数
├── teammateInit.ts # 队友初始化
├── teammateLayoutManager.ts # 布局管理
├── teammateModel.ts # 队友模型
├── teammatePromptAddendum.ts # 提示补充
├── permissionSync.ts # 权限同步
├── reconnection.ts # 重连机制
├── spawnUtils.ts # 生成工具
├── spawnInProcess.ts # 进程内生成
├── inProcessRunner.ts # 进程内运行器
├── constants.ts # 常量定义
└── leaderPermissionBridge.ts # 权限桥接
```
## 2. 团队模式快照 (teammateModeSnapshot.ts)
### 2.1 快照机制
```typescript
// 位置:/src/utils/swarm/backends/teammateModeSnapshot.ts
export type TeammateMode = 'auto' | 'tmux' | 'in-process'
// CLI 覆盖
let cliTeammateModeOverride: TeammateMode | null = null
// 捕获启动时的团队模式
export function captureTeammateModeSnapshot(): void {
if (cliTeammateModeOverride) {
initialTeammateMode = cliTeammateModeOverride
} else {
const config = getGlobalConfig()
initialTeammateMode = config.teammateMode ?? 'auto'
}
}
// 获取快照模式
export function getTeammateModeFromSnapshot(): TeammateMode
```
### 2.2 模式类型
| 模式 | 描述 |
|------|------|
| `auto` | 自动检测可用后端 |
| `tmux` | 强制使用 Tmux 后端 |
| `in-process` | 使用进程内后端 |
## 3. 团队辅助函数 (teamHelpers.ts)
### 3.1 团队文件操作
```typescript
// 获取团队目录
export function getTeamDir(teamName: string): string
// 获取团队配置文件路径
export function getTeamFilePath(teamName: string): string
// 读取团队文件(同步)
export function readTeamFile(teamName: string): TeamFile | null
// 读取团队文件(异步)
export async function readTeamFileAsync(teamName: string): Promise<TeamFile | null>
// 写入团队文件(同步)
function writeTeamFile(teamName: string, teamFile: TeamFile): void
// 写入团队文件(异步)
export async function writeTeamFileAsync(teamName: string, teamFile: TeamFile): Promise<void>
```
### 3.2 团队成员管理
```typescript
// 从团队文件移除队友
export function removeTeammateFromTeamFile(
teamName: string,
identifier: { agentId?: string; name?: string }
): boolean
// 移除成员
export function removeMemberFromTeam(
teamName: string,
tmuxPaneId: string
): boolean
// 按 Agent ID 移除成员
export function removeMemberByAgentId(
teamName: string,
agentId: string
): boolean
// 设置成员权限模式
export function setMemberMode(
teamName: string,
memberName: string,
mode: PermissionMode
): boolean
// 同步队友模式
export function syncTeammateMode(mode: PermissionMode, teamNameOverride?: string): void
// 设置成员活跃状态
export async function setMemberActive(
teamName: string,
memberName: string,
isActive: boolean
): Promise<void>
```
### 3.3 团队清理
```typescript
// 清理会话团队
export async function cleanupSessionTeams(): Promise<void>
// 清理团队目录
export async function cleanupTeamDirectories(teamName: string): Promise<void>
// 注册团队会话清理
export function registerTeamForSessionCleanup(teamName: string): void
// 注销团队会话清理
export function unregisterTeamForSessionCleanup(teamName: string): void
```
## 4. 队友初始化 (teammateInit.ts)
### 4.1 初始化流程
```typescript
// 位置:/src/utils/swarm/teammateInit.ts
export function initializeTeammateHooks(
setAppState: (updater: (prev: AppState) => AppState) => void,
sessionId: string,
teamInfo: { teamName: string; agentId: string; agentName: string }
): void
```
### 4.2 团队权限应用
```typescript
// 应用团队范围的允许路径
if (teamFile.teamAllowedPaths && teamFile.teamAllowedPaths.length > 0) {
for (const allowedPath of teamFile.teamAllowedPaths) {
setAppState(prev => ({
...prev,
toolPermissionContext: applyPermissionUpdate(
prev.toolPermissionContext,
{
type: 'addRules',
rules: [{ toolName: allowedPath.toolName, ruleContent }],
behavior: 'allow',
destination: 'session'
}
)
}))
}
}
```
### 4.3 停止钩子注册
```typescript
// 注册停止钩子以通知团队领导
addFunctionHook(
setAppState,
sessionId,
'Stop',
'',
async (messages, _signal) => {
// 标记为空闲
void setMemberActive(teamName, agentName, false)
// 发送空闲通知
const notification = createIdleNotification(agentName, {...})
await writeToMailbox(leadAgentName, {...})
return true
}
)
```
## 5. 布局管理 (teammateLayoutManager.ts)
### 5.1 队友颜色分配
```typescript
// 分配队友颜色
export function assignTeammateColor(teammateId: string): AgentColorName
// 获取队友颜色
export function getTeammateColor(teammateId: string): AgentColorName | undefined
// 清除所有颜色分配
export function clearTeammateColors(): void
```
### 5.2 后端选择
```typescript
async function getBackend(): Promise<PaneBackend> {
return (await detectAndGetBackend()).backend
}
```
### 5.3 面板操作
```typescript
// 在 Swarm 视图中创建队友面板
export async function createTeammatePaneInSwarmView(
teammateName: string,
teammateColor: AgentColorName
): Promise<{ paneId: string; isFirstTeammate: boolean }>
// 启用面板边框状态
export async function enablePaneBorderStatus(
windowTarget?: string,
useSwarmSocket?: boolean
): Promise<void>
// 发送命令到面板
export async function sendCommandToPane(
paneId: string,
command: string,
useSwarmSocket?: boolean
): Promise<void>
```
## 6. 后端系统 (backends/)
### 6.1 后端类型
**位置:** `/src/utils/swarm/backends/types.ts`
```typescript
export type BackendType = 'tmux' | 'iterm2' | 'in-process'
export type PaneBackendType = 'tmux' | 'iterm2'
export type PaneId = string
export type CreatePaneResult = {
paneId: PaneId
isFirstTeammate: boolean
}
```
### 6.2 PaneBackend 接口
```typescript
export type PaneBackend = {
readonly type: BackendType
readonly displayName: string
readonly supportsHideShow: boolean
isAvailable(): Promise<boolean>
isRunningInside(): Promise<boolean>
createTeammatePaneInSwarmView(
name: string,
color: AgentColorName
): Promise<CreatePaneResult>
sendCommandToPane(
paneId: PaneId,
command: string,
useExternalSession?: boolean
): Promise<void>
setPaneBorderColor(
paneId: PaneId,
color: AgentColorName,
useExternalSession?: boolean
): Promise<void>
setPaneTitle(
paneId: PaneId,
name: string,
color: AgentColorName,
useExternalSession?: boolean
): Promise<void>
enablePaneBorderStatus(
windowTarget?: string,
useExternalSession?: boolean
): Promise<void>
rebalancePanes(windowTarget: string, hasLeader: boolean): Promise<void>
killPane(paneId: PaneId, useExternalSession?: boolean): Promise<boolean>
hidePane(paneId: PaneId, useExternalSession?: boolean): Promise<boolean>
showPane(
paneId: PaneId,
targetWindowOrPane: string,
useExternalSession?: boolean
): Promise<boolean>
}
```
### 6.3 TmuxBackend
**位置:** `/src/utils/swarm/backends/TmuxBackend.ts`
使用 tmux 进行面板管理的后端实现。
**功能:**
- 创建 tmux 窗口和面板
- 发送命令到指定面板
- 设置面板颜色和标题
- 管理面板布局
### 6.4 ITermBackend
**位置:** `/src/utils/swarm/backends/ITermBackend.ts`
使用 iTerm2 原生分割面板的后端实现。
**功能:**
- 通过 it2 CLI 与 iTerm2 通信
- 创建垂直/水平分割
- 设置 profile 和颜色
### 6.5 InProcessBackend
**位置:** `/src/utils/swarm/backends/InProcessBackend.ts`
在当前 Node.js 进程中运行队友的后端。
**特性:**
- 共享 API 客户端和 MCP 连接
- 通过文件邮箱通信
- 使用 AbortController 终止
- 始终可用(无外部依赖)
```typescript
export class InProcessBackend implements TeammateExecutor {
readonly type = 'in-process' as const
async spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult>
async sendMessage(agentId: string, message: TeammateMessage): Promise<void>
async terminate(agentId: string, reason?: string): Promise<boolean>
async kill(agentId: string): Promise<boolean>
async isActive(agentId: string): Promise<boolean>
}
```
### 6.6 后端注册表
**位置:** `/src/utils/swarm/backends/registry.ts`
```typescript
// 检测并获取合适的后端
export async function detectAndGetBackend(): Promise<BackendDetectionResult>
// 注册所有后端
export async function ensureBackendsRegistered(): Promise<void>
// 按类型获取后端
export async function getBackendByType(type: BackendType): Promise<PaneBackend>
```
## 7. 权限同步 (permissionSync.ts)
### 7.1 权限请求流程
```
Worker Agent → 权限请求 → Leader Mailbox
Leader Agent ← 轮询 ← 权限队列
用户批准/拒绝
Leader → 权限响应 → Worker Mailbox
Worker ← 处理响应 ←
```
### 7.2 权限请求结构
```typescript
export type SwarmPermissionRequest = {
id: string
workerId: string
workerName: string
workerColor?: string
teamName: string
toolName: string
toolUseId: string
description: string
input: Record<string, unknown>
permissionSuggestions: unknown[]
status: 'pending' | 'approved' | 'rejected'
resolvedBy?: 'worker' | 'leader'
resolvedAt?: number
feedback?: string
updatedInput?: Record<string, unknown>
permissionUpdates?: PermissionUpdate[]
createdAt: number
}
```
### 7.3 权限操作
```typescript
// 创建权限请求
export function createPermissionRequest(params: {...}): SwarmPermissionRequest
// 写入待处理权限请求
export async function writePermissionRequest(
request: SwarmPermissionRequest
): Promise<SwarmPermissionRequest>
// 读取待处理权限
export async function readPendingPermissions(
teamName?: string
): Promise<SwarmPermissionRequest[]>
// 解决权限请求
export async function resolvePermission(
requestId: string,
resolution: PermissionResolution,
teamName?: string
): Promise<boolean>
// 通过邮箱发送权限请求
export async function sendPermissionRequestViaMailbox(
request: SwarmPermissionRequest
): Promise<boolean>
// 通过邮箱发送权限响应
export async function sendPermissionResponseViaMailbox(
workerName: string,
resolution: PermissionResolution,
requestId: string,
teamName?: string
): Promise<boolean>
```
### 7.4 沙箱权限
```typescript
// 发送沙箱权限请求
export async function sendSandboxPermissionRequestViaMailbox(
host: string,
requestId: string,
teamName?: string
): Promise<boolean>
// 发送沙箱权限响应
export async function sendSandboxPermissionResponseViaMailbox(
workerName: string,
requestId: string,
host: string,
allow: boolean,
teamName?: string
): Promise<boolean>
```
### 7.5 团队领导检查
```typescript
// 检查是否为团队领导
export function isTeamLeader(teamName?: string): boolean
// 检查是否为 Swarm Worker
export function isSwarmWorker(): boolean
```
## 8. 重连机制 (reconnection.ts)
### 8.1 初始团队上下文计算
```typescript
export function computeInitialTeamContext():
| AppState['teamContext']
| undefined {
// 从 CLI 参数获取动态团队上下文
const context = getDynamicTeamContext()
if (!context?.teamName || !context?.agentName) {
return undefined
}
// 读取团队文件获取领导 Agent ID
const teamFile = readTeamFile(teamName)
return {
teamName,
teamFilePath,
leadAgentId: teamFile.leadAgentId,
selfAgentId: agentId,
selfAgentName: agentName,
isLeader,
teammates: {}
}
}
```
### 8.2 从会话恢复团队上下文
```typescript
export function initializeTeammateContextFromSession(
setAppState: (updater: (prev: AppState) => AppState) => void,
teamName: string,
agentName: string
): void {
// 从团队文件读取成员信息
const teamFile = readTeamFile(teamName)
const member = teamFile.members.find(m => m.name === agentName)
const agentId = member?.agentId
// 设置 AppState 中的团队上下文
setAppState(prev => ({
...prev,
teamContext: {
teamName,
teamFilePath,
leadAgentId: teamFile.leadAgentId,
selfAgentId: agentId,
selfAgentName: agentName,
isLeader: false,
teammates: {}
}
}))
}
```
## 9. 队友生成 (spawnUtils.ts, spawnInProcess.ts)
### 9.1 进程内队友生成
```typescript
// 位置:/src/utils/swarm/spawnInProcess.ts
export async function spawnInProcessTeammate(
identity: TeammateIdentity,
context: ToolUseContext
): Promise<{
success: boolean
agentId: string
taskId?: string
teammateContext?: TeammateContext
abortController?: AbortController
error?: string
}>
export function killInProcessTeammate(
taskId: string,
setAppState: (updater: (prev: AppState) => AppState) => void
): boolean
```
### 9.2 进程内运行器
```typescript
// 位置:/src/utils/swarm/inProcessRunner.ts
export async function startInProcessTeammate(params: {
identity: TeammateIdentity
taskId: string
prompt: string
teammateContext: TeammateContext
toolUseContext: ToolUseContext
abortController: AbortController
model?: string
systemPrompt?: string
systemPromptMode?: 'default' | 'replace' | 'append'
allowedTools?: string[]
allowPermissionPrompts?: boolean
}): Promise<void>
```
## 10. TeammateExecutor 接口
### 10.1 接口定义
```typescript
export type TeammateExecutor = {
readonly type: BackendType
isAvailable(): Promise<boolean>
spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult>
sendMessage(agentId: string, message: TeammateMessage): Promise<void>
terminate(agentId: string, reason?: string): Promise<boolean>
kill(agentId: string): Promise<boolean>
isActive(agentId: string): Promise<boolean>
}
```
### 10.2 TeammateSpawnConfig
```typescript
export type TeammateSpawnConfig = TeammateIdentity & {
prompt: string
cwd: string
model?: string
systemPrompt?: string
systemPromptMode?: 'default' | 'replace' | 'append'
worktreePath?: string
parentSessionId: string
permissions?: string[]
allowPermissionPrompts?: boolean
}
```
### 10.3 TeammateSpawnResult
```typescript
export type TeammateSpawnResult = {
success: boolean
agentId: string // 格式: agentName@teamName
error?: string
abortController?: AbortController // 进程内队友使用
taskId?: string // AppState.tasks 中的任务 ID
paneId?: PaneId // 基于面板的后端使用
}
```
## 11. 消息类型
### 11.1 TeammateMessage
```typescript
export type TeammateMessage = {
text: string
from: string
color?: string
timestamp?: string
summary?: string // 5-10 字预览
}
```
## 12. 类型守卫
### 12.1 面板后端检查
```typescript
export function isPaneBackend(type: BackendType): type is 'tmux' | 'iterm2' {
return type === 'tmux' || type === 'iterm2'
}
```
## 13. 环境检测
### 13.1 tmux 检测
```typescript
// 检测是否在 tmux 会话内运行
export async function isInsideTmux(): Promise<boolean>
```
### 13.2 iTerm2 检测
```typescript
// 检测 iTerm2 是否可用
export async function isITerm2Available(): Promise<boolean>
```
## 14. 团队常量
**位置:** `/src/utils/swarm/constants.ts`
```typescript
export const TEAM_LEAD_NAME = 'team-lead'
export const DEFAULT_TEAM_PANE_WIDTH = '30%'
export const DEFAULT_TEAM_PANE_HEIGHT = '50%'
```