# OpenViking Memory API 流程说明

> 本文档整理 OpenViking 中「创建账号/用户 → 创建 session → 写入消息 → commit 抽取长期 memory → 查询 task 状态 → 检索 user memory/session memory」的完整 API 流程。
>
> 出于安全原因，示例中不写入真实 `root_api_key` 或 `user_key`，统一使用环境变量占位。

## 0. 前置变量

```bash
# 在config.yaml里设置的 openviking url 和 api_key
export OV_HOST="http://localhost:1933"
export ROOT_KEY="your-secret-root-key"

# 创建用户后填入返回的 user_key
export USER_A_KEY="<userA-user-key>"
export USER_B_KEY="<userB-user-key>"
```

OpenViking 的常见鉴权方式：

| 场景 | Header |
|---|---|
| Admin API，例如创建 account | `X-API-Key: $ROOT_KEY` |
| 普通用户 API，例如 session/message/search | `X-API-Key: $USER_A_KEY` |

---

## 1. 创建用户隔离工作区 / account

Admin API 用于多租户管理。Memory Gateway 为每个业务用户直接创建一个 admin account，不再调用 `/api/v1/admin/accounts/admin/users`。

```bash
curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userA_account",
    "admin_user_id": "userA"
  }'
```

典型返回：

```json
{
  "status": "ok",
  "result": {
    "account_id": "userA_account",
    "admin_user_id": "userA",
    "user_key": "<userA-user-key>"
  },
  "error": null,
  "telemetry": null
}
```

---

## 2. 创建更多用户

### 2.1 创建 userA

```bash
curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userA_account",
    "admin_user_id": "userA"
  }'
```

返回后保存：

```bash
export USER_A_KEY="<userA-user-key>"
```

### 2.2 创建 userB

```bash
curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userB_account",
    "admin_user_id": "userB"
  }'
```

返回后保存：

```bash
export USER_B_KEY="<userB-user-key>"
```

> 注意：不同用户必须使用各自的 `user_key`。用 userA 的 key 只能访问 userA 的用户空间，用 userB 的 key 只能访问 userB 的用户空间。

---

## 3. 创建 session

Session 是会话容器，用于保存消息、跟踪上下文使用、commit 后抽取长期 memories。

### 3.1 创建 userA 的 sessionA1

```bash
curl -X POST "$OV_HOST/api/v1/sessions" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sessionA1"
  }'
```

典型返回：

```json
{
  "status": "ok",
  "result": {
    "session_id": "sessionA1",
    "user": {
      "account_id": "userA_account",
      "user_id": "userA",
      "agent_id": "default"
    }
  },
  "error": null,
  "telemetry": null
}
```

### 3.2 创建 userB 的 sessionB1

```bash
curl -X POST "$OV_HOST/api/v1/sessions" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sessionB1"
  }'
```

---

## 4. 写入 session 消息

HTTP API 支持简单文本模式：`role + content`。`role` 通常为 `user` 或 `assistant`。

### 4.1 写入 userA / sessionA1 消息

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/messages" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "content": "我喜欢用 Python 写数据分析脚本。"
  }'
```

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/messages" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "assistant",
    "content": "好的，我会记住你偏好 Python 数据分析。"
  }'
```

### 4.2 写入 userB / sessionB1 消息

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/messages" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "content": "我喜欢用 vibe coding 写项目。"
  }'
```

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/messages" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "assistant",
    "content": "好的，我会记住你偏好 vibe coding 项目。"
  }'
```

---

## 5. Commit session，触发长期 memory 抽取

`commit` 是两阶段流程：

1. **Phase 1，同步完成**：把当前 live messages 快照归档，创建 archive 目录，清空 live session。
2. **Phase 2，异步完成**：生成 session 摘要，抽取长期 memories，更新关系和 active count。

因此 `commit` 请求会很快返回 `task_id`，后续要轮询 task 状态。

### 5.1 Commit userA / sessionA1

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/commit" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keep_recent_count": 0
  }'
```

典型返回：

```json
{
  "status": "ok",
  "result": {
    "session_id": "sessionA1",
    "status": "accepted",
    "task_id": "fe6510e1-fdee-4f2d-9f87-5e48b519c2a2",
    "archive_uri": "viking://session/userA/sessionA1/history/archive_001",
    "archived": true
  }
}
```

### 5.2 Commit userB / sessionB1

```bash
curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/commit" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keep_recent_count": 0
  }'
