# 画面設計書 26-セッション

## 概要

本ドキュメントは、OpenCode TUI（ターミナルUI）アプリケーションにおけるセッション画面の設計を定義する。AIとの対話セッションを行うメイン作業画面であり、メッセージタイムライン、ツール実行結果表示、権限確認、サイドバーなど多数の機能を提供する。

### 本画面の処理概要

この画面は、OpenCode TUIアプリケーションの中核となるセッション画面である。ユーザーとAIの対話履歴を表示し、各種ツール（Bash, Edit, Read, Grep等）の実行結果を視覚的に表示する。

**業務上の目的・背景**：ターミナル上でAIコーディングエージェントと対話する際、コードの変更内容、コマンド実行結果、ファイル操作などを直感的に把握できるインターフェースが必要である。本画面は、これらの情報を構造化して表示し、ユーザーがAIの作業内容を追跡・制御できるようにしている。

**画面へのアクセス方法**：
1. ホーム画面からプロンプトを送信
2. 既存セッションを選択（`opencode -s {sessionID}`または画面内選択）
3. サブエージェントタスクからの遷移

**主要な操作・処理内容**：
1. メッセージタイムラインの表示（ユーザー・アシスタントメッセージ）
2. ツール実行結果の表示（Bash, Edit, Write, Read, Grep, Glob, WebFetch, Task等）
3. 権限確認プロンプトの表示（PermissionPrompt）
4. 質問プロンプトの表示（QuestionPrompt）
5. サイドバーでのセッション情報表示
6. コマンドダイアログによる各種操作
7. セッション共有・リネーム・フォーク・コンパクト
8. メッセージのUndo/Redo
9. スクロール操作（ページ単位、メッセージ単位）
10. 差分表示（unified/split）

**画面遷移**：
- この画面から遷移可能：ホーム画面、サブエージェントセッション、親セッション
- この画面に遷移してくる：ホーム画面（プロンプト送信）、セッション選択

**権限による表示制御**：
- サブセッション（parentID有り）の場合、プロンプト入力は非表示
- ワイド画面（120px以上）でサイドバー自動表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Build エージェント | 主機能 | デフォルトエージェントによる開発作業実行 |
| 2 | Plan エージェント | 主機能 | 読み取り専用エージェントによるコード探索・計画 |
| 8 | Bash ツール | 補助機能 | Bashコンポーネントによるシェルコマンド実行結果表示 |
| 9 | Edit ツール | 補助機能 | Editコンポーネントによるファイル編集差分表示 |
| 10 | Write ツール | 補助機能 | Writeコンポーネントによるファイル書き込み結果表示 |
| 11 | Read ツール | 補助機能 | Readコンポーネントによるファイル読み取り表示 |
| 12 | Grep ツール | 補助機能 | Grepコンポーネントによる検索結果表示 |
| 13 | Glob ツール | 補助機能 | Globコンポーネントによるファイルパターン検索結果表示 |
| 14 | WebSearch ツール | 補助機能 | WebSearchコンポーネントによるWeb検索結果表示 |
| 15 | WebFetch ツール | 補助機能 | WebFetchコンポーネントによるURL取得結果表示 |
| 16 | Task ツール | 補助機能 | Taskコンポーネントによるサブエージェントタスク表示 |
| 17 | TodoWrite ツール | 補助機能 | TodoWriteコンポーネントによるタスクリスト表示 |
| 21 | セッション作成 | 主機能 | ルートデータからのセッション同期 |
| 22 | セッションフォーク | 補助機能 | DialogForkFromTimelineによるセッションフォーク |
| 23 | セッション共有 | 補助機能 | コマンドからのセッション共有機能 |
| 25 | メッセージ管理 | 主機能 | メッセージの送受信、UserMessage/AssistantMessageコンポーネントによる表示 |
| 41 | リバート機能 | 補助機能 | メッセージのリバート・アンドゥ機能 |
| 51 | 権限ルールセット | 補助機能 | PermissionPromptによる権限確認表示 |

