code-server injection
This commit is contained in:
@@ -4,7 +4,7 @@ let system_message_idx=0
|
|||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
data = window.appData;
|
data = window.appData;
|
||||||
console.log(data);
|
console.log(data);
|
||||||
socket = io('wss://localhost:5551/agent',{
|
socket = io('wss://hsamooc.cn/agent',{
|
||||||
query:{
|
query:{
|
||||||
user_uuid:data.user_uuid,
|
user_uuid:data.user_uuid,
|
||||||
folder:data.folder
|
folder:data.folder
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import os, uuid, json
|
import os, uuid, json
|
||||||
from flask import Blueprint, current_app, session, redirect, url_for, render_template, request, jsonify
|
from flask import Blueprint, current_app, session, redirect, url_for, render_template, request, jsonify
|
||||||
from ..services.backboard_service import realtime_response
|
from ..services.backboard_service import realtime_response
|
||||||
|
import subprocess
|
||||||
|
|
||||||
bp = Blueprint("vscode", __name__)
|
bp = Blueprint("vscode", __name__)
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ def desktop(user_uuid, course_id, chapter_name, lesson_name):
|
|||||||
if "user_uuid" not in session:
|
if "user_uuid" not in session:
|
||||||
user_uuid = "user_" + str(uuid.uuid4())
|
user_uuid = "user_" + str(uuid.uuid4())
|
||||||
session["user_uuid"] = user_uuid
|
session["user_uuid"] = user_uuid
|
||||||
uuid2username[user_uuid] = "guest"+str(uuid.uuid4())
|
uuid2username[user_uuid] = "guest"+str(uuid.uuid4())[0:5]
|
||||||
username2uuid[uuid2username[user_uuid]] = user_uuid
|
username2uuid[uuid2username[user_uuid]] = user_uuid
|
||||||
|
|
||||||
# 全局映射
|
# 全局映射
|
||||||
@@ -23,15 +24,55 @@ def desktop(user_uuid, course_id, chapter_name, lesson_name):
|
|||||||
|
|
||||||
# 按课程/章节创建工作目录
|
# 按课程/章节创建工作目录
|
||||||
base_root = current_app.config["STUDENT_WORKSPACE_ROOT"]
|
base_root = current_app.config["STUDENT_WORKSPACE_ROOT"]
|
||||||
path_dir = os.path.join(base_root, user_id, course_id, chapter_name)
|
|
||||||
os.makedirs(path_dir, exist_ok=True)
|
|
||||||
|
|
||||||
# 写 .config(并按需要转换为 WSL 路径)
|
user_home = os.path.join("/home", user_id)
|
||||||
|
try:
|
||||||
|
subprocess.run(["sudo", "useradd", "-m", "-d", user_home, user_id]) # 创建用户
|
||||||
|
subprocess.run(["sudo", "chown", "-R", user_id, user_home]) # 设置目录权限为新用户
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creating user {user_id}: {e}")
|
||||||
|
path_dir = os.path.join("/home", user_id, course_id, chapter_name, lesson_name)
|
||||||
|
try:
|
||||||
|
# 使用 sudo 执行 mkdir 命令来创建目录
|
||||||
|
subprocess.run(["sudo", "-u", user_id, "mkdir", "-p", path_dir], check=True)
|
||||||
|
print(f"Directory {path_dir} created successfully for user {user_id}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creating directory {path_dir} details {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
code_server_port = 10000 + int(uuid.uuid4().int % 10000)
|
||||||
|
try:
|
||||||
|
subprocess.Popen([
|
||||||
|
"sudo", "-u", user_id,
|
||||||
|
"code-server", "--bind-addr", f"0.0.0.0:{code_server_port}",
|
||||||
|
"--auth", "none", path_dir
|
||||||
|
])
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error start code-server at {code_server_port} with path{path_dir} {e}")
|
||||||
|
|
||||||
|
|
||||||
|
caddy_conf = f"""
|
||||||
|
handle_path /vsc{user_uuid}/* {{
|
||||||
|
reverse_proxy localhost:{code_server_port}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
caddy_config_path = "/etc/caddy/Caddyfile"
|
||||||
|
with open(caddy_config_path, "r") as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
insert_position = len(lines) - 2 if len(lines) >= 2 else len(lines)
|
||||||
|
lines.insert(insert_position, caddy_conf)
|
||||||
|
with open(caddy_config_path, "w") as f:
|
||||||
|
f.writelines(lines)
|
||||||
|
try:
|
||||||
|
subprocess.run(["sudo", "caddy", "reload", "--config", "/etc/caddy/Caddyfile"])
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error reload caddy {e}")
|
||||||
|
|
||||||
cfg = current_app.config["VSCODE_WEB_PATH"]
|
cfg = current_app.config["VSCODE_WEB_PATH"]
|
||||||
path_for_vscode = path_dir
|
path_for_vscode = path_dir
|
||||||
if cfg.get("is_wsl"):
|
|
||||||
path_for_vscode = path_for_vscode.replace("\\", "/") \
|
|
||||||
.replace(cfg.get("windows_path", ""), cfg.get("wsl_path", ""))
|
|
||||||
|
|
||||||
config_path = os.path.join(path_dir, ".config")
|
config_path = os.path.join(path_dir, ".config")
|
||||||
tmpd = {
|
tmpd = {
|
||||||
@@ -41,14 +82,21 @@ def desktop(user_uuid, course_id, chapter_name, lesson_name):
|
|||||||
"lesson_name": lesson_name,
|
"lesson_name": lesson_name,
|
||||||
"path": path_for_vscode
|
"path": path_for_vscode
|
||||||
}
|
}
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
config_json = json.dumps(tmpd, ensure_ascii=False)
|
||||||
json.dump(tmpd, f, ensure_ascii=False)
|
|
||||||
|
|
||||||
current_app.logger.debug("config file path: %s", config_path)
|
|
||||||
|
|
||||||
|
# 使用 sudo 和 tee 命令将 JSON 数据写入文件
|
||||||
|
subprocess.run(
|
||||||
|
["sudo", "-u", user_id, "bash", "-c", f"echo '{config_json}' | tee {config_path} > /dev/null"],
|
||||||
|
check=True
|
||||||
|
)
|
||||||
|
# 确保文件的所有权归 user_id
|
||||||
|
subprocess.run(
|
||||||
|
["sudo", "chown", f"{user_id}:{user_id}", config_path],
|
||||||
|
check=True
|
||||||
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"desktop.html",
|
"desktop.html",
|
||||||
vscode_web_url=current_app.config["VSCODE_WEB_URL"],
|
vscode_web_url=current_app.config["VSCODE_WEB_URL"]+f"/vsc{user_uuid}",
|
||||||
user_uuid=session["user_uuid"], course_id=course_id, chapter_name=chapter_name, lesson_name=lesson_name,
|
user_uuid=session["user_uuid"], course_id=course_id, chapter_name=chapter_name, lesson_name=lesson_name,
|
||||||
workspace_path=path_for_vscode,
|
workspace_path=path_for_vscode,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ api_key = sk-aMpnWklN2IbsK44d1kNpy6YOP9bk1pdPJjFeEmbb0a5ytEFf
|
|||||||
model=gpt-4.1-nano
|
model=gpt-4.1-nano
|
||||||
|
|
||||||
[VSCODE_WEB]
|
[VSCODE_WEB]
|
||||||
url = http://127.0.0.1:8181
|
url = https://hsamooc.cn
|
||||||
#http://asengine.net:8282
|
#http://asengine.net:8282
|
||||||
[VSCODE_WEB_PATH]
|
[VSCODE_WEB_PATH]
|
||||||
is_wsl = true
|
is_wsl = true
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"user_uuid": "user_7c671995-1d9e-4bbb-9fa1-587d12720754", "course_id": "68bacdfadf5aeae0912f7f18", "chapter_name": "基础算法", "lesson_name": "二分", "path": "/mnt/f/GIThubRepository/CodeAgent/code-agent/study/TCake/68bacdfadf5aeae0912f7f18/基础算法"}
|
{"user_uuid": "user_9a1cbf0a-e9f1-458f-9461-cdaea91b4aa0", "course_id": "68bacdfadf5aeae0912f7f18", "chapter_name": "基础算法", "lesson_name": "二分", "path": "/home/ubuntu/hsamooc/code-agent/study/TCake/68bacdfadf5aeae0912f7f18/基础算法"}
|
||||||
Reference in New Issue
Block a user