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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.324
3
+ Version: 0.1.326
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -4,8 +4,8 @@ autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,
4
4
  autocoder/auto_coder_rag.py,sha256=vOqwBHdK_KwMNUUc8ji_tlZ5DoALAG1rDjWAic3rM-4,34561
5
5
  autocoder/auto_coder_rag_client_mcp.py,sha256=QRxUbjc6A8UmDMQ8lXgZkjgqtq3lgKYeatJbDY6rSo0,6270
6
6
  autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
7
- autocoder/auto_coder_runner.py,sha256=uU2FQPnG6Ze6ZLzjgbN6zFhg78cc6B7q6nbriynKe0U,107604
8
- autocoder/auto_coder_server.py,sha256=E3Z829TPSooRSNhuh3_x9yaZi0f5G0Lm0ntoZhjGaoQ,20576
7
+ autocoder/auto_coder_runner.py,sha256=hVn2Z27Frl2xAwde2DMeu6MABTgSIaEBgVGf-DAh2Dw,107421
8
+ autocoder/auto_coder_server.py,sha256=bLORGEclcVdbBVfM140JCI8WtdrU0jbgqdJIVVupiEU,20578
9
9
  autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
10
10
  autocoder/chat_auto_coder.py,sha256=SzH6fdoH8kJgARYXBu0CTB8J9PY8Q2T9CrIB844PXtM,25841
11
11
  autocoder/chat_auto_coder_lang.py,sha256=p1SUPw1_YBHK69yNViXr6iFhHL-PjFnrXExA2mXJ5ko,21655
@@ -14,7 +14,7 @@ autocoder/command_parser.py,sha256=fx1g9E6GaM273lGTcJqaFQ-hoksS_Ik2glBMnVltPCE,1
14
14
  autocoder/lang.py,sha256=U6AjVV8Rs1uLyjFCZ8sT6WWuNUxMBqkXXIOs4S120uk,14511
15
15
  autocoder/models.py,sha256=AyoZ-Pzy0oyYUmWCxOIRiOImsqboSfRET7LO9-UOuxI,11172
16
16
  autocoder/run_context.py,sha256=IUfSO6_gp2Wt1blFWAmOpN0b0nDrTTk4LmtCYUBIoro,1643
17
- autocoder/version.py,sha256=izddPEZsxPVCGodhDA8N-1QI6vTdRQsEW8KC3GOSYbs,23
17
+ autocoder/version.py,sha256=YGdEBe_w43bQfdo8_Mx3DWCOSWhBc0wXQua_nK1cUuo,23
18
18
  autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  autocoder/agent/auto_demand_organizer.py,sha256=URAq0gSEiHeV_W4zwhOI_83kHz0Ryfj1gcfh5jwCv_w,6501
20
20
  autocoder/agent/auto_filegroup.py,sha256=pBsAkBcpFTff-9L5OwI8xhf2xPKpl-aZwz-skF2B6dc,6296
@@ -102,7 +102,7 @@ autocoder/common/v2/code_auto_merge_diff.py,sha256=xh93G9Gn8zSRhGq6L90tlodFM2u-g
102
102
  autocoder/common/v2/code_auto_merge_editblock.py,sha256=FpXdHAuHhtOLXybrUd2e1rDrxqoge-CpUyWpX0yNEv8,22018
103
103
  autocoder/common/v2/code_auto_merge_strict_diff.py,sha256=jIIedNZGW52dhSmNxb3vB7UdJZp8tg59Z2gg3sCpqoM,10117
104
104
  autocoder/common/v2/code_diff_manager.py,sha256=ciXviNjldX9ce9lgIvmWoG_8JT2GnwRW8U7QCWVdAH0,10512
105
- autocoder/common/v2/code_editblock_manager.py,sha256=AUT_zbawG9nSOrMr68bSfUB5fckSFWMv4yWcBUInyXM,12221
105
+ autocoder/common/v2/code_editblock_manager.py,sha256=vnqXHKSmp6U6Kb1esSO2NRZ7j1Bh5KTaGY6ZxX-6324,11750
106
106
  autocoder/common/v2/code_manager.py,sha256=C403bS-f6urixwitlKHcml-J03hci-UyNwHJOqBiY6Q,9182
107
107
  autocoder/common/v2/code_strict_diff_manager.py,sha256=v-J1kDyLg7tLGg_6_lbO9S4fNkx7M_L8Xr2G7fPptiU,9347
