opencode-collaboration 2.1.0__py3-none-any.whl → 2.2.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencode-collaboration
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: 双Agent协作框架 - 产品经理与开发的分离式协作工具
5
5
  Author-email: OpenCode <dev@opencode.ai>
6
6
  License: MIT
@@ -4,6 +4,7 @@ src/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  src/cli/agent.py,sha256=o8-3UpfcnUMePltpBdVBuBFMECMiKnOA7airyvi1m54,9874
5
5
  src/cli/main.py,sha256=E91PR24_r1gfKPlmtgQin2OZ-YHCck4dUe01X81FpIo,44189
6
6
  src/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ src/core/agent_manager.py,sha256=Mxe4G_IfEaQ1lERdGNfMvK0tIS6DuE3WJUNOxgtAD8o,16535
7
8
  src/core/auto_doc_git.py,sha256=_yphH8tLAMq3R-yMHpc2bcmmap2p7b2So4qVmXUtCh8,1396
8
9
  src/core/auto_docs.py,sha256=rQfJrrKGe8fiQK4eSq4gAp1rfFAu_o-sDV_ZloaFQVQ,11142
9
10
  src/core/auto_engine.py,sha256=bV9VXa0naPpxKuE7p7xHAZKZJe9DIGfzrFwHhiaDHKA,16031
@@ -21,13 +22,17 @@ src/core/git.py,sha256=guy7aE9FX4w62HQ-Wf_N3jzu_rn8JfVFLf8-Ulz-5k8,8928
21
22
  src/core/git_monitor.py,sha256=PFZxq_KodaI6zcO67-40h2vid6zdSpr3bGVZiF2fEsA,15009
22
23
  src/core/git_workflow_enforcer.py,sha256=0B-xMX4T9bvyuulgqrgOlRYYwi7Vr32apjGz-9NVK00,11583
23
24
  src/core/iteration_status_manager.py,sha256=ckPsJK_brsP_NSXtBLLlNrn5DqvmxvEGsE_VqjHOPJ8,9916
25
+ src/core/meeting_manager.py,sha256=lcwZ1fgZHl8Mq8s3Oh5PjFxREgiXoDt852J3B7yJjvY,15375
24
26
  src/core/monitor.py,sha256=3s0xuc6l7pF4MtnRjYVxbfn8MLfKk7p7mljqtsZDQZ0,8949
25
27
  src/core/phase_advance.py,sha256=76UN8TI7RpJgRfjgV4bvs7uWlvNt-h_dz6gTDgK2zrY,11285
28
+ src/core/project_manager.py,sha256=qayc8NHy3go26LWZgw17nL57p8LXKjpprAS1_iKZHDg,16637
29
+ src/core/resource_lock.py,sha256=1G2yOdbqZnWqVdcIt6IKbhRLhSg23kLgJhdwiFt7jdY,13889
26
30
  src/core/signoff.py,sha256=fG6KFNz3AYh6hKYMPfognU_SBs5amCW2q4bne4huFf0,6643
27
31
  src/core/state_machine.py,sha256=L1gfdsYC6mlWcHP5RwQQen8vCTwV2spIP-Ktwz4gux8,14919
28
32
  src/core/state_manager.py,sha256=jkgci5q71DRjmKe8igeFhOTxHJ2xqNjAHJo6THFtw_M,16672
29
33
  src/core/state_migrator.py,sha256=OYXtwxA_ePFAS_XqOMhKR2fyU1werLePbqCyNZg8eXQ,13746
30
34
  src/core/state_validator.py,sha256=Q86jbEO0fNdzDi3zIPB_G_ibQ0QWyXFYV_rPj6Eakjw,18827
35
+ src/core/story_manager.py,sha256=8b0Kelw6zdvZYr9sb0Rnlf7_XeXXOSdVar4q2vQjdbI,21867
31
36
  src/core/supervisor.py,sha256=pT_5CkimpFgB_gyqzsUL-25l3MsRGP1TWFEnHdGJtwo,7290
32
37
  src/core/task_executor.py,sha256=xcM9sNu8MyAVqlNvtc2GL4eiYeTMmeduTrrA3j292aM,23720
33
38
  src/core/workflow.py,sha256=LpH9g6xbtCmYOhhCSxpcstRR7TptN8e6b0mEag3UcW4,5634
