opencode-collaboration 2.1.0__py3-none-any.whl → 2.2.0.post1__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.
- opencode_collaboration-2.2.0.post1.dist-info/METADATA +136 -0
- {opencode_collaboration-2.1.0.dist-info → opencode_collaboration-2.2.0.post1.dist-info}/RECORD +10 -5
- src/core/agent_manager.py +553 -0
- src/core/meeting_manager.py +502 -0
- src/core/project_manager.py +549 -0
- src/core/resource_lock.py +468 -0
- src/core/story_manager.py +712 -0
- opencode_collaboration-2.1.0.dist-info/METADATA +0 -99
- {opencode_collaboration-2.1.0.dist-info → opencode_collaboration-2.2.0.post1.dist-info}/WHEEL +0 -0
- {opencode_collaboration-2.1.0.dist-info → opencode_collaboration-2.2.0.post1.dist-info}/entry_points.txt +0 -0
- {opencode_collaboration-2.1.0.dist-info → opencode_collaboration-2.2.0.post1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
"""会议管理模块 - v2.2.0 M3 会议管理
|
|
2
|
+
|
|
3
|
+
提供会议创建、导入、列表、详情、纪要生成等功能。
|
|
4
|
+
"""
|
|
5
|
+
import uuid
|
|
6
|
+
import os
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Dict, List, Optional
|
|
11
|
+
import yaml
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MeetingType(Enum):
|
|
21
|
+
"""会议类型枚举。"""
|
|
22
|
+
AGENT_DISCUSSION = "agent_discussion" # Agent 间讨论
|
|
23
|
+
CUSTOMER_MEETING = "customer_meeting" # 产品经理与客户讨论
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MeetingStatus(Enum):
|
|
27
|
+
"""会议状态枚举。"""
|
|
28
|
+
DRAFT = "draft" # 草稿
|
|
29
|
+
IN_PROGRESS = "in_progress" # 进行中
|
|
30
|
+
COMPLETED = "completed" # 已完成
|
|
31
|
+
ARCHIVED = "archived" # 已归档
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class MeetingAttachment:
|
|
36
|
+
"""会议附件。"""
|
|
37
|
+
filename: str
|
|
38
|
+
file_path: str
|
|
39
|
+
file_type: str # mp3, wav, txt, pdf, etc.
|
|
40
|
+
upload_time: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
41
|
+
size: int = 0
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
44
|
+
return {
|
|
45
|
+
"filename": self.filename,
|
|
46
|
+
"file_path": self.file_path,
|
|
47
|
+
"file_type": self.file_type,
|
|
48
|
+
"upload_time": self.upload_time,
|
|
49
|
+
"size": self.size
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class Meeting:
|
|
55
|
+
"""会议。"""
|
|
56
|
+
meeting_id: str
|
|
57
|
+
title: str
|
|
58
|
+
meeting_type: MeetingType
|
|
59
|
+
version: str
|
|
60
|
+
participants: List[str] = field(default_factory=list)
|
|
61
|
+
date: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
62
|
+
decisions: List[str] = field(default_factory=list)
|
|
63
|
+
action_items: List[str] = field(default_factory=list)
|
|
64
|
+
attachments: List[MeetingAttachment] = field(default_factory=list)
|
|
65
|
+
status: MeetingStatus = MeetingStatus.DRAFT
|
|
66
|
+
summary: Optional[str] = None
|
|
67
|
+
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
68
|
+
updated_at: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
69
|
+
|
|
70
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
71
|
+
return {
|
|
72
|
+
"meeting_id": self.meeting_id,
|
|
73
|
+
"title": self.title,
|
|
74
|
+
"meeting_type": self.meeting_type.value,
|
|
75
|
+
"version": self.version,
|
|
76
|
+
"participants": self.participants,
|
|
77
|
+
"date": self.date,
|
|
78
|
+
"decisions": self.decisions,
|
|
79
|
+
"action_items": self.action_items,
|
|
80
|
+
"attachments": [a.to_dict() for a in self.attachments],
|
|
81
|
+
"status": self.status.value,
|
|
82
|
+
"summary": self.summary,
|
|
83
|
+
"created_at": self.created_at,
|
|
84
|
+
"updated_at": self.updated_at
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Meeting":
|
|
89
|
+
return cls(
|
|
90
|
+
meeting_id=data["meeting_id"],
|
|
91
|
+
title=data["title"],
|
|
92
|
+
meeting_type=MeetingType(data["meeting_type"]),
|
|
93
|
+
version=data["version"],
|
|
94
|
+
participants=data.get("participants", []),
|
|
95
|
+
date=data.get("date", datetime.now().isoformat()),
|
|
96
|
+
decisions=data.get("decisions", []),
|
|
97
|
+
action_items=data.get("action_items", []),
|
|
98
|
+
attachments=[
|
|
99
|
+
MeetingAttachment(**a) for a in data.get("attachments", [])
|
|
100
|
+
],
|
|
101
|
+
status=MeetingStatus(data.get("status", "draft")),
|
|
102
|
+
summary=data.get("summary"),
|
|
103
|
+
created_at=data.get("created_at", datetime.now().isoformat()),
|
|
104
|
+
updated_at=data.get("updated_at", datetime.now().isoformat())
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class MeetingManagerError(Exception):
|
|
109
|
+
"""会议管理异常基类。"""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class MeetingNotFoundError(MeetingManagerError):
|
|
114
|
+
"""会议未找到异常。"""
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class MeetingManager:
|
|
119
|
+
"""会议管理器。"""
|
|
120
|
+
|
|
121
|
+
DEFAULT_MEETINGS_DIR = "meetings"
|
|
122
|
+
MEETINGS_FILE = "meetings.yaml"
|
|
123
|
+
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
project_path: str,
|
|
127
|
+
meetings_dir: Optional[str] = None,
|
|
128
|
+
meetings_file: Optional[str] = None
|
|
129
|
+
):
|
|
130
|
+
"""初始化会议管理器。
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
project_path: 项目路径
|
|
134
|
+
meetings_dir: 会议附件目录
|
|
135
|
+
meetings_file: 会议数据文件
|
|
136
|
+
"""
|
|
137
|
+
self.project_path = Path(project_path)
|
|
138
|
+
self.meetings_dir = self.project_path / (meetings_dir or self.DEFAULT_MEETINGS_DIR)
|
|
139
|
+
self.meetings_file = self.project_path / (meetings_file or self.MEETINGS_FILE)
|
|
140
|
+
self.meetings: Dict[str, Meeting] = {}
|
|
141
|
+
self._ensure_directories()
|
|
142
|
+
self._load_meetings()
|
|
143
|
+
|
|
144
|
+
def _ensure_directories(self) -> None:
|
|
145
|
+
"""确保目录存在。"""
|
|
146
|
+
self.meetings_dir.mkdir(parents=True, exist_ok=True)
|
|
147
|
+
|
|
148
|
+
def _load_meetings(self) -> None:
|
|
149
|
+
"""加载会议数据。"""
|
|
150
|
+
if self.meetings_file.exists():
|
|
151
|
+
try:
|
|
152
|
+
with open(self.meetings_file, 'r', encoding='utf-8') as f:
|
|
153
|
+
data = yaml.safe_load(f)
|
|
154
|
+
if data and "meetings" in data:
|
|
155
|
+
for meeting_data in data.get("meetings", []):
|
|
156
|
+
meeting = Meeting.from_dict(meeting_data)
|
|
157
|
+
self.meetings[meeting.meeting_id] = meeting
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.warning(f"加载会议数据失败: {e}")
|
|
160
|
+
|
|
161
|
+
def _save_meetings(self) -> None:
|
|
162
|
+
"""保存会议数据。"""
|
|
163
|
+
data = {
|
|
164
|
+
"meetings": [m.to_dict() for m in self.meetings.values()],
|
|
165
|
+
"updated_at": datetime.now().isoformat()
|
|
166
|
+
}
|
|
167
|
+
with open(self.meetings_file, 'w', encoding='utf-8') as f:
|
|
168
|
+
yaml.dump(data, f, allow_unicode=True)
|
|
169
|
+
|
|
170
|
+
def create_meeting(
|
|
171
|
+
self,
|
|
172
|
+
title: str,
|
|
173
|
+
meeting_type: MeetingType,
|
|
174
|
+
version: str,
|
|
175
|
+
participants: Optional[List[str]] = None,
|
|
176
|
+
date: Optional[str] = None
|
|
177
|
+
) -> Meeting:
|
|
178
|
+
"""创建会议。
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
title: 会议标题
|
|
182
|
+
meeting_type: 会议类型
|
|
183
|
+
version: 关联版本
|
|
184
|
+
participants: 参与者
|
|
185
|
+
date: 会议日期
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
创建的会议
|
|
189
|
+
"""
|
|
190
|
+
meeting_id = f"MTG-{len(self.meetings) + 1:03d}"
|
|
191
|
+
meeting = Meeting(
|
|
192
|
+
meeting_id=meeting_id,
|
|
193
|
+
title=title,
|
|
194
|
+
meeting_type=meeting_type,
|
|
195
|
+
version=version,
|
|
196
|
+
participants=participants or [],
|
|
197
|
+
date=date or datetime.now().isoformat()
|
|
198
|
+
)
|
|
199
|
+
self.meetings[meeting_id] = meeting
|
|
200
|
+
self._save_meetings()
|
|
201
|
+
logger.info(f"创建会议: {meeting_id} - {title}")
|
|
202
|
+
return meeting
|
|
203
|
+
|
|
204
|
+
def get_meeting(self, meeting_id: str) -> Meeting:
|
|
205
|
+
"""获取会议。
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
meeting_id: 会议 ID
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
会议
|
|
212
|
+
|
|
213
|
+
Raises:
|
|
214
|
+
MeetingNotFoundError: 会议未找到
|
|
215
|
+
"""
|
|
216
|
+
if meeting_id not in self.meetings:
|
|
217
|
+
raise MeetingNotFoundError(f"会议未找到: {meeting_id}")
|
|
218
|
+
return self.meetings[meeting_id]
|
|
219
|
+
|
|
220
|
+
def list_meetings(
|
|
221
|
+
self,
|
|
222
|
+
version: Optional[str] = None,
|
|
223
|
+
status: Optional[MeetingStatus] = None,
|
|
224
|
+
meeting_type: Optional[MeetingType] = None
|
|
225
|
+
) -> List[Meeting]:
|
|
226
|
+
"""列出会议。
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
version: 版本过滤
|
|
230
|
+
status: 状态过滤
|
|
231
|
+
meeting_type: 类型过滤
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
会议列表
|
|
235
|
+
"""
|
|
236
|
+
meetings = list(self.meetings.values())
|
|
237
|
+
|
|
238
|
+
if version:
|
|
239
|
+
meetings = [m for m in meetings if m.version == version]
|
|
240
|
+
if status:
|
|
241
|
+
meetings = [m for m in meetings if m.status == status]
|
|
242
|
+
if meeting_type:
|
|
243
|
+
meetings = [m for m in meetings if m.meeting_type == meeting_type]
|
|
244
|
+
|
|
245
|
+
return sorted(meetings, key=lambda m: m.date, reverse=True)
|
|
246
|
+
|
|
247
|
+
def add_decision(self, meeting_id: str, decision: str) -> Meeting:
|
|
248
|
+
"""添加决策。
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
meeting_id: 会议 ID
|
|
252
|
+
decision: 决策内容
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
更新后的会议
|
|
256
|
+
|
|
257
|
+
Raises:
|
|
258
|
+
MeetingNotFoundError: 会议未找到
|
|
259
|
+
"""
|
|
260
|
+
meeting = self.get_meeting(meeting_id)
|
|
261
|
+
meeting.decisions.append(decision)
|
|
262
|
+
meeting.updated_at = datetime.now().isoformat()
|
|
263
|
+
self._save_meetings()
|
|
264
|
+
logger.info(f"添加决策: {meeting_id} - {decision[:50]}...")
|
|
265
|
+
return meeting
|
|
266
|
+
|
|
267
|
+
def add_action_item(self, meeting_id: str, action_item: str) -> Meeting:
|
|
268
|
+
"""添加待办事项。
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
meeting_id: 会议 ID
|
|
272
|
+
action_item: 待办事项
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
更新后的会议
|
|
276
|
+
|
|
277
|
+
Raises:
|
|
278
|
+
MeetingNotFoundError: 会议未找到
|
|
279
|
+
"""
|
|
280
|
+
meeting = self.get_meeting(meeting_id)
|
|
281
|
+
meeting.action_items.append(action_item)
|
|
282
|
+
meeting.updated_at = datetime.now().isoformat()
|
|
283
|
+
self._save_meetings()
|
|
284
|
+
logger.info(f"添加待办: {meeting_id} - {action_item[:50]}...")
|
|
285
|
+
return meeting
|
|
286
|
+
|
|
287
|
+
def upload_attachment(
|
|
288
|
+
self,
|
|
289
|
+
meeting_id: str,
|
|
290
|
+
file_path: str,
|
|
291
|
+
target_dir: Optional[str] = None
|
|
292
|
+
) -> MeetingAttachment:
|
|
293
|
+
"""上传附件。
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
meeting_id: 会议 ID
|
|
297
|
+
file_path: 源文件路径
|
|
298
|
+
target_dir: 目标目录
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
创建的附件
|
|
302
|
+
|
|
303
|
+
Raises:
|
|
304
|
+
MeetingNotFoundError: 会议未找到
|
|
305
|
+
"""
|
|
306
|
+
meeting = self.get_meeting(meeting_id)
|
|
307
|
+
|
|
308
|
+
source_path = Path(file_path)
|
|
309
|
+
if not source_path.exists():
|
|
310
|
+
raise FileNotFoundError(f"文件不存在: {file_path}")
|
|
311
|
+
|
|
312
|
+
target_directory = self.meetings_dir / meeting_id / (target_dir or "attachments")
|
|
313
|
+
target_directory.mkdir(parents=True, exist_ok=True)
|
|
314
|
+
|
|
315
|
+
target_path = target_directory / source_path.name
|
|
316
|
+
|
|
317
|
+
import shutil
|
|
318
|
+
shutil.copy2(source_path, target_path)
|
|
319
|
+
|
|
320
|
+
file_type = source_path.suffix.lower().lstrip(".")
|
|
321
|
+
attachment = MeetingAttachment(
|
|
322
|
+
filename=source_path.name,
|
|
323
|
+
file_path=str(target_path),
|
|
324
|
+
file_type=file_type,
|
|
325
|
+
size=target_path.stat().st_size
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
meeting.attachments.append(attachment)
|
|
329
|
+
meeting.updated_at = datetime.now().isoformat()
|
|
330
|
+
self._save_meetings()
|
|
331
|
+
|
|
332
|
+
logger.info(f"上传附件: {meeting_id} - {source_path.name}")
|
|
333
|
+
return attachment
|
|
334
|
+
|
|
335
|
+
def generate_summary(self, meeting_id: str) -> str:
|
|
336
|
+
"""生成会议纪要。
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
meeting_id: 会议 ID
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
会议纪要内容
|
|
343
|
+
|
|
344
|
+
Raises:
|
|
345
|
+
MeetingNotFoundError: 会议未找到
|
|
346
|
+
"""
|
|
347
|
+
meeting = self.get_meeting(meeting_id)
|
|
348
|
+
|
|
349
|
+
summary_parts = [
|
|
350
|
+
f"# {meeting.title}",
|
|
351
|
+
"",
|
|
352
|
+
f"**会议编号**: {meeting.meeting_id}",
|
|
353
|
+
f"**日期**: {meeting.date}",
|
|
354
|
+
f"**参与者**: {', '.join(meeting.participants) if meeting.participants else '无'}",
|
|
355
|
+
f"**版本**: {meeting.version}",
|
|
356
|
+
f"**状态**: {meeting.status.value}",
|
|
357
|
+
"",
|
|
358
|
+
"---",
|
|
359
|
+
"",
|
|
360
|
+
"## 关键决策",
|
|
361
|
+
""
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
for decision in meeting.decisions:
|
|
365
|
+
summary_parts.append(f"- {decision}")
|
|
366
|
+
|
|
367
|
+
summary_parts.extend([
|
|
368
|
+
"",
|
|
369
|
+
"## 待办事项",
|
|
370
|
+
""
|
|
371
|
+
])
|
|
372
|
+
|
|
373
|
+
for item in meeting.action_items:
|
|
374
|
+
summary_parts.append(f"- [ ] {item}")
|
|
375
|
+
|
|
376
|
+
if meeting.attachments:
|
|
377
|
+
summary_parts.extend([
|
|
378
|
+
"",
|
|
379
|
+
"## 附件",
|
|
380
|
+
""
|
|
381
|
+
])
|
|
382
|
+
for attachment in meeting.attachments:
|
|
383
|
+
summary_parts.append(f"- [{attachment.filename}]({attachment.file_path})")
|
|
384
|
+
|
|
385
|
+
summary = "\n".join(summary_parts)
|
|
386
|
+
meeting.summary = summary
|
|
387
|
+
meeting.status = MeetingStatus.COMPLETED
|
|
388
|
+
meeting.updated_at = datetime.now().isoformat()
|
|
389
|
+
self._save_meetings()
|
|
390
|
+
|
|
391
|
+
logger.info(f"生成会议纪要: {meeting_id}")
|
|
392
|
+
return summary
|
|
393
|
+
|
|
394
|
+
def update_meeting_status(
|
|
395
|
+
self,
|
|
396
|
+
meeting_id: str,
|
|
397
|
+
status: MeetingStatus
|
|
398
|
+
) -> Meeting:
|
|
399
|
+
"""更新会议状态。
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
meeting_id: 会议 ID
|
|
403
|
+
status: 新状态
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
更新后的会议
|
|
407
|
+
|
|
408
|
+
Raises:
|
|
409
|
+
MeetingNotFoundError: 会议未找到
|
|
410
|
+
"""
|
|
411
|
+
meeting = self.get_meeting(meeting_id)
|
|
412
|
+
meeting.status = status
|
|
413
|
+
meeting.updated_at = datetime.now().isoformat()
|
|
414
|
+
self._save_meetings()
|
|
415
|
+
logger.info(f"更新状态: {meeting_id} -> {status.value}")
|
|
416
|
+
return meeting
|
|
417
|
+
|
|
418
|
+
def get_meetings_by_version(self, version: str) -> List[Meeting]:
|
|
419
|
+
"""获取指定版本的所有会议。
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
version: 版本号
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
会议列表
|
|
426
|
+
"""
|
|
427
|
+
return self.list_meetings(version=version)
|
|
428
|
+
|
|
429
|
+
def get_meeting_summary(self) -> Dict[str, Any]:
|
|
430
|
+
"""获取会议管理摘要。
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
摘要信息
|
|
434
|
+
"""
|
|
435
|
+
by_status = {}
|
|
436
|
+
by_version = {}
|
|
437
|
+
by_type = {}
|
|
438
|
+
|
|
439
|
+
for meeting in self.meetings.values():
|
|
440
|
+
by_status[meeting.status.value] = by_status.get(meeting.status.value, 0) + 1
|
|
441
|
+
by_version[meeting.version] = by_version.get(meeting.version, 0) + 1
|
|
442
|
+
by_type[meeting.meeting_type.value] = by_type.get(meeting.meeting_type.value, 0) + 1
|
|
443
|
+
|
|
444
|
+
return {
|
|
445
|
+
"total_meetings": len(self.meetings),
|
|
446
|
+
"by_status": by_status,
|
|
447
|
+
"by_version": by_version,
|
|
448
|
+
"by_type": by_type,
|
|
449
|
+
"meetings_dir": str(self.meetings_dir)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
def export_meetings(self, output_path: Optional[str] = None) -> Dict[str, Any]:
|
|
453
|
+
"""导出会议数据。
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
output_path: 输出路径(可选)
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
会议数据字典
|
|
460
|
+
"""
|
|
461
|
+
data = {
|
|
462
|
+
"meetings": [m.to_dict() for m in self.meetings.values()],
|
|
463
|
+
"summary": self.get_meeting_summary(),
|
|
464
|
+
"exported_at": datetime.now().isoformat()
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if output_path:
|
|
468
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
469
|
+
yaml.dump(data, f, allow_unicode=True)
|
|
470
|
+
|
|
471
|
+
return data
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
if __name__ == "__main__":
|
|
475
|
+
import tempfile
|
|
476
|
+
|
|
477
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
478
|
+
manager = MeetingManager(tmpdir)
|
|
479
|
+
|
|
480
|
+
meeting = manager.create_meeting(
|
|
481
|
+
title="v2.2.0 需求讨论",
|
|
482
|
+
meeting_type=MeetingType.AGENT_DISCUSSION,
|
|
483
|
+
version="v2.2.0",
|
|
484
|
+
participants=["Agent 1", "Agent 2"]
|
|
485
|
+
)
|
|
486
|
+
print(f"创建会议: {meeting.meeting_id}")
|
|
487
|
+
|
|
488
|
+
manager.add_decision(
|
|
489
|
+
meeting.meeting_id,
|
|
490
|
+
"资源锁超时采用分层通知机制"
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
manager.add_action_item(
|
|
494
|
+
meeting.meeting_id,
|
|
495
|
+
"创建概要设计文档"
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
summary = manager.generate_summary(meeting.meeting_id)
|
|
499
|
+
print(f"\n会议纪要:\n{summary}")
|
|
500
|
+
|
|
501
|
+
summary_data = manager.get_meeting_summary()
|
|
502
|
+
print(f"\n摘要: {summary_data}")
|