File size: 3,553 Bytes
857894b
a02272f
 
 
 
 
857894b
a02272f
857894b
a02272f
 
 
857894b
37b748e
 
 
 
857894b
37b748e
 
 
 
 
 
 
 
 
 
857894b
37b748e
 
 
 
 
 
 
 
 
857894b
 
279ebac
 
 
a02272f
 
 
279ebac
 
 
 
 
 
 
 
 
 
 
 
a02272f
857894b
a02272f
 
857894b
37b748e
857894b
37b748e
 
 
 
 
 
 
 
 
 
857894b
 
 
a02272f
df55394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a02272f
857894b
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""Cross-platform path resolution for Brain - Local First."""

from pathlib import Path

# ── Constants ──────────────────────────────────────────────

BRAINS_DIR_NAME = ".brains"
WORKSPACE_DIR_NAME = ".brain"
CONFIG_FILE_NAME = "config" # Inside .brain/

# ── Resolvers ──────────────────────────────────────────────

def get_project_root() -> Path:
    """Find the project root by looking for .brain/ or .ever-brain marker."""
    curr = Path.cwd().resolve()
    home = Path.home().resolve()
    
    for parent in [curr] + list(curr.parents):
        # Stop at filesystem root
        if parent.parent == parent:
            break
            
        # 1. Check for designated workspace folder (.brain/)
        if (parent / WORKSPACE_DIR_NAME).exists() and (parent / WORKSPACE_DIR_NAME).is_dir():
            return parent
            
        # 2. Check for global marker file (.ever-brain)
        if (parent / ".ever-brain").exists() and (parent / ".ever-brain").is_file():
            return parent
            
        # 3. Stop at Git boundary (don't search outside the repo)
        if (parent / ".git").exists():
            return parent
            
        # 4. Stop at User Home
        if parent == home:
            break
            
    return curr

def get_global_brains_dir() -> Path:
    """Return ~/.ever-brain/brains/. Creates if missing."""
    p = Path.home() / ".ever-brain" / "brains"
    p.mkdir(parents=True, exist_ok=True)
    return p

def get_brains_dir() -> Path:
    """Return ./.brains/ if it exists, otherwise ~/.ever-brain/brains/."""
    # Check if a project-specific .brains folder exists in the hierarchy
    curr = Path.cwd()
    for parent in [curr] + list(curr.parents):
        local_brains = parent / BRAINS_DIR_NAME
        if local_brains.exists() and local_brains.is_dir():
            return local_brains
    
    # Fallback to global
    return get_global_brains_dir()

def get_brain_path(name: str) -> Path:
    """Return ./.brains/<name>/."""
    return get_brains_dir() / name

def get_workspace_dir(cwd: Path | None = None) -> Path:
    """Return <root>/.brain/ or a global path if in global mode."""
    root = get_project_root()
    
    # Check if this is a global project
    marker = root / ".ever-brain"
    if marker.exists() and marker.is_file():
        # It's a global project. Store metadata in ~/.ever-brain/workspaces/
        # Use root name as a safe identifier
        p = Path.home() / ".ever-brain" / "workspaces" / root.name
        p.mkdir(parents=True, exist_ok=True)
        return p

    p = root / WORKSPACE_DIR_NAME
    p.mkdir(parents=True, exist_ok=True)
    return p

def get_global_projects_dir() -> Path:
    """Return ~/.ever-brain/projects/. Creates if missing."""
    p = Path.home() / ".ever-brain" / "projects"
    p.mkdir(parents=True, exist_ok=True)
    return p

def get_personas_dir() -> Path:
    """Return ~/.ever-brain/personas/. Creates if missing."""
    p = Path.home() / ".ever-brain" / "personas"
    p.mkdir(parents=True, exist_ok=True)
    return p

def get_persona_path(name: str) -> Path:
    """Return ~/.ever-brain/personas/<name>.md."""
    if not name.endswith(".md"):
        name += ".md"
    return get_personas_dir() / name

def get_config_path() -> Path:
    """Return <root>/.brain/config."""
    return get_workspace_dir() / CONFIG_FILE_NAME