diff --git a/agent/app/dto/request/runtime.go b/agent/app/dto/request/runtime.go index 3d7a844b3096..d4dd9db53ee0 100644 --- a/agent/app/dto/request/runtime.go +++ b/agent/app/dto/request/runtime.go @@ -42,12 +42,14 @@ type Environment struct { type Volume struct { Source string `json:"source"` Target string `json:"target"` + Mode string `json:"mode"` } type ExposedPort struct { HostPort int `json:"hostPort"` ContainerPort int `json:"containerPort"` HostIP string `json:"hostIP"` + Protocol string `json:"protocol"` } type ExtraHost struct { diff --git a/agent/app/service/app_utils.go b/agent/app/service/app_utils.go index 66869f78e77a..8f3fc4b3cea9 100644 --- a/agent/app/service/app_utils.go +++ b/agent/app/service/app_utils.go @@ -89,7 +89,15 @@ func checkPort(key string, params map[string]interface{}) (int, error) { return 0, nil } +func isPortInUse(port int, protocol string) bool { + return common.ScanPortWithProto(port, normalizeComposeProtocol(protocol)) +} + func checkPortExist(port int) error { + return checkPortExistWithProtocol(port, "") +} + +func checkPortExistWithProtocol(port int, protocol string) error { errMap := make(map[string]interface{}) errMap["port"] = port appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) @@ -110,7 +118,7 @@ func checkPortExist(port int) error { errMap["name"] = domain.Domain return buserr.WithMap("ErrPortExist", errMap, nil) } - if common.ScanPort(port) { + if isPortInUse(port, protocol) { return buserr.WithDetail("ErrPortInUsed", port, nil) } return nil diff --git a/agent/app/service/docker_compose_config.go b/agent/app/service/docker_compose_config.go new file mode 100644 index 000000000000..91a15a9a29ca --- /dev/null +++ b/agent/app/service/docker_compose_config.go @@ -0,0 +1,84 @@ +package service + +import ( + "fmt" + "strconv" + "strings" + + "github.com/1Panel-dev/1Panel/agent/app/dto/request" +) + +func composePortEnvKeys(index int) (containerPort, hostPort, hostIP, protocol string) { + return fmt.Sprintf("CONTAINER_PORT_%d", index), + fmt.Sprintf("HOST_PORT_%d", index), + fmt.Sprintf("HOST_IP_%d", index), + fmt.Sprintf("PORT_PROTOCOL_%d", index) +} + +func isComposePortEnvKey(key string) bool { + return strings.HasPrefix(key, "CONTAINER_PORT_") || + strings.HasPrefix(key, "HOST_PORT_") || + strings.HasPrefix(key, "HOST_IP_") || + strings.HasPrefix(key, "PORT_PROTOCOL_") +} + +func formatComposePortMapping(hostIP, hostPort, containerPort, protocol string) string { + return fmt.Sprintf("${%s}:${%s}:${%s}/%s", hostIP, hostPort, containerPort, normalizeComposeProtocol(protocol)) +} + +func normalizeComposeProtocol(protocol string) string { + switch strings.ToLower(strings.TrimSpace(protocol)) { + case "udp": + return "udp" + default: + return "tcp" + } +} + +func formatComposeVolume(source, target, mode string) string { + return fmt.Sprintf("%s:%s:%s", source, target, normalizeComposeVolumeMode(mode)) +} + +func normalizeComposeVolumeMode(mode string) string { + switch strings.ToLower(strings.TrimSpace(mode)) { + case "ro": + return "ro" + default: + return "rw" + } +} + +func loadComposeExposedPortsFromEnv(envs map[string]string, defaultHostIP string, strict bool) ([]request.ExposedPort, error) { + var ports []request.ExposedPort + for key, value := range envs { + if !strings.HasPrefix(key, "CONTAINER_PORT_") { + continue + } + index := strings.TrimPrefix(key, "CONTAINER_PORT_") + containerPort, err := strconv.Atoi(value) + if err != nil { + if strict { + return nil, err + } + continue + } + hostPort, err := strconv.Atoi(envs["HOST_PORT_"+index]) + if err != nil { + if strict { + return nil, err + } + continue + } + hostIP := envs["HOST_IP_"+index] + if hostIP == "" { + hostIP = defaultHostIP + } + ports = append(ports, request.ExposedPort{ + ContainerPort: containerPort, + HostPort: hostPort, + HostIP: hostIP, + Protocol: normalizeComposeProtocol(envs["PORT_PROTOCOL_"+index]), + }) + } + return ports, nil +} diff --git a/agent/app/service/mcp_server.go b/agent/app/service/mcp_server.go index 9e40e8a35d55..ecca6d326bca 100644 --- a/agent/app/service/mcp_server.go +++ b/agent/app/service/mcp_server.go @@ -792,9 +792,14 @@ func loadMcpServerComposeConfig(serverDTO *response.McpServerDTO) error { } if service.Volumes != nil { for _, volume := range service.Volumes { + mode := "rw" + if volume.ReadOnly { + mode = "ro" + } serverDTO.Volumes = append(serverDTO.Volumes, request.Volume{ Source: volume.Source, Target: volume.Target, + Mode: mode, }) } } @@ -850,6 +855,9 @@ func handleCreateParams(mcpServer *model.McpServer, environments []request.Envir normalizeMcpServerGateway(mcpServer) serviceValue["command"] = buildSupergatewayCommand(mcpServer) serviceValue["image"] = mcpServer.GatewayImage + serviceValue["ports"] = []string{ + formatComposePortMapping("HOST_IP", "PANEL_APP_PORT_HTTP", "PANEL_APP_PORT_HTTP", ""), + } oldEnv, hasOldEnv := serviceValue["environment"] delete(serviceValue, "environment") if environments != nil && len(environments) > 0 { @@ -869,7 +877,7 @@ func handleCreateParams(mcpServer *model.McpServer, environments []request.Envir if volumes != nil && len(volumes) > 0 { volumeList := make([]string, 0) for _, volume := range volumes { - volumeList = append(volumeList, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) + volumeList = append(volumeList, formatComposeVolume(volume.Source, volume.Target, volume.Mode)) } serviceValue["volumes"] = volumeList } else if volumes == nil { diff --git a/agent/app/service/runtime.go b/agent/app/service/runtime.go index a52b5a900df6..2c55c588b5b1 100644 --- a/agent/app/service/runtime.go +++ b/agent/app/service/runtime.go @@ -137,7 +137,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e create.Install = true for _, export := range create.ExposedPorts { hostPorts = append(hostPorts, strconv.Itoa(export.HostPort)) - if err := checkPortExist(export.HostPort); err != nil { + if err := checkPortExistWithProtocol(export.HostPort, export.Protocol); err != nil { return nil, err } } @@ -241,30 +241,11 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt runtimeDTO.AppID = detail.AppId } for k, v := range envs { - runtimeDTO.Params[k] = v - if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { - if strings.Contains(k, "CONTAINER_PORT") { - matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k) - if len(matches) < 2 { - continue - } - containerPort, err := strconv.Atoi(v) - if err != nil { - continue - } - hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])]) - if err != nil { - continue - } - hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])] - runtimeDTO.ExposedPorts = append(runtimeDTO.ExposedPorts, request.ExposedPort{ - ContainerPort: containerPort, - HostPort: hostPort, - HostIP: hostIP, - }) - } + if !isComposePortEnvKey(k) { + runtimeDTO.Params[k] = v } } + runtimeDTO.ExposedPorts, _ = loadComposeExposedPortsFromEnv(envs, "", false) res = append(res, runtimeDTO) } return total, res, nil @@ -435,9 +416,11 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { return buserr.New("ErrImageExist") } case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet: + ownedPortKeys := runtimeOwnedPortKeys(runtime.Env) for _, export := range req.ExposedPorts { hostPorts = append(hostPorts, strconv.Itoa(export.HostPort)) - if err = checkRuntimePortExist(export.HostPort, false, runtime.ID); err != nil { + _, owned := ownedPortKeys[composePortCheckKey(export.HostPort, export.Protocol)] + if err = checkRuntimePortExistWithProtocol(export.HostPort, export.Protocol, !owned, runtime.ID); err != nil { return err } } @@ -1058,6 +1041,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro var ( composeContent []byte ) + ownedPortKeys := runtimeOwnedPortKeys(runtime.Env) for _, export := range req.ExposedPorts { if strconv.Itoa(export.HostPort) == runtime.Port { return buserr.WithName("ErrPHPRuntimePortFailed", strconv.Itoa(export.HostPort)) @@ -1065,7 +1049,8 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro if export.ContainerPort == 9000 { return buserr.New("ErrPHPPortIsDefault") } - if err = checkRuntimePortExist(export.HostPort, false, runtime.ID); err != nil { + _, owned := ownedPortKeys[composePortCheckKey(export.HostPort, export.Protocol)] + if err = checkRuntimePortExistWithProtocol(export.HostPort, export.Protocol, !owned, runtime.ID); err != nil { return err } } @@ -1090,7 +1075,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro return err } for k := range envs { - if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") || strings.HasPrefix(k, "HOST_IP_") || strings.Contains(k, "APP_PORT") { + if isComposePortEnvKey(k) || strings.Contains(k, "APP_PORT") { delete(envs, k) } } @@ -1102,6 +1087,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro ExposedPorts: req.ExposedPorts, Environments: req.Environments, Volumes: req.Volumes, + ExtraHosts: req.ExtraHosts, }, } composeContent, err = handleCompose(envs, composeContent, create, projectDir) diff --git a/agent/app/service/runtime_utils.go b/agent/app/service/runtime_utils.go index 1bddc8385361..ceba002c9308 100644 --- a/agent/app/service/runtime_utils.go +++ b/agent/app/service/runtime_utils.go @@ -19,7 +19,6 @@ import ( cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/i18n" - "github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto/request" @@ -33,7 +32,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/files" - "github.com/1Panel-dev/1Panel/agent/utils/re" "github.com/pkg/errors" "github.com/subosito/gotenv" "gopkg.in/yaml.v3" @@ -464,7 +462,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte return } for k := range env { - if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") || strings.HasPrefix(k, "HOST_IP_") || strings.Contains(k, "APP_PORT") { + if isComposePortEnvKey(k) || strings.Contains(k, "APP_PORT") { delete(env, k) } } @@ -621,15 +619,16 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime if len(create.ExposedPorts) > 0 { var ports []interface{} for i, port := range create.ExposedPorts { - containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) - hostPortStr := fmt.Sprintf("HOST_PORT_%d", i) + containerPortStr, hostPortStr, hostIPStr, protocolStr := composePortEnvKeys(i) existMap[containerPortStr] = struct{}{} existMap[hostPortStr] = struct{}{} - hostIPStr := fmt.Sprintf("HOST_IP_%d", i) - ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr)) + existMap[hostIPStr] = struct{}{} + existMap[protocolStr] = struct{}{} + ports = append(ports, formatComposePortMapping(hostIPStr, hostPortStr, containerPortStr, port.Protocol)) create.Params[containerPortStr] = port.ContainerPort create.Params[hostPortStr] = port.HostPort create.Params[hostIPStr] = port.HostIP + create.Params[protocolStr] = normalizeComposeProtocol(port.Protocol) } if create.Type == constant.RuntimePHP { ports = append(ports, "127.0.0.1:${PANEL_APP_PORT_HTTP}:9000") @@ -662,7 +661,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime volumes = append(volumes, fmt.Sprintf("%s:%s", k, v)) } for _, volume := range create.Volumes { - volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) + volumes = append(volumes, formatComposeVolume(volume.Source, volume.Target, volume.Mode)) } var extraHosts []interface{} @@ -678,7 +677,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime break } for k := range env { - if strings.Contains(k, "CONTAINER_PORT_") || strings.Contains(k, "HOST_PORT_") { + if isComposePortEnvKey(k) { if _, ok := existMap[k]; !ok { delete(env, k) } @@ -872,9 +871,14 @@ func getDockerComposeVolumes(yml []byte) ([]request.Volume, error) { if len(envArray) > 1 { target = envArray[1] } + mode := "" + if len(envArray) > 2 { + mode = envArray[2] + } res = append(res, request.Volume{ Source: source, Target: target, + Mode: normalizeComposeVolumeMode(mode), }) } } @@ -908,7 +912,31 @@ func getDockerComposeExtraHosts(yml []byte) ([]request.ExtraHost, error) { return res, nil } +func composePortCheckKey(port int, protocol string) string { + return fmt.Sprintf("%d/%s", port, normalizeComposeProtocol(protocol)) +} + +func runtimeOwnedPortKeys(envStr string) map[string]struct{} { + portKeys := make(map[string]struct{}) + envs, err := gotenv.Unmarshal(envStr) + if err != nil { + return portKeys + } + exposedPorts, err := loadComposeExposedPortsFromEnv(envs, "", false) + if err != nil { + return portKeys + } + for _, port := range exposedPorts { + portKeys[composePortCheckKey(port.HostPort, port.Protocol)] = struct{}{} + } + return portKeys +} + func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error { + return checkRuntimePortExistWithProtocol(port, "", scanPort, runtimeID) +} + +func checkRuntimePortExistWithProtocol(port int, protocol string, scanPort bool, runtimeID uint) error { errMap := make(map[string]interface{}) errMap["port"] = port appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) @@ -933,7 +961,7 @@ func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error { errMap["name"] = domain.Domain return buserr.WithMap("ErrPortExist", errMap, nil) } - if scanPort && common.ScanPort(port) { + if scanPort && isPortInUse(port, protocol) { return buserr.WithDetail("ErrPortInUsed", port, nil) } return nil @@ -1006,31 +1034,16 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error { return err } for k, v := range envs { - if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { - if strings.Contains(k, "CONTAINER_PORT") { - matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k) - if len(matches) < 2 { - return fmt.Errorf("invalid container port key: %s", k) - } - containerPort, err := strconv.Atoi(v) - if err != nil { - return err - } - hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])]) - if err != nil { - return err - } - hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])] - res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{ - ContainerPort: containerPort, - HostPort: hostPort, - HostIP: hostIP, - }) - } + if isComposePortEnvKey(k) { + continue } else { res.Params[k] = v } } + res.ExposedPorts, err = loadComposeExposedPortsFromEnv(envs, "", true) + if err != nil { + return err + } if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok { res.Source = v } diff --git a/agent/app/service/tensorrt_llm.go b/agent/app/service/tensorrt_llm.go index e944d83ac41c..5fbf68cb0b2d 100644 --- a/agent/app/service/tensorrt_llm.go +++ b/agent/app/service/tensorrt_llm.go @@ -23,7 +23,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/env" "github.com/1Panel-dev/1Panel/agent/utils/files" - "github.com/1Panel-dev/1Panel/agent/utils/re" ) type TensorRTLLMService struct{} @@ -59,33 +58,7 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR serverDTO.Image = envs["IMAGE"] serverDTO.Command = getCommand(item.Env) - for k, v := range envs { - if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { - if strings.Contains(k, "CONTAINER_PORT") { - matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k) - if len(matches) < 2 { - continue - } - containerPort, err := strconv.Atoi(v) - if err != nil { - continue - } - hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])]) - if err != nil { - continue - } - hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])] - if hostIP == "" { - hostIP = "0.0.0.0" - } - serverDTO.ExposedPorts = append(serverDTO.ExposedPorts, request.ExposedPort{ - ContainerPort: containerPort, - HostPort: hostPort, - HostIP: hostIP, - }) - } - } - } + serverDTO.ExposedPorts, _ = loadComposeExposedPortsFromEnv(envs, "0.0.0.0", false) composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml")) if err == nil { @@ -149,11 +122,9 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e delete(serviceValue, "ports") if len(create.ExposedPorts) > 0 { var ports []interface{} - for i := range create.ExposedPorts { - containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) - hostPortStr := fmt.Sprintf("HOST_PORT_%d", i) - hostIPStr := fmt.Sprintf("HOST_IP_%d", i) - ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr)) + for i, port := range create.ExposedPorts { + containerPortStr, hostPortStr, hostIPStr, _ := composePortEnvKeys(i) + ports = append(ports, formatComposePortMapping(hostIPStr, hostPortStr, containerPortStr, port.Protocol)) } serviceValue["ports"] = ports } @@ -174,7 +145,7 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e volumes = append(volumes, fmt.Sprintf("%s:%s", k, v)) } for _, volume := range create.Volumes { - volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) + volumes = append(volumes, formatComposeVolume(volume.Source, volume.Target, volume.Mode)) } serviceValue["volumes"] = volumes @@ -195,12 +166,11 @@ func handleLLMEnv(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) gote envMap["IMAGE"] = create.Image envMap["COMMAND"] = create.Command for i, port := range create.ExposedPorts { - containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) - hostPortStr := fmt.Sprintf("HOST_PORT_%d", i) - hostIPStr := fmt.Sprintf("HOST_IP_%d", i) + containerPortStr, hostPortStr, hostIPStr, protocolStr := composePortEnvKeys(i) envMap[containerPortStr] = strconv.Itoa(port.ContainerPort) envMap[hostPortStr] = strconv.Itoa(port.HostPort) envMap[hostIPStr] = port.HostIP + envMap[protocolStr] = normalizeComposeProtocol(port.Protocol) } orders := []string{"MODEL_PATH", "COMMAND"} envStr, _ := env.MarshalWithOrder(envMap, orders) @@ -219,7 +189,7 @@ func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error { } } for _, export := range create.ExposedPorts { - if err := checkPortExist(export.HostPort); err != nil { + if err := checkPortExistWithProtocol(export.HostPort, export.Protocol); err != nil { return err } } diff --git a/agent/cmd/server/docs/x-log.json b/agent/cmd/server/docs/x-log.json index f54046ade5ed..e6f894dd4089 100644 --- a/agent/cmd/server/docs/x-log.json +++ b/agent/cmd/server/docs/x-log.json @@ -1247,6 +1247,33 @@ "formatZH": "更新 AI 网关分组 [name]", "formatEN": "update AI proxy group [name]" }, + "/core/enterprise/ai-proxy/model-groups/create": { + "bodyKeys": [ + "name" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "创建 AI 网关模型组 [name]", + "formatEN": "create AI proxy model group [name]" + }, + "/core/enterprise/ai-proxy/model-groups/delete": { + "bodyKeys": [ + "id" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "删除 AI 网关模型组 [id]", + "formatEN": "delete AI proxy model group [id]" + }, + "/core/enterprise/ai-proxy/model-groups/update": { + "bodyKeys": [ + "name" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新 AI 网关模型组 [name]", + "formatEN": "update AI proxy model group [name]" + }, "/core/enterprise/ai-proxy/service/operate": { "bodyKeys": [ "operate" @@ -2166,6 +2193,15 @@ "formatZH": "更新自定义应用配置 [status]", "formatEN": "update custom app config [status]" }, + "/core/xpack/settings/app/image-prefix": { + "bodyKeys": [ + "imagePrefix" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新应用镜像前缀 [imagePrefix]", + "formatEN": "update app image prefix [imagePrefix]" + }, "/core/xpack/settings/reset": { "bodyKeys": [], "paramKeys": [], @@ -2193,25 +2229,13 @@ "/core/xpack/sync/app": { "bodyKeys": [ "sourceNode", - "targetNode", - "appInstallID", - "appBackupID" - ], - "paramKeys": [], - "beforeFunctions": [], - "formatZH": "同步应用备份 [appInstallID] 到节点 [targetNode]", - "formatEN": "sync app backup [appInstallID] to node [targetNode]" - }, - "/core/xpack/sync/app/install": { - "bodyKeys": [ - "appKey", - "version", - "nodes" + "targetNodes", + "appInstallID" ], "paramKeys": [], "beforeFunctions": [], - "formatZH": "安装应用 [appKey] [version] 到节点 [nodes]", - "formatEN": "install app [appKey] [version] to nodes [nodes]" + "formatZH": "同步应用 [appInstallID] 到节点 [targetNodes]", + "formatEN": "sync app [appInstallID] to nodes [targetNodes]" }, "/core/xpack/sync/ssl": { "bodyKeys": [ @@ -2352,6 +2376,15 @@ "formatZH": "更新自定义应用配置 [status]", "formatEN": "update custom app config [status]" }, + "/custom/app/image-prefix": { + "bodyKeys": [ + "imagePrefix" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新应用镜像前缀 [imagePrefix]", + "formatEN": "update app image prefix [imagePrefix]" + }, "/custom/app/install": { "bodyKeys": [ "name", @@ -2379,6 +2412,15 @@ "formatZH": "同步自定义应用商店", "formatEN": "sync custom app store" }, + "/custom/app/sync/backup": { + "bodyKeys": [ + "appInstallID" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "创建应用同步备份 [appInstallID]", + "formatEN": "create app sync backup [appInstallID]" + }, "/dashboard/app/launcher/show": { "bodyKeys": [ "key", @@ -4431,6 +4473,24 @@ "formatZH": "申请证书 [domain]", "formatEN": "apply ssl [domain]" }, + "/websites/ssl/push": { + "bodyKeys": [ + "id" + ], + "paramKeys": [], + "beforeFunctions": [ + { + "input_column": "id", + "input_value": "id", + "isList": false, + "db": "website_ssls", + "output_column": "primary_domain", + "output_value": "domain" + } + ], + "formatZH": "推送证书到节点 [domain]", + "formatEN": "Push ssl to nodes [domain]" + }, "/websites/ssl/update": { "bodyKeys": [ "id" @@ -5083,4 +5143,4 @@ "formatZH": "从主节点同步设置", "formatEN": "sync settings from master" } -} +} \ No newline at end of file diff --git a/agent/go.mod b/agent/go.mod index 8ecd3976a310..efbb761abc5c 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -37,7 +37,7 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.10 - github.com/qiniu/go-sdk/v7 v7.26.12 + github.com/qiniu/go-sdk/v7 v7.26.13 github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil/v4 v4.26.5 github.com/sirupsen/logrus v1.9.4 @@ -46,12 +46,12 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 github.com/subosito/gotenv v1.6.0 - github.com/tencentyun/cos-go-sdk-v5 v0.7.73 + github.com/tencentyun/cos-go-sdk-v5 v0.7.74 github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19 github.com/upyun/go-sdk v2.1.0+incompatible - go.mongodb.org/mongo-driver/v2 v2.6.0 + go.mongodb.org/mongo-driver/v2 v2.6.1 golang.org/x/crypto v0.53.0 - golang.org/x/net v0.55.0 + golang.org/x/net v0.56.0 golang.org/x/oauth2 v0.36.0 golang.org/x/sync v0.21.0 golang.org/x/sys v0.46.0 diff --git a/agent/go.sum b/agent/go.sum index 1a53055a035a..52ed35d7e9d2 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -746,8 +746,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/qiniu/go-sdk/v7 v7.26.12 h1:AnWiKjBY62XpULoB/MySKdNmlUo9S9pQB7/0s7QueCo= -github.com/qiniu/go-sdk/v7 v7.26.12/go.mod h1:ri7fGwbio0pRDFr8EK5TUpx0DbnpIMJ2bMSDxGWfCbk= +github.com/qiniu/go-sdk/v7 v7.26.13 h1:U4usDKoLldAqJntLN4wv4pkAjwvM9dueOUY/wbbO/yM= +github.com/qiniu/go-sdk/v7 v7.26.13/go.mod h1:ri7fGwbio0pRDFr8EK5TUpx0DbnpIMJ2bMSDxGWfCbk= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= @@ -833,8 +833,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.24/go.mod h github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106 h1:YjsxDQwoiB+C0ISjnVk22Wbks02Ir+7Z5wmujcz69Vg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= -github.com/tencentyun/cos-go-sdk-v5 v0.7.73 h1:uFfgp1A7cQaAGR6QP9DsIkoEQ67b8ewj5r1RV6XB540= -github.com/tencentyun/cos-go-sdk-v5 v0.7.73/go.mod h1:STbTNaNKq03u+gscPEGOahKzLcGSYOj6Dzc5zNay7Pg= +github.com/tencentyun/cos-go-sdk-v5 v0.7.74 h1:YCsGhIK+Q5vMcmAiQqPuMyhSQ3zN1p7U+dhlHQD++6c= +github.com/tencentyun/cos-go-sdk-v5 v0.7.74/go.mod h1:STbTNaNKq03u+gscPEGOahKzLcGSYOj6Dzc5zNay7Pg= github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20250515025012-e0eec8a5d123/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= @@ -898,8 +898,8 @@ go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lL go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU= go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ= -go.mongodb.org/mongo-driver/v2 v2.6.0 h1:b9sJOYrkmt4l8bY43ZenFBcPlhYIjaOfYHLtbB/5qi8= -go.mongodb.org/mongo-driver/v2 v2.6.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +go.mongodb.org/mongo-driver/v2 v2.6.1 h1:YyGZ2lt+4Nv+dWuiGMKoyWuxmBSlGLH5jllheKiQGu0= +go.mongodb.org/mongo-driver/v2 v2.6.1/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1073,8 +1073,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/core/cmd/server/docs/docs.go b/core/cmd/server/docs/docs.go index fda4a0e2efe2..df71af64547d 100644 --- a/core/cmd/server/docs/docs.go +++ b/core/cmd/server/docs/docs.go @@ -2883,6 +2883,44 @@ const docTemplate = `{ ] } }, + "/ai/mcp/server/connection/test": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerConnectionTest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.McpServerConnectionTestRes" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Test mcp server connection", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/del": { "post": { "consumes": [ @@ -2918,6 +2956,44 @@ const docTemplate = `{ ] } }, + "/ai/mcp/server/detail": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerDetail" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.McpServerDTO" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Load mcp server detail", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/op": { "post": { "consumes": [ @@ -2953,6 +3029,47 @@ const docTemplate = `{ ] } }, + "/ai/mcp/server/status/sync": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerStatusSync" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/response.McpServerStatusDTO" + }, + "type": "array" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Sync mcp server status", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/update": { "post": { "consumes": [ @@ -27588,6 +27705,59 @@ const docTemplate = `{ } } }, + "/websites/ssl/push": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteSSLPush" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Push ssl to nodes", + "tags": [ + "Website SSL" + ], + "x-panel-log": { + "BeforeFunctions": [ + { + "db": "website_ssls", + "input_column": "id", + "input_value": "id", + "isList": false, + "output_column": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Push ssl to nodes [domain]", + "formatZH": "推送证书到节点 [domain]", + "paramKeys": [] + } + } + }, "/websites/ssl/resolve": { "post": { "consumes": [ @@ -31531,6 +31701,9 @@ const docTemplate = `{ "fileName": { "type": "string" }, + "isImmediate": { + "type": "boolean" + }, "name": { "type": "string" }, @@ -39396,6 +39569,9 @@ const docTemplate = `{ }, "hostPort": { "type": "integer" + }, + "protocol": { + "type": "string" } }, "type": "object" @@ -40282,6 +40458,17 @@ const docTemplate = `{ ], "type": "object" }, + "request.McpServerConnectionTest": { + "properties": { + "id": { + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, "request.McpServerCreate": { "properties": { "baseUrl": { @@ -40299,6 +40486,9 @@ const docTemplate = `{ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -40311,6 +40501,9 @@ const docTemplate = `{ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -40347,6 +40540,17 @@ const docTemplate = `{ ], "type": "object" }, + "request.McpServerDetail": { + "properties": { + "id": { + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, "request.McpServerOperate": { "properties": { "id": { @@ -40383,6 +40587,17 @@ const docTemplate = `{ ], "type": "object" }, + "request.McpServerStatusSync": { + "properties": { + "ids": { + "items": { + "type": "integer" + }, + "type": "array" + } + }, + "type": "object" + }, "request.McpServerUpdate": { "properties": { "baseUrl": { @@ -40400,6 +40615,9 @@ const docTemplate = `{ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -40415,6 +40633,9 @@ const docTemplate = `{ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -41691,6 +41912,9 @@ const docTemplate = `{ }, "request.Volume": { "properties": { + "mode": { + "type": "string" + }, "source": { "type": "string" }, @@ -41852,9 +42076,15 @@ const docTemplate = `{ ], "type": "string" }, + "nodes": { + "type": "string" + }, "pushDir": { "type": "boolean" }, + "pushNode": { + "type": "boolean" + }, "renew": { "type": "boolean" }, @@ -42726,6 +42956,27 @@ const docTemplate = `{ }, "type": "object" }, + "request.WebsiteSSLPush": { + "properties": { + "id": { + "type": "integer" + }, + "nodes": { + "type": "string" + }, + "pushNode": { + "type": "boolean" + }, + "taskID": { + "type": "string" + } + }, + "required": [ + "id", + "taskID" + ], + "type": "object" + }, "request.WebsiteSSLSearch": { "properties": { "acmeAccountID": { @@ -42745,6 +42996,7 @@ const docTemplate = `{ "orderBy": { "enum": [ "created_at", + "updated_at", "expire_date" ], "type": "string" @@ -42843,12 +43095,18 @@ const docTemplate = `{ "description": { "type": "string" }, + "nodes": { + "type": "string" + }, "privateKey": { "type": "string" }, "privateKeyPath": { "type": "string" }, + "pushNode": { + "type": "boolean" + }, "sslID": { "type": "integer" }, @@ -43976,6 +44234,26 @@ const docTemplate = `{ }, "type": "object" }, + "response.McpServerConnectionTestRes": { + "properties": { + "endpoint": { + "type": "string" + }, + "message": { + "type": "string" + }, + "outputTransport": { + "type": "string" + }, + "protocolVersion": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "type": "object" + }, "response.McpServerDTO": { "properties": { "baseUrl": { @@ -44005,6 +44283,9 @@ const docTemplate = `{ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -44023,6 +44304,9 @@ const docTemplate = `{ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -44050,6 +44334,20 @@ const docTemplate = `{ }, "type": "object" }, + "response.McpServerStatusDTO": { + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "type": "object" + }, "response.McpServersRes": { "properties": { "items": { diff --git a/core/cmd/server/docs/swagger.json b/core/cmd/server/docs/swagger.json index bcd9cf091348..54f289d5594d 100644 --- a/core/cmd/server/docs/swagger.json +++ b/core/cmd/server/docs/swagger.json @@ -2879,6 +2879,44 @@ ] } }, + "/ai/mcp/server/connection/test": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerConnectionTest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.McpServerConnectionTestRes" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Test mcp server connection", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/del": { "post": { "consumes": [ @@ -2914,6 +2952,44 @@ ] } }, + "/ai/mcp/server/detail": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerDetail" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.McpServerDTO" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Load mcp server detail", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/op": { "post": { "consumes": [ @@ -2949,6 +3025,47 @@ ] } }, + "/ai/mcp/server/status/sync": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.McpServerStatusSync" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/response.McpServerStatusDTO" + }, + "type": "array" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Sync mcp server status", + "tags": [ + "McpServer" + ] + } + }, "/ai/mcp/server/update": { "post": { "consumes": [ @@ -27584,6 +27701,59 @@ } } }, + "/websites/ssl/push": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteSSLPush" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Push ssl to nodes", + "tags": [ + "Website SSL" + ], + "x-panel-log": { + "BeforeFunctions": [ + { + "db": "website_ssls", + "input_column": "id", + "input_value": "id", + "isList": false, + "output_column": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Push ssl to nodes [domain]", + "formatZH": "推送证书到节点 [domain]", + "paramKeys": [] + } + } + }, "/websites/ssl/resolve": { "post": { "consumes": [ @@ -31527,6 +31697,9 @@ "fileName": { "type": "string" }, + "isImmediate": { + "type": "boolean" + }, "name": { "type": "string" }, @@ -39392,6 +39565,9 @@ }, "hostPort": { "type": "integer" + }, + "protocol": { + "type": "string" } }, "type": "object" @@ -40278,6 +40454,17 @@ ], "type": "object" }, + "request.McpServerConnectionTest": { + "properties": { + "id": { + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, "request.McpServerCreate": { "properties": { "baseUrl": { @@ -40295,6 +40482,9 @@ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -40307,6 +40497,9 @@ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -40343,6 +40536,17 @@ ], "type": "object" }, + "request.McpServerDetail": { + "properties": { + "id": { + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, "request.McpServerOperate": { "properties": { "id": { @@ -40379,6 +40583,17 @@ ], "type": "object" }, + "request.McpServerStatusSync": { + "properties": { + "ids": { + "items": { + "type": "integer" + }, + "type": "array" + } + }, + "type": "object" + }, "request.McpServerUpdate": { "properties": { "baseUrl": { @@ -40396,6 +40611,9 @@ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -40411,6 +40629,9 @@ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -41687,6 +41908,9 @@ }, "request.Volume": { "properties": { + "mode": { + "type": "string" + }, "source": { "type": "string" }, @@ -41848,9 +42072,15 @@ ], "type": "string" }, + "nodes": { + "type": "string" + }, "pushDir": { "type": "boolean" }, + "pushNode": { + "type": "boolean" + }, "renew": { "type": "boolean" }, @@ -42722,6 +42952,27 @@ }, "type": "object" }, + "request.WebsiteSSLPush": { + "properties": { + "id": { + "type": "integer" + }, + "nodes": { + "type": "string" + }, + "pushNode": { + "type": "boolean" + }, + "taskID": { + "type": "string" + } + }, + "required": [ + "id", + "taskID" + ], + "type": "object" + }, "request.WebsiteSSLSearch": { "properties": { "acmeAccountID": { @@ -42741,6 +42992,7 @@ "orderBy": { "enum": [ "created_at", + "updated_at", "expire_date" ], "type": "string" @@ -42839,12 +43091,18 @@ "description": { "type": "string" }, + "nodes": { + "type": "string" + }, "privateKey": { "type": "string" }, "privateKeyPath": { "type": "string" }, + "pushNode": { + "type": "boolean" + }, "sslID": { "type": "integer" }, @@ -43972,6 +44230,26 @@ }, "type": "object" }, + "response.McpServerConnectionTestRes": { + "properties": { + "endpoint": { + "type": "string" + }, + "message": { + "type": "string" + }, + "outputTransport": { + "type": "string" + }, + "protocolVersion": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "type": "object" + }, "response.McpServerDTO": { "properties": { "baseUrl": { @@ -44001,6 +44279,9 @@ }, "type": "array" }, + "gatewayImage": { + "type": "string" + }, "hostIP": { "type": "string" }, @@ -44019,6 +44300,9 @@ "port": { "type": "integer" }, + "protocolVersion": { + "type": "string" + }, "ssePath": { "type": "string" }, @@ -44046,6 +44330,20 @@ }, "type": "object" }, + "response.McpServerStatusDTO": { + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "type": "object" + }, "response.McpServersRes": { "properties": { "items": { diff --git a/core/cmd/server/docs/x-log.json b/core/cmd/server/docs/x-log.json index f54046ade5ed..e6f894dd4089 100644 --- a/core/cmd/server/docs/x-log.json +++ b/core/cmd/server/docs/x-log.json @@ -1247,6 +1247,33 @@ "formatZH": "更新 AI 网关分组 [name]", "formatEN": "update AI proxy group [name]" }, + "/core/enterprise/ai-proxy/model-groups/create": { + "bodyKeys": [ + "name" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "创建 AI 网关模型组 [name]", + "formatEN": "create AI proxy model group [name]" + }, + "/core/enterprise/ai-proxy/model-groups/delete": { + "bodyKeys": [ + "id" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "删除 AI 网关模型组 [id]", + "formatEN": "delete AI proxy model group [id]" + }, + "/core/enterprise/ai-proxy/model-groups/update": { + "bodyKeys": [ + "name" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新 AI 网关模型组 [name]", + "formatEN": "update AI proxy model group [name]" + }, "/core/enterprise/ai-proxy/service/operate": { "bodyKeys": [ "operate" @@ -2166,6 +2193,15 @@ "formatZH": "更新自定义应用配置 [status]", "formatEN": "update custom app config [status]" }, + "/core/xpack/settings/app/image-prefix": { + "bodyKeys": [ + "imagePrefix" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新应用镜像前缀 [imagePrefix]", + "formatEN": "update app image prefix [imagePrefix]" + }, "/core/xpack/settings/reset": { "bodyKeys": [], "paramKeys": [], @@ -2193,25 +2229,13 @@ "/core/xpack/sync/app": { "bodyKeys": [ "sourceNode", - "targetNode", - "appInstallID", - "appBackupID" - ], - "paramKeys": [], - "beforeFunctions": [], - "formatZH": "同步应用备份 [appInstallID] 到节点 [targetNode]", - "formatEN": "sync app backup [appInstallID] to node [targetNode]" - }, - "/core/xpack/sync/app/install": { - "bodyKeys": [ - "appKey", - "version", - "nodes" + "targetNodes", + "appInstallID" ], "paramKeys": [], "beforeFunctions": [], - "formatZH": "安装应用 [appKey] [version] 到节点 [nodes]", - "formatEN": "install app [appKey] [version] to nodes [nodes]" + "formatZH": "同步应用 [appInstallID] 到节点 [targetNodes]", + "formatEN": "sync app [appInstallID] to nodes [targetNodes]" }, "/core/xpack/sync/ssl": { "bodyKeys": [ @@ -2352,6 +2376,15 @@ "formatZH": "更新自定义应用配置 [status]", "formatEN": "update custom app config [status]" }, + "/custom/app/image-prefix": { + "bodyKeys": [ + "imagePrefix" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "更新应用镜像前缀 [imagePrefix]", + "formatEN": "update app image prefix [imagePrefix]" + }, "/custom/app/install": { "bodyKeys": [ "name", @@ -2379,6 +2412,15 @@ "formatZH": "同步自定义应用商店", "formatEN": "sync custom app store" }, + "/custom/app/sync/backup": { + "bodyKeys": [ + "appInstallID" + ], + "paramKeys": [], + "beforeFunctions": [], + "formatZH": "创建应用同步备份 [appInstallID]", + "formatEN": "create app sync backup [appInstallID]" + }, "/dashboard/app/launcher/show": { "bodyKeys": [ "key", @@ -4431,6 +4473,24 @@ "formatZH": "申请证书 [domain]", "formatEN": "apply ssl [domain]" }, + "/websites/ssl/push": { + "bodyKeys": [ + "id" + ], + "paramKeys": [], + "beforeFunctions": [ + { + "input_column": "id", + "input_value": "id", + "isList": false, + "db": "website_ssls", + "output_column": "primary_domain", + "output_value": "domain" + } + ], + "formatZH": "推送证书到节点 [domain]", + "formatEN": "Push ssl to nodes [domain]" + }, "/websites/ssl/update": { "bodyKeys": [ "id" @@ -5083,4 +5143,4 @@ "formatZH": "从主节点同步设置", "formatEN": "sync settings from master" } -} +} \ No newline at end of file diff --git a/core/go.mod b/core/go.mod index 2cb2df624837..73d1325f18c6 100644 --- a/core/go.mod +++ b/core/go.mod @@ -32,7 +32,7 @@ require ( github.com/swaggo/swag v1.16.6 github.com/xlzd/gotp v0.1.0 golang.org/x/crypto v0.53.0 - golang.org/x/net v0.55.0 + golang.org/x/net v0.56.0 golang.org/x/sys v0.46.0 golang.org/x/term v0.44.0 golang.org/x/text v0.38.0 diff --git a/core/go.sum b/core/go.sum index 5946d6c191f1..7b766a3333c2 100644 --- a/core/go.sum +++ b/core/go.sum @@ -256,8 +256,8 @@ golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f715befe0c15..2b829be6b1e9 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -20,11 +20,11 @@ "@vueuse/core": "^14.3.0", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", - "anser": "^2.3.2", + "anser": "^2.3.5", "axios": "^1.17.0", "codemirror": "^6.0.2", "crypto-js": "^4.2.0", - "dompurify": "^3.4.8", + "dompurify": "^3.4.9", "echarts": "^5.5.0", "element-plus": "2.14.0", "js-base64": "^3.7.7", @@ -51,8 +51,8 @@ "@tailwindcss/postcss": "^4.3.0", "@types/node": "^25.9.1", "@types/uuid": "^11.0.0", - "@typescript-eslint/eslint-plugin": "^8.58.1", - "@typescript-eslint/parser": "^8.58.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue": "^6.0.7", "@vitejs/plugin-vue-jsx": "^5.1.5", "@vue/compiler-sfc": "^3.5.35", @@ -3048,17 +3048,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.1.tgz", - "integrity": "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.1", - "@typescript-eslint/type-utils": "8.58.1", - "@typescript-eslint/utils": "8.58.1", - "@typescript-eslint/visitor-keys": "8.58.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -3071,7 +3071,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -3087,17 +3087,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.1.tgz", - "integrity": "sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.58.1", - "@typescript-eslint/types": "8.58.1", - "@typescript-eslint/typescript-estree": "8.58.1", - "@typescript-eslint/visitor-keys": "8.58.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -3113,14 +3113,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.1.tgz", - "integrity": "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.1", - "@typescript-eslint/types": "^8.58.1", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -3135,14 +3135,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz", - "integrity": "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.1", - "@typescript-eslint/visitor-keys": "8.58.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3153,9 +3153,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz", - "integrity": "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -3170,15 +3170,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.1.tgz", - "integrity": "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.1", - "@typescript-eslint/typescript-estree": "8.58.1", - "@typescript-eslint/utils": "8.58.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -3195,9 +3195,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", - "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -3209,16 +3209,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz", - "integrity": "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.1", - "@typescript-eslint/tsconfig-utils": "8.58.1", - "@typescript-eslint/types": "8.58.1", - "@typescript-eslint/visitor-keys": "8.58.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3247,9 +3247,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -3276,16 +3276,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.1.tgz", - "integrity": "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.1", - "@typescript-eslint/types": "8.58.1", - "@typescript-eslint/typescript-estree": "8.58.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3300,13 +3300,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz", - "integrity": "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3829,9 +3829,9 @@ "license": "MIT" }, "node_modules/anser": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/anser/-/anser-2.3.3.tgz", - "integrity": "sha512-QGY1oxYE7/kkeNmbtY/2ZjQ07BCG3zYdz+k/+sf69kMzEIxb93guHkPnIXITQ+BYi61oQwG74twMOX1tD4aesg==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/anser/-/anser-2.3.5.tgz", + "integrity": "sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ==", "license": "MIT" }, "node_modules/ansi-escapes": { @@ -4998,9 +4998,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.8.tgz", - "integrity": "sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==", + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.9.tgz", + "integrity": "sha512-4dPSRMRDqHvs0V4YDFCsaIZo4if5u0xM+llyxiM2fwuZFdKArUBAF3VtI2+n8NKg9P870WMdYk0UhqQNoWXbfQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" diff --git a/frontend/package.json b/frontend/package.json index 839c40e73f66..91e682cc4ac1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,11 +31,11 @@ "@vueuse/core": "^14.3.0", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", - "anser": "^2.3.2", + "anser": "^2.3.5", "axios": "^1.17.0", "codemirror": "^6.0.2", "crypto-js": "^4.2.0", - "dompurify": "^3.4.8", + "dompurify": "^3.4.9", "echarts": "^5.5.0", "element-plus": "2.14.0", "js-base64": "^3.7.7", @@ -62,8 +62,8 @@ "@tailwindcss/postcss": "^4.3.0", "@types/node": "^25.9.1", "@types/uuid": "^11.0.0", - "@typescript-eslint/eslint-plugin": "^8.58.1", - "@typescript-eslint/parser": "^8.58.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue": "^6.0.7", "@vitejs/plugin-vue-jsx": "^5.1.5", "@vue/compiler-sfc": "^3.5.35", diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index efd9c9ed4234..437cfef0d5df 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -256,6 +256,7 @@ export namespace AI { hostPort: number; containerPort: number; hostIP: string; + protocol?: string; } export interface Environment { @@ -265,6 +266,7 @@ export namespace AI { export interface Volume { source: string; target: string; + mode: string; } export interface ExtraHosts { diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index f14cddbb5ec3..51b8974d5861 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -71,6 +71,7 @@ export namespace Runtime { hostPort: number; containerPort: number; hostIP: string; + protocol: string; } export interface Environment { key: string; @@ -79,6 +80,7 @@ export namespace Runtime { export interface Volume { source: string; target: string; + mode: string; } export interface ExtraHost { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index daaa5ef9363b..3c6cfd4148d1 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -4958,7 +4958,7 @@ const message = { theworld: 'TheWorld Browser', edge: 'Microsoft Edge', maxthon: 'Maxthon Browser', - monitorStatusHelper: 'Monitoring is not enabled, please enable it in settings', + monitorStatusHelper: 'Website monitoring is currently disabled. Enable it now', excludeIp: 'Exclude IP Addresses', excludeUa: 'Exclude User-Agent', remotePort: 'Remote Port', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index f93b83b9a930..1279c3aa6ad8 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -5018,7 +5018,7 @@ const message = { theworld: 'TheWorld Browser', edge: 'Microsoft Edge', maxthon: 'Maxthon Browser', - monitorStatusHelper: 'Monitorización no habilitada, actívala en Configuración', + monitorStatusHelper: 'La monitorización del sitio web está deshabilitada. Actívala ahora', excludeIp: 'Excluir IPs', excludeUa: 'Excluir User-Agent', remotePort: 'Puerto remoto', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 3bf7dbb7eefd..f4f9790a5691 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -4996,7 +4996,7 @@ const message = { theworld: 'TheWorldブラウザ', edge: 'Microsoft Edge', maxthon: 'Maxthonブラウザ', - monitorStatusHelper: 'モニタリングは有効ではありません。設定で有効にしてください', + monitorStatusHelper: '現在、Webサイト監視は有効になっていません。今すぐ有効にしてください', excludeIp: 'IPアドレスを除外', excludeUa: 'ユーザーエージェントを除外', remotePort: 'リモートポート', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 54164fabfdc5..25528437ae70 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -4899,7 +4899,7 @@ const message = { theworld: '더월드 브라우저', edge: '마이크로소프트 엣지', maxthon: '맥스톤 브라우저', - monitorStatusHelper: '모니터링이 활성화되지 않았습니다. 설정에서 활성화하세요', + monitorStatusHelper: '현재 웹사이트 모니터링이 비활성화되어 있습니다. 지금 활성화하세요', excludeIp: 'IP 주소 제외', excludeUa: '사용자 에이전트 제외', remotePort: '원격 포트', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index d89b58d1fc0e..7b6b7cd946a4 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -5058,7 +5058,7 @@ const message = { theworld: 'Pelayar TheWorld', edge: 'Microsoft Edge', maxthon: 'Pelayar Maxthon', - monitorStatusHelper: 'Pemantauan tidak diaktifkan, sila aktifkan dalam tetapan', + monitorStatusHelper: 'Pemantauan laman web belum diaktifkan. Aktifkan sekarang', excludeIp: 'Kecualikan Alamat IP', excludeUa: 'Kecualikan User-Agent', remotePort: 'Port Jauh', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index d8918e3d2b1c..a9bfd423b426 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -5202,7 +5202,7 @@ const message = { theworld: 'Navegador TheWorld', edge: 'Microsoft Edge', maxthon: 'Navegador Maxthon', - monitorStatusHelper: 'O monitoramento não está habilitado, por favor habilite-o nas configurações', + monitorStatusHelper: 'O monitoramento do site está desabilitado. Habilite agora', excludeIp: 'Excluir Endereços IP', excludeUa: 'Excluir User-Agent', remotePort: 'Porta Remota', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index f4b0c1364205..59d794220790 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -5049,7 +5049,7 @@ const message = { theworld: 'Браузер TheWorld', edge: 'Microsoft Edge', maxthon: 'Браузер Maxthon', - monitorStatusHelper: 'Мониторинг не включён, пожалуйста, включите его в настройках', + monitorStatusHelper: 'Мониторинг сайта сейчас отключён. Включите его сейчас', excludeIp: 'Исключить IP-адреса', excludeUa: 'Исключить User-Agent', remotePort: 'Удаленный порт', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index dc5dca2b8e17..b67c74404a5b 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -5046,7 +5046,7 @@ const message = { theworld: 'TheWorld Tarayıcı', edge: 'Microsoft Edge', maxthon: 'Maxthon Tarayıcı', - monitorStatusHelper: 'İzleme etkin değil, lütfen ayarlarda etkinleştirin', + monitorStatusHelper: 'Web sitesi izleme şu anda devre dışı. Şimdi etkinleştirin', excludeIp: 'IP Adreslerini Hariç Tut', excludeUa: 'Kullanıcı-Aracısını Hariç Tut', remotePort: 'Uzak Port', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 6b3c9debdcda..afd69816b11d 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -4645,7 +4645,7 @@ const message = { theworld: '世界之窗瀏覽器', edge: 'Edge', maxthon: '遨遊瀏覽器', - monitorStatusHelper: '監控未開啟,請在設定中開啟', + monitorStatusHelper: '目前網站監控未開啟,立即開啟', excludeIp: '排除 IP', excludeUa: '排除 User-Agent', remotePort: '遠端埠', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 6680d419ced0..02b41b077278 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -4083,7 +4083,7 @@ const message = { theworld: '世界之窗浏览器', edge: 'Edge', maxthon: '遨游浏览器', - monitorStatusHelper: '监控未开启,请在设置中打开', + monitorStatusHelper: '当前网站监控未开启,立即开启', excludeIp: '排除 IP', excludeUa: '排除 User-Agent', remotePort: '远程端口', diff --git a/frontend/src/views/ai/mcp/server/operate/index.vue b/frontend/src/views/ai/mcp/server/operate/index.vue index 84e19064b8d4..a61ab3f76d99 100644 --- a/frontend/src/views/ai/mcp/server/operate/index.vue +++ b/frontend/src/views/ai/mcp/server/operate/index.vue @@ -117,34 +117,7 @@ -
- - - - - - - - - - - - - - - {{ $t('commons.button.delete') }} - - - - - - - - {{ $t('commons.button.add') }} - - - -
+
@@ -171,7 +144,8 @@ import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; import { FormInstance } from 'element-plus'; import { ref, watch } from 'vue'; -import Volumes from '../volume/index.vue'; +import Environment from '@/views/website/runtime/components/environment/index.vue'; +import Volumes from '@/views/website/runtime/components/volume/index.vue'; import Import from '../import/index.vue'; const open = ref(false); @@ -216,8 +190,6 @@ const rules = ref({ containerName: [Rules.requiredInput], url: [Rules.requiredInput], ssePath: [Rules.requiredInput], - key: [Rules.requiredInput], - value: [Rules.requiredInput], outputTransport: [Rules.requiredSelect], streamableHttpPath: [Rules.requiredInput], type: [Rules.requiredSelect], @@ -288,17 +260,6 @@ watch( }, ); -const addEnv = () => { - mcpServer.value.environments.push({ - key: '', - value: '', - }); -}; - -const removeEnv = (index: number) => { - mcpServer.value.environments.splice(index, 1); -}; - const normalizeGatewayConfig = () => { mcpServer.value.gatewayImage = mcpServer.value.gatewayImage || defaultGatewayImages[mcpServer.value.type]; mcpServer.value.protocolVersion = mcpServer.value.protocolVersion || defaultProtocolVersion; diff --git a/frontend/src/views/ai/mcp/server/volume/index.vue b/frontend/src/views/ai/mcp/server/volume/index.vue index 562890f5db9c..35ffecb3ef7b 100644 --- a/frontend/src/views/ai/mcp/server/volume/index.vue +++ b/frontend/src/views/ai/mcp/server/volume/index.vue @@ -50,6 +50,7 @@ const addEnv = () => { props.volumes.push({ source: '', target: '', + mode: 'rw', }); }; diff --git a/frontend/src/views/website/runtime/components/environment/index.vue b/frontend/src/views/website/runtime/components/environment/index.vue index 52b7f2ff2154..9ce07ede564e 100644 --- a/frontend/src/views/website/runtime/components/environment/index.vue +++ b/frontend/src/views/website/runtime/components/environment/index.vue @@ -1,5 +1,5 @@