auto-coder 0.1.332__py3-none-any.whl → 0.1.333__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.332
3
+ Version: 0.1.333
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -14,9 +14,9 @@ autocoder/command_parser.py,sha256=fx1g9E6GaM273lGTcJqaFQ-hoksS_Ik2glBMnVltPCE,1
14
14
  autocoder/lang.py,sha256=PFtATuOhHRnfpqHQkXr6p4C893JvpsgwTMif3l-GEi0,14321
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=xwLXHMI8rDhbIMThjGCWE0HubBrylkut9g8gyeI7FB4,23
17
+ autocoder/version.py,sha256=gR3Vjr8bvXetgzl9FG_ppRi16UHuqrJxfSLEsljIxOA,23
18
18
  autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- autocoder/agent/agentic_filter.py,sha256=aHioB01NQPHXV05q6MUUAYEeB96aoWIVTRX6qo68mpg,38725
19
+ autocoder/agent/agentic_filter.py,sha256=yL7ufHJWIJpwmsd5Z5IAdnLopYN89JgB8DlC7NhTYFU,38780
20
20
  autocoder/agent/auto_demand_organizer.py,sha256=URAq0gSEiHeV_W4zwhOI_83kHz0Ryfj1gcfh5jwCv_w,6501
21
21
  autocoder/agent/auto_filegroup.py,sha256=pBsAkBcpFTff-9L5OwI8xhf2xPKpl-aZwz-skF2B6dc,6296
22
22
  autocoder/agent/auto_guess_query.py,sha256=rDSdhpPHcOGE5MuDXvIrhCXAPR4ARS1LqpyoLsx2Jhw,11374
@@ -114,7 +114,7 @@ autocoder/compilers/compiler_config_manager.py,sha256=tNwHEk3t2o2L7ZVpHICDEOOIXR
114
114
  autocoder/compilers/compiler_factory.py,sha256=SLUdvBZdqr_pkY-lfArHCuBVjtiMoIs9uxCGztYj6Ro,10950
115
115
  autocoder/compilers/java_compiler.py,sha256=gR-_GB0_A1ZU3cTgRu1H9VPtLPmCWYo2UwBLEZIMvXU,26362
116
116
  autocoder/compilers/models.py,sha256=ZqGQhiF5vfsK71xzLlsCUS_q_Oune3mqokJ8S8ZOPSc,9527
117
- autocoder/compilers/provided_compiler.py,sha256=UoxXAMcNlbaUxi7f2-cr_z1idJF6aZ7jI66CjxRpc0k,12850
117
+ autocoder/compilers/provided_compiler.py,sha256=DgkaQuvpvSUk_4pMYNByrH-M6t3rgK-p5ciX4psdvyM,14541
118
118
  autocoder/compilers/python_compiler.py,sha256=2w2OM_6H0ZWvaquQpDo1x4VciBWczCZkfwmEyJEEpn8,14389
119
119
  autocoder/compilers/reactjs_compiler.py,sha256=h1_9OqiA8ca84-u3DIxQifvtH-2FSsKFWmhwALzNhqM,18159
120
120
  autocoder/compilers/shadow_compiler.py,sha256=ARx2DBr1U521u7kKnZqg3GbLMi8ggGaX5D7VEckej3U,1699
@@ -137,7 +137,7 @@ autocoder/events/event_manager_singleton.py,sha256=8aBp97fgbas0KYrpHbljTg2n4RcWd
137
137
  autocoder/events/event_store.py,sha256=y6tT3P-o3yhDptrKi-UmqI_ZBNg7v21FriI3f7lo_ME,12709
138
138
  autocoder/events/event_types.py,sha256=wONd3wC_BhGXTbXIlb4kFIr7gkhYSBjQE30JjTc8tnU,3558
139
139
  autocoder/helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
- autocoder/helper/project_creator.py,sha256=YPqWV6nyMQnlpv_lqVIo-oFZ_TgQVs9L2J040WqEZWo,17325
140
+ autocoder/helper/project_creator.py,sha256=sgXrZyAaGc84aUT7K7d7N1ztT-mSNGoLnsT-uKMUvVw,21472
141
141
  autocoder/index/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  autocoder/index/entry.py,sha256=JDONxqd8v201JwlxxKraCIKdOJa0cFhCCx74eHqWiu4,15210
143
143
  autocoder/index/for_command.py,sha256=BFvljE4t6VaMBGboZAuhUCzVK0EitCy_n5D_7FEnihw,3204
