🎨 新增世界书模块,将原有的世界书分离

Signed-off-by: Echo <1711788888@qq.com>
This commit is contained in:
2026-02-27 23:15:30 +08:00
parent 689e8af3df
commit 032d0ccdf0
18 changed files with 1880 additions and 8 deletions

View File

@@ -0,0 +1,64 @@
package request
// CreateWorldbookRequest 创建世界书请求
type CreateWorldbookRequest struct {
Name string `json:"name" binding:"required,max=100"`
Description string `json:"description"`
IsPublic bool `json:"isPublic"`
}
// UpdateWorldbookRequest 更新世界书请求
type UpdateWorldbookRequest struct {
Name *string `json:"name" binding:"omitempty,max=100"`
Description *string `json:"description"`
IsPublic *bool `json:"isPublic"`
}
// GetWorldbookListRequest 获取世界书列表请求
type GetWorldbookListRequest struct {
Page int `json:"page"`
PageSize int `json:"pageSize"`
Keyword string `json:"keyword"`
}
// CreateEntryRequest 创建世界书条目请求
type CreateEntryRequest struct {
Comment string `json:"comment"`
Content string `json:"content" binding:"required"`
Keys []string `json:"keys"`
SecondaryKeys []string `json:"secondaryKeys"`
Constant bool `json:"constant"`
Enabled *bool `json:"enabled"` // 指针以区分 false 和未传
UseRegex bool `json:"useRegex"`
CaseSensitive bool `json:"caseSensitive"`
MatchWholeWords bool `json:"matchWholeWords"`
Selective bool `json:"selective"`
SelectiveLogic int `json:"selectiveLogic"`
Position int `json:"position"`
Depth int `json:"depth"`
Order int `json:"order"`
Probability int `json:"probability"`
ScanDepth int `json:"scanDepth"`
GroupID string `json:"groupId"`
}
// UpdateEntryRequest 更新世界书条目请求(所有字段可选)
type UpdateEntryRequest struct {
Comment *string `json:"comment"`
Content *string `json:"content"`
Keys []string `json:"keys"`
SecondaryKeys []string `json:"secondaryKeys"`
Constant *bool `json:"constant"`
Enabled *bool `json:"enabled"`
UseRegex *bool `json:"useRegex"`
CaseSensitive *bool `json:"caseSensitive"`
MatchWholeWords *bool `json:"matchWholeWords"`
Selective *bool `json:"selective"`
SelectiveLogic *int `json:"selectiveLogic"`
Position *int `json:"position"`
Depth *int `json:"depth"`
Order *int `json:"order"`
Probability *int `json:"probability"`
ScanDepth *int `json:"scanDepth"`
GroupID *string `json:"groupId"`
}

View File

