Pin notes to a chat, and import notes from files

Two additions to the shared notes, both about getting content in and out of
the prompt.

Per-chat pinning. Notes normally reach the model as a title list only, and
the body arrives just if the model decides to call read_note. A 📌 on the tab
now puts a page's full body in the system prompt for the chat that is open,
every turn, no tool round trip. The selection is per session (new table
session_note_pages, unique on session_id + page_id), so different
conversations carry different pages. The title list marks pinned pages so the
model does not read them twice, and bodies are capped per page by
SESSION_NOTES_CONTENT_LIMIT.

A new chat has no session row until its first message, so the front end
cannot PUT the selection yet. POST /chat/stream therefore accepts
note_page_ids and applies it before building the context, which makes the
pins count from the very first turn.

File import. Dropping .md/.txt on the editor - or picking them with the new
⬆ button - creates pages, and a .zip is unpacked into one page per text
entry with the first path component as the section. That is exactly the
shape the export writes, so a downloaded zip round-trips back in. Titles that
collide get a " (2)" suffix rather than overwriting, since restoring a backup
into a live workspace should not destroy anything. UploadFile needs
python-multipart, added to the lockfile.

Toasts grew a kind: the import success message was rendering in the red error
toast, as was the existing session-import message. Both are green now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 16:04:41 +09:00
co-authored by Claude Opus 5
parent 216d38c7bd
commit 0e58a07af4
18 changed files with 629 additions and 33 deletions
+9
View File
@@ -71,10 +71,13 @@ Discord 連携は [discord-bot.md](discord-bot.md)、ノートの操作方法は
|---|---|---|
| 1 蓄積知識 | 過去の Web 検索結果の**見出し一覧のみ**(本文は `read_knowledge` で読む) | 最新 `KNOWLEDGE_CONTEXT_LIMIT`(既定 15)件 |
| 2 共有ノート | ページのタイトル一覧+本文先頭 40 文字 | 全ページ(本文は入れない) |
| 2.5 参照指定ノート | このチャットに紐付けたページの**本文全文** | 紐付いたページのみ・1 ページ `SESSION_NOTES_CONTENT_LIMIT`(既定 8000)文字 |
| 3 ローカル KB | 選ばれた Markdown の**全文** | 類似度上位 `LOCAL_KB_TOP_K`(既定 3)件かつ `LOCAL_KB_MIN_SCORE`(既定 0.75)以上 |
| 4 長期メモリ | 要約を全件連結 | 上限なし |
| 5 短期メモリ | セッション内の全メッセージ | 上限なし(要約で間接的に制御) |
層 2.5 だけは例外で、ユーザーが 📌 で選んだページの本文をツールを介さず直接載せる。
重い情報(ノート本文・蓄積知識の本文・Web 検索)は目次だけを渡し、本体はツール(`read_note` / `write_note` / `read_knowledge` / `web_search`)で
取りに行かせる遅延読み込み方式。`llm.resolve_tool_calls()` が本番生成の前に最大 2 ラウンドでこれを解決する。
@@ -109,6 +112,12 @@ Discord 連携は [discord-bot.md](discord-bot.md)、ノートの操作方法は
- AI 側はタイトル一覧だけを常に見ており、`read_note` で本文を読み、`write_note` で追記/全置換/新規作成する。
AI が書き換えると SSE の `notes_updated` が飛び、開いているノートパネルが自動で最新化される。
- 自分が編集中(未保存)のページは AI の更新で上書きされない。
- **取り込み**: `.md` / `.txt` / `.zip` を本文エリアにドロップするか ⬆ ボタンで選ぶとページになる。
ZIP はフォルダ名がセクションになるので、⬇ で出した ZIP をそのまま戻せば構成ごと復元される。
タイトルが衝突したら `(2)` を足して別ページにするので、既存のページは壊れない。
- **チャットへの紐付け**: タブの 📌 を押すと、そのページの本文が**今開いているチャット**のシステム
プロンプトに毎回そのまま載る。AI が `read_note` を呼ぶのを待たずに確実に参照させたいときに使う。
指定はチャット単位で保存されるので、会話ごとに違う組み合わせを選べる。
- **ダウンロード**: パネル下部の ⬇ ボタンで、開いているページを `.md` として、または全ページを
ZIP(1 ページ 1 Markdown、セクションはフォルダ、ファイル名の通し番号でタブ順を保持)として
手元に保存できる。未保存の編集は書き出す前に保存される。