# 历史记录 (History Records) API

历史记录 API 用于管理通话记录和对话历史。

## 基础信息

| 项目 | 值 |
|------|-----|
| Base URL | `/api/v1/history` |
| 认证方式 | Bearer Token (预留) |

---

## 数据模型

### CallRecord

```typescript
interface CallRecord {
  id: string;                 // 通话记录ID
  user_id: number;            // 所属用户ID
  assistant_id?: string;      // 关联助手ID
  source: string;             // 来源: "debug" | "external"
  status: string;            // 状态: "connected" | "missed" | "failed"
  started_at: string;        // 开始时间 ISO8601
  ended_at?: string;         // 结束时间 ISO8601
  duration_seconds?: int;    // 通话时长(秒)
  summary?: string;          // 通话摘要
  cost?: number;             // 费用
  metadata?: object;         // 元数据
  created_at: string;        // 创建时间
}
```

### TranscriptSegment

```typescript
interface TranscriptSegment {
  turn_index: int;       // 对话轮次
  speaker: string;       // 说话者: "human" | "ai"
  content: string;      // 转写内容
  confidence?: float;    // 置信度 0-1
  start_ms: int;        // 开始时间(毫秒)
  end_ms: int;          // 结束时间(毫秒)
  duration_ms?: int;    // 持续时间(毫秒)
  audio_url?: string;   // 音频URL
  emotion?: string;      // 情绪标签
}
```

### InteractionDetail

```typescript
interface InteractionDetail {
  role: "user" | "assistant";  // 角色
  content: string;              // 文本内容或转写文本
  audio_url?: string;           // 音频URL
  image_urls?: string[];       // 图片URL列表(视频场景)
  timestamp: string;            // 时间戳
}
```

---

## API 端点

### 1. 获取通话记录列表

```http
GET /api/v1/history
```

**Query Parameters:**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| assistant_id | string | 否 | 过滤助手ID |
| status | string | 否 | 过滤状态: "connected" \| "missed" \| "failed" |
| source | string | 否 | 过滤来源: "debug" \| "external" |
| start_date | string | 否 | 开始日期 ISO8601 |
| end_date | string | 否 | 结束日期 ISO8601 |
| page | int | 否 | 页码，默认 1 |
| limit | int | 否 | 每页数量，默认 20 |

**Response:**

```json
{
  "total": 150,
  "page": 1,
  "limit": 20,
  "list": [
    {
      "id": "call_001",
      "user_id": 1,
      "assistant_id": "abc12345",
      "source": "debug",
      "status": "connected",
      "started_at": "2024-01-15T14:30:00Z",
      "ended_at": "2024-01-15T14:33:00Z",
      "duration_seconds": 180,
      "summary": "用户咨询产品A的售后服务",
      "cost": 0.05,
      "created_at": "2024-01-15T14:30:00Z"
    },
    {
      "id": "call_002",
      "user_id": 1,
      "assistant_id": "abc12345",
      "source": "external",
      "status": "missed",
      "started_at": "2024-01-15T14:00:00Z",
      "duration_seconds": 0,
      "created_at": "2024-01-15T14:00:00Z"
    }
  ]
}
```

---

### 2. 获取通话详情

```http
GET /api/v1/history/{call_id}
```

**Response:**

```json
{
  "id": "call_001",
  "user_id": 1,
  "assistant_id": "abc12345",
  "source": "debug",
  "status": "connected",
  "started_at": "2024-01-15T14:30:00Z",
  "ended_at": "2024-01-15T14:33:00Z",
  "duration_seconds": 180,
  "summary": "用户咨询产品A的售后服务",
  "cost": 0.05,
  "metadata": {
    "browser": "Chrome",
    "os": "Windows"
  },
  "transcripts": [
    {
      "turn_index": 0,
      "speaker": "human",
      "content": "您好，我想咨询一下产品A的售后服务",
      "confidence": 0.98,
      "start_ms": 0,
      "end_ms": 3500,
      "duration_ms": 3500,
      "audio_url": "https://storage.example.com/audio/call_001/turn_0.mp3"
    },
    {
      "turn_index": 1,
      "speaker": "ai",
      "content": "您好！产品A享有7天无理由退货和一年质保服务。请问您遇到了什么问题？",
      "confidence": 0.95,
      "start_ms": 4000,
      "end_ms": 12000,
      "duration_ms": 8000,
      "audio_url": "https://storage.example.com/audio/call_001/turn_1.mp3"
    },
    {
      "turn_index": 2,
      "speaker": "human",
      "content": "我发现产品A有一个功能坏了",
      "confidence": 0.92,
      "start_ms": 13000,
      "end_ms": 18000,
      "duration_ms": 5000,
      "audio_url": "https://storage.example.com/audio/call_001/turn_2.mp3"
    }
  ]
}
```

---

### 3. 创建通话记录

```http
POST /api/v1/history
```

**Request Body:**

```json
{
  "user_id": 1,
  "assistant_id": "abc12345",
  "source": "debug"
}
```

**Response:**

```json
{
  "id": "call_new001",
  "user_id": 1,
  "assistant_id": "abc12345",
  "source": "debug",
  "status": "connected",
  "started_at": "2024-01-15T15:00:00Z",
  "created_at": "2024-01-15T15:00:00Z"
}
```

