auto-coder-web 0.1.26__py3-none-any.whl → 0.1.29__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.
auto_coder_web/proxy.py CHANGED
@@ -15,315 +15,39 @@ import os
15
15
  import argparse
16
16
  import aiofiles
17
17
  import pkg_resources
18
- import asyncio
19
- import pathlib
20
- import time
21
18
  import sys
22
- from auto_coder_web.file_group import FileGroupManager
23
- from auto_coder_web.file_manager import get_directory_tree
24
19
  from auto_coder_web.auto_coder_runner import AutoCoderRunner
25
- from autocoder.agent.auto_filegroup import AutoFileGroup
26
- from .types import (
27
- ChatList,
20
+ from .types import (
28
21
  FileContentResponse,
29
22
  )
30
-
31
- from rich.console import Console
32
- from prompt_toolkit.shortcuts import radiolist_dialog
33
- from prompt_toolkit.formatted_text import HTML
34
- import subprocess
35
- from prompt_toolkit import prompt
36
- from pydantic import BaseModel
37
- from autocoder.utils.log_capture import LogCapture
38
23
  from .terminal import terminal_manager
39
24
  from autocoder.common import AutoCoderArgs
40
- import json
41
- import re
42
- import yaml
43
- import git
44
- import hashlib
45
- from datetime import datetime
46
25
  from auto_coder_web.auto_coder_runner_wrapper import AutoCoderRunnerWrapper
47
26
  from .routers import todo_router, settings_router, auto_router, commit_router, chat_router, coding_router
48
27
  from expert_routers import history_router
49
28
  from .common_router import completions_router, file_router, auto_coder_conf_router, chat_list_router, file_group_router
50
-
51
-
52
-
53
- def check_environment():
54
- """Check and initialize the required environment"""
55
- console = Console()
56
- console.print("\n[blue]Initializing the environment...[/blue]")
57
-
58
- def check_project():
59
- """Check if the current directory is initialized as an auto-coder project"""
60
- def print_status(message, status):
61
- if status == "success":
62
- console.print(f"✓ {message}", style="green")
63
- elif status == "warning":
64
- console.print(f"! {message}", style="yellow")
65
- elif status == "error":
66
- console.print(f"✗ {message}", style="red")
67
- else:
68
- console.print(f" {message}")
69
-
70
- if not os.path.exists("actions") or not os.path.exists(".auto-coder"):
71
- print_status("Project not initialized", "warning")
72
- init_choice = input(
73
- " Do you want to initialize the project? (y/n): ").strip().lower()
74
- if init_choice == "y":
75
- try:
76
- if not os.path.exists("actions"):
77
- os.makedirs("actions", exist_ok=True)
78
- print_status("Created actions directory", "success")
79
-
80
- if not os.path.exists(".auto-coder"):
81
- os.makedirs(".auto-coder", exist_ok=True)
82
- print_status(
83
- "Created .auto-coder directory", "success")
84
-
85
- subprocess.run(
86
- ["auto-coder", "init", "--source_dir", "."], check=True)
87
- print_status("Project initialized successfully", "success")
88
- except subprocess.CalledProcessError:
89
- print_status("Failed to initialize project", "error")
90
- print_status(
91
- "Please try to initialize manually: auto-coder init --source_dir .", "warning")
92
- return False
93
- else:
94
- print_status("Exiting due to no initialization", "warning")
95
- return False
96
-
97
- print_status("Project initialization check complete", "success")
98
- return True
99
-
100
- if not check_project():
101
- return False
102
-
103
- def print_status(message, status):
104
- if status == "success":
105
- console.print(f"✓ {message}", style="green")
106
- elif status == "warning":
107
- console.print(f"! {message}", style="yellow")
108
- elif status == "error":
109
- console.print(f"✗ {message}", style="red")
110
- else:
111
- console.print(f" {message}")
112
-
113
- # Check if Ray is running
114
- print_status("Checking Ray", "")
115
- ray_status = subprocess.run(
116
- ["ray", "status"], capture_output=True, text=True)
117
- if ray_status.returncode != 0:
118
- print_status("Ray is not running", "warning")
119
- try:
120
- subprocess.run(["ray", "start", "--head"], check=True)
121
- print_status("Ray started successfully", "success")
122
- except subprocess.CalledProcessError:
123
- print_status("Failed to start Ray", "error")
124
- return False
125
-
126
- # Check if deepseek_chat model is available
127
- print_status("Checking deepseek_chat model", "")
128
- try:
129
- result = subprocess.run(
130
- ["easy-byzerllm", "chat", "deepseek_chat", "你好"],
131
- capture_output=True,
132
- text=True,
133
- timeout=30,
134
- )
135
- if result.returncode == 0:
136
- print_status("deepseek_chat model is available", "success")
137
- print_status("Environment check complete", "success")
138
- return True
139
- except subprocess.TimeoutExpired:
140
- print_status("Model check timeout", "error")
141
- except subprocess.CalledProcessError:
142
- print_status("Model check error", "error")
143
- except Exception as e:
144
- print_status(f"Unexpected error: {str(e)}", "error")
145
-
146
- print_status("deepseek_chat model is not available", "warning")
147
-
148
- # If deepseek_chat is not available, prompt user to choose a provider
149
- choice = radiolist_dialog(
150
- title="Select Provider",
151
- text="Please select a provider for deepseek_chat model:",
152
- values=[
153
- ("1", "硅基流动(https://siliconflow.cn)"),
154
- ("2", "Deepseek官方(https://www.deepseek.com/)"),
155
- ],
156
- ).run()
157
-
158
- if choice is None:
159
- print_status("No provider selected", "error")
160
- return False
161
-
162
- api_key = prompt(HTML("<b>Please enter your API key: </b>"))
163
-
164
- if choice == "1":
165
- print_status("Deploying model with 硅基流动", "")
166
- deploy_cmd = [
167
- "easy-byzerllm",
168
- "deploy",
169
- "deepseek-ai/deepseek-v2-chat",
170
- "--token",
171
- api_key,
172
- "--alias",
173
- "deepseek_chat",
174
- ]
175
- else:
176
- print_status("Deploying model with Deepseek官方", "")
177
- deploy_cmd = [
178
- "byzerllm",
179
- "deploy",
180
- "--pretrained_model_type",
181
- "saas/openai",
182
- "--cpus_per_worker",
183
- "0.001",
184
- "--gpus_per_worker",
185
- "0",
186
- "--worker_concurrency",
187
- "1000",
188
- "--num_workers",
189
- "1",
190
- "--infer_params",
191
- f"saas.base_url=https://api.deepseek.com/v1 saas.api_key={api_key} saas.model=deepseek-chat",
192
- "--model",
193
- "deepseek_chat",
194
- ]
195
-
196
- try:
197
- subprocess.run(deploy_cmd, check=True)
198
- print_status("Model deployed successfully", "success")
199
- except subprocess.CalledProcessError:
200
- print_status("Failed to deploy model", "error")
201
- return False
202
-
203
- # Validate the deployment
204
- print_status("Validating model deployment", "")
205
- try:
206
- validation_result = subprocess.run(
207
- ["easy-byzerllm", "chat", "deepseek_chat", "你好"],
208
- capture_output=True,
209
- text=True,
210
- timeout=30,
211
- check=True,
212
- )
213
- print_status("Model validation successful", "success")
214
- except (subprocess.TimeoutExpired, subprocess.CalledProcessError):
215
- print_status("Model validation failed", "error")
216
- print_status(
217
- "You may need to try manually: easy-byzerllm chat deepseek_chat 你好", "warning")
218
- return False
219
-
220
- print_status("Environment initialization complete", "success")
221
- return True
222
-
223
-
224
- def check_environment_lite():
225
- """Check and initialize the required environment for lite mode"""
226
- console = Console()
227
- console.print("\n[blue]Initializing the environment (Lite Mode)...[/blue]")
228
-
229
- def check_project():
230
- """Check if the current directory is initialized as an auto-coder project"""
231
- def print_status(message, status):
232
- if status == "success":
233
- console.print(f"✓ {message}", style="green")
234
- elif status == "warning":
235
- console.print(f"! {message}", style="yellow")
236
- elif status == "error":
237
- console.print(f"✗ {message}", style="red")
238
- else:
239
- console.print(f" {message}")
240
-
241
- first_time = False
242
- if not os.path.exists("actions") or not os.path.exists(".auto-coder"):
243
- first_time = True
244
- print_status("Project not initialized", "warning")
245
- init_choice = input(
246
- " Do you want to initialize the project? (y/n): ").strip().lower()
247
- if init_choice == "y":
248
- try:
249
- if not os.path.exists("actions"):
250
- os.makedirs("actions", exist_ok=True)
251
- print_status("Created actions directory", "success")
252
-
253
- if not os.path.exists(".auto-coder"):
254
- os.makedirs(".auto-coder", exist_ok=True)
255
- print_status(
256
- "Created .auto-coder directory", "success")
257
-
258
- subprocess.run(
259
- ["auto-coder", "init", "--source_dir", "."], check=True)
260
- print_status("Project initialized successfully", "success")
261
- except subprocess.CalledProcessError:
262
- print_status("Failed to initialize project", "error")
263
- print_status(
264
- "Please try to initialize manually: auto-coder init --source_dir .", "warning")
265
- return False
266
- else:
267
- print_status("Exiting due to no initialization", "warning")
268
- return False
269
-
270
- print_status("Project initialization check complete", "success")
271
- return True
272
-
273
- if not check_project():
274
- return False
275
-
276
- def print_status(message, status):
277
- if status == "success":
278
- console.print(f"✓ {message}", style="green")
279
- elif status == "warning":
280
- console.print(f"! {message}", style="yellow")
281
- elif status == "error":
282
- console.print(f"✗ {message}", style="red")
283
- else:
284
- console.print(f" {message}")
285
-
286
- # Setup deepseek api key
287
- api_key_dir = os.path.expanduser("~/.auto-coder/keys")
288
- api_key_file = os.path.join(api_key_dir, "api.deepseek.com")
289
-
290
- if not os.path.exists(api_key_file):
291
- print_status("API key not found", "warning")
292
- api_key = prompt(HTML("<b>Please enter your API key: </b>"))
293
-
294
- # Create directory if it doesn't exist
295
- os.makedirs(api_key_dir, exist_ok=True)
296
-
297
- # Save the API key
298
- with open(api_key_file, "w") as f:
299
- f.write(api_key)
300
-
301
- print_status(f"API key saved successfully: {api_key_file}", "success")
302
-
303
- print_status("Environment initialization complete", "success")
304
- return True
305
-
29
+ from rich.console import Console
30
+ from loguru import logger
31
+ from auto_coder_web.lang import get_message
306
32
 
307
33
  class ProxyServer:
308
34
  def __init__(self, project_path: str, quick: bool = False, product_mode: str = "pro"):
309
- self.app = FastAPI()
310
-
311
- if not quick:
312
- # Check the environment based on product mode
313
- if product_mode == "lite":
314
- if not check_environment_lite():
315
- print(
316
- "\033[31mEnvironment check failed. Some features may not work properly.\033[0m")
317
- else:
318
- if not check_environment():
319
- print(
320
- "\033[31mEnvironment check failed. Some features may not work properly.\033[0m")
321
-
35
+ self.app = FastAPI()
322
36
  self.setup_middleware()
323
37
 
324
38
  self.setup_static_files()
325
39
  self.project_path = project_path
40
+
41
+ # Check if project is initialized
42
+ self.is_initialized = self.check_project_initialization()
43
+ if not self.is_initialized:
44
+ logger.warning(get_message("project_not_initialized"))
45
+ logger.warning(get_message("run_auto_coder_chat"))
46
+ sys.exit(1)
47
+
326
48
  self.auto_coder_runner = AutoCoderRunnerWrapper(project_path, product_mode=product_mode)
49
+
50
+
327
51
  self.setup_routes()
328
52
  self.client = httpx.AsyncClient()
329
53
 
@@ -354,6 +78,8 @@ class ProxyServer:
354
78
  self.app.state.project_path = self.project_path
355
79
  # Store auto_coder_runner in app state for dependency injection
356
80
  self.app.state.auto_coder_runner = self.auto_coder_runner
81
+ # Store initialization status
82
+ self.app.state.is_initialized = self.is_initialized
357
83
 
358
84
  self.app.include_router(todo_router.router)
359
85
  self.app.include_router(settings_router.router)
@@ -382,8 +108,21 @@ class ProxyServer:
382
108
  if os.path.exists(self.index_html_path):
383
109
  async with aiofiles.open(self.index_html_path, "r") as f:
384
110
  content = await f.read()
111
+
112
+ # If project is not initialized, inject a warning banner
113
+ if not self.is_initialized:
114
+ init_warning = f"""
115
+ <div style="background-color: #fff3cd; color: #856404; padding: 15px; margin: 15px; border-radius: 5px; text-align: center; font-weight: bold;">
116
+ <p>⚠️ {get_message("project_not_initialized")}</p>
117
+ <p>{get_message("run_auto_coder_chat")}</p>
118
+ </div>
119
+ """
120
+ # Insert the warning after the body tag
121
+ content = content.replace("<body>", "<body>" + init_warning)
122
+
385
123
  return HTMLResponse(content=content)
386
124
  return HTMLResponse(content="<h1>Welcome to Proxy Server</h1>")
125
+
387
126
 
388
127
  @self.app.get("/api/project-path")
389
128
  async def get_project_path():
@@ -481,7 +220,26 @@ class ProxyServer:
481
220
  success=False,
482
221
  message=f"读取文件出错: {str(e)}"
483
222
  )
