# 機能設計書 93-ワークフローデザイナー

## 概要

本ドキュメントは、GiselleプラットフォームにおけるビジュアルワークフローエディターUI機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：AIワークフローを視覚的に設計・編集するためのインタラクティブなUIを提供する。ユーザーはノードベースのインターフェースを通じて、テキスト生成、画像生成、GitHub連携などの各種ノードを配置・接続し、複雑なAIワークフローを直感的に構築できる。

**機能の利用シーン**：
- 新規ワークフローの設計・作成
- 既存ワークフローの編集・修正
- ノード間の接続（データフロー）の定義
- ワークフローのプレビュー・テスト実行
- チーム内でのワークフロー共有・閲覧

**主要な処理内容**：
1. React Flowベースのノードグラフ描画・操作
2. 各種ノードタイプ（テキスト生成、画像生成、トリガー、アクション等）の追加・編集
3. ノード間の接続管理（入出力の定義）
4. プロパティパネルによるノード設定の詳細編集
5. ワークスペース状態の自動保存（debounce付き）
6. リードオンリーモード・権限に応じた表示制御
7. キーボードショートカットによる操作
8. ワークスペースツアー（初回利用時のガイド）

**関連システム・外部連携**：
- Giselle API（ワークスペースの保存・読み込み）
- 各種AIプロバイダー（テキスト生成、画像生成のプレビュー）
- GitHub連携（トリガー・アクション設定）

**権限による制御**：viewer/guest/editor/ownerの4種類のロールに応じて編集可否が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主機能 | ワークスペースデータの読み込み・表示・編集 |

## 機能種別

UI / ビジュアルエディター / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| isReadOnly | boolean | No | 読み取り専用モード | デフォルト: false |
| userRole | "viewer" \| "guest" \| "editor" \| "owner" | No | ユーザーの権限ロール | デフォルト: "viewer" |
| onFlowNameChange | (name: string) => Promise<void> | No | フロー名変更時のコールバック | - |
| teamName | string | No | チーム名（ヘッダー表示用） | - |
| teamAvatarUrl | string \| null | No | チームアバターURL | - |

### 入力データソース

- AppDesignerStoreからのワークスペースデータ（Workspace型）
- 言語モデルプロバイダー一覧（LanguageModelProvider[]）
- GiselleClient（APIクライアント）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Workspace | Workspace | 編集後のワークスペースデータ |
| UI State | V2LayoutState | UIのレイアウト状態 |

### 出力先

- Giselle API（ワークスペース保存）
- 画面表示（React Flow Canvas）

## 処理フロー

### 処理シーケンス

```
1. 初期化処理
   └─ AppDesignerProviderでストア初期化 → 初期ワークスペースデータのロード → React Flow初期化

2. ノード追加処理
   └─ ツールバーからノードタイプ選択 → ストアにノード追加 → React Flowで描画 → 永続化

3. 接続処理
   └─ ソースハンドルからドラッグ → ターゲットハンドルにドロップ → 接続バリデーション → ストアに接続追加

4. プロパティ編集処理
   └─ ノード選択 → プロパティパネル表示 → 設定変更 → ストア更新 → 永続化

5. 自動保存処理
   └─ ストア変更検知 → debounce待機（1500ms） → Giselle APIに保存
```

### フローチャート

```mermaid
flowchart TD
    A[Editor起動] --> B[AppDesignerProvider初期化]
    B --> C[ワークスペースデータロード]
    C --> D[React Flow初期化]
    D --> E{初回起動?}
    E -->|Yes| F[ワークスペースツアー表示]
    E -->|No| G[エディタ表示]
    F --> G

    G --> H{ユーザー操作}
    H -->|ノード追加| I[ツールバーからノード選択]
    I --> J[ストアにノード追加]
    J --> K[React Flow再描画]
    K --> L[永続化トリガー]

    H -->|接続| M[ハンドルドラッグ]
    M --> N[接続バリデーション]
    N --> O{有効な接続?}
    O -->|Yes| P[ストアに接続追加]
    O -->|No| Q[接続キャンセル]
    P --> K

    H -->|プロパティ編集| R[ノード選択]
    R --> S[プロパティパネル表示]
    S --> T[設定変更]
    T --> U[ストア更新]
    U --> L

    L --> V[debounce待機]
    V --> W[Giselle API保存]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 自動保存 | ストア変更後、1500msのdebounce後に自動保存 | 常時 |
| BR-002 | リードオンリーモード | isReadOnly=trueの場合、編集操作を無効化 | isReadOnly=true |
| BR-003 | 接続バリデーション | 入力と出力の型互換性をチェック | 接続作成時 |
| BR-004 | 初回ツアー | ノードが0個の場合、ワークスペースツアーを表示 | 初回起動時 |
| BR-005 | beforeunload確認 | 未保存変更がある場合、ページ離脱時に確認ダイアログ表示 | ページ離脱時 |
| BR-006 | ルート変更時保存 | ルート変更時に未保存データをフラッシュ | ルート変更時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ワークスペース保存 | workspaces | UPDATE | ワークスペースJSONの更新 |

※直接のDB操作はGiselle APIを通じて行われる

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SAVE_FAILED | 保存失敗 | APIエラー | リトライまたはユーザーに通知 |
| INVALID_CONNECTION | 接続不正 | 型互換性なし | 接続を拒否 |
| MISSING_PROVIDER | プロバイダー不在 | AppDesignerProviderがツリーにない | エラースロー |

### リトライ仕様

- 保存失敗時のリトライはアプリケーション層で実装（bestEffort保存あり）

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

- ローカルストア（Zustand）での状態管理
- 永続化はAPI呼び出しで非同期実行

## パフォーマンス要件

- ノード操作のリアルタイムレスポンス
- 大規模ワークフロー（100ノード以上）での安定動作
- debounceによるAPI呼び出し最適化

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

- ユーザー権限に応じた編集制御
- XSS防止（React標準のエスケープ）
- CSRF対策（APIトークン使用）

## 備考

- React Flowライブラリをベースに構築
- Zustandで状態管理
- 機能フラグ（layoutV3）による新レイアウトの段階的導入

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app-designer-store.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/app-designer-store.ts` | AppDesignerStoreStateの構造（WorkspaceSlice, AppSlice, UiSlice） |
| 1-2 | state.ts | `internal-packages/workflow-designer-ui/src/editor/v2/state.ts` | V2LayoutState、LeftPanelValueの定義 |

