life-innovation: Cross-session memory and real-life thread for resident DSH agents

Introduction

The DSH route is “everything is a plugin,” and an agent’s capabilities are pieced together by plugins in the profile. The conventional approach is to load tools and context into every session, but once the session ends, the question of “who this agent is” disappears—switching windows means a fresh, unfamiliar start. If you want an agent to reside on a machine permanently, remember what was said continuously, and distinguish between “what was actually done” and “what wasn’t,” then the plugin introduced below is worth a look.

life-innovation (repository Leon-dbh/life-innovation) is a DSH plugin under the “Memory” category on the community directory SkillHub. The maintainer is Leon-dbh, currently with 1 star on GitHub, package version 0.2.2 (from package.json), and license MIT. It puts memory, life timeline, rhythm, and a few limited tools into a single package without generating a persona, only providing a “room.”

What is it?

One-sentence positioning: An agent room installed in a DSH profile, providing cross-session memory, daily life timeline, nightly archiving and dreaming, and a read-only “home” page.

It solves three things:

  1. Cross-session memory: Original text precipitates into a five-layer structure and is loaded into every round of system prompts;
  2. Evidence-based life timeline: Life blocks are only aggregated from truly spoken words and truly called tools; periods without evidence are recorded as “gaps” without fabricating activities;
  3. Autonomous idle time: When no one is speaking, the agent enters different states based on the clock, quietly writing diaries, flipping through memories, reading a book, or dreaming.

Four Things in One Package

The README explicitly states that one package brings four things:

  • Room: life-innovation preset, facts only, no persona;
  • Memory: Original text → Summary → Key points → Portrait + Relations, cross-session;
  • Days: Life line aggregated only from real actions, with evidence, rhythm, and archiving;
  • Her home: /home read-only page, and the “Home” entry in the session header bar.

It is worth noting that the plugin does not hardcode the agent name in the code. The name has only one source: agentName in the plugin config. If agentName is not set, the prompt says “You have no preset name; whatever others call you is up to them,” and the page title is “Home”; if set, the prompt adds “You are called ,” and the page title becomes “’s Home”. The name is not a persona and does not carry personality, tone, or relationships. The repository author’s own instance is named “JingJing” (鲸鲸), nothing more.

Memory: Five-Layer Structure and Lifecycle

The memory database is <home>/state/life-innovation.sqlite (configurable via config.dbPath), with a five-layer structure: raw_turns original text → summaries summaries → assertions key points → profiles portraits + relations relationships.

During every round of assembling the system prompt, ctx.systemPrompt.context currently calculates a “what you remember” segment, defaulting to ≤1200 characters. Rule extraction is deterministic, covering names, cities, work, age, birthdays, pets, likes/dislikes, plans, without calling the model for this; if there is a new description of the same thing, the old description is replaced by superseded_by. Three things explicitly not done: no session isolation, no importing old project libraries, no writing “You are a [persona]”.

The memory pack is not calculated every round. lib/packCache.js uses a set of fingerprints (date, max id of live assertions/actions/summaries, max update time/count of profiles, max id of new raw turns today) to decide whether to rebuild; when fingerprints remain unchanged, the entire segment is reused, the system prompt prefix is stable, and the provider cache hits.

Regarding lifecycle, three designs are worth noting:

  1. Dual Half-life: Normal memory weight drops by half in 30 days, emotional memory drops by half in 7 days; this only affects sorting and does not delete original text;
  2. Archive: Original text older than 90 days is moved to raw_archive, ID remains, evidence raw:N remains valid;
  3. Trash: store.recycleRaw(id) removes original text from recall and reading; the payload stays in the recycle table, restore it with node tools/restore.mjs --list / --id N.

When the memory pack is full, it truncates by whole lines, not splitting words in half.

Days and Rhythm

The life line is aggregated from real actions, without writing an activity pool: raw_turns (spoken words) + actions (called tools) → life_blocks. If there is no action between blocks for more than 45 minutes, it is recorded as a “gap” with empty evidence—do not fill it with “she is reading/staring/thinking.”

The tick checks every 60 seconds: if it satisfies 8–23 o’clock, quiet ≥20 minutes, and no diary has been written in the last 30 minutes, it writes today into <home>/diary/YYYY-MM-DD.md and leaves a write_diary entry in actions. Every diary entry carries an evidence id (raw:1–30 / act:7); days without actions are not forcibly written. Plan items carry due_at, and valid_to records after expiration, no longer appearing in the memory pack.

When no one is speaking, there are only five states, all derived from the clock and real events:

