auto-coder-web 0.1.61__py3-none-any.whl → 0.1.62__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/common_router/auto_coder_conf_router.py +3 -3
- auto_coder_web/common_router/completions_router.py +15 -8
- auto_coder_web/common_router/file_router.py +39 -14
- auto_coder_web/expert_routers/history_router.py +1 -1
- auto_coder_web/file_manager.py +178 -3
- auto_coder_web/proxy.py +2 -1
- auto_coder_web/routers/auto_router.py +1 -1
- auto_coder_web/routers/chat_router.py +2 -2
- auto_coder_web/routers/coding_router.py +3 -3
- auto_coder_web/routers/commit_router.py +1 -1
- auto_coder_web/routers/config_router.py +9 -4
- auto_coder_web/routers/mcp_router.py +287 -62
- auto_coder_web/version.py +1 -1
- auto_coder_web/web/HistoryPanel-WXEMtQ1V.js +1 -0
- auto_coder_web/web/{assets/cssMode-DzQL_FdL.js → cssMode-CQYz0o1d.js} +1 -1
- auto_coder_web/web/{assets/freemarker2-B6aemwaC.js → freemarker2-BJU3cSen.js} +1 -1
- auto_coder_web/web/{assets/handlebars-C2cM4xS8.js → handlebars-VxUdciXQ.js} +1 -1
- auto_coder_web/web/{assets/html-Da2X74rm.js → html-DEgskwXL.js} +1 -1
- auto_coder_web/web/{assets/htmlMode-Y3eBAl3y.js → htmlMode-58cXxJlI.js} +1 -1
- auto_coder_web/web/index.html +2 -2
- auto_coder_web/web/{assets/javascript-zkPPW3gg.js → javascript-DbZlm-ig.js} +1 -1
- auto_coder_web/web/{assets/jsonMode-Ce8jLIxT.js → jsonMode-C2HKgmE0.js} +1 -1
- auto_coder_web/web/{assets/liquid-CHrk1uPD.js → liquid-BFft-XkQ.js} +1 -1
- auto_coder_web/web/main-DxnFm18B.css +32 -0
- auto_coder_web/web/{assets/index-kyBHOjJU.js → main.js} +384 -373
- auto_coder_web/web/{assets/mdx-B7AzIQ1K.js → mdx-DZdDhrJW.js} +1 -1
- auto_coder_web/web/{assets/python-D340AvYz.js → python-DOHUGzLU.js} +1 -1
- auto_coder_web/web/{assets/razor-DfFnL0En.js → razor-Dh5mSHi2.js} +1 -1
- auto_coder_web/web/{assets/tsMode-CwjVYPI2.js → tsMode-tyI6CeIR.js} +1 -1
- auto_coder_web/web/{assets/typescript-JxFW6htN.js → typescript-DZzM_VgT.js} +1 -1
- auto_coder_web/web/{assets/xml-CY673mn0.js → xml-Dl6413Na.js} +1 -1
- auto_coder_web/web/{assets/yaml-D2wmMay7.js → yaml-DML583wh.js} +1 -1
- {auto_coder_web-0.1.61.dist-info → auto_coder_web-0.1.62.dist-info}/METADATA +2 -2
- {auto_coder_web-0.1.61.dist-info → auto_coder_web-0.1.62.dist-info}/RECORD +108 -107
- auto_coder_web/web/assets/index-CRXh98Y9.css +0 -32
- /auto_coder_web/web/{assets/abap-BrgZPUOV.js → abap-BrgZPUOV.js} +0 -0
- /auto_coder_web/web/{assets/apex-DyP6w7ZV.js → apex-DyP6w7ZV.js} +0 -0
- /auto_coder_web/web/{assets/azcli-BaLxmfj-.js → azcli-BaLxmfj-.js} +0 -0
- /auto_coder_web/web/{assets/bat-CFOPXBzS.js → bat-CFOPXBzS.js} +0 -0
- /auto_coder_web/web/{assets/bicep-BfEKNvv3.js → bicep-BfEKNvv3.js} +0 -0
- /auto_coder_web/web/{assets/cameligo-BFG1Mk7z.js → cameligo-BFG1Mk7z.js} +0 -0
- /auto_coder_web/web/{assets/clojure-DTECt2xU.js → clojure-DTECt2xU.js} +0 -0
- /auto_coder_web/web/{assets/codicon-DCmgc-ay.ttf → codicon-DCmgc-ay.ttf} +0 -0
- /auto_coder_web/web/{assets/coffee-CDGzqUPQ.js → coffee-CDGzqUPQ.js} +0 -0
- /auto_coder_web/web/{assets/cpp-CLLBncYj.js → cpp-CLLBncYj.js} +0 -0
- /auto_coder_web/web/{assets/csharp-dUCx_-0o.js → csharp-dUCx_-0o.js} +0 -0
- /auto_coder_web/web/{assets/csp-5Rap-vPy.js → csp-5Rap-vPy.js} +0 -0
- /auto_coder_web/web/{assets/css-D3h14YRZ.js → css-D3h14YRZ.js} +0 -0
- /auto_coder_web/web/{assets/cypher-DrQuvNYM.js → cypher-DrQuvNYM.js} +0 -0
- /auto_coder_web/web/{assets/dart-CFKIUWau.js → dart-CFKIUWau.js} +0 -0
- /auto_coder_web/web/{assets/dockerfile-Zznr-cwX.js → dockerfile-Zznr-cwX.js} +0 -0
- /auto_coder_web/web/{assets/ecl-Ce3n6wWz.js → ecl-Ce3n6wWz.js} +0 -0
- /auto_coder_web/web/{assets/elixir-deUWdS0T.js → elixir-deUWdS0T.js} +0 -0
- /auto_coder_web/web/{assets/flow9-i9-g7ZhI.js → flow9-i9-g7ZhI.js} +0 -0
- /auto_coder_web/web/{assets/fsharp-CzKuDChf.js → fsharp-CzKuDChf.js} +0 -0
- /auto_coder_web/web/{assets/go-Cphgjts3.js → go-Cphgjts3.js} +0 -0
- /auto_coder_web/web/{assets/graphql-Cg7bfA9N.js → graphql-Cg7bfA9N.js} +0 -0
- /auto_coder_web/web/{assets/hcl-0cvrggvQ.js → hcl-0cvrggvQ.js} +0 -0
- /auto_coder_web/web/{assets/ini-Drc7WvVn.js → ini-Drc7WvVn.js} +0 -0
- /auto_coder_web/web/{assets/java-B_fMsGYe.js → java-B_fMsGYe.js} +0 -0
- /auto_coder_web/web/{assets/julia-Bqgm2twL.js → julia-Bqgm2twL.js} +0 -0
- /auto_coder_web/web/{assets/kotlin-BSkB5QuD.js → kotlin-BSkB5QuD.js} +0 -0
- /auto_coder_web/web/{assets/less-BsTHnhdd.js → less-BsTHnhdd.js} +0 -0
- /auto_coder_web/web/{assets/lexon-YWi4-JPR.js → lexon-YWi4-JPR.js} +0 -0
- /auto_coder_web/web/{assets/lua-nf6ki56Z.js → lua-nf6ki56Z.js} +0 -0
- /auto_coder_web/web/{assets/m3-Cpb6xl2v.js → m3-Cpb6xl2v.js} +0 -0
- /auto_coder_web/web/{assets/markdown-DSZPf7rp.js → markdown-DSZPf7rp.js} +0 -0
- /auto_coder_web/web/{assets/mips-B_c3zf-v.js → mips-B_c3zf-v.js} +0 -0
- /auto_coder_web/web/{assets/msdax-rUNN04Wq.js → msdax-rUNN04Wq.js} +0 -0
- /auto_coder_web/web/{assets/mysql-DDwshQtU.js → mysql-DDwshQtU.js} +0 -0
- /auto_coder_web/web/{assets/objective-c-B5zXfXm9.js → objective-c-B5zXfXm9.js} +0 -0
- /auto_coder_web/web/{assets/pascal-CXOwvkN_.js → pascal-CXOwvkN_.js} +0 -0
- /auto_coder_web/web/{assets/pascaligo-Bc-ZgV77.js → pascaligo-Bc-ZgV77.js} +0 -0
- /auto_coder_web/web/{assets/perl-CwNk8-XU.js → perl-CwNk8-XU.js} +0 -0
- /auto_coder_web/web/{assets/pgsql-tGk8EFnU.js → pgsql-tGk8EFnU.js} +0 -0
- /auto_coder_web/web/{assets/php-CpIb_Oan.js → php-CpIb_Oan.js} +0 -0
- /auto_coder_web/web/{assets/pla-B03wrqEc.js → pla-B03wrqEc.js} +0 -0
- /auto_coder_web/web/{assets/postiats-BKlk5iyT.js → postiats-BKlk5iyT.js} +0 -0
- /auto_coder_web/web/{assets/powerquery-Bhzvs7bI.js → powerquery-Bhzvs7bI.js} +0 -0
- /auto_coder_web/web/{assets/powershell-Dd3NCNK9.js → powershell-Dd3NCNK9.js} +0 -0
- /auto_coder_web/web/{assets/protobuf-COyEY5Pt.js → protobuf-COyEY5Pt.js} +0 -0
- /auto_coder_web/web/{assets/pug-BaJupSGV.js → pug-BaJupSGV.js} +0 -0
- /auto_coder_web/web/{assets/qsharp-DXyYeYxl.js → qsharp-DXyYeYxl.js} +0 -0
- /auto_coder_web/web/{assets/r-CdQndTaG.js → r-CdQndTaG.js} +0 -0
- /auto_coder_web/web/{assets/redis-CVwtpugi.js → redis-CVwtpugi.js} +0 -0
- /auto_coder_web/web/{assets/redshift-25W9uPmb.js → redshift-25W9uPmb.js} +0 -0
- /auto_coder_web/web/{assets/restructuredtext-DfzH4Xui.js → restructuredtext-DfzH4Xui.js} +0 -0
- /auto_coder_web/web/{assets/ruby-Cp1zYvxS.js → ruby-Cp1zYvxS.js} +0 -0
- /auto_coder_web/web/{assets/rust-D5C2fndG.js → rust-D5C2fndG.js} +0 -0
- /auto_coder_web/web/{assets/sb-CDntyWJ8.js → sb-CDntyWJ8.js} +0 -0
- /auto_coder_web/web/{assets/scala-BoFRg7Ot.js → scala-BoFRg7Ot.js} +0 -0
- /auto_coder_web/web/{assets/scheme-Bio4gycK.js → scheme-Bio4gycK.js} +0 -0
- /auto_coder_web/web/{assets/scss-4Ik7cdeQ.js → scss-4Ik7cdeQ.js} +0 -0
- /auto_coder_web/web/{assets/shell-CX-rkNHf.js → shell-CX-rkNHf.js} +0 -0
- /auto_coder_web/web/{assets/solidity-Tw7wswEv.js → solidity-Tw7wswEv.js} +0 -0
- /auto_coder_web/web/{assets/sophia-C5WLch3f.js → sophia-C5WLch3f.js} +0 -0
- /auto_coder_web/web/{assets/sparql-DHaeiCBh.js → sparql-DHaeiCBh.js} +0 -0
- /auto_coder_web/web/{assets/sql-CCSDG5nI.js → sql-CCSDG5nI.js} +0 -0
- /auto_coder_web/web/{assets/st-pnP8ivHi.js → st-pnP8ivHi.js} +0 -0
- /auto_coder_web/web/{assets/swift-DwJ7jVG9.js → swift-DwJ7jVG9.js} +0 -0
- /auto_coder_web/web/{assets/systemverilog-B9Xyijhd.js → systemverilog-B9Xyijhd.js} +0 -0
- /auto_coder_web/web/{assets/tcl-DnHyzjbg.js → tcl-DnHyzjbg.js} +0 -0
- /auto_coder_web/web/{assets/twig-CPajHgWi.js → twig-CPajHgWi.js} +0 -0
- /auto_coder_web/web/{assets/typespec-D-MeaMDU.js → typespec-D-MeaMDU.js} +0 -0
- /auto_coder_web/web/{assets/vb-DgyLZaXg.js → vb-DgyLZaXg.js} +0 -0
- /auto_coder_web/web/{assets/wgsl-BIv9DU6q.js → wgsl-BIv9DU6q.js} +0 -0
- {auto_coder_web-0.1.61.dist-info → auto_coder_web-0.1.62.dist-info}/WHEEL +0 -0
- {auto_coder_web-0.1.61.dist-info → auto_coder_web-0.1.62.dist-info}/entry_points.txt +0 -0
- {auto_coder_web-0.1.61.dist-info → auto_coder_web-0.1.62.dist-info}/top_level.txt +0 -0
@@ -4,94 +4,277 @@ import os
|
|
4
4
|
from fastapi import APIRouter, HTTPException, Request, Depends
|
5
5
|
from pydantic import BaseModel, Field
|
6
6
|
from typing import Dict, Any, Optional, List
|
7
|
-
from autocoder.common.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
McpRefreshRequest,
|
7
|
+
from autocoder.common.mcp_server_types import (
|
8
|
+
McpInstallRequest,
|
9
|
+
McpRemoveRequest,
|
10
|
+
McpListRequest,
|
11
|
+
McpListRunningRequest,
|
12
|
+
McpRefreshRequest,
|
14
13
|
McpServerInfoRequest,
|
15
|
-
McpResponse
|
14
|
+
McpResponse,
|
15
|
+
InstallResult,
|
16
|
+
RemoveResult,
|
17
|
+
ListResult,
|
18
|
+
ListRunningResult,
|
19
|
+
RefreshResult,
|
20
|
+
QueryResult,
|
21
|
+
ErrorResult,
|
22
|
+
ServerInfo,
|
23
|
+
ExternalServerInfo,
|
24
|
+
ServerConfig, # Added for InstallResult
|
25
|
+
MarketplaceAddRequest,
|
26
|
+
MarketplaceAddResult,
|
27
|
+
MarketplaceUpdateRequest, # Added for update endpoint
|
28
|
+
MarketplaceUpdateResult, # Added for update endpoint
|
16
29
|
)
|
17
|
-
from autocoder.common.
|
18
|
-
from autocoder.
|
30
|
+
from autocoder.common.mcp_server import get_mcp_server
|
31
|
+
from autocoder.common.printer import Printer # For messages
|
32
|
+
from autocoder.chat_auto_coder_lang import (
|
33
|
+
get_message_with_format,
|
34
|
+
get_message,
|
35
|
+
) # For formatted messages
|
19
36
|
from loguru import logger
|
20
|
-
from byzerllm.utils.langutil import asyncfy_with_semaphore
|
21
|
-
|
22
|
-
# Use asyncfy_with_semaphore to wrap the synchronous send_request method
|
23
|
-
async_send_request = asyncfy_with_semaphore(get_mcp_server().send_request, max_workers=5)
|
24
37
|
|
25
38
|
router = APIRouter()
|
26
|
-
printer = Printer()
|
39
|
+
printer = Printer() # Initialize printer for messages
|
40
|
+
|
41
|
+
|
42
|
+
# Helper function to run the synchronous send_request in a thread
|
43
|
+
async def send_mcp_request_async(*args, **kwargs) -> McpResponse:
|
44
|
+
"""Runs the synchronous MCP send_request in a separate thread."""
|
45
|
+
return await asyncio.to_thread(get_mcp_server().send_request, *args, **kwargs)
|
46
|
+
|
27
47
|
|
28
48
|
# --- Pydantic Models for Requests ---
|
29
49
|
|
30
|
-
|
31
|
-
|
50
|
+
|
51
|
+
class McpInstallRequestModel(BaseModel):
|
52
|
+
server_config: str = Field(
|
53
|
+
..., description="Server configuration string (command-line style or JSON)"
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
# Model for the new /api/mcp/add endpoint
|
58
|
+
class MarketplaceAddRequestModel(BaseModel):
|
59
|
+
name: str = Field(
|
60
|
+
..., description="Name of the MCP server to add to the marketplace"
|
61
|
+
)
|
62
|
+
description: Optional[str] = Field("", description="Description of the MCP server")
|
63
|
+
mcp_type: str = Field(
|
64
|
+
"command", description="Type of MCP server (e.g., 'command', 'sse')"
|
65
|
+
)
|
66
|
+
command: Optional[str] = Field(
|
67
|
+
None, description="Command to run the server (if type is 'command')"
|
68
|
+
) # Allow None
|
69
|
+
args: Optional[List[str]] = Field(None, description="Arguments for the command")
|
70
|
+
env: Optional[Dict[str, str]] = Field(
|
71
|
+
None, description="Environment variables for the command"
|
72
|
+
)
|
73
|
+
url: Optional[str] = Field(
|
74
|
+
None, description="URL endpoint for the server (if type is 'sse')"
|
75
|
+
) # Allow None
|
76
|
+
|
77
|
+
|
78
|
+
# Model for the /api/mcp/update endpoint
|
79
|
+
class MarketplaceUpdateRequestModel(BaseModel):
|
80
|
+
name: str = Field(
|
81
|
+
..., description="Name of the MCP server to update (used as identifier)"
|
82
|
+
)
|
83
|
+
description: Optional[str] = Field(
|
84
|
+
None, description="Updated description of the MCP server"
|
85
|
+
)
|
86
|
+
mcp_type: Optional[str] = Field(
|
87
|
+
None, description="Updated type of MCP server"
|
88
|
+
) # Allow None if not changing
|
89
|
+
command: Optional[str] = Field(None, description="Updated command")
|
90
|
+
args: Optional[List[str]] = Field(None, description="Updated arguments")
|
91
|
+
env: Optional[Dict[str, str]] = Field(
|
92
|
+
None, description="Updated environment variables (replaces existing)"
|
93
|
+
)
|
94
|
+
url: Optional[str] = Field(None, description="Updated URL endpoint")
|
95
|
+
|
32
96
|
|
33
97
|
class McpRemoveRequestModel(BaseModel):
|
34
98
|
server_name: str = Field(..., description="Name of the MCP server to remove")
|
35
99
|
|
100
|
+
|
36
101
|
class McpRefreshRequestModel(BaseModel):
|
37
|
-
server_name: Optional[str] = Field(
|
102
|
+
server_name: Optional[str] = Field(
|
103
|
+
None,
|
104
|
+
description="Name of the MCP server to refresh (optional, refreshes all if None)",
|
105
|
+
)
|
106
|
+
|
38
107
|
|
39
108
|
class McpInfoRequestModel(BaseModel):
|
40
109
|
# Assuming model and product_mode might come from global config or request context later
|
41
110
|
# For now, let's make them optional or derive them if possible
|
42
111
|
model: Optional[str] = None
|
43
|
-
product_mode: Optional[str] = None
|
112
|
+
product_mode: Optional[str] = None # Example: "lite", "pro"
|
113
|
+
|
44
114
|
|
45
115
|
# --- Helper Function to Handle MCP Responses ---
|
46
116
|
|
47
|
-
|
117
|
+
|
118
|
+
async def handle_mcp_response(
|
119
|
+
request: Any, success_key: str, error_key: str, **kwargs
|
120
|
+
) -> Dict[str, Any]:
|
48
121
|
"""Handles sending request to MCP server and formatting the response."""
|
49
122
|
try:
|
50
|
-
response: McpResponse = await
|
123
|
+
response: McpResponse = await send_mcp_request_async(request)
|
51
124
|
if response.error:
|
52
125
|
logger.error(f"MCP Error ({error_key}): {response.error}")
|
53
126
|
# Use get_message_with_format if available, otherwise use the raw error
|
54
127
|
error_message = response.error
|
55
128
|
try:
|
56
129
|
# Attempt to format the error message if a key is provided
|
57
|
-
formatted_error = get_message_with_format(
|
58
|
-
|
130
|
+
formatted_error = get_message_with_format(
|
131
|
+
error_key, error=response.error
|
132
|
+
)
|
133
|
+
if formatted_error: # Check if formatting was successful
|
59
134
|
error_message = formatted_error
|
60
|
-
except Exception:
|
61
|
-
pass
|
135
|
+
except Exception: # Catch potential errors during formatting
|
136
|
+
pass # Stick with the original error message
|
62
137
|
raise HTTPException(status_code=400, detail=error_message)
|
63
138
|
else:
|
64
139
|
# Use get_message_with_format for success message if available
|
65
140
|
success_message = response.result
|
66
141
|
try:
|
67
|
-
formatted_success = get_message_with_format(
|
68
|
-
|
142
|
+
formatted_success = get_message_with_format(
|
143
|
+
success_key, result=response.result, **kwargs
|
144
|
+
)
|
145
|
+
if formatted_success: # Check if formatting was successful
|
69
146
|
success_message = formatted_success
|
70
147
|
except Exception:
|
71
|
-
|
72
|
-
|
148
|
+
pass # Stick with the original result message
|
149
|
+
# Return the formatted message and the raw Pydantic model result
|
150
|
+
return {
|
151
|
+
"status": "success",
|
152
|
+
"message": success_message,
|
153
|
+
"raw_result": response.raw_result,
|
154
|
+
}
|
73
155
|
except HTTPException as http_exc:
|
74
|
-
raise http_exc
|
156
|
+
raise http_exc # Re-raise HTTPException
|
75
157
|
except Exception as e:
|
76
158
|
logger.error(f"Unexpected error during MCP request ({error_key}): {str(e)}")
|
77
159
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
78
160
|
|
161
|
+
|
79
162
|
# --- API Endpoints ---
|
80
163
|
|
164
|
+
|
165
|
+
@router.post("/api/mcp/install")
|
166
|
+
async def install_mcp_server(request: McpInstallRequestModel):
|
167
|
+
"""
|
168
|
+
Installs or updates an MCP server configuration based on name, JSON, or command-line args.
|
169
|
+
Handles built-in, external, and custom server installations.
|
170
|
+
"""
|
171
|
+
# First, try to find the server in the marketplace list via McpListRequest
|
172
|
+
try:
|
173
|
+
list_request = McpListRequest()
|
174
|
+
list_response: McpResponse = await send_mcp_request_async(list_request)
|
175
|
+
|
176
|
+
marketplace_item = None
|
177
|
+
if list_response.raw_result and isinstance(
|
178
|
+
list_response.raw_result, ListResult
|
179
|
+
):
|
180
|
+
# Combine all server lists for searching
|
181
|
+
all_servers = list_response.raw_result.marketplace_items
|
182
|
+
for item in all_servers:
|
183
|
+
if item.name == request.server_config:
|
184
|
+
marketplace_item = item
|
185
|
+
break
|
186
|
+
|
187
|
+
if marketplace_item:
|
188
|
+
# If found in any list, create install request with the item
|
189
|
+
mcp_request = McpInstallRequest(market_install_item=marketplace_item)
|
190
|
+
logger.info(
|
191
|
+
f"Found '{request.server_config}' in available server lists. Installing using item. {marketplace_item}"
|
192
|
+
)
|
193
|
+
else:
|
194
|
+
# If not found in any list, assume it's a direct config string or an unknown name
|
195
|
+
mcp_request = McpInstallRequest(server_name_or_config=request.server_config)
|
196
|
+
logger.info(
|
197
|
+
f"'{request.server_config}' not found in available server lists. Installing using name/config string."
|
198
|
+
)
|
199
|
+
|
200
|
+
# Proceed with installation using the determined request type
|
201
|
+
return await handle_mcp_response(
|
202
|
+
mcp_request,
|
203
|
+
success_key="mcp_install_success",
|
204
|
+
error_key="mcp_install_error",
|
205
|
+
result=request.server_config, # Pass original config for success message formatting
|
206
|
+
)
|
207
|
+
|
208
|
+
except HTTPException as http_exc:
|
209
|
+
# Re-raise HTTP exceptions from handle_mcp_response or list request
|
210
|
+
raise http_exc
|
211
|
+
except Exception as e:
|
212
|
+
logger.error(
|
213
|
+
f"Error during MCP install process for '{request.server_config}': {e}"
|
214
|
+
)
|
215
|
+
# Fallback to original behavior if list fails or other errors occur
|
216
|
+
logger.warning("Falling back to direct install request due to previous error.")
|
217
|
+
mcp_request = McpInstallRequest(server_name_or_config=request.server_config)
|
218
|
+
return await handle_mcp_response(
|
219
|
+
mcp_request,
|
220
|
+
success_key="mcp_install_success",
|
221
|
+
error_key="mcp_install_error",
|
222
|
+
result=request.server_config,
|
223
|
+
)
|
224
|
+
|
225
|
+
|
81
226
|
@router.post("/api/mcp/add")
|
82
|
-
async def
|
227
|
+
async def add_marketplace_server(request: MarketplaceAddRequestModel):
|
83
228
|
"""
|
84
|
-
Adds
|
85
|
-
Accepts command-line style args or a JSON string.
|
229
|
+
Adds a new MCP server configuration to the marketplace file.
|
86
230
|
"""
|
87
|
-
|
231
|
+
# Convert API model to the internal McpHub model
|
232
|
+
mcp_request = MarketplaceAddRequest(
|
233
|
+
name=request.name,
|
234
|
+
description=request.description,
|
235
|
+
mcp_type=request.mcp_type,
|
236
|
+
command=request.command,
|
237
|
+
args=request.args,
|
238
|
+
env=request.env,
|
239
|
+
url=request.url,
|
240
|
+
)
|
88
241
|
return await handle_mcp_response(
|
89
242
|
mcp_request,
|
90
|
-
success_key="
|
91
|
-
error_key="
|
92
|
-
|
243
|
+
success_key="marketplace_add_success",
|
244
|
+
error_key="marketplace_add_error",
|
245
|
+
name=request.name, # Pass name for message formatting
|
93
246
|
)
|
94
247
|
|
248
|
+
|
249
|
+
@router.post("/api/mcp/update")
|
250
|
+
async def update_marketplace_server(request: MarketplaceUpdateRequestModel):
|
251
|
+
"""
|
252
|
+
Updates an existing MCP server configuration in the marketplace file.
|
253
|
+
Uses the 'name' field to identify the server to update.
|
254
|
+
"""
|
255
|
+
# Convert API model to the internal McpHub model for update
|
256
|
+
# Note: We assume MarketplaceUpdateRequest exists in mcp_server
|
257
|
+
# and handles partial updates based on provided fields.
|
258
|
+
# If a field is None in the request, it might mean "don't update this field"
|
259
|
+
# or "set this field to None/empty", depending on McpHub's implementation.
|
260
|
+
# Here, we pass all fields from the request model.
|
261
|
+
mcp_request = MarketplaceUpdateRequest(
|
262
|
+
name=request.name, # Identifier
|
263
|
+
description=request.description,
|
264
|
+
mcp_type=request.mcp_type,
|
265
|
+
command=request.command,
|
266
|
+
args=request.args,
|
267
|
+
env=request.env,
|
268
|
+
url=request.url,
|
269
|
+
)
|
270
|
+
return await handle_mcp_response(
|
271
|
+
mcp_request,
|
272
|
+
success_key="marketplace_update_success", # Define this message key
|
273
|
+
error_key="marketplace_update_error", # Define this message key
|
274
|
+
name=request.name, # Pass name for message formatting
|
275
|
+
)
|
276
|
+
|
277
|
+
|
95
278
|
@router.post("/api/mcp/remove")
|
96
279
|
async def remove_mcp_server(request: McpRemoveRequestModel):
|
97
280
|
"""Removes an MCP server configuration by name."""
|
@@ -100,24 +283,36 @@ async def remove_mcp_server(request: McpRemoveRequestModel):
|
|
100
283
|
mcp_request,
|
101
284
|
success_key="mcp_remove_success",
|
102
285
|
error_key="mcp_remove_error",
|
103
|
-
result=request.server_name
|
286
|
+
result=request.server_name, # Pass server name for success message formatting
|
104
287
|
)
|
105
288
|
|
289
|
+
|
106
290
|
@router.get("/api/mcp/list")
|
107
291
|
async def list_mcp_servers():
|
108
292
|
"""Lists all available built-in and external MCP servers."""
|
109
293
|
mcp_request = McpListRequest()
|
110
294
|
# Specific handling for list as the result is the data itself
|
111
295
|
try:
|
112
|
-
response: McpResponse = await
|
296
|
+
response: McpResponse = await send_mcp_request_async(mcp_request)
|
113
297
|
if response.error:
|
114
298
|
logger.error(f"MCP Error (mcp_list_builtin_error): {response.error}")
|
115
|
-
error_message =
|
116
|
-
|
299
|
+
error_message = (
|
300
|
+
get_message_with_format("mcp_list_builtin_error", error=response.error)
|
301
|
+
or response.error
|
302
|
+
)
|
303
|
+
# Ensure raw_result is included in the error detail if it's an ErrorResult
|
304
|
+
detail = error_message
|
305
|
+
if isinstance(response.raw_result, ErrorResult):
|
306
|
+
detail = f"{error_message} (Details: {response.raw_result.error})"
|
307
|
+
raise HTTPException(status_code=400, detail=detail)
|
117
308
|
else:
|
118
|
-
#
|
119
|
-
|
120
|
-
return {
|
309
|
+
# Return the raw_result which should be of type ListResult
|
310
|
+
# Ensure the response is structured consistently
|
311
|
+
return {
|
312
|
+
"status": "success",
|
313
|
+
"message": "MCP servers listed successfully.",
|
314
|
+
"raw_result": response.raw_result,
|
315
|
+
}
|
121
316
|
except HTTPException as http_exc:
|
122
317
|
raise http_exc
|
123
318
|
except Exception as e:
|
@@ -131,58 +326,88 @@ async def list_running_mcp_servers():
|
|
131
326
|
mcp_request = McpListRunningRequest()
|
132
327
|
# Specific handling for list_running
|
133
328
|
try:
|
134
|
-
response: McpResponse = await
|
329
|
+
response: McpResponse = await send_mcp_request_async(mcp_request)
|
135
330
|
if response.error:
|
136
331
|
logger.error(f"MCP Error (mcp_list_running_error): {response.error}")
|
137
|
-
error_message =
|
138
|
-
|
332
|
+
error_message = (
|
333
|
+
get_message_with_format("mcp_list_running_error", error=response.error)
|
334
|
+
or response.error
|
335
|
+
)
|
336
|
+
# Ensure raw_result is included in the error detail if it's an ErrorResult
|
337
|
+
detail = error_message
|
338
|
+
if isinstance(response.raw_result, ErrorResult):
|
339
|
+
detail = f"{error_message} (Details: {response.raw_result.error})"
|
340
|
+
raise HTTPException(status_code=400, detail=detail)
|
139
341
|
else:
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
342
|
+
# Return the raw_result which should be of type ListRunningResult
|
343
|
+
# Ensure the response is structured consistently
|
344
|
+
return {
|
345
|
+
"status": "success",
|
346
|
+
"message": "Running MCP servers listed successfully.",
|
347
|
+
"raw_result": response.raw_result,
|
348
|
+
}
|
145
349
|
except HTTPException as http_exc:
|
146
350
|
raise http_exc
|
147
351
|
except Exception as e:
|
148
352
|
logger.error(f"Unexpected error during MCP list_running request: {str(e)}")
|
149
353
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
150
354
|
|
355
|
+
|
151
356
|
@router.post("/api/mcp/refresh")
|
152
357
|
async def refresh_mcp_connections(request: McpRefreshRequestModel):
|
153
358
|
"""Refreshes connections to MCP servers (all or a specific one)."""
|
154
359
|
mcp_request = McpRefreshRequest(name=request.server_name)
|
155
360
|
return await handle_mcp_response(
|
156
|
-
mcp_request,
|
157
|
-
success_key="mcp_refresh_success",
|
158
|
-
error_key="mcp_refresh_error"
|
361
|
+
mcp_request, success_key="mcp_refresh_success", error_key="mcp_refresh_error"
|
159
362
|
)
|
160
363
|
|
364
|
+
|
161
365
|
@router.get("/api/mcp/info")
|
162
|
-
async def get_mcp_server_info(
|
366
|
+
async def get_mcp_server_info(
|
367
|
+
model: Optional[str] = None, product_mode: Optional[str] = "lite"
|
368
|
+
):
|
163
369
|
"""Gets detailed information about connected MCP servers."""
|
164
370
|
# TODO: Determine how to get model/product_mode - from app state, global config, or request?
|
165
371
|
# Using optional query params for now.
|
166
372
|
mcp_request = McpServerInfoRequest(model=model, product_mode=product_mode)
|
167
373
|
# Specific handling for info
|
168
374
|
try:
|
169
|
-
response: McpResponse = await
|
375
|
+
response: McpResponse = await send_mcp_request_async(mcp_request)
|
170
376
|
if response.error:
|
171
377
|
logger.error(f"MCP Error (mcp_server_info_error): {response.error}")
|
172
|
-
error_message =
|
173
|
-
|
378
|
+
error_message = (
|
379
|
+
get_message_with_format("mcp_server_info_error", error=response.error)
|
380
|
+
or response.error
|
381
|
+
)
|
382
|
+
# Ensure raw_result is included in the error detail if it's an ErrorResult
|
383
|
+
detail = error_message
|
384
|
+
if isinstance(response.raw_result, ErrorResult):
|
385
|
+
detail = f"{error_message} (Details: {response.raw_result.error})"
|
386
|
+
raise HTTPException(status_code=400, detail=detail)
|
174
387
|
else:
|
175
|
-
#
|
176
|
-
|
388
|
+
# Return the raw_result. It might be a string or a specific Pydantic model later.
|
389
|
+
# For now, we assume it's included in McpResponse.raw_result
|
390
|
+
# Ensure the response is structured consistently
|
391
|
+
# The success message might vary or be generic
|
392
|
+
success_message = (
|
393
|
+
get_message_with_format("mcp_server_info_success")
|
394
|
+
or "Server info retrieved successfully."
|
395
|
+
)
|
396
|
+
return {
|
397
|
+
"status": "success",
|
398
|
+
"message": success_message,
|
399
|
+
"raw_result": response.raw_result,
|
400
|
+
}
|
177
401
|
except HTTPException as http_exc:
|
178
402
|
raise http_exc
|
179
403
|
except Exception as e:
|
180
404
|
logger.error(f"Unexpected error during MCP info request: {str(e)}")
|
181
405
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
182
406
|
|
407
|
+
|
183
408
|
# Potentially add endpoints for direct tool calls or resource access if needed in the future
|
184
409
|
# @router.post("/api/mcp/call_tool")
|
185
410
|
# async def call_mcp_tool(...): ...
|
186
411
|
|
187
412
|
# @router.get("/api/mcp/read_resource")
|
188
|
-
# async def read_mcp_resource(...): ...
|
413
|
+
# async def read_mcp_resource(...): ...
|
auto_coder_web/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.62"
|
@@ -0,0 +1 @@
|
|
1
|
+
import{r,I as K,_ as P,j as e,S as Q,T as q,R as ee,a as I,h as se,v as te,b as U,s as b,d as O,l as J,c as re,e as ae,E as ne,B as M,L as z,C as le,f as W,g as oe,i as ie,M as ce}from"./main.js";var de={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M839.6 433.8L749 150.5a9.24 9.24 0 00-8.9-6.5h-77.4c-4.1 0-7.6 2.6-8.9 6.5l-91.3 283.3c-.3.9-.5 1.9-.5 2.9 0 5.1 4.2 9.3 9.3 9.3h56.4c4.2 0 7.8-2.8 9-6.8l17.5-61.6h89l17.3 61.5c1.1 4 4.8 6.8 9 6.8h61.2c1 0 1.9-.1 2.8-.4 2.4-.8 4.3-2.4 5.5-4.6 1.1-2.2 1.3-4.7.6-7.1zM663.3 325.5l32.8-116.9h6.3l32.1 116.9h-71.2zm143.5 492.9H677.2v-.4l132.6-188.9c1.1-1.6 1.7-3.4 1.7-5.4v-36.4c0-5.1-4.2-9.3-9.3-9.3h-204c-5.1 0-9.3 4.2-9.3 9.3v43c0 5.1 4.2 9.3 9.3 9.3h122.6v.4L587.7 828.9a9.35 9.35 0 00-1.7 5.4v36.4c0 5.1 4.2 9.3 9.3 9.3h211.4c5.1 0 9.3-4.2 9.3-9.3v-43a9.2 9.2 0 00-9.2-9.3zM416 702h-76V172c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v530h-76c-6.7 0-10.5 7.8-6.3 13l112 141.9a8 8 0 0012.6 0l112-141.9c4.1-5.2.4-13-6.3-13z"}}]},name:"sort-ascending",theme:"outlined"},he=function(i,l){return r.createElement(K,P({},i,{ref:l,icon:de}))},fe=r.forwardRef(he),ue={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M839.6 433.8L749 150.5a9.24 9.24 0 00-8.9-6.5h-77.4c-4.1 0-7.6 2.6-8.9 6.5l-91.3 283.3c-.3.9-.5 1.9-.5 2.9 0 5.1 4.2 9.3 9.3 9.3h56.4c4.2 0 7.8-2.8 9-6.8l17.5-61.6h89l17.3 61.5c1.1 4 4.8 6.8 9 6.8h61.2c1 0 1.9-.1 2.8-.4 2.4-.8 4.3-2.4 5.5-4.6 1.1-2.2 1.3-4.7.6-7.1zM663.3 325.5l32.8-116.9h6.3l32.1 116.9h-71.2zm143.5 492.9H677.2v-.4l132.6-188.9c1.1-1.6 1.7-3.4 1.7-5.4v-36.4c0-5.1-4.2-9.3-9.3-9.3h-204c-5.1 0-9.3 4.2-9.3 9.3v43c0 5.1 4.2 9.3 9.3 9.3h122.6v.4L587.7 828.9a9.35 9.35 0 00-1.7 5.4v36.4c0 5.1 4.2 9.3 9.3 9.3h211.4c5.1 0 9.3-4.2 9.3-9.3v-43a9.2 9.2 0 00-9.2-9.3zM310.3 167.1a8 8 0 00-12.6 0L185.7 309c-4.2 5.3-.4 13 6.3 13h76v530c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V322h76c6.7 0 10.5-7.8 6.3-13l-112-141.9z"}}]},name:"sort-descending",theme:"outlined"},xe=function(i,l){return r.createElement(K,P({},i,{ref:l,icon:ue}))},me=r.forwardRef(xe),ge={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M511.4 124C290.5 124.3 112 303 112 523.9c0 128 60.2 242 153.8 315.2l-37.5 48c-4.1 5.3-.3 13 6.3 12.9l167-.8c5.2 0 9-4.9 7.7-9.9L369.8 727a8 8 0 00-14.1-3L315 776.1c-10.2-8-20-16.7-29.3-26a318.64 318.64 0 01-68.6-101.7C200.4 609 192 567.1 192 523.9s8.4-85.1 25.1-124.5c16.1-38.1 39.2-72.3 68.6-101.7 29.4-29.4 63.6-52.5 101.7-68.6C426.9 212.4 468.8 204 512 204s85.1 8.4 124.5 25.1c38.1 16.1 72.3 39.2 101.7 68.6 29.4 29.4 52.5 63.6 68.6 101.7 16.7 39.4 25.1 81.3 25.1 124.5s-8.4 85.1-25.1 124.5a318.64 318.64 0 01-68.6 101.7c-7.5 7.5-15.3 14.5-23.4 21.2a7.93 7.93 0 00-1.2 11.1l39.4 50.5c2.8 3.5 7.9 4.1 11.4 1.3C854.5 760.8 912 649.1 912 523.9c0-221.1-179.4-400.2-400.6-399.9z"}}]},name:"undo",theme:"outlined"},pe=function(i,l){return r.createElement(K,P({},i,{ref:l,icon:ge}))},be=r.forwardRef(pe);J.config({paths:{vs:"/monaco-editor/min/vs"},"vs/nls":{availableLanguages:{"*":"zh-cn"}}});const{TabPane:G}=q,ve=({commitId:n,onClose:i})=>{const[l,B]=r.useState({diff:""}),[o,k]=r.useState(null),[c,v]=r.useState(null),[S,R]=r.useState(!1),[f,E]=r.useState("split"),[u,L]=r.useState(null),[m,y]=r.useState(!1),[g,$]=r.useState("1"),j=r.useRef(null),p=r.useRef(null),w=r.useRef(null),N=r.useRef(null),D=async()=>{if(n){y(!0);try{const t=encodeURIComponent(n),a=await U.get(`/api/history/commit-diff/${t}`);a.data.success?B({diff:a.data.diff,file_changes:a.data.file_changes}):b.error(a.data.message||"获取diff失败")}catch(t){console.error("Error fetching diff:",t),b.error("获取diff失败")}finally{y(!1)}}},C=async t=>{if(n)try{R(!0),v(null),j.current=null,p.current=null,w.current=null;const a=encodeURIComponent(n),x=await U.get(`/api/history/file-diff/${a}?file_path=${encodeURIComponent(t)}`);x.data.success?v(x.data.file_diff):b.error(x.data.message||"获取文件差异失败")}catch(a){console.error("Error fetching file diff:",a),b.error("获取文件差异失败")}finally{R(!1)}},F=t=>{o===t?(k(null),v(null),j.current=null,p.current=null,w.current=null,L(null)):(k(t),C(t),L(null))},A=r.useCallback(t=>{j.current=t},[]),T=r.useCallback(t=>{p.current=t},[]),s=r.useCallback(t=>{w.current=t},[]),d=t=>{var _;const a=(_=t.split(".").pop())==null?void 0:_.toLowerCase();return{js:"javascript",jsx:"javascript",ts:"typescript",tsx:"typescript",py:"python",java:"java",c:"c",cpp:"cpp",cs:"csharp",go:"go",rs:"rust",rb:"ruby",php:"php",html:"html",css:"css",scss:"scss",json:"json",md:"markdown",yml:"yaml",yaml:"yaml",xml:"xml",sh:"shell",bash:"shell",txt:"plaintext"}[a||""]||"plaintext"},h=({viewType:t})=>{const a=u===t;return e.jsx("button",{className:"ml-2 text-gray-400 hover:text-white transition-colors",onClick:x=>{x.stopPropagation(),L(a?null:t)},title:a?"恢复正常视图":"最大化视图",children:a?e.jsx("svg",{className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"})}):e.jsx("svg",{className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"})})})},X=()=>{if(!o||!c)return null;const t=d(o),a=`diff-${n}-${o}-${f}`,x=`before-${n}-${o}`,_=`after-${n}-${o}`,V={readOnly:!0,scrollBeyondLastLine:!1,minimap:{enabled:!1},lineNumbers:"on",wordWrap:"on",automaticLayout:!0,scrollbar:{vertical:"visible",horizontal:"visible",verticalScrollbarSize:14,horizontalScrollbarSize:14}};return f==="unified"?e.jsxs("div",{ref:N,className:"bg-gray-900 rounded-lg border border-gray-700",style:{height:"500px",width:"100%",overflow:"hidden"},children:[e.jsxs("div",{className:"py-1 px-3 bg-gray-800 border-b border-gray-700 text-xs font-medium text-white flex justify-between items-center",children:[e.jsx("span",{children:"差异视图"}),e.jsx(h,{viewType:"diff"})]}),e.jsx(O,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:"diff",value:c.diff_content||"",theme:"vs-dark",onMount:s,options:V,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},a)]}):e.jsxs("div",{ref:N,className:"grid grid-cols-2 gap-2",style:{height:"500px",width:"100%"},children:[(u===null||u==="before")&&e.jsxs("div",{className:`bg-gray-900 rounded-lg border border-gray-700 ${u==="before"?"col-span-2":""}`,style:{overflow:"hidden"},children:[e.jsxs("div",{className:"py-1 px-3 bg-gray-800 border-b border-gray-700 text-xs font-medium text-white flex justify-between items-center",children:[e.jsxs("span",{children:["修改前 (",c.file_status==="added"?"新文件":o,")"]}),e.jsx(h,{viewType:"before"})]}),e.jsx(O,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:t,value:c.before_content||"",theme:"vs-dark",onMount:A,options:V,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},x)]}),(u===null||u==="after")&&e.jsxs("div",{className:`bg-gray-900 rounded-lg border border-gray-700 ${u==="after"?"col-span-2":""}`,style:{overflow:"hidden"},children:[e.jsxs("div",{className:"py-1 px-3 bg-gray-800 border-b border-gray-700 text-xs font-medium text-white flex justify-between items-center",children:[e.jsxs("span",{children:["修改后 (",c.file_status==="deleted"?"文件已删除":o,")"]}),e.jsx(h,{viewType:"after"})]}),e.jsx(O,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:t,value:c.after_content||"",theme:"vs-dark",onMount:T,options:V,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},_)]})]})};r.useEffect(()=>{n&&D()},[n]);const Y={background:"#1F2937",borderBottom:"1px solid #374151",margin:0,padding:"0 16px"},Z=(t,a)=>e.jsx(a,{...t,style:Y,className:"custom-tabs-bar"});return e.jsxs("div",{className:"flex flex-col h-full bg-[#111827] overflow-hidden",children:[e.jsxs("div",{className:"flex justify-between items-center p-4 bg-[#1F2937] border-b border-[#374151]",children:[e.jsx("h2",{className:"text-lg font-semibold text-white",children:"代码变更详情"}),e.jsx(Q,{children:i&&e.jsx("button",{className:"px-3 py-1.5 bg-gray-700 hover:bg-gray-600 text-white rounded text-sm",onClick:i,children:"关闭"})})]}),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs(q,{activeKey:g,onChange:$,type:"card",className:"diff-viewer-tabs",renderTabBar:Z,style:{background:"#111827"},children:[e.jsx(G,{tab:e.jsx("div",{className:`py-2 px-4 ${g==="1"?"text-white font-medium":"text-gray-400"}`,children:"文件列表"}),children:e.jsxs("div",{className:"p-4",children:[e.jsx("div",{className:"space-y-2 mb-4",children:m?e.jsx("div",{className:"flex items-center justify-center py-10",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-white"})}):l.file_changes&&l.file_changes.length>0?l.file_changes.map((t,a)=>e.jsx("div",{className:`text-sm py-2 px-3 rounded cursor-pointer ${o===t.path?"bg-gray-700 border-l-2 border-indigo-500":"hover:bg-gray-750 bg-gray-800"}`,onClick:()=>F(t.path),children:e.jsxs("div",{className:"flex items-center",children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full mr-2 ${t.change_type==="added"?"bg-green-500":t.change_type==="modified"?"bg-yellow-500":t.change_type==="deleted"?"bg-red-500":"bg-blue-500"}`}),e.jsx("span",{className:`font-mono ${t.change_type==="deleted"?"line-through text-gray-500":"text-white"}`,children:t.path}),e.jsx(ee,{className:"ml-2 text-gray-400"})]})},a)):e.jsx("div",{className:"text-center text-white py-8",children:e.jsx("p",{children:"没有文件变更信息"})})}),S&&e.jsx("div",{className:"flex items-center justify-center py-10",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-white"})}),o&&c&&!S&&e.jsx("div",{className:"flex justify-end mb-3",children:e.jsxs(I.Group,{value:f,onChange:t=>E(t.target.value),buttonStyle:"solid",children:[e.jsx(I.Button,{value:"split",style:{color:f==="split"?"#fff":"#1f2937"},children:"分割视图"}),e.jsx(I.Button,{value:"unified",style:{color:f==="unified"?"#fff":"#1f2937"},children:"统一视图"})]})}),o&&c&&!S&&X()]})},"1"),e.jsx(G,{tab:e.jsx("div",{className:`py-2 px-4 ${g==="2"?"text-white font-medium":"text-gray-400"}`,children:"原始差异"}),children:e.jsx("div",{className:"p-4",children:m?e.jsx("div",{className:"flex items-center justify-center py-10",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-white"})}):e.jsx(se,{language:"diff",style:te,customStyle:{padding:"12px",borderRadius:"4px",overflow:"auto",maxHeight:"600px"},children:l.diff||""})})},"2")]})})]})};J.config({paths:{vs:"/monaco-editor/min/vs"},"vs/nls":{availableLanguages:{"*":"zh-cn"}}});const{Text:H}=oe,{TabPane:je}=q,we=()=>{const[n,i]=r.useState([]),[l,B]=r.useState(!1),[o,k]=r.useState(!1),[c,v]=r.useState(!1),[S,R]=r.useState([]),[f,E]=r.useState(null),[u,L]=r.useState(!1),[m,y]=r.useState({show:!1,commitHash:"",commitMessage:""}),[g,$]=r.useState(!1),[j,p]=r.useState(null),[w,N]=r.useState(null),D=s=>{if(!s){b.info("该消息没有关联的代码变更");return}E(s)},C=async()=>{k(!0);try{const s=await U.get("/api/history/validate-and-load");s.data.success?i(s.data.queries):b.error(s.data.message||"加载历史记录失败")}catch(s){console.error("Error loading queries:",s),b.error("加载失败")}finally{k(!1)}};re.useEffect(()=>{C();const s=ae.subscribe(ne.CODING.TASK_COMPLETE,d=>{console.log("Coding task completed, reloading queries",d),C()});return()=>{s()}},[]);const F=(s,d,h)=>{s.stopPropagation(),y({show:!0,commitHash:d,commitMessage:h})},A=async()=>{try{$(!0),p(null),N(null);const s=await fetch(`/api/commits/${m.commitHash}/revert`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){const h=await s.json();throw new Error(h.detail||"撤销提交失败")}const d=await s.json();N(`成功撤销提交。新的撤销提交: ${d.new_commit_hash.substring(0,7)}`),y(h=>({...h,show:!1})),C(),setTimeout(()=>{N(null)},5e3)}catch(s){p(s instanceof Error?s.message:"撤销提交失败"),console.error("Failed to revert commit:",s)}finally{$(!1)}},T=()=>{y({show:!1,commitHash:"",commitMessage:""}),p(null)};return f?e.jsx(ve,{commitId:f,onClose:()=>E(null)}):e.jsxs("div",{className:"flex flex-col bg-[#111827] overflow-hidden",style:{height:"650px"},children:[e.jsx("div",{className:"flex justify-between items-center p-4 bg-[#1F2937] border-b border-[#374151] sticky top-0 z-10 shadow-md",children:e.jsxs(Q,{children:[e.jsx(M,{icon:l?e.jsx(fe,{}):e.jsx(me,{}),onClick:()=>{B(!l),i([...n].reverse())},children:l?"升序":"降序"}),e.jsx(M,{type:"primary",onClick:C,loading:o,children:"刷新"})]})}),m.show&&e.jsx("div",{className:"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6 border border-gray-700",children:[e.jsx("h3",{className:"text-xl font-semibold text-white mb-4",children:"确认撤销提交"}),e.jsx("p",{className:"text-gray-300 mb-6",children:"您确定要撤销此提交吗?这将创建一个新的提交来撤销更改。"}),e.jsxs("div",{className:"bg-gray-900 p-3 rounded mb-6 border border-gray-700",children:[e.jsx("p",{className:"text-sm text-gray-400 mb-1",children:"提交信息:"}),e.jsx("p",{className:"text-white",children:m.commitMessage}),e.jsxs("p",{className:"text-xs text-gray-500 mt-2",children:["Commit: ",m.commitHash.substring(0,7)]})]}),j&&e.jsx("div",{className:"bg-red-900 bg-opacity-25 text-red-400 p-3 rounded mb-4",children:j}),e.jsxs("div",{className:"flex justify-end space-x-3",children:[e.jsx("button",{className:"px-4 py-2 bg-gray-700 hover:bg-gray-600 text-gray-300 rounded transition-colors",onClick:T,disabled:g,children:"取消"}),e.jsx("button",{className:"px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded transition-colors flex items-center",onClick:A,disabled:g,children:g?e.jsxs(e.Fragment,{children:[e.jsxs("svg",{className:"animate-spin -ml-1 mr-2 h-4 w-4 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[e.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),e.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),"处理中..."]}):e.jsx(e.Fragment,{children:"确认撤销"})})]})]})}),w&&e.jsx("div",{className:"fixed top-4 right-4 bg-green-800 text-green-100 p-4 rounded-lg shadow-lg z-50 animate-fade-in-out",children:e.jsxs("div",{className:"flex items-center",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M5 13l4 4L19 7"})}),e.jsx("span",{children:w})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4",children:[e.jsx(z,{dataSource:n,renderItem:s=>e.jsx(z.Item,{className:"border-b border-[#374151] last:border-b-0",children:e.jsx(le,{className:"w-full bg-[#1F2937] border-[#374151] hover:bg-[#2D3748] transition-colors duration-200",title:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsxs("div",{children:[e.jsx(W,{style:{marginRight:"8px",color:"#9CA3AF"}}),e.jsx(H,{style:{color:"#E5E7EB"},children:`${s.file_number}_chat_action.yml`}),s.timestamp&&e.jsx(H,{style:{marginLeft:"10px",fontSize:"12px",color:"#9CA3AF"},children:s.timestamp})]}),e.jsxs("div",{className:"flex space-x-2",children:[s.urls&&s.urls.length>0&&e.jsx(M,{icon:e.jsx(W,{}),type:"link",style:{color:"#60A5FA"},onClick:()=>{R(s.urls||[]),v(!0)},children:"查看上下文"}),s.response&&!s.is_reverted&&e.jsx(M,{icon:e.jsx(be,{}),type:"link",style:{color:"#F87171"},onClick:d=>F(d,s.response,s.query),children:"撤销"}),e.jsx(M,{icon:e.jsx(ie,{}),type:"link",style:{color:s.response?"#60A5FA":"#9CA3AF"},onClick:()=>D(s.response),disabled:!s.response,children:"查看变更"})]})]}),children:e.jsxs("div",{className:`${s.is_reverted?"border border-red-500 rounded-lg p-2 relative":""}`,children:[s.is_reverted&&e.jsx("div",{className:"absolute -top-2 -right-2 bg-red-500 text-white text-xs px-2 py-0.5 rounded-full",children:"已撤销"}),e.jsx("div",{style:{backgroundColor:"#111827",padding:"12px",borderRadius:"4px",color:"#E5E7EB",border:"1px solid #374151",maxWidth:"100%",fontSize:"14px",lineHeight:"1.6",whiteSpace:"normal",wordBreak:"break-word"},children:s.query})]})})})}),e.jsx(ce,{title:"上下文文件列表",open:c,onCancel:()=>v(!1),width:600,footer:null,className:"dark-theme-modal",styles:{content:{backgroundColor:"#1f2937",padding:"20px"},header:{backgroundColor:"#1f2937",borderBottom:"1px solid #374151",color:"#ffffff"},body:{backgroundColor:"#1f2937",color:"#ffffff"},mask:{backgroundColor:"rgba(0, 0, 0, 0.6)"}},children:e.jsx(z,{dataSource:S,className:"dark-theme-list max-h-96 overflow-y-auto",renderItem:s=>e.jsx(z.Item,{className:"text-gray-200 border-gray-700",children:e.jsx("div",{className:"flex items-center w-full",children:e.jsx(H,{style:{color:"#E5E7EB"},children:s})})})})})]})]})};export{we as default};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as et}from"./
|
1
|
+
import{m as et}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as f}from"./
|
1
|
+
import{m as f}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as l}from"./
|
1
|
+
import{m as l}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as s}from"./
|
1
|
+
import{m as s}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as lt}from"./
|
1
|
+
import{m as lt}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
auto_coder_web/web/index.html
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
<link rel="icon" href="/favicon.ico" />
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7
7
|
<title>Vite React App</title>
|
8
|
-
<script type="module" crossorigin src="/
|
9
|
-
<link rel="stylesheet" crossorigin href="/
|
8
|
+
<script type="module" crossorigin src="/main.js"></script>
|
9
|
+
<link rel="stylesheet" crossorigin href="/main-DxnFm18B.css">
|
10
10
|
</head>
|
11
11
|
<body>
|
12
12
|
<div id="root"></div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{conf as t,language as e}from"./typescript-
|
1
|
+
import{conf as t,language as e}from"./typescript-DZzM_VgT.js";import"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as Et}from"./
|
1
|
+
import{m as Et}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{m as l}from"./
|
1
|
+
import{m as l}from"./main.js";/*!-----------------------------------------------------------------------------
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
4
4
|
* Released under the MIT license
|