yourmemory 1.4.2__tar.gz → 1.4.4__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 (42) hide show
  1. {yourmemory-1.4.2 → yourmemory-1.4.4}/PKG-INFO +3 -3
  2. {yourmemory-1.4.2 → yourmemory-1.4.4}/memory_mcp.py +131 -11
  3. {yourmemory-1.4.2 → yourmemory-1.4.4}/pyproject.toml +4 -2
  4. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/PKG-INFO +3 -3
  5. {yourmemory-1.4.2 → yourmemory-1.4.4}/LICENSE +0 -0
  6. {yourmemory-1.4.2 → yourmemory-1.4.4}/README.md +0 -0
  7. {yourmemory-1.4.2 → yourmemory-1.4.4}/setup.cfg +0 -0
  8. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/__init__.py +0 -0
  9. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/app.py +0 -0
  10. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/db/connection.py +0 -0
  11. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/db/duckdb_schema.sql +0 -0
  12. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/db/migrate.py +0 -0
  13. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/db/schema.sql +0 -0
  14. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/db/sqlite_schema.sql +0 -0
  15. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/__init__.py +0 -0
  16. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/backend.py +0 -0
  17. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/graph_store.py +0 -0
  18. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/neo4j_backend.py +0 -0
  19. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/networkx_backend.py +0 -0
  20. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/graph/svo_extract.py +0 -0
  21. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/jobs/decay_job.py +0 -0
  22. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/routes/__init__.py +0 -0
  23. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/routes/agents.py +0 -0
  24. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/routes/memories.py +0 -0
  25. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/routes/retrieve.py +0 -0
  26. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/routes/ui.py +0 -0
  27. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/__init__.py +0 -0
  28. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/agent_registry.py +0 -0
  29. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/api_keys.py +0 -0
  30. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/decay.py +0 -0
  31. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/embed.py +0 -0
  32. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/extract.py +0 -0
  33. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/extract_fallback.py +0 -0
  34. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/resolve.py +0 -0
  35. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/resolve_fallback.py +0 -0
  36. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/retrieve.py +0 -0
  37. {yourmemory-1.4.2 → yourmemory-1.4.4}/src/services/utils.py +0 -0
  38. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/SOURCES.txt +0 -0
  39. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/dependency_links.txt +0 -0
  40. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/entry_points.txt +0 -0
  41. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/requires.txt +2 -2
  42. {yourmemory-1.4.2 → yourmemory-1.4.4}/yourmemory.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yourmemory
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: Persistent memory for Claude — Ebbinghaus forgetting curve, semantic deduplication, MCP-native
5
5
  Author-email: Sachit Misra <mishrasachit1@gmail.com>
6
6
  License-Expression: CC-BY-NC-4.0
@@ -24,12 +24,12 @@ Requires-Dist: duckdb>=0.10.0
24
24
  Requires-Dist: apscheduler
25
25
  Requires-Dist: spacy<4.0,>=3.8.13
26
26
  Requires-Dist: networkx>=3.0
27
+ Requires-Dist: fastapi
28
+ Requires-Dist: uvicorn[standard]
27
29
  Provides-Extra: postgres
28
30
  Requires-Dist: psycopg2-binary; extra == "postgres"
29
31
  Requires-Dist: pgvector; extra == "postgres"
30
32
  Provides-Extra: sse
31
- Requires-Dist: fastapi; extra == "sse"
32
- Requires-Dist: uvicorn[standard]; extra == "sse"
33
33
  Requires-Dist: httpx; extra == "sse"
34
34
  Provides-Extra: neo4j
35
35
  Requires-Dist: neo4j>=5.0; extra == "neo4j"
@@ -555,6 +555,32 @@ async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
555
555
  return [types.TextContent(type="text", text=json.dumps({"error": f"Unknown tool: {name}"}))]
556
556
 
557
557
 
558
+ def _start_dashboard(port: int) -> None:
559
+ """Start the memory dashboard HTTP server in a background daemon thread.
560
+
561
+ Binds to 127.0.0.1 only — local access, not exposed to the network.
562
+ Prints the URL to stderr so it doesn't pollute the MCP stdio stream.
563
+ """
564
+ try:
565
+ import uvicorn
566
+ from src.app import app as dashboard_app
567
+
568
+ config = uvicorn.Config(
569
+ dashboard_app,
570
+ host="127.0.0.1",
571
+ port=port,
572
+ log_level="error",
573
+ access_log=False,
574
+ )
575
+ server = uvicorn.Server(config)
576
+
577
+ t = threading.Thread(target=server.run, daemon=True, name="dashboard")
578
+ t.start()
579
+ print(f" Dashboard → http://127.0.0.1:{port}/ui", file=sys.stderr)
580
+ except Exception as exc:
581
+ print(f" Dashboard unavailable: {exc}", file=sys.stderr)
582
+
583
+
558
584
  def _start_decay_scheduler():
559
585
  """Run the decay job once immediately, then every 24 hours in a background thread."""
560
586
  from src.jobs.decay_job import run as run_decay
