# 通知設計書 2-Session error

## 概要

本ドキュメントは、OpenCodeアプリケーションにおける「Session error（セッションエラー）」システム通知の設計を記述します。セッション中にエラーが発生した際に、ユーザーに対してデスクトップシステム通知を表示する機能です。

### 本通知の処理概要

**業務上の目的・背景**：AIエージェントはAPIエラー、モデル制限、認証失敗など様々な理由でエラーが発生する可能性があります。ユーザーが他の作業中にエラーが発生した場合、通知なしではエラーを見逃す恐れがあります。この通知により、ユーザーはセッションのエラー状態を迅速に把握し、必要な対処（再試行、設定変更など）を行うことができます。

**通知の送信タイミング**：SDKイベント `session.error` が発生した時に送信されます。これはエージェントの処理中にエラーが発生したことを示します。子セッション（parentIDを持つセッション）の場合は通知が送信されません。

**通知の受信者**：現在OpenCodeアプリケーションを使用しているユーザー。ただし、設定画面で `settings.notifications.errors` がオフの場合は通知されません。また、該当セッションを現在表示中の場合は通知されません。

**通知内容の概要**：通知タイトル「Session error」と、セッションのタイトル（またはエラーメッセージ、フォールバックとして「An error occurred」）が説明として表示されます。通知をクリックすると該当セッションに遷移できます。

**期待されるアクション**：ユーザーは通知を受け取った後、通知をクリックして該当セッションに移動し、エラー内容を確認して必要な対処（再試行、設定変更、問い合わせなど）を行うことが期待されます。

## 通知種別

デスクトップシステム通知（プラットフォームネイティブ通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（イベント駆動） |
| 優先度 | 高 |
| リトライ | なし |

### 送信先決定ロジック

1. `session.error` イベントを受信
2. セッション情報を取得（parentIDのチェック）
3. 子セッション（parentID有り）の場合は送信スキップ
4. `settings.notifications.errors` が有効か確認
5. 現在表示中のセッションでないか確認
6. 条件を満たす場合、プラットフォームの通知APIを呼び出し

## 通知テンプレート

### システム通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | `notification.session.error.title`（"Session error"） |
| 説明 | セッションタイトル または エラーメッセージ または フォールバック |
| リンク先 | `/{base64EncodedDirectory}/session/{sessionID}` または `/{base64EncodedDirectory}` |

### 本文テンプレート

