This commit is contained in:
Cai
2025-09-21 14:04:05 +08:00
88 changed files with 1743 additions and 448 deletions

View File

@@ -96,49 +96,50 @@ class ChatManager:
def change_language(self, id, language):
self.ase_client.send_text('language', language)
def sample_judge(self, id, bb):
self.function_manager.call_function('sample_judge', {'bb': bb})
def sample_judge(self, id, bb):
with self.app.app_context():
try:
print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"):
self.socketio.emit('terminal', {'data': f"python {bb.get_active_file_reletive_path()}"}, room=id, namespace='/vscode')
self.socketio.emit('system_message', "代码试运行尚在建设,推荐直接通过命令行执行!", room=id, namespace='/agent')
return FunctionResponse("sample_judge", True, "代码试运行命令已发送请于Terminal查看结果")
else:
self.socketio.emit('system_message', "代码试运行尚仅支持python文件", room=id, namespace='/agent')
return FunctionResponse("sample_judge", False, "代码试运行尚仅支持python文件")
except Exception as e:
print(e)
if (str(e) == "no path specified"):
self.socketio.emit("system_message", "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接", room=id, namespace='/agent')
return FunctionResponse("sample_judge", False, "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接")
def judge(self, id, bb):
agent = self.agents[id]
with self.app.app_context():
try:
if (agent.chapter_chain[agent.chapter_chain_now].append_tools is not None and len(agent.chapter_chain[agent.chapter_chain_now].append_tools)):
for tool, tool_kwargs in agent.chapter_chain[agent.chapter_chain_now].append_tools:
if (self.chapter_chain[self.chapter_chain_now].append_tools is not None and len(self.chapter_chain[self.chapter_chain_now].append_tools)):
for tool, tool_kwargs in self.chapter_chain[self.chapter_chain_now].append_tools:
if tool.__name__ == "judge":
print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"):
# self.socketio.emit('terminal', {'data': f"python {bb.get_active_file_reletive_path()}"}, room=id, namespace='/vscode')
self.socketio.emit('system_message', "代码评测中,请稍后", room=id, namespace='/agent')
agent.function_call({'name':'judge','arguments':{'filepath': bb.get_active_file_reletive_path()}})
return self.function_call('judge',{'filepath': bb.get_active_file_reletive_path(),'name':tool_kwargs['name']})
else:
self.socketio.emit('system_message', "代码评测尚仅支持python文件", room=id, namespace='/agent')
return FunctionResponse("judge", False, "代码评测尚仅支持python文件")
else:
with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
return FunctionResponse("judge", False, "本章学习无需评测")
else:
with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
return FunctionResponse("judge", False, "本章学习无需评测")
except Exception as e:
if (str(e) == "no path specified"):
self.socketio.emit("system_message", "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接", room=id, namespace='/agent')
self.socketio.emit("system_message", "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面,并确保插件已连接", room=id, namespace='/agent')
return FunctionResponse("judge", False, "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接")

View File

