# 機能設計書 89-Copilotスレッド

## 概要

本ドキュメントは、Chatwoot Captain Copilotのスレッド管理機能の設計を記載する。エージェントがAI Copilotと対話するためのスレッド（会話コンテキスト）を管理するEnterprise機能である。

### 本機能の処理概要

Copilotスレッド機能は、エージェントがAIアシスタント（Copilot）と対話するための会話スレッドを管理する機能である。

**業務上の目的・背景**：カスタマーサポートエージェントが顧客対応中に、AIアシスタント（Copilot）に質問や相談を行う機能が必要となる。Copilotスレッドは、エージェントとAIの対話履歴を保持し、コンテキストを維持した会話を実現する。

**機能の利用シーン**：
- エージェントが顧客対応中にCopilotに質問する際
- 過去のCopilotとの会話履歴を参照する際
- 特定の会話コンテキストでCopilotに相談する際

**主要な処理内容**：
1. Copilotスレッドの作成（初回メッセージ送信時）
2. スレッド一覧の取得（ユーザー別）
3. スレッド内メッセージ履歴の管理
4. AI応答ジョブのキュー追加

**関連システム・外部連携**：Captain Copilot ChatService、LLMプロバイダー、使用量制限管理との連携。

**権限による制御**：ログインユーザーのみがアクセス可能。自分のスレッドのみ参照可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | Copilotパネル | 主機能 | Copilotとの対話インターフェース |

## 機能種別

CRUD操作 / AI連携

## 入力仕様

### 入力パラメータ（スレッド作成）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| message | String | Yes | 初回メッセージ内容 | 空白不可 |
| assistant_id | Integer | Yes | 使用するアシスタントID | 存在するアシスタント |
| conversation_id | Integer | No | 閲覧中の会話ID | 存在する会話 |

### 入力パラメータ（一覧取得）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| page | Integer | No | ページ番号 | デフォルト: 1 |

### 入力データソース

- Copilotパネルからのユーザー入力

## 出力仕様

### 出力データ（スレッド一覧）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | BigInt | スレッドID |
| title | String | スレッドタイトル（初回メッセージ） |
| created_at | DateTime | 作成日時 |
| user | Object | ユーザー情報 |
| assistant | Object | アシスタント情報 |

### 出力データ（スレッド作成）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | BigInt | スレッドID |
| title | String | スレッドタイトル |
| copilot_message | Object | 作成された初回メッセージ |

### 出力先

- JSON APIレスポンス
- WebSocket経由でリアルタイム更新

## 処理フロー

### 処理シーケンス

```
1. スレッド一覧取得（index）
   └─ ユーザー別スレッドを作成日時降順で取得
   └─ ページネーション適用
2. スレッド作成（create）
   └─ メッセージ必須チェック
   └─ トランザクション開始
   └─ CopilotThread作成（title=初回メッセージ）
   └─ CopilotMessage作成（message_type=user）
   └─ 使用量制限チェック
   └─ AI応答ジョブキュー追加 or 制限メッセージ作成
   └─ トランザクションコミット
```

### フローチャート

