superlocalmemory 2.3.6 → 2.3.7
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 +24 -0
- package/hooks/memory-list-skill.js +13 -4
- package/hooks/memory-recall-skill.js +6 -1
- package/package.json +1 -1
- package/src/memory_store_v2.py +49 -12
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,30 @@ SuperLocalMemory V2 - Intelligent local memory system for AI coding assistants.
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## [2.3.7] - 2026-02-09
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **--full flag**: Show complete memory content without truncation in search/list/recent/cluster commands
|
|
23
|
+
- **Smart truncation**: Memories <5000 chars shown in full, ≥5000 chars truncated to 2000 chars (previously always truncated at 200 chars)
|
|
24
|
+
- **Help text**: Added --full flag documentation to CLI help output
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- **CLI bug**: Fixed `get` command error - `get_memory()` → `get_by_id()` method call
|
|
28
|
+
- **Content display**: Recall now shows full content for short/medium memories instead of always truncating at 200 chars
|
|
29
|
+
- **User experience**: Agents and users can now see complete memory content by default for most memories
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **Truncation logic**: 200 char limit → 2000 char preview for memories ≥5000 chars
|
|
33
|
+
- **Node.js wrappers**: memory-recall-skill.js and memory-list-skill.js updated to pass --full flag through
|
|
34
|
+
|
|
35
|
+
### Technical Details
|
|
36
|
+
- Added `format_content()` helper function in memory_store_v2.py (line 918)
|
|
37
|
+
- Updated search/list/recent/cluster commands to use smart truncation
|
|
38
|
+
- Backward compatible: same output structure, MCP/API calls unaffected
|
|
39
|
+
- All 74+ existing memories tested: short memories show full, long memories truncate intelligently
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
19
43
|
## [2.3.5] - 2026-02-09
|
|
20
44
|
|
|
21
45
|
### Added
|
|
@@ -34,6 +34,7 @@ Options:
|
|
|
34
34
|
• recent: Latest created first (default)
|
|
35
35
|
• accessed: Most recently accessed
|
|
36
36
|
• importance: Highest importance first
|
|
37
|
+
--full Show complete content without truncation
|
|
37
38
|
|
|
38
39
|
Examples:
|
|
39
40
|
memory-list
|
|
@@ -42,17 +43,17 @@ Examples:
|
|
|
42
43
|
|
|
43
44
|
memory-list --sort importance
|
|
44
45
|
|
|
45
|
-
memory-list --limit 10 --sort accessed
|
|
46
|
+
memory-list --limit 10 --sort accessed --full
|
|
46
47
|
|
|
47
48
|
Output Format:
|
|
48
|
-
• ID, Content (truncated), Tags, Importance
|
|
49
|
+
• ID, Content (smart truncated), Tags, Importance
|
|
49
50
|
• Creation timestamp
|
|
50
51
|
• Access count and last accessed time
|
|
51
52
|
|
|
52
53
|
Notes:
|
|
53
54
|
• Default shows last 20 memories
|
|
54
|
-
•
|
|
55
|
-
• Use
|
|
55
|
+
• Smart truncation: full content if <5000 chars, preview if ≥5000 chars
|
|
56
|
+
• Use --full flag to always show complete content
|
|
56
57
|
• Sort by 'accessed' to find frequently used memories
|
|
57
58
|
`);
|
|
58
59
|
return;
|
|
@@ -61,6 +62,7 @@ Notes:
|
|
|
61
62
|
// Parse options
|
|
62
63
|
let limit = 20;
|
|
63
64
|
let sortBy = 'recent';
|
|
65
|
+
let showFull = false;
|
|
64
66
|
|
|
65
67
|
for (let i = 0; i < args.length; i++) {
|
|
66
68
|
const arg = args[i];
|
|
@@ -83,6 +85,8 @@ Notes:
|
|
|
83
85
|
return;
|
|
84
86
|
}
|
|
85
87
|
i++;
|
|
88
|
+
} else if (arg === '--full') {
|
|
89
|
+
showFull = true;
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
92
|
|
|
@@ -97,6 +101,11 @@ Notes:
|
|
|
97
101
|
pythonArgs = ['list', limit.toString()];
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
// Add --full flag if requested
|
|
105
|
+
if (showFull) {
|
|
106
|
+
pythonArgs.push('--full');
|
|
107
|
+
}
|
|
108
|
+
|
|
100
109
|
try {
|
|
101
110
|
const { stdout, stderr } = await execFileAsync('python3', [memoryScript, ...pythonArgs]);
|
|
102
111
|
|
|
@@ -33,13 +33,14 @@ Arguments:
|
|
|
33
33
|
|
|
34
34
|
Options:
|
|
35
35
|
--limit <n> Maximum results to return (default: 10)
|
|
36
|
+
--full Show complete content without truncation
|
|
36
37
|
|
|
37
38
|
Examples:
|
|
38
39
|
memory-recall "authentication bug"
|
|
39
40
|
|
|
40
41
|
memory-recall "API configuration" --limit 5
|
|
41
42
|
|
|
42
|
-
memory-recall "security best practices"
|
|
43
|
+
memory-recall "security best practices" --full
|
|
43
44
|
|
|
44
45
|
memory-recall "user preferences"
|
|
45
46
|
|
|
@@ -47,6 +48,8 @@ Output Format:
|
|
|
47
48
|
• Ranked by relevance (TF-IDF cosine similarity)
|
|
48
49
|
• Shows: ID, Content, Tags, Importance, Timestamp
|
|
49
50
|
• Higher scores = better matches
|
|
51
|
+
• Smart truncation: full content if <5000 chars, preview if ≥5000 chars
|
|
52
|
+
• Use --full flag to always show complete content
|
|
50
53
|
|
|
51
54
|
Notes:
|
|
52
55
|
• Uses local TF-IDF search (no external APIs)
|
|
@@ -67,6 +70,8 @@ Notes:
|
|
|
67
70
|
if (arg === '--limit' && i + 1 < args.length) {
|
|
68
71
|
// Note: V1 store doesn't support --limit in search, will truncate output instead
|
|
69
72
|
i++; // Skip but don't add to pythonArgs
|
|
73
|
+
} else if (arg === '--full') {
|
|
74
|
+
pythonArgs.push('--full');
|
|
70
75
|
} else if (!arg.startsWith('--') && query === null) {
|
|
71
76
|
query = arg;
|
|
72
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superlocalmemory",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.7",
|
|
4
4
|
"description": "Your AI Finally Remembers You - Local-first intelligent memory system for AI assistants. Works with Claude, Cursor, Windsurf, VS Code/Copilot, Codex, and 16+ AI tools. 100% local, zero cloud dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-memory",
|
package/src/memory_store_v2.py
CHANGED
|
@@ -915,6 +915,25 @@ class MemoryStoreV2:
|
|
|
915
915
|
return ''.join(output)
|
|
916
916
|
|
|
917
917
|
|
|
918
|
+
def format_content(content: str, full: bool = False, threshold: int = 5000, preview_len: int = 2000) -> str:
|
|
919
|
+
"""
|
|
920
|
+
Smart content formatting with optional truncation.
|
|
921
|
+
|
|
922
|
+
Args:
|
|
923
|
+
content: Content to format
|
|
924
|
+
full: If True, always show full content
|
|
925
|
+
threshold: Max length before truncation (default 5000)
|
|
926
|
+
preview_len: Preview length when truncating (default 2000)
|
|
927
|
+
|
|
928
|
+
Returns:
|
|
929
|
+
Formatted content string
|
|
930
|
+
"""
|
|
931
|
+
if full or len(content) < threshold:
|
|
932
|
+
return content
|
|
933
|
+
else:
|
|
934
|
+
return f"{content[:preview_len]}..."
|
|
935
|
+
|
|
936
|
+
|
|
918
937
|
# CLI interface (V1 compatible + V2 extensions)
|
|
919
938
|
if __name__ == "__main__":
|
|
920
939
|
import sys
|
|
@@ -925,16 +944,18 @@ if __name__ == "__main__":
|
|
|
925
944
|
print("MemoryStore V2 CLI")
|
|
926
945
|
print("\nV1 Compatible Commands:")
|
|
927
946
|
print(" python memory_store_v2.py add <content> [--project <path>] [--tags tag1,tag2]")
|
|
928
|
-
print(" python memory_store_v2.py search <query>")
|
|
929
|
-
print(" python memory_store_v2.py list [limit]")
|
|
947
|
+
print(" python memory_store_v2.py search <query> [--full]")
|
|
948
|
+
print(" python memory_store_v2.py list [limit] [--full]")
|
|
930
949
|
print(" python memory_store_v2.py get <id>")
|
|
931
|
-
print(" python memory_store_v2.py recent [limit]")
|
|
950
|
+
print(" python memory_store_v2.py recent [limit] [--full]")
|
|
932
951
|
print(" python memory_store_v2.py stats")
|
|
933
952
|
print(" python memory_store_v2.py context <query>")
|
|
934
953
|
print(" python memory_store_v2.py delete <id>")
|
|
935
954
|
print("\nV2 Extensions:")
|
|
936
955
|
print(" python memory_store_v2.py tree [parent_id]")
|
|
937
|
-
print(" python memory_store_v2.py cluster <cluster_id>")
|
|
956
|
+
print(" python memory_store_v2.py cluster <cluster_id> [--full]")
|
|
957
|
+
print("\nOptions:")
|
|
958
|
+
print(" --full Show complete content (default: smart truncation at 5000 chars)")
|
|
938
959
|
sys.exit(0)
|
|
939
960
|
|
|
940
961
|
command = sys.argv[1]
|
|
@@ -954,6 +975,7 @@ if __name__ == "__main__":
|
|
|
954
975
|
|
|
955
976
|
elif command == "cluster" and len(sys.argv) >= 3:
|
|
956
977
|
cluster_id = int(sys.argv[2])
|
|
978
|
+
show_full = '--full' in sys.argv
|
|
957
979
|
results = store.get_by_cluster(cluster_id)
|
|
958
980
|
|
|
959
981
|
if not results:
|
|
@@ -962,7 +984,7 @@ if __name__ == "__main__":
|
|
|
962
984
|
print(f"Cluster {cluster_id} - {len(results)} memories:")
|
|
963
985
|
for r in results:
|
|
964
986
|
print(f"\n[{r['id']}] Importance: {r['importance']}")
|
|
965
|
-
print(f" {r['content']
|
|
987
|
+
print(f" {format_content(r['content'], full=show_full)}")
|
|
966
988
|
|
|
967
989
|
elif command == "stats":
|
|
968
990
|
stats = store.get_stats()
|
|
@@ -996,10 +1018,11 @@ if __name__ == "__main__":
|
|
|
996
1018
|
elif command == "search":
|
|
997
1019
|
if len(sys.argv) < 3:
|
|
998
1020
|
print("Error: Search query required")
|
|
999
|
-
print("Usage: python memory_store_v2.py search <query>")
|
|
1021
|
+
print("Usage: python memory_store_v2.py search <query> [--full]")
|
|
1000
1022
|
sys.exit(1)
|
|
1001
1023
|
|
|
1002
1024
|
query = sys.argv[2]
|
|
1025
|
+
show_full = '--full' in sys.argv
|
|
1003
1026
|
results = store.search(query, limit=5)
|
|
1004
1027
|
|
|
1005
1028
|
if not results:
|
|
@@ -1011,11 +1034,18 @@ if __name__ == "__main__":
|
|
|
1011
1034
|
print(f"Project: {r['project_name']}")
|
|
1012
1035
|
if r.get('tags'):
|
|
1013
1036
|
print(f"Tags: {', '.join(r['tags'])}")
|
|
1014
|
-
print(f"Content: {r['content']
|
|
1037
|
+
print(f"Content: {format_content(r['content'], full=show_full)}")
|
|
1015
1038
|
print(f"Created: {r['created_at']}")
|
|
1016
1039
|
|
|
1017
1040
|
elif command == "recent":
|
|
1018
|
-
|
|
1041
|
+
show_full = '--full' in sys.argv
|
|
1042
|
+
# Parse limit (skip --full flag)
|
|
1043
|
+
limit = 10
|
|
1044
|
+
for i, arg in enumerate(sys.argv[2:], start=2):
|
|
1045
|
+
if arg != '--full' and arg.isdigit():
|
|
1046
|
+
limit = int(arg)
|
|
1047
|
+
break
|
|
1048
|
+
|
|
1019
1049
|
results = store.get_recent(limit)
|
|
1020
1050
|
|
|
1021
1051
|
if not results:
|
|
@@ -1027,17 +1057,24 @@ if __name__ == "__main__":
|
|
|
1027
1057
|
print(f"Project: {r['project_name']}")
|
|
1028
1058
|
if r.get('tags'):
|
|
1029
1059
|
print(f"Tags: {', '.join(r['tags'])}")
|
|
1030
|
-
print(f"Content: {r['content']
|
|
1060
|
+
print(f"Content: {format_content(r['content'], full=show_full)}")
|
|
1031
1061
|
|
|
1032
1062
|
elif command == "list":
|
|
1033
|
-
|
|
1063
|
+
show_full = '--full' in sys.argv
|
|
1064
|
+
# Parse limit (skip --full flag)
|
|
1065
|
+
limit = 10
|
|
1066
|
+
for i, arg in enumerate(sys.argv[2:], start=2):
|
|
1067
|
+
if arg != '--full' and arg.isdigit():
|
|
1068
|
+
limit = int(arg)
|
|
1069
|
+
break
|
|
1070
|
+
|
|
1034
1071
|
results = store.get_recent(limit)
|
|
1035
1072
|
|
|
1036
1073
|
if not results:
|
|
1037
1074
|
print("No memories found.")
|
|
1038
1075
|
else:
|
|
1039
1076
|
for r in results:
|
|
1040
|
-
print(f"[{r['id']}] {r['content']
|
|
1077
|
+
print(f"[{r['id']}] {format_content(r['content'], full=show_full)}")
|
|
1041
1078
|
|
|
1042
1079
|
elif command == "get":
|
|
1043
1080
|
if len(sys.argv) < 3:
|
|
@@ -1046,7 +1083,7 @@ if __name__ == "__main__":
|
|
|
1046
1083
|
sys.exit(1)
|
|
1047
1084
|
|
|
1048
1085
|
mem_id = int(sys.argv[2])
|
|
1049
|
-
memory = store.
|
|
1086
|
+
memory = store.get_by_id(mem_id)
|
|
1050
1087
|
|
|
1051
1088
|
if not memory:
|
|
1052
1089
|
print(f"Memory {mem_id} not found.")
|