@@ -153,7 +153,7 @@ autocoder/linters/code_linter.py,sha256=JylTj-Mj4jl9-XSH3PVlbQ4l55Y6E1FG-glv860C
153
153
  autocoder/linters/linter_factory.py,sha256=rsDzaY0jFnmEsbY8Co_xxpJe9lXgfs07Nnrht8_WWtY,10273
154
154
  autocoder/linters/models.py,sha256=GBdayu_p50KBxoRms4X68zrDK-OsKDEKKjo926FevwE,9838
155
155
  autocoder/linters/python_linter.py,sha256=4psUpOOvwU8EkSHaHfW_Yd67Qvmuke8bL5_LIaj16wM,22459
156
- autocoder/linters/reactjs_linter.py,sha256=HUDm6oNwlJ7V8l22mj_2nfZUx23m5W7-v2tgWHN2-PM,21171
156
+ autocoder/linters/reactjs_linter.py,sha256=LDCXmAI15LUq8nNPyYko3oryzCc2Su05ob63jEeDdIs,20815
157
157
  autocoder/linters/shadow_linter.py,sha256=SKgRNVnTavNUviFC9osYMz18nGWCVOPOHx9LavEbnmc,15047
158
158
  autocoder/linters/vue_linter.py,sha256=ZyvoxT0kSizFh_UkR7UZYO5DV9edbvDQZaibEF9W95I,20905
159
159
  autocoder/memory/__init__.py,sha256=5FeGvsesRViYL4BkFiHw9SdlyHeWlqALpTyqOpfnBRw,179
@@ -213,7 +213,7 @@ autocoder/rag/stream_event/types.py,sha256=rtLwOE8rShmi1dJdxyBpAV5ZjLBGG9vptMiSz
213
213
  autocoder/regex_project/__init__.py,sha256=EBZeCL5ORyD_9_5u_UuG4s7XtpXOu0y1sWDmxWFtufE,6781
214
214
  autocoder/regexproject/__init__.py,sha256=QMXphSxjuv_LDIx0L_0jnnvCzMfmrOl0VMTVmXabeL0,8976
215
215
  autocoder/shadows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- autocoder/shadows/shadow_manager.py,sha256=pRojC9vW6Thhb1WcUtW_NvShsAh7fRP_HZHaKTKc5Aw,19189
216
+ autocoder/shadows/shadow_manager.py,sha256=pEngER4nVs4i7BYgVafkWdpJpmVMwe6q0poZ5Hy6TRo,19218
217
217
  autocoder/suffixproject/__init__.py,sha256=XZwHQuY5QLRpb__wS2Kad2wQGHSuY-PoANkdwGl0D6s,10354
218
218
  autocoder/tsproject/__init__.py,sha256=e_TWVyXQQxYKsXqdQZuFVqNCQLdtBVNJRTs0fgLXVdA,11055
219
219
  autocoder/utils/__init__.py,sha256=W47ac6IOZhNR1rdbho9fvhHnPI_N1i4oMcZOwxLelbU,1123
@@ -228,7 +228,7 @@ autocoder/utils/model_provider_selector.py,sha256=h1eVf4F7qfSOdJbtdwv7_xfIRcNBk3
228
228
  autocoder/utils/multi_turn.py,sha256=unK9OpqVRbK6uIcTKXgggX2wNmyj7s5eyEAQ2xUwHoM,88
229
229
  autocoder/utils/operate_config_api.py,sha256=K1lQxXNHiAYTgRDS2EGpWmjdJTrQaeP16RUWS0DIorw,5841
230
230
  autocoder/utils/print_table.py,sha256=ZMRhCA9DD0FUfKyJBWd5bDdj1RrtPtgOMWSJwtvZcLs,403
231
- autocoder/utils/project_structure.py,sha256=-RxWM30a9xXIKLwH3mBNAXdrU_0uMQjfixWXiOnfdkU,11375
231
+ autocoder/utils/project_structure.py,sha256=KnRWtGsJSmZrEV5aOOjv120vvBkZ1UZtDTnWkzpMmKI,11426
232
232
  autocoder/utils/queue_communicate.py,sha256=buyEzdvab1QA4i2QKbq35rG5v_9x9PWVLWWMTznWcYM,6832
233
233
  autocoder/utils/request_event_queue.py,sha256=r3lo5qGsB1dIjzVQ05dnr0z_9Z3zOkBdP1vmRciKdi4,2095
234
234
  autocoder/utils/request_queue.py,sha256=nwp6PMtgTCiuwJI24p8OLNZjUiprC-TsefQrhMI-yPE,3889
@@ -240,9 +240,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
240
240
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
241
241
  autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=xuBeWD0YOckqRo8JB1WkVIMOYH6c24m7JfV4svBfPDo,15113