State When What she does
Awake awake Someone spoke in the last 10 minutes Normal chat
Quiet quiet 8–23, quiet ≥20 minutes Write diary, flip memories, read book; max 1 quiet action per 3 hours
Night night 23–8 Don’t seek others; archive/dream only
Closed closed After cross-day catch-up Freeze that day, don’t rewrite diary
Offline offline Host shutdown/restart Only record a gap, don’t fill in any activities

Archiving enters the “Night” state after 23:00, waiting for the day to finish and quiet conditions to be met before closing, writing diary/YYYY-MM-DD.md and leaving a close_day action (successful only once). Dreams take materials from the last 3 days of real original text and real actions, marked non_factual=1, evidence is raw:N / act:N; dreams do not enter life blocks or facts. The next day, the agent can use note_write with dream_date to write the dream to notes/<date>-dream.md, marking the body as “Dreams are not real things.”

State injection is life:rhythm (order 850), name injection is life:name (order 810).

Home Page and Read-Back Tools

The fixed entry http://127.0.0.1:60080/home is a read-only dashboard: what was done today, things remembered about you, relations, summaries, dreams (dreams marked “not real”). When there are no dreams for the day, the page shows yesterday’s and marks it “Last night’s dream · Date,” avoiding false reports like “No dream yet.” The page reads from the same SQLite via a read-only connection, does not write to the database, does not call the model, and does not speak for the agent; text is escaped, auto-refreshes every 90 seconds.

On the right side of the session header is a “Home” button, registered by client.js to conversation.session.header.actions. It opens the DSH same-origin address /life-innovation/home, which remains valid even if the fixed entry port changes.

On the agent side, there are four read-back tools, all querying only their own database, registered in apply using ctx.tools.register, and released on unloading:

Tool Behavior
memory_find(query, limit≤8) Find original text deterministically sorted by word bigram + IDF + freshness + emotion weight; max 8 results, ≤200 chars, returns ref, score, why
memory_read(ref) raw:<id> reads original text (≤2000 chars), act:<id> reads a real action; archived old original text is also readable
life_status() Counts of original text/archive/assertions/actions/trash, what was done today, last injection count, last recall query, relationship last updated
life_days({days:1..7}) Time segments, real activities (with evidence), gaps, action ledger, dreams

Six Hands: Bounded and Quota-Based

Besides speaking and recalling, the agent has six other things it can do, all with boundaries, quotas, and logged in the action ledger:

Tool Purpose Boundaries
room_list / room_read View/read diary, notes, books at home room_list lists diary/, notes/, books/, backups/; room_read is read-only for the first three; path cage rejects .., drive letters, symlink escape
note_write Write notes to notes/; can take dream_date to record last night’s dream Max 3 per day, 2000 chars each; no overwriting same name; one dream per note
book_next Read a segment from Project Gutenberg Fixed 4 public domain books; 4 segments per day; read-only locally after first download
lookup Check Wikipedia summary Max 3 times per day; only traverses Wikipedia domain; returns “not found” if cannot check
notify Pop a Windows notification Max 1 per day, 120 chars; only for interactive desktop sessions

When quiet, tick performs one real action in the order “read a local book -> flip yesterday’s diary -> flip memories,” recording it in actions. The README also specifically warns: if the local network is unreachable to zh.wikipedia.org, lookup will truthfully return “not connected” rather than using model memory to impersonate query results.

Regarding active speaking, the preset hooks @deepseek-ai/dsh-tool-schedule, allowing the agent to set its own alarms (schedule_create/list/update/delete). When the time comes, the Host delivers a message with source.kind='schedule' to wake the agent. Tasks and delivery records are kept in $DSH_HOME/storages/schedule.json, surviving restarts; only the most recent expired one is replenished.

There is an lib/outbox.js ledger for outgoing notifications, a four-state unidirectional state machine: pending / sent / uncertain / failed. If confirmation is not received, it is always uncertain. When integrating a channel, only call recordDelivery(), do not use boolean values to judge “sent or not.”

Installation and Activation

Prerequisites: Windows, Node.js 22+, npm; pnpm is optional (will be auto-installed if missing); DEEPSEEK_API_KEY must be in the user environment variables.

The recommended practice on GitHub is to run the official installation script:

# 1) Clone to any directory
git clone https://github.com/Leon-dbh/life-innovation.git D:/tools/life-innovation

# 2) Install (default profile=life-innovation, data dir=D:\life-innovation-home)
powershell -ExecutionPolicy Bypass -File D:/tools/life-innovation/install/install.ps1

