# 画面設計書 31-GitHub Vector Store設定画面

## 概要

GitHubリポジトリをベクターストアとして管理するための設定画面。チームが所有するGitHubリポジトリのコード、Issue、プルリクエストをベクターストアにインジェストし、AIワークフロー内でGitHub Vector Storeノードとして利用可能にする。

### 本画面の処理概要

**業務上の目的・背景**：AIワークフローでGitHubリポジトリの情報（ソースコード、Issue、プルリクエスト）を活用するためには、事前にリポジトリのデータをベクトル化（埋め込み生成）してベクターストアに格納する必要がある。本画面は、その設定と管理を行うためのインターフェースを提供する。これにより、ワークフローエディタでGitHub Vector Storeノードを利用してコードベースの検索やIssue/PR情報の参照が可能になる。

**画面へのアクセス方法**：設定画面 > チーム設定 > Vector Stores から「GitHub」タブ（デフォルト）を選択してアクセスする。URLは `/settings/team/vector-stores`。

**主要な操作・処理内容**：
1. リポジトリの登録：「Register Repository」ボタンからダイアログを開き、GitHub Appがインストールされたオーナー/組織とリポジトリを選択し、インジェスト対象（Code、Issues、Pull Requests）と埋め込みモデルを設定して登録する
2. リポジトリ一覧の表示：登録済みリポジトリをカード形式で表示し、各リポジトリのインジェスト状況（idle/running/completed/failed）を確認できる
3. 手動インジェスト：各リポジトリのアクションメニューから手動でインジェスト処理をトリガーできる
4. インジェスト設定の変更：コンテンツタイプ（Code/Issues/Pull Requests）や埋め込みモデルの設定を更新できる
5. リポジトリの削除：不要になったリポジトリを削除してベクターストアから除去する
6. 公式リポジトリの利用：Giselle公式が提供する公式リポジトリ（読み取り専用）も利用可能

**画面遷移**：
- 前画面：設定画面（/settings）またはチーム設定画面（/settings/team）
- 関連画面：ドキュメントVector Store設定画面（/settings/team/vector-stores/document）

**権限による表示制御**：
- プランによる制限：Free プランでは GitHub Vector Stores が利用不可（ロック状態で表示）
- Pro/Team プランでは利用可能だが、プランごとに最大ストア数の制限がある
- GitHub認証未完了の場合、認証を促すカードが表示される
- GitHub Appが未インストールの場合、インストールを促すカードが表示される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | クエリサービス | 主機能 | GitHubリポジトリのベクターストア設定と管理 |
| 78 | インジェストパイプライン | 補助機能 | リポジトリデータのベクトルストアへの取り込み処理 |
| 39 | リポジトリ一覧取得 | API連携 | 連携可能なGitHubリポジトリの取得 |

## 画面種別

一覧・登録・編集・削除

## URL/ルーティング

`/settings/team/vector-stores`

## 入出力項目

### リポジトリ登録ダイアログ

| 項目名 | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| Owner / Organization | 入力 | string | 必須 | GitHub App がインストールされたオーナー/組織を選択 |
| Repository Name | 入力 | string | 必須 | インジェスト対象のリポジトリを選択 |
| Code | 入力 | boolean | - | ソースコードファイルをインジェスト（必須・常にON） |
| Issues | 入力 | boolean | - | Issueのタイトル、説明、コメントをインジェスト |
| Pull Requests | 入力 | boolean | - | マージ済みPRのコンテンツとディスカッションをインジェスト |
| Embedding Models | 入力 | number[] | 必須 | 埋め込み生成に使用するモデル（複数選択可） |

## 表示項目

### リポジトリ一覧

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| リポジトリ名 | string | owner/repo 形式で表示 |
| インジェスト状況 | enum | idle/running/completed/failed のいずれか |
| コンテンツタイプ | enum[] | 有効化されているコンテンツタイプ（blob/issue/pull_request） |
| 埋め込みプロファイル | object[] | 設定されている埋め込みモデル情報 |
| 使用状況 | string | 現在の使用数 / 最大数の形式で表示 |