242
242
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
243
- auto_coder-0.1.332.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
244
- auto_coder-0.1.332.dist-info/METADATA,sha256=b7Fu55tiIwI1k49ke632_b38ZA3zQlA27-R0fUF-VCM,2747
245
- auto_coder-0.1.332.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
246
- auto_coder-0.1.332.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
247
- auto_coder-0.1.332.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
248
- auto_coder-0.1.332.dist-info/RECORD,,
243
+ auto_coder-0.1.333.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
244
+ auto_coder-0.1.333.dist-info/METADATA,sha256=47OVdUScaSXgezpPf8UF0SDziICztbvaMaJNB_j2X_o,2747
245
+ auto_coder-0.1.333.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
246
+ auto_coder-0.1.333.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
247
+ auto_coder-0.1.333.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
248
+ auto_coder-0.1.333.dist-info/RECORD,,
@@ -878,7 +878,8 @@ class AgenticFilter:
878
878
  )
879
879
 
880
880
  if success_flag:
881
- return AgenticFilterResponse(**json.loads(content))
881
+ to_model(content, AgenticFilterResponse)
882
+ # return AgenticFilterResponse(**json.loads(content))
882
883
  else:
883
884
  return None
884
885
 
@@ -11,6 +11,7 @@ from typing import Dict, List, Any, Optional, Union
11
11
  import time
12
12
  from pathlib import Path
13
13
 
14
+ from autocoder.common import AutoCoderArgs
14
15
  from autocoder.compilers.base_compiler import BaseCompiler
15
16
  from autocoder.compilers.models import (
16
17
  CompilationError,
@@ -19,6 +20,7 @@ from autocoder.compilers.models import (
19
20
  CompilationErrorPosition,
20
21
  CompilationErrorSeverity
21
22
  )
23
+ from autocoder.utils.project_structure import EnhancedFileAnalyzer
22
24
 
23
25
 
24
26
  class ProvidedCompiler(BaseCompiler):
@@ -233,6 +235,33 @@ class ProvidedCompiler(BaseCompiler):
233
235
  'file_path': file_path,
234
236
  'language': 'unknown'
235
237
  }
238
+
239
+
240
+ def get_all_extensions(self, directory: str = ".") -> str:
241
+ """获取指定目录下所有文件的后缀名,多个按逗号分隔,并且带."""
242
+ args = AutoCoderArgs(
243
+ source_dir=directory,
244
+ # 其他必要参数设置为默认值
245
+ target_file="",
246
+ git_url="",
247
+ project_type="",
248
+ conversation_prune_safe_zone_tokens=0
249
+ )
250
+
251
+ analyzer = EnhancedFileAnalyzer(
252
+ args=args,
253
+ llm=None, # 如果只是获取后缀名,可以不需要LLM
254
+ config=None # 使用默认配置
255
+ )
256
+
257
+ # 获取分析结果
258
+ analysis_result = analyzer.analyze_extensions()
259
+
260
+ # 合并 code 和 config 的后缀名
261
+ all_extensions = set(analysis_result["code"] + analysis_result["config"])
262
+
263
+ # 转换为逗号分隔的字符串
264
+ return ",".join(sorted(all_extensions))
236
265
 
237
266
  def compile_project(self, project_path: str,target_compiler_name:Optional[str] = None) -> ProjectCompilationResult:
238
267
  """
@@ -257,6 +286,16 @@ class ProvidedCompiler(BaseCompiler):
257
286
  return result
258
287
 
259
288
  target_compiler_config = None
289
+ if not target_compiler_name:
290
+ for compiler_config in self.config.get('compilers', []):
291
+ working_dir = os.path.join(project_path,compiler_config.get('working_dir', '.'))
292
+ print(working_dir)
293
+ all_extensions = self.get_all_extensions(working_dir)
294
+ triggers = compiler_config.get("triggers",[])
295
+ if any(trigger in all_extensions for trigger in triggers):
296
+ target_compiler_config = compiler_config
297
+ break
298
+
260
299
  if target_compiler_name:
261
300
  for compiler_config in self.config.get('compilers', []):
262
301
  if compiler_config.get("name","") == target_compiler_name:
@@ -130,34 +130,40 @@ if __name__ == "__main__":
130
130
 
131
131
  class ReactJSFileCreator(FileCreator):
132
132
  """
