auto-coder-web 0.1.94__py3-none-any.whl → 0.1.96__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/agentic_message_parser/__init__.py +10 -0
- auto_coder_web/agentic_message_parser/message_parser.py +79 -0
- auto_coder_web/agentic_message_parser/tool_parsers.py +70 -0
- auto_coder_web/common_router/file_group_router.py +58 -8
- auto_coder_web/routers/auto_router.py +23 -15
- auto_coder_web/version.py +1 -1
- auto_coder_web/web/assets/HistoryPanel-DAeswjWO.js +2 -0
- auto_coder_web/web/assets/{main-D8cC7hK1.css → main-BJLO9M6L.css} +1 -1
- auto_coder_web/web/assets/main.js +352 -352
- auto_coder_web/web/index.html +1 -1
- {auto_coder_web-0.1.94.dist-info → auto_coder_web-0.1.96.dist-info}/METADATA +2 -2
- {auto_coder_web-0.1.94.dist-info → auto_coder_web-0.1.96.dist-info}/RECORD +15 -12
- auto_coder_web/web/assets/HistoryPanel-B59ay4X7.js +0 -1
- {auto_coder_web-0.1.94.dist-info → auto_coder_web-0.1.96.dist-info}/WHEEL +0 -0
- {auto_coder_web-0.1.94.dist-info → auto_coder_web-0.1.96.dist-info}/entry_points.txt +0 -0
- {auto_coder_web-0.1.94.dist-info → auto_coder_web-0.1.96.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
"""
|
2
|
+
Message parser module for processing agentic messages.
|
3
|
+
This module provides functionality to parse and process messages from different tools.
|
4
|
+
"""
|
5
|
+
from .message_parser import parse_message, register_parser, parse_messages
|
6
|
+
|
7
|
+
# Import tool parsers to register them
|
8
|
+
from . import tool_parsers
|
9
|
+
|
10
|
+
__all__ = ['parse_message', 'register_parser', 'parse_messages']
|
@@ -0,0 +1,79 @@
|
|
1
|
+
"""
|
2
|
+
Message parser for processing agentic messages.
|
3
|
+
|
4
|
+
This module provides a registry-based approach to parse and process messages
|
5
|
+
from different tools. New parsers can be easily registered to handle different
|
6
|
+
tool types.
|
7
|
+
"""
|
8
|
+
import json
|
9
|
+
from typing import Dict, Any, Callable, Optional, List, TypeVar, cast
|
10
|
+
|
11
|
+
# Define a type for parser functions
|
12
|
+
T = TypeVar('T')
|
13
|
+
ParserFunc = Callable[[Dict[str, Any], Dict[str, Any]], Optional[Dict[str, Any]]]
|
14
|
+
|
15
|
+
# Registry to store message parsers
|
16
|
+
_PARSERS: Dict[str, ParserFunc] = {}
|
17
|
+
|
18
|
+
def register_parser(tool_name: str):
|
19
|
+
"""
|
20
|
+
Decorator to register a parser function for a specific tool.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
tool_name: The name of the tool this parser handles
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
Decorator function
|
27
|
+
"""
|
28
|
+
def decorator(func: ParserFunc) -> ParserFunc:
|
29
|
+
_PARSERS[tool_name] = func
|
30
|
+
return func
|
31
|
+
return decorator
|
32
|
+
|
33
|
+
def parse_message(message: Dict[str, Any]) -> Dict[str, Any]:
|
34
|
+
"""
|
35
|
+
Parse a message and apply the appropriate parser based on the tool_name.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
message: The message to parse
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
The processed message
|
42
|
+
"""
|
43
|
+
processed_message = message.copy()
|
44
|
+
|
45
|
+
try:
|
46
|
+
# Try to parse the message content as JSON
|
47
|
+
content = message.get("content", "")
|
48
|
+
if not isinstance(content, str):
|
49
|
+
return processed_message
|
50
|
+
|
51
|
+
content_obj = json.loads(content)
|
52
|
+
|
53
|
+
# Try all registered parsers
|
54
|
+
for tool_name, parser in _PARSERS.items():
|
55
|
+
# Let each parser decide if it can handle this message
|
56
|
+
result = parser(content_obj, message)
|
57
|
+
if result is not None:
|
58
|
+
return result
|
59
|
+
|
60
|
+
except (json.JSONDecodeError, TypeError, AttributeError):
|
61
|
+
# If parsing fails, keep the original message unchanged
|
62
|
+
pass
|
63
|
+
|
64
|
+
return processed_message
|
65
|
+
|
66
|
+
def parse_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
67
|
+
"""
|
68
|
+
Parse a list of messages, applying the appropriate parser to each.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
messages: List of messages to parse
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
List of processed messages
|
75
|
+
"""
|
76
|
+
return [parse_message(message) for message in messages]
|
77
|
+
|
78
|
+
# Tool-specific parsers are defined in tool_parsers.py
|
79
|
+
# and automatically registered when that module is imported
|
@@ -0,0 +1,70 @@
|
|
1
|
+
"""
|
2
|
+
Tool-specific parsers for processing messages from different tools.
|
3
|
+
|
4
|
+
This module contains parser implementations for various tools.
|
5
|
+
New parsers can be added here and will be automatically registered.
|
6
|
+
"""
|
7
|
+
import json
|
8
|
+
from typing import Dict, Any, Optional
|
9
|
+
from .message_parser import register_parser
|
10
|
+
|
11
|
+
@register_parser("ReadFileTool")
|
12
|
+
def read_file_tool_parser(content_obj: Dict[str, Any], message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
13
|
+
"""
|
14
|
+
Parser for ReadFileTool messages.
|
15
|
+
Truncates file content to 200 characters if it's too long.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
content_obj: The parsed content object
|
19
|
+
message: The original message
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
The processed message if this parser can handle it, None otherwise
|
23
|
+
"""
|
24
|
+
# Validate if this is a ReadFileTool message
|
25
|
+
if not (isinstance(content_obj, dict) and
|
26
|
+
content_obj.get("tool_name") == "ReadFileTool" and
|
27
|
+
"success" in content_obj and
|
28
|
+
"message" in content_obj and
|
29
|
+
"content" in content_obj):
|
30
|
+
return None
|
31
|
+
|
32
|
+
# Process the content
|
33
|
+
processed_message = message.copy()
|
34
|
+
if isinstance(content_obj["content"], str) and len(content_obj["content"]) > 200:
|
35
|
+
content_obj["content"] = content_obj["content"][:200] + "..."
|
36
|
+
processed_message["content"] = json.dumps(content_obj)
|
37
|
+
|
38
|
+
return processed_message
|
39
|
+
|
40
|
+
# Example of how to add more parsers in the future:
|
41
|
+
#
|
42
|
+
# @register_parser("CodeSearchTool")
|
43
|
+
# def code_search_tool_parser(content_obj: Dict[str, Any], message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
44
|
+
# """
|
45
|
+
# Parser for CodeSearchTool messages.
|
46
|
+
# Truncates search results if they're too long.
|
47
|
+
#
|
48
|
+
# Args:
|
49
|
+
# content_obj: The parsed content object
|
50
|
+
# message: The original message
|
51
|
+
#
|
52
|
+
# Returns:
|
53
|
+
# The processed message if this parser can handle it, None otherwise
|
54
|
+
# """
|
55
|
+
# # Validate if this is a CodeSearchTool message
|
56
|
+
# if not (isinstance(content_obj, dict) and
|
57
|
+
# content_obj.get("tool_name") == "CodeSearchTool" and
|
58
|
+
# "success" in content_obj and
|
59
|
+
# "message" in content_obj and
|
60
|
+
# "content" in content_obj):
|
61
|
+
# return None
|
62
|
+
#
|
63
|
+
# # Process the content
|
64
|
+
# processed_message = message.copy()
|
65
|
+
# if isinstance(content_obj["content"], list) and len(content_obj["content"]) > 5:
|
66
|
+
# content_obj["content"] = content_obj["content"][:5]
|
67
|
+
# content_obj["message"] = f"Showing first 5 of {len(content_obj['content'])} results"
|
68
|
+
# processed_message["content"] = json.dumps(content_obj)
|
69
|
+
#
|
70
|
+
# return processed_message
|
@@ -8,6 +8,11 @@ import os
|
|
8
8
|
from autocoder.rag.token_counter import count_tokens
|
9
9
|
import aiofiles
|
10
10
|
from loguru import logger
|
11
|
+
from autocoder.rag.loaders import (
|
12
|
+
extract_text_from_pdf,
|
13
|
+
extract_text_from_docx,
|
14
|
+
extract_text_from_ppt
|
15
|
+
)
|
11
16
|
|
12
17
|
router = APIRouter()
|
13
18
|
|
@@ -147,6 +152,53 @@ async def auto_create_groups(
|
|
147
152
|
raise HTTPException(status_code=500, detail=str(e))
|
148
153
|
|
149
154
|
|
155
|
+
async def _read_file(file_path_to_read: str) -> str:
|
156
|
+
"""使用线程模拟异步读取文件内容
|
157
|
+
|
158
|
+
Args:
|
159
|
+
file_path_to_read: 要读取的文件路径
|
160
|
+
|
161
|
+
Returns:
|
162
|
+
str: 文件内容
|
163
|
+
"""
|
164
|
+
ext = os.path.splitext(file_path_to_read)[1].lower()
|
165
|
+
|
166
|
+
# 定义各种文件类型的读取函数
|
167
|
+
def read_pdf():
|
168
|
+
logger.info(f"Extracting text from PDF: {file_path_to_read}")
|
169
|
+
return extract_text_from_pdf(file_path_to_read)
|
170
|
+
|
171
|
+
def read_docx():
|
172
|
+
logger.info(f"Extracting text from DOCX: {file_path_to_read}")
|
173
|
+
return extract_text_from_docx(file_path_to_read)
|
174
|
+
|
175
|
+
def read_ppt():
|
176
|
+
logger.info(f"Extracting text from PPT/PPTX: {file_path_to_read}")
|
177
|
+
slide_texts = []
|
178
|
+
for slide_identifier, slide_text_content in extract_text_from_ppt(file_path_to_read):
|
179
|
+
slide_texts.append(f"--- Slide {slide_identifier} ---\n{slide_text_content}")
|
180
|
+
return "\n\n".join(slide_texts) if slide_texts else ""
|
181
|
+
|
182
|
+
def read_text():
|
183
|
+
logger.info(f"Reading plain text file: {file_path_to_read}")
|
184
|
+
with open(file_path_to_read, 'r', encoding='utf-8', errors='replace') as f:
|
185
|
+
return f.read()
|
186
|
+
|
187
|
+
# 根据文件类型选择相应的读取函数
|
188
|
+
if ext == '.pdf':
|
189
|
+
read_func = read_pdf
|
190
|
+
elif ext == '.docx':
|
191
|
+
read_func = read_docx
|
192
|
+
elif ext in ('.pptx', '.ppt'):
|
193
|
+
read_func = read_ppt
|
194
|
+
else:
|
195
|
+
read_func = read_text
|
196
|
+
|
197
|
+
# 使用线程执行耗时的文件读取操作
|
198
|
+
content = await asyncio.to_thread(read_func)
|
199
|
+
return content
|
200
|
+
|
201
|
+
|
150
202
|
async def count_tokens_from_file(file_path: str) -> int:
|
151
203
|
"""异步计算文件的token数
|
152
204
|
|
@@ -156,19 +208,17 @@ async def count_tokens_from_file(file_path: str) -> int:
|
|
156
208
|
Returns:
|
157
209
|
int: token数量,出错时返回0
|
158
210
|
"""
|
159
|
-
try:
|
160
|
-
if not os.path.exists(file_path):
|
161
|
-
logger.warning(f"文件不存在: {file_path}")
|
162
|
-
return 0
|
163
|
-
|
211
|
+
try:
|
164
212
|
logger.info(f"计算文件token: {file_path}")
|
165
|
-
|
166
|
-
|
213
|
+
content = await _read_file(file_path)
|
214
|
+
|
215
|
+
if content is None:
|
216
|
+
return 0
|
167
217
|
|
168
218
|
file_tokens = count_tokens(content)
|
169
219
|
return file_tokens if file_tokens > 0 else 0
|
170
220
|
except Exception as e:
|
171
|
-
logger.error(f"
|
221
|
+
logger.error(f"计算文件token出错: {file_path}, 错误: {str(e)}")
|
172
222
|
return 0
|
173
223
|
|
174
224
|
|
@@ -69,22 +69,30 @@ def ensure_task_dir(project_path: str) -> str:
|
|
69
69
|
|
70
70
|
@byzerllm.prompt()
|
71
71
|
def coding_prompt(messages: List[Dict[str, Any]], query: str):
|
72
|
-
'''
|
73
|
-
|
74
|
-
<messages>
|
72
|
+
'''
|
73
|
+
【历史对话】按时间顺序排列,从旧到新:
|
75
74
|
{% for message in messages %}
|
76
75
|
<message>
|
77
|
-
|
78
|
-
<content>
|
76
|
+
{% if message.type == "USER" or message.type == "USER_RESPONSE" or message.metadata.path == "/agent/edit/tool/result" %}【用户】{% else %}【助手】{% endif %}
|
77
|
+
<content>
|
78
|
+
{{ message.content }}
|
79
|
+
</content>
|
79
80
|
</message>
|
80
81
|
{% endfor %}
|
81
|
-
</messages>
|
82
82
|
|
83
|
-
|
84
|
-
<
|
85
|
-
{{ query }}
|
86
|
-
</
|
83
|
+
【当前问题】用户的最新需求如下:
|
84
|
+
<current_query>
|
85
|
+
{{ query }}
|
86
|
+
</current_query>
|
87
87
|
'''
|
88
|
+
# 使用消息解析器处理消息
|
89
|
+
from auto_coder_web.agentic_message_parser import parse_messages
|
90
|
+
processed_messages = parse_messages(messages)
|
91
|
+
|
92
|
+
return {
|
93
|
+
"messages": processed_messages,
|
94
|
+
"query": query
|
95
|
+
}
|
88
96
|
|
89
97
|
|
90
98
|
|
@@ -148,13 +156,13 @@ async def auto_command(request: AutoCommandRequest, project_path: str = Depends(
|
|
148
156
|
|
149
157
|
# 调用auto_command_wrapper方法
|
150
158
|
logger.info(f"Executing auto command {file_id} with prompt: {prompt_text}")
|
151
|
-
|
159
|
+
wrapper.auto_command_wrapper(prompt_text, {
|
152
160
|
"event_file_id": file_id
|
153
161
|
})
|
154
|
-
get_event_manager(event_file).write_completion(
|
155
|
-
|
156
|
-
|
157
|
-
)
|
162
|
+
# get_event_manager(event_file).write_completion(
|
163
|
+
# EventContentCreator.create_completion(
|
164
|
+
# "200", "completed", result).to_dict()
|
165
|
+
# )
|
158
166
|
logger.info(f"Event file id: {file_id} completed successfully")
|
159
167
|
except Exception as e:
|
160
168
|
logger.error(f"Error executing auto command {file_id}: {str(e)}")
|
auto_coder_web/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.96"
|
@@ -0,0 +1,2 @@
|
|
1
|
+
import{r,I as G,_ as Y,j as e,S as se,T as J,R as re,a as P,h as ne,v as ae,b as U,s as u,d as K,l as te,c as le,e as W,E as q,B as g,g as a,L as T,C as ie,f as Z,i as oe,k as ce,m as de,n as he,M as fe}from"./main.js";var ue={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M296 250c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H296zm184 144H296c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zm-48 458H208V148h560v320c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V108c0-17.7-14.3-32-32-32H168c-17.7 0-32 14.3-32 32v784c0 17.7 14.3 32 32 32h264c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm440-88H728v-36.6c46.3-13.8 80-56.6 80-107.4 0-61.9-50.1-112-112-112s-112 50.1-112 112c0 50.7 33.7 93.6 80 107.4V764H520c-8.8 0-16 7.2-16 16v152c0 8.8 7.2 16 16 16h352c8.8 0 16-7.2 16-16V780c0-8.8-7.2-16-16-16zM646 620c0-27.6 22.4-50 50-50s50 22.4 50 50-22.4 50-50 50-50-22.4-50-50zm180 266H566v-60h260v60z"}}]},name:"audit",theme:"outlined"},xe=function(d,c){return r.createElement(G,Y({},d,{ref:c,icon:ue}))},me=r.forwardRef(xe),ge={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"},pe=function(d,c){return r.createElement(G,Y({},d,{ref:c,icon:ge}))},ve=r.forwardRef(pe),be={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"},ye=function(d,c){return r.createElement(G,Y({},d,{ref:c,icon:be}))},je=r.forwardRef(ye);te.config({paths:{vs:"/monaco-editor/min/vs"},"vs/nls":{availableLanguages:{"*":"zh-cn"}}});const{TabPane:ee}=J,we=({commitId:o,onClose:d})=>{const[c,A]=r.useState({diff:""}),[h,w]=r.useState(null),[f,y]=r.useState(null),[C,E]=r.useState(!1),[x,F]=r.useState("split"),[i,j]=r.useState(null),[L,$]=r.useState(!1),[z,X]=r.useState("1"),m=r.useRef(null),p=r.useRef(null),v=r.useRef(null),N=r.useRef(null),_=async()=>{if(o){$(!0);try{const t=encodeURIComponent(o),s=await U.get(`/api/history/commit-diff/${t}`);s.data.success?A({diff:s.data.diff,file_changes:s.data.file_changes}):u.error(s.data.message||"获取diff失败")}catch(t){console.error("Error fetching diff:",t),u.error("获取diff失败")}finally{$(!1)}}},k=async t=>{if(o)try{E(!0),y(null),m.current=null,p.current=null,v.current=null;const s=encodeURIComponent(o),n=await U.get(`/api/history/file-diff/${s}?file_path=${encodeURIComponent(t)}`);n.data.success?y(n.data.file_diff):u.error(n.data.message||"获取文件差异失败")}catch(s){console.error("Error fetching file diff:",s),u.error("获取文件差异失败")}finally{E(!1)}},B=t=>{h===t?(w(null),y(null),m.current=null,p.current=null,v.current=null,j(null)):(w(t),k(t),j(null))},S=r.useCallback(t=>{m.current=t},[]),H=r.useCallback(t=>{p.current=t},[]),D=r.useCallback(t=>{v.current=t},[]),b=t=>{var l;const s=(l=t.split(".").pop())==null?void 0:l.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"}[s||""]||"plaintext"},R=({viewType:t})=>{const s=i===t;return e.jsx("button",{className:"ml-2 text-gray-400 hover:text-white transition-colors",onClick:n=>{n.stopPropagation(),j(s?null:t)},title:s?"恢复正常视图":"最大化视图",children:s?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"})})})},I=()=>{if(!h||!f)return null;const t=b(h),s=`diff-${o}-${h}-${x}`,n=`before-${o}-${h}`,l=`after-${o}-${h}`,M={readOnly:!0,scrollBeyondLastLine:!1,minimap:{enabled:!1},lineNumbers:"on",wordWrap:"on",automaticLayout:!0,scrollbar:{vertical:"visible",horizontal:"visible",verticalScrollbarSize:14,horizontalScrollbarSize:14}};return x==="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(R,{viewType:"diff"})]}),e.jsx(K,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:"diff",value:f.diff_content||"",theme:"vs-dark",onMount:D,options:M,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},s)]}):e.jsxs("div",{ref:N,className:"grid grid-cols-2 gap-2",style:{height:"500px",width:"100%"},children:[(i===null||i==="before")&&e.jsxs("div",{className:`bg-gray-900 rounded-lg border border-gray-700 ${i==="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:["修改前 (",f.file_status==="added"?"新文件":h,")"]}),e.jsx(R,{viewType:"before"})]}),e.jsx(K,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:t,value:f.before_content||"",theme:"vs-dark",onMount:S,options:M,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},n)]}),(i===null||i==="after")&&e.jsxs("div",{className:`bg-gray-900 rounded-lg border border-gray-700 ${i==="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:["修改后 (",f.file_status==="deleted"?"文件已删除":h,")"]}),e.jsx(R,{viewType:"after"})]}),e.jsx(K,{height:"calc(100% - 26px)",width:"100%",defaultLanguage:t,value:f.after_content||"",theme:"vs-dark",onMount:H,options:M,loading:e.jsx("div",{className:"flex items-center justify-center h-full text-white",children:"加载中..."})},l)]})]})};r.useEffect(()=>{o&&_()},[o]);const V={background:"#1F2937",borderBottom:"1px solid #374151",margin:0,padding:"0 16px"},O=(t,s)=>e.jsx(s,{...t,style:V,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(se,{children:d&&e.jsx("button",{className:"px-3 py-1.5 bg-gray-700 hover:bg-gray-600 text-white rounded text-sm",onClick:d,children:"关闭"})})]}),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs(J,{activeKey:z,onChange:X,type:"card",className:"diff-viewer-tabs",renderTabBar:O,style:{background:"#111827"},children:[e.jsx(ee,{tab:e.jsx("div",{className:`py-2 px-4 ${z==="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:L?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"})}):c.file_changes&&c.file_changes.length>0?c.file_changes.map((t,s)=>e.jsx("div",{className:`text-sm py-2 px-3 rounded cursor-pointer ${h===t.path?"bg-gray-700 border-l-2 border-indigo-500":"hover:bg-gray-750 bg-gray-800"}`,onClick:()=>B(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(re,{className:"ml-2 text-gray-400"})]})},s)):e.jsx("div",{className:"text-center text-white py-8",children:e.jsx("p",{children:"没有文件变更信息"})})}),C&&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"})}),h&&f&&!C&&e.jsx("div",{className:"flex justify-end mb-3",children:e.jsxs(P.Group,{value:x,onChange:t=>F(t.target.value),buttonStyle:"solid",children:[e.jsx(P.Button,{value:"split",style:{color:x==="split"?"#fff":"#1f2937"},children:"分割视图"}),e.jsx(P.Button,{value:"unified",style:{color:x==="unified"?"#fff":"#1f2937"},children:"统一视图"})]})}),h&&f&&!C&&I()]})},"1"),e.jsx(ee,{tab:e.jsx("div",{className:`py-2 px-4 ${z==="2"?"text-white font-medium":"text-gray-400"}`,children:"原始差异"}),children:e.jsx("div",{className:"p-4",children:L?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(ne,{language:"diff",style:ae,customStyle:{padding:"12px",borderRadius:"4px",overflow:"auto",maxHeight:"600px"},children:c.diff||""})})},"2")]})})]})};te.config({paths:{vs:"/monaco-editor/min/vs"},"vs/nls":{availableLanguages:{"*":"zh-cn"}}});const{Text:Q}=oe,{TabPane:Ne}=J,ke=()=>{const[o,d]=r.useState([]),[c,A]=r.useState(!1),[h,w]=r.useState(!1),[f,y]=r.useState(!1),[C,E]=r.useState([]),[x,F]=r.useState(null),[i,j]=r.useState(null),[L,$]=r.useState([]),[z,X]=r.useState(!1),[m,p]=r.useState({show:!1,commitHash:"",commitMessage:""}),[v,N]=r.useState(!1),[_,k]=r.useState(null),[B,S]=r.useState(null),H=s=>{if(!s){u.info(a("noAssociatedCodeChanges"));return}F(s)},D=()=>{i&&(j(null),d(L))},b=async()=>{w(!0);try{const s=await U.get("/api/history/validate-and-load");if(s.data.success){const n=s.data.queries;if($(n),i){const l=n.filter(M=>M.response===i);d(l)}else d(n)}else u.error(s.data.message||a("loadHistoryFailed"))}catch(s){console.error("Error loading queries:",s),u.error(a("loadFailed"))}finally{w(!1)}};le.useEffect(()=>{b();const s=W.subscribe(q.CODING.TASK_COMPLETE,l=>{console.log("Coding task completed, reloading queries",l),b()}),n=W.subscribe(q.HISTORY.FILTER_BY_COMMIT,l=>{console.log("Filtering history by commit hash:",l.commitHash),j(l.commitHash),b()});return()=>{s(),n()}},[i]);const R=(s,n,l)=>{s.stopPropagation(),p({show:!0,commitHash:n,commitMessage:l})},I=async()=>{try{N(!0),k(null),S(null);const s=await fetch(`/api/commits/${m.commitHash}/revert`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){const l=await s.json();throw new Error(l.detail||a("revertCommitFailed"))}const n=await s.json();S(`${a("revertCommitSuccessPrefix")}: ${n.new_commit_hash.substring(0,7)}`),p(l=>({...l,show:!1})),b(),setTimeout(()=>{S(null)},5e3)}catch(s){k(s instanceof Error?s.message:"撤销提交失败"),console.error("Failed to revert commit:",s)}finally{N(!1)}},V=()=>{p({show:!1,commitHash:"",commitMessage:""}),k(null)},O=(s,n)=>{s.stopPropagation(),W.publish(q.CHAT.NEW_MESSAGE,{action:"review",commit_id:n,mode:"chat"}),u.success(a("reviewCommandSent"))},t=(s,n)=>{s.stopPropagation(),navigator.clipboard.writeText(n).then(()=>{u.success(a("commitCopied"))}).catch(l=>{console.error("复制失败:",l),u.error(a("copyFailed"))})};return x?e.jsx(we,{commitId:x,onClose:()=>F(null)}):e.jsxs("div",{className:"flex flex-col bg-[#111827] overflow-hidden",style:{height:"650px"},children:[e.jsxs("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(se,{children:[e.jsx(g,{icon:c?e.jsx(ve,{}):e.jsx(je,{}),onClick:()=>{A(!c),d([...o].reverse())},children:c?a("ascending"):a("descending")}),e.jsx(g,{type:"primary",onClick:b,loading:h,children:a("refresh")}),i&&e.jsx(g,{type:"default",onClick:D,danger:!0,children:a("clearFilter")||"清除过滤"})]}),i&&e.jsxs("div",{className:"px-2 py-1 bg-blue-900/30 text-blue-300 rounded-md text-xs flex items-center",children:[e.jsxs("span",{children:[a("filteringByCommit")||"按提交过滤",":"]}),e.jsx("code",{className:"ml-1 font-mono",children:i.substring(0,8)})]})]}),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:a("confirmRevertTitle")}),e.jsx("p",{className:"text-gray-300 mb-6",children:a("confirmRevertMessage")}),e.jsxs("div",{className:"bg-gray-900 p-3 rounded mb-6 border border-gray-700",children:[e.jsxs("p",{className:"text-sm text-gray-400 mb-1",children:[a("commitInfoLabel"),":"]}),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)]})]}),_&&e.jsx("div",{className:"bg-red-900 bg-opacity-25 text-red-400 p-3 rounded mb-4",children:_}),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:V,disabled:v,children:a("cancel")}),e.jsx("button",{className:"px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded transition-colors flex items-center",onClick:I,disabled:v,children:v?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"})]}),a("processing"),"..."]}):e.jsx(e.Fragment,{children:a("confirmRevertButton")})})]})]})}),B&&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:B})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4",children:[i&&o.length===0&&e.jsx("div",{className:"text-center p-8 text-gray-400",children:e.jsx("p",{children:a("noFilteredResults")||"没有匹配的历史记录"})}),e.jsx(T,{dataSource:o,renderItem:s=>e.jsx(T.Item,{className:"border-b border-[#374151] last:border-b-0",children:e.jsx(ie,{className:`w-full bg-[#1F2937] border-[#374151] hover:bg-[#2D3748] transition-colors duration-200
|
2
|
+
${i&&s.response===i?"border-blue-500 border-2":""}`,title:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsxs("div",{children:[e.jsx(Z,{style:{marginRight:"8px",color:"#9CA3AF"}}),e.jsx(Q,{style:{color:"#E5E7EB"},children:`${s.file_number}_chat_action.yml`}),s.timestamp&&e.jsx(Q,{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(g,{icon:e.jsx(Z,{}),type:"link",style:{color:"#60A5FA"},onClick:()=>{E(s.urls||[]),y(!0)},children:a("viewContext")}),s.response&&!s.is_reverted&&e.jsxs(e.Fragment,{children:[e.jsx(g,{icon:e.jsx(ce,{}),type:"link",style:{color:"#F87171"},onClick:n=>R(n,s.response,s.query),children:a("revert")}),e.jsx(g,{icon:e.jsx(me,{}),type:"link",style:{color:"#10B981"},onClick:n=>O(n,s.response),children:a("reviewChanges")}),e.jsx(g,{icon:e.jsx(de,{}),type:"link",style:{color:"#6366F1"},onClick:n=>t(n,s.response),children:a("copyCommit")})]}),e.jsx(g,{icon:e.jsx(he,{}),type:"link",style:{color:s.response?"#60A5FA":"#9CA3AF"},onClick:()=>H(s.response),disabled:!s.response,children:a("viewChanges")})]})]}),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:a("reverted")}),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(fe,{title:a("contextFileListTitle"),open:f,onCancel:()=>y(!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(T,{dataSource:C,className:"dark-theme-list max-h-96 overflow-y-auto",renderItem:s=>e.jsx(T.Item,{className:"text-gray-200 border-gray-700",children:e.jsx("div",{className:"flex items-center w-full",children:e.jsx(Q,{style:{color:"#E5E7EB"},children:s})})})})})]})]})};export{ke as default};
|