graph-mind-memory 0.3.0__tar.gz → 0.3.1__tar.gz

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 (33) hide show
  1. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/PKG-INFO +10 -2
  2. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/README.md +9 -1
  3. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/conversation_memory.py +38 -1
  4. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/PKG-INFO +10 -2
  5. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/pyproject.toml +1 -1
  6. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/LICENSE +0 -0
  7. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/associative_memory.py +0 -0
  8. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/automatic_capture.py +0 -0
  9. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/automatic_capture_cli.py +0 -0
  10. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/brain_log.py +0 -0
  11. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/clock.py +0 -0
  12. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/coding_memory.py +0 -0
  13. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/development_memory.py +0 -0
  14. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/development_paths.py +0 -0
  15. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/embedding_warmup.py +0 -0
  16. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/entity_timeline.py +0 -0
  17. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/forget.py +0 -0
  18. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_mcp_server.py +0 -0
  19. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/SOURCES.txt +0 -0
  20. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/dependency_links.txt +0 -0
  21. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/entry_points.txt +0 -0
  22. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/requires.txt +0 -0
  23. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/graph_mind_memory.egg-info/top_level.txt +0 -0
  24. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/install.py +0 -0
  25. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/local_brain.py +0 -0
  26. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/local_embedder.py +0 -0
  27. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/semantic_llm_extractor.py +0 -0
  28. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/semantic_memory.py +0 -0
  29. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/semantic_recall.py +0 -0
  30. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/setup.cfg +0 -0
  31. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/temporal_resolver.py +0 -0
  32. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/universal_personal_memory.py +0 -0
  33. {graph_mind_memory-0.3.0 → graph_mind_memory-0.3.1}/vector_cache.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graph-mind-memory
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Local-first memory for AI coding assistants: verbatim, on your own PC, no LLM calls at write time.
5
5
  Author-email: Yohan Ko <goyohan0611@gmail.com>
6
6
  License-Expression: AGPL-3.0-only
@@ -164,7 +164,15 @@ Then restart your AI apps. The server is also listed in the
164
164
  | Claude desktop: chat | what the model saves with `brain_remember` |
165
165
 
166
166
  Before anything is stored, these are masked: API keys, tokens from GitHub, AWS, Google and Slack,
167
- private keys, and passwords inside URLs.
167
+ private keys, passwords inside URLs, values written after `password:` / `api_key=` / `token:`,
168
+ and any long machine-random string even from a service no rule knows (by its randomness: 91% of
169
+ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92 times, nearly
170
+ all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
171
+ purpose.
172
+
173
+ There is no switch to keep keys: a recalled memory goes to your model's provider with the question,
174
+ so a stored key would leave your PC the first time it is useful. To have Graph-MIND remember a key,
175
+ tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under Dev"*.
168
176
 
169
177
  Only what you actually send is captured: the service reads each app's transcript, which is written
170
178
  after you press Enter, so a paste you delete before sending never reaches it. A plain password
@@ -138,7 +138,15 @@ Then restart your AI apps. The server is also listed in the
138
138
  | Claude desktop: chat | what the model saves with `brain_remember` |
139
139
 
140
140
  Before anything is stored, these are masked: API keys, tokens from GitHub, AWS, Google and Slack,
141
- private keys, and passwords inside URLs.
141
+ private keys, passwords inside URLs, values written after `password:` / `api_key=` / `token:`,
142
+ and any long machine-random string even from a service no rule knows (by its randomness: 91% of
143
+ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92 times, nearly
144
+ all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
145
+ purpose.
146
+
147
+ There is no switch to keep keys: a recalled memory goes to your model's provider with the question,
148
+ so a stored key would leave your PC the first time it is useful. To have Graph-MIND remember a key,
149
+ tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under Dev"*.
142
150
 
143
151
  Only what you actually send is captured: the service reads each app's transcript, which is written
144
152
  after you press Enter, so a paste you delete before sending never reaches it. A plain password
@@ -5,8 +5,10 @@ from development_paths import use_wal
5
5
 
6
6
  from datetime import datetime
7
7
  from pathlib import Path
8
+ import collections
8
9
  import hashlib
9
10
  import json
11
+ import math
10
12
  import os
11
13
  import re
12
14
  import sqlite3
@@ -30,7 +32,34 @@ SECRET_PATTERNS = (
30
32
  re.DOTALL), "[REDACTED_PRIVATE_KEY]"),
31
33
  # a database URL carries its password: postgres://user:PASSWORD@host
32
34
  (re.compile(r"(\b[a-z][a-z0-9+.-]*://[^\s:/@]+:)[^\s@/]+(@)"), r"\1[REDACTED]\2"),
35
+ # a password written after its name: "password: x", "pwd=x", "비밀번호: x", "비번=x"
36
+ (re.compile(r"(?i)((?<![a-z])(?:password|passwd|pwd)\s*[:=]\s*)\S+"), r"\1[REDACTED]"),
37
+ (re.compile(r"((?:비밀번호|비번|암호)\s*[:=]\s*)\S+"), r"\1[REDACTED]"),
33
38
  )
