get-claudia 1.2.4 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -46,46 +46,54 @@ class Database:
|
|
|
46
46
|
conn.execute("PRAGMA synchronous = NORMAL")
|
|
47
47
|
conn.execute("PRAGMA foreign_keys = ON")
|
|
48
48
|
|
|
49
|
-
# Try to load sqlite-vec
|
|
49
|
+
# Try to load sqlite-vec for vector search
|
|
50
|
+
# Priority: sqlite_vec Python package first (works on Python 3.13+),
|
|
51
|
+
# then fall back to native extension loading
|
|
52
|
+
loaded = False
|
|
53
|
+
|
|
54
|
+
# Method 1: Try sqlite_vec Python package (recommended, works everywhere)
|
|
50
55
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
str(Path.home() / ".local" / "lib" / "sqlite-vec" / "vec0"),
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
loaded = False
|
|
61
|
-
for path in sqlite_vec_paths:
|
|
62
|
-
try:
|
|
63
|
-
conn.load_extension(path)
|
|
64
|
-
loaded = True
|
|
65
|
-
logger.debug(f"Loaded sqlite-vec from {path}")
|
|
66
|
-
break
|
|
67
|
-
except sqlite3.OperationalError:
|
|
68
|
-
continue
|
|
69
|
-
|
|
70
|
-
if not loaded:
|
|
71
|
-
# Try loading via sqlite_vec Python package
|
|
72
|
-
try:
|
|
73
|
-
import sqlite_vec
|
|
74
|
-
sqlite_vec.load(conn)
|
|
75
|
-
loaded = True
|
|
76
|
-
logger.debug("Loaded sqlite-vec via Python package")
|
|
77
|
-
except ImportError:
|
|
78
|
-
pass
|
|
79
|
-
|
|
80
|
-
if not loaded:
|
|
81
|
-
logger.warning(
|
|
82
|
-
"sqlite-vec extension not found. Vector search will be unavailable. "
|
|
83
|
-
"Install with: pip install sqlite-vec"
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
conn.enable_load_extension(False)
|
|
56
|
+
import sqlite_vec
|
|
57
|
+
sqlite_vec.load(conn)
|
|
58
|
+
loaded = True
|
|
59
|
+
logger.debug("Loaded sqlite-vec via Python package")
|
|
60
|
+
except ImportError:
|
|
61
|
+
logger.debug("sqlite_vec package not installed")
|
|
87
62
|
except Exception as e:
|
|
88
|
-
logger.
|
|
63
|
+
logger.debug(f"sqlite_vec package failed: {e}")
|
|
64
|
+
|
|
65
|
+
# Method 2: Try native extension loading (for systems with pre-installed sqlite-vec)
|
|
66
|
+
if not loaded:
|
|
67
|
+
try:
|
|
68
|
+
conn.enable_load_extension(True)
|
|
69
|
+
sqlite_vec_paths = [
|
|
70
|
+
"vec0", # If installed system-wide
|
|
71
|
+
"/usr/local/lib/sqlite-vec/vec0",
|
|
72
|
+
"/opt/homebrew/lib/sqlite-vec/vec0",
|
|
73
|
+
str(Path.home() / ".local" / "lib" / "sqlite-vec" / "vec0"),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
for path in sqlite_vec_paths:
|
|
77
|
+
try:
|
|
78
|
+
conn.load_extension(path)
|
|
79
|
+
loaded = True
|
|
80
|
+
logger.debug(f"Loaded sqlite-vec from {path}")
|
|
81
|
+
break
|
|
82
|
+
except sqlite3.OperationalError:
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
conn.enable_load_extension(False)
|
|
86
|
+
except AttributeError:
|
|
87
|
+
# Python 3.13+ may not have enable_load_extension
|
|
88
|
+
logger.debug("enable_load_extension not available (Python 3.13+)")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.debug(f"Extension loading failed: {e}")
|
|
91
|
+
|
|
92
|
+
if not loaded:
|
|
93
|
+
logger.warning(
|
|
94
|
+
"sqlite-vec not available. Vector search will be disabled. "
|
|
95
|
+
"Install with: pip install sqlite-vec"
|
|
96
|
+
)
|
|
89
97
|
|
|
90
98
|
self._local.connection = conn
|
|
91
99
|
|
|
@@ -3,10 +3,13 @@ Embedding service for Claudia Memory System
|
|
|
3
3
|
|
|
4
4
|
Connects to local Ollama for generating text embeddings.
|
|
5
5
|
Uses all-minilm:l6-v2 model (384 dimensions) for semantic search.
|
|
6
|
+
|
|
7
|
+
Includes retry logic to wait for Ollama to start (e.g., after system boot).
|
|
6
8
|
"""
|
|
7
9
|
|
|
8
10
|
import asyncio
|
|
9
11
|
import logging
|
|
12
|
+
import time
|
|
10
13
|
from typing import List, Optional
|
|
11
14
|
|
|
12
15
|
import httpx
|
|
@@ -15,6 +18,10 @@ from .config import get_config
|
|
|
15
18
|
|
|
16
19
|
logger = logging.getLogger(__name__)
|
|
17
20
|
|
|
21
|
+
# Retry configuration for waiting on Ollama
|
|
22
|
+
OLLAMA_RETRY_ATTEMPTS = 5
|
|
23
|
+
OLLAMA_RETRY_DELAY = 2 # seconds
|
|
24
|
+
|
|
18
25
|
|
|
19
26
|
class EmbeddingService:
|
|
20
27
|
"""Generate embeddings using local Ollama"""
|
|
@@ -40,11 +47,52 @@ class EmbeddingService:
|
|
|
40
47
|
self._sync_client = httpx.Client(timeout=30.0)
|
|
41
48
|
return self._sync_client
|
|
42
49
|
|
|
50
|
+
async def _wait_for_ollama(self, max_retries: int = OLLAMA_RETRY_ATTEMPTS, delay: float = OLLAMA_RETRY_DELAY) -> bool:
|
|
51
|
+
"""Wait for Ollama to be available with retries (async)"""
|
|
52
|
+
client = await self._get_client()
|
|
53
|
+
for i in range(max_retries):
|
|
54
|
+
try:
|
|
55
|
+
response = await client.get(f"{self.host}/api/tags", timeout=5.0)
|
|
56
|
+
if response.status_code == 200:
|
|
57
|
+
logger.debug(f"Ollama available after {i + 1} attempt(s)")
|
|
58
|
+
return True
|
|
59
|
+
except Exception:
|
|
60
|
+
pass
|
|
61
|
+
if i < max_retries - 1:
|
|
62
|
+
logger.debug(f"Waiting for Ollama (attempt {i + 1}/{max_retries})...")
|
|
63
|
+
await asyncio.sleep(delay)
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def _wait_for_ollama_sync(self, max_retries: int = OLLAMA_RETRY_ATTEMPTS, delay: float = OLLAMA_RETRY_DELAY) -> bool:
|
|
67
|
+
"""Wait for Ollama to be available with retries (sync)"""
|
|
68
|
+
client = self._get_sync_client()
|
|
69
|
+
for i in range(max_retries):
|
|
70
|
+
try:
|
|
71
|
+
response = client.get(f"{self.host}/api/tags", timeout=5.0)
|
|
72
|
+
if response.status_code == 200:
|
|
73
|
+
logger.debug(f"Ollama available after {i + 1} attempt(s)")
|
|
74
|
+
return True
|
|
75
|
+
except Exception:
|
|
76
|
+
pass
|
|
77
|
+
if i < max_retries - 1:
|
|
78
|
+
logger.debug(f"Waiting for Ollama (attempt {i + 1}/{max_retries})...")
|
|
79
|
+
time.sleep(delay)
|
|
80
|
+
return False
|
|
81
|
+
|
|
43
82
|
async def is_available(self) -> bool:
|
|
44
|
-
"""Check if Ollama is running and model is available
|
|
83
|
+
"""Check if Ollama is running and model is available.
|
|
84
|
+
|
|
85
|
+
Uses retry logic to wait for Ollama if it's starting up (e.g., after boot).
|
|
86
|
+
"""
|
|
45
87
|
if self._available is not None:
|
|
46
88
|
return self._available
|
|
47
89
|
|
|
90
|
+
# Wait for Ollama to be available (with retries)
|
|
91
|
+
if not await self._wait_for_ollama():
|
|
92
|
+
logger.warning("Ollama not available after retries. Vector search disabled.")
|
|
93
|
+
self._available = False
|
|
94
|
+
return self._available
|
|
95
|
+
|
|
48
96
|
try:
|
|
49
97
|
client = await self._get_client()
|
|
50
98
|
response = await client.get(f"{self.host}/api/tags")
|
|
@@ -65,16 +113,25 @@ class EmbeddingService:
|
|
|
65
113
|
else:
|
|
66
114
|
self._available = False
|
|
67
115
|
except Exception as e:
|
|
68
|
-
logger.warning(f"Ollama
|
|
116
|
+
logger.warning(f"Ollama error: {e}")
|
|
69
117
|
self._available = False
|
|
70
118
|
|
|
71
119
|
return self._available
|
|
72
120
|
|
|
73
121
|
def is_available_sync(self) -> bool:
|
|
74
|
-
"""Synchronous check if Ollama is available
|
|
122
|
+
"""Synchronous check if Ollama is available.
|
|
123
|
+
|
|
124
|
+
Uses retry logic to wait for Ollama if it's starting up (e.g., after boot).
|
|
125
|
+
"""
|
|
75
126
|
if self._available is not None:
|
|
76
127
|
return self._available
|
|
77
128
|
|
|
129
|
+
# Wait for Ollama to be available (with retries)
|
|
130
|
+
if not self._wait_for_ollama_sync():
|
|
131
|
+
logger.warning("Ollama not available after retries. Vector search disabled.")
|
|
132
|
+
self._available = False
|
|
133
|
+
return self._available
|
|
134
|
+
|
|
78
135
|
try:
|
|
79
136
|
client = self._get_sync_client()
|
|
80
137
|
response = client.get(f"{self.host}/api/tags")
|
|
@@ -88,7 +145,7 @@ class EmbeddingService:
|
|
|
88
145
|
else:
|
|
89
146
|
self._available = False
|
|
90
147
|
except Exception as e:
|
|
91
|
-
logger.warning(f"Ollama
|
|
148
|
+
logger.warning(f"Ollama error: {e}")
|
|
92
149
|
self._available = False
|
|
93
150
|
|
|
94
151
|
return self._available
|
|
@@ -94,18 +94,73 @@ else
|
|
|
94
94
|
echo -e " ${DIM}Database will be created on first use.${NC}"
|
|
95
95
|
fi
|
|
96
96
|
|
|
97
|
-
# Check 7: Ollama
|
|
98
|
-
echo -n "7. Ollama
|
|
97
|
+
# Check 7: Ollama installed
|
|
98
|
+
echo -n "7. Ollama installed... "
|
|
99
|
+
if command -v ollama &> /dev/null; then
|
|
100
|
+
echo -e "${GREEN}✓ OK${NC}"
|
|
101
|
+
else
|
|
102
|
+
echo -e "${YELLOW}○ Not installed (keyword search will be used)${NC}"
|
|
103
|
+
echo -e " ${DIM}Optional: brew install ollama${NC}"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Check 8: Ollama running
|
|
107
|
+
echo -n "8. Ollama running... "
|
|
108
|
+
if curl -s http://localhost:11434/api/tags &>/dev/null; then
|
|
109
|
+
echo -e "${GREEN}✓ Running${NC}"
|
|
110
|
+
else
|
|
111
|
+
echo -e "${YELLOW}○ Not running${NC}"
|
|
112
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
113
|
+
if [ -f "$HOME/Library/LaunchAgents/com.ollama.serve.plist" ]; then
|
|
114
|
+
echo -e " ${DIM}LaunchAgent exists - try: launchctl load ~/Library/LaunchAgents/com.ollama.serve.plist${NC}"
|
|
115
|
+
else
|
|
116
|
+
echo -e " ${DIM}Start with: ollama serve${NC}"
|
|
117
|
+
fi
|
|
118
|
+
else
|
|
119
|
+
echo -e " ${DIM}Start with: ollama serve${NC}"
|
|
120
|
+
fi
|
|
121
|
+
ISSUES_FOUND=$((ISSUES_FOUND + 1))
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Check 9: Ollama auto-start (macOS only)
|
|
125
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
126
|
+
echo -n "9. Ollama auto-start... "
|
|
127
|
+
if [ -f "$HOME/Library/LaunchAgents/com.ollama.serve.plist" ]; then
|
|
128
|
+
echo -e "${GREEN}✓ LaunchAgent configured${NC}"
|
|
129
|
+
else
|
|
130
|
+
echo -e "${YELLOW}○ No LaunchAgent${NC}"
|
|
131
|
+
echo -e " ${DIM}Ollama won't start on boot. Re-run memory installer to configure.${NC}"
|
|
132
|
+
fi
|
|
133
|
+
else
|
|
134
|
+
echo -e "9. Ollama auto-start... ${DIM}(Linux - check systemd if needed)${NC}"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Check 10: Embedding model
|
|
138
|
+
echo -n "10. Embedding model... "
|
|
99
139
|
if command -v ollama &> /dev/null; then
|
|
100
140
|
if ollama list 2>/dev/null | grep -q "minilm"; then
|
|
101
|
-
echo -e "${GREEN}✓
|
|
141
|
+
echo -e "${GREEN}✓ all-minilm model available${NC}"
|
|
102
142
|
else
|
|
103
|
-
echo -e "${YELLOW}○
|
|
143
|
+
echo -e "${YELLOW}○ No embedding model${NC}"
|
|
104
144
|
echo -e " ${DIM}Run: ollama pull all-minilm:l6-v2${NC}"
|
|
145
|
+
ISSUES_FOUND=$((ISSUES_FOUND + 1))
|
|
105
146
|
fi
|
|
106
147
|
else
|
|
107
|
-
echo -e "${
|
|
108
|
-
|
|
148
|
+
echo -e "${DIM}○ Skipped (Ollama not installed)${NC}"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Check 11: sqlite-vec (vector search)
|
|
152
|
+
echo -n "11. Vector search (sqlite-vec)... "
|
|
153
|
+
VENV_PYTHON="$HOME/.claudia/daemon/venv/bin/python"
|
|
154
|
+
if [ -f "$VENV_PYTHON" ]; then
|
|
155
|
+
if $VENV_PYTHON -c "import sqlite_vec; print('ok')" 2>/dev/null | grep -q "ok"; then
|
|
156
|
+
echo -e "${GREEN}✓ sqlite-vec available${NC}"
|
|
157
|
+
else
|
|
158
|
+
echo -e "${YELLOW}○ sqlite-vec not working${NC}"
|
|
159
|
+
echo -e " ${DIM}Fix: $HOME/.claudia/daemon/venv/bin/pip install sqlite-vec${NC}"
|
|
160
|
+
ISSUES_FOUND=$((ISSUES_FOUND + 1))
|
|
161
|
+
fi
|
|
162
|
+
else
|
|
163
|
+
echo -e "${RED}✗ Virtual environment missing${NC}"
|
|
109
164
|
fi
|
|
110
165
|
|
|
111
166
|
# Summary
|
|
@@ -137,6 +137,45 @@ else
|
|
|
137
137
|
fi
|
|
138
138
|
fi
|
|
139
139
|
|
|
140
|
+
# Configure Ollama to auto-start on boot (macOS)
|
|
141
|
+
if [[ "$OSTYPE" == "darwin"* ]] && [ "$OLLAMA_AVAILABLE" = true ]; then
|
|
142
|
+
OLLAMA_PLIST="$HOME/Library/LaunchAgents/com.ollama.serve.plist"
|
|
143
|
+
|
|
144
|
+
if [ ! -f "$OLLAMA_PLIST" ]; then
|
|
145
|
+
# Find Ollama binary location
|
|
146
|
+
OLLAMA_BIN=$(command -v ollama)
|
|
147
|
+
|
|
148
|
+
mkdir -p "$HOME/Library/LaunchAgents"
|
|
149
|
+
cat > "$OLLAMA_PLIST" << PLIST
|
|
150
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
151
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
152
|
+
<plist version="1.0">
|
|
153
|
+
<dict>
|
|
154
|
+
<key>Label</key>
|
|
155
|
+
<string>com.ollama.serve</string>
|
|
156
|
+
<key>ProgramArguments</key>
|
|
157
|
+
<array>
|
|
158
|
+
<string>$OLLAMA_BIN</string>
|
|
159
|
+
<string>serve</string>
|
|
160
|
+
</array>
|
|
161
|
+
<key>RunAtLoad</key>
|
|
162
|
+
<true/>
|
|
163
|
+
<key>KeepAlive</key>
|
|
164
|
+
<true/>
|
|
165
|
+
<key>StandardOutPath</key>
|
|
166
|
+
<string>/tmp/ollama.log</string>
|
|
167
|
+
<key>StandardErrorPath</key>
|
|
168
|
+
<string>/tmp/ollama.err</string>
|
|
169
|
+
</dict>
|
|
170
|
+
</plist>
|
|
171
|
+
PLIST
|
|
172
|
+
launchctl load "$OLLAMA_PLIST" 2>/dev/null || true
|
|
173
|
+
echo -e " ${GREEN}✓${NC} Ollama configured to auto-start on boot"
|
|
174
|
+
else
|
|
175
|
+
echo -e " ${GREEN}✓${NC} Ollama LaunchAgent already configured"
|
|
176
|
+
fi
|
|
177
|
+
fi
|
|
178
|
+
|
|
140
179
|
echo
|
|
141
180
|
echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
142
181
|
echo
|
|
@@ -145,14 +184,41 @@ echo
|
|
|
145
184
|
echo -e "${BOLD}Step 2/7: AI Models${NC}"
|
|
146
185
|
echo
|
|
147
186
|
if [ "$OLLAMA_AVAILABLE" = true ]; then
|
|
187
|
+
# Ensure Ollama is running before pulling model
|
|
188
|
+
if ! curl -s http://localhost:11434/api/tags &>/dev/null; then
|
|
189
|
+
echo -e " ${CYAN}◐${NC} Starting Ollama server..."
|
|
190
|
+
ollama serve &>/dev/null &
|
|
191
|
+
OLLAMA_PID=$!
|
|
192
|
+
|
|
193
|
+
# Wait for Ollama to be ready (up to 10 seconds)
|
|
194
|
+
for i in {1..10}; do
|
|
195
|
+
if curl -s http://localhost:11434/api/tags &>/dev/null; then
|
|
196
|
+
break
|
|
197
|
+
fi
|
|
198
|
+
sleep 1
|
|
199
|
+
done
|
|
200
|
+
|
|
201
|
+
if curl -s http://localhost:11434/api/tags &>/dev/null; then
|
|
202
|
+
echo -e " ${GREEN}✓${NC} Ollama server running"
|
|
203
|
+
else
|
|
204
|
+
echo -e " ${YELLOW}!${NC} Could not start Ollama (will retry on boot)"
|
|
205
|
+
fi
|
|
206
|
+
else
|
|
207
|
+
echo -e " ${GREEN}✓${NC} Ollama server already running"
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
# Pull embedding model
|
|
148
211
|
if ollama list 2>/dev/null | grep -q "all-minilm"; then
|
|
149
212
|
echo -e " ${GREEN}✓${NC} Embedding model ready"
|
|
150
213
|
else
|
|
151
214
|
echo -e " ${CYAN}◐${NC} Downloading embedding model (45MB)..."
|
|
152
215
|
echo -e " ${DIM}This gives Claudia semantic understanding${NC}"
|
|
153
216
|
echo
|
|
154
|
-
ollama pull all-minilm:l6-v2 2>/dev/null
|
|
155
|
-
|
|
217
|
+
if ollama pull all-minilm:l6-v2 2>/dev/null; then
|
|
218
|
+
echo -e " ${GREEN}✓${NC} Model downloaded"
|
|
219
|
+
else
|
|
220
|
+
echo -e " ${YELLOW}!${NC} Model pull failed (will retry when Ollama runs)"
|
|
221
|
+
fi
|
|
156
222
|
fi
|
|
157
223
|
else
|
|
158
224
|
echo -e " ${YELLOW}○${NC} Skipping (Ollama not available)"
|
|
@@ -309,20 +375,58 @@ echo
|
|
|
309
375
|
echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
310
376
|
echo
|
|
311
377
|
|
|
312
|
-
# Verify
|
|
378
|
+
# Verify all services
|
|
313
379
|
echo -e "${BOLD}Step 7/7: Verification${NC}"
|
|
314
380
|
echo
|
|
315
|
-
echo -e " ${CYAN}◐${NC}
|
|
381
|
+
echo -e " ${CYAN}◐${NC} Checking all services..."
|
|
316
382
|
sleep 3
|
|
317
383
|
|
|
384
|
+
# Check 1: Ollama running
|
|
385
|
+
if curl -s http://localhost:11434/api/tags &>/dev/null; then
|
|
386
|
+
echo -e " ${GREEN}✓${NC} Ollama running"
|
|
387
|
+
else
|
|
388
|
+
echo -e " ${YELLOW}○${NC} Ollama not running (will start on next boot)"
|
|
389
|
+
fi
|
|
390
|
+
|
|
391
|
+
# Check 2: Ollama LaunchAgent (macOS)
|
|
392
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
393
|
+
if [ -f "$HOME/Library/LaunchAgents/com.ollama.serve.plist" ]; then
|
|
394
|
+
echo -e " ${GREEN}✓${NC} Ollama auto-start configured"
|
|
395
|
+
else
|
|
396
|
+
echo -e " ${YELLOW}○${NC} Ollama auto-start not configured"
|
|
397
|
+
fi
|
|
398
|
+
fi
|
|
399
|
+
|
|
400
|
+
# Check 3: Embedding model
|
|
401
|
+
if [ "$OLLAMA_AVAILABLE" = true ] && ollama list 2>/dev/null | grep -q "minilm"; then
|
|
402
|
+
echo -e " ${GREEN}✓${NC} Embedding model ready"
|
|
403
|
+
else
|
|
404
|
+
echo -e " ${YELLOW}○${NC} Embedding model pending"
|
|
405
|
+
fi
|
|
406
|
+
|
|
407
|
+
# Check 4: sqlite-vec (vector search)
|
|
408
|
+
if "$VENV_DIR/bin/python" -c "import sqlite_vec" 2>/dev/null; then
|
|
409
|
+
echo -e " ${GREEN}✓${NC} Vector search available (sqlite-vec)"
|
|
410
|
+
else
|
|
411
|
+
echo -e " ${YELLOW}○${NC} Vector search unavailable (keyword search only)"
|
|
412
|
+
fi
|
|
413
|
+
|
|
414
|
+
# Check 5: Memory daemon health
|
|
318
415
|
if curl -s "http://localhost:3848/health" 2>/dev/null | grep -q "healthy"; then
|
|
319
|
-
echo -e " ${GREEN}✓${NC}
|
|
416
|
+
echo -e " ${GREEN}✓${NC} Memory daemon running"
|
|
320
417
|
HEALTH_OK=true
|
|
321
418
|
else
|
|
322
|
-
echo -e " ${YELLOW}○${NC}
|
|
419
|
+
echo -e " ${YELLOW}○${NC} Memory daemon starting..."
|
|
323
420
|
HEALTH_OK=false
|
|
324
421
|
fi
|
|
325
422
|
|
|
423
|
+
# Check 6: Claudia LaunchAgent (macOS)
|
|
424
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
425
|
+
if [ -f "$HOME/Library/LaunchAgents/com.claudia.memory.plist" ]; then
|
|
426
|
+
echo -e " ${GREEN}✓${NC} Claudia auto-start configured"
|
|
427
|
+
fi
|
|
428
|
+
fi
|
|
429
|
+
|
|
326
430
|
echo
|
|
327
431
|
echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
328
432
|
echo
|