# 機能設計書 58-VS Code拡張

## 概要

本ドキュメントは、OpenCodeのVS Code拡張機能について、その設計仕様を記述するものである。

### 本機能の処理概要

VS Code拡張機能は、VS CodeエディタからOpenCodeを直接起動・操作するための統合機能を提供する。ターミナルにOpenCodeを起動し、編集中のファイルパスを自動的にプロンプトに追加する機能により、エディタとAIアシスタントをシームレスに連携させる。

**業務上の目的・背景**：開発者は通常VS Codeで作業を行っており、別のターミナルウィンドウでOpenCodeを起動する手間を省くことで、開発フローを効率化する。ファイルコンテキストを自動的にAIに伝えることで、より正確なコード支援を実現する。

**機能の利用シーン**：
- コードレビューやリファクタリング時のAI支援
- エラー解析時にファイルコンテキストを伴ったAI相談
- 新機能実装時のコード生成支援
- ドキュメント生成やコメント追加

**主要な処理内容**：
1. OpenCodeターミナルの新規作成（opencode.openNewTerminal）
2. 既存ターミナルへのフォーカス/新規作成（opencode.openTerminal）
3. アクティブファイルパスのターミナルへの追加（opencode.addFilepathToTerminal）
4. HTTP経由でのプロンプト追加（append-promptエンドポイント）
5. 選択範囲の行番号を含むファイル参照形式の生成

**関連システム・外部連携**：VS Code API、OpenCode HTTPサーバー、OpenCode TUI

**権限による制御**：VS Code拡張として必要な権限のみ（ターミナル操作、ファイルシステムアクセス）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | VS Codeエディタ | 主機能 | 拡張コマンド実行元 |
| - | VS Codeターミナル | 主機能 | OpenCode TUI表示 |

## 機能種別

エディタ拡張 / IDE統合

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| command | string | Yes | 実行するコマンド名 | 登録済みコマンド |
| - | - | - | （コマンドはキーバインドまたはコマンドパレットから実行） | - |

### 入力データソース

- VS Codeアクティブエディタ（vscode.window.activeTextEditor）
- VS Codeワークスペース（vscode.workspace）
- VS Codeターミナル（vscode.window.terminals）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| terminal | vscode.Terminal | 作成/フォーカスされたターミナル |
| fileRef | string | ファイル参照文字列（@path#Lx-y形式） |

### 出力先

- VS Codeターミナル
- OpenCode HTTPサーバー（/tui/append-prompt）

## 処理フロー

### 処理シーケンス

