auto-coder 0.1.389__py3-none-any.whl → 0.1.391__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.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

@@ -0,0 +1,287 @@
1
+ """
2
+ 文件文档模块 - 负责生成和更新 active.md 文件的文档部分
3
+ """
4
+
5
+ import re
6
+ import time
7
+ from typing import Dict, Any, Optional, Tuple
8
+ import byzerllm
9
+ from byzerllm import MetaHolder
10
+ from loguru import logger as global_logger
11
+ from autocoder.common.token_cost_caculate import TokenCostCalculator, TokenUsageStats
12
+ from autocoder.common import AutoCoderArgs
13
+
14
+
15
+ class ActiveDocuments:
16
+ """
17
+ 负责处理 active.md 文件的文档部分
18
+ """
19
+
20
+ def __init__(self, llm: byzerllm.ByzerLLM, product_mode: str = "lite"):
21
+ """
22
+ 初始化文档处理器
23
+
24
+ Args:
25
+ llm: ByzerLLM实例,用于生成文档内容
26
+ product_mode: 产品模式,用于获取模型价格信息
27
+ """
28
+ self.llm = llm
29
+ self.product_mode = product_mode
30
+ self.logger = global_logger.bind(name="ActiveDocuments")
31
+
32
+ def generate_documents(self, context: Dict[str, Any], query: str, args: AutoCoderArgs) -> Tuple[str, Dict[str, Any]]:
33
+ """
34
+ 生成文档内容
35
+
36
+ Args:
37
+ context: 目录上下文字典
38
+ query: 用户查询/需求
39
+ args: AutoCoderArgs实例,包含配置信息
40
+
41
+ Returns:
42
+ Tuple[str, Dict[str, Any]]: 生成的文档内容和token使用统计
43
+ """
44
+ try:
45
+ meta_holder = MetaHolder()
46
+ start_time = time.monotonic()
47
+
48
+ document = self.generate_document.with_llm(self.llm).with_meta(
49
+ meta_holder).run(context, query)
50
+
51
+ end_time = time.monotonic()
52
+
53
+ # 使用TokenCostCalculator跟踪token使用情况
54
+ token_calculator = TokenCostCalculator(logger_name="ActiveDocuments", args=args)
55
+ stats: TokenUsageStats = token_calculator.track_token_usage(
56
+ llm=self.llm,
57
+ meta_holder=meta_holder,
58
+ operation_name="Document Generation",
59
+ start_time=start_time,
60
+ end_time=end_time,
61
+ product_mode=self.product_mode
62
+ )
63
+
64
+ self.logger.info(f"Document Generation - Total tokens: {stats.total_tokens}, Total cost: ${stats.total_cost:.6f}")
65
+
66
+ return document, {
67
+ "total_tokens": stats.total_tokens,
68
+ "input_tokens": stats.input_tokens,
69
+ "output_tokens": stats.output_tokens,
70
+ "cost": stats.total_cost
71
+ }
72
+ except Exception as e:
73
+ self.logger.error(f"Error generating documents: {e}")
74
+ empty_stats = {
75
+ "total_tokens": 0,
76
+ "input_tokens": 0,
77
+ "output_tokens": 0,
78
+ "cost": 0.0
79
+ }
80
+ return f"生成文档内容时出错: {str(e)}", empty_stats
81
+
82
+ def extract_documents(self, content: str) -> str:
83
+ """
84
+ 从现有内容中提取文档部分
85
+
86
+ Args:
87
+ content: 现有文件内容
88
+
89
+ Returns:
90
+ str: 提取的文档部分
91
+ """
92
+ try:
93
+ # 提取文档部分
94
+ document_match = re.search(r'## 文档\s*\n(.*?)(?=\n## |$)', content, re.DOTALL)
95
+ if document_match:
96
+ document = document_match.group(1).strip()
97
+ self.logger.debug("Successfully extracted documents from existing content")
98
+ return document
99
+ else:
100
+ self.logger.warning("No documents section found in existing content")
101
+ return ""
102
+ except Exception as e:
103
+ self.logger.error(f"Error extracting documents: {e}")
104
+ return ""
105
+
106
+ def update_documents(self, context: Dict[str, Any], query: str, existing_document: str, args: AutoCoderArgs) -> Tuple[str, Dict[str, Any]]:
107
+ """
108
+ 更新现有的文档内容
109
+
110
+ Args:
111
+ context: 目录上下文字典
112
+ query: 用户查询/需求
113
+ existing_document: 现有的文档内容
114
+ args: AutoCoderArgs实例,包含配置信息
115
+
116
+ Returns:
117
+ Tuple[str, Dict[str, Any]]: 更新后的文档内容和token使用统计
118
+ """
119
+ try:
120
+ meta_holder = MetaHolder()
121
+ start_time = time.monotonic()
122
+
123
+ updated_document = self.update_document.with_llm(self.llm).with_meta(
124
+ meta_holder).run(context, query, existing_document)
125
+
126
+ end_time = time.monotonic()
127
+
128
+ # 使用TokenCostCalculator跟踪token使用情况
129
+ token_calculator = TokenCostCalculator(logger_name="ActiveDocuments", args=args)
130
+ stats: TokenUsageStats = token_calculator.track_token_usage(
131
+ llm=self.llm,
132
+ meta_holder=meta_holder,
133
+ operation_name="Update Document",
134
+ start_time=start_time,
135
+ end_time=end_time,
136
+ product_mode=self.product_mode
137
+ )
138
+
139
+ self.logger.info(f"Document Update - Total tokens: {stats.total_tokens}, Total cost: ${stats.total_cost:.6f}")
140
+
141
+ return updated_document, {
142
+ "total_tokens": stats.total_tokens,
143
+ "input_tokens": stats.input_tokens,
144
+ "output_tokens": stats.output_tokens,
145
+ "cost": stats.total_cost
146
+ }
147
+ except Exception as e:
148
+ self.logger.error(f"Error updating documents: {e}")
149
+ empty_stats = {
150
+ "total_tokens": 0,
151
+ "input_tokens": 0,
152
+ "output_tokens": 0,
153
+ "cost": 0.0
154
+ }
155
+ return f"更新文档内容时出错: {str(e)}", empty_stats
156
+
157
+ @byzerllm.prompt()
158
+ def update_document(self, context: Dict[str, Any], query: str, existing_document: str) -> str:
159
+ """
160
+ 请基于现有的"文档"部分和新的变更信息,生成一个更新后的"文档"部分。
161
+
162
+ 现有的"文档"内容:
163
+ ```
164
+ {{ existing_document }}
165
+ ```
166
+
167
+ 当前需求:
168
+ {{ query }}
169
+
170
+ 目录:{{ context.directory_path }}
171
+
172
+ 相关文件:
173
+ {% for file in context.changed_files %}
174
+ - {{ file.path }}
175
+ {% endfor %}
176
+
177
+ {% if context.current_files %}
178
+ 当前目录中的其他相关文件:
179
+ {% for file in context.current_files %}
180
+ - {{ file.path }}
181
+ {% endfor %}
182
+ {% endif %}
183
+
184
+ {% if context.file_diffs %}
185
+ 文件变更摘要:
186
+ {% for diff in context.file_diffs %}
187
+ - {{ diff.path }}: {% if diff.type == 'modified' %}修改 (从{{ diff.before_lines }}行到{{ diff.after_lines }}行){% elif diff.type == 'added' %}新增{% elif diff.type == 'deleted' %}删除{% endif %}
188
+ {% endfor %}
189
+ {% endif %}
190
+
191
+ {% if context.changed_files and context.changed_files[0].has_diff %}
192
+ 变更前后的代码对比:
193
+ {% for file in context.changed_files %}
194
+ {% if file.has_diff %}
195
+ 文件: {{ file.path }}
196
+ 变更前:
197
+ ```
198
+ {{ file.before_content }}
199
+ ```
200
+
201
+ 变更后:
202
+ ```
203
+ {{ file.after_content }}
204
+ ```
205
+ {% endif %}
206
+ {% endfor %}
207
+ {% endif %}
208
+
209
+ 请执行以下任务:
210
+ 1. 保留现有文档中的准确信息
211
+ 2. 更新每个文件的文档,反映最新的变更
212
+ 3. 如果有新文件,为其创建完整的文档
213
+ 4. 确保文档格式一致性,每个文件的文档包含:功能、关键组件、变更影响、与其他文件的关系
214
+ 5. 如有冲突信息,优先保留最新信息,但保留历史上下文
215
+
216
+ 格式应为:
217
+
218
+ ### [文件名]
219
+ - **功能**:
220
+ - **关键组件**:
221
+ - **变更影响**:
222
+ - **关系**:
223
+
224
+ 你的回答应该是一个完整的"文档"部分内容,不需要包含标题。
225
+ """
226
+
227
+ @byzerllm.prompt()
228
+ def generate_document(self, context: Dict[str, Any], query: str) -> str:
229
+ """
230
+ 请为下面列出的每个文件生成详细的文档说明。
231
+
232
+ 需求:
233
+ {{ query }}
234
+
235
+ 目录:{{ context.directory_path }}
236
+
237
+ 文件列表:
238
+ {% for file in context.changed_files %}
239
+ - {{ file.path }}
240
+ {% endfor %}
241
+
242
+ {% if context.current_files %}
243
+ 当前目录中的其他相关文件:
244
+ {% for file in context.current_files %}
245
+ - {{ file.path }}
246
+ {% endfor %}
247
+ {% endif %}
248
+
249
+ {% if context.file_diffs %}
250
+ 文件变更摘要:
251
+ {% for diff in context.file_diffs %}
252
+ - {{ diff.path }}: {% if diff.type == 'modified' %}修改 (从{{ diff.before_lines }}行到{{ diff.after_lines }}行){% elif diff.type == 'added' %}新增{% elif diff.type == 'deleted' %}删除{% endif %}
253
+ {% endfor %}
254
+ {% endif %}
255
+
256
+ {% if context.changed_files and context.changed_files[0].has_diff %}
257
+ 变更前后的代码对比:
258
+ {% for file in context.changed_files %}
259
+ {% if file.has_diff %}
260
+ 文件: {{ file.path }}
261
+ 变更前:
262
+ ```
263
+ {{ file.before_content }}
264
+ ```
265
+
266
+ 变更后:
267
+ ```
268
+ {{ file.after_content }}
269
+ ```
270
+ {% endif %}
271
+ {% endfor %}
272
+ {% endif %}
273
+
274
+ 对于每个文件,请提供:
275
+ 1. 文件的主要功能
276
+ 2. 文件中的关键组件(类、函数等)
277
+ 3. 此次变更对文件的影响(如果适用)
278
+ 4. 文件与其他文件的关系
279
+
280
+ 格式应为:
281
+
282
+ ### [文件名]
283
+ - **功能**:
284
+ - **关键组件**:
285
+ - **变更影响**:
286
+ - **关系**:
287
+ """
@@ -0,0 +1,88 @@
1
+ """
2
+ 活动上下文标题模块 - 负责生成和更新 active.md 文件的标题部分
3
+ """
4
+
5
+ import os
6
+ import re
7
+ from typing import Dict, Any, Optional
8
+ from loguru import logger as global_logger
9
+
10
+
11
+ class ActiveHeader:
12
+ """
13
+ 负责处理 active.md 文件的标题部分
14
+ """
15
+
16
+ def __init__(self):
17
+ """初始化活动标题处理器"""
18
+ self.logger = global_logger.bind(name="ActiveHeader")
19
+
20
+ def generate_header(self, context: Dict[str, Any]) -> str:
21
+ """
22
+ 生成活动上下文标题
23
+
24
+ Args:
25
+ context: 目录上下文字典
26
+
27
+ Returns:
28
+ str: 生成的标题内容
29
+ """
30
+ try:
31
+ # 安全获取目录名称
32
+ dir_name = os.path.basename(context.get('directory_path', '未知目录'))
33
+ header = f"# 活动上下文 - {dir_name}\n\n"
34
+
35
+ self.logger.debug(f"Generated header for directory: {dir_name}")
36
+ return header
37
+ except Exception as e:
38
+ self.logger.error(f"Error generating header: {e}")
39
+ return "# 活动上下文 - 未知目录\n\n"
40
+
41
+ def extract_header(self, content: str) -> str:
42
+ """
43
+ 从现有内容中提取标题部分
44
+
45
+ Args:
46
+ content: 现有文件内容
47
+
48
+ Returns:
49
+ str: 提取的标题部分
50
+ """
51
+ try:
52
+ # 提取标题部分(到第一个二级标题之前)
53
+ header_match = re.search(r'^(.*?)(?=\n## )', content, re.DOTALL)
54
+ if header_match:
55
+ header = header_match.group(1).strip() + "\n\n"
56
+ self.logger.debug("Successfully extracted header from existing content")
57
+ return header
58
+ else:
59
+ self.logger.warning("No header found in existing content, using default")
60
+ return "# 活动上下文\n\n"
61
+ except Exception as e:
62
+ self.logger.error(f"Error extracting header: {e}")
63
+ return "# 活动上下文\n\n"
64
+
65
+ def update_header(self, context: Dict[str, Any], existing_header: str) -> str:
66
+ """
67
+ 更新现有的标题部分
68
+
69
+ Args:
70
+ context: 目录上下文字典
71
+ existing_header: 现有的标题内容
72
+
73
+ Returns:
74
+ str: 更新后的标题内容
75
+ """
76
+ try:
77
+ # 如果现有标题包含正确的目录名,则保留;否则更新
78
+ dir_name = os.path.basename(context.get('directory_path', '未知目录'))
79
+
80
+ if dir_name in existing_header and existing_header.strip():
81
+ self.logger.debug(f"Keeping existing header for directory: {dir_name}")
82
+ return existing_header
83
+ else:
84
+ self.logger.debug(f"Updating header for directory: {dir_name}")
85
+ return self.generate_header(context)
86
+ except Exception as e:
87
+ self.logger.error(f"Error updating header: {e}")
88
+ return self.generate_header(context)