39
+ # A token no pattern above knows: long, machine-random (mixed case and digits, no word-shaped
40
+ # pieces, high character entropy). Measured: catches 91% of random 20-64 character tokens; in
41
+ # LongMemEval's 246,750 chat turns it fires 92 times, nearly all on real ids and tokens (an
42
+ # OAuth token, Drive file ids, ad click ids); in this repository's code and docs, never.
43
+ # Commit ids, hashes and UUIDs are left alone: those get recalled on purpose.
44
+ RANDOM_CANDIDATE = re.compile(r"(?<![A-Za-z0-9_\-])[A-Za-z0-9_\-]{20,}(?![A-Za-z0-9_\-])")
45
+ UUID = re.compile(r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}")
46
+ WORD_PIECE = re.compile(r"[A-Z]?[a-z]+|[A-Z]+(?![a-z])")
47
+
48
+
49
+ def _looks_random(token):
50
+ if UUID.fullmatch(token):
51
+ return False
52
+ core = re.sub(r"[_\-]", "", token)
53
+ if len(core) < 18 or re.fullmatch(r"[0-9a-fA-F]+", core):
54
+ return False
55
+ if not (any(c.isupper() for c in core) and any(c.islower() for c in core)
56
+ and sum(c.isdigit() for c in core) >= 2):
57
+ return False
58
+ pieces = WORD_PIECE.findall(core) # code names are words strung together
59
+ if pieces and sum(map(len, pieces)) / len(pieces) >= 3.0:
60
+ return False
61
+ counts = collections.Counter(core)
62
+ return -sum(n / len(core) * math.log2(n / len(core)) for n in counts.values()) >= 3.7
34
63
  AUTOMATIC_BLOCKS = re.compile(
35
64
  r"<(?:environment_context|recommended_plugins|in-app-browser-context)\b[^>]*>.*?"
36
65
  r"</(?:environment_context|recommended_plugins|in-app-browser-context)>",
@@ -56,7 +85,15 @@ def _redact(value):
56
85
  for pattern, replacement in SECRET_PATTERNS:
57
86
  cleaned, replacements = pattern.subn(replacement, cleaned)
58
87
  count += replacements
59
- return cleaned.strip(), count
88
+ found = [0]
89
+
90
+ def unknown_token(match):
91
+ if not _looks_random(match.group(0)):
92
+ return match.group(0)
93
+ found[0] += 1
94
+ return "[REDACTED_SECRET]"
95
+ cleaned = RANDOM_CANDIDATE.sub(unknown_token, cleaned)
96
+ return cleaned.strip(), count + found[0]
60
97
 
61
98
 
62
99
  def _message_text(payload):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graph-mind-memory
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Local-first memory for AI coding assistants: verbatim, on your own PC, no LLM calls at write time.
5
5
  Author-email: Yohan Ko <goyohan0611@gmail.com>
6
6
  License-Expression: AGPL-3.0-only
@@ -164,7 +164,15 @@ Then restart your AI apps. The server is also listed in the
164
164
  | Claude desktop: chat | what the model saves with `brain_remember` |
165
165
 
166
166
  Before anything is stored, these are masked: API keys, tokens from GitHub, AWS, Google and Slack,
167
- private keys, and passwords inside URLs.
167
+ private keys, passwords inside URLs, values written after `password:` / `api_key=` / `token:`,
168
+ and any long machine-random string even from a service no rule knows (by its randomness: 91% of
169
+ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92 times, nearly
170
+ all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
171
+ purpose.
172
+
173
+ There is no switch to keep keys: a recalled memory goes to your model's provider with the question,
174
+ so a stored key would leave your PC the first time it is useful. To have Graph-MIND remember a key,
175
+ tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under Dev"*.
168
176
 
169
177
  Only what you actually send is captured: the service reads each app's transcript, which is written
170
178
  after you press Enter, so a paste you delete before sending never reaches it. A plain password
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "graph-mind-memory"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Local-first memory for AI coding assistants: verbatim, on your own PC, no LLM calls at write time."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"