108
108
  autocoder/data/byzerllm.md,sha256=SGCMpEaUQ0ysPxQsgzyyp5sgvEr8dZsxEGAfVcPBIq0,47741
@@ -143,8 +143,8 @@ autocoder/linters/reactjs_linter.py,sha256=HUDm6oNwlJ7V8l22mj_2nfZUx23m5W7-v2tgW
143
143
  autocoder/linters/shadow_linter.py,sha256=LIbv21g9DJ_gK4fAV-zSaCQdVgSoASFGmWaydokNsEg,14810
144
144
  autocoder/linters/vue_linter.py,sha256=ZyvoxT0kSizFh_UkR7UZYO5DV9edbvDQZaibEF9W95I,20905
145
145
  autocoder/memory/__init__.py,sha256=5FeGvsesRViYL4BkFiHw9SdlyHeWlqALpTyqOpfnBRw,179
146
- autocoder/memory/active_context_manager.py,sha256=HFNdXoFaQn8XhgxzIEgTFbzFw_caKfbBQud9OruJQbU,33177
147
- autocoder/memory/active_package.py,sha256=DKJgiL470iq_OsSZfi9C-_C7RbaCBOtdEIudIkkUsdQ,25456
146
+ autocoder/memory/active_context_manager.py,sha256=IhBRHK-muaN3-RCPcEY52erQpv9MtE6HNDD8JBcdBgI,33666
147
+ autocoder/memory/active_package.py,sha256=S42zypuVg2hbQ0gaeZML9PmIboJMGuijfOmdKJ1AVgo,25500
148
148
  autocoder/memory/async_processor.py,sha256=htHzLGupw9IHQAEdLe2AEaALZSItPi3AltDt8FMTRHk,4643
149
149
  autocoder/memory/directory_mapper.py,sha256=BXHblOdRpeZb7URDECALp9uN5oi91KmkW9g_UaWFuZY,2513
150
150
  autocoder/plugins/__init__.py,sha256=uc8UNSAVb9uQvr5zUSS-Xu_RhrdbO2i3w2NhkrVtODM,43023
@@ -226,9 +226,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
226
226
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
227
227
  autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=xuBeWD0YOckqRo8JB1WkVIMOYH6c24m7JfV4svBfPDo,15113
228
228
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
229
- auto_coder-0.1.324.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
230
- auto_coder-0.1.324.dist-info/METADATA,sha256=hXCMoch8Ys41G0P1nDGgYIhY70pIE4ev0x0VnBUK-y8,2747
231
- auto_coder-0.1.324.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
232
- auto_coder-0.1.324.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
233
- auto_coder-0.1.324.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
234
- auto_coder-0.1.324.dist-info/RECORD,,
229
+ auto_coder-0.1.326.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
230
+ auto_coder-0.1.326.dist-info/METADATA,sha256=aHhdCGHnZfnbnfXPguIXzw8gTa4xtOPdRMrvr3pjgbs,2747
231
+ auto_coder-0.1.326.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
232
+ auto_coder-0.1.326.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
233
+ auto_coder-0.1.326.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
234
+ auto_coder-0.1.326.dist-info/RECORD,,
@@ -1416,8 +1416,8 @@ def commit(query: str):
1416
1416
  commit_message = git_utils.generate_commit_message.with_llm(llm).run(
1417
1417
  uncommitted_changes
1418
1418
  )
1419
- memory["conversation"].append(
1420
- {"role": "user", "content": commit_message})
1419
+ # memory["conversation"].append(
1420
+ # {"role": "user", "content": commit_message})
1421
1421
  except Exception as e:
1422
1422
  printer.print_in_terminal("commit_failed", style="red", error=str(e), model_name=target_model)
1423
1423
  return
@@ -1479,7 +1479,7 @@ def coding(query: str):
1479
1479
  code_next(query)
1480
1480
  return
1481
1481
 
1482
- memory["conversation"].append({"role": "user", "content": query})
1482
+ # memory["conversation"].append({"role": "user", "content": query})
1483
1483
  conf = memory.get("conf", {})
1484
1484
 
1485
1485
  current_files = memory["current_files"]["files"]
@@ -1649,13 +1649,11 @@ def chat(query: str):
1649
1649
  if len(commands_infos) > 0:
1650
1650
  if "query" in commands_infos:
1651
1651
  query = " ".join(commands_infos["query"]["args"])
1652
- else:
1653
- # 获取第一个有位置参数的command 的最后一个位置参数作为默认query
1652
+ else:
1654
1653
  temp_query = ""
1655
1654
  for (command,command_info) in commands_infos.items():
