docs(api): use /api/v2 in docs and examples, demote v1 to legacy (#370)

1.2.0 introduced /api/v2 as the canonical, cloud-aligned prefix and mounted
every business router twice, but the user-facing entry points (README,
README.zh-CN, QUICKSTART, the docs/ set, the Langfuse example) still taught
/api/v1 — so new users were pointed at the compatibility alias while
docs/api.md already declared v2 canonical.

- Switch every EverOS endpoint reference in docs, examples, and
  `everos demo --live` to /api/v2, plus the matching CLI test expectations.
- Describe /api/v1 as a legacy compatibility alias that may be removed in a
  future major release, rather than a permanent one. Nothing changes at
  runtime: both prefixes still resolve to the same handlers and the
  v1/v2 parity test is untouched.
- Add a short note in README / README.zh-CN / QUICKSTART so existing v1
  integrations know they keep working.
- Fix the five dead endpoint anchors in the docs/api.md table of contents,
  which still pointed at the pre-1.2.0 #post-apiv1... slugs.

Left on v1 deliberately: docs/migration-to-1.0.0.md (historical record),
CHANGELOG history, tests/** (v1 must stay covered), and the
use-cases/claude-code-plugin + openher READMEs, which document a different
cloud API.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dani 2026-07-28 22:52:29 -04:00 committed by GitHub
parent 6c9792ed11
commit 649046b0df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 104 additions and 73 deletions

View File

@ -22,7 +22,7 @@ A good module docstring states:
Example (abbreviated, from `memory/search/manager.py`): Example (abbreviated, from `memory/search/manager.py`):
```python ```python
"""SearchManager — top-level orchestrator for POST /api/v1/memory/search. """SearchManager — top-level orchestrator for POST /api/v2/memory/search.
Hard partition by owner_type: user → episodes (+ profiles), agent → Hard partition by owner_type: user → episodes (+ profiles), agent →
agent_cases + agent_skills. The manager never writes to storage; it only agent_cases + agent_skills. The manager never writes to storage; it only

View File

@ -19,6 +19,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`metadata = {"method": ..., "calibrated": ...}` now, a structured field that `metadata = {"method": ..., "calibrated": ...}` now, a structured field that
can be split on, alongside the existing human-readable comment. Dashboards can be split on, alongside the existing human-readable comment. Dashboards
built on `recall_top_score` for keyword search need to switch to the new name. 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 instead of `/api/v1`. `/api/v1` keeps resolving
to the same handlers, so nothing breaks; 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`.
### Fixed
- **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`, so all five endpoint links in the TOC were dead.
## [1.2.0] - 2026-07-24 ## [1.2.0] - 2026-07-24
@ -26,8 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **`/api/v2` API prefix** — every business endpoint (`memory/*`, `ome/*`, - **`/api/v2` API prefix** — every business endpoint (`memory/*`, `ome/*`,
`knowledge/*`) is now served under `/api/v2`, aligning the open-source API `knowledge/*`) is now served under `/api/v2`, aligning the open-source API
with the EverOS Cloud contract. `/api/v1` is retained as a permanent, with the EverOS Cloud contract. `/api/v1` is retained as a legacy
backward-compatible alias: both prefixes resolve to the same handlers with compatibility alias: both prefixes resolve to the same handlers with
identical request/response contracts, so existing integrations keep working identical request/response contracts, so existing integrations keep working
unchanged. Infrastructure endpoints (`/health`, `/metrics`) stay unversioned. unchanged. Infrastructure endpoints (`/health`, `/metrics`) stay unversioned.
- **Native OpenTelemetry tracing** — memory operations (add / flush, memcell - **Native OpenTelemetry tracing** — memory operations (add / flush, memcell

View File

@ -123,11 +123,17 @@ Send messages to the server — one at a time or in batches. Each batch
belongs to a `session_id`, which represents one conversation thread. belongs to a `session_id`, which represents one conversation thread.
Timestamps are Unix epoch in **milliseconds** (UTC). Timestamps are Unix epoch in **milliseconds** (UTC).
> [!NOTE]
> Business endpoints live under `/api/v2`. The older `/api/v1` prefix still
> resolves to the same handlers so existing integrations keep working, but it
> is a legacy alias that may be removed in a future major release — write new
> code against `/api/v2`.
First, a chat about climbing: First, a chat about climbing:
```bash ```bash
TS=$(($(date +%s)*1000)) TS=$(($(date +%s)*1000))
curl -X POST http://127.0.0.1:8000/api/v1/memory/add \ curl -X POST http://127.0.0.1:8000/api/v2/memory/add \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d "{ -d "{
\"session_id\": \"demo-001\", \"session_id\": \"demo-001\",
@ -143,7 +149,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/memory/add \
Now the topic shifts to work: Now the topic shifts to work:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/add \ curl -X POST http://127.0.0.1:8000/api/v2/memory/add \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d "{ -d "{
\"session_id\": \"demo-001\", \"session_id\": \"demo-001\",
@ -184,7 +190,7 @@ If you want to extract memory without waiting for a topic shift — for
example at the end of a session — call `/flush`: example at the end of a session — call `/flush`:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/flush \ curl -X POST http://127.0.0.1:8000/api/v2/memory/flush \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{"session_id":"demo-001"}' -d '{"session_id":"demo-001"}'
``` ```
@ -202,7 +208,7 @@ This forces extraction of whatever is still in the buffer.
## 6. Search ## 6. Search
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/search \ curl -X POST http://127.0.0.1:8000/api/v2/memory/search \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"user_id": "alice", "user_id": "alice",
@ -277,7 +283,7 @@ edit — no database driver needed.
requests to partition memory spaces inside one server (defaults to requests to partition memory spaces inside one server (defaults to
`"default"` when omitted). `"default"` when omitted).
- **Knowledge base** — upload documents via - **Knowledge base** — upload documents via
`/api/v1/knowledge/documents` and search with hybrid retrieval. See `/api/v2/knowledge/documents` and search with hybrid retrieval. See
[docs/knowledge.md](docs/knowledge.md). [docs/knowledge.md](docs/knowledge.md).
- **Reflection** — offline memory consolidation; enable in `ome.toml`. - **Reflection** — offline memory consolidation; enable in `ome.toml`.
See [docs/reflection.md](docs/reflection.md). See [docs/reflection.md](docs/reflection.md).

View File

@ -195,18 +195,24 @@ everos demo --live
``` ```
Live demo mode connects to the running server and performs the real Live demo mode connects to the running server and performs the real
`/health` -> `/api/v1/memory/add` -> `/api/v1/memory/flush` -> `/health` -> `/api/v2/memory/add` -> `/api/v2/memory/flush` ->
`/api/v1/memory/search` flow before opening the same memory sphere UI. Use `/api/v2/memory/search` flow before opening the same memory sphere UI. Use
`--server-url <url>` if your server is not on `http://127.0.0.1:8000`. `--server-url <url>` if your server is not on `http://127.0.0.1:8000`.
### 5. Try Your First Memory ### 5. Try Your First Memory
> [!NOTE]
> Business endpoints live under `/api/v2`. The older `/api/v1` prefix still
> resolves to the same handlers so existing integrations keep working, but it
> is a legacy alias that may be removed in a future major release — write new
> code against `/api/v2`.
Add a tiny conversation: Add a tiny conversation:
```bash ```bash
TS=$(($(date +%s)*1000)) TS=$(($(date +%s)*1000))
curl -X POST http://127.0.0.1:8000/api/v1/memory/add \ curl -X POST http://127.0.0.1:8000/api/v2/memory/add \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d "{ -d "{
\"session_id\": \"demo-001\", \"session_id\": \"demo-001\",
@ -222,7 +228,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/memory/add \
Force extraction for the local demo: Force extraction for the local demo:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/flush \ curl -X POST http://127.0.0.1:8000/api/v2/memory/flush \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{"session_id":"demo-001","app_id":"default","project_id":"default"}' -d '{"session_id":"demo-001","app_id":"default","project_id":"default"}'
``` ```
@ -230,7 +236,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/memory/flush \
Search it back: Search it back:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/search \ curl -X POST http://127.0.0.1:8000/api/v2/memory/search \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"user_id": "alice", "user_id": "alice",
@ -258,7 +264,7 @@ For annotated responses and the Markdown files EverOS creates, see
### Optional: Ingest Multimodal Files ### Optional: Ingest Multimodal Files
To ingest non-text content (image / pdf / audio / office documents) To ingest non-text content (image / pdf / audio / office documents)
through `/api/v1/memory/add` `content` items, install the optional through `/api/v2/memory/add` `content` items, install the optional
extra: extra:
```bash ```bash

View File

@ -212,18 +212,23 @@ everos demo --live
``` ```
Live demo mode 会连接正在运行的 server并在打开同一个 memory sphere UI Live demo mode 会连接正在运行的 server并在打开同一个 memory sphere UI
之前真实执行 `/health` -> `/api/v1/memory/add` -> `/api/v1/memory/flush` -> 之前真实执行 `/health` -> `/api/v2/memory/add` -> `/api/v2/memory/flush` ->
`/api/v1/memory/search`。如果 server 不在 `http://127.0.0.1:8000`,可以使用 `/api/v2/memory/search`。如果 server 不在 `http://127.0.0.1:8000`,可以使用
`--server-url <url>` `--server-url <url>`
### 5. 试写第一条记忆 ### 5. 试写第一条记忆
> [!NOTE]
> 业务接口位于 `/api/v2`。旧的 `/api/v1` 前缀仍然指向同一批 handler已有集成
> 不会受影响;但它只是兼容用的 legacy alias未来的大版本可能移除 —— 新代码请
> 直接使用 `/api/v2`
添加一个很小的 conversation 添加一个很小的 conversation
```bash ```bash
TS=$(($(date +%s)*1000)) TS=$(($(date +%s)*1000))
curl -X POST http://127.0.0.1:8000/api/v1/memory/add \ curl -X POST http://127.0.0.1:8000/api/v2/memory/add \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d "{ -d "{
\"session_id\": \"demo-001\", \"session_id\": \"demo-001\",
@ -239,7 +244,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/memory/add \
为了本地 demo手动触发一次 extraction 为了本地 demo手动触发一次 extraction
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/flush \ curl -X POST http://127.0.0.1:8000/api/v2/memory/flush \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{"session_id":"demo-001","app_id":"default","project_id":"default"}' -d '{"session_id":"demo-001","app_id":"default","project_id":"default"}'
``` ```
@ -247,7 +252,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/memory/flush \
再把这条记忆搜索回来: 再把这条记忆搜索回来:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/search \ curl -X POST http://127.0.0.1:8000/api/v2/memory/search \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"user_id": "alice", "user_id": "alice",
@ -271,7 +276,7 @@ Markdown 会同步写入,本地索引会在后台追上。
### 可选:摄取多模态文件 ### 可选:摄取多模态文件
如果要通过 `/api/v1/memory/add` 的 `content` items 摄取非文本内容 如果要通过 `/api/v2/memory/add` 的 `content` items 摄取非文本内容
image / pdf / audio / office documents安装可选 extra image / pdf / audio / office documents安装可选 extra
```bash ```bash

View File

@ -26,11 +26,11 @@ business semantics the raw spec does not carry.
- [SearchMethod](#searchmethod) - [SearchMethod](#searchmethod)
- [GetMemoryType](#getmemorytype) - [GetMemoryType](#getmemorytype)
- [Endpoints](#endpoints) - [Endpoints](#endpoints)
- [POST /api/v2/memory/add](#post-apiv1memoryadd) - [POST /api/v2/memory/add](#post-apiv2memoryadd)
- [POST /api/v2/memory/flush](#post-apiv1memoryflush) - [POST /api/v2/memory/flush](#post-apiv2memoryflush)
- [POST /api/v2/memory/search](#post-apiv1memorysearch) - [POST /api/v2/memory/search](#post-apiv2memorysearch)
- [POST /api/v2/memory/get](#post-apiv1memoryget) - [POST /api/v2/memory/get](#post-apiv2memoryget)
- [POST /api/v2/ome/trigger](#post-apiv1ometrigger) - [POST /api/v2/ome/trigger](#post-apiv2ometrigger)
- [Knowledge endpoints](#knowledge-endpoints) - [Knowledge endpoints](#knowledge-endpoints)
- [OpenAPI spec source](#openapi-spec-source) - [OpenAPI spec source](#openapi-spec-source)
@ -52,11 +52,13 @@ but are intentionally outside this reference — they are runtime probes
for deployment, not part of the application contract. for deployment, not part of the application contract.
`/api/v2` is the canonical prefix, aligned with the EverOS Cloud API. Every `/api/v2` is the canonical prefix, aligned with the EverOS Cloud API. Every
business endpoint is **also** served under `/api/v1`, which is retained as a business endpoint is **also** served under `/api/v1`, kept as a legacy
permanent, backward-compatible alias: the two prefixes resolve to the same compatibility alias: the two prefixes resolve to the same handlers with
handlers with identical request/response contracts. Existing `/api/v1` identical request/response contracts, so existing `/api/v1` integrations keep
integrations keep working unchanged; new integrations should use `/api/v2`. working today. The alias carries no long-term guarantee — it may be removed in
Swap the prefix in any example below to reach the same endpoint under v1. a future major release, and it will be announced in the changelog with a
deprecation window before that happens. Write new integrations against
`/api/v2`, and migrate existing ones when convenient.
### Content type ### Content type

View File

@ -38,9 +38,9 @@ Live mode keeps the same TUI, but the memory lifecycle is backed by real
server calls: server calls:
1. `GET /health` 1. `GET /health`
2. `POST /api/v1/memory/add` 2. `POST /api/v2/memory/add`
3. `POST /api/v1/memory/flush` 3. `POST /api/v2/memory/flush`
4. `POST /api/v1/memory/search` 4. `POST /api/v2/memory/search`
If your server is not running on `http://127.0.0.1:8000`, pass If your server is not running on `http://127.0.0.1:8000`, pass
`--server-url <url>`. `--server-url <url>`.

View File

@ -302,7 +302,7 @@ The CLI ([cli.md](cli.md)) is intentionally small:
`rm -rf <memory-root>/.index/lancedb`, restart — the cascade `rm -rf <memory-root>/.index/lancedb`, restart — the cascade
rebuilds from markdown. For an incremental catch-up, use rebuilds from markdown. For an incremental catch-up, use
`everos cascade sync`. `everos cascade sync`.
- **Flush** is an HTTP endpoint (`POST /api/v1/memory/flush`), not a - **Flush** is an HTTP endpoint (`POST /api/v2/memory/flush`), not a
CLI command — it forces *extraction* of the session buffer, which is CLI command — it forces *extraction* of the session buffer, which is
a different thing from forcing *index sync* (`cascade sync`). a different thing from forcing *index sync* (`cascade sync`).

View File

@ -13,14 +13,14 @@ and keeps the original file for reference.
```bash ```bash
# Upload a document # Upload a document
curl -s -X POST http://localhost:8000/api/v1/knowledge/documents \ curl -s -X POST http://localhost:8000/api/v2/knowledge/documents \
-F "file=@my-report.pdf" \ -F "file=@my-report.pdf" \
-F "title=Q1 Engineering Report" \ -F "title=Q1 Engineering Report" \
| jq .data | jq .data
# → { "doc_id": "d_a1b2c3d4e5f6", "category_id": "Technology", "topic_count": 8, ... } # → { "doc_id": "d_a1b2c3d4e5f6", "category_id": "Technology", "topic_count": 8, ... }
# Search # Search
curl -s -X POST http://localhost:8000/api/v1/knowledge/search \ curl -s -X POST http://localhost:8000/api/v2/knowledge/search \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"query": "performance bottleneck", "method": "hybrid"}' \ -d '{"query": "performance bottleneck", "method": "hybrid"}' \
| jq '.data.hits[:3] | .[] | {topic_name, score}' | jq '.data.hits[:3] | .[] | {topic_name, score}'
@ -206,7 +206,7 @@ request to bypass LLM classification.
## API reference ## API reference
All endpoints are under `/api/v1/knowledge`. Responses use the envelope All endpoints are under `/api/v2/knowledge`. Responses use the envelope
format `{"request_id": "...", "data": {...}}`. The `request_id` field is format `{"request_id": "...", "data": {...}}`. The `request_id` field is
omitted from examples below for brevity. omitted from examples below for brevity.
@ -256,7 +256,7 @@ async def upload_document(file_path: str, title: str) -> dict:
async with httpx.AsyncClient(base_url="http://localhost:8000") as client: async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
with open(file_path, "rb") as f: with open(file_path, "rb") as f:
resp = await client.post( resp = await client.post(
"/api/v1/knowledge/documents", "/api/v2/knowledge/documents",
files={"file": (Path(file_path).name, f)}, files={"file": (Path(file_path).name, f)},
data={"title": title}, data={"title": title},
) )
@ -267,7 +267,7 @@ async def upload_document(file_path: str, title: str) -> dict:
**Example — curl**: **Example — curl**:
```bash ```bash
curl -X POST http://localhost:8000/api/v1/knowledge/documents \ curl -X POST http://localhost:8000/api/v2/knowledge/documents \
-F "file=@report.pdf" \ -F "file=@report.pdf" \
-F "title=Quarterly Report" \ -F "title=Quarterly Report" \
-F "category_id=Finance" -F "category_id=Finance"
@ -605,7 +605,7 @@ Storage paths, SQLite rows, and LanceDB indexes are all scoped by
A complete workflow from upload to search: A complete workflow from upload to search:
```bash ```bash
BASE=http://localhost:8000/api/v1/knowledge BASE=http://localhost:8000/api/v2/knowledge
# 1. List available categories # 1. List available categories
curl -s "$BASE/categories" | jq '[.data.categories[] | .category_id]' curl -s "$BASE/categories" | jq '[.data.categories[] | .category_id]'

View File

@ -29,7 +29,7 @@ result is fully retrievable with the same `/search` stack.
## How it works ## How it works
``` ```
POST /api/v1/memory/add POST /api/v2/memory/add
messages[].content = [ ContentItem, ContentItem, ... ] messages[].content = [ ContentItem, ContentItem, ... ]
│ text items → used verbatim │ text items → used verbatim
@ -157,7 +157,7 @@ way — only the parsed text is.
```bash ```bash
TS=$(($(date +%s) * 1000)) # v1 contract: timestamp in ms TS=$(($(date +%s) * 1000)) # v1 contract: timestamp in ms
curl -X POST http://127.0.0.1:8000/api/v1/memory/add \ curl -X POST http://127.0.0.1:8000/api/v2/memory/add \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d "{ -d "{
\"session_id\": \"mm-001\", \"session_id\": \"mm-001\",
@ -244,7 +244,7 @@ HTTP library:
import httpx import httpx
httpx.post( httpx.post(
"http://127.0.0.1:8000/api/v1/memory/add", "http://127.0.0.1:8000/api/v2/memory/add",
json={ json={
"session_id": "mm-001", "session_id": "mm-001",
"messages": [ "messages": [
@ -319,7 +319,7 @@ episodes and memory cells as text turns, every retrieval method works
across multimodal-derived memory unchanged: across multimodal-derived memory unchanged:
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/v1/memory/search \ curl -X POST http://127.0.0.1:8000/api/v2/memory/search \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"user_id": "alice", "user_id": "alice",

View File

@ -221,7 +221,7 @@ dedicated CLI command).
### Triggering a run ### Triggering a run
``` ```
POST /api/v1/ome/trigger POST /api/v2/ome/trigger
Content-Type: application/json Content-Type: application/json
``` ```
@ -249,7 +249,7 @@ import httpx
async def trigger_reflection() -> str: async def trigger_reflection() -> str:
async with httpx.AsyncClient(base_url="http://localhost:8000") as client: async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
resp = await client.post( resp = await client.post(
"/api/v1/ome/trigger", "/api/v2/ome/trigger",
json={"name": "reflect_episodes", "timeout": 120, "force": True}, json={"name": "reflect_episodes", "timeout": 120, "force": True},
) )
resp.raise_for_status() resp.raise_for_status()
@ -259,7 +259,7 @@ async def trigger_reflection() -> str:
**Example — curl**: **Example — curl**:
```bash ```bash
curl -X POST http://localhost:8000/api/v1/ome/trigger \ curl -X POST http://localhost:8000/api/v2/ome/trigger \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"name": "reflect_episodes", "timeout": 120, "force": true}' -d '{"name": "reflect_episodes", "timeout": 120, "force": true}'
``` ```
@ -327,7 +327,7 @@ real deployment, once enabled it runs automatically on schedule, so this step
isn't needed. isn't needed.
```bash ```bash
BASE=http://localhost:8000/api/v1 BASE=http://localhost:8000/api/v2
# 1. With Reflection enabled (set enabled = true in <root>/ome.toml), # 1. With Reflection enabled (set enabled = true in <root>/ome.toml),
# trigger a run by hand here (for the demo; in production it runs on schedule) # trigger a run by hand here (for the demo; in production it runs on schedule)

View File

@ -42,11 +42,11 @@ zero tracing overhead.
| EverOS operation | Langfuse observation | | EverOS operation | Langfuse observation |
| --- | --- | | --- | --- |
| `POST /api/v1/memory/add` · `flush` | span `everos.memory.add` / `everos.memory.flush` | | `POST /api/v2/memory/add` · `flush` | span `everos.memory.add` / `everos.memory.flush` |
| memcell boundary detection (LLM) | generation `everos.memcell.boundary` (model + tokens) | | memcell boundary detection (LLM) | generation `everos.memcell.boundary` (model + tokens) |
| episode extraction (LLM) | generation `everos.extract` | | episode extraction (LLM) | generation `everos.extract` |
| markdown persistence | span `everos.persist.markdown` | | markdown persistence | span `everos.persist.markdown` |
| `POST /api/v1/memory/search` | retriever `everos.memory.search``recall` / `rank` | | `POST /api/v2/memory/search` | retriever `everos.memory.search``recall` / `rank` |
| query / recall embedding | embedding `everos.embedding` | | query / recall embedding | embedding `everos.embedding` |
| OME reflection strategies | agent `everos.ome.<strategy>` (linked to the triggering request's trace) | | OME reflection strategies | agent `everos.ome.<strategy>` (linked to the triggering request's trace) |

View File

@ -39,7 +39,7 @@ def main() -> None:
ts = int(time.time() * 1000) ts = int(time.time() * 1000)
add = _post( add = _post(
"/api/v1/memory/add", "/api/v2/memory/add",
{ {
"session_id": SESSION, "session_id": SESSION,
"messages": [ "messages": [
@ -62,7 +62,7 @@ def main() -> None:
) )
print("add ->", add["data"]) print("add ->", add["data"])
flush = _post("/api/v1/memory/flush", {"session_id": SESSION, "messages": []}) flush = _post("/api/v2/memory/flush", {"session_id": SESSION, "messages": []})
print("flush ->", flush["data"]) print("flush ->", flush["data"])
print("waiting for async index sync ...") print("waiting for async index sync ...")
@ -70,7 +70,7 @@ def main() -> None:
for method in ("keyword", "hybrid", "agentic"): for method in ("keyword", "hybrid", "agentic"):
resp = _post( resp = _post(
"/api/v1/memory/search", "/api/v2/memory/search",
{ {
"user_id": USER, "user_id": USER,
"query": "which vector database did we move to and why", "query": "which vector database did we move to and why",

View File

@ -125,13 +125,13 @@ def create_app(
app.include_router(health.router) app.include_router(health.router)
app.include_router(metrics.router) app.include_router(metrics.router)
# Business API — served under both /api/v2 (cloud-aligned name) and # Business API — served under both /api/v2 (canonical, cloud-aligned name)
# /api/v1 (retained as a permanent backward-compatible alias). The same # and /api/v1 (legacy compatibility alias, removable in a future major).
# router object is mounted twice, so both prefixes resolve to the exact # The same router object is mounted twice, so both prefixes resolve to the
# same handlers; FastAPI's default operationId embeds the path, so the # exact same handlers; FastAPI's default operationId embeds the path, so
# two copies get distinct OpenAPI ids automatically (no collision). # the two copies get distinct OpenAPI ids automatically (no collision).
# v1 and v2 stay identical by construction — see test_api_versioning. # v1 and v2 stay identical by construction — see test_api_versioning.
# v1 first — retained alias, behavior identical. # v1 first — legacy alias, behavior identical.
app.include_router(memorize.router, prefix="/api/v1") app.include_router(memorize.router, prefix="/api/v1")
app.include_router(search.router, prefix="/api/v1") app.include_router(search.router, prefix="/api/v1")
app.include_router(get.router, prefix="/api/v1") app.include_router(get.router, prefix="/api/v1")

View File

@ -160,7 +160,7 @@ def _run_live_demo_flow(
timestamp_ms = int(get_utc_now().timestamp() * 1000) timestamp_ms = int(get_utc_now().timestamp() * 1000)
request( request(
"POST", "POST",
"/api/v1/memory/add", "/api/v2/memory/add",
base_url=base_url, base_url=base_url,
json_body={ json_body={
"session_id": LIVE_DEMO_SESSION_ID, "session_id": LIVE_DEMO_SESSION_ID,
@ -179,7 +179,7 @@ def _run_live_demo_flow(
) )
request( request(
"POST", "POST",
"/api/v1/memory/flush", "/api/v2/memory/flush",
base_url=base_url, base_url=base_url,
json_body={ json_body={
"session_id": LIVE_DEMO_SESSION_ID, "session_id": LIVE_DEMO_SESSION_ID,
@ -199,7 +199,7 @@ def _run_live_demo_flow(
for attempt in range(search_attempts): for attempt in range(search_attempts):
search = request( search = request(
"POST", "POST",
"/api/v1/memory/search", "/api/v2/memory/search",
base_url=base_url, base_url=base_url,
json_body=search_payload, json_body=search_payload,
timeout_seconds=timeout_seconds, timeout_seconds=timeout_seconds,

View File

@ -1,10 +1,10 @@
"""API version aliasing — every business route is served under v1 and v2. """API version aliasing — every business route is served under v1 and v2.
The ``/api/v2`` prefix is the cloud-aligned name; ``/api/v1`` is retained as a The ``/api/v2`` prefix is the canonical, cloud-aligned name; ``/api/v1`` is a
permanent backward-compatible alias pointing to the *same* endpoint. These legacy compatibility alias pointing to the *same* endpoint. These tests are
tests are the completeness guard: they fail if any versioned route is exposed the completeness guard: they fail if any versioned route is exposed under one
under one prefix but not the other, or if the two prefixes ever diverge to prefix but not the other, or if the two prefixes ever diverge to different
different handlers. Infrastructure endpoints (``/health``, ``/metrics``) are handlers. Infrastructure endpoints (``/health``, ``/metrics``) are
deliberately unversioned and must NOT be mirrored. deliberately unversioned and must NOT be mirrored.
Assertions run against ``app.openapi()["paths"]`` the authoritative, Assertions run against ``app.openapi()["paths"]`` the authoritative,

View File

@ -134,11 +134,11 @@ def test_live_demo_flow_calls_server_and_builds_story() -> None:
assert timeout_seconds == 3.0 assert timeout_seconds == 3.0
if path == "/health": if path == "/health":
return {"status": "ok"} return {"status": "ok"}
if path == "/api/v1/memory/add": if path == "/api/v2/memory/add":
return {"message_count": 1, "status": "accumulated"} return {"message_count": 1, "status": "accumulated"}
if path == "/api/v1/memory/flush": if path == "/api/v2/memory/flush":
return {"message_count": 1, "status": "extracted"} return {"message_count": 1, "status": "extracted"}
if path == "/api/v1/memory/search": if path == "/api/v2/memory/search":
return { return {
"data": { "data": {
"episodes": [ "episodes": [
@ -172,9 +172,9 @@ def test_live_demo_flow_calls_server_and_builds_story() -> None:
assert [path for _, path, _ in calls] == [ assert [path for _, path, _ in calls] == [
"/health", "/health",
"/api/v1/memory/add", "/api/v2/memory/add",
"/api/v1/memory/flush", "/api/v2/memory/flush",
"/api/v1/memory/search", "/api/v2/memory/search",
] ]
add_body = calls[1][2] add_body = calls[1][2]
assert add_body is not None assert add_body is not None