@@ -828,29 +854,68 @@ def setup():
828
854
 
829
855
  # ── 4. Inject memory rules into global agent instructions ───────────────
830
856
  print("\n[4/4] Injecting memory rules into global agent instructions…")
831
- _inject_memory_rules(home)
857
+
858
+ # Resolve user_id: env var → saved file → prompt
859
+ uid_path = os.path.join(home, ".yourmemory", "user_id")
860
+ user_id = os.getenv("YOURMEMORY_USER", "").strip()
861
+ if not user_id and os.path.exists(uid_path):
862
+ with open(uid_path) as f:
863
+ user_id = f.read().strip()
864
+ if not user_id:
865
+ try:
866
+ user_id = input(" Your name (used as memory user_id, e.g. 'alice'): ").strip()
867
+ except (EOFError, OSError):
868
+ user_id = ""
869
+ if not user_id:
870
+ user_id = "user"
871
+ os.makedirs(os.path.dirname(uid_path), exist_ok=True)
872
+ with open(uid_path, "w") as f:
873
+ f.write(user_id)
874
+ print(f" user_id → {user_id}")
875
+
876
+ _inject_memory_rules(home, user_id)
832
877
 
833
878
  print("\n✓ Setup complete. Restart your AI client to load YourMemory.\n")
834
879
 
835
880
 