1656
1655
  if command_info["args"]:
1657
- temp_query = " ".join(command_info["args"])
1658
- # 删除break,使循环继续,这样最后一个有args的command会覆盖之前的
1656
+ temp_query = " ".join(command_info["args"])
1659
1657
  query = temp_query
1660
1658
 
1661
1659
  is_new = "new" in commands_infos
@@ -198,7 +198,7 @@ async def delete_config(key: str):
198
198
 
199
199
  @app.post("/coding")
200
200
  async def coding(request: QueryRequest, background_tasks: BackgroundTasks):
201
- memory["conversation"].append({"role": "user", "content": request.query})
201
+ # memory["conversation"].append({"role": "user", "content": request.query})
202
202
  conf = memory.get("conf", {})
203
203
  current_files = memory["current_files"]["files"]
204
204
  request_id = str(uuid.uuid4())
@@ -39,7 +39,7 @@ class CodeEditBlockManager:
39
39
  It generates code, lints it, and if there are errors, regenerates the code up to 5 times
40
40
  before merging the final result.
41
41
  """
42
-
42
+
43
43
  def __init__(
44
44
  self,
45
45
  llm: byzerllm.ByzerLLM,
@@ -56,11 +56,12 @@ class CodeEditBlockManager:
56
56
  self.generate_times_same_model = args.generate_times_same_model
57
57
  self.max_correction_attempts = args.auto_fix_lint_max_attempts
58
58
  self.printer = Printer()
59
-
59
+
60
60
  # Initialize sub-components
61
- self.code_generator = CodeAutoGenerateEditBlock(llm, args, action, fence_0, fence_1)
61
+ self.code_generator = CodeAutoGenerateEditBlock(
62
+ llm, args, action, fence_0, fence_1)
62
63
  self.code_merger = CodeAutoMergeEditBlock(llm, args, fence_0, fence_1)
63
-
64
+
64
65
  # Create shadow manager for linting
65
66
  self.shadow_manager = ShadowManager(args.source_dir, args.event_file)
66
67
  self.shadow_linter = ShadowLinter(self.shadow_manager, verbose=False)
@@ -72,7 +73,7 @@ class CodeEditBlockManager:
72
73
  <lint_issues>
73
74
  {{ lint_issues }}
74
75
  </lint_issues>
75
-
76
+
76
77
  用户原始需求:
77
78
  <user_query_wrapper>
78
79
  {{ query }}
@@ -81,79 +82,80 @@ class CodeEditBlockManager:
81
82
  修复上述问题,请确保代码质量问题被解决,同时保持代码的原有功能。
82
83
  请严格遵守*SEARCH/REPLACE block*的格式。
83
84
  """
84
-
85
+
85
86
  def _create_shadow_files_from_edits(self, generation_result: CodeGenerateResult) -> Dict[str, str]:
86
87
  """
87
88
  从编辑块内容中提取代码并创建临时影子文件用于检查。
88
-
89
+
89
90
  参数:
90
91
  generation_result (CodeGenerateResult): 包含SEARCH/REPLACE块的内容
91
-
92
+
92
93
  返回:
93
94
  Dict[str, str]: 映射 {影子文件路径: 内容}
94
95
  """
95
96
  result = self.code_merger.choose_best_choice(generation_result)
96
- merge = self.code_merger._merge_code_without_effect(result.contents[0])
97
+ merge = self.code_merger._merge_code_without_effect(result.contents[0])
97
98
  shadow_files = {}
98
99
  for file_path, new_content in merge.success_blocks:
99
100
  self.shadow_manager.update_file(file_path, new_content)
100
- shadow_files[self.shadow_manager.to_shadow_path(file_path)] = new_content
101
+ shadow_files[self.shadow_manager.to_shadow_path(
102
+ file_path)] = new_content
101
103
 
102
104
  return shadow_files
103
105
 
104
- def _format_lint_issues(self, lint_results:ProjectLintResult,levels:List[IssueSeverity]=[IssueSeverity.ERROR]) -> str:
106
+ def _format_lint_issues(self, lint_results: ProjectLintResult, levels: List[IssueSeverity] = [IssueSeverity.ERROR]) -> str:
105
107
  """
106
108
  将linter结果格式化为字符串供模型使用
107
-
109
+
108
110
  参数:
109
111
  lint_results: Linter结果对象
110
112
  level: 过滤问题的级别
111
-
113
+
112
114
  返回:
113
115
  str: 格式化的问题描述
114
116
  """
