Skip to content

EverOS 1.2.1

Latest

Choose a tag to compare

@dani1005 dani1005 released this 29 Jul 17:21
4256419

[embedding] and [rerank] configuration become optional at runtime — EverOS now boots with only [llm] configured and degrades into three capability tiers, with a new everos cascade backfill command to fill in rows written without an embedding provider.

This release also hardens the cascade queue's retry and delete handling, and fixes a path traversal in knowledge upload — see Security for the affected versions.

Added

  • [embedding] and [rerank] are now soft runtime dependencies — EverOS boots and serves requests with only [llm] configured. A missing or misconfigured embedding / rerank / multimodal provider no longer aborts startup; the accessor logs <provider>_capability_build_failed and reports available=False. Features degrade into three tiers: Tier 1 ([llm] only) → KEYWORD search + add/flush + md writes + cascade sync; Tier 2 (+ [embedding]) → adds VECTOR/HYBRID search + reflection + skill extraction + backfill; Tier 3 (+ [rerank]) → adds AGENTIC search + knowledge write/search. Tier upgrades require a server restart. Downgrades are read-safe: knowledge documents stay readable / renamable / deletable after a Tier-3 → Tier-2 downgrade; only write and search endpoints return 422.
  • everos cascade backfill CLI command — three-phase interactive backfill (vectorsclustersskills, or --phase all) that upgrades Tier-1 rows to Tier-2 once [embedding] is configured. Each phase prints row / token estimates and blocks on y/N; --yes / -y for CI. Exit codes: 0 success, 1 user declined, 2 phase preconditions unmet, 3 server running, 4 completed-with-failures, 130 SIGINT.
  • LanceDB schema v2 — the six business tables (episode, atomic_fact, foresight, agent_case, agent_skill, knowledge_topic) now allow vector NULL, so cascade can write rows without vectors when [embedding] is unavailable and a later backfill fills them in. The migration runs once on first startup under a cross-process memory_root_lock (fcntl.flock), followed by a per-table optimize(cleanup_older_than=timedelta(0)) to physically prune older manifest versions.
  • Startup unbackfilled-rows banner — after the LanceDB lifespan, a sweep emits unbackfilled_memory_rows when rows with vector IS NULL exist, pointing at everos cascade backfill.
  • PyPI Trusted Publishing workflow — tag-triggered .github/workflows/release.yml builds, smoke-tests and uploads via OIDC (no stored token) behind the release environment's manual-approval gate. A version / tag mismatch aborts the publish. Companion /release skill lives under .claude/skills/release/.

Changed

  • ProviderNotConfiguredError → HTTP 422 CAPABILITY_UNAVAILABLE — write / search endpoints that need embed or rerank now return 422 with a section-aware hint (pointing at the everos.toml section, never at EVEROS_* env vars) instead of erroring at startup or 500-ing at request time.
  • GET /health returns a Pydantic HealthResponse model — with typed capabilities and disabled_features fields, so OpenAPI codegen produces real shapes instead of additionalProperties: true.
  • MemoryRoot.default()MemoryRoot.resolve() — renamed to make the precedence walk (--root / EVEROS_ROOT / default) explicit. A default() alias is kept as a backward-compatibility shim that forwards to resolve() and emits a DeprecationWarning; it will be removed in a future major release, so update call sites when convenient.
  • Uncalibrated recall scores moved to their own nameKEYWORD and single-route VECTOR searches now report their top score as recall_top_score_raw; recall_top_score is reserved for the calibrated methods (HYBRID LR sigmoid, AGENTIC cross-encoder), whose values share a comparable [0, 1] scale. Langfuse aggregates scores by name, so the previous single name meant a chart could average an unbounded BM25 score together with a probability. Every recall score also carries metadata = {"method": ..., "calibrated": ...}. Dashboards built on recall_top_score for keyword search need to switch to the new name.
  • Docs and examples now use /api/v2 — README, QUICKSTART, the docs/ reference set, the Langfuse example and everos demo --live all call the canonical /api/v2 prefix. /api/v1 keeps resolving to the same handlers, so nothing breaks, but it is now described as a legacy compatibility alias that may be removed in a future major release rather than a permanent one. New integrations should target /api/v2.
  • cluster_repo.find_cluster_id_for_member now requires (app_id, project_id, owner_id) — reverse-index lookups JOIN Cluster for scope filtering. entry_id is per-owner unique by design, so the reverse index alone could collide across owners writing on the same day.
  • All six cascade handlers register unconditionally — a Tier-3 → Tier-2/1 downgrade no longer strands DELETE / PATCH events. Embed-requiring branches inside each handler body-guard on capability availability at execution time.
  • Interactive TTY log level defaults to WARNING — keeps INFO lines from drowning out the backfill y/N prompts; non-interactive / CI stays at INFO, and --verbose / -v forces INFO.
  • click>=8.1 promoted to a first-class dependency — previously transitive via typer. typer.Abort and click.exceptions.Abort are distinct classes under typer 0.15+, so the interrupt catch in cascade backfill covers both.
  • Test harness pins EVEROS_ROOT to a temp pathconftest.py scrubs every EVEROS_* env var so a developer's ~/.everos/everos.toml cannot make tests accidentally green against a real provider.

