8.4 KiB
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的对象以便前端预览与分页请求。 - 结构示例:
{
"__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(读取失败)
- Query:
-
POST /api/files/upload— 上传文件(multipart)- Form:
file(multipart file) - Query:
path(目标目录)、username(可选) - Response:
{ "success": true, "file": FileInfo, "message": "..." } - Notes: 如果同名文件已存在会自动加后缀避免覆盖(除非使用专门的 save/force 接口)。
- Form:
-
POST /api/files/action— 文件基本操作- Body:
FileAction模型{ action, path, target?, new_name? } - 支持操作:
move,delete,mkdir,rename - Response: 视操作返回
{ success: true, ... }或详细信息
- Body:
-
GET /api/files/download— 下载- Query:
path(必需) - Response: 返回
FileResponse(streamed)
- Query:
-
GET /api/files/info— 获取文件/文件夹信息- Query:
path(必需) - Response:
FileInfo(或{ exists: false })
- Query:
模型参考 (FileInfo, FileAction)
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等。
- Response:
-
POST /api/node/preview— 预览单个节点执行结果- Body:
NodePreviewRequest{ node: NodeSchema, limit: int = 10 } - NodeSchema 支持
data或params两种字段(兼容历史 payload) - Response 示例:
- Body:
{
"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 (成功示例):
- Body:
{
"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)
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: [...] } }
- Body:
-
GET /api/custom-nodes/read/{filename}— 读取节点源码- Response:
{ success: true, filename, code, size, modified }
- Response:
-
POST /api/custom-nodes/save— 保存并加载节点- Body:
{ filename, code, force?: bool } - 行为: 验证代码后保存,支持备份与强制覆盖,保存后调用 loader 加载节点并返回
load_result。
- Body:
-
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/app/api/endpoints_upload.py, server/app/api/endpoints_graph.py, server/app/api/endpoints_custom_nodes.py