- Add ExtractWikiLinks to vault/store.go for graph edges - Add appendVaultGraph to api/pico.go for vault visualization - Integrate vault notes as graph nodes in buildPicoMemoryGraph - Vault notes become nodes (kind=document, group=memory) - Wiki-links [[...]] become edges (kind=wikilink) - Connect vault system to cockpit UI memory-graph component Implements complete three-layer learning system: 1. Episodic: JSONL + frontmatter (Task 1-3) 2. Semantic: Vault with Obsidian-compatible markdown (Task 4-5) 3. Procedural: Tool skills ready (Task 6, 10) 4. UI: Vanilla JS sidebar with vault browser (Task 7-9)
52 lines
No EOL
1.3 KiB
Go
52 lines
No EOL
1.3 KiB
Go
package vault
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/memory"
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
// ReadNote reads a note file and parses frontmatter
|
|
func (vs *VaultStore) ReadNote(name string) (map[string]interface{}, string, error) {
|
|
notePath := filepath.Join(vs.rootPath, name+".md")
|
|
content, err := os.ReadFile(notePath)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
return memory.ParseFrontmatter(string(content))
|
|
}
|
|
|
|
// ExtractWikiLinks extracts [[link]] patterns from content
|
|
func ExtractWikiLinks(content string) []string {
|
|
re := regexp.MustCompile(`\[\[([^\]]+)\]`)
|
|
matches := re.FindAllStringSubmatch(content, -1)
|
|
links := make([]string, 0, len(matches))
|
|
for _, m := range matches {
|
|
links = append(links, m[1])
|
|
}
|
|
return links
|
|
} |