graph-mind-memory 0.5.0__tar.gz → 0.5.2__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.
- {graph_mind_memory-0.5.0/graph_mind_memory.egg-info → graph_mind_memory-0.5.2}/PKG-INFO +10 -4
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/README.md +8 -3
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/automatic_capture.py +30 -1
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/conversation_memory.py +9 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_mcp_server.py +20 -1
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2/graph_mind_memory.egg-info}/PKG-INFO +10 -4
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/pyproject.toml +2 -1
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/LICENSE +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/associative_memory.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/automatic_capture_cli.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/brain_log.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/clock.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/coding_memory.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/development_memory.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/development_paths.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/embedding_warmup.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/entity_timeline.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/forget.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/SOURCES.txt +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/dependency_links.txt +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/entry_points.txt +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/requires.txt +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/top_level.txt +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/install.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/local_brain.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/local_embedder.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/semantic_llm_extractor.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/semantic_memory.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/semantic_recall.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/setup.cfg +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/temporal_resolver.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/universal_personal_memory.py +0 -0
- {graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/vector_cache.py +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graph-mind-memory
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
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
|
|
7
7
|
Project-URL: Homepage, https://github.com/goyohan0611-png/graph-mind
|
|
8
8
|
Project-URL: Issues, https://github.com/goyohan0611-png/graph-mind/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/goyohan0611-png/graph-mind/blob/main/CHANGELOG.md
|
|
9
10
|
Keywords: mcp,memory,claude,codex,llm,longmemeval,local-first
|
|
10
11
|
Classifier: Development Status :: 3 - Alpha
|
|
11
12
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -120,6 +121,8 @@ Requires Python 3.10+ (64-bit). Windows, macOS or Linux. Hosting a brain that ot
|
|
|
120
121
|
needs Python 3.12 or older on that one PC (its Postgres helper, pgserver, has no newer build yet);
|
|
121
122
|
everything else, joining included, works on 3.13 and 3.14 too.
|
|
122
123
|
|
|
124
|
+
What changed in each release: [CHANGELOG.md](CHANGELOG.md).
|
|
125
|
+
|
|
123
126
|
```bash
|
|
124
127
|
pip install graph-mind-memory
|
|
125
128
|
graph-mind-install
|
|
@@ -180,9 +183,12 @@ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92
|
|
|
180
183
|
all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
|
|
181
184
|
purpose.
|
|
182
185
|
|
|
183
|
-
|
|
184
|
-
so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
185
|
-
tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
186
|
+
Keep masking on if you use a cloud model: a recalled memory goes to your model's provider with the
|
|
187
|
+
question, so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
188
|
+
remember a key, tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
189
|
+
Dev"*. If your model runs on your own machines and you want keys remembered as typed, add
|
|
190
|
+
`"mask_secrets": false` to `~/.graph-mind/config.json` (applies from the next message; already
|
|
191
|
+
masked text stays masked).
|
|
186
192
|
|
|
187
193
|
Only what you actually send is captured: the service reads each app's transcript, which is written
|
|
188
194
|
after you press Enter, so a paste you delete before sending never reaches it. A plain password
|
|
@@ -93,6 +93,8 @@ Requires Python 3.10+ (64-bit). Windows, macOS or Linux. Hosting a brain that ot
|
|
|
93
93
|
needs Python 3.12 or older on that one PC (its Postgres helper, pgserver, has no newer build yet);
|
|
94
94
|
everything else, joining included, works on 3.13 and 3.14 too.
|
|
95
95
|
|
|
96
|
+
What changed in each release: [CHANGELOG.md](CHANGELOG.md).
|
|
97
|
+
|
|
96
98
|
```bash
|
|
97
99
|
pip install graph-mind-memory
|
|
98
100
|
graph-mind-install
|
|
@@ -153,9 +155,12 @@ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92
|
|
|
153
155
|
all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
|
|
154
156
|
purpose.
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
158
|
-
tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
158
|
+
Keep masking on if you use a cloud model: a recalled memory goes to your model's provider with the
|
|
159
|
+
question, so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
160
|
+
remember a key, tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
161
|
+
Dev"*. If your model runs on your own machines and you want keys remembered as typed, add
|
|
162
|
+
`"mask_secrets": false` to `~/.graph-mind/config.json` (applies from the next message; already
|
|
163
|
+
masked text stays masked).
|
|
159
164
|
|
|
160
165
|
Only what you actually send is captured: the service reads each app's transcript, which is written
|
|
161
166
|
after you press Enter, so a paste you delete before sending never reaches it. A plain password
|
|
@@ -234,10 +234,39 @@ class AutomaticCaptureService:
|
|
|
234
234
|
"conversation_sources": conversation, "semantic": semantic,
|
|
235
235
|
"semantic_llm": semantic_llm,
|
|
236
236
|
"associative": associative,
|
|
237
|
-
"errors": errors
|
|
237
|
+
"errors": errors,
|
|
238
|
+
"warnings": self._stall_warnings(conversation)}
|
|
238
239
|
self._write_status(result)
|
|
239
240
|
return result
|
|
240
241
|
|
|
242
|
+
STALL_ROWS = 2000
|
|
243
|
+
|
|
244
|
+
def _stall_warnings(self, conversation):
|
|
245
|
+
"""A source whose transcripts keep growing while no conversation comes out of them: the
|
|
246
|
+
app most likely changed its transcript format, and capture would otherwise stop without
|
|
247
|
+
a word. Counted across passes in capture-health.json; reset by the next turn found."""
|
|
248
|
+
path = self.state_dir / "capture-health.json"
|
|
249
|
+
try:
|
|
250
|
+
health = json.loads(path.read_text(encoding="utf-8"))
|
|
251
|
+
except (OSError, ValueError):
|
|
252
|
+
health = {}
|
|
253
|
+
warnings = []
|
|
254
|
+
for name, outcome in conversation.items():
|
|
255
|
+
if not isinstance(outcome, dict) or "scanned_rows" not in outcome:
|
|
256
|
+
continue
|
|
257
|
+
entry = health.setdefault(name, {"rows_without_turns": 0, "last_turn_at": None})
|
|
258
|
+
if outcome.get("recorded_turns"):
|
|
259
|
+
entry.update(rows_without_turns=0, last_turn_at=self.now())
|
|
260
|
+
else:
|
|
261
|
+
entry["rows_without_turns"] += outcome["scanned_rows"]
|
|
262
|
+
if entry["rows_without_turns"] >= self.STALL_ROWS:
|
|
263
|
+
warnings.append(
|
|
264
|
+
f"{name}: {entry['rows_without_turns']} new transcript lines and no "
|
|
265
|
+
f"conversation found in them since {entry['last_turn_at'] or 'capture began'}"
|
|
266
|
+
" - the app may have changed its format; update Graph-MIND or report it")
|
|
267
|
+
_atomic_json(path, health)
|
|
268
|
+
return warnings
|
|
269
|
+
|
|
241
270
|
def _write_status(self, result):
|
|
242
271
|
_atomic_json(self.status_path, {**result, "pid": os.getpid(),
|
|
243
272
|
"config_db": str(self.db_path)})
|
|
@@ -79,8 +79,17 @@ AGENT_INSTRUCTIONS = re.compile(
|
|
|
79
79
|
r"(?:#\s*AGENTS\.md instructions[^\n]*\s*)?<INSTRUCTIONS>.*?</INSTRUCTIONS>", flags=re.DOTALL)
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def masking_on():
|
|
83
|
+
"""On unless ~/.graph-mind/config.json says "mask_secrets": false: someone running a model on
|
|
84
|
+
their own machines may want keys kept in memory verbatim."""
|
|
85
|
+
from brain_log import _config
|
|
86
|
+
return _config().get("mask_secrets", True) is not False
|
|
87
|
+
|
|
88
|
+
|
|
82
89
|
def _redact(value):
|
|
83
90
|
cleaned = AGENT_INSTRUCTIONS.sub("", AUTOMATIC_BLOCKS.sub("", value))
|
|
91
|
+
if not masking_on():
|
|
92
|
+
return cleaned.strip(), 0
|
|
84
93
|
count = 0
|
|
85
94
|
for pattern, replacement in SECRET_PATTERNS:
|
|
86
95
|
cleaned, replacements = pattern.subn(replacement, cleaned)
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
from datetime import datetime, timedelta
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any, Literal
|
|
7
|
+
import json
|
|
7
8
|
import os
|
|
8
9
|
import sys
|
|
9
10
|
import threading
|
|
@@ -346,6 +347,17 @@ def gather(database, query, *, scopes=None, as_of, knowledge_cutoff=None, limit=
|
|
|
346
347
|
return result
|
|
347
348
|
|
|
348
349
|
|
|
350
|
+
def capture_warnings() -> list[str]:
|
|
351
|
+
"""What the capture service last reported as wrong (a source that stopped yielding turns)."""
|
|
352
|
+
try:
|
|
353
|
+
from automatic_capture import default_service_state_dir
|
|
354
|
+
status = json.loads((default_service_state_dir() / "status.json")
|
|
355
|
+
.read_text(encoding="utf-8"))
|
|
356
|
+
return list(status.get("warnings") or [])
|
|
357
|
+
except Exception:
|
|
358
|
+
return []
|
|
359
|
+
|
|
360
|
+
|
|
349
361
|
def build_server(db_path=None):
|
|
350
362
|
database = Path(db_path).expanduser() if db_path is not None else configured_db_path()
|
|
351
363
|
server = MCPServer(
|
|
@@ -368,7 +380,8 @@ def build_server(db_path=None):
|
|
|
368
380
|
"project, file or symbol, use code_activity. brain_folder shows or changes where the "
|
|
369
381
|
"memory lives and shares it with the user's other PCs. When the user asks to "
|
|
370
382
|
"delete something from memory, use brain_forget: list first, delete only what the "
|
|
371
|
-
"user picks.
|
|
383
|
+
"user picks. If a result carries capture_warnings, tell the user once, plainly: "
|
|
384
|
+
"conversations from that app are no longer being saved. Preserve provenance."
|
|
372
385
|
),
|
|
373
386
|
version=SERVER_VERSION,
|
|
374
387
|
)
|
|
@@ -557,6 +570,9 @@ def build_server(db_path=None):
|
|
|
557
570
|
packet = build_context_pack(recalled, max_chars=max_chars,
|
|
558
571
|
order="time" if recent else "relevance")
|
|
559
572
|
packet["route"] = route
|
|
573
|
+
warnings = capture_warnings()
|
|
574
|
+
if warnings:
|
|
575
|
+
packet["capture_warnings"] = warnings
|
|
560
576
|
if route["mode"] == "EXECUTE":
|
|
561
577
|
packet.setdefault("warnings", []).append(
|
|
562
578
|
"STRUCTURED_EXECUTION_REQUIRED_FOR_COMPLETE_SCOPE_CLAIMS")
|
|
@@ -626,6 +642,9 @@ def build_server(db_path=None):
|
|
|
626
642
|
result = {} if shared_out is None else {
|
|
627
643
|
"connection_code": shared_out["connection_code"],
|
|
628
644
|
"reachable_at": shared_out["addresses"], "firewall": shared_out["firewall"]}
|
|
645
|
+
warnings = capture_warnings()
|
|
646
|
+
if warnings:
|
|
647
|
+
result["capture_warnings"] = warnings
|
|
629
648
|
return {**result, "folder": where, "this_device": device_name(),
|
|
630
649
|
"devices": devices(shared),
|
|
631
650
|
"imported_from_other_devices": imported["imported"],
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graph-mind-memory
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
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
|
|
7
7
|
Project-URL: Homepage, https://github.com/goyohan0611-png/graph-mind
|
|
8
8
|
Project-URL: Issues, https://github.com/goyohan0611-png/graph-mind/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/goyohan0611-png/graph-mind/blob/main/CHANGELOG.md
|
|
9
10
|
Keywords: mcp,memory,claude,codex,llm,longmemeval,local-first
|
|
10
11
|
Classifier: Development Status :: 3 - Alpha
|
|
11
12
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -120,6 +121,8 @@ Requires Python 3.10+ (64-bit). Windows, macOS or Linux. Hosting a brain that ot
|
|
|
120
121
|
needs Python 3.12 or older on that one PC (its Postgres helper, pgserver, has no newer build yet);
|
|
121
122
|
everything else, joining included, works on 3.13 and 3.14 too.
|
|
122
123
|
|
|
124
|
+
What changed in each release: [CHANGELOG.md](CHANGELOG.md).
|
|
125
|
+
|
|
123
126
|
```bash
|
|
124
127
|
pip install graph-mind-memory
|
|
125
128
|
graph-mind-install
|
|
@@ -180,9 +183,12 @@ random 20-64 character tokens caught; in 246,750 ordinary chat turns it fired 92
|
|
|
180
183
|
all on real ids and tokens). Commit ids, hashes and UUIDs are kept, since you recall those on
|
|
181
184
|
purpose.
|
|
182
185
|
|
|
183
|
-
|
|
184
|
-
so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
185
|
-
tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
186
|
+
Keep masking on if you use a cloud model: a recalled memory goes to your model's provider with the
|
|
187
|
+
question, so a stored key would leave your PC the first time it is useful. To have Graph-MIND
|
|
188
|
+
remember a key, tell it **where the key is**, not the key: *"my OpenAI key is in 1Password, under
|
|
189
|
+
Dev"*. If your model runs on your own machines and you want keys remembered as typed, add
|
|
190
|
+
`"mask_secrets": false` to `~/.graph-mind/config.json` (applies from the next message; already
|
|
191
|
+
masked text stays masked).
|
|
186
192
|
|
|
187
193
|
Only what you actually send is captured: the service reads each app's transcript, which is written
|
|
188
194
|
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.5.
|
|
7
|
+
version = "0.5.2"
|
|
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"
|
|
@@ -35,6 +35,7 @@ dependencies = [
|
|
|
35
35
|
[project.urls]
|
|
36
36
|
Homepage = "https://github.com/goyohan0611-png/graph-mind"
|
|
37
37
|
Issues = "https://github.com/goyohan0611-png/graph-mind/issues"
|
|
38
|
+
Changelog = "https://github.com/goyohan0611-png/graph-mind/blob/main/CHANGELOG.md"
|
|
38
39
|
|
|
39
40
|
[project.scripts]
|
|
40
41
|
graph-mind = "graph_mind_mcp_server:main"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{graph_mind_memory-0.5.0 → graph_mind_memory-0.5.2}/graph_mind_memory.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|