life-innovation:給常駐 DSH agent 一份跨會話記憶和真實生活線

前言

DSH 路線是「一切皆插件」,agent 的能力由 profile 裏的插件拼出來。常規做法是每次會話把工具和上下文裝進去,會話一結束,這個 agent 「是誰」就沒了——換個窗口,又是一次陌生開場。如果你想讓一個 agent 常駐在一臺機器上,持續記得和你說過的話,並且能夠區分「今天真的做了什麼」和「沒做什麼」,那麼下面介紹的這個插件值得看一下。

life-innovation(倉庫 Leon-dbh/life-innovation)是社區目錄 SkillHub 上「記憶」分類下的一個 DSH 插件,維護者是 Leon-dbh,GitHub 上目前 1 個 star,包版本 0.2.2(來自 package.json),許可證 MIT。它把記憶、生活線、節律和幾個有限的工具放進同一個包裏,不生成人設,只提供「房間」。

這是什麼

一句話定位:一個裝在 DSH profile 裏的 agent 房間,提供跨會話記憶、白天生活線、夜間歸檔與夢境,以及一個只讀的「家」頁面。

它解決三件事:

  1. 跨會話記憶:原話按五層結構沉澱,裝進每輪系統提示詞;
  2. 有證據的生活線:生活塊只從真實說過的話和真實調用過的工具聚合,沒有證據的時段記成「空檔」,不編造活動;
  3. 空閒時的自治:沒人說話時,agent 按時鐘進入不同狀態,安靜地寫日記、翻記憶、讀一段書、做夢。

一個包裏的四樣東西

README 明確寫,一個包帶來四樣東西:

  • 房間:life-innovation preset,只給事實,不寫人設;
  • 記憶:原話 → 梗概 → 要點 → 畫像 + 關係,跨會話;
  • 日子:只從真實動作聚合出生活線,帶證據、有節律、會歸檔;
  • 她的家:/home 只讀頁面,和會話標題欄裏的「家」入口。

需要說明的是,插件不在代碼裏寫死 agent 名字。名字只有一個來源,插件 config 裏的 agentName。不設 agentName,提示詞裏就寫「你沒有預設的名字;別人叫你什麼,由對方決定」,頁面標題是「家」;設了,提示詞加一句「你叫<名字>。」,頁面標題變成「<名字>的家」。名字不是人設,不帶性格、語氣和關係。倉庫作者自己的實例叫「鯨鯨」,僅此而已。

記憶:五層結構與生命週期

記憶庫是 <home>/state/life-innovation.sqlite(可在 config.dbPath 改),結構是五層:raw_turns 原話 → summaries 梗概 → assertions 要點 → profiles 畫像 + relations 關係。

每輪組裝系統提示詞時,ctx.systemPrompt.context 現算一段「你記得的事」,默認 ≤1200 字。規則抽取是確定性的,覆蓋名字、城市、工作、年齡、生日、養了什麼、好惡、計劃,不爲此調模型;同一件事有了新說法,舊說法會被 superseded_by 取代。明確不做的三件事:不按會話隔離、不導入舊項目的庫、不寫「你是一個」。

記憶包不每輪現算。lib/packCache.js 用一組指紋(日期、live 斷言最大 id/條數、動作最大 id、梗概最大 id、畫像最大更新時間/條數、當天新原話最大 id)決定是否重建;指紋不變時整段複用,系統提示詞前綴穩定,provider 緩存才命中。

生命週期方面有三個設計值得注意:

  1. 雙半衰期:普通記憶 30 天權重掉一半,帶情緒的 7 天掉一半,隻影響排序,不刪原話;
  2. 歸檔:90 天前的原話搬到 raw_archive,id 不變,證據 raw:N 仍然有效;
  3. 回收站:store.recycleRaw(id) 把原話從召回和閱讀裏拿走,payload 留在 recycle 表,放回去用 node tools/restore.mjs --list / --id N。

記憶包放不下時按整行截斷,不切半個詞。

日子與節律

生活線從真實動作聚合,不寫活動池:raw_turns(說過的話)+ actions(調用過的工具)→ life_blocks。塊與塊之間超過 45 分鐘沒有動作,記成「空檔」,證據爲空——不拿「她在看書/發呆/想事情」去填。

tick 每 60 秒看一眼:滿足 8–23 點、安靜 ≥20 分鐘、30 分鐘內沒寫過日記,就把今天寫成 <home>/diary/YYYY-MM-DD.md,並在 actions 裏留一條 write_diary。日記每條都帶證據 id(raw:1–30 / act:7);沒有動作的一天不硬寫。計劃項帶 due_at,過期後 valid_to 記下,不再出現在記憶包裏。

沒人說話時,狀態只有五種,全部由時鐘和真實事件推導:

