fix many feather

This commit is contained in:
Cai
2025-09-21 05:50:19 +00:00
parent b1f832a2fb
commit 25223ac6fe
89 changed files with 1746 additions and 454 deletions

2111
Html/.log

File diff suppressed because it is too large Load Diff

View File

@@ -96,49 +96,50 @@ class ChatManager:
def change_language(self, id, language): def change_language(self, id, language):
self.ase_client.send_text('language', language) self.ase_client.send_text('language', language)
def sample_judge(self, id, bb): def sample_judge(self, id, bb):
self.function_manager.call_function('sample_judge', {'bb': bb})
with self.app.app_context(): with self.app.app_context():
try: try:
print(bb.get_active_file_reletive_path()) print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified" assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"): 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('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: else:
self.socketio.emit('system_message', "代码试运行尚仅支持python文件", room=id, namespace='/agent') self.socketio.emit('system_message', "代码试运行尚仅支持python文件", room=id, namespace='/agent')
return FunctionResponse("sample_judge", False, "代码试运行尚仅支持python文件")
except Exception as e: except Exception as e:
print(e) print(e)
if (str(e) == "no path specified"): 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("sample_judge", False, "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接")
def judge(self, id, bb): def judge(self, id, bb):
agent = self.agents[id]
with self.app.app_context(): with self.app.app_context():
try: 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)): 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 agent.chapter_chain[agent.chapter_chain_now].append_tools: for tool, tool_kwargs in self.chapter_chain[self.chapter_chain_now].append_tools:
if tool.__name__ == "judge": if tool.__name__ == "judge":
print(bb.get_active_file_reletive_path()) print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified" assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"): 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('terminal', {'data': f"python {bb.get_active_file_reletive_path()}"}, room=id, namespace='/vscode')
self.socketio.emit('system_message', "代码评测中,请稍后", room=id, namespace='/agent') 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: else:
self.socketio.emit('system_message', "代码评测尚仅支持python文件", room=id, namespace='/agent') self.socketio.emit('system_message', "代码评测尚仅支持python文件", room=id, namespace='/agent')
return FunctionResponse("judge", False, "代码评测尚仅支持python文件")
else: else:
with self.app.app_context(): with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent') self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
return FunctionResponse("judge", False, "本章学习无需评测")
else: else:
with self.app.app_context(): with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent') self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
return FunctionResponse("judge", False, "本章学习无需评测")
except Exception as e: except Exception as e:
if (str(e) == "no path specified"): 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 import os
from ..models.function import FunctionResponse 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. """Call this method to judge the student's solution after they have completed the problem.
Args: 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. name (`str`): The name of the problem.
course_id (`str`): The id of the course. 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. root_path (`str`): The root path of the user's workspace project.
Returns: 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文件 # 从books/code_tests/name/中获取所有.in文件
directory = 'books/code_tests/'+course_id+'/'+name directory = 'books/code_tests/'+course_id+'/'+name
print(f"Directory: {directory}")
# 如果目录不存在,报错 # 如果目录不存在,报错
if not os.path.exists(directory): if not os.path.exists(directory):
return FunctionResponse("judge", False, f"The name {name} is not found.") 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 = "" erroroutput = ""
exceptoutput="" exceptoutput=""
for file in in_files: for file in in_files:
print(f"Testing {file}")
file_path = os.path.join(save_dir, f"_{name}.out") file_path = os.path.join(save_dir, f"_{name}.out")
if os.path.exists(file_path): if os.path.exists(file_path):
os.remove(file_path) os.remove(file_path)

View File

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

View File

@@ -75,15 +75,16 @@ class AgentNamespace(Namespace):
entry=self, entry=self,
init_data={'room': user_uuid} init_data={'room': user_uuid}
) )
fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name) fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
chatmanager = user_uuid2chatmanager[user_uuid] 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.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}) chatmanager.function_manager.add_function(next_chapter, {'user_uuid': user_uuid})
join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room 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.bb = backboard_manager.get_backboard(user_uuid)
chatmanager.focus_chapter(0) chatmanager.focus_chapter(0)
@@ -116,6 +117,7 @@ class AgentNamespace(Namespace):
d['data'] = res.to_dict() d['data'] = res.to_dict()
print("function_call_res", d['data']) print("function_call_res", d['data'])
emit(d['route'], d, room=uuid, namespace='/agent') 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): 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) print("receive_ase_next_chapter", data)
namespace_entry.emit('request_function',data, room=init_data['room'], namespace='/agent') # data 是一个列表 /dict也支持 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") print("User active function call")
ex = current_app.extensions ex = current_app.extensions
agent_manager = ex["agent_manager"]
backboard_manager = ex["backboard_manager"]
uuid = session.get('user_uuid') uuid = session.get('user_uuid')
manager = ex["user_uuid2chatmanager"][uuid]
backboard_manager = ex["backboard_manager"]
if data['name'] == 'sample_judge': 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': 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 布局 */ /* 主容器,使用 grid 布局 */
#maxcontainer { #maxcontainer {
display: grid; display: grid;
grid-template-columns: 1fr 5px 3fr 5px 1fr; /* 默认宽度比例 */ grid-template-columns: 2fr 5px 3fr 5px 1fr; /* 默认宽度比例 */
height: 100%; height: 100%;
} }

View File

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

View File

@@ -10,11 +10,8 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
</head> </head>
<body class="markdown-body"> <body class="markdown-body">
<h1>二分</h1> <h1>二分查找与二分答案</h1>
<blockquote> <h2>二分查找</h2>
<p>Auto-generated at 2025-09-05 19:48</p>
</blockquote>
<h2>阶段一:示例阶段</h2>
<h3>引入</h3> <h3>引入</h3>
<p>二分是一个很简单基础,但很重要的知识点,为以后许多高级的数据结构与算法铺垫。</p> <p>二分是一个很简单基础,但很重要的知识点,为以后许多高级的数据结构与算法铺垫。</p>
<p>下面是一个用二分的简单场景:</p> <p>下面是一个用二分的简单场景:</p>
@@ -47,7 +44,7 @@
<p>第三行一个整数q表示询问的次数。(1&lt;=q&lt;=10^4)</p> <p>第三行一个整数q表示询问的次数。(1&lt;=q&lt;=10^4)</p>
<p>后q行每行一个整数b表示询问的数。(0&lt;=b&lt;=10^8)</p> <p>后q行每行一个整数b表示询问的数。(0&lt;=b&lt;=10^8)</p>
<h5>输出</h5> <h5>输出</h5>
<p>q行每行一个整数对应每次询问的返回结果</p> <p>q行每行一个整数对应每次询问的返回结果</p>
<h5>提示:</h5> <h5>提示:</h5>
<p>完成代码后通知Agent进行评测。</p> <p>完成代码后通知Agent进行评测。</p>
<p>如果你还不完全会这个算法询问Agent获取提示并进行学习。</p> <p>如果你还不完全会这个算法询问Agent获取提示并进行学习。</p>

View File

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