mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-05-28 02:02:27 +02:00
79 lines
2.4 KiB
Go
79 lines
2.4 KiB
Go
package project
|
||
|
||
import (
|
||
"fmt"
|
||
"sort"
|
||
"strings"
|
||
|
||
"cyberstrike-ai/internal/config"
|
||
"cyberstrike-ai/internal/database"
|
||
)
|
||
|
||
// AppendSystemPromptBlock 将附加块追加到 system prompt。
|
||
func AppendSystemPromptBlock(base, block string) string {
|
||
base = strings.TrimSpace(base)
|
||
block = strings.TrimSpace(block)
|
||
if block == "" {
|
||
return base
|
||
}
|
||
if base == "" {
|
||
return block
|
||
}
|
||
return base + "\n\n" + block
|
||
}
|
||
|
||
// BuildFactIndexBlock 为 Agent 系统提示生成项目黑板索引(仅 key + summary,不含 body)。
|
||
func BuildFactIndexBlock(db *database.DB, projectID string, cfg config.ProjectConfig) (string, error) {
|
||
if db == nil || !cfg.Enabled {
|
||
return "", nil
|
||
}
|
||
projectID = strings.TrimSpace(projectID)
|
||
if projectID == "" {
|
||
return "", nil
|
||
}
|
||
|
||
proj, err := db.GetProject(projectID)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
facts, err := db.ListProjectFactsForIndex(projectID, cfg.DefaultInjectDeprecated)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if len(facts) == 0 {
|
||
return fmt.Sprintf("## 项目黑板索引(project: %s, id: %s)\n(暂无事实)\n需要写入请使用 upsert_project_fact;需要详情请调用 get_project_fact(fact_key)。", proj.Name, proj.ID), nil
|
||
}
|
||
|
||
sort.SliceStable(facts, func(i, j int) bool {
|
||
if facts[i].Pinned != facts[j].Pinned {
|
||
return facts[i].Pinned
|
||
}
|
||
return facts[i].UpdatedAt.After(facts[j].UpdatedAt)
|
||
})
|
||
|
||
maxRunes := cfg.FactIndexMaxRunesEffective()
|
||
var b strings.Builder
|
||
b.WriteString(fmt.Sprintf("## 项目黑板索引(project: %s, id: %s)\n", proj.Name, proj.ID))
|
||
used := len([]rune(b.String()))
|
||
omitted := 0
|
||
|
||
for _, f := range facts {
|
||
line := fmt.Sprintf("- [%s] %s — %s (%s)\n", f.FactKey, f.Category, strings.TrimSpace(f.Summary), f.Confidence)
|
||
lineRunes := len([]rune(line))
|
||
if used+lineRunes > maxRunes {
|
||
omitted++
|
||
continue
|
||
}
|
||
b.WriteString(line)
|
||
used += lineRunes
|
||
}
|
||
|
||
if omitted > 0 {
|
||
b.WriteString(fmt.Sprintf("\n(另有 %d 条未列入索引,请使用 list_project_facts 或 search_project_facts 查询。)\n", omitted))
|
||
}
|
||
b.WriteString("需要完整内容(攻击链、POC、请求响应等)时必须调用 get_project_fact(fact_key),禁止凭摘要臆造细节。\n")
|
||
b.WriteString("写入事实时:summary 写「什么+在哪+如何验证」;body 写可复现全流程(发现/利用类 fact_key 建议 finding|chain|exploit|poc/ 前缀)。\n")
|
||
return b.String(), nil
|
||
}
|