oobe.

· by 師岡 誠太

ObsidianのAIプラグインを改造して、日本語IMEのEnter誤送信を直した話

#Obsidian #Claude Code #TypeScript #OSS #AI活用

私は日々の業務のほとんどを、AIアシスタント(Claude Code)と並走しながら進めています。その入り口のひとつが、ノートアプリ Obsidian の中で Claude と会話できるコミュニティプラグイン「Claudian」(Yishen Tu 氏作・MIT ライセンス)です。

このプラグインには、AIが「選択肢形式」で質問してくる UI があります。A・B・C から選ぶか、「その他」欄に自由記述で答えるか——という画面です。ところがこの「その他」欄、日本語で入力していると、変換を確定するための Enter で回答そのものが送信されてしまうのです。「承認フローの見直しを……」と打って変換確定した瞬間、書きかけの数文字が回答として飛んでいく。使うたびに小さなストレスでした。

既製品なら「そういう仕様か」で終わりです。でもソースが公開されているツールなら、中を開けて直せます。この記事は、その診断から修正・検証までの記録です。

症状を正確にする — 「Enterで送信される」は3つの問題だった

まず該当 UI の実装(InlineAskUserQuestion.ts)を読み、症状を分解しました。「Enterで誤送信される」と一言で感じていた不満は、実際には独立した3つの問題の重なりでした。

// 修正前: 入力欄フォーカス中のキー処理(要約)
if (e.key === 'Tab' || e.key === 'Enter') {
  e.preventDefault();
  this.isInputFocused = false;
  activeElement?.blur();
  this.switchTab(this.activeTabIndex + 1); // 無条件で「回答確定 → 次の質問へ」
}
  1. Enter が無条件で「確定」扱い — 修飾キーも設定も見ずに、Enter は常に回答を確定して次の質問へ移動する実装だった
  2. そもそも改行を入力できない — 入力欄が1行用の <input type="text"> で作られており、仮に Enter の挙動を変えても複数行の回答は物理的に書けない
  3. IME 変換中の Enter を区別していない — キーイベントには「いま日本語変換の途中か」を示す isComposing というフラグがあるのに、参照していない。変換確定の Enter と送信の Enter が同一視されていた

興味深いのは、このプラグインのチャット本体の入力欄には「送信に Cmd/Ctrl+Enter を必須にする」という設定が既にあり、そちらは IME も正しく処理していることです。つまり作者は問題を理解している。選択肢 UI だけが、その設計から取り残されていました。

修正方針 — 新しい挙動を発明しない

改造で一番やってはいけないのは、自分だけの独自ルールを増やすことだと考えています。今回の方針は「チャット本体の既存設定に、選択肢 UI を連動させる」の一点です。

  • 「送信に Cmd/Ctrl+Enter 必須」設定が ON なら: Enter は改行、Cmd/Ctrl+Enter で回答確定
  • 設定が OFF なら: 従来どおり Enter で確定(Shift+Enter で改行)
  • IME 変換中の Enter は、設定に関わらず常に無視する

実装は、入力欄を自動で高さが伸びる <textarea> に置き換えた上で、キー判定をこう変えました。

if (e.key === 'Enter') {
  // IME変換中のEnterは変換確定であって送信ではない
  if (e.isComposing) return;

  const hasCommitModifier = Platform.isMacOS
    ? e.metaKey && !e.ctrlKey && !e.altKey
    : e.ctrlKey && !e.metaKey && !e.altKey;

  // 設定ONなら修飾キーなしのEnterは改行として通す
  if (this.config.requireModifierToCommit ? !hasCommitModifier : e.shiftKey) return;
}
// ここまで抜けたら回答を確定して次の質問へ

なお、パスワード形式で聞かれる秘密入力だけは <textarea> にできない(伏せ字表示が効かない)ため、従来の1行入力のまま残しています。一律に変えないことも設計判断のうちです。

検証 — テストを割らずに、テストを足す

このプラグインには既存のユニットテストが61件ありました。改造の検証は「既存を1件も割らないこと」と「新しい挙動そのものをテストにすること」の両方です。

  • 「設定ONのとき、素のEnterでは回答が確定しない」
  • 「Cmd+Enterでは確定する」
  • 「IME変換中のEnterでは、設定に関わらず確定しない」

といった6件を追加し、計67件が全て通ることを確認しました。日本語IMEの挙動はまさに今回の主役なので、リグレッションを防ぐ保険としてテストに焼き込んでおく価値があります。

ひとつ罠も踏みました。スタイルの修正をリポジトリ直下の styles.css に入れたところ、ビルドしたら消えたのです。調べると、このファイルは src/style/ 配下のモジュール CSS を連結して生成されるビルド成果物でした。成果物を直接編集しても、次のビルドで上書きされて消えます。ソースと成果物の区別は、他人のリポジトリを触るときに最初に確認すべきことのひとつです。

まとめ — 道具は「使う」だけでなく「直せる」

今回の変更は、行数にすれば大きくありません。でも「Enterを押すたびに回答が飛ぶ」という毎日のストレスが消え、日本語での長文回答が普通に書けるようになりました。AIとの協業が日常になるほど、こういう入力体験の摩擦は積み重なって効いてきます。

  • 症状は分解する(「誤送信」の正体は3つの独立した問題だった)
  • 修正は既存の設計に寄せる(独自ルールを発明しない)
  • 検証はテストに焼き込む(既存61件+新規6件)

oobe では、こうした「既製ツールのあと一歩」を埋める改修や、業務に合わせた AI 活用環境の構築を行っています。使っているツールへの小さな不満が積もっている方は、お問い合わせからお気軽にどうぞ。