Skip to content

Releases: EverMind-AI/EverOS

EverOS 1.3.1

Choose a tag to compare

@github-actions github-actions released this 08 Sep 08:19
b4d5205

One reproducible runner for four long-term-memory benchmarks, plus an
LLM-guided multi-round retrieval method.
LoCoMo, LongMemEval, EverMemBench,
and SubtleMemory now share the same staged ADD → SEARCH → ANSWER → JUDGE
workflow, resume model, metrics, and run manifest. The new
llm_multiround search method iteratively recalls episode blocks, asks a
separately configurable decider to retain core evidence and issue follow-up
queries, and returns a bounded final context without a cross-encoder.

Added

  • LLM-guided multi-round episode retrieval.
    POST /api/v2/memory/search accepts method = "llm_multiround" for user
    memory. Each round independently fuses BM25 and vector candidates for the
    current sub-queries with RRF, then uses the decider to select core evidence
    and identify remaining gaps. Existing search response fields are unchanged;
    decider failures are recorded in structured logs and optional trace dumps.
  • Independent decider configuration. The new [decider] section selects
    the model, endpoint, timeout, request extras, retry policy, and loop tuning.
    Empty connection fields inherit [llm], preserving single-model setups.
  • Unified benchmark harness. One runner and four adapters cover LoCoMo,
    LongMemEval, EverMemBench, and SubtleMemory with explicit dataset configs,
    resumable stage artifacts, deterministic run identities, shared IR metrics,
    decider preflight checks, and trace validation that rejects degraded
    multi-round runs before reporting scores.
  • Cascade snapshot control. POST /api/v1/cascade/quiesce and
    POST /api/v2/cascade/quiesce drain the Markdown-to-index queue and stop the
    cascade subsystem until restart. Startup switches can disable all cascade
    work or only the filesystem watcher for managed read-only workloads.

Changed

  • OME attempts are bounded. One strategy attempt now has a 1,800-second
    default wall-clock timeout and follows the existing retry/dead-letter path on
    timeout. Environment settings can tune concurrency or disable the timeout.
  • SQLite pool saturation fails visibly. Pool size, overflow, checkout
    timeout, recycle, and pre-ping are explicit settings; exhausted pools now
    raise after a bounded wait and emit saturation diagnostics instead of waiting
    indefinitely.
  • Extraction LLM transport is configurable. [llm] now exposes request
    timeout and provider-specific SDK arguments while retaining the previous
    60-second default.

Fixed

  • Permanent embedding request errors no longer retry. HTTP 400, 401, 403,
    404, 413, 414, and 422 responses are classified as rejected input or
    configuration and leave the retry loop; timeouts, 429 responses, and server
    errors remain retryable.
  • EverMemBench owner mapping no longer changes profile extraction. The
    adapter uses one stable synthetic owner per topic for both ingestion and
    search while preserving each real participant's name in message metadata.
    The production Profile cluster/direct extraction paths are unchanged.

Upgrade

pip install --upgrade everos   # or: uv sync
  • No storage migration or index rebuild is required. Existing search methods
    keep their prior behavior unless callers explicitly select
    llm_multiround.
  • Deployments with a healthy OME strategy that legitimately runs for more than
    1,800 seconds must raise EVEROS_OME_RUN_TIMEOUT_SECONDS or set it to 0 /
    off before upgrading.

Full changelog: v1.3.0...v1.3.1

EverOS 1.3.0

Choose a tag to compare

@github-actions github-actions released this 07 Sep 13:17
e8612b9

Milvus as an optional index backend, behind a port that hides which one you
run.
The rebuildable BM25/vector index can now live in a remote Milvus Server
or Zilliz Cloud instead of the embedded LanceDB, selected by one setting and
verified at startup. Nothing about the default installation changes: LanceDB
stays the backend, pymilvus stays an optional extra, and markdown stays the
source of truth — the index is derived either way, so switching backends is a
rebuild, not a migration. Both backends implement the same typed ports, so
cascade, search and /get never branch on physical storage; a filter is a
backend-neutral predicate tree rather than a rendered SQL string, which is what
lets one set of contract tests hold both adapters to the same behaviour. The
vector metric is now cosine everywhere, which corrects an inconsistency
described under Changed.

