Skip to content

fix: Gemini CLI promptPattern does not match actual Gemini prompt format #386

@Kewton

Description

@Kewton

Note: このIssueは 2026-03-09 にレビュー結果(Stage 1, Stage 3)を反映して更新されました。
詳細: dev-reports/issue/386/issue-review/

概要

Gemini CLIの応答完了後、ステータスがスピナー(processing)のまま ready に遷移しない。
GEMINI_PROMPT_PATTERN が実際のGeminiプロンプト形式にマッチしないことが原因。

現象

  • Worktree: commandmate-marketing-main(CLIツール: gemini)
  • Geminiが応答完了してプロンプト入力待ち状態にもかかわらず、UIのステータスがスピナー(isProcessing: true)のまま
  • API応答: sessionStatusByCli.gemini = { isRunning: true, isWaitingForResponse: false, isProcessing: true }

原因

現在の GEMINI_PROMPT_PATTERN

// src/lib/cli-patterns.ts:132
export const GEMINI_PROMPT_PATTERN = /^[>]\s*$/m;

行頭が > または で、その後が空白のみの行にマッチする。

実際のGeminiプロンプト出力

 >   Type your message or @path/to/file
  • 先頭にスペースがある( >
  • > の後にプレースホルダーテキストがある(Type your message or @path/to/file

status-detector.ts での検出失敗フロー

  1. ステップ1(プロンプト検出): detectPrompt() → 対話的プロンプトではないためスキップ
  2. ステップ2(thinking検出): detectThinking() → thinkingインジケーターなしでスキップ
  3. ステップ3(入力プロンプト検出): getCliToolPatterns("gemini").promptPattern(= GEMINI_PROMPT_PATTERN)を介して promptPattern.test(lastLines) が呼ばれる → マッチしない(先頭スペース+テキスト付きのため)
  4. ステップ4(時間ベース): lastOutputTimestamp 未提供のためスキップ
  5. ステップ5(デフォルト): status: 'running'スピナー表示

修正方針

GEMINI_PROMPT_PATTERN を実際のGeminiプロンプト形式にもマッチするよう拡張する。

// 現在
export const GEMINI_PROMPT_PATTERN = /^[>]\s*$/m;

// 修正案: 先頭スペース許容、プレースホルダーテキスト許容
export const GEMINI_PROMPT_PATTERN = /^\s*[>]\s*(Type your message.*)?$/m;

リテラル文字列依存に関する考察

修正案は Type your message というリテラル文字列に依存しており、Gemini CLIのバージョンアップでプレースホルダーテキストが変更された場合(例: Ask a question 等)に再度マッチしなくなるリスクがある。

より堅牢な代替案として /^\s*[>❯]\s*(.*)$/m> or の後は任意テキスト許容)も検討したが、他のCLIツールのレスポンス行でたまたま > で始まる行を誤検出するリスクとのトレードオフがある。

現案を採用する理由: 現時点でのGemini CLIプロンプトの実態に即した最小変更であり、誤検出リスクを避けつつ既知の問題を確実に解消できる。将来プレースホルダーが変更された場合は、その時点で再度パターンを更新する方針とする。

修正対象

  • src/lib/cli-patterns.ts: GEMINI_PROMPT_PATTERN(132行目)の修正
  • src/lib/cli-patterns.ts: getCliToolPatterns('gemini')skipPatterns(311行目)内のインラインパターン /^[>❯]\s*$/GEMINI_PROMPT_PATTERN への参照に変更し、DRY原則に適合させる(新しいプロンプト形式もフィルタ対象に含める)
  • src/lib/cli-tools/gemini.ts: handleTrustDialog 内(128行目)のハードコードパターン /^[>❯]\s*$/mGEMINI_PROMPT_PATTERN への参照に変更し、新しいプロンプト形式(先頭スペース+テキスト付き)でもGeminiプロンプトを正しく検出できるようにする
  • テストファイル: パターン修正に対応するテスト追加(具体的なテストケースは受入条件を参照)

変更不要の箇所

  • src/lib/cli-patterns.ts: claude用 skipPatterns(272行目)の /^[>❯]\s*$/ はClaude専用のため変更不要。GeminiのGEMINI_PROMPT_PATTERNの修正による影響はない
  • src/lib/response-poller.ts: 759行目の userPromptPattern = /^[>❯]\s+\S/ および879行目の /^[>❯]\s+(\S.*)$/m はユーザーが入力したプロンプト行(> メッセージ)を検出するためのパターンであり、Geminiの待機プロンプト( > Type your message...)とは用途が異なる。先頭スペース付きの待機プロンプトはこれらのパターンにマッチしないため、現時点では影響なし(調査済み)

受入条件

  • Gemini応答完了後、ステータスが ready に遷移する(スピナーが消える)
  • 既存のGeminiプロンプト形式(> のみの行)も引き続きマッチする
  • 新しいプロンプト形式( > Type your message or @path/to/file)もマッチする
  • getCliToolPatterns("gemini").skipPatterns が新しいプロンプト形式にもマッチすること
  • gemini.tshandleTrustDialog 内のパターンも新形式にマッチすること
  • 既存テストが通る

具体的なテストケース

以下のテストケースを tests/unit/lib/cli-patterns.test.ts に追加すること:

  1. 旧形式マッチ: > のみの行が GEMINI_PROMPT_PATTERN にマッチする
  2. 旧形式マッチ(❯): のみの行が GEMINI_PROMPT_PATTERN にマッチする
  3. 新形式マッチ: > Type your message or @path/to/fileGEMINI_PROMPT_PATTERN にマッチする
  4. 誤検出防止: レスポンス本文中の > quoted text(先頭スペースなし、引用テキスト)が GEMINI_PROMPT_PATTERN に誤マッチしないこと
  5. skipPatterns検証: getCliToolPatterns("gemini").skipPatterns が新形式にもマッチすること

レビュー履歴

Stage 1 (2026-03-09)

  • 修正方針の明確化、リテラル文字列依存に関する考察を追加
  • skipPatterns修正をDRY原則の観点で追加

Stage 3 (2026-03-09) - 影響範囲レビュー

  • I1: gemini.ts handleTrustDialog内のハードコードパターンを修正対象に追加
  • I2: response-poller.tsのパターンは影響なしであることを「変更不要の箇所」として明記
  • I3: 具体的なテストケース5件を受入条件に追加
  • I4: claude用skipPatterns(272行目)は変更不要であることを明記

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions