4bf614a07c
编排好的 Agent 现在可命名保存到服务端、跨会话可见;左侧「我的编排」列出本人全部。
- store: sundynix_agent 表(owner+name 唯一,Graph=React Flow {nodes,edges} JSON 含布局,
UpdatedAt);ListAgents(最近在前)/SaveAgent(OnConflict 覆盖图+时间)/DeleteAgent。AutoMigrate +Agent。
- gateway: GET/POST/DELETE /api/v1/agents(owner 隔离,身份取自 X-User-ID)。
- 前端:api listAgents/saveAgent/deleteAgent;StudioView 左面板下半区「我的编排(N)」列出本人编排,
点击载入(含布局)、悬停删除;工具栏 编排名+保存(服务端),去掉 localStorage 模板。
验证:curl 保存「合同审查流程」→ wt 列表含之,alice 列表为空(隔离)。Preview:示例图填名「尽调问答
Agent」保存 → 左「我的编排(2)」即时出现两条、可点载入。tsc+vite+gateway build 通过;重建 .app。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AgentList: GET /api/v1/agents —— 当前用户保存的全部 Agent 编排(owner 隔离,最近在前)。
|
|
func (h *Handler) AgentList(c *gin.Context) {
|
|
rows, err := h.db.ListAgents(c.Request.Context(), userID(c))
|
|
if err != nil {
|
|
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
out := make([]gin.H, 0, len(rows))
|
|
for _, r := range rows {
|
|
out = append(out, gin.H{"name": r.Name, "graph": r.Graph, "updated_at": r.UpdatedAt})
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"agents": out})
|
|
}
|
|
|
|
// AgentSave: POST /api/v1/agents {name, graph} —— 保存/更新一份编排(graph 为 {nodes,edges} JSON)。
|
|
func (h *Handler) AgentSave(c *gin.Context) {
|
|
var body struct {
|
|
Name string `json:"name"`
|
|
Graph string `json:"graph"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil || strings.TrimSpace(body.Name) == "" || strings.TrimSpace(body.Graph) == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "name/graph required"})
|
|
return
|
|
}
|
|
if err := h.db.SaveAgent(c.Request.Context(), userID(c), strings.TrimSpace(body.Name), body.Graph); err != nil {
|
|
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"name": strings.TrimSpace(body.Name)})
|
|
}
|
|
|
|
// AgentDelete: DELETE /api/v1/agents?name= —— 删除一份编排。
|
|
func (h *Handler) AgentDelete(c *gin.Context) {
|
|
name := strings.TrimSpace(c.Query("name"))
|
|
if name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "name required"})
|
|
return
|
|
}
|
|
if err := h.db.DeleteAgent(c.Request.Context(), userID(c), name); err != nil {
|
|
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
}
|