dsh-memory-dba 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/README.md +207 -147
- package/README.zh-CN.md +62 -0
- package/package.json +4 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.3 — 2026-10-26
|
|
4
|
+
|
|
5
|
+
Documentation-only revision. No runtime source file, API, or behavior changed.
|
|
6
|
+
|
|
7
|
+
- Corrected the release history: `0.1.0` was the first functional release; `0.1.1`
|
|
8
|
+
only added `repository`/`homepage`/`bugs` metadata.
|
|
9
|
+
- README release section renamed to "Release notes" so it no longer hardcodes the
|
|
10
|
+
version it documents.
|
|
11
|
+
|
|
12
|
+
## 0.1.2 — 2026-10-26
|
|
13
|
+
|
|
14
|
+
Documentation-only revision. No runtime source file, API, or behavior changed.
|
|
15
|
+
|
|
16
|
+
- Added a Chinese scope summary in `README.zh-CN.md`.
|
|
17
|
+
- README now separates three delivery classes explicitly: implemented in this npm
|
|
18
|
+
package, present in the original Python DBA but not migrated here, and still
|
|
19
|
+
unaccepted research in the overall DBA project.
|
|
20
|
+
- Added the capability comparison tables and a legacy note: the older five-layer
|
|
21
|
+
consolidation/retire/dedupe path is legacy in the current DBA, not a current
|
|
22
|
+
capability missing from this package.
|
|
23
|
+
- Added a "Limits and operating notes" section covering: process-wide single-slot
|
|
24
|
+
retrieval (`latestHits`) with no concurrent-session/subagent isolation; the
|
|
25
|
+
recent-1,000-entries / 128 KiB stream recall window (the byte cap is enforced in
|
|
26
|
+
source but was not independently end-to-end tested); 300/600-character
|
|
27
|
+
truncation of stream text instead of model summarization; manual `index` for the
|
|
28
|
+
semantic cache; core overflow clipping instead of compression; log-only write
|
|
29
|
+
failures without retry; and the default memory directory differing from the old
|
|
30
|
+
Python DBA, which requires an explicit `home` to reuse an existing library.
|
|
31
|
+
- Corrected the research status: state-decoder training on frozen RWKV features was performed (v4, 5,000 steps)
|
|
32
|
+
but did not meet acceptance (dev all-slot exact 0/1779, no-state loss better than
|
|
33
|
+
true-state, Not qualified, no final test). It is not described as untrained.
|
|
34
|
+
|
|
35
|
+
## 0.1.1 — 2026-10-26
|
|
36
|
+
|
|
37
|
+
- Package metadata only: added `repository`, `homepage`, and `bugs` so the npm
|
|
38
|
+
page links back to the GitHub source. No source file, API, or behavior changed.
|
|
39
|
+
|
|
40
|
+
## 0.1.0 — 2026-10-26
|
|
41
|
+
|
|
42
|
+
- First functional release: three-layer store, two-section prompt injection, BM25
|
|
43
|
+
with CJK bigrams, optional Ollama/bge-m3 semantic recall, DSH session-event
|
|
44
|
+
integration, CLI, and 40 tests.
|
|
45
|
+
|
|
46
|
+
## 0.0.0-stage — 2026-10-26
|
|
47
|
+
|
|
48
|
+
- Temporary placeholder build; deprecated in favour of later versions.
|
package/README.md
CHANGED
|
@@ -1,147 +1,207 @@
|
|
|
1
|
-
# dsh-memory-dba
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
dsh-memory-dba
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
The
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
1
|
+
# dsh-memory-dba
|
|
2
|
+
|
|
3
|
+
[中文功能范围说明](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
File-based long-term memory for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), stored as plain files you can read, diff, and commit.
|
|
6
|
+
|
|
7
|
+
Session logs answer "what happened in this conversation". This plugin answers "what did we decide three weeks ago" — across sessions, across machines, and across models.
|
|
8
|
+
|
|
9
|
+
This package is the **file-memory and retrieval plugin** of the wider DBA (Dual-Brain Architecture) project. It is not the complete DBA runtime. The original Python DBA's local RWKV-7 state backend, full two-sided event archive, and durable turn-processing pipeline are not part of this npm package. The scope sections below are the authoritative statement of what you get and what you do not, as of 0.1.2.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
core.md injected in full every turn, byte-capped
|
|
13
|
+
stream.md one line per finished turn, retrieved only
|
|
14
|
+
ws/<area>.md detail notes, retrieved only
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Everything lives in one directory. Copy it, put it in git, point two harness installs at the same folder, or read it with `cat`. There is no database or required embedding service.
|
|
18
|
+
|
|
19
|
+
## Scope: implemented, not migrated, and not yet accepted
|
|
20
|
+
|
|
21
|
+
### 1. Implemented in this npm package
|
|
22
|
+
|
|
23
|
+
| Capability | What this package actually does |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Three-layer file memory | `core.md`, `stream.md`, `ws/<area>.md` under one directory, plain UTF-8, no database. `init` creates the layout; existing files are never overwritten. |
|
|
26
|
+
| Two-section prompt injection | `core` (default order `-50`) and retrieval `hits` (default order `200`) are separate sections. The core layer is re-read on every assembly; the hits section is last so it cannot invalidate the cached prefix above it. |
|
|
27
|
+
| BM25 retrieval | BM25 (`k1=1.5`, `b=0.75`) over all three layers. Latin runs stay whole words, CJK runs emit unigrams and bigrams. Recency reranking only reorders candidates that relevance already found, and only when they overflow the byte budget. |
|
|
28
|
+
| Optional Ollama / bge-m3 semantic recall | Cosine hits above `minScore` from a `<home>/.vec/embeddings.json` cache are appended after keyword hits without reordering the keyword results. Synchronous 1,500 ms budget (`Atomics.wait` on a worker), 60 s cooldown after a failure, silent degradation to BM25. The cache is built by the CLI, not automatically. |
|
|
29
|
+
| DSH session-event integration | Listens on `session/event`: a user-authored `user/message` triggers recall; `assistant/message` text is accumulated for the turn; `turn/end` appends the stream line; `session/disposed` drops the in-memory pending turn. |
|
|
30
|
+
| Current stream writing | One line per finished turn: `- YYYY-MM-DD HH:mm | 用户:… | 助手:…`. Whitespace is collapsed, the user side is cut to **300 characters**, the assistant side to **600 characters**, credential-shaped strings are redacted, a line identical to the previous one is skipped, and a turn missing either side is not written. |
|
|
31
|
+
|
|
32
|
+
### 2. Exists in the original Python DBA, not migrated into this package
|
|
33
|
+
|
|
34
|
+
| Capability | Original Python DBA | In this package |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| RWKV-7 continuous session state and summary backend | `scripts/nb_rwkv.py`, `scripts/nb_rwkv_bridge.py`; `scripts/nb_turn.py` uses the local RWKV backend by default for session recursion, summaries, and branch isolation. | No RWKV backend, no state interface, no summary generation. |
|
|
37
|
+
| Full two-sided event archive and event-vector recall | Sanitized complete user/assistant events stored under `.turns/events`, with their own event-level vectors and recall path. | Only a mechanically truncated single stream line per turn; no event archive and no event vectors. |
|
|
38
|
+
| Persistent outbox, idempotent receipts, retries | Durable outbox with idempotent event receipts and retry handling. | Only an in-memory `pending` map; a process exit loses the in-progress turn, and a failed write is logged without retry. |
|
|
39
|
+
| Message drafts and interrupted-turn recovery | Draft and resume path for interrupted turns. | None. |
|
|
40
|
+
| Controlled `core` / `ws` writes | Dedicated `remember_core` / `remember_ws` write paths with their own checks. | CLI `write` appends to `stream.md` only; `core.md` and `ws/*.md` are edited with ordinary file tools. |
|
|
41
|
+
| Index-maintenance loop | Chained maintenance for the keyword index, notebook vectors, and event vectors. | BM25 invalidates its corpus cache on file metadata changes; the semantic cache is rebuilt only by a manual `index` run. |
|
|
42
|
+
|
|
43
|
+
These are real capabilities of the original Python system, not hypothetical future work. Installing this npm package does **not** install them. The plugin does not claim parity with the Python DBA. They may coexist, but concurrent writes to the same memory directory are not coordinated; use one writer per shared directory.
|
|
44
|
+
|
|
45
|
+
### 3. Research not yet accepted for use in the overall DBA project
|
|
46
|
+
|
|
47
|
+
| Research item | Actual state |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Decoding RWKV state into reliable slots or memory codes | State-decoder training experiments were performed on frozen RWKV features, but they did not reach the acceptance standard. The v4 decoder run completed 5,000 steps; on dev, all-slot exact matches were 0/1779, and the final no-state loss was better than the true-state loss. It was judged **Not qualified** and never entered the final test. There is no usable state-to-slot decoder today. |
|
|
50
|
+
| Cross-model consumption of state | Cloud models consume text summaries and retrieved text, not RWKV state tensors or dedicated memory codes. The interface is not built. |
|
|
51
|
+
| A genuinely resident service | RWKV runs through a local runner/bridge. Continuity across turns is not the same as an accepted always-on service; no resident deployment has been accepted. |
|
|
52
|
+
|
|
53
|
+
These items are neither implemented in this package nor accepted upstream. They are research gaps of the whole DBA project, not capabilities that exist somewhere and were merely left out of the npm package.
|
|
54
|
+
|
|
55
|
+
### Legacy note
|
|
56
|
+
|
|
57
|
+
The old five-layer architecture's periodic consolidation / retire / dedupe path (`memory_maintenance.py` in the Python tree) is **legacy** in the current DBA and is skipped. It is not a current DBA feature, it was not migrated into this package, and its absence is not a regression or a missing "current" capability.
|
|
58
|
+
|
|
59
|
+
## Limits and operating notes
|
|
60
|
+
|
|
61
|
+
Read these before relying on the plugin as shared or historical memory.
|
|
62
|
+
|
|
63
|
+
- **The retrieval output is a process-wide single slot.** `latestHits` is one variable for the whole plugin instance. The harness passes only a scope key to a prompt section callback, not a session id, so the hits section always renders the most recent user query in the process. Concurrent sessions or same-process subagents are **not isolated**: a later query overwrites the earlier one. An independent audit reproduced this at callback level in a temporary memory directory with the vector path disabled (session A rendered session B's hits). This was not a full host end-to-end concurrency test. The workaround is one agent per process; there is no per-session isolation in 0.1.2.
|
|
64
|
+
- **Stream retrieval only covers a recent window.** The index takes at most the most recent **1,000 non-empty stream entries**, within at most **128 KiB** of entry text (an entry larger than 128 KiB is skipped; the scan stops when the byte cap would be exceeded). Older entries remain in `stream.md` but are not in the retrieval candidate set. The 1,000-entry cutoff was exercised in the audit; the 128 KiB cap is enforced in `src/search.mjs` and was **not** independently exercised end-to-end. Move durable facts into `ws/*.md`, which is not capped.
|
|
65
|
+
- **The stream is truncated text, not a summary.** The line is a whitespace-collapsed prefix of the original messages (300 characters for the user side, 600 for the assistant side). It is not produced by a local model and does not extract facts; the tail of either message can be lost. This plugin does not keep its own complete event archive; the original Python pipeline provides one separately.
|
|
66
|
+
- **Semantic recall needs manual indexing.** The vector cache is not updated by the plugin while it runs. Run `dsh-memory-dba index` after editing memory; documents that are new or changed are still searchable by BM25 but not by semantics until then.
|
|
67
|
+
- **An over-budget core is clipped, not compressed.** When `core.md` exceeds `coreLimitKB`, the injected section is cut and marked `[...clipped to fit the memory budget]`. The file itself is not rewritten, summarized, or reorganized.
|
|
68
|
+
- **Failed writes are not retried.** A read-only or full disk still serves readable memory, but a failed turn append is logged (`[memory-dba] session event failed: …`) and the turn is lost; there is no outbox or retry queue in this package.
|
|
69
|
+
- **The default memory directory is not the old Python DBA directory.** On Windows it is `%LOCALAPPDATA%\dsh-memory-dba`; elsewhere `~/.dsh-memory-dba`, unless `home` or `DSH_MEMORY_HOME` says otherwise. To reuse an existing Python DBA memory library, set `home` explicitly (for example `D:/AI/DBA/memory`).
|
|
70
|
+
|
|
71
|
+
## Release notes
|
|
72
|
+
|
|
73
|
+
`0.1.2` and `0.1.3` are documentation-only revisions. No runtime source file or behavior changed in either release; the changes are the scope tables, the limits above, and the corrected release history, so that the npm page matches what is actually delivered. See `CHANGELOG.md` for the full history.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
Install it into the profile directory the harness runs from (`~/.dsh/profiles/<name>/`), so the loader can resolve the package name:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# from the npm registry
|
|
81
|
+
npm install dsh-memory-dba --prefix ~/.dsh/profiles/web
|
|
82
|
+
|
|
83
|
+
# or straight from GitHub
|
|
84
|
+
npm install github:TNong611/dsh-memory-dba --prefix ~/.dsh/profiles/web
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Then append one entry to the `insert:` list in that profile's `cordis.patch.yml`:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
- insert:
|
|
91
|
+
# ... existing entries
|
|
92
|
+
- id: memory-dba
|
|
93
|
+
name: dsh-memory-dba
|
|
94
|
+
config:
|
|
95
|
+
home: '~/.dsh-memory-dba'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Omit `config` entirely to use the defaults. Restart the harness process after adding the entry; a profile reload is not enough because the prompt sections are registered at startup.
|
|
99
|
+
|
|
100
|
+
The plugin hooks two prompt sections and the session event stream. Nothing else is required.
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
|
|
104
|
+
| Field | Default | Meaning |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `home` | platform default | Memory directory. `DSH_MEMORY_HOME` overrides the default when `home` is unset. |
|
|
107
|
+
| `coreLimitKB` | `15` | Byte cap for the core section. Text past the cap is clipped and marked. |
|
|
108
|
+
| `hitBudgetKB` | `6` | Byte cap for the retrieval section. |
|
|
109
|
+
| `topK` | `5` | Maximum retrieved notes per turn. |
|
|
110
|
+
| `timeDecay` | `true` | When the candidate set overflows the budget, rerank with a recency weight. |
|
|
111
|
+
| `halfLifeDays` | `30` | Recency weight halves every N days, floor 0.5. |
|
|
112
|
+
| `writeStream` | `true` | Append one line per finished turn to `stream.md`. |
|
|
113
|
+
| `tag` | `''` | Optional label written into stream lines. |
|
|
114
|
+
| `exclude` | `[]` | Workspace file names to keep out of retrieval, e.g. role-play notes. |
|
|
115
|
+
| `coreOrder` | `-50` | Prompt section order for the core layer. |
|
|
116
|
+
| `hitsOrder` | `200` | Prompt section order for retrieval hits. |
|
|
117
|
+
| `vector.enabled` | `true` | Try optional semantic recall when a cache exists. |
|
|
118
|
+
| `vector.url` | `http://127.0.0.1:11434` | Ollama embedding server. |
|
|
119
|
+
| `vector.model` | `bge-m3` | Model used for indexing and queries. |
|
|
120
|
+
| `vector.timeoutMs` | `1500` | Total synchronous worker-join budget in milliseconds; also caps the embedding request. |
|
|
121
|
+
| `vector.minScore` | `0.45` | Cosine floor for an appended semantic hit. |
|
|
122
|
+
| `vector.keepAlive` | `30m` | Passed to Ollama so the model stays resident between turns. |
|
|
123
|
+
|
|
124
|
+
Partial `vector` objects inherit unspecified defaults. Set `vector: { enabled: false }` to disable semantic recall entirely.
|
|
125
|
+
|
|
126
|
+
## Why two prompt sections
|
|
127
|
+
|
|
128
|
+
The core layer changes every few days; retrieval hits change every turn. Injecting them as one section would invalidate the cached prompt prefix whenever a hit appears, which costs far more than the memory is worth. The core section sits near the front, the hit section last.
|
|
129
|
+
|
|
130
|
+
Core text is reread on each assembly so edits take effect without restarting a session. See the single-slot limitation above for why the hits section is process-wide rather than per-session.
|
|
131
|
+
|
|
132
|
+
## Retrieval
|
|
133
|
+
|
|
134
|
+
BM25 over all three layers, tokenized for mixed Chinese/English text: Latin runs stay whole words (so identifiers such as `1234567890` remain searchable), CJK runs emit unigrams and bigrams (a trigram index cannot match a two-character Chinese query).
|
|
135
|
+
|
|
136
|
+
Ranking is two-step:
|
|
137
|
+
|
|
138
|
+
1. relevance only — same query, same candidates;
|
|
139
|
+
2. if the candidate set exceeds the byte budget, rerank by relevance × recency.
|
|
140
|
+
|
|
141
|
+
Recency never introduces a candidate that relevance did not find.
|
|
142
|
+
|
|
143
|
+
Core and stream entries split per non-empty line. Workspace headings and blank lines delimit note blocks; reported line numbers refer to the original files. Workspace additions, edits, removals, and renames invalidate the cached corpus using file names, sizes, and modification times.
|
|
144
|
+
|
|
145
|
+
For predictable stream retrieval latency, only the most recent **1,000 non-empty stream entries**, within **128 KiB of entry text**, are indexed. Individual entries larger than 128 KiB are skipped. Earlier entries remain on disk but are outside the candidate set; move lasting details into `ws/*.md` to keep them searchable. Core and workspace documents are not capped. A 5 MiB mixed Chinese/English stream is covered by a cold-load-plus-search benchmark test targeting 300 ms; actual timing depends on hardware. Reading and UTF-8 validation still scan the whole stream, so this is not a constant-time guarantee for arbitrarily large files.
|
|
146
|
+
|
|
147
|
+
If the first query finds no shared term, recall retries once with CJK unigrams plus Latin words. Existing shared-term hits are never relaxed. The result reports `relaxed: true` only when the retry supplies hits; there are at most two ranking attempts.
|
|
148
|
+
|
|
149
|
+
## Semantic recall (optional)
|
|
150
|
+
|
|
151
|
+
BM25 always works on a bare Node install. To add semantic recall, install an Ollama embedding model separately, then build the derived cache:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
ollama pull bge-m3
|
|
155
|
+
dsh-memory-dba index --home ./memory --url http://127.0.0.1:11434 --model bge-m3
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Indexing uses four concurrent requests. Duplicate document texts share one entry (reported as skipped). Rebuild after editing memory; unchanged text still matches, while uncached or changed documents remain searchable by BM25. Indexing refuses with exit code 2 if the embedder is unavailable, without replacing the previous cache. Indexing requests have a separate 30-second timeout so model startup does not consume the recall budget.
|
|
159
|
+
|
|
160
|
+
The portable `<home>/.vec/embeddings.json` cache stores version, model, dimension, and SHA-1 document-text keys, never document paths. Each vector is quantized to signed int8 with its own `max(abs(vector)) / 127` scale and base64 bytes. `bge-m3` normally uses 1024 dimensions; the cache records the actual model dimension.
|
|
161
|
+
|
|
162
|
+
On each user message, a lazily reused, unreferenced worker embeds the query using `/api/embed` (falling back once to `/api/embeddings` on HTTP 404), then compares it with cached vectors by cosine similarity. Only document keys are sent, not corpus text. A fresh shared buffer returns at most eight matching corpus indices and scores. The main thread joins synchronously using `Atomics.wait`, with a **1500 ms total budget**, including worker startup and message posting. Prompt section callbacks remain synchronous; no background result mutates a later turn's hits.
|
|
163
|
+
|
|
164
|
+
Keyword ranking is never rewritten by semantics. Hits above `minScore` that keywords missed are **appended** after the keyword hits, marked `(semantic)`, and cut to a 600-byte excerpt; the prompt budget keeps at most 70% for keyword hits so a long workspace section cannot crowd them out entirely. Fusion of the two rankings was tried and rejected: with no score floor, a semantic table of contents outranked an exact keyword match.
|
|
165
|
+
|
|
166
|
+
A cold `bge-m3` takes about two seconds to load, longer than the join budget, so the plugin fires one background warmup request when it mounts and asks Ollama to keep the model resident for `keepAlive`. After a failed or timed-out lookup the endpoint is skipped for 60 seconds, which keeps a down or cold embedder from costing the budget on every turn.
|
|
167
|
+
|
|
168
|
+
Missing caches, unavailable models (including Ollama HTTP 404), network errors, model/dimension mismatches, corrupt caches, and timeouts silently degrade to BM25 during recall. No model is installed automatically. `doctor` reports vector entry counts and corpus coverage; a missing cache is optional even without an embedder, while a corrupt cache fails the vector check. `stats` includes cache bytes when present.
|
|
169
|
+
|
|
170
|
+
## CLI
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
dsh-memory-dba init # create the directory and layer files
|
|
174
|
+
dsh-memory-dba recall "clock drift" # what retrieval would return
|
|
175
|
+
dsh-memory-dba index # build optional semantic cache
|
|
176
|
+
dsh-memory-dba write --user "..." --assistant "..."
|
|
177
|
+
dsh-memory-dba stats # bytes per layer
|
|
178
|
+
dsh-memory-dba doctor # layout, budget, corpus, retrieval checks
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Useful while tuning `coreLimitKB` and inspecting why a note did or did not surface. The CLI is an operator tool; the plugin does not need it at runtime.
|
|
182
|
+
|
|
183
|
+
## Writing memory
|
|
184
|
+
|
|
185
|
+
The plugin appends one line per finished turn:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
- 2026-10-26 22:48 | 用户:… | 助手:…
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Credential-shaped strings (`sk-…`, bearer tokens, long hex runs, long digit runs) are redacted before the line is written, because these files are meant to be committed.
|
|
192
|
+
|
|
193
|
+
Ordinary separated dates and timestamps (including ISO timestamps) and CJK text are preserved. Unbroken 13–19 digit runs are intentionally redacted, even when they represent epoch milliseconds or compact timestamps. Tags use the same redaction and single-line rules as turn text. This is heuristic redaction, not a guarantee that every secret is removed.
|
|
194
|
+
|
|
195
|
+
The stream is a timeline, not a transcript. Detail belongs in `ws/<area>.md`, which the model can write with ordinary file tools and retrieval can reach later. There is no controlled `core`/`ws` write command in this package (see scope item 2).
|
|
196
|
+
|
|
197
|
+
## Degradation
|
|
198
|
+
|
|
199
|
+
Memory is an enhancement. A missing directory, an unreadable layer, or a corrupt file yields an empty section and never fails a turn. `doctor` reports what is wrong.
|
|
200
|
+
|
|
201
|
+
Layers are decoded as strict UTF-8: an invalid byte sequence skips that entire layer rather than injecting replacement characters. Healthy layers remain searchable; `doctor` uses strict diagnostics and exits non-zero on unreadable or corrupt layers. A read-only home can still serve readable memory, but failed turn writes are logged and not retried. CLI parse errors, missing commands, and queries with no searchable terms exit non-zero without stack traces.
|
|
202
|
+
|
|
203
|
+
Cache invalidation is metadata-based, not content-hashed: deliberately preserving both size and modification time can hide an edit. Concurrent writers are not locked; use one writer per memory directory if strict write ordering is required. Permission-error tests simulate filesystem errors for consistent Windows/Linux coverage; the suite does not depend on platform-specific ACL changes.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# dsh-memory-dba:功能范围
|
|
2
|
+
|
|
3
|
+
[English README](README.md) · 版本 0.1.3
|
|
4
|
+
|
|
5
|
+
本包是 DBA(Dual-Brain Architecture,双脑架构)的**文件记忆与检索插件**,不是完整双脑运行时。安装它不会同时安装 RWKV 小脑、连续状态后端或原 Python DBA 的可靠事件处理链。
|
|
6
|
+
|
|
7
|
+
0.1.2 / 0.1.3 是说明文档修订版:明确交付范围和限制、修正发布历史,没有新增运行时功能,也没有修复下列尚未实现的能力。
|
|
8
|
+
|
|
9
|
+
## 本 npm 包已实现
|
|
10
|
+
|
|
11
|
+
| 能力 | 实际行为 |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| 三层文件记忆 | core.md、stream.md、ws/*.md;可直接阅读和迁移 |
|
|
14
|
+
| 两段提示词注入 | 核心记忆与本轮召回分开;默认预算分别为 15 KiB 和 6 KiB |
|
|
15
|
+
| BM25 关键词检索 | 支持中英文混合、中文单字和双字;预算溢出时可按时间重排 |
|
|
16
|
+
| 可选语义召回 | 使用 Ollama/bge-m3 与手动建立的向量缓存;超过阈值的语义结果追加到关键词结果之后 |
|
|
17
|
+
| DSH 会话接入 | 监听用户/助手消息,在轮次结束时追加记忆流 |
|
|
18
|
+
| 当前记忆流写法 | 用户文本最多 300 字符、助手文本最多 600 字符,折成一行并做启发式脱敏;不是小模型提炼出的摘要 |
|
|
19
|
+
|
|
20
|
+
## 原 Python DBA 已有,但本包尚未迁入
|
|
21
|
+
|
|
22
|
+
| 能力 | 本包现状 |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| RWKV-7 会话连续状态、恢复与摘要后端 | 未接入 |
|
|
25
|
+
| 完整双方事件档案、独立事件向量召回 | 未接入;截断流水不能代替完整事件档案 |
|
|
26
|
+
| 持久 outbox、幂等收据与失败重试 | 未接入;当前 pending 只在内存中 |
|
|
27
|
+
| 消息草稿与中断轮次恢复 | 未接入 |
|
|
28
|
+
| core/ws 受控写入接口 | 未迁入;CLI write 只写 stream,core/ws 依赖普通文件操作 |
|
|
29
|
+
| 原系统的关键词、记事本向量与事件向量维护链 | 未完整迁入;本包语义缓存须手动执行 index |
|
|
30
|
+
|
|
31
|
+
这些能力在原 Python 系统中有实现,不能把它们写成“原 DBA 从未实现”,也不能把安装本包说成已获得这些能力。两个系统可并存,但共享同一记忆目录时没有并发写入协调,应只保留一个写入者。
|
|
32
|
+
|
|
33
|
+
## 整体 DBA 仍在研究、未达验收标准
|
|
34
|
+
|
|
35
|
+
- **RWKV 状态可靠解码为槽位或记忆码**:做过基于冻结 RWKV 特征的解码器训练实验。v4 完成 5000 步,但验证集全槽精确命中为 0/1779,未通过验收,也未进入最终测试;这不等于 RWKV 主干微调已成功或已有可用状态接口。
|
|
36
|
+
- **跨模型状态消费**:云端目前消费文本摘要与检索原文,不是直接接收 RWKV 状态张量或专用记忆码。
|
|
37
|
+
- **经验证的模型常驻服务**:跨轮状态连续与进程/权重始终常驻是两回事,原系统也没有完成常驻部署验收。
|
|
38
|
+
|
|
39
|
+
旧五层架构的定期 consolidation/retire/dedupe 已列为 legacy,不属于当前三层架构已交付能力。
|
|
40
|
+
|
|
41
|
+
## 当前限制
|
|
42
|
+
|
|
43
|
+
1. **同进程并发会话不隔离**:latestHits 是共享槽,后一次查询会覆盖前一次的召回。隔离的回调级测试已复现;这不是完整 DSH 多会话端到端测试。本版未修复,可用独立进程隔离查询。
|
|
44
|
+
2. **旧流水可能搜不到**:仅最近 1000 条、合计最多 128 KiB 的非空流水记录进入检索;更旧的内容仍在文件里,却不在候选集中。1000 条窗口有隔离测试依据;128 KiB 上限来自源码,未单独进行端到端边界测试。长期细节应放入 ws。
|
|
45
|
+
3. **截断不等于理解或压缩**:用户/助手文本尾部可能丢失;核心记忆超预算时裁切注入内容,不会自动整理或压缩磁盘文件。
|
|
46
|
+
4. **语义缓存不会自动更新**:编辑记忆后需执行 index。未建立缓存、模型不可用或超时,会降级为 BM25;运行时不会主动提示所有降级原因,可用 doctor 检查缓存。
|
|
47
|
+
5. **写失败无可靠重试**:只记录错误日志,没有持久队列保证重试。脱敏是启发式规则,也不能保证移除所有秘密。
|
|
48
|
+
6. **默认目录与旧 DBA 不同**:Windows 默认 `%LOCALAPPDATA%/dsh-memory-dba`,其他平台默认 `~/.dsh-memory-dba`。要复用原库,须明确设置 home;仅安装插件不会自动找到旧 Python 仓库。
|
|
49
|
+
|
|
50
|
+
## 安装与配置
|
|
51
|
+
|
|
52
|
+
安装到实际运行的 DSH profile 目录,再在其 cordis.patch.yml 中添加:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
- insert:
|
|
56
|
+
- id: memory-dba
|
|
57
|
+
name: dsh-memory-dba
|
|
58
|
+
config:
|
|
59
|
+
home: '/absolute/path/to/existing/memory'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
完整安装步骤、配置字段、向量索引与 CLI 用法见 [English README](README.md)。新增插件后需重启宿主。本轮发布不会替换用户已运行的插件或移动既有记忆。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-memory-dba",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "File-based, git-portable long-term memory for DeepSeek Harness: core/stream/workspace layers, BM25 retrieval with CJK bigrams, two-section prompt injection",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
"src",
|
|
27
27
|
"bin",
|
|
28
28
|
"README.md",
|
|
29
|
-
"
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"README.zh-CN.md"
|
|
30
32
|
],
|
|
31
33
|
"engines": {
|
|
32
34
|
"node": ">=22"
|