133
- React TypeScript 计算器项目文件创建器
133
+ Vite + React TypeScript 计算器项目文件创建器
134
134
  """
135
135
 
136
136
  def create_files(self, project_dir: str) -> None:
137
- """创建 React TypeScript 项目文件"""
137
+ """创建 Vite + React TypeScript 项目文件"""
138
138
  # 创建 package.json
139
139
  self._create_package_json(project_dir)
140
140
  # 创建 index.html
141
141
  self._create_index_html(project_dir)
142
+ # 创建 vite.config.ts
143
+ self._create_vite_config(project_dir)
142
144
  # 创建 src 目录
143
145
  src_dir = os.path.join(project_dir, "src")
144
146
  os.makedirs(src_dir, exist_ok=True)
145
147
  # 创建 App.tsx 和 Calculator.tsx 组件
146
148
  self._create_app_tsx(src_dir)
147
149
  self._create_calculator_component(src_dir)
148
- self._create_index_tsx(src_dir)
149
- # 创建 tsconfig.json
150
+ self._create_main_tsx(src_dir)
151
+ # 创建 tsconfig.json 和 tsconfig.node.json
150
152
  self._create_tsconfig_json(project_dir)
153
+ self._create_tsconfig_node_json(project_dir)
154
+ # 创建 .gitignore
155
+ self._create_gitignore(project_dir)
151
156
 
152
157
  def get_file_paths(self, project_dir: str) -> List[str]:
153
- """获取 React TypeScript 项目的主要文件路径"""
158
+ """获取 Vite + React TypeScript 项目的主要文件路径"""
154
159
  abs_project_dir = os.path.abspath(project_dir)
155
160
  return [
156
161
  os.path.join(abs_project_dir, "package.json"),
162
+ os.path.join(abs_project_dir, "vite.config.ts"),
157
163
  os.path.join(abs_project_dir, "tsconfig.json"),
158
164
  os.path.join(abs_project_dir, "src", "App.tsx"),
159
165
  os.path.join(abs_project_dir, "src", "Calculator.tsx"),
160
- os.path.join(abs_project_dir, "src", "index.tsx")
166
+ os.path.join(abs_project_dir, "src", "main.tsx")
161
167
  ]
162
168
 
163
169
  @property
@@ -167,20 +173,17 @@ class ReactJSFileCreator(FileCreator):
167
173
 
168
174
  def _create_index_html(self, project_dir: str) -> None:
169
175
  """创建 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)
176
+ index_html_path = os.path.join(project_dir, "index.html")
172
177
  index_html_content = """<!DOCTYPE html>
173
178
  <html lang="en">
174
179
  <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
+ <meta charset="UTF-8" />
181
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
182
+ <title>Vite + React Calculator</title>
180
183
  </head>
181
184
  <body>
182
- <noscript>You need to enable JavaScript to run this app.</noscript>
183
185
  <div id="root"></div>
186
+ <script type="module" src="/src/main.tsx"></script>
184
187
  </body>
185
188
  </html>"""
186
189
  with open(index_html_path, "w", encoding="utf-8") as f:
@@ -191,133 +194,213 @@ class ReactJSFileCreator(FileCreator):
191
194
  package_path = os.path.join(project_dir, "package.json")
192
195
  package_content = """{
193
196
  "name": "calculator-app",
194
- "version": "0.1.0",
195
197
  "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
- },
198
+ "version": "0.1.0",
199
+ "type": "module",
205
200
  "scripts": {
206
- "start": "react-scripts start",
207
- "build": "react-scripts build",
208
- "test": "react-scripts test",
209
- "eject": "react-scripts eject"
201
+ "dev": "vite",
202
+ "build": "tsc && vite build",
203
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
204
+ "preview": "vite preview"
210
205
  },
211
- "eslintConfig": {
212
- "extends": [
213
- "react-app",
214
- "react-app/jest"
215
- ]
206
+ "dependencies": {
207
+ "react": "^18.2.0",
208
+ "react-dom": "^18.2.0"
216
209
  },
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
- ]
210
+ "devDependencies": {
211
+ "@types/react": "^18.2.15",
212
+ "@types/react-dom": "^18.2.7",
213
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
214
+ "@typescript-eslint/parser": "^6.0.0",
215
+ "@vitejs/plugin-react": "^4.0.3",
216
+ "eslint": "^8.45.0",
217
+ "eslint-plugin-react-hooks": "^4.6.0",
218
+ "eslint-plugin-react-refresh": "^0.4.3",
219
+ "typescript": "^5.0.2",
220
+ "vite": "^4.4.5"
228
221
  }
229
222
  }"""
230
223
  with open(package_path, "w", encoding="utf-8") as f:
231
224
  f.write(package_content)
232
225
 
