Files

77 lines
2.6 KiB
Python

from __future__ import annotations
import re
from typing import Any
from memrelay.errors import AppError
class FakeBasicMemory:
def __init__(self) -> None:
self.notes: dict[str, dict[str, Any]] = {}
self.write_calls = 0
self.fail_semantic = False
async def health(self) -> dict[str, Any]:
return {"status": "ok", "project_count": 1, "url": "memory://fake"}
async def write_note(
self,
*,
title: str,
content: str,
directory: str,
tags: list[str],
note_type: str,
metadata: dict[str, Any],
overwrite: bool,
) -> dict[str, Any]:
slug = re.sub(r"[^a-z0-9]+", "-", title.casefold()).strip("-") or "memory"
permalink = f"{directory}/{slug}"
if permalink in self.notes and not overwrite:
raise AppError("BASIC_MEMORY_CONFLICT", "note exists", 409)
self.write_calls += 1
self.notes[permalink] = {
"title": title,
"content": content,
"tags": tags,
"note_type": note_type,
"metadata": metadata,
"permalink": permalink,
}
return {
"title": title,
"permalink": permalink,
"action": "updated" if overwrite else "created",
}
async def read_note(self, identifier: str) -> dict[str, Any]:
if identifier not in self.notes:
raise AppError("MEMORY_NOT_FOUND", "not found", 404)
return self.notes[identifier]
async def search_notes(
self, query: str, search_type: str = "hybrid", page_size: int = 20
) -> dict[str, Any]:
if self.fail_semantic and search_type in {"hybrid", "vector"}:
raise AppError("BASIC_MEMORY_UNAVAILABLE", "semantic unavailable", 503)
words = query.casefold().split()
results = []
for note in self.notes.values():
haystack = f"{note['title']} {note['content']}".casefold()
if any(word in haystack for word in words):
results.append(
{"title": note["title"], "permalink": note["permalink"], "score": 1.0}
)
return {"results": results[:page_size]}
async def move_note(self, identifier: str, destination_path: str) -> dict[str, Any]:
note = self.notes.pop(identifier)
permalink = destination_path.removesuffix(".md")
note["permalink"] = permalink
self.notes[permalink] = note
return {"permalink": permalink}
async def delete_note(self, identifier: str) -> None:
self.notes.pop(identifier, None)