Files
ai_site/platform/internal/logic/applogic/agent_sync_bind.go
whm 4b6c90904b fix: Z35 map Chinese display names to stable physical DB names
Keep Chinese on Binding for UI; Agents use user_{id} or db{hash}; sanitize on attach/heal/publish.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 02:12:55 +08:00

108 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package applogic
import (
"fmt"
"strings"
"aijianzhan/platform/internal/agentstore"
"aijianzhan/platform/internal/dbsync"
"aijianzhan/platform/internal/schema"
"aijianzhan/platform/internal/svc"
"aijianzhan/platform/internal/types"
"aijianzhan/platform/internal/userstore"
)
// fillAgentSyncOnToken Z12a换票带回同步落点。
func fillAgentSyncOnToken(resp *types.TokenResp, acc *agentstore.Account) {
if resp == nil || acc == nil {
return
}
resp.ChannelID = strings.TrimSpace(acc.ChannelID)
resp.OnlineDBID = strings.TrimSpace(acc.OnlineDBID)
resp.DatabaseName = strings.TrimSpace(acc.DatabaseName)
if resp.DatabaseName != "" && !schema.ValidDBName(resp.DatabaseName) {
resp.DatabaseName = ""
}
resp.SyncBound = resp.ChannelID != "" && resp.OnlineDBID != ""
}
// fillUserSyncOnToken人类登录优先从本人 Binding 带回落点。
func fillUserSyncOnToken(svcCtx *svc.ServiceContext, resp *types.TokenResp, u *userstore.User) {
if resp == nil || u == nil || svcCtx == nil || svcCtx.DBSync == nil || u.TenantID <= 0 {
return
}
list, err := svcCtx.DBSync.Store().ListBindingsFiltered(u.TenantID, u.UserID, "")
if err != nil || len(list) == 0 {
return
}
b := list[0]
for i := range list {
if list[i].ChannelID != "" && list[i].OnlineDBID != "" {
b = list[i]
break
}
}
resp.ChannelID = strings.TrimSpace(b.ChannelID)
resp.OnlineDBID = strings.TrimSpace(b.OnlineDBID)
// Z35database_name 仅物理库名;勿把中文 DisplayName 填进该字段
resp.DatabaseName = strings.TrimSpace(b.DatabaseName)
if resp.DatabaseName != "" && !schema.ValidDBName(resp.DatabaseName) {
resp.DatabaseName = ""
}
resp.SyncBound = resp.ChannelID != "" && resp.OnlineDBID != ""
}
// ensureAgentSyncBind Z12c/Z12h无通道或通道已删除时创建/复用默认同步通道并写回智能体。
func (l *AgentAdminLogic) ensureAgentSyncBind(acc *agentstore.Account) (*agentstore.Account, error) {
if acc == nil {
return nil, fmt.Errorf("agent nil")
}
if l.svcCtx.DBSync == nil {
return acc, nil
}
alive := channelAlive(l.svcCtx.DBSync.Store(), acc.TenantID, acc.ChannelID)
if alive && strings.TrimSpace(acc.OnlineDBID) != "" {
return acc, nil
}
if _, err := HealTenantSyncBind(l.ctx, l.svcCtx, acc.TenantID); err != nil {
return nil, fmt.Errorf("heal sync bind: %w", err)
}
st, err := l.store()
if err != nil {
return nil, err
}
updated, err := st.Get(l.ctx, acc.TenantID, acc.AgentID)
if err != nil {
return nil, err
}
// 若 heal 未覆盖该智能体(例如无 Binding 仅 Agent再显式挂一次
if !channelAlive(l.svcCtx.DBSync.Store(), updated.TenantID, updated.ChannelID) || strings.TrimSpace(updated.OnlineDBID) == "" {
cfg := l.svcCtx.Config.DBSync
driver := dbsync.Driver(strings.TrimSpace(cfg.DefaultRemoteDriver))
if driver == "" {
driver = dbsync.DriverPostgres
}
ch, err := l.svcCtx.DBSync.EnsureAndStartSystemDefaultChannel(dbsync.DefaultChannelOpts{
TenantID: acc.TenantID,
AgentID: acc.AgentID,
Name: fmt.Sprintf("默认同步 · %s", acc.Name),
RemoteDriver: driver,
RemoteDSN: strings.TrimSpace(cfg.DefaultRemoteDSN),
DatabaseName: acc.DatabaseName,
})
if err != nil {
return nil, fmt.Errorf("ensure default channel: %w", err)
}
online := strings.TrimSpace(updated.OnlineDBID)
if online == "" {
online = dbsync.ResolveOnlineDBID("", ch.ID)
}
dbName := schema.SafeSyncDatabaseName(updated.DatabaseName, updated.AgentID, 0)
updated, err = st.AttachSyncBind(l.ctx, updated.AgentID, updated.TenantID, ch.ID, online, dbName, updated.Status == agentstore.StatusActive || updated.Status == "")
if err != nil {
return nil, err
}
}
return updated, nil
}