@@ -0,0 +1,114 @@
package response
import (
"encoding/json"
"time"
"git.echol.cn/loser/st/server/model/app"
)
// WorldbookResponse 世界书响应
type WorldbookResponse struct {
ID uint `json:"id"`
UserID uint `json:"userId"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic bool `json:"isPublic"`
EntryCount int `json:"entryCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// WorldbookListResponse 世界书列表响应
type WorldbookListResponse struct {
List []WorldbookResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// EntryResponse 世界书条目响应
type EntryResponse struct {
ID uint `json:"id"`
WorldbookID uint `json:"worldbookId"`
Comment string `json:"comment"`
Content string `json:"content"`
Keys []string `json:"keys"`
SecondaryKeys []string `json:"secondaryKeys"`
Constant bool `json:"constant"`
Enabled bool `json:"enabled"`
UseRegex bool `json:"useRegex"`
CaseSensitive bool `json:"caseSensitive"`
MatchWholeWords bool `json:"matchWholeWords"`
Selective bool `json:"selective"`
SelectiveLogic int `json:"selectiveLogic"`
Position int `json:"position"`
Depth int `json:"depth"`
Order int `json:"order"`
Probability int `json:"probability"`
ScanDepth int `json:"scanDepth"`
GroupID string `json:"groupId"`
Extensions map[string]interface{} `json:"extensions"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// EntryListResponse 条目列表响应
type EntryListResponse struct {
List []EntryResponse `json:"list"`
Total int64 `json:"total"`
}
// ToWorldbookResponse 转换为世界书响应结构
func ToWorldbookResponse(wb *app.Worldbook) WorldbookResponse {
return WorldbookResponse{
ID: wb.ID,
UserID: wb.UserID,
Name: wb.Name,
Description: wb.Description,
IsPublic: wb.IsPublic,
EntryCount: wb.EntryCount,
CreatedAt: wb.CreatedAt,
UpdatedAt: wb.UpdatedAt,
}
}
// ToEntryResponse 转换为条目响应结构
func ToEntryResponse(entry *app.WorldbookEntry) EntryResponse {
var keys []string
if len(entry.Keys) > 0 {
json.Unmarshal(entry.Keys, &keys)
}
var secondaryKeys []string
if len(entry.SecondaryKeys) > 0 {
json.Unmarshal(entry.SecondaryKeys, &secondaryKeys)
}
var extensions map[string]interface{}
if len(entry.Extensions) > 0 {
json.Unmarshal(entry.Extensions, &extensions)
}
return EntryResponse{
ID: entry.ID,
WorldbookID: entry.WorldbookID,
Comment: entry.Comment,
Content: entry.Content,
Keys: keys,
SecondaryKeys: secondaryKeys,
Constant: entry.Constant,
Enabled: entry.Enabled,
UseRegex: entry.UseRegex,
CaseSensitive: entry.CaseSensitive,
MatchWholeWords: entry.MatchWholeWords,
Selective: entry.Selective,
SelectiveLogic: entry.SelectiveLogic,
Position: entry.Position,
Depth: entry.Depth,
Order: entry.Order,
Probability: entry.Probability,
ScanDepth: entry.ScanDepth,
GroupID: entry.GroupID,
Extensions: extensions,
CreatedAt: entry.CreatedAt,
UpdatedAt: entry.UpdatedAt,
}
}

View File

@@ -0,0 +1,68 @@
package app
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// Worldbook 世界书主表
type Worldbook struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
UserID uint `gorm:"index;not null" json:"userId"`
Name string `gorm:"type:varchar(100);not null" json:"name"`
Description string `gorm:"type:text" json:"description"`
IsPublic bool `gorm:"default:false" json:"isPublic"`
EntryCount int `gorm:"default:0" json:"entryCount"`
}
func (Worldbook) TableName() string {
return "worldbooks"
}
// WorldbookEntry 世界书条目表(完全兼容 SillyTavern 格式)
type WorldbookEntry struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
WorldbookID uint `gorm:"index;not null" json:"worldbookId"`
Comment string `gorm:"type:varchar(200)" json:"comment"` // 条目标题/备注
Content string `gorm:"type:text;not null" json:"content"` // 注入内容
// 关键词(存为 JSONB []string
Keys datatypes.JSON `gorm:"type:jsonb" json:"keys"`
SecondaryKeys datatypes.JSON `gorm:"type:jsonb" json:"secondaryKeys"`
// 触发设置
Constant bool `gorm:"default:false" json:"constant"` // 常驻注入,无需关键词触发
Enabled bool `gorm:"default:true" json:"enabled"` // 是否启用
UseRegex bool `gorm:"default:false" json:"useRegex"` // 关键词用正则表达式
CaseSensitive bool `gorm:"default:false" json:"caseSensitive"` // 区分大小写
MatchWholeWords bool `gorm:"default:false" json:"matchWholeWords"` // 全词匹配
Selective bool `gorm:"default:false" json:"selective"` // 是否需要次要关键词
SelectiveLogic int `gorm:"default:0" json:"selectiveLogic"` // 0=AND, 1=NOT
// 注入位置与优先级
Position int `gorm:"default:1" json:"position"` // 0=系统提示词前, 1=系统提示词后, 4=指定深度
Depth int `gorm:"default:4" json:"depth"` // position=4 时生效
Order int `gorm:"default:100" json:"order"` // 同位置时的排序
// 概率与触发控制SillyTavern 兼容字段)
Probability int `gorm:"default:100" json:"probability"` // 触发概率 0-100
ScanDepth int `gorm:"default:2" json:"scanDepth"` // 扫描最近 N 条消息0=全部)
GroupID string `gorm:"type:varchar(100)" json:"groupId"` // 条目分组
// 扩展字段
Extensions datatypes.JSON `gorm:"type:jsonb" json:"extensions"`
}
func (WorldbookEntry) TableName() string {
return "worldbook_entries"
}