```
タイトル: Session error
説明: {session.title ?? error ?? "An error occurred"}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルは使用されません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| session.title | セッションのタイトル | session.get API | No |
| error | エラーメッセージ | イベントプロパティ | No |
| sessionID | セッションの一意識別子 | イベントプロパティ | No |
| directory | プロジェクトディレクトリパス | イベント名 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| SDKイベント | `session.error` | settings.notifications.errors = true かつ parentID = undefined | セッションエラー発生時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| settings.notifications.errors = false | ユーザーがエラー通知を無効にしている場合 |
| session.parentID が存在 | 子セッション（サブエージェント）の場合 |
| 現在表示中のセッション | ユーザーが該当セッションを閲覧中の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[session.error イベント受信] --> B[セッション情報取得]
    B --> C{parentID有り?}
    C -->|Yes| D[送信スキップ]
    C -->|No| E{サウンド設定有効?}
    E -->|Yes| F[エラーサウンド再生]
    E -->|No| G{通知設定有効?}
    F --> G
    G -->|No| D
    G -->|Yes| H{表示中のセッション?}
    H -->|Yes| D
    H -->|No| I[platform.notify呼び出し]
    I --> J[通知表示]
    D --> K[終了]
    J --> K
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| session | セッション情報の取得 | SDK経由でアクセス |
| settings | 通知設定の確認 | ローカルストレージ |

### テーブル別参照項目詳細

#### session

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | セッション識別 | sessionID一致 |
| title | 通知説明文 | - |
| parentID | 子セッション判定 | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| notification | INSERT | 内部通知リストへの追加 |

#### 通知ストア

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | type | "error" | 通知種別 |
| INSERT | directory | イベントディレクトリ | プロジェクトパス |
| INSERT | session | sessionID または "global" | セッションID |
| INSERT | time | Date.now() | 通知時刻 |
| INSERT | viewed | viewedInCurrentSession() | 閲覧済みフラグ |
| INSERT | error | event.properties.error | エラー情報 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| セッション取得失敗 | セッションが存在しない/削除済み | エラー通知は送信（セッション情報なしでも通知可能） |
| 通知API失敗 | プラットフォームAPI呼び出し失敗 | エラーをキャッチして無視 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（イベント駆動） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（24時間配信可能）

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

- エラーメッセージにはAPIキーや認証情報が含まれないよう、サーバー側でサニタイズされている前提
- セッションタイトルにはユーザーが入力した内容が含まれる可能性あり
- ディレクトリパスはbase64エンコードされてURLに含まれる

## 備考

- エラー通知はデフォルトでは無効（settings.notifications.errors = false）
- エラーサウンド設定はデフォルトで有効
- sessionIDが存在しない場合、"global"としてストアに記録され、リンク先はプロジェクトルートになる

---

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

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

### 推奨読解順序

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

エラー通知の型定義を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notification.tsx | `packages/app/src/context/notification.tsx` | ErrorNotification型（29-32行目）でエラー通知構造を理解 |
| 1-2 | notification.tsx | `packages/app/src/context/notification.tsx` | Notification union型（34行目）で通知種別を理解 |

**読解のコツ**: ErrorNotificationはNotificationBaseを拡張し、errorプロパティを持つことに注目。

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

イベントリスナーとエラーハンドリングを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | notification.tsx | `packages/app/src/context/notification.tsx` | globalSDK.event.listen（288-303行目）でイベントフィルタリングを理解 |
| 2-2 | notification.tsx | `packages/app/src/context/notification.tsx` | handleSessionError関数（255-286行目）でエラー処理フローを理解 |

**主要処理フロー**:
1. **288-299行目**: session.errorイベントをフィルタリング
2. **297-298行目**: handleSessionErrorを呼び出し
3. **255-286行目**: セッション情報取得、エラーサウンド再生、通知追加、platform.notify呼び出し

#### Step 3: エラー情報の取得と表示を理解する

エラーメッセージの決定ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notification.tsx | `packages/app/src/context/notification.tsx` | description変数（278-280行目）でエラー説明文の決定ロジックを理解 |
| 3-2 | en.ts | `packages/app/src/i18n/en.ts` | notification.session.error.fallbackDescription（483行目）でフォールバックを確認 |

**主要処理フロー**:
- **278-280行目**: session.title ?? error ?? fallbackDescription の優先順位

#### Step 4: 設定確認を理解する

エラー通知の設定を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | settings.tsx | `packages/app/src/context/settings.tsx` | defaultSettings.notifications.errors（67行目）でデフォルト値を確認 |

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

```
globalSDK.event.listen (notification.tsx:288)
    │
    ├─ handleSessionIdle (notification.tsx:229)
    │
    └─ handleSessionError (notification.tsx:255)
           ├─ lookup (notification.tsx:208-217)
           │      └─ globalSDK.client.session.get
           ├─ playSound (utils/sound.ts) - エラーサウンド
           ├─ append (notification.tsx:196)
           │      └─ appendToIndex (notification.tsx:147)
           └─ platform.notify (platform.tsx:37)
```

### データフロー図

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

SDKイベント               NotificationContext
session.error ────────▶  handleSessionError()  ────────────▶  デスクトップ通知
  │                           │                               内部通知ストア
  │                           │
  ▼                           ▼
sessionID               lookup() でセッション情報取得（任意）
directory               settings.notifications.errors 確認
error                   description = title ?? error ?? fallback
                        append() で内部ストアに追加（type: "error"）
                        platform.notify() で通知表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notification.tsx | `packages/app/src/context/notification.tsx` | ソース | 通知コンテキスト・メインロジック |
| platform.tsx | `packages/app/src/context/platform.tsx` | ソース | プラットフォーム通知API定義 |
| settings.tsx | `packages/app/src/context/settings.tsx` | ソース | 通知設定の管理 |
| en.ts | `packages/app/src/i18n/en.ts` | 設定 | 英語翻訳キー |
| sound.ts | `packages/app/src/utils/sound.ts` | ソース | 通知サウンド再生 |
| sdk.gen.ts | `packages/sdk/js/src/v2/gen/types.gen.ts` | ソース | EventSessionError型定義 |