Added

  • Optional Milvus derived-index backend. Install with
    pip install everos[milvus] and select it with:

    [index]
    backend = "milvus"
    
    [milvus]
    uri = "http://127.0.0.1:19530"   # or a Zilliz Cloud endpoint
    token = ""                        # Zilliz Cloud API key
    db_name = ""
    consistency_level = "Session"     # Strong | Bounded | Session | Eventually
    collection_prefix = "everos"

    Every field binds to an environment variable
    (EVEROS_INDEX__BACKEND, EVEROS_MILVUS__URI, ...). The seven business
    tables are created as <collection_prefix>_<kind>.

    Remote Milvus Server or Zilliz Cloud only. A local database path is
    rejected at startup rather than silently accepted: embedded Milvus Lite is
    not supported, because its pure-Python rewrite degrades a single query to a
    full scan and drops search-time parameters.

    Startup verifies the physical collection field by field — datatype, primary
    key, nullability, vector dimension, and the index metric (dense COSINE,
    BM25 output fields) — so a collection that disagrees with the declared schema
    fails immediately instead of at the first write or search.

Changed

  • Vector search now uses cosine distance on LanceDB too. The generic
    vector path called nearest_to() without a distance type, so it ran on
    LanceDB's L2 default while agent_skill recall and every Milvus query
    already used cosine. All of them are cosine now. Ranking can shift for
    existing deployments
    — the same vectors are scored by a different metric.
    No action is required and no rebuild is involved; the index is unchanged.
  • everalgo's transitive layer is pinned. everalgo-boundary,
    everalgo-core and everalgo-clustering are now direct == dependencies
    matching the versions the test suite resolves. The consumer packages declare
    them as >=0.2.0,<2.0.0, which treats a 0.x line as if only a major bump
    could break compatibility, so a fresh resolution could pick releases the
    suite had never run against. Raise them deliberately, together with a smoke
    run against a PyPI-resolved install — make package installs the built
    wheel with --no-deps, so it cannot catch a resolution break on its own.

Fixed

  • POST /api/v1/memory/add no longer fails on a freshly resolved install.
    everalgo-boundary 0.3.0 added a third required field to the public
    DetectionResult NamedTuple while everalgo-agent-memory 0.4.0 still built
    it with two, so a default (memorize.mode = "agent") install answered
    500 TypeError: DetectionResult.__new__() missing 1 required positional argument: 'should_wait'. Chat mode was unaffected. The pin above resolves
    the compatible pair.
  • Milvus datetime round-trips are exact below the millisecond threshold.
    Timestamps were written in milliseconds but read back through a
    seconds-or-milliseconds heuristic, so any instant before 2001-09-09 either
    landed in the year 30000 or raised ValueError. Physical column reads now
    use an exact inverse.
  • Concurrent update() on the Milvus backend no longer loses writes. The
    read half of the read-modify-write cycle sat outside the write lock, so a
    backfill writing vector and a reflection writing deprecated_by could
    overwrite each other on the same row. Both halves share one lock, and the
    silent 10,000-row truncation on that path is gone.
  • Milvus queries stay inside the engine's result window. Row scans and
    search topK are bounded by the 16,384-row ceiling instead of requesting
    more and failing.

Upgrade

pip install --upgrade everos   # or: uv sync

Full changelog: v1.2.3...v1.3.0

EverOS 1.2.3

Choose a tag to compare

@github-actions github-actions released this 07 Aug 11:53
48fc908

Background maintenance that fails loudly instead of quietly. A soak run on
1.2.2 found a table that had stopped reclaiming disk for 100 minutes while
/health stayed green — nothing had failed, a call had simply never returned,
and every signal was built from failure counters. Auditing for that shape turned
up six more places it could happen: reads with no deadline (which stop the whole
md to LanceDB projection, not just one table), background loops that die
permanently on one exception with no log at all, an alert counter reset by the
remediation it triggers. All of them are now bounded, and a stall that does
happen names the table it happened to. Alongside that, agent-skill extraction is
rescued from a retry-then-dead-letter loop, keyword search no longer returns 500
during an index rebuild, and the maintenance cadences moved into settings.

Fixed

  • Agent skill extraction is no longer stuck in a retry-then-dead-letter
    loop.
    Target case data now travels on SkillClusterUpdated and existing
    skills for the cluster are read from markdown (strong-consistency), so the
    strategy never races cascade indexing. Prior to this fix, running a fresh
    agent trajectory produced zero SKILL.md files — .skills/ did not exist.
    The related stale-index clobber is fully closed only for clusters at or
    below MAX_SKILLS_IN_PROMPT (10).
    Above it, markdown still supplies the
    candidate set but LanceDB orders it, and the skill a lagging index omits is
    by definition the one written most recently — the one most likely to need
    update — so it can be ranked out of the prompt and re-added instead. The
    window is narrow (it needs a cluster over 10 skills and an index that has
    not caught up) and the consequence is the pre-existing full-replace, not a
    new failure mode.
  • POST /api/v2/ome/trigger no longer masks strategy state. The status
    field now distinguishes not_dispatched (all dispatch gates rejected the
    strategy — usually a missing "force": true) from ok (dispatched and
    settled). The new runs field surfaces dead-lettered strategy runs that
    were previously invisible to the caller. If your client matches
    status exhaustively (Python Literal, TypeScript union), add a
    not_dispatched branch.
  • Agentic search on agent memory now uses the skill-shaped rerank
    passage.
    The cross-encoder previously saw only the raw description
    field instead of the name + description + skill instruction triple that
    the HYBRID lane uses. A skill with empty description (a legal everalgo
    output — see everalgo/agent_memory/skill_ops.py:294) no longer causes
    HTTP 500 during the LLM sufficiency check.
  • OME strategy retries now back off between attempts. A retry-class error
    (e.g. waiting on eventually-consistent state) previously exhausted its
    max_retries budget in milliseconds; the loop now sleeps
    min(base * 2**(attempt-1), cap) plus up to jitter seconds
    (defaults: 1s base / 10s cap / 0.5s jitter — code-only defaults,
    not currently exposed via everos.toml or ome.toml). engine_sem is
    now held per attempt rather than across the whole retry chain
    , so the
    backoff sleep does not occupy a concurrency slot. The cap bounds
    concurrent strategy work — LLM calls, embeddings, storage IO — and a
    coroutine waiting to retry consumes none of it; holding the slot would
    have turned a partial outage into a total stall, since enough
    simultaneously-failing runs park every one of the
    max_concurrent_runs slots in asyncio.sleep and starve strategies that
    would have succeeded. Backpressure on failing work is intended;
    backpressure on everything else is not.
  • Path-traversal hardening for LLM-generated agent-skill names (CWE-22).
    AgentSkillFrontmatter.name comes straight from LLM output
    (extract_agent_skill) and was concatenated unsanitized into the
    skills/skill_<name>/ directory segment on both the write and read
    paths; given a sufficiently long ../ prefix, the write target could
    escape the memory root. This is the same class of defect previously
    fixed for knowledge-upload titles/categories (see knowledge_writer.py
    in an earlier 1.2.x). The sanitizer is now a single shared helper
    (everos.core.persistence.markdown.sanitize_dirname) used by both
    KnowledgeWriter and the new SkillPathMixin.skill_dir_name() /
    sanitize_skill_name(), instead of two independently maintained copies.
    extract_agent_skill now sanitizes the LLM-emitted name before
    constructing AgentSkillFrontmatter, so AgentSkillFrontmatter.name
    and the LanceDB agent_skill primary key now hold the sanitized name

    (spaces become _, characters outside [\w\-.] are dropped, capped at
    50 chars), not the raw LLM output — a user-visible change for anything
    that reads a skill's name field expecting the verbatim LLM string.
    AgentSkillFrontmatter.name also gained a validator rejecting a name
    containing a path separator, or being exactly .., so a hand-edited
    SKILL.md that bypasses the writer's sanitization is caught on read
    rather than silently relocated (the substring form, e.g. a name that
    merely contains .., is deliberately allowed — sanitized output can
    legitimately contain runs of literal dots). sanitize_dirname itself
    falls back (not just on an empty result, but also on . or ..) so a
    short input that is itself a sanitizer fixpoint — e.g. "../" sanitizes
    to ".." verbatim without this fallback — cannot resolve to the same
    directory or its parent; this closes both the agent-skill case and an
    equivalent one-level escape on the knowledge-upload path, which has no
    skill_-style prefix protecting its sanitized segment. No data
    migration is needed for agent skills
    : extraction has never
    successfully produced a SKILL.md before this release (see the
    cascade-lag fix above), so there is no legacy skill corpus whose
    directory names would change. Knowledge documents do have a
    pre-existing corpus
    , and two inputs resolve to a different directory
    than before: a decomposed (NFD) topic or category now keeps its
    combining marks ("Résumé" no longer degrades to "Resume") because
    the shared helper NFC-normalizes first, and a topic or category of
    exactly . or .. now falls back instead of resolving onto the
    parent directory. Precomposed input — including CJK — is unaffected;
    the character class is unchanged from the previous private copy.
    Sanitizing is lossy: skills whose raw names
    differ only in characters the sanitizer drops or replaces (e.g.
    "fix django" vs. "fix_django") now share one SKILL.md, and so do
    names differing only in a combining mark regardless of script (e.g.
    Devanagari "किताब" vs. "कताब" — a combining mark alone is not \w
    and is stripped either way; same for Thai tone marks, Hebrew niqqud,
    Arabic harakat). The later write wins — the earlier skill's
    source_case_ids, maturity_score, and body are silently lost, not
    merged. Case is not folded, so "Fix Django" and "fix django" stay
    two distinct sanitized names — two LanceDB rows, but one directory on a
    case-insensitive filesystem (macOS APFS and Windows NTFS defaults),
    where the index then advertises a name whose content was overwritten.
    This is accepted for now rather than mitigated: detecting a collision
    and raising would reintroduce the dead-letter DoS the sanitizer was
    built to avoid, and a disambiguating suffix — the workable option —
    needs a collision probe plus a case-folding rule, so it is deferred to
    a deliberate pass rather than added here.
  • A renamed skill no longer leaves an orphan directory that pollutes the
    next extraction.
    everalgo treats a name change as a first-class update
    (skill_ops._apply_update preserves prior.id while swapping the name),
    so the emitted skill was written to a new skill_<new_name>/ while the
    old directory survived carrying the same cluster_id. Because existing
    skills are now read from markdown rather than LanceDB, that orphan did
    not merely sit on disk — it came back in the next run's
    existing_relevant_skills as a duplicate of a skill the LLM had already
    renamed, feeding exactly the add-instead-of-update full-replace
    clobber this release set out to close, once more per rename. The old
    directory is now reaped after the new one is written, keyed on the
    skill's id (the only thing that survives a rename; a fresh add mints
    a uuid and can never match). A prior name that another skill in the same
    batch just claimed is never deleted.
  • extract_agent_skill retire ops are documented as unimplemented rather
    than silently mispersisted.
    AgentSkillExtractor.aextract returns a
    flat list with no op discriminator, so a retirement arrives as an
    ordinary skill with confidence < retire_confidence and was written back
    like any other — staying in markdown, in the next prompt, and in search.
    The behaviour is unchanged; the module docstring no longer claims retire
    is handled. Honouring it is a design decision (delete the directory, or
    add a retired flag that the enumeration, cascade, and search all
    filter on) deferred to its own change.
  • reference_name and script_filename are sanitized. Both are
    appended after the skill_<name> segment, so skill_dir_name never
    covered them; they now go through the same sanitize_dirname primitive
    on both the reader and the writer. No caller in src/ reaches them
    today, so nothing was exploitable — this closes the gap before
    progressive disclosure wires them up.
  • A single unparseable SKILL.md no longer disables skill extraction
    for its whole cluster.
    AgentSkillReader.list_by_cluster propagated
    any frontmatter ValidationError, which...
