Skip to content

Commit 484cc07

Browse files
author
phernandez
committed
fix: re-add feature to read multiple notes
1 parent 95e1790 commit 484cc07

File tree

14 files changed

+59
-32
lines changed

14 files changed

+59
-32
lines changed

src/basic_memory/api/routers/resource_router.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
router = APIRouter(prefix="/resource", tags=["resources"])
2222

2323

24-
def get_entity_ids(item: SearchIndexRow) -> list[int]:
24+
def get_entity_ids(item: SearchIndexRow) -> list[int]: # pyright: ignore [reportReturnType]
2525
match item.type:
2626
case SearchItemType.ENTITY:
2727
return [item.id]
@@ -31,6 +31,8 @@ def get_entity_ids(item: SearchIndexRow) -> list[int]:
3131
from_entity = item.from_id
3232
to_entity = item.to_id
3333
return [from_entity, to_entity] if to_entity else [from_entity]
34+
case _:
35+
raise ValueError(f"Unexpected type: {item.type}")
3436

3537

3638
@router.get("/{identifier:path}")

src/basic_memory/cli/commands/import_chatgpt.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ def traverse_messages(
6969

7070

7171
def format_chat_markdown(
72-
title: str, mapping: Dict[str, Any], root_id: Optional[str], created_at: float, modified_at: float
72+
title: str,
73+
mapping: Dict[str, Any],
74+
root_id: Optional[str],
75+
created_at: float,
76+
modified_at: float,
7377
) -> str:
7478
"""Format chat as clean markdown."""
7579

src/basic_memory/db.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,15 @@ async def run_migrations(app_config: ProjectConfig, database_type=DatabaseType.F
140140

141141
# Set required Alembic config options programmatically
142142
config.set_main_option("script_location", str(alembic_dir))
143-
config.set_main_option("file_template",
144-
"%%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s")
143+
config.set_main_option(
144+
"file_template",
145+
"%%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s",
146+
)
145147
config.set_main_option("timezone", "UTC")
146148
config.set_main_option("revision_environment", "false")
147-
config.set_main_option("sqlalchemy.url", DatabaseType.get_db_url(app_config.database_path, database_type))
149+
config.set_main_option(
150+
"sqlalchemy.url", DatabaseType.get_db_url(app_config.database_path, database_type)
151+
)
148152

149153
command.upgrade(config, "head")
150154
logger.info("Migrations completed successfully")
@@ -153,4 +157,4 @@ async def run_migrations(app_config: ProjectConfig, database_type=DatabaseType.F
153157
await SearchRepository(session_maker).init_search_index()
154158
except Exception as e: # pragma: no cover
155159
logger.error(f"Error running migrations: {e}")
156-
raise
160+
raise

src/basic_memory/mcp/tools/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,4 @@ async def call_delete(
151151
return response
152152
except HTTPStatusError as e:
153153
logger.error(f"Error calling DELETE {url}: {e}")
154-
raise ToolError(f"Error calling tool: {e}") from e
154+
raise ToolError(f"Error calling tool: {e}") from e

src/basic_memory/models/search.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@
3131
tokenize='unicode61 tokenchars 0x2F', -- Hex code for /
3232
prefix='1,2,3,4' -- Support longer prefixes for paths
3333
);
34-
""")
34+
""")

src/basic_memory/repository/search_repository.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,35 +73,35 @@ async def init_search_index(self):
7373
async with db.scoped_session(self.session_maker) as session:
7474
await session.execute(CREATE_SEARCH_INDEX)
7575
await session.commit()
76-
except Exception as e: # pragma: no cover
76+
except Exception as e: # pragma: no cover
7777
logger.error(f"Error initializing search index: {e}")
7878
raise e
79-
79+
8080
def _prepare_search_term(self, term: str, is_prefix: bool = True) -> str:
8181
"""Prepare a search term for FTS5 query.
82-
82+
8383
Args:
8484
term: The search term to prepare
8585
is_prefix: Whether to add prefix search capability (* suffix)
86-
86+
8787
For FTS5:
8888
- Special characters and phrases need to be quoted
8989
- Terms with spaces or special chars need quotes
9090
"""
9191
if "*" in term:
9292
return term
93-
93+
9494
# List of special characters that need quoting (excluding *)
9595
special_chars = ["/", "-", ".", " ", "(", ")", "[", "]", '"', "'"]
96-
96+
9797
# Check if term contains any special characters
9898
needs_quotes = any(c in term for c in special_chars)
99-
99+
100100
if needs_quotes:
101101
# If the term already contains quotes, escape them and add a wildcard
102102
term = term.replace('"', '""')
103103
term = f'"{term}"*'
104-
104+
105105
return term
106106

107107
async def search(
@@ -140,14 +140,15 @@ async def search(
140140
# Handle permalink match search, supports *
141141
if permalink_match:
142142
# Clean and prepare permalink for FTS5 GLOB match
143-
permalink_text = self._prepare_search_term(permalink_match.lower().strip(), is_prefix=False)
143+
permalink_text = self._prepare_search_term(
144+
permalink_match.lower().strip(), is_prefix=False
145+
)
144146
params["permalink"] = permalink_text
145147
if "*" in permalink_match:
146148
conditions.append("permalink GLOB :permalink")
147-
else:
149+
else:
148150
conditions.append("permalink MATCH :permalink")
149151

150-
151152
# Handle type filter
152153
if types:
153154
type_list = ", ".join(f"'{t.value}'" for t in types)
@@ -223,7 +224,9 @@ async def search(
223224

224225
logger.debug(f"Found {len(results)} search results")
225226
for r in results:
226-
logger.debug(f"Search result: type:{r.type} title: {r.title} permalink: {r.permalink} score: {r.score}")
227+
logger.debug(
228+
f"Search result: type:{r.type} title: {r.title} permalink: {r.permalink} score: {r.score}"
229+
)
227230

228231
return results
229232

src/basic_memory/schemas/response.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
3. Responses include everything needed for next operations
1111
4. Bulk operations return all affected items
1212
"""
13+
1314
from datetime import datetime
1415
from typing import List, Optional, Dict
1516

@@ -42,6 +43,7 @@ class ObservationResponse(Observation, SQLAlchemyModel):
4243
"context": "Initial database design meeting"
4344
}
4445
"""
46+
4547
permalink: Permalink
4648

4749

@@ -59,6 +61,7 @@ class RelationResponse(Relation, SQLAlchemyModel):
5961
"context": "Comprehensive test suite"
6062
}
6163
"""
64+
6265
permalink: Permalink
6366

6467
from_id: Permalink = Field(

src/basic_memory/services/entity_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,12 @@ async def get_by_permalink(self, permalink: str) -> EntityModel:
184184
if not db_entity:
185185
raise EntityNotFoundError(f"Entity not found: {permalink}")
186186
return db_entity
187-
187+
188188
async def get_entities_by_id(self, ids: List[int]) -> Sequence[EntityModel]:
189189
"""Get specific entities and their relationships."""
190190
logger.debug(f"Getting entities: {ids}")
191191
return await self.repository.find_by_ids(ids)
192-
192+
193193
async def get_entities_by_permalinks(self, permalinks: List[str]) -> Sequence[EntityModel]:
194194
"""Get specific nodes and their relationships."""
195195
logger.debug(f"Getting entities permalinks: {permalinks}")

src/basic_memory/services/link_resolver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async def resolve_link(self, link_text: str, use_search: bool = True) -> Optiona
4646
logger.debug(f"Found title match: {entity.title}")
4747
return entity
4848

49-
if use_search and '*' not in clean_text:
49+
if use_search and "*" not in clean_text:
5050
# 3. Fall back to search for fuzzy matching on title
5151
results = await self.search_service.search(
5252
query=SearchQuery(title=clean_text, types=[SearchItemType.ENTITY]),

tests/api/test_resource_router.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ async def test_get_resource_entities(client, test_config, entity_repository):
165165
assert response.status_code == 200
166166
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
167167
assert (
168-
f"""
168+
f"""
169169
--- memory://test/test-entity {entity1.updated_at.isoformat()} {entity1.checksum[:8]}
170170
171171
# Test Content
@@ -176,11 +176,10 @@ async def test_get_resource_entities(client, test_config, entity_repository):
176176
- links to [[Test Entity]]
177177
178178
""".strip()
179-
in response.text
179+
in response.text
180180
)
181181

182182

183-
184183
@pytest.mark.asyncio
185184
async def test_get_resource_relation(client, test_config, entity_repository):
186185
"""Test getting content by relation permalink."""

0 commit comments

Comments
 (0)