basic-memory 0.6.0__py3-none-any.whl → 0.8.0__py3-none-any.whl

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.

Potentially problematic release.


This version of basic-memory might be problematic. Click here for more details.

Files changed (70) hide show
  1. basic_memory/__init__.py +1 -1
  2. basic_memory/alembic/alembic.ini +119 -0
  3. basic_memory/alembic/env.py +23 -1
  4. basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
  5. basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
  6. basic_memory/api/app.py +0 -4
  7. basic_memory/api/routers/knowledge_router.py +1 -9
  8. basic_memory/api/routers/memory_router.py +41 -25
  9. basic_memory/api/routers/resource_router.py +119 -12
  10. basic_memory/api/routers/search_router.py +17 -9
  11. basic_memory/cli/app.py +0 -2
  12. basic_memory/cli/commands/db.py +11 -8
  13. basic_memory/cli/commands/import_chatgpt.py +31 -27
  14. basic_memory/cli/commands/import_claude_conversations.py +29 -27
  15. basic_memory/cli/commands/import_claude_projects.py +30 -29
  16. basic_memory/cli/commands/import_memory_json.py +28 -26
  17. basic_memory/cli/commands/status.py +16 -26
  18. basic_memory/cli/commands/sync.py +11 -12
  19. basic_memory/cli/commands/tools.py +180 -0
  20. basic_memory/cli/main.py +1 -1
  21. basic_memory/config.py +16 -2
  22. basic_memory/db.py +1 -0
  23. basic_memory/deps.py +5 -1
  24. basic_memory/file_utils.py +6 -4
  25. basic_memory/markdown/entity_parser.py +3 -3
  26. basic_memory/mcp/async_client.py +1 -1
  27. basic_memory/mcp/main.py +25 -0
  28. basic_memory/mcp/prompts/__init__.py +15 -0
  29. basic_memory/mcp/prompts/ai_assistant_guide.py +28 -0
  30. basic_memory/mcp/prompts/continue_conversation.py +172 -0
  31. basic_memory/mcp/prompts/json_canvas_spec.py +25 -0
  32. basic_memory/mcp/prompts/recent_activity.py +46 -0
  33. basic_memory/mcp/prompts/search.py +127 -0
  34. basic_memory/mcp/prompts/utils.py +98 -0
  35. basic_memory/mcp/server.py +3 -7
  36. basic_memory/mcp/tools/__init__.py +6 -4
  37. basic_memory/mcp/tools/canvas.py +99 -0
  38. basic_memory/mcp/tools/knowledge.py +26 -14
  39. basic_memory/mcp/tools/memory.py +57 -31
  40. basic_memory/mcp/tools/notes.py +65 -72
  41. basic_memory/mcp/tools/resource.py +192 -0
  42. basic_memory/mcp/tools/search.py +13 -4
  43. basic_memory/mcp/tools/utils.py +2 -1
  44. basic_memory/models/knowledge.py +27 -11
  45. basic_memory/repository/repository.py +1 -1
  46. basic_memory/repository/search_repository.py +17 -4
  47. basic_memory/schemas/__init__.py +0 -11
  48. basic_memory/schemas/base.py +4 -1
  49. basic_memory/schemas/memory.py +14 -2
  50. basic_memory/schemas/request.py +1 -1
  51. basic_memory/schemas/search.py +4 -1
  52. basic_memory/services/context_service.py +14 -6
  53. basic_memory/services/entity_service.py +19 -12
  54. basic_memory/services/file_service.py +69 -2
  55. basic_memory/services/link_resolver.py +12 -9
  56. basic_memory/services/search_service.py +59 -13
  57. basic_memory/sync/__init__.py +3 -2
  58. basic_memory/sync/sync_service.py +287 -107
  59. basic_memory/sync/watch_service.py +125 -129
  60. basic_memory/utils.py +27 -15
  61. {basic_memory-0.6.0.dist-info → basic_memory-0.8.0.dist-info}/METADATA +3 -2
  62. basic_memory-0.8.0.dist-info/RECORD +91 -0
  63. basic_memory/alembic/README +0 -1
  64. basic_memory/schemas/discovery.py +0 -28
  65. basic_memory/sync/file_change_scanner.py +0 -158
  66. basic_memory/sync/utils.py +0 -31
  67. basic_memory-0.6.0.dist-info/RECORD +0 -81
  68. {basic_memory-0.6.0.dist-info → basic_memory-0.8.0.dist-info}/WHEEL +0 -0
  69. {basic_memory-0.6.0.dist-info → basic_memory-0.8.0.dist-info}/entry_points.txt +0 -0
  70. {basic_memory-0.6.0.dist-info → basic_memory-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,158 +0,0 @@
1
- """Service for detecting changes between filesystem and database."""
2
-
3
- from dataclasses import dataclass, field
4
- from pathlib import Path
5
- from typing import Dict, Sequence
6
-
7
- from loguru import logger
8
-
9
- from basic_memory.file_utils import compute_checksum
10
- from basic_memory.models import Entity
11
- from basic_memory.repository.entity_repository import EntityRepository
12
- from basic_memory.sync.utils import SyncReport
13
-
14
-
15
- @dataclass
16
- class FileState:
17
- """State of a file including file path, permalink and checksum info."""
18
-
19
- file_path: str
20
- permalink: str
21
- checksum: str
22
-
23
-
24
- @dataclass
25
- class ScanResult:
26
- """Result of scanning a directory."""
27
-
28
- # file_path -> checksum
29
- files: Dict[str, str] = field(default_factory=dict)
30
- # file_path -> error message
31
- errors: Dict[str, str] = field(default_factory=dict)
32
-
33
-
34
- class FileChangeScanner:
35
- """
36
- Service for detecting changes between filesystem and database.
37
- The filesystem is treated as the source of truth.
38
- """
39
-
40
- def __init__(self, entity_repository: EntityRepository):
41
- self.entity_repository = entity_repository
42
-
43
- async def scan_directory(self, directory: Path) -> ScanResult:
44
- """
45
- Scan directory for markdown files and their checksums.
46
- Only processes .md files, logs and skips others.
47
-
48
- Args:
49
- directory: Directory to scan
50
-
51
- Returns:
52
- ScanResult containing found files and any errors
53
- """
54
- logger.debug(f"Scanning directory: {directory}")
55
- result = ScanResult()
56
-
57
- if not directory.exists():
58
- logger.debug(f"Directory does not exist: {directory}")
59
- return result
60
-
61
- for path in directory.rglob("*"):
62
- if not path.is_file() or not path.name.endswith(".md"):
63
- if path.is_file():
64
- logger.debug(f"Skipping non-markdown file: {path}")
65
- continue
66
-
67
- try:
68
- # Get relative path first - used in error reporting if needed
69
- rel_path = str(path.relative_to(directory))
70
- content = path.read_text()
71
- checksum = await compute_checksum(content)
72
- result.files[rel_path] = checksum
73
-
74
- except Exception as e:
75
- rel_path = str(path.relative_to(directory))
76
- result.errors[rel_path] = str(e)
77
- logger.error(f"Failed to read {rel_path}: {e}")
78
-
79
- logger.debug(f"Found {len(result.files)} markdown files")
80
- if result.errors:
81
- logger.warning(f"Encountered {len(result.errors)} errors while scanning")
82
-
83
- return result
84
-
85
- async def find_changes(
86
- self, directory: Path, db_file_state: Dict[str, FileState]
87
- ) -> SyncReport:
88
- """Find changes between filesystem and database."""
89
- # Get current files and checksums
90
- scan_result = await self.scan_directory(directory)
91
- current_files = scan_result.files
92
-
93
- # Build report
94
- report = SyncReport(total=len(current_files))
95
-
96
- # Track potentially moved files by checksum
97
- files_by_checksum = {} # checksum -> file_path
98
-
99
- # First find potential new files and record checksums
100
- for file_path, checksum in current_files.items():
101
- logger.debug(f"{file_path} ({checksum[:8]})")
102
-
103
- if file_path not in db_file_state:
104
- # Could be new or could be the destination of a move
105
- report.new.add(file_path)
106
- files_by_checksum[checksum] = file_path
107
- elif checksum != db_file_state[file_path].checksum:
108
- report.modified.add(file_path)
109
-
110
- report.checksums[file_path] = checksum
111
-
112
- # Now detect moves and deletions
113
- for db_file_path, db_state in db_file_state.items():
114
- if db_file_path not in current_files:
115
- if db_state.checksum in files_by_checksum:
116
- # Found a move - file exists at new path with same checksum
117
- new_path = files_by_checksum[db_state.checksum]
118
- report.moves[db_file_path] = new_path
119
- # Remove from new files since it's a move
120
- report.new.remove(new_path)
121
- else:
122
- # Actually deleted
123
- report.deleted.add(db_file_path)
124
-
125
- # Log summary
126
- logger.debug(f"Total files: {report.total}")
127
- logger.debug(f"Changes found: {report.total_changes}")
128
- logger.debug(f" New: {len(report.new)}")
129
- logger.debug(f" Modified: {len(report.modified)}")
130
- logger.debug(f" Moved: {len(report.moves)}")
131
- logger.debug(f" Deleted: {len(report.deleted)}")
132
-
133
- if scan_result.errors: # pragma: no cover
134
- logger.warning("Files skipped due to errors:")
135
- for file_path, error in scan_result.errors.items():
136
- logger.warning(f" {file_path}: {error}")
137
-
138
- return report
139
-
140
- async def get_db_file_state(self, db_records: Sequence[Entity]) -> Dict[str, FileState]:
141
- """Get file_path and checksums from database.
142
- Args:
143
- db_records: database records
144
- Returns:
145
- Dict mapping file paths to FileState
146
- :param db_records: the data from the db
147
- """
148
- return {
149
- r.file_path: FileState(
150
- file_path=r.file_path, permalink=r.permalink, checksum=r.checksum or ""
151
- )
152
- for r in db_records
153
- }
154
-
155
- async def find_knowledge_changes(self, directory: Path) -> SyncReport:
156
- """Find changes in knowledge directory."""
157
- db_file_state = await self.get_db_file_state(await self.entity_repository.find_all())
158
- return await self.find_changes(directory=directory, db_file_state=db_file_state)
@@ -1,31 +0,0 @@
1
- """Types and utilities for file sync."""
2
-
3
- from dataclasses import dataclass, field
4
- from typing import Set, Dict
5
-
6
-
7
- @dataclass
8
- class SyncReport:
9
- """Report of file changes found compared to database state.
10
-
11
- Attributes:
12
- total: Total number of files in directory being synced
13
- new: Files that exist on disk but not in database
14
- modified: Files that exist in both but have different checksums
15
- deleted: Files that exist in database but not on disk
16
- moves: Files that have been moved from one location to another
17
- checksums: Current checksums for files on disk
18
- """
19
-
20
- total: int = 0
21
- # We keep paths as strings in sets/dicts for easier serialization
22
- new: Set[str] = field(default_factory=set)
23
- modified: Set[str] = field(default_factory=set)
24
- deleted: Set[str] = field(default_factory=set)
25
- moves: Dict[str, str] = field(default_factory=dict) # old_path -> new_path
26
- checksums: Dict[str, str] = field(default_factory=dict) # path -> checksum
27
-
28
- @property
29
- def total_changes(self) -> int:
30
- """Total number of changes."""
31
- return len(self.new) + len(self.modified) + len(self.deleted) + len(self.moves)
@@ -1,81 +0,0 @@
1
- basic_memory/__init__.py,sha256=dDb_uz3MKuWHLxcMY3ytbIQPv3aAHuYxKZ3jAvt2rPo,122
2
- basic_memory/config.py,sha256=NGalTXjTw6OlIDdmWRygy-2jBqGfl9AuXGHy3MUdM-I,1793
3
- basic_memory/db.py,sha256=IK_gz8Uiwcgxe8TjarW7kpl8cVVNtEnR0lm1LemgZ8I,5283
4
- basic_memory/deps.py,sha256=UzivBw6e6iYcU_8SQ8LNCmSsmFyHfjdzfWvnfNzqbRc,5375
5
- basic_memory/file_utils.py,sha256=gp7RCFWaddFnELIyTc1E19Rk8jJsrKshG2n8ZZR-kKA,5751
6
- basic_memory/utils.py,sha256=UriwNFpuHXaWLjEQwIitb1yelzeMhkuKDnIpUh6Zfbw,3388
7
- basic_memory/alembic/README,sha256=MVlc9TYmr57RbhXET6QxgyCcwWP7w-vLkEsirENqiIQ,38
8
- basic_memory/alembic/env.py,sha256=XqJVQhS41ba7NCPmmaSZ09_tbSLnwsY2bcpJpqx_ZTc,2107
9
- basic_memory/alembic/migrations.py,sha256=CIbkMHEKZ60aDUhFGSQjv8kDNM7sazfvEYHGGcy1DBk,858
10
- basic_memory/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
11
- basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py,sha256=lTbWlAnd1es7xU99DoJgfaRe1_Kte8TL98riqeKGV80,4363
12
- basic_memory/api/__init__.py,sha256=wCpj-21j1D0KzKl9Ql6unLBVFY0K1uGp_FeSZRKtqpk,72
13
- basic_memory/api/app.py,sha256=0vmDJDhKkRN1f7XDO3hqcUpXrLRmcHOH79O5x4hPtho,1573
14
- basic_memory/api/routers/__init__.py,sha256=iviQ1QVYobC8huUuyRhEjcA0BDjrOUm1lXHXhJkxP9A,239
15
- basic_memory/api/routers/knowledge_router.py,sha256=cMLhRczOfSRnsZdyR0bSS8PENPRTu70dlwaV27O34bs,5705
16
- basic_memory/api/routers/memory_router.py,sha256=pF0GzmWoxmjhtxZM8jCmfLwqjey_fmXER5vYbD8fsQw,4556
17
- basic_memory/api/routers/resource_router.py,sha256=MoW8LEjBfNbJsp6Nt2JnE4LKe3ysiVqwgY5BMCFuPCQ,4360
18
- basic_memory/api/routers/search_router.py,sha256=dCRnBbp3r966U8UYwgAaxZBbg7yX7pC8QJqagdACUi0,1086
19
- basic_memory/cli/__init__.py,sha256=arcKLAWRDhPD7x5t80MlviZeYzwHZ0GZigyy3NKVoGk,33
20
- basic_memory/cli/app.py,sha256=NG6gs_UzyXBiQLHbiZRZlew3nb7G7i_8gwPh1383EnA,450
21
- basic_memory/cli/main.py,sha256=4RElTaSskLZvS7EAk4KbkU7inDRhoQqHcr_UR5I6lMo,423
22
- basic_memory/cli/commands/__init__.py,sha256=OQGLaKTsOdPsp2INM_pHzmOlbVfdL0sytBNgvqTqCDY,159
23
- basic_memory/cli/commands/db.py,sha256=XW2ujzas5j2Gf01NOPQI89L4NK-21GksO_OIekKxv6c,770
24
- basic_memory/cli/commands/import_chatgpt.py,sha256=Jnqj_kswM9S-qauPCHqLiMIQMvY4PXULHZSiqVJ_veQ,8150
25
- basic_memory/cli/commands/import_claude_conversations.py,sha256=Ba97fH5yfW642yrkxay3YkyDdgIYCeru-MUIZfEGblo,6812
26
- basic_memory/cli/commands/import_claude_projects.py,sha256=euht03ydbI6c5IO_VeArlk9YUYMXNZGXekaa7uG8i7g,6635
27
- basic_memory/cli/commands/import_memory_json.py,sha256=zqpU4eCzQXx04aRsigddJAyhvklmTgSAzeRTuEdNw0c,5194
28
- basic_memory/cli/commands/mcp.py,sha256=BPdThcufdriIvrDskc87a0oCC1BkZ0PZsgNao_-oNKk,611
29
- basic_memory/cli/commands/status.py,sha256=G7aAdbCuiFe38VFxMTcAfY2DKqol3WIQxYa491ui4yM,5728
30
- basic_memory/cli/commands/sync.py,sha256=LpoEPstcguhRPT2bwsbAI3ypiY0cDoNn_gxUmLpX21Q,6827
31
- basic_memory/markdown/__init__.py,sha256=DdzioCWtDnKaq05BHYLgL_78FawEHLpLXnp-kPSVfIc,501
32
- basic_memory/markdown/entity_parser.py,sha256=sJk8TRUd9cAaIjATiJn7dBQRorrYngRbd7MRVfc0Oc4,3781
33
- basic_memory/markdown/markdown_processor.py,sha256=mV3pYoDTaQMEl1tA5n_XztBvNlYyH2SzKs4vnKdAet4,4952
34
- basic_memory/markdown/plugins.py,sha256=gtIzKRjoZsyvBqLpVNnrmzl_cbTZ5ZGn8kcuXxQjRko,6639
35
- basic_memory/markdown/schemas.py,sha256=mzVEDUhH98kwETMknjkKw5H697vg_zUapsJkJVi17ho,1894
36
- basic_memory/markdown/utils.py,sha256=ZtHa-dG--ZwFEUC3jfl04KZGhM_ZWo5b-8d8KpJ90gY,2758
37
- basic_memory/mcp/__init__.py,sha256=dsDOhKqjYeIbCULbHIxfcItTbqudEuEg1Np86eq0GEQ,35
38
- basic_memory/mcp/async_client.py,sha256=vMN5nApPA428Oz4Siq2mNTiBjTcM5A5OSZTnX7_sDxE,234
39
- basic_memory/mcp/server.py,sha256=L92Vit7llaKT9NlPZfxdp67C33niObmRH2QFyUhmnD0,355
40
- basic_memory/mcp/tools/__init__.py,sha256=MHZmWw016N0qbtC3f186Jg1tPzh2g88_ZsCKJ0oyrrs,873
41
- basic_memory/mcp/tools/knowledge.py,sha256=2U8YUKCizsAETHCC1mBVKMfCEef6tlc_pa2wOmA9mD4,2016
42
- basic_memory/mcp/tools/memory.py,sha256=gl4MBm9l2lMOfu_xmUqjoZacWSIHOAYZiAm8z7oDuY8,5203
43
- basic_memory/mcp/tools/notes.py,sha256=ZJGMU-14_aIQvrDA-yaLbnDoFdjIgx7SzE7PWTf7c4o,7249
44
- basic_memory/mcp/tools/search.py,sha256=tx6aIuB2FWmmrvzu3RHSQvszlk-zHcwrWhkLLHWjuZc,1105
45
- basic_memory/mcp/tools/utils.py,sha256=icm-Xyqw3GxooGYkXqjEjoZvIGy_Z3CPw-uUYBxR_YQ,4831
46
- basic_memory/models/__init__.py,sha256=Bf0xXV_ryndogvZDiVM_Wb6iV2fHUxYNGMZNWNcZi0s,307
47
- basic_memory/models/base.py,sha256=4hAXJ8CE1RnjKhb23lPd-QM7G_FXIdTowMJ9bRixspU,225
48
- basic_memory/models/knowledge.py,sha256=R05mLr2GXDfUcmPe2ja20wvzP818b4npnxL1PvQooEY,5921
49
- basic_memory/models/search.py,sha256=IB-ySJUqlQq9FqLGfWnraIFcB_brWa9eBwsQP1rVTeI,1164
50
- basic_memory/repository/__init__.py,sha256=TnscLXARq2iOgQZFvQoT9X1Bn9SB_7s1xw2fOqRs3Jg,252
51
- basic_memory/repository/entity_repository.py,sha256=VFLymzJ1W6AZru_s1S3U6nlqSprBrVV5Toy0-qysIfw,3524
52
- basic_memory/repository/observation_repository.py,sha256=BOcy4wARqCXu-thYyt7mPxt2A2C8TW0le3s_X9wrK6I,1701
53
- basic_memory/repository/relation_repository.py,sha256=DwpTcn9z_1sZQcyMOUABz1k1VSwo_AU63x2zR7aerTk,2933
54
- basic_memory/repository/repository.py,sha256=jUScHWOfcB2FajwVZ2Sbjtg-gSI2Y2rhiIaTULjvmn8,11321
55
- basic_memory/repository/search_repository.py,sha256=NcOGMkPvwo3VlbsmeQWDsA2f1eTzX5cyl-7M2b-ADYs,10036
56
- basic_memory/schemas/__init__.py,sha256=eVxrtuPT7-9JIQ7UDx2J8t8xlS3u0iUkV_VLNbzvxo4,1575
57
- basic_memory/schemas/base.py,sha256=epSauNNVZ2lRLATf-HIzqeberq4ZBTgxliNmjitAsWc,5538
58
- basic_memory/schemas/delete.py,sha256=UAR2JK99WMj3gP-yoGWlHD3eZEkvlTSRf8QoYIE-Wfw,1180
59
- basic_memory/schemas/discovery.py,sha256=6Y2tUiv9f06rFTsa8_wTH2haS2bhCfuQh0uW33hwdd8,876
60
- basic_memory/schemas/memory.py,sha256=mqslazV0lQswtbNgYv_y2-KxmifIvRlg5I3IuTTMnO4,2882
61
- basic_memory/schemas/request.py,sha256=rt_guNWrUMePJvDmsh1g1dc7IqEY6K6mGXMKx8tBCj8,1614
62
- basic_memory/schemas/response.py,sha256=lVYR31DTtSeFRddGWX_wQWnQgyiwX0LEpNJ4f4lKpTM,6440
63
- basic_memory/schemas/search.py,sha256=pWBA1-xEQ3rH8vLIgrQT4oygq9MMwr0B7VCbFafVVOw,3278
64
- basic_memory/services/__init__.py,sha256=oop6SKmzV4_NAYt9otGnupLGVCCKIVgxEcdRQWwh25I,197
65
- basic_memory/services/context_service.py,sha256=Bu1wVl9q3FDGbGChrLqgFGQW95-W1OfjNqq6SGljqWg,9388
66
- basic_memory/services/entity_service.py,sha256=CoN1HVrjlT2JDaG3tfs6NixkZgJ4xbaEjABkv8hyGJ4,11784
67
- basic_memory/services/exceptions.py,sha256=VGlCLd4UD2w5NWKqC7QpG4jOM_hA7jKRRM-MqvEVMNk,288
68
- basic_memory/services/file_service.py,sha256=r4JfPY1wyenAH0Y-iq7vGHPwT616ayUWoLnvA1NuzpA,5695
69
- basic_memory/services/link_resolver.py,sha256=GmUPTViW5JplQo4yJNaX18OGInqMitrxUeR4LQqUABA,4581
70
- basic_memory/services/search_service.py,sha256=VDtRYYCHojzG2-yQbi_8ncs5YdoyHM7k_QHdA-0g6oI,7829
71
- basic_memory/services/service.py,sha256=V-d_8gOV07zGIQDpL-Ksqs3ZN9l3qf3HZOK1f_YNTag,336
72
- basic_memory/sync/__init__.py,sha256=ko0xLQv1S5U7sAOmIP2XKl03akVPzoY-a9m3TFPcMh4,193
73
- basic_memory/sync/file_change_scanner.py,sha256=4whJej6t9sxwUp1ox93efJ0bBHSnAr6STpk_PsKU6to,5784
74
- basic_memory/sync/sync_service.py,sha256=nAOX4N90lbpRJeq5tRR_7PYptIoWwhXMUljE7yrneF4,7087
75
- basic_memory/sync/utils.py,sha256=wz1Fe7Mb_M5N9vYRQnDKGODiMGcj5MEK16KVJ3eoQ9g,1191
76
- basic_memory/sync/watch_service.py,sha256=CtKBrP1imI3ZSEgJl7Ffi-JZ_oDGKrhiyGgs41h5QYI,7563
77
- basic_memory-0.6.0.dist-info/METADATA,sha256=GcfzSP0T_Fr8dh6xAIYPrZKBXLOTiMyQ-9vg6EJ3JkI,10849
78
- basic_memory-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
79
- basic_memory-0.6.0.dist-info/entry_points.txt,sha256=IDQa_VmVTzmvMrpnjhEfM0S3F--XsVGEj3MpdJfuo-Q,59
80
- basic_memory-0.6.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
81
- basic_memory-0.6.0.dist-info/RECORD,,