# To name the agent, add -AgentName (only affects prompt and page, not plugin code)
powershell -ExecutionPolicy Bypass -File D:/tools/life-innovation/install/install.ps1 -AgentName '鲸鲸'

# 3) Open the fixed entry
start http://127.0.0.1:60080/

Alternatively, let DSH install directly from git:

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

Or download the offline package from the Release: https://github.com/Leon-dbh/life-innovation/releases/latest. Note that the repository root directory is the plugin package, no sub-packages.

The installation script does five things idempotently: checks node/npm/pnpm and API key; creates D:\life-innovation-home\{state,diary,logs,backups}; writes package.json and cordis.patch.yml in %DSH_HOME%\profiles\life-innovation (default preset life-innovation); dsh plugin --profile life-innovation add <this plugin>; registers scheduled task LifeInnovationDailyBackup (at 03:30 daily, keeping 14 copies).

Common parameters:

-DataHome E:\my-agent-home     # Change data directory
-AgentName '名字'              # Name the agent; if blank, no preset name
-Profile my-agent              # Change DSH profile name
-EntryPort 60080               # Fixed entry port
-DryRun                        # Only show what will happen
-Force                         # Rewrite existing profile files after backup

Startup method:

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

The line dsh web: http://127.0.0.1:60081/?token=… in the log is the actual entry; accessing / directly returns 401. After entering, select the life-innovation-home workspace and create a new session; the first sentence can be “What is your name?”

Manual installation without running the script: dsh plugin --profile life-innovation add D:/workspace_1/plugins/life-innovation.

Typical Usage

All data is in the home directory; moving to another machine only requires moving this directory:

  • state/life-innovation.sqlite: memory + actions + life line + outbound ledger;
  • diary/YYYY-MM-DD.md: diary entries;
  • backups/export-*: archives (auto-cleaning old copies).

Use home: D:/life-innovation-home in the plugin config; changing the directory only requires changing this one place, or setting the environment variable LIFE_INNOVATION_HOME (the old JINGJING_HOME is still a fallback). If a new library does not exist during an upgrade but the old state/jingjing.sqlite exists in the same directory, it will automatically read the old library without losing memory; to explicitly specify, use config.dbPath or LIFE_INNOVATION_DB.

Export and import:

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 <export directory> --db <new machine>/state/life-innovation.sqlite --data <new machine>

Importing defaults to not overwriting existing libraries (add --force to overwrite, which first leaves a .bak-<timestamp>); diary files are merged by filename; after import, a recount is performed, and an error is reported if the numbers do not match, rather than pretending success. Archives use node tools/backup.mjs --db … --data … --keep 14, which is what the scheduled task runs.

When merging memory from another machine, stop the running web first, then merge:

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

Merging is append-only: duplicate original text is deduplicated by “time + who said it + original text,” and only one action per call_id is kept; since the self-incrementing IDs differ on both sides, assertions.source and life_blocks.evidence will be re-pointed to the merged IDs; evidence that cannot be pointed to is not moved. Trash is not moved during merge.

Applicable Scenarios and Notes

Who is it for: Someone who wants to run a resident agent on a Windows machine and is willing to give it its own memory and rhythm, rather than starting from zero every round. The memory layer, life line, and archiving all revolve around “things that actually happened,” leaving gaps without evidence, which aligns with scenarios requiring strict factual standards.

Points to note before use:

  1. The plugin runs with the current DSH process permissions; check the source code and license (MIT) before installing and do not directly stack load it in an unknown profile;
  2. Currently a single-database design; memory and diary are in the same home directory; the web must be stopped before merging across machines to avoid write conflicts during the process;
  3. Known limitations: original text with low IDs recovered from the trash can still be read and participate in recall, but will not enter new automatic summaries; lookup will only truthfully report an error if the network is unreachable;
  4. Star count is currently low (1 star), it is an early project, and the functional boundaries follow the repository README.

Ecosystem background note: DSH’s philosophy is “everything is a plugin,” SkillHub is an independent community directory site with no official affiliation to DeepSeek/Xuanfuan, do not treat it as an official app store.

Conclusion

The value of life-innovation lies not in “giving the agent a persona,” but in packaging cross-session memory, evidence-based life lines, and idle rhythms into a single package, while maintaining restraint on what is factual and what lacks evidence. If you are building a resident desktop agent, you can start with the step dsh plugin --profile life-innovation add github:Leon-dbh/life-innovation.

Directory page: https://www.skillhub.cn/plugins/Leon-dbh/life-innovation
Repository: https://github.com/Leon-dbh/life-innovation

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

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

Xiaoye