226
+ def _create_vite_config(self, project_dir: str) -> None:
227
+ """创建 vite.config.ts 文件"""
228
+ vite_config_path = os.path.join(project_dir, "vite.config.ts")
229
+ vite_config_content = """import { defineConfig } from 'vite'
230
+ import react from '@vitejs/plugin-react'
231
+
232
+ // https://vitejs.dev/config/
233
+ export default defineConfig({
234
+ plugins: [react()],
235
+ })
236
+ """
237
+ with open(vite_config_path, "w", encoding="utf-8") as f:
238
+ f.write(vite_config_content)
239
+
233
240
  def _create_tsconfig_json(self, project_dir: str) -> None:
234
241
  """创建 tsconfig.json 文件"""
235
242
  tsconfig_path = os.path.join(project_dir, "tsconfig.json")
236
243
  tsconfig_content = """{
237
244
  "compilerOptions": {
238
- "target": "es5",
239
- "lib": ["dom", "dom.iterable", "esnext"],
240
- "allowJs": true,
245
+ "target": "ES2020",
246
+ "useDefineForClassFields": true,
247
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
248
+ "module": "ESNext",
241
249
  "skipLibCheck": true,
242
- "esModuleInterop": true,
243
- "allowSyntheticDefaultImports": true,
244
- "strict": true,
245
- "forceConsistentCasingInFileNames": true,
246
- "noFallthroughCasesInSwitch": true,
247
- "module": "esnext",
248
- "moduleResolution": "node",
250
+
251
+ /* Bundler mode */
252
+ "moduleResolution": "bundler",
253
+ "allowImportingTsExtensions": true,
249
254
  "resolveJsonModule": true,
250
255
  "isolatedModules": true,
251
256
  "noEmit": true,
252
- "jsx": "react-jsx"
257
+ "jsx": "react-jsx",
258
+
259
+ /* Linting */
260
+ "strict": true,
261
+ "noUnusedLocals": true,
262
+ "noUnusedParameters": true,
263
+ "noFallthroughCasesInSwitch": true
253
264
  },
254
- "include": ["src"]
265
+ "include": ["src"],
266
+ "references": [{ "path": "./tsconfig.node.json" }]
255
267
  }"""
256
268
  with open(tsconfig_path, "w", encoding="utf-8") as f:
257
269
  f.write(tsconfig_content)
258
270
 
271
+ def _create_tsconfig_node_json(self, project_dir: str) -> None:
272
+ """创建 tsconfig.node.json 文件"""
273
+ tsconfig_node_path = os.path.join(project_dir, "tsconfig.node.json")
274
+ tsconfig_node_content = """{
275
+ "compilerOptions": {
276
+ "composite": true,
277
+ "skipLibCheck": true,
278
+ "module": "ESNext",
279
+ "moduleResolution": "bundler",
280
+ "allowSyntheticDefaultImports": true
281
+ },
282
+ "include": ["vite.config.ts"]
283
+ }"""
284
+ with open(tsconfig_node_path, "w", encoding="utf-8") as f:
285
+ f.write(tsconfig_node_content)
286
+
287
+ def _create_gitignore(self, project_dir: str) -> None:
288
+ """创建 .gitignore 文件"""
289
+ gitignore_path = os.path.join(project_dir, ".gitignore")
290
+ gitignore_content = """# Logs
291
+ logs
292
+ *.log
293
+ npm-debug.log*
294
+ yarn-debug.log*
295
+ yarn-error.log*
296
+ pnpm-debug.log*
297
+ lerna-debug.log*
298
+
299
+ node_modules
300
+ dist
301
+ dist-ssr
302
+ *.local
303
+
304
+ # Editor directories and files
305
+ .vscode/*
306
+ !.vscode/extensions.json
307
+ .idea
308
+ .DS_Store
309
+ *.suo
310
+ *.ntvs*
311
+ *.njsproj
312
+ *.sln
313
+ *.sw?
314
+ """
315
+ with open(gitignore_path, "w", encoding="utf-8") as f:
316
+ f.write(gitignore_content)
317
+
259
318
  def _create_app_tsx(self, src_dir: str) -> None:
260
319
  """创建 App.tsx 文件"""
261
320
  app_path = os.path.join(src_dir, "App.tsx")
262
- app_content = """import React from 'react';
263
- import Calculator from './Calculator';
321
+ app_content = """import { useState } from 'react'
322
+ import Calculator from './Calculator'
323
+ import './App.css'
264
324
 
265
- const App: React.FC = () => {
325
+ function App() {
266
326
  return (
267
327
  <div className="App">
268
328
  <header className="App-header">
269
- <h1>React Calculator</h1>
329
+ <h1>Vite + React Calculator</h1>
270
330
  </header>
271
331
  <main>
272
332
  <Calculator />
273
333
  </main>
274
334
  </div>
275
- );
276
- };
335
+ )
336
+ }
277
337
 