115
117
  formatted_issues = []
116
-
117
- for file_path, result in lint_results.file_results.items():
118
+
119
+ for file_path, result in lint_results.file_results.items():
118
120
  file_has_issues = False
119
121
  file_issues = []
120
-
121
- for issue in result.issues:
122
+
123
+ for issue in result.issues:
122
124
  if issue.severity.value not in levels:
123
125
  continue
124
-
126
+
125
127
  if not file_has_issues:
126
128
  file_has_issues = True
127
129
  file_issues.append(f"文件: {file_path}")
128
-
130
+
129
131
  severity = "错误" if issue.severity == IssueSeverity.ERROR else "警告" if issue.severity == IssueSeverity.WARNING else "信息"
130
132
  line_info = f"第{issue.position.line}行"
131
133
  if issue.position.column:
132
134
  line_info += f", 第{issue.position.column}列"
133
-
135
+
134
136
  file_issues.append(
135
137
  f" - [{severity}] {line_info}: {issue.message} (规则: {issue.code})"
136
138
  )
137
-
139
+
138
140
  if file_has_issues:
139
141
  formatted_issues.extend(file_issues)
140
142
  formatted_issues.append("") # 空行分隔不同文件
141
-
143
+
142
144
  return "\n".join(formatted_issues)
143
145
 
144
- def _count_errors(self, lint_results:ProjectLintResult,levels:List[IssueSeverity]=[IssueSeverity.ERROR]) -> int:
146
+ def _count_errors(self, lint_results: ProjectLintResult, levels: List[IssueSeverity] = [IssueSeverity.ERROR]) -> int:
145
147
  """
146
148
  计算lint结果中的错误数量
147
-
149
+
148
150
  参数:
149
151
  lint_results: Linter结果对象
150
-
152
+
151
153
  返回:
152
154
  int: 错误数量
153
155
  """
154
156
  error_count = 0
155
-
156
- for _, result in lint_results.file_results.items():
157
+
158
+ for _, result in lint_results.file_results.items():
157
159
  if IssueSeverity.ERROR in levels:
158
160
  error_count += result.error_count
159
161
  if IssueSeverity.WARNING in levels:
@@ -162,25 +164,26 @@ class CodeEditBlockManager:
162
164
  error_count += result.info_count
163
165
  if IssueSeverity.HINT in levels:
164
166
  error_count += result.hint_count
165
-
167
+
166
168
  return error_count
167
169
 
168
170
  def generate_and_fix(self, query: str, source_code_list: SourceCodeList) -> CodeGenerateResult:
169
171
  """
170
172
  生成代码,运行linter,修复错误,最多尝试指定次数
171
-
173
+
172
174
  参数:
173
175
  query (str): 用户查询
174
176
  source_code_list (SourceCodeList): 源代码列表
175
-
177
+
176
178
  返回:
177
179
  CodeGenerateResult: 生成的代码结果
178
180
  """
179
181
  # 初始代码生成
180
182
  self.printer.print_in_terminal("generating_initial_code")
181
183
  start_time = time.time()
182
- generation_result = self.code_generator.single_round_run(query, source_code_list)
183
-
184
+ generation_result = self.code_generator.single_round_run(
185
+ query, source_code_list)
186
+
184
187
  token_cost_calculator = TokenCostCalculator(args=self.args)
185
188
  token_cost_calculator.track_token_usage_by_generate(
186
189
  llm=self.llm,
@@ -189,113 +192,112 @@ class CodeEditBlockManager:
189
192
  start_time=start_time,
190
193
  end_time=time.time()
191
194
  )
192
-
195
+
193
196
  # 确保结果非空
194
197
  if not generation_result.contents:
195
198
  self.printer.print_in_terminal("generation_failed", style="red")
196
199
  return generation_result
197
-
198
-
200
+
199
201
  # 最多尝试修复5次
200
202
  for attempt in range(self.max_correction_attempts):
201
203
  global_cancel.check_and_raise()
202
204
  # 代码生成结果更新到影子文件里去
203
- shadow_files = self._create_shadow_files_from_edits(generation_result)
204
-
205
+ shadow_files = self._create_shadow_files_from_edits(
206
+ generation_result)
207
+
205
208
  if not shadow_files:
206
- self.printer.print_in_terminal("no_files_to_lint", style="yellow")
209
+ self.printer.print_in_terminal(
210
+ "no_files_to_lint", style="yellow")
207
211
  break
208
-
212
+
209
213
  # 运行linter
