superlocalmemory 3.6.13 → 3.6.14

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.
Files changed (124) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/README.md +187 -741
  3. package/package.json +12 -5
  4. package/plugin/.claude-plugin/plugin.json +20 -0
  5. package/plugin/.mcp.json +12 -0
  6. package/plugin/CLAUDE.md +43 -0
  7. package/plugin/_GENERATED.md +6 -0
  8. package/plugin/agents/slm-memory-advisor.md +43 -0
  9. package/plugin/agents/slm-optimize-advisor.md +38 -0
  10. package/plugin/hooks/hooks.json +14 -0
  11. package/plugin/requirements.txt +1 -0
  12. package/plugin/scripts/ensure-venv.bat +122 -0
  13. package/plugin/scripts/ensure-venv.sh +105 -0
  14. package/plugin/scripts/slm-launch +15 -0
  15. package/plugin/scripts/slm-launch.bat +17 -0
  16. package/plugin/settings.json +16 -0
  17. package/plugin/skills/slm-cache/SKILL.md +140 -0
  18. package/plugin/skills/slm-compress/SKILL.md +143 -0
  19. package/plugin/skills/slm-graph/SKILL.md +300 -0
  20. package/plugin/skills/slm-recall/SKILL.md +196 -0
  21. package/plugin/skills/slm-remember/SKILL.md +182 -0
  22. package/plugin/skills/slm-session/SKILL.md +207 -0
  23. package/plugin/skills/slm-status/SKILL.md +149 -0
  24. package/plugin-src/.mcp.json +12 -0
  25. package/plugin-src/agents/slm-memory-advisor.md +43 -0
  26. package/plugin-src/agents/slm-optimize-advisor.md +38 -0
  27. package/plugin-src/commands/slm-optimize.md +22 -0
  28. package/plugin-src/commands/slm-recall.md +16 -0
  29. package/plugin-src/commands/slm-remember.md +16 -0
  30. package/plugin-src/commands/slm-status.md +15 -0
  31. package/plugin-src/hooks/.gitkeep +0 -0
  32. package/plugin-src/hooks/hooks.json +14 -0
  33. package/plugin-src/manifest.json +25 -0
  34. package/plugin-src/requirements.txt +1 -0
  35. package/plugin-src/rules/AGENTS.md +90 -0
  36. package/plugin-src/rules/CLAUDE.md.fragment +43 -0
  37. package/plugin-src/scripts/ensure-venv.bat +122 -0
  38. package/plugin-src/scripts/ensure-venv.sh +105 -0
  39. package/plugin-src/scripts/slm-launch +15 -0
  40. package/plugin-src/scripts/slm-launch.bat +17 -0
  41. package/plugin-src/settings.json +16 -0
  42. package/plugin-src/skills/slm-cache/SKILL.md +140 -0
  43. package/plugin-src/skills/slm-compress/SKILL.md +143 -0
  44. package/plugin-src/skills/slm-graph/SKILL.md +300 -0
  45. package/plugin-src/skills/slm-recall/SKILL.md +196 -0
  46. package/plugin-src/skills/slm-remember/SKILL.md +182 -0
  47. package/plugin-src/skills/slm-session/SKILL.md +207 -0
  48. package/plugin-src/skills/slm-status/SKILL.md +149 -0
  49. package/pyproject.toml +6 -2
  50. package/scripts/__tests__/build-plugin.test.mjs +613 -0
  51. package/scripts/_savings_math.py +270 -0
  52. package/scripts/build-plugin.js +742 -0
  53. package/scripts/dogfood_savings.py +490 -0
  54. package/scripts/install-skills.ps1 +4 -334
  55. package/scripts/install-skills.sh +4 -435
  56. package/scripts/postinstall-interactive.js +0 -27
  57. package/scripts/postinstall.js +21 -2
  58. package/src/superlocalmemory/__init__.py +1 -1
  59. package/src/superlocalmemory/cli/_lazy_init.py +115 -0
  60. package/src/superlocalmemory/cli/commands.py +348 -39
  61. package/src/superlocalmemory/cli/main.py +47 -4
  62. package/src/superlocalmemory/cli/setup_wizard.py +20 -6
  63. package/src/superlocalmemory/core/config.py +79 -9
  64. package/src/superlocalmemory/core/embeddings.py +10 -5
  65. package/src/superlocalmemory/core/engine.py +2 -2
  66. package/src/superlocalmemory/hooks/claude_code_hooks.py +27 -3
  67. package/src/superlocalmemory/hooks/portable_kit.py +506 -0
  68. package/src/superlocalmemory/infra/cloud_backup.py +99 -23
  69. package/src/superlocalmemory/mcp/cli_fallback.py +602 -0
  70. package/src/superlocalmemory/mcp/server.py +75 -4
  71. package/src/superlocalmemory/mcp/tools_code_graph.py +3 -3
  72. package/src/superlocalmemory/mcp/tools_core.py +12 -4
  73. package/src/superlocalmemory/optimize/cache/boundary_store.py +25 -6
  74. package/src/superlocalmemory/optimize/cache/centroid_store.py +27 -4
  75. package/src/superlocalmemory/optimize/cache/manager.py +92 -6
  76. package/src/superlocalmemory/optimize/cache/semantic.py +20 -1
  77. package/src/superlocalmemory/optimize/compress/ccr.py +12 -0
  78. package/src/superlocalmemory/optimize/compress/router.py +46 -13
  79. package/src/superlocalmemory/optimize/config/schema.py +6 -0
  80. package/src/superlocalmemory/optimize/proxy/_helpers.py +111 -8
  81. package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +14 -4
  82. package/src/superlocalmemory/optimize/proxy/gemini_surface.py +23 -6
  83. package/src/superlocalmemory/optimize/proxy/openai_surface.py +10 -4
  84. package/src/superlocalmemory/optimize/proxy/server.py +11 -0
  85. package/src/superlocalmemory/optimize/proxy/vertex_surface.py +246 -0
  86. package/src/superlocalmemory/optimize/storage/db.py +30 -0
  87. package/src/superlocalmemory/server/recall_serializer.py +3 -1
  88. package/src/superlocalmemory/server/unified_daemon.py +24 -6
  89. package/src/superlocalmemory/ui/css/legacy-dashboard.css +18 -0
  90. package/src/superlocalmemory/ui/css/neural-glass.css +5 -0
  91. package/src/superlocalmemory/ui/index.html +2 -2
  92. package/src/superlocalmemory/ui/js/core.js +98 -0
  93. package/src/superlocalmemory/ui/js/dashboard.js +8 -1
  94. package/src/superlocalmemory/ui/js/ide-status.js +16 -3
  95. package/src/superlocalmemory/ui/js/math-health.js +15 -3
  96. package/src/superlocalmemory/ui/js/optimize.js +18 -2
  97. package/src/superlocalmemory/ui/js/trust-dashboard.js +10 -1
  98. package/src/superlocalmemory.egg-info/PKG-INFO +189 -742
  99. package/src/superlocalmemory.egg-info/SOURCES.txt +6 -9
  100. package/src/superlocalmemory.egg-info/requires.txt +1 -0
  101. package/ide/skills/slm-build-graph/SKILL.md +0 -423
  102. package/ide/skills/slm-list-recent/SKILL.md +0 -348
  103. package/ide/skills/slm-recall/SKILL.md +0 -326
  104. package/ide/skills/slm-remember/SKILL.md +0 -194
  105. package/ide/skills/slm-show-patterns/SKILL.md +0 -224
  106. package/ide/skills/slm-status/SKILL.md +0 -363
  107. package/ide/skills/slm-switch-profile/SKILL.md +0 -442
  108. package/skills/slm-build-graph/SKILL.md +0 -423
  109. package/skills/slm-list-recent/SKILL.md +0 -348
  110. package/skills/slm-optimize/README.md +0 -55
  111. package/skills/slm-optimize/SKILL.md +0 -139
  112. package/skills/slm-recall/SKILL.md +0 -343
  113. package/skills/slm-remember/SKILL.md +0 -194
  114. package/skills/slm-show-patterns/SKILL.md +0 -224
  115. package/skills/slm-status/SKILL.md +0 -363
  116. package/skills/slm-switch-profile/SKILL.md +0 -442
  117. package/src/superlocalmemory/cli/doctor_cmd.py +0 -152
  118. package/src/superlocalmemory/skills/slm-build-graph/SKILL.md +0 -423
  119. package/src/superlocalmemory/skills/slm-list-recent/SKILL.md +0 -348
  120. package/src/superlocalmemory/skills/slm-recall/SKILL.md +0 -343
  121. package/src/superlocalmemory/skills/slm-remember/SKILL.md +0 -194
  122. package/src/superlocalmemory/skills/slm-show-patterns/SKILL.md +0 -224
  123. package/src/superlocalmemory/skills/slm-status/SKILL.md +0 -363
  124. package/src/superlocalmemory/skills/slm-switch-profile/SKILL.md +0 -442
