Files
playchat/docs/api.md
T
colcaroliandClaude Opus 5 f085db421c Browse the knowledge base from a single side panel menu
Add a read-only view of backend/knowledge_base/**.md so the files that get
injected into the system prompt can be inspected from the GUI:

- GET /api/kb/files lists the Markdown files (title, preview, size, mtime and
  whether the file is already embedded), GET /api/kb/file returns one in full.
  Paths are resolved against the knowledge base directory and rejected unless
  they stay inside it and end in .md.
- KnowledgeBasePanel.vue groups the files by folder (collapsible, so web_search
  can be folded away), filters by title/path/preview and renders the selected
  file with MarkdownContent.

The header had grown to four side panel toggles, so collapse them into one
menu: panels.ts now holds the list of panels along with the component each one
renders, App.vue picks it with <component :is>, and SidePanelMenu.vue shows the
active panel on its button. Re-picking the open panel (or "パネルを閉じる")
closes it; a click outside or Esc closes just the menu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 21:38:54 +09:00

11 KiB
Raw Blame History

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)",
  "note_page_ids": [1, 2]
}

note_page_ids は「このセッションで本文をシステムプロンプトに載せる共有ノートのページ ID」。 渡すとコンテキスト組み立ての前にサーバー側の指定を丸ごと置き換える(PUT /chat/sessions/{id}/notes と同じ内容)。 新規セッションではフロントがまだ session_id を持てないため、初回はここでしか指定できない。省略すると現在の指定を変更しない。

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": [] }
]

GET /chat/sessions/{session_id}/notes

このセッションで本文をシステムプロンプトに載せるよう指定された共有ノートのページ ID を返す。 順序はノートのタブ順(position)。セッションが無ければ 404。

レスポンス

{ "page_ids": [1, 2] }

PUT /chat/sessions/{session_id}/notes

指定を丸ごと置き換える。存在しないページ ID は黙って捨てられ、実際に紐付いた ID が返る。 空配列を渡すと全解除。セッションが無ければ 404。

リクエスト

{ "page_ids": [1, 2] }

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 を返す。


POST /api/notes/import

multipart/form-data の files でアップロードされたファイルをページとして取り込み、 201 Created で作成したページの配列を返す。

拡張子 取り込み方
.md / .markdown / .txt / .text 1 ファイル 1 ページ。タイトルはファイル名から拡張子と 01_ 形式の通し番号を落としたもの
.zip 中のテキストファイルを 1 つずつページにする。第 1 階層のフォルダ名がセクションになる(GET /api/notes/export の ZIP をそのまま戻せる)
  • 既存ページとタイトルが衝突したら タイトル (2) のように連番を足して別ページとして作る(上書きはしない)
  • 文字コードは UTF-8 (BOM 可) → CP932 の順に試す
  • 対象外の拡張子・NOTES_IMPORT_MAX_BYTES(既定 2,000,000)超のファイル・NOTES_IMPORT_MAX_PAGES(既定 100)を超えた分・壊れた ZIP は黙って飛ばす
  • 1 ページも取り込めなかった場合のみ 400

GET /api/notes/export

全ページを ZIP でダウンロードさせる(Content-Disposition: attachment)。 1 ページ 1 ファイルの Markdown で、本文はそのまま。エントリ名は <セクション>/<通し番号>_<タイトル>.md (セクション無しのページは ZIP 直下)。通し番号は position 順なのでタブの並びが残る。 ファイル名は notes_YYYYMMDD.zip。


GET /api/notes/{page_id}/export

1 ページを Markdown ファイルとしてダウンロードさせる。本文はそのままで、ファイル名がタイトルになる。 ページが存在しない場合は 404。

日本語タイトルを扱うため Content-Disposition には RFC 5987 形式を併記する:

attachment; filename="______.md"; filename*=UTF-8''%E8%B2%B7%E3%81%84%E7%89%A9%E3%83%AA%E3%82%B9%E3%83%88.md

ファイル名に使えない文字(\ / : * ? " < > | と制御文字)は _ に置き換え、80 文字で切る。


ローカルナレッジベース(閲覧)

backend/knowledge_base/**.md を GUI から読むための読み取り専用 API。編集・削除はできない。

GET /api/kb/files

ナレッジベース配下の Markdown を、パス順の一覧で返す(本文は含めない)。

[
  {
    "path": "web_search/02b627ac75bb2fd4.md",
    "name": "02b627ac75bb2fd4.md",
    "directory": "web_search",
    "title": "SOUL.md use-soul-with-hermes",
    "preview": "SOUL.mdは、Hermes Agent インスタンスの主要な…",
    "size": 6150,
    "updated_at": "2026-06-21T05:03:52.684324Z",
    "indexed": true
  }
]

directory はナレッジベース直下なら空文字。indexed は local_knowledge_docs に埋め込み済み (=話題に応じた自動注入の対象になっている)かどうか。未埋め込みのファイルは次回のチャット時に sync_local_kb() が取り込む。


GET /api/kb/file

1 ファイルの全文を返す。

クエリパラメーター

名前 必須 説明
path ✓ ナレッジベースディレクトリからの相対パス(web_search/xxxx.md など)

ナレッジベースの外を指すパス(../ や絶対パス)、.md 以外、存在しないファイルはすべて 404。

{
  "path": "fgo.md",
  "name": "fgo.md",
  "title": "Fate / Grand Order",
  "content": "# Fate / Grand Order

…",
  "size": 13942,
  "updated_at": "2026-06-20T09:39:45.542875Z"
}

ログ

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" }