@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.
- package/CHANGELOG.md +46 -0
- package/LICENSE +21 -0
- package/README.md +263 -0
- package/VERSION +1 -0
- package/bin/mnemo.js +139 -0
- package/memory.ps1 +178 -0
- package/memory_mac.sh +2447 -0
- package/package.json +36 -0
- package/scripts/memory/installer/bootstrap.ps1 +21 -0
- package/scripts/memory/installer/core/bridge.ps1 +285 -0
- package/scripts/memory/installer/core/io.ps1 +110 -0
- package/scripts/memory/installer/core/paths.ps1 +83 -0
- package/scripts/memory/installer/features/gitignore_setup.ps1 +80 -0
- package/scripts/memory/installer/features/hooks_setup.ps1 +157 -0
- package/scripts/memory/installer/features/mcp_setup.ps1 +87 -0
- package/scripts/memory/installer/features/memory_scaffold.ps1 +541 -0
- package/scripts/memory/installer/features/vector_setup.ps1 +103 -0
- package/scripts/memory/installer/templates/add-journal-entry.ps1 +122 -0
- package/scripts/memory/installer/templates/add-lesson.ps1 +151 -0
- package/scripts/memory/installer/templates/autonomy/__init__.py +6 -0
- package/scripts/memory/installer/templates/autonomy/context_safety.py +181 -0
- package/scripts/memory/installer/templates/autonomy/entity_resolver.py +215 -0
- package/scripts/memory/installer/templates/autonomy/ingest_pipeline.py +252 -0
- package/scripts/memory/installer/templates/autonomy/lifecycle_engine.py +254 -0
- package/scripts/memory/installer/templates/autonomy/policies.yaml +59 -0
- package/scripts/memory/installer/templates/autonomy/reranker.py +220 -0
- package/scripts/memory/installer/templates/autonomy/retrieval_router.py +148 -0
- package/scripts/memory/installer/templates/autonomy/runner.py +272 -0
- package/scripts/memory/installer/templates/autonomy/schema.py +150 -0
- package/scripts/memory/installer/templates/autonomy/vault_policy.py +205 -0
- package/scripts/memory/installer/templates/build-memory-sqlite.py +111 -0
- package/scripts/memory/installer/templates/clear-active.ps1 +55 -0
- package/scripts/memory/installer/templates/customization.md +84 -0
- package/scripts/memory/installer/templates/lint-memory.ps1 +217 -0
- package/scripts/memory/installer/templates/mnemo_vector.py +556 -0
- package/scripts/memory/installer/templates/query-memory-sqlite.py +95 -0
- package/scripts/memory/installer/templates/query-memory.ps1 +122 -0
- 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
|
+
}
|