# 画面設計書 109-プレイグラウンド画面

## 概要

Captain AIアシスタントをテストするためのプレイグラウンド画面設計書です。アシスタントとの会話をシミュレーションし、応答の正確性、速度、トーンを確認する機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：Captain AIアシスタントを本番環境で使用する前に、その動作を確認・テストする必要があります。プレイグラウンドは開発者や管理者がアシスタントにメッセージを送信し、期待通りの応答が返ってくるかを検証するためのサンドボックス環境です。これにより、FAQ、ドキュメント、シナリオなどの設定が正しく機能しているかを確認できます。

**画面へのアクセス方法**：Captain機能のサイドナビゲーションから「Playground」を選択してアクセスします。URLパスは `/app/accounts/:accountId/captain/:assistantId/playground` です。

**主要な操作・処理内容**：
1. アシスタントへのメッセージ送信
2. アシスタントからの応答受信
3. 会話履歴の表示
4. 会話のリセット

**画面遷移**：
- 遷移元：Captainアシスタント一覧画面、サイドナビゲーション
- 遷移先：なし（単独画面）

**権限による表示制御**：administrator および agent ロールがアクセス可能です。CAPTAINフィーチャーフラグが有効で、CloudまたはEnterpriseインストールタイプの場合のみ利用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 85 | Playground | 主機能 | アシスタントのテスト会話 |

## 画面種別

詳細 / テスト

## URL/ルーティング

| パス | ルート名 |
|------|----------|
| `/app/accounts/:accountId/captain/:assistantId/playground` | `captain_assistants_playground_index` |

## 入出力項目

### 入力項目

| 項目名 | 物理名 | 型 | 必須 | バリデーション | 備考 |
|--------|--------|-----|------|---------------|------|
| メッセージ | newMessage | string | Yes | 空文字不可 | ユーザー入力メッセージ |

### 出力項目

| 項目名 | 物理名 | 型 | 備考 |
|--------|--------|-----|------|
| メッセージ一覧 | messages | array | 会話履歴 |
| メッセージ内容 | content | string | メッセージ本文 |
| 送信者 | sender | string | 'user' または 'assistant' |
| タイムスタンプ | timestamp | datetime | メッセージ送信日時 |

## 表示項目

### ヘッダー領域

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| タイトル | "Playground" | セクションヘッダー |
| 説明 | テキスト | テスト目的の説明 |
| リセットボタン | アイコンボタン | 会話リセット |

### メッセージエリア

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| メッセージリスト | MessageList | 会話履歴表示 |
| ユーザーメッセージ | チャットバブル（右） | "You"ラベル |
| アシスタント応答 | チャットバブル（左） | "Assistant"ラベル |
| ローディング状態 | ローディングインジケータ | 応答待ち時表示 |

### 入力エリア

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 入力フィールド | テキストボックス | プレースホルダー付き |
| 送信ボタン | アイコンボタン | メッセージ空の場合は無効 |

### フッター

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| クレジット注記 | テキスト | "Messages sent here will count toward your Captain credits." |

## イベント仕様

### 1-メッセージ送信

1. メッセージ入力後、Enterキー押下または送信ボタンクリック
2. `sendMessage()` が呼び出される
3. 空文字またはローディング中の場合は処理中断
4. ユーザーメッセージを `messages` 配列に追加
5. `isLoading` を true に設定
6. `CaptainAssistant.playground()` APIを呼び出し
7. 成功時：アシスタント応答を `messages` 配列に追加
8. 失敗時：エラーをコンソールに出力
9. 最終的に `isLoading` を false に設定

### 2-会話リセット

1. リセットボタンをクリック
2. `resetConversation()` が呼び出される
3. `messages` 配列を空にする
4. `newMessage` を空文字にする

### 3-アシスタント切り替え時のリセット

1. URLパラメータの `assistantId` が変更される
2. watchで変更を検知（32-40行目）
3. 新旧IDが異なる場合、`resetConversation()` を呼び出し
4. 会話履歴をクリア

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| プレイグラウンドAPI呼び出し | - | API | アシスタントへの問い合わせ |

### API仕様

プレイグラウンド機能はデータベースへの永続的な保存を行いません。APIはリアルタイムでAIモデルに問い合わせを行い、応答を返します。

#### playground API

| メソッド | エンドポイント | 備考 |
|---------|---------------|------|
| POST | `/api/v1/accounts/:accountId/captain/assistants/:assistantId/playground` | アシスタントテスト |

#### リクエストボディ

```json
{
  "message_content": "ユーザーメッセージ",
  "message_history": [
    { "role": "user", "content": "過去のメッセージ" },
    { "role": "assistant", "content": "過去の応答" }
  ]
}
```

#### レスポンスボディ

```json
{
  "response": "アシスタントの応答テキスト"
}
```

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 |
|------|---------------|---------------|
| 説明 | CAPTAIN.PLAYGROUND.HEADER | "Playground" |
| 説明 | CAPTAIN.PLAYGROUND.DESCRIPTION | テスト目的の説明 |
| プレースホルダー | CAPTAIN.PLAYGROUND.MESSAGE_PLACEHOLDER | "Type your message..." |
| 注記 | CAPTAIN.PLAYGROUND.CREDIT_NOTE | "Messages sent here will count toward your Captain credits." |
| ラベル | CAPTAIN.PLAYGROUND.USER | "You" |
| ラベル | CAPTAIN.PLAYGROUND.ASSISTANT | "Assistant" |