278
- export default App;"""
338
+ export default App
339
+ """
279
340
  with open(app_path, "w", encoding="utf-8") as f:
280
341
  f.write(app_content)
342
+
343
+ # 创建 App.css 文件
344
+ app_css_path = os.path.join(src_dir, "App.css")
345
+ app_css_content = """.App {
346
+ max-width: 1280px;
347
+ margin: 0 auto;
348
+ padding: 2rem;
349
+ text-align: center;
350
+ }
351
+
352
+ .App-header {
353
+ margin-bottom: 2rem;
354
+ }
355
+
356
+ .App-header h1 {
357
+ font-size: 2.5em;
358
+ line-height: 1.1;
359
+ }
360
+ """
361
+ with open(app_css_path, "w", encoding="utf-8") as f:
362
+ f.write(app_css_content)
281
363
 
282
364
  def _create_calculator_component(self, src_dir: str) -> None:
283
365
  """创建 Calculator.tsx 组件"""
284
366
  calculator_path = os.path.join(src_dir, "Calculator.tsx")
285
- calculator_content = """import React, { useState } from 'react';
367
+ calculator_content = """import { useState } from 'react'
368
+ import './Calculator.css'
286
369
 
287
370
  interface CalculatorProps {}
288
371
 
289
372
  const Calculator: React.FC<CalculatorProps> = () => {
290
- const [display, setDisplay] = useState<string>('0');
291
- const [equation, setEquation] = useState<string>('');
373
+ const [display, setDisplay] = useState<string>('0')
374
+ const [equation, setEquation] = useState<string>('')
292
375
 
293
376
  const handleNumber = (num: string) => {
294
377
  if (display === '0') {
295
- setDisplay(num);
378
+ setDisplay(num)
296
379
  } else {
297
- setDisplay(display + num);
380
+ setDisplay(display + num)
298
381
  }
299
- };
382
+ }
300
383
 
301
384
  const handleOperator = (operator: string) => {
302
- setEquation(display + ' ' + operator + ' ');
303
- setDisplay('0');
304
- };
385
+ setEquation(display + ' ' + operator + ' ')
386
+ setDisplay('0')
387
+ }
305
388
 
306
389
  const handleEqual = () => {
307
390
  try {
308
- const result = eval(equation + display);
309
- setDisplay(result.toString());
310
- setEquation('');
391
+ const result = eval(equation + display)
392
+ setDisplay(result.toString())
393
+ setEquation('')
311
394
  } catch (error) {
312
- setDisplay('Error');
313
- setEquation('');
395
+ setDisplay('Error')
396
+ setEquation('')
314
397
  }
315
- };
398
+ }
316
399
 
317
400
  const handleClear = () => {
318
- setDisplay('0');
319
- setEquation('');
320
- };
401
+ setDisplay('0')
402
+ setEquation('')
403
+ }
321
404
 
322
405
  return (
323
406
  <div className="calculator">
@@ -345,31 +428,130 @@ const Calculator: React.FC<CalculatorProps> = () => {
345
428
  <button onClick={() => handleNumber('.')}>.</button>
346
429
  </div>
347
430
  </div>
348
- );
349
- };
431
+ )
432
+ }
350
433
 
351
- export default Calculator;"""
434
+ export default Calculator
435
+ """
352
436
  with open(calculator_path, "w", encoding="utf-8") as f:
353
437
  f.write(calculator_content)
