dsh-engram 0.2.0
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/LICENSE +21 -0
- package/README.md +331 -0
- package/README.zh.md +276 -0
- package/cordis.patch.yml +10 -0
- package/lib/api.js +418 -0
- package/lib/capture.js +208 -0
- package/lib/client.js +1438 -0
- package/lib/index-block.js +179 -0
- package/lib/index.js +322 -0
- package/lib/settings.js +95 -0
- package/lib/store.js +565 -0
- package/lib/tools.js +471 -0
- package/lib/usage.js +96 -0
- package/lib/util.js +119 -0
- package/package.json +92 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-loom contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# dsh-engram
|
|
2
|
+
|
|
3
|
+
> **[English](README.md) · [中文](README.zh.md)**
|
|
4
|
+
|
|
5
|
+
Minimalist long-term memory for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), distilled from the
|
|
6
|
+
[symbolic-index](https://github.com/skepsun/symbolic-index) and [pi-esr](https://github.com/skepsun/pi-esr) ideas —
|
|
7
|
+
with one goal: **save tokens**.
|
|
8
|
+
|
|
9
|
+
- **Zero-LLM intake** — auto-captures meaningful events from tool results by pure
|
|
10
|
+
pattern matching (git milestones with a written `-m` commit message, edits to
|
|
11
|
+
key files, repeated errors), plus an explicit `engram_store`. Nothing on the hot
|
|
12
|
+
path calls a model, and pure plumbing — `git push` / `git stash` / silent
|
|
13
|
+
commits — is deliberately never recorded (see *Auto-capture policy* below).
|
|
14
|
+
- **Symbolic index + progressive disclosure** — a compact `[ENGRAM]` block (default
|
|
15
|
+
budget 700 chars ≈ 175 tokens; one line per memory) is injected at prompt
|
|
16
|
+
assembly and **frozen per session**, keeping the request prefix byte-stable for
|
|
17
|
+
KV-cache reuse. The agent drills down with `engram_recall` / `engram_detail` instead
|
|
18
|
+
of dumping raw hits into context.
|
|
19
|
+
- **ESR-lite closure protocol** — `esr_task` / `esr_close` / `esr_link` give tasks
|
|
20
|
+
a `draft → active → stable` lifecycle where `stable` requires real evidence
|
|
21
|
+
(`artifact` / `evaluation` / `memory_ref`), surfacing closure gaps instead of
|
|
22
|
+
letting the agent declare victory without proof.
|
|
23
|
+
- **Memory GC (pi-esr constraints)** — a scheduled, mechanical, archive-only
|
|
24
|
+
sweep: TTL-expired memories are archived, over-cap workspaces evict the
|
|
25
|
+
lowest-value entries, stable tasks past their retention window leave the
|
|
26
|
+
`[ESR]` surface, and dangling link edges are dropped. The working set (active
|
|
27
|
+
task refs, task memories, indexed hits) is never touched, and nothing is
|
|
28
|
+
hard-deleted — every archived entry keeps its id and stays re-fetchable.
|
|
29
|
+
- **Web viewer** — a memory browser with benchmark-ish stats and a config card,
|
|
30
|
+
built entirely on DSH's native settings slots (no third-party UI package).
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
MIT · node >= 22.19 · host-half + browser-half in one package
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Why another memory plugin?
|
|
37
|
+
|
|
38
|
+
Surveys of the existing DSH plugin ecosystem show the recall-bridge, approval-gate,
|
|
39
|
+
LLM-distillation and vector/graph niches are already crowded. dsh-engram fills the
|
|
40
|
+
three gaps that matter for token discipline:
|
|
41
|
+
|
|
42
|
+
1. **No model in the write path** — capture is deterministic pattern matching.
|
|
43
|
+
2. **No raw text in the prompt** — a bounded symbolic index is injected, retrieval
|
|
44
|
+
stays on demand ("retrieved ≠ injected").
|
|
45
|
+
3. **Honest task closure** — STABLE cannot be declared without evidence.
|
|
46
|
+
|
|
47
|
+
DSH already provides cross-session FTS (`ctx.sessionQuery`), storage
|
|
48
|
+
(`ctx.storageDomain`), prompt-injection hooks and settings slots; dsh-engram is a
|
|
49
|
+
thin composition layer over them, not a re-implementation.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
# from GitHub (this repo)
|
|
55
|
+
dsh plugin --profile web add github:skepsun/dsh-engram
|
|
56
|
+
|
|
57
|
+
# once published to npm
|
|
58
|
+
dsh plugin --profile web add dsh-engram
|
|
59
|
+
|
|
60
|
+
# local development (symlink — edits apply immediately)
|
|
61
|
+
dsh plugin --profile web add link:/path/to/dsh-engram
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then **restart `dsh web`**. Data persists in `~/.dsh/storages/dsh_engram.json`.
|
|
65
|
+
|
|
66
|
+
> The npm and GitHub installs below need **no manual dependency step**: pnpm
|
|
67
|
+
> installs `zod` and vendors the optional `@deepseek-ai/*` peers into the
|
|
68
|
+
> plugin's own `node_modules`, and the CLI auto-registers the plugin into the
|
|
69
|
+
> profile's `dsh.profile.bundles`. The `setup-links` step below is only for
|
|
70
|
+
> the `link:` development workflow, where pnpm deliberately does not install a
|
|
71
|
+
> symlinked directory's dependencies.
|
|
72
|
+
|
|
73
|
+
> A fresh session is required to see the injected `[ENGRAM]`/`[ESR]` blocks and the
|
|
74
|
+
> tools; both prompts and the tools registry are assembled per session.
|
|
75
|
+
|
|
76
|
+
### Dependencies for `link:` installs
|
|
77
|
+
|
|
78
|
+
A *symlinked* plugin resolves its imports from its own `node_modules`, so the
|
|
79
|
+
host-side dependencies must be present **next to the checkout** — they are not
|
|
80
|
+
tracked by git:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
cd /path/to/dsh-engram
|
|
84
|
+
node scripts/setup-links.mjs # one command: links the @deepseek-ai
|
|
85
|
+
# workspace packages into node_modules AND
|
|
86
|
+
# installs zod (reused from the harness
|
|
87
|
+
# pnpm store, or via `npm install`)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The script auto-locates the harness checkout at `../deepseek-harness` (also
|
|
91
|
+
works when it sits next to the repo's *parent*, e.g. `E:\deepseek-harness` +
|
|
92
|
+
`E:\kototoro_demo\dsh-engram`); override with `DSH_HARNESS_DIR`. Without this
|
|
93
|
+
step, `dsh web` boot fails with `ERR_MODULE_NOT_FOUND: Cannot find package
|
|
94
|
+
'zod'` (and would fail on the `@deepseek-ai/*` peers next). `node
|
|
95
|
+
scripts/setup-links.mjs --check` prints the state without writing anything.
|
|
96
|
+
|
|
97
|
+
## What you get in the GUI
|
|
98
|
+
|
|
99
|
+
After restart, inside the **native** DSH settings surface:
|
|
100
|
+
|
|
101
|
+
- **Settings → Engram Memory** — a standalone first-class settings section
|
|
102
|
+
(right after the Plugins section, not a child tab of it). Default
|
|
103
|
+
"All workspaces" view shows every workspace's memories/tasks/links
|
|
104
|
+
grouped by workspace (dropdown + prev/next workspace pager; the memory
|
|
105
|
+
table additionally pages 10 rows per page with a jump dropdown, fixed
|
|
106
|
+
column widths, 3-line clamped content ellipsis and full text on hover).
|
|
107
|
+
Overview
|
|
108
|
+
stat cards (counts by workspace/kind, auto-capture totals, per-workspace
|
|
109
|
+
`[ENGRAM]` index token estimate, cumulative GC totals), a searchable /
|
|
110
|
+
filterable memory table with archive + delete actions, an ESR task board
|
|
111
|
+
with an inline "new task" form and a per-task "fill evidence to close"
|
|
112
|
+
(artifact / evaluation / memory_ref → STABLE, same gates as esr_close),
|
|
113
|
+
a node + relation list (nodes are domain objects the model registers via
|
|
114
|
+
esr_node — package/service/repo/concept; relations via esr_link), and a
|
|
115
|
+
memory-GC panel (dry-run toggle + run button + pointer report). The GUI
|
|
116
|
+
create/close use the host's new `POST /api/dsh-engram/tasks` and
|
|
117
|
+
`POST /api/dsh-engram/tasks/close` routes. Model-side proactivity is driven
|
|
118
|
+
by the [ENGRAM]/[ESR] injected blocks: multi-step work gets a task now,
|
|
119
|
+
recurring domain objects get a node, related tasks/nodes get a link.
|
|
120
|
+
|
|
121
|
+
**Real behaviour telemetry (agent observability)** — the ESR page opens
|
|
122
|
+
with an "agent behaviour" panel fed by a new `usage` table (per workspace
|
|
123
|
+
× day rollup) + `GET /api/dsh-engram/stats`: every `engram_*`/`esr_*` tool call
|
|
124
|
+
is recorded (counts, failures, recall mechanics). Reported ratios:
|
|
125
|
+
**ESR proactivity** = esr calls / (memory + esr calls); **recall hit rate**
|
|
126
|
+
= recalls returning ≥1 hit / total recalls; **mean hits per query**;
|
|
127
|
+
**detail conversion** = a engram_detail following a hit recall within 8
|
|
128
|
+
session events. Per-tool counts + a 14-day daily rollup are shown too.
|
|
129
|
+
Numbers are real, from real sessions — lift ESR proactivity by watching
|
|
130
|
+
this panel and tuning the injected prompt.
|
|
131
|
+
- **Settings → Plugins → Plugin configuration → dsh-engram** — a collapsible
|
|
132
|
+
config card in the same style as the built-in "Shell / Agent loop / Web
|
|
133
|
+
search" cards: title + one-line description + chevron, collapsed by default,
|
|
134
|
+
click to expand/collapse. Open, its ~12 options render under four groups —
|
|
135
|
+
Capture & Search / Index / Lifecycle & GC / Security. Changes apply to new
|
|
136
|
+
sessions (frozen blocks stay stable); Discard / Save with an "unsaved" badge
|
|
137
|
+
on the header. The card drives the namespace through the connection's own
|
|
138
|
+
settings RPCs (not the isLoopback-gated scope), so it stays editable even
|
|
139
|
+
when the GUI is reached through an operator-authorized tunnel.
|
|
140
|
+
|
|
141
|
+
The browser half is served by DSH's client-module loader directly from this
|
|
142
|
+
package (`dsh.client` + `exports["./client"]`, no web-application rebuild); the
|
|
143
|
+
data comes from the loopback-fenced `/api/dsh-engram/*` route family. The fence
|
|
144
|
+
stays closed by default; to reach the memory viewer from an authorized tunnel
|
|
145
|
+
hostname, list it in the plugin's `trustedHosts` config (e.g. via the registry
|
|
146
|
+
or a profile patch):
|
|
147
|
+
|
|
148
|
+
```jsonc
|
|
149
|
+
// patch/engram.json
|
|
150
|
+
{ "engram": { "trustedHosts": ["cream-club-fragrances-caught.trycloudflare.com"] } }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
If you change `client/src`, rebuild the bundle with:
|
|
154
|
+
|
|
155
|
+
```sh
|
|
156
|
+
npm run build:client
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Tools
|
|
160
|
+
|
|
161
|
+
| Tool | Purpose | Kind |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `engram_store` | Explicitly store one memory (kind, tags, optional entity anchor) | write |
|
|
164
|
+
| `engram_recall` | Deterministic keyword recall over workspace memories; optional `search_sessions` FTS over past sessions | read |
|
|
165
|
+
| `engram_detail` | Full record of one memory id (provenance, tags, hits) | read |
|
|
166
|
+
| `esr_task` | Create a task entity (draft → active) | write |
|
|
167
|
+
| `esr_close` | Close a task via the evidence protocol (artifact + evaluation + memory_ref) | write |
|
|
168
|
+
| `esr_link` | Add a typed relation between two entities (mini graph) | write |
|
|
169
|
+
| `esr_gc` | Run the memory GC for the workspace (`dry_run:true` previews) | write |
|
|
170
|
+
|
|
171
|
+
## Memory GC
|
|
172
|
+
|
|
173
|
+
A scheduled sweep (`gcIntervalHours`, default 24h) plus a manual `esr_gc` /
|
|
174
|
+
GUI button keeps the store bounded the pi-esr way — **mechanical, working-set
|
|
175
|
+
protected, archive-only**:
|
|
176
|
+
|
|
177
|
+
- TTL-expired memories are archived (soft; the id stays, retrievable via the
|
|
178
|
+
GUI's archived filter);
|
|
179
|
+
- over-cap workspaces evict the lowest-value *non-protected* memories;
|
|
180
|
+
- stable tasks past `gcStableRetentionDays` become archived and leave `[ESR]`;
|
|
181
|
+
- links whose **both** endpoints are gone are dropped (dangling edges).
|
|
182
|
+
|
|
183
|
+
GC never touches the working set: memories referenced by an active task
|
|
184
|
+
(`memory_refs`), task-kind memories, and already-indexed hits
|
|
185
|
+
(`hits >= promoteHits`). Run `esr_gc` with `dry_run: true` to preview. Nothing
|
|
186
|
+
is hard-deleted — the report ends with re-fetch pointers for everything it
|
|
187
|
+
archived, so archives are recoverable, not lost.
|
|
188
|
+
|
|
189
|
+
## Auto-capture policy
|
|
190
|
+
|
|
191
|
+
Capture is deterministic and offline — it only sees tool *results*, never the
|
|
192
|
+
conversation. Exactly what earns a memory record:
|
|
193
|
+
|
|
194
|
+
| Tool result | Action | Signal |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| `git commit … -m "subject"` | record — the written subject is the memory | 0.55 |
|
|
197
|
+
| `git merge` / `rebase` / `cherry-pick` / `tag` / `checkout -b` | record (milestone) | 0.5 |
|
|
198
|
+
| `git push` / `git stash` / commit without `-m` | **skip** — plumbing echo, not a decision | — |
|
|
199
|
+
| write/edit of a significant config & doc path | record | 0.3 |
|
|
200
|
+
| read of a config path | record | 0.3 |
|
|
201
|
+
| repeated tool error | record (deduped by message) | 0.25 |
|
|
202
|
+
|
|
203
|
+
Explicit `engram_store` writes are always recorded regardless of these rules
|
|
204
|
+
(rate-limited per session).
|
|
205
|
+
|
|
206
|
+
**Who earns a `[ENGRAM]` index line** (this is what actually touches the prompt):
|
|
207
|
+
`signal >= minIndexSignal` **or** `hits >= promoteHits` **or** `kind === "task"`,
|
|
208
|
+
then capped by `indexMaxLines` / `indexMaxChars`. One extra guard keeps the pipe
|
|
209
|
+
clean: auto-captured git command echoes — text that embeds a shell chain
|
|
210
|
+
(`git push: cd … && …`) — stay out of the index even when above the signal
|
|
211
|
+
threshold, until recall hits have promoted them. Everything else sits quietly in
|
|
212
|
+
storage, reachable on demand via `engram_recall` / `engram_detail` — "retrieved ≠
|
|
213
|
+
injected".
|
|
214
|
+
|
|
215
|
+
## Injected blocks
|
|
216
|
+
|
|
217
|
+
What the model actually sees (rendered once per session, then frozen):
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
[ENGRAM] workspace: symbolic-index · 2 memories · 1 task(s) active · 0 links
|
|
221
|
+
[D] 06-18 Decided: use sqlite-vec for retrieval #a2331d87
|
|
222
|
+
[T] 06-18 Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref #tsk_8b26
|
|
223
|
+
drill: engram_store (user asks to remember) | engram_recall <query> | engram_detail <id> | esr_task / esr_close / esr_link
|
|
224
|
+
|
|
225
|
+
[ESR] tasks: 1 active / 1 stable
|
|
226
|
+
- tsk_0d: Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref
|
|
227
|
+
- closed: tsk_9a (RAG eval) · +1
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Prefixes: `[D]` decision · `[E]` error · `[P]` procedure · `[F]` fact ·
|
|
231
|
+
`[I]` insight · `[H]` handoff · `[T]` task. Membership follows the
|
|
232
|
+
*Auto-capture policy* (signal threshold / recall promotion / git-echo guard),
|
|
233
|
+
bounded by the configured line and character budgets. `#` ids address the full
|
|
234
|
+
records via `engram_detail`. When a workspace has no tasks, `[ESR]` still renders
|
|
235
|
+
one line naming `esr_task`/`esr_close` so the mechanism stays visible to the
|
|
236
|
+
model instead of vanishing.
|
|
237
|
+
|
|
238
|
+
## Config
|
|
239
|
+
|
|
240
|
+
Defaults are token-conscious; override any key via the profile patch
|
|
241
|
+
(`~/.dsh/profiles/web/cordis.patch.yml`) or the web config card:
|
|
242
|
+
|
|
243
|
+
```yaml
|
|
244
|
+
- id: engram
|
|
245
|
+
config:
|
|
246
|
+
autoCapture: true # zero-LLM tool-result capture
|
|
247
|
+
sessionSearch: true # engram_recall may also FTS past sessions
|
|
248
|
+
autoCapturePerSession: 40
|
|
249
|
+
indexMaxLines: 12 # [ENGRAM] line cap
|
|
250
|
+
indexMaxChars: 700 # [ENGRAM] char cap (token budget)
|
|
251
|
+
minIndexSignal: 0.4 # auto-captures below this stay out of the index
|
|
252
|
+
# (git command echoes are excluded regardless,
|
|
253
|
+
# until promoted by recall hits)
|
|
254
|
+
promoteHits: 3 # ...until recalled this many times
|
|
255
|
+
expireDays: 180 # memory TTL (0 = never)
|
|
256
|
+
maxMemoriesPerWorkspace: 2000
|
|
257
|
+
gcEnabled: true # scheduled memory GC
|
|
258
|
+
gcIntervalHours: 24 # sweep cadence
|
|
259
|
+
gcStableRetentionDays: 120 # stable tasks leave [ESR] after this
|
|
260
|
+
engramIndexOrder: 40 # systemPrompt section order (before tools band)
|
|
261
|
+
esrOrder: 41
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
npm test # 29 tests: core + web API + GC + usage-observability (node:test)
|
|
268
|
+
npm run eval # offline recall + structure benchmark (deterministic)
|
|
269
|
+
npm run build:client
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Testing & evaluation (two layers of real testing)
|
|
273
|
+
|
|
274
|
+
**npm run eval** (eval/recall-bench.mjs) is the deterministic layer —
|
|
275
|
+
LongMemEval-style: a controlled corpus (ASCII + CJK, known tags/entities/
|
|
276
|
+
timestamps) measured through the real store/recall path (openEngramDomain +
|
|
277
|
+
domain.recall), reporting Precision@k / Recall@k / MRR / Hit@1 per probe
|
|
278
|
+
(exact tag, substring, multi-term, CJK, phrase-single, ordering, negative)
|
|
279
|
+
plus StructMemEval-flavoured structure metrics (exact-duplicate dedup rate,
|
|
280
|
+
entity anchoring coverage, dangling-link hygiene). Honest, reproducible
|
|
281
|
+
numbers — everyone gets the same output. Current run: AVG P@k 0.770 /
|
|
282
|
+
AVG R@k 1.000 / MRR 0.889 / hit@1 0.889 / 0 negative false-positives /
|
|
283
|
+
dedup 1.0.
|
|
284
|
+
|
|
285
|
+
**/api/dsh-engram/stats + the observability panel** is the real-session layer —
|
|
286
|
+
it answers how the model actually uses the memory in production (ESR
|
|
287
|
+
proactivity ratio, recall hit rate, detail conversion), while the eval
|
|
288
|
+
answers how good the retrieval layer itself is.
|
|
289
|
+
|
|
290
|
+
Repo layout: `lib/` (host half: store / capture / index-block / tools / api /
|
|
291
|
+
settings), `client/` (browser half, TSX + `build.mjs`), `test/` (node:test).
|
|
292
|
+
|
|
293
|
+
## Troubleshooting
|
|
294
|
+
|
|
295
|
+
**The web GUI opens and immediately shows “Failed to load plugins”**, with a
|
|
296
|
+
loader error like:
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
failed to apply loader entry … (@linxin666/dsh-client-ui-web-ui-settings):
|
|
300
|
+
keyed slot "settings.plugin.item" requires options.key
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Cause: DSH hosts since `0.1.0-rc.7` declare the config-card slot
|
|
304
|
+
`settings.plugin.item` as **keyed by the settings namespace a card edits** —
|
|
305
|
+
which is exactly how dsh-engram's own config card registers (under
|
|
306
|
+
`key: "dsh-engram"`). The `@linxin666/dsh-web-ui-all` family **before 0.2.0**
|
|
307
|
+
(`dsh-client-ui-web-ui-settings`) registered its group card into that slot
|
|
308
|
+
**without a `key`**, and because a single failed loader entry aborts the whole
|
|
309
|
+
boot, the GUI stays stuck on the failure page.
|
|
310
|
+
|
|
311
|
+
Fixes:
|
|
312
|
+
|
|
313
|
+
- **Proper fix — upgrade the family**: `@linxin666/dsh-web-ui-all@^0.2.x`.
|
|
314
|
+
The 0.2 line moved its settings surface out of the keyed slot into a
|
|
315
|
+
first-level `settings.section` (the upstream fix for exactly this error).
|
|
316
|
+
- **Immediate unblock**: add `key: "web-ui-plugins"` to that one
|
|
317
|
+
`settings.plugin.item` registration in the installed
|
|
318
|
+
`node_modules/@linxin666/dsh-client-ui-web-ui-settings/lib/client.js`, then
|
|
319
|
+
restart `dsh web`. (Under namespace-keyed dispatch the group card simply
|
|
320
|
+
stays hidden; nothing else on the page is affected.)
|
|
321
|
+
|
|
322
|
+
## Related
|
|
323
|
+
|
|
324
|
+
- [symbolic-index](https://github.com/skepsun/symbolic-index) — the original cross-session
|
|
325
|
+
memory plugin (5-signal RRF fusion, sqlite-vec, Dream Engine).
|
|
326
|
+
- [pi-esr](https://github.com/skepsun/pi-esr) — project-lifetime evidence-driven
|
|
327
|
+
task states; the closure protocol here is its lite form.
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
MIT
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# dsh-engram
|
|
2
|
+
|
|
3
|
+
> **[中文](README.zh.md) · [English](README.md)**
|
|
4
|
+
|
|
5
|
+
为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 设计的极简长期记忆插件,融合了
|
|
6
|
+
[symbolic-index](https://github.com/skepsun/symbolic-index) 与 [pi-esr](https://github.com/skepsun/pi-esr) 的思想——
|
|
7
|
+
目标只有一个:**省 token**。
|
|
8
|
+
|
|
9
|
+
- **零 LLM 摄入** — 纯模式匹配从工具结果自动捕获有意义的事件(带书面 `-m` 提交信息的 git 里程碑、
|
|
10
|
+
关键文件编辑、反复出现的错误),另有显式 `engram_store`。热路径上没有任何模型调用,纯粹的操作
|
|
11
|
+
——`git push` / `git stash` / 无提交信息的 commit——刻意**从不记录**(见下方「自动捕获策略」)。
|
|
12
|
+
- **符号索引 + 渐进披露** — 一个紧凑的 `[ENGRAM]` 块(默认预算 700 字符 ≈ 175 token;每条记忆一行)在
|
|
13
|
+
组装提示词时注入,并**按会话冻结**,让请求前缀字节稳定以复用 KV 缓存。模型需要细节时用
|
|
14
|
+
`engram_recall` / `engram_detail` 下钻,而不是把命中的原文灌进上下文。
|
|
15
|
+
- **ESR-lite 证据闭环** — `esr_task` / `esr_close` / `esr_link` 给任务一个 `draft → active → stable`
|
|
16
|
+
生命周期,其中 `stable` 必须要有真实证据(`artifact` / `evaluation` / `memory_ref`),把"缺什么"
|
|
17
|
+
摊在明面上,而不是让 agent 没有证据就宣布完成。
|
|
18
|
+
- **记忆 GC(pi-esr 约束)** — 定时、机械、只归档的回收:TTL 过期记忆归档、超容量工作区淘汰低价值条目、
|
|
19
|
+
stable 任务超保留窗离开 `[ESR]` 表面、悬空链接边清理。工作集(active 任务引用 / 任务记忆 / 已入索引命中)
|
|
20
|
+
永不触碰;**不硬删任何东西**——归档条目保留 id、始终可重取。
|
|
21
|
+
- **Web 查看器** — 一个带统计的记忆浏览器和配置卡片,完全构建在 DSH 原生设置槽位上(不碰任何第三方 UI 包)。
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
MIT · node >= 22.19 · host 半边 + 浏览器半边合在一包
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 为什么还要一个记忆插件?
|
|
28
|
+
|
|
29
|
+
对既有 DSH 插件生态的调研显示,记忆领域里"召回桥 / 审批门 / LLM 蒸馏 / 向量+图"这几个方向已经挤满了。
|
|
30
|
+
dsh-engram 补的是对 token 纪律真正重要的三个空白:
|
|
31
|
+
|
|
32
|
+
1. **写入路径没有模型** — 捕获是确定性的模式匹配。
|
|
33
|
+
2. **提示词里不灌原文** — 只注入有界的符号索引,检索按需进行("检索到 ≠ 注入")。
|
|
34
|
+
3. **诚实的任务闭环** — 没有证据就不能宣布 STABLE。
|
|
35
|
+
|
|
36
|
+
DSH 已经提供跨会话 FTS(`ctx.sessionQuery`)、存储(`ctx.storageDomain`)、提示词注入钩子和设置槽位;
|
|
37
|
+
dsh-engram 只是这些能力之上的一层薄组合层,而非重新实现。
|
|
38
|
+
|
|
39
|
+
## 安装
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# 从 GitHub(本仓库)
|
|
43
|
+
dsh plugin --profile web add github:skepsun/dsh-engram
|
|
44
|
+
|
|
45
|
+
# 发布到 npm 之后
|
|
46
|
+
dsh plugin --profile web add dsh-engram
|
|
47
|
+
|
|
48
|
+
# 本地开发(符号链接——改动立即生效)
|
|
49
|
+
dsh plugin --profile web add link:/path/to/dsh-engram
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
然后**重启 `dsh web`**。数据保存在 `~/.dsh/storages/dsh_engram.json`。
|
|
53
|
+
|
|
54
|
+
> npm 与 GitHub 两种装法**都不需要手动补依赖**:pnpm 会自动安装 `zod`,
|
|
55
|
+
> 并把可选的 `@deepseek-ai/*` peers 嵌套装进插件自身的 `node_modules`,CLI 也会
|
|
56
|
+
> 自动把插件登记进 profile 的 `dsh.profile.bundles`。下面的 `setup-links` 只在
|
|
57
|
+
> `link:` 开发工作流里需要——pnpm 故意不为符号链接目录安装依赖。
|
|
58
|
+
|
|
59
|
+
> 需要新建会话才能看到注入的 `[ENGRAM]`/`[ESR]` 块和全部工具——提示词与工具注册表都是按会话装配的。
|
|
60
|
+
|
|
61
|
+
### `link:` 安装的依赖准备
|
|
62
|
+
|
|
63
|
+
符号链接安装的插件从**自身 checkout 的 `node_modules`** 解析 import,而这层依赖
|
|
64
|
+
不被 git 跟踪,换机器(尤其 Windows)会报
|
|
65
|
+
`ERR_MODULE_NOT_FOUND: Cannot find package 'zod'`(接着是 `@deepseek-ai/*` peers)。
|
|
66
|
+
一条命令重建依赖层:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
cd /path/to/dsh-engram
|
|
70
|
+
node scripts/setup-links.mjs # 把 @deepseek-ai 工作区包软链进 node_modules,
|
|
71
|
+
# 并安装 zod(优先复用 harness pnpm store,
|
|
72
|
+
# 找不到则回退 `npm install`)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
脚本会自动定位 harness:`../deepseek-harness`(仓库上一级平级),也支持「仓库父级平级」布局
|
|
76
|
+
(如 `E:\deepseek-harness` 与 `E:\kototoro_demo\dsh-engram`)——都找不到再用 `DSH_HARNESS_DIR` 指定。
|
|
77
|
+
`node scripts/setup-links.mjs --check` 只打印状态不写入。
|
|
78
|
+
|
|
79
|
+
## 在 Web 端能得到什么
|
|
80
|
+
|
|
81
|
+
重启后,全部落在 **DSH 原生**设置界面里:
|
|
82
|
+
|
|
83
|
+
- **设置 → Engram 记忆** — 独立的一级设置页签(位于「插件」之后),不再是「插件」页里的子 tab;默认
|
|
84
|
+
「全部工作区」视图完整展示所有工作区的记忆/任务/关系(按工作区分组,工作区下拉 + 上一/下一工作区
|
|
85
|
+
翻页;记忆表格另行 10 条/页分页 + 跳页下拉,仅「类型 / 内容 / 操作」三列——正文列占满,时间、
|
|
86
|
+
标签、signal/hits/TTL 等全部折叠进内容行内(meta 行 + 标签行),正文限高三行省略、
|
|
87
|
+
行内「展开全文/收起」与 hover 均可看全文,归档/删除按钮竖向堆叠)。概览统计卡片(各工作区/类型的计数、自动捕获总量、各工作区 `[ENGRAM]` 索引
|
|
88
|
+
token 估算、GC 累计统计)、可搜索/可过滤的记忆表格(含归档与删除操作)、ESR 任务看板(「新建任务」
|
|
89
|
+
表单 + 点击「填写证据关闭…」补 artifact/evaluation/memory_ref 转 STABLE)、节点与关系清单
|
|
90
|
+
(节点 = 模型用 esr_node 登记的领域对象,如包/服务/仓库/概念;关系 = esr_link),
|
|
91
|
+
以及记忆 GC 面板(dry-run 开关 + 运行按钮 + 指针报告)。ESR 的 GUI 新建/关闭走宿主新增的
|
|
92
|
+
`POST /api/dsh-engram/tasks` 与 `POST /api/dsh-engram/tasks/close`(与 esr_task / esr_close 同一证据门)。
|
|
93
|
+
模型侧的主动行为由 [ENGRAM]/[ESR] 注入块驱动:多步工作即时建任务、反复出现的领域对象即时登记节点、相关任务/节点即时互连。
|
|
94
|
+
|
|
95
|
+
**真实行为观测(agent 遥测)** — ESR 页顶部新增「agent 行为观测」面板:每次模型调用 `engram_*`/`esr_*` 工具都实时累计到
|
|
96
|
+
按(工作区 × 天)的 usage 滚动行(新增 `usage` 表 + `GET /api/dsh-engram/stats`),折算成指标:
|
|
97
|
+
**ESR 主动性** = esr 工具调用数 /(记忆 + esr 工具调用总数);**召回命中率** = 有命中的 engram_recall 次数 / 总次数;
|
|
98
|
+
**平均命中/查询**;**detail 转化** = 命中召回后很快跟一次 engram_detail 的比例(会话内 8 事件窗口);失败数按工具记。
|
|
99
|
+
面板同时列出各工具调用计数与最近 14 天逐日滚动。这些是真实会话的真实数字——想提升 ESR 主动性,
|
|
100
|
+
就观察面板上 esr 占比并调整注入提示。
|
|
101
|
+
- **设置 → 插件 → 插件配置 → dsh-engram** — 与内置「终端 / Agent 循环 / 网页搜索」同款的
|
|
102
|
+
**默认折叠卡片**:标题 + 一行描述 + 箭头,点击展开/收起;展开后 12 个设置项按
|
|
103
|
+
「捕获与检索 / 索引 / 生命周期与 GC / 安全」四个分组展示。改动对新建会话即时生效
|
|
104
|
+
(已冻结的块保持稳定);支持放弃修改 / 保存,有未保存改动时标题上出现「未保存」徽标。
|
|
105
|
+
卡片通过连接自身的 settings RPC 直连命名空间(不走 isLoopback 门控的 scope),因此即使
|
|
106
|
+
GUI 经运营商授权的隧道访问也保持可编辑。
|
|
107
|
+
|
|
108
|
+
浏览器半边由 DSH 的 client-module loader 直接从本包提供(`dsh.client` + `exports["./client"]`,无需重建
|
|
109
|
+
web 应用);数据来自 loopback 围栏保护的 `/api/dsh-engram/*` 路由族。围栏默认关闭隧道访问;如需经授权的
|
|
110
|
+
隧道域名访问记忆查看器,把域名加进插件的 `trustedHosts` 配置(如通过 registry 或 profile patch):
|
|
111
|
+
|
|
112
|
+
```jsonc
|
|
113
|
+
// patch/engram.json
|
|
114
|
+
{ "engram": { "trustedHosts": ["cream-club-fragrances-caught.trycloudflare.com"] } }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
修改 `client/src` 后重建 bundle:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
npm run build:client
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 测试与评测
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
npm test # 29 项单元测试(含 usage 滚动 / /stats 路由)
|
|
127
|
+
npm run eval # 离线召回 + 结构基准(确定性语料,跑真实 store/recall 路径)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`npm run eval` 的检索部分参照 LongMemEval 的问答式评测:受控语料(ASCII + CJK、标签/实体/时间戳已知),
|
|
131
|
+
对真实 `domain.recall()` 逐一校准 **Precision@k / Recall@k / MRR / Hit@1**(probe 覆盖 tag 精确、子串、
|
|
132
|
+
多词、CJK、短语唯一、标签排序、负样本无回);结构部分借鉴 StructMemEval:精确去重率(同文本存 3 次折叠为 1)、
|
|
133
|
+
实体锚定覆盖率、节点/链接卫生(无悬空链接)。数字诚实、非调优——任何人跑出来都一样,复现即所得。
|
|
134
|
+
|
|
135
|
+
两层「真实测试」的分工:`npm run eval` 回答「检索层本身有多好」(确定性、可复现);
|
|
136
|
+
`/api/dsh-engram/stats` + 观测面板回答「真实会话里模型实际怎么用」(ESR 主动性、召回命中率、detail 转化),
|
|
137
|
+
两者结合才能判断:召回层没问题但命中率低 = 模型没学会问;反之亦然。
|
|
138
|
+
|
|
139
|
+
## 工具
|
|
140
|
+
|
|
141
|
+
| 工具 | 用途 | 类型 |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| `engram_store` | 显式存入一条记忆(kind、tags、可选实体锚点) | 写 |
|
|
144
|
+
| `engram_recall` | 工作区记忆的确定性关键词召回;可选 `search_sessions` 跨会话 FTS | 读 |
|
|
145
|
+
| `engram_detail` | 一条记忆 id 的完整记录(来源、标签、命中数) | 读 |
|
|
146
|
+
| `esr_task` | 创建任务实体(draft → active) | 写 |
|
|
147
|
+
| `esr_close` | 按证据协议关闭任务(artifact + evaluation + memory_ref) | 写 |
|
|
148
|
+
| `esr_link` | 在两个实体之间添加类型化关系(迷你图) | 写 |
|
|
149
|
+
| `esr_gc` | 运行本工作区的记忆 GC(`dry_run:true` 预览不落库) | 写 |
|
|
150
|
+
|
|
151
|
+
## 记忆 GC
|
|
152
|
+
|
|
153
|
+
定时回收(`gcIntervalHours`,默认 24h)+ `esr_gc` 手动触发 + GUI 按钮,按 pi-esr 方式把存储保持在
|
|
154
|
+
有界内——**机械、工作集保护、只归档**:
|
|
155
|
+
|
|
156
|
+
- TTL 过期记忆归档(软删;id 保留,可通过 GUI 的 archived 筛选检索);
|
|
157
|
+
- 超容量工作区淘汰最低价值的*非保护*记忆;
|
|
158
|
+
- stable 任务超 `gcStableRetentionDays` 归档、离开 `[ESR]`;
|
|
159
|
+
- 两端点都已消失的链接被清理(悬空边)。
|
|
160
|
+
|
|
161
|
+
GC 永不触碰工作集:active 任务 `memory_refs` 引用的记忆、task 类记忆、已入索引的命中
|
|
162
|
+
(`hits >= promoteHits`)。用 `esr_gc` + `dry_run: true` 先预览。**不硬删**——报告的末尾为所有
|
|
163
|
+
归档项附上重取指针,归档可恢复、不是丢失。
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
## 自动捕获策略
|
|
167
|
+
|
|
168
|
+
捕获是确定性、离线的——只看到工具*结果*,从不看对话本身。什么会被记录成一条记忆:
|
|
169
|
+
|
|
170
|
+
| 工具结果 | 行为 | 信号 |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| `git commit … -m "提交信息"` | 记录——书面提交信息就是这条记忆 | 0.55 |
|
|
173
|
+
| `git merge` / `rebase` / `cherry-pick` / `tag` / `checkout -b` | 记录(里程碑) | 0.5 |
|
|
174
|
+
| `git push` / `git stash` / 无 `-m` 的 commit | **跳过**——操作回显,不是决策 | — |
|
|
175
|
+
| 写入/编辑关键配置与文档路径 | 记录 | 0.3 |
|
|
176
|
+
| 读取配置路径 | 记录 | 0.3 |
|
|
177
|
+
| 反复出现的工具错误 | 记录(按消息去重) | 0.25 |
|
|
178
|
+
|
|
179
|
+
显式 `engram_store` 的记录不受上述规则约束(按会话限流)。
|
|
180
|
+
|
|
181
|
+
**谁能拿到 `[ENGRAM]` 索引行**(这才是真正进提示词的部分):
|
|
182
|
+
`signal >= minIndexSignal` **或** `hits >= promoteHits` **或** `kind === "task"`,
|
|
183
|
+
再由 `indexMaxLines` / `indexMaxChars` 封顶。另有一道额外的闸保持管道干净:
|
|
184
|
+
自动捕获的 git 命令回显——文本里嵌着 shell 命令链(`git push: cd … && …`)——
|
|
185
|
+
即使信号超阈值也不进索引,直到被召回命中晋升为止。其余条目安静地躺在存储里,
|
|
186
|
+
按需用 `engram_recall` / `engram_detail` 取用——「检索到 ≠ 注入」。
|
|
187
|
+
|
|
188
|
+
## 注入块
|
|
189
|
+
|
|
190
|
+
模型实际看到的内容(每个会话渲染一次,然后冻结):
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
[ENGRAM] workspace: symbolic-index · 2 memories · 1 task(s) active · 0 links
|
|
194
|
+
[D] 06-18 Decided: use sqlite-vec for retrieval #a2331d87
|
|
195
|
+
[T] 06-18 Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref #tsk_8b26
|
|
196
|
+
drill: engram_store (user asks to remember) | engram_recall <query> | engram_detail <id> | esr_task / esr_close / esr_link
|
|
197
|
+
|
|
198
|
+
[ESR] tasks: 1 active / 1 stable
|
|
199
|
+
- tsk_0d: Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref
|
|
200
|
+
- closed: tsk_9a (RAG eval) · +1
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
前缀:`[D]` 决定 · `[E]` 错误 · `[P]` 流程 · `[F]` 事实 · `[I]` 洞察 · `[H]` 交接 · `[T]` 任务。
|
|
204
|
+
入选规则遵循「自动捕获策略」(信号阈值 / 命中晋升 / git 回显守卫),并按配置的行数与字符预算封顶。
|
|
205
|
+
`#` id 通过 `engram_detail` 取完整记录。工作区没有任务时,`[ESR]` 仍会渲染一行点名 `esr_task`/`esr_close`,
|
|
206
|
+
让机制对模型保持可见,而不是整体消失。
|
|
207
|
+
|
|
208
|
+
## 配置
|
|
209
|
+
|
|
210
|
+
默认值以 token 为优先;可通过 profile 补丁(`~/.dsh/profiles/web/cordis.patch.yml`)或 Web 配置卡片覆盖任意键:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
- id: engram
|
|
214
|
+
config:
|
|
215
|
+
autoCapture: true # 零 LLM 工具结果捕获
|
|
216
|
+
sessionSearch: true # engram_recall 也可对历史会话 FTS
|
|
217
|
+
autoCapturePerSession: 40
|
|
218
|
+
indexMaxLines: 12 # [ENGRAM] 行数上限
|
|
219
|
+
indexMaxChars: 700 # [ENGRAM] 字符上限(token 预算)
|
|
220
|
+
minIndexSignal: 0.4 # 低于此信号的自动捕获不进索引
|
|
221
|
+
# (git 命令回显即便超阈值也不进,直到命中晋升)
|
|
222
|
+
promoteHits: 3 # ……直到被召回这么多次才进索引
|
|
223
|
+
expireDays: 180 # 记忆 TTL(0 = 永不过期)
|
|
224
|
+
maxMemoriesPerWorkspace: 2000
|
|
225
|
+
gcEnabled: true # 定时记忆 GC
|
|
226
|
+
gcIntervalHours: 24 # 回收节奏
|
|
227
|
+
gcStableRetentionDays: 120 # 超过此天数的 stable 任务离开 [ESR]
|
|
228
|
+
engramIndexOrder: 40 # systemPrompt section 顺序(位于 tools 段之前)
|
|
229
|
+
esrOrder: 41
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 开发
|
|
233
|
+
|
|
234
|
+
```sh
|
|
235
|
+
npm test # 21 个测试:核心 + Web API + GC(node:test)
|
|
236
|
+
npm run build:client
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
仓库结构:`lib/`(宿主半边:store / capture / index-block / tools / api / settings)、
|
|
240
|
+
`client/`(浏览器半边,TSX + `build.mjs`)、`test/`(node:test)。
|
|
241
|
+
|
|
242
|
+
## 故障排查
|
|
243
|
+
|
|
244
|
+
**Web 界面一打开就停在 “Failed to load plugins”**,loader 报错形如:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
failed to apply loader entry … (@linxin666/dsh-client-ui-web-ui-settings):
|
|
248
|
+
keyed slot "settings.plugin.item" requires options.key
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
原因:DSH 自 `0.1.0-rc.7` 起把配置卡槽位 `settings.plugin.item` 声明为**按
|
|
252
|
+
settings 命名空间键控**(卡片用自身编辑的命名空间作 `key` 注册——dsh-engram
|
|
253
|
+
的配置卡正是用 `key: "dsh-engram"` 这样注册的)。`@linxin666/dsh-web-ui-all`
|
|
254
|
+
**0.2.0 之前的** `dsh-client-ui-web-ui-settings` 向该槽位注册分组卡片时**没有
|
|
255
|
+
提供 `key`**;而 loader 只要有一个 entry 失败就会中止整个启动流程,于是 GUI
|
|
256
|
+
一直卡在失败页。
|
|
257
|
+
|
|
258
|
+
修复方式:
|
|
259
|
+
|
|
260
|
+
- **正确修复——升级全家桶**:`@linxin666/dsh-web-ui-all@^0.2.x`。0.2
|
|
261
|
+
系列已把自身设置面从键控槽位迁出,改为一级 `settings.section`(上游正是
|
|
262
|
+
为这个报错做的修复)。
|
|
263
|
+
- **临时解阻**:在已安装的
|
|
264
|
+
`node_modules/@linxin666/dsh-client-ui-web-ui-settings/lib/client.js` 中给那
|
|
265
|
+
个 `settings.plugin.item` 注册补上 `key: "web-ui-plugins"`,然后重启
|
|
266
|
+
`dsh web`。(在按命名空间键控的派发下,分组卡片只是不显示,不影响页面其
|
|
267
|
+
他部分。)
|
|
268
|
+
|
|
269
|
+
## 相关项目
|
|
270
|
+
|
|
271
|
+
- [symbolic-index](https://github.com/skepsun/symbolic-index) — 原始跨会话记忆插件(5 信号 RRF 融合、sqlite-vec、Dream Engine)。
|
|
272
|
+
- [pi-esr](https://github.com/skepsun/pi-esr) — 项目全周期的证据驱动任务状态;这里的闭环协议是它的简化形态。
|
|
273
|
+
|
|
274
|
+
## 许可
|
|
275
|
+
|
|
276
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dsh-engram bundle patch: inserts the host plugin row into the web profile
|
|
2
|
+
# roster. Activate with:
|
|
3
|
+
# dsh plugin --profile web add file:/d1/chuxiong/code/dsh-engram
|
|
4
|
+
#
|
|
5
|
+
# The row is a bare host-half plugin by package name. It does not need to
|
|
6
|
+
# enable storage-domain / storage-json / session-query-sqlite — the standard
|
|
7
|
+
# web profile (dsh-base x dsh-web-app) already mounts them.
|
|
8
|
+
- insert:
|
|
9
|
+
- id: engram
|
|
10
|
+
name: dsh-engram
|