223
+
224
+ @self.app.get("/api/initialization-status")
225
+ async def get_initialization_status():
226
+ """Get the project initialization status"""
227
+ return {
228
+ "initialized": self.is_initialized,
229
+ "message": None if self.is_initialized else get_message("run_auto_coder_chat")
230
+ }
231
+
232
+ def check_project_initialization(self) -> bool:
233
+ """Check if the project has been initialized with auto-coder.chat"""
234
+ auto_coder_dir = os.path.join(self.project_path, ".auto-coder")
235
+ actions_dir = os.path.join(self.project_path, "actions")
236
+ return os.path.exists(auto_coder_dir) and os.path.exists(actions_dir)
484
237
 
238
+ def check_project_conf(self):
239
+ conf = self.auto_coder_runner.get_conf_wrapper()
240
+ if conf.get("human_as_model","false") in ["true","True","TRUE"]:
241
+ logger.warning(get_message("human_as_model_warning"))
242
+ self.auto_coder_runner.configure_wrapper("human_as_model=false")
485
243
 
486
244
 
487
245
  def main():
@@ -15,6 +15,7 @@ from autocoder.events.event_types import EventType
15
15
  from byzerllm.utils.langutil import asyncfy_with_semaphore
16
16
  from autocoder.common.global_cancel import global_cancel, CancelRequestedException
