ACP / MCP

This commit is contained in:
2026-06-12 11:44:19 +08:00
parent 2a9661a6ef
commit 4ea4adfd8e
47 changed files with 2558 additions and 240 deletions
+86
View File
@@ -68,6 +68,11 @@ func (h *Handler) Mount(r chi.Router) {
r.Get("/{id}", h.getAgentKind)
r.Patch("/{id}", h.updateAgentKind)
r.Delete("/{id}", h.deleteAgentKind)
// 配置文件管理(admin only,service 层鉴权)。rel_path 含斜杠,
// 不放 URL path,统一走 body / query。
r.Get("/{id}/config-files", h.listConfigFiles)
r.Put("/{id}/config-files", h.upsertConfigFile)
r.Delete("/{id}/config-files", h.deleteConfigFile)
})
r.Route("/api/v1/acp/sessions", func(r chi.Router) {
r.Use(middleware.Auth(h.resolver, middleware.AuthOptions{}))
@@ -209,6 +214,8 @@ func (h *Handler) createAgentKind(w http.ResponseWriter, r *http.Request) {
Env: req.Env,
Enabled: enabled,
ToolAllowlist: req.ToolAllowlist,
ClientType: ClientType(req.ClientType),
MCPServers: req.MCPServers,
}
out, err := h.akSvc.Create(r.Context(), c, in)
if err != nil {
@@ -265,6 +272,11 @@ func (h *Handler) updateAgentKind(w http.ResponseWriter, r *http.Request) {
Env: req.Env,
Enabled: req.Enabled,
ToolAllowlist: req.ToolAllowlist,
MCPServers: req.MCPServers,
}
if req.ClientType != nil {
ct := ClientType(*req.ClientType)
in.ClientType = &ct
}
out, err := h.akSvc.Update(r.Context(), c, id, in)
if err != nil {
@@ -292,6 +304,74 @@ func (h *Handler) deleteAgentKind(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
// ===== AgentKind 配置文件 endpoints =====
func (h *Handler) listConfigFiles(w http.ResponseWriter, r *http.Request) {
c, err := h.caller(r)
if err != nil {
writeErr(w, r, err)
return
}
id, perr := uuid.Parse(chi.URLParam(r, "id"))
if perr != nil {
writeErr(w, r, errs.New(errs.CodeInvalidInput, "bad id"))
return
}
files, err := h.akSvc.ListConfigFiles(r.Context(), c, id)
if err != nil {
writeErr(w, r, err)
return
}
out := make([]ConfigFileDTO, 0, len(files))
for _, f := range files {
out = append(out, configFileToDTO(f))
}
httpx.WriteJSON(w, http.StatusOK, out)
}
func (h *Handler) upsertConfigFile(w http.ResponseWriter, r *http.Request) {
c, err := h.caller(r)
if err != nil {
writeErr(w, r, err)
return
}
id, perr := uuid.Parse(chi.URLParam(r, "id"))
if perr != nil {
writeErr(w, r, errs.New(errs.CodeInvalidInput, "bad id"))
return
}
var req UpsertConfigFileReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeErr(w, r, errs.New(errs.CodeInvalidInput, "bad json"))
return
}
out, err := h.akSvc.UpsertConfigFile(r.Context(), c, id, req.RelPath, req.Content)
if err != nil {
writeErr(w, r, err)
return
}
httpx.WriteJSON(w, http.StatusOK, configFileToDTO(out))
}
func (h *Handler) deleteConfigFile(w http.ResponseWriter, r *http.Request) {
c, err := h.caller(r)
if err != nil {
writeErr(w, r, err)
return
}
id, perr := uuid.Parse(chi.URLParam(r, "id"))
if perr != nil {
writeErr(w, r, errs.New(errs.CodeInvalidInput, "bad id"))
return
}
relPath := r.URL.Query().Get("rel_path")
if err := h.akSvc.DeleteConfigFile(r.Context(), c, id, relPath); err != nil {
writeErr(w, r, err)
return
}
w.WriteHeader(http.StatusNoContent)
}
// ===== Session endpoints =====
func (h *Handler) listSessions(w http.ResponseWriter, r *http.Request) {
@@ -617,6 +697,10 @@ func (h *Handler) agentKindToAdminDTO(k *AgentKind) AgentKindAdminDTO {
sort.Strings(envKeys)
}
}
mcpServers := []McpServerSpec{}
if servers, err := decryptMCPServers(h.enc, k.EncryptedMCPServers); err == nil {
mcpServers = servers
}
return AgentKindAdminDTO{
ID: k.ID,
Name: k.Name,
@@ -627,6 +711,8 @@ func (h *Handler) agentKindToAdminDTO(k *AgentKind) AgentKindAdminDTO {
EnvKeys: envKeys,
Enabled: k.Enabled,
ToolAllowlist: append([]string(nil), k.ToolAllowlist...),
ClientType: string(k.ClientType),
MCPServers: mcpServers,
CreatedBy: k.CreatedBy,
CreatedAt: k.CreatedAt.UTC().Format("2006-01-02T15:04:05Z"),
UpdatedAt: k.UpdatedAt.UTC().Format("2006-01-02T15:04:05Z"),