@@ -1,14 +1,17 @@
import os
from ..models.function import FunctionResponse
def judge(filepath:str, name: str, course_id: str, lesson_name: str, root_path:str):
def judge(filepath:str, name: str, course_id: str, root_path:str):
"""Call this method to judge the student's solution after they have completed the problem.
Args:
filepath (`str`): The path to the file containing the student's solution.
filepath (`str`): The path from root_path to the file containing the student's solution.
name (`str`): The name of the problem.
course_id (`str`): The id of the course.
lesson_name (`str`): The name of the lesson.
root_path (`str`): The root path of the user's workspace project.
Returns:
@@ -17,6 +20,7 @@ def judge(filepath:str, name: str, course_id: str, lesson_name: str, root_path:s
# 从books/code_tests/name/中获取所有.in文件
directory = 'books/code_tests/'+course_id+'/'+name
print(f"Directory: {directory}")
# 如果目录不存在,报错
if not os.path.exists(directory):
return FunctionResponse("judge", False, f"The name {name} is not found.")
@@ -30,6 +34,7 @@ def judge(filepath:str, name: str, course_id: str, lesson_name: str, root_path:s
erroroutput = ""
exceptoutput=""
for file in in_files:
print(f"Testing {file}")
file_path = os.path.join(save_dir, f"_{name}.out")
if os.path.exists(file_path):
os.remove(file_path)

View File

@@ -33,8 +33,8 @@ def realtime_response(config: dict, realtime_action: dict) -> None:
elif rtype == "activeFile":
file_path = realtime_action.get("filePath")
assert isinstance(file_path, str)
with sudo_open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f
with open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f.read()
bb.active_file_path = file_path
elif rtype == "paste":
@@ -43,15 +43,15 @@ def realtime_response(config: dict, realtime_action: dict) -> None:
bb.pasted_file_path = file_path
bb.pasted_content = realtime_action.get("content")
bb.active_file_path = file_path
with sudo_open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f
with open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f.read()
elif rtype == "fileEdit":
file_path = realtime_action.get("filePath")
assert isinstance(file_path, str)
bb.active_file_path = file_path
with sudo_open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f
with open(file_path, "r", encoding="utf-8") as f:
bb.active_file_content = f.read()
chatmanager.upload_bb()

View File

@@ -75,15 +75,16 @@ class AgentNamespace(Namespace):
entry=self,
init_data={'room': user_uuid}
)
fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
chatmanager = user_uuid2chatmanager[user_uuid]
chatmanager.init(user_uuid, user_uuid2ase_client[user_uuid], fmd, fmdp, fsp, max_iter=5, app=current_app, socketio=self)
chatmanager.function_manager.add_function(judge, {'course_id': course_id, 'lesson_name': lesson_name, 'root_path': f'../../study/{user_id}/{course_id}/{chapter_name}/{lesson_name}'})
# 注册函数,以确保一些初始参数
chatmanager.function_manager.add_function(judge, {'course_id': course_id, 'root_path': f'/home/{user_id}/{course_id}/{chapter_name}/{lesson_name}'})
chatmanager.function_manager.add_function(next_chapter, {'user_uuid': user_uuid})
join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room
backboard_manager.add_backboard(user_uuid, user_id, course_id, lesson_name, root_path=f'../../study/{user_id}/{course_id}/{chapter_name}/{lesson_name}')
backboard_manager.add_backboard(user_uuid, user_id, course_id, lesson_name, root_path=f'/home/{user_id}/{course_id}/{chapter_name}/{lesson_name}')
chatmanager.bb = backboard_manager.get_backboard(user_uuid)
chatmanager.focus_chapter(0)
@@ -116,6 +117,7 @@ class AgentNamespace(Namespace):
d['data'] = res.to_dict()
print("function_call_res", d['data'])
emit(d['route'], d, room=uuid, namespace='/agent')
user_uuid2ase_client[uuid].send_text(d['route'], data['data'])
def receive_ase_dialog(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
@@ -130,16 +132,17 @@ class AgentNamespace(Namespace):
print("receive_ase_next_chapter", data)
namespace_entry.emit('request_function',data, room=init_data['room'], namespace='/agent') # data 是一个列表 /dict也支持
def on_initiative(self,data):
def on_initiative(self,data): # 主动call
print("User active function call")
ex = current_app.extensions
agent_manager = ex["agent_manager"]
backboard_manager = ex["backboard_manager"]
uuid = session.get('user_uuid')
manager = ex["user_uuid2chatmanager"][uuid]
backboard_manager = ex["backboard_manager"]
if data['name'] == 'sample_judge':
agent_manager.sample_judge(uuid, backboard_manager.get_backboard(uuid))
manager.sample_judge(uuid, backboard_manager.get_backboard(uuid))
if data['name'] == 'judge':
agent_manager.judge(uuid, backboard_manager.get_backboard(uuid))
res = manager.judge(uuid, backboard_manager.get_backboard(uuid))
emit('message', res.message, room=uuid, namespace='/agent')

View File

@@ -114,7 +114,7 @@
/* 主容器,使用 grid 布局 */
#maxcontainer {
display: grid;
grid-template-columns: 1fr 5px 3fr 5px 1fr; /* 默认宽度比例 */
grid-template-columns: 2fr 5px 3fr 5px 1fr; /* 默认宽度比例 */
height: 100%;
}

View File

@@ -725,6 +725,10 @@ function sanitizeHeadingsBeyondFirst(text = "") {
// PUT 请求保存更新
try {
console.log("saveToOrigin", CURRENT.links.lesson, CURRENT.links.prompt, CURRENT.links.score);
console.log("updatedLesson", updatedLesson);
console.log("updatedPrompt", updatedPrompt);
console.log("updatedScore", updatedScore);
const result = await saveToOrigin({
lesson: { cdn_link: CURRENT.links.lesson, content: updatedLesson },
prompt: { cdn_link: CURRENT.links.prompt, content: updatedPrompt },
@@ -771,6 +775,11 @@ function sanitizeHeadingsBeyondFirst(text = "") {
// 替换该步骤内容
const lines = [...parsed.lines];
console.log("lines length", lines.length);
console.log("startLine", startLine);
console.log("endLine", endLine);
console.log("endLine - startLine + 1", endLine - startLine + 1);
console.log("newContent", newContent);
lines.splice(startLine, endLine - startLine + 1, newContent); // 用新内容替换
return lines.join('\n'); // 返回更新后的完整内容

View File

@@ -110,8 +110,8 @@
const dragbar = document.getElementById('dragbar');
const dragbar2 = document.getElementById('dragbar2');
const container = document.getElementById('maxcontainer');
let leftWidth = 300; // 设置左侧栏的初始宽度
let rightWidth = 300; // 设置右侧栏的初始宽度
let leftWidth = 500;
let rightWidth = 400;
let isDraggingLeft = false;
let isDraggingRight = false;