### 公式リポジトリセクション

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| リポジトリ名 | string | Giselle公式が提供するリポジトリ |
| 状態 | enum | 読み取り専用のインジェスト状況 |

## イベント仕様

### 1-リポジトリ登録ボタン押下

「Register Repository」ボタン押下でダイアログが開き、フォーム入力後に「Register」ボタンでリポジトリを登録する。

1. 入力値のバリデーション（Owner、Repository必須）
2. `registerRepositoryIndex` Server Action を呼び出し
3. GitHubアクセス権限の検証（ユーザーがリポジトリにアクセスできるか確認）
4. プランのクォータ確認（最大ストア数に達していないか）
5. `github_repository_index` テーブルにレコード挿入
6. `github_repository_embedding_profiles` テーブルに埋め込みプロファイル挿入
7. `github_repository_content_status` テーブルにコンテンツ状態挿入
8. 成功時：ダイアログを閉じ、一覧を更新（revalidatePath）
9. 失敗時：エラーメッセージを表示

### 2-手動インジェストボタン押下

リポジトリのアクションメニューから「Ingest」を選択してインジェスト処理をトリガーする。

1. `triggerManualIngest` Server Action を呼び出し
2. リポジトリとコンテンツ状態の取得
3. インジェスト可能かどうかの判定（ステータスがrunning中でないか等）
4. バックグラウンドで `processRepository` を実行
5. 即座に一覧を更新（running状態を表示）

### 3-リポジトリ削除ボタン押下

リポジトリのアクションメニューから「Delete」を選択してリポジトリを削除する。

1. 確認ダイアログを表示
2. `deleteRepositoryIndex` Server Action を呼び出し
3. `github_repository_index` テーブルからレコード削除（関連テーブルもカスケード削除）
4. 一覧を更新（revalidatePath）

### 4-設定変更ボタン押下

リポジトリのアクションメニューから「Configure Sources」を選択して設定を変更する。

1. 設定ダイアログを開く
2. コンテンツタイプと埋め込みプロファイルを変更
3. `updateRepositoryIndex` Server Action を呼び出し
4. 既存プロファイルとの差分を計算し、追加/削除を実行
5. コンテンツ状態を更新
6. 一覧を更新（revalidatePath）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| リポジトリ登録 | github_repository_index | INSERT | リポジトリインデックスの新規作成 |
| リポジトリ登録 | github_repository_embedding_profiles | INSERT | 埋め込みプロファイルの関連付け |
| リポジトリ登録 | github_repository_content_status | INSERT | 各コンテンツタイプの状態を初期化 |
| リポジトリ削除 | github_repository_index | DELETE | リポジトリインデックスの削除 |
| 設定変更 | github_repository_embedding_profiles | DELETE/INSERT | プロファイルの差し替え |
| 設定変更 | github_repository_content_status | UPSERT | コンテンツ状態の更新 |
| 手動インジェスト | github_repository_content_status | UPDATE | ステータスをrunningに更新 |

### テーブル別更新項目詳細

#### github_repository_index

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | `gthbi_${cuid2}` | 一意のリポジトリインデックスID |
| INSERT | owner | 選択されたリポジトリのオーナー名 | GitHubオーナー/組織名 |
| INSERT | repo | 選択されたリポジトリ名 | GitHubリポジトリ名 |
| INSERT | team_db_id | 現在のチームのDB ID | チームとの関連付け |
| INSERT | installation_id | GitHub App インストールID | API呼び出しに使用 |

#### github_repository_embedding_profiles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | repository_index_db_id | 親リポジトリのDB ID | 外部キー |
| INSERT | embedding_profile_id | 選択された埋め込みプロファイルID | 1:OpenAI Small, 2:OpenAI Largeなど |
| INSERT | created_at | 現在日時 | 作成日時 |