Read more

EverOS 1.2.2

Choose a tag to compare

@gloryfromca gloryfromca released this 05 Aug 05:35
84554eb

Storage-layer reliability. LanceDB maintenance is split into lock-free compaction and write-locked reclamation, fixing unbounded index growth — the previous bundled call issued a Rewrite that concurrent writes kept preempting, so version cleanup lost the race indefinitely (a soak run measured 16 successes against 547 conflicts over 21h, with the index directory growing to the disk guardrail). Every write-lock critical section is now bounded by a deadline that covers lock acquisition as well as the body, so no operation can wedge a table permanently and silently.

This release also adds the operational surface to see those faults: a cascade readiness block on GET /health with per-kind prune staleness, and everos cascade rebuild as the supported recovery from a drifted or corrupt index. Verified by nine soak / concurrency / fault-injection runs (~120h).

Added

  • GET /health now carries a cascade readiness blockhealthy, human-readable reasons, and the counters behind them (pending,failed_permanent, failed_retryable, drain_consecutive_failures, unrecoverable_total, optimize_failure_streak, prune_stale_seconds). null when the app runs without the cascade lifespan.
    Alert oncascade.healthy: it flips false only on operational faults — drain loop failing (≥3 in a row), index maintenance wedged (≥5), or version cleanup stalled on some table (≥3 missed 300s beats, and reasons names the table). failed_permanent is a data-quality backlog awaiting cascade fix and deliberately does not flip healthy, otherwise the signal sits red until a human edits markdown. The HTTP status stays 200 even when the block says unhealthy — it is a liveness signal, and a degraded projection must not trigger a container restart. If the probe itself fails (locked / full SQLite), the block returns healthy=false with a cascade health probe failed: … reason and zeroed counters — read zeros next to that reason as "unknown", not "clean".

  • everos cascade rebuild CLI command — drops every business LanceDB table, clears the cascade queue, and re-indexes all markdown from scratch. The supported recovery from a drifted or corrupt index: unlike deleting the index directory, it re-enqueues every file (a bare rm -rf leaves the queue marked done, so nothing re-indexes and the index comes back empty), and unlike deleting .index/ it preserves SQLite state that markdown cannot rebuild — notably unprocessed_buffer. Requires the server to be stopped: it refuses to start (exit code 3) while a server holds the OME lock, because a live daemon keeps writing through cached table handles to the dropped dataset. --yes/-y for non-interactive use; Ctrl-C exits 130 and the re-index resumes on the next run or server start.

  • Startup schema verification now detects column type drift, not just missing / extra columns. Catches the class of corruption behind #337 — an episode.subject_vector left as string by an older build while the schema declares a 1024-d fixed_size_list — which a name-only check waved through and which then failed deep inside merge_insert with an opaque LanceError(IO). The error now points at everos cascade rebuild.

