Files
EverOS/pyproject.toml
Elliot Chen 518b8eca85 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.
2026-06-06 07:33:17 +08:00

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",
]