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,570 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ ProjectCreator 类:用于创建示例项目的工具类
6
+ 可以灵活配置项目结构、文件内容和 Git 初始化选项
7
+ """
8
+
9
+ import os
10
+ import shutil
11
+ import git
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional, Any
14
+ from abc import ABC, abstractmethod
15
+
16
+
17
+ class FileCreator(ABC):
18
+ """
19
+ 文件创建抽象基类,定义了创建项目文件的接口
20
+ """
21
+
22
+ @abstractmethod
23
+ def create_files(self, project_dir: str) -> None:
24
+ """
25
+ 在项目目录中创建必要的文件
26
+
27
+ 参数:
28
+ project_dir: 项目目录路径
29
+ """
30
+ pass
31
+
32
+ @abstractmethod
33
+ def get_file_paths(self, project_dir: str) -> List[str]:
34
+ """
35
+ 获取创建的文件路径列表,用于配置文件中引用
36
+
37
+ 参数:
38
+ project_dir: 项目目录路径
39
+
40
+ 返回:
41
+ List[str]: 文件路径的列表
42
+ """
43
+ pass
44
+
45
+ @property
46
+ @abstractmethod
47
+ def project_type(self) -> str:
48
+ """返回项目类型标识"""
49
+ pass
50
+
51
+
52
+ class PythonFileCreator(FileCreator):
53
+ """
54
+ Python 计算器项目文件创建器
55
+ """
56
+
57
+ def create_files(self, project_dir: str) -> None:
58
+ """创建 Python 项目文件"""
59
+ # 创建计算器文件
60
+ self._create_calculator_file(project_dir)
61
+ # 创建主程序文件
62
+ self._create_main_file(project_dir)
63
+
64
+ def get_file_paths(self, project_dir: str) -> List[str]:
65
+ """获取 Python 项目的主要文件路径"""
66
+ abs_project_dir = os.path.abspath(project_dir)
67
+ return [
68
+ os.path.join(abs_project_dir, "calculator.py"),
69
+ os.path.join(abs_project_dir, "main.py")
70
+ ]
71
+
72
+ @property
73
+ def project_type(self) -> str:
74
+ """返回项目类型"""
75
+ return "py"
76
+
77
+ def _create_calculator_file(self, project_dir: str) -> None:
78
+ """创建计算器示例文件"""
79
+ calculator_path = os.path.join(project_dir, "calculator.py")
80
+ calculator_content = """
81
+ class Calculator:
82
+ def __init__(self):
83
+ self.history = []
84
+
85
+ def add(self, a, b):
86
+ '''加法函数'''
87
+ result = a + b
88
+ self.history.append(f"{a} + {b} = {result}")
89
+ return result
90
+
91
+ def subtract(self, a, b):
92
+ '''减法函数'''
93
+ result = a - b
94
+ self.history.append(f"{a} - {b} = {result}")
95
+ return result
96
+
97
+ def clear_history(self):
98
+ '''清除历史记录'''
99
+ self.history = []
100
+ """
101
+
102
+ with open(calculator_path, "w", encoding="utf-8") as f:
103
+ f.write(calculator_content)
104
+
105
+ def _create_main_file(self, project_dir: str) -> None:
106
+ """创建主程序文件"""
107
+ main_path = os.path.join(project_dir, "main.py")
108
+ main_content = """
109
+ from calculator import Calculator
110
+ from abc import ABC, abstractmethod
111
+ def main():
112
+ calc = Calculator()
113
+
114
+ # 进行一些计算
115
+ print(calc.add(5, 3))
116
+ print(calc.subtract(10, 4))
117
+
118
+ # 打印历史记录
119
+ print("计算历史:")
120
+ for item in calc.history:
121
+ print(item)
122
+
123
+ if __name__ == "__main__":
124
+ main()
125
+ """
126
+
127
+ with open(main_path, "w", encoding="utf-8") as f:
128
+ f.write(main_content)
129
+
130
+
131
+ class ReactJSFileCreator(FileCreator):
132
+ """
133
+ React TypeScript 计算器项目文件创建器
134
+ """
135
+
136
+ def create_files(self, project_dir: str) -> None:
137
+ """创建 React TypeScript 项目文件"""
138
+ # 创建 package.json
139
+ self._create_package_json(project_dir)
140
+ # 创建 index.html
141
+ self._create_index_html(project_dir)
142
+ # 创建 src 目录
143
+ src_dir = os.path.join(project_dir, "src")
144
+ os.makedirs(src_dir, exist_ok=True)
145
+ # 创建 App.tsx 和 Calculator.tsx 组件
146
+ self._create_app_tsx(src_dir)
147
+ self._create_calculator_component(src_dir)
148
+ self._create_index_tsx(src_dir)
149
+ # 创建 tsconfig.json
150
+ self._create_tsconfig_json(project_dir)
151
+
152
+ def get_file_paths(self, project_dir: str) -> List[str]:
153
+ """获取 React TypeScript 项目的主要文件路径"""
154
+ abs_project_dir = os.path.abspath(project_dir)
155
+ return [
156
+ os.path.join(abs_project_dir, "package.json"),
157
+ os.path.join(abs_project_dir, "tsconfig.json"),
158
+ os.path.join(abs_project_dir, "src", "App.tsx"),
159
+ os.path.join(abs_project_dir, "src", "Calculator.tsx"),
160
+ os.path.join(abs_project_dir, "src", "index.tsx")
161
+ ]
162
+
163
+ @property
164
+ def project_type(self) -> str:
165
+ """返回项目类型"""
166
+ return "tsx"
167
+
168
+ def _create_index_html(self, project_dir: str) -> None:
169
+ """创建 index.html 文件"""
170
+ index_html_path = os.path.join(project_dir, "public", "index.html")
171
+ os.makedirs(os.path.dirname(index_html_path), exist_ok=True)
172
+ index_html_content = """<!DOCTYPE html>
173
+ <html lang="en">
174
+ <head>
175
+ <meta charset="utf-8" />
176
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
177
+ <meta name="theme-color" content="#000000" />
178
+ <meta name="description" content="React Calculator App" />
179
+ <title>React Calculator</title>
180
+ </head>
181
+ <body>
182
+ <noscript>You need to enable JavaScript to run this app.</noscript>
183
+ <div id="root"></div>
184
+ </body>
185
+ </html>"""
186
+ with open(index_html_path, "w", encoding="utf-8") as f:
187
+ f.write(index_html_content)
188
+
189
+ def _create_package_json(self, project_dir: str) -> None:
190
+ """创建 package.json 文件"""
191
+ package_path = os.path.join(project_dir, "package.json")
192
+ package_content = """{
193
+ "name": "calculator-app",
194
+ "version": "0.1.0",
195
+ "private": true,
196
+ "dependencies": {
197
+ "react": "^18.2.0",
198
+ "react-dom": "^18.2.0",
199
+ "react-scripts": "5.0.1",
200
+ "@types/node": "^16.18.0",
201
+ "@types/react": "^18.2.0",
202
+ "@types/react-dom": "^18.2.0",
203
+ "typescript": "^4.9.5"
204
+ },
205
+ "scripts": {
206
+ "start": "react-scripts start",
207
+ "build": "react-scripts build",
208
+ "test": "react-scripts test",
209
+ "eject": "react-scripts eject"
210
+ },
211
+ "eslintConfig": {
212
+ "extends": [
213
+ "react-app",
214
+ "react-app/jest"
215
+ ]
216
+ },
217
+ "browserslist": {
218
+ "production": [
219
+ ">0.2%",
220
+ "not dead",
221
+ "not op_mini all"
222
+ ],
223
+ "development": [
224
+ "last 1 chrome version",
225
+ "last 1 firefox version",
226
+ "last 1 safari version"
227
+ ]
228
+ }
229
+ }"""
230
+ with open(package_path, "w", encoding="utf-8") as f:
231
+ f.write(package_content)
232
+
233
+ def _create_tsconfig_json(self, project_dir: str) -> None:
234
+ """创建 tsconfig.json 文件"""
235
+ tsconfig_path = os.path.join(project_dir, "tsconfig.json")
236
+ tsconfig_content = """{
237
+ "compilerOptions": {
238
+ "target": "es5",
239
+ "lib": ["dom", "dom.iterable", "esnext"],
240
+ "allowJs": true,
241
+ "skipLibCheck": true,
242
+ "esModuleInterop": true,
243
+ "allowSyntheticDefaultImports": true,
244
+ "strict": true,
245
+ "forceConsistentCasingInFileNames": true,
246
+ "noFallthroughCasesInSwitch": true,
247
+ "module": "esnext",
248
+ "moduleResolution": "node",
249
+ "resolveJsonModule": true,
250
+ "isolatedModules": true,
251
+ "noEmit": true,
252
+ "jsx": "react-jsx"
253
+ },
254
+ "include": ["src"]
255
+ }"""
256
+ with open(tsconfig_path, "w", encoding="utf-8") as f:
257
+ f.write(tsconfig_content)
258
+
259
+ def _create_app_tsx(self, src_dir: str) -> None:
260
+ """创建 App.tsx 文件"""
261
+ app_path = os.path.join(src_dir, "App.tsx")
262
+ app_content = """import React from 'react';
263
+ import Calculator from './Calculator';
264
+
265
+ const App: React.FC = () => {
266
+ return (
267
+ <div className="App">
268
+ <header className="App-header">
269
+ <h1>React Calculator</h1>
270
+ </header>
271
+ <main>
272
+ <Calculator />
273
+ </main>
274
+ </div>
275
+ );
276
+ };
277
+
278
+ export default App;"""
279
+ with open(app_path, "w", encoding="utf-8") as f:
280
+ f.write(app_content)
281
+
282
+ def _create_calculator_component(self, src_dir: str) -> None:
283
+ """创建 Calculator.tsx 组件"""
284
+ calculator_path = os.path.join(src_dir, "Calculator.tsx")
285
+ calculator_content = """import React, { useState } from 'react';
286
+
287
+ interface CalculatorProps {}
288
+
289
+ const Calculator: React.FC<CalculatorProps> = () => {
290
+ const [display, setDisplay] = useState<string>('0');
291
+ const [equation, setEquation] = useState<string>('');
292
+
293
+ const handleNumber = (num: string) => {
294
+ if (display === '0') {
295
+ setDisplay(num);
296
+ } else {
297
+ setDisplay(display + num);
298
+ }
299
+ };
300
+
301
+ const handleOperator = (operator: string) => {
302
+ setEquation(display + ' ' + operator + ' ');
303
+ setDisplay('0');
304
+ };
305
+
306
+ const handleEqual = () => {
307
+ try {
308
+ const result = eval(equation + display);
309
+ setDisplay(result.toString());
310
+ setEquation('');
311
+ } catch (error) {
312
+ setDisplay('Error');
313
+ setEquation('');
314
+ }
315
+ };
316
+
317
+ const handleClear = () => {
318
+ setDisplay('0');
319
+ setEquation('');
320
+ };
321
+
322
+ return (
323
+ <div className="calculator">
324
+ <div className="display">
325
+ <div className="equation">{equation}</div>
326
+ <div className="current">{display}</div>
327
+ </div>
328
+ <div className="buttons">
329
+ <button onClick={handleClear}>C</button>
330
+ <button onClick={() => handleOperator('/')}>/</button>
331
+ <button onClick={() => handleOperator('*')}>×</button>
332
+ <button onClick={() => handleNumber('7')}>7</button>
333
+ <button onClick={() => handleNumber('8')}>8</button>
334
+ <button onClick={() => handleNumber('9')}>9</button>
335
+ <button onClick={() => handleOperator('-')}>-</button>
336
+ <button onClick={() => handleNumber('4')}>4</button>
337
+ <button onClick={() => handleNumber('5')}>5</button>
338
+ <button onClick={() => handleNumber('6')}>6</button>
339
+ <button onClick={() => handleOperator('+')}>+</button>
340
+ <button onClick={() => handleNumber('1')}>1</button>
341
+ <button onClick={() => handleNumber('2')}>2</button>
342
+ <button onClick={() => handleNumber('3')}>3</button>
343
+ <button onClick={handleEqual}>=</button>
344
+ <button onClick={() => handleNumber('0')}>0</button>
345
+ <button onClick={() => handleNumber('.')}>.</button>
346
+ </div>
347
+ </div>
348
+ );
349
+ };
350
+
351
+ export default Calculator;"""
352
+ with open(calculator_path, "w", encoding="utf-8") as f:
353
+ f.write(calculator_content)
354
+
355
+ def _create_index_tsx(self, src_dir: str) -> None:
356
+ """创建 index.tsx 文件"""
357
+ index_path = os.path.join(src_dir, "index.tsx")
358
+ index_content = """import React from 'react';
359
+ import ReactDOM from 'react-dom/client';
360
+ import App from './App';
361
+
362
+ const root = ReactDOM.createRoot(
363
+ document.getElementById('root') as HTMLElement
364
+ );
365
+
366
+ root.render(
367
+ <React.StrictMode>
368
+ <App />
369
+ </React.StrictMode>
370
+ );"""
371
+ with open(index_path, "w", encoding="utf-8") as f:
372
+ f.write(index_content)
373
+
374
+
375
+ class FileCreatorFactory:
376
+ """
377
+ 文件创建器工厂类,根据项目类型返回对应的文件创建器
378
+ """
379
+
380
+ @staticmethod
381
+ def get_creator(project_type: str) -> FileCreator:
382
+ """
383
+ 获取指定类型的文件创建器
384
+
385
+ 参数:
386
+ project_type: 项目类型,支持 'python'/'py' 或 'react'/'js'
387
+
388
+ 返回:
389
+ FileCreator: 对应的文件创建器实例
390
+
391
+ 异常:
392
+ ValueError: 不支持的项目类型
393
+ """
394
+ project_type = project_type.lower()
395
+
396
+ if project_type in ('python', 'py'):
397
+ return PythonFileCreator()
398
+ elif project_type in ('react', 'reactjs', 'js'):
399
+ return ReactJSFileCreator()
400
+ else:
401
+ raise ValueError(f"不支持的项目类型: {project_type}")
402
+
403
+
404
+ class ProjectCreator:
405
+ """
406
+ 创建示例项目的工具类,支持自定义项目结构和内容
407
+ """
408
+
409
+ def __init__(
410
+ self,
411
+ project_name: str = "test_project",
412
+ project_type: str = "python",
413
+ git_init: bool = True,
414
+ git_user_email: str = "example@example.com",
415
+ git_user_name: str = "Example User",
416
+ create_actions: bool = True,
417
+ query: str = "给计算器添加乘法和除法功能",
418
+ model: str = "v3_chat",
419
+ product_mode: str = "lite"
420
+ ):
421
+ """
422
+ 初始化项目创建器
423
+
424
+ 参数:
425
+ project_name: 项目名称和目录名
426
+ project_type: 项目类型,支持 'python'/'py' 或 'react'/'js'
427
+ git_init: 是否初始化 Git 仓库
428
+ git_user_email: Git 用户邮箱
429
+ git_user_name: Git 用户名
430
+ create_actions: 是否创建 actions 目录和配置文件
431
+ query: 默认查询内容
432
+ model: 使用的模型名称
433
+ product_mode: 模型的产品模式
434
+ """
435
+ self.project_name = project_name
436
+ self.git_init = git_init
437
+ self.git_user_email = git_user_email
438
+ self.git_user_name = git_user_name
439
+ self.create_actions = create_actions
440
+ self.query = query
441
+ self.model = model
442
+ self.product_mode = product_mode
443
+
444
+ # 使用工厂获取文件创建器
445
+ self.file_creator = FileCreatorFactory.get_creator(project_type)
446
+
447
+ def create_project(self) -> str:
448
+ """
449
+ 创建一个示例项目目录和文件
450
+
451
+ 返回:
452
+ str: 项目目录的绝对路径
453
+ """
454
+ # 创建项目目录
455
+ project_dir = self.project_name
456
+ if os.path.exists(project_dir):
457
+ shutil.rmtree(project_dir)
458
+ os.makedirs(project_dir)
459
+
460
+ # 使用文件创建器创建项目文件
461
+ self.file_creator.create_files(project_dir)
462
+
463
+ # 创建配置文件
464
+ if self.create_actions:
465
+ self._create_actions_files(project_dir)
466
+
467
+ # 初始化 Git 仓库
468
+ if self.git_init:
469
+ self._init_git_repo(project_dir)
470
+
471
+ return os.path.abspath(project_dir)
472
+
473
+ def _create_actions_files(self, project_dir: str) -> None:
474
+ """创建 actions 目录和配置文件"""
475
+ # 创建 actions 目录
476
+ actions_dir = os.path.join(project_dir, "actions")
477
+ os.makedirs(actions_dir, exist_ok=True)
478
+
479
+ # 创建 base 目录
480
+ base_dir = os.path.join(actions_dir, "base")
481
+ os.makedirs(base_dir, exist_ok=True)
482
+
483
+ # 创建 base.yml 文件
484
+ self._create_base_yml(project_dir, base_dir)
485
+
486
+ # 创建 chat_action.yml 文件
487
+ self._create_chat_action_yml(project_dir, actions_dir)
488
+
489
+ def _create_base_yml(self, project_dir: str, base_dir: str) -> None:
490
+ """创建 base.yml 配置文件"""
491
+ base_yml_path = os.path.join(base_dir, "base.yml")
492
+ abs_project_dir = os.path.abspath(project_dir)
493
+ base_yml_content = f"""source_dir: {abs_project_dir}
494
+ target_file: {os.path.join(abs_project_dir, "output.txt")}
495
+ project_type: {self.file_creator.project_type}
496
+
497
+ model: {self.model}
498
+ index_model: {self.model}
499
+
500
+ index_filter_level: 1
501
+ index_model_max_input_length: 100000
502
+ model_max_input_length: 120000
503
+ index_filter_workers: 100
504
+ index_build_workers: 100
505
+
506
+ skip_build_index: false
507
+ execute: true
508
+ enable_multi_round_generate: false
509
+ auto_merge: editblock
510
+ human_as_model: false
511
+ """
512
+
513
+ with open(base_yml_path, "w", encoding="utf-8") as f:
514
+ f.write(base_yml_content)
515
+
516
+ def _create_chat_action_yml(self, project_dir: str, actions_dir: str) -> None:
517
+ """创建 chat_action.yml 配置文件"""
518
+ chat_action_path = os.path.join(actions_dir, "000000000001_chat_action.yml")
519
+
520
+ # 获取文件路径列表
521
+ file_paths = self.file_creator.get_file_paths(project_dir)
522
+ file_urls = "\n".join([f"- {path}" for path in file_paths])
523
+
524
+ chat_action_content = f"""add_updated_urls: []
525
+ auto_merge: editblock
526
+ chat_model: {self.model}
527
+ code_model: {self.model}
528
+ enable_active_context: true
529
+ enable_global_memory: false
530
+ enable_task_history: true
531
+ generate_times_same_model: 1
532
+ human_as_model: false
533
+ include_file:
534
+ - ./base/base.yml
535
+ include_project_structure: true
536
+ model: {self.model}
537
+ product_mode: {self.product_mode}
538
+ query: '{self.query}'
539
+ silence: false
540
+ skip_build_index: true
541
+ skip_confirm: true
542
+ skip_filter_index: false
543
+ urls:
544
+ {file_urls}
545
+ """
546
+
547
+ with open(chat_action_path, "w", encoding="utf-8") as f:
548
+ f.write(chat_action_content)
549
+
550
+ def _init_git_repo(self, project_dir: str) -> None:
551
+ """初始化 Git 仓库"""
552
+ try:
553
+ # 初始化 Git 仓库
554
+ repo = git.Repo.init(project_dir)
555
+
556
+ # 设置用户信息
557
+ config_writer = repo.config_writer()
558
+ config_writer.set_value("user", "email", self.git_user_email)
559
+ config_writer.set_value("user", "name", self.git_user_name)
560
+ config_writer.release()
561
+
562
+ # 添加所有文件
563
+ repo.git.add(A=True)
564
+
565
+ # 提交
566
+ repo.index.commit("Initial commit")
567
+
568
+ print("Git 仓库初始化成功")
569
+ except Exception as e:
570
+ print(f"Git 初始化失败: {e}")