python单文件实现类似curosr等ai编程工具ide的编程开发工具bfwide代码
代码语言:python
所属分类:其他
代码描述:python单文件实现类似curosr等ai编程工具ide的编程开发工具bfwide代码,包括多项目目录管理,文件树,多tab代码编辑器、ai问答和build自动修改文件和运行cmd命令行等ai聊天模块,包含了基本的ai编辑器功能,还能设置多个不同的ai大模型api,并选择不同的ai大模型切换问答。
代码标签: python 单文件 实现 类似 curosr ai 编程 工具 ide 编程 开发 工具 代码 b
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
import os
import shutil
import subprocess
import threading
import uvicorn
import webview
import json
import uuid
import xml.etree.ElementTree as ET
from typing import List, Optional, Dict, Any
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi import FastAPI, Query, Response, HTTPException
from pydantic import BaseModel
# --- FastAPI App Definition ---
app = FastAPI()
# --- Configuration ---
BASE_DIR = os.path.join(os.getcwd(), 'projects')
PROJECTS_XML = os.path.join(BASE_DIR, 'projects.xml')
MODELS_JSON = os.path.join(os.getcwd(), 'models.json') # 模型配置文件
# --- pywebview API Class for JS Interop ---
class Api:
def select_folder(self):
window = webview.windows[0]
result = window.create_file_dialog(webview.FOLDER_DIALOG)
return result
def open_file_dialog(self):
window = webview.windows[0]
result = window.create_file_dialog(webview.OPEN_DIALOG)
return result
def save_file_dialog(self):
window = webview.windows[0]
result = window.create_file_dialog(webview.SAVE_DIALOG)
return result
def read_file_content(self, path: str) -> Optional[str]:
try:
with open(path, 'r', encoding='utf-8') as f:
return f.read()
except Exception as e:
return None
def save_file_content(self, path: str, content: str) -> bool:
try:
with open(path, 'w', encoding='utf-8') as f:
f.write(content)
return True
except Exception as e:
return False
api = Api()
# --- Pydantic Models ---
class Project(BaseModel):
id: str
name: str
serverType: str
localFolder: Optional[str] = None
class CommandExecution(BaseModel):
command: str
project: str
class FileData(BaseModel):
path: str
content: str
project: Optional[str] = None
class NewItemData(BaseModel):
path: str
name: str
project: str
class RenameData(BaseModel):
path: str
newName: str
project: str
class DeleteData(BaseModel):
path: str
project: str
class AIModelBase(BaseModel):
model_config = {'protected_namespaces': ()}
name: str
base_url: str
api_key: str
model_name: str
class AIModel(AIModelBase):
id: str
class Msg(BaseModel):
role: str
content: str
class ChatMessage(BaseModel):
model_config = {'protected_namespaces': ()}
message: str
history: List[Msg] = []
mode: str = 'ask' # 'ask' or 'build'
project: str
model_id: Optional[str] = None
files: List[Dict[str, Any]] = []
# --- Helper Functions ---
if not os.path.exists(BASE_DIR): os.makedirs(BASE_DIR)
if not os.path.exists(PROJECTS_XML):
root = ET.Element("Projects")
tree = ET.ElementTree(root)
tree.write(PROJECTS_XML, encoding='utf-8', xml_declaration=True)
def find_project_by_id(project_id: str) -> Optional[Dict[str, Any]]:
if not os.path.exists(PROJECTS_XML) or project_id is None: return None
try:
tree = ET.parse(PROJECTS_XML)
root = tree.getroot()
for project_elem in root.findall('Project'):
id_elem = project_elem.find('id')
if id_elem is not None and id_elem.text == project_id:
project_info = {}
for child in project_elem:
project_info[child.tag] = child.text
return project_info
except Exception: pass
return None
def load_projects() -> List[Dict[str, Any]]:
if not os.path.exists(PROJECTS_XML): return []
tree = ET.parse(PROJECTS_XML)
projects = []
for project_elem in tree.getroot().findall('Project'):
project = {child.tag: child.text for child in project_elem}
projects.append(project)
return projects
def save_projects(projects: List[Dict[str, Any]]):
root = ET.Element("Projects")
for project in projects:
project_elem = ET.SubElement(root, "Project")
for key, value in project.items():
if value is not None:
ET.SubElement(project_elem, key).text = str(value)
ET.ElementTree(root).write(PROJECTS_XML, encoding='utf-8', xml_declaration=True)
def load_models() -> List[AIModel]:
if not os.path.exists(MODELS_JSON): return []
try:
with open(MODELS_JSON, 'r', encoding='utf-8') as f:
return [AIModel(**data) for data in json.load(f)]
except Exception: return []
def save_models(models: List[AIModel]):
with open(MODELS_JSON, 'w', encoding='utf-8') as f:
json.dump([model.dict() for model in models], f, indent=4, ensure_ascii=False)
def execute_local_command(command, working_dir):
try:
result = subprocess.run(command, shell=True, capture_output=True, cwd=working_dir)
try: out = result.stdout.decode('utf-8')
except UnicodeDecodeError: out = result.stdout.decode('gbk', errors='ignore')
try: err = result.stderr.decode('utf-8')
except UnicodeDecodeError: err = result.stderr.decode('gbk', errors='ignore')
return out + err, None
except Exception as e: return None, str(e)
def read_local_file(path):
if not os.path.exists(path) or os.path.isdir(path): return None
try:
with open(path, 'r', encoding='utf-8', errors='ignore') as f: return f.read()
except Exception: return None
# 增强的上下文读取(支持递归文件夹)
def _get_file_context(project_base_path, files, projectinfo):
context = []
ignore_dirs = {'.git', 'node_modules', '__pycache__', '.venv', 'venv', 'dist', 'build'}
valid_exts = {'.js', '.ts', '.py', '.html', '.css', '.vue', '.json', '.xml', '.md', '.java', '.c', '.cpp', '.txt', '.yaml', '.yml'}
total_chars = 0
max_chars = 100000 # 限制上下文大小,防止Token溢出
for file_info in files:
if total_chars > max_chars: break
path = file_info.get('path')
if not path: continue
full_path = os.path.normpath(os.path.join(project_base_path, path))
if not full_path.startswith(os.path.normpath(project_base_path)): continue
if os.path.isfile(full_path):
content = read_local_file(full_path)
if content:
context.append(f"====== File: {path} ======\n{content}\n")
total_chars += len(content)
elif os.path.isdir(full_path):
for root, dirs, filenames in os.walk(full_path):
dirs[:] = [d for d in dirs if d not in ignore_dirs and not d.startswith('.')]
for name in filenames:
if total_chars > max_chars:.........完整代码请登录后点击上方下载按钮下载查看















网友评论0