210
214
  lint_results = self.shadow_linter.lint_all_shadow_files()
211
215
  error_count = self._count_errors(lint_results)
212
216
  # print(f"error_count: {error_count}")
213
- # print(f"lint_results: {json.dumps(lint_results.model_dump(), indent=4,ensure_ascii=False)}")
214
-
217
+ # print(f"lint_results: {json.dumps(lint_results.model_dump(), indent=4,ensure_ascii=False)}")
218
+
215
219
  # 如果没有错误则完成
216
220
  if error_count == 0:
217
- self.printer.print_in_terminal("no_lint_errors_found", style="green")
221
+ self.printer.print_in_terminal(
222
+ "no_lint_errors_found", style="green")
218
223
  break
219
224
 
220
225
  # 格式化lint问题
221
- formatted_issues = self._format_lint_issues(lint_results, [IssueSeverity.ERROR, IssueSeverity.WARNING])
226
+ formatted_issues = self._format_lint_issues(
227
+ lint_results, [IssueSeverity.ERROR, IssueSeverity.WARNING])
222
228
 
223
229
  # 打印当前错误
224
230
  self.printer.print_in_terminal(
225
- "lint_attempt_status",
226
- style="yellow",
227
- attempt=(attempt + 1),
231
+ "lint_attempt_status",
232
+ style="yellow",
233
+ attempt=(attempt + 1),
228
234
  max_correction_attempts=self.max_correction_attempts,
229
235
  error_count=error_count,
230
236
  formatted_issues=formatted_issues
231
237
  )
232
238
 
233
- get_event_manager(self.args.event_file).add_event(Event(
234
- event_type=EventType.RESULT,
235
- content=EventContentCreator.create_result(
236
- content=EventContentCreator.ResultContent(
237
- content=f"Lint attempt {attempt + 1}/{self.max_correction_attempts}: Found {error_count} issues:\n {formatted_issues}",
238
- metadata={}
239
- )
240
- ).to_dict(),
239
+ get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
240
+ content=EventContentCreator.ResultContent(content=f"Lint attempt {attempt + 1}/{self.max_correction_attempts}: Found {error_count} issues:\n {formatted_issues}",
241
+ metadata={}
242
+ ).to_dict(),
241
243
  metadata={
242
244
  "stream_out_type": LintStreamOutType.LINT.value,
243
245
  "action_file": self.args.file
244
246
  }
245
247
  ))
246
-
248
+
247
249
  if attempt == self.max_correction_attempts - 1:
248
- self.printer.print_in_terminal("max_attempts_reached", style="yellow")
250
+ self.printer.print_in_terminal(
251
+ "max_attempts_reached", style="yellow")
249
252
  break
250
-
251
-
252
-
253
+
253
254
  # 准备修复提示
254
255
  fix_prompt = self.fix_linter_errors.prompt(
255
256
  query=query,
256
257
  lint_issues=formatted_issues
257
258
  )
258
-
259
+
259
260
  # for source in source_code_list.sources:
260
- # print(f"file_path: {source.module_name}")
261
+ # print(f"file_path: {source.module_name}")
261
262
  # print(f"fix_prompt: {fix_prompt}")
262
-
263
+
263
264
  # 将 shadow_files 转化为 source_code_list
264
265
  start_time = time.time()
265
- source_code_list = self.code_merger.get_source_code_list_from_shadow_files(shadow_files)
266
- generation_result = self.code_generator.single_round_run(fix_prompt, source_code_list)
266
+ source_code_list = self.code_merger.get_source_code_list_from_shadow_files(
267
+ shadow_files)
268
+ generation_result = self.code_generator.single_round_run(
269
+ fix_prompt, source_code_list)
267
270
  token_cost_calculator.track_token_usage_by_generate(
268
271
  llm=self.llm,
269
272
  generate=generation_result,
270
273
  operation_name="code_generation_complete",
271
274
  start_time=start_time,
272
275
  end_time=time.time()
273
- )
276
+ )
274
277
 
275
-
276
278
  # 清理临时影子文件
277
279
  self.shadow_manager.clean_shadows()
278
-
280
+
279
281
  # 返回最终结果
280
282
  return generation_result
281
283
 
282
284
  def run(self, query: str, source_code_list: SourceCodeList) -> CodeGenerateResult:
283
285
  """
284
286
  执行完整的代码生成、修复、合并流程
285
-
287
+
286
288
  参数:
287
289
  query (str): 用户查询
288
290
  source_code_list (SourceCodeList): 源代码列表
289
-
291
+
290
292
  返回:
291
293
  CodeGenerateResult: 生成和修复的代码结果
292
294
  """