---

### 4. 更新通话记录

```http
PUT /api/v1/history/{call_id}
```

**Request Body:**

```json
{
  "status": "connected",
  "summary": "用户咨询产品A的售后服务，已引导用户提交工单",
  "duration_seconds": 180,
  "ended_at": "2024-01-15T14:33:00Z"
}
```

---

### 5. 删除通话记录

```http
DELETE /api/v1/history/{call_id}
```

---

### 6. 添加转写片段

```http
POST /api/v1/history/{call_id}/transcripts
```

**Request Body:**

```json
{
  "turn_index": 3,
  "speaker": "ai",
  "content": "好的，我已经为您创建了工单，编号 #12345，请保持电话畅通，我们的客服人员会在24小时内联系您。",
  "confidence": 0.96,
  "start_ms": 20000,
  "end_ms": 28000,
  "duration_ms": 8000,
  "emotion": "neutral"
}
```

**Response:**

```json
{
  "id": 100,
  "turn_index": 3,
  "speaker": "ai",
  "content": "好的，我已经为您创建了工单...",
  "confidence": 0.96,
  "start_ms": 20000,
  "end_ms": 28000,
  "duration_ms": 8000,
  "audio_url": "https://storage.example.com/audio/call_001/turn_3.mp3",
  "emotion": "neutral"
}
```

---

### 7. 获取音频

```http
GET /api/v1/history/{call_id}/audio/{turn_index}
```

**Response:** 重定向到音频文件 URL

---

### 8. 搜索通话记录

```http
GET /api/v1/history/search
```

**Query Parameters:**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| q | string | 是 | 搜索关键词 |
| page | int | 否 | 页码 |
| limit | int | 否 | 每页数量 |

**Response:**

```json
{
  "total": 5,
  "page": 1,
  "limit": 20,
  "list": [
    {
      "id": "call_001",
      "started_at": "2024-01-15T14:30:00Z",
      "matched_content": "用户咨询产品A的售后服务"
    }
  ]
}
```

---

### 9. 获取统计信息

```http
GET /api/v1/history/stats
```

**Query Parameters:**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| start_date | string | 否 | 开始日期 |
| end_date | string | 否 | 结束日期 |
| assistant_id | string | 否 | 助手ID |

**Response:**

```json
{
  "total_calls": 150,
  "connected_calls": 135,
  "missed_calls": 15,
  "failed_calls": 0,
  "avg_duration_seconds": 180,
  "total_cost": 7.50,
  "by_status": {
    "connected": 135,
    "missed": 15,
    "failed": 0
  },
  "by_source": {
    "debug": 100,
    "external": 50
  },
  "daily_trend": [
    {
      "date": "2024-01-15",
      "calls": 20,
      "connected": 18,
      "avg_duration": 175
    }
  ]
}
```

---

## 推荐的 Schema 定义

```python
# ============ Call Record ============
class CallRecordSource(str, Enum):
    DEBUG = "debug"
    EXTERNAL = "external"

class CallRecordStatus(str, Enum):
    CONNECTED = "connected"
    MISSED = "missed"
    FAILED = "failed"

class CallRecordBase(BaseModel):
    assistant_id: Optional[str] = None
    source: str = "debug"

class CallRecordCreate(CallRecordBase):
    pass

class CallRecordUpdate(BaseModel):
    status: Optional[str] = None
    summary: Optional[str] = None
    duration_seconds: Optional[int] = None
    ended_at: Optional[str] = None
    cost: Optional[float] = None
    metadata: Optional[dict] = None

class TranscriptSegment(BaseModel):
    turn_index: int
    speaker: str  # "human" | "ai"
    content: str
    confidence: Optional[float] = None
    start_ms: int
    end_ms: int
    duration_ms: Optional[int] = None
    emotion: Optional[str] = None

class CallRecordOut(BaseModel):
    id: str
    user_id: int
    assistant_id: Optional[str] = None
    source: str
    status: str
    started_at: str
    ended_at: Optional[str] = None
    duration_seconds: Optional[int] = None
    summary: Optional[str] = None
    cost: float = 0.0
    metadata: dict = {}
    created_at: datetime
    transcripts: List[TranscriptSegment] = []

    class Config:
        from_attributes = True

class TranscriptCreate(BaseModel):
    turn_index: int
    speaker: str
    content: str
    confidence: Optional[float] = None
    start_ms: int
    end_ms: int
    duration_ms: Optional[int] = None
    emotion: Optional[str] = None

class TranscriptOut(TranscriptCreate):
    id: int
    audio_url: Optional[str] = None

    class Config:
        from_attributes = True

class HistoryStats(BaseModel):
    total_calls: int
    connected_calls: int
    missed_calls: int
    failed_calls: int
    avg_duration_seconds: float
    total_cost: float
    by_status: dict
    by_source: dict
    daily_trend: List[dict]
```

---

## Web 端对应接口映射

| Web Type | API Endpoint |
|----------|--------------|
| CallLog (list) | `GET /api/v1/history` |
| CallLog (detail) | `GET /api/v1/history/{id}` |
| InteractionDetail | `GET /api/v1/history/{id}` (transcripts 字段) |
