# AI-Core Service API

**Base URL:** `http://<host>:8081` | **Auth:** 无（/internal 路由除外）

AI-Core 是 LLM 编排引擎，负责对话处理、意图分析、子会话调度、结果合成。所有对话和记忆端点通过 **Server-Sent Events (SSE)** 或 **JSON** 返回。

---

## 目录

1. [POST /api/v1/chat — 对话](#1-post-apiv1chat)
2. [GET /api/v1/memory/search — 记忆搜索](#2-get-apiv1memorysearch)
3. [GET /api/v1/memory — 记忆列表](#3-get-apiv1memory)
4. [POST /api/v1/memory — 添加记忆](#4-post-apiv1memory)
5. [DELETE /api/v1/memory — 删除记忆](#5-delete-apiv1memory)
6. [POST /api/v1/internal/presence — 在线状态](#6-post-apiv1internalpresence)
7. [GET /api/v1/system/info — OS 环境信息](#7-get-apiv1systeminfo)
8. [GET /api/v1/tools/calls — 工具调用日志](#8-get-apiv1toolscalls)
9. [GET /api/v1/llm-calls — LLM 调用日志](#9-get-apiv1llm-calls)
10. [GET /api/v1/health — 健康检查](#10-get-apiv1health)
11. [Model Selector 路由说明](#11-model-selector-路由说明)

---

## 1. POST /api/v1/chat

**类型:** SSE 流式 | **Content-Type:** `application/json` → `text/event-stream`

### 请求体 (JSON)

| JSON 字段 | Go 类型 | 必填 | 说明 |
|-----------|---------|------|------|
| `user_id` | string | 是 | 用户 ID |
| `session_id` | string | 是 | 会话 ID |
| `message` | string | 是 | 用户消息文本（纯图片时可留空 `""`） |
| `images` | []string | 否 | 图片 URL 数组（data URL 或 https URL） |
| `mode` | string | 否 | 默认 `"text"` |
| `nickname` | string | 否 | 用户昵称 |

> **图片预处理：** 当 `images` 非空时，AI-Core 使用视觉模型 (`routing.vision`) 自动分析图片：
> - 纯图片 (`message=""`) → 生成场景描述作为用户消息
> - 文字+图片 → 视觉分析追加到消息末尾
> - 原始图片仍传递给下游 LLM（如模型支持多模态）

### SSE 事件

**delta** — 逐 token 发送
```json
{ "delta": "token 文本", "message_id": "msg-1717000000000000000" }
```

**segments** — 断句事件（生成完成后）
```json
{
  "message_id": "string",
  "mode": "string",
  "segments": [
    { "index": 0, "text": "第一句话" },
    { "index": 1, "text": "第二句话" }
  ]
}
```

**review** — 审查后结构化消息（action/chat 分离）
```json
{
  "message_id": "string",
  "review_messages": [
    { "type": "action", "content": "打开灯光", "delay_ms": 0 },
    { "type": "chat", "content": "好的，已为你打开客厅的灯光。", "delay_ms": 200 }
  ]
}
```

**tool_progress** — 工具执行进度
```json
{
  "type": "tool_progress",
  "tool_name": "host_exec",
  "status": "started|running|completed|failed",
  "progress": 0.5,
  "message": "正在执行 host_exec",
  "message_id": "string"
}
```

**done** — 流结束
```json
{ "message_id": "string", "mode": "string", "done": true }
```

**error** — 错误
```json
{ "delta": "", "error": "错误描述" }
```

终端标记: `data: [DONE]\n\n`

### HTTP 状态码

| 状态码 | 含义 |
|--------|------|
| 200 | 流开始 |
| 400 | JSON 解析失败 |
| 405 | 非 POST 请求 |
| 500 | 服务端不支持流式 |

---

## 2. GET /api/v1/memory/search

### Query 参数

| 参数 | 必填 | 说明 |
|------|------|------|
| `user_id` | 是 | 用户 ID |
| `q` | 是 | 搜索关键词 |

### 响应 200

```json
{
  "user_id": "string",
  "query": "搜索词",
  "memories": [ MemoryEntry, ... ],
  "total": 5
}
```

### 错误 (200 + error 字段)

```json
{
  "user_id": "string",
  "query": "string",
  "memories": [],
  "error": "错误描述",
  "errorType": "memory_store_unavailable|retrieve_failed",
  "hint": "解决方案 (仅 memory_store_unavailable)"
}
```

---

## 3. GET /api/v1/memory — 记忆列表

`?user_id=xxx` 最大返回 50 条。

```json
{
  "user_id": "string",
  "memories": [ MemoryEntry, ... ],
  "total": 3
}
```

---

## 4. POST /api/v1/memory — 添加记忆

```json
// 请求
{
  "user_id": "string (必填)",
  "content": "string (必填)",
  "category": "string (默认 other)",
  "priority": 1
}

// 响应 201
{
  "status": "saved",
  "memory": MemoryEntry
}
```

### 错误

| 状态码 | errorType | 说明 |
|--------|-----------|------|
| 400 | — | 缺少 user_id 或 content |
| 500 | `save_failed` | 保存失败 |
| 503 | `memory_store_unavailable` | 存储未初始化 |

---

## 5. DELETE /api/v1/memory — 删除记忆

`?id=<memory_id>`

```json
// 响应 200
{ "status": "deleted", "memory_id": "string" }
```

### 错误

| 状态码 | errorType |
|--------|-----------|
| 400 | 缺少 id 参数 |
| 500 | `delete_failed` |
| 503 | `memory_store_unavailable` |

---

## 6. POST /api/v1/internal/presence

**Auth:** `X-Internal-Token` header。Gateway 内部调用的用户上线/下线通知。

```json
// 请求
{
  "user_id": "string (必填)",
  "status": "online|offline (必填)",
  "session_id": "string (必填)"
}

// 响应 200
{ "status": "ok" }
```

| 状态码 | 含义 |
|--------|------|
| 200 | 成功 |
| 400 | JSON 无效 |
| 401 | Token 无效 |

---

## 7. GET /api/v1/system/info

返回 OS 环境状态信息（WSL/Docker 后端状态、系统信息、磁盘使用）。

```json
{
  "os_enabled": true,
  "backend": "wsl",
  "system": { "hostname": "...", "os": "linux", "arch": "amd64", "cpu_cores": 12, "total_memory": "16.0 GB" },
  "disk": { "path": "/", "total": "250.0 GB", "used": "120.0 GB", "free": "130.0 GB", "used_percent": 48.0 }
}
```

`os_enabled=false` 表示未配置 OS 后端。

---

## 8. GET /api/v1/tools/calls

工具调用日志（分页）。

| Query 参数 | 说明 |
|-----------|------|
| `tool_name` | 按工具名过滤 |
| `limit` | 每页条数 (默认 50, 最大 500) |
| `page` | 页码 (从 1 开始) |

```json
{
  "calls": [ CallLogRecord ],
  "total": 100,
  "total_pages": 2,
  "page": 1,
  "limit": 50
}
```

### GET /api/v1/tools/calls/stats — 工具调用统计

返回各工具的调用次数、成功率等统计信息。

---

## 9. GET /api/v1/llm-calls

LLM 调用日志（调试用）。

`?limit=50` (默认 50, 最大 500)

```json
{
  "calls": [ LLMCallRecord ],
  "total": 50
}
```

---

## 10. GET /api/v1/health

```json
{
  "status": "ok",
  "service": "ai-core",
  "model": "gpt-4o"
}
```

---

## 11. Model Selector 路由说明

AI-Core 使用基于用途的模型路由。模型配置从 `models.json` 加载，回退到 `.env` 环境变量。

### Purpose 常量

| Purpose | 常量 | 用途 |
|---------|------|------|
| `chat` | `PurposeChat` | 通用对话 |
| `deep_thinking` | `PurposeDeepThinking` | 后台深度思考 |
| `intent_analysis` | `PurposeIntentAnalysis` | 意图分析 |
| `tool_calling` | `PurposeToolCalling` | 工具调用 |
| `memory_extraction` | `PurposeMemoryExtraction` | 记忆提取 |
| `vision` | `PurposeVision` | 图片理解/视觉分析 (图片预处理、vision_analyze 工具) |
| `ocr` | `PurposeOCR` | 专用 OCR 文字提取 |

### 路由策略

1. `models.json` 存在 → 按 `routing.<purpose>.fallback_chain` 顺序尝试
2. `models.json` 不存在 → 回退到 `.env` 的 `LLM_API_URL`/`LLM_API_KEY`/`LLM_MODEL`
3. 全部失败 → 返回 `DefaultAdapter()` 使用 fallback model

### MemoryEntry 结构

| JSON 字段 | Go 类型 | 说明 |
|-----------|---------|------|
| `id` | string | UUID |
| `user_id` | string | 所属用户 |
| `content` | string | 完整内容 |
| `summary` | string | 摘要 |
| `category` | string | `user_preference`, `personal_info`, `conversation`, `knowledge`, `event`, `task`, `relationship` |
| `priority` | int | 0=Temp, 1=Normal, 2=Important, 3=Core |
| `importance` | int | 1-10 |
| `keywords` | []string | 关键词标签 |
| `session_id` | string | 来源会话 |
| `source` | string | `conversation`, `thinking`, `manual` |
| `access_count` | int | 访问次数 |
| `last_access` | time | 最近访问 |
| `created_at` | time | 创建时间 |
| `updated_at` | time | 更新时间 |
| `expires_at` | *time | 临时记忆过期（可空） |