Changed

  • LanceDB maintenance is split into compaction and reclamation. optimize() is lock-free compaction; the new prune() runs cleanup_older_than under the per-table write lock. Fixes unbounded index growth: the previous bundled call issued a Rewrite that concurrent writes kept preempting, so version cleanup lost the race indefinitely (a soak run measured 16 successes against 547 conflicts over 21h, with the index directory growing to the disk guardrail). Reclamation now completes on every beat, at the cost of a brief same-table write stall (measured ~40ms). Retention is decoupled from cadence: files older than 60s are eligible, reclaimed on a 300s beat.

  • Every write-lock critical section is now bounded. All seven operations (add / upsert / update / delete / delete_by_md_path / prune /rebuild_indexes) run under a deadline that covers lock acquisition as well as the body, so no code path can wait for the lock — or hold it — indefinitely. Budgets are sized from measured durations (row writes are 2–25ms, worst observed 63ms → 15s; index rebuild → 300s; prune → 60s). Expiry raises the retryable VectorStoreBusyError, so the cascade worker retries the row instead of marking it permanently failed. Without this, one operation stuck outside the old narrow timeout wedged a table permanently: every writer blocked on acquire, and the maintenance scheduler skipped a kind whose task never finished, so that table stopped reclaiming versions altogether (observed: 150 versions retained, disk 11x live size, with nothing logged because nothing failed).

  • Benign LanceDB commit conflicts no longer count as failures. A lost optimistic-concurrency race logs at debug on either maintenance beat. The heavy beat needs this too: its write lock is in-process only, so a second process (cascade sync, cascade backfill) can preempt its commit. Counting those triggered spurious fallback index rebuilds, which drop every index before recreating them — and if the rebuild also lost the race, the table sat without an FTS index and every search on that kind returned 500 until the next 12h sweep.

  • A query vector whose width disagrees with the embedding provider's declared dim now fails immediately with CONFIGURATION_ERROR instead of reaching LanceDB. It previously surfaced as an opaque ValueError after the query was built — 13–14s per request, as an unhandled 500.

  • Exception logging no longer renders frame locals. structlog's default traceback formatter (show_locals=True, up to 100 frames) rendered one unhandled exception on an async stack into 6423 log lines — 85MB of logs across 11 exceptions in one soak run — at ~290ms of synchronous CPU each, and risked printing request payloads into logs. Now locals-off and capped at 15 frames: the same traceback is 103 lines.

  • cascade backfill reclaims through the daemon's retention window rather than at zero age, so it cannot delete files out from under an in-flight /search in the server process.

  • lancedb pinned to >=0.34.0,<0.35.0. 0.35 embeds lance-rust v9; 0.34.0 is the version validated under sustained churn. Environments installing from uv.lock are unaffected (already 0.34.0). Never widen the floor below 0.34 — older lance cannot read v8 data.

