mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 16:52:00 +00:00
964eeaa829
在画布上拖拽编排 agent 工作流,并实时看着它执行。 后端 FastAPI + LangGraph:把画布 JSON 编译成 StateGraph,15 种节点 (模型/Agent/多Agent、工具/沙箱、分支/循环/子图、记忆/检索/整形、 人工介入/结构校验)。选 LangGraph 是因为可视化编排真正难的是暂停、 恢复和回放,而 checkpointer + interrupt() 正好把这几件事做在了底层。 前端 React + React Flow:节点元数据驱动属性面板与连接桩,运行时 节点高亮、边流动画、卡片内流式 token 全部由同一份事件流驱动。 关键实现: - Agent 内工具审批用 @task 缓存模型调用,interrupt 重放时不重复计费 - 沙箱保持只读根文件系统,代码经 exec+base64 写入(put_archive 会被 只读容器拒绝),断网、非 root、内存/CPU/超时限额 - 检索为向量与 BM25 混合,本地哈希 embedding 零配置可用 - 分支条件走 AST 白名单求值器;HTTP 工具逐 IP 拦截内网与元数据地址 - Mock provider 让无 API Key 也能跑通完整链路 7 个内置模板全部冒烟通过,含真实模型端到端验证。
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter
|
|
from pydantic import BaseModel, Field
|
|
|
|
from app.sandbox.base import SandboxLimits
|
|
from app.sandbox.manager import sandbox_manager
|
|
|
|
router = APIRouter(prefix="/api/sandbox", tags=["sandbox"])
|
|
|
|
|
|
@router.get("/health")
|
|
async def health() -> dict[str, Any]:
|
|
return await sandbox_manager.health()
|
|
|
|
|
|
class ExecIn(BaseModel):
|
|
code: str = Field(min_length=1)
|
|
language: str = "python"
|
|
timeout: int = Field(default=30, ge=1, le=300)
|
|
memory_mb: int = Field(default=512, ge=64, le=4096)
|
|
network: bool = False
|
|
session_id: str = "playground"
|
|
files: dict[str, str] = Field(default_factory=dict)
|
|
|
|
|
|
@router.post("/exec")
|
|
async def execute(payload: ExecIn) -> dict[str, Any]:
|
|
"""沙箱试验台。在画布外面直接跑一段代码,用来试限额、试依赖。"""
|
|
result = await sandbox_manager.run(
|
|
payload.code,
|
|
language=payload.language,
|
|
limits=SandboxLimits(
|
|
timeout=payload.timeout,
|
|
memory_mb=payload.memory_mb,
|
|
network=payload.network,
|
|
),
|
|
session_id=payload.session_id,
|
|
files=payload.files,
|
|
)
|
|
return result.model_dump()
|
|
|
|
|
|
@router.post("/cleanup/{session_id}")
|
|
async def cleanup(session_id: str) -> dict[str, bool]:
|
|
await sandbox_manager.cleanup(session_id)
|
|
return {"ok": True}
|