mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-01 10:15:37 +02:00
Add files via upload
This commit is contained in:
@@ -1283,6 +1283,12 @@ func (a *Agent) UpdateConfig(cfg *config.OpenAIConfig) {
|
|||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
defer a.mu.Unlock()
|
defer a.mu.Unlock()
|
||||||
a.config = cfg
|
a.config = cfg
|
||||||
|
|
||||||
|
// 同时更新MemoryCompressor的配置(如果存在)
|
||||||
|
if a.memoryCompressor != nil {
|
||||||
|
a.memoryCompressor.UpdateConfig(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
a.logger.Info("Agent配置已更新",
|
a.logger.Info("Agent配置已更新",
|
||||||
zap.String("base_url", cfg.BaseURL),
|
zap.String("base_url", cfg.BaseURL),
|
||||||
zap.String("model", cfg.Model),
|
zap.String("model", cfg.Model),
|
||||||
|
|||||||
@@ -138,6 +138,26 @@ func NewMemoryCompressor(cfg MemoryCompressorConfig) (*MemoryCompressor, error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateConfig 更新OpenAI配置(用于动态更新模型配置)
|
||||||
|
func (mc *MemoryCompressor) UpdateConfig(cfg *config.OpenAIConfig) {
|
||||||
|
if cfg == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新summaryModel字段
|
||||||
|
if cfg.Model != "" {
|
||||||
|
mc.summaryModel = cfg.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新completionClient中的配置(如果是OpenAICompletionClient)
|
||||||
|
if openAIClient, ok := mc.completionClient.(*OpenAICompletionClient); ok {
|
||||||
|
openAIClient.config = cfg
|
||||||
|
mc.logger.Info("MemoryCompressor配置已更新",
|
||||||
|
zap.String("model", cfg.Model),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CompressHistory 根据Token限制压缩历史消息。
|
// CompressHistory 根据Token限制压缩历史消息。
|
||||||
func (mc *MemoryCompressor) CompressHistory(ctx context.Context, messages []ChatMessage) ([]ChatMessage, bool, error) {
|
func (mc *MemoryCompressor) CompressHistory(ctx context.Context, messages []ChatMessage) ([]ChatMessage, bool, error) {
|
||||||
if len(messages) == 0 {
|
if len(messages) == 0 {
|
||||||
@@ -238,11 +258,24 @@ func (mc *MemoryCompressor) countTotalTokens(systemMsgs, regularMsgs []ChatMessa
|
|||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getModelName 获取当前使用的模型名称(优先从completionClient获取最新配置)
|
||||||
|
func (mc *MemoryCompressor) getModelName() string {
|
||||||
|
// 如果completionClient是OpenAICompletionClient,从它获取最新的模型名称
|
||||||
|
if openAIClient, ok := mc.completionClient.(*OpenAICompletionClient); ok {
|
||||||
|
if openAIClient.config != nil && openAIClient.config.Model != "" {
|
||||||
|
return openAIClient.config.Model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 否则使用保存的summaryModel
|
||||||
|
return mc.summaryModel
|
||||||
|
}
|
||||||
|
|
||||||
func (mc *MemoryCompressor) countTokens(text string) int {
|
func (mc *MemoryCompressor) countTokens(text string) int {
|
||||||
if mc.tokenCounter == nil {
|
if mc.tokenCounter == nil {
|
||||||
return len(text) / 4
|
return len(text) / 4
|
||||||
}
|
}
|
||||||
count, err := mc.tokenCounter.Count(mc.summaryModel, text)
|
modelName := mc.getModelName()
|
||||||
|
count, err := mc.tokenCounter.Count(modelName, text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(text) / 4
|
return len(text) / 4
|
||||||
}
|
}
|
||||||
@@ -269,7 +302,9 @@ func (mc *MemoryCompressor) summarizeChunk(ctx context.Context, chunk []ChatMess
|
|||||||
conversation := strings.Join(formatted, "\n")
|
conversation := strings.Join(formatted, "\n")
|
||||||
prompt := fmt.Sprintf(summaryPromptTemplate, conversation)
|
prompt := fmt.Sprintf(summaryPromptTemplate, conversation)
|
||||||
|
|
||||||
summary, err := mc.completionClient.Complete(ctx, mc.summaryModel, prompt, mc.timeout)
|
// 使用动态获取的模型名称,而不是保存的summaryModel
|
||||||
|
modelName := mc.getModelName()
|
||||||
|
summary, err := mc.completionClient.Complete(ctx, modelName, prompt, mc.timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ChatMessage{}, err
|
return ChatMessage{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -128,9 +128,9 @@ func New(cfg *config.Config, log *logger.Logger) (*App, error) {
|
|||||||
monitorHandler.SetExternalMCPManager(externalMCPMgr) // 设置外部MCP管理器,以便获取外部MCP执行记录
|
monitorHandler.SetExternalMCPManager(externalMCPMgr) // 设置外部MCP管理器,以便获取外部MCP执行记录
|
||||||
conversationHandler := handler.NewConversationHandler(db, log.Logger)
|
conversationHandler := handler.NewConversationHandler(db, log.Logger)
|
||||||
authHandler := handler.NewAuthHandler(authManager, cfg, configPath, log.Logger)
|
authHandler := handler.NewAuthHandler(authManager, cfg, configPath, log.Logger)
|
||||||
configHandler := handler.NewConfigHandler(configPath, cfg, mcpServer, executor, agent, externalMCPMgr, log.Logger)
|
|
||||||
externalMCPHandler := handler.NewExternalMCPHandler(externalMCPMgr, cfg, configPath, log.Logger)
|
|
||||||
attackChainHandler := handler.NewAttackChainHandler(db, &cfg.OpenAI, log.Logger)
|
attackChainHandler := handler.NewAttackChainHandler(db, &cfg.OpenAI, log.Logger)
|
||||||
|
configHandler := handler.NewConfigHandler(configPath, cfg, mcpServer, executor, agent, attackChainHandler, externalMCPMgr, log.Logger)
|
||||||
|
externalMCPHandler := handler.NewExternalMCPHandler(externalMCPMgr, cfg, configPath, log.Logger)
|
||||||
|
|
||||||
// 设置路由
|
// 设置路由
|
||||||
setupRoutes(
|
setupRoutes(
|
||||||
|
|||||||
@@ -74,15 +74,15 @@ func (db *DB) GetConversation(id string) (*Conversation, error) {
|
|||||||
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05", createdAt)
|
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
}
|
}
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
conv.CreatedAt, err1 = time.Parse(time.RFC3339, createdAt)
|
conv.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05.999999999-07:00", updatedAt)
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05.999999999-07:00", updatedAt)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05", updatedAt)
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05", updatedAt)
|
||||||
}
|
}
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
conv.UpdatedAt, err2 = time.Parse(time.RFC3339, updatedAt)
|
conv.UpdatedAt, _ = time.Parse(time.RFC3339, updatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载消息
|
// 加载消息
|
||||||
@@ -155,17 +155,17 @@ func (db *DB) ListConversations(limit, offset int) ([]*Conversation, error) {
|
|||||||
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05", createdAt)
|
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
}
|
}
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
conv.CreatedAt, err1 = time.Parse(time.RFC3339, createdAt)
|
conv.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05.999999999-07:00", updatedAt)
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05.999999999-07:00", updatedAt)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05", updatedAt)
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05", updatedAt)
|
||||||
}
|
}
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
conv.UpdatedAt, err2 = time.Parse(time.RFC3339, updatedAt)
|
conv.UpdatedAt, _ = time.Parse(time.RFC3339, updatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
conversations = append(conversations, &conv)
|
conversations = append(conversations, &conv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ func (db *DB) DeleteConversation(id string) error {
|
|||||||
// AddMessage 添加消息
|
// AddMessage 添加消息
|
||||||
func (db *DB) AddMessage(conversationID, role, content string, mcpExecutionIDs []string) (*Message, error) {
|
func (db *DB) AddMessage(conversationID, role, content string, mcpExecutionIDs []string) (*Message, error) {
|
||||||
id := uuid.New().String()
|
id := uuid.New().String()
|
||||||
|
|
||||||
var mcpIDsJSON string
|
var mcpIDsJSON string
|
||||||
if len(mcpExecutionIDs) > 0 {
|
if len(mcpExecutionIDs) > 0 {
|
||||||
jsonData, err := json.Marshal(mcpExecutionIDs)
|
jsonData, err := json.Marshal(mcpExecutionIDs)
|
||||||
@@ -272,7 +272,7 @@ func (db *DB) GetMessages(conversationID string) ([]Message, error) {
|
|||||||
msg.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
msg.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
|
msg.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析MCP执行ID
|
// 解析MCP执行ID
|
||||||
@@ -290,19 +290,19 @@ func (db *DB) GetMessages(conversationID string) ([]Message, error) {
|
|||||||
|
|
||||||
// ProcessDetail 过程详情事件
|
// ProcessDetail 过程详情事件
|
||||||
type ProcessDetail struct {
|
type ProcessDetail struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
MessageID string `json:"messageId"`
|
MessageID string `json:"messageId"`
|
||||||
ConversationID string `json:"conversationId"`
|
ConversationID string `json:"conversationId"`
|
||||||
EventType string `json:"eventType"` // iteration, thinking, tool_calls_detected, tool_call, tool_result, progress, error
|
EventType string `json:"eventType"` // iteration, thinking, tool_calls_detected, tool_call, tool_result, progress, error
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Data string `json:"data"` // JSON格式的数据
|
Data string `json:"data"` // JSON格式的数据
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddProcessDetail 添加过程详情事件
|
// AddProcessDetail 添加过程详情事件
|
||||||
func (db *DB) AddProcessDetail(messageID, conversationID, eventType, message string, data interface{}) error {
|
func (db *DB) AddProcessDetail(messageID, conversationID, eventType, message string, data interface{}) error {
|
||||||
id := uuid.New().String()
|
id := uuid.New().String()
|
||||||
|
|
||||||
var dataJSON string
|
var dataJSON string
|
||||||
if data != nil {
|
if data != nil {
|
||||||
jsonData, err := json.Marshal(data)
|
jsonData, err := json.Marshal(data)
|
||||||
@@ -351,7 +351,7 @@ func (db *DB) GetProcessDetails(messageID string) ([]ProcessDetail, error) {
|
|||||||
detail.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
detail.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
detail.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
|
detail.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
details = append(details, detail)
|
details = append(details, detail)
|
||||||
@@ -387,7 +387,7 @@ func (db *DB) GetProcessDetailsByConversation(conversationID string) (map[string
|
|||||||
detail.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
detail.CreatedAt, err = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
detail.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
|
detail.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
detailsMap[detail.MessageID] = append(detailsMap[detail.MessageID], detail)
|
detailsMap[detail.MessageID] = append(detailsMap[detail.MessageID], detail)
|
||||||
@@ -395,4 +395,3 @@ func (db *DB) GetProcessDetailsByConversation(conversationID string) (map[string
|
|||||||
|
|
||||||
return detailsMap, nil
|
return detailsMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type AttackChainHandler struct {
|
|||||||
db *database.DB
|
db *database.DB
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
openAIConfig *config.OpenAIConfig
|
openAIConfig *config.OpenAIConfig
|
||||||
|
mu sync.RWMutex // 保护 openAIConfig 的并发访问
|
||||||
// 用于防止同一对话的并发生成
|
// 用于防止同一对话的并发生成
|
||||||
generatingLocks sync.Map // map[string]*sync.Mutex
|
generatingLocks sync.Map // map[string]*sync.Mutex
|
||||||
}
|
}
|
||||||
@@ -32,6 +33,24 @@ func NewAttackChainHandler(db *database.DB, openAIConfig *config.OpenAIConfig, l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateConfig 更新OpenAI配置
|
||||||
|
func (h *AttackChainHandler) UpdateConfig(cfg *config.OpenAIConfig) {
|
||||||
|
h.mu.Lock()
|
||||||
|
defer h.mu.Unlock()
|
||||||
|
h.openAIConfig = cfg
|
||||||
|
h.logger.Info("AttackChainHandler配置已更新",
|
||||||
|
zap.String("base_url", cfg.BaseURL),
|
||||||
|
zap.String("model", cfg.Model),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getOpenAIConfig 获取OpenAI配置(线程安全)
|
||||||
|
func (h *AttackChainHandler) getOpenAIConfig() *config.OpenAIConfig {
|
||||||
|
h.mu.RLock()
|
||||||
|
defer h.mu.RUnlock()
|
||||||
|
return h.openAIConfig
|
||||||
|
}
|
||||||
|
|
||||||
// GetAttackChain 获取攻击链(按需生成)
|
// GetAttackChain 获取攻击链(按需生成)
|
||||||
// GET /api/attack-chain/:conversationId
|
// GET /api/attack-chain/:conversationId
|
||||||
func (h *AttackChainHandler) GetAttackChain(c *gin.Context) {
|
func (h *AttackChainHandler) GetAttackChain(c *gin.Context) {
|
||||||
@@ -50,7 +69,8 @@ func (h *AttackChainHandler) GetAttackChain(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 先尝试从数据库加载(如果已生成过)
|
// 先尝试从数据库加载(如果已生成过)
|
||||||
builder := attackchain.NewBuilder(h.db, h.openAIConfig, h.logger)
|
openAIConfig := h.getOpenAIConfig()
|
||||||
|
builder := attackchain.NewBuilder(h.db, openAIConfig, h.logger)
|
||||||
chain, err := builder.LoadChainFromDatabase(conversationID)
|
chain, err := builder.LoadChainFromDatabase(conversationID)
|
||||||
if err == nil && len(chain.Nodes) > 0 {
|
if err == nil && len(chain.Nodes) > 0 {
|
||||||
// 如果已存在,直接返回
|
// 如果已存在,直接返回
|
||||||
@@ -139,7 +159,8 @@ func (h *AttackChainHandler) RegenerateAttackChain(c *gin.Context) {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
builder := attackchain.NewBuilder(h.db, h.openAIConfig, h.logger)
|
openAIConfig := h.getOpenAIConfig()
|
||||||
|
builder := attackchain.NewBuilder(h.db, openAIConfig, h.logger)
|
||||||
chain, err := builder.BuildChainFromConversation(ctx, conversationID)
|
chain, err := builder.BuildChainFromConversation(ctx, conversationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("生成攻击链失败", zap.String("conversationId", conversationID), zap.Error(err))
|
h.logger.Error("生成攻击链失败", zap.String("conversationId", conversationID), zap.Error(err))
|
||||||
|
|||||||
+29
-16
@@ -22,14 +22,20 @@ import (
|
|||||||
|
|
||||||
// ConfigHandler 配置处理器
|
// ConfigHandler 配置处理器
|
||||||
type ConfigHandler struct {
|
type ConfigHandler struct {
|
||||||
configPath string
|
configPath string
|
||||||
config *config.Config
|
config *config.Config
|
||||||
mcpServer *mcp.Server
|
mcpServer *mcp.Server
|
||||||
executor *security.Executor
|
executor *security.Executor
|
||||||
agent AgentUpdater // Agent接口,用于更新Agent配置
|
agent AgentUpdater // Agent接口,用于更新Agent配置
|
||||||
externalMCPMgr *mcp.ExternalMCPManager // 外部MCP管理器
|
attackChainHandler AttackChainUpdater // 攻击链处理器接口,用于更新配置
|
||||||
logger *zap.Logger
|
externalMCPMgr *mcp.ExternalMCPManager // 外部MCP管理器
|
||||||
mu sync.RWMutex
|
logger *zap.Logger
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttackChainUpdater 攻击链处理器更新接口
|
||||||
|
type AttackChainUpdater interface {
|
||||||
|
UpdateConfig(cfg *config.OpenAIConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AgentUpdater Agent更新接口
|
// AgentUpdater Agent更新接口
|
||||||
@@ -39,15 +45,16 @@ type AgentUpdater interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewConfigHandler 创建新的配置处理器
|
// NewConfigHandler 创建新的配置处理器
|
||||||
func NewConfigHandler(configPath string, cfg *config.Config, mcpServer *mcp.Server, executor *security.Executor, agent AgentUpdater, externalMCPMgr *mcp.ExternalMCPManager, logger *zap.Logger) *ConfigHandler {
|
func NewConfigHandler(configPath string, cfg *config.Config, mcpServer *mcp.Server, executor *security.Executor, agent AgentUpdater, attackChainHandler AttackChainUpdater, externalMCPMgr *mcp.ExternalMCPManager, logger *zap.Logger) *ConfigHandler {
|
||||||
return &ConfigHandler{
|
return &ConfigHandler{
|
||||||
configPath: configPath,
|
configPath: configPath,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
mcpServer: mcpServer,
|
mcpServer: mcpServer,
|
||||||
executor: executor,
|
executor: executor,
|
||||||
agent: agent,
|
agent: agent,
|
||||||
externalMCPMgr: externalMCPMgr,
|
attackChainHandler: attackChainHandler,
|
||||||
logger: logger,
|
externalMCPMgr: externalMCPMgr,
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,6 +529,12 @@ func (h *ConfigHandler) ApplyConfig(c *gin.Context) {
|
|||||||
h.logger.Info("Agent配置已更新")
|
h.logger.Info("Agent配置已更新")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新AttackChainHandler的OpenAI配置
|
||||||
|
if h.attackChainHandler != nil {
|
||||||
|
h.attackChainHandler.UpdateConfig(&h.config.OpenAI)
|
||||||
|
h.logger.Info("AttackChainHandler配置已更新")
|
||||||
|
}
|
||||||
|
|
||||||
h.logger.Info("配置已应用",
|
h.logger.Info("配置已应用",
|
||||||
zap.Int("tools_count", len(h.config.Security.Tools)),
|
zap.Int("tools_count", len(h.config.Security.Tools)),
|
||||||
)
|
)
|
||||||
|
|||||||
+22
-3
@@ -506,7 +506,7 @@ function initializeChatUI() {
|
|||||||
let messageCounter = 0;
|
let messageCounter = 0;
|
||||||
|
|
||||||
// 添加消息
|
// 添加消息
|
||||||
function addMessage(role, content, mcpExecutionIds = null, progressId = null) {
|
function addMessage(role, content, mcpExecutionIds = null, progressId = null, createdAt = null) {
|
||||||
const messagesDiv = document.getElementById('chat-messages');
|
const messagesDiv = document.getElementById('chat-messages');
|
||||||
const messageDiv = document.createElement('div');
|
const messageDiv = document.createElement('div');
|
||||||
messageCounter++;
|
messageCounter++;
|
||||||
@@ -582,7 +582,25 @@ function addMessage(role, content, mcpExecutionIds = null, progressId = null) {
|
|||||||
// 添加时间戳
|
// 添加时间戳
|
||||||
const timeDiv = document.createElement('div');
|
const timeDiv = document.createElement('div');
|
||||||
timeDiv.className = 'message-time';
|
timeDiv.className = 'message-time';
|
||||||
timeDiv.textContent = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
|
// 如果有传入的创建时间,使用它;否则使用当前时间
|
||||||
|
let messageTime;
|
||||||
|
if (createdAt) {
|
||||||
|
// 处理字符串或Date对象
|
||||||
|
if (typeof createdAt === 'string') {
|
||||||
|
messageTime = new Date(createdAt);
|
||||||
|
} else if (createdAt instanceof Date) {
|
||||||
|
messageTime = createdAt;
|
||||||
|
} else {
|
||||||
|
messageTime = new Date(createdAt);
|
||||||
|
}
|
||||||
|
// 如果解析失败,使用当前时间
|
||||||
|
if (isNaN(messageTime.getTime())) {
|
||||||
|
messageTime = new Date();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageTime = new Date();
|
||||||
|
}
|
||||||
|
timeDiv.textContent = messageTime.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
|
||||||
contentWrapper.appendChild(timeDiv);
|
contentWrapper.appendChild(timeDiv);
|
||||||
|
|
||||||
// 如果有MCP执行ID或进度ID,添加查看详情区域(统一使用"渗透测试详情"样式)
|
// 如果有MCP执行ID或进度ID,添加查看详情区域(统一使用"渗透测试详情"样式)
|
||||||
@@ -1088,7 +1106,8 @@ async function loadConversation(conversationId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageId = addMessage(msg.role, displayContent, msg.mcpExecutionIds || []);
|
// 传递消息的创建时间
|
||||||
|
const messageId = addMessage(msg.role, displayContent, msg.mcpExecutionIds || [], null, msg.createdAt);
|
||||||
// 如果有过程详情,显示它们
|
// 如果有过程详情,显示它们
|
||||||
if (msg.processDetails && msg.processDetails.length > 0 && msg.role === 'assistant') {
|
if (msg.processDetails && msg.processDetails.length > 0 && msg.role === 'assistant') {
|
||||||
// 延迟一下,确保消息已经渲染
|
// 延迟一下,确保消息已经渲染
|
||||||
|
|||||||
Reference in New Issue
Block a user