opencode-collaboration 0.2.1__tar.gz → 0.2.3__tar.gz
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-0.2.1 → opencode_collaboration-0.2.3}/PKG-INFO +1 -1
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/PKG-INFO +1 -1
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/SOURCES.txt +25 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/pyproject.toml +2 -2
- opencode_collaboration-0.2.3/src/core/__init__.py +0 -0
- opencode_collaboration-0.2.3/src/core/auto_doc_git.py +41 -0
- opencode_collaboration-0.2.3/src/core/auto_docs.py +329 -0
- opencode_collaboration-0.2.3/src/core/auto_engine.py +458 -0
- opencode_collaboration-0.2.3/src/core/auto_git_sync.py +61 -0
- opencode_collaboration-0.2.3/src/core/auto_retry.py +231 -0
- opencode_collaboration-0.2.3/src/core/brain_engine.py +387 -0
- opencode_collaboration-0.2.3/src/core/daemon.py +221 -0
- opencode_collaboration-0.2.3/src/core/detector.py +71 -0
- opencode_collaboration-0.2.3/src/core/doc_generator.py +460 -0
- opencode_collaboration-0.2.3/src/core/exception_handler.py +497 -0
- opencode_collaboration-0.2.3/src/core/git.py +258 -0
- opencode_collaboration-0.2.3/src/core/git_monitor.py +429 -0
- opencode_collaboration-0.2.3/src/core/phase_advance.py +334 -0
- opencode_collaboration-0.2.3/src/core/signoff.py +170 -0
- opencode_collaboration-0.2.3/src/core/state_machine.py +425 -0
- opencode_collaboration-0.2.3/src/core/state_manager.py +475 -0
- opencode_collaboration-0.2.3/src/core/supervisor.py +247 -0
- opencode_collaboration-0.2.3/src/core/task_executor.py +796 -0
- opencode_collaboration-0.2.3/src/core/workflow.py +165 -0
- opencode_collaboration-0.2.3/src/utils/__init__.py +0 -0
- opencode_collaboration-0.2.3/src/utils/date.py +22 -0
- opencode_collaboration-0.2.3/src/utils/file.py +51 -0
- opencode_collaboration-0.2.3/src/utils/lock.py +103 -0
- opencode_collaboration-0.2.3/src/utils/yaml.py +24 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/README.md +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/dependency_links.txt +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/entry_points.txt +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/requires.txt +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/opencode_collaboration.egg-info/top_level.txt +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/setup.cfg +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/src/__init__.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/src/cli/__init__.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/src/cli/agent.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/src/cli/main.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/src/main.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_agent_behavior.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_agent_daemon.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_agent_daemon_complete.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_agent_daemon_long_running.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_agent_daemon_true_long_running.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_detector.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_doc_generator.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_e2e.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_exception_handler.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_git_monitor.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_state_machine.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_state_manager.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_state_manager_v2.py +0 -0
- {opencode_collaboration-0.2.1 → opencode_collaboration-0.2.3}/tests/test_workflow.py +0 -0
|
@@ -11,6 +11,31 @@ src/main.py
|
|
|
11
11
|
src/cli/__init__.py
|
|
12
12
|
src/cli/agent.py
|
|
13
13
|
src/cli/main.py
|
|
14
|
+
src/core/__init__.py
|
|
15
|
+
src/core/auto_doc_git.py
|
|
16
|
+
src/core/auto_docs.py
|
|
17
|
+
src/core/auto_engine.py
|
|
18
|
+
src/core/auto_git_sync.py
|
|
19
|
+
src/core/auto_retry.py
|
|
20
|
+
src/core/brain_engine.py
|
|
21
|
+
src/core/daemon.py
|
|
22
|
+
src/core/detector.py
|
|
23
|
+
src/core/doc_generator.py
|
|
24
|
+
src/core/exception_handler.py
|
|
25
|
+
src/core/git.py
|
|
26
|
+
src/core/git_monitor.py
|
|
27
|
+
src/core/phase_advance.py
|
|
28
|
+
src/core/signoff.py
|
|
29
|
+
src/core/state_machine.py
|
|
30
|
+
src/core/state_manager.py
|
|
31
|
+
src/core/supervisor.py
|
|
32
|
+
src/core/task_executor.py
|
|
33
|
+
src/core/workflow.py
|
|
34
|
+
src/utils/__init__.py
|
|
35
|
+
src/utils/date.py
|
|
36
|
+
src/utils/file.py
|
|
37
|
+
src/utils/lock.py
|
|
38
|
+
src/utils/yaml.py
|
|
14
39
|
tests/test_agent_behavior.py
|
|
15
40
|
tests/test_agent_daemon.py
|
|
16
41
|
tests/test_agent_daemon_complete.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opencode-collaboration"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "双Agent协作框架 - 产品经理与开发的分离式协作工具"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -45,7 +45,7 @@ oc-collab = "src.cli.main:main"
|
|
|
45
45
|
|
|
46
46
|
[tool.setuptools.packages.find]
|
|
47
47
|
where = ["."]
|
|
48
|
-
include = ["src", "src.cli"]
|
|
48
|
+
include = ["src", "src.cli", "src.core", "src.utils"]
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
[tool.pytest.ini_options]
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""文档自动添加git引擎"""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, Any, List
|
|
4
|
+
import subprocess
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
class AutoDocGitAddEngine:
|
|
10
|
+
"""自动添加新文档到 git"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, project_path: str):
|
|
13
|
+
self.project_path = Path(project_path)
|
|
14
|
+
self.docs_dir = self.project_path / 'docs'
|
|
15
|
+
self.tracked_file = self.project_path / 'state' / 'tracked_docs.txt'
|
|
16
|
+
|
|
17
|
+
def detect_new_docs(self) -> List[str]:
|
|
18
|
+
"""检测新文档"""
|
|
19
|
+
result = subprocess.run(
|
|
20
|
+
['git', 'ls-files', '--others', '--exclude-standard'],
|
|
21
|
+
capture_output=True, text=True,
|
|
22
|
+
cwd=self.project_path
|
|
23
|
+
)
|
|
24
|
+
new_files = [f for f in result.stdout.strip().split('
|
|
25
|
+
') if f and f.startswith('docs/')]
|
|
26
|
+
return new_files
|
|
27
|
+
|
|
28
|
+
def auto_add_docs(self) -> Dict[str, Any]:
|
|
29
|
+
"""自动添加新文档"""
|
|
30
|
+
new_docs = self.detect_new_docs()
|
|
31
|
+
if not new_docs:
|
|
32
|
+
return {"added": [], "message": "无新文档"}
|
|
33
|
+
|
|
34
|
+
for doc in new_docs:
|
|
35
|
+
subprocess.run(['git', 'add', doc], cwd=self.project_path, capture_output=True)
|
|
36
|
+
|
|
37
|
+
return {"added": new_docs, "message": f"已添加 {len(new_docs)} 个新文档"}
|
|
38
|
+
|
|
39
|
+
def sync(self) -> Dict[str, Any]:
|
|
40
|
+
"""同步新文档"""
|
|
41
|
+
return self.auto_add_docs()
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"""文档自动同步模块。"""
|
|
2
|
+
import re
|
|
3
|
+
from typing import Dict, Any, List, Optional, Tuple
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
from ..utils.yaml import load_yaml, save_yaml
|
|
10
|
+
from ..utils.date import get_current_time
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class AutoDocsConfig:
|
|
17
|
+
"""文档自动同步配置"""
|
|
18
|
+
enabled: bool = True
|
|
19
|
+
update_changelog: bool = True
|
|
20
|
+
update_manual: bool = True
|
|
21
|
+
update_tests: bool = False
|
|
22
|
+
require_confirm: bool = True
|
|
23
|
+
auto_commit: bool = False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AutoDocs:
|
|
27
|
+
"""文档自动同步器"""
|
|
28
|
+
|
|
29
|
+
CHANGE_TYPE_MAP = {
|
|
30
|
+
"feat": "新功能",
|
|
31
|
+
"fix": "缺陷修复",
|
|
32
|
+
"docs": "文档更新",
|
|
33
|
+
"test": "测试更新",
|
|
34
|
+
"refactor": "重构",
|
|
35
|
+
"perf": "性能优化",
|
|
36
|
+
"chore": "构建/工具",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
DOC_IMPACT_MAP = {
|
|
40
|
+
"src/cli/main.py": {
|
|
41
|
+
"docs": ["docs/使用手册.md"],
|
|
42
|
+
"tests": ["tests/test_e2e.py"],
|
|
43
|
+
"changelog": True,
|
|
44
|
+
},
|
|
45
|
+
"src/core/git.py": {
|
|
46
|
+
"docs": ["docs/使用手册.md"],
|
|
47
|
+
"tests": [],
|
|
48
|
+
"changelog": True,
|
|
49
|
+
},
|
|
50
|
+
"src/core/auto_retry.py": {
|
|
51
|
+
"docs": ["docs/使用手册.md"],
|
|
52
|
+
"tests": [],
|
|
53
|
+
"changelog": True,
|
|
54
|
+
},
|
|
55
|
+
"src/core/": {
|
|
56
|
+
"docs": [],
|
|
57
|
+
"tests": [],
|
|
58
|
+
"changelog": True,
|
|
59
|
+
},
|
|
60
|
+
"docs/04-changelog/": {
|
|
61
|
+
"docs": [],
|
|
62
|
+
"tests": [],
|
|
63
|
+
"changelog": True,
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
def __init__(self, project_path: str, config: Optional[AutoDocsConfig] = None):
|
|
68
|
+
"""初始化文档自动同步器"""
|
|
69
|
+
self.project_path = Path(project_path)
|
|
70
|
+
self.config = config or AutoDocsConfig()
|
|
71
|
+
self.state_file = self.project_path / "state" / "project_state.yaml"
|
|
72
|
+
self.changelog_file = self.project_path / "docs" / "04-changelog" / "change_log.md"
|
|
73
|
+
self.manual_file = self.project_path / "docs" / "使用手册.md"
|
|
74
|
+
|
|
75
|
+
def _load_state(self) -> Dict[str, Any]:
|
|
76
|
+
"""加载状态"""
|
|
77
|
+
if self.state_file.exists():
|
|
78
|
+
return load_yaml(str(self.state_file))
|
|
79
|
+
return {}
|
|
80
|
+
|
|
81
|
+
def _save_state(self, state: Dict[str, Any]) -> None:
|
|
82
|
+
"""保存状态"""
|
|
83
|
+
self.state_file.parent.mkdir(parents=True, exist_ok=True)
|
|
84
|
+
save_yaml(str(self.state_file), state)
|
|
85
|
+
|
|
86
|
+
def _detect_change_type(self, message: str) -> str:
|
|
87
|
+
"""检测变更类型"""
|
|
88
|
+
message_lower = message.lower()
|
|
89
|
+
for prefix, name in self.CHANGE_TYPE_MAP.items():
|
|
90
|
+
if message_lower.startswith(prefix):
|
|
91
|
+
return name
|
|
92
|
+
return "其他更新"
|
|
93
|
+
|
|
94
|
+
def _extract_scope(self, message: str) -> str:
|
|
95
|
+
"""提取影响范围"""
|
|
96
|
+
match = re.search(r'\((.*?)\)', message)
|
|
97
|
+
if match:
|
|
98
|
+
return match.group(1)
|
|
99
|
+
return "系统"
|
|
100
|
+
|
|
101
|
+
def detect_changes(self, last_commit: Optional[str] = None) -> Dict[str, Any]:
|
|
102
|
+
"""
|
|
103
|
+
检测代码变更影响
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
last_commit: 上次检测的提交(可选)
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
{
|
|
110
|
+
"changed_files": [...],
|
|
111
|
+
"impacted_docs": [...],
|
|
112
|
+
"impacted_commands": [...],
|
|
113
|
+
"change_type": str,
|
|
114
|
+
}
|
|
115
|
+
"""
|
|
116
|
+
import subprocess
|
|
117
|
+
|
|
118
|
+
changed_files = []
|
|
119
|
+
impacted_docs = []
|
|
120
|
+
impacted_commands = []
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
if last_commit:
|
|
124
|
+
result = subprocess.run(
|
|
125
|
+
["git", "diff", "--name-only", last_commit, "HEAD"],
|
|
126
|
+
cwd=str(self.project_path),
|
|
127
|
+
capture_output=True,
|
|
128
|
+
text=True
|
|
129
|
+
)
|
|
130
|
+
else:
|
|
131
|
+
result = subprocess.run(
|
|
132
|
+
["git", "diff", "--cached", "--name-only"],
|
|
133
|
+
cwd=str(self.project_path),
|
|
134
|
+
capture_output=True,
|
|
135
|
+
text=True
|
|
136
|
+
)
|
|
137
|
+
if not result.stdout.strip():
|
|
138
|
+
result = subprocess.run(
|
|
139
|
+
["git", "diff", "--name-only", "HEAD~1", "HEAD"],
|
|
140
|
+
cwd=str(self.project_path),
|
|
141
|
+
capture_output=True,
|
|
142
|
+
text=True
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
changed_files = [f for f in result.stdout.strip().split('\n') if f]
|
|
146
|
+
|
|
147
|
+
except Exception as e:
|
|
148
|
+
logger.warning(f"检测变更失败: {e}")
|
|
149
|
+
|
|
150
|
+
for file_path in changed_files:
|
|
151
|
+
for pattern, impact in self.DOC_IMPACT_MAP.items():
|
|
152
|
+
if file_path.startswith(pattern):
|
|
153
|
+
impacted_docs.extend(impact.get("docs", []))
|
|
154
|
+
if "cli/main.py" in file_path:
|
|
155
|
+
impacted_commands.extend(self._extract_commands_from_diff(file_path))
|
|
156
|
+
break
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
"changed_files": list(set(changed_files)),
|
|
160
|
+
"impacted_docs": list(set(impacted_docs)),
|
|
161
|
+
"impacted_commands": list(set(impacted_commands)),
|
|
162
|
+
"change_type": "代码更新",
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
def _extract_commands_from_diff(self, file_path: str) -> List[str]:
|
|
166
|
+
"""从 diff 中提取新增的命令"""
|
|
167
|
+
import subprocess
|
|
168
|
+
|
|
169
|
+
commands = []
|
|
170
|
+
try:
|
|
171
|
+
result = subprocess.run(
|
|
172
|
+
["git", "diff", "HEAD~1", file_path],
|
|
173
|
+
cwd=str(self.project_path),
|
|
174
|
+
capture_output=True,
|
|
175
|
+
text=True
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
new_commands = re.findall(r'@main\.command\(["\'](.+?)["\']\)', result.stdout)
|
|
179
|
+
commands = list(set(new_commands))
|
|
180
|
+
|
|
181
|
+
except Exception as e:
|
|
182
|
+
logger.warning(f"提取命令失败: {e}")
|
|
183
|
+
|
|
184
|
+
return commands
|
|
185
|
+
|
|
186
|
+
def update_changelog(self, change_type: str, message: str) -> bool:
|
|
187
|
+
"""更新变更记录"""
|
|
188
|
+
if not self.changelog_file.exists():
|
|
189
|
+
logger.warning(f"变更记录文件不存在: {self.changelog_file}")
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
with open(self.changelog_file, 'r', encoding='utf-8') as f:
|
|
194
|
+
content = f.read()
|
|
195
|
+
|
|
196
|
+
today = datetime.now().strftime("%Y-%m-%d")
|
|
197
|
+
scope = self._extract_scope(message)
|
|
198
|
+
|
|
199
|
+
new_entry = f"""
|
|
200
|
+
| v.next | {today} | {change_type} | {message[:50]}... | {scope} | 系统 |
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
change_type_section = f"### {change_type}"
|
|
204
|
+
if change_type_section in content:
|
|
205
|
+
content = content.replace(
|
|
206
|
+
change_type_section,
|
|
207
|
+
f"{change_type_section}\n{new_entry.strip()}"
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
sections = content.split("## ")
|
|
211
|
+
for i, section in enumerate(sections):
|
|
212
|
+
if "变更历史" in section or "变更类型" in section:
|
|
213
|
+
continue
|
|
214
|
+
|
|
215
|
+
new_section = f"## 变更历史\n\n| 版本 | 日期 | 变更类型 | 变更内容 | 变更原因 | 决策人 |\n|-----|------|---------|---------|---------|--------|\n{new_entry}\n"
|
|
216
|
+
content = new_section + "\n".join(sections[1:])
|
|
217
|
+
|
|
218
|
+
with open(self.changelog_file, 'w', encoding='utf-8') as f:
|
|
219
|
+
f.write(content)
|
|
220
|
+
|
|
221
|
+
logger.info(f"✓ 已更新变更记录")
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
except Exception as e:
|
|
225
|
+
logger.error(f"更新变更记录失败: {e}")
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
def update_manual(self, command: str, description: str = "") -> bool:
|
|
229
|
+
"""更新使用手册"""
|
|
230
|
+
if not self.manual_file.exists():
|
|
231
|
+
logger.warning(f"使用手册不存在: {self.manual_file}")
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
try:
|
|
235
|
+
with open(self.manual_file, 'r', encoding='utf-8') as f:
|
|
236
|
+
content = f.read()
|
|
237
|
+
|
|
238
|
+
new_section = f"""
|
|
239
|
+
### 4.X {command}
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
oc-collab {command}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**功能**:
|
|
246
|
+
- {description if description else "自动化执行"}
|
|
247
|
+
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
section_pattern = r'(### 4\.\d+ help - 帮助信息)'
|
|
251
|
+
if re.search(section_pattern, content):
|
|
252
|
+
content = re.sub(
|
|
253
|
+
section_pattern,
|
|
254
|
+
f"{new_section.strip()}\n\n\\1",
|
|
255
|
+
content,
|
|
256
|
+
count=1
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
with open(self.manual_file, 'w', encoding='utf-8') as f:
|
|
260
|
+
f.write(content)
|
|
261
|
+
|
|
262
|
+
logger.info(f"✓ 已更新使用手册(新增 {command})")
|
|
263
|
+
return True
|
|
264
|
+
else:
|
|
265
|
+
logger.warning("未找到帮助信息章节,无法插入")
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
except Exception as e:
|
|
269
|
+
logger.error(f"更新使用手册失败: {e}")
|
|
270
|
+
return False
|
|
271
|
+
|
|
272
|
+
def preview_updates(self) -> str:
|
|
273
|
+
"""预览待更新内容"""
|
|
274
|
+
changes = self.detect_changes()
|
|
275
|
+
|
|
276
|
+
preview = []
|
|
277
|
+
preview.append("=== 文档更新预览 ===\n")
|
|
278
|
+
preview.append(f"变更文件: {len(changes['changed_files'])}")
|
|
279
|
+
|
|
280
|
+
if changes['changed_files']:
|
|
281
|
+
preview.append("\n受影响的文件:")
|
|
282
|
+
for f in changes['changed_files'][:10]:
|
|
283
|
+
preview.append(f" - {f}")
|
|
284
|
+
|
|
285
|
+
if changes['impacted_docs']:
|
|
286
|
+
preview.append("\n需要更新的文档:")
|
|
287
|
+
for d in changes['impacted_docs']:
|
|
288
|
+
preview.append(f" - {d}")
|
|
289
|
+
|
|
290
|
+
preview.append(f"\n变更类型: {changes['change_type']}")
|
|
291
|
+
|
|
292
|
+
return '\n'.join(preview)
|
|
293
|
+
|
|
294
|
+
def apply_updates(self, message: str, confirmed: bool = False) -> Dict[str, bool]:
|
|
295
|
+
"""
|
|
296
|
+
应用文档更新
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
message: 提交信息
|
|
300
|
+
confirmed: 是否已确认
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
{
|
|
304
|
+
"changelog": bool,
|
|
305
|
+
"manual": bool,
|
|
306
|
+
}
|
|
307
|
+
"""
|
|
308
|
+
if not self.config.enabled:
|
|
309
|
+
logger.info("文档自动同步已禁用")
|
|
310
|
+
return {"changelog": False, "manual": False}
|
|
311
|
+
|
|
312
|
+
if self.config.require_confirm and not confirmed:
|
|
313
|
+
preview = self.preview_updates()
|
|
314
|
+
logger.info(f"\n{preview}")
|
|
315
|
+
logger.info("\n请使用 --apply 选项确认应用更新")
|
|
316
|
+
return {"changelog": False, "manual": False}
|
|
317
|
+
|
|
318
|
+
results = {}
|
|
319
|
+
|
|
320
|
+
if self.config.update_changelog:
|
|
321
|
+
change_type = self._detect_change_type(message)
|
|
322
|
+
results["changelog"] = self.update_changelog(change_type, message)
|
|
323
|
+
|
|
324
|
+
if self.config.update_manual:
|
|
325
|
+
commands = self.detect_changes().get("impacted_commands", [])
|
|
326
|
+
for cmd in commands:
|
|
327
|
+
results["manual"] = self.update_manual(cmd)
|
|
328
|
+
|
|
329
|
+
return results
|