Files
Agent-System-Backend/internal/runmgr/material_sources_test.go

191 lines
9.9 KiB
Go
Raw Permalink 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 runmgr
import (
core "agent-system-core"
"regexp"
"strings"
"testing"
"time"
)
func TestMaterialSourceInlineAnnotationsPreserveProvidedPrefix(t *testing.T) {
d := materialDocs()[0]
d.Meta.Origin = &core.DocumentOrigin{ArtifactID: "art1", ContentHash: strings.Repeat("a", 64), ParserRevision: "docx1"}
docs := []core.ParsedDocument{d}
provided := strings.TrimSpace(d.PlainText())
got := annotateProvidedMaterial(d, provided, materialSources(docs, 48000))
markers := regexp.MustCompile(`(?m)^sourceId=src_[a-f0-9]+ blockIndex=[0-9]+\n`)
if !markers.MatchString(got) {
t.Fatal("provided block has no source marker")
}
if markers.ReplaceAllString(got, "") != provided {
t.Fatal("source annotations changed the provided material bytes")
}
}
func TestMaterialSourceInlineAnnotationsNeverExposeHiddenBlocks(t *testing.T) {
d := core.ParsedDocument{Meta: core.DocMeta{Filename: "资料.txt", Origin: &core.DocumentOrigin{ArtifactID: "art2", ContentHash: strings.Repeat("b", 64), ParserRevision: "txt1"}}, Blocks: []core.DocBlock{
{Type: core.BlockPara, Text: "上线六月"},
{Type: core.BlockPara, Text: "隐藏的审批结论"},
}}
provided := "上线六月"
got := annotateProvidedMaterial(d, provided, materialSources([]core.ParsedDocument{d}, 4))
if strings.Count(got, "sourceId=") != 1 || strings.Contains(got, "隐藏的审批结论") {
t.Fatalf("unprovided block received a marker or text: %q", got)
}
if strings.Count(got, provided) != 1 {
t.Fatalf("provided prefix was duplicated: %q", got)
}
}
func TestMaterialSourceInlineAnnotationsPreserveTableAndUntrustedText(t *testing.T) {
trusted := core.ParsedDocument{Meta: core.DocMeta{Filename: "预算.xlsx", Origin: &core.DocumentOrigin{ArtifactID: "table", ContentHash: strings.Repeat("d", 64), ParserRevision: "xlsx1"}}, Blocks: []core.DocBlock{{Type: core.BlockTable, Rows: [][]string{{"项目", "预算"}, {"一期", "50万元"}}}}}
provided := strings.TrimSpace(trusted.PlainText())
got := annotateProvidedMaterial(trusted, provided, materialSources([]core.ParsedDocument{trusted}, 48000))
markers := regexp.MustCompile(`(?m)^sourceId=src_[a-f0-9]+ blockIndex=[0-9]+\n`)
if markers.ReplaceAllString(got, "") != provided || !strings.Contains(got, "一期\t50万元") {
t.Fatalf("table text changed while adding a source marker: %q", got)
}
untrusted := core.ParsedDocument{Meta: core.DocMeta{Filename: "无来源.txt"}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "不得生成引用ID"}}}
plain := strings.TrimSpace(untrusted.PlainText())
if got := annotateProvidedMaterial(untrusted, plain, materialSources([]core.ParsedDocument{untrusted}, 48000)); got != plain {
t.Fatalf("document without Origin gained a source marker: %q", got)
}
}
func TestMaterialSourceInlineAnnotationsKeepOnlyPartialLastBlock(t *testing.T) {
d := core.ParsedDocument{Meta: core.DocMeta{Filename: "资料.txt", Origin: &core.DocumentOrigin{ArtifactID: "partial", ContentHash: strings.Repeat("e", 64), ParserRevision: "txt1"}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "上线六月"}, {Type: core.BlockPara, Text: "隐藏的审批结论"}}}
provided := string([]rune(strings.TrimSpace(d.PlainText()))[:7])
got := annotateProvidedMaterial(d, provided, materialSources([]core.ParsedDocument{d}, 7))
markers := regexp.MustCompile(`(?m)^sourceId=src_[a-f0-9]+ blockIndex=[0-9]+\n`)
if markers.ReplaceAllString(got, "") != provided || strings.Contains(got, "藏") {
t.Fatalf("partial block exposed unavailable text: %q", got)
}
}
func TestMaterialSourceInlineAnnotationsRejectDifferentParserRevision(t *testing.T) {
d := core.ParsedDocument{Meta: core.DocMeta{Filename: "同一工件.txt", Origin: &core.DocumentOrigin{ArtifactID: "same", ContentHash: strings.Repeat("f", 64), ParserRevision: "parser-old"}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "上线六月"}}}
oldSources := materialSources([]core.ParsedDocument{d}, 48000)
d.Meta.Origin.ParserRevision = "parser-new"
provided := strings.TrimSpace(d.PlainText())
if got := annotateProvidedMaterial(d, provided, oldSources); got != provided {
t.Fatalf("old parser source ID leaked into new parsing: %q", got)
}
}
func TestMaterialSourceInlineAnnotationsMatchRegistryIDs(t *testing.T) {
d := core.ParsedDocument{Meta: core.DocMeta{Filename: "多段.txt", Origin: &core.DocumentOrigin{ArtifactID: "multi", ContentHash: strings.Repeat("9", 64), ParserRevision: "txt1"}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "第一段"}, {Type: core.BlockPara, Text: "第二段"}, {Type: core.BlockPara, Text: "第三段"}}}
sources := materialSources([]core.ParsedDocument{d}, 48000)
got := annotateProvidedMaterial(d, strings.TrimSpace(d.PlainText()), sources)
if strings.Count(got, "sourceId=") != len(sources) {
t.Fatalf("annotation count=%d registry=%d", strings.Count(got, "sourceId="), len(sources))
}
for id := range sources {
if strings.Count(got, "sourceId="+id+" ") != 1 {
t.Fatalf("registered source %s missing or duplicated", id)
}
}
}
func TestMaterialKeyDetectsEqualLengthEdits(t *testing.T) {
a := []core.ParsedDocument{{Meta: core.DocMeta{Filename: "决定.txt", Parser: "builtin:md"}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "上线六月"}}}}
b := []core.ParsedDocument{{Meta: a[0].Meta, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "上线七月"}}}}
if materialKey(a) == materialKey(b) {
t.Fatal("same length edit reused a prior material result")
}
}
func TestMaterialSourceQuoteRequiresActualProvidedBlock(t *testing.T) {
docs := []core.ParsedDocument{{Meta: core.DocMeta{Filename: "决定.txt", Parser: "builtin:md", Origin: &core.DocumentOrigin{ArtifactID: "art1", ContentHash: strings.Repeat("a", 64), ParserRevision: "ir1"}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "上线六月"}, {Type: core.BlockPara, Text: "预算未定"}}}}
sources := materialSources(docs, 5)
if len(sources) == 0 {
t.Fatal("provided source was not registered")
}
for id, src := range sources {
if src.Ref.BlockIndex != 0 {
continue
}
got, err := sources.validate(core.TaskSourceQuote{SourceID: id, BlockIndex: 0, Quote: "上线六月"})
if err != nil || got.ArtifactID != "art1" {
t.Fatal("real source rejected", err)
}
if _, err = sources.validate(core.TaskSourceQuote{SourceID: id, BlockIndex: 1, Quote: "上线六月"}); err == nil {
t.Fatal("wrong block accepted")
}
if _, err = sources.validate(core.TaskSourceQuote{SourceID: id, BlockIndex: 0, Quote: "上线七月"}); err == nil {
t.Fatal("invented quote accepted")
}
}
if _, err := sources.validate(core.TaskSourceQuote{SourceID: "foreign", Quote: "上线六月"}); err == nil {
t.Fatal("foreign source accepted")
}
}
func TestMaterialInputRevisionIncludesProcessingVersion(t *testing.T) {
items := []materialInputItem{{Parsed: materialDocs()[0], OriginalHash: strings.Repeat("a", 64)}}
if materialInputRevision(items, "recipe1") == materialInputRevision(items, "recipe2") {
t.Fatal("processing change reused result")
}
}
func TestMaterialKeyChangesWithParserAndWarnings(t *testing.T) {
a := materialDocs()
b := materialDocs()
b[0].Meta.Parser = "different-parser"
if materialKey(a) == materialKey(b) {
t.Fatal("parser version ignored")
}
b = materialDocs()
b[0].Warnings = []string{"未解析图片"}
if materialKey(a) == materialKey(b) {
t.Fatal("changed coverage warning ignored")
}
b = materialDocs()
b[0].Meta.ParsedAt = time.Now()
b[0].Meta.Origin = &core.DocumentOrigin{ArtifactID: "new-upload-id"}
if materialKey(a) != materialKey(b) {
t.Fatal("transport identity/time should not change content identity")
}
}
func TestMaterialSourceDuplicateTextDoesNotAuthorizeUnprovidedBlock(t *testing.T) {
d := core.ParsedDocument{Meta: core.DocMeta{Filename: "重复.txt", Origin: &core.DocumentOrigin{ArtifactID: "a", ContentHash: "h", ParserRevision: "txt"}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: "相同内容"}, {Type: core.BlockPara, Text: "相同内容"}}}
registry := materialSources([]core.ParsedDocument{d}, 4)
for _, src := range registry {
if src.Ref.BlockIndex == 1 {
t.Fatal("unprovided duplicate block authorized")
}
}
}
func TestMaterialTaskExplainsBoundedEvidenceWithoutAnotherModelRound(t *testing.T) {
c := checkpointEnvironment(t)
for _, src := range c.sources {
c.attachments = []core.ParsedDocument{{Meta: core.DocMeta{Filename: "决定.txt", Origin: &core.DocumentOrigin{ArtifactID: src.Ref.ArtifactID, ContentHash: src.Ref.ContentHash, ParserRevision: src.Ref.ParserRevision}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: src.Text}}}}
break
}
task := buildMaterialTaskFor(c)
for _, want := range []string{"publish_work_checkpoint", "evidence", "sourceIndex", "unresolved_relation", "待确认", "材料存在差异,需核对", "原样记载用 material_record,只附 sources,不附 evidence"} {
if !strings.Contains(task, want) {
t.Fatalf("material task omits %s", want)
}
}
}
func TestMaterialTaskBoundsCheckpointsToHostFinalOnlyNotice(t *testing.T) {
c := checkpointEnvironment(t)
for _, src := range c.sources {
c.attachments = []core.ParsedDocument{{Meta: core.DocMeta{Filename: "决定.txt", Origin: &core.DocumentOrigin{ArtifactID: src.Ref.ArtifactID, ContentHash: src.Ref.ContentHash, ParserRevision: src.Ref.ParserRevision}}, Blocks: []core.DocBlock{{Type: core.BlockPara, Text: src.Text}}}}
break
}
task := buildMaterialTaskFor(c)
crosscheck := strings.Index(task, "后再次调用,phaseId=crosscheck;")
bound := strings.Index(task, "检查点通常最多2次")
if crosscheck < 0 || bound < crosscheck {
t.Fatal("checkpoint bound is not stated after the crosscheck instruction")
}
for _, want := range []string{"检查点通常最多2次", "第2次即 phaseId=crosscheck", "工具结果提示不再接受检查点后", "不再调用 publish_work_checkpoint", "最后输出完整整理结果", "约1500字以内", "一次写完"} {
if !strings.Contains(task, want) {
t.Fatalf("material task omits %s", want)
}
}
}