feat(memory): add YAML frontmatter parser for JSONL sessions
- Add ParseFrontmatter function to extract YAML frontmatter from content - Add test coverage for valid YAML, no frontmatter, and invalid YAML cases - Use gopkg.in/yaml.v3 for parsing
This commit is contained in:
parent
4bdeb5dfbf
commit
2b75c88428
2 changed files with 82 additions and 0 deletions
29
pkg/memory/frontmatter.go
Normal file
29
pkg/memory/frontmatter.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// ParseFrontmatter extracts YAML frontmatter delimited by --- from content
|
||||
// Returns: frontmatter map, remaining body, error
|
||||
func ParseFrontmatter(content string) (map[string]interface{}, string, error) {
|
||||
result := make(map[string]interface{})
|
||||
body := content
|
||||
|
||||
// Check for frontmatter delimiters
|
||||
parts := strings.SplitN(content, "---", 3)
|
||||
if len(parts) < 3 {
|
||||
// No frontmatter, return empty map and original content
|
||||
return result, body, nil
|
||||
}
|
||||
|
||||
// Parse YAML
|
||||
fmText := parts[1]
|
||||
if err := yaml.Unmarshal([]byte(fmText), &result); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
body = parts[2]
|
||||
return result, body, nil
|
||||
}
|
||||
53
pkg/memory/frontmatter_test.go
Normal file
53
pkg/memory/frontmatter_test.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func TestParseFrontmatter_ValidYAML(t *testing.T) {
|
||||
input := `---
|
||||
session_id: "abc123"
|
||||
timestamp: "2026-05-06T14:30:00Z"
|
||||
tags: ["coding", "bug-fix"]
|
||||
model: "claude-sonnet-4"
|
||||
---
|
||||
{"role": "user", "content": "test"}
|
||||
`
|
||||
fm, body, err := ParseFrontmatter(input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if fm["session_id"] != "abc123" {
|
||||
t.Errorf("expected session_id 'abc123', got %v", fm["session_id"])
|
||||
}
|
||||
if len(fm["tags"].([]interface{})) != 2 {
|
||||
t.Errorf("expected 2 tags, got %v", fm["tags"])
|
||||
}
|
||||
if !strings.Contains(body, `"role": "user"`) {
|
||||
t.Errorf("expected body to contain JSON, got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFrontmatter_NoFrontmatter(t *testing.T) {
|
||||
input := `{"role": "user", "content": "test"}`
|
||||
_, body, err := ParseFrontmatter(input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(body, `"role": "user"`) {
|
||||
t.Errorf("expected body unchanged, got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFrontmatter_InvalidYAML(t *testing.T) {
|
||||
input := `---
|
||||
invalid: [unclosed
|
||||
---
|
||||
{"role": "user"}
|
||||
`
|
||||
_, _, err := ParseFrontmatter(input)
|
||||
if err == nil {
|
||||
t.Error("expected error for invalid YAML")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue