chore: initialize EverOS 1.0.0

md-first memory extraction framework for AI agents.

Markdown is the single source of truth; SQLite holds state and LanceDB
provides the rebuildable vector + BM25 + scalar index. The codebase follows
a single-direction DDD layering (entrypoints -> service -> memory -> infra,
with component / core / config cross-cutting) enforced by import-linter.

Engineering surface:
- Coding conventions in .claude/rules/ (path-scoped) and workflows in
  .claude/skills/ (/commit, /new-branch, /pr).
- GitHub Actions CI runs make lint + test + integration; pre-commit mirrors
  the gates locally (ruff, hygiene hooks, gitlint commit-msg).
- Commit messages follow Conventional Commits, enforced by gitlint.
- make lint also enforces datetime two-zone discipline and OpenAPI drift.
This commit is contained in:
Elliot Chen
2026-06-05 22:35:51 +08:00
commit 518b8eca85
636 changed files with 160553 additions and 0 deletions

View File

@ -0,0 +1,35 @@
"""HTTP API lifespan providers.
Concrete :class:`everos.core.lifespan.LifespanProvider` implementations
for the storage + chassis backends this entrypoint composes. They live next to
``app.py`` because they are *application-bootstrap* details, not
generic chassis: a different deployment mode (CLI, embedded, batch
worker) may compose a different set of providers.
Putting these here also keeps ``core.lifespan`` free of concrete-
backend imports — the chassis stays portable.
External usage::
from everos.entrypoints.api.lifespans import (
LLMLifespanProvider,
SqliteLifespanProvider,
LanceDBLifespanProvider,
CascadeLifespanProvider,
OmeLifespanProvider,
)
"""
from .cascade import CascadeLifespanProvider as CascadeLifespanProvider
from .lancedb import LanceDBLifespanProvider as LanceDBLifespanProvider
from .llm import LLMLifespanProvider as LLMLifespanProvider
from .ome import OmeLifespanProvider as OmeLifespanProvider
from .sqlite import SqliteLifespanProvider as SqliteLifespanProvider
__all__ = [
"CascadeLifespanProvider",
"LLMLifespanProvider",
"LanceDBLifespanProvider",
"OmeLifespanProvider",
"SqliteLifespanProvider",
]

View File

@ -0,0 +1,55 @@
"""Cascade lifespan provider — starts/stops :class:`CascadeOrchestrator`.
Ordered after SqliteLifespan + LanceDBLifespan: the orchestrator
depends on both stores being ready before its watcher / scanner /
worker tasks can take the first row.
Construction reads the live :class:`Settings` to build the embedding +
tokenizer providers. If either is misconfigured the lifespan fails
fast — the daemon would be useless without them anyway.
"""
from __future__ import annotations
from typing import Any
from fastapi import FastAPI
from everos.component.embedding import build_embedding_provider
from everos.component.tokenizer import build_tokenizer
from everos.config import load_settings
from everos.core.lifespan import LifespanProvider
from everos.core.observability.logging import get_logger
from everos.core.persistence import MemoryRoot
from everos.memory.cascade import CascadeOrchestrator
logger = get_logger(__name__)
class CascadeLifespanProvider(LifespanProvider):
"""Manage the cascade subsystem for the app lifecycle."""
def __init__(self, order: int = 12) -> None:
super().__init__(name="cascade", order=order)
self._orchestrator: CascadeOrchestrator | None = None
async def startup(self, app: FastAPI) -> Any:
settings = load_settings()
memory_root = MemoryRoot.default()
memory_root.ensure()
embedder = build_embedding_provider(settings.embedding)
tokenizer = build_tokenizer()
self._orchestrator = CascadeOrchestrator(
memory_root=memory_root,
embedder=embedder,
tokenizer=tokenizer,
)
await self._orchestrator.start()
logger.info("cascade_lifespan_ready")
return self._orchestrator
async def shutdown(self, app: FastAPI) -> None:
if self._orchestrator is not None:
await self._orchestrator.stop()
self._orchestrator = None

View File

