@dinasor/mnemo-cli 0.0.1

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 (38) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE +21 -0
  3. package/README.md +263 -0
  4. package/VERSION +1 -0
  5. package/bin/mnemo.js +139 -0
  6. package/memory.ps1 +178 -0
  7. package/memory_mac.sh +2447 -0
  8. package/package.json +36 -0
  9. package/scripts/memory/installer/bootstrap.ps1 +21 -0
  10. package/scripts/memory/installer/core/bridge.ps1 +285 -0
  11. package/scripts/memory/installer/core/io.ps1 +110 -0
  12. package/scripts/memory/installer/core/paths.ps1 +83 -0
  13. package/scripts/memory/installer/features/gitignore_setup.ps1 +80 -0
  14. package/scripts/memory/installer/features/hooks_setup.ps1 +157 -0
  15. package/scripts/memory/installer/features/mcp_setup.ps1 +87 -0
  16. package/scripts/memory/installer/features/memory_scaffold.ps1 +541 -0
  17. package/scripts/memory/installer/features/vector_setup.ps1 +103 -0
  18. package/scripts/memory/installer/templates/add-journal-entry.ps1 +122 -0
  19. package/scripts/memory/installer/templates/add-lesson.ps1 +151 -0
  20. package/scripts/memory/installer/templates/autonomy/__init__.py +6 -0
  21. package/scripts/memory/installer/templates/autonomy/context_safety.py +181 -0
  22. package/scripts/memory/installer/templates/autonomy/entity_resolver.py +215 -0
  23. package/scripts/memory/installer/templates/autonomy/ingest_pipeline.py +252 -0
  24. package/scripts/memory/installer/templates/autonomy/lifecycle_engine.py +254 -0
  25. package/scripts/memory/installer/templates/autonomy/policies.yaml +59 -0
  26. package/scripts/memory/installer/templates/autonomy/reranker.py +220 -0
  27. package/scripts/memory/installer/templates/autonomy/retrieval_router.py +148 -0
  28. package/scripts/memory/installer/templates/autonomy/runner.py +272 -0
  29. package/scripts/memory/installer/templates/autonomy/schema.py +150 -0
  30. package/scripts/memory/installer/templates/autonomy/vault_policy.py +205 -0
  31. package/scripts/memory/installer/templates/build-memory-sqlite.py +111 -0
  32. package/scripts/memory/installer/templates/clear-active.ps1 +55 -0
  33. package/scripts/memory/installer/templates/customization.md +84 -0
  34. package/scripts/memory/installer/templates/lint-memory.ps1 +217 -0
  35. package/scripts/memory/installer/templates/mnemo_vector.py +556 -0
  36. package/scripts/memory/installer/templates/query-memory-sqlite.py +95 -0
  37. package/scripts/memory/installer/templates/query-memory.ps1 +122 -0
  38. package/scripts/memory/installer/templates/rebuild-memory-index.ps1 +293 -0