Fixed

  • Maintenance deadlines now cover the whole call, not just the critical section. Resolving a table handle sat outside the timeout, so a hang there never returned — and because the scheduler runs one maintenance task per kind and skips a kind whose task is in flight, that table stopped being maintained permanently and silently (a soak run caught one table 13 minutes without a reclaim, retained versions climbing, while its siblings reclaimed normally and nothing was logged because nothing failed). Handle resolution moved inside the deadline for all seven locked operations, the lock-free compaction beat got its own deadline, and the scheduler adds a last-resort 180s bound on the whole call. The per-kind staleness alert added in this release is what surfaced it.

  • AGENTIC search crashed on agent memory (agent_case / agent_skill) — candidate metadata now satisfies the everalgo _format_docs contract, removing a TypeError in the sufficiency / multi-query steps.

  • Per-kind version-cleanup staleness is no longer masked. The health signal reported time since the newest successful prune across all kinds, so on a multi-kind deployment one kind whose cleanup died was hidden by the others pruning on schedule. It now reports the worst kind and names it.

  • cascade backfill silently skipped compaction and reclamation — it still called the removed optimize(cleanup_older_than=…) signature, and the resulting TypeError was swallowed by a best-effort except, so the disk growth this release fixes came back after every backfill.

  • Empty _indices/<uuid>/ husks are removed after cleanup (a soak run accumulated 13061 directories, 98% of them empty), which bloated inode usage and slowed directory scans.

Docs

  • Rewrote the cascade runbook's recovery paths: the /health cascade block and its alert thresholds, cascade rebuild (including the stop-the-server requirement), why rm -rf .index/lancedb yields an empty index, and whyrm -rf .index loses un-extracted buffered messages.

