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

Files changed (41) hide show
  1. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/RECORD +41 -20
  3. autocoder/auto_coder_runner.py +1 -2
  4. autocoder/common/__init__.py +3 -0
  5. autocoder/common/auto_coder_lang.py +24 -0
  6. autocoder/common/code_auto_merge_editblock.py +2 -42
  7. autocoder/common/git_utils.py +2 -2
  8. autocoder/common/token_cost_caculate.py +103 -42
  9. autocoder/common/v2/__init__.py +0 -0
  10. autocoder/common/v2/code_auto_generate.py +199 -0
  11. autocoder/common/v2/code_auto_generate_diff.py +361 -0
  12. autocoder/common/v2/code_auto_generate_editblock.py +380 -0
  13. autocoder/common/v2/code_auto_generate_strict_diff.py +269 -0
  14. autocoder/common/v2/code_auto_merge.py +211 -0
  15. autocoder/common/v2/code_auto_merge_diff.py +354 -0
  16. autocoder/common/v2/code_auto_merge_editblock.py +523 -0
  17. autocoder/common/v2/code_auto_merge_strict_diff.py +259 -0
  18. autocoder/common/v2/code_diff_manager.py +266 -0
  19. autocoder/common/v2/code_editblock_manager.py +282 -0
  20. autocoder/common/v2/code_manager.py +238 -0
  21. autocoder/common/v2/code_strict_diff_manager.py +241 -0
  22. autocoder/dispacher/actions/action.py +16 -0
  23. autocoder/dispacher/actions/plugins/action_regex_project.py +6 -0
  24. autocoder/events/event_manager_singleton.py +2 -2
  25. autocoder/helper/__init__.py +0 -0
  26. autocoder/helper/project_creator.py +570 -0
  27. autocoder/linters/linter_factory.py +44 -25
  28. autocoder/linters/models.py +220 -0
  29. autocoder/linters/python_linter.py +1 -7
  30. autocoder/linters/reactjs_linter.py +580 -0
  31. autocoder/linters/shadow_linter.py +390 -0
  32. autocoder/linters/vue_linter.py +576 -0
  33. autocoder/memory/active_context_manager.py +0 -4
  34. autocoder/memory/active_package.py +12 -12
  35. autocoder/shadows/__init__.py +0 -0
  36. autocoder/shadows/shadow_manager.py +235 -0
  37. autocoder/version.py +1 -1
  38. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/LICENSE +0 -0
  39. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/WHEEL +0 -0
  40. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/entry_points.txt +0 -0
  41. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,576 @@
