diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index 9488edbc926e..a8c7b1b079f8 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -152,6 +152,26 @@ func (b *BaseApi) BindAgentWebsite(c *gin.Context) { helper.Success(c) } +// @Tags AI +// @Summary Unbind Agent website +// @Accept json +// @Param request body dto.AgentIDReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/website/unbind [post] +func (b *BaseApi) UnbindAgentWebsite(c *gin.Context) { + var req dto.AgentIDReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.UnbindWebsite(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + // @Tags AI // @Summary Get Agent model config // @Accept json diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index b59fa3d0afb9..d31bd71238c4 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -46,6 +46,7 @@ type AgentItem struct { AppInstallID uint `json:"appInstallId"` WebsiteID uint `json:"websiteId"` WebsitePrimaryDomain string `json:"websitePrimaryDomain"` + WebsiteType string `json:"websiteType"` WebsiteProtocol string `json:"websiteProtocol"` AccountID uint `json:"accountId"` AppVersion string `json:"appVersion"` diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index f23652636fbf..d6bd24f39580 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -36,6 +36,7 @@ type IAgentService interface { ResetToken(req dto.AgentTokenResetReq) error UpdateRemark(req dto.AgentRemarkUpdateReq) error BindWebsite(req dto.AgentWebsiteBindReq) error + UnbindWebsite(req dto.AgentIDReq) error GetModelConfig(req dto.AgentIDReq) (*dto.AgentModelConfig, error) UpdateModelConfig(req dto.AgentModelConfigUpdateReq) error GetHermesChatSessions(req dto.AgentIDReq) ([]dto.AgentHermesChatSessionItem, error) diff --git a/agent/app/service/agents_website.go b/agent/app/service/agents_website.go index 9defff7f047c..5e5e98240168 100644 --- a/agent/app/service/agents_website.go +++ b/agent/app/service/agents_website.go @@ -48,6 +48,27 @@ func (a AgentService) BindWebsite(req dto.AgentWebsiteBindReq) error { return ensureOpenclawWebsiteAllowedOrigin(agent, &website) } +func (a AgentService) UnbindWebsite(req dto.AgentIDReq) error { + agent, err := agentRepo.GetFirst(repo.WithByID(req.AgentID)) + if err != nil { + return err + } + if agent.WebsiteID == 0 { + return nil + } + + website, err := websiteRepo.GetFirst(repo.WithByID(agent.WebsiteID)) + if err != nil { + return err + } + if website.Type == constant.Deployment { + return buserr.New("ErrAgentWebsiteUnbindUnsupported") + } + + agent.WebsiteID = 0 + return agentRepo.Save(agent) +} + func hydrateAgentWebsiteItems(items []dto.AgentItem) error { explicitWebsiteMap, err := loadAgentWebsiteMapByID(items) if err != nil { @@ -126,9 +147,11 @@ func fillAgentWebsiteItems(items []dto.AgentItem, explicitWebsiteMap map[uint]mo if !ok { items[index].WebsiteID = 0 items[index].WebsitePrimaryDomain = "" + items[index].WebsiteType = "" items[index].WebsiteProtocol = "" continue } + items[index].WebsiteType = website.Type items[index].WebsiteProtocol = website.Protocol websiteDomains := websiteDomainMap[items[index].WebsiteID] if len(websiteDomains) == 0 { diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml index 993039640f41..7074f506dde5 100644 --- a/agent/i18n/lang/en.yaml +++ b/agent/i18n/lang/en.yaml @@ -64,6 +64,7 @@ ErrAgentLimitReached: 'Community Edition supports up to {{ .max }} AI agents. Up ErrAgentWebsiteBound: 'This agent is already bound to a website' ErrAgentWebsiteTypeUnsupported: 'Only proxy or static websites can be bound' ErrAgentWebsiteInUse: 'This website is already bound to another agent' +ErrAgentWebsiteUnbindUnsupported: 'Deployment websites cannot be unbound manually' #backup Localhost: 'Local' diff --git a/agent/i18n/lang/es-ES.yaml b/agent/i18n/lang/es-ES.yaml index 5757887434a4..5b19c222cb07 100644 --- a/agent/i18n/lang/es-ES.yaml +++ b/agent/i18n/lang/es-ES.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'La edición Community admite hasta {{ .max }} agentes de ErrAgentWebsiteBound: 'Este agente ya está vinculado a un sitio web' ErrAgentWebsiteTypeUnsupported: 'Solo se pueden vincular sitios proxy o estáticos' ErrAgentWebsiteInUse: 'Este sitio web ya está vinculado a otro agente' +ErrAgentWebsiteUnbindUnsupported: 'Los sitios web de despliegue no se pueden desvincular manualmente' Localhost: 'Máquina local' ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada' ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}' diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml index ce1c5b5f7067..98f051448277 100644 --- a/agent/i18n/lang/ja.yaml +++ b/agent/i18n/lang/ja.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'Community Edition では AI エージェントを最大 { ErrAgentWebsiteBound: 'このエージェントはすでにサイトに関連付けられています' ErrAgentWebsiteTypeUnsupported: '関連付けできるのはプロキシサイトまたは静的サイトのみです' ErrAgentWebsiteInUse: 'このサイトはすでに別のエージェントに関連付けられています' +ErrAgentWebsiteUnbindUnsupported: 'ワンクリックデプロイのサイトは手動で関連解除できません' Localhost: 'ローカルマシン' ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中' ErrBackupCheck: '接続テストに失敗しました: {{ .err }}' diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml index 64ffbb3ce445..61ceaa98acc8 100644 --- a/agent/i18n/lang/ko.yaml +++ b/agent/i18n/lang/ko.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: '커뮤니티 에디션에서는 AI 에이전트를 최대 ErrAgentWebsiteBound: '이 에이전트는 이미 웹사이트에 연결되어 있습니다' ErrAgentWebsiteTypeUnsupported: '프록시 또는 정적 웹사이트만 연결할 수 있습니다' ErrAgentWebsiteInUse: '이 웹사이트는 이미 다른 에이전트에 연결되어 있습니다' +ErrAgentWebsiteUnbindUnsupported: '원클릭 배포 웹사이트는 수동으로 연결 해제할 수 없습니다' Localhost: '로컬 머신' ErrBackupInUsed: '백업 계정이 예약에 사용 중' ErrBackupCheck: '연결 테스트 실패: {{ .err }}' diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml index d4696f37609f..d925a1d8b530 100644 --- a/agent/i18n/lang/ms.yaml +++ b/agent/i18n/lang/ms.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'Edisi Community menyokong sehingga {{ .max }} ejen AI. Na ErrAgentWebsiteBound: 'Ejen ini sudah dipautkan ke laman web' ErrAgentWebsiteTypeUnsupported: 'Hanya laman web proxy atau statik boleh dipautkan' ErrAgentWebsiteInUse: 'Laman web ini sudah dipautkan ke ejen lain' +ErrAgentWebsiteUnbindUnsupported: 'Laman web one-click deployment tidak menyokong nyahikat manual' Localhost: 'Mesin Tempatan' ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas' ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}' diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml index ee652e903798..45347136200f 100644 --- a/agent/i18n/lang/pt-BR.yaml +++ b/agent/i18n/lang/pt-BR.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'A edição Community suporta até {{ .max }} agentes de I ErrAgentWebsiteBound: 'Este agente já está vinculado a um site' ErrAgentWebsiteTypeUnsupported: 'Somente sites proxy ou estáticos podem ser vinculados' ErrAgentWebsiteInUse: 'Este site já está vinculado a outro agente' +ErrAgentWebsiteUnbindUnsupported: 'Sites implantados em um clique não podem ser desvinculados manualmente' Localhost: 'Máquina Local' ErrBackupInUsed: 'Conta de backup em uso por tarefa' ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}' diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml index f7520c9dfd51..32ff57aec77c 100644 --- a/agent/i18n/lang/ru.yaml +++ b/agent/i18n/lang/ru.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'Community Edition поддерживает до {{ .max } ErrAgentWebsiteBound: 'Этот агент уже связан с сайтом' ErrAgentWebsiteTypeUnsupported: 'Можно связывать только proxy- или static-сайты' ErrAgentWebsiteInUse: 'Этот сайт уже связан с другим агентом' +ErrAgentWebsiteUnbindUnsupported: 'Сайты one-click deployment нельзя отвязать вручную' Localhost: 'Локальная машина' ErrBackupInUsed: 'Аккаунт бэкапа занят задачей' ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}' diff --git a/agent/i18n/lang/tr.yaml b/agent/i18n/lang/tr.yaml index 1729127dd9c2..04fe9cb99dad 100644 --- a/agent/i18n/lang/tr.yaml +++ b/agent/i18n/lang/tr.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: 'Community sürümü en fazla {{ .max }} AI ajanını dest ErrAgentWebsiteBound: 'Bu ajan zaten bir web sitesine bağlı' ErrAgentWebsiteTypeUnsupported: 'Yalnızca proxy veya statik web siteleri bağlanabilir' ErrAgentWebsiteInUse: 'Bu web sitesi zaten başka bir ajana bağlı' +ErrAgentWebsiteUnbindUnsupported: 'Tek tıkla dağıtılan web sitelerinin bağlantısı manuel olarak kaldırılamaz' Localhost: 'Yerel Makine' ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor' ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}' diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml index a498247545a5..371244a8cb26 100644 --- a/agent/i18n/lang/zh-Hant.yaml +++ b/agent/i18n/lang/zh-Hant.yaml @@ -59,6 +59,7 @@ ErrAgentLimitReached: '社群版最多支援建立 {{ .max }} 個 AI 智能體 ErrAgentWebsiteBound: '該智能體已關聯網站' ErrAgentWebsiteTypeUnsupported: '只能關聯反向代理或靜態網站' ErrAgentWebsiteInUse: '該網站已被其他智能體關聯' +ErrAgentWebsiteUnbindUnsupported: '一鍵部署網站不支援手動解綁' Localhost: '本機' ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除' ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}' diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml index 03d3a4ea2e7e..850bea82706e 100644 --- a/agent/i18n/lang/zh.yaml +++ b/agent/i18n/lang/zh.yaml @@ -64,6 +64,7 @@ ErrAgentLimitReached: "社区版最多支持创建 {{ .max }} 个智能体,升 ErrAgentWebsiteBound: "该智能体已关联网站" ErrAgentWebsiteTypeUnsupported: "只能关联反向代理或静态网站" ErrAgentWebsiteInUse: "该网站已被其他智能体关联" +ErrAgentWebsiteUnbindUnsupported: "一键部署网站不支持手动解绑" #backup Localhost: '本机' diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index d6e10adebe61..4f412d569547 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -47,6 +47,7 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/token/reset", baseApi.ResetAgentToken) aiToolsRouter.POST("/agents/remark", baseApi.UpdateAgentRemark) aiToolsRouter.POST("/agents/website/bind", baseApi.BindAgentWebsite) + aiToolsRouter.POST("/agents/website/unbind", baseApi.UnbindAgentWebsite) aiToolsRouter.POST("/agents/model/get", baseApi.GetAgentModelConfig) aiToolsRouter.POST("/agents/model/update", baseApi.UpdateAgentModelConfig) aiToolsRouter.POST("/agents/hermes/chat/sessions", baseApi.GetHermesChatSessions) diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index 9f217f9b984c..3f880fe4b5b1 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -282,6 +282,7 @@ export namespace AI { appInstallId: number; websiteId: number; websitePrimaryDomain: string; + websiteType: string; websiteProtocol: string; accountId: number; appVersion: string; diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index 766ff3ba27a6..4b77be3bd909 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -122,6 +122,10 @@ export const bindAgentWebsite = (req: AI.AgentWebsiteBindReq) => { return http.post(`/ai/agents/website/bind`, req); }; +export const unbindAgentWebsite = (req: AI.AgentIDReq) => { + return http.post(`/ai/agents/website/unbind`, req); +}; + export const getAgentModelConfig = (req: AI.AgentIDReq) => { return http.post(`/ai/agents/model/get`, req); }; diff --git a/frontend/src/views/ai/agents/agent/index.vue b/frontend/src/views/ai/agents/agent/index.vue index 7c450419aea8..f498f5a6a54f 100644 --- a/frontend/src/views/ai/agents/agent/index.vue +++ b/frontend/src/views/ai/agents/agent/index.vue @@ -126,6 +126,14 @@ + + {{ $t('commons.button.unbind') }} + {{ $t('commons.button.bind') }} @@ -204,7 +212,7 @@ + +