mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-10 22:33:48 +02:00
Add files via upload
This commit is contained in:
@@ -1234,9 +1234,20 @@ func (db *DB) GetProcessDetailByID(id string) (*ProcessDetail, error) {
|
||||
|
||||
// ProcessDetailsSummary 过程详情摘要(用于折叠态展示,避免全量加载)。
|
||||
type ProcessDetailsSummary struct {
|
||||
Total int `json:"total"`
|
||||
IterationCount int `json:"iterationCount"`
|
||||
MaxIteration int `json:"maxIteration"`
|
||||
Total int `json:"total"`
|
||||
IterationCount int `json:"iterationCount"`
|
||||
MaxIteration int `json:"maxIteration"`
|
||||
ToolCount int `json:"toolCount"`
|
||||
ToolExecutions []ProcessDetailsToolExecution `json:"toolExecutions,omitempty"`
|
||||
MCPExecutionIDs []string `json:"mcpExecutionIds,omitempty"`
|
||||
}
|
||||
|
||||
type ProcessDetailsToolExecution struct {
|
||||
ProcessDetailID string `json:"processDetailId,omitempty"`
|
||||
ToolName string `json:"toolName,omitempty"`
|
||||
ToolCallID string `json:"toolCallId,omitempty"`
|
||||
ExecutionID string `json:"executionId,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// GetProcessDetailsSummary 统计消息的过程详情数量与迭代轮次。
|
||||
@@ -1254,6 +1265,110 @@ func (db *DB) GetProcessDetailsSummary(messageID string) (*ProcessDetailsSummary
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
if err := db.QueryRow(
|
||||
"SELECT COUNT(*) FROM process_details WHERE message_id = ? AND event_type = 'tool_call'",
|
||||
messageID,
|
||||
).Scan(&summary.ToolCount); err != nil {
|
||||
return nil, fmt.Errorf("统计工具调用详情失败: %w", err)
|
||||
}
|
||||
|
||||
execRows, err := db.Query(
|
||||
"SELECT id, event_type, data FROM process_details WHERE message_id = ? AND event_type IN ('tool_call', 'tool_result') ORDER BY created_at ASC, rowid ASC",
|
||||
messageID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询工具执行摘要失败: %w", err)
|
||||
}
|
||||
seenExecIDs := make(map[string]bool)
|
||||
toolIndexByCallID := make(map[string]int)
|
||||
unmatchedToolIdx := 0
|
||||
for execRows.Next() {
|
||||
var detailID string
|
||||
var eventType string
|
||||
var dataJSON string
|
||||
if err := execRows.Scan(&detailID, &eventType, &dataJSON); err != nil {
|
||||
execRows.Close()
|
||||
return nil, fmt.Errorf("扫描工具执行摘要失败: %w", err)
|
||||
}
|
||||
if dataJSON == "" {
|
||||
continue
|
||||
}
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(dataJSON), &payload); err != nil {
|
||||
continue
|
||||
}
|
||||
toolName, _ := payload["toolName"].(string)
|
||||
toolName = strings.TrimSpace(toolName)
|
||||
toolCallID, _ := payload["toolCallId"].(string)
|
||||
toolCallID = strings.TrimSpace(toolCallID)
|
||||
execID, _ := payload["executionId"].(string)
|
||||
execID = strings.TrimSpace(execID)
|
||||
status := ""
|
||||
if eventType == "tool_result" {
|
||||
if success, ok := payload["success"].(bool); ok {
|
||||
if success {
|
||||
status = "completed"
|
||||
} else {
|
||||
status = "failed"
|
||||
}
|
||||
} else if isErr, ok := payload["isError"].(bool); ok && isErr {
|
||||
status = "failed"
|
||||
}
|
||||
}
|
||||
if eventType == "tool_call" {
|
||||
summary.ToolExecutions = append(summary.ToolExecutions, ProcessDetailsToolExecution{
|
||||
ProcessDetailID: strings.TrimSpace(detailID),
|
||||
ToolName: toolName,
|
||||
ToolCallID: toolCallID,
|
||||
Status: "running",
|
||||
})
|
||||
if toolCallID != "" {
|
||||
toolIndexByCallID[toolCallID] = len(summary.ToolExecutions) - 1
|
||||
}
|
||||
}
|
||||
if eventType == "tool_result" {
|
||||
idx := -1
|
||||
if toolCallID != "" {
|
||||
if found, ok := toolIndexByCallID[toolCallID]; ok {
|
||||
idx = found
|
||||
}
|
||||
}
|
||||
if idx < 0 && unmatchedToolIdx < len(summary.ToolExecutions) {
|
||||
idx = unmatchedToolIdx
|
||||
unmatchedToolIdx++
|
||||
}
|
||||
if idx >= 0 && idx < len(summary.ToolExecutions) {
|
||||
if summary.ToolExecutions[idx].ToolName == "" {
|
||||
summary.ToolExecutions[idx].ToolName = toolName
|
||||
}
|
||||
if summary.ToolExecutions[idx].ToolCallID == "" {
|
||||
summary.ToolExecutions[idx].ToolCallID = toolCallID
|
||||
}
|
||||
summary.ToolExecutions[idx].ExecutionID = execID
|
||||
if status != "" {
|
||||
summary.ToolExecutions[idx].Status = status
|
||||
}
|
||||
} else {
|
||||
summary.ToolExecutions = append(summary.ToolExecutions, ProcessDetailsToolExecution{
|
||||
ProcessDetailID: strings.TrimSpace(detailID),
|
||||
ToolName: toolName,
|
||||
ToolCallID: toolCallID,
|
||||
ExecutionID: execID,
|
||||
Status: status,
|
||||
})
|
||||
}
|
||||
}
|
||||
if execID != "" && !seenExecIDs[execID] {
|
||||
seenExecIDs[execID] = true
|
||||
summary.MCPExecutionIDs = append(summary.MCPExecutionIDs, execID)
|
||||
}
|
||||
}
|
||||
if err := execRows.Err(); err != nil {
|
||||
execRows.Close()
|
||||
return nil, fmt.Errorf("遍历工具执行摘要失败: %w", err)
|
||||
}
|
||||
execRows.Close()
|
||||
|
||||
rows, err := db.Query(
|
||||
"SELECT data FROM process_details WHERE message_id = ? AND event_type = 'iteration' ORDER BY created_at ASC, rowid ASC",
|
||||
messageID,
|
||||
@@ -1333,6 +1448,36 @@ func (db *DB) GetProcessDetailsPage(messageID string, limit, offset int) ([]Proc
|
||||
return details, total, nil
|
||||
}
|
||||
|
||||
// GetProcessDetailOffset 返回某条过程详情在所属消息详情流中的零基 offset。
|
||||
func (db *DB) GetProcessDetailOffset(messageID, detailID string) (int, error) {
|
||||
messageID = strings.TrimSpace(messageID)
|
||||
detailID = strings.TrimSpace(detailID)
|
||||
if messageID == "" || detailID == "" {
|
||||
return 0, fmt.Errorf("messageID and detailID are required")
|
||||
}
|
||||
var createdAt string
|
||||
var rowID int64
|
||||
if err := db.QueryRow(
|
||||
"SELECT created_at, rowid FROM process_details WHERE message_id = ? AND id = ?",
|
||||
messageID, detailID,
|
||||
).Scan(&createdAt, &rowID); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return 0, fmt.Errorf("过程详情不存在")
|
||||
}
|
||||
return 0, fmt.Errorf("查询过程详情锚点失败: %w", err)
|
||||
}
|
||||
var offset int
|
||||
if err := db.QueryRow(
|
||||
`SELECT COUNT(*) FROM process_details
|
||||
WHERE message_id = ?
|
||||
AND (created_at < ? OR (created_at = ? AND rowid < ?))`,
|
||||
messageID, createdAt, createdAt, rowID,
|
||||
).Scan(&offset); err != nil {
|
||||
return 0, fmt.Errorf("计算过程详情锚点位置失败: %w", err)
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// GetProcessDetailsByConversation 获取对话的所有过程详情(按消息分组)
|
||||
func (db *DB) GetProcessDetailsByConversation(conversationID string) (map[string][]ProcessDetail, error) {
|
||||
rows, err := db.Query(
|
||||
|
||||
Reference in New Issue
Block a user