PRODUCT NOTE / PRD
ページを閉じずに、その場で AI に訊く。
この文書は「どう使うか」ではなく、なぜ・誰のために・どんな判断で作ったかを記録した開発ノートです。
| ステータス | Shipped / Active(v2.0.2) |
|---|---|
| 初版 | 2023-09-30(v0.5 系・ChatGPT 連携のポップアップ版) |
| 刷新 | 2026-07-18(v2.0.0・サイドパネル型へ全面刷新) |
| ストア公開 | 2026-07-20(Chrome ウェブストアで公開) |
| 提供形態 | Chrome 拡張機能(Manifest V3 / Chrome 116 以降)・限定公開 |
| 対象ユーザー | Google 認証で許可されたユーザーのみ(許可リスト制) |
| 最終更新 | 2026-08-02 |
| 技術 | Manifest V3 ・ chrome.sidePanel ・ Google OAuth(id_token)→ 自前 JWT ・ FastAPI ・ Gemini 2.5 Flash ・ LangChain |
| 関連リンク | Chrome ウェブストア ・ 開発ノート一覧 |
Quick Query Question は、ブラウザのサイドパネルに常駐する AI アシスタントです。
閲覧中のページから離れずに、引用テキスト・画面キャプチャ・各種ファイル(PDF・画像・動画・CSV・テキスト等)を添えて質問・翻訳・校正・要約ができます。
バックエンドは nzw.jp(Gemini)で、利用は許可制です。
v2.0.0 以前の動機は当時の設計文書が残っていないため、コミット履歴と実装から再構成した。v1 系の背景は推測
運営者本人と、許可リストに登録された知人。Google 認証を通ったユーザーのみが利用でき、一般公開は前提にしていない。
「ページを離れずに完結したか」を中心に見る。数値は目標仮置き
v2.0.1 以降の項目は実作業に基づく記録。v2.0.0 以前および security / UX の項目は、実装から読み取れる判断を再構成したもの。一部は実装から再構成
v2.0.1 で「引用ボタンはパネルの開閉に関わらず常に出す」と決めたが、未認証のときは設定に関わらず出さないという条件を足した。
ログアウトした瞬間、すでに表示中のボタンも消す。判定は content script が保存済みユーザー情報の有効期限(exp)だけを見て行い、JWT 本体は読まない。
認証状態が読み取れるまでは OFF 扱いにする。あわせて引用ボタンの表示 ON/OFF を設定画面に出した(即時反映)。
この拡張は許可リスト制で、未ログインのままでは押しても何も起きない。押して無反応なボタンは「機能がある」ではなく「壊れている」と読まれる。
加えて拡張はあらゆるページに注入されるため、権限のない相手にまで UI を撒くこと自体が無駄でもある。判定を content script 側で完結させたのは、ページごとに背景へ問い合わせる往復を避けるため。
ただしページ側のコードに認証情報の中身を持ち込まないのは譲れないので、読むのは有効期限だけに絞った。読めない・判断がつかない状態は「出さない」側へ倒す(fail-closed)。
min-height と JS 側の定数の両方に同じ値を持たせている。1 行から伸びる入力欄は短文の投稿を前提とした形だが、この拡張の主用途は「引用やファイルを添えて長めに指示する」ほう。書いている途中で欄が伸びるたびにレイアウトが動き、直前に書いた文が視界の外へ押し出される。
最初から広く取っておけば、入力中に高さが変わらない。
chrome.sidePanel による常駐パネルへ作り直した。同時に AI 基盤を ChatGPT 直叩きから nzw.jp(Gemini)経由へ移した。ポップアップは「ページをクリックすると閉じる」という仕様上、ページを見ながらの会話が原理的に成立しない。UI の改善では埋まらない構造的な問題だと判断した。
バックエンドを自前に寄せたのは、API キーを拡張に埋め込まず許可制にできるため。
images 経路、それ以外は新設の files 経路(base64 + mime_type)で送る 2 系統に分けた。引用ボタンと範囲添付は「選択テキストを渡す」という同じ仕事をしており、ボタンが 2 つあること自体が迷いを生んでいた。機能を足すより先に、重複を消して枠を空けるべきだと判断した。
経路を分けたのは、画像は送信前の縮小が必要で、他形式とは前処理が異なるため。
.txt の添付へ切り出す。実装上の落とし穴があった。chrome.sidePanel.open() はユーザー操作の直後にしか呼べないため、await を挟んでから呼ぶとジェスチャが失効して拒否される。
引用テキストの保存より先に open() を呼ぶ順序が必須で、ここを崩すと機能が壊れる。
id_token を nzw.jp のバックエンドで検証し、自前 JWT に交換して /v1/assistant/* を呼ぶ。許可リストに載ったメールアドレスのみ通す。scripting 権限を manifest から削除した。拡張は 3 つのスクリプトに役割を分けている。ネットワーク通信は service worker に集約し、ページ側のスクリプトは最小限に留める。
| 構成要素 | 役割 |
|---|---|
background.js(service worker) | Google 認証(id_token → 自前 JWT の交換)と API 通信を集約。拡張の worker から fetch するため CORS を回避できる |
sidepanel.js | チャット UI・履歴・プロンプト・入力欄制御。ファイルの読み込みと base64 化もここで行う |
contents.js(content script) | ページ上の「引用する」ボタンのみ。選択テキストを service worker へ渡す |
| 受け渡し | 引用テキストは chrome.storage.local を仲介。パネルが開いていれば onChanged、閉じていれば起動時の読み込みで取り込む |
| バックエンド | FastAPI の /v1/assistant/chat。添付は Gemini の inline データへ変換して送信 |
初版。ChatGPT 連携のポップアップ型ツールとして公開
入力上限の緩和、右クリックメニュー、コピー・テキスト書き出しなどを追加
サイドパネル型へ全面刷新。nzw.jp(Gemini)連携・Google 認証・会話履歴・プロンプト登録・引用ボタン・画面キャプチャ添付に対応
範囲添付を廃止しファイル添付(ドラッグ&ドロップ・長文の自動ファイル化)へ置換。引用ボタンをパネル未起動でも利用可能に。scripting 権限を削除
未認証時は引用ボタンを表示しない(判定は有効期限のみ・fail-closed)。引用ボタンの表示 ON/OFF を設定に追加。入力欄の高さを常時 5 行ぶん確保
未決事項:添付データの保持方針、AI 利用コストの上限設計、公開範囲を広げるかどうか。