1
+ """
2
+ Module for linting Vue projects.
3
+ This module provides functionality to analyze Vue projects for code quality and best practices.
4
+ """
5
+
6
+ import os
7
+ import json
8
+ import subprocess
9
+ from typing import Dict, List, Optional, Any
10
+
11
+ from autocoder.linters.base_linter import BaseLinter
12
+
13
+
14
+ class VueLinter(BaseLinter):
15
+ """
16
+ A class that provides linting functionality for Vue projects and single files.
17
+ """
18
+
19
+ def __init__(self, verbose: bool = False):
20
+ """
21
+ Initialize the VueLinter.
22
+
23
+ Args:
24
+ verbose (bool): Whether to display verbose output.
25
+ """
26
+ super().__init__(verbose)
27
+
28
+ def _check_dependencies(self) -> bool:
29
+ """
30
+ Check if required dependencies (node, npm, npx) are installed.
31
+
32
+ Returns:
33
+ bool: True if all dependencies are available, False otherwise.
34
+ """
35
+ try:
36
+ # Check if node and npm are installed
37
+ subprocess.run(["node", "--version"], check=True,
38
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
39
+ subprocess.run(["npm", "--version"], check=True,
40
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
41
+ subprocess.run(["npx", "--version"], check=True,
42
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
43
+ return True
44
+ except (subprocess.SubprocessError, FileNotFoundError):
45
+ return False
46
+
47
+ def get_supported_extensions(self) -> List[str]:
48
+ """
49
+ Get the list of file extensions supported by this linter.
50
+
51
+ Returns:
52
+ List[str]: List of supported file extensions.
53
+ """
54
+ return ['.vue', '.js', '.ts']
55
+
56
+ def _detect_project_type(self, project_path: str) -> bool:
57
+ """
58
+ Detect whether the project is Vue.
59
+
60
+ Args:
61
+ project_path (str): Path to the project directory.
62
+
63
+ Returns:
64
+ bool: True if it's a Vue project, False otherwise
65
+ """
66
+ # Check for package.json
67
+ package_json_path = os.path.join(project_path, 'package.json')
68
+ if not os.path.exists(package_json_path):
69
+ return False
70
+
71
+ try:
72
+ with open(package_json_path, 'r') as f:
73
+ package_data = json.load(f)
74
+
75
+ dependencies = {
76
+ **package_data.get('dependencies', {}),
77
+ **package_data.get('devDependencies', {})
78
+ }
79
+
80
+ # Check for Vue
81
+ return 'vue' in dependencies
82
+ except (json.JSONDecodeError, FileNotFoundError):
83
+ return False
84
+
85
+ def _detect_file_type(self, file_path: str) -> bool:
86
+ """
87
+ Detect if the file is a Vue file.
88
+
89
+ Args:
90
+ file_path (str): Path to the file.
91
+
92
+ Returns:
93
+ bool: True if it's a Vue file, False otherwise
94
+ """
95
+ if not os.path.exists(file_path) or not os.path.isfile(file_path):
96
+ return False
97
+
98
+ # Get file extension
99
+ ext = self.get_file_extension(file_path)
100
+
101
+ if ext == '.vue':
102
+ return True
103
+ elif ext == '.js' or ext == '.ts':
104
+ # Check content for Vue imports
105
+ try:
106
+ with open(file_path, 'r', encoding='utf-8') as f:
107
+ content = f.read()
108
+ if 'import Vue' in content or 'from "vue"' in content or "from 'vue'" in content:
109
+ return True
110
+ except:
111
+ pass
112
+
113
+ return False
114
+
115
+ def _install_eslint_if_needed(self, project_path: str) -> bool:
116
+ """
117
+ Install ESLint and the appropriate Vue plugins if they're not already installed.
118
+
119
+ Args:
120
+ project_path (str): Path to the project directory.
121
+
122
+ Returns:
123
+ bool: True if installation was successful, False otherwise.
124
+ """
125
+ try:
126
+ # 首先尝试运行 npx eslint --version 检查是否已安装
127
+ if self.verbose:
128
+ print("Checking if ESLint is already installed...")
129
+
130
+ try:
131
+ result = subprocess.run(
132
+ ["npx", "eslint", "--version"],
133
+ cwd=project_path,
134
+ stdout=subprocess.PIPE,
135
+ stderr=subprocess.PIPE,
136
+ text=True,
137
+ check=False
138
+ )
139
+
140
+ if result.returncode == 0:
141
+ if self.verbose:
142
+ print(f"ESLint is already installed: {result.stdout.strip()}")
143
+ return True
144
+ except subprocess.SubprocessError:
145
+ if self.verbose:
146
+ print("ESLint not found via npx, will proceed with installation")
147
+
148
+ # 检查 .eslintrc.* 配置文件是否存在
149
+ eslint_configs = [
150
+ os.path.join(project_path, '.eslintrc'),
151
+ os.path.join(project_path, '.eslintrc.js'),
152
+ os.path.join(project_path, '.eslintrc.json'),
153
+ os.path.join(project_path, '.eslintrc.yml'),
154
+ os.path.join(project_path, '.eslintrc.yaml')
155
+ ]
156
+
157
+ if any(os.path.exists(config) for config in eslint_configs):
158
+ if self.verbose:
159
+ print("ESLint configuration found.")
160
+ return True
161
+
162
+ # Install eslint and Vue plugins
163
+ cmd = ["npm", "install", "--save-dev", "eslint", "eslint-plugin-vue"]
164
+ if self.verbose:
165
+ print("Installing ESLint with Vue plugins...")
166
+
167
+ result = subprocess.run(
168
+ cmd,
169
+ cwd=project_path,
170
+ stdout=subprocess.PIPE if not self.verbose else None,
171
+ stderr=subprocess.PIPE if not self.verbose else None
172
+ )
173
+
174
+ # Create basic configuration
175
+ eslint_config = {
176
+ "env": {
177
+ "browser": True,
178
+ "es2021": True,
179
+ "node": True
180
+ },
181
+ "extends": ["eslint:recommended", "plugin:vue/vue3-recommended"],
182
+ "plugins": ["vue"],
183
+ "parserOptions": {
184
+ "ecmaVersion": 2021,
185
+ "sourceType": "module"
186
+ }
187
+ }
188
+
189
+ # Write configuration
190
+ with open(os.path.join(project_path, '.eslintrc.json'), 'w') as f:
191
+ json.dump(eslint_config, f, indent=2)
192
+
193
+ return result.returncode == 0
194
+ except subprocess.SubprocessError:
195
+ return False
196
+
197
+ def _extract_json_from_output(self, output_text: str) -> str:
198
+ """
199
+ Extract JSON string from output text that might contain non-JSON content at the beginning.
200
+
201
+ Args:
202
+ output_text (str): The output text that may contain a JSON string after a separator.
203
+
204
+ Returns:
205
+ str: The extracted JSON string, or the original text if no separator is found.
206
+ """
207
+ if "=============" in output_text:
208
+ lines = output_text.split('\n')
209
+ json_lines = []
210
+ found_separator = False
211
+
212
+ for line in lines:
213
+ if line.startswith("============="):
214
+ found_separator = True
215
+ continue
216
+ if found_separator:
217
+ json_lines.append(line)
218
+
219
+ if json_lines:
220
+ return '\n'.join(json_lines)
221
+
222
+ return output_text
223
+
224
+ def lint_file(self, file_path: str, fix: bool = False, project_path: str = None) -> Dict[str, Any]:
225
+ """
226
+ Lint a single Vue file using ESLint.
227
+
228
+ Args:
229
+ file_path (str): Path to the file to lint.
230
+ fix (bool): Whether to automatically fix fixable issues.
231
+ project_path (str, optional): Path to the project directory. If not provided,
232
+ the parent directory of the file will be used.
233
+
234
+ Returns:
235
+ Dict: A dictionary containing lint results.
236
+ """
237
+ result = {
238
+ 'success': False,
239
+ 'framework': 'vue',
240
+ 'files_analyzed': 0,
241
+ 'error_count': 0,
242
+ 'warning_count': 0,
243
+ 'issues': []
244
+ }
245
+
246
+ # Check if file exists
247
+ if not os.path.exists(file_path) or not os.path.isfile(file_path):
248
+ result['error'] = f"File '{file_path}' does not exist or is not a file"
249
+ return result
250
+
251
+ # Check if file is supported
252
+ if not self.is_supported_file(file_path):
253
+ result['error'] = f"Unsupported file type for '{file_path}'"
254
+ return result
255
+
256
+ # Check if it's a Vue file
257
+ if not self._detect_file_type(file_path):
258
+ result['error'] = f"Not a Vue file: '{file_path}'"
259
+ return result
260
+
261
+ # Check dependencies
262
+ if not self._check_dependencies():
263
+ result['error'] = "Required dependencies (node, npm, npx) are not installed"
264
+ return result
265
+
266
+ # If project_path is not provided, use parent directory
267
+ if project_path is None:
268
+ project_path = os.path.dirname(file_path)
269
+
270
+ # Install ESLint if needed
271
+ if not self._install_eslint_if_needed(project_path):
272
+ result['error'] = "Failed to install or configure ESLint"
273
+ return result
274
+
275
+ # Run ESLint on the file
276
+ try:
277
+ cmd = ["npx", "eslint", "--format", "json"]
278
+
279
+ # Add fix flag if requested
280
+ if fix:
281
+ cmd.append("--fix")
282
+
283
+ # Add file path
284
+ cmd.append(file_path)
285
+
286
+ process = subprocess.run(
287
+ cmd,
288
+ cwd=project_path,
289
+ stdout=subprocess.PIPE,
290
+ stderr=subprocess.PIPE,
291
+ text=True
292
+ )
293
+
294
+ # Parse ESLint output
295
+ if process.stdout:
296
+ try:
297
+ output_text = process.stdout
298
+ try:
299
+ eslint_output = json.loads(output_text)
300
+ except json.JSONDecodeError:
301
+ # Try to extract JSON from output if it contains separator
302
+ json_text = self._extract_json_from_output(output_text)
303
+ eslint_output = json.loads(json_text)
304
+
305
+ # print(f"eslint_output: {json.dumps(eslint_output, indent=4,ensure_ascii=False)}")
306
+
307
+ # Count files analyzed (should be 1)
308
+ result['files_analyzed'] = len(eslint_output)
309
+
310
+ # Track overall counts
311
+ total_errors = 0
312
+ total_warnings = 0
313
+
314
+ # Process the file result
315
+ for file_result in eslint_output:
316
+ file_rel_path = os.path.relpath(
317
+ file_result['filePath'], project_path)
318
+
319
+ # Add error and warning counts
320
+ total_errors += file_result.get('errorCount', 0)
321
+ total_warnings += file_result.get('warningCount', 0)
322
+
323
+ # Process individual messages
324
+ for message in file_result.get('messages', []):
325
+ issue = {
326
+ 'file': file_rel_path,
327
+ 'line': message.get('line', 0),
328
+ 'column': message.get('column', 0),
329
+ 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
330
+ 'message': message.get('message', ''),
331
+ 'rule': message.get('ruleId', 'unknown')
332
+ }
333
+ result['issues'].append(issue)
334
+
335
+ result['error_count'] = total_errors
336
+ result['warning_count'] = total_warnings
337
+ result['success'] = True
338
+ except json.JSONDecodeError:
339
+ # Handle case where ESLint output is not valid JSON
340
+ result['error'] = "Failed to parse ESLint output"
341
+ else:
342
+ # Handle case where ESLint didn't produce any output
343
+ stderr = process.stderr.strip()
344
+ if stderr:
345
+ result['error'] = f"ESLint error: {stderr}"
346
+ else:
347
+ # No errors found
348
+ result['success'] = True
349
+ except subprocess.SubprocessError as e:
350
+ result['error'] = f"Error running ESLint: {str(e)}"
351
+
352
+ return result
353
+
354
+ def lint_project(self, project_path: str, fix: bool = False) -> Dict[str, Any]:
355
+ """
356
+ Lint a Vue project.
357
+
358
+ Args:
359
+ project_path (str): Path to the project directory.
360
+ fix (bool): Whether to automatically fix fixable issues.
361
+
362
+ Returns:
363
+ Dict: A dictionary containing lint results.
364
+ """
365
+ result = {
366
+ 'success': False,
367
+ 'framework': 'vue',
368
+ 'files_analyzed': 0,
369
+ 'error_count': 0,
370
+ 'warning_count': 0,
371
+ 'issues': []
372
+ }
373
+
374
+ # Check if the path exists
375
+ if not os.path.exists(project_path) or not os.path.isdir(project_path):
376
+ result['error'] = f"Path '{project_path}' does not exist or is not a directory"
377
+ return result
378
+
379
+ # Check dependencies
380
+ if not self._check_dependencies():
381
+ result['error'] = "Required dependencies (node, npm, npx) are not installed"
382
+ return result
383
+
384
+ # Detect project type
385
+ if not self._detect_project_type(project_path):
386
+ result['error'] = "Not a Vue project"
387
+ return result
388
+
389
+ # Install ESLint if needed
390
+ if not self._install_eslint_if_needed(project_path):
391
+ result['error'] = "Failed to install or configure ESLint"
392
+ return result
393
+
394
+ # Run ESLint
395
+ try:
396
+ cmd = ["npx", "eslint", "--format", "json"]
397
+
398
+ # Add fix flag if requested
399
+ if fix:
400
+ cmd.append("--fix")
401
+
402
+ # Target Vue files
403
+ cmd.extend([
404
+ "src/**/*.js",
405
+ "src/**/*.vue",
406
+ "src/**/*.ts"
407
+ ])
408
+
409
+ process = subprocess.run(
410
+ cmd,
411
+ cwd=project_path,
412
+ stdout=subprocess.PIPE,
413
+ stderr=subprocess.PIPE,
414
+ text=True
415
+ )
416
+
417
+ # Parse ESLint output
418
+ if process.stdout:
419
+ try:
420
+ try:
421
+ eslint_output = json.loads(process.stdout)
422
+ except json.JSONDecodeError:
423
+ # Try to extract JSON from output if it contains separator
424
+ json_text = self._extract_json_from_output(process.stdout)
425
+ eslint_output = json.loads(json_text)
426
+
427
+ # Count files analyzed
428
+ result['files_analyzed'] = len(eslint_output)
429
+
430
+ # Track overall counts
431
+ total_errors = 0
432
+ total_warnings = 0
433
+
434
+ # Process each file result
435
+ for file_result in eslint_output:
436
+ file_path = os.path.relpath(
437
+ file_result['filePath'], project_path)
438
+
439
+ # Add error and warning counts
440
+ total_errors += file_result.get('errorCount', 0)
441
+ total_warnings += file_result.get('warningCount', 0)
442
+
443
+ # Process individual messages
444
+ for message in file_result.get('messages', []):
445
+ issue = {
446
+ 'file': file_path,
447
+ 'line': message.get('line', 0),
448
+ 'column': message.get('column', 0),
449
+ 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
450
+ 'message': message.get('message', ''),
451
+ 'rule': message.get('ruleId', 'unknown')
452
+ }
453
+ result['issues'].append(issue)
454
+
455
+ result['error_count'] = total_errors
456
+ result['warning_count'] = total_warnings
457
+ result['success'] = True
458
+ except json.JSONDecodeError:
459
+ # Handle case where ESLint output is not valid JSON
460
+ result['error'] = "Failed to parse ESLint output"
461
+ else:
462
+ # Handle case where ESLint didn't produce any output
463
+ stderr = process.stderr.strip()
464
+ if stderr:
465
+ result['error'] = f"ESLint error: {stderr}"
466
+ else:
467
+ # No errors found
468
+ result['success'] = True
469
+ except subprocess.SubprocessError as e:
470
+ result['error'] = f"Error running ESLint: {str(e)}"
471
+
472
+ return result
473
+
474
+ def format_lint_result(self, lint_result: Dict[str, Any]) -> str:
475
+ """
476
+ Format lint results into a human-readable string.
477
+
478
+ Args:
479
+ lint_result (Dict): The lint result dictionary.
480
+
481
+ Returns:
482
+ str: A formatted string representation of the lint results.
483
+ """
484
+ if not lint_result.get('success', False):
485
+ return f"Linting failed: {lint_result.get('error', 'Unknown error')}"
486
+
487
+ files_analyzed = lint_result.get('files_analyzed', 0)
488
+ error_count = lint_result.get('error_count', 0)
489
+ warning_count = lint_result.get('warning_count', 0)
490
+
491
+ output = [
492
+ "Vue Lint Results",
493
+ f"{'=' * 30}",
494
+ f"Files analyzed: {files_analyzed}",
495
+ f"Errors: {error_count}",
496
+ f"Warnings: {warning_count}",
497
+ ""
498
+ ]
499
+
500
+ if error_count == 0 and warning_count == 0:
501
+ output.append("No issues found. Great job!")
502
+ else:
503
+ output.append("Issues:")
504
+ output.append(f"{'-' * 30}")
505
+
506
+ # Group issues by file
507
+ issues_by_file = {}
508
+ for issue in lint_result.get('issues', []):
509
+ file_path = issue.get('file', '')
510
+ if file_path not in issues_by_file:
511
+ issues_by_file[file_path] = []
512
+ issues_by_file[file_path].append(issue)
513
+
514
+ # Display issues grouped by file
515
+ for file_path, issues in issues_by_file.items():
516
+ output.append(f"\nFile: {file_path}")
517
+
518
+ for issue in issues:
519
+ severity = issue.get('severity', '').upper()
520
+ line = issue.get('line', 0)
521
+ column = issue.get('column', 0)
522
+ message = issue.get('message', '')
523
+ rule = issue.get('rule', 'unknown')
524
+
525
+ output.append(
526
+ f" [{severity}] Line {line}, Col {column}: {message} ({rule})")
527
+
528
+ return "\n".join(output)
529
+
530
+
531
+ def lint_project(project_path: str, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
532
+ """
533
+ Utility function to lint a Vue project.
534
+
535
+ Args:
536
+ project_path (str): Path to the project directory.
537
+ fix (bool): Whether to automatically fix fixable issues.
538
+ verbose (bool): Whether to display verbose output.
539
+
540
+ Returns:
541
+ Dict: A dictionary containing lint results.
542
+ """
543
+ linter = VueLinter(verbose=verbose)
544
+ return linter.lint_project(project_path, fix=fix)
545
+
546
+
547
+ def lint_file(file_path: str, project_path: str = None, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
548
+ """
549
+ Utility function to lint a single Vue file.
550
+
551
+ Args:
552
+ file_path (str): Path to the file to lint.
553
+ project_path (str, optional): Path to the project directory. If not provided,
554
+ the parent directory of the file will be used.
555
+ fix (bool): Whether to automatically fix fixable issues.
556
+ verbose (bool): Whether to display verbose output.
557
+
558
+ Returns:
559
+ Dict: A dictionary containing lint results.
560
+ """
561
+ linter = VueLinter(verbose=verbose)
562
+ return linter.lint_file(file_path, fix=fix, project_path=project_path)
563
+
564
+
565
+ def format_lint_result(lint_result: Dict[str, Any]) -> str:
566
+ """
567
+ Format lint results into a human-readable string.
568
+
569
+ Args:
570
+ lint_result (Dict): The lint result dictionary.
571
+
572
+ Returns:
573
+ str: A formatted string representation of the lint results.
574
+ """
575
+ linter = VueLinter()
576
+ return linter.format_lint_result(lint_result)
@@ -1,7 +1,3 @@
1
- """
2
- 活动上下文管理器 - 子系统的主要接口
3
- """
4
-
5
1
  import os
6
2
  import sys
7
3
  import time
@@ -33,9 +33,7 @@ class ActivePackage:
33
33
  self.llm = llm
34
34
  self.product_mode = product_mode
35
35
  # 创建专用的 logger 实例
36
- self.logger = global_logger.bind(name="ActivePackage")
37
- # 创建Token计费计算器
38
- self.token_calculator = TokenCostCalculator(logger_name="ActivePackage.TokenCost")
36
+ self.logger = global_logger.bind(name="ActivePackage")
39
37
 
40
38
  def generate_active_file(self, context: Dict[str, Any], query: str,
41
39
  existing_file_path: Optional[str] = None,
@@ -79,7 +77,7 @@ class ActivePackage:
79
77
  # 根据是否有现有内容选择不同的生成方式
80
78
  if existing_content:
81
79
  # 有现有内容,使用更新模式
82
- file_content, usage_stats = self.generate_updated_active_file(enhanced_context, query, existing_content)
80
+ file_content, usage_stats = self.generate_updated_active_file(enhanced_context, query, existing_content,args)
83
81
  # 合并token和费用统计
84
82
  total_stats["total_tokens"] += usage_stats["total_tokens"]
85
83
  total_stats["input_tokens"] += usage_stats["input_tokens"]
@@ -87,7 +85,7 @@ class ActivePackage:
87
85
  total_stats["cost"] += usage_stats["cost"]
88
86
  else:
89
87
  # 无现有内容,使用创建模式
90
- file_content, usage_stats = self.generate_new_active_file(enhanced_context, query)
88
+ file_content, usage_stats = self.generate_new_active_file(enhanced_context, query,args)
91
89
  # 合并token和费用统计
92
90
  total_stats["total_tokens"] += usage_stats["total_tokens"]
93
91
  total_stats["input_tokens"] += usage_stats["input_tokens"]
@@ -174,7 +172,7 @@ class ActivePackage:
174
172
 
175
173
  return enhanced_context
176
174
 
177
- def generate_new_active_file(self, context: Dict[str, Any], query: str) -> Tuple[str, Dict[str, Any]]:
175
+ def generate_new_active_file(self, context: Dict[str, Any], query: str,args:AutoCoderArgs) -> Tuple[str, Dict[str, Any]]:
178
176
  """
179
177
  生成全新的活动文件内容
180
178
 
@@ -194,7 +192,8 @@ class ActivePackage:
194
192
  end_time_current_change = time.monotonic()
195
193
 
196
194
  # 使用TokenCostCalculator跟踪token使用情况
197
- current_change_stats: TokenUsageStats = self.token_calculator.track_token_usage(
195
+ token_calculator = TokenCostCalculator(logger_name="ActivePackage.TokenCost",args=args)
196
+ current_change_stats: TokenUsageStats = token_calculator.track_token_usage(
198
197
  llm=self.llm,
199
198
  meta_holder=meta_holder_current_change,
200
199
  operation_name="Current Change Generation",
@@ -213,7 +212,7 @@ class ActivePackage:
213
212
  end_time_document = time.monotonic()
214
213
 
215
214
  # 使用TokenCostCalculator跟踪token使用情况
216
- document_stats: TokenUsageStats = self.token_calculator.track_token_usage(
215
+ document_stats: TokenUsageStats = token_calculator.track_token_usage(
217
216
  llm=self.llm,
218
217
  meta_holder=meta_holder_document,
219
218
  operation_name="Document Generation",
@@ -293,7 +292,7 @@ class ActivePackage:
293
292
  self.logger.error(f"Error extracting sections: {e}")
294
293
  return header, current_change_section, document_section
295
294
 
296
- def generate_updated_active_file(self, context: Dict[str, Any], query: str, existing_content: str) -> Tuple[str, Dict[str, Any]]:
295
+ def generate_updated_active_file(self, context: Dict[str, Any], query: str, existing_content: str,args:AutoCoderArgs) -> Tuple[str, Dict[str, Any]]:
297
296
  """
298
297
  基于现有内容生成更新后的活动文件内容
299
298
 
@@ -317,7 +316,8 @@ class ActivePackage:
317
316
  end_time_current_change = time.monotonic()
318
317
 
319
318
  # 使用TokenCostCalculator跟踪token使用情况
320
- update_current_change_stats: TokenUsageStats = self.token_calculator.track_token_usage(
319
+ token_calculator = TokenCostCalculator(logger_name="ActivePackage.TokenCost",args=args)
320
+ update_current_change_stats: TokenUsageStats = token_calculator.track_token_usage(
321
321
  llm=self.llm,
322
322
  meta_holder=meta_holder_current_change,
323
323
  operation_name="Update Current Change",
@@ -335,8 +335,8 @@ class ActivePackage:
335
335
  meta_holder_document).run(context, query, existing_document)
336
336
  end_time_document = time.monotonic()
337
337
 
338
- # 使用TokenCostCalculator跟踪token使用情况
339
- update_document_stats: TokenUsageStats = self.token_calculator.track_token_usage(
338
+ # 使用TokenCostCalculator跟踪token使用情况
339
+ update_document_stats: TokenUsageStats = token_calculator.track_token_usage(
340
340
  llm=self.llm,
341
341
  meta_holder=meta_holder_document,
342
342
  operation_name="Update Document",
File without changes