Event のストリーミング
Session のログを SSE で追尾し、接続が切れたら止まったところから再開する。
永続的な event ログの要点は、それを見ているかどうかが任意だということです。Run は誰かがつながっているかどうかに関わらず進み続け、再接続すればログが見逃したことをすべて教えてくれます。
ログを読む
2 つのエンドポイントが同じ event を読みます。ページングするほうはすでに起きた session に追いつくためのもので、ストリームはいま起きているものを見るためのものです。
GET /v1/sessions/{session_id}/events
GET /v1/sessions/{session_id}/events/stream
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
どちらのエンドポイントも session token を取ります — 作成した session が返した id と session_token で、ここでは SESSION_ID と SUBAKO_SESSION_TOKEN に入っています。API key でも動きますが、ブラウザに渡すべきなのは session ひとつを読めるトークンのほうです。
ストリームはどこから始まるか
カーソルなしで接続すると、ログの 現在の先頭 から追尾します。これから起きることは見えますが、すでに起きたことは見えません。これはこれから自分で動かす session には望ましい挙動ですが、すでに進行中の session には向きません — そこでは run の冒頭の event を取り逃し、run がすでに終わっていれば何も受け取れません。
after_seq は開始点を指定し、そのシーケンス番号より厳密に大きい event を送ります。after_seq=0 はログ全体を再生してからライブに続くので、ひとつの接続で追いつきと追尾を同時に行えます。
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream?after_seq=0" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
SSE のフレームはそれぞれ 3 つのフィールドを持ちます。
| フィールド | 内容 |
|---|---|
id |
その event のシーケンス番号 — 再接続の再開点 |
event |
Event の種類。例: message_assistant |
data |
ページングするエンドポイントがその event について返すのと同じ本体 |
切断からの再開
実際に処理し終えた最後のシーケンス番号を Last-Event-ID に設定して再接続します。ストリームはその直後から再生し、そのままライブに続きます。
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN" \
-H "Last-Event-ID: 42"
ブラウザでは、EventSource が最後に見た id を使って再接続時にそのヘッダーを送ってくれます。これを正しく保つルールが 2 つあります。
event を処理し終えてからカーソルを進める
このヘッダーは、届いたものではなく処理し終えたものについての約束です。 カーソルはハンドラーの最後で動かしてください。
event は再生されうるものとして扱う
カーソルが遅れていれば、再接続によってすでに見た event が渡されることがあります。UI の状態は、無条件に追加するのではなくシーケンス番号を手がかりにしてください。
Run の終わりを知る
Run は次の 3 つの event のちょうどひとつで終わります。
run_completed the turn finished with nothing left to do
run_failed it stopped on an error; `error` carries the text
run_cancelled a cancel request was honored
Run が終わってもストリームは閉じません — session はまだそこにあり、さらに入力を追記すれば次の run が始まります。特定の run を待っているなら、接続が閉じるのを待つのではなく、終端 event に載る run_id を見てください。
POST /v1/sessions/{session_id}/cancel
キャンセルは、いまの run に停止を求めるものです。強制終了ではなく要求なので、すでにログにコミットされたものはそこに残り、要求が届いたところで run は run_cancelled で終わります。