## 例外処理

| 例外条件 | 処理内容 | 表示 |
|----------|----------|------|
| API通信エラー | コンソールにエラー出力 | 特別な表示なし |
| 空メッセージ送信試行 | 処理中断 | 送信ボタン無効状態 |
| ローディング中の送信試行 | 処理中断 | 送信ボタンが応答待ち状態 |

## 備考

- プレイグラウンドでのメッセージはCaptainクレジットを消費
- 会話履歴はフロントエンドのメモリにのみ保持（リロードでクリア）
- 会話履歴はAPIリクエストに含められ、コンテキストとして使用
- アシスタント切り替え時は自動的に会話がリセット
- MessageListコンポーネントで会話履歴を表示

---

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

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

### 推奨読解順序

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

まず、メッセージデータの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AssistantPlayground.vue | `app/javascript/dashboard/components-next/captain/assistant/AssistantPlayground.vue` | messagesの構造（content, sender, timestamp）を確認 |

**読解のコツ**: メッセージはローカルステート（ref）で管理され、APIリクエスト時に `formatMessagesForApi()` でフォーマット変換されます。

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

処理の起点となるVueコンポーネントを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue (playground) | `app/javascript/dashboard/routes/dashboard/captain/assistants/playground/Index.vue` | ページラッパーの構造を確認 |
| 2-2 | AssistantPlayground.vue | `app/javascript/dashboard/components-next/captain/assistant/AssistantPlayground.vue` | 実際のプレイグラウンド実装を確認 |

**主要処理フロー（AssistantPlayground.vue）**:
1. **16-17行目**: `messages`, `newMessage`, `isLoading` のref定義
2. **20-25行目**: `formatMessagesForApi()` で履歴をAPI形式に変換
3. **27-30行目**: `resetConversation()` でリセット処理
4. **32-40行目**: watchでassistantId変更時のリセット
5. **42-73行目**: `sendMessage()` でメッセージ送信

#### Step 3: API通信を理解する

プレイグラウンドAPI呼び出しを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | assistant.js (api) | `app/javascript/dashboard/api/captain/assistant.js` | playgroundメソッドを確認（18-23行目） |

**主要処理フロー**:
- **18-23行目**: `playground()` メソッドでPOSTリクエスト
- リクエストボディ：`message_content`, `message_history`

#### Step 4: メッセージ表示を理解する

メッセージリスト表示の実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MessageList.vue | `app/javascript/dashboard/components-next/captain/assistant/MessageList.vue` | メッセージ描画コンポーネントを確認 |

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

```
Index.vue (playground)
    |
    +-- PageLayout.vue
    |       |
    |       +-- show-assistant-switcher (アシスタント切り替え)
    |       +-- show-pagination-footer=false
    |       +-- show-know-more=false
    |
    +-- AssistantPlayground.vue
            |
            +-- タイトル・説明表示
            |
            +-- リセットボタン
            |       |
            |       +-- @click -> resetConversation()
            |
            +-- MessageList.vue
            |       |
            |       +-- messages配列を描画
            |       +-- isLoadingでローディング表示
            |
            +-- 入力フィールド
            |       |
            |       +-- v-model -> newMessage
            |       +-- @keyup.enter -> sendMessage()
            |
            +-- 送信ボタン
            |       |
            |       +-- @click -> sendMessage()
            |       +-- :disabled -> !newMessage.trim()
            |
            +-- クレジット注記
```

### データフロー図

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

メッセージ入力 ────────▶ sendMessage()
                              │
                              ├── ユーザーメッセージをmessagesに追加
                              │
                              ├── formatMessagesForApi()
                              │       │
                              │       └── {role, content}形式に変換
                              │
                              ▼
                        CaptainAssistant.playground()
                              │
                              ▼
                        POST /api/v1/.../captain/assistants/:id/playground
                              │
                              ▼
                        応答受信
                              │
                              ▼
                        アシスタント応答をmessagesに追加
                              │
                              ▼
                        MessageList描画 ────────▶ 会話履歴表示

リセットボタン ────────▶ resetConversation()
                              │
                              ▼
                        messages = []
                        newMessage = ''
                              │
                              ▼
                        MessageList再描画 ────────▶ 空表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/captain/assistants/playground/Index.vue` | ソース | ページラッパー |
| captain.routes.js | `app/javascript/dashboard/routes/dashboard/captain/captain.routes.js` | 設定 | ルーティング定義 |
| AssistantPlayground.vue | `app/javascript/dashboard/components-next/captain/assistant/AssistantPlayground.vue` | ソース | プレイグラウンド本体 |
| MessageList.vue | `app/javascript/dashboard/components-next/captain/assistant/MessageList.vue` | ソース | メッセージリスト表示 |
| assistant.js (api) | `app/javascript/dashboard/api/captain/assistant.js` | ソース | APIクライアント |
| PageLayout.vue | `app/javascript/dashboard/components-next/captain/PageLayout.vue` | ソース | ページレイアウト |
| Button.vue | `app/javascript/dashboard/components-next/button/Button.vue` | ソース | ボタンコンポーネント |
