auto-coder-web 0.1.14__py3-none-any.whl → 0.1.16__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/auto_coder_runner.py +54 -3
- auto_coder_web/proxy.py +190 -74
- auto_coder_web/routers/__init__.py +0 -0
- auto_coder_web/routers/settings_router.py +76 -0
- auto_coder_web/routers/todo_router.py +156 -0
- auto_coder_web/types.py +72 -0
- auto_coder_web/version.py +1 -1
- auto_coder_web/web/asset-manifest.json +6 -6
- auto_coder_web/web/index.html +1 -1
- auto_coder_web/web/monaco-editor/min/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- auto_coder_web/web/monaco-editor/min/vs/base/worker/workerMain.js +31 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/abap/abap.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/apex/apex.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/azcli/azcli.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/bat/bat.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/bicep/bicep.js +11 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/cameligo/cameligo.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/clojure/clojure.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/coffee/coffee.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/cpp/cpp.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/csharp/csharp.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/csp/csp.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/css/css.js +12 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/cypher/cypher.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/dart/dart.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/dockerfile/dockerfile.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/ecl/ecl.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/elixir/elixir.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/flow9/flow9.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/freemarker2/freemarker2.js +12 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/fsharp/fsharp.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/go/go.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/graphql/graphql.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/handlebars/handlebars.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/hcl/hcl.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/html/html.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/ini/ini.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/java/java.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/javascript/javascript.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/julia/julia.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/kotlin/kotlin.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/less/less.js +11 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/lexon/lexon.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/liquid/liquid.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/lua/lua.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/m3/m3.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/markdown/markdown.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/mdx/mdx.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/mips/mips.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/msdax/msdax.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/mysql/mysql.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/objective-c/objective-c.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/pascal/pascal.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/pascaligo/pascaligo.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/perl/perl.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/pgsql/pgsql.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/php/php.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/pla/pla.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/postiats/postiats.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/powerquery/powerquery.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/powershell/powershell.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/protobuf/protobuf.js +11 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/pug/pug.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/python/python.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/qsharp/qsharp.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/r/r.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/razor/razor.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/redis/redis.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/redshift/redshift.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/ruby/ruby.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/rust/rust.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/sb/sb.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/scala/scala.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/scheme/scheme.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/scss/scss.js +12 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/shell/shell.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/solidity/solidity.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/sophia/sophia.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/sparql/sparql.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/sql/sql.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/st/st.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/swift/swift.js +13 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/systemverilog/systemverilog.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/tcl/tcl.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/twig/twig.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/typescript/typescript.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/typespec/typespec.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/vb/vb.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/wgsl/wgsl.js +307 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/xml/xml.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/basic-languages/yaml/yaml.js +10 -0
- auto_coder_web/web/monaco-editor/min/vs/editor/editor.main.css +8 -0
- auto_coder_web/web/monaco-editor/min/vs/editor/editor.main.js +798 -0
- auto_coder_web/web/monaco-editor/min/vs/language/css/cssMode.js +13 -0
- auto_coder_web/web/monaco-editor/min/vs/language/css/cssWorker.js +77 -0
- auto_coder_web/web/monaco-editor/min/vs/language/html/htmlMode.js +13 -0
- auto_coder_web/web/monaco-editor/min/vs/language/html/htmlWorker.js +454 -0
- auto_coder_web/web/monaco-editor/min/vs/language/json/jsonMode.js +19 -0
- auto_coder_web/web/monaco-editor/min/vs/language/json/jsonWorker.js +42 -0
- auto_coder_web/web/monaco-editor/min/vs/language/typescript/tsMode.js +20 -0
- auto_coder_web/web/monaco-editor/min/vs/language/typescript/tsWorker.js +51328 -0
- auto_coder_web/web/monaco-editor/min/vs/loader.js +11 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.de.js +21 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.es.js +21 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.fr.js +19 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.it.js +19 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.ja.js +21 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.ko.js +19 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.ru.js +21 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.zh-cn.js +21 -0
- auto_coder_web/web/monaco-editor/min/vs/nls.messages.zh-tw.js +19 -0
- auto_coder_web/web/static/css/main.3cb5c1ac.css +6 -0
- auto_coder_web/web/static/css/main.3cb5c1ac.css.map +1 -0
- auto_coder_web/web/static/js/main.8cc287dc.js +3 -0
- auto_coder_web/web/static/js/main.8cc287dc.js.LICENSE.txt +164 -0
- auto_coder_web/web/static/js/main.8cc287dc.js.map +1 -0
- {auto_coder_web-0.1.14.dist-info → auto_coder_web-0.1.16.dist-info}/METADATA +2 -1
- auto_coder_web-0.1.16.dist-info/RECORD +199 -0
- auto_coder_web-0.1.14.dist-info/RECORD +0 -87
- {auto_coder_web-0.1.14.dist-info → auto_coder_web-0.1.16.dist-info}/WHEEL +0 -0
- {auto_coder_web-0.1.14.dist-info → auto_coder_web-0.1.16.dist-info}/entry_points.txt +0 -0
- {auto_coder_web-0.1.14.dist-info → auto_coder_web-0.1.16.dist-info}/top_level.txt +0 -0
@@ -39,6 +39,7 @@ from autocoder.index.symbols_utils import (
|
|
39
39
|
SymbolsInfo,
|
40
40
|
SymbolType,
|
41
41
|
)
|
42
|
+
from autocoder.utils.llms import get_single_llm
|
42
43
|
|
43
44
|
|
44
45
|
class SymbolItem(BaseModel):
|
@@ -48,7 +49,7 @@ class SymbolItem(BaseModel):
|
|
48
49
|
|
49
50
|
|
50
51
|
class AutoCoderRunner:
|
51
|
-
def __init__(self, project_path: str):
|
52
|
+
def __init__(self, project_path: str, product_mode: str = "pro"):
|
52
53
|
self.project_path = project_path
|
53
54
|
self.base_persist_dir = os.path.join(
|
54
55
|
project_path, ".auto-coder", "plugins", "chat-auto-coder")
|
@@ -61,6 +62,8 @@ class AutoCoderRunner:
|
|
61
62
|
"exclude_dirs": [],
|
62
63
|
}
|
63
64
|
self.load_memory()
|
65
|
+
# Configure product mode
|
66
|
+
self.configure("product_mode", product_mode)
|
64
67
|
|
65
68
|
@contextmanager
|
66
69
|
def redirect_stdout(self):
|
@@ -319,7 +322,7 @@ class AutoCoderRunner:
|
|
319
322
|
|
320
323
|
def convert_yaml_to_config(self, yaml_file: str):
|
321
324
|
"""Convert YAML file to AutoCoderArgs configuration"""
|
322
|
-
from autocoder.
|
325
|
+
from autocoder.commmon import AutoCoderArgs, load_include_files, Template
|
323
326
|
args = AutoCoderArgs()
|
324
327
|
with open(yaml_file, "r") as f:
|
325
328
|
config = yaml.safe_load(f)
|
@@ -366,7 +369,9 @@ class AutoCoderRunner:
|
|
366
369
|
return_paths=True
|
367
370
|
)
|
368
371
|
args = self.convert_yaml_to_config(execute_file)
|
369
|
-
|
372
|
+
product_mode = conf.get("product_mode", "pro")
|
373
|
+
target_model = args.code_model or args.model
|
374
|
+
llm = get_single_llm(target_model, product_mode)
|
370
375
|
uncommitted_changes = git_utils.get_uncommitted_changes(".")
|
371
376
|
commit_message = git_utils.generate_commit_message.with_llm(
|
372
377
|
llm).run(uncommitted_changes)
|
@@ -828,3 +833,49 @@ query: |
|
|
828
833
|
"status": False,
|
829
834
|
"message": "No previous chat action found."
|
830
835
|
}
|
836
|
+
|
837
|
+
async def auto_command(self, query: str):
|
838
|
+
"""处理/auto指令"""
|
839
|
+
from autocoder.commands.auto_command import CommandAutoTuner, AutoCommandRequest, CommandConfig
|
840
|
+
args = self.get_final_config()
|
841
|
+
|
842
|
+
# 准备请求参数
|
843
|
+
request = AutoCommandRequest(
|
844
|
+
user_input=query
|
845
|
+
)
|
846
|
+
|
847
|
+
# 初始化调优器
|
848
|
+
llm = get_single_llm(args.chat_model or args.model, product_mode=args.product_mode)
|
849
|
+
tuner = CommandAutoTuner(llm,
|
850
|
+
args=args,
|
851
|
+
memory_config=MemoryConfig(memory=self.memory, save_memory_func=self.save_memory),
|
852
|
+
command_config=CommandConfig(
|
853
|
+
add_files=self.add_files,
|
854
|
+
remove_files=self.remove_files,
|
855
|
+
list_files=self.list_files,
|
856
|
+
conf=self.configure,
|
857
|
+
revert=self.revert,
|
858
|
+
commit=self.commit,
|
859
|
+
help=self.help,
|
860
|
+
exclude_dirs=self.exclude_dirs,
|
861
|
+
ask=self.ask,
|
862
|
+
chat=self.chat,
|
863
|
+
coding=self.coding,
|
864
|
+
design=self.design,
|
865
|
+
summon=self.summon,
|
866
|
+
lib=self.lib_command,
|
867
|
+
mcp=self.mcp,
|
868
|
+
models=self.manage_models,
|
869
|
+
index_build=self.index_build,
|
870
|
+
index_query=self.index_query,
|
871
|
+
execute_shell_command=self.execute_shell,
|
872
|
+
generate_shell_command=self.generate_shell_command
|
873
|
+
))
|
874
|
+
|
875
|
+
# 生成建议
|
876
|
+
response = await tuner.analyze(request)
|
877
|
+
|
878
|
+
return {
|
879
|
+
"suggestions": [s.dict() for s in response.suggestions],
|
880
|
+
"reasoning": response.reasoning
|
881
|
+
}
|
auto_coder_web/proxy.py
CHANGED
@@ -6,7 +6,6 @@ from fastapi.staticfiles import StaticFiles
|
|
6
6
|
import uvicorn
|
7
7
|
import httpx
|
8
8
|
import uuid
|
9
|
-
from typing import Optional, Dict, List, Any
|
10
9
|
import os
|
11
10
|
import argparse
|
12
11
|
import aiofiles
|
@@ -18,6 +17,21 @@ import sys
|
|
18
17
|
from .file_group import FileGroupManager
|
19
18
|
from .file_manager import get_directory_tree
|
20
19
|
from .auto_coder_runner import AutoCoderRunner
|
20
|
+
from autocoder.agent.auto_filegroup import AutoFileGroup
|
21
|
+
from .types import (
|
22
|
+
EventGetRequest,
|
23
|
+
EventResponseRequest,
|
24
|
+
CompletionItem,
|
25
|
+
CompletionResponse,
|
26
|
+
ChatList,
|
27
|
+
HistoryQuery,
|
28
|
+
ValidationResponse,
|
29
|
+
QueryWithFileNumber,
|
30
|
+
ValidationResponseWithFileNumbers,
|
31
|
+
FileContentResponse,
|
32
|
+
FileChange,
|
33
|
+
CommitDiffResponse,
|
34
|
+
)
|
21
35
|
|
22
36
|
from rich.console import Console
|
23
37
|
from prompt_toolkit.shortcuts import radiolist_dialog
|
@@ -26,7 +40,6 @@ import subprocess
|
|
26
40
|
from prompt_toolkit import prompt
|
27
41
|
from pydantic import BaseModel
|
28
42
|
from autocoder.utils.log_capture import LogCapture
|
29
|
-
from typing import Optional, Dict, List, Any
|
30
43
|
from .terminal import terminal_manager
|
31
44
|
from autocoder.common import AutoCoderArgs
|
32
45
|
import json
|
@@ -35,69 +48,11 @@ import yaml
|
|
35
48
|
import git
|
36
49
|
import hashlib
|
37
50
|
from datetime import datetime
|
51
|
+
from autocoder.utils import operate_config_api
|
52
|
+
from .routers import todo_router
|
53
|
+
from .routers import settings_router
|
38
54
|
|
39
55
|
|
40
|
-
class EventGetRequest(BaseModel):
|
41
|
-
request_id: str
|
42
|
-
|
43
|
-
|
44
|
-
class EventResponseRequest(BaseModel):
|
45
|
-
request_id: str
|
46
|
-
event: Dict[str, str]
|
47
|
-
response: str
|
48
|
-
|
49
|
-
|
50
|
-
class CompletionItem(BaseModel):
|
51
|
-
name: str
|
52
|
-
path: str
|
53
|
-
display: str
|
54
|
-
location: Optional[str] = None
|
55
|
-
|
56
|
-
|
57
|
-
class CompletionResponse(BaseModel):
|
58
|
-
completions: List[CompletionItem]
|
59
|
-
|
60
|
-
|
61
|
-
class ChatList(BaseModel):
|
62
|
-
name: str
|
63
|
-
messages: List[Dict[str, Any]]
|
64
|
-
|
65
|
-
class HistoryQuery(BaseModel):
|
66
|
-
query: str
|
67
|
-
timestamp: Optional[str] = None
|
68
|
-
|
69
|
-
class ValidationResponse(BaseModel):
|
70
|
-
success: bool
|
71
|
-
message: str = ""
|
72
|
-
queries: List[HistoryQuery] = []
|
73
|
-
|
74
|
-
class QueryWithFileNumber(BaseModel):
|
75
|
-
query: str
|
76
|
-
timestamp: Optional[str] = None
|
77
|
-
file_number: int
|
78
|
-
response: Optional[str] = None
|
79
|
-
urls: Optional[List[str]] = None
|
80
|
-
|
81
|
-
class ValidationResponseWithFileNumbers(BaseModel):
|
82
|
-
success: bool
|
83
|
-
message: str = ""
|
84
|
-
queries: List[QueryWithFileNumber] = []
|
85
|
-
|
86
|
-
class FileContentResponse(BaseModel):
|
87
|
-
success: bool
|
88
|
-
message: str = ""
|
89
|
-
content: Optional[str] = None
|
90
|
-
|
91
|
-
class FileChange(BaseModel):
|
92
|
-
path: str
|
93
|
-
change_type: str # "added" 或 "modified"
|
94
|
-
|
95
|
-
class CommitDiffResponse(BaseModel):
|
96
|
-
success: bool
|
97
|
-
message: str = ""
|
98
|
-
diff: Optional[str] = None
|
99
|
-
file_changes: Optional[List[FileChange]] = None
|
100
|
-
|
101
56
|
def check_environment():
|
102
57
|
"""Check and initialize the required environment"""
|
103
58
|
console = Console()
|
@@ -114,10 +69,8 @@ def check_environment():
|
|
114
69
|
console.print(f"✗ {message}", style="red")
|
115
70
|
else:
|
116
71
|
console.print(f" {message}")
|
117
|
-
|
118
|
-
|
119
|
-
if not os.path.exists("actions") or not os.path.exists(".auto-coder"):
|
120
|
-
first_time = True
|
72
|
+
|
73
|
+
if not os.path.exists("actions") or not os.path.exists(".auto-coder"):
|
121
74
|
print_status("Project not initialized", "warning")
|
122
75
|
init_choice = input(
|
123
76
|
" Do you want to initialize the project? (y/n): ").strip().lower()
|
@@ -271,23 +224,113 @@ def check_environment():
|
|
271
224
|
return True
|
272
225
|
|
273
226
|
|
227
|
+
def check_environment_lite():
|
228
|
+
"""Check and initialize the required environment for lite mode"""
|
229
|
+
console = Console()
|
230
|
+
console.print("\n[blue]Initializing the environment (Lite Mode)...[/blue]")
|
231
|
+
|
232
|
+
def check_project():
|
233
|
+
"""Check if the current directory is initialized as an auto-coder project"""
|
234
|
+
def print_status(message, status):
|
235
|
+
if status == "success":
|
236
|
+
console.print(f"✓ {message}", style="green")
|
237
|
+
elif status == "warning":
|
238
|
+
console.print(f"! {message}", style="yellow")
|
239
|
+
elif status == "error":
|
240
|
+
console.print(f"✗ {message}", style="red")
|
241
|
+
else:
|
242
|
+
console.print(f" {message}")
|
243
|
+
|
244
|
+
first_time = False
|
245
|
+
if not os.path.exists("actions") or not os.path.exists(".auto-coder"):
|
246
|
+
first_time = True
|
247
|
+
print_status("Project not initialized", "warning")
|
248
|
+
init_choice = input(
|
249
|
+
" Do you want to initialize the project? (y/n): ").strip().lower()
|
250
|
+
if init_choice == "y":
|
251
|
+
try:
|
252
|
+
if not os.path.exists("actions"):
|
253
|
+
os.makedirs("actions", exist_ok=True)
|
254
|
+
print_status("Created actions directory", "success")
|
255
|
+
|
256
|
+
if not os.path.exists(".auto-coder"):
|
257
|
+
os.makedirs(".auto-coder", exist_ok=True)
|
258
|
+
print_status(
|
259
|
+
"Created .auto-coder directory", "success")
|
260
|
+
|
261
|
+
subprocess.run(
|
262
|
+
["auto-coder", "init", "--source_dir", "."], check=True)
|
263
|
+
print_status("Project initialized successfully", "success")
|
264
|
+
except subprocess.CalledProcessError:
|
265
|
+
print_status("Failed to initialize project", "error")
|
266
|
+
print_status(
|
267
|
+
"Please try to initialize manually: auto-coder init --source_dir .", "warning")
|
268
|
+
return False
|
269
|
+
else:
|
270
|
+
print_status("Exiting due to no initialization", "warning")
|
271
|
+
return False
|
272
|
+
|
273
|
+
print_status("Project initialization check complete", "success")
|
274
|
+
return True
|
275
|
+
|
276
|
+
if not check_project():
|
277
|
+
return False
|
278
|
+
|
279
|
+
def print_status(message, status):
|
280
|
+
if status == "success":
|
281
|
+
console.print(f"✓ {message}", style="green")
|
282
|
+
elif status == "warning":
|
283
|
+
console.print(f"! {message}", style="yellow")
|
284
|
+
elif status == "error":
|
285
|
+
console.print(f"✗ {message}", style="red")
|
286
|
+
else:
|
287
|
+
console.print(f" {message}")
|
288
|
+
|
289
|
+
# Setup deepseek api key
|
290
|
+
api_key_dir = os.path.expanduser("~/.auto-coder/keys")
|
291
|
+
api_key_file = os.path.join(api_key_dir, "api.deepseek.com")
|
292
|
+
|
293
|
+
if not os.path.exists(api_key_file):
|
294
|
+
print_status("API key not found", "warning")
|
295
|
+
api_key = prompt(HTML("<b>Please enter your API key: </b>"))
|
296
|
+
|
297
|
+
# Create directory if it doesn't exist
|
298
|
+
os.makedirs(api_key_dir, exist_ok=True)
|
299
|
+
|
300
|
+
# Save the API key
|
301
|
+
with open(api_key_file, "w") as f:
|
302
|
+
f.write(api_key)
|
303
|
+
|
304
|
+
print_status(f"API key saved successfully: {api_key_file}", "success")
|
305
|
+
|
306
|
+
print_status("Environment initialization complete", "success")
|
307
|
+
return True
|
308
|
+
|
309
|
+
|
274
310
|
class ProxyServer:
|
275
|
-
def __init__(self, project_path: str, quick: bool = False):
|
311
|
+
def __init__(self, project_path: str, quick: bool = False, product_mode: str = "pro"):
|
276
312
|
self.app = FastAPI()
|
277
313
|
|
278
314
|
if not quick:
|
279
|
-
# Check the environment
|
280
|
-
if
|
281
|
-
|
282
|
-
|
315
|
+
# Check the environment based on product mode
|
316
|
+
if product_mode == "lite":
|
317
|
+
if not check_environment_lite():
|
318
|
+
print(
|
319
|
+
"\033[31mEnvironment check failed. Some features may not work properly.\033[0m")
|
320
|
+
else:
|
321
|
+
if not check_environment():
|
322
|
+
print(
|
323
|
+
"\033[31mEnvironment check failed. Some features may not work properly.\033[0m")
|
324
|
+
|
283
325
|
self.setup_middleware()
|
284
326
|
|
285
327
|
self.setup_static_files()
|
286
328
|
|
287
329
|
self.setup_routes()
|
330
|
+
|
288
331
|
self.client = httpx.AsyncClient()
|
289
332
|
self.project_path = project_path
|
290
|
-
self.auto_coder_runner = AutoCoderRunner(project_path)
|
333
|
+
self.auto_coder_runner = AutoCoderRunner(project_path, product_mode=product_mode)
|
291
334
|
self.file_group_manager = FileGroupManager(self.auto_coder_runner)
|
292
335
|
|
293
336
|
def setup_middleware(self):
|
@@ -308,6 +351,10 @@ class ProxyServer:
|
|
308
351
|
"/static", StaticFiles(directory=self.static_dir), name="static")
|
309
352
|
|
310
353
|
def setup_routes(self):
|
354
|
+
|
355
|
+
self.app.include_router(todo_router.router)
|
356
|
+
self.app.include_router(settings_router.router)
|
357
|
+
|
311
358
|
@self.app.on_event("shutdown")
|
312
359
|
async def shutdown_event():
|
313
360
|
await self.client.aclose()
|
@@ -357,6 +404,42 @@ class ProxyServer:
|
|
357
404
|
group = await self.file_group_manager.create_group(name, description)
|
358
405
|
return group
|
359
406
|
|
407
|
+
@self.app.post("/api/file-groups/auto")
|
408
|
+
async def auto_create_groups(request: Request):
|
409
|
+
try:
|
410
|
+
data = await request.json()
|
411
|
+
file_size_limit = data.get("file_size_limit", 100)
|
412
|
+
skip_diff = data.get("skip_diff", False)
|
413
|
+
group_num_limit = data.get("group_num_limit", 10)
|
414
|
+
|
415
|
+
# Create AutoFileGroup instance
|
416
|
+
auto_grouper = AutoFileGroup(
|
417
|
+
operate_config_api.get_llm(self.auto_coder_runner.memory),
|
418
|
+
self.project_path,
|
419
|
+
skip_diff=skip_diff,
|
420
|
+
file_size_limit=file_size_limit,
|
421
|
+
group_num_limit=group_num_limit
|
422
|
+
)
|
423
|
+
|
424
|
+
# Get groups
|
425
|
+
groups = auto_grouper.group_files()
|
426
|
+
|
427
|
+
# Create groups using file_group_manager
|
428
|
+
for group in groups:
|
429
|
+
await self.file_group_manager.create_group(
|
430
|
+
name=group.name,
|
431
|
+
description=group.description
|
432
|
+
)
|
433
|
+
# Add files to the group
|
434
|
+
await self.file_group_manager.add_files_to_group(
|
435
|
+
group.name,
|
436
|
+
group.urls
|
437
|
+
)
|
438
|
+
|
439
|
+
return {"status": "success", "message": f"Created {len(groups)} groups"}
|
440
|
+
except Exception as e:
|
441
|
+
raise HTTPException(status_code=500, detail=str(e))
|
442
|
+
|
360
443
|
@self.app.get("/api/os")
|
361
444
|
async def get_os():
|
362
445
|
return {"os": os.name}
|
@@ -843,6 +926,17 @@ class ProxyServer:
|
|
843
926
|
|
844
927
|
|
845
928
|
def main():
|
929
|
+
from autocoder.rag.variable_holder import VariableHolder
|
930
|
+
from tokenizers import Tokenizer
|
931
|
+
try:
|
932
|
+
tokenizer_path = pkg_resources.resource_filename(
|
933
|
+
"autocoder", "data/tokenizer.json"
|
934
|
+
)
|
935
|
+
VariableHolder.TOKENIZER_PATH = tokenizer_path
|
936
|
+
VariableHolder.TOKENIZER_MODEL = Tokenizer.from_file(tokenizer_path)
|
937
|
+
except FileNotFoundError:
|
938
|
+
tokenizer_path = None
|
939
|
+
|
846
940
|
parser = argparse.ArgumentParser(description="Proxy Server")
|
847
941
|
parser.add_argument(
|
848
942
|
"--port",
|
@@ -861,9 +955,31 @@ def main():
|
|
861
955
|
action="store_true",
|
862
956
|
help="Skip environment check",
|
863
957
|
)
|
958
|
+
parser.add_argument(
|
959
|
+
"--product_mode",
|
960
|
+
type=str,
|
961
|
+
default="pro",
|
962
|
+
help="The mode of the auto-coder.chat, lite/pro default is pro",
|
963
|
+
)
|
964
|
+
parser.add_argument(
|
965
|
+
"--lite",
|
966
|
+
action="store_true",
|
967
|
+
help="Run in lite mode (equivalent to --product_mode lite)",
|
968
|
+
)
|
969
|
+
parser.add_argument(
|
970
|
+
"--pro",
|
971
|
+
action="store_true",
|
972
|
+
help="Run in pro mode (equivalent to --product_mode pro)",
|
973
|
+
)
|
864
974
|
args = parser.parse_args()
|
865
975
|
|
866
|
-
|
976
|
+
# Handle lite/pro flags
|
977
|
+
if args.lite:
|
978
|
+
args.product_mode = "lite"
|
979
|
+
elif args.pro:
|
980
|
+
args.product_mode = "pro"
|
981
|
+
|
982
|
+
proxy_server = ProxyServer(quick=args.quick, project_path=os.getcwd(), product_mode=args.product_mode)
|
867
983
|
uvicorn.run(proxy_server.app, host=args.host, port=args.port)
|
868
984
|
|
869
985
|
|
File without changes
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
import os
|
3
|
+
import json
|
4
|
+
import logging
|
5
|
+
import aiofiles
|
6
|
+
from fastapi import APIRouter, HTTPException
|
7
|
+
from pydantic import BaseModel
|
8
|
+
from typing import Optional
|
9
|
+
from pathlib import Path
|
10
|
+
import asyncio
|
11
|
+
|
12
|
+
router = APIRouter()
|
13
|
+
|
14
|
+
# 配置存储路径
|
15
|
+
SETTINGS_FILE = Path(".auto-coder/auto-coder.web/settings/settings.json")
|
16
|
+
|
17
|
+
# 确保目录存在
|
18
|
+
SETTINGS_FILE.parent.mkdir(parents=True, exist_ok=True)
|
19
|
+
|
20
|
+
logger = logging.getLogger(__name__)
|
21
|
+
|
22
|
+
class SettingsModel(BaseModel):
|
23
|
+
language: str = "zh"
|
24
|
+
theme: str = "dark"
|
25
|
+
font_size: int = 14
|
26
|
+
auto_save: bool = True
|
27
|
+
show_line_numbers: bool = True
|
28
|
+
|
29
|
+
async def load_settings() -> SettingsModel:
|
30
|
+
"""异步加载设置"""
|
31
|
+
if not await asyncio.to_thread(lambda: SETTINGS_FILE.exists()):
|
32
|
+
# 如果文件不存在,返回默认设置
|
33
|
+
return SettingsModel()
|
34
|
+
|
35
|
+
try:
|
36
|
+
async with aiofiles.open(SETTINGS_FILE, mode='r') as f:
|
37
|
+
content = await f.read()
|
38
|
+
return SettingsModel(**json.loads(content))
|
39
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
40
|
+
logger.error("Failed to parse settings.json, returning default settings")
|
41
|
+
return SettingsModel()
|
42
|
+
|
43
|
+
async def save_settings(settings: SettingsModel):
|
44
|
+
"""异步保存设置"""
|
45
|
+
async with aiofiles.open(SETTINGS_FILE, mode='w') as f:
|
46
|
+
await f.write(settings.json(indent=2, ensure_ascii=False))
|
47
|
+
|
48
|
+
@router.get("/api/settings")
|
49
|
+
async def get_settings():
|
50
|
+
"""获取当前设置"""
|
51
|
+
return await load_settings()
|
52
|
+
|
53
|
+
@router.post("/api/settings")
|
54
|
+
async def update_settings(settings: dict):
|
55
|
+
"""更新设置"""
|
56
|
+
current_settings = await load_settings()
|
57
|
+
updated_settings = current_settings.copy(update=settings)
|
58
|
+
await save_settings(updated_settings)
|
59
|
+
return updated_settings
|
60
|
+
|
61
|
+
@router.post("/api/settings/language")
|
62
|
+
async def set_language(language: str):
|
63
|
+
"""设置语言"""
|
64
|
+
if language not in ["zh", "en"]:
|
65
|
+
raise HTTPException(status_code=400, detail="Invalid language, must be 'zh' or 'en'")
|
66
|
+
|
67
|
+
current_settings = await load_settings()
|
68
|
+
current_settings.language = language
|
69
|
+
await save_settings(current_settings)
|
70
|
+
return {"status": "success", "language": language}
|
71
|
+
|
72
|
+
@router.get("/api/settings/language")
|
73
|
+
async def get_language():
|
74
|
+
"""获取当前语言设置"""
|
75
|
+
settings = await load_settings()
|
76
|
+
return {"language": settings.language}
|
@@ -0,0 +1,156 @@
|
|
1
|
+
import os
|
2
|
+
import json
|
3
|
+
import uuid
|
4
|
+
import logging
|
5
|
+
import asyncio
|
6
|
+
import aiofiles
|
7
|
+
from fastapi import APIRouter, HTTPException
|
8
|
+
from pydantic import BaseModel
|
9
|
+
from typing import List, Optional
|
10
|
+
from datetime import datetime
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
router = APIRouter()
|
14
|
+
|
15
|
+
# 配置存储路径
|
16
|
+
TODO_FILE = Path(".auto-coder/auto-coder.web/todos/todos.json")
|
17
|
+
|
18
|
+
# 确保目录存在
|
19
|
+
TODO_FILE.parent.mkdir(parents=True, exist_ok=True)
|
20
|
+
|
21
|
+
logger = logging.getLogger(__name__)
|
22
|
+
|
23
|
+
class TodoItem(BaseModel):
|
24
|
+
id: str
|
25
|
+
title: str
|
26
|
+
status: str # pending/developing/testing/done
|
27
|
+
priority: str # P0/P1/P2/P3
|
28
|
+
tags: List[str] = []
|
29
|
+
owner: Optional[str] = None
|
30
|
+
due_date: Optional[str] = None
|
31
|
+
created_at: str
|
32
|
+
updated_at: str
|
33
|
+
|
34
|
+
class CreateTodoRequest(BaseModel):
|
35
|
+
title: str
|
36
|
+
priority: str
|
37
|
+
tags: List[str] = []
|
38
|
+
|
39
|
+
class ReorderTodoRequest(BaseModel):
|
40
|
+
source_status: str
|
41
|
+
source_index: int
|
42
|
+
destination_status: str
|
43
|
+
destination_index: int
|
44
|
+
todo_id: str
|
45
|
+
|
46
|
+
async def load_todos() -> List[TodoItem]:
|
47
|
+
"""异步加载所有待办事项"""
|
48
|
+
if not await asyncio.to_thread(lambda: TODO_FILE.exists()):
|
49
|
+
return []
|
50
|
+
|
51
|
+
try:
|
52
|
+
async with aiofiles.open(TODO_FILE, mode='r') as f:
|
53
|
+
content = await f.read()
|
54
|
+
return [TodoItem(**item) for item in json.loads(content)]
|
55
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
56
|
+
logger.error("Failed to parse todos.json, returning empty list")
|
57
|
+
return []
|
58
|
+
|
59
|
+
async def save_todos(todos: List[TodoItem]):
|
60
|
+
"""异步保存待办事项"""
|
61
|
+
async with aiofiles.open(TODO_FILE, mode='w') as f:
|
62
|
+
await f.write(json.dumps([todo.dict() for todo in todos], indent=2,ensure_ascii=False))
|
63
|
+
|
64
|
+
@router.get("/api/todos", response_model=List[TodoItem])
|
65
|
+
async def get_all_todos():
|
66
|
+
"""获取所有待办事项"""
|
67
|
+
return await load_todos()
|
68
|
+
|
69
|
+
@router.post("/api/todos", response_model=TodoItem)
|
70
|
+
async def create_todo(request: CreateTodoRequest):
|
71
|
+
"""创建新待办事项"""
|
72
|
+
todos = await load_todos()
|
73
|
+
|
74
|
+
new_todo = TodoItem(
|
75
|
+
id=str(uuid.uuid4()),
|
76
|
+
title=request.title,
|
77
|
+
status="pending",
|
78
|
+
priority=request.priority,
|
79
|
+
tags=request.tags,
|
80
|
+
created_at=datetime.now().isoformat(),
|
81
|
+
updated_at=datetime.now().isoformat()
|
82
|
+
)
|
83
|
+
|
84
|
+
todos.append(new_todo)
|
85
|
+
await save_todos(todos)
|
86
|
+
return new_todo
|
87
|
+
|
88
|
+
@router.put("/api/todos/{todo_id}", response_model=TodoItem)
|
89
|
+
async def update_todo(todo_id: str, update_data: dict):
|
90
|
+
"""更新待办事项"""
|
91
|
+
todos = await load_todos()
|
92
|
+
|
93
|
+
for index, todo in enumerate(todos):
|
94
|
+
if todo.id == todo_id:
|
95
|
+
updated_data = todos[index].dict()
|
96
|
+
updated_data.update(update_data)
|
97
|
+
updated_data["updated_at"] = datetime.now().isoformat()
|
98
|
+
todos[index] = TodoItem(**updated_data)
|
99
|
+
await save_todos(todos)
|
100
|
+
return todos[index]
|
101
|
+
|
102
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
103
|
+
|
104
|
+
@router.delete("/api/todos/{todo_id}")
|
105
|
+
async def delete_todo(todo_id: str):
|
106
|
+
"""删除待办事项"""
|
107
|
+
todos = await load_todos()
|
108
|
+
new_todos = [todo for todo in todos if todo.id != todo_id]
|
109
|
+
|
110
|
+
if len(new_todos) == len(todos):
|
111
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
112
|
+
|
113
|
+
await save_todos(new_todos)
|
114
|
+
return {"status": "success"}
|
115
|
+
|
116
|
+
@router.post("/api/todos/reorder")
|
117
|
+
async def reorder_todos(request: ReorderTodoRequest):
|
118
|
+
"""处理拖放排序"""
|
119
|
+
todos = await load_todos()
|
120
|
+
|
121
|
+
# 找到移动的待办事项
|
122
|
+
moved_todo = next((t for t in todos if t.id == request.todo_id), None)
|
123
|
+
if not moved_todo:
|
124
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
125
|
+
|
126
|
+
# 移除原位置
|
127
|
+
todos = [t for t in todos if t.id != request.todo_id]
|
128
|
+
|
129
|
+
# 更新状态
|
130
|
+
moved_todo.status = request.destination_status
|
131
|
+
moved_todo.updated_at = datetime.now().isoformat()
|
132
|
+
|
133
|
+
# 插入新位置
|
134
|
+
todos.insert(
|
135
|
+
await get_insert_index(todos, request.destination_status, request.destination_index),
|
136
|
+
moved_todo
|
137
|
+
)
|
138
|
+
|
139
|
+
await save_todos(todos)
|
140
|
+
return {"status": "success"}
|
141
|
+
|
142
|
+
async def get_insert_index(todos: List[TodoItem], status: str, destination_index: int) -> int:
|
143
|
+
"""计算插入位置的绝对索引"""
|
144
|
+
status_todos = [i for i, t in enumerate(todos) if t.status == status]
|
145
|
+
if not status_todos:
|
146
|
+
return len(todos)
|
147
|
+
|
148
|
+
# 确保目标索引在有效范围内
|
149
|
+
destination_index = min(max(destination_index, 0), len(status_todos))
|
150
|
+
|
151
|
+
# 如果目标列没有项目,直接插入到最后
|
152
|
+
if not status_todos:
|
153
|
+
return len(todos)
|
154
|
+
|
155
|
+
# 返回目标列中对应位置的索引
|
156
|
+
return status_todos[destination_index] if destination_index < len(status_todos) else status_todos[-1] + 1
|