**読解のコツ**: Zustandのスライスパターンを理解する。各スライス（workspace-slice, app-slice, ui-slice）が独立した状態とアクションを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.tsx | `internal-packages/workflow-designer-ui/src/editor/index.tsx` | Editorコンポーネントのエントリーポイント |
| 2-2 | v2-placeholder.tsx | `internal-packages/workflow-designer-ui/src/editor/v2/v2-placeholder.tsx` | V2Placeholderの実装（メインUI構造） |

**主要処理フロー**:
1. **6-28行目（index.tsx）**: Editorコンポーネント定義、V2Placeholderへの委譲
2. **14-112行目（v2-placeholder.tsx）**: メインUI構造、状態管理、イベントハンドラ
3. **27-29行目**: defaultTour判定（ノード数0でツアー表示）
4. **79-103行目**: RootProvider、V2Header、V2Container、V2Footerの配置

#### Step 3: ストアと永続化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | app-designer-provider.tsx | `internal-packages/workflow-designer-ui/src/app-designer/store/app-designer-provider.tsx` | ストア初期化と永続化コントローラーの設定 |
| 3-2 | controller.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/persistence/controller.ts` | debounce保存、beforeunload処理の実装 |

**主要処理フロー**:
- **58-77行目（provider）**: ストアと永続化コントローラーの初期化
- **80-97行目**: ルート変更時のflush処理
- **99-114行目**: beforeunloadイベントハンドリング

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | components/index.ts | `internal-packages/workflow-designer-ui/src/editor/v2/components/index.ts` | V2Header、V2Container、V2Footerのエクスポート |
| 4-2 | properties-panel/index.tsx | `internal-packages/workflow-designer-ui/src/editor/properties-panel/index.tsx` | プロパティパネルの実装 |

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

```
Editor (index.tsx)
    │
    └─ V2Placeholder (v2-placeholder.tsx)
           │
           ├─ [状態管理]
           │      ├─ useAppDesignerStore (Zustand)
           │      ├─ useState (layoutState, isTourOpen, isChatOpen)
           │      └─ useFeatureFlag (layoutV3)
           │
           ├─ ReadOnlyBanner (条件付き表示)
           │
           ├─ RootProvider (provider.tsx)
           │      │
           │      └─ [子コンポーネント]
           │             │
           │             ├─ V2Header
           │             │      └─ ワークスペース名、チーム情報
           │             │
           │             ├─ V2Container
           │             │      ├─ React Flow Canvas
           │             │      ├─ プロパティパネル
           │             │      └─ 左パネル（条件付き）
           │             │
           │             └─ V2Footer (layoutV3の場合)
           │                    └─ ツールバー、パネル切替
           │
           ├─ WorkspaceTour (isTourOpenの場合)
           │
           └─ FloatingChat (isChatOpenの場合)
```

### データフロー図

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

initialWorkspace ─────────┐
                          │
giselleClient ────────────┼──▶ AppDesignerProvider
                          │         │
llmProviders ─────────────┤         ├──▶ AppDesignerStore (Zustand)
                          │         │         │
debounceMs ───────────────┤         │         ├──▶ WorkspaceSlice
                          │         │         │         └─ nodes, connections, ui
save callback ────────────┘         │         │
                                    │         ├──▶ UiSlice
                                    │         │         └─ llmProviders, shortcutScope
                                    │         │
                                    │         └──▶ AppSlice
                                    │                   └─ apps
                                    │
                                    └──▶ PersistenceController
                                              │
                                              └──▶ Giselle API
                                                        │
                                                        └──▶ Database
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.tsx | `internal-packages/workflow-designer-ui/src/editor/index.tsx` | ソース | Editorエントリーポイント |
| v2-placeholder.tsx | `internal-packages/workflow-designer-ui/src/editor/v2/v2-placeholder.tsx` | ソース | メインUI構造 |
| app-designer-provider.tsx | `internal-packages/workflow-designer-ui/src/app-designer/store/app-designer-provider.tsx` | ソース | ストアプロバイダー |
| app-designer-store.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/app-designer-store.ts` | ソース | Zustandストア定義 |
| workspace-slice.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/slices/workspace-slice.ts` | ソース | ワークスペース状態スライス |
| ui-slice.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/slices/ui-slice.ts` | ソース | UI状態スライス |
| controller.ts | `internal-packages/workflow-designer-ui/src/app-designer/store/persistence/controller.ts` | ソース | 永続化コントローラー |
| properties-panel/index.tsx | `internal-packages/workflow-designer-ui/src/editor/properties-panel/index.tsx` | ソース | プロパティパネル |
| workspace-tour.tsx | `internal-packages/workflow-designer-ui/src/editor/workspace-tour/workspace-tour.tsx` | ソース | ワークスペースツアー |
| floating-chat.tsx | `internal-packages/workflow-designer-ui/src/editor/chat/floating-chat.tsx` | ソース | フローティングチャット |