#### github_repository_content_status

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPSERT | repository_index_db_id | 親リポジトリのDB ID | 外部キー |
| INSERT/UPSERT | embedding_profile_id | 埋め込みプロファイルID | 複合キーの一部 |
| INSERT/UPSERT | content_type | blob/issue/pull_request | コンテンツ種別 |
| INSERT/UPSERT | enabled | true/false | 有効/無効 |
| INSERT/UPSERT | status | idle/running/completed/failed | インジェスト状態 |
| UPDATE | error_code | エラーコード | 失敗時のエラー情報 |
| UPDATE | retry_after | リトライ可能日時 | レート制限時に設定 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|---------|
| 成功 | （ダイアログクローズ） | リポジトリ登録成功時 |
| エラー | Owner is required | オーナー未選択時 |
| エラー | Repository is required | リポジトリ未選択時 |
| エラー | Repository {owner}/{repo} is already registered for this team | 重複登録時 |
| エラー | GitHub Vector Stores are not included in your plan. | Freeプランで登録試行時 |
| エラー | You've reached the maximum number of GitHub Vector Stores included in your plan. | クォータ超過時 |
| エラー | GitHub account authentication is required | GitHub認証未完了時 |
| エラー | Installation not found | GitHub Appインストールが見つからない場合 |
| エラー | You don't have access to this repository | リポジトリへのアクセス権がない場合 |
| エラー | Failed to register repository. Please try again. | 登録処理の一般エラー |
| 情報 | No repositories are registered. | リポジトリ未登録時の空状態表示 |
| 警告 | GitHub Vector Stores are not included in the {plan} plan | Freeプランでのロック表示 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| GitHub認証未完了 | GitHubAuthRequiredCard を表示し、認証を促す |
| GitHub認証エラー | GitHubAuthErrorCard を表示し、エラーメッセージを表示 |
| GitHub App未インストール | GitHubAppInstallRequiredCard を表示し、インストールを促す |
| プラン制限 | GitHubVectorStoreLockedCard を表示し、プランアップグレードを促す |
| クォータ超過 | 登録ボタンを無効化し、ツールチップで理由を表示 |
| API呼び出しエラー | エラーメッセージを表示し、リトライを促す |

## 備考

- コード（blob）コンテンツタイプは必須であり、無効化できない
- 埋め込みプロファイルは最低1つ選択する必要がある
- インジェスト処理はバックグラウンドで実行され、完了まで数分〜数十分かかる場合がある
- 公式リポジトリは読み取り専用で、設定変更や削除はできない

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/types.ts` | ActionResult, InstallationWithRepos, DiagnosticResult などの型定義を確認 |
| 1-2 | github.ts (RepositoryWithStatuses) | `apps/studio.giselles.ai/lib/vector-stores/github/index.ts` | リポジトリとコンテンツ状態を含むデータ構造 |

**読解のコツ**: TypeScriptの型定義を先に理解することで、データの流れが把握しやすくなる。

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

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | page.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/page.tsx` | Server Component としてのページレンダリング |

**主要処理フロー**:
1. **行25-28**: GitHubIdentityState と公式リポジトリを並列取得
2. **行30-49**: 認証状態に応じたエラーカード表示の分岐
3. **行51-60**: GitHub Appインストール状態の確認
4. **行62-68**: リポジトリ一覧、チーム情報、クォータの取得
5. **行79-98**: RepositoryRegistrationDialog と RepositoryList のレンダリング

#### Step 3: データ取得層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | data.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/data.ts` | リポジトリインデックスとGitHub連携情報の取得関数 |

**主要処理フロー**:
- **行21-67**: fetchRepositoryIndexes - DBからリポジトリとコンテンツ状態を結合取得
- **行95-141**: getInstallationsWithRepos - GitHub APIからインストールとリポジトリ一覧を取得

#### Step 4: Server Actions を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | actions.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/actions.ts` | リポジトリ登録・更新・削除・インジェストのサーバーアクション |

