Tool calls were invisible until the answer arrived: the only trace was the sources list, and only for web searches. Surface them as they happen instead. Add llm.stream_tool_calls(), an incremental version of resolve_tool_calls() that yields a start and a completion event per tool call and ends with a "resolved" event carrying the previous return value. resolve_tool_calls() is kept as a thin wrapper that drops the progress events. api/chat.py relays those events as a new SSE "tool" event, and wraps the search-summary/knowledge-save step in one of the same shape, since it is a noticeable pause of its own. On the front end, ToolActivityList.vue renders one row per tool above the assistant bubble (label, target, spinner while running, short result when done). The store merges events by id and marks anything still running as interrupted when the stream ends early. Display only - not persisted, so the rows disappear when the session is reloaded, same as sources. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6.4 KiB
API リファレンス
ベースURL: http://localhost:8000
Swagger UI: http://localhost:8000/docs
チャット
POST /chat/stream
SSE でストリーミング応答を返す。
リクエストボディ
{
"message": "こんにちは",
"session_id": "uuid(省略時は新規セッション作成)",
"model": "gpt-5.4(省略時は DEFAULT_MODEL)"
}
SSE イベント
| type | value | タイミング |
|---|---|---|
session_id |
セッション UUID | 新規セッション作成直後 |
chunk |
テキスト断片 | LLM トークン生成ごと |
tool |
{id, name, label, detail, status, result} |
ツール実行の開始時 (status: running) と完了時 (status: done)。同じ id で 2 回届くのでフロントはマージして表示する |
sources |
[{title, url}] |
Web 検索した時のみ(出典一覧) |
notes_updated |
— | AI が共有ノートを書き換えた直後 |
done |
— | 正常完了 |
error |
エラーメッセージ | 例外発生時 |
GET /chat/sessions
セッション一覧を updated_at 降順で返す。
レスポンス
[
{
"id": "uuid",
"title": "セッションタイトル",
"model": "gpt-5.4",
"updated_at": "2026-06-01T12:00:00"
}
]
GET /chat/sessions/{session_id}/messages
セッションのメッセージ一覧を created_at 昇順で返す。要約に取り込まれた(アーカイブ済みの)
メッセージも含めて返し、archived_at で区別する。アーカイブ済みのものは LLM に渡す
コンテキストには入らないが、履歴としては残っている。
レスポンス
[
{ "id": 1, "role": "user", "content": "...", "created_at": "...", "archived_at": "2026-08-20T04:00:00+00:00", "tags": [] },
{ "id": 2, "role": "assistant", "content": "...", "created_at": "...", "archived_at": null, "tags": [] }
]
DELETE /chat/sessions/{session_id}
セッションと紐づくメッセージ・メモリをすべて削除。204 No Content を返す。
メモリ
GET /memory/{session_id}
セッションの長期メモリ(要約)一覧を created_at 昇順で返す。
レスポンス
[
{
"id": 1,
"session_id": "uuid",
"summary": "要約テキスト",
"created_at": "2026-06-01T12:00:00"
}
]
DELETE /memory/{memory_id}
特定のメモリエントリを削除。204 No Content を返す。
共有ノート
ユーザーと AI が共同編集するノート。ページのタイトル一覧は毎回システムプロンプトに注入され、
本文は AI が read_note / write_note ツールで読み書きする。
section を設定すると、同じセクション名のページはタブバー上で常に連続してグループ表示される。
GET /api/notes
全ページを position 昇順で返す。同じ section のページは常に連続する(隣接=同一グループとして扱われる)。
レスポンス
[
{
"id": 1,
"title": "買い物リスト",
"content": "- 牛乳
- 卵",
"position": 0,
"section": "生活",
"updated_at": "2026-08-19T12:00:00"
}
]
POST /api/notes
ページを新規作成し、201 Created で作成したページを返す。
section を指定すると、作成直後にそのセクションの末尾へ配置される(他ページの position も再採番される)。
リクエスト
{ "title": "新しいページ", "content": "", "section": null }
PATCH /api/notes/{page_id}
ページのタイトル・本文・セクションを更新する。指定したフィールドだけが変更される。
タイトルを空文字にしようとした場合は 400、ページが存在しない場合は 404 を返す。
section はリクエストボディにキーとして含まれているかどうかで判定する(null を明示的に送るとグループ解除)。
セクションを変更すると、そのページは新しいセクションの末尾(該当ページが無ければ末尾)へ移動し、
全ページの position が振り直される。
リクエスト
{ "content": "更新後の本文", "section": "生活" }
POST /api/notes/sections/rename
old_name セクションに属する全ページを new_name セクションへ一括で付け替える。
new_name を空文字/未指定にすると、そのセクションの全ページのグループを解除する。
ページの並び順(position)は変更しない。
リクエスト
{ "old_name": "生活", "new_name": "生活雑貨" }
レスポンス
{ "renamed": 2 }
POST /api/notes/reorder
タブのドラッグ&ドロップによる並べ替えを反映する。order には全ページIDをドラッグ後の
新しい順序で渡す(サーバー側では計算しない。フロントが store.pages から算出する)。
page_id のページには先に section を設定してから、order の順に position を振り直す。
別セクションのタブの前後にドロップした場合は、そのセクションへの移動も兼ねる。
order が現在の全ページIDの集合と一致しない場合は 400 を返す。
リクエスト
{ "page_id": 3, "section": "生活", "order": [1, 3, 2, 4] }
レスポンス
{ "reordered": 4 }
DELETE /api/notes/{page_id}
ページを削除。204 No Content を返す。
ログ
GET /logs
LLM API 呼び出しログを created_at 降順で返す。
クエリパラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
session_id |
string | セッションで絞り込み |
status |
ok / error |
成功・失敗で絞り込み |
limit |
int (≤500) | 最大件数(デフォルト 100) |
offset |
int | スキップ件数 |
レスポンス
[
{
"id": 1,
"session_id": "uuid",
"model": "gpt-5.4",
"request_json": "[{\"role\":\"user\",\"content\":\"...\"}]",
"response_text": "...",
"error": null,
"latency_ms": 832.5,
"created_at": "2026-06-01T12:00:00"
}
]
DELETE /logs/{log_id}
指定ログを削除。204 No Content を返す。
ヘルスチェック
GET /health
{ "status": "ok" }