チュートリアル 3: ストリーミングコードレビュー
スクリプト: src/python/scripts/tutorials/03_streaming_review.py
学べること
SessionConfigでストリーミングを有効にする方法- リアルタイム出力のために
ASSISTANT_MESSAGE_DELTAイベントを受信する方法 - 統合差分(unified diff)をもとにコードレビュープロンプトを構造化する方法
- ストリーミングと非ストリーミングのレスポンスの違い
前提条件
copilotCLI がインストール済みかつ認証済み(はじめに を参照)github-copilot-sdkがインストール済み
ストリーミング vs 非ストリーミング
| モード | streaming=True |
streaming=False |
|---|---|---|
| トークンの到着 | ASSISTANT_MESSAGE_DELTA で逐次届く |
完全なレスポンスが生成された後 |
| 最初のバイトのレイテンシ | 低い — すぐに出力が表示される | 高い — 完全な回答を待つ |
| ユースケース | インタラクティブ UI、長いレスポンス、進捗表示 | バッチ処理、構造化出力のパース |
ステップ 1 — SessionConfig でストリーミングを有効にする
session = await client.create_session(
SessionConfig(
on_permission_request=approve_all,
tools=[],
streaming=True, # ← ストリーミングを有効化
system_message=SystemMessageReplaceConfig(
mode="replace",
content=(
"You are a senior software engineer conducting a thorough code review. "
"For each change in the diff: identify bugs, security issues, and style problems."
),
),
)
)
ステップ 2 — トークンが届くたびに出力する
各デルタトークンを直接 stdout に出力するイベントハンドラを登録します:
from copilot.generated.session_events import SessionEventType
def on_event(event) -> None:
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
print(event.data.delta_content, end="", flush=True)
elif event.type == SessionEventType.SESSION_ERROR:
print(f"\n[Error] {event.data.message}")
session.on(on_event)
重要なのは end="" と flush=True — これによりトークン間に改行が入らず、即座に出力されます。
ステップ 3 — コードレビュープロンプトを送信する
差分をプロンプトに直接埋め込みます:
diff_text = """
diff --git a/src/auth.py b/src/auth.py
...
- return hashlib.md5(password.encode()).hexdigest()
+ return hashlib.sha256(password.encode()).hexdigest()
"""
prompt = f"Please review the following diff and provide feedback:\n\n```diff\n{diff_text}\n```"
await session.send_and_wait(MessageOptions(prompt=prompt), timeout=300)
print() # ストリーミング出力終了後の改行
イベントフローの理解
streaming=True の場合、イベントはこの順序で届きます:
ASSISTANT_TURN_START
ASSISTANT_MESSAGE_DELTA (トークン 1)
ASSISTANT_MESSAGE_DELTA (トークン 2)
ASSISTANT_MESSAGE_DELTA (トークン 3)
...
ASSISTANT_TURN_END
SESSION_IDLE
send_and_wait は SESSION_IDLE の後に返ります。すべてのデルタイベントはその前にハンドラに配信されます。
サンプル出力
組み込みのサンプル差分に対してスクリプトを実行した場合:
=== Streaming Code Review ===
### Security Issues
**Line -12:** `hashlib.md5` is a cryptographically broken hash function.
Using it for password hashing exposes users to collision attacks.
✅ The fix to `sha256` is correct, but consider using `bcrypt` or `argon2` for
password storage instead of raw SHA-256.
### Incomplete Implementation
**Line 31:** The `# TODO: add expiry check` comment indicates the token
validation logic is incomplete. This could allow expired tokens to be accepted.
### Critical: Missing Authorization
**Lines 35-37:** `delete_user()` performs a destructive operation with no
authorization check. Any caller can delete any user...
スクリプトの実行
cd src/python
# 組み込みのサンプル差分を使用
uv run python scripts/tutorials/03_streaming_review.py
# 独自の差分をレビュー
uv run python scripts/tutorials/03_streaming_review.py --diff path/to/changes.diff
# カスタム CLI サーバー(オプション)
uv run python scripts/tutorials/03_streaming_review.py --cli-url localhost:3000
まとめ
SessionConfigでstreaming=Trueを設定すると逐次トークンを受信できるASSISTANT_MESSAGE_DELTAイベントを処理してトークンが届くたびに出力する- シームレスなストリーミング出力のために
end=""とflush=Trueを使用する send_and_waitは完全なレスポンスを待つ — ストリーミングはトークンをいつ取得するかの問題- 完全なレスポンスは
send_and_waitの戻り値からも取得できる