836
- def _inject_memory_rules(home: str) -> None:
837
- """Append _MEMORY_RULES to every detected global agent instruction file.
838
- Skips silently if the rules block is already present.
881
+ def _inject_memory_rules(home: str, user_id: str = "user") -> None:
882
+ """Append memory rules to every detected global agent instruction file.
883
+ Replaces <your_name> with the actual user_id. Skips if already present.
839
884
  """
885
+ rules = _MEMORY_RULES.replace("<your_name>", user_id)
886
+
840
887
  candidates = [
841
- # Claude Code global instructions
888
+ # Claude Code all platforms
842
889
  os.path.join(home, ".claude", "CLAUDE.md"),
843
- # Cursor global rules
890
+ # Cursor all platforms
844
891
  os.path.join(home, ".cursor", "rules", "memory.mdc"),
845
- # Windsurf global rules
892
+ # Windsurf all platforms
846
893
  os.path.join(home, ".codeium", "windsurf", "memories", "memory_rules.md"),
894
+ # OpenCode — all platforms
895
+ os.path.join(home, ".config", "opencode", "instructions.md"),
847
896
  ]
848
897
 
898
+ # Cline (VS Code) — platform-specific globalStorage path
899
+ if sys.platform == "darwin":
900
+ vscode_global = os.path.join(home, "Library", "Application Support",
901
+ "Code", "User", "globalStorage")
902
+ elif sys.platform == "win32":
903
+ vscode_global = os.path.join(os.getenv("APPDATA", ""), "Code",
904
+ "User", "globalStorage")
905
+ else:
906
+ vscode_global = os.path.join(home, ".config", "Code", "User", "globalStorage")
907
+
908
+ if os.path.isdir(vscode_global):
909
+ for entry in os.listdir(vscode_global):
910
+ if "claude-dev" in entry or "cline" in entry.lower():
911
+ candidates.append(os.path.join(vscode_global, entry, "settings", "instructions.md"))
912
+ break
913
+
849
914
  wrote_any = False
850
915
  for path in candidates:
851
916
  dir_ = os.path.dirname(path)
852
917
  if not os.path.isdir(dir_):
853
- continue # client not installed — skip
918
+ continue
854
919
  try:
855
920
  existing = ""
856
921
  if os.path.exists(path):
@@ -860,22 +925,75 @@ def _inject_memory_rules(home: str) -> None:
860
925
  print(f" ✓ Already present → {path}")
861
926
  wrote_any = True
862
927
  continue
928
+ os.makedirs(dir_, exist_ok=True)
863
929
  with open(path, "a") as f:
864
930
  if existing and not existing.endswith("\n"):
865
931
  f.write("\n")
866
- f.write("\n" + _MEMORY_RULES)
867
- print(f" ✓ Memory rules appended → {path}")
932
+ f.write("\n" + rules)
933
+ print(f" ✓ Memory rules injected → {path}")
868
934
  wrote_any = True
869
935
  except Exception as exc:
870
936
  print(f" ✗ Could not write to {path}: {exc}")
871
937
 
872
938
  if not wrote_any:
873
- print(" (No global instruction files detected — add MEMORY_RULES.md to your project's CLAUDE.md manually.)")
939
+ print(" (No global instruction files detected — copy sample_CLAUDE.md to your project's CLAUDE.md manually.)")
940
+
941
+
942
+ def _first_run_setup() -> None:
943
+ """Silently run first-time setup when the MCP server starts for the first time.
944
+
945
+ Triggered when ~/.yourmemory/user_id does not exist.
946
+ All output goes to stderr — stdout is reserved for the MCP stdio stream.
947
+ spaCy download runs in a background thread so it doesn't delay server startup.
948
+ """
949
+ home = os.path.expanduser("~")
950
+ uid_path = os.path.join(home, ".yourmemory", "user_id")
951
+
952
+ if os.path.exists(uid_path):
953
+ return # already set up
954
+
955
+ print(" [YourMemory] First run detected — running setup…", file=sys.stderr)
956
+
957
+ # Resolve user_id: env var → system login → fallback
958
+ user_id = os.getenv("YOURMEMORY_USER", "").strip()
959
+ if not user_id:
960
+ try:
961
+ import getpass
962
+ user_id = getpass.getuser()
963
+ except Exception:
964
+ user_id = "user"
965
+
966
+ os.makedirs(os.path.join(home, ".yourmemory"), exist_ok=True)
967
+ with open(uid_path, "w") as f:
968
+ f.write(user_id)
969
+ print(f" [YourMemory] user_id → {user_id}", file=sys.stderr)
970
+
971
+ # Inject memory rules into detected client instruction files
972
+ _inject_memory_rules(home, user_id)
973
+
974
+ # Fire install ping
975
+ _ping_install()
976
+
977
+ # Download spaCy model in background — don't block server startup
978
+ def _download_spacy():
979
+ try:
980
+ import subprocess
981
+ subprocess.run(
982
+ [sys.executable, "-m", "spacy", "download", "en_core_web_sm"],
983
+ check=False, capture_output=True,
984
+ )
985
+ except Exception:
986
+ pass
987
+
988
+ threading.Thread(target=_download_spacy, daemon=True, name="spacy-dl").start()
989
+
990
+ print(" [YourMemory] Setup complete. Memory rules injected into your AI client.", file=sys.stderr)
874
991
 
875
992
 
876
993
  def run():
877
994
  from src.db.migrate import migrate
878
995
  migrate()
996
+ _first_run_setup()
879
997
  _start_decay_scheduler()
880
998
 
881
999
  # SSE mode: --sse flag, PORT env var, or Windows default (stdio pipes unreliable on Windows)
@@ -892,6 +1010,8 @@ def run():
892
1010
  # Default to SSE on Windows — stdio pipes break intermittently on Windows
893
1011
  _run_sse(int(os.getenv("PORT", 3033)))
894
1012
  else:
1013
+ dashboard_port = int(os.getenv("YOURMEMORY_DASHBOARD_PORT", 3033))
1014
+ _start_dashboard(dashboard_port)
895
1015
  asyncio.run(main())
896
1016
 
897
1017
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "yourmemory"
7
- version = "1.4.2"
7
+ version = "1.4.4"
8
8
  description = "Persistent memory for Claude — Ebbinghaus forgetting curve, semantic deduplication, MCP-native"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -30,11 +30,13 @@ dependencies = [
30
30
  "apscheduler",
31
31
  "spacy>=3.8.13,<4.0",
32
32
  "networkx>=3.0",
33
+ "fastapi",
34
+ "uvicorn[standard]",
33
35
  ]
34
36
 
35
37
  [project.optional-dependencies]
36
38
  postgres = ["psycopg2-binary", "pgvector"]
37
- sse = ["fastapi", "uvicorn[standard]", "httpx"]
39
+ sse = ["httpx"]
38
40
  neo4j = ["neo4j>=5.0"]
39
41
  all = ["yourmemory[postgres,sse,neo4j]"]
40
42
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yourmemory
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: Persistent memory for Claude — Ebbinghaus forgetting curve, semantic deduplication, MCP-native
5
5
  Author-email: Sachit Misra <mishrasachit1@gmail.com>
6
6
  License-Expression: CC-BY-NC-4.0
@@ -24,12 +24,12 @@ Requires-Dist: duckdb>=0.10.0
24
24
  Requires-Dist: apscheduler
25
25
  Requires-Dist: spacy<4.0,>=3.8.13
26
26
  Requires-Dist: networkx>=3.0
27
+ Requires-Dist: fastapi
28
+ Requires-Dist: uvicorn[standard]
27
29
  Provides-Extra: postgres
28
30
  Requires-Dist: psycopg2-binary; extra == "postgres"
29
31
  Requires-Dist: pgvector; extra == "postgres"
30
32
  Provides-Extra: sse
31
- Requires-Dist: fastapi; extra == "sse"
32
- Requires-Dist: uvicorn[standard]; extra == "sse"
33
33
  Requires-Dist: httpx; extra == "sse"
34
34
  Provides-Extra: neo4j
35
35
  Requires-Dist: neo4j>=5.0; extra == "neo4j"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -7,6 +7,8 @@ duckdb>=0.10.0
7
7
  apscheduler
8
8
  spacy<4.0,>=3.8.13
9
9
  networkx>=3.0
10
+ fastapi
11
+ uvicorn[standard]
10
12
 
11
13
  [all]
12
14
  yourmemory[neo4j,postgres,sse]
@@ -19,6 +21,4 @@ psycopg2-binary
19
21
  pgvector
20
22
 
21
23
  [sse]
22
- fastapi
23
- uvicorn[standard]
24
24
  httpx