@@ -0,0 +1,157 @@
1
+ <#
2
+ hooks_setup.ps1 - Git hooks setup for Mnemo (pre-commit + optional post-commit vector sync).
3
+ Dot-sourced by bootstrap.ps1.
4
+ #>
5
+
6
+ function Install-GitHooks {
7
+ param(
8
+ [Parameter(Mandatory=$true)][hashtable]$Ctx,
9
+ [object]$VectorPython = $null,
10
+ [switch]$EnableVector,
11
+ [switch]$Force
12
+ )
13
+
14
+ $hookBody = @'
15
+ #!/bin/sh
16
+ # Mnemo: auto-rebuild indexes + lint before commit
17
+
18
+ set -e
19
+
20
+ ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
21
+ cd "$ROOT"
22
+
23
+ echo "[Mnemo] Rebuilding indexes + lint..."
24
+ if command -v powershell.exe >/dev/null 2>&1; then
25
+ powershell.exe -ExecutionPolicy Bypass -File "./scripts/memory/rebuild-memory-index.ps1"
26
+ powershell.exe -ExecutionPolicy Bypass -File "./scripts/memory/lint-memory.ps1"
27
+ elif command -v pwsh >/dev/null 2>&1; then
28
+ pwsh -ExecutionPolicy Bypass -File "./scripts/memory/rebuild-memory-index.ps1"
29
+ pwsh -ExecutionPolicy Bypass -File "./scripts/memory/lint-memory.ps1"
30
+ else
31
+ echo "[Mnemo] PowerShell not found; skipping memory rebuild/lint."
32
+ fi
33
+
34
+ for p in \
35
+ .mnemo/memory/lessons/index.md \
36
+ .mnemo/memory/lessons-index.json \
37
+ .mnemo/memory/journal-index.md \
38
+ .mnemo/memory/journal-index.json \
39
+ .mnemo/memory/digests/*.digest.md \
40
+ .cursor/memory/lessons/index.md \
41
+ .cursor/memory/lessons-index.json \
42
+ .cursor/memory/journal-index.md \
43
+ .cursor/memory/journal-index.json \
44
+ .cursor/memory/digests/*.digest.md
45
+ do
46
+ git add $p 2>/dev/null || true
47
+ done
48
+
49
+ exit 0
50
+ '@
51
+
52
+ $githookPath = Join-Path $Ctx.PortableHooksDir "pre-commit"
53
+ Write-MnemoFile $githookPath $hookBody -ForceWrite:$Force -LineEndings "LF"
54
+
55
+ if (Test-Path $Ctx.GitHooksDir) {
56
+ $legacyHookPath = Join-Path $Ctx.GitHooksDir "pre-commit"
57
+ if ((Test-Path $legacyHookPath) -and (-not $Force)) {
58
+ $existing = Get-Content -Raw -ErrorAction SilentlyContinue $legacyHookPath
59
+ if ($existing -match "Mnemo: auto-rebuild" -or $existing -match "Cursor Memory: auto-rebuild") {
60
+ Write-Host "SKIP (exists): $legacyHookPath" -ForegroundColor DarkYellow
61
+ } else {
62
+ $combined = ($existing.TrimEnd() + "`n`n" + $hookBody)
63
+ Write-MnemoFile $legacyHookPath $combined -ForceWrite:$true -LineEndings "LF"
64
+ }
65
+ } else {
66
+ Write-MnemoFile $legacyHookPath $hookBody -ForceWrite:$Force -LineEndings "LF"
67
+ }
68
+ }
69
+
70
+ if ($EnableVector -and (-not $script:DryRun) -and $null -ne $VectorPython) {
71
+ _Install-PostCommitVectorHook -Ctx $Ctx -VectorPython $VectorPython -VectorProvider $VectorProvider -Force:$Force
72
+ } elseif ($EnableVector -and $script:DryRun) {
73
+ Write-Host "[DRY RUN] WOULD CONFIGURE: .githooks/post-commit (MnemoVector wrapper)" -ForegroundColor DarkCyan
74
+ }
75
+ }
76
+
77
+ function _Install-PostCommitVectorHook {
78
+ param(
79
+ [hashtable]$Ctx,
80
+ [object]$VectorPython,
81
+ [string]$VectorProvider,
82
+ [switch]$Force
83
+ )
84
+
85
+ $apiGuard = if ($VectorProvider -eq "gemini") {
86
+ '[ -z "${GEMINI_API_KEY:-}" ] && exit 0'
87
+ } else {
88
+ '[ -z "${OPENAI_API_KEY:-}" ] && exit 0'
89
+ }
90
+
91
+ $pyHookPath = ($VectorPython.Path -replace '\\', '/')
92
+ $backupName = "post-commit.before-mnemo-vector"
93
+ $postMarker = "Mnemo Vector Hook Wrapper"
94
+
95
+ $postHookBody = @"
96
+ #!/bin/sh
97
+ # Mnemo Vector Hook Wrapper
98
+ set -e
99
+
100
+ ROOT="`$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
101
+ cd "`$ROOT" || exit 0
102
+
103
+ if [ -f ".githooks/$backupName" ]; then
104
+ sh ".githooks/$backupName" || true
105
+ fi
106
+
107
+ $apiGuard
108
+
109
+ LOCKDIR="`$ROOT/.mnemo/memory/.sync.lock"
110
+ if [ ! -d "`$ROOT/.mnemo/memory" ] && [ -d "`$ROOT/.cursor/memory" ]; then
111
+ LOCKDIR="`$ROOT/.cursor/memory/.sync.lock"
112
+ fi
113
+ if [ -d "`$LOCKDIR" ]; then
114
+ NOW=`$(date +%s 2>/dev/null || echo 0)
115
+ MTIME=`$(stat -c %Y "`$LOCKDIR" 2>/dev/null || stat -f %m "`$LOCKDIR" 2>/dev/null || echo 0)
116
+ AGE=`$((NOW - MTIME))
117
+ if [ "`$AGE" -gt 600 ] 2>/dev/null; then
118
+ rmdir "`$LOCKDIR" 2>/dev/null || true
119
+ fi
120
+ fi
121
+
122
+ if mkdir "`$LOCKDIR" 2>/dev/null; then
123
+ trap 'rmdir "`$LOCKDIR" 2>/dev/null || true' EXIT INT TERM
124
+ "$pyHookPath" -c "import sys; sys.path.insert(0, 'scripts/memory'); from mnemo_vector import vector_sync; print('[MnemoVector]', vector_sync())" 2>&1 | tail -1 || true
125
+ fi
126
+
127
+ exit 0
128
+ "@
129
+
130
+ $postHookPath = Join-Path $Ctx.PortableHooksDir "post-commit"
131
+ $backupPath = Join-Path $Ctx.PortableHooksDir $backupName
132
+
133
+ if (Test-Path $postHookPath) {
134
+ $existingPost = Get-Content -Raw -ErrorAction SilentlyContinue $postHookPath
135
+ if ($existingPost -and $existingPost -notmatch [regex]::Escape($postMarker)) {
136
+ if (!(Test-Path $backupPath) -or $Force) {
137
+ [System.IO.File]::WriteAllText($backupPath, $existingPost, (New-Object System.Text.UTF8Encoding $false))
138
+ }
139
+ }
140
+ }
141
+
142
+ Write-MnemoFile $postHookPath $postHookBody -ForceWrite:$Force -LineEndings "LF"
143
+
144
+ if (Test-Path $Ctx.GitHooksDir) {
145
+ $legacyPost = Join-Path $Ctx.GitHooksDir "post-commit"
146
+ if ((Test-Path $legacyPost) -and (-not $Force)) {
147
+ $legacyExisting = Get-Content -Raw -ErrorAction SilentlyContinue $legacyPost
148
+ if ($legacyExisting -and $legacyExisting -notmatch [regex]::Escape($postMarker)) {
149
+ Write-Host "SKIP (legacy post-commit exists): $legacyPost" -ForegroundColor DarkYellow
150
+ } else {
151
+ Write-MnemoFile $legacyPost $postHookBody -ForceWrite:$Force -LineEndings "LF"
152
+ }
153
+ } else {
154
+ Write-MnemoFile $legacyPost $postHookBody -ForceWrite:$Force -LineEndings "LF"
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,87 @@
1
+ <#
2
+ mcp_setup.ps1 - MCP configuration for Mnemo vector engine.
3
+ Dot-sourced by bootstrap.ps1.
4
+ #>
5
+
6
+ function Install-McpConfig {
7
+ param(
8
+ [Parameter(Mandatory=$true)][hashtable]$Ctx,
9
+ [Parameter(Mandatory=$true)][object]$VectorPython,
10
+ [string]$VectorProvider = "openai",
11
+ [switch]$Force
12
+ )
13
+
14
+ if ($script:DryRun) {
15
+ Write-Host "[DRY RUN] WOULD CONFIGURE: .mnemo/mcp/cursor.mcp.json (+ .cursor/mcp.json bridge)" -ForegroundColor DarkCyan
16
+ return
17
+ }
18
+
19
+ $mcpPath = $Ctx.MnemoCursorMcpPath
20
+ $engineAbsPath = (Resolve-Path (Join-Path $Ctx.MemScripts "mnemo_vector.py")).Path
21
+ $mcpRoot = [ordered]@{}
22
+
23
+ if (Test-Path $mcpPath) {
24
+ try {
25
+ $existingMcp = Get-Content -Raw -Encoding UTF8 $mcpPath | ConvertFrom-Json
26
+ if ($existingMcp) {
27
+ foreach ($prop in $existingMcp.PSObject.Properties) {
28
+ $mcpRoot[$prop.Name] = $prop.Value
29
+ }
30
+ }
31
+ } catch {
32
+ Write-Host "WARNING: Could not parse .cursor/mcp.json, rebuilding mcpServers block." -ForegroundColor Yellow
33
+ }
34
+ }
35
+
36
+ $servers = [ordered]@{}
37
+ if ($mcpRoot.Contains("mcpServers") -and $mcpRoot["mcpServers"]) {
38
+ foreach ($prop in $mcpRoot["mcpServers"].PSObject.Properties) {
39
+ $servers[$prop.Name] = $prop.Value
40
+ }
41
+ }
42
+
43
+ $envBlock = @{ MNEMO_PROVIDER = $VectorProvider }
44
+ if ($VectorProvider -eq "gemini") {
45
+ $envBlock["GEMINI_API_KEY"] = '${env:GEMINI_API_KEY}'
46
+ } else {
47
+ $envBlock["OPENAI_API_KEY"] = '${env:OPENAI_API_KEY}'
48
+ }
49
+
50
+ $argsList = @()
51
+ if ($VectorPython.Args) { $argsList += $VectorPython.Args }
52
+ $argsList += $engineAbsPath
53
+
54
+ $servers["MnemoVector"] = @{
55
+ command = $VectorPython.Path
56
+ args = $argsList
57
+ env = $envBlock
58
+ }
59
+ $mcpRoot["mcpServers"] = $servers
60
+ $mcpJson = $mcpRoot | ConvertTo-Json -Depth 15
61
+
62
+ $writeMcp = $true
63
+ if ((-not $Force) -and (Test-Path $mcpPath)) {
64
+ try {
65
+ $existingCanonical = (Get-Content -Raw -Encoding UTF8 $mcpPath | ConvertFrom-Json | ConvertTo-Json -Depth 15)
66
+ $existingNorm = ($existingCanonical -replace "`r?`n", "`n").Trim()
67
+ $newNorm = ($mcpJson -replace "`r?`n", "`n").Trim()
68
+ if ($existingNorm -eq $newNorm) {
69
+ $writeMcp = $false
70
+ Write-Host "SKIP (exists): $mcpPath (MnemoVector MCP unchanged)" -ForegroundColor DarkYellow
71
+ }
72
+ } catch {}
73
+ }
74
+
75
+ if ($writeMcp) {
76
+ if (Test-Path $mcpPath) {
77
+ Copy-Item -Path $mcpPath -Destination "$mcpPath.bak" -Force
78
+ }
79
+ $mcpTmp = "$mcpPath.tmp"
80
+ [System.IO.File]::WriteAllText($mcpTmp, $mcpJson, (New-Object System.Text.UTF8Encoding $false))
81
+ Move-Item -Path $mcpTmp -Destination $mcpPath -Force
82
+ Write-Host "WROTE: $mcpPath" -ForegroundColor Green
83
+ }
84
+
85
+ # Keep Cursor integration path in sync as a bridge target.
86
+ Ensure-MnemoFileBridge -CanonicalPath $mcpPath -BridgePath $Ctx.CursorMcpPath | Out-Null
87
+ }