兼容新版 EverOS memory API
This commit is contained in:
69
README.md
69
README.md
@ -66,7 +66,7 @@ Memory Gateway 需要先连上两个后端服务。默认本地端口约定:
|
|||||||
| 服务 | 默认地址 | 作用 |
|
| 服务 | 默认地址 | 作用 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| OpenViking | `http://127.0.0.1:1933` | session、archive、long-term memory、resources、semantic search |
|
| OpenViking | `http://127.0.0.1:1933` | session、archive、long-term memory、resources、semantic search |
|
||||||
| EverOS EverCore | `http://127.0.0.1:1995` | profile、episodic memory、recall |
|
| EverOS | `http://127.0.0.1:1995` | profile、episodic memory、recall |
|
||||||
| Memory Gateway | `http://127.0.0.1:1934` | 对业务方暴露统一 `/memory-system` API |
|
| Memory Gateway | `http://127.0.0.1:1934` | 对业务方暴露统一 `/memory-system` API |
|
||||||
|
|
||||||
### 安装 OpenViking
|
### 安装 OpenViking
|
||||||
@ -82,23 +82,28 @@ pip install openviking --upgrade --force-reinstall
|
|||||||
|
|
||||||
如果本机已经有 OpenViking 源码或已安装的 `openviking-server`,可以跳过安装,直接确认 `openviking-server --help` 可用。
|
如果本机已经有 OpenViking 源码或已安装的 `openviking-server`,可以跳过安装,直接确认 `openviking-server --help` 可用。
|
||||||
|
|
||||||
### 安装 EverOS / EverCore
|
### 安装 EverOS
|
||||||
|
|
||||||
Memory Gateway 使用 EverOS 里的 EverCore HTTP 服务。按 [EverOS / EverCore Quick Start](https://github.com/EverMind-AI/EverOS#evercore):
|
Memory Gateway 使用当前 EverOS HTTP 服务:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/EverMind-AI/EverOS.git /Users/tom/projects/EverOS
|
git clone https://github.com/EverMind-AI/EverOS.git /Users/tom/projects/EverOS
|
||||||
cd /Users/tom/projects/EverOS/methods/EverCore
|
cd /Users/tom/projects/EverOS
|
||||||
|
|
||||||
# 需要 Docker 和 Python 3.12。
|
# 编辑 .env,至少配置 LLM、multimodal、embedding、rerank 的 model/api_key/base_url。
|
||||||
cp /Users/tom/projects/memory-gateway/everos.env.example .env
|
uv sync --extra dev
|
||||||
# 编辑 .env,至少填入实际可用的 LLM_API_KEY 和 VECTORIZE_API_KEY。
|
|
||||||
|
|
||||||
docker compose up -d
|
|
||||||
uv sync
|
|
||||||
```
|
```
|
||||||
|
|
||||||
如果 EverOS 已经在本机存在,只需要进入 `methods/EverCore` 并补齐 `.env`。
|
如果 EverOS 已经在本机存在,只需要进入 EverOS 根目录并补齐 `.env`。
|
||||||
|
|
||||||
|
当前 Memory Gateway 兼容的 EverOS v1 记忆接口是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
POST /api/v1/memory/add
|
||||||
|
POST /api/v1/memory/flush
|
||||||
|
POST /api/v1/memory/search
|
||||||
|
POST /api/v1/memory/get
|
||||||
|
```
|
||||||
|
|
||||||
### 安装 Memory Gateway
|
### 安装 Memory Gateway
|
||||||
|
|
||||||
@ -149,16 +154,25 @@ openviking-server doctor
|
|||||||
|
|
||||||
`root_api_key` 只放在 OpenViking 和 Memory Gateway 的服务端配置里。业务调用方不要传 root key。
|
`root_api_key` 只放在 OpenViking 和 Memory Gateway 的服务端配置里。业务调用方不要传 root key。
|
||||||
|
|
||||||
### EverOS / EverCore 配置
|
### EverOS 配置
|
||||||
|
|
||||||
Memory Gateway 仓库内也提供 EverOS / EverCore 的 `.env` 模板。复制到 EverCore 目录:
|
在 EverOS 根目录创建或编辑 `.env`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/tom/projects/EverOS/methods/EverCore
|
cd /Users/tom/projects/EverOS
|
||||||
cp /Users/tom/projects/memory-gateway/everos.env.example .env
|
$EDITOR .env
|
||||||
```
|
```
|
||||||
|
|
||||||
然后编辑 `.env`,至少填入 `LLM_API_KEY`、`LLM_MODEL`、`VECTORIZE_API_KEY`、`EMBEDDING_MODEL` 和 `RERANK_MODEL`。Docker 依赖地址默认使用模板里的本地 compose 端口;如果改过 EverCore 的 compose 配置,需要同步修改 `.env`。
|
至少需要配置:
|
||||||
|
|
||||||
|
```text
|
||||||
|
EVEROS_LLM__MODEL / EVEROS_LLM__API_KEY / EVEROS_LLM__BASE_URL
|
||||||
|
EVEROS_MULTIMODAL__MODEL / EVEROS_MULTIMODAL__API_KEY / EVEROS_MULTIMODAL__BASE_URL
|
||||||
|
EVEROS_EMBEDDING__MODEL / EVEROS_EMBEDDING__API_KEY / EVEROS_EMBEDDING__BASE_URL
|
||||||
|
EVEROS_RERANK__MODEL / EVEROS_RERANK__API_KEY / EVEROS_RERANK__BASE_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
大模型较慢时,建议同时设置 `EVEROS_LLM__TIMEOUT_SECONDS` 和 `EVEROS_MULTIMODAL__TIMEOUT_SECONDS`。
|
||||||
|
|
||||||
### Memory Gateway 配置
|
### Memory Gateway 配置
|
||||||
|
|
||||||
@ -220,12 +234,11 @@ openviking-server --config ~/.openviking/ov.conf
|
|||||||
|
|
||||||
如果使用 Docker 方式运行 OpenViking,确认对 Memory Gateway 暴露的是 `1933` 端口,避免和 Memory Gateway 的 `1934` 端口冲突。
|
如果使用 Docker 方式运行 OpenViking,确认对 Memory Gateway 暴露的是 `1933` 端口,避免和 Memory Gateway 的 `1934` 端口冲突。
|
||||||
|
|
||||||
终端 2:启动 EverOS / EverCore。
|
终端 2:启动 EverOS。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/tom/projects/EverOS/methods/EverCore
|
cd /Users/tom/projects/EverOS
|
||||||
docker compose up -d
|
uv run everos server start
|
||||||
uv run python src/run.py --port 1995
|
|
||||||
```
|
```
|
||||||
|
|
||||||
终端 3:启动 Memory Gateway。
|
终端 3:启动 Memory Gateway。
|
||||||
@ -335,7 +348,7 @@ curl -sS -X POST "$API/users" \
|
|||||||
|
|
||||||
### `POST /messages`
|
### `POST /messages`
|
||||||
|
|
||||||
写入用户消息和/或助手消息。至少要传 `user_message` 或 `assistant_message` 其中一个。网关会先确保 OpenViking user/session 存在,再把消息写入 OpenViking session,同时写入 EverOS。
|
写入用户消息和/或助手消息。至少要传 `user_message` 或 `assistant_message` 其中一个。网关会先确保 OpenViking user/session 存在,再把消息写入 OpenViking session,同时调用 EverOS `POST /api/v1/memory/add`。
|
||||||
|
|
||||||
请求体:
|
请求体:
|
||||||
|
|
||||||
@ -367,7 +380,7 @@ curl -sS -X POST "$API/messages" \
|
|||||||
|
|
||||||
### `POST /sessions/{session_id}/commit`
|
### `POST /sessions/{session_id}/commit`
|
||||||
|
|
||||||
提交会话。OpenViking 会归档 session 并异步抽取长期记忆,通常会返回 `task_id`;EverOS 会 flush 当前 session。
|
提交会话。OpenViking 会归档 session 并异步抽取长期记忆,通常会返回 `task_id`;EverOS 会调用 `POST /api/v1/memory/flush` flush 当前 session。
|
||||||
|
|
||||||
路径参数:
|
路径参数:
|
||||||
|
|
||||||
@ -419,7 +432,7 @@ GET /api/v1/sessions/{session_id}/context
|
|||||||
X-API-Key: <user_key>
|
X-API-Key: <user_key>
|
||||||
```
|
```
|
||||||
|
|
||||||
同时用同一个 `query` 调用 EverOS `/api/v1/memories/search`,返回相关 episodic/profile/raw message 记忆。适合在回答用户问题前,把“当前 session 工作记忆”和“EverOS 相关记忆”一起取回。
|
同时用同一个 `query` 调用 EverOS `POST /api/v1/memory/search`,请求体使用顶层 `user_id`,并把 `session_id` 放在 `filters.session_id` 中。适合在回答用户问题前,把“当前 session 工作记忆”和“EverOS 相关记忆”一起取回。
|
||||||
|
|
||||||
路径参数:
|
路径参数:
|
||||||
|
|
||||||
@ -455,7 +468,7 @@ curl -sS -X POST "$API/sessions/sessionA1/context" \
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `context` | OpenViking `result`,包含 `latest_archive_overview`、`pre_archive_abstracts`、`messages`、`stats` |
|
| `context` | OpenViking `result`,包含 `latest_archive_overview`、`pre_archive_abstracts`、`messages`、`stats` |
|
||||||
| `items` | EverOS 搜索命中的精简记忆结果,含 `source_backend: "everos"` |
|
| `items` | EverOS 搜索命中的精简记忆结果,含 `source_backend: "everos"` |
|
||||||
| `backends` | 两个后端的精简诊断信息,不重复返回完整 OpenViking context 或 EverOS `original_data` |
|
| `backends` | 两个后端的精简诊断信息,不重复返回完整 OpenViking context 或 EverOS 原始大 payload |
|
||||||
|
|
||||||
### `GET/POST /openviking/tasks/{task_id}`
|
### `GET/POST /openviking/tasks/{task_id}`
|
||||||
|
|
||||||
@ -667,7 +680,7 @@ curl -sS -X DELETE -G "$API/resources" \
|
|||||||
|
|
||||||
### `POST /search`
|
### `POST /search`
|
||||||
|
|
||||||
同时查询 OpenViking 和 EverOS,并合并结果。
|
同时查询 OpenViking 和 EverOS,并合并结果。EverOS 分支调用 `POST /api/v1/memory/search`,请求体形如 `{"user_id": "...", "query": "...", "method": "hybrid|agentic", "top_k": 10, "include_profile": true, "filters": {"session_id": "..."}}`。
|
||||||
|
|
||||||
请求体:
|
请求体:
|
||||||
|
|
||||||
@ -675,7 +688,7 @@ curl -sS -X DELETE -G "$API/resources" \
|
|||||||
|---|---|---:|---|
|
|---|---|---:|---|
|
||||||
| `user_id` | string | 是 | 用户 ID |
|
| `user_id` | string | 是 | 用户 ID |
|
||||||
| `user_key` | string | 是 | `/users` 返回的 user key |
|
| `user_key` | string | 是 | `/users` 返回的 user key |
|
||||||
| `session_id` | string/null | 否 | 会话 ID;用于 EverOS 过滤和鉴权身份 |
|
| `session_id` | string/null | 否 | 会话 ID;用于 EverOS `filters.session_id` 和 OpenViking agent identity |
|
||||||
| `query` | string | 是 | 查询文本 |
|
| `query` | string | 是 | 查询文本 |
|
||||||
| `use_llm` | bool | 否 | 只影响 EverOS 检索方式:`false` 使用 hybrid,`true` 使用 agentic |
|
| `use_llm` | bool | 否 | 只影响 EverOS 检索方式:`false` 使用 hybrid,`true` 使用 agentic |
|
||||||
| `limit` | int | 否 | 返回条数,默认 10,范围 1 到 100 |
|
| `limit` | int | 否 | 返回条数,默认 10,范围 1 到 100 |
|
||||||
@ -707,11 +720,11 @@ curl -sS -X POST "$API/search" \
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `status` | 总体状态 |
|
| `status` | 总体状态 |
|
||||||
| `items` | 合并后的记忆结果,含 `source_backend` |
|
| `items` | 合并后的记忆结果,含 `source_backend` |
|
||||||
| `backends` | 两个后端的精简诊断信息,例如命中数量、query plan 或查询过滤条件;不再回传完整原始命中和 `original_data` |
|
| `backends` | 两个后端的精简诊断信息,例如命中数量、query plan 或查询过滤条件;不再回传完整原始命中 |
|
||||||
|
|
||||||
### `GET/POST /users/{user_id}/profile`
|
### `GET/POST /users/{user_id}/profile`
|
||||||
|
|
||||||
读取用户画像。该接口需要 `user_key`,用于确认调用方属于该 user。网关会读取 EverOS profile,并用同一个 `query` 调 OpenViking `/api/v1/search/search`,固定传 `target_uri: viking://user/memories` 和 `level`。
|
读取用户画像。该接口需要 `user_key`,用于确认调用方属于该 user。网关会调用 EverOS `POST /api/v1/memory/get`,请求体为 `{"user_id": "...", "memory_type": "profile", "page": 1, "page_size": 20}`;同时用同一个 `query` 调 OpenViking `/api/v1/search/search`,固定传 `target_uri: viking://user/memories` 和 `level`。
|
||||||
|
|
||||||
请求体:
|
请求体:
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ openviking:
|
|||||||
api_key: "<OPENVIKING_ROOT_KEY>"
|
api_key: "<OPENVIKING_ROOT_KEY>"
|
||||||
|
|
||||||
everos:
|
everos:
|
||||||
# EverOS EverCore HTTP server.
|
# EverOS HTTP server exposing /api/v1/memory/*.
|
||||||
url: "http://127.0.0.1:1995"
|
url: "http://127.0.0.1:1995"
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
|
|||||||
@ -403,7 +403,7 @@ class EverOSMemorySystemClient:
|
|||||||
async def append_message(self, user_id: str, session_id: str, role: str, content: str) -> dict[str, Any]:
|
async def append_message(self, user_id: str, session_id: str, role: str, content: str) -> dict[str, Any]:
|
||||||
async with self._client() as client:
|
async with self._client() as client:
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
"/api/v1/memories",
|
"/api/v1/memory/add",
|
||||||
json=self.build_message_payload(user_id=user_id, session_id=session_id, role=role, content=content),
|
json=self.build_message_payload(user_id=user_id, session_id=session_id, role=role, content=content),
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
@ -414,7 +414,6 @@ class EverOSMemorySystemClient:
|
|||||||
sender_id = "assistant" if everos_role == "assistant" else user_id
|
sender_id = "assistant" if everos_role == "assistant" else user_id
|
||||||
timestamp = int(datetime.now(timezone.utc).timestamp() * 1000)
|
timestamp = int(datetime.now(timezone.utc).timestamp() * 1000)
|
||||||
return {
|
return {
|
||||||
"user_id": user_id,
|
|
||||||
"session_id": session_id,
|
"session_id": session_id,
|
||||||
"messages": [
|
"messages": [
|
||||||
{
|
{
|
||||||
@ -430,25 +429,30 @@ class EverOSMemorySystemClient:
|
|||||||
|
|
||||||
async def flush(self, user_id: str, session_id: str) -> dict[str, Any]:
|
async def flush(self, user_id: str, session_id: str) -> dict[str, Any]:
|
||||||
async with self._client() as client:
|
async with self._client() as client:
|
||||||
response = await client.post("/api/v1/memories/flush", json={"user_id": user_id, "session_id": session_id})
|
response = await client.post(
|
||||||
|
"/api/v1/memory/flush",
|
||||||
|
json={"session_id": session_id},
|
||||||
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
async def search(self, user_id: str, session_id: str | None, query: str, method: str, limit: int) -> dict[str, Any]:
|
async def search(self, user_id: str, session_id: str | None, query: str, method: str, limit: int) -> dict[str, Any]:
|
||||||
filters: dict[str, Any] = {"user_id": user_id}
|
filters: dict[str, Any] = {}
|
||||||
if session_id:
|
if session_id:
|
||||||
filters["session_id"] = session_id
|
filters["session_id"] = session_id
|
||||||
|
payload: dict[str, Any] = {
|
||||||
|
"user_id": user_id,
|
||||||
|
"query": query,
|
||||||
|
"method": method,
|
||||||
|
"top_k": limit,
|
||||||
|
"include_profile": True,
|
||||||
|
}
|
||||||
|
if filters:
|
||||||
|
payload["filters"] = filters
|
||||||
async with self._client() as client:
|
async with self._client() as client:
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
"/api/v1/memories/search",
|
"/api/v1/memory/search",
|
||||||
json={
|
json=payload,
|
||||||
"query": query,
|
|
||||||
"method": method,
|
|
||||||
"memory_types": ["episodic_memory", "profile", "raw_message"],
|
|
||||||
"filters": filters,
|
|
||||||
"top_k": limit,
|
|
||||||
"include_original_data": True,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.json()
|
return response.json()
|
||||||
@ -456,10 +460,10 @@ class EverOSMemorySystemClient:
|
|||||||
async def get_profile(self, user_id: str) -> dict[str, Any]:
|
async def get_profile(self, user_id: str) -> dict[str, Any]:
|
||||||
async with self._client() as client:
|
async with self._client() as client:
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
"/api/v1/memories/get",
|
"/api/v1/memory/get",
|
||||||
json={
|
json={
|
||||||
|
"user_id": user_id,
|
||||||
"memory_type": "profile",
|
"memory_type": "profile",
|
||||||
"filters": {"user_id": user_id},
|
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"page_size": 20,
|
"page_size": 20,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -264,7 +264,7 @@ curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/search \
|
|||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
Raw API search responses include merged `items` plus compact backend diagnostics. Fields named `vector` are stripped recursively before the API returns JSON. The API does not return EverOS `original_data` or full episode payloads inside `backends` anymore. OpenViking search uses `/api/v1/search/search`; `target_uri`, `level`, and `score_threshold` are optional request fields.
|
Raw API search responses include merged `items` plus compact backend diagnostics. Fields named `vector` are stripped recursively before the API returns JSON. The API calls current EverOS `POST /api/v1/memory/search` with top-level `user_id`, `query`, `method`, `top_k`, `include_profile`, and optional `filters.session_id`; it does not return full EverOS episode/profile payloads inside `backends`. OpenViking search uses `/api/v1/search/search`; `target_uri`, `level`, and `score_threshold` are optional request fields.
|
||||||
|
|
||||||
The search response shape should now look more like:
|
The search response shape should now look more like:
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ The search response shape should now look more like:
|
|||||||
"everos": {
|
"everos": {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"result": {
|
"result": {
|
||||||
"counts": {"episodes": 1, "profiles": 0, "raw_messages": 0},
|
"counts": {"episodes": 1, "profiles": 0},
|
||||||
"query": {"text": "我喜欢喝什么?", "method": "agentic"}
|
"query": {"text": "我喜欢喝什么?", "method": "agentic"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -732,3 +732,117 @@ def test_everos_user_payload_uses_user_id_as_sender():
|
|||||||
assert message["role"] == "user"
|
assert message["role"] == "user"
|
||||||
assert message["sender_id"] == "tom"
|
assert message["sender_id"] == "tom"
|
||||||
assert message["sender_name"] == "tom"
|
assert message["sender_name"] == "tom"
|
||||||
|
|
||||||
|
|
||||||
|
def test_everos_append_message_posts_current_memory_add_contract():
|
||||||
|
client = EverOSMemorySystemClient()
|
||||||
|
calls = []
|
||||||
|
responses = [FakeResponse(200, {"request_id": "req-1", "data": {"status": "accumulated", "message_count": 1}})]
|
||||||
|
client._client = lambda: FakeAsyncClient( # type: ignore[method-assign]
|
||||||
|
calls,
|
||||||
|
responses,
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = asyncio.run(client.append_message("tom", "sess-1", "user", "我喜欢拿铁"))
|
||||||
|
|
||||||
|
assert result == {"request_id": "req-1", "data": {"status": "accumulated", "message_count": 1}}
|
||||||
|
assert calls[0][0] == "post"
|
||||||
|
assert calls[0][3] == "/api/v1/memory/add"
|
||||||
|
payload = calls[0][4]
|
||||||
|
assert payload["session_id"] == "sess-1"
|
||||||
|
assert "user_id" not in payload
|
||||||
|
assert payload["messages"][0]["sender_id"] == "tom"
|
||||||
|
assert payload["messages"][0]["role"] == "user"
|
||||||
|
assert payload["messages"][0]["content"] == "我喜欢拿铁"
|
||||||
|
|
||||||
|
|
||||||
|
def test_everos_flush_posts_current_memory_flush_contract():
|
||||||
|
client = EverOSMemorySystemClient()
|
||||||
|
calls = []
|
||||||
|
responses = [FakeResponse(200, {"request_id": "req-1", "data": {"status": "extracted"}})]
|
||||||
|
client._client = lambda: FakeAsyncClient( # type: ignore[method-assign]
|
||||||
|
calls,
|
||||||
|
responses,
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = asyncio.run(client.flush("tom", "sess-1"))
|
||||||
|
|
||||||
|
assert result == {"request_id": "req-1", "data": {"status": "extracted"}}
|
||||||
|
assert calls == [
|
||||||
|
(
|
||||||
|
"post",
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
"/api/v1/memory/flush",
|
||||||
|
{"session_id": "sess-1"},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_everos_search_posts_current_memory_search_contract():
|
||||||
|
client = EverOSMemorySystemClient()
|
||||||
|
calls = []
|
||||||
|
responses = [FakeResponse(200, {"request_id": "req-1", "data": {"episodes": []}})]
|
||||||
|
client._client = lambda: FakeAsyncClient( # type: ignore[method-assign]
|
||||||
|
calls,
|
||||||
|
responses,
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = asyncio.run(client.search("tom", "sess-1", "牛奶在哪里", "hybrid", 7))
|
||||||
|
|
||||||
|
assert result == {"request_id": "req-1", "data": {"episodes": []}}
|
||||||
|
assert calls == [
|
||||||
|
(
|
||||||
|
"post",
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
"/api/v1/memory/search",
|
||||||
|
{
|
||||||
|
"user_id": "tom",
|
||||||
|
"query": "牛奶在哪里",
|
||||||
|
"method": "hybrid",
|
||||||
|
"top_k": 7,
|
||||||
|
"include_profile": True,
|
||||||
|
"filters": {"session_id": "sess-1"},
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_everos_get_profile_posts_current_memory_get_contract():
|
||||||
|
client = EverOSMemorySystemClient()
|
||||||
|
calls = []
|
||||||
|
responses = [FakeResponse(200, {"request_id": "req-1", "data": {"profiles": []}})]
|
||||||
|
client._client = lambda: FakeAsyncClient( # type: ignore[method-assign]
|
||||||
|
calls,
|
||||||
|
responses,
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = asyncio.run(client.get_profile("tom"))
|
||||||
|
|
||||||
|
assert result == {"request_id": "req-1", "data": {"profiles": []}}
|
||||||
|
assert calls == [
|
||||||
|
(
|
||||||
|
"post",
|
||||||
|
client.api_key or "",
|
||||||
|
{},
|
||||||
|
"/api/v1/memory/get",
|
||||||
|
{
|
||||||
|
"user_id": "tom",
|
||||||
|
"memory_type": "profile",
|
||||||
|
"page": 1,
|
||||||
|
"page_size": 20,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user