fix(doc): verify inline media from jsonml readback
This commit is contained in:
+20
-3
@@ -758,7 +758,7 @@ func readAllDocBlocksForVerification(ctx context.Context, nodeID string) ([]any,
|
||||
seen := map[string]bool{}
|
||||
for start := 0; start < maxItems; start += pageSize {
|
||||
text, err := callMCPToolReturnTextOnServer(ctx, "doc", "list_document_blocks", map[string]any{
|
||||
"nodeId": nodeID, "format": "element", "startIndex": start, "endIndex": start + pageSize - 1,
|
||||
"nodeId": nodeID, "format": "jsonml", "startIndex": start, "endIndex": start + pageSize - 1,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -834,16 +834,33 @@ func findVerifiedMediaBlock(blocks []any, blockID, resourceID, resourceURL strin
|
||||
if candidateID == "" || (blockID != "" && candidateID != blockID) {
|
||||
continue
|
||||
}
|
||||
if resourceID != "" && nestedDocString(value, "resourceId") == resourceID {
|
||||
mediaValue := docMediaReadbackValue(value)
|
||||
if resourceID != "" && nestedDocString(mediaValue, "resourceId") == resourceID {
|
||||
return candidateID
|
||||
}
|
||||
if resourceID == "" && resourceURL != "" && nestedDocString(value, "resourceUrl") == resourceURL {
|
||||
if resourceURL != "" && nestedDocString(mediaValue, "resourceUrl", "src") == resourceURL {
|
||||
return candidateID
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func docMediaReadbackValue(value any) any {
|
||||
block, ok := value.(map[string]any)
|
||||
if !ok {
|
||||
return value
|
||||
}
|
||||
encoded, ok := block["jsonml"].(string)
|
||||
if !ok || strings.TrimSpace(encoded) == "" {
|
||||
return value
|
||||
}
|
||||
var decoded any
|
||||
if json.Unmarshal([]byte(encoded), &decoded) != nil {
|
||||
return value
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
func docNumberAsInt(value any) (int, bool) {
|
||||
switch typed := value.(type) {
|
||||
case float64:
|
||||
|
||||
@@ -206,6 +206,23 @@ func TestCrossPlatformCoverageDocUploadAndMediaErrorEdges(t *testing.T) {
|
||||
t.Fatal("invalid media insert response returned nil")
|
||||
}
|
||||
})
|
||||
t.Run("small image verifies src readback when upload also returns resource ID", func(t *testing.T) {
|
||||
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return nil }
|
||||
caller := &scriptedToolCaller{steps: []scriptedToolStep{
|
||||
{text: `{"uploadUrl":"https://upload","resourceId":"resource","resourceUrl":"https://image"}`},
|
||||
{text: `{"blockId":"media-block"}`},
|
||||
{text: `{"blocks":[{"blockId":"media-block","jsonml":"[\"p\",{\"uuid\":\"media-block\"},[\"img\",{\"src\":\"https://image\"}]]"}],"hasMore":false}`},
|
||||
}}
|
||||
if err := mediaCommand(t, caller, file, "image/png"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if caller.calls != 3 {
|
||||
t.Fatalf("media insert calls = %d, want credential, insert, and one readback", caller.calls)
|
||||
}
|
||||
if caller.args["format"] != "jsonml" {
|
||||
t.Fatalf("media readback format = %#v, want jsonml", caller.args["format"])
|
||||
}
|
||||
})
|
||||
t.Run("large image becomes attachment", func(t *testing.T) {
|
||||
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return nil }
|
||||
large := filepath.Join(t.TempDir(), "large.png")
|
||||
@@ -337,10 +354,13 @@ func TestCrossPlatformCoverageDocMediaReadbackDefensiveEdges(t *testing.T) {
|
||||
if nestedDocString(map[string]any{"x": []any{map[string]any{"id": " nested "}}}, "id") != "nested" || nestedDocString(3, "id") != "" {
|
||||
t.Fatal("nested string traversal failed")
|
||||
}
|
||||
blocks := []any{map[string]any{"id": "block", "resourceId": "rid"}, map[string]any{"id": "url-block", "resourceUrl": "https://media"}}
|
||||
if findVerifiedMediaBlock(blocks, "block", "rid", "") != "block" || findVerifiedMediaBlock(blocks, "", "rid", "") != "block" || findVerifiedMediaBlock(blocks, "", "", "https://media") != "url-block" || findVerifiedMediaBlock(blocks, "block", "wrong", "") != "" || findVerifiedMediaBlock(blocks, "", "missing", "") != "" {
|
||||
blocks := []any{map[string]any{"id": "block", "resourceId": "rid"}, map[string]any{"id": "url-block", "resourceUrl": "https://media"}, map[string]any{"id": "src-block", "jsonml": `["p",{},["img",{"src":"https://image"}]]`}}
|
||||
if findVerifiedMediaBlock(blocks, "block", "rid", "") != "block" || findVerifiedMediaBlock(blocks, "", "rid", "") != "block" || findVerifiedMediaBlock(blocks, "", "", "https://media") != "url-block" || findVerifiedMediaBlock(blocks, "src-block", "upload-resource", "https://image") != "src-block" || findVerifiedMediaBlock(blocks, "other-block", "upload-resource", "https://image") != "" || findVerifiedMediaBlock(blocks, "block", "wrong", "") != "" || findVerifiedMediaBlock(blocks, "", "missing", "") != "" {
|
||||
t.Fatal("media block matching failed")
|
||||
}
|
||||
if findVerifiedMediaBlock([]any{map[string]any{"id": "bad-jsonml", "jsonml": `[`}}, "bad-jsonml", "", "https://image") != "" {
|
||||
t.Fatal("invalid JSONML unexpectedly verified")
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
value any
|
||||
want bool
|
||||
|
||||
Reference in New Issue
Block a user