438
+
439
+ # 创建 Calculator.css 文件
440
+ calculator_css_path = os.path.join(src_dir, "Calculator.css")
441
+ calculator_css_content = """.calculator {
442
+ width: 300px;
443
+ margin: 0 auto;
444
+ border: 1px solid #ccc;
445
+ border-radius: 5px;
446
+ padding: 10px;
447
+ background-color: #f7f7f7;
448
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
449
+ }
450
+
451
+ .display {
452
+ background-color: #fff;
453
+ border: 1px solid #ddd;
454
+ border-radius: 3px;
455
+ margin-bottom: 10px;
456
+ padding: 10px;
457
+ text-align: right;
458
+ min-height: 60px;
459
+ }
460
+
461
+ .equation {
462
+ color: #777;
463
+ font-size: 14px;
464
+ min-height: 20px;
465
+ }
466
+
467
+ .current {
468
+ font-size: 24px;
469
+ font-weight: bold;
470
+ margin-top: 5px;
471
+ }
472
+
473
+ .buttons {
474
+ display: grid;
475
+ grid-template-columns: repeat(4, 1fr);
476
+ gap: 5px;
477
+ }
478
+
479
+ button {
480
+ background-color: #e0e0e0;
481
+ border: 1px solid #ccc;
482
+ border-radius: 3px;
483
+ font-size: 18px;
484
+ padding: 10px;
485
+ cursor: pointer;
486
+ transition: background-color 0.2s;
487
+ }
488
+
489
+ button:hover {
490
+ background-color: #d0d0d0;
491
+ }
492
+
493
+ button:active {
494
+ background-color: #c0c0c0;
495
+ }
496
+ """
497
+ with open(calculator_css_path, "w", encoding="utf-8") as f:
498
+ f.write(calculator_css_content)
354
499
 
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(
500
+ def _create_main_tsx(self, src_dir: str) -> None:
501
+ """创建 main.tsx 文件"""
502
+ main_path = os.path.join(src_dir, "main.tsx")
503
+ main_content = """import React from 'react'
504
+ import ReactDOM from 'react-dom/client'
505
+ import App from './App'
506
+ import './index.css'
507
+
508
+ ReactDOM.createRoot(document.getElementById('root')!).render(
367
509
  <React.StrictMode>
368
510
  <App />
369
- </React.StrictMode>
370
- );"""
371
- with open(index_path, "w", encoding="utf-8") as f:
372
- f.write(index_content)
511
+ </React.StrictMode>,
512
+ )
513
+ """
514
+ with open(main_path, "w", encoding="utf-8") as f:
515
+ f.write(main_content)
516
+
517
+ # 创建 index.css 文件
518
+ index_css_path = os.path.join(src_dir, "index.css")
519
+ index_css_content = """:root {
520
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
521
+ line-height: 1.5;
522
+ font-weight: 400;
523
+
524
+ color-scheme: light dark;
525
+ color: rgba(255, 255, 255, 0.87);
526
+ background-color: #242424;
527
+
528
+ font-synthesis: none;
529
+ text-rendering: optimizeLegibility;
530
+ -webkit-font-smoothing: antialiased;
531
+ -moz-osx-font-smoothing: grayscale;
532
+ }
533
+
534
+ @media (prefers-color-scheme: light) {
535
+ :root {
536
+ color: #213547;
537
+ background-color: #ffffff;
538
+ }
539
+ }
540
+
541
+ body {
542
+ margin: 0;
543
+ display: flex;
544
+ place-items: center;
545
+ min-width: 320px;
546
+ min-height: 100vh;
547
+ }
548
+
549
+ * {
550
+ box-sizing: border-box;
551
+ }
552
+ """
553
+ with open(index_css_path, "w", encoding="utf-8") as f:
554
+ f.write(index_css_content)
373
555
 
374
556
 
375
557
  class FileCreatorFactory:
@@ -207,22 +207,59 @@ class ReactJSLinter(BaseLinter):
207
207
  Returns:
208
208
  str: The extracted JSON string, or the original text if no separator is found.
209
209
  """
210
- if "=============" in output_text:
211
- lines = output_text.split('\n')
212
- json_lines = []
213
- found_separator = False
214
-
215
- for line in lines:
216
- if line.startswith("============="):
217
- found_separator = True
218
- continue
219
- if found_separator:
220
- json_lines.append(line)
210
+ return output_text.split("=============")[-1]
211
+
212
+ def _convert_raw_lint_result_to_dict(self, raw_result: str,result: Dict[str, Any], project_path: str):
213
+ try:
214
+ output_text = raw_result
215
+ eslint_output = []
216
+ try:
217
+ eslint_output = json.loads(output_text)
218
+ except json.JSONDecodeError:
219
+ # Try to extract JSON from output if it contains separator
220
+ json_text = self._extract_json_from_output(output_text)
221
+ try:
222
+ eslint_output = json.loads(json_text)
223
+ except json.JSONDecodeError:
224
+ print(json_text[0:100],"...",json_text[-100:])
221
225
 
