mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-20 22:41:23 +02:00
Attack chain: failure text goes to textContent, so opt out of i18next interpolation escaping that rendered upstream errors as //"; give regenerate its own message key; keep the summary card expanded across a 409 refresh; probe for a cached graph before parsing last_react_input so polling no longer re-reads a multi-megabyte column; hide the card in the node-details exclusive state and bound it on narrow screens; drop the dead hardcoded Chinese title from the API payload. Blackboard: stop mirroring note/context-* keys into the fact body links section, which get_project_fact returns verbatim without scope filtering; single-line category and confidence in index rows so a newline cannot inject a fake row; make the path overview fail closed on an empty index set. Provenance: reuse fitUserIntentLedgerText when sanitizing a ledger entry so a single entry cannot exceed its cap by the three ellipsis runes. The .cjs harness now escapes interpolated values like real i18next, so the existing XSS test also pins the escapeValue opt-out.
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package attackchain
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"strings"
|
|
|
|
"cyberstrike-ai/internal/agent"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ContextSummary is read-only context from the conversation's latest persisted
|
|
// model trace. It is neither a graph node nor evidence of tool execution. A
|
|
// cached graph may predate this context; no snapshot files are opened here.
|
|
type ContextSummary struct {
|
|
ID string `json:"id"`
|
|
Content string `json:"content"`
|
|
Provenance string `json:"provenance"`
|
|
}
|
|
|
|
// contextSummaries always rereads the conversation's latest trace: a cached
|
|
// graph may predate it, so context must not be frozen for the Builder's lifetime.
|
|
func (b *Builder) contextSummaries(conversationID string) []ContextSummary {
|
|
trace, _, err := b.db.GetAgentTrace(conversationID)
|
|
if err != nil {
|
|
b.logger.Warn("加载攻击链上下文摘要失败", zap.String("conversationId", conversationID), zap.Error(err))
|
|
return nil
|
|
}
|
|
return b.contextSummariesFromTrace(trace)
|
|
}
|
|
|
|
func (b *Builder) contextSummariesFromTrace(trace string) []ContextSummary {
|
|
msgs, err := agent.ParseTraceMessages(trace)
|
|
if err != nil {
|
|
b.logger.Warn("解析攻击链上下文摘要失败", zap.Error(err))
|
|
return nil
|
|
}
|
|
var summaries []ContextSummary
|
|
seen := make(map[string]struct{})
|
|
for _, msg := range msgs {
|
|
// Require the host's allowlisted provenance. Human text, skills, and
|
|
// execution templates are never classified by matching their bodies.
|
|
if !strings.EqualFold(msg.Role, "user") || msg.SummarizationKind != "summary" || strings.TrimSpace(msg.Content) == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[msg.Content]; ok {
|
|
continue
|
|
}
|
|
seen[msg.Content] = struct{}{}
|
|
hash := sha256.Sum256([]byte(msg.Content))
|
|
summaries = append(summaries, ContextSummary{
|
|
ID: "summary-" + hex.EncodeToString(hash[:])[:16],
|
|
Content: msg.Content,
|
|
Provenance: "system_generated_summary",
|
|
})
|
|
}
|
|
return summaries
|
|
}
|