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>
71 lines
3.4 KiB
Go
71 lines
3.4 KiB
Go
// Package router 装配 Gin 统一接入层的路由与中间件。
|
||
package router
|
||
|
||
import (
|
||
"github.com/gin-gonic/gin"
|
||
|
||
"github.com/sundynix/sundynix-gateway/internal/handler"
|
||
"github.com/sundynix/sundynix-gateway/internal/middleware"
|
||
"github.com/sundynix/sundynix-gateway/internal/nats"
|
||
"github.com/sundynix/sundynix-gateway/internal/store"
|
||
)
|
||
|
||
// New 构建带有 Guardrail / 限流中间件的 Gin 引擎。
|
||
func New(db *store.Postgres, cache *store.Redis, bus *nats.Bus) *gin.Engine {
|
||
r := gin.Default()
|
||
r.Use(cors()) // 桌面端/浏览器跨源访问(开发期放开)
|
||
r.Use(middleware.RateLimit(cache))
|
||
r.Use(middleware.Guardrail()) // Harness: Input/Output Guardrail
|
||
|
||
h := handler.New(db, cache, bus)
|
||
api := r.Group("/api/v1")
|
||
{
|
||
api.POST("/tasks", h.SubmitTask) // 1. 解析 DSL 并 Publish 到 NATS
|
||
api.GET("/tasks/:id/stream", h.StreamTask) // 4. SSE/WS 回流 Token Stream
|
||
api.GET("/tasks/:id/exec", h.StreamExec) // 4b. SSE 回流执行轨迹事件(运行·观测)
|
||
api.PUT("/memory", h.SetMemory) // 偏好记忆登记(→ mcp-go memory_upsert)
|
||
api.GET("/kb/list", h.KbList) // 当前用户的知识库列表(owner 隔离)
|
||
api.POST("/kb/create", h.KbCreate) // 新建知识库(项目/案件/文件夹/通用)
|
||
api.POST("/kb/ingest", h.KbIngest) // 知识库入库(文本,→ mcp-go kb_ingest)
|
||
api.POST("/kb/ingest_file", h.KbIngestFile) // 文件入库(docx/xlsx/pdf… 异步)
|
||
api.GET("/kb/ingest/:id/stream", h.KbIngestStream) // 入库进度 SSE(实时监控)
|
||
api.POST("/kb/search", h.KbSearch) // 知识库检索台(→ mcp-go kb_search)
|
||
api.GET("/kb/vault", h.KbVault) // 文库:原始文档浏览(Obsidian 式)
|
||
api.POST("/kb/note", h.KbSaveNote) // 新建/编辑笔记(落库 + 按 doc 重入库)
|
||
api.GET("/kb/graph", h.KbGraph) // 知识图谱三元组(→ mcp-go kb_graph,Neo4j)
|
||
|
||
api.GET("/agents", h.AgentList) // 我的 Agent 编排列表(owner 隔离)
|
||
api.POST("/agents", h.AgentSave) // 保存/更新编排
|
||
api.DELETE("/agents", h.AgentDelete) // 删除编排
|
||
api.POST("/reports", h.GenerateReport) // 报告生成(intent=report 任务 → Dispatcher 专用编排)
|
||
api.GET("/reports/:id/download", h.DownloadReport) // 下载渲染好的 Word(.docx)
|
||
api.GET("/health", h.Health) // 依赖健康聚合(顶栏五盏灯)
|
||
api.GET("/billing", h.Billing)
|
||
|
||
// 运维控制面:LLM 模型配置(独立运维控制台调用)。
|
||
admin := api.Group("/admin")
|
||
{
|
||
admin.GET("/models", h.ListModels)
|
||
admin.POST("/models", h.SaveModel)
|
||
admin.POST("/models/:id/active", h.SetActiveModel)
|
||
admin.DELETE("/models/:id", h.DeleteModel)
|
||
admin.POST("/models/test", h.TestModel)
|
||
}
|
||
}
|
||
return r
|
||
}
|
||
|
||
// cors 放开跨源访问,允许桌面端/浏览器带自定义身份头与 SSE 访问网关(开发期)。
|
||
func cors() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
c.Header("Access-Control-Allow-Origin", "*")
|
||
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||
c.Header("Access-Control-Allow-Headers", "Content-Type, X-User-ID, X-Session-ID")
|
||
if c.Request.Method == "OPTIONS" {
|
||
c.AbortWithStatus(204)
|
||
return
|
||
}
|
||
c.Next()
|
||
}
|
||
}
|