狀態 什麼時候 她做什麼
醒着 awake 最近 10 分鐘內有人說話 正常聊天
安靜 quiet 8–23 點,安靜 ≥20 分鐘 寫日記、翻舊記憶、讀一段書;每 3 小時最多一次安靜動作
夜裏 night 23–8 點 不主動找人;只歸檔、做夢
今天已收起來 closed 跨天補收之後 當天凍結,不再改寫日記
沒在運行 offline 宿主關機/重啓 只記一段空檔,不補寫任何活動

歸檔在 23:00 後進入夜裏,等這一天過完、安靜滿足條件再收,寫 diary/YYYY-MM-DD.md,落一條 close_day 動作(只成功一次)。夢從近 3 天真實原話和真實動作裏取素材,標 non_factual=1,證據是 raw:N / act:N;夢不進生活塊、不進事實。第二天 agent 可以用 note_write 帶 dream_date 把夢寫成 notes/<date>-dream.md,正文標「夢不是真事」。

狀態注入在 life:rhythm(order 850),名字注入在 life:name(order 810)。

家頁面與回讀工具

固定入口 http://127.0.0.1:60080/home 是隻讀儀表盤:今天做了什麼、記得關於你的事、關係、梗概、夢(夢會標「不是真事」)。當天還沒有夢時,頁面顯示昨天那條並標「昨晚的夢 · 日期」,不會誤報「還沒有夢」。頁面以只讀連接讀同一個 SQLite,不寫庫、不調模型、不替 agent 說話;文本做轉義,90 秒自動刷新。

會話標題欄右側有一個「家」按鈕,由 client.js 註冊到 conversation.session.header.actions,打開的是 DSH 同源地址 /life-innovation/home,改固定入口端口不會讓它失效。

Agent 側有四個只讀回讀工具,全部只查自己的庫,在 apply 裏用 ctx.tools.register 註冊,卸載即釋放:

工具 行爲
memory_find(query, limit≤8) 按詞面 bigram + IDF + 新鮮度 + 情緒權重做確定性排序找原話,每條 ≤200 字,帶 ref、score、why
memory_read(ref) raw:<id> 讀原文(≤2000 字),act:<id> 讀一條真實動作;歸檔裏的老原話也讀得到
life_status() 原話/歸檔/斷言/動作/回收站條數、今天做了什麼、最近一次注入多少字、最近一次召回查了什麼、關係多久沒動
life_days({days:1..7}) 狀態段、真實做過的事(帶證據)、空檔、動作賬本、夢

六隻手:有邊界、有額度

除了說話和回憶,agent 還有六件事可做,全部有邊界、有額度、落動作賬本:

工具 用途 邊界
room_list / room_read 看/讀自己家裏的日記、便籤、書 room_list 可列 diary/、notes/、books/、backups/;room_read 只讀前三處;路徑牢籠拒絕 ..、盤符、符號鏈接逃逸
note_write 寫便籤存進 notes/;可帶 dream_date 記昨晚的夢 每天 3 張、每張 2000 字;同名不覆蓋;一個夢只能記一張
book_next 從 Project Gutenberg 讀一段 固定四本公共領域書;每天 4 段;首次下載後只讀本地
lookup 查 Wikipedia 摘要 每天 3 次;只走 Wikipedia 域名;查不到就報查不到
notify 彈一條 Windows 通知 每天 1 次、120 字;僅交互式桌面會話

安靜下來時,tick 按「讀一段本地書 → 翻昨天的日記 → 翻記憶」的順序做一件真事,記進 actions。README 裏還專門提示:本機網絡到 zh.wikipedia.org 不通時,lookup 會如實返回「沒連上」,不會用模型記憶冒充查詢結果。

主動開口方面,preset 掛 @deepseek-ai/dsh-tool-schedule,agent 可以自己定鬧鐘(schedule_create/list/update/delete);到點由 Host 投遞一條 source.kind='schedule' 的消息喚醒,任務與投遞記錄在 $DSH_HOME/storages/schedule.json,重啓不丟,過期只補最近一次。

外發通知有一層 lib/outbox.js 賬本,pending / sent / uncertain / failed 四態單向狀態機;沒拿到確認一律 uncertain。渠道接入時只調 recordDelivery(),不要再用布爾值判斷「發沒發出去」。

安裝與啓用

前置條件:Windows、Node.js 22+、npm;pnpm 可選(沒有會自動裝);DEEPSEEK_API_KEY 在用戶環境變量裏。

GitHub 上推薦的做法是跑官方安裝腳本:

# 1) 克隆到任意目錄
git clone https://github.com/Leon-dbh/life-innovation.git D:/tools/life-innovation

# 2) 安裝(默認 profile=life-innovation,數據目錄=D:\life-innovation-home)
powershell -ExecutionPolicy Bypass -File D:/tools/life-innovation/install/install.ps1

# 想給 agent 起名,就加 -AgentName(隻影響提示詞與頁面,不寫進插件代碼)
powershell -ExecutionPolicy Bypass -File D:/tools/life-innovation/install/install.ps1 -AgentName '鯨鯨'

# 3) 打開固定入口
start http://127.0.0.1:60080/

也可以讓 DSH 直接從 git 裝:

dsh plugin --profile life-innovation add github:Leon-dbh/life-innovation

或者下載 Release 裏的離線包:https://github.com/Leon-dbh/life-innovation/releases/latest。注意倉庫根目錄就是插件包,沒有子包。

安裝腳本做五件事,冪等:檢查 node/npm/pnpm 與 API key;建 D:\life-innovation-home\{state,diary,logs,backups};在 %DSH_HOME%\profiles\life-innovation 寫 package.json 與 cordis.patch.yml(默認 preset life-innovation);dsh plugin --profile life-innovation add <本插件>;註冊計劃任務 LifeInnovationDailyBackup(每天 03:30,留 14 份)。

常用參數:

-DataHome E:\my-agent-home     # 換數據目錄
-AgentName '名字'              # 給 agent 起名;不填就沒有預設名字
-Profile my-agent              # 換 DSH profile 名
-EntryPort 60080               # 固定入口端口
-DryRun                        # 只看會做什麼
-Force                         # 備份後重寫已有 profile 文件

啓動方式:

$env:DSH_HOME='D:\dsh-home'
dsh --profile life-innovation --port 60081 --no-open

日誌裏那行 dsh web: http://127.0.0.1:60081/?token=… 纔是入口,裸 / 會 401。進去後選 life-innovation-home 工作區,新建會話;第一句可以問「你叫什麼」。

不跑腳本的手動安裝:dsh plugin --profile life-innovation add D:/workspace_1/plugins/life-innovation。

典型用法

數據全部在 home 目錄裏,換機器只搬這一個目錄:

  • state/life-innovation.sqlite:記憶 + 動作 + 生活線 + 外發賬本;
  • diary/YYYY-MM-DD.md:日記;
  • backups/export-*:存檔(自動清理舊份)。

插件 config 用 home: D:/life-innovation-home,換目錄只改這一處,或設環境變量 LIFE_INNOVATION_HOME(舊的 JINGJING_HOME 仍兜底)。升級時如果新庫不存在、同一目錄下舊 state/jingjing.sqlite 存在,會自動讀舊庫,不會丟記憶;要顯式指定,用 config.dbPath 或 LIFE_INNOVATION_DB。

導出與接回:

node tools/export.mjs --db D:/life-innovation-home/state/life-innovation.sqlite --data D:/life-innovation-home --out D:/life-innovation-home/backups/export-manual
node tools/import.mjs --from <導出目錄> --db <新機器>/state/life-innovation.sqlite --data <新機器>

導入默認不覆蓋已有庫(要覆蓋加 --force,會先留 .bak-<時間>);日記按文件名合併;導入後重新點數,數字對不上就報錯,不假裝成功。存檔用 node tools/backup.mjs --db … --data … --keep 14,計劃任務跑的就是它。

合併另一臺機器的記憶時,先停掉正在跑的 web,再合併:

node tools\merge.mjs --target D:\life-innovation-home\state\life-innovation.sqlite `
                    --source D:\backup\export-2026-11-05\life-innovation.sqlite `
                    --data D:\life-innovation-home

合併是隻增不刪:重複原話按「時間 + 誰說的 + 原話」去重,同一 call_id 的動作只留一條;兩邊自增 id 不同,assertions.source 和 life_blocks.evidence 會被重新指到合併後的 id,指不到的證據寧可不搬。合併不搬回收站。

適用場景與注意

適合誰:想在 Windows 機器上跑一個常駐 agent,並且願意讓它有自己的記憶和節律,而不是每輪從零開始的人。記憶層、生活線和歸檔都圍繞「真實發生過的事」,沒有證據的時段寧可留空,這和需要嚴格事實口徑的場景是合拍的。

使用前需要留意幾點:

  1. 插件以當前 dsh 進程權限運行,安裝前應檢查源碼與許可證(MIT),不要在一個來路不明的 profile 裏直接堆載;
  2. 目前是單庫設計,記憶庫和日記都在一個 home 目錄下,跨機器合併前必須先停 web,避免寫入期間的衝突;
  3. 已知限制:從回收站恢復的低 id 原話仍能讀、仍參與召回,但不會再進入新的自動梗概;lookup 在網絡不通時只會如實報錯;
  4. 星標量目前很低(1 star),屬於早期項目,功能邊界以倉庫 README 爲準。

生態背景補充一句:DSH 的理念是「一切皆插件」,SkillHub 是獨立的社區目錄站點,與 DeepSeek / 幻方無官方從屬關係,不要把它當成官方應用商店。

結尾

life-innovation 的價值不在於「讓 agent 有人設」,而在於把跨會話記憶、帶證據的生活線和空閒節律裝進同一個包裏,並且對哪些是真事、哪些沒有證據保持克制。如果你在做一個常駐的桌面 agent,可以先從 dsh plugin --profile life-innovation add github:Leon-dbh/life-innovation 這一步試起。

目錄頁:https://www.skillhub.cn/plugins/Leon-dbh/life-innovation
倉庫:https://github.com/Leon-dbh/life-innovation

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