293
- # 生成代码并自动修复lint错误
295
+ # 生成代码并自动修复lint错误
294
296
 
295
297
  generation_result = self.generate_and_fix(query, source_code_list)
296
- global_cancel.check_and_raise()
298
+ global_cancel.check_and_raise()
297
299
 
298
- # 合并代码
300
+ # 合并代码
299
301
  self.code_merger.merge_code(generation_result)
300
-
301
- return generation_result
302
+
303
+ return generation_result
@@ -108,8 +108,22 @@ class ActiveContextManager:
108
108
  global_logger.configure(
109
109
  handlers=[
110
110
  # 移除控制台输出,只保留文件输出
111
- {"sink": log_file, "level": "DEBUG", "rotation": "10 MB", "retention": "1 week",
112
- "format": "{time:YYYY-MM-DD HH:mm:ss} | {level} | {name} | {message}"}
111
+ # 文件 Handler(仅处理 DirectoryMapper)
112
+ {
113
+ "sink": log_file,
114
+ "level": "INFO",
115
+ "rotation": "10 MB",
116
+ "retention": "1 week",
117
+ "format": "{time:YYYY-MM-DD HH:mm:ss} | {level} | {name} | {message}",
118
+ "filter": lambda record: record["extra"].get("name") in ["DirectoryMapper", "ActiveContextManager","ActivePackage","AsyncProcessor"]
119
+ },
120
+ # 控制台 Handler(排除 DirectoryMapper)
121
+ {
122
+ "sink": sys.stdout,
123
+ "level": "INFO",
124
+ "format": "{time:YYYY-MM-DD HH:mm:ss} | {name} | {message}",
125
+ "filter": lambda record: record["extra"].get("name") not in ["ActiveContextManager"]
126
+ }
113
127
  ]
114
128
  )
115
129
 
@@ -118,17 +132,18 @@ class ActiveContextManager:
118
132
  self.logger.info(f"初始化 ActiveContextManager,日志输出到 {log_file}")
119
133
 
120
134
  self.llm = llm
121
- self.directory_mapper = DirectoryMapper()
135
+ self.directory_mapper = DirectoryMapper()
122
136
  self.async_processor = AsyncProcessor()
123
137
  self.yml_manager = ActionYmlFileManager(source_dir)
124
-
138
+
125
139
  # 任务持久化文件路径
126
- self.tasks_file_path = os.path.join(source_dir, ".auto-coder", "active-context", "tasks.json")
127
-
140
+ self.tasks_file_path = os.path.join(
141
+ source_dir, ".auto-coder", "active-context", "tasks.json")
142
+
128
143
  # 加载已存在的任务
129
144
  self.tasks = self._load_tasks_from_disk()
130
145
  self.tasks_lock = threading.Lock() # 添加锁以保护任务字典的操作
131
-
146
+
132
147
  self.printer = Printer()
133
148
 
134
149
  # 初始化任务队列和锁
@@ -142,11 +157,11 @@ class ActiveContextManager:
142
157
 
143
158
  # 标记为已初始化
144
159
  self._is_initialized = True
145
-
160
+
146
161
  def _load_tasks_from_disk(self) -> Dict[str, Dict[str, Any]]:
147
162
  """
148
163
  从磁盘加载任务信息
149
-
164
+
150
165
  Returns:
151
166
  Dict: 任务字典
152
167
  """
@@ -154,22 +169,25 @@ class ActiveContextManager:
154
169
  if os.path.exists(self.tasks_file_path):
155
170
  with open(self.tasks_file_path, 'r', encoding='utf-8') as f:
156
171
  tasks_json = json.load(f)
157
-
172
+
158
173
  # 转换时间字符串为datetime对象
159
174
  for task_id, task in tasks_json.items():
160
175
  if 'start_time' in task and task['start_time']:
161
176
  try:
162
- task['start_time'] = datetime.fromisoformat(task['start_time'])
177
+ task['start_time'] = datetime.fromisoformat(
178
+ task['start_time'])
163
179
  except:
164
180
  task['start_time'] = None
165
-
181
+
166
182
  if 'completion_time' in task and task['completion_time']:
167
183
  try:
168
- task['completion_time'] = datetime.fromisoformat(task['completion_time'])
184
+ task['completion_time'] = datetime.fromisoformat(
185
+ task['completion_time'])
169
186
  except:
170
187
  task['completion_time'] = None