```

---

## 6. 查询 commit task 状态

```bash
curl -s "$OV_HOST/api/v1/tasks/<task_id>" \
  -H "X-API-Key: $USER_A_KEY" | jq .
```

成功完成后类似：

```json
{
  "status": "ok",
  "result": {
    "task_id": "fe6510e1-fdee-4f2d-9f87-5e48b519c2a2",
    "task_type": "session_commit",
    "status": "completed",
    "resource_id": "sessionA1",
    "result": {
      "session_id": "sessionA1",
      "archive_uri": "viking://session/userA/sessionA1/history/archive_001",
      "memories_extracted": {
        "preferences": 1
      },
      "active_count_updated": 0
    },
    "error": null
  },
  "error": null,
  "telemetry": null
}
```

关键字段说明：

| 字段 | 含义 |
|---|---|
| `status: completed` | Phase 2 已完成，memory 抽取结束 |
| `result.archive_uri` | 本次归档目录 URI |
| `result.memories_extracted` | 本次 commit 提取到的 memory 分类计数，不是 memory 内容 |
| `active_count_updated` | 本次基于 `sessions/{id}/used` 使用记录更新的活跃计数数量 |

如果返回：

```json
"status": "running"
```

说明后台任务还没完成。此时可以稍后继续查询同一个 task。

---

## 7. 用 `search/find` 向量搜索 user 长期 memory

`find` 是纯向量检索，不使用 session 上下文，也不做意图分析。适合直接按语义检索用户长期 memory。

使用显式用户路径：

```bash
curl -s -X POST "$OV_HOST/api/v1/search/find" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $USER_A_KEY" \
  -d '{
    "query": "我之前说了什么",
    "target_uri": "viking://user/userA/memories/",
    "limit": 3
  }' | jq .
```

典型返回：

```json
{
  "status": "ok",
  "result": {
    "memories": [
      {
        "context_type": "memory",
        "uri": "viking://user/userA/memories/preferences/mem_xxx.md",
        "level": 2,
        "score": 0.7411,
        "abstract": "Python 数据分析：偏好使用 Python 编写数据分析脚本"
      }
    ],
    "resources": [],
    "skills": [],
    "total": 1
  }
}
```

---

## 9. 用 `search/search` 做带 session 上下文的 LLM 搜索

`search` 是智能检索：在 `find` 的基础上增加 session context、意图分析和 query expansion。它适合「用户当前对话里有上下文，查询语义不完整」的场景。

```bash
curl -s -X POST "$OV_HOST/api/v1/search/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $USER_A_KEY" \
  -d '{
    "query": "我正在做什么",
    "target_uri": "viking://user/userA/sessionA1", # 
    "session_id": "sessionA1",
    "limit": 10,
  }
```

典型返回：
```json
{
  "status": "ok",
  "result": {
    "memories": [],
    "resources": [],
    "skills": [],
    "total": 0,
    "query_plan": {
      "reasoning": "1. Conversational task (user asking '我正在做什么' - 'What am I doing?'); 2. This is a simple conversational query about current state/activity; 3. The session context contains the user's previous interactions about Python preferences and EverOS API questions; 4. No specific context gaps need to be filled for this conversational task, but a memory query about the user's current activity context could help provide a more personalized response",
      "queries": [
        {
          "query": "User's current activity and task context",
          "context_type": "memory",
          "intent": "Understand what the user is currently working on to provide relevant context",
          "priority": 3
        }
      ]
    }
  }
}
```

---

## 10. `find` 与 `search` 的选择

| 接口 | 是否使用 session 上下文 | 是否做意图分析 | 适合场景 |
|---|---:|---:|---|
| `/api/v1/search/find` | 否 | 否 | 直接按 query 做向量检索，稳定查 user memory |
| `/api/v1/search/search` | 是，可传 `session_id` | 是 | 对话式检索，需要结合 session 语境、自动扩展 query |

推荐实践：

1. **验证 memory 是否已经写入**：先用 `tasks/{task_id}` 确认 `completed`。
2. **确认 user 长期 memory 是否可召回**：用 `/api/v1/search/find`，query 写得贴近 memory 内容。
3. **需要结合当前会话上下文**：再用 `/api/v1/search/search` 加 `session_id`。