## 画面種別

対話・作業画面

## URL/ルーティング

- ルート: `session`（TUI内部ルーティング）
- パラメータ: `sessionID` - セッション識別子
- ファイル: `packages/opencode/src/cli/cmd/tui/routes/session/index.tsx`

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| プロンプト入力 | string | いいえ | AIへの指示テキスト |
| 添付ファイル | File[] | いいえ | プロンプトに添付するファイル |
| 権限応答 | boolean | 条件付き | 権限確認への応答（許可/拒否） |
| 質問応答 | string[] | 条件付き | AIからの質問への回答 |

### ルートデータ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sessionID | string | 対象セッションID |
| initialPrompt | PromptInfo | 初期プロンプト（フォーク時） |

### 同期データ（sync.data）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| session | Session[] | セッション一覧 |
| message | Record<sessionID, Message[]> | メッセージ（セッションIDでグループ化） |
| part | Record<messageID, Part[]> | パーツ（メッセージIDでグループ化） |
| permission | Record<sessionID, Permission[]> | 権限リクエスト |
| question | Record<sessionID, Question[]> | 質問リクエスト |
| session_status | Record<sessionID, SessionStatus> | セッション状態 |

## 表示項目

| セクション | 項目名 | 表示内容 | 説明 |
|-----------|--------|----------|------|
| ヘッダー | セッション情報 | Header コンポーネント | サイドバー非表示時のみ |
| メイン | メッセージ一覧 | scrollbox内For each | UserMessage/AssistantMessage |
| メイン | ユーザーメッセージ | テキスト、添付ファイル | 左ボーダー付きブロック |
| メイン | アシスタントメッセージ | テキスト、ツール結果 | パーツごとに表示 |
| メイン | リバート表示 | revert情報 | 取り消されたメッセージ数 |
| 下部 | 権限プロンプト | PermissionPrompt | 権限リクエスト時 |
| 下部 | 質問プロンプト | QuestionPrompt | 質問リクエスト時 |
| 下部 | プロンプト | Prompt コンポーネント | 通常時 |
| 右側 | サイドバー | Sidebar コンポーネント | ワイド画面時自動/手動表示 |
| オーバーレイ | Toast | 通知メッセージ | 各種操作結果 |

## イベント仕様

### 1-プロンプト送信

ユーザーがプロンプトを入力してEnterキーを押すと、メッセージが送信される。

### 2-コマンド一覧（コマンドダイアログ）

| コマンド | 説明 | キーバインド |
|---------|------|-------------|
| session.share | セッション共有/URL取得 | session_share |
| session.rename | セッションリネーム | session_rename |
| session.timeline | メッセージジャンプ | session_timeline |
| session.fork | メッセージからフォーク | session_fork |
| session.compact | セッションコンパクト化 | session_compact |
| session.unshare | 共有解除 | session_unshare |
| session.undo | 前メッセージを取り消し | messages_undo |
| session.redo | 取り消しを復元 | messages_redo |
| session.sidebar.toggle | サイドバー表示切替 | sidebar_toggle |
| session.toggle.conceal | コード隠蔽切替 | messages_toggle_conceal |
| session.toggle.timestamps | タイムスタンプ表示切替 | - |
| session.toggle.thinking | 思考過程表示切替 | display_thinking |
| session.toggle.actions | ツール詳細表示切替 | tool_details |
| session.toggle.scrollbar | スクロールバー表示切替 | scrollbar_toggle |
| session.toggle.header | ヘッダー表示切替 | - |
| session.page.up/down | ページスクロール | messages_page_up/down |
| session.line.up/down | 行スクロール | messages_line_up/down |
| session.half.page.up/down | 半ページスクロール | messages_half_page_up/down |
| session.first/last | 先頭/末尾へ移動 | messages_first/last |
| session.message.next/previous | 次/前メッセージ | messages_next/previous |
| messages.copy | 最終アシスタントメッセージコピー | messages_copy |
| session.copy | トランスクリプトコピー | - |
| session.export | トランスクリプトエクスポート | session_export |
| session.child.next/previous | 子セッション切替 | session_child_cycle |
| session.parent | 親セッションへ移動 | session_parent |

