Skip to content

アシスタントチャット機能 #649

@Kewton

Description

@Kewton

Note: このIssueは 2026-04-14 にStage 3(影響範囲)レビュー結果を反映して更新されました。
詳細: dev-reports/issue/649/issue-review/

概要

Home 画面にアシスタントチャット UI を追加し、特定の worktree に紐づかない汎用的な CLI セッション(インストール済みの全CLIツール)を利用可能にする。登録済みリポジトリの中から作業ディレクトリを選択し、リポジトリ横断の開発指示を行える。

デフォルトで CommandMate CLI の使い方と登録済みリポジトリの情報をコンテキストとして付与する。

背景・課題

  • 現在の CLI セッションはすべて worktree 単位で紐づいており、複数 worktree にまたがる操作(一括指示・状況確認・リポジトリ横断の質問)を行う場所がない
  • commandmatedev CLI の使い方を対話的に聞ける窓口がなく、ドキュメントを別途参照する必要がある
  • リポジトリ全体の俯瞰的な開発相談(設計判断・Issue 整理等)を行うための汎用的なセッションが存在しない

提案する解決策

1. グローバルセッション概念の追加

worktree に紐づかない「グローバルセッション」を新設する:

  • tmux セッション名: mcbd-{cli_tool_id}-__global__ 形式(例: mcbd-claude-__global__, mcbd-codex-__global__
    • 既存の BaseCLITool.getSessionName(worktreeId) をそのまま再利用し、worktreeId__global__ を渡す
    • getSessionName('__global__')mcbd-{tool}-__global__ を返す(既存コードの変更不要)
    • CLIツール毎に独立したセッションを持つ(CLIツール切替時に既存セッションを破棄する必要がない)
    • cli-tools/validation.tsSESSION_NAME_PATTERNmcbd-claude-__global__ を許容済み(確認済み)
    • security/path-validator.tsWORKTREE_ID_PATTERN__global__ を許容(アンダースコア許可、確認済み)
  • 作業ディレクトリ: 登録リポジトリの一覧から選択(ドロップダウン)
    • セッション実行中にリポジトリを変更した場合は確認ダイアログを表示し、既存セッションを停止して再作成する
  • CLI ツール: CLIToolManager.getInstalledTools() で取得したインストール済みツール全種を選択肢として表示する(claude / codex / gemini / vibe-local / opencode / copilot)
    • 既存の CLI_TOOL_IDS 定数(src/lib/cli-tools/types.ts)の全6種類と整合

2. Home 画面への埋め込み

現在の Home 画面(セッションサマリー + ショートカットカード)の上部にチャット UI を配置:

  • グローバルセッション専用の簡略版コンポーネント AssistantMessageInput を新規作成する
    • 既存の MessageInputworktreeId を必須Propsとして受け取り、内部で worktreeApi.sendMessage() / useSlashCommands() / useImageAttachment() / InterruptButton 等が全て worktreeId に依存しているため、そのまま拡張すると50箇所以上の影響がある
    • AssistantMessageInput はメッセージ送信のみに特化し、スラッシュコマンド・画像添付・割り込みボタン等のworktree固有機能は含めない
    • グローバルセッション用APIルート(/api/assistant/*)を直接呼び出す設計とする
  • リポジトリ選択ドロップダウン + CLI ツール選択
  • ターミナル出力表示: 既存の capturePane API と同等のキャプチャ機構を利用してリアルタイム表示する
  • レイアウト考慮:
    • チャットUI部分は折りたたみ可能(Collapse/Expand)とし、非アクティブ時は最小化表示にする
    • 高さは最大 50vh を上限とし、スクロール可能にする
    • モバイルレイアウトではタブ切替方式(チャット / セッションサマリー)で表示する

3. チャット履歴の保存方針

セッション内のみ(Phase 1): ターミナル出力のキャプチャ(capturePane)のみで表示し、DBマイグレーションは不要とする。

  • tmuxセッション終了時に履歴は失われる
  • Phase 1 では DB 操作を一切行わない: chat-db.tscreateMessage()session-db.tsupdateSessionState() は呼び出さない
    • chat_messages テーブルの FOREIGN KEY (worktree_id) REFERENCES worktrees(id) ON DELETE CASCADE 制約により、__global__ での INSERT は失敗する(init-db.ts:46
    • session_states テーブルも同様の FOREIGN KEY 制約を持つ(init-db.ts:79-88
    • DBスキーマ変更(chat_messages.worktree_id の NOT NULL 制約変更等)を回避し、影響範囲を最小化する
  • DB保存が必要になった場合は follow-up Issue で対応する(仮想worktreeレコード挿入方式 or FOREIGN KEY 制約の見直しを検討)
  • Phase 1 では会話ログファイル出力もスコープ外: conversation-logger.tsrecordClaudeConversation()worktreeId で DB 問合せするため、DB 非保存方針では常に null を返しログが記録されない

4. レスポンスポーリング設計

グローバルセッション専用のポーリング関数を新規実装する(既存 response-checker.ts の再利用を廃止):

  • 既存の response-checker.tscheckForResponse() は冒頭で getWorktreeById(db, worktreeId) を呼び出し、結果が null の場合に stopPolling() して return する(response-checker.ts:408-415)。仮想 worktreeID __global__worktrees テーブルに存在しないため、ポーリング開始直後に停止される
  • 対応方針: グローバルセッション専用のポーリング関数 pollGlobalSession(cliToolId) を新規作成する
    • DB チェック(getWorktreeById)をスキップ
    • DB 保存(createMessage, updateSessionState)をスキップ
    • tmux キャプチャ出力のみを返す軽量なポーリングループ
    • activePollers Map のキーには __global__:{cliToolId} を使用して既存ポーラーとの重複を防止
  • startPolling('__global__', cliToolId) / stopPolling('__global__', cliToolId) は使用しない(既存関数内部の DB 依存ロジックとの衝突を回避)

5. デフォルトコンテキスト

セッション開始時に以下をコンテキストとして付与する:

  • CommandMate CLI コマンド一覧・使い方
  • 登録済みリポジトリ一覧(名前・パス・別名・worktree 数)
  • 現在アクティブな worktree セッションのステータス(セッション開始時のスナップショット。都度更新はしない)

CLIツール毎のコンテキスト付与方式:

CLIツール 付与方法
Claude Code CLAUDE.md 自動読み込み(CLI 標準動作) + 初回メッセージにリポジトリ情報付与
Codex --system-prompt 引数でコンテキスト全体を渡す
Gemini 初回メッセージとしてコンテキスト情報を送信
Copilot 初回メッセージとしてコンテキスト情報を送信
OpenCode 初回メッセージとしてコンテキスト情報を送信
Vibe Local 初回メッセージとしてコンテキスト情報を送信

6. セッションのライフサイクル管理

  • セッション停止: UI 上にセッション停止ボタンを配置し、ユーザーが明示的に停止できるようにする
  • サーバー再起動時: session-cleanup.tscleanupGlobalSessions() 関数を新規追加し、以下を行う:
    • mcbd-{cli_tool_id}-__global__ パターン(全 CLI_TOOL_IDS をループ)の孤立 tmux セッションを検出・停止
    • syncWorktreesAndCleanup() から呼び出す(DB ベースの削除 ID ループとは別の独立した処理として実装)
    • サーバー起動時にも既存グローバルセッションを検出してクリーンアップ
  • ページ遷移時: グローバルセッションは維持する(Home画面に戻った際にセッション状態を復元表示する)
  • CLIツール切替時: 各CLIツールが独立セッションを持つため、切替時に既存セッションの停止は不要。ただし前のツールのセッションが残り続けるため、UIに「全セッション停止」ボタンも提供する
  • サイドバー表示の除外: worktree-status-helper.tsdetectWorktreeSessionStatus() でグローバルセッション(__global__)をサイドバーの worktree 一覧から除外するフィルタを追加する。worktrees API のレスポンスにグローバルセッションが含まれないようにする

7. API 追加

  • POST /api/assistant/start — グローバルセッション開始(ディレクトリ・CLI ツール指定)
  • POST /api/assistant/terminal — グローバルセッションへのメッセージ送信
  • GET /api/assistant/current-output — グローバルセッションの出力取得
  • DELETE /api/assistant/session — グローバルセッション停止
  • 認証: /api/assistant/*middleware.ts の認証マッチャーで自動的にカバーされる(AUTH_EXCLUDED_PATHS に追加しないこと)。実装時に認証テストを追加して確認する

8. スコープ定義(Phase 1)

Phase 1 では基本的なメッセージ送受信のみをサポートする。以下の高度な機能はスコープ外とし、必要に応じて follow-up Issue で対応する:

  • Auto-Yes 機能のグローバルセッション対応
  • スケジューラー連携
  • CLI コマンド(commandmate ls, send, wait 等)からのグローバルセッション操作
  • チャット履歴の DB 永続化
  • スラッシュコマンド / 画像添付
  • 会話ログファイル出力(conversation-logger.ts

Phase 1 スコープ外機能一覧

機能 スコープ外理由 Phase 2 引き継ぎ要否
Auto-Yes auto-yes-manager.ts の Map キーが worktreeId 依存。resource-cleanup.tscleanupOrphanedMapEntries()__global__ を孤立と判定して削除する 要: cleanupOrphanedMapEntries() に予約 ID スキップロジック追加
スケジューラー連携 schedule-manager.ts が worktree 単位のジョブ管理。グローバルセッション用のジョブ定義が未設計 要: グローバルセッション用スケジュール設計
CLI コマンド統合 commandmate ls/send/wait 等が worktreeId を必須引数として受け取る設計 要: --global フラグ追加等の設計
DB 永続化 chat_messages / session_states の FOREIGN KEY 制約が __global__ を拒否 要: 仮想レコード挿入 or FK 制約見直し
スラッシュコマンド useSlashCommands() が worktreeId ベースのコマンドファイル探索 要: グローバルスコープのコマンド探索設計
画像添付 useImageAttachment() が worktreeId ベースのアップロード先管理 要: グローバルセッション用アップロードパス設計
会話ログ出力 conversation-logger.ts が worktreeId で DB 問合せ。DB 非保存方針では機能しない 要: DB 保存対応後に連携
resource-cleanup.ts 予約ID対応 cleanupOrphanedMapEntries()__global__ エントリを孤立判定 要: 予約 ID スキップロジック追加

実装タスク

  • グローバルセッション管理ロジック追加(tmux セッション作成・管理・停止・クリーンアップ)
    • tmux セッション名は mcbd-{cli_tool_id}-__global__ 形式(既存の getSessionName('__global__') を再利用)
  • POST/GET/DELETE /api/assistant/* API ルート追加(start, terminal, current-output, session)
    • DB 操作(createMessage, updateSessionState)は一切行わない
  • /api/assistant/* への認証ミドルウェア適用確認テスト追加
    • AUTH_EXCLUDED_PATHS/api/assistant を追加しないことを確認するテスト
  • リポジトリパスのバリデーション(registeredリポジトリのパスのみ許可)
  • Home 画面にアシスタントチャット UI コンポーネント追加(AssistantMessageInput 新規作成)
  • チャットUI 折りたたみ・最小化表示の実装
  • リポジトリ選択ドロップダウン実装(登録リポジトリ一覧取得)
  • リポジトリ変更時の確認ダイアログとセッション再作成フロー
  • CLI ツール選択 UI 実装(CLIToolManager.getInstalledTools() を使用)
  • デフォルトコンテキスト生成ロジック(CLI 使い方 + リポジトリ情報、CLIツール毎の付与方式対応)
  • グローバルセッション専用ポーリング関数 pollGlobalSession(cliToolId) の新規実装
    • DB チェック(getWorktreeById)をスキップ
    • DB 保存(createMessage, updateSessionState)をスキップ
    • tmux キャプチャ出力のみを返す軽量ポーリング
  • ターミナル出力リアルタイム表示(capturePane 連携)
  • セッション停止UI(個別停止 + 全セッション停止ボタン)
  • session-cleanup.ts への cleanupGlobalSessions() 関数追加
    • CLI_TOOL_IDS をループして mcbd-{cli_tool_id}-__global__ パターンのセッションを検出・停止
    • syncWorktreesAndCleanup() から呼び出し
    • サーバー起動時の既存グローバルセッション検出・クリーンアップ
  • worktree-status-helper.ts にグローバルセッション除外フィルタ追加
    • detectWorktreeSessionStatus()__global__ セッションをサイドバー表示から除外
  • モバイルレイアウト対応(タブ切替方式)
  • ユニットテスト・結合テスト追加
    • 既存 session-cleanup テストの回帰確認
    • グローバルセッション用クリーンアップテスト追加
    • pollGlobalSession の正常系・異常系テスト
    • /api/assistant/* の認証テスト
  • 実装完了後に CLAUDE.md のモジュール一覧に新規 API ルート・コンポーネントを追記

受入条件

  • Home 画面でアシスタントチャットが利用できる
  • 登録済みリポジトリの一覧から作業ディレクトリを選択できる
  • インストール済みの全CLIツールから選択してセッションを開始できる
  • セッション開始時に CLI 使い方・リポジトリ情報がコンテキストとして付与される(CLIツール毎の付与方式に従う)
  • メッセージの送受信が正常に動作する
  • アシスタントのターミナル出力がリアルタイムに表示される
  • ターミナル出力のキャプチャ間隔が既存の capture API と同等である
  • セッション停止ボタンからグローバルセッションを停止できる
  • セッション実行中にリポジトリを変更した場合、確認ダイアログが表示される
  • サーバー再起動時に孤立した mcbd-{cli_tool_id}-__global__ セッションがクリーンアップされる
  • グローバルセッションがサイドバーの worktree 一覧に表示されない
  • チャットUIが折りたたみ/展開できる
  • 既存の worktree セッション機能に影響がない(回帰テストパス)
  • ダークモード対応
  • モバイルレイアウトでチャットUIが適切に表示される
  • /api/assistant/* が認証ミドルウェアで保護されている
  • npm run lint / npx tsc --noEmit / npm run test:unit がパスする

影響範囲

変更対象ファイル(想定)

ファイル 変更内容
src/app/page.tsx アシスタントチャット UI の組み込み
src/app/api/assistant/ (新規) グローバルセッション用 API ルート(start, terminal, current-output, session)。DB 操作は行わない
src/lib/session/ グローバルセッション管理ロジック追加
src/lib/polling/ (新規) グローバルセッション専用ポーリング関数 pollGlobalSession()
src/lib/session-cleanup.ts cleanupGlobalSessions() 関数追加(mcbd-{cli_tool_id}-__global__ パターン対応)
src/lib/session/worktree-status-helper.ts グローバルセッション除外フィルタ追加
src/lib/tmux/tmux.ts グローバルセッション用の tmux 操作対応
src/components/home/ (新規) AssistantMessageInput, AssistantChatPanel 等のコンポーネント
src/middleware.ts /api/assistant/* への認証ミドルウェア適用確認(変更不要、テストのみ)

影響を受けるが変更しないファイル(Phase 1)

ファイル 影響内容 対応方針
src/lib/polling/response-checker.ts checkForResponse()getWorktreeById()__global__ で null を返す 専用ポーリング関数で回避(既存コード変更なし)
src/lib/db/chat-db.ts createMessage() の FOREIGN KEY 制約 Phase 1 では呼び出さない
src/lib/db/session-db.ts updateSessionState() の FOREIGN KEY 制約 Phase 1 では呼び出さない
src/lib/conversation-logger.ts recordClaudeConversation() が null を返す Phase 1 ではスコープ外
src/lib/resource-cleanup.ts cleanupOrphanedMapEntries()__global__ を孤立判定 Phase 2 で予約 ID スキップ対応

関連コンポーネント

  • MessageInput — メッセージ入力 UI(参考設計。直接流用ではなく AssistantMessageInput を新規作成)
  • CLIToolManager — CLI ツール管理(getInstalledTools() でインストール済みツール一覧取得)
  • HomeSessionSummary — 既存 Home コンポーネント(レイアウト調整、モバイル時タブ切替対応)
  • repositoryApi.list() — リポジトリ一覧取得(Issue feat(repositories): リポジトリ一覧表示と別名編集UI #644 で追加済み)
  • session-cleanup.ts — セッションクリーンアップ(cleanupGlobalSessions() 新規追加)
  • BaseCLITool.getSessionName() — セッション名生成(__global__ を引数として既存関数を再利用)

レビュー履歴

Stage 1 (2026-04-14)

  • S1-001: CLIツール選択範囲をインストール済み全ツール(6種)に拡張
  • S1-002: MessageInput拡張方針を明確化(グローバルセッション専用 AssistantMessageInput 新規作成)
  • S1-003: レスポンスポーリング設計方針追記(仮想worktreeID __global__ 使用)
  • S1-004: セッションのライフサイクル管理追記(停止UI、クリーンアップ、ページ遷移時の方針)
  • S1-005: tmuxセッション名を mcbd-global-{cli_tool_id} 形式に変更(CLIツール毎に独立セッション)
  • S1-006: チャット履歴保存方針をセッション内のみ(Phase 1)に確定
  • S1-007: デフォルトコンテキスト付与方法をCLIツール毎に具体化
  • S1-008: 作業ディレクトリ変更時の処理方針追記(確認ダイアログ + セッション再作成)
  • S1-009: 受入条件にターミナル出力表示の検証項目追加
  • S1-010: セッション停止API(DELETE /api/assistant/session)追加
  • S1-011: Home画面レイアウト変更への配慮追記(折りたたみ、高さ上限、モバイル対応)

Stage 3 - 影響範囲レビュー (2026-04-14)

  • S3-MF-001: ポーリング設計を「専用関数方式」に変更(response-checker.tsgetWorktreeById() チェック回避)
  • S3-MF-002: Phase 1 で DB 操作を一切行わないことを明記(FOREIGN KEY 制約対策)
  • S3-MF-003: cleanupGlobalSessions() 関数の実装タスク追加(tmux セッションリーク防止)
  • S3-SF-001: Phase 1 で会話ログファイル出力がスコープ外であることを明記
  • S3-SF-002: resource-cleanup.ts の予約 ID スキップ対応を Phase 2 タスクとして明記
  • S3-SF-003: セッション命名を mcbd-{cli_tool_id}-__global__ に統一(既存 getSessionName() 再利用)
  • S3-SF-004: 回帰テスト・グローバルセッション用テストのタスクを詳細化
  • S3-SF-005: サイドバーからグローバルセッションを除外するフィルタ実装タスク追加
  • S3-SF-006: /api/assistant/* の認証テスト追加を実装タスクに明記
  • S3-SF-007: session_states の FOREIGN KEY 制約対策を S3-MF-002 に統合
  • S3-NTH-001: CLAUDE.md モジュール一覧更新タスク追加
  • S3-NTH-002: Phase 1 スコープ外機能一覧テーブル追加

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions