# 画面設計書 16-ワークスペース一覧画面

## 概要

本ドキュメントは、Giselle Studio の「ワークスペース一覧画面」に関する画面設計書である。チームが所有するワークスペース（エージェント）の一覧表示、検索、フィルタリング機能を提供する画面を定義する。

### 本画面の処理概要

**業務上の目的・背景**：ユーザーが所属するチームのワークスペース（AIエージェント）を一覧形式で管理・閲覧できるようにする。ワークスペースの検索、ソート、表示モード切替（グリッド/リスト）により、効率的なワークスペース管理を実現する。

**画面へのアクセス方法**：グローバルナビゲーションの「Agents」メニュー、またはロビー画面からアクセス可能。

**主要な操作・処理内容**：
1. ワークスペース一覧の表示（グリッド/リストビュー切替）
2. ワークスペース名での検索
3. ソート機能（名前順/日付順、昇順/降順）
4. 各ワークスペースの詳細表示（実行回数、作成者、連携サービスなど）
5. ワークフローエディタ画面への遷移

**画面遷移**：
- 遷移元：ロビー画面（/lobby）、グローバルナビゲーション
- 遷移先：ワークフローエディタ画面（/workspaces/[workspaceId]）、プレイグラウンド画面（/playground）

**権限による表示制御**：認証済みユーザーのみアクセス可能。表示されるワークスペースは現在選択中のチームに紐づく。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ワークスペース取得 | 主機能 | チームのワークスペース（エージェント）一覧を取得・表示 |
| 1 | ワークスペース作成 | 補助機能 | 新規ワークスペース作成ダイアログからの作成処理 |
| 34 | トリガー取得 | API連携 | ワークスペースに設定されたトリガー情報の取得 |
| 40 | リポジトリ名取得 | API連携 | GitHubリポジトリ名の非同期取得 |

## 画面種別

一覧画面

## URL/ルーティング

`/workspaces`

## 入出力項目

| 項目名 | 項目ID | 入出力 | 必須 | データ型 | 制約・バリデーション |
|--------|--------|--------|------|----------|---------------------|
| 検索キーワード | searchQuery | 入力 | 任意 | string | フリーテキスト |
| ソートオプション | sortOption | 入力 | 任意 | string | name-asc, name-desc, date-desc, date-asc |
| 表示モード | viewMode | 入力 | 任意 | string | grid, list |

## 表示項目

| 項目名 | 説明 | データソース |
|--------|------|-------------|
| ワークスペース名 | エージェントの名前 | agents.name |
| 更新日時 | 最終更新日時 | agents.updatedAt |
| 実行回数 | タスク実行回数 | acts テーブルからカウント |
| 作成者 | ワークスペース作成者情報 | users テーブル（displayName, avatarUrl） |
| GitHub連携リポジトリ | 連携しているGitHubリポジトリ名 | ワークスペースノードから抽出 |
| ドキュメントファイル | ベクトルストアに登録されたドキュメント名 | documentVectorStores から抽出 |
| LLMプロバイダ | 使用している言語モデルプロバイダ | ワークスペースノードから抽出 |

## イベント仕様

### 1-ワークスペース検索

**トリガー**: 検索フィールドへの入力

**処理フロー**:
1. searchQueryステートを更新
2. filteredAgentsを再計算（useMemoによるメモ化）
3. ワークスペース名に検索キーワードが含まれるもののみ表示

### 2-ソート変更

**トリガー**: ソートドロップダウンで選択

**処理フロー**:
1. sortOptionステートを更新
2. sortedAgentsを再計算（useMemoによるメモ化）
3. 選択されたソート順序でリストを並び替え

### 3-表示モード切替

**トリガー**: グリッド/リストアイコンをクリック

**処理フロー**:
1. viewModeステートを更新（grid/list）
2. 対応するビューコンポーネント（AgentCard/AppListItem）を表示

### 4-ワークスペース選択

**トリガー**: ワークスペースカード/行をクリック

**処理フロー**:
1. /workspaces/{workspaceId} へ遷移
2. ワークフローエディタ画面を表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧取得 | agents | SELECT | チームに紐づくエージェント一覧取得 |
| 一覧取得 | acts | SELECT | 各ワークスペースの実行回数取得 |
| 一覧取得 | users | SELECT | 作成者情報取得 |

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

#### agents（SELECT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, dbId, teamDbId, name, workspaceId, graphUrl, createdAt, updatedAt, creatorDbId, metadata | WHERE teamDbId = 現在チームのdbId AND workspaceId IS NOT NULL | ORDER BY updatedAt DESC |

#### acts（SELECT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | count(dbId) | WHERE teamDbId = チームID AND sdkWorkspaceId IN (ワークスペースID一覧) | GROUP BY sdkWorkspaceId |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|-------------|---------------|----------|
| 空状態 | no_workspaces | No workspaces yet. | ワークスペースが0件の場合 |
| 空状態説明 | create_hint | Please create a new workspace with the 'New Workspace +' button. | ワークスペースが0件の場合 |
| 検索結果なし | no_results | No workspaces found. | 検索結果が0件の場合 |
| 検索ヒント | search_hint | Try searching with a different keyword. | 検索結果が0件の場合 |

## 例外処理

| 例外状況 | 処理内容 | ユーザーへの通知 |
|---------|---------|----------------|
| データ取得エラー | コンソールにエラー出力 | なし（サイレント） |
| GitHub情報取得エラー（404） | スキップして続行 | なし（サイレント） |
| ワークスペースデータ不正 | スキップ（workspaceIdがnullの場合） | なし |

## 備考

- 一覧データはサーバーサイドで取得し、Suspenseでローディング状態を管理
- GitHub連携情報はワークスペースのノードデータを解析して抽出（VectorStoreNode, TriggerNode, ActionNode）
- ドキュメントベクトルストア情報はチーム単位で一括取得後、ワークスペースごとにマッピング
- LLMプロバイダ情報はTextGenerationNodeから抽出
- サンプルワークスペースは作成者名を「Giselle Team」として表示

---

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

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

### 推奨読解順序

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

エージェント情報の型定義とクエリ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | page.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/page.tsx` | AgentWithMetadata型の推測（17-35行目のPromise型から） |

**読解のコツ**: agents テーブルの基本カラムに加え、executionCount、creator、githubRepositories、documentVectorStoreFiles、llmProviders、hasGithubIntegrationが追加されている。

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

Server Componentでのデータ取得とSuspense構成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | page.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/page.tsx` | agentsQuery関数（54-288行目）、ページコンポーネント（290-300行目） |

**主要処理フロー**:
1. **291行目**: fetchCurrentTeam()で現在のチーム取得
2. **292行目**: agentsQuery(teamDbId)でエージェント一覧取得（Promise）
3. **295-297行目**: SuspenseでAgentListをラップ
4. **55-73行目**: agentsQueryでDrizzle ORMによるクエリ実行
5. **76-99行目**: 実行回数カウントの取得
6. **120-262行目**: ワークスペースノード解析（GitHub、ドキュメント、LLM情報抽出）

#### Step 3: クライアントコンポーネントを理解する

検索、ソート、表示モード切替の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | searchable-agent-list.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/searchable-agent-list.tsx` | ステート管理（33-35行目）、フィルタリング（38-45行目）、ソート（48-63行目） |

**主要処理フロー**:
- **33-35行目**: searchQuery, sortOption, viewModeのステート定義
- **38-45行目**: useMemoでfilteredAgentsを計算（名前検索）
- **48-63行目**: useMemoでsortedAgentsを計算（ソート適用）
- **89-94行目**: グリッドビューでAgentCardを表示
- **96-154行目**: リストビューでAppListItemを表示

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

```
page.tsx (Server Component)
    │
    ├─ fetchCurrentTeam() ─── services/teams
    │
    ├─ agentsQuery(teamDbId)
    │      │
    │      ├─ db.select().from(agents) ─── Drizzle ORM
    │      │      └─ leftJoin(users)
    │      │
    │      ├─ db.select().from(acts) ─── 実行回数カウント
    │      │
    │      ├─ getDocumentVectorStores() ─── ドキュメントストア取得
    │      │
    │      └─ giselle.getWorkspace() ─── 各ワークスペース詳細
    │             │
    │             ├─ isTextGenerationNode() ─── LLMプロバイダ抽出
    │             ├─ isVectorStoreNode() ─── ベクトルストア情報抽出
    │             ├─ isTriggerNode() ─── トリガー情報抽出
    │             └─ isActionNode() ─── アクション情報抽出
    │
    └─ SearchableAgentList (Client Component)
           │
           ├─ SearchHeader ─── 検索・ソート・表示モードUI
           │
           ├─ AgentCard ─── グリッドビュー用カード
           │
           └─ AppListItem ─── リストビュー用行
```

### データフロー図

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

チームID ────────────▶ agentsQuery() ───────────────▶ エージェント一覧
                             │
                             ├─ agents SELECT
                             ├─ acts COUNT
                             ├─ users JOIN
                             └─ workspace解析
                                    │
                                    ▼
                             SearchableAgentList
                                    │
検索キーワード ─────────▶ filteredAgents ─────────────▶ フィルタ済み一覧
ソートオプション ───────▶ sortedAgents ───────────────▶ ソート済み一覧
表示モード ──────────────▶ viewMode ────────────────────▶ Grid/List表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| page.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/page.tsx` | ソース | ページエントリーポイント（Server Component） |
| searchable-agent-list.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/searchable-agent-list.tsx` | ソース | 検索・ソート可能一覧（Client Component） |
| agent-card.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/agent-card.tsx` | ソース | グリッドビュー用カード |
| app-list-item.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/app-list-item.tsx` | ソース | リストビュー用行 |
| search-header.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/search-header.tsx` | ソース | 検索ヘッダーUI |
| llm-provider-icon.tsx | `apps/studio.giselles.ai/app/(main)/workspaces/components/llm-provider-icon.tsx` | ソース | LLMプロバイダアイコン |