### 3-権限確認応答

PermissionPromptで許可/拒否を選択。

### 4-質問応答

QuestionPromptで回答を入力。

### 5-メッセージクリック

UserMessageをクリックするとDialogMessageが表示され、コピー・フォーク等の操作が可能。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| セッション同期 | session | SELECT | セッション情報取得 |
| メッセージ送信 | message | INSERT | 新規メッセージ追加 |
| セッション共有 | share | INSERT | 共有情報作成 |
| セッションリネーム | session | UPDATE | タイトル更新 |
| メッセージリバート | session | UPDATE | revert情報更新 |

## メッセージ仕様

| 種別 | 表示条件 | メッセージ内容 |
|------|----------|---------------|
| 成功 | 共有URL取得成功 | "Share URL copied to clipboard!" |
| 成功 | メッセージコピー成功 | "Message copied to clipboard!" |
| 成功 | トランスクリプトコピー成功 | "Session transcript copied to clipboard!" |
| 成功 | エクスポート成功 | "Session exported to {filename}" |
| 成功 | 共有解除成功 | "Session unshared successfully" |
| エラー | 共有失敗 | "Failed to share session" |
| エラー | コピー失敗 | "Failed to copy to clipboard" |
| エラー | セッション未発見 | "Session not found: {sessionID}" |
| エラー | メッセージなし | "No assistant messages found" |
| 警告 | プロバイダー未接続 | "Connect a provider to summarize this session" |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|-----|----------|---------|
| セッション同期失敗 | 無効なsessionID | Toastエラー表示、ホーム画面へ遷移 |
| 権限拒否 | ユーザーが権限を拒否 | ツール実行結果に取り消し線表示 |

## 備考

- 2000行以上の大規模コンポーネント
- 各ツールごとに専用の表示コンポーネント（Bash, Edit, Write, Read, Grep, Glob, WebFetch, Task, TodoWrite, Question, Skill等）
- スクロールアクセラレーション設定対応（MacOS風/固定速度）
- 差分表示スタイル設定（stacked/auto）
- クリップボード操作、外部エディタ連携
- 親子セッション関係のサポート

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | @opencode-ai/sdk/v2 | 外部パッケージ | Session, Message, Part, ToolPartの型定義 |
| 1-2 | sync.ts | `packages/opencode/src/cli/cmd/tui/context/sync.ts` | sync.dataの構造 |

