From 6e1be04fba4ea037b88482b4547ba62a9e47fc20 Mon Sep 17 00:00:00 2001 From: Elliot Chen Date: Mon, 20 Jul 2026 17:47:22 +0800 Subject: [PATCH] chore(release): update EverOS to 1.1.4 --- CHANGELOG.md | 29 ++++++++++++++++++- CITATION.md | 2 +- docs/openapi.json | 2 +- docs/overview.md | 2 +- pyproject.toml | 2 +- src/everos/memory/cascade/worker.py | 5 +++- .../test_memory/test_cascade/test_worker.py | 29 +++++++++++++++++++ uv.lock | 2 +- 8 files changed, 66 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b720c364..379c9c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.4] - 2026-07-20 + +### Added + +- **Langfuse integration example** — added an OpenTelemetry-based wrapper for + tracing EverOS add, flush/extract, search, and reflection operations, with a + built-in mock and support for connecting to a real EverOS server. + +### Fixed + +- **Cascade delete/modify race** — when a file disappears after its modified + event is queued, the worker now processes it as a deletion instead of leaving + a stale indexed row and permanently failed queue item. +- **Langfuse live-server traces use only real telemetry** — synthetic child + spans are now limited to responses that provide stage details, while real + servers emit accurate top-level latency, output, and recall-quality scores. + +## [1.1.3] - 2026-07-10 + +### Fixed + +- **LanceDB FTS optimize crash and disk growth** — disabled unused positional + data in OR-mode BM25 indexes, automatically rebuilds affected indexes, and + escalates repeated optimize failures so cleanup cannot fail silently. + ## [1.1.2] - 2026-07-07 ### Fixed @@ -226,7 +251,9 @@ for AI agents. - **Decoupled algorithms** — memory extraction algorithms live in the standalone `everalgo-*` libraries published on PyPI. -[Unreleased]: https://github.com/EverMind-AI/everos/compare/v1.1.2...HEAD +[Unreleased]: https://github.com/EverMind-AI/everos/compare/v1.1.4...HEAD +[1.1.4]: https://github.com/EverMind-AI/everos/compare/v1.1.3...v1.1.4 +[1.1.3]: https://github.com/EverMind-AI/everos/compare/v1.1.2...v1.1.3 [1.1.2]: https://github.com/EverMind-AI/everos/compare/v1.1.1...v1.1.2 [1.1.1]: https://github.com/EverMind-AI/everos/compare/v1.1.0...v1.1.1 [1.1.0]: https://github.com/EverMind-AI/everos/compare/v1.0.1...v1.1.0 diff --git a/CITATION.md b/CITATION.md index 2b16b357..4ee7096e 100644 --- a/CITATION.md +++ b/CITATION.md @@ -33,7 +33,7 @@ To cite the software itself: ``` EverOS: local-first memory runtime for AI agents -Version: 1.1.0 +Version: 1.1.4 URL: https://github.com/EverMind-AI/EverOS License: Apache 2.0 ``` diff --git a/docs/openapi.json b/docs/openapi.json index 58ad559e..c45a2e0b 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "everos", "description": "md-first memory extraction framework", - "version": "1.1.2" + "version": "1.1.4" }, "paths": { "/health": { diff --git a/docs/overview.md b/docs/overview.md index 7f9be38e..07297673 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -86,4 +86,4 @@ Strict single-direction dependency, enforced by `import-linter` in CI. ## Status -**Latest stable release: v1.1.0** (PyPI) — the v1 API is stable. +**Latest stable release: v1.1.4** (PyPI) — the v1 API is stable. diff --git a/pyproject.toml b/pyproject.toml index 0e359b6e..216b2476 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "everos" -version = "1.1.2" +version = "1.1.4" description = "EverOS — local-first markdown memory framework for AI agents and user chats; lightweight, dev-friendly, small-team" license = {text = "Apache-2.0"} readme = "README.md" diff --git a/src/everos/memory/cascade/worker.py b/src/everos/memory/cascade/worker.py index 8525cb36..432f0436 100644 --- a/src/everos/memory/cascade/worker.py +++ b/src/everos/memory/cascade/worker.py @@ -330,7 +330,10 @@ async def _process_one(self, row: MdChangeState) -> str | None: if row.change_type == "deleted": outcome = await handler.handle_deleted(row.md_path) else: - outcome = await handler.handle_added_or_modified(row.md_path) + try: + outcome = await handler.handle_added_or_modified(row.md_path) + except FileNotFoundError: + outcome = await handler.handle_deleted(row.md_path) except RecoverableError as exc: last_error = f"{type(exc).__name__}: {exc}" logger.warning( diff --git a/tests/unit/test_memory/test_cascade/test_worker.py b/tests/unit/test_memory/test_cascade/test_worker.py index b2622f04..42e6a65b 100644 --- a/tests/unit/test_memory/test_cascade/test_worker.py +++ b/tests/unit/test_memory/test_cascade/test_worker.py @@ -103,6 +103,20 @@ async def handle_added_or_modified(self, md_path: str) -> HandlerOutcome: raise RuntimeError("unexpected boom") +class _VanishedFileHandler(_OkHandler): + """Simulate a file removed after its modified event was queued.""" + + def __init__(self) -> None: + self.deleted_paths: list[str] = [] + + async def handle_added_or_modified(self, md_path: str) -> HandlerOutcome: + raise FileNotFoundError(md_path) + + async def handle_deleted(self, md_path: str) -> HandlerOutcome: + self.deleted_paths.append(md_path) + return await super().handle_deleted(md_path) + + @pytest.fixture def patched_repo(monkeypatch: pytest.MonkeyPatch) -> _FakeRepo: """Drop a fake repo onto the module the worker imports.""" @@ -157,6 +171,21 @@ async def test_bare_exception_marked_permanent(patched_repo: _FakeRepo) -> None: assert retryable is False +async def test_modified_event_for_vanished_file_is_processed_as_delete( + patched_repo: _FakeRepo, +) -> None: + """A stale modified event must not leave the indexed row behind.""" + patched_repo.batch = [_Row(md_path="vanished.md", change_type="modified")] + handler = _VanishedFileHandler() + w = CascadeWorker({"episode": handler}, retry_backoff_seconds=0) + + await w.drain_once() + + assert handler.deleted_paths == ["vanished.md"] + assert patched_repo.done == ["vanished.md"] + assert patched_repo.failed == [] + + async def test_unknown_kind_marks_permanent_without_handler( patched_repo: _FakeRepo, ) -> None: diff --git a/uv.lock b/uv.lock index 65fa5d51..56205158 100644 --- a/uv.lock +++ b/uv.lock @@ -560,7 +560,7 @@ wheels = [ [[package]] name = "everos" -version = "1.1.2" +version = "1.1.4" source = { editable = "." } dependencies = [ { name = "aiosqlite" },