Give the write path a CLI and an MCP face
remember / supersede / forget now reach the one Python writer from a terminal, from MCP, and from HTTP. The server, not the caller, decides who owns a memory. - cli: remember, supersede, forget. --holder falls back to settings.default_holder until the holder registry lands. Timestamps are parsed once with one clear message. - ingestion: import pymupdf as fitz. The deprecated fitz import printed a warning to stdout, so every CLI command's JSON answer was unparseable. - mcp: remember, supersede_memory and forget_memory forward to the Python writer over HTTP (ELY_EYE_API, default http://127.0.0.1:8765). SQLite stays read-only to the Go side, so the write rules live in one place. - mcp reads follow schema v2: atoms.time became ingested_at, and reads go through v_atoms_current, so a superseded memory stops being findable. holder, origin, scenario and event_time now show up in fetch_atom and search_atoms. - scripts/mcp_write_smoke.sh proves the loop end to end: remember, search, supersede, forget, then not found. Evidence: 92 pytest passed; go build, go vet and go test clean; mypy clean on the 10 touched source files with a fresh cache; ruff clean except a pre-existing B008 at cli.py:292, identical at HEAD.
This commit is contained in:
1 parent
181f6bf57e
commit
3d792417cf
20 files changed
+1425
-33
No files matched your search
@@ -35,6 +35,7 @@ from .evaluation_schemas import (
|
||||
)
|
||||
from .evidence_graph import EvidenceGraphService
|
||||
from .ingestion import IngestionService
|
||||
from .memory import MemoryService
|
||||
from .profiles import runtime_profile_report
|
||||
from .research_modules import ResearchModuleService
|
||||
from .runtime import QwenRuntime, RuntimeUnavailableError
|
||||
@@ -43,10 +44,16 @@ from .schemas import (
|
||||
AdapterStatus,
|
||||
AnswerResponse,
|
||||
CartridgeAssetReport,
|
||||
EvidenceAtom,
|
||||
ForgetReport,
|
||||
ForgetRequest,
|
||||
MemoryOrigin,
|
||||
MemoryStatus,
|
||||
PathIngestRequest,
|
||||
RememberRequest,
|
||||
RuntimeProfile,
|
||||
RuntimeProfileReport,
|
||||
SupersedeRequest,
|
||||
SystemStatus,
|
||||
UploadIngestRequest,
|
||||
)
|
||||
@@ -183,6 +190,50 @@ def create_app() -> FastAPI:
|
||||
runtime_backend=generation.backend,
|
||||
)
|
||||
|
||||
@app.post("/api/memory", response_model=EvidenceAtom)
|
||||
def remember(
|
||||
request: RememberRequest, settings: Annotated[Settings, Depends(settings_dep)]
|
||||
) -> EvidenceAtom:
|
||||
try:
|
||||
return MemoryService(settings).remember(
|
||||
request.text,
|
||||
holder_id=settings.default_holder,
|
||||
origin=MemoryOrigin.self_,
|
||||
scenario=request.scenario,
|
||||
event_time=request.event_time,
|
||||
event_time_precision=request.event_time_precision,
|
||||
event_time_source=request.event_time_source,
|
||||
retention_until=request.retention_until,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
|
||||
@app.post("/api/memory/supersede", response_model=EvidenceAtom)
|
||||
def supersede(
|
||||
request: SupersedeRequest, settings: Annotated[Settings, Depends(settings_dep)]
|
||||
) -> EvidenceAtom:
|
||||
try:
|
||||
return MemoryService(settings).supersede(
|
||||
request.atom_id,
|
||||
text=request.text,
|
||||
holder_id=settings.default_holder,
|
||||
scenario=request.scenario,
|
||||
event_time=request.event_time,
|
||||
event_time_precision=request.event_time_precision,
|
||||
event_time_source=request.event_time_source,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
|
||||
@app.post("/api/memory/forget", response_model=ForgetReport)
|
||||
def forget(request: ForgetRequest, settings: Annotated[Settings, Depends(settings_dep)]) -> ForgetReport:
|
||||
try:
|
||||
return MemoryService(settings).forget(
|
||||
atom_id=request.atom_id, source_id=request.source_id, reason=request.reason
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
|
||||
@app.get("/api/cartridges")
|
||||
def cartridges(settings: Annotated[Settings, Depends(settings_dep)]):
|
||||
return CartridgeService(settings).list_manifests()
|
||||
|
||||
Reference in new issue
Block a user