From 27aaa5e7d1611352109a63856f58904d6859f962 Mon Sep 17 00:00:00 2001 From: Dark aura Date: Thu, 7 May 2026 05:36:39 +0100 Subject: [PATCH] feat(vault): add VaultStore for managing Obsidian-compatible markdown notes --- pkg/vault/store.go | 28 +++++++++++++++++++ pkg/vault/store_test.go | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 pkg/vault/store.go create mode 100644 pkg/vault/store_test.go diff --git a/pkg/vault/store.go b/pkg/vault/store.go new file mode 100644 index 000000000..2d663f866 --- /dev/null +++ b/pkg/vault/store.go @@ -0,0 +1,28 @@ +package vault + +import ( + "os" + "path/filepath" + "gopkg.in/yaml.v3" +) + +type VaultStore struct { + rootPath string +} + +func NewVaultStore(rootPath string) *VaultStore { + return &VaultStore{rootPath: rootPath} +} + +func (vs *VaultStore) CreateNote(name string, frontmatter map[string]interface{}, content string) error { + if err := os.MkdirAll(vs.rootPath, 0755); err != nil { + return err + } + note := "---\n" + if fm, err := yaml.Marshal(frontmatter); err == nil { + note += string(fm) + } + note += "---\n\n" + content + notePath := filepath.Join(vs.rootPath, name+".md") + return os.WriteFile(notePath, []byte(note), 0644) +} \ No newline at end of file diff --git a/pkg/vault/store_test.go b/pkg/vault/store_test.go new file mode 100644 index 000000000..9607b7ffc --- /dev/null +++ b/pkg/vault/store_test.go @@ -0,0 +1,62 @@ +package vault + +import ( + "testing" + "path/filepath" + "os" +) + +func TestCreateNote(t *testing.T) { + tmpDir, _ := os.MkdirTemp("", "test-vault") + defer os.RemoveAll(tmpDir) + + store := NewVaultStore(tmpDir) + + err := store.CreateNote("test-note", map[string]interface{}{ + "title": "Test Note", + "tags": []string{"memory", "test"}, + }, "## Content here") + + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + notePath := filepath.Join(tmpDir, "test-note.md") + if _, err := os.Stat(notePath); os.IsNotExist(err) { + t.Errorf("expected note file to be created at %s", notePath) + } +} + +func TestReadNoteWithFrontmatter(t *testing.T) { + store := NewVaultStore("/tmp/test-vault") + + // Create note with frontmatter + store.CreateNote("MEMORY", map[string]interface{}{ + "title": "Agent Memory", + "tags": []string{"memory"}, + }, "# Content") + + fm, body, err := store.ReadNote("MEMORY") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if fm["title"] != "Agent Memory" { + t.Errorf("expected title in frontmatter") + } + if !contains(body, "# Content") { + t.Errorf("expected body to contain content") + } +} + +func contains(s, substr string) bool { + return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsHelper(s, substr)) +} + +func containsHelper(s, substr string) bool { + for i := 0; i <= len(s)-len(substr); i++ { + if s[i:i+len(substr)] == substr { + return true + } + } + return false +}