# Memoir(記憶帳) [简体中文](README.md) · [English](README.en.md) · [Français](README.fr.md) · [Deutsch](README.de.md) · **日本語** [![CI](https://github.com/Yansera/dsh-living-memoir/actions/workflows/ci.yml/badge.svg)](https://github.com/Yansera/dsh-living-memoir/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/@yansera/dsh-living-memoir?color=0969da&label=npm)](https://www.npmjs.com/package/@yansera/dsh-living-memoir) [![license](https://img.shields.io/badge/license-MIT-8250df)](LICENSE) DeepSeek Harness のセッション横断メモリです。記憶は Markdown ファイルの集まりとして持ち、毎ターンの終わりに丸ごと書き直します。追記はしません。 ![画面と記憶ディレクトリ](docs/assets/hero.en.svg) ## 📦 インストール ```sh dsh plugin --profile desktop add @yansera/dsh-living-memoir ``` `desktop` はご自分のプロファイル名に置き換えてください。`dsh` は DeepSeek Harness に同梱されています。デスクトップ版では `<インストール先>\resources\runtime\cli\bin\dsh.cmd` にあります。 ソースから入れる場合: ```sh dsh plugin --profile desktop add 'file:D:\path\to\dsh-living-memoir' ``` 入れたあとはクライアントを完全に終了してから開き直してください。DSH がプラグインのコードを読むのはインストールした瞬間だけで、ウィンドウを閉じるのは終了ではありません。 ## 🚀 使うとこうなる サイドバーに「記憶帳」が出ます。クリックするとメイン領域いっぱいに広がり、左にカテゴリ、右に項目が並びます。左上の「← 会話に戻る」で会話に戻ります。 あとは設定不要です。長く効く好みを口にしたとき、方針を決めたとき、間違いを指摘したときに、モデルが自分で書きます。「1 件記録」を押すこともできますし、`$DSH_HOME/memoir/` の下の Markdown を直接編集してもかまいません。編集したらページを再読み込みすれば反映されます。 止めたいときは右上の設定で「記憶の書き込み」を切ります。切ると読み込みも書き込みもしません。 ## 🧱 三つの階層 ``` # 進行中のこと ## Memoir - セッション横断の記憶を短い Markdown の生きた文書として保つ ## ネットワーク:意味のトポロジー - トポロジーが意味を担うネットワークを育てる ``` 第一階層はカテゴリで、1 つにつき Markdown ファイル 1 枚です。第二階層は節で、たいていはプロジェクト 1 つにつき 1 つです。第三階層は項目で、一文まで、それより深くはしません。 カテゴリは情報の種類ではなく主題で切ります。何かを探すとき人は「どのプロジェクトの話か」を考えます。「これは決定か進捗か」とは考えません。1 つのプロジェクトのことは、そのプロジェクト自身の節にまとめます。 カテゴリの数も形も、中身からモデルが決めます。決まった一覧はありません。インストール時に 5 つの起点カテゴリを置くので、要らないものは消してください。カテゴリが大きくなりすぎたとき、あるいは関係のない 2 つが同居していると分かったときは、モデルが分割します。 ## ✍️ 書き込む三つの道 モデルのツール:残す価値があるとモデルが判断して `memoir_note` を呼びます。`memoir_recall` と `memoir_forget` で読み出しと削除をします。 ページから:「1 件記録」を押すか、Markdown を直接編集します。 自動書き換え:ターンが静まって 20 秒後、帳面全体を読み直し、書き換えた版を書き込みます。 前の二つは追記です。三つめは書き換えで、ここが要です。文書が増える一方にならないようにしています。 ## 🔄 自動書き換え モデルには「記憶帳の現在の中身すべて」と「今回の会話の切れ端」を渡し、返してもらうのは書き換えた完全版です。統合も削除も言い換えも追加も、すべてこの 1 段で起きます。 いくつかの歯止め: - セッションごとのカーソルで前回以降の出来事だけを消費するので、同じ切れ端を二度書き換えることはありません - 失敗した回はカーソルを進めません。次のターン終わりに同じ切れ端を再試行します - 400 文字に満たない切れ端は飛ばしますが、カーソルは進めます - 同時に終わるセッションは順番待ちをし、いっせいに走りません - カテゴリを解釈できないときは何も書きません。項目の総数が半分以上減ったとき(もともと 6 件以上ある場合)は、その書き換えを丸ごと拒否します 各項目には二つの印が付きます。`conf` は確かさで、ご自身が言ったことは `high`、会話から抽出したものは `med`、モデルが推し量ったものは `low` です。場所を空けるときは `low` から捨てます。`pin` は留め金で、付いた項目は書き換えてもそのまま残さなければなりません。1 冊に多くても数件です。 ## ⚙️ 設定 右上の歯車です。変更は記憶ディレクトリ内の `.settings.json` に入り、データと同じ場所にあるのでプロファイルを変えても残ります。 書き込みの主スイッチを切ると、記憶はプロンプトに挿し込まれなくなり、3 つのツールは実行を拒み、ページからも HTTP からも書き込みは 403 を返し、自動書き換えは止まります。 書き換えに使うモデルは、ホストが登録済みのものから選びます。プラグインは `ctx.llm.listProviders()` と `ctx.llm.listModels(provider)` を呼び、その結果をドロップダウンにします。プロバイダ名もモデル ID も打ち込む必要はありません。DSH に繋がっていれば、内蔵でもローカルでも外部 API でも、そこに出ます。ホストが列挙しないもののために、一覧の下に入力欄も残しています。 思考は既定でオフです。書き換えは整理であって問題解決ではなく、考えるモデルは出力の予算を推論に使い切って本文を一切返しません。 表示言語と記憶の言語は別々のスイッチです。前者はボタンとラベルを変え、後者はファイルに書き込む言語を決めます。カテゴリ名と節の名前も含みます。どちらも既定は英語です。 ## 🔧 設定ファイル 配備レベルの設定は `cordis.patch.yml` に置きます: ```yaml - id: memoir name: '@yansera/dsh-living-memoir' config: memoryDir: '' # 空 = $DSH_HOME/memoir injectIndex: true # 記憶の目次をシステムプロンプトに挿し込む maxInjectEntries: 12 # 挿し込む項目数の上限 autoDistill: true # 毎ターンの終わりに書き換える distillDebounceMs: 20000 # 書き換え前の静けさ(ミリ秒) distillMinChars: 400 # これより短い切れ端は飛ばす distillMaxItems: 60 # 帳面全体の項目数の上限 distillMaxTokens: 8000 # 出力予算の下限。規模に応じて自動で上がります distillReasoningEffort: off # 書き換えに推論は要らない memoryLanguage: '' # 記憶の言語。空 = 制限なし pageEntryLimit: 12 # この数を超えたカテゴリは強制整理 bookEntryLimit: 40 # この数を超えた帳面は強制整理 ``` 変更後は再起動が必要です。コードの変更と同じ扱いです。 ## 📂 ファイルの中身 カテゴリごとに Markdown ファイル 1 枚です。ただのテキストで、どのエディタでも開け、版管理にも入れられます。データベースもキャッシュも独自形式もありません。 項目のメタデータは HTML コメントに入るので、読むときの邪魔になりません: ``` - ダウンロードの前には必ず尋ね、容量を GB で示すこと ``` `- ` で始まる行を足せば項目が 1 つ増えます。読み取り側が認めるのは 3 種類の行(`# カテゴリ`、`## 節`、`- 項目`)だけで、ほかはすべて無視します。 ## ❓ よくある質問 **ほかの記憶の仕組みと衝突しませんか。** しません。記憶帳が扱うのは長期・大局の一層だけです。利用者が誰か、助手が誰か、何が進行中か、どんな大きな方針を決めたか。短期・手続き的な中身、たとえば技術的な細部や落とし穴、進捗の記録は対象外で、ここには書きません。データは専用のディレクトリにあります。 **増え続けませんか。** 増えません。追記ではなく書き換えるので、長さは履歴ではなく中身に従います。カテゴリで 12 件、帳面で 40 件を超えると強制整理が走ります。 **記憶が間違って書き換えられたら。** カテゴリのファイルはどれも直接編集でき、ページを再読み込みすれば反映されます。次の書き換えは、変えたカテゴリ名を尊重します。大事な項目には `pin` を付けられます。 **どこかにデータを送りますか。** 送りません。プラグインは自分から一切ネットワークに出ません。書き換えはホスト自身の `llm` 能力を通します。 **記憶を持ち出せますか。** 持ち出せます。記憶の置き場は 1 つのディレクトリなので、まるごとコピーしてください。 ## 🛠 開発 ```sh npm test # オフラインの自己テスト 259 件すべて npm run test:store # 保存層:解析、重複排除、移動、検索 npm run test:plugin # ホスト側:登録、ツール、プロンプト、HTTP 経路 npm run test:client # ページ側:React の代役に対して実バンドルを描画 npm run test:distill # 書き換え:解析、デバウンス、カーソル、再試行 ``` テストはすべてオフラインです。DSH のホストを必要とせず、実際のプロファイルにも触りません。 ソースを変えたあと(Windows): ```powershell & .\scripts\sync.ps1 ``` pnpm が `file:` でローカルのパッケージを入れるときはハードリンクになります。ソースを編集するとリンクが切れ、インストール先の複製が更新されなくなるので、同期と再起動の両方が要ります。 構成: ``` src/ 実装本体(index = ホスト側、distill = 書き換え、client = ページ側) test/ オフラインの自己テスト docs/ 設計と形式の覚え書き scripts/ 同期スクリプト、起動中のクライアントに対するスモークテスト ``` 詳しくは [CONTRIBUTING.md](CONTRIBUTING.md) と [docs/](docs/) をどうぞ:[設計](docs/design.md)、[保存形式](docs/storage-format.md)、[設定](docs/configuration.md)。 ## 📄 ライセンス [MIT](LICENSE) © Yansera