17
17
  from loguru import logger
18
+ import byzerllm
18
19
 
19
20
  router = APIRouter()
20
21
 
@@ -54,6 +55,25 @@ def ensure_task_dir(project_path: str) -> str:
54
55
  os.makedirs(task_dir, exist_ok=True)
55
56
  return task_dir
56
57
 
58
+ @byzerllm.prompt()
59
+ def coding_prompt(messages: List[Dict[str, Any]], request: CodingCommandRequest):
60
+ '''
61
+ 下面是我们已经产生的一个消息列表,其中 USER_RESPONSE 表示用户的输入,RESULT 你的输出:
62
+ <messages>
63
+ {% for message in messages %}
64
+ <message>
65
+ <type>{{ message.type }}</type>
66
+ <content>{{ message.content }}</content>
67
+ </message>
68
+ {% endfor %}
69
+ </messages>
70
+
71
+ 下面是用户的最新需求:
72
+ <request>
73
+ {{ request.command }}
74
+ </request>
75
+ '''
76
+
57
77
  @router.post("/api/coding-command")
58
78
  async def coding_command(request: CodingCommandRequest, project_path: str = Depends(get_project_path)):
59
79
  """
@@ -70,8 +90,54 @@ async def coding_command(request: CodingCommandRequest, project_path: str = Depe
70
90
  wrapper = AutoCoderRunnerWrapper(project_path)
71
91
  wrapper.configure_wrapper(f"event_file:{event_file}")
72
92
 
73
- # 调用coding方法
74
- result = wrapper.coding_wapper(request.command)
93
+ # 获取当前会话名称
94
+ current_session_file = os.path.join(project_path, ".auto-coder", "auto-coder.web", "current-session.json")
95
+ current_session_name = ""
96
+ if os.path.exists(current_session_file):
97
+ try:
98
+ with open(current_session_file, 'r') as f:
99
+ session_data = json.load(f)
100
+ current_session_name = session_data.get("session_name", "")
101
+ except Exception as e:
102
+ logger.error(f"Error reading current session: {str(e)}")
103
+
104
+ # 获取历史消息
105
+ messages = []
106
+ if current_session_name:
107
+ chat_list_file = os.path.join(project_path, ".auto-coder", "auto-coder.web", "chat-lists", f"{current_session_name}.json")
108
+ if os.path.exists(chat_list_file):
109
+ try:
110
+ with open(chat_list_file, 'r', encoding="utf-8") as f:
111
+ chat_data = json.load(f)
112
+ # 从聊天历史中提取消息
113
+ for msg in chat_data.get("messages", []):
114
+ # 只保留用户和中间结果信息
115
+ if msg.get("type","") not in ["USER_RESPONSE","RESULT"]:
116
+ continue
117
+
118
+ if msg.get("contentType","") in ["token_stat"]:
119
+ continue
120
+
121
+ messages.append(msg)
122
+ except Exception as e:
123
+ logger.error(f"Error reading chat history: {str(e)}")
124
+
125
+ # 构建提示信息
126
+ prompt_text = ""
127
+ if messages:
128
+ # 调用coding_prompt生成包含历史消息的提示
129
+ prompt_text = coding_prompt.prompt(messages, request)
130
+ logger.info(prompt_text)
131
+
132
+ # 调用coding方法,如果有历史消息,传递包含历史的提示
133
+ if prompt_text:
134
+ logger.info(f"Using conversation history with {len(messages)} messages for coding command")
135
+ result = wrapper.coding_wapper(prompt_text)
136
+ else:
137
+ # 如果没有历史消息或获取失败,直接传递原始命令
138
+ logger.info("Using original command without conversation history")
139
+ result = wrapper.coding_wapper(request.command)
140
+
75
141
  get_event_manager(event_file).write_completion(
76
142
  EventContentCreator.create_completion(
77
143
  "200", "completed", result).to_dict()
auto_coder_web/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.26"
1
+ __version__ = "0.1.29"
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "files": {
3
- "main.css": "/static/css/main.b9764291.css",
4
- "main.js": "/static/js/main.a707a18c.js",
3
+ "main.css": "/static/css/main.8a602674.css",
4
+ "main.js": "/static/js/main.0ade47f8.js",
5
5
  "static/js/453.d855a71b.chunk.js": "/static/js/453.d855a71b.chunk.js",
6
6
  "index.html": "/index.html",
7
- "main.b9764291.css.map": "/static/css/main.b9764291.css.map",
8
- "main.a707a18c.js.map": "/static/js/main.a707a18c.js.map",
7
+ "main.8a602674.css.map": "/static/css/main.8a602674.css.map",
8
+ "main.0ade47f8.js.map": "/static/js/main.0ade47f8.js.map",
9
9
  "453.d855a71b.chunk.js.map": "/static/js/453.d855a71b.chunk.js.map"
10
10
  },
11
11
  "entrypoints": [
12
- "static/css/main.b9764291.css",
13
- "static/js/main.a707a18c.js"
12
+ "static/css/main.8a602674.css",
13
+ "static/js/main.0ade47f8.js"
14
14
  ]
15
15
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.a707a18c.js"></script><link href="/static/css/main.b9764291.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.0ade47f8.js"></script><link href="/static/css/main.8a602674.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>