Compare commits

..
12 Commits
798 changed files with 22966 additions and 78282 deletions
-1
View File
@@ -6,7 +6,6 @@ permissions:
jobs:
generic_handler:
name: Add Labels to PR
if: github.repository == '1Panel-dev/1Panel'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -0,0 +1,47 @@
name: Create Release And Upload assets
on:
push:
tags:
- 'v*'
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.19.0'
- name: Build Web
run: |
cd frontend && npm install && npm run build:pro
env:
NODE_OPTIONS: --max-old-space-size=8192
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Build Release
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: '~> v2'
args: release --skip=publish --clean
- name: Upload Assets
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
draft: true
files: |
dist/*.tar.gz
dist/checksums.txt
- name: Setup OSSUTIL
uses: yizhoumo/setup-ossutil@v2
with:
endpoint: ${{ secrets.OSS_ENDPOINT }}
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
ossutil-version: '1.7.18'
- name: Upload Assets to OSS
run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
@@ -1,43 +1,33 @@
name: Build And Publish (OSS + R2)
name: Create Release And Upload Cloudflare R2
on:
push:
tags:
- 'v*'
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.19.0'
- name: Build Web
run: |
cd frontend && npm install && npm run build:pro
env:
NODE_OPTIONS: --max-old-space-size=8192
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache-dependency-path: |
core/go.sum
agent/go.sum
go-version: '1.23'
- name: Build Release
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: '~> v2'
args: release --skip=publish --clean
- name: Upload Assets
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
@@ -46,24 +36,10 @@ jobs:
files: |
dist/*.tar.gz
dist/checksums.txt
- name: Setup OSSUTIL
uses: yizhoumo/setup-ossutil@v2
with:
endpoint: ${{ secrets.OSS_ENDPOINT }}
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
ossutil-version: '1.7.18'
- name: Upload Assets to OSS
run: |
ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to Cloudflare R2
run: |
rclone copy dist/ cloudflare_r2:package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --progress
-1
View File
@@ -8,7 +8,6 @@ on:
jobs:
sonarcloud:
name: SonarCloud
if: github.repository == '1Panel-dev/1Panel'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
-1
View File
@@ -2,7 +2,6 @@ name: Synchronize to Gitee
on: [push]
jobs:
repo-sync:
if: github.repository == '1Panel-dev/1Panel'
runs-on: ubuntu-latest
steps:
- name: Mirror the Github organization repos to Gitee.
+2 -15
View File
@@ -44,17 +44,12 @@ frontend/src/xpack
agent/xpack
agent/router/entry_xpack.go
agent/server/init_xpack.go
agent/utils/xpack/xpack.go
agent/utils/xpack/xpack_xpack.go
core/xpack
core/router/entry_xpack.go
core/server/init_xpack.go
core/utils/xpack/xpack.go
core/utils/xpack/xpack_xpack.go
core/xpack-ee
core/router/entry_xpackee.go
core/server/init_xpackee.go
core/utils/xpack/xpack_xpackee.go
xpack
.history/
dist/
@@ -67,12 +62,4 @@ cmd/server/fileList.txt
1Panel.code-workspace
core/.golangci.yml
agent/.golangci.yml
.opencode
openspec
CLAUDE.md
AGENTS.md
opencode.json
superpowers
.worktrees/
agent/.golangci.yml
+8 -3
View File
@@ -33,6 +33,9 @@ builds:
- ppc64le
- s390x
- riscv64
hooks:
post:
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
- id: core
dir: core
@@ -56,6 +59,9 @@ builds:
- ppc64le
- s390x
- riscv64
hooks:
post:
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
archives:
- formats: [ 'tar.gz' ]
@@ -64,12 +70,11 @@ archives:
wrap_in_directory: true
files:
- 1pctl
- install.sh
- 1panel-core.service
- 1panel-agent.service
- initscript/*
- lang/*
- install.sh
- GeoIP.mmdb
- lang/*
checksum:
name_template: 'checksums.txt'
+5 -5
View File
@@ -30,20 +30,20 @@ build_frontend:
build_core_on_linux:
cd $(CORE_PATH) \
&& CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_agent_on_linux:
cd $(AGENT_PATH) \
&& CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_core_on_darwin:
cd $(CORE_PATH) \
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_agent_on_darwin:
cd $(AGENT_PATH) \
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_all: build_frontend build_core_on_linux build_agent_on_linux
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin
+14 -14
View File
@@ -1,5 +1,5 @@
<p align="center"><a href="https://1panel.pro"><img src="https://resource.1panel.pro/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
<h3 align="center">Take control of your VPS with 1Panel</h3>
<p align="center"><b>Top-Rated Web-based Linux Server Management Tool</b><br>Best VPS control panel<br>新一代的 Linux 服务器运维管理面板</p>
<p align="center">
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 240px; height: auto;" /></a>
</p>
@@ -30,30 +30,30 @@
</p>
------------------------------
## What is 1Panel?
1Panel is a modern, open-source VPS control panel that streamlines administration through an intuitive, clean web interface.
1Panel is an open-source, modern web-based control panel for Linux server management.
## Key Features
- **One-Click OpenClaw Deployment**: Seamlessly deploy OpenClaw agents, host local LLMs using Ollama, and monitor GPU utilization—all within a unified workspace.  
- **One-Click Website Deployment**: Launch production-ready websites instantly with automatic domain binding, SSL certificate provisioning, and configuration—zero manual setup required.  
- **Curated App Marketplace**: Discover, install, and update trusted open-source applications (Nextcloud, Bitwarden, Umami, and more) with a single click.  
- **Centralized Server Management**: Monitor system resources and manage files, databases, containers, and services effortlessly through a unified, intuitive dashboard.  
- **Enterprise-Grade Security**: Strengthen your defenses with container isolation, firewall controls, audit logging, and secure deployment practices—ensuring compliance and peace of mind.  
- **Intelligent Backup & Restore**: Schedule automated backups or perform instant restores to local storage or major cloud platforms (AWS S3, Cloudflare R2, and more), with flexible retention and destination options.  
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, container management, LLMs management.
- **Rapid Website Deployment**: With deep integration of the popular open-source website building software WordPress, 1Panel streamlines the process of domain binding and SSL certificate configuration, all achievable with just one click.
- **Application Store**: 1Panel curates a wide range of high-quality open-source tools and applications, facilitating easy installation and updates for its users.
- **Security and Reliability**: By leveraging containerization and secure application deployment practices, 1Panel minimizes vulnerability exposure. It further enhances security through integrated firewall management and log auditing capabilities.
- **One-Click Backup & Restore**: Data protection is made simple with 1Panel's one-click backup and restore functionality, supporting various cloud storage solutions to ensure data integrity and availability.
## Quick Start
Execute the script below and follow the prompts to install 1Panel:
```bash
bash -c "$(curl -sSL https://resource.1panel.pro/v2/quick_start.sh)"
curl -sSL https://resource.1panel.pro/quick_start.sh -o quick_start.sh && bash quick_start.sh
```
Please refer to our [documentation](https://docs.1panel.pro/quick_start/) for more details.
中国用户请使用这个 [安装脚本](https://1panel.cn/docs/installation/online_installation/),其应用数量比国际版本更丰富。
## Screenshot
![UI Display](https://resource.1panel.pro/img/overview_en_v2.png)
![UI Display](https://resource.1panel.pro/img/1panel.png)
## Star History
@@ -73,4 +73,4 @@ Licensed under The GNU General Public License version 3 (GPLv3) (the "License")
<https://www.gnu.org/licenses/gpl-3.0.html>
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-865
View File
@@ -1,865 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)
// @Tags AI
// @Summary Create Agent
// @Accept json
// @Param request body dto.AgentCreateReq true "request"
// @Success 200 {object} dto.AgentItem
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents [post]
func (b *BaseApi) CreateAgent(c *gin.Context) {
var req dto.AgentCreateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := agentService.Create(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags AI
// @Summary Page Agents
// @Accept json
// @Param request body dto.SearchWithPage true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/search [post]
func (b *BaseApi) PageAgents(c *gin.Context) {
var req dto.SearchWithPage
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := agentService.Page(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags AI
// @Summary Delete Agent
// @Accept json
// @Param request body dto.AgentDeleteReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/delete [post]
func (b *BaseApi) DeleteAgent(c *gin.Context) {
var req dto.AgentDeleteReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.Delete(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Reset Agent token
// @Accept json
// @Param request body dto.AgentTokenResetReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/token/reset [post]
func (b *BaseApi) ResetAgentToken(c *gin.Context) {
var req dto.AgentTokenResetReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.ResetToken(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Update Agent model config
// @Accept json
// @Param request body dto.AgentModelConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/model/update [post]
func (b *BaseApi) UpdateAgentModelConfig(c *gin.Context) {
var req dto.AgentModelConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateModelConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent overview
// @Accept json
// @Param request body dto.AgentOverviewReq true "request"
// @Success 200 {object} dto.AgentOverview
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/overview [post]
func (b *BaseApi) GetAgentOverview(c *gin.Context) {
var req dto.AgentOverviewReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := agentService.GetOverview(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags AI
// @Summary Get Providers
// @Success 200 {array} dto.ProviderInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/providers [get]
func (b *BaseApi) GetAgentProviders(c *gin.Context) {
list, err := agentService.GetProviders()
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags AI
// @Summary Create Agent account
// @Accept json
// @Param request body dto.AgentAccountCreateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts [post]
func (b *BaseApi) CreateAgentAccount(c *gin.Context) {
var req dto.AgentAccountCreateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.CreateAccount(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Update Agent account
// @Accept json
// @Param request body dto.AgentAccountUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/update [post]
func (b *BaseApi) UpdateAgentAccount(c *gin.Context) {
var req dto.AgentAccountUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateAccount(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Page Agent accounts
// @Accept json
// @Param request body dto.AgentAccountSearch true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/search [post]
func (b *BaseApi) PageAgentAccounts(c *gin.Context) {
var req dto.AgentAccountSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := agentService.PageAccounts(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags AI
// @Summary List Agent account models
// @Accept json
// @Param request body dto.AgentAccountModelReq true "request"
// @Success 200 {array} dto.AgentAccountModel
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/models [post]
func (b *BaseApi) GetAgentAccountModels(c *gin.Context) {
var req dto.AgentAccountModelReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := agentService.GetAccountModels(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags AI
// @Summary Create Agent account model
// @Accept json
// @Param request body dto.AgentAccountModelCreateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/models/create [post]
func (b *BaseApi) CreateAgentAccountModel(c *gin.Context) {
var req dto.AgentAccountModelCreateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.CreateAccountModel(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Update Agent account model
// @Accept json
// @Param request body dto.AgentAccountModelUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/models/update [post]
func (b *BaseApi) UpdateAgentAccountModel(c *gin.Context) {
var req dto.AgentAccountModelUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateAccountModel(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Delete Agent account model
// @Accept json
// @Param request body dto.AgentAccountModelDeleteReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/models/delete [post]
func (b *BaseApi) DeleteAgentAccountModel(c *gin.Context) {
var req dto.AgentAccountModelDeleteReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.DeleteAccountModel(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Verify Agent account
// @Accept json
// @Param request body dto.AgentAccountVerifyReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/verify [post]
func (b *BaseApi) VerifyAgentAccount(c *gin.Context) {
var req dto.AgentAccountVerifyReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.VerifyAccount(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Delete Agent account
// @Accept json
// @Param request body dto.AgentAccountDeleteReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/accounts/delete [post]
func (b *BaseApi) DeleteAgentAccount(c *gin.Context) {
var req dto.AgentAccountDeleteReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.DeleteAccount(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent Feishu channel config
// @Accept json
// @Param request body dto.AgentFeishuConfigReq true "request"
// @Success 200 {object} dto.AgentFeishuConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/feishu/get [post]
func (b *BaseApi) GetAgentFeishuConfig(c *gin.Context) {
var req dto.AgentFeishuConfigReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetFeishuConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent Feishu channel config
// @Accept json
// @Param request body dto.AgentFeishuConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/feishu/update [post]
func (b *BaseApi) UpdateAgentFeishuConfig(c *gin.Context) {
var req dto.AgentFeishuConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateFeishuConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent Telegram channel config
// @Accept json
// @Param request body dto.AgentTelegramConfigReq true "request"
// @Success 200 {object} dto.AgentTelegramConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/telegram/get [post]
func (b *BaseApi) GetAgentTelegramConfig(c *gin.Context) {
var req dto.AgentTelegramConfigReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetTelegramConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent Telegram channel config
// @Accept json
// @Param request body dto.AgentTelegramConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/telegram/update [post]
func (b *BaseApi) UpdateAgentTelegramConfig(c *gin.Context) {
var req dto.AgentTelegramConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateTelegramConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent Discord channel config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentDiscordConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/discord/get [post]
func (b *BaseApi) GetAgentDiscordConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetDiscordConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent Discord channel config
// @Accept json
// @Param request body dto.AgentDiscordConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/discord/update [post]
func (b *BaseApi) UpdateAgentDiscordConfig(c *gin.Context) {
var req dto.AgentDiscordConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateDiscordConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent QQ Bot channel config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentWecomConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/wecom/get [post]
func (b *BaseApi) GetAgentWecomConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetWecomConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent WeCom channel config
// @Accept json
// @Param request body dto.AgentWecomConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/wecom/update [post]
func (b *BaseApi) UpdateAgentWecomConfig(c *gin.Context) {
var req dto.AgentWecomConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateWecomConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent DingTalk channel config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentDingTalkConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/dingtalk/get [post]
func (b *BaseApi) GetAgentDingTalkConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetDingTalkConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent DingTalk channel config
// @Accept json
// @Param request body dto.AgentDingTalkConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/dingtalk/update [post]
func (b *BaseApi) UpdateAgentDingTalkConfig(c *gin.Context) {
var req dto.AgentDingTalkConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateDingTalkConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent QQ Bot channel config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentQQBotConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/qqbot/get [post]
func (b *BaseApi) GetAgentQQBotConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetQQBotConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent QQ Bot channel config
// @Accept json
// @Param request body dto.AgentQQBotConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/qqbot/update [post]
func (b *BaseApi) UpdateAgentQQBotConfig(c *gin.Context) {
var req dto.AgentQQBotConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateQQBotConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Install Agent plugin
// @Accept json
// @Param request body dto.AgentPluginInstallReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/plugin/install [post]
func (b *BaseApi) InstallAgentPlugin(c *gin.Context) {
var req dto.AgentPluginInstallReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.InstallPlugin(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Check Agent plugin installation status
// @Accept json
// @Param request body dto.AgentPluginCheckReq true "request"
// @Success 200 {object} dto.AgentPluginStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/plugin/check [post]
func (b *BaseApi) CheckAgentPlugin(c *gin.Context) {
var req dto.AgentPluginCheckReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.CheckPlugin(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Get Agent Security config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentSecurityConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/security/get [post]
func (b *BaseApi) GetAgentSecurityConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetSecurityConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent Security config
// @Accept json
// @Param request body dto.AgentSecurityConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/security/update [post]
func (b *BaseApi) UpdateAgentSecurityConfig(c *gin.Context) {
var req dto.AgentSecurityConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateSecurityConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent Other config
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {object} dto.AgentOtherConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/other/get [post]
func (b *BaseApi) GetAgentOtherConfig(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetOtherConfig(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent Other config
// @Accept json
// @Param request body dto.AgentOtherConfigUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/other/update [post]
func (b *BaseApi) UpdateAgentOtherConfig(c *gin.Context) {
var req dto.AgentOtherConfigUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateOtherConfig(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Get Agent config file
// @Accept json
// @Param request body dto.AgentConfigFileReq true "request"
// @Success 200 {object} dto.AgentConfigFile
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/config-file/get [post]
func (b *BaseApi) GetAgentConfigFile(c *gin.Context) {
var req dto.AgentConfigFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.GetConfigFile(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent config file
// @Accept json
// @Param request body dto.AgentConfigFileUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/config-file/update [post]
func (b *BaseApi) UpdateAgentConfigFile(c *gin.Context) {
var req dto.AgentConfigFileUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateConfigFile(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary List Agent skills
// @Accept json
// @Param request body dto.AgentIDReq true "request"
// @Success 200 {array} dto.AgentSkillItem
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/skills/list [post]
func (b *BaseApi) ListAgentSkills(c *gin.Context) {
var req dto.AgentIDReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.ListSkills(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Search Agent skills
// @Accept json
// @Param request body dto.AgentSkillSearchReq true "request"
// @Success 200 {array} dto.AgentSkillSearchItem
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/skills/search [post]
func (b *BaseApi) SearchAgentSkills(c *gin.Context) {
var req dto.AgentSkillSearchReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := agentService.SearchSkills(req)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags AI
// @Summary Update Agent skill status
// @Accept json
// @Param request body dto.AgentSkillUpdateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/skills/update [post]
func (b *BaseApi) UpdateAgentSkill(c *gin.Context) {
var req dto.AgentSkillUpdateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.UpdateSkill(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Install Agent skill
// @Accept json
// @Param request body dto.AgentSkillInstallReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/skills/install [post]
func (b *BaseApi) InstallAgentSkill(c *gin.Context) {
var req dto.AgentSkillInstallReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.InstallSkill(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Login Agent Weixin channel
// @Accept json
// @Param request body dto.AgentWeixinLoginReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/weixin/login [post]
func (b *BaseApi) LoginAgentWeixinChannel(c *gin.Context) {
var req dto.AgentWeixinLoginReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.LoginWeixinChannel(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
// @Tags AI
// @Summary Approve Agent channel pairing code
// @Accept json
// @Param request body dto.AgentChannelPairingApproveReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/agents/channel/pairing/approve [post]
func (b *BaseApi) ApproveAgentChannelPairing(c *gin.Context) {
var req dto.AgentChannelPairingApproveReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := agentService.ApproveChannelPairing(req); err != nil {
helper.BadRequest(c, err)
return
}
helper.Success(c)
}
+2 -63
View File
@@ -1,13 +1,10 @@
package v2
import (
"net/http"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/appicon"
"github.com/gin-gonic/gin"
)
@@ -29,7 +26,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
helper.InternalServer(c, err)
return
}
helper.SuccessWithDataGzipped(c, list)
helper.SuccessWithData(c, list)
}
// @Tags App
@@ -164,7 +161,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
install, err := appService.Install(req, true)
install, err := appService.Install(req)
if err != nil {
helper.InternalServer(c, err)
return
@@ -195,61 +192,3 @@ func (b *BaseApi) GetAppListUpdate(c *gin.Context) {
}
helper.SuccessWithData(c, res)
}
// @Tags App
// @Summary Get app icon by app_id
// @Accept json
// @Param appId path integer true "app id"
// @Success 200 {file} file "app icon"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/icon/:key [get]
func (b *BaseApi) GetAppIcon(c *gin.Context) {
appKey, err := helper.GetStrParamByKey(c, "key")
if err != nil {
helper.BadRequest(c, err)
return
}
iconBytes, filename, etag, err := appService.GetAppIcon(appKey)
if err != nil {
helper.InternalServer(c, err)
return
}
if len(iconBytes) == 0 {
c.Status(http.StatusNoContent)
return
}
c.Header("Cache-Control", "public, max-age=2592000")
if etag != "" && filename != "" {
c.Header("ETag", etag)
if c.GetHeader("If-None-Match") == etag {
c.Status(http.StatusNotModified)
return
}
}
c.Data(http.StatusOK, appicon.ContentTypePNG, iconBytes)
}
// @Tags App
// @Summary Search app detail by appkey and version
// @Accept json
// @Param appId path integer true "app key"
// @Param version path string true "app version"
// @Success 200 {object} response.AppDetailSimpleDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/detail/node/:appKey/:version [get]
func (b *BaseApi) GetAppDetailForNode(c *gin.Context) {
appKey := c.Param("appKey")
version := c.Param("version")
appDetailDTO, err := appService.GetAppDetailByKey(appKey, version)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, appDetailDTO)
}
+2 -14
View File
@@ -109,7 +109,7 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
// @Success 200 {object} response.DatabaseConn
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/conninfo [post]
// @Router /apps/installed/conninfo [POST]
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -294,7 +294,7 @@ func (b *BaseApi) GetParams(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/params/update [post]
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"name","output_value":"name"}],"formatZH":"应用参数修改 [name]","formatEN":"Application param update [name]"}
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用参数修改 [installId]","formatEN":"Application param update [installId]"}
func (b *BaseApi) UpdateInstalled(c *gin.Context) {
var req request.AppInstalledUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -349,15 +349,3 @@ func (b *BaseApi) GetAppInstallInfo(c *gin.Context) {
}
helper.SuccessWithData(c, info)
}
func (b *BaseApi) UpdateAppInstallSort(c *gin.Context) {
var req request.AppInstallSort
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appInstallService.UpdateSort(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
-47
View File
@@ -25,23 +25,6 @@ func (b *BaseApi) CheckBackupUsed(c *gin.Context) {
helper.Success(c)
}
// @Tags Backup Account
// @Summary Check backup account
// @Accept json
// @Param request body dto.BackupOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /backups/check [post]
func (b *BaseApi) CheckBackup(c *gin.Context) {
var req dto.BackupOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, backupService.CheckConn(req))
}
// @Tags Backup Account
// @Summary Create backup account
// @Accept json
@@ -430,16 +413,6 @@ func (b *BaseApi) Backup(c *gin.Context) {
helper.InternalServer(c, err)
return
}
case "container":
if err := backupService.ContainerBackup(req); err != nil {
helper.InternalServer(c, err)
return
}
case "compose":
if err := backupService.ComposeBackup(req); err != nil {
helper.InternalServer(c, err)
return
}
}
helper.Success(c)
}
@@ -495,16 +468,6 @@ func (b *BaseApi) Recover(c *gin.Context) {
helper.InternalServer(c, err)
return
}
case "container":
if err := backupService.ContainerRecover(req); err != nil {
helper.InternalServer(c, err)
return
}
case "compose":
if err := backupService.ComposeRecover(req); err != nil {
helper.InternalServer(c, err)
return
}
}
helper.Success(c)
}
@@ -545,16 +508,6 @@ func (b *BaseApi) RecoverByUpload(c *gin.Context) {
helper.InternalServer(c, err)
return
}
case "container":
if err := backupService.ContainerRecover(req); err != nil {
helper.InternalServer(c, err)
return
}
case "compose":
if err := backupService.ComposeRecover(req); err != nil {
helper.InternalServer(c, err)
return
}
}
helper.Success(c)
}
-22
View File
@@ -28,28 +28,6 @@ func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
helper.Success(c)
}
// @Tags Container Compose-template
// @Summary Bacth compose template
// @Accept json
// @Param request body dto.ComposeTemplateBatch true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/template/batch [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量导入编排模版","formatEN":"batch import compose templates"}
func (b *BaseApi) BatchComposeTemplate(c *gin.Context) {
var req dto.ComposeTemplateBatch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := composeTemplateService.Batch(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Container Compose-template
// @Summary Page compose templates
// @Accept json
+24 -228
View File
@@ -1,9 +1,6 @@
package v2
import (
"net/http"
"net/url"
"path"
"strconv"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
@@ -56,162 +53,6 @@ func (b *BaseApi) LoadContainerUsers(c *gin.Context) {
helper.SuccessWithData(c, containerService.LoadUsers(req))
}
// @Tags Container
// @Summary List container files
// @Accept json
// @Param request body dto.ContainerFileReq true "request"
// @Success 200 {array} dto.ContainerFileInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/search [post]
func (b *BaseApi) ListContainerFiles(c *gin.Context) {
var req dto.ContainerFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
files, err := containerService.ListContainerFiles(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, files)
}
// @Tags Container
// @Summary Upload container file
// @Accept multipart/form-data
// @Param containerID formData string true "containerID"
// @Param path formData string true "path"
// @Param file formData file true "file"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/upload [post]
// @x-panel-log {"bodyKeys":["containerID","path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器 [containerID] 上传文件到 [path]","formatEN":"Upload file to [path] in container [containerID]"}
func (b *BaseApi) UploadContainerFile(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
helper.BadRequest(c, err)
return
}
containerIDs := form.Value["containerID"]
paths := form.Value["path"]
uploadFiles := form.File["file"]
if len(containerIDs) == 0 || len(paths) == 0 || len(uploadFiles) == 0 {
helper.BadRequest(c, errors.New("invalid container file upload params"))
return
}
req := dto.ContainerFileReq{
ContainerID: containerIDs[0],
Path: paths[0],
}
for _, uploadFile := range uploadFiles {
file, err := uploadFile.Open()
if err != nil {
helper.InternalServer(c, err)
return
}
err = containerService.UploadContainerFile(req, path.Base(uploadFile.Filename), uploadFile.Size, file)
_ = file.Close()
if err != nil {
helper.InternalServer(c, err)
return
}
}
helper.Success(c)
}
// @Tags Container
// @Summary Get container file content
// @Accept json
// @Param request body dto.ContainerFileReq true "request"
// @Success 200 {object} dto.ContainerFileContent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/content [post]
func (b *BaseApi) GetContainerFileContent(c *gin.Context) {
var req dto.ContainerFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := containerService.GetContainerFileContent(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, content)
}
// @Tags Container
// @Summary Get container file size
// @Accept json
// @Param request body dto.ContainerFileReq true "request"
// @Success 200 {int} size
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/size [post]
func (b *BaseApi) GetContainerFileSize(c *gin.Context) {
var req dto.ContainerFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
size, err := containerService.GetContainerFileSize(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, size)
}
// @Tags Container
// @Summary Delete container file
// @Accept json
// @Param request body dto.ContainerFileBatchDeleteReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/del [post]
// @x-panel-log {"bodyKeys":["containerID","paths"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器 [containerID] 文件 [paths]","formatEN":"Delete files [paths] in container [containerID]"}
func (b *BaseApi) DeleteContainerFile(c *gin.Context) {
var req dto.ContainerFileBatchDeleteReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.DeleteContainerFile(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Container
// @Summary Download container file
// @Accept json
// @Param request body dto.ContainerFileReq true "request"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/files/download [post]
// @x-panel-log {"bodyKeys":["containerID","path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载容器 [containerID] 文件 [path]","formatEN":"Download file [path] from container [containerID]"}
func (b *BaseApi) DownloadContainerFile(c *gin.Context) {
var req dto.ContainerFileReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.BadRequest(c, err)
return
}
if req.ContainerID == "" || req.Path == "" {
helper.BadRequest(c, errors.New("invalid container file download params"))
return
}
reader, fileName, contentType, err := containerService.DownloadContainerFile(req)
if err != nil {
helper.InternalServer(c, err)
return
}
defer reader.Close()
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName))
c.DataFromReader(http.StatusOK, -1, contentType, reader, nil)
}
// @Tags Container
// @Summary List containers
// @Accept json
@@ -422,27 +263,6 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) {
helper.SuccessWithData(c, data)
}
// @Summary Load container stats size
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.ContainerItemStats
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/item/stats [post]
func (b *BaseApi) ContainerItemStats(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := containerService.ContainerItemStats(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Container
// @Summary Create container
// @Accept json
@@ -465,6 +285,27 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
helper.Success(c)
}
// @Tags Container
// @Summary Create container by command
// @Accept json
// @Param request body dto.ContainerCreateByCommand true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/command [post]
func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) {
var req dto.ContainerCreateByCommand
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerCreateByCommand(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Container
// @Summary Upgrade container
// @Accept json
@@ -473,7 +314,7 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/upgrade [post]
// @x-panel-log {"bodyKeys":["names","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [names][image]","formatEN":"upgrade container image [names][image]"}
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"}
func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
var req dto.ContainerUpgrade
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -531,28 +372,6 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
helper.Success(c)
}
// @Tags Container
// @Summary Clean compose log
// @Accept json
// @Param request body dto.ComposeLogClean true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose/clean/log [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器编排 [name] 日志","formatEN":"clean compose [name] logs"}
func (b *BaseApi) CleanComposeLog(c *gin.Context) {
var req dto.ComposeLogClean
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ComposeLogClean(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Container
// @Summary Rename Container
// @Accept json
@@ -662,12 +481,13 @@ func (b *BaseApi) Inspect(c *gin.Context) {
helper.SuccessWithData(c, result)
}
// @Router /containers/download/log [post]
func (b *BaseApi) DownloadContainerLogs(c *gin.Context) {
var req dto.ContainerLog
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := containerService.DownloadContainerLogs(req.ContainerType, req.Container, req.Since, strconv.Itoa(int(req.Tail)), req.Timestamp, c)
err := containerService.DownloadContainerLogs(req.ContainerType, req.Container, req.Since, strconv.Itoa(int(req.Tail)), c)
if err != nil {
helper.InternalServer(c, err)
}
@@ -869,34 +689,12 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
helper.Success(c)
}
// @Tags Container Compose
// @Summary Load compose environment variables
// @Accept json
// @Param request body dto.FilePath true "request"
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose/env [post]
func (b *BaseApi) LoadComposeEnv(c *gin.Context) {
var req dto.FilePath
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := containerService.LoadComposeEnv(req.Path)
if err != nil {
helper.InternalServer(c, err)
}
helper.SuccessWithData(c, data)
}
// @Tags Container
// @Summary Container logs
// @Param container query string false "容器名称"
// @Param since query string false "时间筛选"
// @Param follow query string false "是否追踪"
// @Param tail query string false "显示行号"
// @Param timestamp query string false "是否显示时间"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/search/log [get]
@@ -909,7 +707,6 @@ func (b *BaseApi) ContainerStreamLogs(c *gin.Context) {
since := c.Query("since")
follow := c.Query("follow") == "true"
tail := c.Query("tail")
timestamp := c.Query("timestamp") == "true"
container := c.Query("container")
compose := c.Query("compose")
@@ -919,7 +716,6 @@ func (b *BaseApi) ContainerStreamLogs(c *gin.Context) {
Since: since,
Follow: follow,
Tail: tail,
Timestamp: timestamp,
Type: "container",
}
if compose != "" {
+1 -1
View File
@@ -211,7 +211,7 @@ func (b *BaseApi) LoadRecordLog(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /cronjobs/records/clean [post]
// @x-panel-log {"bodyKeys":["cronjobID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"cronjobID","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
func (b *BaseApi) CleanRecord(c *gin.Context) {
var req dto.CronjobClean
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+4 -26
View File
@@ -27,7 +27,7 @@ func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
// @Tags Dashboard
// @Summary Load app launcher
// @Accept json
// @Success 200 {array} dto.AppLauncher
// @Success 200 {Array} dto.AppLauncher
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/app/launcher [get]
@@ -37,14 +37,14 @@ func (b *BaseApi) LoadAppLauncher(c *gin.Context) {
helper.InternalServer(c, err)
return
}
helper.SuccessWithDataGzipped(c, data)
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load app launcher options
// @Accept json
// @Param request body dto.SearchByFilter true "request"
// @Success 200 {array} dto.LauncherOption
// @Success 200 {Array} dto.LauncherOption
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/app/launcher/option [post]
@@ -85,7 +85,7 @@ func (b *BaseApi) UpdateAppLauncher(c *gin.Context) {
// @Tags Dashboard
// @Summary Load quick jump options
// @Success 200 {array} dto.QuickJump
// @Success 200 {Array} dto.QuickJump
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/quick/option [get]
@@ -179,28 +179,6 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load top cpu processes
// @Success 200 {array} dto.Process
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/current/top/cpu [get]
func (b *BaseApi) LoadDashboardTopCPU(c *gin.Context) {
data := dashboardService.LoadTopCPU()
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load top memory processes
// @Success 200 {array} dto.Process
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/current/top/mem [get]
func (b *BaseApi) LoadDashboardTopMem(c *gin.Context) {
data := dashboardService.LoadTopMem()
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary System restart
// @Accept json
+10 -9
View File
@@ -195,26 +195,27 @@ func (b *BaseApi) SearchMysql(c *gin.Context) {
}
// @Tags Database Mysql
// @Summary List mysql database format collation options
// @Summary List mysql database names
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200 {array} dto.MysqlFormatCollationOption
// @Param request body dto.PageInfo true "request"
// @Success 200 {array} dto.MysqlOption
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/format/options [post]
func (b *BaseApi) ListDBFormatCollationOptions(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
// @Router /databases/options [get]
func (b *BaseApi) ListDBName(c *gin.Context) {
list, err := mysqlService.ListDBOption()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, mysqlService.LoadFormatOption(req))
helper.SuccessWithData(c, list)
}
// @Tags Database Mysql
// @Summary Load mysql database from remote
// @Accept json
// @Param request body dto.MysqlLoadDB true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/load [post]
-1
View File
@@ -167,7 +167,6 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) {
// @Summary Load postgresql database from remote
// @Accept json
// @Param request body dto.PostgresqlLoadDB true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/pg/:database/load [post]
+1 -1
View File
@@ -27,7 +27,7 @@ func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) {
// @Tags Device
// @Summary list time zone options
// @Accept json
// @Success 200 {array} string
// @Success 200 {Array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/device/zone/options [get]
+2 -2
View File
@@ -12,7 +12,7 @@ import (
// @Tags Container Docker
// @Summary Load docker status
// @Produce json
// @Success 200 {object} dto.DockerStatus
// @Success 200 {string} dto.DockerStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/docker/status [get]
@@ -24,7 +24,7 @@ func (b *BaseApi) LoadDockerStatus(c *gin.Context) {
// @Tags Container Docker
// @Summary Load docker daemon.json
// @Produce json
// @Success 200 {string} string
// @Success 200 {object} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/daemonjson/file [get]
-3
View File
@@ -20,7 +20,6 @@ var (
aiToolService = service.NewIAIToolService()
mcpServerService = service.NewIMcpServerService()
tensorrtLLMService = service.NewITensorRTLLMService()
agentService = service.NewIAgentService()
containerService = service.NewIContainerService()
composeTemplateService = service.NewIComposeTemplateService()
@@ -39,7 +38,6 @@ var (
fileService = service.NewIFileService()
sshService = service.NewISSHService()
firewallService = service.NewIFirewallService()
iptablesService = service.NewIIptablesService()
monitorService = service.NewIMonitorService()
systemService = service.NewISystemService()
@@ -70,7 +68,6 @@ var (
recycleBinService = service.NewIRecycleBinService()
favoriteService = service.NewIFavoriteService()
hostService = service.NewIHostService()
websiteCAService = service.NewIWebsiteCAService()
taskService = service.NewITaskService()
+2 -4
View File
@@ -28,7 +28,7 @@ func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) {
// @Summary Page fail2ban ip list
// @Accept json
// @Param request body dto.Fail2BanSearch true "request"
// @Success 200 {array} string
// @Success 200 {Array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/search [post]
@@ -51,7 +51,6 @@ func (b *BaseApi) SearchFail2Ban(c *gin.Context) {
// @Summary Operate fail2ban
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/operate [post]
@@ -73,8 +72,7 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) {
// @Tags Fail2ban
// @Summary Operate sshd of fail2ban
// @Accept json
// @Param request body dto.Fail2BanSet true "request"
// @Success 200
// @Param request body dto.Operate true "request"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/operate/sshd [post]
+3 -99
View File
@@ -90,7 +90,7 @@ func (b *BaseApi) GetFileTree(c *gin.Context) {
helper.InternalServer(c, err)
return
}
helper.SuccessWithDataGzipped(c, tree)
helper.SuccessWithData(c, tree)
}
// @Tags File
@@ -265,33 +265,6 @@ func (b *BaseApi) GetContent(c *gin.Context) {
helper.InternalServer(c, err)
return
}
if info.Size > 2*1024 && info.Size < 5*1024*1024 {
helper.SuccessWithDataGzipped(c, info)
} else {
helper.SuccessWithData(c, info)
}
}
// @Tags File
// @Summary Preview file content
// @Accept json
// @Param request body request.FileContentReq true "request"
// @Success 200 {object} response.FileInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/preview [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"预览文件内容 [path]","formatEN":"Preview file content [path]"}
func (b *BaseApi) PreviewContent(c *gin.Context) {
var req request.FileContentReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
info, err := fileService.GetPreviewContent(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, info)
}
@@ -515,29 +488,6 @@ func (b *BaseApi) WgetFile(c *gin.Context) {
})
}
// @Tags File
// @Summary Stop wget file download
// @Accept json
// @Param request body request.FileProcessReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/wget/stop [post]
// @x-panel-log {"bodyKeys":["key"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"停止下载任务 [key]","formatEN":"Stop wget task [key]"}
func (b *BaseApi) StopWget(c *gin.Context) {
var req request.FileProcessReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if strings.TrimSpace(req.Key) == "" {
helper.BadRequest(c, errors.New("key is required"))
return
}
files.CancelDownload(req.Key)
helper.Success(c)
}
// @Tags File
// @Summary Move file
// @Accept json
@@ -571,14 +521,9 @@ func (b *BaseApi) Download(c *gin.Context) {
file, err := os.Open(filePath)
if err != nil {
helper.InternalServer(c, err)
return
}
defer file.Close()
info, err := file.Stat()
if err != nil {
helper.InternalServer(c, err)
return
}
info, _ := file.Stat()
c.Header("Content-Length", strconv.FormatInt(info.Size(), 10))
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name()))
http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file)
@@ -896,11 +841,7 @@ func (b *BaseApi) ReadFileByLine(c *gin.Context) {
helper.InternalServer(c, err)
return
}
if res.TotalLines > 100 {
helper.SuccessWithDataGzipped(c, res)
} else {
helper.SuccessWithData(c, res)
}
helper.SuccessWithData(c, res)
}
// @Tags File
@@ -1001,40 +942,3 @@ func (b *BaseApi) ConvertLog(c *gin.Context) {
Total: total,
})
}
// @Tags File
// @Summary Batch get file remarks
// @Accept json
// @Param request body request.FileRemarkBatch true "request"
// @Success 200 {object} response.FileRemarksRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/remarks [post]
func (b *BaseApi) BatchGetFileRemarks(c *gin.Context) {
var req request.FileRemarkBatch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
remarks := fileService.BatchGetRemarks(req)
helper.SuccessWithData(c, response.FileRemarksRes{Remarks: remarks})
}
// @Tags File
// @Summary Set file remark
// @Accept json
// @Param request body request.FileRemarkUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/remark [post]
func (b *BaseApi) SetFileRemark(c *gin.Context) {
var req request.FileRemarkUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.SetRemark(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
+8 -124
View File
@@ -8,19 +8,12 @@ import (
// @Tags Firewall
// @Summary Load firewall base info
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.FirewallBaseInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/base [post]
// @Router /hosts/firewall/base [get]
func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := firewallService.LoadBaseInfo(req.Name)
data, err := firewallService.LoadBaseInfo()
if err != nil {
helper.InternalServer(c, err)
return
@@ -102,14 +95,14 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) {
// OperateForwardRule
// @Tags Firewall
// @Summary Operate forward rule
// @Summary Create group
// @Accept json
// @Param request body dto.ForwardRuleOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/forward [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则","formatEN":"update port forward rules"}
// @x-panel-log {"bodyKeys":["source_port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则 [source_port]","formatEN":"update port forward rules [source_port]"}
func (b *BaseApi) OperateForwardRule(c *gin.Context) {
var req dto.ForwardRuleOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -124,7 +117,7 @@ func (b *BaseApi) OperateForwardRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Operate Ip rule
// @Summary Create group
// @Accept json
// @Param request body dto.AddrRuleOperate true "request"
// @Success 200
@@ -146,7 +139,7 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Batch operate rule
// @Summary Create group
// @Accept json
// @Param request body dto.BatchRuleOperate true "request"
// @Success 200
@@ -188,7 +181,7 @@ func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
}
// @Tags Firewall
// @Summary Update port rule
// @Summary Create group
// @Accept json
// @Param request body dto.PortRuleUpdate true "request"
// @Success 200
@@ -209,7 +202,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Update Ip rule
// @Summary Create group
// @Accept json
// @Param request body dto.AddrRuleUpdate true "request"
// @Success 200
@@ -228,112 +221,3 @@ func (b *BaseApi) UpdateAddrRule(c *gin.Context) {
}
helper.Success(c)
}
// @Tags Firewall
// @Summary search iptables filter rules
// @Accept json
// @Param request body dto.SearchPageWithType true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/search [post]
func (b *BaseApi) SearchFilterRules(c *gin.Context) {
var req dto.SearchPageWithType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := iptablesService.Search(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags Firewall
// @Summary Operate iptables filter rule
// @Accept json
// @Param request body dto.IptablesRuleOp true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/rule/operate [post]
// @x-panel-log {"bodyKeys":["operation","chain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] filter规则到 [chain]","formatEN":"[operation] filter rule to [chain]"}
func (b *BaseApi) OperateFilterRule(c *gin.Context) {
var req dto.IptablesRuleOp
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.OperateRule(req, true); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary Batch operate iptables filter rules
// @Accept json
// @Param request body dto.IptablesBatchOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/rule/batch [post]
func (b *BaseApi) BatchOperateFilterRule(c *gin.Context) {
var req dto.IptablesBatchOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.BatchOperate(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary Apply/Unload/Init iptables filter
// @Accept json
// @Param request body dto.IptablesOp true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/operate [post]
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] iptables filter 防火墙","formatEN":"[operate] iptables filter firewall"}
func (b *BaseApi) OperateFilterChain(c *gin.Context) {
var req dto.IptablesOp
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.Operate(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary load chain status with name
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/chain/status [post]
func (b *BaseApi) LoadChainStatus(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, iptablesService.LoadChainStatus(req))
}
-1
View File
@@ -54,7 +54,6 @@ func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) {
// @Summary Operate FTP
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/ftp/operate [post]
-40
View File
@@ -1,14 +1,10 @@
package helper
import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"github.com/1Panel-dev/1Panel/agent/global"
"gorm.io/gorm"
@@ -50,42 +46,6 @@ func SuccessWithData(ctx *gin.Context, data interface{}) {
ctx.Abort()
}
var gzipWriterPool = sync.Pool{
New: func() interface{} {
return gzip.NewWriter(nil)
},
}
func SuccessWithDataGzipped(ctx *gin.Context, data interface{}) {
if !strings.Contains(ctx.GetHeader("Accept-Encoding"), "gzip") {
SuccessWithData(ctx, data)
return
}
if data == nil {
data = gin.H{}
}
res := dto.Response{
Code: http.StatusOK,
Data: data,
}
jsonBytes, err := json.Marshal(res)
if err != nil {
ErrorWithDetail(ctx, http.StatusInternalServerError, "ErrInternalServer", err)
return
}
ctx.Header("Content-Encoding", "gzip")
ctx.Header("Content-Type", "application/json; charset=utf-8")
ctx.Status(http.StatusOK)
gz := gzipWriterPool.Get().(*gzip.Writer)
gz.Reset(ctx.Writer)
_, _ = gz.Write(jsonBytes)
_ = gz.Close()
gzipWriterPool.Put(gz)
ctx.Abort()
}
func Success(ctx *gin.Context) {
res := dto.Response{
Code: http.StatusOK,
-167
View File
@@ -1,167 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/gin-gonic/gin"
)
func (b *BaseApi) CreateHost(c *gin.Context) {
var req dto.HostOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
host, err := hostService.Create(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, host)
}
func (b *BaseApi) TestByInfo(c *gin.Context) {
var req dto.HostConnTest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, hostService.TestByInfo(req))
}
func (b *BaseApi) TestByID(c *gin.Context) {
var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, hostService.TestLocalConn(req.ID))
}
func (b *BaseApi) HostTree(c *gin.Context) {
var req dto.SearchForTree
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := hostService.SearchForTree(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
func (b *BaseApi) SearchHost(c *gin.Context) {
var req dto.SearchPageWithGroup
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := hostService.SearchWithPage(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{Items: list, Total: total})
}
func (b *BaseApi) DeleteHost(c *gin.Context) {
var req dto.OperateByIDs
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := hostService.Delete(req.IDs); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) UpdateHost(c *gin.Context) {
var req dto.HostOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
var err error
if len(req.Password) != 0 && req.AuthMode == "password" {
req.Password, err = hostService.EncryptHost(req.Password)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PrivateKey = ""
req.PassPhrase = ""
}
if len(req.PrivateKey) != 0 && req.AuthMode == "key" {
req.PrivateKey, err = hostService.EncryptHost(req.PrivateKey)
if err != nil {
helper.BadRequest(c, err)
return
}
if len(req.PassPhrase) != 0 {
req.PassPhrase, err = encrypt.StringEncrypt(req.PassPhrase)
if err != nil {
helper.BadRequest(c, err)
return
}
}
req.Password = ""
}
upMap := map[string]interface{}{
"name": req.Name,
"group_id": req.GroupID,
"addr": req.Addr,
"port": req.Port,
"user": req.User,
"auth_mode": req.AuthMode,
"remember_password": req.RememberPassword,
"description": req.Description,
}
if req.AuthMode == "password" {
upMap["password"] = req.Password
upMap["private_key"] = ""
upMap["pass_phrase"] = ""
} else {
upMap["password"] = ""
upMap["private_key"] = req.PrivateKey
upMap["pass_phrase"] = req.PassPhrase
}
hostItem, err := hostService.Update(req.ID, upMap)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, hostItem)
}
func (b *BaseApi) UpdateHostGroup(c *gin.Context) {
var req dto.ChangeGroup
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if _, err := hostService.Update(req.ID, map[string]interface{}{"group_id": req.GroupID}); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) GetHostByID(c *gin.Context) {
var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
info, err := hostService.GetHostByID(req.ID)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, info)
}
-25
View File
@@ -28,27 +28,6 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
helper.InternalServer(c, err)
return
}
helper.SuccessWithDataGzipped(c, data)
}
// @Tags Monitor
// @Summary Load monitor data
// @Param request body dto.MonitorGPUSearch true "request"
// @Success 200 {object} dto.MonitorGPUData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/gpu/search [post]
func (b *BaseApi) LoadGPUMonitor(c *gin.Context) {
var req dto.MonitorGPUSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := monitorService.LoadGPUMonitorData(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
@@ -126,7 +105,3 @@ func (b *BaseApi) GetIOOptions(c *gin.Context) {
sort.Strings(options)
helper.SuccessWithData(c, options)
}
func (b *BaseApi) GetCPUOptions(c *gin.Context) {
helper.SuccessWithData(c, monitorService.LoadGPUOptions())
}
+2 -2
View File
@@ -161,13 +161,13 @@ func (b *BaseApi) GetNginxModules(c *gin.Context) {
// @Tags OpenResty
// @Summary Operate default HTTPs
// @Accept json
// @Param request body request.NginxDefaultHTTPSUpdate true "request"
// @Param request body request.NginxOperateReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /openresty/https [post]
func (b *BaseApi) OperateDefaultHTTPs(c *gin.Context) {
var req request.NginxDefaultHTTPSUpdate
var req request.NginxOperateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+1 -16
View File
@@ -40,7 +40,7 @@ func (b *BaseApi) StopProcess(c *gin.Context) {
// @Tags Process
// @Summary Get Process Info By PID
// @Param pid path int true "PID"
// @Success 200
// @Success 200 {object} websocket.PsProcessData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /process/{pid} [get]
@@ -57,18 +57,3 @@ func (b *BaseApi) GetProcessInfoByPID(c *gin.Context) {
}
helper.SuccessWithData(c, data)
}
// @Tags Process
// @Summary Get Listening Process
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /process/listening [post]
func (b *BaseApi) GetListeningProcess(c *gin.Context) {
procs, err := processService.GetListeningProcess(c)
if err != nil {
helper.BadRequest(c, err)
return
}
helper.SuccessWithData(c, procs)
}
+2 -70
View File
@@ -27,15 +27,6 @@ func (b *BaseApi) GetSettingInfo(c *gin.Context) {
helper.SuccessWithData(c, setting)
}
func (b *BaseApi) GetTerminalAISettingInfo(c *gin.Context) {
setting, err := settingService.GetTerminalAIInfo()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, setting)
}
// @Tags System Setting
// @Summary Load system available status
// @Success 200
@@ -68,19 +59,6 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
helper.Success(c)
}
func (b *BaseApi) UpdateTerminalAISetting(c *gin.Context) {
var req dto.TerminalAIInfo
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.UpdateTerminalAI(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags System Setting
// @Summary Load local backup dir
// @Success 200 {string} path
@@ -102,38 +80,13 @@ func (b *BaseApi) LoadLocalConn(c *gin.Context) {
}
func (b *BaseApi) CheckLocalConn(c *gin.Context) {
client, err := loadLocalConn()
if err == nil && client != nil {
client.Close()
}
_, err := loadLocalConn()
helper.SuccessWithData(c, err == nil)
}
// @Tags System Setting
// @Summary Update local is conn
// @Accept json
// @Param request body dto.SSHDefaultConn true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssh/conn/default [post]
// @x-panel-log {"bodyKeys":["defaultConn"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"本地终端默认连接 [defaultConn]","formatEN":"update system default conn [defaultConn]"}
func (b *BaseApi) SetDefaultIsConn(c *gin.Context) {
var req dto.SSHDefaultConn
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.SetDefaultIsConn(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags System Setting
// @Summary Check local conn info
// @Success 200 {boolean} isOk
// @Success 200 {bool} isOk
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssh/check/info [post]
@@ -202,24 +155,3 @@ func (b *BaseApi) GetSettingByKey(c *gin.Context) {
value := settingService.GetSettingByKey(key)
helper.SuccessWithData(c, value)
}
// @Tags System Setting
// @Summary Save common description
// @Accept json
// @Param request body dto.CommonDescription true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/description/save [post]
func (b *BaseApi) SaveDescription(c *gin.Context) {
var req dto.CommonDescription
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.SaveDescription(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
+1 -1
View File
@@ -53,7 +53,7 @@ func (b *BaseApi) OperateSSH(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/update [post]
// @x-panel-log {"bodyKeys":["key","newValue"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [newValue]","formatEN":"update SSH setting [key] => [newValue]"}
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"}
func (b *BaseApi) UpdateSSH(c *gin.Context) {
var req dto.SSHUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// @Tags Host
// @Summary Check if a system component exists
// @Accept json
// @Param name path string true "Component name to check (e.g., rsync, docker)"
// @Param name query string true "Component name to check (e.g., rsync, docker)"
// @Success 200 {object} response.ComponentInfo
// @Security ApiKeyAuth
// @Security Timestamp
+1 -1
View File
@@ -32,7 +32,7 @@ func (b *BaseApi) PageTasks(c *gin.Context) {
// @Tags TaskLog
// @Summary Get the number of executing tasks
// @Success 200 {integer} int64
// @Success 200 {object} int64
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/tasks/executing/count [get]
+5 -31
View File
@@ -9,10 +9,8 @@ import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/service"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
"github.com/1Panel-dev/1Panel/agent/utils/terminal"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
@@ -42,33 +40,9 @@ func (b *BaseApi) WsSSH(c *gin.Context) {
return
}
hostID, _ := strconv.Atoi(c.DefaultQuery("id", "0"))
var client *ssh.SSHClient
if hostID > 0 {
host, err := service.GetHostInfo(uint(hostID))
if wshandleError(wsConn, errors.WithMessage(err, "load host info by id failed")) {
return
}
connInfo := ssh.ConnInfo{
Addr: host.Addr,
Port: int(host.Port),
User: host.User,
AuthMode: host.AuthMode,
Password: host.Password,
PrivateKey: []byte(host.PrivateKey),
}
if len(host.PassPhrase) != 0 {
connInfo.PassPhrase = []byte(host.PassPhrase)
}
client, err = ssh.NewClient(connInfo)
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) {
return
}
} else {
client, err = loadLocalConn()
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) {
return
}
client, err := loadLocalConn()
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) {
return
}
defer client.Close()
command := c.DefaultQuery("command", "")
@@ -254,8 +228,8 @@ func wshandleError(ws *websocket.Conn, err error) bool {
}
var upGrader = websocket.Upgrader{
ReadBufferSize: 4096,
WriteBufferSize: 16384,
ReadBufferSize: 1024,
WriteBufferSize: 1024 * 1024 * 10,
CheckOrigin: func(r *http.Request) bool {
return true
},
+5 -109
View File
@@ -73,7 +73,7 @@ func (b *BaseApi) GetWebsiteOptions(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites [post]
// @x-panel-log {"bodyKeys":["alias"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [alias]","formatEN":"Create website [alias]"}
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"}
func (b *BaseApi) CreateWebsite(c *gin.Context) {
var req request.WebsiteCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -506,7 +506,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies/update [post]
// @x-panel-log {"bodyKeys":["id","name","operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改 [operate] 网站 [domain] 反向代理配置 [name] ","formatEN":"Update [operate] domain [domain] proxy config [name]"}
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"}
func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
var req request.WebsiteProxyConfig
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -520,50 +520,6 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
helper.Success(c)
}
// @Tags Website
// @Summary Delete proxy config
// @Accept json
// @Param request body request.WebsiteProxyDel true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies/delete [post]
// @x-panel-log {"bodyKeys":["id","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain] 反向代理配置 [name] ","formatEN":"Delete domain [domain] proxy config [name]"}
func (b *BaseApi) DeleteProxyConfig(c *gin.Context) {
var req request.WebsiteProxyDel
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.DeleteProxy(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Update proxy config status
// @Accept json
// @Param request body request.WebsiteProxyStatusUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies/status [post]
// @x-panel-log {"bodyKeys":["id","name","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 [name] 状态 [status] ","formatEN":"Update domain [domain] proxy config [name] status [status]"}
func (b *BaseApi) UpdateProxyConfigStatus(c *gin.Context) {
var req request.WebsiteProxyStatusUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.UpdateProxyStatus(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Update proxy file
// @Accept json
@@ -572,7 +528,7 @@ func (b *BaseApi) UpdateProxyConfigStatus(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies/file [post]
// @x-panel-log {"bodyKeys":["websiteID","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置文件 [name] ","formatEN":"Update domain [domain] proxy config file [name]"}
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
var req request.NginxProxyUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -716,7 +672,7 @@ func (b *BaseApi) UpdateAntiLeech(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/redirect/update [post]
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向配置 ","formatEN":"Update domain [domain] redirect config"}
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向理配置 ","formatEN":"Update domain [domain] redirect config"}
func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
var req request.NginxRedirectReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -1189,7 +1145,7 @@ func (b *BaseApi) ExecComposer(c *gin.Context) {
// @Tags Website
// @Summary Batch operate websites
// @Accept json
// @Param request body request.BatchWebsiteOp true "request"
// @Param request body request.BatchOpWebsite true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
@@ -1206,26 +1162,6 @@ func (b *BaseApi) BatchOpWebsites(c *gin.Context) {
helper.Success(c)
}
// @Tags Website
// @Summary Batch set website group
// @Accept json
// @Param request body request.BatchWebsiteGroup true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/batch/group [post]
func (b *BaseApi) BatchSetWebsiteGroup(c *gin.Context) {
var req request.BatchWebsiteGroup
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.BatchSetGroup(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Get CORS Config
// @Accept json
@@ -1267,43 +1203,3 @@ func (b *BaseApi) UpdateCORSConfig(c *gin.Context) {
}
helper.Success(c)
}
// @Tags Website
// @Summary Update Stream Config
// @Accept json
// @Param request body request.StreamUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/stream/update [post]
func (b *BaseApi) UpdateStreamConfig(c *gin.Context) {
var req request.StreamUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateStream(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Batch set HTTPS for websites
// @Accept json
// @Param request body request.BatchWebsiteHttps true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/batch/https [post]
func (b *BaseApi) BatchSetHttps(c *gin.Context) {
var req request.BatchWebsiteHttps
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.BatchSetHttps(c, req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
+21 -32
View File
@@ -1,14 +1,14 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"io"
"mime/multipart"
"net/http"
"net/url"
"reflect"
"strconv"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
@@ -25,39 +25,27 @@ import (
// @Router /websites/ssl/search [post]
func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, accounts, err := websiteSSLService.Page(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithDataGzipped(c, dto.PageResult{
Total: total,
Items: accounts,
})
}
// @Tags Website SSL
// @Summary List website ssl
// @Accept json
// @Param request body request.WebsiteSSLListReq true "request"
// @Success 200 {array} response.WebsiteSSLDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/list [post]
func (b *BaseApi) ListWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLListReq
if err := helper.CheckBind(&req, c); err != nil {
return
}
list, err := websiteSSLService.Search(req)
if err != nil {
helper.InternalServer(c, err)
return
if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) {
total, accounts, err := websiteSSLService.Page(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: accounts,
})
} else {
list, err := websiteSSLService.Search(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, list)
}
helper.SuccessWithDataGzipped(c, list)
}
// @Tags Website SSL
@@ -247,6 +235,7 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
func (b *BaseApi) UploadSSLFile(c *gin.Context) {
var req request.WebsiteSSLFileUpload
req.Type = c.PostForm("type")
req.Description = c.PostForm("description")
sslID := c.PostForm("sslID")
if sslID != "" {
@@ -290,7 +279,7 @@ func (b *BaseApi) UploadSSLFile(c *gin.Context) {
return
}
helper.Success(c)
helper.SuccessWithData(c, nil)
}
func readUploadedFile(fileHeader *multipart.FileHeader) ([]byte, error) {
-403
View File
@@ -1,403 +0,0 @@
package dto
import "time"
type AgentCreateReq struct {
Name string `json:"name" validate:"required"`
AppVersion string `json:"appVersion" validate:"required"`
WebUIPort int `json:"webUIPort" validate:"required"`
BridgePort int `json:"bridgePort"`
AllowedOrigins []string `json:"allowedOrigins"`
AgentType string `json:"agentType" validate:"required,oneof=openclaw copaw"`
Model string `json:"model"`
AccountID uint `json:"accountId"`
Token string `json:"token"`
TaskID string `json:"taskID"`
Advanced bool `json:"advanced"`
ContainerName string `json:"containerName"`
AllowPort bool `json:"allowPort"`
SpecifyIP string `json:"specifyIP"`
RestartPolicy string `json:"restartPolicy"`
CpuQuota float64 `json:"cpuQuota"`
MemoryLimit float64 `json:"memoryLimit"`
MemoryUnit string `json:"memoryUnit"`
PullImage bool `json:"pullImage"`
EditCompose bool `json:"editCompose"`
DockerCompose string `json:"dockerCompose"`
}
type AgentItem struct {
ID uint `json:"id"`
Name string `json:"name"`
AgentType string `json:"agentType"`
Provider string `json:"provider"`
ProviderName string `json:"providerName"`
Model string `json:"model"`
APIType string `json:"apiType"`
MaxTokens int `json:"maxTokens"`
ContextWindow int `json:"contextWindow"`
BaseURL string `json:"baseUrl"`
APIKey string `json:"apiKey"`
Token string `json:"token"`
Status string `json:"status"`
Message string `json:"message"`
AppInstallID uint `json:"appInstallId"`
AccountID uint `json:"accountId"`
AppVersion string `json:"appVersion"`
Container string `json:"containerName"`
WebUIPort int `json:"webUIPort"`
BridgePort int `json:"bridgePort"`
Path string `json:"path"`
ConfigPath string `json:"configPath"`
Upgradable bool `json:"upgradable"`
CreatedAt time.Time `json:"createdAt"`
}
type AgentDeleteReq struct {
ID uint `json:"id" validate:"required"`
TaskID string `json:"taskID"`
ForceDelete bool `json:"forceDelete"`
}
type AgentTokenResetReq struct {
ID uint `json:"id" validate:"required"`
}
type AgentModelConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
AccountID uint `json:"accountId" validate:"required"`
Model string `json:"model" validate:"required"`
}
type AgentOverviewReq struct {
AgentID uint `json:"agentId" validate:"required"`
}
type AgentIDReq struct {
AgentID uint `json:"agentId" validate:"required"`
}
type AgentOverview struct {
Snapshot AgentOverviewSnapshot `json:"snapshot"`
}
type AgentOverviewSnapshot struct {
ContainerStatus string `json:"containerStatus"`
AppVersion string `json:"appVersion"`
DefaultModel string `json:"defaultModel"`
ChannelCount int `json:"channelCount"`
SkillCount int `json:"skillCount"`
JobCount int `json:"jobCount"`
SessionCount int `json:"sessionCount"`
}
type AgentAccountModel struct {
RecordID uint `json:"recordId"`
ID string `json:"id"`
Name string `json:"name"`
ContextWindow int `json:"contextWindow"`
MaxTokens int `json:"maxTokens"`
Reasoning bool `json:"reasoning"`
Input []string `json:"input"`
}
type AgentAccountModelReq struct {
AccountID uint `json:"accountId" validate:"required"`
}
type AgentAccountModelCreateReq struct {
AccountID uint `json:"accountId" validate:"required"`
Model AgentAccountModel `json:"model" validate:"required"`
}
type AgentAccountModelUpdateReq struct {
AccountID uint `json:"accountId" validate:"required"`
Model AgentAccountModel `json:"model" validate:"required"`
}
type AgentAccountModelDeleteReq struct {
AccountID uint `json:"accountId" validate:"required"`
RecordID uint `json:"recordId" validate:"required"`
}
type AgentAccountCreateReq struct {
Provider string `json:"provider" validate:"required"`
Name string `json:"name" validate:"required"`
APIKey string `json:"apiKey" validate:"required"`
RememberAPIKey bool `json:"rememberApiKey"`
BaseURL string `json:"baseURL"`
Models []AgentAccountModel `json:"models"`
APIType string `json:"apiType" validate:"required"`
Remark string `json:"remark"`
}
type AgentAccountUpdateReq struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
APIKey string `json:"apiKey" validate:"required"`
RememberAPIKey bool `json:"rememberApiKey"`
BaseURL string `json:"baseURL"`
APIType string `json:"apiType" validate:"required"`
Remark string `json:"remark"`
SyncAgents bool `json:"syncAgents"`
}
type AgentAccountVerifyReq struct {
Provider string `json:"provider" validate:"required"`
APIKey string `json:"apiKey" validate:"required"`
BaseURL string `json:"baseURL"`
}
type AgentAccountDeleteReq struct {
ID uint `json:"id" validate:"required"`
}
type AgentAccountSearch struct {
PageInfo
Provider string `json:"provider"`
Name string `json:"name"`
}
type AgentAccountInfo struct {
ID uint `json:"id"`
Provider string `json:"provider"`
ProviderName string `json:"providerName"`
Name string `json:"name"`
APIKey string `json:"apiKey"`
RememberAPIKey bool `json:"rememberApiKey"`
BaseURL string `json:"baseUrl"`
Models []AgentAccountModel `json:"models"`
APIType string `json:"apiType"`
Verified bool `json:"verified"`
Remark string `json:"remark"`
CreatedAt time.Time `json:"createdAt"`
}
type ProviderModelInfo struct {
ID string `json:"id"`
Name string `json:"name"`
ContextWindow int `json:"contextWindow"`
MaxTokens int `json:"maxTokens"`
Reasoning bool `json:"reasoning"`
Input []string `json:"input"`
}
type ProviderInfo struct {
Sort uint `json:"-"`
Provider string `json:"provider"`
DisplayName string `json:"displayName"`
BaseURL string `json:"baseUrl"`
Models []ProviderModelInfo `json:"models"`
}
type AgentFeishuConfigReq struct {
AgentID uint `json:"agentId" validate:"required"`
}
type AgentFeishuConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
BotName string `json:"botName" validate:"required"`
AppID string `json:"appId" validate:"required"`
AppSecret string `json:"appSecret" validate:"required"`
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy" validate:"required"`
}
type AgentFeishuPairingApproveReq struct {
AgentID uint `json:"agentId" validate:"required"`
PairingCode string `json:"pairingCode" validate:"required"`
}
type AgentFeishuConfig struct {
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy"`
BotName string `json:"botName"`
AppID string `json:"appId"`
AppSecret string `json:"appSecret"`
}
type AgentTelegramConfigReq struct {
AgentID uint `json:"agentId" validate:"required"`
}
type AgentTelegramConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy" validate:"required"`
BotToken string `json:"botToken" validate:"required"`
Proxy string `json:"proxy"`
}
type AgentTelegramConfig struct {
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy"`
BotToken string `json:"botToken"`
Proxy string `json:"proxy"`
}
type AgentChannelPairingApproveReq struct {
AgentID uint `json:"agentId" validate:"required"`
Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom dingtalk-connector"`
PairingCode string `json:"pairingCode" validate:"required"`
}
type AgentWecomConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy" validate:"required,oneof=pairing open"`
BotID string `json:"botId" validate:"required"`
Secret string `json:"secret" validate:"required"`
}
type AgentWecomConfig struct {
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy"`
BotID string `json:"botId"`
Secret string `json:"secret"`
Installed bool `json:"installed"`
}
type AgentDingTalkConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Enabled bool `json:"enabled"`
ClientID string `json:"clientId" validate:"required"`
ClientSecret string `json:"clientSecret" validate:"required"`
DmPolicy string `json:"dmPolicy" validate:"required,oneof=pairing allowlist open disabled"`
AllowFrom []string `json:"allowFrom"`
GroupPolicy string `json:"groupPolicy" validate:"required,oneof=open allowlist disabled"`
GroupAllowFrom []string `json:"groupAllowFrom"`
}
type AgentDingTalkConfig struct {
Enabled bool `json:"enabled"`
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
DmPolicy string `json:"dmPolicy"`
AllowFrom []string `json:"allowFrom"`
GroupPolicy string `json:"groupPolicy"`
GroupAllowFrom []string `json:"groupAllowFrom"`
Installed bool `json:"installed"`
}
type AgentWeixinLoginReq struct {
AgentID uint `json:"agentId" validate:"required"`
TaskID string `json:"taskID" validate:"required"`
}
type AgentQQBotConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Enabled bool `json:"enabled"`
AppID string `json:"appId" validate:"required"`
ClientSecret string `json:"clientSecret" validate:"required"`
}
type AgentQQBotConfig struct {
Enabled bool `json:"enabled"`
AppID string `json:"appId"`
ClientSecret string `json:"clientSecret"`
Installed bool `json:"installed"`
}
type AgentPluginInstallReq struct {
AgentID uint `json:"agentId" validate:"required"`
Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk weixin"`
TaskID string `json:"taskID" validate:"required"`
}
type AgentPluginCheckReq struct {
AgentID uint `json:"agentId" validate:"required"`
Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk weixin"`
}
type AgentPluginStatus struct {
Installed bool `json:"installed"`
}
type AgentDiscordConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy" validate:"required"`
GroupPolicy string `json:"groupPolicy" validate:"required,oneof=open allowlist disabled"`
Token string `json:"token" validate:"required"`
Proxy string `json:"proxy"`
}
type AgentDiscordConfig struct {
Enabled bool `json:"enabled"`
DmPolicy string `json:"dmPolicy"`
GroupPolicy string `json:"groupPolicy"`
Token string `json:"token"`
Proxy string `json:"proxy"`
}
type AgentSecurityConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
AllowedOrigins []string `json:"allowedOrigins"`
}
type AgentSecurityConfig struct {
AllowedOrigins []string `json:"allowedOrigins"`
}
type AgentOtherConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
UserTimezone string `json:"userTimezone" validate:"required"`
BrowserEnabled bool `json:"browserEnabled"`
NPMRegistry string `json:"npmRegistry" validate:"required"`
}
type AgentOtherConfig struct {
UserTimezone string `json:"userTimezone"`
BrowserEnabled bool `json:"browserEnabled"`
NPMRegistry string `json:"npmRegistry"`
}
type AgentConfigFileReq struct {
AgentID uint `json:"agentId" validate:"required"`
}
type AgentConfigFileUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Content string `json:"content" validate:"required"`
}
type AgentConfigFile struct {
Content string `json:"content"`
}
type AgentSkillSearchReq struct {
AgentID uint `json:"agentId" validate:"required"`
Source string `json:"source" validate:"required,oneof=clawhub skillhub"`
Keyword string `json:"keyword" validate:"required"`
}
type AgentSkillItem struct {
Name string `json:"name"`
Description string `json:"description"`
Source string `json:"source"`
Bundled bool `json:"bundled"`
Disabled bool `json:"disabled"`
}
type AgentSkillSearchItem struct {
Slug string `json:"slug"`
Name string `json:"name"`
Description string `json:"description"`
Summary string `json:"summary"`
Version string `json:"version"`
Source string `json:"source"`
Score string `json:"score"`
}
type AgentSkillUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"`
Name string `json:"name" validate:"required"`
Enabled bool `json:"enabled"`
}
type AgentSkillInstallReq struct {
AgentID uint `json:"agentId" validate:"required"`
Source string `json:"source" validate:"required,oneof=clawhub skillhub"`
Slug string `json:"slug" validate:"required"`
TaskID string `json:"taskID" validate:"required"`
}
+1 -11
View File
@@ -317,7 +317,7 @@ type AlertCommonConfig struct {
type AlertSmsConfig struct {
Phone string `json:"phone"`
AlertDailyNum string `json:"alertDailyNum"`
AlertDailyNum uint `json:"alertDailyNum"`
}
type AlertEmailConfig struct {
@@ -330,13 +330,3 @@ type AlertEmailConfig struct {
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
Recipient string `json:"recipient"`
}
type AgentInfo struct {
NodeName string `json:"nodeName"`
NodeAddr string `json:"nodeAddr"`
}
type AlertWebhookConfig struct {
DisplayName string `json:"displayName"`
Url string `json:"url"`
}
+19 -22
View File
@@ -12,8 +12,6 @@ type AppDatabase struct {
DbUser string `json:"PANEL_DB_USER"`
Password string `json:"PANEL_DB_USER_PASSWORD"`
DatabaseName string `json:"DATABASE_NAME"`
Format string `json:"format"`
Collation string `json:"collation"`
}
type AuthParam struct {
@@ -84,26 +82,25 @@ type ExtraProperties struct {
}
type AppProperty struct {
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description Locale `json:"description"`
Key string `json:"key"`
Required []string `json:"Required"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" yaml:"limit"`
Recommend int `json:"recommend" yaml:"recommend"`
Website string `json:"website"`
Github string `json:"github"`
Document string `json:"document"`
Architectures []string `json:"architectures"`
MemoryRequired int `json:"memoryRequired" yaml:"memoryRequired"`
GpuSupport bool `json:"gpuSupport" yaml:"gpuSupport"`
Version float64 `json:"version"`
Deprecated float64 `json:"deprecated"`
BatchInstallSupport bool `json:"batchInstallSupport"`
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description Locale `json:"description"`
Key string `json:"key"`
Required []string `json:"Required"`
CrossVersionUpdate bool `json:"crossVersionUpdate"`
Limit int `json:"limit"`
Recommend int `json:"recommend"`
Website string `json:"website"`
Github string `json:"github"`
Document string `json:"document"`
Architectures []string `json:"architectures"`
MemoryRequired int `json:"memoryRequired"`
GpuSupport bool `json:"gpuSupport"`
Version float64 `json:"version"`
Deprecated float64 `json:"deprecated"`
}
type AppConfigVersion struct {
+7 -16
View File
@@ -33,12 +33,6 @@ type BackupInfo struct {
RememberAuth bool `json:"rememberAuth"`
}
type BackupCheckRes struct {
IsOk bool `json:"isOk"`
Msg string `json:"msg"`
Token string `json:"token"`
}
type ForBuckets struct {
Type string `json:"type" validate:"required"`
AccessKey string `json:"accessKey"`
@@ -65,27 +59,24 @@ type UploadForRecover struct {
}
type CommonBackup struct {
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster container compose"`
Name string `json:"name"`
DetailName string `json:"detailName"`
Secret string `json:"secret"`
StopBefore bool `json:"stopBefore"`
TaskID string `json:"taskID"`
FileName string `json:"fileName"`
Args []string `json:"args"`
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster"`
Name string `json:"name"`
DetailName string `json:"detailName"`
Secret string `json:"secret"`
TaskID string `json:"taskID"`
FileName string `json:"fileName"`
Description string `json:"description"`
}
type CommonRecover struct {
DownloadAccountID uint `json:"downloadAccountID" validate:"required"`
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster container compose"`
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster"`
Name string `json:"name"`
DetailName string `json:"detailName"`
File string `json:"file"`
Secret string `json:"secret"`
TaskID string `json:"taskID"`
BackupRecordID uint `json:"backupRecordID"`
Timeout int `json:"timeout"`
}
type RecordSearch struct {
-6
View File
@@ -11,12 +11,6 @@ type SearchPageWithType struct {
Type string `json:"type"`
}
type SearchPageWithGroup struct {
PageInfo
GroupID uint `json:"groupID"`
Info string `json:"info"`
}
type PageInfo struct {
Page int `json:"page" validate:"required,number"`
PageSize int `json:"pageSize" validate:"required,number"`
-4
View File
@@ -8,10 +8,6 @@ type ComposeTemplateCreate struct {
Content string `json:"content"`
}
type ComposeTemplateBatch struct {
Templates []ComposeTemplateCreate `json:"templates" validate:"required"`
}
type ComposeTemplateUpdate struct {
ID uint `json:"id"`
Description string `json:"description"`
+49 -116
View File
@@ -15,9 +15,8 @@ type PageContainer struct {
}
type InspectReq struct {
ID string `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
Detail string `json:"detail"`
ID string `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
}
type ContainerInfo struct {
@@ -38,9 +37,6 @@ type ContainerInfo struct {
AppName string `json:"appName"`
AppInstallName string `json:"appInstallName"`
Websites []string `json:"websites"`
IsPinned bool `json:"isPinned"`
Description string `json:"description"`
}
type ContainerOptions struct {
@@ -48,42 +44,15 @@ type ContainerOptions struct {
State string `json:"state"`
}
type ContainerFileReq struct {
ContainerID string `json:"containerID" validate:"required"`
Path string `json:"path" validate:"required"`
}
type ContainerFileBatchDeleteReq struct {
ContainerID string `json:"containerID" validate:"required"`
Paths []string `json:"paths" validate:"required,min=1,dive,required"`
}
type ContainerFileInfo struct {
Name string `json:"name"`
Path string `json:"path"`
IsDir bool `json:"isDir"`
IsLink bool `json:"isLink"`
LinkTo string `json:"linkTo"`
Size int64 `json:"size"`
Mode string `json:"mode"`
ModTime string `json:"modTime"`
}
type ContainerFileContent struct {
Content string `json:"content"`
Size int64 `json:"size"`
Truncated bool `json:"truncated"`
IsBinary bool `json:"isBinary"`
}
type ContainerStatus struct {
Created int `json:"created"`
Running int `json:"running"`
Paused int `json:"paused"`
Restarting int `json:"restarting"`
Removing int `json:"removing"`
Exited int `json:"exited"`
Dead int `json:"dead"`
All uint `json:"all"`
Created uint `json:"created"`
Running uint `json:"running"`
Paused uint `json:"paused"`
Restarting uint `json:"restarting"`
Removing uint `json:"removing"`
Exited uint `json:"exited"`
Dead uint `json:"dead"`
ContainerCount int `json:"containerCount"`
ComposeCount int `json:"composeCount"`
@@ -92,6 +61,8 @@ type ContainerStatus struct {
NetworkCount int `json:"networkCount"`
VolumeCount int `json:"volumeCount"`
RepoCount int `json:"repoCount"`
ImageSize uint64 `json:"imageSize"`
}
type ResourceLimit struct {
CPU int `json:"cpu"`
@@ -99,16 +70,17 @@ type ResourceLimit struct {
}
type ContainerOperate struct {
TaskID string `json:"taskID"`
ForcePull bool `json:"forcePull"`
Name string `json:"name" validate:"required"`
Image string `json:"image" validate:"required"`
Hostname string `json:"hostname"`
DomainName string `json:"domainName"`
DNS []string `json:"dns"`
Networks []ContainerNetwork `json:"networks"`
TaskID string `json:"taskID"`
ForcePull bool `json:"forcePull"`
Name string `json:"name" validate:"required"`
Image string `json:"image" validate:"required"`
Network string `json:"network"`
Hostname string `json:"hostname"`
DomainName string `json:"domainName"`
MacAddr string `json:"macAddr"`
DNS []string `json:"dns"`
Ipv4 string `json:"ipv4"`
Ipv6 string `json:"ipv6"`
PublishAllPorts bool `json:"publishAllPorts"`
ExposedPorts []PortHelper `json:"exposedPorts"`
Tty bool `json:"tty"`
@@ -123,23 +95,11 @@ type ContainerOperate struct {
Privileged bool `json:"privileged"`
AutoRemove bool `json:"autoRemove"`
Volumes []VolumeHelper `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
Labels []string `json:"labels"`
Env []string `json:"env"`
RestartPolicy string `json:"restartPolicy"`
}
type ExtraHost struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
}
type ContainerNetwork struct {
Network string `json:"network"`
Ipv4 string `json:"ipv4"`
Ipv6 string `json:"ipv6"`
MacAddr string `json:"macAddr"`
}
type ContainerCreateByCommand struct {
TaskID string `json:"taskID"`
Command string `json:"command"`
@@ -152,19 +112,6 @@ type ContainerUpgrade struct {
ForcePull bool `json:"forcePull"`
}
type ContainerItemStats struct {
SizeRw int64 `json:"sizeRw"`
SizeRootFs int64 `json:"sizeRootFs"`
ContainerUsage int64 `json:"containerUsage"`
ContainerReclaimable int64 `json:"containerReclaimable"`
ImageUsage int64 `json:"imageUsage"`
ImageReclaimable int64 `json:"imageReclaimable"`
VolumeUsage int64 `json:"volumeUsage"`
VolumeReclaimable int64 `json:"volumeReclaimable"`
BuildCacheUsage int64 `json:"buildCacheUsage"`
BuildCacheReclaimable int64 `json:"buildCacheReclaimable"`
}
type ContainerListStats struct {
ContainerID string `json:"containerID"`
@@ -206,7 +153,6 @@ type PortHelper struct {
}
type ContainerOperation struct {
TaskID string `json:"taskID"`
Names []string `json:"names" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=up start stop restart kill pause unpause remove"`
}
@@ -287,62 +233,50 @@ type BatchDelete struct {
}
type ComposeInfo struct {
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
CreatedBy string `json:"createdBy"`
ContainerCount int `json:"containerCount"`
RunningCount int `json:"runningCount"`
ConfigFile string `json:"configFile"`
Workdir string `json:"workdir"`
ComposeFileExists bool `json:"composeFileExists"`
Path string `json:"path"`
Containers []ComposeContainer `json:"containers"`
Env string `json:"env"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
CreatedBy string `json:"createdBy"`
ContainerCount int `json:"containerCount"`
RunningCount int `json:"runningCount"`
ConfigFile string `json:"configFile"`
Workdir string `json:"workdir"`
Path string `json:"path"`
Containers []ComposeContainer `json:"containers"`
Env []string `json:"env"`
}
type ComposeContainer struct {
ContainerID string `json:"containerID"`
Name string `json:"name"`
CreateTime string `json:"createTime"`
State string `json:"state"`
Ports []string `json:"ports"`
ContainerID string `json:"containerID"`
Name string `json:"name"`
CreateTime string `json:"createTime"`
State string `json:"state"`
}
type ComposeCreate struct {
TaskID string `json:"taskID"`
Name string `json:"name"`
From string `json:"from" validate:"required,oneof=edit path template"`
File string `json:"file"`
Path string `json:"path"`
Template uint `json:"template"`
Env string `json:"env"`
ForcePull bool `json:"forcePull"`
TaskID string `json:"taskID"`
Name string `json:"name"`
From string `json:"from" validate:"required,oneof=edit path template"`
File string `json:"file"`
Path string `json:"path"`
Template uint `json:"template"`
Env []string `json:"env"`
}
type ComposeOperation struct {
Name string `json:"name" validate:"required"`
Path string `json:"path"`
Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete"`
WithFile bool `json:"withFile"`
Force bool `json:"force"`
Force bool `josn:"force"`
}
type ComposeUpdate struct {
TaskID string `json:"taskID"`
Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"`
DetailPath string `json:"detailPath"`
Content string `json:"content" validate:"required"`
Env string `json:"env"`
ForcePull bool `json:"forcePull"`
}
type ComposeLogClean struct {
Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"`
DetailPath string `json:"detailPath"`
Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"`
Content string `json:"content" validate:"required"`
Env []string `json:"env"`
}
type ContainerLog struct {
Container string `json:"container" validate:"required"`
Since string `json:"since"`
Tail uint `json:"tail"`
Timestamp bool `json:"timestamp"`
ContainerType string `json:"containerType"`
}
@@ -352,6 +286,5 @@ type StreamLog struct {
Since string
Follow bool
Tail string
Timestamp bool
Type string
}
-9
View File
@@ -49,17 +49,10 @@ type CronjobOperate struct {
Timeout uint `json:"timeout" validate:"number,min=1"`
IgnoreErr bool `json:"ignoreErr"`
Secret string `json:"secret"`
Args string `json:"args"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
AlertMethod string `json:"alertMethod"`
CleanLogConfig
}
type CleanLogConfig struct {
Scopes []string `json:"scopes"`
}
type SnapshotRule struct {
@@ -124,7 +117,6 @@ type CronjobInfo struct {
LastRecordTime string `json:"lastRecordTime"`
Status string `json:"status"`
Secret string `json:"secret"`
Args string `json:"args"`
AlertCount uint `json:"alertCount"`
}
@@ -164,7 +156,6 @@ type CronjobTrans struct {
IgnoreErr bool `json:"ignoreErr"`
SnapshotRule SnapshotTransHelper `json:"snapshotRule"`
Secret string `json:"secret"`
Args string `json:"args"`
SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"`
+10 -19
View File
@@ -4,7 +4,6 @@ import "time"
type DashboardBase struct {
WebsiteNumber int `json:"websiteNumber"`
AgentNumber int `json:"agentNumber"`
DatabaseNumber int `json:"databaseNumber"`
CronjobNumber int `json:"cronjobNumber"`
AppInstalledNumber int `json:"appInstalledNumber"`
@@ -14,17 +13,15 @@ type DashboardBase struct {
Platform string `json:"platform"`
PlatformFamily string `json:"platformFamily"`
PlatformVersion string `json:"platformVersion"`
PrettyDistro string `json:"prettyDistro"`
KernelArch string `json:"kernelArch"`
KernelVersion string `json:"kernelVersion"`
VirtualizationSystem string `json:"virtualizationSystem"`
IpV4Addr string `json:"ipV4Addr"`
SystemProxy string `json:"systemProxy"`
CPUCores int `json:"cpuCores"`
CPULogicalCores int `json:"cpuLogicalCores"`
CPUModelName string `json:"cpuModelName"`
CPUMhz float64 `json:"cpuMhz"`
CPUCores int `json:"cpuCores"`
CPULogicalCores int `json:"cpuLogicalCores"`
CPUModelName string `json:"cpuModelName"`
QuickJumps []QuickJump `json:"quickJump"`
CurrentInfo DashboardCurrent `json:"currentInfo"`
@@ -51,7 +48,6 @@ type OsInfo struct {
PlatformFamily string `json:"platformFamily"`
KernelArch string `json:"kernelArch"`
KernelVersion string `json:"kernelVersion"`
PrettyDistro string `json:"prettyDistro"`
DiskSize int64 `json:"diskSize"`
}
@@ -62,10 +58,9 @@ type NodeCurrent struct {
Load15 float64 `json:"load15"`
LoadUsagePercent float64 `json:"loadUsagePercent"`
CPUUsedPercent float64 `json:"cpuUsedPercent"`
CPUUsed float64 `json:"cpuUsed"`
CPUTotal int `json:"cpuTotal"`
CPUDetailedPercent []float64 `json:"cpuDetailedPercent"`
CPUUsedPercent float64 `json:"cpuUsedPercent"`
CPUUsed float64 `json:"cpuUsed"`
CPUTotal int `json:"cpuTotal"`
MemoryTotal uint64 `json:"memoryTotal"`
MemoryAvailable uint64 `json:"memoryAvailable"`
@@ -89,11 +84,10 @@ type DashboardCurrent struct {
Load15 float64 `json:"load15"`
LoadUsagePercent float64 `json:"loadUsagePercent"`
CPUPercent []float64 `json:"cpuPercent"`
CPUUsedPercent float64 `json:"cpuUsedPercent"`
CPUUsed float64 `json:"cpuUsed"`
CPUTotal int `json:"cpuTotal"`
CPUDetailedPercent []float64 `json:"cpuDetailedPercent"`
CPUPercent []float64 `json:"cpuPercent"`
CPUUsedPercent float64 `json:"cpuUsedPercent"`
CPUUsed float64 `json:"cpuUsed"`
CPUTotal int `json:"cpuTotal"`
MemoryTotal uint64 `json:"memoryTotal"`
MemoryUsed uint64 `json:"memoryUsed"`
@@ -122,9 +116,6 @@ type DashboardCurrent struct {
GPUData []GPUInfo `json:"gpuData"`
XPUData []XPUInfo `json:"xpuData"`
TopCPUItems []Process `json:"topCPUItems"`
TopMemItems []Process `json:"topMemItems"`
ShotTime time.Time `json:"shotTime"`
}
+16 -26
View File
@@ -38,7 +38,6 @@ type MysqlDBInfo struct {
From string `json:"from"`
MysqlName string `json:"mysqlName"`
Format string `json:"format"`
Collation string `json:"collation"`
Username string `json:"username"`
Password string `json:"password"`
Permission string `json:"permission"`
@@ -58,19 +57,13 @@ type MysqlDBCreate struct {
Name string `json:"name" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Database string `json:"database" validate:"required"`
Format string `json:"format" validate:"required"`
Collation string `json:"collation"`
Format string `json:"format" validate:"required,oneof=utf8mb4 utf8 gbk big5"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
Permission string `json:"permission" validate:"required"`
Description string `json:"description"`
}
type MysqlFormatCollationOption struct {
Format string `json:"format"`
Collations []string `json:"collations"`
}
type BindUser struct {
Database string `json:"database" validate:"required"`
DB string `json:"db" validate:"required"`
@@ -258,7 +251,6 @@ type DatabaseInfo struct {
Version string `json:"version"`
Address string `json:"address"`
Port uint `json:"port"`
InitialDB string `json:"initialDB"`
Username string `json:"username"`
Password string `json:"password"`
@@ -289,15 +281,14 @@ type DatabaseItem struct {
}
type DatabaseCreate struct {
Name string `json:"name" validate:"required,max=256"`
Type string `json:"type" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
InitialDB string `json:"initialDB"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
Name string `json:"name" validate:"required,max=256"`
Type string `json:"type" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
SSL bool `json:"ssl"`
RootCert string `json:"rootCert"`
@@ -310,14 +301,13 @@ type DatabaseCreate struct {
}
type DatabaseUpdate struct {
ID uint `json:"id"`
Type string `json:"type" validate:"required"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
InitialDB string `json:"initialDB"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
ID uint `json:"id"`
Type string `json:"type" validate:"required"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
SSL bool `json:"ssl"`
RootCert string `json:"rootCert"`
+3 -38
View File
@@ -4,8 +4,6 @@ type FirewallBaseInfo struct {
Name string `json:"name"`
IsExist bool `json:"isExist"`
IsActive bool `json:"isActive"`
IsInit bool `json:"isInit"`
IsBind bool `json:"isBind"`
Version string `json:"version"`
PingStatus string `json:"pingStatus"`
}
@@ -19,14 +17,12 @@ type RuleSearch struct {
}
type FirewallOperation struct {
Operation string `json:"operation" validate:"required,oneof=start stop restart disableBanPing enableBanPing"`
Operation string `json:"operation" validate:"required,oneof=start stop restart disablePing enablePing"`
WithDockerRestart bool `json:"withDockerRestart"`
}
type PortRuleOperate struct {
ID uint `json:"id"`
Operation string `json:"operation" validate:"required,oneof=add remove"`
Chain string `json:"chain"`
Address string `json:"address"`
Port string `json:"port" validate:"required"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
@@ -50,11 +46,8 @@ type ForwardRuleOperate struct {
type UpdateFirewallDescription struct {
Type string `json:"type"`
Chain string `json:"chain"`
SrcIP string `json:"srcIP"`
DstIP string `json:"dstIP"`
SrcPort string `json:"srcPort"`
DstPort string `json:"dstPort"`
Address string `json:"address"`
Port string `json:"port"`
Protocol string `json:"protocol"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
@@ -62,7 +55,6 @@ type UpdateFirewallDescription struct {
}
type AddrRuleOperate struct {
ID uint `json:"id"`
Operation string `json:"operation" validate:"required,oneof=add remove"`
Address string `json:"address" validate:"required"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
@@ -84,30 +76,3 @@ type BatchRuleOperate struct {
Type string `json:"type" validate:"required"`
Rules []PortRuleOperate `json:"rules"`
}
type IptablesOp struct {
Name string `json:"name" validate:"required,oneof=1PANEL_INPUT 1PANEL_OUTPUT 1PANEL_BASIC"`
Operate string `json:"operate" validate:"required,oneof=init-base init-forward init-advance bind-base unbind-base bind unbind"`
}
type IptablesRuleOp struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
ID uint `json:"id"`
Chain string `json:"chain" validate:"required,oneof=1PANEL_BASIC 1PANEL_BASIC_BEFORE 1PANEL_INPUT 1PANEL_OUTPUT"`
Protocol string `json:"protocol"`
SrcIP string `json:"srcIP"`
SrcPort uint `json:"srcPort"`
DstIP string `json:"dstIP"`
DstPort uint `json:"dstPort"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop reject"`
Description string `json:"description"`
}
type IptablesBatchOperate struct {
Rules []IptablesRuleOp `json:"rules"`
}
type IptablesChainStatus struct {
IsBind bool `json:"isBind"`
DefaultStrategy string `json:"defaultStrategy"`
}
+1 -7
View File
@@ -15,14 +15,10 @@ type ImageInfo struct {
IsUsed bool `json:"isUsed"`
Tags []string `json:"tags"`
Size int64 `json:"size"`
IsPinned bool `json:"isPinned"`
Description string `json:"description"`
}
type ImageLoad struct {
TaskID string `json:"taskID"`
Paths []string `json:"paths" validate:"required,dive,required"`
Path string `json:"path" validate:"required"`
}
type ImageBuild struct {
@@ -31,7 +27,6 @@ type ImageBuild struct {
Name string `json:"name" validate:"required"`
Dockerfile string `json:"dockerfile" validate:"required"`
Tags []string `json:"tags"`
Args []string `json:"args"`
}
type ImagePull struct {
@@ -53,7 +48,6 @@ type ImagePush struct {
}
type ImageSave struct {
TaskID string `json:"taskID"`
TagName string `json:"tagName" validate:"required"`
Path string `json:"path" validate:"required"`
Name string `json:"name" validate:"required"`
+3 -56
View File
@@ -4,78 +4,25 @@ import "time"
type MonitorSearch struct {
Param string `json:"param" validate:"required,oneof=all cpu memory load io network"`
IO string `json:"io"`
Network string `json:"network"`
Info string `json:"info"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
}
type MonitorData struct {
Param string `json:"param"`
Param string `json:"param" validate:"required,oneof=cpu memory load io network"`
Date []time.Time `json:"date"`
Value []interface{} `json:"value"`
}
type Process struct {
Name string `json:"name"`
Pid int32 `json:"pid"`
Percent float64 `json:"percent"`
Memory uint64 `json:"memory"`
Cmd string `json:"cmd"`
User string `json:"user"`
}
type MonitorSetting struct {
MonitorStatus string `json:"monitorStatus"`
MonitorStoreDays string `json:"monitorStoreDays"`
MonitorInterval string `json:"monitorInterval"`
DefaultNetwork string `json:"defaultNetwork"`
DefaultIO string `json:"defaultIO"`
}
type MonitorSettingUpdate struct {
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork DefaultIO"`
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork"`
Value string `json:"value"`
}
type MonitorGPUOptions struct {
GPUType string `json:"gpuType"`
ChartHide []GPUChartHide `json:"chartHide"`
Options []string `json:"options"`
}
type GPUChartHide struct {
ProductName string `json:"productName"`
Process bool `json:"process"`
GPU bool `json:"gpu"`
Memory bool `json:"memory"`
Power bool `json:"power"`
Temperature bool `json:"temperature"`
Speed bool `json:"speed"`
}
type MonitorGPUSearch struct {
ProductName string `json:"productName"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
}
type MonitorGPUData struct {
Date []time.Time `json:"date"`
GPUValue []float64 `json:"gpuValue"`
TemperatureValue []float64 `json:"temperatureValue"`
PowerTotal []float64 `json:"powerTotal"`
PowerUsed []float64 `json:"powerUsed"`
PowerPercent []float64 `json:"powerPercent"`
MemoryTotal []float64 `json:"memoryTotal"`
MemoryUsed []float64 `json:"memoryUsed"`
MemoryPercent []float64 `json:"memoryPercent"`
SpeedValue []int `json:"speedValue"`
ProcessCount []int `json:"processCount"`
GPUProcesses [][]GPUProcess `json:"gpuProcesses"`
}
type GPUProcess struct {
Pid string `json:"pid"`
Type string `json:"type"`
ProcessName string `json:"processName"`
UsedMemory string `json:"usedMemory"`
}
+6 -7
View File
@@ -73,13 +73,12 @@ type NginxUpstream struct {
}
type NginxUpstreamServer struct {
Server string `json:"server"`
Weight int `json:"weight"`
FailTimeout int `json:"failTimeout"`
FailTimeoutUnit string `json:"failTimeoutUnit"`
MaxFails int `json:"maxFails"`
MaxConns int `json:"maxConns"`
Flag string `json:"flag"`
Server string `json:"server"`
Weight int `json:"weight"`
FailTimeout string `json:"failTimeout"`
MaxFails int `json:"maxFails"`
MaxConns int `json:"maxConns"`
Flag string `json:"flag"`
}
var LBAlgorithms = map[string]struct{}{"ip_hash": {}, "least_conn": {}}
+7 -26
View File
@@ -22,16 +22,7 @@ type AppInstallCreate struct {
Name string `json:"name" validate:"required"`
Services map[string]string `json:"services"`
TaskID string `json:"taskID"`
AppContainerConfig
NodePushConfig
}
type NodePushConfig struct {
Nodes []string `json:"nodes"`
PushNode bool `json:"pushNode"`
AppKey string `json:"appKey"`
Version string `json:"version"`
}
type AppContainerConfig struct {
@@ -54,14 +45,13 @@ type AppContainerConfig struct {
type AppInstalledSearch struct {
dto.PageInfo
Type string `json:"type"`
Name string `json:"name"`
Tags []string `json:"tags"`
Update bool `json:"update"`
Unused bool `json:"unused"`
All bool `json:"all"`
Sync bool `json:"sync"`
CheckUpdate bool `json:"checkUpdate"`
Type string `json:"type"`
Name string `json:"name"`
Tags []string `json:"tags"`
Update bool `json:"update"`
Unused bool `json:"unused"`
All bool `json:"all"`
Sync bool `json:"sync"`
}
type AppInstalledInfo struct {
@@ -138,12 +128,3 @@ type AppUpdateVersion struct {
AppInstallID uint `json:"appInstallID" validate:"required"`
UpdateVersion string `json:"updateVersion"`
}
type AppInstallSortItem struct {
InstallID uint `json:"installID"`
SortOrder int `json:"sortOrder"`
}
type AppInstallSort struct {
Items []AppInstallSortItem `json:"items" validate:"required"`
}
-1
View File
@@ -13,7 +13,6 @@ type DiskMountRequest struct {
MountPoint string `json:"mountPoint" validate:"required"`
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
AutoMount bool `json:"autoMount"`
NoFail bool `json:"noFail"`
}
type DiskUnmountRequest struct {
+1 -9
View File
@@ -13,6 +13,7 @@ type FileContentReq struct {
Path string `json:"path" validate:"required"`
IsDetail bool `json:"isDetail"`
}
type SearchUploadWithPage struct {
dto.PageInfo
Path string `json:"path" validate:"required"`
@@ -163,12 +164,3 @@ type FileConvertRequest struct {
DeleteSource bool `json:"deleteSource"`
TaskID string `json:"taskID"`
}
type FileRemarkBatch struct {
Paths []string `json:"paths" validate:"required"`
}
type FileRemarkUpdate struct {
Path string `json:"path" validate:"required"`
Remark string `json:"remark"`
}
-5
View File
@@ -130,8 +130,3 @@ type NginxModuleUpdate struct {
type NginxOperateReq struct {
Operate string `json:"operate" validate:"required,oneof=enable disable"`
}
type NginxDefaultHTTPSUpdate struct {
Operate string `json:"operate" validate:"required,oneof=enable disable"`
SSLRejectHandshake bool `json:"sslRejectHandshake"`
}
-7
View File
@@ -32,7 +32,6 @@ type NodeConfig struct {
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
}
type Environment struct {
@@ -50,11 +49,6 @@ type ExposedPort struct {
HostIP string `json:"hostIP"`
}
type ExtraHost struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
}
type RuntimeDelete struct {
ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"`
@@ -141,7 +135,6 @@ type PHPContainerConfig struct {
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
}
type RuntimeRemark struct {
-53
View File
@@ -38,22 +38,6 @@ type WebsiteCreate struct {
FtpConfig
DataBaseConfig
SSLConfig
StreamConfig
}
type StreamConfig struct {
StreamPorts string `json:"streamPorts"`
Name string `json:"name"`
Algorithm string `json:"algorithm"`
UDP bool `json:"udp"`
Servers []dto.NginxUpstreamServer `json:"servers"`
}
type StreamUpdate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
StreamConfig
}
type WebsiteOptionReq struct {
@@ -125,30 +109,6 @@ type BatchWebsiteOp struct {
TaskID string `json:"taskID" validate:"required"`
}
type BatchWebsiteGroup struct {
IDs []uint `json:"ids" validate:"required"`
GroupID uint `json:"groupID" validate:"required"`
}
type BatchWebsiteHttps struct {
IDs []uint `json:"ids" validate:"required"`
TaskID string `json:"taskID" validate:"required"`
WebsiteSSLID uint `json:"websiteSSLId"`
Type string `json:"type" validate:"oneof=existed auto manual"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
ImportType string `json:"importType"`
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
Http3 bool `json:"http3"`
}
type WebsiteRedirectUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
@@ -269,21 +229,9 @@ type WebsiteProxyConfig struct {
Replaces map[string]string `json:"replaces"`
SNI bool `json:"sni"`
ProxySSLName string `json:"proxySSLName"`
SSLVerify bool `json:"sslVerify"`
CorsConfig
}
type WebsiteProxyDelete struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
}
type WebsiteProxyStatusUpdate struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
Status string `json:"status" validate:"required"`
}
type CorsConfig struct {
Cors bool `json:"cors"`
AllowOrigins string `json:"allowOrigins"`
@@ -323,7 +271,6 @@ type WebsiteHtmlReq struct {
type WebsiteHtmlUpdate struct {
Type string `json:"type" validate:"required"`
Content string `json:"content" validate:"required"`
Sync bool `json:"sync"`
}
type WebsiteLBCreate struct {
+2 -8
View File
@@ -6,12 +6,8 @@ type WebsiteSSLSearch struct {
dto.PageInfo
AcmeAccountID string `json:"acmeAccountID"`
Domain string `json:"domain"`
OrderBy string `json:"orderBy" validate:"omitempty,oneof=created_at expire_date"`
Order string `json:"order" validate:"omitempty,oneof=null ascending descending"`
}
type WebsiteSSLListReq struct {
AcmeAccountID string `json:"acmeAccountID"`
OrderBy string `json:"orderBy" validate:"required,oneof=expire_date"`
Order string `json:"order" validate:"required,oneof=null ascending descending"`
}
type WebsiteSSLCreate struct {
@@ -35,7 +31,6 @@ type WebsiteSSLCreate struct {
Shell string `json:"shell"`
PushNode bool `json:"pushNode"`
Nodes string `json:"nodes"`
IsIp bool `json:"isIp"`
}
type WebsiteDNSReq struct {
@@ -67,7 +62,6 @@ type WebsiteAcmeAccountCreate struct {
EabHmacKey string `json:"eabHmacKey"`
UseProxy bool `json:"useProxy"`
CaDirURL string `json:"caDirURL"`
UseEAB bool `json:"useEAB"`
}
type WebsiteAcmeAccountUpdate struct {
+17 -24
View File
@@ -29,18 +29,22 @@ type AppDTO struct {
}
type AppItem struct {
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
Description string `json:"description"`
Status string `json:"status"`
Installed bool `json:"installed"`
Limit int `json:"limit"`
Tags []string `json:"tags"`
GpuSupport bool `json:"gpuSupport"`
Recommend int `json:"recommend"`
Type string `json:"type"`
BatchInstallSupport bool `json:"batchInstallSupport"`
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
Description string `json:"description"`
Icon string `json:"icon"`
Type string `json:"type"`
Status string `json:"status"`
Resource string `json:"resource"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Limit int `json:"limit"`
Tags []TagDTO `json:"tags"`
Github string `json:"github"`
Website string `json:"website"`
GpuSupport bool `json:"gpuSupport"`
Recommend int `json:"recommend"`
}
type TagDTO struct {
@@ -76,10 +80,6 @@ type AppDetailDTO struct {
GpuSupport bool `json:"gpuSupport"`
}
type AppDetailSimpleDTO struct {
ID uint `json:"id"`
}
type IgnoredApp struct {
Icon string `json:"icon"`
Name string `json:"name"`
@@ -126,12 +126,8 @@ type AppInstallDTO struct {
WebUI string `json:"webUI"`
CreatedAt time.Time `json:"createdAt"`
Favorite bool `json:"favorite"`
SortOrder int `json:"sortOrder"`
App AppDetail `json:"app"`
Container string `json:"container"`
IsEdit bool `json:"isEdit"`
LinkDB bool `json:"linkDB"`
ServiceName string `json:"serviceName"`
}
type AppInstallInfo struct {
@@ -143,8 +139,6 @@ type AppInstallInfo struct {
HttpPort int `json:"HttpPort"`
Container string `json:"container"`
ComposePath string `json:"composePath"`
AppKey string `json:"appKey"`
AppPorts []int `json:"appPorts"`
Env map[string]interface{} `json:"env"`
}
@@ -182,7 +176,6 @@ type AppParam struct {
}
type AppConfig struct {
Params []AppParam `json:"params"`
RawCompose string `json:"rawCompose"`
Params []AppParam `json:"params"`
request.AppContainerConfig
}
+1 -1
View File
@@ -24,7 +24,7 @@ type DiskBasicInfo struct {
type CompleteDiskInfo struct {
Disks []DiskInfo `json:"disks"`
UnpartitionedDisks []DiskBasicInfo `json:"unpartitionedDisks"`
SystemDisks []DiskInfo `json:"systemDisks"`
SystemDisk *DiskInfo `json:"systemDisk"`
TotalDisks int `json:"totalDisks"`
TotalCapacity int64 `json:"totalCapacity"`
}
-4
View File
@@ -81,7 +81,3 @@ type FileConvertLog struct {
Status string `json:"status"`
Message string `json:"message"`
}
type FileRemarksRes struct {
Remarks map[string]string `json:"remarks"`
}
+1 -2
View File
@@ -82,6 +82,5 @@ type NginxBuildConfig struct {
}
type NginxConfigRes struct {
Https bool `json:"https"`
SSLRejectHandshake bool `json:"sslRejectHandshake"`
Https bool `json:"https"`
}
-1
View File
@@ -28,7 +28,6 @@ type RuntimeDTO struct {
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
ExtraHosts []request.ExtraHost `json:"extraHosts"`
ContainerStatus string `json:"containerStatus"`
Container string `json:"container"`
Remark string `json:"remark"`
-6
View File
@@ -3,7 +3,6 @@ package response
import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
)
@@ -17,10 +16,6 @@ type WebsiteDTO struct {
RuntimeType string `json:"runtimeType"`
SiteDir string `json:"siteDir"`
OpenBaseDir bool `json:"openBaseDir"`
Algorithm string `json:"algorithm"`
UDP bool `json:"udp"`
Servers []dto.NginxUpstreamServer `json:"servers"`
}
type WebsiteRes struct {
@@ -40,7 +35,6 @@ type WebsiteRes struct {
SSLStatus string `json:"sslStatus"`
AppInstallID uint `json:"appInstallId"`
ChildSites []string `json:"childSites"`
ParentSite string `json:"parentSite"`
RuntimeType string `json:"runtimeType"`
Favorite bool `json:"favorite"`
IPV6 bool `json:"IPV6"`
-22
View File
@@ -10,7 +10,6 @@ type SettingInfo struct {
NtpSite string `json:"ntpSite"`
DefaultNetwork string `json:"defaultNetwork"`
DefaultIO string `json:"defaultIO"`
LastCleanTime string `json:"lastCleanTime"`
LastCleanSize string `json:"lastCleanSize"`
LastCleanData string `json:"lastCleanData"`
@@ -37,7 +36,6 @@ type SyncTime struct {
type CleanData struct {
SystemClean []CleanTree `json:"systemClean"`
BackupClean []CleanTree `json:"backupClean"`
UploadClean []CleanTree `json:"uploadClean"`
DownloadClean []CleanTree `json:"downloadClean"`
SystemLogClean []CleanTree `json:"systemLogClean"`
@@ -63,10 +61,6 @@ type Clean struct {
Size uint64 `json:"size"`
}
type SSHDefaultConn struct {
WithReset bool `json:"withReset"`
DefaultConn string `json:"defaultConn"`
}
type SSHConnData struct {
Addr string `json:"addr" validate:"required"`
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
@@ -86,19 +80,3 @@ type SystemProxy struct {
User string `json:"user"`
Password string `json:"password"`
}
type TerminalAIInfo struct {
AIStatus string `json:"aiStatus"`
AIAccountID string `json:"aiAccountId"`
AIPrefix string `json:"aiPrefix" validate:"required,oneof=@ai #ai /ai"`
AIRiskCommands string `json:"aiRiskCommands"`
AIRiskCommandsDefault string `json:"aiRiskCommandsDefault"`
}
type CommonDescription struct {
ID string `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
DetailType string `json:"detailType"`
IsPinned bool `json:"isPinned"`
Description string `json:"description"`
}
-1
View File
@@ -52,7 +52,6 @@ type DataTree struct {
Label string `json:"label"`
Key string `json:"key"`
Name string `json:"name"`
IsLocal bool `json:"isLocal"`
Size uint64 `json:"size"`
IsCheck bool `json:"isCheck"`
IsDisable bool `json:"isDisable"`
-20
View File
@@ -1,20 +0,0 @@
package model
type Agent struct {
BaseModel
Name string `json:"name" gorm:"not null;unique"`
AgentType string `json:"agentType" gorm:"default:openclaw"`
Provider string `json:"provider"`
Model string `json:"model"`
APIType string `json:"apiType"`
MaxTokens int `json:"maxTokens"`
ContextWindow int `json:"contextWindow"`
BaseURL string `json:"baseUrl"`
APIKey string `json:"apiKey"`
Token string `json:"token"`
Status string `json:"status"`
Message string `json:"message"`
AppInstallID uint `json:"appInstallId"`
AccountID uint `json:"accountId"`
ConfigPath string `json:"configPath"`
}
-17
View File
@@ -1,17 +0,0 @@
package model
type AgentAccount struct {
BaseModel
Provider string `json:"provider"`
Name string `json:"name"`
APIKey string `json:"apiKey"`
BaseURL string `json:"baseUrl"`
APIType string `json:"apiType"`
RememberAPIKey bool `json:"rememberApiKey"`
Verified bool `json:"verified"`
Remark string `json:"remark"`
}
func (AgentAccount) TableName() string {
return "agent_provider_accounts"
}
-17
View File
@@ -1,17 +0,0 @@
package model
type AgentAccountModel struct {
BaseModel
AccountID uint `json:"accountId" gorm:"index"`
Model string `json:"model" gorm:"index"`
Name string `json:"name"`
ContextWindow int `json:"contextWindow"`
MaxTokens int `json:"maxTokens"`
Reasoning bool `json:"reasoning"`
Input string `json:"input" gorm:"type:text"`
SortOrder int `json:"sortOrder" gorm:"index"`
}
func (AgentAccountModel) TableName() string {
return "agent_account_models"
}
+1 -1
View File
@@ -11,7 +11,7 @@ type Alert struct {
Status string `gorm:"type:varchar(64);not null" json:"status"`
Method string `gorm:"type:varchar(64);not null" json:"method"`
SendCount uint `gorm:"type:integer" json:"sendCount"`
AdvancedParams string `gorm:"type:longText" json:"advancedParams"`
AdvancedParams string `gorm:"type:longText" json:"advancedParam"`
}
type AlertTask struct {
-1
View File
@@ -34,7 +34,6 @@ type App struct {
MemoryRequired int `json:"memoryRequired"`
GpuSupport bool `json:"gpuSupport"`
RequiredPanelVersion float64 `json:"requiredPanelVersion"`
BatchInstallSupport bool `json:"batchInstallSupport" yaml:"batchInstallSupport"`
Details []AppDetail `json:"-" gorm:"-:migration"`
TagsKey []string `json:"tags" yaml:"tags" gorm:"-"`
-1
View File
@@ -26,7 +26,6 @@ type AppInstall struct {
HttpsPort int `json:"httpsPort"`
WebUI string `json:"webUI"`
Favorite bool `json:"favorite"`
SortOrder int `json:"sortOrder" gorm:"default:0"`
App App `json:"app" gorm:"-:migration"`
}
-1
View File
@@ -37,7 +37,6 @@ type Cronjob struct {
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
RetainCopies uint64 `json:"retainCopies"`
Args string `json:"args"`
IsExecuting bool `json:"isExecuting"`
Status string `json:"status"`
-1
View File
@@ -9,7 +9,6 @@ type Database struct {
From string `json:"from" gorm:"not null"`
Address string `json:"address" gorm:"not null"`
Port uint `json:"port" gorm:"not null"`
InitialDB string `json:"initialDB"`
Username string `json:"username"`
Password string `json:"password"`
-1
View File
@@ -6,7 +6,6 @@ type DatabaseMysql struct {
From string `json:"from" gorm:"not null;default:local"`
MysqlName string `json:"mysqlName" gorm:"not null"`
Format string `json:"format" gorm:"not null"`
Collation string `json:"collation"`
Username string `json:"username" gorm:"not null"`
Password string `json:"password" gorm:"not null"`
Permission string `json:"permission" gorm:"not null"`
+15 -11
View File
@@ -3,16 +3,20 @@ package model
type Firewall struct {
BaseModel
Type string `json:"type"`
Port string `json:"port"` // Deprecated
Address string `json:"address"` // Deprecated
Chain string `json:"chain"`
Protocol string `json:"protocol"`
SrcIP string `json:"srcIP"`
SrcPort string `json:"srcPort"`
DstIP string `json:"dstIP"`
DstPort string `json:"dstPort"`
Type string `gorm:"not null" json:"type"`
Port string `gorm:"not null" json:"port"`
Protocol string `gorm:"not null" json:"protocol"`
Address string `gorm:"not null" json:"address"`
Strategy string `gorm:"not null" json:"strategy"`
Description string `json:"description"`
Description string `gorm:"not null" json:"description"`
}
type Forward struct {
BaseModel
Protocol string `gorm:"not null" json:"protocol"`
Port string `gorm:"not null" json:"port"`
TargetIP string `gorm:"not null" json:"targetIP"`
TargetPort string `gorm:"not null" json:"targetPort"`
Interface string `json:"interface"`
}
-13
View File
@@ -31,16 +31,3 @@ type MonitorNetwork struct {
Up float64 `json:"up"`
Down float64 `json:"down"`
}
type MonitorGPU struct {
BaseModel
ProductName string `json:"productName"`
GPUUtil float64 `json:"gpuUtil"`
Temperature float64 `json:"temperature"`
PowerDraw float64 `json:"powerDraw"`
MaxPowerLimit float64 `json:"maxPowerLimit"`
MemUsed float64 `json:"memUsed"`
MemTotal float64 `json:"memTotal"`
FanSpeed int `json:"fanSpeed"`
Processes string `json:"processes"`
}
-8
View File
@@ -7,14 +7,6 @@ type Setting struct {
About string `json:"about"`
}
type CommonDescription struct {
ID string `json:"id"`
Type string `json:"type"`
DetailType string `json:"detailType"`
IsPinned bool `json:"isPinned"`
Description string `json:"description"`
}
type NodeInfo struct {
Scope string `json:"scope"`
BaseDir string `json:"baseDir"`
-2
View File
@@ -37,8 +37,6 @@ type Website struct {
Favorite bool `json:"favorite"`
StreamPorts string `json:"streamPorts"`
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
}
-1
View File
@@ -11,7 +11,6 @@ type WebsiteAcmeAccount struct {
KeyType string `gorm:"not null;default:2048" json:"keyType"`
UseProxy bool `gorm:"default:false" json:"useProxy"`
CaDirURL string `json:"caDirURL"`
UseEAB bool `json:"useEAB"`
}
func (w WebsiteAcmeAccount) TableName() string {
-1
View File
@@ -41,7 +41,6 @@ type WebsiteSSL struct {
PushNode bool `json:"pushNode"`
PrivateKeyPath string `json:"privateKeyPath"`
CertPath string `json:"certPath"`
IsIp bool `json:"isIP"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`
-440
View File
@@ -1,440 +0,0 @@
package provider
import (
"strings"
)
type Model struct {
ID string
Name string
ContextWindow int
MaxTokens int
Reasoning bool
Input []string
}
type RuntimeDefault struct {
APIType string
ContextWindow int
MaxTokens int
Input []string
}
type Meta struct {
Key string
DisplayName string
Sort uint
DefaultBaseURL string
EnvKey string
Default RuntimeDefault
Models []Model
}
var catalog = map[string]Meta{
"custom": {
Key: "custom",
DisplayName: "Custom",
Sort: 10,
DefaultBaseURL: "",
EnvKey: "CUSTOM_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 128000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{},
},
"ollama": {
Key: "ollama",
DisplayName: "Ollama",
Sort: 15,
Default: RuntimeDefault{
APIType: "openai-responses",
ContextWindow: 160000,
MaxTokens: 8192,
Input: []string{"text"},
},
},
"vllm": {
Key: "vllm",
DisplayName: "vLLM",
Sort: 20,
DefaultBaseURL: "",
EnvKey: "VLLM_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 128000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{},
},
"deepseek": {
Key: "deepseek",
DisplayName: "DeepSeek",
Sort: 25,
DefaultBaseURL: "https://api.deepseek.com/v1",
EnvKey: "DEEPSEEK_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 128000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "deepseek/deepseek-chat", Name: "DeepSeek Chat"},
{ID: "deepseek/deepseek-reasoner", Name: "DeepSeek Reasoner", Reasoning: true},
{ID: "deepseek/deepseek-r1:1.5b", Name: "DeepSeek R1 1.5B", Reasoning: true},
},
},
"bailian-coding-plan": {
Key: "bailian-coding-plan",
DisplayName: "阿里云百炼 Coding Plan",
Sort: 30,
DefaultBaseURL: "https://coding.dashscope.aliyuncs.com/v1",
EnvKey: "QWEN_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "bailian-coding-plan/qwen3.5-plus", Name: "Qwen3.5-Plus", Reasoning: true},
{ID: "bailian-coding-plan/qwen3-max", Name: "Qwen3-Max", Reasoning: true},
{ID: "bailian-coding-plan/qwen3-coder-next", Name: "Qwen3-Coder-Next", Reasoning: true},
{ID: "bailian-coding-plan/qwen3-coder-plus", Name: "Qwen3-Coder-Plus", Reasoning: true},
{ID: "bailian-coding-plan/minimax-m2.5", Name: "MiniMax M2.5", Reasoning: true},
{ID: "bailian-coding-plan/glm-5", Name: "GLM-5", Reasoning: true},
{ID: "bailian-coding-plan/kimi-k2.5", Name: "Kimi-k2.5", Reasoning: true},
{ID: "bailian-coding-plan/glm-4.7", Name: "GLM-4.7", Reasoning: true},
},
},
"ark-coding-plan": {
Key: "ark-coding-plan",
DisplayName: "方舟 Coding Plan",
Sort: 35,
DefaultBaseURL: "https://ark.cn-beijing.volces.com/api/coding/v3",
EnvKey: "ARK_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "ark-coding-plan/doubao-seed-2.0-code", Name: "Doubao-Seed-2.0-Code"},
{ID: "ark-coding-plan/doubao-seed-code", Name: "Doubao-Seed-Code"},
{ID: "ark-coding-plan/kimi-k2.5", Name: "Kimi-K2.5", Reasoning: true},
{ID: "ark-coding-plan/glm-4.7", Name: "GLM-4.7", Reasoning: true},
{ID: "ark-coding-plan/deepseek-v3.2", Name: "DeepSeek-V3.2", Reasoning: true},
{ID: "ark-coding-plan/kimi-k2-thinking", Name: "Kimi-K2-thinking", Reasoning: true},
},
},
"zai": {
Key: "zai",
DisplayName: "Z.ai",
Sort: 40,
DefaultBaseURL: "https://open.bigmodel.cn/api/paas/v4",
EnvKey: "ZAI_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 204800,
MaxTokens: 131072,
Input: []string{"text"},
},
Models: []Model{
{ID: "zai/glm-5", Name: "GLM-5", Reasoning: true},
{ID: "zai/glm-4.7", Name: "GLM-4.7", Reasoning: true},
{ID: "zai/glm-4.7-flash", Name: "GLM-4.7-Flash", Reasoning: true},
{ID: "zai/glm-4.7-flashx", Name: "GLM-4.7-FlashX", Reasoning: true},
},
},
"minimax": {
Key: "minimax",
DisplayName: "MiniMax (CN)",
Sort: 45,
DefaultBaseURL: "https://api.minimaxi.com/anthropic",
EnvKey: "MINIMAX_API_KEY",
Default: RuntimeDefault{
APIType: "anthropic-messages",
ContextWindow: 200000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "minimax/MiniMax-M2.7", Name: "MiniMax M2.7"},
{ID: "minimax/MiniMax-M2.7-highspeed", Name: "MiniMax M2.7 highspeed"},
{ID: "minimax/MiniMax-M2.5", Name: "MiniMax M2.5", Reasoning: true},
{ID: "minimax/MiniMax-M2.5-highspeed", Name: "MiniMax M2.5 highspeed"},
},
},
"xiaomi": {
Key: "xiaomi",
DisplayName: "Xiaomi",
Sort: 46,
DefaultBaseURL: "https://api.xiaomimimo.com/anthropic",
EnvKey: "XIAOMI_API_KEY",
Default: RuntimeDefault{
APIType: "anthropic-messages",
ContextWindow: 262144,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "xiaomi/mimo-v2-pro", Name: "Xiaomi MiMo V2 Pro"},
{ID: "xiaomi/mimo-v2-omni", Name: "Xiaomi MiMo V2 Omni"},
{ID: "xiaomi/mimo-v2-tts", Name: "Xiaomi MiMo V2 TTS"},
{ID: "xiaomi/mimo-v2-flash", Name: "Xiaomi MiMo V2 Flash"},
},
},
"kimi": {
Key: "kimi",
DisplayName: "Kimi (CN)",
Sort: 50,
DefaultBaseURL: "https://api.moonshot.cn/v1",
EnvKey: "KIMI_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text", "image"},
},
Models: []Model{
{ID: "kimi/kimi-k2.5", Name: "Kimi K2.5", Reasoning: true},
{ID: "kimi/kimi-k2-0905-preview", Name: "Kimi K2 0905 Preview"},
{ID: "kimi/kimi-k2-thinking", Name: "Kimi K2 Thinking", Reasoning: true},
},
},
"kimi-coding": {
Key: "kimi-coding",
DisplayName: "Kimi Coding",
Sort: 51,
DefaultBaseURL: "https://api.kimi.com/coding/",
EnvKey: "KIMI_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 262144,
MaxTokens: 32768,
Input: []string{"text", "image"},
},
Models: []Model{
{ID: "kimi-coding/k2p5", Name: "Kimi K2.5", Reasoning: true},
},
},
"openai": {
Key: "openai",
DisplayName: "OpenAI",
Sort: 55,
DefaultBaseURL: "https://api.openai.com/v1",
EnvKey: "OPENAI_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text", "image"},
},
Models: []Model{
{ID: "openai/codex-mini-latest", Name: "Codex Mini", Reasoning: true},
{ID: "openai/gpt-5", Name: "GPT-5", Reasoning: true},
{ID: "openai/gpt-5-mini", Name: "GPT-5 Mini", Reasoning: true},
{ID: "openai/gpt-5.4", Name: "GPT-5.4", Reasoning: true},
{ID: "openai/gpt-5.3-codex", Name: "GPT-5.3-Codex", Reasoning: true},
},
},
"openrouter": {
Key: "openrouter",
DisplayName: "OpenRouter",
Sort: 56,
DefaultBaseURL: "https://openrouter.ai/api/v1",
EnvKey: "OPENROUTER_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 128000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "openrouter/free", Name: "openrouter/free"},
{ID: "openrouter/auto", Name: "openrouter/auto"},
},
},
"anthropic": {
Key: "anthropic",
DisplayName: "Anthropic",
Sort: 60,
DefaultBaseURL: "https://api.anthropic.com",
EnvKey: "ANTHROPIC_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text", "image"},
},
Models: []Model{
{ID: "anthropic/claude-3-haiku-20240307", Name: "Claude 3 Haiku"},
{ID: "anthropic/claude-3-5-haiku-latest", Name: "Claude 3.5 Haiku"},
{ID: "anthropic/claude-3-5-sonnet-20241022", Name: "Claude 3.5 Sonnet"},
{ID: "anthropic/claude-3-7-sonnet-20250219", Name: "Claude 3.7 Sonnet", Reasoning: true},
{ID: "anthropic/claude-opus-4-1", Name: "Claude Opus 4.1", Reasoning: true},
},
},
"gemini": {
Key: "gemini",
DisplayName: "Gemini",
Sort: 65,
DefaultBaseURL: "https://generativelanguage.googleapis.com",
EnvKey: "GEMINI_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text", "image"},
},
Models: []Model{
{ID: "google/gemini-3-flash-preview", Name: "Gemini 3 Flash Preview", Reasoning: true},
{ID: "google/gemini-flash-latest", Name: "Gemini Flash Latest"},
{ID: "google/gemini-3-pro-preview", Name: "Gemini 3 Pro Preview", Reasoning: true},
},
},
"moonshot": {
Key: "moonshot",
DisplayName: "Moonshot (Global)",
Sort: 70,
DefaultBaseURL: "https://api.moonshot.ai/v1",
EnvKey: "MOONSHOT_API_KEY",
Default: RuntimeDefault{
APIType: "openai-completions",
ContextWindow: 256000,
MaxTokens: 8192,
Input: []string{"text"},
},
Models: []Model{
{ID: "moonshot/kimi-k2.5", Name: "Kimi K2.5", Reasoning: true},
{ID: "moonshot/kimi-k2-0905-preview", Name: "Kimi K2 0905 Preview"},
{ID: "moonshot/kimi-k2-thinking", Name: "Kimi K2 Thinking", Reasoning: true},
},
},
}
func Get(key string) (Meta, bool) {
meta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]
if !ok {
return Meta{}, false
}
return cloneMeta(meta), true
}
func All() map[string]Meta {
result := make(map[string]Meta, len(catalog))
for key, meta := range catalog {
result[key] = cloneMeta(meta)
}
return result
}
func DefaultBaseURL(key string) (string, bool) {
meta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]
if !ok || strings.TrimSpace(meta.DefaultBaseURL) == "" {
return "", false
}
return meta.DefaultBaseURL, true
}
func EnvKey(key string) string {
meta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]
if !ok {
return ""
}
return meta.EnvKey
}
func DisplayName(key string) string {
meta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]
if !ok {
return key
}
if strings.TrimSpace(meta.DisplayName) == "" {
return key
}
return meta.DisplayName
}
func FindModel(key, modelID string) (Model, bool) {
meta, ok := Get(key)
if !ok {
return Model{}, false
}
for _, item := range meta.Models {
if item.ID == modelID {
return item, true
}
}
return Model{}, false
}
func cloneMeta(meta Meta) Meta {
clone := meta
if len(meta.Default.Input) > 0 {
clone.Default.Input = make([]string, len(meta.Default.Input))
copy(clone.Default.Input, meta.Default.Input)
}
if len(meta.Models) > 0 {
clone.Models = make([]Model, len(meta.Models))
for i, item := range meta.Models {
clone.Models[i] = normalizeModel(meta, item)
}
}
return clone
}
func normalizeModel(meta Meta, model Model) Model {
clone := model
clone.ID = strings.TrimSpace(clone.ID)
clone.Name = strings.TrimSpace(clone.Name)
if clone.Name == "" {
clone.Name = clone.ID
}
if clone.MaxTokens <= 0 {
clone.MaxTokens = meta.Default.MaxTokens
}
if clone.ContextWindow <= 0 {
clone.ContextWindow = meta.Default.ContextWindow
}
if len(clone.Input) == 0 && len(meta.Default.Input) > 0 {
clone.Input = make([]string, len(meta.Default.Input))
copy(clone.Input, meta.Default.Input)
}
return clone
}
func ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {
defaultAPIType := "openai-completions"
defaultMaxTokens := 8192
defaultContextWindow := 256000
if meta, ok := Get(provider); ok {
if meta.Default.APIType != "" {
defaultAPIType = meta.Default.APIType
}
if meta.Default.MaxTokens > 0 {
defaultMaxTokens = meta.Default.MaxTokens
}
if meta.Default.ContextWindow > 0 {
defaultContextWindow = meta.Default.ContextWindow
}
}
resolvedAPI := apiType
if strings.TrimSpace(apiType) == "" {
resolvedAPI = defaultAPIType
}
resolvedMaxTokens := defaultMaxTokens
resolvedContextWindow := defaultContextWindow
if maxTokens > 0 {
resolvedMaxTokens = maxTokens
}
if contextWindow > 0 {
resolvedContextWindow = contextWindow
}
return resolvedAPI, resolvedMaxTokens, resolvedContextWindow
}
-338
View File
@@ -1,338 +0,0 @@
package provider
import (
"fmt"
"strings"
)
type OpenClawPatch struct {
PrimaryModel string
Models map[string]interface{}
}
type openClawModelSpec struct {
ID string
Name string
Reasoning bool
Input []string
ContextWindow int
MaxTokens int
}
type openClawPatchSpec struct {
PrimaryModel string
Provider string
APIKey string
BaseURL string
APIType string
AuthHeader bool
Model openClawModelSpec
}
func BuildOpenClawPatch(provider, modelName, apiType string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) (*OpenClawPatch, error) {
provider = strings.ToLower(strings.TrimSpace(provider))
modelName = strings.TrimSpace(modelName)
if modelName == "" {
return nil, fmt.Errorf("model is required")
}
apiType, maxTokens, contextWindow = ResolveRuntimeParams(provider, apiType, maxTokens, contextWindow)
modelID := modelName
if parts := strings.SplitN(modelName, "/", 2); len(parts) == 2 {
modelID = parts[1]
}
var spec openClawPatchSpec
switch provider {
case "deepseek":
spec = buildDeepseekPatchSpec(modelName, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "gemini":
spec = buildGenericPatchSpec(provider, modelName, modelID, apiType, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "moonshot", "kimi":
spec = buildMoonshotPatchSpec(provider, modelName, modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "bailian-coding-plan":
spec = buildBailianPatchSpec(modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "ark-coding-plan":
spec = buildArkPatchSpec(modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "minimax":
spec = buildMiniMaxPatchSpec(modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "xiaomi":
spec = buildXiaomiPatchSpec(modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "custom", "vllm":
spec = buildCustomPatchSpec(provider, modelName, apiType, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "ollama":
spec = buildOllamaPatchSpec(modelName, modelID, apiType, reasoning, maxTokens, contextWindow, baseURL)
case "kimi-coding":
spec = buildKimiCodingPatchSpec(modelName, modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
case "zai":
spec = buildZaiPatchSpec(modelID, reasoning, maxTokens, contextWindow, baseURL, apiKey)
default:
spec = buildGenericPatchSpec(provider, modelName, modelID, apiType, reasoning, maxTokens, contextWindow, baseURL, apiKey)
}
return buildOpenClawPatch(spec), nil
}
func buildOpenClawPatch(spec openClawPatchSpec) *OpenClawPatch {
return &OpenClawPatch{
PrimaryModel: spec.PrimaryModel,
Models: providerModels(
spec.Provider,
spec.APIKey,
spec.BaseURL,
spec.APIType,
spec.AuthHeader,
buildOpenClawModel(spec.Model),
),
}
}
func buildOpenClawModel(spec openClawModelSpec) map[string]interface{} {
return map[string]interface{}{
"id": spec.ID,
"name": spec.Name,
"reasoning": spec.Reasoning,
"input": spec.Input,
"contextWindow": spec.ContextWindow,
"maxTokens": spec.MaxTokens,
"cost": map[string]interface{}{},
}
}
func buildDeepseekPatchSpec(modelName string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: modelName,
Provider: "deepseek",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "openai-completions",
Model: openClawModelSpec{
ID: "deepseek-chat",
Name: "DeepSeek Chat",
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildMoonshotPatchSpec(provider, modelName, modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
configProvider := provider
primaryModel := modelName
if provider == "kimi" {
configProvider = "moonshot"
primaryModel = "moonshot/" + modelID
}
return openClawPatchSpec{
PrimaryModel: primaryModel,
Provider: configProvider,
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "openai-completions",
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildBailianPatchSpec(modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: "bailian-coding-plan/" + modelID,
Provider: "bailian-coding-plan",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "openai-completions",
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildArkPatchSpec(modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: "ark-coding-plan/" + modelID,
Provider: "ark-coding-plan",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "openai-completions",
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildMiniMaxPatchSpec(modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: "minimax/" + modelID,
Provider: "minimax",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "anthropic-messages",
AuthHeader: true,
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildXiaomiPatchSpec(modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
normalizedID := strings.TrimSpace(modelID)
return openClawPatchSpec{
PrimaryModel: "xiaomi/" + normalizedID,
Provider: "xiaomi",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "anthropic-messages",
Model: openClawModelSpec{
ID: normalizedID,
Name: normalizedID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildCustomPatchSpec(provider, modelName, apiType string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
customModelID := normalizeCustomModel(modelName)
return openClawPatchSpec{
PrimaryModel: provider + "/" + customModelID,
Provider: provider,
APIKey: strings.TrimSpace(apiKey),
BaseURL: strings.TrimSpace(baseURL),
APIType: apiType,
Model: openClawModelSpec{
ID: customModelID,
Name: customModelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildOllamaPatchSpec(modelName, modelID, apiType string, reasoning bool, maxTokens, contextWindow int, baseURL string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: modelName,
Provider: "ollama",
APIKey: "ollama",
BaseURL: strings.TrimSpace(baseURL),
APIType: apiType,
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildKimiCodingPatchSpec(modelName, modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: modelName,
Provider: "kimi-coding",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "anthropic-messages",
Model: openClawModelSpec{
ID: modelID,
Name: "Kimi for Coding",
Reasoning: reasoning,
Input: []string{"text", "image"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildZaiPatchSpec(modelID string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
return openClawPatchSpec{
PrimaryModel: "zai/" + modelID,
Provider: "zai",
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: "openai-completions",
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func buildGenericPatchSpec(provider, modelName, modelID, apiType string, reasoning bool, maxTokens, contextWindow int, baseURL, apiKey string) openClawPatchSpec {
providerName := provider
primaryModel := modelName
if provider == "gemini" {
providerName = "google"
primaryModel = "google/" + modelID
}
return openClawPatchSpec{
PrimaryModel: primaryModel,
Provider: providerName,
APIKey: strings.TrimSpace(apiKey),
BaseURL: baseURL,
APIType: apiType,
Model: openClawModelSpec{
ID: modelID,
Name: modelID,
Reasoning: reasoning,
Input: []string{"text"},
ContextWindow: contextWindow,
MaxTokens: maxTokens,
},
}
}
func providerModels(provider, apiKey, baseURL, api string, authHeader bool, model map[string]interface{}) map[string]interface{} {
providerConfig := map[string]interface{}{
"apiKey": apiKey,
"baseUrl": baseURL,
"api": api,
"models": []map[string]interface{}{model},
}
if authHeader {
providerConfig["authHeader"] = true
}
return map[string]interface{}{
"mode": "merge",
"providers": map[string]interface{}{
provider: providerConfig,
},
}
}
func normalizeCustomModel(modelName string) string {
trim := strings.TrimSpace(modelName)
trim = strings.TrimLeft(trim, "/")
if parts := strings.SplitN(trim, "/", 2); len(parts) == 2 && strings.EqualFold(parts[0], "custom") {
return strings.TrimLeft(strings.TrimSpace(parts[1]), "/")
}
return trim
}
-190
View File
@@ -1,190 +0,0 @@
package provider
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/buserr"
)
type VerifyRequest struct {
Method string
URL string
Headers map[string]string
Body []byte
}
const (
defaultVerifyTimeout = 30 * time.Second
)
func SkipVerification(key string) bool {
switch strings.ToLower(strings.TrimSpace(key)) {
case "custom", "vllm", "ollama", "kimi-coding":
return true
default:
return false
}
}
func VerifyAccount(provider, baseURL, apiKey string) error {
req := BuildVerifyRequest(provider, baseURL, apiKey)
var body *bytes.Buffer
if len(req.Body) > 0 {
body = bytes.NewBuffer(req.Body)
} else {
body = bytes.NewBuffer(nil)
}
httpReq, err := http.NewRequest(req.Method, req.URL, body)
if err != nil {
return err
}
for key, value := range req.Headers {
httpReq.Header.Set(key, value)
}
resp, err := (&http.Client{Timeout: verifyTimeout()}).Do(httpReq)
if err != nil {
return buserr.WithErr("ErrAgentAccountUnavailable", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return buserr.WithErr("ErrAgentAccountUnavailable", fmt.Errorf("verify failed: %s", resp.Status))
}
return nil
}
func verifyTimeout() time.Duration {
return defaultVerifyTimeout
}
func BuildVerifyRequest(provider, baseURL, apiKey string) VerifyRequest {
provider = strings.ToLower(strings.TrimSpace(provider))
base := strings.TrimRight(strings.TrimSpace(baseURL), "/")
headers := map[string]string{}
request := VerifyRequest{Method: http.MethodGet, Headers: headers}
switch provider {
case "anthropic", "kimi-coding":
headers["x-api-key"] = apiKey
headers["anthropic-version"] = "2023-06-01"
if strings.Contains(base, "/v1") {
request.URL = base + "/models"
} else {
request.URL = base + "/v1/models"
}
case "gemini":
request.Method = http.MethodPost
if strings.Contains(base, "/v1beta") {
request.URL = base + "/models/gemini-3-flash-preview:generateContent"
} else {
request.URL = base + "/v1beta/models/gemini-3-flash-preview:generateContent"
}
headers["x-goog-api-key"] = apiKey
headers["Content-Type"] = "application/json"
request.Body = mustJSON(map[string]interface{}{
"contents": []map[string]interface{}{{
"parts": []map[string]string{{
"text": "Explain how AI works in a few words",
}},
}},
})
case "zai":
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
request.URL = base + "/models"
case "bailian-coding-plan":
request.Method = http.MethodPost
if !strings.Contains(base, "/v1") {
base = base + "/v1"
}
request.URL = base + "/chat/completions"
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
headers["Content-Type"] = "application/json"
request.Body = mustJSON(map[string]interface{}{
"model": "qwen3.5-plus",
"messages": []map[string]string{{"role": "user", "content": "test"}},
"max_tokens": 1,
})
case "ark-coding-plan":
request.Method = http.MethodPost
if !strings.Contains(base, "/api/coding/v3") {
base = "https://ark.cn-beijing.volces.com/api/coding/v3"
}
request.URL = base + "/chat/completions"
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
headers["Content-Type"] = "application/json"
request.Body = mustJSON(map[string]interface{}{
"model": "doubao-seed-2.0-code",
"messages": []map[string]string{{"role": "user", "content": "test"}},
"max_tokens": 1,
})
case "minimax":
request.Method = http.MethodPost
headers["x-api-key"] = apiKey
headers["anthropic-version"] = "2023-06-01"
headers["Content-Type"] = "application/json"
if strings.Contains(base, "/v1") {
request.URL = base + "/messages"
} else {
request.URL = base + "/v1/messages"
}
request.Body = mustJSON(map[string]interface{}{
"model": "MiniMax-M2.5",
"max_tokens": 1,
"messages": []map[string]interface{}{{
"role": "user",
"content": []map[string]string{{
"type": "text",
"text": "test",
}},
}},
})
case "xiaomi":
request.Method = http.MethodPost
headers["x-api-key"] = apiKey
headers["anthropic-version"] = "2023-06-01"
headers["Content-Type"] = "application/json"
if strings.Contains(base, "/v1") {
request.URL = base + "/messages"
} else {
request.URL = base + "/v1/messages"
}
request.Body = mustJSON(map[string]interface{}{
"model": "mimo-v2-flash",
"max_tokens": 1,
"messages": []map[string]interface{}{{
"role": "user",
"content": []map[string]string{{
"type": "text",
"text": "test",
}},
}},
})
case "openrouter":
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
if strings.Contains(base, "/v1") {
request.URL = base + "/key"
} else {
request.URL = base + "/v1/key"
}
default:
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
if strings.Contains(base, "/v1") {
request.URL = base + "/models"
} else {
request.URL = base + "/v1/models"
}
}
return request
}
func mustJSON(value interface{}) []byte {
payload, err := json.Marshal(value)
if err != nil {
return []byte("{}")
}
return payload
}
-75
View File
@@ -1,75 +0,0 @@
package repo
import (
"context"
"github.com/1Panel-dev/1Panel/agent/app/model"
)
type AgentRepo struct{}
type IAgentRepo interface {
Page(page, size int, opts ...DBOption) (int64, []model.Agent, error)
GetFirst(opts ...DBOption) (*model.Agent, error)
Create(agent *model.Agent) error
Save(agent *model.Agent) error
DeleteByID(id uint) error
DeleteByAppInstallID(appInstallID uint) error
DeleteByAppInstallIDWithCtx(ctx context.Context, appInstallID uint) error
List(opts ...DBOption) ([]model.Agent, error)
}
func NewIAgentRepo() IAgentRepo {
return &AgentRepo{}
}
func (a AgentRepo) Page(page, size int, opts ...DBOption) (int64, []model.Agent, error) {
var agents []model.Agent
db := getDb(opts...).Model(&model.Agent{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&agents).Error
return count, agents, err
}
func (a AgentRepo) GetFirst(opts ...DBOption) (*model.Agent, error) {
var agent model.Agent
if err := getDb(opts...).First(&agent).Error; err != nil {
return nil, err
}
return &agent, nil
}
func (a AgentRepo) Create(agent *model.Agent) error {
return getDb().Create(agent).Error
}
func (a AgentRepo) Save(agent *model.Agent) error {
return getDb().Save(agent).Error
}
func (a AgentRepo) DeleteByID(id uint) error {
return getDb().Delete(&model.Agent{}, id).Error
}
func (a AgentRepo) DeleteByAppInstallID(appInstallID uint) error {
if appInstallID == 0 {
return nil
}
return getDb().Where("app_install_id = ?", appInstallID).Delete(&model.Agent{}).Error
}
func (a AgentRepo) DeleteByAppInstallIDWithCtx(ctx context.Context, appInstallID uint) error {
if appInstallID == 0 {
return nil
}
return getTx(ctx).Where("app_install_id = ?", appInstallID).Delete(&model.Agent{}).Error
}
func (a AgentRepo) List(opts ...DBOption) ([]model.Agent, error) {
var agents []model.Agent
if err := getDb(opts...).Find(&agents).Error; err != nil {
return nil, err
}
return agents, nil
}
-55
View File
@@ -1,55 +0,0 @@
package repo
import "github.com/1Panel-dev/1Panel/agent/app/model"
type AgentAccountRepo struct{}
type IAgentAccountRepo interface {
Page(page, size int, opts ...DBOption) (int64, []model.AgentAccount, error)
GetFirst(opts ...DBOption) (*model.AgentAccount, error)
Create(account *model.AgentAccount) error
Save(account *model.AgentAccount) error
DeleteByID(id uint) error
List(opts ...DBOption) ([]model.AgentAccount, error)
}
func NewIAgentAccountRepo() IAgentAccountRepo {
return &AgentAccountRepo{}
}
func (a AgentAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.AgentAccount, error) {
var accounts []model.AgentAccount
db := getDb(opts...).Model(&model.AgentAccount{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&accounts).Error
return count, accounts, err
}
func (a AgentAccountRepo) GetFirst(opts ...DBOption) (*model.AgentAccount, error) {
var account model.AgentAccount
if err := getDb(opts...).First(&account).Error; err != nil {
return nil, err
}
return &account, nil
}
func (a AgentAccountRepo) Create(account *model.AgentAccount) error {
return getDb().Create(account).Error
}
func (a AgentAccountRepo) Save(account *model.AgentAccount) error {
return getDb().Save(account).Error
}
func (a AgentAccountRepo) DeleteByID(id uint) error {
return getDb().Delete(&model.AgentAccount{}, id).Error
}
func (a AgentAccountRepo) List(opts ...DBOption) ([]model.AgentAccount, error) {
var accounts []model.AgentAccount
if err := getDb(opts...).Find(&accounts).Error; err != nil {
return nil, err
}
return accounts, nil
}
-50
View File
@@ -1,50 +0,0 @@
package repo
import "github.com/1Panel-dev/1Panel/agent/app/model"
type AgentAccountModelRepo struct{}
type IAgentAccountModelRepo interface {
List(opts ...DBOption) ([]model.AgentAccountModel, error)
GetFirst(opts ...DBOption) (*model.AgentAccountModel, error)
Create(item *model.AgentAccountModel) error
Save(item *model.AgentAccountModel) error
DeleteByID(id uint) error
Delete(opts ...DBOption) error
}
func NewIAgentAccountModelRepo() IAgentAccountModelRepo {
return &AgentAccountModelRepo{}
}
func (a AgentAccountModelRepo) List(opts ...DBOption) ([]model.AgentAccountModel, error) {
var list []model.AgentAccountModel
if err := getDb(opts...).Find(&list).Error; err != nil {
return nil, err
}
return list, nil
}
func (a AgentAccountModelRepo) GetFirst(opts ...DBOption) (*model.AgentAccountModel, error) {
var item model.AgentAccountModel
if err := getDb(opts...).First(&item).Error; err != nil {
return nil, err
}
return &item, nil
}
func (a AgentAccountModelRepo) Create(item *model.AgentAccountModel) error {
return getDb().Create(item).Error
}
func (a AgentAccountModelRepo) Save(item *model.AgentAccountModel) error {
return getDb().Save(item).Error
}
func (a AgentAccountModelRepo) DeleteByID(id uint) error {
return getDb().Delete(&model.AgentAccountModel{}, id).Error
}
func (a AgentAccountModelRepo) Delete(opts ...DBOption) error {
return getDb(opts...).Delete(&model.AgentAccountModel{}).Error
}
+11 -9
View File
@@ -20,7 +20,6 @@ type IAppRepo interface {
WithResource(resource string) DBOption
WithNotLocal() DBOption
WithByLikeName(name string) DBOption
WithKeyIn(keys []string) DBOption
WithArch(arch string) DBOption
WithPanelVersion(panelVersion string) DBOption
@@ -28,13 +27,14 @@ type IAppRepo interface {
GetFirst(opts ...DBOption) (model.App, error)
GetBy(opts ...DBOption) ([]model.App, error)
BatchCreate(ctx context.Context, apps []model.App) error
GetByKey(ctx context.Context, key string) (model.App, error)
Create(ctx context.Context, app *model.App) error
Save(ctx context.Context, app *model.App) error
BatchDelete(ctx context.Context, apps []model.App) error
DeleteByIDs(ctx context.Context, ids []uint) error
DeleteBy(opts ...DBOption) error
GetTopRecommend() ([]string, error)
GetTopRecomment() ([]string, error)
}
func NewIAppRepo() IAppRepo {
@@ -56,12 +56,6 @@ func (a AppRepo) WithKey(key string) DBOption {
}
}
func (a AppRepo) WithKeyIn(keys []string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("`key` in (?)", keys)
}
}
func (a AppRepo) WithType(typeStr string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("type = ?", typeStr)
@@ -131,7 +125,7 @@ func (a AppRepo) GetBy(opts ...DBOption) ([]model.App, error) {
return apps, nil
}
func (a AppRepo) GetTopRecommend() ([]string, error) {
func (a AppRepo) GetTopRecomment() ([]string, error) {
var (
apps []model.App
names []string
@@ -150,6 +144,14 @@ func (a AppRepo) BatchCreate(ctx context.Context, apps []model.App) error {
return getTx(ctx).Omit(clause.Associations).Create(&apps).Error
}
func (a AppRepo) GetByKey(ctx context.Context, key string) (model.App, error) {
var app model.App
if err := getTx(ctx).Where("key = ?", key).First(&app).Error; err != nil {
return app, err
}
return app, nil
}
func (a AppRepo) Create(ctx context.Context, app *model.App) error {
return getTx(ctx).Omit(clause.Associations).Create(app).Error
}
+1 -2
View File
@@ -80,10 +80,9 @@ func (u *LauncherRepo) ListQuickJump(withAll bool) []model.QuickJump {
}
if !withAll && len(quicks) == 0 {
return []model.QuickJump{
{Name: "Agent", Title: "aiTools.agents.agent", Recommend: 1, IsShow: true, Router: "/ai/agents/agent"},
{Name: "Website", Title: "menu.website", Recommend: 10, IsShow: true, Router: "/websites"},
{Name: "Database", Title: "menu.database", Recommend: 30, IsShow: true, Router: "/databases"},
{Name: "Cronjob", Title: "menu.cronjob", Recommend: 50, IsShow: false, Router: "/cronjobs"},
{Name: "Cronjob", Title: "menu.cronjob", Recommend: 50, IsShow: true, Router: "/cronjobs"},
{Name: "AppInstalled", Title: "home.appInstalled", Recommend: 70, IsShow: true, Router: "/apps/installed"},
}
}
+1 -2
View File
@@ -20,7 +20,6 @@ type IBackupRepo interface {
WithByPublic(isPublic bool) DBOption
ListRecord(opts ...DBOption) ([]model.BackupRecord, error)
GetRecord(opts ...DBOption) (*model.BackupRecord, error)
PageRecord(page, size int, opts ...DBOption) (int64, []model.BackupRecord, error)
CreateRecord(record *model.BackupRecord) error
DeleteRecord(ctx context.Context, opts ...DBOption) error
@@ -161,7 +160,7 @@ func (u *BackupRepo) WithByCronID(cronjobID uint) DBOption {
}
func (u *BackupRepo) GetRecord(opts ...DBOption) (*model.BackupRecord, error) {
record := &model.BackupRecord{}
var record *model.BackupRecord
db := global.DB.Model(&model.BackupRecord{})
for _, opt := range opts {
db = opt(db)
+7 -59
View File
@@ -7,7 +7,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"gorm.io/gorm"
)
@@ -19,12 +18,6 @@ func WithByID(id uint) DBOption {
}
}
func WithByGroupID(id uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("group_id = ?", id)
}
}
func WithByNOTID(id uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id != ?", id)
@@ -49,12 +42,6 @@ func WithByName(name string) DBOption {
}
}
func WithByAddr(addr string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("addr = ?", addr)
}
}
func WithByKey(key string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("key = ?", key)
@@ -85,43 +72,11 @@ func WithByDetailName(detailName string) DBOption {
}
}
func WithByProvider(provider string) DBOption {
return func(g *gorm.DB) *gorm.DB {
if len(provider) == 0 {
return g
}
return g.Where("provider = ?", provider)
}
}
func WithByModel(model string) DBOption {
return func(g *gorm.DB) *gorm.DB {
if len(model) == 0 {
return g
}
return g.Where("model = ?", model)
}
}
func WithByAccountID(accountID uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
if accountID == 0 {
return g
}
return g.Where("account_id = ?", accountID)
}
}
func WithByType(tp string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("`type` = ?", tp)
}
}
func WithByDetailType(tp string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("`detail_type` = ?", tp)
}
}
func WithTypes(types []string) DBOption {
return func(db *gorm.DB) *gorm.DB {
@@ -164,30 +119,23 @@ func WithByCreatedAt(startTime, endTime time.Time) DBOption {
}
}
func WithOrderDesc(orderBy string) DBOption {
return WithOrderRuleBy(orderBy, constant.Desc)
func WithOrderBy(orderStr string) DBOption {
if orderStr == "createdAt" {
orderStr = "created_at"
}
return func(g *gorm.DB) *gorm.DB {
return g.Order(orderStr)
}
}
func WithOrderAsc(orderBy string) DBOption {
return WithOrderRuleBy(orderBy, constant.Asc)
}
func WithOrderRuleBy(orderBy, order string) DBOption {
if orderBy == "createdAt" {
orderBy = "created_at"
}
if !re.GetRegex(re.OrderByValidationPattern).MatchString(orderBy) {
orderBy = "created_at"
}
switch order {
case constant.OrderDesc:
order = "desc"
case constant.OrderAsc:
order = "asc"
case constant.Desc:
order = "desc"
case constant.Asc:
order = "asc"
default:
orderBy = "created_at"
order = "desc"
+1 -1
View File
@@ -173,7 +173,7 @@ func (u *CronjobRepo) AddFailedRecord(cronjobID uint, message string) {
var record model.JobRecords
record.StartTime = time.Now()
record.CronjobID = cronjobID
record.Status = constant.StatusUnexecuted
record.Status = constant.StatusFailed
record.Message = message
if err := global.DB.Create(&record).Error; err != nil {
global.LOG.Errorf("create record status failed, err: %v", err)
+21 -126
View File
@@ -4,28 +4,16 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"gorm.io/gorm"
)
type HostRepo struct{}
type IHostRepo interface {
Get(opts ...DBOption) (model.Host, error)
GetList(opts ...DBOption) ([]model.Host, error)
Page(limit, offset int, opts ...DBOption) (int64, []model.Host, error)
Create(host *model.Host) error
Update(id uint, vars map[string]interface{}) error
UpdateGroup(group, newGroup uint) error
Delete(opts ...DBOption) error
WithByInfo(info string) DBOption
WithByPort(port uint) DBOption
WithByUser(user string) DBOption
GetFirewallRecord(opts ...DBOption) (model.Firewall, error)
ListFirewallRecord(opts ...DBOption) ([]model.Firewall, error)
ListFirewallRecord() ([]model.Firewall, error)
SaveFirewallRecord(firewall *model.Firewall) error
DeleteFirewallRecordByID(id uint) error
DeleteFirewallRecord(fType, port, protocol, address, strategy string) error
SyncCert(data []model.RootCert) error
GetCert(opts ...DBOption) (model.RootCert, error)
@@ -34,88 +22,12 @@ type IHostRepo interface {
SaveCert(cert *model.RootCert) error
UpdateCert(id uint, vars map[string]interface{}) error
DeleteCert(opts ...DBOption) error
WithByChain(chain string) DBOption
}
func NewIHostRepo() IHostRepo {
return &HostRepo{}
}
func (h *HostRepo) Get(opts ...DBOption) (model.Host, error) {
var host model.Host
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&host).Error
return host, err
}
func (h *HostRepo) GetList(opts ...DBOption) ([]model.Host, error) {
var hosts []model.Host
db := global.DB.Model(&model.Host{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&hosts).Error
return hosts, err
}
func (h *HostRepo) Page(page, size int, opts ...DBOption) (int64, []model.Host, error) {
var hosts []model.Host
db := global.DB.Model(&model.Host{})
for _, opt := range opts {
db = opt(db)
}
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&hosts).Error
return count, hosts, err
}
func (h *HostRepo) WithByInfo(info string) DBOption {
return func(g *gorm.DB) *gorm.DB {
if len(info) == 0 {
return g
}
infoStr := "%" + info + "%"
return g.Where("name LIKE ? OR addr LIKE ?", infoStr, infoStr)
}
}
func (h *HostRepo) WithByPort(port uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("port = ?", port)
}
}
func (h *HostRepo) WithByUser(user string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("user = ?", user)
}
}
func (h *HostRepo) Create(host *model.Host) error {
return global.DB.Create(host).Error
}
func (h *HostRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.Host{}).Where("id = ?", id).Updates(vars).Error
}
func (h *HostRepo) UpdateGroup(group, newGroup uint) error {
return global.DB.Model(&model.Host{}).Where("group_id = ?", group).Updates(map[string]interface{}{"group_id": newGroup}).Error
}
func (h *HostRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.Host{}).Error
}
func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) {
var firewall model.Firewall
db := global.DB
@@ -126,16 +38,12 @@ func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) {
return firewall, err
}
func (h *HostRepo) ListFirewallRecord(opts ...DBOption) ([]model.Firewall, error) {
var firewalls []model.Firewall
db := global.DB
for _, opt := range opts {
db = opt(db)
func (h *HostRepo) ListFirewallRecord() ([]model.Firewall, error) {
var datas []model.Firewall
if err := global.DB.Find(&datas).Error; err != nil {
return datas, nil
}
if err := global.DB.Find(&firewalls).Error; err != nil {
return firewalls, nil
}
return firewalls, nil
return datas, nil
}
func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
@@ -143,27 +51,16 @@ func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
return global.DB.Save(firewall).Error
}
var data model.Firewall
switch firewall.Type {
case "port":
_ = global.DB.Where("type = ? AND dst_port = ? AND protocol = ? AND src_ip = ? AND strategy = ?", "port",
firewall.DstPort,
firewall.Protocol,
firewall.SrcIP,
firewall.Strategy,
).First(&data).Error
case "ip":
_ = global.DB.Where("type = ? AND src_ip = ? AND strategy = ?", "address", firewall.SrcIP, firewall.Strategy).First(&data)
default:
_ = global.DB.Where("type = ? AND chain = ? AND src_port = ? AND dst_port = ? AND protocol = ? AND src_ip = ? AND dst_ip = ? AND strategy = ?",
firewall.Type,
firewall.Chain,
firewall.SrcPort,
firewall.DstPort,
firewall.Protocol,
firewall.SrcIP,
firewall.DstIP,
firewall.Strategy,
).First(&data).Error
if firewall.Type == "port" {
_ = global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
} else {
_ = global.DB.Where("type = ? AND address = ? AND strategy = ?", "address", firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
}
return global.DB.Save(firewall).Error
}
@@ -172,6 +69,10 @@ func (h *HostRepo) DeleteFirewallRecordByID(id uint) error {
return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error
}
func (h *HostRepo) DeleteFirewallRecord(fType, port, protocol, address, strategy string) error {
return global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete(&model.Firewall{}).Error
}
func (u *HostRepo) GetCert(opts ...DBOption) (model.RootCert, error) {
var cert model.RootCert
db := global.DB
@@ -250,9 +151,3 @@ func (u *HostRepo) SyncCert(data []model.RootCert) error {
tx.Commit()
return nil
}
func (u *HostRepo) WithByChain(chain string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("chain = ?", chain)
}
}
-27
View File
@@ -5,27 +5,21 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"gorm.io/gorm"
)
type MonitorRepo struct{}
type IMonitorRepo interface {
GetBase(opts ...DBOption) ([]model.MonitorBase, error)
GetGPU(opts ...DBOption) ([]model.MonitorGPU, error)
GetIO(opts ...DBOption) ([]model.MonitorIO, error)
GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error)
CreateMonitorBase(model model.MonitorBase) error
BatchCreateMonitorGPU(list []model.MonitorGPU) error
BatchCreateMonitorIO(ioList []model.MonitorIO) error
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
DelMonitorBase(timeForDelete time.Time) error
DelMonitorGPU(timeForDelete time.Time) error
DelMonitorIO(timeForDelete time.Time) error
DelMonitorNet(timeForDelete time.Time) error
WithByProductName(name string) DBOption
}
func NewIMonitorRepo() IMonitorRepo {
@@ -59,22 +53,10 @@ func (u *MonitorRepo) GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, erro
err := db.Find(&data).Error
return data, err
}
func (u *MonitorRepo) GetGPU(opts ...DBOption) ([]model.MonitorGPU, error) {
var data []model.MonitorGPU
db := global.GPUMonitorDB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&data).Error
return data, err
}
func (u *MonitorRepo) CreateMonitorBase(model model.MonitorBase) error {
return global.MonitorDB.Create(&model).Error
}
func (s *MonitorRepo) BatchCreateMonitorGPU(list []model.MonitorGPU) error {
return global.GPUMonitorDB.CreateInBatches(&list, len(list)).Error
}
func (u *MonitorRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
}
@@ -90,12 +72,3 @@ func (u *MonitorRepo) DelMonitorIO(timeForDelete time.Time) error {
func (u *MonitorRepo) DelMonitorNet(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
}
func (s *MonitorRepo) DelMonitorGPU(timeForDelete time.Time) error {
return global.GPUMonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorGPU{}).Error
}
func (s *MonitorRepo) WithByProductName(name string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("product_name = ?", name)
}
}
+26 -40
View File
@@ -2,6 +2,7 @@ package repo
import (
"errors"
"time"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
@@ -18,14 +19,13 @@ type ISettingRepo interface {
Update(key, value string) error
WithByKey(key string) DBOption
CreateMonitorBase(model model.MonitorBase) error
BatchCreateMonitorIO(ioList []model.MonitorIO) error
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
DelMonitorBase(timeForDelete time.Time) error
DelMonitorIO(timeForDelete time.Time) error
DelMonitorNet(timeForDelete time.Time) error
UpdateOrCreate(key, value string) error
GetDescription(opts ...DBOption) (model.CommonDescription, error)
GetDescriptionList(opts ...DBOption) ([]model.CommonDescription, error)
CreateDescription(data *model.CommonDescription) error
UpdateDescription(id string, val map[string]interface{}) error
DelDescription(id string) error
WithByDescriptionID(id string) DBOption
}
func NewISettingRepo() ISettingRepo {
@@ -78,6 +78,25 @@ func (s *SettingRepo) Update(key, value string) error {
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
}
func (s *SettingRepo) CreateMonitorBase(model model.MonitorBase) error {
return global.MonitorDB.Create(&model).Error
}
func (s *SettingRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
}
func (s *SettingRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error {
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
}
func (s *SettingRepo) DelMonitorBase(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
}
func (s *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
}
func (s *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
}
func (s *SettingRepo) UpdateOrCreate(key, value string) error {
var setting model.Setting
result := global.DB.Where("key = ?", key).First(&setting)
@@ -89,36 +108,3 @@ func (s *SettingRepo) UpdateOrCreate(key, value string) error {
}
return global.DB.Model(&setting).UpdateColumn("value", value).Error
}
func (s *SettingRepo) GetDescriptionList(opts ...DBOption) ([]model.CommonDescription, error) {
var lists []model.CommonDescription
db := global.DB.Model(&model.CommonDescription{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&lists).Error
return lists, err
}
func (s *SettingRepo) GetDescription(opts ...DBOption) (model.CommonDescription, error) {
var data model.CommonDescription
db := global.DB.Model(&model.CommonDescription{})
for _, opt := range opts {
db = opt(db)
}
err := db.First(&data).Error
return data, err
}
func (s *SettingRepo) CreateDescription(data *model.CommonDescription) error {
return global.DB.Create(data).Error
}
func (s *SettingRepo) UpdateDescription(id string, val map[string]interface{}) error {
return global.DB.Model(&model.CommonDescription{}).Where("id = ?", id).Updates(val).Error
}
func (s *SettingRepo) DelDescription(id string) error {
return global.DB.Where("id = ?", id).Delete(&model.CommonDescription{}).Error
}
func (s *SettingRepo) WithByDescriptionID(id string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id = ?", id)
}
}
-875
View File
@@ -1,875 +0,0 @@
package service
import (
"context"
"encoding/json"
"fmt"
"os"
"path"
"sort"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/model"
providercatalog "github.com/1Panel-dev/1Panel/agent/app/provider"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
terminalai "github.com/1Panel-dev/1Panel/agent/utils/terminal/ai"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"gorm.io/gorm"
)
type IAgentService interface {
Create(req dto.AgentCreateReq) (*dto.AgentItem, error)
Page(req dto.SearchWithPage) (int64, []dto.AgentItem, error)
Delete(req dto.AgentDeleteReq) error
ResetToken(req dto.AgentTokenResetReq) error
UpdateModelConfig(req dto.AgentModelConfigUpdateReq) error
GetOverview(req dto.AgentOverviewReq) (*dto.AgentOverview, error)
GetProviders() ([]dto.ProviderInfo, error)
GetSecurityConfig(req dto.AgentIDReq) (*dto.AgentSecurityConfig, error)
UpdateSecurityConfig(req dto.AgentSecurityConfigUpdateReq) error
GetOtherConfig(req dto.AgentIDReq) (*dto.AgentOtherConfig, error)
UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error
GetConfigFile(req dto.AgentConfigFileReq) (*dto.AgentConfigFile, error)
UpdateConfigFile(req dto.AgentConfigFileUpdateReq) error
ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, error)
SearchSkills(req dto.AgentSkillSearchReq) ([]dto.AgentSkillSearchItem, error)
UpdateSkill(req dto.AgentSkillUpdateReq) error
InstallSkill(req dto.AgentSkillInstallReq) error
CreateAccount(req dto.AgentAccountCreateReq) error
UpdateAccount(req dto.AgentAccountUpdateReq) error
SyncAgentsByAccount(account *model.AgentAccount) error
PageAccounts(req dto.AgentAccountSearch) (int64, []dto.AgentAccountInfo, error)
GetAccountModels(req dto.AgentAccountModelReq) ([]dto.AgentAccountModel, error)
CreateAccountModel(req dto.AgentAccountModelCreateReq) error
UpdateAccountModel(req dto.AgentAccountModelUpdateReq) error
DeleteAccountModel(req dto.AgentAccountModelDeleteReq) error
VerifyAccount(req dto.AgentAccountVerifyReq) error
DeleteAccount(req dto.AgentAccountDeleteReq) error
GetFeishuConfig(req dto.AgentFeishuConfigReq) (*dto.AgentFeishuConfig, error)
UpdateFeishuConfig(req dto.AgentFeishuConfigUpdateReq) error
GetTelegramConfig(req dto.AgentTelegramConfigReq) (*dto.AgentTelegramConfig, error)
UpdateTelegramConfig(req dto.AgentTelegramConfigUpdateReq) error
GetDiscordConfig(req dto.AgentIDReq) (*dto.AgentDiscordConfig, error)
UpdateDiscordConfig(req dto.AgentDiscordConfigUpdateReq) error
GetWecomConfig(req dto.AgentIDReq) (*dto.AgentWecomConfig, error)
UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error
GetDingTalkConfig(req dto.AgentIDReq) (*dto.AgentDingTalkConfig, error)
UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error
LoginWeixinChannel(req dto.AgentWeixinLoginReq) error
GetQQBotConfig(req dto.AgentIDReq) (*dto.AgentQQBotConfig, error)
UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error
InstallPlugin(req dto.AgentPluginInstallReq) error
CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPluginStatus, error)
ApproveChannelPairing(req dto.AgentChannelPairingApproveReq) error
}
const (
defaultBrowserExecutablePath = "/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome"
defaultBrowserProfile = "openclaw"
defaultUserTimezone = "Asia/Shanghai"
defaultToolsProfile = "full"
defaultToolsSessionVisibility = "all"
maxCommunityAIAgents = int64(5)
openclawPluginBaseDir = "/home/node/.openclaw/extensions"
openclawPluginPackageTmpDir = "/tmp/openclaw-plugin"
openclawManagedSkillsDir = "/home/node/.openclaw/skills"
openclawGatewayPort = 18789
openclawAllowedOriginHost = "127.0.0.1"
openclawHTTPSVersion = "2026.3.13"
openclawHTTPVersion = "2026.3.23"
openclawTrustedProxyLoopback = "127.0.0.1/32"
defaultOpenclawNPMRegistry = "https://registry.npmjs.org/"
)
func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
agentType := req.AgentType
if err := checkPortExist(req.WebUIPort); err != nil {
return nil, err
}
if exist, _ := agentRepo.GetFirst(repo.WithByLowerName(req.Name)); exist != nil && exist.ID > 0 {
return nil, buserr.New("ErrNameIsExist")
}
if installs, _ := appInstallRepo.ListBy(context.Background(), repo.WithByLowerName(req.Name)); len(installs) > 0 {
return nil, buserr.New("ErrNameIsExist")
}
if !xpack.IsXpack() {
count, _, err := agentRepo.Page(1, 1)
if err != nil {
return nil, err
}
if count >= maxCommunityAIAgents {
return nil, buserr.WithMap("ErrAgentLimitReached", map[string]interface{}{"max": maxCommunityAIAgents}, nil)
}
}
app, err := appRepo.GetFirst(appRepo.WithKey(agentType))
if err != nil || app.ID == 0 {
return nil, buserr.New("ErrRecordNotFound")
}
detail, err := appDetailRepo.GetFirst(appDetailRepo.WithAppId(app.ID), appDetailRepo.WithVersion(req.AppVersion))
if err != nil || detail.ID == 0 {
return nil, buserr.New("ErrRecordNotFound")
}
provider := ""
baseURL := ""
apiType := ""
maxTokens := 0
contextWindow := 0
apiKey := ""
runtimeModel := ""
accountID := uint(0)
token := ""
configPath := ""
storedModel := ""
var allowedOrigins []string
var account *model.AgentAccount
var installHooks *appInstallHooks
if agentType == constant.AppOpenclaw {
var err error
allowedOrigins, err = normalizeAllowedOrigins(req.AllowedOrigins)
if err != nil {
return nil, err
}
if len(allowedOrigins) == 0 {
return nil, fmt.Errorf("allowed origins is required")
}
if req.AccountID == 0 {
return nil, buserr.New("ErrAgentAccountRequired")
}
account, err = agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return nil, err
}
if !account.Verified {
return nil, buserr.New("ErrAgentAccountNotVerified")
}
provider = account.Provider
baseURL = strings.TrimSpace(account.BaseURL)
resolvedRuntime, err := resolveOpenclawAccountModelRuntimeByID(account, req.Model)
if err != nil {
return nil, err
}
storedModel = resolvedRuntime.StoredModel
apiType = resolvedRuntime.APIType
maxTokens = resolvedRuntime.MaxTokens
contextWindow = resolvedRuntime.ContextWindow
runtimeModel = resolvedRuntime.PrimaryModel
apiKey = account.APIKey
accountID = account.ID
token = strings.TrimSpace(req.Token)
if token == "" {
token = generateToken()
}
installHooks = &appInstallHooks{
AfterCopyData: func(appInstall *model.AppInstall) error {
return prepareOpenclawInstallFiles(appInstall, account, storedModel, token, allowedOrigins)
},
}
}
params := map[string]interface{}{
constant.CPUS: "0",
constant.MemoryLimit: "0",
constant.HostIP: "",
}
if agentType == constant.AppOpenclaw {
if isOpenclawHTTPSWindowVersion(detail.Version) {
params["PANEL_APP_PORT_HTTPS"] = req.WebUIPort
} else {
params["PANEL_APP_PORT_HTTP"] = req.WebUIPort
}
if allowedOrigin := firstAllowedOrigin(allowedOrigins); allowedOrigin != "" {
params["ALLOWED_ORIGIN"] = allowedOrigin
}
params["PROVIDER"] = provider
params["MODEL"] = runtimeModel
params["API_TYPE"] = apiType
params["MAX_TOKENS"] = maxTokens
params["CONTEXT_WINDOW"] = contextWindow
params["BASE_URL"] = baseURL
params["API_KEY"] = apiKey
params["OPENCLAW_GATEWAY_TOKEN"] = token
} else {
params["PANEL_APP_PORT_HTTP"] = req.WebUIPort
}
if req.EditCompose && strings.TrimSpace(req.DockerCompose) == "" {
return nil, buserr.New("ErrAgentComposeRequired")
}
installReq := request.AppInstallCreate{
AppDetailId: detail.ID,
Name: req.Name,
Params: params,
TaskID: req.TaskID,
AppContainerConfig: request.AppContainerConfig{
Advanced: req.Advanced,
ContainerName: req.ContainerName,
AllowPort: req.AllowPort,
SpecifyIP: req.SpecifyIP,
RestartPolicy: req.RestartPolicy,
CpuQuota: req.CpuQuota,
MemoryLimit: req.MemoryLimit,
MemoryUnit: req.MemoryUnit,
PullImage: req.PullImage,
EditCompose: req.EditCompose,
DockerCompose: req.DockerCompose,
},
}
appInstall, err := AppService{}.installWithHooks(installReq, false, installHooks)
if err != nil {
return nil, err
}
if agentType == constant.AppOpenclaw {
configPath = path.Join(appInstall.GetPath(), "data", "conf", "openclaw.json")
}
agent := &model.Agent{
Name: req.Name,
AgentType: agentType,
Provider: provider,
Model: storedModel,
APIType: apiType,
MaxTokens: maxTokens,
ContextWindow: contextWindow,
BaseURL: baseURL,
APIKey: apiKey,
Token: token,
Status: appInstall.Status,
Message: appInstall.Message,
AppInstallID: appInstall.ID,
AccountID: accountID,
ConfigPath: configPath,
}
if err := agentRepo.Create(agent); err != nil {
return nil, err
}
item := buildAgentItem(agent, appInstall, nil)
return &item, nil
}
func (a AgentService) Page(req dto.SearchWithPage) (int64, []dto.AgentItem, error) {
var opts []repo.DBOption
if strings.TrimSpace(req.Info) != "" {
opts = append(opts, repo.WithByLikeName(req.Info))
}
count, list, err := agentRepo.Page(req.Page, req.PageSize, opts...)
if err != nil {
return 0, nil, err
}
items := make([]dto.AgentItem, 0, len(list))
for _, item := range list {
appInstall, _ := appInstallRepo.GetFirst(repo.WithByID(item.AppInstallID))
envMap := readInstallEnv(appInstall.Env)
agentItem := buildAgentItem(&item, &appInstall, envMap)
agentItem.Upgradable = checkAgentUpgradable(appInstall)
items = append(items, agentItem)
}
return count, items, nil
}
func (a AgentService) Delete(req dto.AgentDeleteReq) error {
agent, err := agentRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
}
if agent.AppInstallID == 0 {
return agentRepo.DeleteByID(agent.ID)
}
operate := request.AppInstalledOperate{
InstallId: agent.AppInstallID,
Operate: constant.Delete,
TaskID: req.TaskID,
ForceDelete: req.ForceDelete,
}
if err := NewIAppInstalledService().Operate(operate); err != nil {
return err
}
return nil
}
func (a AgentService) ResetToken(req dto.AgentTokenResetReq) error {
agent, err := loadOpenclawAgentByID(req.ID)
if err != nil {
return err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return err
}
newToken := generateToken()
if newToken == "" {
return fmt.Errorf("generate token failed")
}
gatewayMap := ensureChildMap(conf, "gateway")
authMap := ensureChildMap(gatewayMap, "auth")
if _, ok := authMap["mode"]; !ok {
authMap["mode"] = "token"
}
authMap["token"] = newToken
if err := writeOpenclawConfigRaw(agent.ConfigPath, conf); err != nil {
return err
}
agent.Token = newToken
return agentRepo.Save(agent)
}
func (a AgentService) UpdateModelConfig(req dto.AgentModelConfigUpdateReq) error {
agent, err := loadOpenclawAgentByID(req.AgentID)
if err != nil {
return err
}
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return err
}
resolvedRuntime, err := resolveOpenclawAccountModelRuntimeByID(account, req.Model)
if err != nil {
return err
}
modelName := resolvedRuntime.StoredModel
apiType, maxTokens, contextWindow := resolvedRuntime.APIType, resolvedRuntime.MaxTokens, resolvedRuntime.ContextWindow
confDir := path.Dir(agent.ConfigPath)
if err := writeOpenclawConfig(confDir, account, modelName, agent.Token, nil); err != nil {
return err
}
agent.Provider = account.Provider
agent.Model = modelName
agent.APIType = apiType
agent.MaxTokens = maxTokens
agent.ContextWindow = contextWindow
agent.BaseURL = account.BaseURL
agent.APIKey = account.APIKey
agent.AccountID = account.ID
return agentRepo.Save(agent)
}
func (a AgentService) GetProviders() ([]dto.ProviderInfo, error) {
definitions := providercatalog.All()
providers := make([]dto.ProviderInfo, 0, len(definitions))
for key, def := range definitions {
models := make([]dto.ProviderModelInfo, 0, len(def.Models))
for _, item := range def.Models {
models = append(models, dto.ProviderModelInfo{
ID: item.ID,
Name: item.Name,
ContextWindow: item.ContextWindow,
MaxTokens: item.MaxTokens,
Reasoning: item.Reasoning,
Input: append([]string(nil), item.Input...),
})
}
providers = append(providers, dto.ProviderInfo{
Sort: def.Sort,
Provider: key,
DisplayName: def.DisplayName,
BaseURL: def.DefaultBaseURL,
Models: models,
})
}
sort.Slice(providers, func(i, j int) bool {
return providers[i].Sort < providers[j].Sort
})
return providers, nil
}
func (a AgentService) CreateAccount(req dto.AgentAccountCreateReq) error {
provider := req.Provider
if exist, _ := agentAccountRepo.GetFirst(repo.WithByProvider(provider), repo.WithByName(req.Name)); exist != nil && exist.ID > 0 {
return buserr.New("ErrRecordExist")
}
resolvedInput, err := resolveAgentAccountInput(provider, req.APIKey, req.BaseURL)
if err != nil {
return err
}
account := &model.AgentAccount{
Provider: resolvedInput.Provider,
Name: req.Name,
APIKey: resolvedInput.APIKey,
RememberAPIKey: req.RememberAPIKey,
BaseURL: resolvedInput.BaseURL,
APIType: req.APIType,
Verified: true,
Remark: req.Remark,
}
initialModels, err := buildInitialAgentAccountModels(account, req.Models)
if err != nil {
return err
}
if err := global.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(account).Error; err != nil {
return err
}
if len(initialModels) == 0 {
return nil
}
return replacePersistedAgentAccountModelsWithTx(tx, account.ID, initialModels)
}); err != nil {
return err
}
asyncReportAIProviderInstall(provider)
return nil
}
func (a AgentService) UpdateAccount(req dto.AgentAccountUpdateReq) error {
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
}
provider := account.Provider
resolvedInput, err := resolveAgentAccountInput(provider, req.APIKey, req.BaseURL)
if err != nil {
return err
}
account.Name = req.Name
account.APIKey = resolvedInput.APIKey
account.RememberAPIKey = req.RememberAPIKey
account.BaseURL = resolvedInput.BaseURL
account.APIType = req.APIType
account.Remark = req.Remark
account.Verified = true
if err := global.DB.Save(account).Error; err != nil {
return err
}
terminalai.InvalidateTerminalRuntimeCache()
if req.SyncAgents {
if err := a.syncAgentsByAccount(account); err != nil {
return err
}
}
return nil
}
func (a AgentService) PageAccounts(req dto.AgentAccountSearch) (int64, []dto.AgentAccountInfo, error) {
var opts []repo.DBOption
if strings.TrimSpace(req.Provider) != "" {
opts = append(opts, repo.WithByProvider(req.Provider))
}
if strings.TrimSpace(req.Name) != "" {
opts = append(opts, repo.WithByLikeName(req.Name))
}
count, list, err := agentAccountRepo.Page(req.Page, req.PageSize, opts...)
if err != nil {
return 0, nil, err
}
items := make([]dto.AgentAccountInfo, 0, len(list))
for _, item := range list {
apiKey := ""
if item.RememberAPIKey {
apiKey = item.APIKey
}
items = append(items, dto.AgentAccountInfo{
ID: item.ID,
Provider: item.Provider,
ProviderName: providercatalog.DisplayName(item.Provider),
Name: item.Name,
APIKey: apiKey,
RememberAPIKey: item.RememberAPIKey,
BaseURL: item.BaseURL,
Models: nil,
APIType: item.APIType,
Verified: item.Verified,
Remark: item.Remark,
CreatedAt: item.CreatedAt,
})
}
for i := range items {
models, err := loadAgentAccountModels(&list[i])
if err != nil {
return 0, nil, err
}
items[i].Models = models
}
return count, items, nil
}
func (a AgentService) GetAccountModels(req dto.AgentAccountModelReq) ([]dto.AgentAccountModel, error) {
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return nil, err
}
return loadAgentAccountModels(account)
}
func (a AgentService) CreateAccountModel(req dto.AgentAccountModelCreateReq) error {
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return err
}
models, err := loadAgentAccountModels(account)
if err != nil {
return err
}
nextModel := cloneAgentAccountModel(req.Model)
if _, ok := findAgentAccountModelForProvider(account.Provider, models, nextModel.ID); ok {
return buserr.New("ErrRecordExist")
}
inputPayload, err := json.Marshal(nextModel.Input)
if err != nil {
return err
}
sortOrder := len(models) + 1
record := &model.AgentAccountModel{
AccountID: account.ID,
Model: nextModel.ID,
Name: nextModel.Name,
ContextWindow: nextModel.ContextWindow,
MaxTokens: nextModel.MaxTokens,
Reasoning: nextModel.Reasoning,
Input: string(inputPayload),
SortOrder: sortOrder,
}
if err := agentAccountModelRepo.Create(record); err != nil {
return err
}
return a.syncAgentsByAccount(account)
}
func (a AgentService) UpdateAccountModel(req dto.AgentAccountModelUpdateReq) error {
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return err
}
record, err := agentAccountModelRepo.GetFirst(repo.WithByID(req.Model.RecordID), repo.WithByAccountID(req.AccountID))
if err != nil {
return err
}
models, err := loadAgentAccountModels(account)
if err != nil {
return err
}
nextModel := cloneAgentAccountModel(req.Model)
for _, item := range models {
if item.RecordID == req.Model.RecordID {
continue
}
if sameProviderModelID(account.Provider, item.ID, nextModel.ID) {
return buserr.New("ErrRecordExist")
}
}
nextModels := make([]dto.AgentAccountModel, 0, len(models))
for _, item := range models {
if item.RecordID == req.Model.RecordID {
nextModels = append(nextModels, nextModel)
continue
}
nextModels = append(nextModels, item)
}
if err := ensureAccountModelsNotBound(account, nextModels); err != nil {
return err
}
inputPayload, err := json.Marshal(nextModel.Input)
if err != nil {
return err
}
record.Model = nextModel.ID
record.Name = nextModel.Name
record.ContextWindow = nextModel.ContextWindow
record.MaxTokens = nextModel.MaxTokens
record.Reasoning = nextModel.Reasoning
record.Input = string(inputPayload)
if err := agentAccountModelRepo.Save(record); err != nil {
return err
}
terminalai.InvalidateTerminalRuntimeCache()
return a.syncAgentsByAccount(account)
}
func (a AgentService) DeleteAccountModel(req dto.AgentAccountModelDeleteReq) error {
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return err
}
if _, err := agentAccountModelRepo.GetFirst(repo.WithByID(req.RecordID), repo.WithByAccountID(req.AccountID)); err != nil {
return err
}
models, err := loadAgentAccountModels(account)
if err != nil {
return err
}
nextModels := make([]dto.AgentAccountModel, 0, len(models))
for _, item := range models {
if item.RecordID == req.RecordID {
continue
}
nextModels = append(nextModels, item)
}
if err := ensureAccountModelsNotBound(account, nextModels); err != nil {
return err
}
if err := agentAccountModelRepo.DeleteByID(req.RecordID); err != nil {
return err
}
if err := compactPersistedAgentAccountModelSortOrder(req.AccountID); err != nil {
return err
}
terminalai.InvalidateTerminalRuntimeCache()
return a.syncAgentsByAccount(account)
}
func (a AgentService) SyncAgentsByAccount(account *model.AgentAccount) error {
if account == nil || account.ID == 0 {
return nil
}
return a.syncAgentsByAccount(account)
}
func (a AgentService) VerifyAccount(req dto.AgentAccountVerifyReq) error {
_, err := resolveAgentAccountInput(req.Provider, req.APIKey, req.BaseURL)
return err
}
func (a AgentService) DeleteAccount(req dto.AgentAccountDeleteReq) error {
if exists, _ := agentRepo.GetFirst(repo.WithByAccountID(req.ID)); exists != nil && exists.ID > 0 {
return buserr.New("ErrAgentAccountBound")
}
if err := agentAccountModelRepo.Delete(repo.WithByAccountID(req.ID)); err != nil {
return err
}
terminalai.InvalidateTerminalRuntimeCache()
return agentAccountRepo.DeleteByID(req.ID)
}
func (a AgentService) GetSecurityConfig(req dto.AgentIDReq) (*dto.AgentSecurityConfig, error) {
agent, _, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return nil, err
}
result := extractSecurityConfig(conf)
return &result, nil
}
func (a AgentService) UpdateSecurityConfig(req dto.AgentSecurityConfigUpdateReq) error {
agent, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return err
}
allowedOrigins, err := normalizeAllowedOrigins(req.AllowedOrigins)
if err != nil {
return err
}
if len(allowedOrigins) == 0 {
return fmt.Errorf("allowed origins is required")
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return err
}
setSecurityConfig(conf, dto.AgentSecurityConfig{AllowedOrigins: allowedOrigins})
if err := writeOpenclawConfigRaw(agent.ConfigPath, conf); err != nil {
return err
}
if err := syncOpenclawAllowedOriginEnv(install, allowedOrigins); err != nil {
return err
}
return appInstallRepo.Save(context.Background(), install)
}
func (a AgentService) GetOtherConfig(req dto.AgentIDReq) (*dto.AgentOtherConfig, error) {
agent, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return nil, err
}
result := extractOtherConfig(conf)
npmRegistry, err := getOpenclawNPMRegistry(install.ContainerName)
if err == nil {
result.NPMRegistry = npmRegistry
}
return &result, nil
}
func (a AgentService) UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error {
agent, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return err
}
if err := ensureContainerRunning(install.ContainerName); err != nil {
return err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return err
}
setOtherConfig(conf, dto.AgentOtherConfig{
UserTimezone: strings.TrimSpace(req.UserTimezone),
BrowserEnabled: req.BrowserEnabled,
})
if err := writeOpenclawConfigRaw(agent.ConfigPath, conf); err != nil {
return err
}
return setOpenclawNPMRegistry(install.ContainerName, req.NPMRegistry)
}
func (a AgentService) GetConfigFile(req dto.AgentConfigFileReq) (*dto.AgentConfigFile, error) {
agent, _, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
content, err := os.ReadFile(agent.ConfigPath)
if err != nil {
return nil, err
}
return &dto.AgentConfigFile{Content: string(content)}, nil
}
func (a AgentService) UpdateConfigFile(req dto.AgentConfigFileUpdateReq) error {
agent, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return err
}
var payload interface{}
if err := json.Unmarshal([]byte(req.Content), &payload); err != nil {
return err
}
info, err := os.Stat(agent.ConfigPath)
if err != nil {
return err
}
if err := os.WriteFile(agent.ConfigPath, []byte(req.Content), info.Mode()); err != nil {
return err
}
return NewIAppInstalledService().Operate(request.AppInstalledOperate{
InstallId: install.ID,
Operate: constant.Restart,
})
}
func getOpenclawNPMRegistry(containerName string) (string, error) {
registry, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut("docker exec %s npm get registry", 20*time.Second, containerName)
if err != nil {
return "", err
}
registry = strings.TrimSpace(registry)
if registry == "" {
return defaultOpenclawNPMRegistry, nil
}
return registry, nil
}
func setOpenclawNPMRegistry(containerName, registry string) error {
return cmd.RunDefaultBashCf("docker exec %s npm set registry %q", containerName, registry)
}
func (a AgentService) loadAgentAndInstall(agentID uint) (*model.Agent, *model.AppInstall, error) {
agent, err := agentRepo.GetFirst(repo.WithByID(agentID))
if err != nil {
return nil, nil, err
}
if agent.AppInstallID == 0 {
return nil, nil, buserr.New("ErrRecordNotFound")
}
install, err := appInstallRepo.GetFirst(repo.WithByID(agent.AppInstallID))
if err != nil {
return nil, nil, err
}
return agent, &install, nil
}
func (a AgentService) loadOpenclawAgentAndInstall(agentID uint) (*model.Agent, *model.AppInstall, error) {
agent, install, err := a.loadAgentAndInstall(agentID)
if err != nil {
return nil, nil, err
}
if agent.AgentType == constant.AppCopaw {
return nil, nil, fmt.Errorf("copaw does not support")
}
return agent, install, nil
}
func (a AgentService) loadAgentConfig(agentID uint) (*model.Agent, *model.AppInstall, map[string]interface{}, error) {
agent, install, err := a.loadAgentAndInstall(agentID)
if err != nil {
return nil, nil, nil, err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return nil, nil, nil, err
}
return agent, install, conf, nil
}
func (a AgentService) loadOpenclawAgentConfig(agentID uint) (*model.Agent, *model.AppInstall, map[string]interface{}, error) {
agent, install, conf, err := a.loadAgentConfig(agentID)
if err != nil {
return nil, nil, nil, err
}
if agent.AgentType == constant.AppCopaw {
return nil, nil, nil, fmt.Errorf("copaw does not support")
}
return agent, install, conf, nil
}
func (a AgentService) mutateAgentConfig(agentID uint, fn func(agent *model.Agent, install *model.AppInstall, conf map[string]interface{}) error) error {
agent, install, conf, err := a.loadAgentConfig(agentID)
if err != nil {
return err
}
if err := fn(agent, install, conf); err != nil {
return err
}
return writeOpenclawConfigRaw(agent.ConfigPath, conf)
}
func (a AgentService) syncAgentsByAccount(account *model.AgentAccount) error {
agents, err := agentRepo.List(repo.WithByAccountID(account.ID))
if err != nil {
return err
}
accountModels, err := loadAgentAccountModels(account)
if err != nil {
return err
}
if len(accountModels) == 0 {
return nil
}
baseURL := resolveAccountBaseURL(account)
for _, agent := range agents {
confDir := path.Dir(agent.ConfigPath)
modelName := strings.TrimSpace(agent.Model)
var selectedAccountModel dto.AgentAccountModel
if modelName != "" {
selectedAccountModel, err = requireAgentAccountModelForProvider(account.Provider, accountModels, modelName)
if err != nil {
return buserr.WithName("ErrAgentModelInUse", agent.Name)
}
} else {
selectedAccountModel = accountModels[0]
}
resolvedRuntime, err := buildOpenclawAccountModelRuntime(account, selectedAccountModel)
if err != nil {
return err
}
modelName = resolvedRuntime.StoredModel
apiType, maxTokens, contextWindow := resolvedRuntime.APIType, resolvedRuntime.MaxTokens, resolvedRuntime.ContextWindow
if err := writeOpenclawConfig(confDir, account, modelName, agent.Token, nil); err != nil {
return err
}
agent.BaseURL = baseURL
agent.APIKey = account.APIKey
agent.Provider = account.Provider
agent.Model = modelName
agent.APIType = apiType
agent.MaxTokens = maxTokens
agent.ContextWindow = contextWindow
_ = agentRepo.Save(&agent)
}
return nil
}
-619
View File
@@ -1,619 +0,0 @@
package service
import (
"fmt"
"path"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
)
func (a AgentService) GetFeishuConfig(req dto.AgentFeishuConfigReq) (*dto.AgentFeishuConfig, error) {
_, _, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractFeishuConfig(conf)
return &result, nil
}
func (a AgentService) UpdateFeishuConfig(req dto.AgentFeishuConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setFeishuConfig(conf, dto.AgentFeishuConfig{
Enabled: req.Enabled,
DmPolicy: req.DmPolicy,
BotName: req.BotName,
AppID: req.AppID,
AppSecret: req.AppSecret,
})
setFeishuPluginEnabled(conf, req.Enabled)
return nil
})
}
func (a AgentService) GetTelegramConfig(req dto.AgentTelegramConfigReq) (*dto.AgentTelegramConfig, error) {
_, _, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractTelegramConfig(conf)
return &result, nil
}
func (a AgentService) UpdateTelegramConfig(req dto.AgentTelegramConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setTelegramConfig(conf, dto.AgentTelegramConfig{
Enabled: req.Enabled,
DmPolicy: req.DmPolicy,
BotToken: req.BotToken,
Proxy: req.Proxy,
})
return nil
})
}
func (a AgentService) GetDiscordConfig(req dto.AgentIDReq) (*dto.AgentDiscordConfig, error) {
_, _, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractDiscordConfig(conf)
return &result, nil
}
func (a AgentService) UpdateDiscordConfig(req dto.AgentDiscordConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setDiscordConfig(conf, dto.AgentDiscordConfig{
Enabled: req.Enabled,
DmPolicy: req.DmPolicy,
GroupPolicy: req.GroupPolicy,
Token: req.Token,
Proxy: req.Proxy,
})
return nil
})
}
func (a AgentService) GetQQBotConfig(req dto.AgentIDReq) (*dto.AgentQQBotConfig, error) {
_, install, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractQQBotConfig(conf)
installed, _ := checkPluginInstalled(install.ContainerName, "qqbot")
result.Installed = installed
return &result, nil
}
func (a AgentService) UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setQQBotConfig(conf, dto.AgentQQBotConfig{
Enabled: req.Enabled,
AppID: req.AppID,
ClientSecret: req.ClientSecret,
})
return nil
})
}
func (a AgentService) GetWecomConfig(req dto.AgentIDReq) (*dto.AgentWecomConfig, error) {
_, install, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractWecomConfig(conf)
installed, _ := checkPluginInstalled(install.ContainerName, "wecom")
result.Installed = installed
return &result, nil
}
func (a AgentService) UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setWecomConfig(conf, dto.AgentWecomConfig{
Enabled: req.Enabled,
DmPolicy: req.DmPolicy,
BotID: req.BotID,
Secret: req.Secret,
})
return nil
})
}
func (a AgentService) GetDingTalkConfig(req dto.AgentIDReq) (*dto.AgentDingTalkConfig, error) {
_, install, conf, err := a.loadAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
result := extractDingTalkConfig(conf)
installed, _ := checkPluginInstalled(install.ContainerName, "dingtalk")
result.Installed = installed
return &result, nil
}
func (a AgentService) UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error {
return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error {
setDingTalkConfig(conf, dto.AgentDingTalkConfig{
Enabled: req.Enabled,
ClientID: req.ClientID,
ClientSecret: req.ClientSecret,
DmPolicy: req.DmPolicy,
AllowFrom: req.AllowFrom,
GroupPolicy: req.GroupPolicy,
GroupAllowFrom: req.GroupAllowFrom,
})
return nil
})
}
func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error {
agent, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return err
}
spec, pluginID, err := resolvePluginMeta(req.Type)
if err != nil {
return err
}
installTask, err := task.NewTaskWithOps(req.Type, task.TaskInstall, task.TaskScopeAI, req.TaskID, req.AgentID)
if err != nil {
return err
}
installTask.AddSubTask("Install OpenClaw plugin", func(t *task.Task) error {
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute))
if req.Type == "qqbot" {
legacyPluginPath := path.Join(openclawPluginBaseDir, "qqbot")
if err := mgr.RunBashCf("docker exec %s test -d %s", install.ContainerName, legacyPluginPath); err == nil {
if err := mgr.Run("docker", "exec", "-i", install.ContainerName, "sh", "-c", "printf 'yes\\n' | openclaw plugins uninstall qqbot"); err != nil {
return err
}
}
}
if err := mgr.Run("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawPluginInstallScript(spec, pluginID)); err != nil {
return err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return err
}
appendPluginAllow(conf, pluginID)
return writeOpenclawConfigRaw(agent.ConfigPath, conf)
}, nil)
go func() {
if err := installTask.Execute(); err != nil {
global.LOG.Errorf("install openclaw plugin failed: %v", err)
}
}()
return nil
}
func (a AgentService) LoginWeixinChannel(req dto.AgentWeixinLoginReq) error {
_, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return err
}
loginTask, err := task.NewTaskWithOps("weixin", task.TaskExec, task.TaskScopeAI, req.TaskID, req.AgentID)
if err != nil {
return err
}
loginTask.AddSubTask("Login OpenClaw Weixin channel", func(t *task.Task) error {
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(30*time.Minute))
return mgr.RunBashCf("docker exec %s openclaw channels login --channel openclaw-weixin", install.ContainerName)
}, nil)
go func() {
if err := loginTask.Execute(); err != nil {
global.LOG.Errorf("login openclaw weixin channel failed: %v", err)
}
}()
return nil
}
func (a AgentService) CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPluginStatus, error) {
_, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
installed, err := checkPluginInstalled(install.ContainerName, req.Type)
if err != nil {
return nil, err
}
return &dto.AgentPluginStatus{Installed: installed}, nil
}
func (a AgentService) ApproveChannelPairing(req dto.AgentChannelPairingApproveReq) error {
_, install, err := a.loadAgentAndInstall(req.AgentID)
if err != nil {
return err
}
if err := cmd.RunDefaultBashCf(
"docker exec %s openclaw pairing approve %s %q",
install.ContainerName,
req.Type,
strings.TrimSpace(req.PairingCode),
); err != nil {
return err
}
return nil
}
func extractFeishuConfig(conf map[string]interface{}) dto.AgentFeishuConfig {
result := dto.AgentFeishuConfig{Enabled: true, DmPolicy: "pairing"}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
feishu, ok := channels["feishu"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := feishu["enabled"].(bool); ok {
result.Enabled = enabled
}
if dmPolicy, ok := feishu["dmPolicy"].(string); ok && strings.TrimSpace(dmPolicy) != "" {
result.DmPolicy = dmPolicy
}
accounts, ok := feishu["accounts"].(map[string]interface{})
if !ok {
return result
}
main, ok := accounts["main"].(map[string]interface{})
if !ok {
return result
}
if appID, ok := main["appId"].(string); ok {
result.AppID = appID
}
if appSecret, ok := main["appSecret"].(string); ok {
result.AppSecret = appSecret
}
if botName, ok := main["botName"].(string); ok {
result.BotName = botName
}
return result
}
func setFeishuConfig(conf map[string]interface{}, config dto.AgentFeishuConfig) {
channels := ensureChildMap(conf, "channels")
feishu := ensureChildMap(channels, "feishu")
feishu["enabled"] = config.Enabled
feishu["dmPolicy"] = config.DmPolicy
accounts := ensureChildMap(feishu, "accounts")
main := ensureChildMap(accounts, "main")
main["appId"] = config.AppID
main["appSecret"] = config.AppSecret
main["botName"] = config.BotName
if strings.EqualFold(config.DmPolicy, "open") {
feishu["allowFrom"] = []string{"*"}
}
}
func setFeishuPluginEnabled(conf map[string]interface{}, enabled bool) {
plugins := ensureChildMap(conf, "plugins")
entries := ensureChildMap(plugins, "entries")
feishu := ensureChildMap(entries, "feishu")
feishu["enabled"] = enabled
}
func extractTelegramConfig(conf map[string]interface{}) dto.AgentTelegramConfig {
result := dto.AgentTelegramConfig{Enabled: true, DmPolicy: "pairing"}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
telegram, ok := channels["telegram"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := telegram["enabled"].(bool); ok {
result.Enabled = enabled
}
if dmPolicy, ok := telegram["dmPolicy"].(string); ok && strings.TrimSpace(dmPolicy) != "" {
result.DmPolicy = dmPolicy
}
if botToken, ok := telegram["botToken"].(string); ok {
result.BotToken = botToken
}
if proxy, ok := telegram["proxy"].(string); ok {
result.Proxy = proxy
}
return result
}
func setTelegramConfig(conf map[string]interface{}, config dto.AgentTelegramConfig) {
channels := ensureChildMap(conf, "channels")
telegram := map[string]interface{}{
"enabled": config.Enabled,
"dmPolicy": config.DmPolicy,
"botToken": config.BotToken,
}
if strings.EqualFold(config.DmPolicy, "open") {
telegram["allowFrom"] = []string{"*"}
}
if strings.TrimSpace(config.Proxy) != "" {
telegram["proxy"] = strings.TrimSpace(config.Proxy)
}
channels["telegram"] = telegram
}
func extractDiscordConfig(conf map[string]interface{}) dto.AgentDiscordConfig {
result := dto.AgentDiscordConfig{Enabled: true, DmPolicy: "pairing", GroupPolicy: "open"}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
discord, ok := channels["discord"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := discord["enabled"].(bool); ok {
result.Enabled = enabled
}
if token, ok := discord["token"].(string); ok {
result.Token = token
}
if groupPolicy, ok := discord["groupPolicy"].(string); ok && strings.TrimSpace(groupPolicy) != "" {
result.GroupPolicy = groupPolicy
}
if proxy, ok := discord["proxy"].(string); ok {
result.Proxy = proxy
}
if policy, ok := discord["dmPolicy"].(string); ok && strings.TrimSpace(policy) != "" {
result.DmPolicy = policy
return result
}
dm, ok := discord["dm"].(map[string]interface{})
if ok {
if policy, ok := dm["policy"].(string); ok && strings.TrimSpace(policy) != "" {
result.DmPolicy = policy
}
}
return result
}
func setDiscordConfig(conf map[string]interface{}, config dto.AgentDiscordConfig) {
channels := ensureChildMap(conf, "channels")
discord := ensureChildMap(channels, "discord")
discord["enabled"] = config.Enabled
discord["token"] = config.Token
discord["dmPolicy"] = config.DmPolicy
discord["groupPolicy"] = config.GroupPolicy
if strings.EqualFold(config.DmPolicy, "open") {
discord["allowFrom"] = []string{"*"}
} else {
delete(discord, "allowFrom")
}
if strings.TrimSpace(config.Proxy) != "" {
discord["proxy"] = strings.TrimSpace(config.Proxy)
} else {
delete(discord, "proxy")
}
delete(discord, "dm")
}
func extractQQBotConfig(conf map[string]interface{}) dto.AgentQQBotConfig {
result := dto.AgentQQBotConfig{Enabled: true}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
qqbot, ok := channels["qqbot"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := qqbot["enabled"].(bool); ok {
result.Enabled = enabled
}
if appID, ok := qqbot["appId"].(string); ok {
result.AppID = appID
}
if clientSecret, ok := qqbot["clientSecret"].(string); ok {
result.ClientSecret = clientSecret
}
return result
}
func extractWecomConfig(conf map[string]interface{}) dto.AgentWecomConfig {
result := dto.AgentWecomConfig{Enabled: true, DmPolicy: "pairing"}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
wecom, ok := channels["wecom"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := wecom["enabled"].(bool); ok {
result.Enabled = enabled
}
if dmPolicy, ok := wecom["dmPolicy"].(string); ok && strings.TrimSpace(dmPolicy) != "" {
result.DmPolicy = strings.TrimSpace(dmPolicy)
}
if botID, ok := wecom["botId"].(string); ok {
result.BotID = botID
}
if secret, ok := wecom["secret"].(string); ok {
result.Secret = secret
}
return result
}
func extractDingTalkConfig(conf map[string]interface{}) dto.AgentDingTalkConfig {
result := dto.AgentDingTalkConfig{
Enabled: true,
DmPolicy: "pairing",
GroupPolicy: "disabled",
AllowFrom: []string{},
GroupAllowFrom: []string{},
}
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return result
}
dingtalk, ok := channels["dingtalk-connector"].(map[string]interface{})
if !ok {
return result
}
if enabled, ok := dingtalk["enabled"].(bool); ok {
result.Enabled = enabled
}
if clientID, ok := dingtalk["clientId"].(string); ok {
result.ClientID = clientID
}
if clientSecret, ok := dingtalk["clientSecret"].(string); ok {
result.ClientSecret = clientSecret
}
if dmPolicy, ok := dingtalk["dmPolicy"].(string); ok && strings.TrimSpace(dmPolicy) != "" {
result.DmPolicy = dmPolicy
}
if groupPolicy, ok := dingtalk["groupPolicy"].(string); ok && strings.TrimSpace(groupPolicy) != "" {
result.GroupPolicy = groupPolicy
}
result.AllowFrom = extractStringList(dingtalk["allowFrom"])
result.GroupAllowFrom = extractStringList(dingtalk["groupAllowFrom"])
return result
}
func setWecomConfig(conf map[string]interface{}, config dto.AgentWecomConfig) {
channels := ensureChildMap(conf, "channels")
wecom := ensureChildMap(channels, "wecom")
wecom["enabled"] = config.Enabled
wecom["botId"] = strings.TrimSpace(config.BotID)
wecom["secret"] = strings.TrimSpace(config.Secret)
wecom["dmPolicy"] = strings.TrimSpace(config.DmPolicy)
if strings.EqualFold(config.DmPolicy, "open") {
wecom["allowFrom"] = []string{"*"}
} else {
wecom["allowFrom"] = []string{}
}
plugins := ensureChildMap(conf, "plugins")
entries := ensureChildMap(plugins, "entries")
wecomEntry := ensureChildMap(entries, "wecom-openclaw-plugin")
wecomEntry["enabled"] = config.Enabled
}
func setDingTalkConfig(conf map[string]interface{}, config dto.AgentDingTalkConfig) {
channels := ensureChildMap(conf, "channels")
dingtalk := ensureChildMap(channels, "dingtalk-connector")
dingtalk["enabled"] = config.Enabled
dingtalk["clientId"] = strings.TrimSpace(config.ClientID)
dingtalk["clientSecret"] = strings.TrimSpace(config.ClientSecret)
dingtalk["dmPolicy"] = config.DmPolicy
dingtalk["groupPolicy"] = config.GroupPolicy
dingtalk["gatewayToken"] = extractGatewayToken(conf)
switch config.DmPolicy {
case "open":
dingtalk["allowFrom"] = []string{"*"}
case "allowlist":
dingtalk["allowFrom"] = append([]string(nil), config.AllowFrom...)
default:
delete(dingtalk, "allowFrom")
}
switch config.GroupPolicy {
case "open":
dingtalk["groupAllowFrom"] = []string{"*"}
case "allowlist":
dingtalk["groupAllowFrom"] = append([]string(nil), config.GroupAllowFrom...)
default:
delete(dingtalk, "groupAllowFrom")
}
plugins := ensureChildMap(conf, "plugins")
entries := ensureChildMap(plugins, "entries")
dingtalkEntry := ensureChildMap(entries, "dingtalk-connector")
dingtalkEntry["enabled"] = config.Enabled
gateway := ensureChildMap(conf, "gateway")
httpMap := ensureChildMap(gateway, "http")
endpoints := ensureChildMap(httpMap, "endpoints")
chatCompletions := ensureChildMap(endpoints, "chatCompletions")
chatCompletions["enabled"] = true
}
func setQQBotConfig(conf map[string]interface{}, config dto.AgentQQBotConfig) {
channels := ensureChildMap(conf, "channels")
qqbot := ensureChildMap(channels, "qqbot")
delete(qqbot, "dmPolicy")
qqbot["enabled"] = config.Enabled
qqbot["allowFrom"] = []string{"*"}
qqbot["appId"] = strings.TrimSpace(config.AppID)
qqbot["clientSecret"] = strings.TrimSpace(config.ClientSecret)
plugins := ensureChildMap(conf, "plugins")
entries := ensureChildMap(plugins, "entries")
delete(entries, "qqbot")
qqbotEntry := ensureChildMap(entries, "openclaw-qqbot")
qqbotEntry["enabled"] = config.Enabled
}
func appendPluginAllow(conf map[string]interface{}, pluginID string) {
plugins := ensureChildMap(conf, "plugins")
allow := make([]string, 0, 4)
seen := map[string]struct{}{}
switch values := plugins["allow"].(type) {
case []interface{}:
for _, value := range values {
text, ok := value.(string)
if !ok || text == "" {
continue
}
if _, ok := seen[text]; ok {
continue
}
seen[text] = struct{}{}
allow = append(allow, text)
}
}
if _, ok := seen[pluginID]; ok {
plugins["allow"] = allow
return
}
plugins["allow"] = append(allow, pluginID)
}
func buildOpenclawPluginInstallScript(spec, pluginID string) string {
return fmt.Sprintf(
"set -e; workdir=%s/%s; rm -rf \"$workdir\"; mkdir -p \"$workdir\"; cd \"$workdir\"; npm pack --silent %q >/dev/null 2>&1; pkg=$(find \"$workdir\" -maxdepth 1 -type f -name '*.tgz' | head -n 1); printf '%%s\\n' \"$pkg\"; openclaw plugins install \"$pkg\"; rm -rf \"$workdir\"",
openclawPluginPackageTmpDir,
pluginID,
spec,
)
}
func resolvePluginMeta(pluginType string) (string, string, error) {
switch pluginType {
case "qqbot":
return "@tencent-connect/openclaw-qqbot@latest", "openclaw-qqbot", nil
case "wecom":
return "@wecom/wecom-openclaw-plugin", "wecom-openclaw-plugin", nil
case "dingtalk":
return "@dingtalk-real-ai/dingtalk-connector", "dingtalk-connector", nil
case "weixin":
return "@tencent-weixin/openclaw-weixin", "openclaw-weixin", nil
default:
return "", "", fmt.Errorf("unsupported plugin type")
}
}
func checkPluginInstalled(containerName, pluginType string) (bool, error) {
_, pluginDir, err := resolvePluginMeta(pluginType)
if err != nil {
return false, err
}
if strings.TrimSpace(containerName) == "" {
return false, buserr.New("ErrRecordNotFound")
}
pluginPath := path.Join(openclawPluginBaseDir, pluginDir)
mgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
if err := mgr.RunBashCf("docker exec %s test -d %s", containerName, pluginPath); err != nil {
return false, nil
}
return true, nil
}
-244
View File
@@ -1,244 +0,0 @@
package service
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"sync"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
)
const (
openclawCronJobsRelativePath = "data/conf/cron/jobs.json"
openclawSessionStoreRelativeGlob = "data/conf/agents/*/sessions/sessions.json"
openclawSessionFilesRelativeGlob = "data/conf/agents/*/sessions/*.jsonl"
)
func (a AgentService) GetOverview(req dto.AgentOverviewReq) (*dto.AgentOverview, error) {
agent, install, conf, err := a.loadOpenclawAgentConfig(req.AgentID)
if err != nil {
return nil, err
}
overview := &dto.AgentOverview{
Snapshot: dto.AgentOverviewSnapshot{
ContainerStatus: install.Status,
AppVersion: install.Version,
DefaultModel: extractOpenclawDefaultModel(conf),
ChannelCount: countOpenclawConfiguredChannels(conf),
},
}
if overview.Snapshot.DefaultModel == "" {
overview.Snapshot.DefaultModel = agent.Model
}
if install.Status != constant.StatusRunning {
return overview, nil
}
var wg sync.WaitGroup
wg.Add(3)
go func() {
defer wg.Done()
skillCount, err := loadOpenclawOverviewSkillStats(install.ContainerName)
if err == nil {
overview.Snapshot.SkillCount = skillCount
}
}()
go func() {
defer wg.Done()
sessionCount, err := loadOpenclawOverviewSessionCount(install.GetPath())
if err == nil {
overview.Snapshot.SessionCount = sessionCount
}
}()
go func() {
defer wg.Done()
jobCount, err := loadOpenclawOverviewJobCount(install.GetPath())
if err == nil {
overview.Snapshot.JobCount = jobCount
}
}()
wg.Wait()
return overview, nil
}
func extractOpenclawDefaultModel(conf map[string]interface{}) string {
agents, ok := conf["agents"].(map[string]interface{})
if !ok {
return ""
}
defaults, ok := agents["defaults"].(map[string]interface{})
if !ok {
return ""
}
model, ok := defaults["model"].(map[string]interface{})
if !ok {
return ""
}
primary, _ := model["primary"].(string)
return strings.TrimSpace(primary)
}
func countOpenclawConfiguredChannels(conf map[string]interface{}) int {
channels, ok := conf["channels"].(map[string]interface{})
if !ok {
return 0
}
count := 0
for _, value := range channels {
channel, ok := value.(map[string]interface{})
if !ok || len(channel) == 0 {
continue
}
count++
}
return count
}
func loadOpenclawOverviewSkillStats(containerName string) (int, error) {
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
"docker exec %s openclaw skills list --json 2>&1",
30*time.Second,
containerName,
)
if err != nil {
return 0, err
}
if strings.TrimSpace(output) == "" {
return 0, nil
}
skills, err := parseOpenclawSkillsList(output)
if err != nil {
return 0, err
}
return len(skills), nil
}
func loadOpenclawOverviewSessionCount(installPath string) (int, error) {
sessionStorePaths, err := filepath.Glob(filepath.Join(installPath, openclawSessionStoreRelativeGlob))
if err != nil {
return 0, err
}
total := 0
for _, sessionStorePath := range sessionStorePaths {
count, err := loadOpenclawSessionCountFromFile(sessionStorePath)
if err != nil {
continue
}
total += count
}
if total > 0 {
return total, nil
}
sessionFiles, err := filepath.Glob(filepath.Join(installPath, openclawSessionFilesRelativeGlob))
if err != nil {
return 0, err
}
return len(sessionFiles), nil
}
func loadOpenclawSessionCountFromFile(sessionStorePath string) (int, error) {
content, err := os.ReadFile(sessionStorePath)
if err != nil {
return 0, err
}
return parseOpenclawSessionCount(string(content))
}
func loadOpenclawOverviewJobCount(installPath string) (int, error) {
content, err := os.ReadFile(filepath.Join(installPath, openclawCronJobsRelativePath))
if err != nil {
if os.IsNotExist(err) {
return 0, nil
}
return 0, err
}
return parseOpenclawCronCount(string(content))
}
func parseOpenclawSessionCount(output string) (int, error) {
if strings.TrimSpace(output) == "" {
return 0, nil
}
var payload interface{}
if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil {
return 0, err
}
return countOpenclawSessions(payload), nil
}
func parseOpenclawCronCount(output string) (int, error) {
if strings.TrimSpace(output) == "" {
return 0, nil
}
var payload interface{}
if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil {
return 0, err
}
switch value := payload.(type) {
case []interface{}:
return len(value), nil
case map[string]interface{}:
if total, ok := value["total"].(float64); ok {
return int(total), nil
}
if jobs, ok := value["jobs"].([]interface{}); ok {
return len(jobs), nil
}
return len(value), nil
default:
return 0, nil
}
}
func countOpenclawSessions(payload interface{}) int {
switch value := payload.(type) {
case []interface{}:
return len(value)
case map[string]interface{}:
if count, ok := value["count"].(float64); ok {
return int(count)
}
if sessions, ok := value["sessions"]; ok {
return countOpenclawSessions(sessions)
}
count := 0
for _, item := range value {
switch typed := item.(type) {
case map[string]interface{}:
if looksLikeOpenclawSession(typed) {
count++
}
case string:
if strings.HasSuffix(strings.TrimSpace(typed), ".jsonl") {
count++
}
}
}
return count
default:
return 0
}
}
func looksLikeOpenclawSession(item map[string]interface{}) bool {
if _, ok := item["sessionFile"]; ok {
return true
}
if _, ok := item["agentId"]; ok {
return true
}
if _, ok := item["lastActivityTs"]; ok {
return true
}
if _, ok := item["updatedAt"]; ok {
return true
}
return false
}
-256
View File
@@ -1,256 +0,0 @@
package service
import (
"encoding/json"
"fmt"
"regexp"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
)
type openclawSkillsList struct {
Skills []openclawSkillListItem `json:"skills"`
}
type openclawSkillListItem struct {
Name string `json:"name"`
Description string `json:"description"`
Source string `json:"source"`
Bundled bool `json:"bundled"`
Disabled bool `json:"disabled"`
}
type openclawSkillInfo struct {
SkillKey string `json:"skillKey"`
}
type skillhubSearchPayload struct {
Skills []dto.AgentSkillSearchItem `json:"skills"`
Results []dto.AgentSkillSearchItem `json:"results"`
}
var clawhubSearchLinePattern = regexp.MustCompile(`^(\S+)\s+(.+?)\s+\(([\d.]+)\)$`)
func (a AgentService) ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, error) {
_, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
if err := ensureContainerRunning(install.ContainerName); err != nil {
return nil, err
}
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
"docker exec %s openclaw skills list --json 2>&1",
30*time.Second,
install.ContainerName,
)
if err != nil {
return nil, err
}
if len(output) == 0 {
return nil, nil
}
return parseOpenclawSkillsList(output)
}
func (a AgentService) SearchSkills(req dto.AgentSkillSearchReq) ([]dto.AgentSkillSearchItem, error) {
_, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return nil, err
}
if err := ensureContainerRunning(install.ContainerName); err != nil {
return nil, err
}
output, err := loadOpenclawSkillSearchOutput(install.ContainerName, req.Source, req.Keyword)
if err != nil {
return nil, err
}
if len(output) == 0 {
return nil, nil
}
switch req.Source {
case "skillhub":
return parseSkillhubSearchResult(output)
default:
return parseClawhubSearchResult(output), nil
}
}
func (a AgentService) UpdateSkill(req dto.AgentSkillUpdateReq) error {
agent, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return err
}
if err := ensureContainerRunning(install.ContainerName); err != nil {
return err
}
conf, err := readOpenclawConfig(agent.ConfigPath)
if err != nil {
return err
}
skillKey, err := getOpenclawSkillKey(install.ContainerName, req.Name)
if err != nil {
return err
}
setOpenclawSkillEnabled(conf, skillKey, req.Enabled)
return writeOpenclawConfigRaw(agent.ConfigPath, conf)
}
func (a AgentService) InstallSkill(req dto.AgentSkillInstallReq) error {
_, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
if err != nil {
return err
}
if err := ensureContainerRunning(install.ContainerName); err != nil {
return err
}
installTask, err := task.NewTaskWithOps(req.Slug, task.TaskInstall, task.TaskScopeAI, req.TaskID, req.AgentID)
if err != nil {
return err
}
installTask.AddSubTask("Install OpenClaw skill", func(t *task.Task) error {
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute))
return mgr.Run("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawSkillInstallCommand(req.Source, req.Slug))
}, nil)
go func() {
if err := installTask.Execute(); err != nil {
global.LOG.Errorf("install openclaw skill failed: %v", err)
}
}()
return nil
}
func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) {
var payload openclawSkillsList
if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil {
return nil, err
}
items := make([]dto.AgentSkillItem, 0, len(payload.Skills))
for _, item := range payload.Skills {
items = append(items, dto.AgentSkillItem{
Name: item.Name,
Description: item.Description,
Source: item.Source,
Bundled: item.Bundled,
Disabled: item.Disabled,
})
}
return items, nil
}
func loadOpenclawSkillSearchOutput(containerName, source, keyword string) (string, error) {
switch source {
case "skillhub":
return cmd.RunDefaultWithStdoutBashCfAndTimeOut(
"docker exec %s skillhub search %q --json 2>&1",
30*time.Second,
containerName,
keyword,
)
default:
return cmd.RunDefaultWithStdoutBashCfAndTimeOut(
"docker exec %s clawhub search %q 2>&1",
30*time.Second,
containerName,
keyword,
)
}
}
func parseSkillhubSearchResult(output string) ([]dto.AgentSkillSearchItem, error) {
trimmed := strings.TrimSpace(output)
if trimmed == "" {
return nil, nil
}
var list []dto.AgentSkillSearchItem
if err := json.Unmarshal([]byte(trimmed), &list); err == nil {
for i := range list {
list[i].Source = "skillhub"
}
return list, nil
}
var payload skillhubSearchPayload
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
return nil, err
}
items := payload.Skills
if len(items) == 0 {
items = payload.Results
}
for i := range items {
items[i].Source = "skillhub"
}
return items, nil
}
func parseClawhubSearchResult(output string) []dto.AgentSkillSearchItem {
lines := strings.Split(strings.TrimSpace(output), "\n")
items := make([]dto.AgentSkillSearchItem, 0, len(lines))
for _, line := range lines {
matches := clawhubSearchLinePattern.FindStringSubmatch(strings.TrimSpace(line))
if len(matches) != 4 {
continue
}
items = append(items, dto.AgentSkillSearchItem{
Slug: matches[1],
Name: matches[2],
Score: matches[3],
Source: "clawhub",
})
}
return items
}
func buildOpenclawSkillInstallCommand(source, slug string) string {
switch source {
case "clawhub":
return fmt.Sprintf(
"mkdir -p %s && clawhub --workdir /home/node/.openclaw --dir skills install %q",
openclawManagedSkillsDir,
slug,
)
default:
return fmt.Sprintf(
"mkdir -p %s && skillhub --dir %s install %q",
openclawManagedSkillsDir,
openclawManagedSkillsDir,
slug,
)
}
}
func getOpenclawSkillKey(containerName, name string) (string, error) {
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
"docker exec %s openclaw skills info %q --json 2>&1",
30*time.Second,
containerName,
name,
)
if err != nil {
return "", err
}
return parseOpenclawSkillKey(name, output)
}
func parseOpenclawSkillKey(name, output string) (string, error) {
var payload openclawSkillInfo
if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil {
return "", err
}
if payload.SkillKey == "" {
return "", fmt.Errorf("skill %s does not have a skillKey", name)
}
return payload.SkillKey, nil
}
func setOpenclawSkillEnabled(conf map[string]interface{}, skillKey string, enabled bool) {
skills := ensureChildMap(conf, "skills")
entries := ensureChildMap(skills, "entries")
entry := ensureChildMap(entries, skillKey)
entry["enabled"] = enabled
}

Some files were not shown because too many files have changed in this diff Show More