# 帳票設計書 2-Transcript Export (Markdown)

## 概要

本ドキュメントは、opencodeのセッション会話内容をMarkdown形式でエクスポートするトランスクリプト機能の設計書である。

### 本帳票の処理概要

本帳票は、opencodeのAIアシスタントとの対話履歴を人間が読みやすいMarkdown形式で出力する機能を提供する。

**業務上の目的・背景**：AIアシスタントとの対話セッションを文書化し、レビューや共有、ドキュメント化のために必要である。JSON形式のエクスポートとは異なり、人間が直接読めるフォーマットで出力することで、対話内容の確認や報告書作成、チーム内での知識共有が容易になる。また、技術ブログやドキュメントへの転記も簡単に行える。

**帳票の利用シーン**：開発者がセッションの内容をレビューしたい場合、AIとの対話プロセスをチームメンバーと共有したい場合、または対話履歴をプロジェクトドキュメントとして残したい場合に利用される。特に、複雑な問題解決の過程を文書化する際や、AIの推論プロセスを確認・分析する際に有用である。

**主要な出力内容**：
1. セッションヘッダー（タイトル、ID、作成日時、更新日時）
2. ユーザーメッセージ（ユーザーからの入力テキスト）
3. アシスタントメッセージ（AIの応答、使用モデル、処理時間）
4. 思考過程（オプション：AIの推論プロセス）
5. ツール呼び出し詳細（オプション：入出力データ）

**帳票の出力タイミング**：TUI内部のユーティリティ関数として実装されており、formatTranscript関数を呼び出した時点で出力される。セッション情報とメッセージデータを引数として渡す必要がある。

**帳票の利用者**：開発者、コードレビュアー、テクニカルライター、プロジェクトマネージャー

## 帳票種別

トランスクリプト / 対話履歴ドキュメント

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | TUI内部 | ユーティリティ関数呼び出し | formatTranscript関数実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Markdown (.md) |
| 用紙サイズ | 該当なし（テキストファイル） |
| 向き | 該当なし |
| ファイル名 | 呼び出し元で指定（関数は文字列を返却） |
| 出力方法 | 関数戻り値として文字列を返却 |
| 文字コード | UTF-8 |

### オプション設定

| オプション | 説明 | デフォルト |
|-----------|------|-----------|
| thinking | 思考過程（reasoning）を含める | false |
| toolDetails | ツールの入出力詳細を含める | false |
| assistantMetadata | アシスタントのメタデータ（エージェント名、モデルID、処理時間）を含める | false |

## 帳票レイアウト

### レイアウト概要

Markdown形式で階層的に情報を整理する。

```
┌─────────────────────────────────────┐
│         セッションヘッダー           │
│  (# タイトル、メタ情報)              │
├─────────────────────────────────────┤
│           ---区切り線---             │
├─────────────────────────────────────┤
│         メッセージ1                  │
│  (## User/Assistant + 内容)          │
├─────────────────────────────────────┤
│           ---区切り線---             │
├─────────────────────────────────────┤
│         メッセージ2                  │
│              ...                    │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | title | セッションタイトル | SessionInfo.title | `# {title}` |
| 2 | Session ID | セッションID | SessionInfo.id | `**Session ID:** {id}` |
| 3 | Created | 作成日時 | SessionInfo.time.created | `**Created:** {localeString}` |
| 4 | Updated | 更新日時 | SessionInfo.time.updated | `**Updated:** {localeString}` |

### メッセージ部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | role header | メッセージの役割 | MessageInfo.role | `## User` または `## Assistant (...)` |
| 2 | text | テキスト内容 | Part.text (type=text) | そのまま出力 |
| 3 | reasoning | 思考過程 | Part.text (type=reasoning) | `_Thinking:_\n\n{text}` |
| 4 | tool | ツール呼び出し | Part (type=tool) | `**Tool: {name}**` + 入出力 |

### アシスタントヘッダー詳細（メタデータ有効時）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | agent | エージェント種別 | AssistantMessage.agent | titlecase変換 |
| 2 | modelID | 使用モデルID | AssistantMessage.modelID | そのまま |
| 3 | duration | 処理時間 | (completed - created) / 1000 | `{秒}s` |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| session | セッション情報オブジェクト | Yes |
| messages | メッセージ配列 | Yes |
| options | 出力オプション | Yes |

### オプションによるフィルタリング

| オプション | 対象パートタイプ | 有効時の動作 |
|-----------|----------------|-------------|
| thinking | reasoning | 思考過程を出力に含める |
| toolDetails | tool | ツールの入出力詳細を含める |
| assistantMetadata | - | アシスタントヘッダーにメタ情報追加 |

### 除外条件

| パートタイプ | 条件 | 動作 |
|-------------|-----|------|
| text | synthetic === true | 除外（出力しない） |
| reasoning | options.thinking === false | 除外 |
| tool | options.toolDetails === false | ツール名のみ出力 |

## データベース参照仕様

### 入力データ型

本機能はデータベースを直接参照せず、引数として渡されたデータを処理する。

#### SessionInfo型

| プロパティ | 型 | 説明 |
|-----------|---|------|
| id | string | セッションID |
| title | string | セッションタイトル |
| time.created | number | 作成日時（UNIXミリ秒） |
| time.updated | number | 更新日時（UNIXミリ秒） |