222
- if json_lines:
223
- return '\n'.join(json_lines)
224
-
225
- return output_text
226
+ # print(f"eslint_output: {json.dumps(eslint_output, indent=4,ensure_ascii=False)}")
227
+
228
+ # Count files analyzed (should be 1)
229
+ result['files_analyzed'] = len(eslint_output)
230
+
231
+ # Track overall counts
232
+ total_errors = 0
233
+ total_warnings = 0
234
+
235
+ # Process the file result
236
+ for file_result in eslint_output:
237
+ file_rel_path = os.path.relpath(
238
+ file_result['filePath'], project_path)
239
+
240
+ # Add error and warning counts
241
+ total_errors += file_result.get('errorCount', 0)
242
+ total_warnings += file_result.get('warningCount', 0)
243
+
244
+ # Process individual messages
245
+ for message in file_result.get('messages', []):
246
+ issue = {
247
+ 'file': file_rel_path,
248
+ 'line': message.get('line', 0),
249
+ 'column': message.get('column', 0),
250
+ 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
251
+ 'message': message.get('message', ''),
252
+ 'rule': message.get('ruleId', 'unknown')
253
+ }
254
+ result['issues'].append(issue)
255
+
256
+ result['error_count'] = total_errors
257
+ result['warning_count'] = total_warnings
258
+ result['success'] = True
259
+ except json.JSONDecodeError:
260
+ # Handle case where ESLint output is not valid JSON
261
+ result['error'] = "Failed to parse ESLint output"
262
+
226
263
 
227
264
  def lint_file(self, file_path: str, fix: bool = False, project_path: str = None) -> Dict[str, Any]:
228
265
  """
@@ -296,51 +333,7 @@ class ReactJSLinter(BaseLinter):
296
333
 
297
334
  # Parse ESLint output
298
335
  if process.stdout:
299
- try:
300
- output_text = process.stdout
301
- try:
302
- eslint_output = json.loads(output_text)
303
- except json.JSONDecodeError:
304
- # Try to extract JSON from output if it contains separator
305
- json_text = self._extract_json_from_output(output_text)
306
- eslint_output = json.loads(json_text)
307
-
308
- # print(f"eslint_output: {json.dumps(eslint_output, indent=4,ensure_ascii=False)}")
309
-
310
- # Count files analyzed (should be 1)
311
- result['files_analyzed'] = len(eslint_output)
312
-
313
- # Track overall counts
314
- total_errors = 0
315
- total_warnings = 0
316
-
317
- # Process the file result
318
- for file_result in eslint_output:
319
- file_rel_path = os.path.relpath(
320
- file_result['filePath'], project_path)
321
-
322
- # Add error and warning counts
323
- total_errors += file_result.get('errorCount', 0)
324
- total_warnings += file_result.get('warningCount', 0)
325
-
326
- # Process individual messages
327
- for message in file_result.get('messages', []):
328
- issue = {
329
- 'file': file_rel_path,
330
- 'line': message.get('line', 0),
331
- 'column': message.get('column', 0),
332
- 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
333
- 'message': message.get('message', ''),
334
- 'rule': message.get('ruleId', 'unknown')
335
- }
336
- result['issues'].append(issue)
337
-
338
- result['error_count'] = total_errors
339
- result['warning_count'] = total_warnings
340
- result['success'] = True
341
- except json.JSONDecodeError:
342
- # Handle case where ESLint output is not valid JSON
343
- result['error'] = "Failed to parse ESLint output"
336
+ self._convert_raw_lint_result_to_dict(process.stdout, result, project_path)
344
337
  else:
345
338
  # Handle case where ESLint didn't produce any output
346
339
  stderr = process.stderr.strip()
@@ -577,4 +570,5 @@ def format_lint_result(lint_result: Dict[str, Any]) -> str:
577
570
  str: A formatted string representation of the lint results.
578
571
  """
579
572
  linter = ReactJSLinter()
580
- return linter.format_lint_result(lint_result)
573
+ return linter.format_lint_result(lint_result)
574
+
@@ -285,7 +285,7 @@ class ShadowManager:
285
285
  # 删除链接项目目录中的所有内容
286
286
  for item in os.listdir(self.link_projects_dir):
287
287
  item_path = os.path.join(self.link_projects_dir, item)
288
- if os.path.isfile(item_path):
288
+ if os.path.isfile(item_path) or os.path.islink(item_path):
289
289
  os.unlink(item_path)
290
290
  elif os.path.isdir(item_path):
291
291
  shutil.rmtree(item_path)
@@ -127,9 +127,9 @@ class EnhancedFileAnalyzer:
127
127
  return self._basic_analysis(extensions)
128
128
 
129
129
  def _collect_extensions(self) -> Set[str]:
130
- """带过滤的文件后缀收集"""
130
+ """带过滤的文件后缀收集,支持软链接目录和文件"""
131
131
  extensions = set()
132
- for root, dirs, files in os.walk(self.directory):
132
+ for root, dirs, files in os.walk(self.directory, followlinks=True):
133
133
  dirs[:] = [d for d in dirs if not self.file_filter.should_ignore(d, True)]
134
134
  for file in files:
135
135
  if self.file_filter.should_ignore(file, False):
autocoder/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.332"
1
+ __version__ = "0.1.333"