**主要処理フロー**:
- **行62-117**: validateGitHubAccess - GitHub APIアクセス権限の検証
- **行119-263**: registerRepositoryIndex - リポジトリ登録（トランザクション内でクォータ確認）
- **行269-421**: updateRepositoryIndex - リポジトリ設定の更新
- **行423-434**: deleteRepositoryIndex - リポジトリの削除
- **行566-605**: triggerManualIngest - 手動インジェストのトリガー

#### Step 5: UIコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | repository-registration-dialog.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-registration-dialog.tsx` | リポジトリ登録ダイアログのUI実装 |
| 5-2 | repository-list.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-list.tsx` | リポジトリ一覧の表示コンポーネント |
| 5-3 | repository-item.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-item.tsx` | 個別リポジトリカードの表示 |

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

```
TeamVectorStorePage (page.tsx)
    │
    ├─ getGitHubIdentityState() ─────────────────────────▶ GitHub認証状態取得
    │
    ├─ getOfficialGitHubRepositoryIndexes() ─────────────▶ 公式リポジトリ取得
    │
    ├─ userClient.getInstallations() ────────────────────▶ GitHub App インストール取得
    │
    ├─ getInstallationsWithRepos() ──────────────────────▶ リポジトリ一覧取得
    │      └─ userClient.getRepositories()
    │
    ├─ getGitHubRepositoryIndexes() ─────────────────────▶ 登録済みリポジトリ取得
    │      └─ fetchRepositoryIndexes()
    │             └─ DB Query (githubRepositoryIndex + githubRepositoryContentStatus)
    │
    ├─ fetchCurrentTeam() ───────────────────────────────▶ チーム情報取得
    │
    └─ getGitHubVectorStoreQuota() ──────────────────────▶ クォータ計算
```

### データフロー図

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

GitHub App                      ┌─────────────────────┐
Installation ───────────────▶   │ getInstallations    │
                                │ WithRepos()         │ ─────────▶ InstallationWithRepos[]
                                └─────────────────────┘

User Selection                  ┌─────────────────────┐
(owner/repo/contentTypes) ──▶   │ registerRepository  │
                                │ Index()             │ ─────────▶ DB Insert
                                └─────────────────────┘             (github_repository_index,
                                        │                            github_repository_embedding_profiles,
                                        ▼                            github_repository_content_status)
                                ┌─────────────────────┐
                                │ validateGitHubAccess│
                                │ ()                  │ ─────────▶ 権限検証結果
                                └─────────────────────┘

DB Records                      ┌─────────────────────┐
(github_repository_index) ──▶   │ getGitHubRepository │
                                │ Indexes()           │ ─────────▶ RepositoryWithStatuses[]
                                └─────────────────────┘
                                        │
                                        ▼
                                ┌─────────────────────┐
                                │ RepositoryList      │ ─────────▶ 画面表示
                                └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| page.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/page.tsx` | ソース | ページのエントリーポイント（Server Component） |
| actions.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/actions.ts` | ソース | Server Actions（登録・更新・削除・インジェスト） |
| data.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/data.ts` | ソース | データ取得関数 |
| types.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/types.ts` | ソース | 型定義 |
| repository-list.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-list.tsx` | ソース | リポジトリ一覧表示コンポーネント |
| repository-item.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-item.tsx` | ソース | リポジトリカードコンポーネント |
| repository-registration-dialog.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/repository-registration-dialog.tsx` | ソース | 登録ダイアログコンポーネント |
| status-cards.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/status-cards.tsx` | ソース | 認証状態エラーカードコンポーネント |
| official-repository-section.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/official-repository-section.tsx` | ソース | 公式リポジトリセクションコンポーネント |
| github-embedding-profiles.ts | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/github-embedding-profiles.ts` | ソース | 埋め込みプロファイルの定義 |
| layout.tsx | `apps/studio.giselles.ai/app/(main)/settings/team/vector-stores/layout.tsx` | ソース | Vector Storesのレイアウト |