@@ -1,442 +0,0 @@
1
- ---
2
- name: slm-switch-profile
3
- description: Switch between memory profiles for context isolation and management. Use when the user wants to change profile context, separate work/personal memories, or manage multiple independent memory spaces. Each profile has its own database, graph, and patterns.
4
- version: "3.4.23"
5
- license: AGPL-3.0-or-later
6
- compatibility: "Requires SuperLocalMemory V2 installed at ~/.claude-memory/"
7
- attribution:
8
- creator: Varun Pratap Bhardwaj
9
- role: Solution Architect & Original Creator
10
- project: SuperLocalMemory V2
11
- ---
12
-
13
- # SuperLocalMemory: Switch Profile
14
-
15
- Switch between memory profiles to maintain separate contexts for different projects or use cases.
16
-
17
- ## Usage
18
-
19
- ```bash
20
- slm switch-profile <name> [--create]
21
- ```
22
-
23
- ## What are Profiles?
24
-
25
- **Profiles = Isolated Memory Spaces**
26
-
27
- Each profile has its own:
28
- - ✅ **Separate database** - Zero context bleeding
29
- - ✅ **Independent knowledge graph** - Profile-specific relationships
30
- - ✅ **Unique patterns** - Different coding preferences per profile
31
- - ✅ **Isolated history** - No cross-contamination
32
-
33
- **Think of profiles as workspaces:**
34
- - `default` - General use
35
- - `work` - Work projects
36
- - `personal` - Personal projects
37
- - `client-acme` - Specific client work
38
- - `experiment` - Testing/learning
39
-
40
- ## Examples
41
-
42
- ### Example 1: Switch to Existing Profile
43
- ```bash
44
- $ slm switch-profile work
45
- ```
46
-
47
- **Output:**
48
- ```
49
- 🔄 Switching profile: default → work
50
-
51
- Profile Information:
52
- Name: work
53
- Created: 2026-01-20
54
- Memories: 342
55
- Last Used: 2026-02-05 09:15
56
-
57
- ✅ Switched to profile "work"
58
-
59
- Restart your AI tools (Cursor, ChatGPT, etc.) to use the new profile.
60
- ```
61
-
62
- ### Example 2: Create New Profile
63
- ```bash
64
- $ slm switch-profile client-acme --create
65
- ```
66
-
67
- **Output:**
68
- ```
69
- 🆕 Creating new profile: client-acme
70
-
71
- Profile created successfully!
72
- Location: ~/.claude-memory/profiles/client-acme/
73
- Database: memory.db (empty)
74
- Status: Active
75
-
76
- ✅ Switched to profile "client-acme"
77
-
78
- Next steps:
79
- • Start saving memories: slm remember "..."
80
- • AI tools will use this profile automatically
81
- ```
82
-
83
- ### Example 3: List All Profiles
84
- ```bash
85
- $ slm list-profiles
86
- ```
87
-
88
- **Output:**
89
- ```
90
- 📁 Available Profiles (4 total)
91
-
92
- → work (active)
93
- Created: 2026-01-20
94
- Memories: 342
95
- Size: 1.8 MB
96
- Last used: 2 minutes ago
97
-
98
- default
99
- Created: 2026-01-15
100
- Memories: 1,247
101
- Size: 4.2 MB
102
- Last used: 3 hours ago
103
-
104
- personal
105
- Created: 2026-01-22
106
- Memories: 89
107
- Size: 0.4 MB
108
- Last used: Yesterday
109
-
110
- client-acme
111
- Created: 2026-02-07
112
- Memories: 0
113
- Size: 0 KB
114
- Last used: Never
115
- ```
116
-
117
- ### Example 4: Return to Default
118
- ```bash
119
- $ slm switch-profile default
120
- ```
121
-
122
- **Always works** (default profile always exists)
123
-
124
- ## Arguments
125
-
126
- | Argument | Type | Required | Description |
127
- |----------|------|----------|-------------|
128
- | `<name>` | string | Yes | Profile name (lowercase, hyphens allowed) |
129
- | `--create` | flag | No | Create profile if doesn't exist |
130
- | `--force` | flag | No | Switch even if current profile has unsaved work |
131
-
132
- ## Profile Naming Rules
133
-
134
- **Valid:**
135
- - Lowercase letters: `a-z`
136
- - Numbers: `0-9`
137
- - Hyphens: `-`
138
- - Length: 1-64 characters
139
-
140
- **Examples:**
141
- - ✅ `work`
142
- - ✅ `client-acme`
143
- - ✅ `project-2024`
144
- - ✅ `personal`
145
-
146
- **Invalid:**
147
- - ❌ `Work` (uppercase)
148
- - ❌ `client_acme` (underscore)
149
- - ❌ `client acme` (space)
150
- - ❌ `client.acme` (period)
151
-
152
- ## Use Cases
153
-
154
- ### 1. Work/Personal Separation
155
- ```bash
156
- # Morning: Start work
157
- slm switch-profile work
158
- slm remember "Sprint planning: focus on auth system"
159
-
160
- # Evening: Personal projects
161
- slm switch-profile personal
162
- slm remember "Learning Rust - ownership is tricky"
163
- ```
164
-
165
- **Benefit:** No mixing of work and personal context
166
-
167
- ### 2. Multi-Client Consulting
168
- ```bash
169
- # Client A project
170
- slm switch-profile client-a
171
- slm remember "Client A uses AWS, prefers TypeScript"
172
-
173
- # Client B project
174
- slm switch-profile client-b
175
- slm remember "Client B uses Azure, prefers C#"
176
- ```
177
-
178
- **Benefit:** Client-specific preferences and patterns
179
-
180
- ### 3. Experimentation
181
- ```bash
182
- # Create throwaway profile for learning
183
- slm switch-profile experiment --create
184
- slm remember "Testing new framework..."
185
-
186
- # Later: delete when done
187
- slm delete-profile experiment
188
- ```
189
-
190
- **Benefit:** Safe experimentation without polluting main memory
191
-
192
- ### 4. Project Isolation
193
- ```bash
194
- # Different tech stacks
195
- slm switch-profile backend-api # Python/FastAPI
196
- slm switch-profile frontend-app # React/TypeScript
197
- slm switch-profile ml-pipeline # Python/PyTorch
198
- ```
199
-
200
- **Benefit:** Pattern learning adapts to each stack
201
-
202
- ### 5. Team Shared Profiles (Advanced)
203
- ```bash
204
- # Sync profile to team folder
205
- slm export-profile work > team-shared/work-profile.db
206
-
207
- # Team members import
208
- slm import-profile team-shared/work-profile.db --name work
209
- ```
210
-
211
- **Benefit:** Shared knowledge base for team
212
-
213
- ## How Switching Works
214
-
215
- ### Behind the Scenes
216
-
217
- **1. Profile Structure:**
218
- ```
219
- ~/.claude-memory/
220
- ├── memory.db ← Current active profile (symlink)
221
- ├── profiles/
222
- │ ├── default/
223
- │ │ └── memory.db ← Default profile database
224
- │ ├── work/
225
- │ │ └── memory.db ← Work profile database
226
- │ └── personal/
227
- │ └── memory.db ← Personal profile database
228
- └── current_profile ← Text file with active profile name
229
- ```
230
-
231
- **2. Switching Process:**
232
- ```bash
233
- $ slm switch-profile work
234
- ```
235
-
236
- - **Step 1:** Verify "work" profile exists
237
- - **Step 2:** Update symlink: `memory.db` → `profiles/work/memory.db`
238
- - **Step 3:** Write "work" to `current_profile` file
239
- - **Step 4:** Notify user to restart AI tools
240
-
241
- **3. AI Tools Read:**
242
- - MCP server reads `~/.claude-memory/memory.db`
243
- - Symlink automatically points to active profile
244
- - Transparent to AI tools
245
-
246
- ## Important Notes
247
-
248
- ### Restart Required
249
- **After switching, restart your AI tools:**
250
- - **Cursor:** Cmd+Q, reopen
251
- - **Claude Desktop:** Quit, reopen
252
- - **ChatGPT:** Close, reopen
253
- - **VS Code:** Reload window
254
-
255
- **Why:** Tools cache database connection at startup
256
-
257
- ### Profile Isolation is Complete
258
- **Each profile has:**
259
- - ❌ **NO access** to other profiles' memories
260
- - ❌ **NO shared** knowledge graph
261
- - ❌ **NO cross-profile** pattern learning
262
-
263
- **This is by design** for true isolation.
264
-
265
- ### Default Profile Special
266
- - Always exists
267
- - Cannot be deleted
268
- - Safe fallback
269
-
270
- ## Advanced Usage
271
-
272
- ### Profile Management
273
-
274
- **Create multiple profiles:**
275
- ```bash
276
- slm switch-profile work --create
277
- slm switch-profile personal --create
278
- slm switch-profile client-a --create
279
- ```
280
-
281
- **Backup profile:**
282
- ```bash
283
- cp -r ~/.claude-memory/profiles/work ~/.claude-memory/backups/work-2026-02-07
284
- ```
285
-
286
- **Delete profile:**
287
- ```bash
288
- slm delete-profile experiment
289
- # Warning: This permanently deletes all memories!
290
- ```
291
-
292
- **Rename profile:**
293
- ```bash
294
- slm rename-profile old-name new-name
295
- ```
296
-
297
- ### Scripting & Automation
298
-
299
- **Auto-switch by project directory:**
300
- ```bash
301
- # Add to .bashrc or .zshrc
302
- function cd() {
303
- builtin cd "$@"
304
-
305
- # Check for .slm-profile file
306
- if [ -f ".slm-profile" ]; then
307
- profile=$(cat .slm-profile)
308
- slm switch-profile "$profile" --quiet
309
- fi
310
- }
311
- ```
312
-
313
- **Usage:**
314
- ```bash
315
- # In project directory
316
- echo "myapp" > .slm-profile
317
-
318
- # CD into directory
319
- cd ~/projects/myapp
320
- # Automatically switches to "myapp" profile
321
- ```
322
-
323
- **Daily profile switching:**
324
- ```bash
325
- #!/bin/bash
326
- # cron: 0 9 * * 1-5 (Mon-Fri at 9 AM)
327
-
328
- slm switch-profile work
329
- echo "Switched to work profile" | notify-send "SuperLocalMemory"
330
- ```
331
-
332
- ### Profile Statistics
333
-
334
- **Compare profiles:**
335
- ```bash
336
- slm list-profiles --stats
337
- ```
338
-
339
- **Output:**
340
- ```
341
- Profile Memories Size Nodes Edges Patterns
342
- default 1,247 4.2 MB 892 2,134 34
343
- work 342 1.8 MB 256 789 12
344
- personal 89 0.4 MB 67 145 4
345
- ```
346
-
347
- **Export profile summary:**
348
- ```bash
349
- slm profile-summary work > work-summary.txt
350
- ```
351
-
352
- ## Troubleshooting
353
-
354
- ### "Profile not found"
355
-
356
- **Cause:** Typo or profile doesn't exist
357
-
358
- **Solution:**
359
- ```bash
360
- # List existing profiles
361
- slm list-profiles
362
-
363
- # Create if needed
364
- slm switch-profile myprofile --create
365
- ```
366
-
367
- ### "Switch failed: Database locked"
368
-
369
- **Cause:** AI tool still using old profile
370
-
371
- **Solution:**
372
- ```bash
373
- # Kill all MCP servers
374
- killall python3
375
-
376
- # Try again
377
- slm switch-profile work
378
-
379
- # Restart AI tools
380
- ```
381
-
382
- ### "Memories disappeared after switching"
383
-
384
- **Cause:** Switched to empty/different profile (working as intended)
385
-
386
- **Solution:**
387
- ```bash
388
- # Check current profile
389
- slm status | grep "Current Profile"
390
-
391
- # Switch back to profile with memories
392
- slm switch-profile default
393
-
394
- # Or list all profiles to find the right one
395
- slm list-profiles
396
- ```
397
-
398
- ### "AI tools still see old profile"
399
-
400
- **Cause:** Didn't restart tools
401
-
402
- **Solution:**
403
- ```bash
404
- # Must completely restart (not just reload)
405
- # macOS: Cmd+Q, then reopen
406
- # Windows/Linux: Close all windows, reopen
407
- ```
408
-
409
- ## Performance
410
-
411
- | Operation | Time | Notes |
412
- |-----------|------|-------|
413
- | Switch profile | ~100ms | Instant |
414
- | Create profile | ~200ms | Fast |
415
- | List profiles | ~50ms | Very fast |
416
-
417
- **Switching is fast** because it's just updating a symlink.
418
-
419
- ## Notes
420
-
421
- - **No data loss:** Switching never deletes memories
422
- - **Profile persistence:** Memories stay in original profile
423
- - **Tool transparency:** AI tools don't need special config per profile
424
- - **Backup-friendly:** Each profile is separate directory
425
-
426
- ## Related Commands
427
-
428
- - `slm list-profiles` - Show all profiles
429
- - `slm delete-profile <name>` - Delete a profile
430
- - `slm rename-profile <old> <new>` - Rename profile
431
- - `slm status` - Shows current profile
432
- - `slm export-profile <name>` - Export to file
433
- - `slm import-profile <file>` - Import from file
434
-
435
- ---
436
-
437
- **Created by:** [Varun Pratap Bhardwaj](https://github.com/varun369) (Solution Architect)
438
- **Project:** SuperLocalMemory V2
439
- **License:** MIT (see [LICENSE](../../LICENSE))
440
- **Repository:** https://github.com/varun369/SuperLocalMemoryV2
441
-
442
- *Open source doesn't mean removing credit. Attribution must be preserved per MIT License terms.*
@@ -1,152 +0,0 @@
1
- # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under AGPL-3.0-or-later - see LICENSE file
3
- # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
-
5
- """slm doctor — preflight and health checks.
6
-
7
- Part of Qualixar | Author: Varun Pratap Bhardwaj
8
- """
9
-
10
- from __future__ import annotations
11
-
12
- import json
13
- import platform
14
- import sys
15
- from pathlib import Path
16
- from typing import Any
17
-
18
- _DEFAULT_DATA_DIR = Path.home() / ".superlocalmemory"
19
-
20
-
21
- def _check_python() -> dict[str, Any]:
22
- v = sys.version_info
23
- ok = (v.major, v.minor) >= (3, 10)
24
- return {
25
- "name": "python",
26
- "status": "ok" if ok else "error",
27
- "detail": f"Python {v.major}.{v.minor}.{v.micro}",
28
- "hint": None if ok else "SLM requires Python >= 3.10",
29
- }
30
-
31
-
32
- def _check_platform() -> dict[str, Any]:
33
- return {
34
- "name": "platform",
35
- "status": "ok",
36
- "detail": f"{platform.system()} {platform.release()} {platform.machine()}",
37
- "hint": None,
38
- }
39
-
40
-
41
- def _check_portalocker() -> dict[str, Any]:
42
- try:
43
- import portalocker # noqa: F401
44
- return {
45
- "name": "portalocker",
46
- "status": "ok",
47
- "detail": "installed",
48
- "hint": None,
49
- }
50
- except ImportError:
51
- return {
52
- "name": "portalocker",
53
- "status": "error",
54
- "detail": "not installed",
55
- "hint": "pip install --upgrade superlocalmemory",
56
- }
57
-
58
-
59
- def _check_data_dir(data_dir: Path) -> dict[str, Any]:
60
- from superlocalmemory.core import safe_fs
61
- try:
62
- safe_fs.validate_data_dir(data_dir)
63
- return {
64
- "name": "data directory",
65
- "status": "ok",
66
- "detail": str(data_dir),
67
- "hint": None,
68
- }
69
- except safe_fs.SafeFsError as exc:
70
- return {
71
- "name": "data directory",
72
- "status": "error",
73
- "detail": str(data_dir),
74
- "hint": str(exc),
75
- }
76
-
77
-
78
- def _check_migration(data_dir: Path) -> dict[str, Any]:
79
- from superlocalmemory.migrations.v3_4_25_to_v3_4_26 import is_ready
80
- ok = is_ready(data_dir)
81
- return {
82
- "name": "v3.4.26 migration",
83
- "status": "ok" if ok else "warn",
84
- "detail": "ready" if ok else "not migrated yet",
85
- "hint": None if ok else
86
- "Run once: python -m superlocalmemory.migrations.v3_4_25_to_v3_4_26",
87
- }
88
-
89
-
90
- def _check_queue_db(data_dir: Path) -> dict[str, Any]:
91
- queue = data_dir / "recall_queue.db"
92
- if queue.exists():
93
- return {
94
- "name": "queue database",
95
- "status": "ok",
96
- "detail": f"{queue} ({queue.stat().st_size} bytes)",
97
- "hint": None,
98
- }
99
- return {
100
- "name": "queue database",
101
- "status": "warn",
102
- "detail": "not yet created",
103
- "hint": "The daemon will create this on first use.",
104
- }
105
-
106
-
107
- def run_checks(*, data_dir: Path | None = None) -> dict[str, Any]:
108
- dd = Path(data_dir) if data_dir is not None else _DEFAULT_DATA_DIR
109
- checks = [
110
- _check_python(),
111
- _check_platform(),
112
- _check_portalocker(),
113
- _check_data_dir(dd),
114
- _check_migration(dd),
115
- _check_queue_db(dd),
116
- ]
117
- has_error = any(c["status"] == "error" for c in checks)
118
- exit_code = 1 if has_error else 0
119
- return {
120
- "data_dir": str(dd),
121
- "checks": checks,
122
- "exit_code": exit_code,
123
- }
124
-
125
-
126
- def _print_report(report: dict[str, Any]) -> None:
127
- glyphs = {"ok": "\u2713", "warn": "\u26a0", "error": "\u2717"}
128
- print(f"SLM doctor — data dir: {report['data_dir']}\n")
129
- for c in report["checks"]:
130
- g = glyphs.get(c["status"], "?")
131
- print(f" {g} {c['name']:<20} {c['detail']}")
132
- if c.get("hint"):
133
- print(f" {c['hint']}")
134
- print(f"\nExit code: {report['exit_code']}")
135
-
136
-
137
- def main(argv: list[str] | None = None) -> int:
138
- import argparse
139
- parser = argparse.ArgumentParser(prog="slm-doctor")
140
- parser.add_argument("--json", action="store_true", help="JSON output")
141
- parser.add_argument("--data-dir", type=Path, default=None)
142
- args = parser.parse_args(argv)
143
- report = run_checks(data_dir=args.data_dir)
144
- if args.json:
145
- print(json.dumps(report, indent=2))
146
- else:
147
- _print_report(report)
148
- return int(report["exit_code"])
149
-
150
-
151
- if __name__ == "__main__":
152
- raise SystemExit(main())