171
-
172
- self.logger.info(f"从 {self.tasks_file_path} 加载了 {len(tasks_json)} 个任务")
188
+
189
+ self.logger.info(
190
+ f"从 {self.tasks_file_path} 加载了 {len(tasks_json)} 个任务")
173
191
  return tasks_json
174
192
  else:
175
193
  self.logger.info(f"任务文件 {self.tasks_file_path} 不存在,将创建新文件")
@@ -177,7 +195,7 @@ class ActiveContextManager:
177
195
  except Exception as e:
178
196
  self.logger.error(f"加载任务文件失败: {e}")
179
197
  return {}
180
-
198
+
181
199
  def _save_tasks_to_disk(self):
182
200
  """
183
201
  将任务信息保存到磁盘
@@ -195,22 +213,24 @@ class ActiveContextManager:
195
213
  else:
196
214
  task_copy[k] = v
197
215
  tasks_copy[task_id] = task_copy
198
-
216
+
199
217
  # 确保目录存在
200
- os.makedirs(os.path.dirname(self.tasks_file_path), exist_ok=True)
201
-
218
+ os.makedirs(os.path.dirname(
219
+ self.tasks_file_path), exist_ok=True)
220
+
202
221
  # 写入JSON文件
203
222
  with open(self.tasks_file_path, 'w', encoding='utf-8') as f:
204
223
  json.dump(tasks_copy, f, ensure_ascii=False, indent=2)
205
-
206
- self.logger.debug(f"成功保存 {len(tasks_copy)} 个任务到 {self.tasks_file_path}")
224
+
225
+ self.logger.debug(
226
+ f"成功保存 {len(tasks_copy)} 个任务到 {self.tasks_file_path}")
207
227
  except Exception as e:
208
228
  self.logger.error(f"保存任务到磁盘失败: {e}")
209
-
229
+
210
230
  def _update_task(self, task_id: str, **kwargs):
211
231
  """
212
232
  更新任务信息并持久化到磁盘
213
-
233
+
214
234
  Args:
215
235
  task_id: 任务ID
216
236
  **kwargs: 要更新的任务属性
@@ -221,7 +241,7 @@ class ActiveContextManager:
221
241
  self.logger.debug(f"更新任务 {task_id} 信息: {kwargs.keys()}")
222
242
  else:
223
243
  self.logger.warning(f"尝试更新不存在的任务: {task_id}")
224
-
244
+
225
245
  # 持久化到磁盘
226
246
  self._save_tasks_to_disk()
227
247
 
@@ -326,8 +346,8 @@ class ActiveContextManager:
326
346
  self.logger.error(f"Error in process_changes: {e}")
327
347
  raise
328
348
 
329
- def _execute_task_in_background(self, task_id: str,
330
- query: str,
349
+ def _execute_task_in_background(self, task_id: str,
350
+ query: str,
331
351
  changed_urls: List[str], current_urls: List[str],
332
352
  args: AutoCoderArgs):
333
353
  """
@@ -348,7 +368,8 @@ class ActiveContextManager:
348
368
  task_id, query, changed_urls, current_urls, args)
349
369
 
350
370
  # 更新任务状态为已完成
351
- self._update_task(task_id, status='completed', completion_time=datetime.now())
371
+ self._update_task(task_id, status='completed',
372
+ completion_time=datetime.now())
352
373
 
353
374
  except Exception as e:
354
375
  # 记录错误,但不允许异常传播到主线程
@@ -409,7 +430,7 @@ class ActiveContextManager:
409
430
  input_tokens = 0
410
431
  output_tokens = 0
411
432
  cost = 0.0
412
-
433
+
413
434
  for i, context in enumerate(directory_contexts):
414
435
  dir_path = context['directory_path']
415
436
  self.logger.info(
@@ -417,29 +438,30 @@ class ActiveContextManager:
417
438
  try:
418
439
  result = self._process_directory_context(
419
440
  context, query, file_changes, args)
420
-
441
+
421
442
  # 如果返回了token和费用信息,则累加
422
443
  if isinstance(result, dict):
423
444
  dir_tokens = result.get('total_tokens', 0)
424
445
  dir_input_tokens = result.get('input_tokens', 0)
425
446
  dir_output_tokens = result.get('output_tokens', 0)
426
447
  dir_cost = result.get('cost', 0.0)
427
-
448
+
428
449
  total_tokens += dir_tokens
429
450
  input_tokens += dir_input_tokens
430
451
  output_tokens += dir_output_tokens
431
452
  cost += dir_cost
432
-
433
- self.logger.info(f"目录 {dir_path} 处理完成,使用了 {dir_tokens} tokens,费用 {dir_cost:.6f}")
434
-
453
+
454
+ self.logger.info(
455
+ f"目录 {dir_path} 处理完成,使用了 {dir_tokens} tokens,费用 {dir_cost:.6f}")
456
+
435
457
  processed_dirs.append(os.path.basename(dir_path))
436
-
458
+
437
459
  except Exception as e:
438
460
  self.logger.error(f"处理目录 {dir_path} 时出错: {str(e)}")
439
-
461
+
440
462
  # 更新任务的token和费用信息
441
463
  self._update_task(
442
- task_id,
464
+ task_id,
443
465
  total_tokens=total_tokens,
444
466
  input_tokens=input_tokens,
445
467
  output_tokens=output_tokens,
@@ -448,16 +470,17 @@ class ActiveContextManager:
448
470
  )
449
471
 
450
472
  # 3. 更新任务状态
451
- self._update_task(task_id,
452
- status='completed',
453
- completion_time=datetime.now())
473
+ self._update_task(task_id,
474
+ status='completed',
475
+ completion_time=datetime.now())
454
476
 
455
477
  duration = (datetime.now() -
456
478
  self.tasks[task_id]['start_time']).total_seconds()
457
479
  self.logger.info(f"==== 任务 {task_id} 处理完成 ====")
458
480
  self.logger.info(f"总耗时: {duration:.2f}秒")
459
481
  self.logger.info(f"处理的目录数: {len(processed_dirs)}")
460
- self.logger.info(f"使用总tokens: {total_tokens} (输入: {input_tokens}, 输出: {output_tokens})")
482
+ self.logger.info(
483
+ f"使用总tokens: {total_tokens} (输入: {input_tokens}, 输出: {output_tokens})")
461
484
  self.logger.info(f"总费用: {cost:.6f}")
462
485
 
463
486
  except Exception as e:
@@ -474,7 +497,7 @@ class ActiveContextManager:
474
497
  query: 用户查询/需求
475
498
  file_changes: 文件变更字典,键为文件路径,值为(变更前内容, 变更后内容)的元组
476
499
  args: AutoCoderArgs实例,包含配置信息
477
-
500
+
478
501
  Returns:
479
502
  Dict: 包含token和费用信息的字典
480
503
  """
@@ -544,9 +567,9 @@ class ActiveContextManager:
544
567
 
545
568
  # 3. 生成活动文件内容
546
569
  self.logger.info(f"开始为目录 {directory_path} 生成活动文件内容...")
547
-
570
+
548
571
  active_package = ActivePackage(self.llm, args.product_mode)
549
-
572
+
550
573
  # 调用生成方法,捕获token和费用信息
551
574
  generation_result = active_package.generate_active_file(
552
575
  context,
@@ -555,7 +578,7 @@ class ActiveContextManager:
555
578
  file_changes=directory_changes,
556
579
  args=args
557
580
  )
558
-
581
+
559
582
  # 检查返回值类型,兼容现有逻辑
560
583
  if isinstance(generation_result, tuple) and len(generation_result) >= 2:
561
584
  markdown_content = generation_result[0]
@@ -582,7 +605,7 @@ class ActiveContextManager:
582
605
 
583
606
  self.logger.info(f"成功创建/更新目录 {directory_path} 的活动文件")
584
607
  self.logger.debug(f"--- 处理目录上下文完成: {directory_path} ---")
585
-
608
+
586
609
  # 返回token和费用信息
587
610
  return tokens_info
588
611
 
@@ -661,7 +684,7 @@ class ActiveContextManager:
661
684
 
662
685
  if 'error' in task:
663
686
  result['error'] = task['error']
664
-
687
+
665
688
  # 添加token和费用信息
666
689
  for key in ['total_tokens', 'input_tokens', 'output_tokens', 'cost']:
667
690
  if key in task:
@@ -429,6 +429,7 @@ class ActivePackage:
429
429
  3. 明确指出新的变更与之前变更的关系(如继续完善、修复问题、新增功能等)
430
430
  4. 确保变更描述清晰、具体,并表明每个文件的变更内容和目的
431
431
  5. 如果有冲突的信息,优先保留最新的信息
432
+ 6. 变更部分最多保留20条。
432
433
 
433
434
  你的回答应该是一个完整的"当前变更"部分内容,不需要包含标题。
434
435
  """
autocoder/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.324"
1
+ __version__ = "0.1.326"