@ -0,0 +1,55 @@
"""LanceDB lifespan provider (HTTP API entrypoint).
Startup:
Open the connection via ``get_connection`` (lazy, idempotent).
Importing :mod:`everos.infra.persistence.lancedb` also triggers the
side-effect import of ``tables`` so business schemas are loaded
(future: preflight registration).
Shutdown:
Close the connection (also clears the table cache).
"""
from __future__ import annotations
from typing import Any
from fastapi import FastAPI
from everos.core.lifespan import LifespanProvider
from everos.core.observability.logging import get_logger
from everos.infra.persistence.lancedb import (
dispose_connection,
ensure_business_indexes,
get_connection,
verify_business_schemas,
)
logger = get_logger(__name__)
class LanceDBLifespanProvider(LifespanProvider):
"""Manage the LanceDB connection + table cache for the app lifecycle.
Startup runs three steps:
1. ``get_connection`` — lazy-open the async connection.
2. ``verify_business_schemas`` — fail loud if an on-disk table's
columns drift from the current Pydantic schema. LanceDB has no
online migration; cascade is rebuildable from md so the recovery
is documented as ``rm -rf ~/.everos/.index/lancedb``.
3. ``ensure_business_indexes`` — idempotent FTS index creation.
"""
def __init__(self, order: int = 11) -> None:
super().__init__(name="lancedb", order=order)
async def startup(self, app: FastAPI) -> Any:
conn = await get_connection()
await verify_business_schemas()
await ensure_business_indexes()
logger.info("lancedb_ready", uri=conn.uri)
return conn
async def shutdown(self, app: FastAPI) -> None:
await dispose_connection()

View File

@ -0,0 +1,36 @@
"""LLM lifespan provider — eagerly resolves the LLM singleton at startup.
The framework's core value (memory extraction) is meaningless without
an LLM, so misconfiguration must surface as a startup failure instead
of N silent skips per request downstream. Ordered before the storage
stack so we fail before paying to bring sqlite / lancedb / cascade up.
"""
from __future__ import annotations
from typing import Any
from fastapi import FastAPI
from everos.component.llm import get_llm_client
from everos.core.lifespan import LifespanProvider
from everos.core.observability.logging import get_logger
logger = get_logger(__name__)
class LLMLifespanProvider(LifespanProvider):
"""Resolve the LLM client at startup; raise if credentials are missing."""
def __init__(self, order: int = 8) -> None:
super().__init__(name="llm", order=order)
async def startup(self, app: FastAPI) -> Any:
client = get_llm_client()
logger.info("llm_lifespan_ready")
return client
async def shutdown(self, app: FastAPI) -> None:
# The client is stateless (algo facade over openai.AsyncOpenAI);
# nothing to tear down.
return None

View File

@ -0,0 +1,39 @@
"""OME engine lifespan provider (HTTP API entrypoint).
Startup: build the singleton engine via service.memorize._get_engine
(which also registers strategies) and start it.
Shutdown: stop the engine.
"""
from __future__ import annotations
import importlib
from typing import Any
from fastapi import FastAPI
from everos.core.lifespan import LifespanProvider
from everos.core.observability.logging import get_logger
logger = get_logger(__name__)
class OmeLifespanProvider(LifespanProvider):
"""Manage the OfflineEngine lifecycle for the FastAPI app."""
def __init__(self, order: int = 50) -> None:
super().__init__(name="ome", order=order)
async def startup(self, app: FastAPI) -> Any:
svc = importlib.import_module("everos.service.memorize")
engine = svc._get_engine() # noqa: SLF001 — service-internal accessor
await engine.start()
logger.info("ome_engine_started")
return engine
async def shutdown(self, app: FastAPI) -> None:
svc = importlib.import_module("everos.service.memorize")
engine = svc._get_engine() # noqa: SLF001
await engine.stop()
logger.info("ome_engine_stopped")

View File

@ -0,0 +1,45 @@
"""SQLite system-DB lifespan provider (HTTP API entrypoint).
Startup:
1. Build the engine via ``get_engine`` (lazy, idempotent). Importing
:mod:`everos.infra.persistence.sqlite` also triggers the side-
effect import of ``tables`` so every business SQLModel registers
itself in ``SQLModel.metadata``.
2. ``SQLModel.metadata.create_all`` so every registered table exists.
Shutdown:
Dispose the engine + connection pool.
"""
from __future__ import annotations
from typing import Any
from fastapi import FastAPI
from sqlmodel import SQLModel
from everos.core.lifespan import LifespanProvider
from everos.core.observability.logging import get_logger
from everos.infra.persistence.sqlite import dispose_engine, get_engine
logger = get_logger(__name__)
class SqliteLifespanProvider(LifespanProvider):
"""Manage the SQLite system-DB engine + schema for the app lifecycle."""
def __init__(self, order: int = 10) -> None:
super().__init__(name="sqlite", order=order)
async def startup(self, app: FastAPI) -> Any:
engine = get_engine()
async with engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.create_all)
logger.info(
"sqlite_schema_ready",
tables=len(SQLModel.metadata.tables),
)
return engine
async def shutdown(self, app: FastAPI) -> None:
await dispose_engine()