Fixed

  • Cascade retry classification and total-retry budget — the worker now catches ExternalServiceError (transient embedding / LLM / rerank failures) and retries inline up to 3 times before marking a row retryable=True. A total budget of 12 attempts across scanner cycles bounds retrying during a prolonged outage, and failed rows with retryable=False on a stable mtime skip auto-retry, so editing and re-saving the md is what grants another attempt.
  • The reconciler no longer overwrites the worker's mark_donepending / processing rows with a stable mtime are no longer re-enqueued. SQLite REAL round-trip precision loss in mtime comparisons is absorbed with a 10 ms tolerance.
  • A file deleted while its modified event was still queued is now processed as a deletion — previously the handler raised FileNotFoundError, which left a stale indexed row and a permanently failed queue item behind.
  • Stuck optimize() escalates to a full index rebuild — after 5 consecutive failures the worker falls back to drop_index + create_index instead of letting compaction and version cleanup stay wedged (workaround for the lance-format/lance#7653 panic path).
  • The embedding provider raises on HTTP 200 with empty data — it previously returned zero-length vectors silently, corrupting search results.
  • Episode extraction retries on malformed LLM output — the synchronous /flush path retries everalgo ValueError (typically a truncated provider response) twice with 1 s / 2 s backoff before surfacing a 500.
  • Filename validation on knowledge upload — NUL bytes and filenames longer than 255 UTF-8 bytes now fail fast with InvalidInputError → HTTP 400 instead of surfacing OS errors as a 500 with a half-written md file.
  • HTML upload no longer takes the UTF-8 fast path — knowledge upload's plaintext short-circuit uses an explicit allowlist (text/plain, text/markdown, text/x-rst, text/x-markdown) plus known extensions; text/html is deliberately excluded so HTML still goes through everalgo's clean_html_for_llm. Prevents a 503 when a Tier-3 user without [multimodal] uploads a markdown doc.
  • Broken table-of-contents links in docs/api.md — the endpoint anchors still pointed at the pre-1.2.0 #post-apiv1… slugs after the headings moved to /api/v2, leaving all five TOC links dead.

Removed

  • README "Star us" section.

Security

  • Knowledge upload path traversal (CWE-22) — the knowledge document upload joined the untrusted multipart filename into _original/ verbatim, so an absolute or ..-laden filename let a caller write attacker-controlled bytes outside the document directory. The filename is now reduced to a safe basename, and the resolved target is asserted to stay inside _original/ before any filesystem touch.

    Affected: every release before 1.1.4, and 1.2.0. Not affected: 1.1.4. Fixed in: 1.2.1. The fix shipped in 1.1.4 but was not present on the branch 1.2.0 was built from, so upgrading 1.1.4 → 1.2.0 reintroduced it.

Upgrade

pip install --upgrade everos   # or: uv sync

On first startup after upgrading, LanceDB runs the schema-v2 migration once — it takes a cross-process lock and optimizes each table afterwards. No manual steps. If rows were written while [embedding] was unavailable, the startup banner will point you at everos cascade backfill to fill in their vectors.

Full changelog: v1.2.0...v1.2.1