Upgrade

pip install --upgrade everos   # or: uv sync

No manual migration. Two things to expect on the first startup after upgrading:

  • Startup schema verification now checks column types, not just names. An index left drifted by an older build — the #337 class of corruption, where episode.subject_vector stayed a string — is now reported at startup instead of failing later inside merge_insert with an opaque LanceError(IO). Recovery is everos cascade rebuild, which requires the server to be stopped.
  • An index that already grew unbounded reclaims itself. The new prune() beat runs every 300s over files older than 60s, so the disk a wedged version cleanup was holding comes back without intervention.

lancedb is pinned to >=0.34.0,<0.35.0. Environments installing from uv.lock are already on 0.34.0 and unaffected; never widen the floor below 0.34, since older lance cannot read v8 data.

Full changelog: v1.2.1...v1.2.2

EverOS 1.2.1

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

EverOS 1.2.0

Choose a tag to compare

@gloryfromca gloryfromca released this 24 Jul 10:22
64e0fdc

EverOS 1.2.0

Minor release adding the /api/v2 API prefix and native OpenTelemetry tracing.

Added

  • /api/v2 API prefix — every business endpoint (memory/*, ome/*, knowledge/*) is now served under /api/v2, aligning the open-source API with the EverOS Cloud contract. /api/v1 is retained as a permanent, backward-compatible alias: both prefixes resolve to the same handlers with identical contracts, so existing integrations keep working unchanged.
  • Native OpenTelemetry tracing — memory operations (add/flush, memcell boundary, episode extraction, search, and OME reflection) export to any OTLP backend (e.g. Langfuse) as nested traces carrying LLM/embedding token usage, per-request correlation, and recall-quality scores. Off by default; enable via [observability] with the optional otel extra. Content capture (query / extracted memory) is opt-in and redaction-aware.

Upgrade

pip install --upgrade everos

Or update the project environment with uv sync.

Full changelog: v1.1.4...v1.2.0

EverOS 1.1.4

Choose a tag to compare

@cyfyifanchen cyfyifanchen released this 23 Jul 05:22
02dae05

Note on the published package: the everos==1.1.4 release on PyPI was built from a separate internal release lane and contains fixes that are not in this tag's source — including a knowledge-upload path-traversal fix (CWE-22). See the 1.1.4 section of CHANGELOG.md for the full list, and the v1.2.1 notes for the affected-version range.

EverOS 1.1.4

Patch release adding Langfuse observability and fixing cascade file deletion races.

Added

  • Langfuse OpenTelemetry integration example for tracing add, flush and extraction, search, and reflection operations.

Fixed

  • Process a queued modified event as a deletion when the source file disappears, preventing stale indexed rows and permanently failed queue items.
  • Limit synthetic Langfuse child spans to responses with stage details so live-server traces use real telemetry.

Upgrade

pip install --upgrade everos

Or update the project environment with uv sync.

Full changelog: v1.1.3...v1.1.4

EverOS 1.1.3

Choose a tag to compare

@dani1005 dani1005 released this 20 Jul 22:27
45656d3

EverOS 1.1.3

Fixes unbounded index growth from a LanceDB FTS regression.

Fixed

  • LanceDB FTS with_position crashes optimize(), bloating the index
    until the disk fills.
    On lancedb ≥ 0.32, FTS indexes built with
    with_position=True crash lance's optimize() / compaction when it merges
    an unindexed tail (Max offset exceeds length of values — an upstream
    lance-encoding v4 → v6 regression, reported at
    lance-format/lance#7653).
    Because the crash aborted optimize() including version cleanup, the
    index directory grew without bound.

    The fix:

    • FTS now defaults to with_position=False — lossless for EverOS, since
      recall uses OR-mode BM25 and never runs phrase queries.
    • A marker-guarded startup migration rebuilds pre-fix indexes and reclaims
      the orphaned fragments automatically.
    • Consecutive optimize() failures now escalate warning → error instead
      of being swallowed silently.

Upgrade

pip install --upgrade everos   # or: uv sync

Existing installations are migrated automatically on next startup — the
pre-fix index is rebuilt once and the leaked fragments are reclaimed. No
manual steps required.

Full changelog: v1.1.2...v1.1.3

EverOS 1.1.2

Choose a tag to compare

@dani1005 dani1005 released this 20 Jul 22:27
56ee9c8

EverOS 1.1.2

Fixes agent-track search.

Fixed

  • Agent-track search broken by deprecated_by IS NULL filter.
    compile_filters() unconditionally appended a deprecated_by IS NULL
    clause to every LanceDB query, but only the episode and atomic_fact
    tables carry that column. As a result, agent-track search (agent_case,
    agent_skill) failed on every method. The clause is now applied
    conditionally, only when owner_type == "user".

Upgrade

pip install --upgrade everos   # or: uv sync

No configuration or data-migration changes required.

Full changelog: v1.1.1...v1.1.2

EverOS 1.1.1

Choose a tag to compare

@cyfyifanchen cyfyifanchen released this 07 Jul 10:33
15efd11

EverOS 1.1.1

EverOS 1.1.1 focuses on benchmark reproducibility, search quality, and keeping the public GitHub release aligned with the 1.1.1 source package while preserving GitHub-only project assets.

Highlights

  • Added the LoCoMo benchmark runner under benchmarks/, including TOML configuration, an environment template, staged ingestion/search/answer/judge execution, result artifacts, and benchmark documentation to make metric reproduction easier.
  • Improved hybrid search with heap-driven lazy expansion and global top-N competition. The 1.1.1 benchmark package reports stable LoCoMo targets around 91% for hybrid search and 93% for agentic search.
  • Synced the 1.1.1 source package while preserving GitHub-only workflows, templates, contributor-doc checks, public release support, use-case material, and the existing English README.md structure.
  • Expanded CI coverage to Python 3.12 and 3.13, refreshed package metadata, and kept docs/OpenAPI checks in the release flow.
  • Updated quickstart, benchmark, Chinese README, docs index, and cross-document references for the current setup and benchmark workflow.

Fixes

  • Fixed concurrent Knowledge cascade upserts by switching to an atomic INSERT ... ON CONFLICT DO UPDATE path.
  • Kept the OpenAPI application version in sync with package metadata instead of a hardcoded version.
  • Fixed profile middleware so inner handler exceptions are re-raised instead of being swallowed.
  • Reduced unnecessary LanceDB optimize() I/O by throttling cascade optimize calls.

Compatibility Notes

  • Existing EverOS demo TUI and live demo changes remain preserved.
  • Existing DashScope rerank provider support remains preserved.
  • The English README.md keeps the GitHub main structure; release-package README changes were not applied to the default README.
  • Existing local-first file:// URI handling remains allow-any by default. For server deployments, configure FILE_URI_ALLOW_DIRS explicitly to constrain readable file paths.
  • GitLab/internal-only artifacts such as .gitlab/, .gitlab-ci.yml, .vscode/, .claude/skills/release/SKILL.md, and evaluation/ are not part of the GitHub release.

Upgrade Notes

  • Run uv sync --frozen against the updated uv.lock.
  • Use benchmarks/README.md and benchmarks/config.toml as the entrypoint for LoCoMo benchmark reproduction.
  • Review updated config templates in src/everos/config/default.toml, src/everos/config/default_ome.toml, and src/everos/templates/env.template.
  • Review CHANGELOG.md for the complete 1.1.1 changelog.

Verification

This release was checked with:

  • make docs-check
  • uv lock --check
  • make lint
  • uv run pytest tests/unit/test_scripts/test_check_github_contributor_docs.py -q
  • PR #327 full CI: unit tests, integration tests, lint, links, package build, commit-message check, and PR-title check on Python 3.12 and 3.13