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.
222 lines
8.0 KiB
TOML
222 lines
8.0 KiB
TOML
[project]
|
|
name = "everos"
|
|
version = "1.0.0"
|
|
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"
|
|
requires-python = ">=3.12"
|
|
authors = [
|
|
{name = "EverMind AI"},
|
|
]
|
|
keywords = ["memory", "ai-agent", "markdown", "lancedb", "rag", "everos"]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"License :: OSI Approved :: Apache Software License",
|
|
"Programming Language :: Python :: 3",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
]
|
|
dependencies = [
|
|
# Core data validation & config
|
|
"pydantic>=2.7.1",
|
|
"pydantic-settings>=2.0.0",
|
|
"python-dotenv>=1.0.1",
|
|
|
|
# Storage stack (md-first three-piece set)
|
|
"lancedb>=0.13.0", # Vector + BM25 + scalar filter (Arrow-based)
|
|
"aiosqlite>=0.20.0", # Async SQLite driver (used by SA async engine)
|
|
"sqlmodel>=0.0.22", # ORM (Pydantic + SQLAlchemy 2.0 async)
|
|
"alembic>=1.13.0", # SQLite schema migrations
|
|
"greenlet>=3.0", # Required by SQLAlchemy async
|
|
|
|
# LLM & embedding (one provider per file pattern)
|
|
"openai>=1.0.0",
|
|
|
|
# Markdown / file system
|
|
"PyYAML>=6.0", # YAML frontmatter parsing
|
|
"watchdog>=4.0.0", # Cross-platform file system events (cascade daemon)
|
|
|
|
# Web framework (entrypoints/api)
|
|
"fastapi>=0.104.0",
|
|
"uvicorn[standard]>=0.24.0",
|
|
|
|
# Observability (core/observability)
|
|
"structlog>=24.0.0",
|
|
"prometheus-client>=0.20.0",
|
|
|
|
# CLI
|
|
"typer>=0.12.0",
|
|
|
|
# Tokenization (BM25 Chinese support)
|
|
"jieba==0.42.1",
|
|
|
|
# OME (Offline Memory Evolution) async scheduler & file I/O
|
|
"apscheduler>=3.10.4,<4.0", # async strategy scheduler chassis
|
|
"portalocker>=2.8.2", # cross-platform file lock for single-engine guard
|
|
"watchfiles>=0.21.0", # native fs watcher for config hot reload
|
|
"anyio>=4.0", # Async file I/O (anyio.Path, to_thread.run_sync) for the markdown layer
|
|
|
|
# Algorithm library (everalgo monorepo, published on PyPI).
|
|
"everalgo-core==0.2.0",
|
|
"everalgo-boundary==0.2.0",
|
|
"everalgo-user-memory==0.2.0",
|
|
"everalgo-agent-memory==0.2.0",
|
|
"everalgo-rank==0.3.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
multimodal = ["everalgo-parser[svg]>=0.1.0"] # [svg] bundles cairosvg → SVG works by default
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["src/everos"]
|
|
|
|
# ``env.template`` lives at src/everos/templates/env.template and is
|
|
# auto-included via ``packages``. ``everos init`` reads it through
|
|
# ``importlib.resources``. No force-include needed.
|
|
|
|
# sdist uses an include-whitelist (not exclude) so we don't accidentally ship
|
|
# things like CLAUDE.md, .claude/, CI configs, or IDE settings. New top-level
|
|
# files default to NOT-shipped — you have to opt them in here.
|
|
#
|
|
# exclude is kept as belt-and-suspenders for build artefacts that CI may
|
|
# generate inside the project tree (e.g. UV_CACHE_DIR=.uv-cache).
|
|
[tool.hatch.build.targets.sdist]
|
|
include = [
|
|
"/src",
|
|
"/tests",
|
|
"/data",
|
|
"/docs",
|
|
"/pyproject.toml",
|
|
"/uv.lock",
|
|
"/README.md",
|
|
"/QUICKSTART.md",
|
|
"/CHANGELOG.md",
|
|
"/CONTRIBUTING.md",
|
|
"/CODE_OF_CONDUCT.md",
|
|
"/SECURITY.md",
|
|
"/ACKNOWLEDGMENTS.md",
|
|
"/CITATION.md",
|
|
"/LICENSE",
|
|
"/NOTICE",
|
|
"/config.example.toml",
|
|
]
|
|
exclude = [".uv-cache", ".venv"]
|
|
|
|
[project.scripts]
|
|
everos = "everos.entrypoints.cli.main:app"
|
|
|
|
# ───────────────────────────────────────────────────────────────────────────────
|
|
# Tooling
|
|
# ───────────────────────────────────────────────────────────────────────────────
|
|
|
|
[tool.ruff]
|
|
line-length = 88
|
|
target-version = "py312"
|
|
extend-exclude = ["src_old"]
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "N", "UP", "B", "SIM", "ASYNC"]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
# LoCoMo benchmark embeds LLM prompts (ANSWER_PROMPT / JUDGE_*_PROMPT) and
|
|
# verbose argparse help strings as multi-line string literals. Line breaks
|
|
# would change what the LLM actually sees or noise the --help output, so
|
|
# E501 is silenced for this file only.
|
|
"tests/test_locomo.py" = ["E501"]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
python_files = ["test_*.py"]
|
|
python_functions = ["test_*"]
|
|
asyncio_mode = "auto"
|
|
addopts = "-v --tb=short -m 'not slow and not live_llm'"
|
|
markers = [
|
|
"slow: runs that take >=10s (regardless of dependency); CI default excludes these. Run with `pytest -m slow`.",
|
|
"live_llm: requires real LLM / embedder / reranker credentials from .env; burns tokens. CI default excludes. Run with `pytest -m live_llm`.",
|
|
]
|
|
|
|
[tool.coverage.run]
|
|
source = ["src/everos"]
|
|
branch = true
|
|
omit = ["**/__init__.py"]
|
|
|
|
[tool.importlinter]
|
|
root_packages = ["everos"]
|
|
|
|
[[tool.importlinter.contracts]]
|
|
name = "Layered architecture"
|
|
type = "layers"
|
|
layers = [
|
|
"everos.entrypoints",
|
|
"everos.service",
|
|
"everos.memory",
|
|
"everos.infra",
|
|
]
|
|
|
|
[[tool.importlinter.contracts]]
|
|
name = "Subpackage internals are private"
|
|
type = "forbidden"
|
|
source_modules = ["everos.service", "everos.memory", "everos.entrypoints"]
|
|
# `**` matches any descendant (writer.py, reader.py, sub.foo.bar, ...).
|
|
# Public API must be reached via the subpackage `__init__.py`.
|
|
forbidden_modules = [
|
|
"everos.infra.persistence.markdown.**",
|
|
"everos.infra.persistence.lancedb.**",
|
|
"everos.infra.persistence.sqlite.**",
|
|
]
|
|
# `forbidden` contracts run a *transitive closure* — any path from a
|
|
# source module to a forbidden module fails the check, even when the
|
|
# source only imports the subpackage top-level. The whitelist below
|
|
# carves out **intra-subpackage wiring**: each storage subpackage's
|
|
# own ``__init__.py`` imports its own ``tables`` / ``repos`` / manager
|
|
# children to assemble the public API surface that outer layers reach.
|
|
# These edges are normal Python package wiring, *not* a privacy
|
|
# breach — without these ignores, even a legitimate
|
|
# ``from everos.infra.persistence.sqlite import X`` would be punished
|
|
# because the transitive scan walks one hop further into the package.
|
|
#
|
|
# Direct imports from outer layers into a subpackage internal module
|
|
# (e.g. ``from everos.infra.persistence.sqlite.tables import X`` written
|
|
# in ``service`` or ``entrypoints``) remain blocked — that edge is not
|
|
# in this whitelist.
|
|
ignore_imports = [
|
|
"everos.infra.persistence.sqlite -> everos.infra.persistence.sqlite.tables",
|
|
"everos.infra.persistence.sqlite -> everos.infra.persistence.sqlite.repos",
|
|
"everos.infra.persistence.sqlite -> everos.infra.persistence.sqlite.sqlite_manager",
|
|
"everos.infra.persistence.lancedb -> everos.infra.persistence.lancedb.tables",
|
|
"everos.infra.persistence.lancedb -> everos.infra.persistence.lancedb.repos",
|
|
"everos.infra.persistence.lancedb -> everos.infra.persistence.lancedb.lancedb_manager",
|
|
"everos.infra.persistence.markdown -> everos.infra.persistence.markdown.mds",
|
|
"everos.infra.persistence.markdown -> everos.infra.persistence.markdown.writers",
|
|
"everos.infra.persistence.markdown -> everos.infra.persistence.markdown.readers",
|
|
]
|
|
|
|
[[tool.importlinter.contracts]]
|
|
name = "OME does not depend on memory/service/entrypoints or sibling infra subpackages"
|
|
type = "forbidden"
|
|
source_modules = ["everos.infra.ome"]
|
|
forbidden_modules = [
|
|
"everos.infra.persistence",
|
|
"everos.memory",
|
|
"everos.service",
|
|
"everos.entrypoints",
|
|
]
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"ruff>=0.8.0",
|
|
"pytest>=8.4.0",
|
|
"pytest-asyncio>=1.1.0",
|
|
"pytest-cov>=6.0.0",
|
|
"pytest-rerunfailures>=15.0",
|
|
"import-linter>=2.0",
|
|
"pre-commit>=4.0.0",
|
|
"ipdb>=0.13.13",
|
|
"pyinstrument>=5.0.0",
|
|
]
|