**読解のコツ**: ToolPartの`state`プロパティが`pending`/`running`/`completed`/`error`の状態を持ち、各状態で表示が異なる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | session/index.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/index.tsx` | Sessionコンポーネント全体構造 |

**主要処理フロー**:
1. **112行目**: Session()関数コンポーネント定義
2. **113-134行目**: 各種フック呼び出しと状態初期化
3. **144-178行目**: 表示設定の状態管理
4. **180-194行目**: セッション同期処理
5. **326-922行目**: コマンドダイアログへのコマンド登録
6. **977-1162行目**: UIレンダリング（scrollbox, メッセージ一覧, プロンプト）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | UserMessage | 同ファイル内（行1175-1270） | ユーザーメッセージの表示ロジック |
| 3-2 | AssistantMessage | 同ファイル内（行1272-1349） | アシスタントメッセージの表示ロジック |
| 3-3 | ToolPart | 同ファイル内（行1424-1512） | ツール実行結果の振り分け |

#### Step 4: 個別ツール表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Bash | 同ファイル内（行1691-1756） | シェルコマンド実行結果 |
| 4-2 | Edit | 同ファイル内（行1960-2027） | ファイル編集差分 |
| 4-3 | Write | 同ファイル内（行1758-1801） | ファイル書き込み結果 |
| 4-4 | Task | 同ファイル内（行1894-1958） | サブエージェントタスク |

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

```
Session (index.tsx)
    │
    ├─ useRouteData("session")
    │      └─ sessionID, initialPrompt取得
    │
    ├─ useSync()
    │      ├─ sync.data.session
    │      ├─ sync.data.message[sessionID]
    │      ├─ sync.data.part[messageID]
    │      ├─ sync.data.permission[sessionID]
    │      └─ sync.data.question[sessionID]
    │
    ├─ useKV()
    │      └─ 表示設定（sidebar, timestamps, thinking等）
    │
    ├─ useCommandDialog()
    │      └─ コマンド登録（share, rename, fork等）
    │
    ├─ Context Provider
    │      └─ width, sessionID, conceal, showThinking等
    │
    └─ UI Components
           ├─ <Header /> (条件付き)
           ├─ <scrollbox>
           │      └─ <For each={messages()}>
           │             ├─ <UserMessage />
           │             │      └─ テキスト, ファイル添付, タイムスタンプ
           │             │
           │             └─ <AssistantMessage />
           │                    └─ <For each={parts}>
           │                           └─ <ToolPart />
           │                                  ├─ <Bash />
           │                                  ├─ <Edit />
           │                                  ├─ <Write />
           │                                  ├─ <Read />
           │                                  ├─ <Grep />
           │                                  ├─ <Glob />
           │                                  ├─ <WebFetch />
           │                                  ├─ <Task />
           │                                  ├─ <TodoWrite />
           │                                  └─ <GenericTool />
           │
           ├─ <PermissionPrompt /> (条件付き)
           ├─ <QuestionPrompt /> (条件付き)
           ├─ <Prompt /> (条件付き)
           ├─ <Toast />
           └─ <Sidebar /> (条件付き)
```

### データフロー図

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

sessionID
    │
    ▼
sync.session.sync() ──▶ セッション同期
    │
    ▼
sync.data ────────────▶ リアクティブ更新
    │
    ├──▶ messages ──────▶ For each ──▶ UserMessage/AssistantMessage
    │         │
    │         └──▶ parts ──▶ ToolPart ──▶ Bash/Edit/Write/Read...
    │
    ├──▶ permissions ───▶ PermissionPrompt表示
    │
    └──▶ questions ─────▶ QuestionPrompt表示

プロンプト入力
    │
    ▼
Prompt.submit() ──▶ SDK送信 ──▶ sync.data更新 ──▶ UI更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| session/index.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/index.tsx` | ソース | セッション画面メインコンポーネント |
| header.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/header.tsx` | ソース | ヘッダーコンポーネント |
| sidebar.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx` | ソース | サイドバーコンポーネント |
| footer.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx` | ソース | フッターコンポーネント |
| permission.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx` | ソース | 権限確認コンポーネント |
| question.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/question.tsx` | ソース | 質問プロンプトコンポーネント |
| dialog-timeline.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx` | ソース | タイムラインダイアログ |
| dialog-fork-from-timeline.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx` | ソース | フォークダイアログ |
| dialog-message.tsx | `packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx` | ソース | メッセージダイアログ |
| prompt/index.tsx | `packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx` | ソース | プロンプト入力コンポーネント |
| todo-item.tsx | `packages/opencode/src/cli/cmd/tui/component/todo-item.tsx` | ソース | Todoアイテムコンポーネント |
| border.tsx | `packages/opencode/src/cli/cmd/tui/component/border.tsx` | ソース | ボーダーユーティリティ |
| transcript.ts | `packages/opencode/src/cli/cmd/tui/util/transcript.ts` | ソース | トランスクリプト整形 |
| clipboard.ts | `packages/opencode/src/cli/cmd/tui/util/clipboard.ts` | ソース | クリップボード操作 |
| editor.ts | `packages/opencode/src/cli/cmd/tui/util/editor.ts` | ソース | 外部エディタ連携 |
