mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-28 19:14:13 +08:00
feat: Support for terminal operation with the Ollama model (#7907)
This commit is contained in:
parent
c3685f6b74
commit
c329fb6599
@ -18,7 +18,7 @@ import (
|
|||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Security Timestamp
|
// @Security Timestamp
|
||||||
// @Router /ai/ollama/model [post]
|
// @Router /ai/ollama/model [post]
|
||||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加模型 [name]","formatEN":"add Ollama model [name]"}
|
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型 [name]","formatEN":"add Ollama model [name]"}
|
||||||
func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
|
func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
|
||||||
var req dto.OllamaModelName
|
var req dto.OllamaModelName
|
||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
@ -40,7 +40,7 @@ func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
|
|||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Security Timestamp
|
// @Security Timestamp
|
||||||
// @Router /ai/ollama/model/recreate [post]
|
// @Router /ai/ollama/model/recreate [post]
|
||||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加模型重试 [name]","formatEN":"re-add Ollama model [name]"}
|
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型重试 [name]","formatEN":"re-add Ollama model [name]"}
|
||||||
func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
|
func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
|
||||||
var req dto.OllamaModelName
|
var req dto.OllamaModelName
|
||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
@ -54,6 +54,28 @@ func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags AI
|
||||||
|
// @Summary Close Ollama model conn
|
||||||
|
// @Accept json
|
||||||
|
// @Param request body dto.OllamaModelName true "request"
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Security Timestamp
|
||||||
|
// @Router /ai/ollama/model/close [post]
|
||||||
|
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"关闭 Ollama 模型连接 [name]","formatEN":"close conn for Ollama model [name]"}
|
||||||
|
func (b *BaseApi) CloseOllamaModel(c *gin.Context) {
|
||||||
|
var req dto.OllamaModelName
|
||||||
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := AIToolService.Close(req.Name); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// @Tags AI
|
// @Tags AI
|
||||||
// @Summary Sync Ollama model list
|
// @Summary Sync Ollama model list
|
||||||
// @Success 200 {array} dto.OllamaModelDropList
|
// @Success 200 {array} dto.OllamaModelDropList
|
||||||
@ -127,7 +149,7 @@ func (b *BaseApi) LoadOllamaModelDetail(c *gin.Context) {
|
|||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Security Timestamp
|
// @Security Timestamp
|
||||||
// @Router /ai/ollama/model/del [post]
|
// @Router /ai/ollama/model/del [post]
|
||||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"ollama_models","output_column":"name","output_value":"name"}],"formatZH":"删除 ollama 模型 [name]","formatEN":"remove ollama model [name]"}
|
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"ollama_models","output_column":"name","output_value":"names"}],"formatZH":"删除 Ollama 模型 [names]","formatEN":"remove Ollama model [names]"}
|
||||||
func (b *BaseApi) DeleteOllamaModel(c *gin.Context) {
|
func (b *BaseApi) DeleteOllamaModel(c *gin.Context) {
|
||||||
var req dto.ForceDelete
|
var req dto.ForceDelete
|
||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/copier"
|
"github.com/1Panel-dev/1Panel/backend/utils/copier"
|
||||||
@ -146,6 +147,70 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) OllamaWsSsh(c *gin.Context) {
|
||||||
|
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer wsConn.Close()
|
||||||
|
|
||||||
|
if global.CONF.System.IsDemo {
|
||||||
|
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
||||||
|
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
||||||
|
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name := c.Query("name")
|
||||||
|
if cmd.CheckIllegal(name) {
|
||||||
|
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container, err := service.LoadContainerName()
|
||||||
|
if wshandleError(wsConn, errors.WithMessage(err, " load container name for ollama failed")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
commands := []string{"ollama", "run", name}
|
||||||
|
|
||||||
|
pidMap := loadMapFromDockerTop(container)
|
||||||
|
fmt.Println("pidMap")
|
||||||
|
for k, v := range pidMap {
|
||||||
|
fmt.Println(k, v)
|
||||||
|
}
|
||||||
|
itemCmds := append([]string{"exec", "-it", container}, commands...)
|
||||||
|
slave, err := terminal.NewCommand(itemCmds)
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer killBash(container, strings.Join(commands, " "), pidMap)
|
||||||
|
defer slave.Close()
|
||||||
|
|
||||||
|
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
quitChan := make(chan bool, 3)
|
||||||
|
tty.Start(quitChan)
|
||||||
|
go slave.Wait(quitChan)
|
||||||
|
|
||||||
|
<-quitChan
|
||||||
|
|
||||||
|
global.LOG.Info("websocket finished")
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
||||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,6 +28,7 @@ type AIToolService struct{}
|
|||||||
type IAIToolService interface {
|
type IAIToolService interface {
|
||||||
Search(search dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error)
|
Search(search dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error)
|
||||||
Create(name string) error
|
Create(name string) error
|
||||||
|
Close(name string) error
|
||||||
Recreate(name string) error
|
Recreate(name string) error
|
||||||
Delete(req dto.ForceDelete) error
|
Delete(req dto.ForceDelete) error
|
||||||
Sync() ([]dto.OllamaModelDropList, error)
|
Sync() ([]dto.OllamaModelDropList, error)
|
||||||
@ -69,7 +70,7 @@ func (u *AIToolService) LoadDetail(name string) (string, error) {
|
|||||||
if cmd.CheckIllegal(name) {
|
if cmd.CheckIllegal(name) {
|
||||||
return "", buserr.New(constant.ErrCmdIllegal)
|
return "", buserr.New(constant.ErrCmdIllegal)
|
||||||
}
|
}
|
||||||
containerName, err := loadContainerName()
|
containerName, err := LoadContainerName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -88,7 +89,7 @@ func (u *AIToolService) Create(name string) error {
|
|||||||
if modelInfo.ID != 0 {
|
if modelInfo.ID != 0 {
|
||||||
return constant.ErrRecordExist
|
return constant.ErrRecordExist
|
||||||
}
|
}
|
||||||
containerName, err := loadContainerName()
|
containerName, err := LoadContainerName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -114,6 +115,21 @@ func (u *AIToolService) Create(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *AIToolService) Close(name string) error {
|
||||||
|
if cmd.CheckIllegal(name) {
|
||||||
|
return buserr.New(constant.ErrCmdIllegal)
|
||||||
|
}
|
||||||
|
containerName, err := LoadContainerName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdout, err := cmd.Execf("docker exec %s ollama stop %s", containerName, name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("handle ollama stop %s failed, stdout: %s, err: %v", name, stdout, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *AIToolService) Recreate(name string) error {
|
func (u *AIToolService) Recreate(name string) error {
|
||||||
if cmd.CheckIllegal(name) {
|
if cmd.CheckIllegal(name) {
|
||||||
return buserr.New(constant.ErrCmdIllegal)
|
return buserr.New(constant.ErrCmdIllegal)
|
||||||
@ -122,7 +138,7 @@ func (u *AIToolService) Recreate(name string) error {
|
|||||||
if modelInfo.ID == 0 {
|
if modelInfo.ID == 0 {
|
||||||
return constant.ErrRecordNotFound
|
return constant.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
containerName, err := loadContainerName()
|
containerName, err := LoadContainerName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -148,7 +164,7 @@ func (u *AIToolService) Delete(req dto.ForceDelete) error {
|
|||||||
if len(ollamaList) == 0 {
|
if len(ollamaList) == 0 {
|
||||||
return constant.ErrRecordNotFound
|
return constant.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
containerName, err := loadContainerName()
|
containerName, err := LoadContainerName()
|
||||||
if err != nil && !req.ForceDelete {
|
if err != nil && !req.ForceDelete {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -167,7 +183,7 @@ func (u *AIToolService) Delete(req dto.ForceDelete) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *AIToolService) Sync() ([]dto.OllamaModelDropList, error) {
|
func (u *AIToolService) Sync() ([]dto.OllamaModelDropList, error) {
|
||||||
containerName, err := loadContainerName()
|
containerName, err := LoadContainerName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -335,7 +351,7 @@ func (u *AIToolService) UpdateBindDomain(req dto.OllamaBindDomain) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadContainerName() (string, error) {
|
func LoadContainerName() (string, error) {
|
||||||
ollamaBaseInfo, err := appInstallRepo.LoadBaseInfo("ollama", "")
|
ollamaBaseInfo, err := appInstallRepo.LoadBaseInfo("ollama", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("ollama service is not found, err: %v", err)
|
return "", fmt.Errorf("ollama service is not found, err: %v", err)
|
||||||
|
@ -15,6 +15,8 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
|
|||||||
|
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
|
aiToolsRouter.GET("/ollama/exec", baseApi.OllamaWsSsh)
|
||||||
|
aiToolsRouter.POST("/ollama/close", baseApi.CloseOllamaModel)
|
||||||
aiToolsRouter.POST("/ollama/model", baseApi.CreateOllamaModel)
|
aiToolsRouter.POST("/ollama/model", baseApi.CreateOllamaModel)
|
||||||
aiToolsRouter.POST("/ollama/model/recreate", baseApi.RecreateOllamaModel)
|
aiToolsRouter.POST("/ollama/model/recreate", baseApi.RecreateOllamaModel)
|
||||||
aiToolsRouter.POST("/ollama/model/search", baseApi.SearchOllamaModel)
|
aiToolsRouter.POST("/ollama/model/search", baseApi.SearchOllamaModel)
|
||||||
|
@ -156,7 +156,51 @@ const docTemplate = `{
|
|||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
"formatEN": "add Ollama model [name]",
|
"formatEN": "add Ollama model [name]",
|
||||||
"formatZH": "添加模型 [name]",
|
"formatZH": "添加 Ollama 模型 [name]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ai/ollama/model/close": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Timestamp": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"AI"
|
||||||
|
],
|
||||||
|
"summary": "Close Ollama model conn",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.OllamaModelName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [],
|
||||||
|
"bodyKeys": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"formatEN": "close conn for Ollama model [name]",
|
||||||
|
"formatZH": "关闭 Ollama 模型连接 [name]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,17 +243,17 @@ const docTemplate = `{
|
|||||||
{
|
{
|
||||||
"db": "ollama_models",
|
"db": "ollama_models",
|
||||||
"input_column": "id",
|
"input_column": "id",
|
||||||
"input_value": "id",
|
"input_value": "ids",
|
||||||
"isList": false,
|
"isList": true,
|
||||||
"output_column": "name",
|
"output_column": "name",
|
||||||
"output_value": "name"
|
"output_value": "names"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bodyKeys": [
|
"bodyKeys": [
|
||||||
"id"
|
"ids"
|
||||||
],
|
],
|
||||||
"formatEN": "remove ollama model [name]",
|
"formatEN": "remove Ollama model [names]",
|
||||||
"formatZH": "删除 ollama 模型 [name]",
|
"formatZH": "删除 Ollama 模型 [names]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,7 +335,7 @@ const docTemplate = `{
|
|||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
"formatEN": "re-add Ollama model [name]",
|
"formatEN": "re-add Ollama model [name]",
|
||||||
"formatZH": "添加模型重试 [name]",
|
"formatZH": "添加 Ollama 模型重试 [name]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20633,18 +20677,15 @@ const docTemplate = `{
|
|||||||
"domain"
|
"domain"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"allowIPs": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"appInstallID": {
|
"appInstallID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"domain": {
|
"domain": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"ipList": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"sslID": {
|
"sslID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -20673,6 +20714,9 @@ const docTemplate = `{
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"connUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"domain": {
|
"domain": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -153,7 +153,51 @@
|
|||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
"formatEN": "add Ollama model [name]",
|
"formatEN": "add Ollama model [name]",
|
||||||
"formatZH": "添加模型 [name]",
|
"formatZH": "添加 Ollama 模型 [name]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ai/ollama/model/close": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Timestamp": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"AI"
|
||||||
|
],
|
||||||
|
"summary": "Close Ollama model conn",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.OllamaModelName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [],
|
||||||
|
"bodyKeys": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"formatEN": "close conn for Ollama model [name]",
|
||||||
|
"formatZH": "关闭 Ollama 模型连接 [name]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,17 +240,17 @@
|
|||||||
{
|
{
|
||||||
"db": "ollama_models",
|
"db": "ollama_models",
|
||||||
"input_column": "id",
|
"input_column": "id",
|
||||||
"input_value": "id",
|
"input_value": "ids",
|
||||||
"isList": false,
|
"isList": true,
|
||||||
"output_column": "name",
|
"output_column": "name",
|
||||||
"output_value": "name"
|
"output_value": "names"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bodyKeys": [
|
"bodyKeys": [
|
||||||
"id"
|
"ids"
|
||||||
],
|
],
|
||||||
"formatEN": "remove ollama model [name]",
|
"formatEN": "remove Ollama model [names]",
|
||||||
"formatZH": "删除 ollama 模型 [name]",
|
"formatZH": "删除 Ollama 模型 [names]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,7 +332,7 @@
|
|||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
"formatEN": "re-add Ollama model [name]",
|
"formatEN": "re-add Ollama model [name]",
|
||||||
"formatZH": "添加模型重试 [name]",
|
"formatZH": "添加 Ollama 模型重试 [name]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20630,18 +20674,15 @@
|
|||||||
"domain"
|
"domain"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"allowIPs": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"appInstallID": {
|
"appInstallID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"domain": {
|
"domain": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"ipList": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"sslID": {
|
"sslID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -20670,6 +20711,9 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"connUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"domain": {
|
"domain": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -2457,14 +2457,12 @@ definitions:
|
|||||||
- ProxyCache
|
- ProxyCache
|
||||||
dto.OllamaBindDomain:
|
dto.OllamaBindDomain:
|
||||||
properties:
|
properties:
|
||||||
allowIPs:
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
appInstallID:
|
appInstallID:
|
||||||
type: integer
|
type: integer
|
||||||
domain:
|
domain:
|
||||||
type: string
|
type: string
|
||||||
|
ipList:
|
||||||
|
type: string
|
||||||
sslID:
|
sslID:
|
||||||
type: integer
|
type: integer
|
||||||
websiteID:
|
websiteID:
|
||||||
@ -2486,6 +2484,8 @@ definitions:
|
|||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
|
connUrl:
|
||||||
|
type: string
|
||||||
domain:
|
domain:
|
||||||
type: string
|
type: string
|
||||||
sslID:
|
sslID:
|
||||||
@ -6583,7 +6583,34 @@ paths:
|
|||||||
bodyKeys:
|
bodyKeys:
|
||||||
- name
|
- name
|
||||||
formatEN: add Ollama model [name]
|
formatEN: add Ollama model [name]
|
||||||
formatZH: 添加模型 [name]
|
formatZH: 添加 Ollama 模型 [name]
|
||||||
|
paramKeys: []
|
||||||
|
/ai/ollama/model/close:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- description: request
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/dto.OllamaModelName'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
- Timestamp: []
|
||||||
|
summary: Close Ollama model conn
|
||||||
|
tags:
|
||||||
|
- AI
|
||||||
|
x-panel-log:
|
||||||
|
BeforeFunctions: []
|
||||||
|
bodyKeys:
|
||||||
|
- name
|
||||||
|
formatEN: close conn for Ollama model [name]
|
||||||
|
formatZH: 关闭 Ollama 模型连接 [name]
|
||||||
paramKeys: []
|
paramKeys: []
|
||||||
/ai/ollama/model/del:
|
/ai/ollama/model/del:
|
||||||
post:
|
post:
|
||||||
@ -6609,14 +6636,14 @@ paths:
|
|||||||
BeforeFunctions:
|
BeforeFunctions:
|
||||||
- db: ollama_models
|
- db: ollama_models
|
||||||
input_column: id
|
input_column: id
|
||||||
input_value: id
|
input_value: ids
|
||||||
isList: false
|
isList: true
|
||||||
output_column: name
|
output_column: name
|
||||||
output_value: name
|
output_value: names
|
||||||
bodyKeys:
|
bodyKeys:
|
||||||
- id
|
- ids
|
||||||
formatEN: remove ollama model [name]
|
formatEN: remove Ollama model [names]
|
||||||
formatZH: 删除 ollama 模型 [name]
|
formatZH: 删除 Ollama 模型 [names]
|
||||||
paramKeys: []
|
paramKeys: []
|
||||||
/ai/ollama/model/load:
|
/ai/ollama/model/load:
|
||||||
post:
|
post:
|
||||||
@ -6665,7 +6692,7 @@ paths:
|
|||||||
bodyKeys:
|
bodyKeys:
|
||||||
- name
|
- name
|
||||||
formatEN: re-add Ollama model [name]
|
formatEN: re-add Ollama model [name]
|
||||||
formatZH: 添加模型重试 [name]
|
formatZH: 添加 Ollama 模型重试 [name]
|
||||||
paramKeys: []
|
paramKeys: []
|
||||||
/ai/ollama/model/search:
|
/ai/ollama/model/search:
|
||||||
post:
|
post:
|
||||||
|
@ -20,6 +20,9 @@ export const loadOllamaModel = (name: string) => {
|
|||||||
export const syncOllamaModel = () => {
|
export const syncOllamaModel = () => {
|
||||||
return http.post<Array<AI.OllamaModelDropInfo>>(`/ai/ollama/model/sync`);
|
return http.post<Array<AI.OllamaModelDropInfo>>(`/ai/ollama/model/sync`);
|
||||||
};
|
};
|
||||||
|
export const closeOllamaModel = (name: string) => {
|
||||||
|
return http.post(`/ai/ollama/close`, { name: name });
|
||||||
|
};
|
||||||
|
|
||||||
export const loadGPUInfo = () => {
|
export const loadGPUInfo = () => {
|
||||||
return http.get<any>(`/ai/gpu/load`);
|
return http.get<any>(`/ai/gpu/load`);
|
||||||
|
@ -15,6 +15,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: 'Run',
|
||||||
create: 'Create ',
|
create: 'Create ',
|
||||||
add: 'Add ',
|
add: 'Add ',
|
||||||
save: 'Save ',
|
save: 'Save ',
|
||||||
@ -122,6 +123,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: 'No data available',
|
noneData: 'No data available',
|
||||||
|
disConn:
|
||||||
|
'If you want to disconnect the terminal, please click the disconnect button directly, do not enter exit commands like {0}.',
|
||||||
delete: `This operation delete can't be undone. Do you want to continue?`,
|
delete: `This operation delete can't be undone. Do you want to continue?`,
|
||||||
clean: `This operation clean can't be undone. Do you want to continue?`,
|
clean: `This operation clean can't be undone. Do you want to continue?`,
|
||||||
deleteTitle: 'Delete',
|
deleteTitle: 'Delete',
|
||||||
@ -1229,6 +1232,7 @@ const message = {
|
|||||||
resource: 'Resource',
|
resource: 'Resource',
|
||||||
operate: 'Operate',
|
operate: 'Operate',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: 'Group',
|
groups: 'Group',
|
||||||
hosts: 'Host',
|
hosts: 'Host',
|
||||||
apps: 'App',
|
apps: 'App',
|
||||||
|
@ -14,6 +14,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: '実行',
|
||||||
create: '作成する',
|
create: '作成する',
|
||||||
add: '追加',
|
add: '追加',
|
||||||
save: '保存',
|
save: '保存',
|
||||||
@ -121,6 +122,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: '利用可能なデータはありません',
|
noneData: '利用可能なデータはありません',
|
||||||
|
disConn:
|
||||||
|
'端末を切断する場合は、切断ボタンを直接クリックしてください。{0} のような終了コマンドを入力しないでください。',
|
||||||
delete: `この操作削除は元に戻すことはできません。続けたいですか?`,
|
delete: `この操作削除は元に戻すことはできません。続けたいですか?`,
|
||||||
clean: `この操作は取り消すことはできません。続けたいですか?`,
|
clean: `この操作は取り消すことはできません。続けたいですか?`,
|
||||||
deleteTitle: '消去',
|
deleteTitle: '消去',
|
||||||
@ -1209,6 +1212,7 @@ const message = {
|
|||||||
resource: 'リソース',
|
resource: 'リソース',
|
||||||
operate: '動作します',
|
operate: '動作します',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: 'グループ',
|
groups: 'グループ',
|
||||||
hosts: 'ホスト',
|
hosts: 'ホスト',
|
||||||
apps: 'アプリ',
|
apps: 'アプリ',
|
||||||
|
@ -15,6 +15,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: '실행',
|
||||||
create: '생성',
|
create: '생성',
|
||||||
add: '추가',
|
add: '추가',
|
||||||
save: '저장',
|
save: '저장',
|
||||||
@ -122,6 +123,7 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: '데이터가 없습니다',
|
noneData: '데이터가 없습니다',
|
||||||
|
disConn: '터미널을 끊으려면 직접 끊기 버튼을 클릭하세요. {0} 과 같은 종료 명령을 입력하지 마세요.',
|
||||||
delete: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
delete: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
||||||
clean: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
clean: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
||||||
deleteTitle: '삭제',
|
deleteTitle: '삭제',
|
||||||
@ -1196,6 +1198,7 @@ const message = {
|
|||||||
resource: '자원',
|
resource: '자원',
|
||||||
operate: '작업',
|
operate: '작업',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: '그룹',
|
groups: '그룹',
|
||||||
hosts: '호스트',
|
hosts: '호스트',
|
||||||
apps: '애플리케이션',
|
apps: '애플리케이션',
|
||||||
|
@ -15,6 +15,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: 'Jalankan',
|
||||||
create: 'Cipta',
|
create: 'Cipta',
|
||||||
add: 'Tambah',
|
add: 'Tambah',
|
||||||
save: 'Simpan',
|
save: 'Simpan',
|
||||||
@ -122,6 +123,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: 'Tiada data tersedia',
|
noneData: 'Tiada data tersedia',
|
||||||
|
disConn:
|
||||||
|
'Jika anda ingin memutuskan sambungan terminal, sila klik butang putus sambungan secara langsung, jangan masukkan arahan keluar seperti {0}.',
|
||||||
delete: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
delete: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
||||||
clean: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
clean: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
||||||
deleteTitle: 'Padam',
|
deleteTitle: 'Padam',
|
||||||
@ -1251,6 +1254,7 @@ const message = {
|
|||||||
resource: 'Sumber',
|
resource: 'Sumber',
|
||||||
operate: 'Operasi',
|
operate: 'Operasi',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: 'Kumpulan',
|
groups: 'Kumpulan',
|
||||||
hosts: 'Hos',
|
hosts: 'Hos',
|
||||||
apps: 'Aplikasi',
|
apps: 'Aplikasi',
|
||||||
|
@ -15,6 +15,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: 'Executar',
|
||||||
create: 'Criar',
|
create: 'Criar',
|
||||||
add: 'Adicionar',
|
add: 'Adicionar',
|
||||||
save: 'Salvar',
|
save: 'Salvar',
|
||||||
@ -122,6 +123,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: 'Nenhum dado disponível',
|
noneData: 'Nenhum dado disponível',
|
||||||
|
disConn:
|
||||||
|
'Se você deseja desconectar o terminal, clique diretamente no botão de desconexão, não insira comandos de saída como {0}.',
|
||||||
delete: 'Esta operação de exclusão não pode ser desfeita. Deseja continuar?',
|
delete: 'Esta operação de exclusão não pode ser desfeita. Deseja continuar?',
|
||||||
clean: 'Esta operação de limpeza não pode ser desfeita. Deseja continuar?',
|
clean: 'Esta operação de limpeza não pode ser desfeita. Deseja continuar?',
|
||||||
deleteTitle: 'Excluir',
|
deleteTitle: 'Excluir',
|
||||||
@ -1236,6 +1239,7 @@ const message = {
|
|||||||
resource: 'Recurso',
|
resource: 'Recurso',
|
||||||
operate: 'Operar',
|
operate: 'Operar',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: 'Grupo',
|
groups: 'Grupo',
|
||||||
hosts: 'Host',
|
hosts: 'Host',
|
||||||
apps: 'Aplicativo',
|
apps: 'Aplicativo',
|
||||||
|
@ -15,6 +15,7 @@ const message = {
|
|||||||
fit2cloud: 'FIT2CLOUD',
|
fit2cloud: 'FIT2CLOUD',
|
||||||
lingxia: 'Lingxia',
|
lingxia: 'Lingxia',
|
||||||
button: {
|
button: {
|
||||||
|
run: 'Запуск',
|
||||||
create: 'Создать ',
|
create: 'Создать ',
|
||||||
add: 'Добавить ',
|
add: 'Добавить ',
|
||||||
save: 'Сохранить ',
|
save: 'Сохранить ',
|
||||||
@ -123,6 +124,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: 'Нет данных',
|
noneData: 'Нет данных',
|
||||||
|
disConn:
|
||||||
|
'Если вы хотите отключить терминал, пожалуйста, нажмите кнопку отключения напрямую, не вводите команды выхода, такие как {0}.',
|
||||||
delete: 'Эта операция удаления не может быть отменена. Хотите продолжить?',
|
delete: 'Эта операция удаления не может быть отменена. Хотите продолжить?',
|
||||||
clean: 'Эта операция очистки не может быть отменена. Хотите продолжить?',
|
clean: 'Эта операция очистки не может быть отменена. Хотите продолжить?',
|
||||||
deleteTitle: 'Удалить',
|
deleteTitle: 'Удалить',
|
||||||
@ -1242,6 +1245,7 @@ const message = {
|
|||||||
resource: 'Ресурс',
|
resource: 'Ресурс',
|
||||||
operate: 'Операция',
|
operate: 'Операция',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: 'Группа',
|
groups: 'Группа',
|
||||||
hosts: 'Хост',
|
hosts: 'Хост',
|
||||||
apps: 'Приложение',
|
apps: 'Приложение',
|
||||||
|
@ -14,6 +14,7 @@ const message = {
|
|||||||
fit2cloud: '飛致雲',
|
fit2cloud: '飛致雲',
|
||||||
lingxia: '凌霞',
|
lingxia: '凌霞',
|
||||||
button: {
|
button: {
|
||||||
|
run: '運行',
|
||||||
create: '建立',
|
create: '建立',
|
||||||
add: '新增',
|
add: '新增',
|
||||||
save: '儲存',
|
save: '儲存',
|
||||||
@ -122,6 +123,7 @@ const message = {
|
|||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
noneData: '暫無資料',
|
noneData: '暫無資料',
|
||||||
|
disConn: '如果要斷開終端,請直接點擊斷開按鈕,不要輸入 {0} 等退出命令。',
|
||||||
delete: '刪除 操作不可復原,是否繼續?',
|
delete: '刪除 操作不可復原,是否繼續?',
|
||||||
clean: '清空 操作不可復原,是否繼續?',
|
clean: '清空 操作不可復原,是否繼續?',
|
||||||
deleteTitle: '刪除',
|
deleteTitle: '刪除',
|
||||||
@ -1169,6 +1171,7 @@ const message = {
|
|||||||
resource: '資源',
|
resource: '資源',
|
||||||
operate: '操作',
|
operate: '操作',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: '分組',
|
groups: '分組',
|
||||||
hosts: '主機',
|
hosts: '主機',
|
||||||
apps: '應用',
|
apps: '應用',
|
||||||
|
@ -14,6 +14,7 @@ const message = {
|
|||||||
fit2cloud: '飞致云',
|
fit2cloud: '飞致云',
|
||||||
lingxia: '凌霞',
|
lingxia: '凌霞',
|
||||||
button: {
|
button: {
|
||||||
|
run: '运行',
|
||||||
create: '创建',
|
create: '创建',
|
||||||
add: '添加',
|
add: '添加',
|
||||||
save: '保存',
|
save: '保存',
|
||||||
@ -120,6 +121,7 @@ const message = {
|
|||||||
Rollbacking: '快照回滚中,请稍候...',
|
Rollbacking: '快照回滚中,请稍候...',
|
||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
|
disConn: '如果要断开终端请直接点击断开按钮,不要输入 {0} 等退出命令',
|
||||||
noneData: '暂无数据',
|
noneData: '暂无数据',
|
||||||
delete: '删除 操作不可回滚,是否继续?',
|
delete: '删除 操作不可回滚,是否继续?',
|
||||||
clean: '清空 操作不可回滚,是否继续?',
|
clean: '清空 操作不可回滚,是否继续?',
|
||||||
@ -1171,6 +1173,7 @@ const message = {
|
|||||||
resource: '资源',
|
resource: '资源',
|
||||||
operate: '操作',
|
operate: '操作',
|
||||||
detail: {
|
detail: {
|
||||||
|
ai: 'AI',
|
||||||
groups: '分组',
|
groups: '分组',
|
||||||
hosts: '主机',
|
hosts: '主机',
|
||||||
apps: '应用',
|
apps: '应用',
|
||||||
|
@ -172,6 +172,7 @@
|
|||||||
<AddDialog ref="addRef" @search="search" @log="onLoadLog" />
|
<AddDialog ref="addRef" @search="search" @log="onLoadLog" />
|
||||||
<Log ref="logRef" @close="search" />
|
<Log ref="logRef" @close="search" />
|
||||||
<Del ref="delRef" @search="search" />
|
<Del ref="delRef" @search="search" />
|
||||||
|
<Terminal ref="terminalRef" />
|
||||||
<Conn ref="connRef" />
|
<Conn ref="connRef" />
|
||||||
<CodemirrorDialog ref="detailRef" />
|
<CodemirrorDialog ref="detailRef" />
|
||||||
<PortJumpDialog ref="dialogPortJumpRef" />
|
<PortJumpDialog ref="dialogPortJumpRef" />
|
||||||
@ -183,6 +184,7 @@
|
|||||||
import AppStatus from '@/components/app-status/index.vue';
|
import AppStatus from '@/components/app-status/index.vue';
|
||||||
import AddDialog from '@/views/ai/model/add/index.vue';
|
import AddDialog from '@/views/ai/model/add/index.vue';
|
||||||
import Conn from '@/views/ai/model/conn/index.vue';
|
import Conn from '@/views/ai/model/conn/index.vue';
|
||||||
|
import Terminal from '@/views/ai/model/terminal/index.vue';
|
||||||
import Del from '@/views/ai/model/del/index.vue';
|
import Del from '@/views/ai/model/del/index.vue';
|
||||||
import Log from '@/components/log-dialog/index.vue';
|
import Log from '@/components/log-dialog/index.vue';
|
||||||
import PortJumpDialog from '@/components/port-jump/index.vue';
|
import PortJumpDialog from '@/components/port-jump/index.vue';
|
||||||
@ -214,6 +216,7 @@ const logRef = ref();
|
|||||||
const detailRef = ref();
|
const detailRef = ref();
|
||||||
const delRef = ref();
|
const delRef = ref();
|
||||||
const connRef = ref();
|
const connRef = ref();
|
||||||
|
const terminalRef = ref();
|
||||||
const openWebUIPort = ref();
|
const openWebUIPort = ref();
|
||||||
const dashboardVisible = ref(false);
|
const dashboardVisible = ref(false);
|
||||||
const dialogPortJumpRef = ref();
|
const dialogPortJumpRef = ref();
|
||||||
@ -403,6 +406,15 @@ const onLoadLog = (row: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.run'),
|
||||||
|
click: (row: AI.OllamaModelInfo) => {
|
||||||
|
terminalRef.value.acceptParams({ name: row.name });
|
||||||
|
},
|
||||||
|
disabled: (row: any) => {
|
||||||
|
return row.status !== 'Success';
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('commons.button.retry'),
|
label: i18n.global.t('commons.button.retry'),
|
||||||
click: (row: AI.OllamaModelInfo) => {
|
click: (row: AI.OllamaModelInfo) => {
|
||||||
|
101
frontend/src/views/ai/model/terminal/index.vue
Normal file
101
frontend/src/views/ai/model/terminal/index.vue
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer
|
||||||
|
v-model="terminalVisible"
|
||||||
|
@close="handleClose"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:size="globalStore.isFullScreen ? '100%' : '50%'"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<DrawerHeader :header="$t('container.containerTerminal')" :resource="title" :back="handleClose">
|
||||||
|
<template #extra v-if="!mobile">
|
||||||
|
<el-tooltip :content="loadTooltip()" placement="top">
|
||||||
|
<el-button @click="toggleFullscreen" class="fullScreen" icon="FullScreen" plain></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</DrawerHeader>
|
||||||
|
</template>
|
||||||
|
<el-alert type="error" :closable="false">
|
||||||
|
<template #title>
|
||||||
|
<span>{{ $t('commons.msg.disConn', ['/bye exit']) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
|
<Terminal class="mt-2" style="height: calc(100vh - 225px)" ref="terminalRef"></Terminal>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="handleClose">
|
||||||
|
{{ $t('commons.button.disconnect') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, nextTick, ref } from 'vue';
|
||||||
|
import Terminal from '@/components/terminal/index.vue';
|
||||||
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
|
import { closeOllamaModel } from '@/api/modules/ai';
|
||||||
|
import { GlobalStore } from '@/store';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
|
||||||
|
const globalStore = GlobalStore();
|
||||||
|
const mobile = computed(() => {
|
||||||
|
return globalStore.isMobile();
|
||||||
|
});
|
||||||
|
|
||||||
|
const title = ref();
|
||||||
|
const terminalVisible = ref(false);
|
||||||
|
const itemName = ref();
|
||||||
|
const terminalRef = ref();
|
||||||
|
|
||||||
|
interface DialogProps {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||||
|
itemName.value = params.name;
|
||||||
|
terminalVisible.value = true;
|
||||||
|
initTerm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadTooltip = () => {
|
||||||
|
return i18n.global.t('commons.button.' + (globalStore.isFullScreen ? 'quitFullscreen' : 'fullscreen'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const initTerm = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
terminalRef.value.acceptParams({
|
||||||
|
endpoint: '/api/v1/ai/ollama/exec',
|
||||||
|
args: `name=${itemName.value}`,
|
||||||
|
error: '',
|
||||||
|
initCmd: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function toggleFullscreen() {
|
||||||
|
globalStore.isFullScreen = !globalStore.isFullScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClose = async () => {
|
||||||
|
await closeOllamaModel(itemName.value)
|
||||||
|
.then(() => {
|
||||||
|
terminalRef.value?.onClose();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
terminalRef.value?.onClose();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
onClose();
|
||||||
|
globalStore.isFullScreen = false;
|
||||||
|
terminalVisible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -10,7 +10,12 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<DrawerHeader :header="$t('container.containerTerminal')" :resource="title" :back="handleClose" />
|
<DrawerHeader :header="$t('container.containerTerminal')" :resource="title" :back="handleClose" />
|
||||||
</template>
|
</template>
|
||||||
<el-form ref="formRef" :model="form" label-position="top">
|
<el-alert type="error" :closable="false">
|
||||||
|
<template #title>
|
||||||
|
<span>{{ $t('commons.msg.disConn', ['exit']) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
|
<el-form ref="formRef" class="mt-2" :model="form" label-position="top">
|
||||||
<el-form-item :label="$t('commons.table.user')" prop="user">
|
<el-form-item :label="$t('commons.table.user')" prop="user">
|
||||||
<el-input placeholder="root" clearable v-model="form.user" />
|
<el-input placeholder="root" clearable v-model="form.user" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -46,7 +51,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else @click="onClose()">{{ $t('commons.button.disconnect') }}</el-button>
|
<el-button v-else @click="onClose()">{{ $t('commons.button.disconnect') }}</el-button>
|
||||||
<Terminal
|
<Terminal
|
||||||
style="height: calc(100vh - 302px); margin-top: 18px"
|
style="height: calc(100vh - 355px); margin-top: 18px"
|
||||||
ref="terminalRef"
|
ref="terminalRef"
|
||||||
v-if="terminalOpen"
|
v-if="terminalOpen"
|
||||||
></Terminal>
|
></Terminal>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user