# TraceStudio — 后端 API 文档(server 视角) 本文件以实现代码为准,汇总了当前后端提供的 HTTP API(可用于生成 OpenAPI 或 mock server)。所有路径以服务器根地址为前缀,路由通常被挂载在 `/api` 下(例如最终完整路径为 `/api/files/list`)。 **概览** - **Backend stack**: FastAPI(Python 3.11+)、Polars、自定义节点加载/执行框架。 - **安全约定**: 所有文件路径会经过 `sanitize_path` / `is_safe_path` 校验以防目录遍历;自定义节点文件名通过 `NodeValidator.is_safe_filename` 验证。 **DataFrame 序列化说明** - **字段约定**: 后端在返回计算结果中会将 `polars.DataFrame` 序列化为一个带 `__type: DataFrame` 的对象以便前端预览与分页请求。 - **结构示例**: ```json { "__type": "DataFrame", "columns": ["col1", "col2"], "preview": [{"col1": 1, "col2": "a"}, ...], "rows": 1234 } ``` 此格式用于 `/node/preview` 返回和 `/graph/execute` 中每个节点 outputs 的预览。`preview` 的长度受服务端限制(通常为 10 或 20)。 **全局错误处理约定** - 成功返回一般为 JSON 对象并包含 `success` 或 `status: "success"`。 - 失败时使用 HTTP 错误码(400/403/404/500)并在 body 中提供 `detail` 字段;`/graph/execute` 在 500 时会返回更详细的 `traceback` 对象。 -- **1) 文件与文件管理(Files)** 说明: 文件相关接口分布在 `server/file_manager.py`(router prefix `/api/files`)与 `server/app/api/endpoints_upload.py`(被挂载到 `/api`,内部路径为 `/files/*`),两套接口在功能上有重叠,前端可以任选其一,推荐使用 `/api/files/*` 族。 - `GET /api/files/list` — 列出目录 - Query: `path`(string, 可空,空或 `/` 表示根),`username`(可选,用于确保用户目录存在) - Response: `{ "path": "...", "items": [ {name,path,type,size,modified,extension}, ... ] } - Errors: 400(路径不是目录)、403(路径非法)、404(路径不存在)、500(读取失败) - `POST /api/files/upload` — 上传文件(multipart) - Form: `file` (multipart file) - Query: `path`(目标目录)、`username`(可选) - Response: `{ "success": true, "file": FileInfo, "message": "..." }` - Notes: 如果同名文件已存在会自动加后缀避免覆盖(除非使用专门的 save/force 接口)。 - `POST /api/files/action` — 文件基本操作 - Body: `FileAction` 模型 `{ action, path, target?, new_name? }` - 支持操作: `move`, `delete`, `mkdir`, `rename` - Response: 视操作返回 `{ success: true, ... }` 或详细信息 - `GET /api/files/download` — 下载 - Query: `path`(必需) - Response: 返回 `FileResponse` (streamed) - `GET /api/files/info` — 获取文件/文件夹信息 - Query: `path`(必需) - Response: `FileInfo`(或 `{ exists: false }`) 模型参考 (`FileInfo`, `FileAction`) ```py class FileInfo(BaseModel): name: str path: str type: str # 'file' | 'folder' size: Optional[int] modified: Optional[str] extension: Optional[str] class FileAction(BaseModel): action: str # 'move'|'delete'|'mkdir'|'rename' path: str target: Optional[str] new_name: Optional[str] ``` 实现状态: 已实现(路径清理、权限检查、用户目录创建、重命名/删除/移动、下载流)。 -- **2) 图/节点(Graph & Node)** - `GET /api/plugins` — 获取可用节点插件 - Response: `{ "plugins": { class_name: metadata }, "total": N, "categories": [...] }` - Notes: metadata 包含 `display_name`, `category`, `description`, `inputs`, `outputs`, `param_schema`, `class_name` 等。 - `POST /api/node/preview` — 预览单个节点执行结果 - Body: `NodePreviewRequest` `{ node: NodeSchema, limit: int = 10 }` - NodeSchema 支持 `data` 或 `params` 两种字段(兼容历史 payload) - Response 示例: ```json { "class_name": "MyNode", "status": "success", "columns": ["a","b"], "preview": [{"a":1,"b":2}], "context": {...} } ``` - `POST /api/graph/execute` — 执行完整图 - Body: `GraphExecuteRequest` `{ nodes: [NodeSchema], edges: [EdgeSchema], settings?: {} }` - Response (成功示例): ```json { "status": "success", "message": "成功执行 3 个节点", "execution_time": 0.123, "results": { "node1": { "status": "ok", "outputs": {"out": {"__type":"DataFrame", ...}}, "error": null } }, "stats": { "total_nodes": 3, "total_edges": 2, "execution_order": ["node1","node2"] } } ``` - 返回格式说明: `results` 为 node_id 映射;每个节点包含 `status`, `outputs`, `error`。如果输出为 DataFrame,按上文序列化规则返回。 模型摘要 (`NodeSchema`, `EdgeSchema`, `GraphExecuteRequest`) ```py class NodeSchema(BaseModel): id: str type: str class_name: Optional[str] function: Optional[str] data: Optional[Dict[str,Any]] params: Optional[Dict[str,Any]] class EdgeSchema(BaseModel): id: Optional[str] source: str target: str dimension_mode: str source_port: Optional[str] target_port: Optional[str] class GraphExecuteRequest(BaseModel): nodes: List[NodeSchema] edges: List[EdgeSchema] settings: Optional[Dict[str,Any]] ``` 实现状态: 已实现。注意:后端兼容旧/新 executor 返回格式(可能是 `node_infos/node_results` 或 node_id->info 映射)。`/nodes/save` 接口为占位,尚需实现持久化策略。 -- **3) 自定义节点管理(Custom Nodes)** - 前缀: `/api/custom-nodes/*` - `GET /api/custom-nodes/list` — 列出自定义节点文件(含验证状态) - `POST /api/custom-nodes/validate` — 验证节点代码(不保存) - Body: `{ code: str, filename?: str }` - Response: `{ success: true, validation: { valid: bool, errors: [...] } }` - `GET /api/custom-nodes/read/{filename}` — 读取节点源码 - Response: `{ success: true, filename, code, size, modified }` - `POST /api/custom-nodes/save` — 保存并加载节点 - Body: `{ filename, code, force?: bool }` - 行为: 验证代码后保存,支持备份与强制覆盖,保存后调用 loader 加载节点并返回 `load_result`。 - `POST /api/custom-nodes/action` — 对节点执行 `load`/`unload`/`delete`/`rename` - `GET /api/custom-nodes/download/{filename}` — 下载节点文件 - `POST /api/custom-nodes/upload` — 上传节点文件(会验证并加载) - `GET /api/custom-nodes/loaded` — 返回运行时已加载类及其 metadata - `POST /api/custom-nodes/reload-all` — 重新加载所有自定义节点 - `GET /api/custom-nodes/example` — 返回示例节点代码(供编辑器使用) 模型参考 (`NodeValidateRequest`, `NodeSaveRequest`, `NodeActionRequest`) 实现状态: 功能齐全(验证、保存、备份、加载/卸载、列出、下载)。注意:保存/上传过程会在保存前使用 `validate_node_code` 做静态验证并在失败时阻止加载。 -- **4) 用户管理相关(简要)** - `GET /api/users/list` — 返回 `{ users: [...], count: N }` - `POST /api/users/add` — 接受 `{ username, display_name? }`,会验证用户名格式、写入 users DB 并创建用户工作区。 实现状态: 已实现(基础用户 CRUD 含创建与列表)。 -- **5) 其他/占位接口** - `POST /api/nodes/save` — 当前仅作占位,返回 success: true;需要后续实现节点保存到文件或 DB 的策略。 -- **对前端/集成测试的建议** - 使用 `NodeSchema` 中的 `class_name` 作为后端加载的实现类标识;如果客户端只提供 `data/params` 中的 `meta.class_name`,后端也会兼容读取。 - 推荐按 `__type: DataFrame` 约定解析节点输出并在前端提供 DataFrame 视图组件(columns + preview + rows)。 - 自定义节点上传必须在后端验证通过后才加载,前端应展示 `validation` 结果并要求用户确认覆盖。 -- 如需我把上述模型转换为可直接导入的 OpenAPI spec(`openapi.json`)以便一键生成 mock server 或 SDK,请回复确认,我会在下一步生成并附上简化 schema 片段。 --- 引用实现: [server/file_manager.py](server/file_manager.py#L1-L400) 参考实现: [server/app/api/endpoints_upload.py](server/app/api/endpoints_upload.py#L1-L400), [server/app/api/endpoints_graph.py](server/app/api/endpoints_graph.py#L1-L400), [server/app/api/endpoints_custom_nodes.py](server/app/api/endpoints_custom_nodes.py#L1-L400)