diff --git a/Html/app.py b/Html/app.py
index df3bc94..b7a0de2 100644
--- a/Html/app.py
+++ b/Html/app.py
@@ -14,7 +14,8 @@ if __name__ == "__main__":
host="0.0.0.0",
port=5551,
debug=True, # 开发期打开
- allow_unsafe_werkzeug=True # 避免 dev server 的安全限制提示
+ allow_unsafe_werkzeug=True, # 避免 dev server 的安全限制提示
+ ssl_context=('server.crt', 'server.key')
)
diff --git a/Html/apps/extension_ase/ase_client/__init__.py b/Html/apps/extension_ase/ase_client/__init__.py
index 80bdad0..56c27c6 100644
--- a/Html/apps/extension_ase/ase_client/__init__.py
+++ b/Html/apps/extension_ase/ase_client/__init__.py
@@ -1 +1,2 @@
-from .client import ASEngineClient
\ No newline at end of file
+from .client import ASEngineClient, HSAEngineClient
+from .manager import ChatManager
\ No newline at end of file
diff --git a/Html/apps/extension_ase/ase_client/client.py b/Html/apps/extension_ase/ase_client/client.py
index 140c0c2..6c2c93d 100644
--- a/Html/apps/extension_ase/ase_client/client.py
+++ b/Html/apps/extension_ase/ase_client/client.py
@@ -56,9 +56,6 @@ class ASEngineClient:
def on_response(data):
print(f"Received response: {data}")
-
-
-
def register_route_with_entry(self, route: str,
callback: Optional[Callable] = None,
entry: Any = None,
@@ -167,10 +164,7 @@ class ASEngineClient:
print("Not connected to server")
return False
- if route not in self.routes:
- print(f"Route '{route}' not registered")
- return False
-
+
try:
self.sio.emit(route, {'type': 'text', 'data': text}, namespace=self.namespace)
print(f"Sent text to route '{route}': {text}")
@@ -264,4 +258,14 @@ class ASEngineClient:
print("Client stopped by user")
self.disconnect()
else:
- print("Not connected to server")
\ No newline at end of file
+ print("Not connected to server")
+
+
+class HSAEngineClient(ASEngineClient):
+ def __init__(self, server_url: str, namespace: str):
+ super().__init__(server_url, namespace)
+ def loadmarkdown(self, fmd, fmdp, fsp):
+ self.send_text('markdown-in', fmd)
+ self.send_text('markdown-prompt-in', fmdp)
+ self.send_text('score-prompt-in', fsp)
+
diff --git a/Html/apps/extension_ase/ase_client/manager.py b/Html/apps/extension_ase/ase_client/manager.py
new file mode 100644
index 0000000..08adf3f
--- /dev/null
+++ b/Html/apps/extension_ase/ase_client/manager.py
@@ -0,0 +1,120 @@
+import sys
+import os
+current_directory = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(current_directory)
+from flask_socketio import SocketIO, join_room, emit, Namespace
+import agentscope
+from agentscope.message import Msg
+import os
+import asyncio
+import threading
+import json
+
+
+import configparser
+from ...function_tools.function_manager import FunctionManager
+
+
+import uuid
+from ...utils import *
+EMPTY_CHAPTER_CHAIN = [ Chapter(1, CHAPTER_FOCUS, "本章是未打开某个具体章节时的默认章节。", "处于本章节时不会有任何章节跳转。请作为一名经验丰富的算法教师,回答用户的问题。") ]
+
+
+
+class ChatManager:
+ def __init__(self,user_uuid,ase_client,raw_markdown,raw_markdown_prompts,raw_score_prompts,max_iter = 5, app=None, socketio=None):
+ self.chapter_chain_now = -1
+ self.ase_client = ase_client
+ self.app = app
+ self.socketio = socketio
+ self.user_uuid = user_uuid
+ self.raw_markdown = raw_markdown
+ self.raw_markdown_prompts = raw_markdown_prompts
+ self.raw_score_prompts = raw_score_prompts
+ self.chapter_chain = load_chapters(raw_markdown, raw_markdown_prompts, raw_score_prompts)
+ self.function_manager = FunctionManager()
+
+
+ def next_chapter(self):
+ assert self.chapter_chain_now + 1 < len(self.chapter_chain), "chapter_chain_now out of range"
+ self.chapter_chain_now += 1
+ self.focus_chapter(self.chapter_chain_now)
+
+ def focus_chapter(self, chapter_index):
+ assert chapter_index < len(self.chapter_chain), "chapter_index out of range"
+ self.chapter_chain_now = chapter_index
+ self.chapter_chain[chapter_index].Focus()
+ self.ase_client.loadmarkdown(self.chapter_chain[chapter_index].chapter, self.chapter_chain[chapter_index].chapter_prompt, self.chapter_chain[chapter_index].score_prompt)
+
+
+ def message_pass(self, messagetype, message):
+ print("message_pass", self.user_uuid, messagetype, message)
+ with self.app.app_context():
+ try:
+ self.socketio.emit(messagetype, message, room=self.user_uuid, namespace='/agent')
+ except Exception as e:
+ print("message_pass",e)
+
+ def system_message(self, message):
+ with self.app.app_context():
+ try:
+ self.socketio.emit('system_message', message, room=self.user_uuid, namespace='/agent')
+ except Exception as e:
+ print("ERROR: system_message",e)
+
+
+ def save_chapter_memory(self, agent,course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal):
+
+ self.app.my_function.save_chapter_memory(self.user_uuid, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
+
+
+
+ def function_call(self, function_name, arg_function):
+ return self.function_manager.call_function(function_name, arg_function)
+
+ 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})
+
+ 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')
+ else:
+ self.socketio.emit('system_message', "代码试运行尚仅支持python文件", room=id, namespace='/agent')
+ except Exception as e:
+ print(e)
+ if (str(e) == "no path specified"):
+ self.socketio.emit("system_message", "未加载IDE文件同步,请尝试重新打开IDE文件或刷新页面,并确保插件已连接", room=id, namespace='/agent')
+
+ 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 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()}})
+ else:
+ self.socketio.emit('system_message', "代码评测尚仅支持python文件", room=id, namespace='/agent')
+
+ else:
+ with self.app.app_context():
+ self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
+ else:
+ with self.app.app_context():
+ self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
+ except Exception as e:
+ if (str(e) == "no path specified"):
+ self.socketio.emit("system_message", "未加载IDE文件同步,请尝试重新打开IDE文件或刷新页面,并确保插件已连接", room=id, namespace='/agent')
+
diff --git a/Html/apps/extensions.py b/Html/apps/extensions.py
index 300203e..2c6aaba 100644
--- a/Html/apps/extensions.py
+++ b/Html/apps/extensions.py
@@ -29,7 +29,7 @@ course_list = CourseList()
user_uuid2UserClass = {}
user_uuid2ase_client = {}
-
+user_uuid2chatmanager = {}
from AlgoriAgent.projects.algoriAgent.agent_manager import AgentManager
agent_manager = AgentManager()
def init_extensions(app):
@@ -43,7 +43,7 @@ def init_extensions(app):
)
cors.init_app(
app,
- resources={r"/*": {"origins": app.config["VSCODE_WEB_URL"]}},
+ resources={r"/*": {"origins": "*"}},#app.config["VSCODE_WEB_URL"]}},
supports_credentials=True,
)
@@ -59,6 +59,7 @@ def init_extensions(app):
app.extensions["agent_manager"] = agent_manager
app.extensions["my_function"] = MyFunction()
app.extensions["user_uuid2ase_client"] = user_uuid2ase_client
+ app.extensions["user_uuid2chatmanager"] = user_uuid2chatmanager
mongo.init_app(app,uri=app.config["MONGO_URI"])
app.extensions["mongo"] = mongo
diff --git a/Html/apps/function_tools/__init__.py b/Html/apps/function_tools/__init__.py
new file mode 100644
index 0000000..4522ded
--- /dev/null
+++ b/Html/apps/function_tools/__init__.py
@@ -0,0 +1,2 @@
+from . import judge
+from .function_manager import FunctionManager
\ No newline at end of file
diff --git a/Html/apps/function_tools/function_manager.py b/Html/apps/function_tools/function_manager.py
new file mode 100644
index 0000000..0ad90cf
--- /dev/null
+++ b/Html/apps/function_tools/function_manager.py
@@ -0,0 +1,18 @@
+from typing import Callable
+class FunctionManager:
+ def __init__(self):
+ self.function_caller = {}
+ self.function_predifine_args = {}
+
+ def add_function(self, function:Callable, predifine_args:dict):
+ self.function_caller[function.__name__] = function
+ self.function_predifine_args[function.__name__] = predifine_args
+
+ def get_function(self, function_name:str):
+ return self.function_caller[function_name]
+
+ def get_function_predifine_args(self, function_name:str):
+ return self.function_predifine_args[function_name]
+
+ def call_function(self, function_name:str, args:dict):
+ return self.function_caller[function_name]( **args, **self.function_predifine_args[function_name])
diff --git a/Html/apps/function_tools/judge.py b/Html/apps/function_tools/judge.py
new file mode 100644
index 0000000..68a94b4
--- /dev/null
+++ b/Html/apps/function_tools/judge.py
@@ -0,0 +1,74 @@
+
+import os
+from ..models.function import FunctionResponse, FunctionStatus
+def judge(filepath:str, name: str, course_id: str, lesson_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.
+ name (`str`): The name of the problem.
+ course_id (`str`): The id of the course.
+ lesson_id (`str`): The id of the lesson.
+ root_path (`str`): The root path of the user's workspace project.
+
+ Returns:
+ Report `tuple(int,str)`: The report of the student's solution.
+ """
+ # 从books/code_tests/name/中获取所有.in文件
+
+ directory = 'books/code_tests/'+course_id+'/'+name
+ # 如果目录不存在,报错
+ if not os.path.exists(directory):
+ status = FunctionStatus.FAILED
+ return FunctionResponse("judge", status, f"The name {name} is not found.")
+ files = os.listdir(directory)
+ in_files = [file for file in files if file.endswith('.in')]
+ save_dir = root_path
+ Report = ""
+ passed_num=0
+ failed_num=0
+ erroroutput = ""
+ exceptoutput=""
+ for file in in_files:
+ file_path = os.path.join(save_dir, f"_{name}.out")
+ if os.path.exists(file_path):
+ os.remove(file_path)
+ with open(file_path, 'w') as ff:
+ ff.write("")
+
+ cmd = "cat " + os.path.join(directory, file) + " | " + "python " + os.path.join(root_path, filepath) +" > " + os.path.join(save_dir, f"_{name}.out")
+ os.system(cmd)
+ # 比较结果
+ re = ""
+ if compare_file(os.path.join(save_dir, f"_{name}.out"), os.path.join(directory, file.replace(".in", ".out"))):
+ re = f"Passed {file}"
+ passed_num += 1
+ else:
+ re = f"Failed {file}"
+ failed_num += 1
+ with open(os.path.join(directory, file.replace(".in", ".out")),'r') as f: exceptoutput = f.read()
+ with open(os.path.join(save_dir, f"_{name}.out"),'r') as f: erroroutput = f.read()
+ Report = Report + re + "\n"
+ os.remove(os.path.join(save_dir, f"_{name}.out"))
+ score = int (100 * passed_num / (passed_num + failed_num))
+
+
+
+ status = FunctionStatus.SUCCESS
+ return FunctionResponse("judge", status, f"评测得分为 {score}, 在 {passed_num + failed_num} 个测试用例中通过了 {passed_num}个。最后一个错误样例期望输出:'{exceptoutput}',但你的输出:'{erroroutput}")
+
+
+def compare_file(path1:str, path2:str):
+ """
+ Compare two files and return true if they are the same.
+ """
+ with open(path1, 'r') as f1, open(path2, 'r') as f2:
+ # 逐行比较
+ print('-------------------COMPARE-------------------------')
+ for line1, line2 in zip(f1, f2):
+ print(line1.strip(), "||",line2.strip())
+ if line1.strip() != line2.strip():
+ return False
+ return True
+
+judge_tools = [judge]
\ No newline at end of file
diff --git a/Html/apps/models/function.py b/Html/apps/models/function.py
new file mode 100644
index 0000000..558824f
--- /dev/null
+++ b/Html/apps/models/function.py
@@ -0,0 +1,11 @@
+from pydantic import BaseModel
+from enum import Enum
+from typing import Optional
+
+FunctionStatus = Enum("FunctionStatus", ["SUCCESS", "ERROR"])
+
+class FunctionResponse(BaseModel):
+ name: str
+ status: FunctionStatus
+ message: str = ""
+ args: Optional[dict] = None
\ No newline at end of file
diff --git a/Html/apps/sockets/namespaces.py b/Html/apps/sockets/namespaces.py
index f0c8146..0a4ed93 100644
--- a/Html/apps/sockets/namespaces.py
+++ b/Html/apps/sockets/namespaces.py
@@ -2,10 +2,13 @@
import json
from flask import current_app, request, session
from flask_socketio import Namespace, join_room, leave_room, emit
+
+from ..function_tools import judge
from ..services.memory_service import save_chapter_memory_by_uuid
from ..services.backboard_service import realtime_response
from ..services.markdown_service import load_full_markdown_file
-from ..extension_ase.ase_client import ASEngineClient
+from ..extension_ase.ase_client import HSAEngineClient, ChatManager
+
class VSCodeNamespace(Namespace):
def on_login(self,data):
@@ -50,32 +53,32 @@ class AgentNamespace(Namespace):
user_id = uuid2username[user_uuid]
session['user_uuid'] = user_uuid
print(f'User connected with session user_uuid: {user_uuid}')
+ user_uuid2chatmanager = ex["user_uuid2chatmanager"]
user_uuid2ase_client = ex["user_uuid2ase_client"]
- user_uuid2ase_client[user_uuid] = ASEngineClient(current_app.config["ASE_ENGINE_URL"], current_app.config["ASE_ENGINE_NAMESPACE"])
+ user_uuid2ase_client[user_uuid] = HSAEngineClient(current_app.config["ASE_ENGINE_URL"], current_app.config["ASE_ENGINE_NAMESPACE"])
user_uuid2ase_client[user_uuid].connect()
user_uuid2ase_client[user_uuid].register_route_with_entry(
route='dialog',
callback=self.receive_ase_dialog,
- entry=self, # 传你的 Namespace 对象
- init_data={'room': user_uuid} # 想传啥都可以
+ entry=self,
+ init_data={'room': user_uuid}
)
fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
- # 从markdown、markdown_prompts、score_prompts中各读取数据folder.md并进行new_agent
+ user_uuid2chatmanager[user_uuid] = ChatManager(user_uuid, user_uuid2ase_client[user_uuid], fmd, fmdp, fsp, max_iter=5, app=current_app, socketio=self)
+ chatmanager = user_uuid2chatmanager[user_uuid]
+ 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}'})
- user_uuid, agent = agent_manager.new_agent(course_id, lesson_name, fmd, fmdp, fsp, id=user_uuid,
- root_path=f'../../study/{user_id}/{course_id}/{chapter_name}/{lesson_name}')
- print(user_uuid)
+ user_uuid2ase_client[user_uuid].loadmarkdown(fmd, fmdp, fsp)
+
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}')
+ chatmanager.focus_chapter(0)
+
def on_language(self, language):
ex = current_app.extensions
- agent_manager = ex["agent_manager"]
- uuid2username = ex["uuid2username"]
- uuid = session.get('user_uuid')
- user_id = uuid2username[uuid]
- agent_manager.change_language(uuid, language)
+ print(f"Language changed to: {language}")
def on_message(self, data):
print(f"Message from client: {data}")
@@ -89,7 +92,6 @@ class AgentNamespace(Namespace):
if (type(data)==str):
data = json.loads(data)
if data['type'] == 'text':
- # res = agent_manager.invoke(uuid, data['data'], backboard_manager.get_backboard(uuid).get_info_prompt())
user_uuid2ase_client[uuid].send_text('dialog', data['data'])
# print('=*='*20)
# print(res.content)
@@ -102,12 +104,11 @@ class AgentNamespace(Namespace):
agent_manager.function_call(uuid, data['data'])
- def receive_ase_dialog(client_entry: ASEngineClient, namespace_entry: Namespace, data, init_data):
- print(f"Received from ASEngine: {data}")
- # 直接使用 entry(也就是你的 Namespace 对象)
+ def receive_ase_dialog(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
namespace_entry.emit('message', data['data'], room=init_data['room'], namespace='/agent')
-
+ def receive_ase_function(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
+ namespace_entry.emit('request_function', data['data'], room=init_data['room'], namespace='/agent')
def on_initiative(self,data):
print("User active function call")
diff --git a/Html/apps/static/js/chatbox.js b/Html/apps/static/js/chatbox.js
index 49115a3..82b9215 100644
--- a/Html/apps/static/js/chatbox.js
+++ b/Html/apps/static/js/chatbox.js
@@ -4,7 +4,7 @@ let system_message_idx=0
document.addEventListener('DOMContentLoaded', function() {
data = window.appData;
console.log(data);
- socket = io('ws://localhost:5551/agent',{
+ socket = io('wss://localhost:5551/agent',{
query:{
user_uuid:data.user_uuid,
folder:data.folder
diff --git a/Html/apps/utils/__init__.py b/Html/apps/utils/__init__.py
new file mode 100644
index 0000000..eeeb2b2
--- /dev/null
+++ b/Html/apps/utils/__init__.py
@@ -0,0 +1 @@
+from .chapterUtil import *
\ No newline at end of file
diff --git a/Html/apps/utils/chapterUtil.py b/Html/apps/utils/chapterUtil.py
new file mode 100644
index 0000000..5f61098
--- /dev/null
+++ b/Html/apps/utils/chapterUtil.py
@@ -0,0 +1,159 @@
+from typing import Callable, Any
+from AlgoriAgent.projects.algoriAgent.tools.judge_tools import judge
+
+CHAPTER_FINISH = 0
+CHAPTER_FOCUS = 1
+CHAPTER_LATTER = 2
+CHAPTER_FAILED = 3
+
+def tool_name_to_tool(tool_name_list):
+ tools = []
+ for tool_name in tool_name_list:
+ if tool_name == "":
+ continue
+ if tool_name == "judge":
+ tools.append(judge)
+ return tools
+
+def tool_name_to_tool_with_args(tool_name_list, tool_args_list) -> list[tuple[Callable, dict]]:
+ tools = []
+ for tool_name, tool_args in zip(tool_name_list, tool_args_list):
+ if tool_name == "":
+ continue
+ if tool_name == "judge":
+ tools.append((judge, {"name": tool_args[0]}))
+ return tools
+
+class Chapter():
+ def __init__(self, No = 1, focus = 2,title="", chapter = "", chapter_prompt = "",
+ score_prompt = "", append_tools : list[Callable[..., Any], dict] = None) -> None:
+ '''
+ No : 序号
+ focus : 0: Finished, 1: Focus, 2: Latter, 3: Failed
+ title : 子章节标题
+ chapter : 教案子章节内容
+ chapter_prompt : 教案的提示
+ score_prompt : 评测标准
+ append_tools : 追加工具函数
+ '''
+ self.No = No
+ self.focus = focus
+ self.chapter = chapter
+ self.chapter_prompt = chapter_prompt
+ self.score_prompt = score_prompt
+ self.append_tools = append_tools
+ self.memory = None
+ self.title =title
+
+
+ def GetChapter(self):
+ if self.focus == CHAPTER_FINISH: f = "(Finished Chapter)"
+ elif self.focus == CHAPTER_FOCUS: f = "(Your Now Chapter)"
+ elif self.focus == CHAPTER_LATTER: f = "(Ignore for Latter Chapter)"
+ elif self.focus == CHAPTER_FAILED: f = "(Failed Chapter)"
+ # des = f"{f} Chapter {self.No}: {self.chapter if self.focus else 'Hidden for further study.'}"
+ des = f"{f} Chapter {self.No}: "
+ if self.focus == CHAPTER_FINISH or self.focus == CHAPTER_FAILED: des += 'Hidden due to finished.'
+ if self.focus == CHAPTER_LATTER: des += 'Hidden for further study.'
+ if self.focus == CHAPTER_FOCUS:
+ des+=self.chapter
+ des+='\n'
+ des+='Here are some concrete instructions:\n'
+ des+=self.chapter_prompt+'\n'
+
+ return des
+
+
+
+ def Finished(self, successful: bool = True):
+ if successful: self.focus = 0
+ else: self.focus = 3
+
+ def Focus(self):
+ self.focus = 1
+def load_chapters(markdown, markdown_prompt, score_prompt):
+ markdown_list = markdown.split("\n")
+ markdown_prompt_list = markdown_prompt.split("\n")
+ score_prompt_list = score_prompt.split("\n")
+ # 获取 H1 标题
+ title = ""
+ for line in markdown_list:
+ if line.startswith("# "):
+ title = line[2:]
+ break
+
+ # 对于 H3 标题 构造每一个 Chapter
+ # 首先找到所有的 H3 标题
+ chapter_dict = {}
+ chapter_sequence = []
+ for line in markdown_list:
+ if line.startswith("### "):
+ chapter_name = line[4:]
+ chapter_dict[chapter_name] = {}
+ chapter_sequence.append(chapter_name)
+ # 将 H3 标题 和 其对应的内容 构造成一个 Chapter
+
+ h3_name = ""
+ content = ""
+ for i in range(len(markdown_list)):
+ if markdown_list[i].startswith("### "):
+ if(h3_name != ""):
+ chapter_dict[h3_name]["markdown"] = content
+ h3_name = markdown_list[i][4:]
+ content = ""
+ continue
+ if h3_name != "":
+ content += markdown_list[i]+"\n"
+ if(h3_name != ""):
+ chapter_dict[h3_name]["markdown"] = content
+
+
+ h3_name = ""
+ content = ""
+ require_tools = []
+ require_tools_args = []
+ for i in range(len(markdown_prompt_list)):
+ if markdown_prompt_list[i].startswith("### "):
+ if(h3_name != ""):
+ chapter_dict[h3_name]["markdown_prompt"] = content
+ chapter_dict[h3_name]["require_tools"] = tool_name_to_tool_with_args(require_tools, require_tools_args)
+ h3_name = markdown_prompt_list[i][4:]
+ content = ""
+ require_tools=[]
+ require_tools_args = []
+ continue
+
+ if h3_name != "":
+ if markdown_prompt_list[i].startswith("_require_tools"):
+ require_tools.append(markdown_prompt_list[i].split("=")[1].strip().split(",")[0])
+ require_tools_args.append((markdown_prompt_list[i].split("=")[1].strip().split(",")[1:]))
+ continue
+ content += markdown_prompt_list[i]+"\n"
+ if(h3_name != ""):
+ chapter_dict[h3_name]["markdown_prompt"] = content
+ chapter_dict[h3_name]["require_tools"] = tool_name_to_tool_with_args(require_tools, require_tools_args)
+
+
+ h3_name = ""
+ content = ""
+ for i in range(len(score_prompt_list)):
+ if score_prompt_list[i].startswith("### "):
+ if(h3_name != ""):
+ chapter_dict[h3_name]["score_prompt"] = content
+ h3_name = score_prompt_list[i][4:]
+ content = ""
+ continue
+
+ if h3_name != "":
+ content += score_prompt_list[i]+"\n"
+ if(h3_name != ""):
+ chapter_dict[h3_name]["score_prompt"] = content
+
+
+ chapter_chain = []
+ No = 1
+ print (chapter_dict)
+ for chapter_name in chapter_sequence:
+ chapter_chain.append(Chapter( No, CHAPTER_LATTER, chapter_name, chapter_dict[chapter_name]["markdown"], chapter_dict[chapter_name]["markdown_prompt"], chapter_dict[chapter_name]["score_prompt"],chapter_dict[chapter_name]["require_tools"]))
+ No+=1
+ return chapter_chain
\ No newline at end of file
diff --git a/Html/apps/views/vscode.py b/Html/apps/views/vscode.py
index aec9588..5bc1ae9 100644
--- a/Html/apps/views/vscode.py
+++ b/Html/apps/views/vscode.py
@@ -62,7 +62,10 @@ def desktop_nouser(course_id, chapter_name, lesson_name):
@bp.route("/vscode_data", methods=["POST"])
def vscode_data():
- data = request.get_json(force=True)
- config = data.get("config") or {}
- realtime_response(config, data) # 调用服务层逻辑
- return jsonify({"status": "success", "received": data})
+ # data = request.get_json(force=True)
+ # config = data.get("config") or {}
+
+ # realtime_response(config, data) # 调用服务层逻辑
+ # return jsonify({"status": "success", "received": data})
+
+ return jsonify({"status": "success", "received": "success"})
diff --git a/Html/server.crt b/Html/server.crt
new file mode 100644
index 0000000..1f2645d
--- /dev/null
+++ b/Html/server.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAokCFF/OMLJof3ypmpQCK3zGNpJ15pDBMA0GCSqGSIb3DQEBCwUAMIGM
+MQswCQYDVQQGEwJVUzESMBAGA1UECAwJU29tZVN0YXRlMREwDwYDVQQHDAhTb21l
+Q2l0eTEQMA4GA1UECgwHU29tZU9yZzERMA8GA1UECwwIU29tZVVuaXQxEjAQBgNV
+BAMMCWxvY2FsaG9zdDEdMBsGCSqGSIb3DQEJARYOeW91ckBlbWFpbC5jb20wHhcN
+MjUwOTEwMTYzMTU4WhcNMjYwOTEwMTYzMTU4WjCBjDELMAkGA1UEBhMCVVMxEjAQ
+BgNVBAgMCVNvbWVTdGF0ZTERMA8GA1UEBwwIU29tZUNpdHkxEDAOBgNVBAoMB1Nv
+bWVPcmcxETAPBgNVBAsMCFNvbWVVbml0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHTAb
+BgkqhkiG9w0BCQEWDnlvdXJAZW1haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA0BFtyncXSrEEXn0iCSumufiJMwIf+qmes3tv8db05yHPjReD
+gDvwzSmm4+5lDo/EkMK64gOXAoqy7nO/40OyEnIOBbWrUg6M9gPM6F9DEJZsM9Ae
+M/1lkwnsJ3IgbKSf2uw+riwBAfnnClDWvEkIqH96d4352yQba694k7Zn936NnzWd
+ROYaLXqy4HoR2UYOM4nzaPq9EoANLsPNgftQjWMDVhsAnt7FtDnvT+86wB4KWKXA
+QVIw2QmjrhaeajpL2N4xG5SQxb6mlFaZKw/sCHAo5JqmRhQ9p7CAE47DYHIDC+Sp
+GHaJJKrbA81RLU1iTLtmsYrpRHNp+S2f1nJODQIDAQABMA0GCSqGSIb3DQEBCwUA
+A4IBAQAhagxrnwPkVpdM6tqaaEE4xGdWxrIuipBNXTbtYd/8WOhVDDaLWjMo0vG4
+70Pgq+HJ166XdL00ZTj4UfcC1Ls5qRLkfimb/Rz59BfK0iE8QVEKt6yfJWUD6HuI
+y2tl9hqUJrW1OTcMgEOV6Dg+RX3VpDcDML5SJ17r9IqaaB0HAV9IVGt+jK1ZzUBp
+h0iQUrH3+x9xR5x41Vz2TKgeFuxYnwqGPhCdRdDX2prYWDMV4awAkUvx/5oyCw3q
+juisnWoyzFw1WMiA9Hl+29XL1k5X1QE9gLrW3qvhB/OnrRaYK3sfHZMSYSrr+CDJ
++bT/JOuQBdTSsc4VCLphezh8C1Sy
+-----END CERTIFICATE-----
diff --git a/Html/server.key b/Html/server.key
new file mode 100644
index 0000000..17e0d40
--- /dev/null
+++ b/Html/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQEW3KdxdKsQRe
+fSIJK6a5+IkzAh/6qZ6ze2/x1vTnIc+NF4OAO/DNKabj7mUOj8SQwrriA5cCirLu
+c7/jQ7IScg4FtatSDoz2A8zoX0MQlmwz0B4z/WWTCewnciBspJ/a7D6uLAEB+ecK
+UNa8SQiof3p3jfnbJBtrr3iTtmf3fo2fNZ1E5hoterLgehHZRg4zifNo+r0SgA0u
+w82B+1CNYwNWGwCe3sW0Oe9P7zrAHgpYpcBBUjDZCaOuFp5qOkvY3jEblJDFvqaU
+VpkrD+wIcCjkmqZGFD2nsIATjsNgcgML5KkYdokkqtsDzVEtTWJMu2axiulEc2n5
+LZ/Wck4NAgMBAAECggEAE3JAOyc0mj//eF9PR4vOCjKUNsa7kL9lUZa3UziJF3MT
+BWJNtuCjSbbbXhE2s7eJzRJ4yffrl2AO3MzHrJNz+K0H6iOyY+Rv60GsAd8paEr5
+c5bqGRIqpKVNmNrd9Jl8RpyZjR4YEq8LF206bKA80Ba+A5+AMH7oQIEcDrOCdbXc
+m9JYo0yiehyZyVtPZJjw70uAstJ+n/gFhIh1B7kSaIbKCPLmHHph19jnWAEXKVLX
+Hzb7Q5BhcCqiON7RJ3kDlomGiMmS/xuqjdbsruNcdg2ze/iAA2Gvw7Y52Q4/q69e
+y/yxupS5FeFz9YjrmSJavws8ttZTVb1Y2W3ZoUFFZwKBgQDq5ZZXsWieslAq6x6S
+MAwIz4NGAlui721QBG8aFipMr3B/wi9PJHqNkkCywYnm26xjkkpRsiPlWkbnfbeB
+7mw6t1Yo58qZPNCxVKpl8cFX76mzhNyPEjI7b2N7fmiwJZQx6QXEQ98XEWeWrPVg
+7E5SN4/aw6EScxC/Qlwf9CgjLwKBgQDiws4R14/+K4lv9omdobs+AX2TqZ/XugQR
+zClLWgHziPhj+lzJlbuFqM6h+aFKETTCPRlJGjDy42R+FrU4rtfhEmILaEyuox02
+0xHfNdJ7bziQSiRrOqNmpKIhZvt71ozh0XuRBwFMQOwFI5nnCvbyGWRep9ChMw8m
+czFqhb1DgwKBgQCLu6vl2smLrjN2dIupFx/xldBXs0tj794tPZYCBLGBENRxi8is
+4dxtn1URgYRRathwGzROyRQFeeC4ENc7WePUQf/lMY4Z/k1/UAhVwKztbMqc2iqC
+iaaMKMUbT6VjM9emoSInEOEDTf07awRFdg1ZZ2gSEVIeMYkC3a0D7TB7TQKBgQCD
+KPBuq4OTHXWSeERjE9As7knHZj6ZVfPSo4djGT21so0RrxeKVfwwNFLIp44ePFOK
+4jJE8UxMwTA4KkRJ8//UJIDnXj20aY6VToKw2/3R/aP2+ZuVFka7MRDCR0HBAHle
+iH9zhFzA0XBzDIOReusZX4yJn4FyLAlgURLNLWwqpwKBgB/hh4aM0oUcl3KNnvMY
+Vd/PFTiGgwfTebOpIAMBiyquAjDyto659M6N2ZE5kMipvfX+mqaV0ZLTw1rKzVhp
+qvUVtFXlZipkb6yCFnkLvvoC+FJrobKK0cqZ3KlIcfx3hkt07ykmcqd8Q2rV7qMT
+8/exXLRwkWtd0Tfq52ZLH+Yw
+-----END PRIVATE KEY-----