```mermaid
flowchart TD
    A[Copilotパネル] --> B[POST /captain/copilot_threads]
    B --> C[CopilotThreadsController#create]
    C --> D{メッセージ存在?}
    D -->|No| E[422 Error]
    D -->|Yes| F[トランザクション開始]
    F --> G[CopilotThread作成]
    G --> H[CopilotMessage作成<br/>type: user]
    H --> I{使用量制限チェック}
    I -->|制限内| J[ResponseJob enqueue]
    I -->|制限超過| K[制限メッセージ作成<br/>type: assistant]
    J --> L[トランザクションコミット]
    K --> L
    L --> M[JSON応答]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-89-01 | メッセージ必須 | スレッド作成時はメッセージ必須 | 作成時 |
| BR-89-02 | タイトル自動設定 | 初回メッセージがスレッドタイトルになる | 作成時 |
| BR-89-03 | ユーザー限定 | ユーザーは自分のスレッドのみアクセス可能 | 全操作 |
| BR-89-04 | 使用量制限 | captain.responses.current_availableで制限 | AI応答時 |
| BR-89-05 | 制限超過時 | 制限超過時は定型メッセージを返却 | AI応答時 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | copilot_threads | SELECT | ユーザー別スレッド取得 |
| 作成 | copilot_threads | INSERT | スレッドレコード作成 |
| 作成 | copilot_messages | INSERT | 初回メッセージ作成 |
| 作成 | copilot_messages | INSERT | 制限メッセージ作成（制限超過時） |

### テーブル別操作詳細

#### copilot_threads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | user_id, account_id | Current.user.id, Current.account.id | ユーザー条件 |
| INSERT | title | 初回メッセージ内容 | 必須 |
| INSERT | user_id | Current.user.id | 必須 |
| INSERT | account_id | Current.account.id | 必須 |
| INSERT | assistant_id | パラメータ | 必須 |

#### copilot_messages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | copilot_thread_id | 作成したスレッドID | 必須 |
| INSERT | message | {content: メッセージ内容} | JSONB |
| INSERT | message_type | user / assistant | enum |
| INSERT | account_id | 自動設定（before_validation） | スレッドから取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 422 | CouldNotCreateError | メッセージが空 | メッセージを入力 |
| 404 | NotFound | アシスタントが存在しない | 有効なアシスタントを選択 |

### リトライ仕様

AI応答ジョブはSidekiq標準のリトライ機能に従う

## トランザクション仕様

スレッド作成とメッセージ作成はActiveRecord::Base.transactionでラップ

## パフォーマンス要件

- スレッド一覧は5件/ページのページネーション
- includes(:user, :assistant)でN+1防止

## セキュリティ考慮事項

- ユーザー認証必須
- 自分のスレッドのみアクセス可能（user_id条件）

## 備考

- Enterprise版機能
- WebSocket（COPILOT_MESSAGE_CREATED）でリアルタイム通知
- AI応答は非同期ジョブで処理

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、CopilotThreadのデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | copilot_thread.rb | `enterprise/app/models/copilot_thread.rb` | モデル定義 |

**読解のコツ**:
- **19-22行目**: belongs_to関連（user, account, assistant）
- **23行目**: has_many copilot_messages（destroy_async）
- **25行目**: titleバリデーション（presence）
- **27-35行目**: push_event_dataでWebSocket用データ生成
- **37-47行目**: previous_historyでメッセージ履歴を取得

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | copilot_threads_controller.rb | `enterprise/app/controllers/api/v1/accounts/captain/copilot_threads_controller.rb` | CRUD操作 |

**主要処理フロー**:
- **4-10行目**: indexでユーザー別スレッド取得（ページネーション）
- **12-28行目**: createでトランザクション内スレッド・メッセージ作成
- **32-41行目**: build_copilot_responseで使用量制限チェックと応答処理
- **43-45行目**: ensure_messageでメッセージ必須チェック

#### Step 3: AI応答の仕組みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | copilot_message.rb | `enterprise/app/models/copilot_message.rb` | メッセージモデル |
| 3-2 | chat_service.rb | `enterprise/app/services/captain/copilot/chat_service.rb` | Copilot ChatService |

**主要処理フロー（CopilotMessage）**:
- **40-48行目**: enqueue_response_jobでResponseJobキュー追加

**主要処理フロー（ChatService）**:
- **22-33行目**: generate_responseでLLM呼び出しと使用量インクリメント

### プログラム呼び出し階層図

```
CopilotThreadsController
    │
    ├─ index
    │      └─ copilot_threads.where(user_id:)
    │              └─ includes(:user, :assistant)
    │              └─ page().per(5)
    │
    └─ create
           │
           ├─ ensure_message
           │
           └─ transaction
                  │
                  ├─ CopilotThread.create!
                  │
                  ├─ copilot_messages.create!
                  │      └─ message_type: :user
                  │
                  └─ build_copilot_response
                         │
                         ├─ usage_limits[:captain][:responses] チェック
                         │
                         ├─ (制限内) enqueue_response_job
                         │      └─ Captain::Copilot::ResponseJob
                         │              └─ ChatService.generate_response
                         │
                         └─ (制限超過) copilot_messages.create!
                                └─ message_type: :assistant
                                └─ content: I18n.t('captain.copilot_limit')
```

### データフロー図

```
[入力]                        [処理]                         [出力]

message ───▶ CopilotThreadsController ───▶ CopilotThread
assistant_id        │                              │
conversation_id     └─ create                      └─ copilot_messages
                           │
                           └─ 使用量チェック
                                  │
                    ┌─────────────┴─────────────┐
                    ▼                           ▼
               ResponseJob              制限メッセージ作成
                    │
                    └─ ChatService
                           │
                           └─ LLM API ───▶ AI応答
                                              │
                                              └─ WebSocket配信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| copilot_threads_controller.rb | `enterprise/app/controllers/api/v1/accounts/captain/copilot_threads_controller.rb` | コントローラー | CRUD API |
| copilot_thread.rb | `enterprise/app/models/copilot_thread.rb` | モデル | スレッドデータモデル |
| copilot_message.rb | `enterprise/app/models/copilot_message.rb` | モデル | メッセージデータモデル |
| chat_service.rb | `enterprise/app/services/captain/copilot/chat_service.rb` | サービス | Copilot ChatService |
| response_job.rb | `enterprise/app/jobs/captain/copilot/response_job.rb` | ジョブ | 非同期AI応答処理 |