```
1. コマンド実行
   ├─ opencode.openNewTerminal: 新規ターミナル作成
   ├─ opencode.openTerminal: 既存ターミナルフォーカスまたは新規作成
   └─ opencode.addFilepathToTerminal: ファイルパス追加

2. ターミナル作成（openTerminal内部）
   ├─ ランダムポート生成（16384-65535）
   ├─ createTerminal実行
   ├─ opencode --port コマンド送信
   └─ サーバー起動待機（200ms x 10回）

3. ファイル参照生成（getActiveFile）
   ├─ アクティブエディタ取得
   ├─ 相対パス計算
   └─ 選択範囲の行番号追加
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド実行] --> B{コマンド種別}
    B -->|openTerminal| C{既存ターミナルあり?}
    B -->|openNewTerminal| D[openTerminal関数]
    B -->|addFilepath| E[getActiveFile]
    C -->|Yes| F[既存ターミナルshow]
    C -->|No| D
    D --> G[ランダムポート生成]
    G --> H[createTerminal]
    H --> I[opencode --port 送信]
    I --> J[サーバー起動待機]
    J --> K{接続成功?}
    K -->|Yes| L[appendPrompt]
    K -->|No| M[終了]
    E --> N{activeEditor存在?}
    N -->|Yes| O[相対パス取得]
    N -->|No| M
    O --> P{選択範囲あり?}
    P -->|Yes| Q[行番号付加]
    P -->|No| R[パスのみ]
    Q --> S[ターミナルに送信]
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ターミナル名 | ターミナル名は固定で"opencode" | ターミナル作成時 |
| BR-02 | ポート範囲 | ランダムポートは16384-65535の範囲 | ターミナル作成時 |
| BR-03 | 接続リトライ | 200ms間隔で最大10回接続試行 | サーバー起動待機時 |
| BR-04 | ファイル参照形式 | @相対パス#Lstart-end形式 | 選択範囲あり時 |
| BR-05 | 単一行選択 | @相対パス#Lline形式 | 単一行選択時 |
| BR-06 | 環境変数設定 | _EXTENSION_OPENCODE_PORT、OPENCODE_CALLER=vscode | ターミナル作成時 |

### 計算ロジック

- ポート生成: `Math.floor(Math.random() * (65535 - 16384 + 1)) + 16384`
- 行番号: 0ベースから1ベースに変換（`selection.start.line + 1`）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベースは使用しない |

### テーブル別操作詳細

該当なし（VS Code拡張はクライアントサイドのみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 接続タイムアウト | 10回のリトライ後も接続失敗 | サイレント失敗（ターミナルは表示） |
| - | アクティブエディタなし | エディタが開かれていない | 処理中断（return） |
| - | ワークスペース外ファイル | ワークスペース外のファイル | 処理中断（return） |

### リトライ仕様

- サーバー接続: 200ms間隔で最大10回（合計2秒）
- fetch失敗時はサイレントで次のリトライへ

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

該当なし

## パフォーマンス要件

- ターミナル作成: 即時
- サーバー起動待機: 最大2秒
- ファイルパス追加: 即時

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

- ポートはランダム生成でポート衝突を回避
- HTTP通信はlocalhostのみ（外部通信なし）
- OPENCODE_CALLER環境変数で呼び出し元識別

## 備考

- パッケージ名: opencode
- 発行者: sst-dev
- 対応VS Codeバージョン: ^1.94.0
- キーバインド:
  - Cmd+Escape (Mac) / Ctrl+Escape (Win/Linux): opencode.openTerminal
  - Cmd+Shift+Escape (Mac) / Ctrl+Shift+Escape (Win/Linux): opencode.openNewTerminal
  - Cmd+Alt+K (Mac) / Ctrl+Alt+K (Win/Linux): opencode.addFilepathToTerminal

---

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

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

### 推奨読解順序

#### Step 1: パッケージ構成を理解する

拡張機能のマニフェストを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | package.json | `sdks/vscode/package.json` | コマンド定義、キーバインド、メニュー |

**読解のコツ**:
- contributes.commandsで登録されるコマンド一覧
- contributes.keybindingsでのショートカット定義
- contributes.menusでのエディタタイトルバー統合

#### Step 2: 拡張機能のエントリーポイントを理解する

activate関数でのコマンド登録を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | extension.ts | `sdks/vscode/src/extension.ts` | activate、コマンド登録 |

**主要処理フロー**:
- **6行目**: `TERMINAL_NAME = "opencode"` - ターミナル名定数
- **8-43行目**: `activate(context)` - コマンド登録
- **9-11行目**: opencode.openNewTerminalコマンド登録
- **13-22行目**: opencode.openTerminalコマンド登録（既存ターミナル検索含む）
- **24-41行目**: opencode.addFilepathToTerminalコマンド登録

#### Step 3: ターミナル作成処理を理解する

openTerminal関数の詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extension.ts | `sdks/vscode/src/extension.ts` | openTerminal関数 |

**主要処理フロー**:
- **45-91行目**: `openTerminal()` - メイン処理
- **47行目**: ランダムポート生成（16384-65535）
- **48-62行目**: createTerminal呼び出し（アイコン、位置、環境変数設定）
- **65行目**: `opencode --port` コマンド送信
- **73-84行目**: サーバー起動待機ループ（200ms x 10回）
- **87-90行目**: 接続成功時のプロンプト追加

#### Step 4: HTTP通信処理を理解する

appendPrompt関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | extension.ts | `sdks/vscode/src/extension.ts` | appendPrompt関数 |

**主要処理フロー**:
- **93-101行目**: `appendPrompt(port, text)` - HTTPでプロンプト追加
- **94-100行目**: `/tui/append-prompt`エンドポイントへPOST

#### Step 5: ファイル参照生成を理解する

getActiveFile関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | extension.ts | `sdks/vscode/src/extension.ts` | getActiveFile関数 |

**主要処理フロー**:
- **103-136行目**: `getActiveFile()` - ファイル参照生成
- **104-107行目**: アクティブエディタ存在チェック
- **110-113行目**: ワークスペースフォルダ存在チェック
- **116-117行目**: 相対パス計算と@プレフィックス付加
- **120-132行目**: 選択範囲の行番号追加（#Lx-y形式）

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

```
activate(context) (extension.ts: 8行目)
    │
    ├─ vscode.commands.registerCommand("opencode.openNewTerminal")
    │      │
    │      └─ openTerminal()
    │
    ├─ vscode.commands.registerCommand("opencode.openTerminal")
    │      │
    │      ├─ vscode.window.terminals.find() → 既存ターミナル検索
    │      │
    │      └─ openTerminal() (既存なし時)
    │
    └─ vscode.commands.registerCommand("opencode.addFilepathToTerminal")
           │
           ├─ getActiveFile() → ファイル参照生成
           │
           └─ appendPrompt() or terminal.sendText()