@@ -36,8 +41,8 @@ src/utils/date.py,sha256=iWS0hTaoDE2iC0jJb3lTIB5yK5xxRbrC1C98Fgb8LFc,577
36
41
  src/utils/file.py,sha256=5IFKkT2m1emJUHDzIiLsa4YG9GCqOhhmiLvc6aVY9-Y,1301
37
42
  src/utils/lock.py,sha256=soxYFsBKJHUzN-_QXkorVfgnmt0D5p1SZtqwPNqcWPI,2880
38
43
  src/utils/yaml.py,sha256=zcbh0OP7NOqxTexEAR3akQkllUh8xeKt42O2CHIImyg,777
39
- opencode_collaboration-2.1.0.dist-info/METADATA,sha256=S0iMP93dKx2xMA5c-PkSrZ6rAW1btFTuHHOJBdLIeyI,3145
40
- opencode_collaboration-2.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
41
- opencode_collaboration-2.1.0.dist-info/entry_points.txt,sha256=fYyHWa_NefMp527B7fHl-29SwZQCElRdtxm_7LoUK-Y,48
42
- opencode_collaboration-2.1.0.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
43
- opencode_collaboration-2.1.0.dist-info/RECORD,,
44
+ opencode_collaboration-2.2.0.dist-info/METADATA,sha256=JUqcf6qs5uBE2tjP4CNyLXxGR8ev6msaZIFNiFnNJjg,3145
45
+ opencode_collaboration-2.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
46
+ opencode_collaboration-2.2.0.dist-info/entry_points.txt,sha256=fYyHWa_NefMp527B7fHl-29SwZQCElRdtxm_7LoUK-Y,48
47
+ opencode_collaboration-2.2.0.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
48
+ opencode_collaboration-2.2.0.dist-info/RECORD,,
@@ -0,0 +1,553 @@
1
+ """Agent 管理模块 - v2.2.0 M1 多 Agent 动态管理
2
+
3
+ 提供 Agent 角色体系、动态添加、职责约束等功能。
4
+ """
5
+ import os
6
+ import uuid
7
+ from dataclasses import dataclass, field
8
+ from enum import Enum
9
+ from pathlib import Path
10
+ from typing import Any, Dict, List, Optional, Set
11
+ import yaml
12
+ import json
13
+ import logging
14
+
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class AgentType(Enum):
20
+ """Agent 类型枚举。"""
21
+ PRODUCT_MANAGER = "product_manager"
22
+ DEVELOPMENT_LEAD = "development_lead"
23
+ FRONTEND_DEV = "frontend_dev"
24
+ BACKEND_DEV = "backend_dev"
25
+ DESIGNER = "designer"
26
+ TESTER = "tester"
27
+
28
+
29
+ class ActionType(Enum):
30
+ """操作类型枚举。"""
31
+ CREATE_REQUIREMENTS = "CREATE_REQUIREMENTS"
32
+ REVIEW_DESIGN = "REVIEW_DESIGN"
33
+ SIGN_OFF = "SIGN_OFF"
34
+ MANAGE_PROJECT = "MANAGE_PROJECT"
35
+ WRITE_CODE = "WRITE_CODE"
36
+ CREATE_DESIGN = "CREATE_DESIGN"
37
+ CODE_REVIEW = "CODE_REVIEW"
38
+ WRITE_CODE_FRONTEND = "WRITE_CODE_FRONTEND"
39
+ WRITE_CODE_BACKEND = "WRITE_CODE_BACKEND"
40
+ REVIEW_DESIGN_FRONTEND = "REVIEW_DESIGN_FRONTEND"
41
+ API_DESIGN = "API_DESIGN"
42
+ UPLOAD_DESIGN = "UPLOAD_DESIGN"
43
+ EXECUTE_TEST = "EXECUTE_TEST"
44
+
45
+
46
+ @dataclass
47
+ class AgentConfig:
48
+ """Agent 配置。"""
49
+ agent_id: str
50
+ agent_type: AgentType
51
+ name: str
52
+ role: str
53
+ responsibilities: List[str]
54
+ forbidden: List[str]
55
+ tech_stack: Optional[str] = None
56
+ created_at: str = field(default_factory=lambda: str(uuid.uuid4()))
57
+ last_active: Optional[str] = None
58
+ status: str = "active"
59
+
60
+ def to_dict(self) -> Dict[str, Any]:
61
+ """转换为字典。"""
62
+ return {
63
+ "agent_id": self.agent_id,
64
+ "agent_type": self.agent_type.value,
65
+ "name": self.name,
66
+ "role": self.role,
67
+ "responsibilities": self.responsibilities,
68
+ "forbidden": self.forbidden,
69
+ "tech_stack": self.tech_stack,
70
+ "created_at": self.created_at,
71
+ "last_active": self.last_active,
72
+ "status": self.status
73
+ }
74
+
75
+ @classmethod
76
+ def from_dict(cls, data: Dict[str, Any]) -> "AgentConfig":
77
+ """从字典创建。"""
78
+ return cls(
79
+ agent_id=data["agent_id"],
80
+ agent_type=AgentType(data["agent_type"]),
81
+ name=data["name"],
82
+ role=data["role"],
83
+ responsibilities=data["responsibilities"],
84
+ forbidden=data["forbidden"],
85
+ tech_stack=data.get("tech_stack"),
86
+ created_at=data.get("created_at", str(uuid.uuid4())),
87
+ last_active=data.get("last_active"),
88
+ status=data.get("status", "active")
89
+ )
90
+
91
+
92
+ AGENT_ROLE_CONFIG: Dict[AgentType, Dict[str, Any]] = {
93
+ AgentType.PRODUCT_MANAGER: {
94
+ "role": "产品经理/项目经理",
95
+ "allowed": [
96
+ ActionType.CREATE_REQUIREMENTS,
97
+ ActionType.REVIEW_DESIGN,
98
+ ActionType.SIGN_OFF,
99
+ ActionType.MANAGE_PROJECT
100
+ ],
101
+ "forbidden": [
102
+ ActionType.WRITE_CODE,
103
+ ActionType.CREATE_DESIGN
104
+ ],
105
+ "required": True,
106
+ "initial_count": 1
107
+ },
108
+ AgentType.DEVELOPMENT_LEAD: {
109
+ "role": "开发负责人",
110
+ "allowed": [
111
+ ActionType.CREATE_DESIGN,
112
+ ActionType.WRITE_CODE,
113
+ ActionType.CODE_REVIEW
114
+ ],
115
+ "forbidden": [
116
+ ],
117
+ "required": True,
118
+ "initial_count": 1
119
+ },
120
+ AgentType.FRONTEND_DEV: {
121
+ "role": "前端开发",
122
+ "allowed": [
123
+ ActionType.WRITE_CODE_FRONTEND,
124
+ ActionType.REVIEW_DESIGN_FRONTEND
125
+ ],
126
+ "forbidden": [
127
+ ActionType.WRITE_CODE_BACKEND,
128
+ ActionType.CREATE_REQUIREMENTS
129
+ ],
130
+ "required": False,
131
+ "initial_count": 0
132
+ },
133
+ AgentType.BACKEND_DEV: {
134
+ "role": "后端开发",
135
+ "allowed": [
136
+ ActionType.WRITE_CODE_BACKEND,
137
+ ActionType.API_DESIGN
138
+ ],
139
+ "forbidden": [
140
+ ActionType.WRITE_CODE_FRONTEND,
141
+ ActionType.CREATE_REQUIREMENTS
142
+ ],
143
+ "required": False,
144
+ "initial_count": 0
145
+ },
146
+ AgentType.DESIGNER: {
147
+ "role": "UI/UE 设计",
148
+ "allowed": [
149
+ ActionType.CREATE_DESIGN,
150
+ ActionType.UPLOAD_DESIGN,
151
+ ActionType.REVIEW_DESIGN
152
+ ],
153
+ "forbidden": [
154
+ ActionType.WRITE_CODE,
155
+ ActionType.CREATE_REQUIREMENTS
156
+ ],
157
+ "required": False,
158
+ "initial_count": 0
159
+ },
160
+ AgentType.TESTER: {
161
+ "role": "测试",
162
+ "allowed": [
163
+ ActionType.EXECUTE_TEST,
164
+ ActionType.REVIEW_DESIGN
165
+ ],
166
+ "forbidden": [
167
+ ActionType.WRITE_CODE,
168
+ ActionType.CREATE_REQUIREMENTS,
169
+ ActionType.CREATE_DESIGN
170
+ ],
171
+ "required": False,
172
+ "initial_count": 0
173
+ }
174
+ }
175
+
176
+
177
+ class AgentManagerError(Exception):
178
+ """Agent 管理异常基类。"""
179
+ pass
180
+
181
+
182
+ class AgentNotFoundError(AgentManagerError):
183
+ """Agent 未找到异常。"""
184
+ pass
185
+
186
+
187
+ class AgentTypeNotSupportedError(AgentManagerError):
188
+ """Agent 类型不支持异常。"""
189
+ pass
190
+
191
+
192
+ class AgentConstraintViolationError(AgentManagerError):
193
+ """Agent 约束违反异常。"""
194
+ pass
195
+
196
+
197
+ class AgentManager:
198
+ """Agent 管理器。"""
199
+
200
+ DEFAULT_AGENTS_DIR = "agents"
201
+ AGENT_CONFIG_FILE = "agent_config.yaml"
202
+
203
+ def __init__(self, project_path: str, agents_dir: Optional[str] = None):
204
+ """初始化 Agent 管理器。
205
+
206
+ Args:
207
+ project_path: 项目路径
208
+ agents_dir: Agent 配置目录,默认为 project_path/agents
209
+ """
210
+ self.project_path = Path(project_path)
211
+ self.agents_dir = self.project_path / (agents_dir or self.DEFAULT_AGENTS_DIR)
212
+ self.agents: Dict[str, AgentConfig] = {}
213
+ self._ensure_agents_directory()
214
+
215
+ def _ensure_agents_directory(self) -> None:
216
+ """确保 Agent 目录存在。"""
217
+ self.agents_dir.mkdir(parents=True, exist_ok=True)
218
+
219
+ def _generate_agent_id(self, agent_type: AgentType, tech_stack: Optional[str] = None) -> str:
220
+ """生成 Agent ID。
221
+
222
+ Args:
223
+ agent_type: Agent 类型
224
+ tech_stack: 技术栈(可选)
225
+
226
+ Returns:
227
+ Agent ID
228
+ """
229
+ base_name = agent_type.value
230
+ if tech_stack:
231
+ base_name = f"{base_name}_{tech_stack}"
232
+ existing_count = sum(
233
+ 1 for a in self.agents.values()
234
+ if a.agent_type == agent_type and (a.tech_stack or "") == (tech_stack or "")
235
+ )
236
+ return f"agent_{base_name}_{existing_count + 1}"
237
+
238
+ def _create_default_agents(self) -> List[AgentConfig]:
239
+ """创建默认的 Agent 列表。
240
+
241
+ Returns:
242
+ 默认 Agent 列表
243
+ """
244
+ agents = []
245
+
246
+ for agent_type, config in AGENT_ROLE_CONFIG.items():
247
+ for i in range(config["initial_count"]):
248
+ agent_id = self._generate_agent_id(agent_type)
249
+ agent = AgentConfig(
250
+ agent_id=agent_id,
251
+ agent_type=agent_type,
252
+ name=f"{config['role']} {i + 1}",
253
+ role=config["role"],
254
+ responsibilities=config["role"].split("/"),
255
+ forbidden=[a.value for a in config["forbidden"]],
256
+ tech_stack=None
257
+ )
258
+ agents.append(agent)
259
+
260
+ return agents
261
+
262
+ def initialize_agents(self, custom_agents: Optional[List[AgentConfig]] = None) -> List[AgentConfig]:
263
+ """初始化 Agent。
264
+
265
+ Args:
266
+ custom_agents: 自定义 Agent 列表
267
+
268
+ Returns:
269
+ 初始化后的 Agent 列表
270
+ """
271
+ if custom_agents:
272
+ agents = custom_agents
273
+ else:
274
+ agents = self._create_default_agents()
275
+
276
+ for agent in agents:
277
+ self.agents[agent.agent_id] = agent
278
+ self._save_agent_config(agent)
279
+
280
+ logger.info(f"初始化了 {len(agents)} 个 Agent")
281
+ return agents
282
+
283
+ def _save_agent_config(self, agent: AgentConfig) -> None:
284
+ """保存 Agent 配置。
285
+
286
+ Args:
287
+ agent: Agent 配置
288
+ """
289
+ config_file = self.agents_dir / f"{agent.agent_id}.yaml"
290
+ with open(config_file, 'w', encoding='utf-8') as f:
291
+ yaml.dump(agent.to_dict(), f, allow_unicode=True)
292
+
293
+ def load_agents(self) -> List[AgentConfig]:
294
+ """加载所有 Agent 配置。
295
+
296
+ Returns:
297
+ Agent 配置列表
298
+ """
299
+ self.agents.clear()
300
+
301
+ for config_file in self.agents_dir.glob("*.yaml"):
302
+ try:
303
+ with open(config_file, 'r', encoding='utf-8') as f:
304
+ data = yaml.safe_load(f)
305
+ if data:
306
+ agent = AgentConfig.from_dict(data)
307
+ self.agents[agent.agent_id] = agent
308
+ except Exception as e:
309
+ logger.warning(f"加载 Agent 配置失败: {config_file}, 错误: {e}")
310
+
311
+ return list(self.agents.values())
312
+
313
+ def add_agent(
314
+ self,
315
+ agent_type: AgentType,
316
+ tech_stack: Optional[str] = None,
317
+ name: Optional[str] = None
318
+ ) -> AgentConfig:
319
+ """添加新 Agent。
320
+
321
+ Args:
322
+ agent_type: Agent 类型
323
+ tech_stack: 技术栈(可选)
324
+ name: Agent 名称(可选)
325
+
326
+ Returns:
327
+ 新创建的 Agent 配置
328
+
329
+ Raises:
330
+ AgentTypeNotSupportedError: Agent 类型不支持
331
+ """
332
+ if agent_type not in AGENT_ROLE_CONFIG:
333
+ raise AgentTypeNotSupportedError(f"不支持的 Agent 类型: {agent_type}")
334
+
335
+ role_config = AGENT_ROLE_CONFIG[agent_type]
336
+ agent_id = self._generate_agent_id(agent_type, tech_stack)
337
+
338
+ agent = AgentConfig(
339
+ agent_id=agent_id,
340
+ agent_type=agent_type,
341
+ name=name or f"{role_config['role']} {len([a for a in self.agents.values() if a.agent_type == agent_type]) + 1}",
342
+ role=role_config["role"],
343
+ responsibilities=role_config["role"].split("/"),
344
+ forbidden=[a.value for a in role_config["forbidden"]],
345
+ tech_stack=tech_stack
346
+ )
347
+
348
+ self.agents[agent.agent_id] = agent
349
+ self._save_agent_config(agent)
350
+
351
+ logger.info(f"添加了新 Agent: {agent_id} ({agent_type.value})")
352
+ return agent
353
+
354
+ def remove_agent(self, agent_id: str) -> bool:
355
+ """移除 Agent。
356
+
357
+ Args:
358
+ agent_id: Agent ID
359
+
360
+ Returns:
361
+ 是否成功移除
362
+
363
+ Raises:
364
+ AgentNotFoundError: Agent 未找到
365
+ """
366
+ if agent_id not in self.agents:
367
+ raise AgentNotFoundError(f"Agent 未找到: {agent_id}")
368
+
369
+ agent = self.agents.pop(agent_id)
370
+ config_file = self.agents_dir / f"{agent_id}.yaml"
371
+
372
+ if config_file.exists():
373
+ config_file.unlink()
374
+
375
+ logger.info(f"移除了 Agent: {agent_id}")
376
+ return True
377
+
378
+ def get_agent(self, agent_id: str) -> AgentConfig:
379
+ """获取 Agent 配置。
380
+
381
+ Args:
382
+ agent_id: Agent ID
383
+
384
+ Returns:
385
+ Agent 配置
386
+
387
+ Raises:
388
+ AgentNotFoundError: Agent 未找到
389
+ """
390
+ if agent_id not in self.agents:
391
+ raise AgentNotFoundError(f"Agent 未找到: {agent_id}")
392
+ return self.agents[agent_id]
393
+
394
+ def list_agents(self, agent_type: Optional[AgentType] = None, status: Optional[str] = None) -> List[AgentConfig]:
395
+ """列出 Agent。
396
+
397
+ Args:
398
+ agent_type: Agent 类型过滤
399
+ status: 状态过滤
400
+
401
+ Returns:
402
+ Agent 配置列表
403
+ """
404
+ agents = list(self.agents.values())
405
+
406
+ if agent_type:
407
+ agents = [a for a in agents if a.agent_type == agent_type]
408
+
409
+ if status:
410
+ agents = [a for a in agents if a.status == status]
411
+
412
+ return agents
413
+
414
+ def check_action_allowed(self, agent_id: str, action: ActionType) -> bool:
415
+ """检查 Agent 是否允许执行某个操作。
416
+
417
+ Args:
418
+ agent_id: Agent ID
419
+ action: 操作类型
420
+
421
+ Returns:
422
+ 是否允许
423
+
424
+ Raises:
425
+ AgentNotFoundError: Agent 未找到
426
+ """
427
+ agent = self.get_agent(agent_id)
428
+
429
+ if action.value in agent.forbidden:
430
+ return False
431
+
432
+ if agent.agent_type in AGENT_ROLE_CONFIG:
433
+ role_config = AGENT_ROLE_CONFIG[agent.agent_type]
434
+ return action in role_config["allowed"]
435
+
436
+ return True
437
+
438
+ def get_allowed_actions(self, agent_id: str) -> Set[ActionType]:
439
+ """获取 Agent 允许的操作列表。
440
+
441
+ Args:
442
+ agent_id: Agent ID
443
+
444
+ Returns:
445
+ 允许的操作集合
446
+
447
+ Raises:
448
+ AgentNotFoundError: Agent 未找到
449
+ """
450
+ agent = self.get_agent(agent_id)
451
+
452
+ if agent.agent_type in AGENT_ROLE_CONFIG:
453
+ return set(AGENT_ROLE_CONFIG[agent.agent_type]["allowed"])
454
+
455
+ return set()
456
+
457
+ def get_forbidden_actions(self, agent_id: str) -> Set[ActionType]:
458
+ """获取 Agent 被禁止的操作列表。
459
+
460
+ Args:
461
+ agent_id: Agent ID
462
+
463
+ Returns:
464
+ 被禁止的操作集合
465
+
466
+ Raises:
467
+ AgentNotFoundError: Agent 未找到
468
+ """
469
+ agent = self.get_agent(agent_id)
470
+ return set(ActionType(a) for a in agent.forbidden)
471
+
472
+ def update_agent_status(self, agent_id: str, status: str) -> AgentConfig:
473
+ """更新 Agent 状态。
474
+
475
+ Args:
476
+ agent_id: Agent ID
477
+ status: 新状态
478
+
479
+ Returns:
480
+ 更新后的 Agent 配置
481
+
482
+ Raises:
483
+ AgentNotFoundError: Agent 未找到
484
+ """
485
+ agent = self.get_agent(agent_id)
486
+ agent.status = status
487
+ self._save_agent_config(agent)
488
+
489
+ return agent
490
+
491
+ def get_agent_summary(self) -> Dict[str, Any]:
492
+ """获取 Agent 管理摘要。
493
+
494
+ Returns:
495
+ 摘要信息
496
+ """
497
+ agent_counts = {}
498
+ for agent_type in AgentType:
499
+ count = len(self.list_agents(agent_type=agent_type))
500
+ agent_counts[agent_type.value] = count
501
+
502
+ return {
503
+ "total_agents": len(self.agents),
504
+ "by_type": agent_counts,
505
+ "agents_dir": str(self.agents_dir)
506
+ }
507
+
508
+ def export_config(self, output_path: Optional[str] = None) -> Dict[str, Any]:
509
+ """导出 Agent 管理配置。
510
+
511
+ Args:
512
+ output_path: 输出路径(可选)
513
+
514
+ Returns:
515
+ 配置字典
516
+ """
517
+ config = {
518
+ "project_path": str(self.project_path),
519
+ "agents_dir": str(self.agents_dir),
520
+ "agents": [agent.to_dict() for agent in self.agents.values()],
521
+ "agent_types": {
522
+ at.value: {
523
+ "role": AGENT_ROLE_CONFIG[at]["role"],
524
+ "required": AGENT_ROLE_CONFIG[at]["required"]
525
+ }
526
+ for at in AgentType
527
+ }
528
+ }
529
+
530
+ if output_path:
531
+ with open(output_path, 'w', encoding='utf-8') as f:
532
+ yaml.dump(config, f, allow_unicode=True)
533
+
534
+ return config
535
+
536
+
537
+ if __name__ == "__main__":
538
+ import tempfile
539
+
540
+ with tempfile.TemporaryDirectory() as tmpdir:
541
+ manager = AgentManager(tmpdir)
542
+
543
+ agents = manager.initialize_agents()
544
+ print(f"初始化了 {len(agents)} 个 Agent")
545
+
546
+ for agent in agents:
547
+ print(f" - {agent.agent_id}: {agent.role}")
548
+
549
+ new_agent = manager.add_agent(AgentType.FRONTEND_DEV, "react")
550
+ print(f"\n添加了新 Agent: {new_agent.agent_id}")
551
+
552
+ summary = manager.get_agent_summary()
553
+ print(f"\nAgent 摘要: {summary}")