fix(media): prepend path tags for JSON content, narrow looksLikeJSON

Two fixes from code review:

1. looksLikeJSON now only checks for '{' prefix (not '['), avoiding
   false positives on regular text like "[update] see attached".

2. For JSON content (Feishu cards/posts), path tags are prepended
   before the JSON instead of being silently dropped. This ensures
   the LLM can discover attached images via the path tag while the
   JSON payload stays valid for downstream parsing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guoguo 2026-04-29 19:13:17 -07:00
parent 77beafa6d3
commit f13f6b531d
2 changed files with 16 additions and 12 deletions

View file

@ -269,6 +269,7 @@ func injectPathTags(content string, tags []string) string {
} }
if isStructured { if isStructured {
content = tag + "\n" + content
continue continue
} }
@ -283,5 +284,5 @@ func injectPathTags(content string, tags []string) string {
func looksLikeJSON(s string) bool { func looksLikeJSON(s string) bool {
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
return len(s) > 1 && (s[0] == '{' || s[0] == '[') return len(s) > 1 && s[0] == '{'
} }

View file

@ -5040,23 +5040,25 @@ func TestInjectPathTags_DoesNotReplacePathTag(t *testing.T) {
} }
} }
func TestInjectPathTags_SkipsAppendForJSONContent(t *testing.T) { func TestInjectPathTags_PrependsForJSONContent(t *testing.T) {
jsonContent := `{"schema":"2.0","body":{"elements":[{"tag":"img","img_key":"img_123"}]}}` jsonContent := `{"schema":"2.0","body":{"elements":[{"tag":"img","img_key":"img_123"}]}}`
got := injectPathTags(jsonContent, []string{"[image:/tmp/photo.png]"}) got := injectPathTags(jsonContent, []string{"[image:/tmp/photo.png]"})
if got != jsonContent { want := "[image:/tmp/photo.png]\n" + jsonContent
t.Fatalf("expected JSON content unchanged, got %q", got) if got != want {
t.Fatalf("expected tag prepended to JSON, got %q", got)
} }
} }
func TestInjectPathTags_JSONArrayContent(t *testing.T) { func TestInjectPathTags_BracketTextNotTreatedAsJSON(t *testing.T) {
jsonContent := `[{"tag":"text","text":"hello"}]` content := "[update] see attached report"
got := injectPathTags(jsonContent, []string{"[file:/tmp/doc.pdf]"}) got := injectPathTags(content, []string{"[file:/tmp/report.pdf]"})
if got != jsonContent { want := "[update] see attached report [file:/tmp/report.pdf]"
t.Fatalf("expected JSON array content unchanged, got %q", got) if got != want {
t.Fatalf("expected tag appended to bracket text, got %q", got)
} }
} }
func TestResolveMediaRefs_JSONContentPreservesStructure(t *testing.T) { func TestResolveMediaRefs_JSONContentPrependsPathTag(t *testing.T) {
store := media.NewFileMediaStore() store := media.NewFileMediaStore()
dir := t.TempDir() dir := t.TempDir()
@ -5076,8 +5078,9 @@ func TestResolveMediaRefs_JSONContentPreservesStructure(t *testing.T) {
} }
result := resolveMediaRefs(messages, store, config.DefaultMaxMediaSize) result := resolveMediaRefs(messages, store, config.DefaultMaxMediaSize)
if result[0].Content != jsonContent { want := "[image:" + pngPath + "]\n" + jsonContent
t.Fatalf("expected JSON content preserved, got %q", result[0].Content) if result[0].Content != want {
t.Fatalf("expected path tag prepended to JSON content, got %q", result[0].Content)
} }
} }