#### MessageWithParts型

| プロパティ | 型 | 説明 |
|-----------|---|------|
| info | UserMessage \| AssistantMessage | メッセージ情報 |
| parts | Part[] | メッセージパーツ配列 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 処理時間（duration） | (time.completed - time.created) / 1000 | 小数点1桁（toFixed(1)） | 秒単位 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[formatTranscript呼び出し] --> B[ヘッダー部生成]
    B --> C[セッションタイトル出力]
    C --> D[メタ情報出力]
    D --> E{メッセージループ}
    E --> F[formatMessage呼び出し]
    F --> G{role判定}
    G -->|user| H[## User ヘッダー出力]
    G -->|assistant| I[formatAssistantHeader呼び出し]
    H --> J[パーツループ]
    I --> J
    J --> K[formatPart呼び出し]
    K --> L{パートタイプ判定}
    L -->|text| M[テキスト出力]
    L -->|reasoning| N{thinking有効?}
    L -->|tool| O{toolDetails有効?}
    N -->|Yes| P[思考過程出力]
    N -->|No| Q[スキップ]
    O -->|Yes| R[ツール詳細出力]
    O -->|No| S[ツール名のみ出力]
    M --> T[区切り線追加]
    P --> T
    Q --> T
    R --> T
    S --> T
    T --> E
    E -->|完了| U[文字列返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| - | - | - | 関数はエラーをスローせず、空文字列や部分的な出力を返す |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1セッションあたり数百〜数千メッセージ |
| 目標出力時間 | ミリ秒〜数秒 |
| 同時出力数上限 | 制限なし（純粋関数のため） |

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

- 出力内容にはセッションの全対話履歴が含まれるため、機密情報が含まれる可能性がある
- ツール詳細を有効にした場合、ツールの入出力データ（ファイル内容、コマンド結果等）も含まれる
- 共有時は機密情報のマスキングを検討する

## 備考

- 日時はブラウザ/Node.jsのロケール設定に基づいて表示される（toLocaleString使用）
- syntheticフラグが立っているテキストパーツは出力されない（システム生成テキストの除外）
- ツールエラー時はerror状態の詳細も出力される

---

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

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

### 推奨読解順序

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

まず、入出力に関わるデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transcript.ts | `packages/opencode/src/cli/cmd/tui/util/transcript.ts` | TranscriptOptions、SessionInfo、MessageWithParts型定義（4-22行） |

**読解のコツ**: 型定義を最初に確認し、関数の入出力を把握してから実装を読む。

#### Step 2: メイン関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | transcript.ts | `packages/opencode/src/cli/cmd/tui/util/transcript.ts` | formatTranscript関数（24-41行）がエントリーポイント |

**主要処理フロー**:
1. **29-32行**: ヘッダー部の生成（タイトル、ID、作成日時、更新日時）
2. **35-38行**: メッセージループでformatMessageを呼び出し
3. **40行**: 完成した文字列を返却

#### Step 3: メッセージフォーマット処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transcript.ts | `packages/opencode/src/cli/cmd/tui/util/transcript.ts` | formatMessage関数（43-57行）、formatAssistantHeader関数（59-68行）、formatPart関数（70-98行） |

**主要処理フロー**:
- **43-57行**: ロールによるヘッダー分岐、パーツループ
- **59-68行**: アシスタントメタデータの条件付き出力
- **70-98行**: パートタイプごとの出力処理

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

```
formatTranscript(session, messages, options)
    │
    ├─ ヘッダー生成（直接文字列結合）
    │      └─ Date.toLocaleString() - 日時フォーマット
    │
    └─ for (msg of messages)
           │
           └─ formatMessage(msg.info, msg.parts, options)
                  │
                  ├─ formatAssistantHeader(msg, options.assistantMetadata)
                  │      └─ Locale.titlecase() - エージェント名変換
                  │
                  └─ for (part of parts)
                         │
                         └─ formatPart(part, options)
                                ├─ text出力（synthetic除外）
                                ├─ reasoning出力（thinking有効時）
                                └─ tool出力（詳細はtoolDetails依存）
```

### データフロー図

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

SessionInfo ──────────────▶ formatTranscript() ─────────────────▶ Markdown文字列
                                   │
MessageWithParts[] ────────▶     │
                                   │
TranscriptOptions ─────────▶     │
  - thinking                       ├─▶ ヘッダー部
  - toolDetails                    │     # {title}
  - assistantMetadata              │     **Session ID:** ...
                                   │
                                   ├─▶ メッセージ部
                                   │     ## User / ## Assistant
                                   │     {text content}
                                   │     _Thinking:_ ...
                                   │     **Tool: xxx**
                                   │
                                   └─▶ 区切り線（---）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transcript.ts | `packages/opencode/src/cli/cmd/tui/util/transcript.ts` | ソース | トランスクリプト生成メイン処理 |
| locale.ts | `packages/opencode/src/util/locale.ts` | ソース | titlecase等の文字列ユーティリティ |
| message-v2.ts | `packages/opencode/src/session/message-v2.ts` | ソース | メッセージ・パート型定義 |
| index.ts | `packages/opencode/src/session/index.ts` | ソース | Session.Info型定義 |