openTerminal() (extension.ts: 45行目)
    │
    ├─ Math.random() → ポート生成
    │
    ├─ vscode.window.createTerminal() → ターミナル作成
    │
    ├─ terminal.sendText(`opencode --port ${port}`)
    │
    ├─ fetch(`http://localhost:${port}/app`) → 接続確認（リトライ）
    │
    └─ appendPrompt(port, fileRef) → プロンプト追加

getActiveFile() (extension.ts: 103行目)
    │
    ├─ vscode.window.activeTextEditor → エディタ取得
    │
    ├─ vscode.workspace.getWorkspaceFolder() → ワークスペース取得
    │
    ├─ vscode.workspace.asRelativePath() → 相対パス変換
    │
    └─ selection.start.line / selection.end.line → 行番号取得
```

### データフロー図

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

コマンド実行
  キーバインド ──────────▶ activate.registerCommand ───▶ コマンド登録
     │
VS Code状態
  activeTextEditor ─────▶ getActiveFile() ────────────▶ @path#Lx-y
  workspaceFolder              │
  selection                    │
     │                         │
ターミナル作成                  │
  ランダムポート ─────────▶ createTerminal() ──────────▶ Terminal
     │                         │
     │                         ▼
HTTP通信                  terminal.sendText()
  ポート番号 ──────────▶ opencode --port {port}
     │                         │
     │                         ▼
サーバー応答              fetch(/app) ──────────────────▶ 接続確認
     │                         │
     │                         ▼
プロンプト追加            appendPrompt() ───────────────▶ /tui/append-prompt
  text ───────────────▶ POST JSON
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| extension.ts | `sdks/vscode/src/extension.ts` | ソース | 拡張機能エントリーポイント |
| package.json | `sdks/vscode/package.json` | 設定 | 拡張機能マニフェスト |
| button-dark.svg | `sdks/vscode/images/button-dark.svg` | アセット | ライトテーマ用アイコン |
| button-light.svg | `sdks/vscode/images/button-light.svg` | アセット | ダークテーマ用アイコン |
| icon.png | `sdks/vscode/images/icon.png` | アセット | 拡張機能アイコン |
| esbuild.js | `sdks/vscode/esbuild.js` | ビルド | バンドル設定 |
| tsconfig.json | `sdks/vscode/tsconfig.json` | 設定 | TypeScript設定 |
