dsh-memento 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/ARCHITECTURE.md +132 -0
- package/CHANGELOG.md +46 -0
- package/LICENSE +201 -0
- package/README.es.md +166 -0
- package/README.hi.md +166 -0
- package/README.md +166 -0
- package/README.pt.md +166 -0
- package/README.zh.md +166 -0
- package/THIRD_PARTY_NOTICES.md +15 -0
- package/client/client.d.ts +6 -0
- package/client/client.js +240 -0
- package/cordis.patch.yml +4 -0
- package/index.mjs +1849 -0
- package/lib/budget.mjs +110 -0
- package/lib/constants.mjs +58 -0
- package/lib/errors.mjs +143 -0
- package/lib/extract.mjs +54 -0
- package/lib/gate.mjs +131 -0
- package/lib/match.mjs +43 -0
- package/lib/snapshot.mjs +115 -0
- package/lib/store.mjs +654 -0
- package/lib/strings.mjs +43 -0
- package/lib/workspace.mjs +31 -0
- package/package.json +93 -0
- package/types.d.ts +191 -0
package/README.hi.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# dsh-memento
|
|
2
|
+
|
|
3
|
+
**DeepSeek Harness के लिए परिबद्ध, स्तरित, अनुमोदन-द्वारी, लेखा-परीक्षण-योग्य क्रॉस-सेशन मेमोरी।**
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/@deepseek-ai/dsh)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
10
|
+
|
|
11
|
+
[English](README.md) · [中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
12
|
+
|
|
13
|
+
> अन्य मेमोरी प्लगइन एक **गोदाम (warehouse)** बेचते हैं। dsh-memento **सीम (seam)** बेचता है: एक टाइप्ड `ctx.memory` सेवा, एक लेखन-अनुमोदन द्वार जिसे कोई मॉडल पथ बायपास नहीं कर सकता, और ऑडिट ट्रेल जिन्हें आप सेशन लॉग से पुनर्निर्मित कर सकते हैं। DeepSeek Harness के लिए नेटिव-फर्स्ट मेमोरी — प्रोटोकॉल + ट्रस्ट गेट + ऑडिट, शून्य नेटवर्क और शून्य क्रेडेंशियल के साथ।
|
|
14
|
+
|
|
15
|
+
## ✨ dsh-memento क्यों?
|
|
16
|
+
|
|
17
|
+
- **यह एक क्षमता सीम (capability seam) है, कोई और स्टोर नहीं।** सर्विस डेफ़िनिशन (`ctx.memory`), लोकल SQLite प्रोवाइडर (`node:sqlite`, WAL, `0600`), और कंज़्यूमर (`memory` टूल + फ़्रोज़न स्नैपशॉट इंजेक्शन)। कोई भी भविष्य का प्लगइन — एक `dsh-claude-move` सीड इंटीग्रेशन, एक ब्रिज, एक पैनल — **उसी स्टोर को उसी द्वार के माध्यम से** पढ़ता और लिखता है।
|
|
18
|
+
- **द्वार को बायपास नहीं किया जा सकता।** हर लेखन पथ (`add`/`replace`/`remove`/`seed`) **सेवा के अंदर** अनुमोदन वॉटरफॉल से गुज़रता है, टूल लेयर में नहीं। `writePolicy: ask | auto | off` ऐसा कॉन्फ़िगरेशन है जिसे मॉडल न तो देख सकता है और न ही बदल सकता है; एक सेशन-स्तरीय `never` रुख फिर भी सब कुछ पहले ही रोक देता है।
|
|
19
|
+
- **Model-visible ⟺ logged.** इंजेक्ट किया गया स्नैपशॉट `request/header.system` में शब्दशः उतरता है; हर लेखन `approval/asked` (पूर्ण पेलोड) + `approval/decided` (परिणाम) + प्लगइन की अपनी ऑडिट टेबल से पुनर्निर्मित किया जा सकता है।
|
|
20
|
+
- **परिबद्ध और ईमानदार।** हर-ट्रैक/हर-लेयर कठोर वर्ण बजट (डिफ़ॉल्ट user 2000 / agent 4000)। भरा हुआ स्टोर **संरचित त्रुटि के साथ विफल** होता है (उपयोग + सीमा) — मॉडल समेकित करके पुनः प्रयास करता है। कभी काटा नहीं जाता, कभी स्वतः-कॉम्पैक्ट नहीं होता।
|
|
21
|
+
|
|
22
|
+
## ⚡ त्वरित शुरुआत
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# requires Node ^22.19 || >=24 and DSH 0.1.0-rc.6
|
|
26
|
+
dsh plugin --profile web add dsh-memento # or ./dsh-memento / a tarball / a GitHub URL
|
|
27
|
+
dsh --profile web --dump-config # expect a "# == dsh-memento" layer, no FAILED at startup
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
फिर, Web UI में: मॉडल से कुछ याद रखने को कहें → लेखन को अनुमोदित करें → एक **नया सेशन** शुरू करें और पूछें कि उसे क्या याद है। बस यही पूरा डेमो है।
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
# optional override in the profile's cordis.patch.yml
|
|
34
|
+
- id: memento
|
|
35
|
+
config:
|
|
36
|
+
writePolicy: ask # ask (default) | auto | off — model-invisible
|
|
37
|
+
budgets:
|
|
38
|
+
user: { userGlobal: 4000, workspace: 2000 } # Chinese-heavy memory: raise + note why
|
|
39
|
+
agent: { userGlobal: 4000, workspace: 4000 }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🧠 यह क्या करता है
|
|
43
|
+
|
|
44
|
+
| | घटक | आपको क्या मिलता है |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| 🧩 Service Definition | `ctx.memory` — `add` / `replace` / `remove` / `query` / `seed` / `budgets()` | टाइप्ड, merge-घोषित सेवा; लेखन विधियाँ द्वार को आंतरिक रूप से लागू करती हैं |
|
|
47
|
+
| 💾 Provider | `lib/store.mjs` — `node:sqlite` एकल फ़ाइल (`$DSH_HOME/dsh-memento/memory.db`, WAL) | शून्य निर्भरता, शून्य नेटवर्क; एंट्री + ऑडिट टेबल; यूनीक-सबस्ट्रिंग मिलान |
|
|
48
|
+
| 🛠 Consumers | `memory` टूल · फ़्रोज़न स्नैपशॉट इंजेक्शन (system-prompt सेक्शन, क्रम `-50`) · `memory_recall` टूल · `/memory` कमांड · रीड-ओनली Web पैनल | मॉडल-मुखी लेखन/पठन, बजट-शीर्ष फ़्रोज़न स्नैपशॉट, दो-भाग रिकॉल, यूज़र-साइड कमांड, ब्राउज़र ड्रॉअर |
|
|
49
|
+
|
|
50
|
+
**दो ट्रैक × दो लेयर × प्रति-एजेंट कुंजी।** `user` ट्रैक = उपयोगकर्ता के बारे में तथ्य (प्राथमिकताएँ, संचार शैली, संवेदनशील बिंदु); `agent` ट्रैक = पर्यावरण तथ्य, प्रोजेक्ट परंपराएँ, सीखे गए पाठ। हर ट्रैक में `user-global` (क्रॉस-वर्कस्पेस) और `workspace` (प्रति-सेशन cwd) लेयर होती हैं — Codex-शैली मर्ज्ड लेयरिंग, Hermes-शैली केवल-ग्लोबल नहीं। एक तीसरा आयाम सत्र के `agentPreset` से प्रविष्टियों को अलग करता है (प्रति-एजेंट स्कोप); बिना preset वाली प्रविष्टियाँ सबको दिखने वाली साझा लेयर में रहती हैं।
|
|
51
|
+
|
|
52
|
+
**फ़्रोज़न स्नैपशॉट।** स्नैपशॉट हर सेशन में पहली प्रॉम्प्ट असेंबली पर एक बार रेंडर होता है (सिंक्रोनस SQLite रीड + प्रति-सेशन कैश) और सेशन के बीच कभी नहीं बदलता — निर्माण से ही प्रीफ़िक्स-कैश स्थिर। सेशन-आंतरिक परिवर्तन केवल डिस्क + ऑडिट में स्थायी होते हैं।
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Consumer: memory tool Consumer: frozen snapshot (systemPrompt section, order -50)
|
|
56
|
+
add/replace/remove/query per-session freeze, budget-headed
|
|
57
|
+
│ writes (agent+callId) │ reads (sync, session cwd)
|
|
58
|
+
▼ ▼
|
|
59
|
+
Service Definition: ctx.memory — budgets/add/replace/remove/query/seed
|
|
60
|
+
every write: budget precheck → ctx.approval.request (approval waterfall) → budget recheck → persist → audit
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
Provider: lib/store.mjs — node:sqlite (WAL, 0600), entries + audit tables, unique-substring match
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 🧰 इंस्टॉल और अनइंस्टॉल
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile <name> add ./dsh-memento # local checkout (no build step)
|
|
70
|
+
dsh plugin --profile <name> add git+https://github.com/PerryLink/dsh-memento.git # GitHub इंस्टॉल; npm पहले release के बाद
|
|
71
|
+
dsh plugin --profile <name> remove dsh-memento # uninstall: DB + session logs are kept
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
अनइंस्टॉल के बाद मेमोरी डेटाबेस और वे सेशन लॉग, जिन्होंने मेमोरी गतिविधि रिकॉर्ड की थी, बचे रहते हैं; पुराने सेशन लोड होने योग्य बने रहते हैं।
|
|
75
|
+
|
|
76
|
+
## ⚙️ कॉन्फ़िगरेशन
|
|
77
|
+
|
|
78
|
+
हर फ़ील्ड एक मान्यीकृत Schemastery `Config` है; अमान्य मान लोड के समय ज़ोर से विफल होते हैं। cordis.yml में `memento` पंक्ति के अंतर्गत ओवरराइड करें।
|
|
79
|
+
|
|
80
|
+
| फ़ील्ड | डिफ़ॉल्ट | अर्थ |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `enabled` | `true` | `false` सेवा, टूल, स्नैपशॉट, कमांड, पैनल और उत्तरदाता को पूरी तरह हटा देता है (कोई अधूरी स्थिति नहीं) |
|
|
83
|
+
| `dbPath` | `''` → `$DSH_HOME/dsh-memento/memory.db` | निरपेक्ष, या `$DSH_HOME` के सापेक्ष |
|
|
84
|
+
| `budgets.user.userGlobal` / `budgets.user.workspace` | `2000` / `2000` | user ट्रैक की हर लेयर का कठोर वर्ण बजट |
|
|
85
|
+
| `budgets.agent.userGlobal` / `budgets.agent.workspace` | `4000` / `4000` | agent ट्रैक की हर लेयर का कठोर वर्ण बजट |
|
|
86
|
+
| `writePolicy` | `'ask'` | `'ask'` = उपयोगकर्ता अनुमोदन; `'auto'` = अनुमति दें (अनुमोदन स्रोत रिकॉर्ड किया गया); `'off'` = अस्वीकार करें। मॉडल-अदृश्य |
|
|
87
|
+
| `writePolicies` | `{}` | प्रति-ट्रैक/स्कोप या प्रति-स्रोत ओवरराइड: कुंजियाँ `user/workspace`, `agent/user-global`, `source:claude`, … → `ask`/`auto`/`off`; बेमेल `writePolicy` पर गिरता है |
|
|
88
|
+
| `language` | `'en'` | मॉडल-दृश्य पाठ और कमांड आउटपुट की भाषा: `'en'` (डिफ़ॉल्ट) या `'zh'` — टूल विवरण, फ्रोज़न स्नैपशॉट, `/memory` कमांड और वेब पैनल सभी इसका अनुसरण करते हैं |
|
|
89
|
+
| `snapshotOrder` | `-50` | स्नैपशॉट सेक्शन क्रम: harness आइडेंटिटी (`-100`) के बाद, persona (`0`) से पहले |
|
|
90
|
+
| `maxEntriesPerQuery` | `20` | प्रति-क्वेरी परिणाम की डिफ़ॉल्ट सीमा (स्पष्ट `limit` अनुमत, कठोर सीमा 1000) |
|
|
91
|
+
| `commandListLimit` | `50` | प्रति `/memory list` / `query` कमांड दिखाई गई प्रविष्टियाँ |
|
|
92
|
+
| `commandAuditLimit` | `10` | प्रति `/memory audit` कमांड दिखाई गई ऑडिट पंक्तियाँ |
|
|
93
|
+
| `recall.historyLimitDefault` / `recall.snippetCap` / `recall.snippetChars` / `recall.windowDays` | `8` / `5` / `300` / `30` | `memory_recall` इतिहास डिफ़ॉल्ट: स्कैन किए सेशन, प्रति सेशन स्निपेट, स्निपेट वर्ण, दिनों की विंडो |
|
|
94
|
+
| `panelEntriesLimit` | `200` | वेब पैनल प्रविष्टि पृष्ठ आकार (और सीमा) |
|
|
95
|
+
| `panelAuditLimit` | `20` | वेब पैनल ऑडिट पंक्तियाँ डिफ़ॉल्ट (सीमा 200) |
|
|
96
|
+
| `auditRetentionDays` | `0` | ऑडिट अवधारण: 0 = हमेशा, >0 = स्टोर खुलने पर पुरानी पंक्तियाँ हटाएँ |
|
|
97
|
+
| `proposals.enabled` / `proposals.maxChars` / `proposals.maxPending` | `true` / `2000` / `8` | ऑटो-कैप्चर: हर सफल कॉम्पैक्शन के बाद लंबित मेमोरी प्रस्ताव (काटा गया, प्रति सेशन एक); बंद करें या सीमाएँ बदलें |
|
|
98
|
+
|
|
99
|
+
## 🛠 टूल और सतहें
|
|
100
|
+
|
|
101
|
+
- **`memory`** — विवरण में अंतर्निहित Save/Skip मार्गदर्शन के साथ add/replace/remove/consolidate/query (उपयोगकर्ता प्राथमिकताएँ, सुधार, पर्यावरण तथ्य, परंपराएँ, सबक सहेजें; तुच्छ बातें, पुनः-व्युत्पन्न तथ्य, डंप, एक-बार के पथ छोड़ें)। लेखन अनुमोदन द्वार से गुज़रते हैं; पठन निःशुल्क हैं; replace/remove एक **यूनीक सबस्ट्रिंग** को लक्षित करते हैं (अस्पष्ट मिलान उम्मीदवार सूची के साथ विफल होते हैं); consolidate एक अनुमोदन और एक परमाणु लेखन से 1..20 प्रविष्टियों को एक में मिलाता है।
|
|
102
|
+
- **`memory_recall`** — दो-भाग रिकॉल: परिबद्ध मेमोरी मिलान **और साथ में** `ctx.sessionQuery` के माध्यम से हाल के सेशन-इतिहास मिलान (जहाँ सेवा अनुपस्थित हो वहाँ केवल-मेमोरी पर सहजता से गिरता है)।
|
|
103
|
+
- **`/memory`** — उपयोगकर्ता-ट्रिगर कमांड (मॉडल टर्न नहीं): `list` · `query <word>` · `add [--track=user|agent] [--scope=user-global|workspace] <text>` · `remove [flags] <substring>` · `consolidate [flags] <substring...> => <text>` · `proposals [approve|dismiss <id>]` · `budgets` · `audit` · `export`। कमांड लेखन उसी वॉटरफॉल + नीति से गुज़रते हैं; ऑडिट प्लगइन ऑडिट टेबल + `command/done` में दर्ज होता है। `export` रीड-ओनली है और सभी प्रविष्टियाँ + बजट एक JSON दस्तावेज़ के रूप में निकालता है (बैकअप / माइग्रेशन)।
|
|
104
|
+
- **ऑटो-कैप्चर प्रस्ताव** — सफल सेशन कॉम्पैक्शन के बाद सारांश एक लंबित मेमोरी प्रस्ताव (`agent/workspace`) बन जाता है; approve उसे अनुमोदन द्वार से लिखता है, dismiss उसे हटाता है। लंबित प्रस्ताव फ्रोज़न स्नैपशॉट और पैनल में दिखते हैं।
|
|
105
|
+
- **Web पैनल** — शून्य-बिल्ड `dsh.client` ड्रॉअर: ट्रैक/लेयर के अनुसार एंट्री ब्राउज़ करें, खोजें, बजट बार, ऑडिट टेल। डिज़ाइन से रीड-ओनली: लेखन और अनुमोदन `memory` टूल और बिल्ट-इन अनुमोदन UI के माध्यम से होते हैं।
|
|
106
|
+
|
|
107
|
+
## 🎓 टर्मिनल मेमोरियों से हमने क्या सीखा
|
|
108
|
+
|
|
109
|
+
dsh-memento Claude Code, Codex या Hermes का पोर्ट नहीं है — पर इसके डिज़ाइन ने जान-बूझकर उनका सही हिस्सा आत्मसात किया और नुकसानदेह हिस्सों को ठुकराया:
|
|
110
|
+
|
|
111
|
+
| टर्मिनल मेमोरी | उसने क्या सही किया | dsh-memento ने क्या अपनाया |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| **Claude Code** — `CLAUDE.md` | पदानुक्रमित **सादा-पाठ मेमोरी फ़ाइलें** (उपयोगकर्ता स्तर → प्रोजेक्ट स्तर), जिन्हें इंसान पढ़-संपादित कर सकता है, और हर सेशन में अपने-आप मर्ज होती हैं — ऐसी मेमोरी जिसे आप खुद पढ़ और ठीक कर सकते हैं | सादा-पाठ प्रविष्टियाँ; प्रति सेशन मर्ज होने वाली `user-global` / `workspace` लेयरें; एक स्टोर जिसे आप ब्राउज़, `export` और ऑडिट कर सकते हैं — पारदर्शिता ही फ़ीचर है |
|
|
114
|
+
| **Codex** — `AGENTS.md` | **प्रति-निर्देशिका स्कोप्ड निर्देश** अपने-आप खोजे और बिना किसी मॉडल-घर्षण के इंजेक्ट होते हैं — स्थानीयता मात्रा से बड़ी चीज़ है; मेमोरी "लोड" करने के लिए कोई टूल-कॉल नहीं चाहिए | सेशन के cwd से बँधी `workspace` लेयर (Windows में केस-इनसेंसिटिव); फ्रोज़न स्नैपशॉट सेशन शुरू होते ही अपने-आप इंजेक्ट होता है |
|
|
115
|
+
| **Hermes** — `memory.md` | **सक्रिय मेमोरी सेव** (save/update/delete) और [issue #48181](https://github.com/NousResearch/hermes-agent/issues/48181) की सुरक्षा सीख: केवल टूल लेयर पर लगाया गया द्वार देर से हुए टूल-इंजेक्शन से बायपास हो सकता है — द्वार वहाँ लगाओ जहाँ हर लेखन पथ मिलता है | स्पष्ट Save/Skip मार्गदर्शन वाला `memory` टूल + अनुमोदन-द्वारित ऑटो-कैप्चर प्रस्ताव; अनुमोदन द्वार **`ctx.memory` के लेखन मेथड्स के अंदर** रहता है, टूल लेयर में नहीं |
|
|
116
|
+
|
|
117
|
+
स्रोत: [Claude Code मेमोरी](https://code.claude.com/docs/en/memory) · [Codex AGENTS.md](https://developers.openai.com/codex/cli/agents-md) · [Hermes मेमोरी](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/memory.md) · [Hermes #48181](https://github.com/NousResearch/hermes-agent/issues/48181)।
|
|
118
|
+
|
|
119
|
+
और जिन हिस्सों को हमने जान-बूझकर ठुकराया: मॉडल के निजी स्टेट में छिपी ऑटो-समरीकरण (यहाँ कॉम्पैक्शन सारांश **लंबित प्रस्ताव** बनते हैं जो इंसानी approve/dismiss की प्रतीक्षा करते हैं), वेयरहाउस/वेक्टर-स्टोर महत्वाकांक्षाएँ, और ऐसा कोई भी लेखन जिसमें इंसान को दिखने वाला अनुमोदन या ऑडिट-ट्रेल न हो। साथ ही Hermes की दस्तावेज़ित चेतावनी अपनाई: एक ही home निर्देशिका साझा करने वाले दो प्रोसेस एक ही मेमोरी फ़ाइल लिखते हैं — सुरक्षा सीमाएँ देखें।
|
|
120
|
+
|
|
121
|
+
## 🆚 यह कैसे अलग है
|
|
122
|
+
|
|
123
|
+
| प्लगइन | यह क्या है | dsh-memento का अंतर |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| dsh-memory-evolve | मेमोरी वेयरहाउस / इवोल्यूशन लूप | एक टाइप्ड सेवा सीम, अनुमोदन द्वार, और सेशन-लॉग ऑडिट; कोई वेयरहाउस महत्वाकांक्षा नहीं |
|
|
126
|
+
| dsh-mnemon | मेमोरी स्टोर सहायक | प्रोटोकॉल + द्वार + ऑडिट, कोई और स्टोर नहीं |
|
|
127
|
+
| dsh-kb-sieve | नॉलेज-बेस छानना | कोई रिट्रीवल इंजीनियरिंग नहीं: छोटे-कॉर्पस सबस्ट्रिंग खोज, `session_search`/`sessionQuery` के माध्यम से क्रॉस-सेशन रिकॉल |
|
|
128
|
+
| dsh-tdai-memory | कार्य-चालित मेमोरी टूलिंग | बजट प्रति ट्रैक×लेयर होते हैं और सेवा में लागू होते हैं, बेस्ट-एफ़र्ट नहीं |
|
|
129
|
+
| claude-bridge | Claude Code ब्रिजिंग | DSH-नेटिव; भविष्य का `seed(source:'claude')` पथ ब्रिज को उसी स्टोर में फ़ीड करने देता है |
|
|
130
|
+
| dsh-external/Recall | बाहरी एजेंट मेमोरी | लोकल-फर्स्ट, शून्य-नेटवर्क, DSH के अपने अनुमोदन सीम पर चलता है |
|
|
131
|
+
| Official MCP memory examples | DSH की घोषित "memory = external MCP" स्थिति | **नेटिव फर्स्ट-पार्टी** पूरक: समान लक्ष्य, कोई बाहरी सर्वर नहीं; दोनों सह-अस्तित्व में रहते हैं |
|
|
132
|
+
|
|
133
|
+
नाम **`dsh-memento`** है (npm और GitHub पर निःशुल्क)। `dsh-recall` नहीं (dsh-external/Recall से भ्रमित होने वाला), और न ही हटाया गया पुराना नाम `dsh-memory`।
|
|
134
|
+
|
|
135
|
+
## 🔒 सुरक्षा सीमाएँ
|
|
136
|
+
|
|
137
|
+
- **केवल सार्वजनिक सेवाएँ** (`tools`, `systemPrompt`, अनुमोदन सीम)। कोई engine / agent-loop / apiproxy / official-UI परिवर्तन नहीं।
|
|
138
|
+
- **शून्य नेटवर्क, शून्य क्रेडेंशियल।** स्थानीय डेटाबेस; POSIX फ़ाइल मोड `0600`।
|
|
139
|
+
- **ज़ोर से विफल होता है।** दूषित DB या नया schema लोड पर विफल होता है; भरे हुए बजट और अस्पष्ट सबस्ट्रिंग मिलान संरचित त्रुटियों के साथ विफल होते हैं। कुछ भी चुपचाप निगला या काटा नहीं जाता।
|
|
140
|
+
- **एक प्रोसेस, एक स्टोर।** एक प्रोसेस में कई सेशन SQLite स्टोर साझा करते हैं (क्रमबद्ध लेखन, प्रति-सेशन ऑडिट)। एक ही `$DSH_HOME` साझा करने वाली दो **प्रोसेस** एक ही फ़ाइल लिखती हैं: SQLite लॉकिंग के तहत last-writer-wins — यदि आपको क्रॉस-प्रोसेस स्थिरता चाहिए तो एक `$DSH_HOME` पर दो harness इंस्टेंस न चलाएँ (वही चेतावनी जो Hermes प्रोजेक्ट दस्तावेज़ित करता है)।
|
|
141
|
+
|
|
142
|
+
## ⚠️ ज्ञात सीमाएँ
|
|
143
|
+
|
|
144
|
+
- **सेशन ईवेंट शब्दावली घोषित है, अभी उत्सर्जित नहीं (rc.6)।** `memory/added|updated|removed|recalled|snapshot` `types.d.ts` में merge-घोषित हैं, लेकिन rc.6 में रेपो-बाह्य ईवेंट प्रकारों के लिए कोई पंजीकरण सतह नहीं है (अपंजीकृत append स्थायी सेशन को अनलोड-अयोग्य बना देते)। ऑडिट पूर्णता अनुमोदन जोड़ी + ऑडिट टेबल से आती है; जैसे ही कोई harness बिल्ड प्रकारों को पंजीकृत करता है, उत्सर्जन स्वतः चालू हो जाता है। देखें [ARCHITECTURE.md](ARCHITECTURE.md) निर्णय 4।
|
|
145
|
+
- **`ask` नीति को एक उत्तरदाता चाहिए।** कोई UI/ACP उत्तरदाता रचित न होने पर, लेखन बंद-स्थिति में विफल होते हैं (`unavailable`) — डिज़ाइन से, अनुमोदन सीम का fail-closed रुख।
|
|
146
|
+
- **कोई FTS5 इंडेक्स नहीं।** सबस्ट्रिंग खोज केस-इनसेंसिटिव `instr` से चलती है (CJK के लिए सही); रिकॉल रैंकिंग प्रति-एंट्री हिट गणना का उपयोग करती है। FTS5 का trigram टोकनाइज़र एकल-वर्ण CJK वर्णों को इंडेक्स नहीं कर सकता, इसलिए इसका उपयोग नहीं होता — देखें [ARCHITECTURE.md](ARCHITECTURE.md) निर्णय 10।
|
|
147
|
+
|
|
148
|
+
## 🧪 विकास
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
npm install
|
|
152
|
+
npm test # node --test: 103 tests — budget, unique-substring, gate policy, store, snapshot, mock-ctx integration (S2/S3 invariants), V2 command/recall/panel
|
|
153
|
+
npm run typecheck # index.mjs / lib / scripts पर tsc --checkJs द्वार
|
|
154
|
+
npm run check:coverage # लाइन-कवरेज द्वार: lib ≥90%, index.mjs ≥85%, सभी ≥90%
|
|
155
|
+
npm run check:readmes # पाँच-भाषा README संगति द्वार
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`lib/` शून्य-DSH-निर्भरता है (केवल node: बिल्ट-इन); DSH आयात केवल `index.mjs` में मौजूद हैं। पूर्ण अनुशासन [AGENTS.md](AGENTS.md) में; डिज़ाइन निर्णय [ARCHITECTURE.md](ARCHITECTURE.md) में।
|
|
159
|
+
|
|
160
|
+
## 🏷 विषय
|
|
161
|
+
|
|
162
|
+
सुझाए गए GitHub विषय: `dsh` · `dsh-plugin` · `deepseek-harness` · `memory` · `agent-memory` · `approval` · `audit` · `sqlite` · `cordis` · `llm`
|
|
163
|
+
|
|
164
|
+
## 📄 लाइसेंस
|
|
165
|
+
|
|
166
|
+
Apache License 2.0 — देखें [LICENSE](LICENSE)। कोई तृतीय-पक्ष कोड पुनर्वितरित नहीं किया जाता; देखें [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)।
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# dsh-memento
|
|
2
|
+
|
|
3
|
+
**Bounded, layered, approval-gated, auditable cross-session memory for DeepSeek Harness.**
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/@deepseek-ai/dsh)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
10
|
+
|
|
11
|
+
[English](README.md) · [中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
12
|
+
|
|
13
|
+
> Other memory plugins sell a **warehouse**. dsh-memento sells the **seam**: a typed `ctx.memory` service, a write approval gate no model path can bypass, and audit trails you can rebuild from the session log. Native-first memory for DeepSeek Harness — protocol + trust gate + audit, with zero network and zero credentials.
|
|
14
|
+
|
|
15
|
+
## ✨ Why dsh-memento?
|
|
16
|
+
|
|
17
|
+
- **It's a capability seam, not another store.** Service Definition (`ctx.memory`), local SQLite Provider (`node:sqlite`, WAL, `0600`), and Consumers (`memory` tool + frozen snapshot injection). Any future plugin — a `dsh-claude-move` seed integration, a bridge, a panel — feeds and reads the **same store through the same gate**.
|
|
18
|
+
- **The gate cannot be bypassed.** Every write path (`add`/`replace`/`remove`/`seed`) is forced through the approval waterfall **inside the service**, not in the tool layer. `writePolicy: ask | auto | off` is configuration the model can neither see nor change; a session-level `never` stance still pre-empts everything.
|
|
19
|
+
- **Model-visible ⟺ logged.** The injected snapshot lands verbatim in `request/header.system`; every write is reconstructable from `approval/asked` (full payload) + `approval/decided` (outcome) + the plugin's own audit table.
|
|
20
|
+
- **Bounded and honest.** Hard per-track/per-layer character budgets (default user 2000 / agent 4000). A full store **fails with a structured error** (usage + limit) — the model consolidates and retries. Never truncated, never auto-compacted.
|
|
21
|
+
|
|
22
|
+
## ⚡ Quick start
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# requires Node ^22.19 || >=24 and DSH 0.1.0-rc.6
|
|
26
|
+
dsh plugin --profile web add dsh-memento # or ./dsh-memento / a tarball / a GitHub URL
|
|
27
|
+
dsh --profile web --dump-config # expect a "# == dsh-memento" layer, no FAILED at startup
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then, in the Web UI: ask the model to remember something → approve the write → start a **new session** and ask what it remembers. That's the whole demo.
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
# optional override in the profile's cordis.patch.yml
|
|
34
|
+
- id: memento
|
|
35
|
+
config:
|
|
36
|
+
writePolicy: ask # ask (default) | auto | off — model-invisible
|
|
37
|
+
budgets:
|
|
38
|
+
user: { userGlobal: 4000, workspace: 2000 } # Chinese-heavy memory: raise + note why
|
|
39
|
+
agent: { userGlobal: 4000, workspace: 4000 }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🧠 What it does
|
|
43
|
+
|
|
44
|
+
| | Component | What you get |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| 🧩 Service Definition | `ctx.memory` — `add` / `replace` / `remove` / `query` / `seed` / `budgets()` | Typed, merge-declared service; write methods enforce the gate internally |
|
|
47
|
+
| 💾 Provider | `lib/store.mjs` — `node:sqlite` single file (`$DSH_HOME/dsh-memento/memory.db`, WAL) | Zero dependencies, zero network; entry + audit tables; unique-substring match |
|
|
48
|
+
| 🛠 Consumers | `memory` tool · frozen snapshot injection (system-prompt section, order `-50`) · `memory_recall` tool · `/memory` command · read-only Web panel | Model-facing writes/reads, budget-headed frozen snapshot, two-part recall, user-side command, browser drawer |
|
|
49
|
+
|
|
50
|
+
**Two tracks × two layers × per-agent key.** `user` track = facts about the user (preferences, communication style, landmines); `agent` track = environment facts, project conventions, lessons learned. Each track has `user-global` (cross-workspace) and `workspace` (per-session cwd) layers — Codex-style merged layering, not Hermes-style global-only. A third dimension isolates entries by the session's `agentPreset` (per-agent scope); entries without a preset stay in the shared layer visible to everyone.
|
|
51
|
+
|
|
52
|
+
**Frozen snapshots.** The snapshot is rendered once per session at first prompt assembly (synchronous SQLite read + per-session cache) and never changes mid-session — prefix-cache stable by construction. Session-internal changes persist to disk + audit only.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Consumer: memory tool Consumer: frozen snapshot (systemPrompt section, order -50)
|
|
56
|
+
add/replace/remove/query per-session freeze, budget-headed
|
|
57
|
+
│ writes (agent+callId) │ reads (sync, session cwd)
|
|
58
|
+
▼ ▼
|
|
59
|
+
Service Definition: ctx.memory — budgets/add/replace/remove/query/seed
|
|
60
|
+
every write: budget precheck → ctx.approval.request (approval waterfall) → budget recheck → persist → audit
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
Provider: lib/store.mjs — node:sqlite (WAL, 0600), entries + audit tables, unique-substring match
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 🧰 Install & uninstall
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile <name> add ./dsh-memento # local checkout (no build step)
|
|
70
|
+
dsh plugin --profile <name> add git+https://github.com/PerryLink/dsh-memento.git # GitHub install; npm after first release
|
|
71
|
+
dsh plugin --profile <name> remove dsh-memento # uninstall: DB + session logs are kept
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
After uninstall the memory database and the session logs that recorded memory activity remain; old sessions stay loadable.
|
|
75
|
+
|
|
76
|
+
## ⚙️ Configuration
|
|
77
|
+
|
|
78
|
+
Every field is a validated Schemastery `Config`; invalid values fail loudly at load. Override in cordis.yml under the `memento` row.
|
|
79
|
+
|
|
80
|
+
| Field | Default | Meaning |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `enabled` | `true` | `false` removes the service, tools, snapshot, command, panel, and answerer entirely (no half-state) |
|
|
83
|
+
| `dbPath` | `''` → `$DSH_HOME/dsh-memento/memory.db` | absolute, or relative to `$DSH_HOME` |
|
|
84
|
+
| `budgets.user.userGlobal` / `budgets.user.workspace` | `2000` / `2000` | hard char budget per layer of the user track |
|
|
85
|
+
| `budgets.agent.userGlobal` / `budgets.agent.workspace` | `4000` / `4000` | hard char budget per layer of the agent track |
|
|
86
|
+
| `writePolicy` | `'ask'` | `'ask'` = user approval; `'auto'` = allow through (approval source recorded); `'off'` = reject. Model-invisible |
|
|
87
|
+
| `writePolicies` | `{}` | per-track/scope or per-source overrides: keys `user/workspace`, `agent/user-global`, `source:claude`, … → `ask`/`auto`/`off`; unmatched falls back to `writePolicy` |
|
|
88
|
+
| `language` | `'en'` | model-visible text and command output language: `'en'` (default) or `'zh'` — tool descriptions, frozen snapshot, `/memory` command, and web panel all follow it |
|
|
89
|
+
| `snapshotOrder` | `-50` | snapshot section order: after harness identity (`-100`), before persona (`0`) |
|
|
90
|
+
| `maxEntriesPerQuery` | `20` | default per-query result cap (explicit `limit` allowed, hard-capped at 1000) |
|
|
91
|
+
| `commandListLimit` | `50` | entries rendered per `/memory list` / `query` command |
|
|
92
|
+
| `commandAuditLimit` | `10` | audit rows rendered per `/memory audit` command |
|
|
93
|
+
| `recall.historyLimitDefault` / `recall.snippetCap` / `recall.snippetChars` / `recall.windowDays` | `8` / `5` / `300` / `30` | `memory_recall` history defaults: sessions scanned, snippets per session, snippet chars, recency window in days |
|
|
94
|
+
| `panelEntriesLimit` | `200` | web panel entries page size (and clamp) |
|
|
95
|
+
| `panelAuditLimit` | `20` | web panel audit rows by default (ceiling 200) |
|
|
96
|
+
| `auditRetentionDays` | `0` | audit retention: 0 = keep forever, >0 = prune rows older than N days at store open |
|
|
97
|
+
| `proposals.enabled` / `proposals.maxChars` / `proposals.maxPending` | `true` / `2000` / `8` | auto-capture: pending memory proposal after each successful compaction (truncated, one per session); disable or tune caps |
|
|
98
|
+
|
|
99
|
+
## 🛠 Tools & surfaces
|
|
100
|
+
|
|
101
|
+
- **`memory`** — add/replace/remove/consolidate/query with Save/Skip guidance embedded in the description (save user preferences, corrections, environment facts, conventions, lessons; skip trivia, re-derivable facts, dumps, one-off paths). Writes ride the approval gate; reads are free; replace/remove target a **unique substring** (ambiguous matches fail with the candidate list); consolidate merges 1..20 entries into one with a single approval and one atomic write.
|
|
102
|
+
- **`memory_recall`** — two-part recall: bounded memory matches **plus** recent session-history matches via `ctx.sessionQuery` (degrades gracefully to memory-only where the service is absent).
|
|
103
|
+
- **`/memory`** — user-triggered command (not a model turn): `list` · `query <word>` · `add [--track=user|agent] [--scope=user-global|workspace] <text>` · `remove [flags] <substring>` · `consolidate [flags] <substring...> => <text>` · `proposals [approve|dismiss <id>]` · `budgets` · `audit` · `export`. Command writes ride the same waterfall + policy; audit lands in the plugin audit table + `command/done`. `export` is read-only and dumps all entries + budgets as one JSON document (backup / migration).
|
|
104
|
+
- **Auto-capture proposals** — after a successful session compaction, the summary lands as a pending memory proposal (`agent/workspace`); approving writes it through the approval gate, dismissing drops it. Pending proposals appear in the frozen snapshot and the panel.
|
|
105
|
+
- **Web panel** — zero-build `dsh.client` drawer: browse entries by track/layer, search, budget bars, audit tail. Read-only by design: writes and approval happen through the `memory` tool and the built-in approval UI.
|
|
106
|
+
|
|
107
|
+
## 🎓 What we learned from the terminal memories
|
|
108
|
+
|
|
109
|
+
dsh-memento is not a port of Claude Code, Codex, or Hermes — but its design deliberately absorbed the parts each of them got right, and refused the parts that hurt:
|
|
110
|
+
|
|
111
|
+
| Terminal memory | What it got right | What dsh-memento adopted |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| **Claude Code** — `CLAUDE.md` | hierarchical **plain-text memory files** (user-level → project-level) that are human-readable, human-editable, and merged automatically into every session — memory you can read and fix yourself | plain-text entries; `user-global` / `workspace` layers merged per session; a store you can browse, `export`, and audit — transparency as a feature |
|
|
114
|
+
| **Codex** — `AGENTS.md` | **per-directory scoped instructions** auto-discovered and injected with zero model friction — locality beats volume, no tool call needed to "load" memory | `workspace` layer keyed by the session's cwd (Windows case-insensitive); the frozen snapshot is injected automatically at session start |
|
|
115
|
+
| **Hermes** — `memory.md` | **proactive memory saves** (save/update/delete) and, in [issue #48181](https://github.com/NousResearch/hermes-agent/issues/48181), the security lesson that a gate enforced only in the tool layer is bypassable by late tool injection — enforce it where every write path meets | the `memory` tool with explicit Save/Skip guidance + approval-gated auto-capture proposals; the approval gate lives **inside** `ctx.memory`'s write methods, not in the tool layer |
|
|
116
|
+
|
|
117
|
+
Sources: [Claude Code memory](https://code.claude.com/docs/en/memory) · [Codex AGENTS.md](https://developers.openai.com/codex/cli/agents-md) · [Hermes memory](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/memory.md) · [Hermes #48181](https://github.com/NousResearch/hermes-agent/issues/48181).
|
|
118
|
+
|
|
119
|
+
And the parts we deliberately refused: hidden auto-summarization into model-private state (compaction summaries here become **pending proposals** that wait for a human approve/dismiss), warehouse/vector-store ambitions, and any write that lacks a human-visible approval or audit trail. Also adopted: Hermes's documented caveat that two processes sharing one home directory write the same memory file — see Security boundaries.
|
|
120
|
+
|
|
121
|
+
## 🆚 How it's different
|
|
122
|
+
|
|
123
|
+
| Plugin | What it is | dsh-memento's difference |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| dsh-memory-evolve | memory warehouse / evolution loops | a typed service seam, approval gate, and session-log audit; no warehouse ambition |
|
|
126
|
+
| dsh-mnemon | memory store helper | protocol + gate + audit, not another store |
|
|
127
|
+
| dsh-kb-sieve | knowledge-base sieving | no retrieval engineering: small-corpus substring search, cross-session recall via `session_search`/`sessionQuery` |
|
|
128
|
+
| dsh-tdai-memory | task-driven memory tooling | budgets are per track×layer and enforced in the service, not best-effort |
|
|
129
|
+
| claude-bridge | Claude Code bridging | DSH-native; a future `seed(source:'claude')` path lets a bridge feed the same store |
|
|
130
|
+
| dsh-external/Recall | external agent memory | local-first, zero-network, rides DSH's own approval seam |
|
|
131
|
+
| Official MCP memory examples | DSH's stated "memory = external MCP" position | the **native first-party** complement: same goal, no external server; both coexist |
|
|
132
|
+
|
|
133
|
+
The name is **`dsh-memento`** (free on npm and GitHub). Not `dsh-recall` (confusable with dsh-external/Recall), not the deleted legacy name `dsh-memory`.
|
|
134
|
+
|
|
135
|
+
## 🔒 Security boundaries
|
|
136
|
+
|
|
137
|
+
- **Public services only** (`tools`, `systemPrompt`, the approval seam). No engine / agent-loop / apiproxy / official-UI changes.
|
|
138
|
+
- **Zero network, zero credentials.** Local database; POSIX file mode `0600`.
|
|
139
|
+
- **Fail loud.** Corrupt DB or newer schema fails at load; full budgets and ambiguous substring matches fail with structured errors. Nothing silently swallowed or truncated.
|
|
140
|
+
- **One process, one store.** Multiple sessions in one process share the SQLite store (serialized writes, per-session audit). Two **processes** sharing one `$DSH_HOME` write the same file: last-writer-wins under SQLite locking — don't run two harness instances on one `$DSH_HOME` if you need cross-process consistency (same caveat the Hermes project documents).
|
|
141
|
+
|
|
142
|
+
## ⚠️ Known limitations
|
|
143
|
+
|
|
144
|
+
- **Session events vocabulary is declared, not yet emitted (rc.6).** `memory/added|updated|removed|recalled|snapshot` are merge-declared in `types.d.ts`, but rc.6 has no registration surface for out-of-repo event types (unregistered appends would make persisted sessions unloadable). Audit completeness comes from the approval pair + the audit table; emission turns on automatically once a harness build registers the types. See [ARCHITECTURE.md](ARCHITECTURE.md) decision 4.
|
|
145
|
+
- **`ask` policy needs an answerer.** With no UI/ACP answerer composed, writes fail closed (`unavailable`) — by design, the approval seam's fail-closed stance.
|
|
146
|
+
- **No FTS5 indexing.** Substring search runs on case-insensitive `instr` (correct for CJK); recall ranking uses per-entry hit counts. FTS5's trigram tokenizer cannot index single-character CJK tokens, so it is not used — see [ARCHITECTURE.md](ARCHITECTURE.md) decision 10.
|
|
147
|
+
|
|
148
|
+
## 🧪 Development
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
npm install
|
|
152
|
+
npm test # node --test: 103 tests — budget, unique-substring, gate policy, store, snapshot, mock-ctx integration (S2/S3 invariants), V2 command/recall/panel
|
|
153
|
+
npm run typecheck # tsc --checkJs gate over index.mjs / lib / scripts
|
|
154
|
+
npm run check:coverage # line-coverage gate: lib ≥90%, index.mjs ≥85%, all files ≥90%
|
|
155
|
+
npm run check:readmes # five-language README consistency gate
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`lib/` is zero-DSH-dependency (node: builtins only); DSH imports exist only in `index.mjs`. Full discipline in [AGENTS.md](AGENTS.md); design decisions in [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
159
|
+
|
|
160
|
+
## 🏷 Topics
|
|
161
|
+
|
|
162
|
+
Suggested GitHub topics: `dsh` · `dsh-plugin` · `deepseek-harness` · `memory` · `agent-memory` · `approval` · `audit` · `sqlite` · `cordis` · `llm`
|
|
163
|
+
|
|
164
|
+
## 📄 License
|
|
165
|
+
|
|
166
|
+
Apache License 2.0 — see [LICENSE](LICENSE). No third-party code is redistributed; see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
package/README.pt.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# dsh-memento
|
|
2
|
+
|
|
3
|
+
**Memória entre sessões limitada, em camadas, protegida por aprovação e auditável para o DeepSeek Harness.**
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/@deepseek-ai/dsh)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
10
|
+
|
|
11
|
+
[English](README.md) · [中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
12
|
+
|
|
13
|
+
> Outros plugins de memória vendem um **armazém**. O dsh-memento vende a **emenda (seam)**: um serviço tipado `ctx.memory`, um portão de aprovação de escrita que nenhum caminho de modelo pode contornar e trilhas de auditoria que você pode reconstruir a partir do log da sessão. Memória nativa em primeiro lugar para o DeepSeek Harness — protocolo + portão de confiança + auditoria, com zero rede e zero credenciais.
|
|
14
|
+
|
|
15
|
+
## ✨ Por que dsh-memento?
|
|
16
|
+
|
|
17
|
+
- **É uma emenda de capacidade, não mais um armazenamento.** Service Definition (`ctx.memory`), Provider local em SQLite (`node:sqlite`, WAL, `0600`) e Consumers (ferramenta `memory` + injeção de snapshot congelado). Qualquer plugin futuro — uma integração de semente `dsh-claude-move`, uma ponte, um painel — alimenta e lê o **mesmo armazenamento através do mesmo portão**.
|
|
18
|
+
- **O portão não pode ser contornado.** Todo caminho de escrita (`add`/`replace`/`remove`/`seed`) é forçado pela cascata de aprovação **dentro do serviço**, não na camada da ferramenta. `writePolicy: ask | auto | off` é uma configuração que o modelo não pode ver nem alterar; uma postura `never` em nível de sessão ainda antecipa tudo.
|
|
19
|
+
- **Visível ao modelo ⟺ registrado em log.** O snapshot injetado cai literalmente em `request/header.system`; toda escrita é reconstruível a partir de `approval/asked` (carga completa) + `approval/decided` (resultado) + a própria tabela de auditoria do plugin.
|
|
20
|
+
- **Limitado e honesto.** Orçamentos rígidos de caracteres por trilha/camada (padrão usuário 2000 / agente 4000). Um armazenamento cheio **falha com um erro estruturado** (uso + limite) — o modelo consolida e tenta novamente. Nunca truncado, nunca auto-compactado.
|
|
21
|
+
|
|
22
|
+
## ⚡ Início rápido
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# requer Node ^22.19 || >=24 e DSH 0.1.0-rc.6
|
|
26
|
+
dsh plugin --profile web add dsh-memento # ou ./dsh-memento / um tarball / uma URL do GitHub
|
|
27
|
+
dsh --profile web --dump-config # espere uma camada "# == dsh-memento", sem FAILED na inicialização
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Depois, na Web UI: peça ao modelo para lembrar algo → aprove a escrita → inicie uma **nova sessão** e pergunte o que ele lembra. Essa é a demonstração inteira.
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
# substituição opcional no cordis.patch.yml do perfil
|
|
34
|
+
- id: memento
|
|
35
|
+
config:
|
|
36
|
+
writePolicy: ask # ask (padrão) | auto | off — invisível ao modelo
|
|
37
|
+
budgets:
|
|
38
|
+
user: { userGlobal: 4000, workspace: 2000 } # memória com muito chinês: aumente + anote o porquê
|
|
39
|
+
agent: { userGlobal: 4000, workspace: 4000 }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🧠 O que ele faz
|
|
43
|
+
|
|
44
|
+
| | Componente | O que você recebe |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| 🧩 Service Definition | `ctx.memory` — `add` / `replace` / `remove` / `query` / `seed` / `budgets()` | Serviço tipado, declarado por merge; os métodos de escrita impõem o portão internamente |
|
|
47
|
+
| 💾 Provider | `lib/store.mjs` — `node:sqlite` arquivo único (`$DSH_HOME/dsh-memento/memory.db`, WAL) | Zero dependências, zero rede; tabelas de entrada + auditoria; correspondência por substring única |
|
|
48
|
+
| 🛠 Consumers | ferramenta `memory` · injeção de snapshot congelado (seção de system-prompt, ordem `-50`) · ferramenta `memory_recall` · comando `/memory` · painel Web somente leitura | Escritas/leituras voltadas ao modelo, snapshot congelado com cabeçalho de orçamento, recuperação em duas partes, comando do usuário, gaveta do navegador |
|
|
49
|
+
|
|
50
|
+
**Duas trilhas × duas camadas × chave por agente.** Trilha `user` = fatos sobre o usuário (preferências, estilo de comunicação, pontos sensíveis); trilha `agent` = fatos do ambiente, convenções do projeto, lições aprendidas. Cada trilha tem camadas `user-global` (entre workspaces) e `workspace` (cwd por sessão) — camadas mescladas no estilo Codex, não global-apenas no estilo Hermes. Uma terceira dimensão isola entradas pelo `agentPreset` da sessão (escopo por agente); entradas sem preset ficam na camada compartilhada visível para todos.
|
|
51
|
+
|
|
52
|
+
**Snapshots congelados.** O snapshot é renderizado uma vez por sessão na primeira montagem do prompt (leitura síncrona do SQLite + cache por sessão) e nunca muda no meio da sessão — estável por cache de prefixo por construção. Mudanças internas da sessão persistem apenas em disco + auditoria.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Consumer: memory tool Consumer: frozen snapshot (systemPrompt section, order -50)
|
|
56
|
+
add/replace/remove/query per-session freeze, budget-headed
|
|
57
|
+
│ writes (agent+callId) │ reads (sync, session cwd)
|
|
58
|
+
▼ ▼
|
|
59
|
+
Service Definition: ctx.memory — budgets/add/replace/remove/query/seed
|
|
60
|
+
every write: budget precheck → ctx.approval.request (approval waterfall) → budget recheck → persist → audit
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
Provider: lib/store.mjs — node:sqlite (WAL, 0600), entries + audit tables, unique-substring match
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 🧰 Instalar e desinstalar
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile <name> add ./dsh-memento # checkout local (sem etapa de build)
|
|
70
|
+
dsh plugin --profile <name> add git+https://github.com/PerryLink/dsh-memento.git # GitHub; npm após o primeiro release
|
|
71
|
+
dsh plugin --profile <name> remove dsh-memento # desinstalar: o BD + os logs de sessão são mantidos
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Após desinstalar, o banco de dados de memória e os logs de sessão que registraram a atividade de memória permanecem; sessões antigas continuam carregáveis.
|
|
75
|
+
|
|
76
|
+
## ⚙️ Configuração
|
|
77
|
+
|
|
78
|
+
Todo campo é um `Config` Schemastery validado; valores inválidos falham ruidosamente no carregamento. Substitua no cordis.yml sob a linha `memento`.
|
|
79
|
+
|
|
80
|
+
| Campo | Padrão | Significado |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `enabled` | `true` | `false` remove o serviço, as ferramentas, o snapshot, o comando, o painel e o answerer por completo (sem estado parcial) |
|
|
83
|
+
| `dbPath` | `''` → `$DSH_HOME/dsh-memento/memory.db` | absoluto, ou relativo a `$DSH_HOME` |
|
|
84
|
+
| `budgets.user.userGlobal` / `budgets.user.workspace` | `2000` / `2000` | orçamento rígido de caracteres por camada da trilha user |
|
|
85
|
+
| `budgets.agent.userGlobal` / `budgets.agent.workspace` | `4000` / `4000` | orçamento rígido de caracteres por camada da trilha agent |
|
|
86
|
+
| `writePolicy` | `'ask'` | `'ask'` = aprovação do usuário; `'auto'` = permite passar (fonte da aprovação registrada); `'off'` = rejeita. Invisível ao modelo |
|
|
87
|
+
| `writePolicies` | `{}` | substituições por trilha/camada ou por fonte: chaves `user/workspace`, `agent/user-global`, `source:claude`, … → `ask`/`auto`/`off`; sem correspondência cai para `writePolicy` |
|
|
88
|
+
| `language` | `'en'` | idioma do texto visível ao modelo e da saída do comando: `'en'` (padrão) ou `'zh'` — descrições de ferramentas, snapshot congelado, comando `/memory` e painel web o seguem |
|
|
89
|
+
| `snapshotOrder` | `-50` | ordem da seção do snapshot: depois da identidade do harness (`-100`), antes da persona (`0`) |
|
|
90
|
+
| `maxEntriesPerQuery` | `20` | limite padrão de resultados por consulta (`limit` explícito permitido, teto rígido 1000) |
|
|
91
|
+
| `commandListLimit` | `50` | entradas exibidas por comando `/memory list` / `query` |
|
|
92
|
+
| `commandAuditLimit` | `10` | linhas de auditoria exibidas por comando `/memory audit` |
|
|
93
|
+
| `recall.historyLimitDefault` / `recall.snippetCap` / `recall.snippetChars` / `recall.windowDays` | `8` / `5` / `300` / `30` | padrões de histórico do `memory_recall`: sessões escaneadas, trechos por sessão, caracteres por trecho, janela em dias |
|
|
94
|
+
| `panelEntriesLimit` | `200` | tamanho da página de entradas do painel web (e teto) |
|
|
95
|
+
| `panelAuditLimit` | `20` | linhas de auditoria do painel web por padrão (teto 200) |
|
|
96
|
+
| `auditRetentionDays` | `0` | retenção de auditoria: 0 = para sempre, >0 = poda ao abrir a loja |
|
|
97
|
+
| `proposals.enabled` / `proposals.maxChars` / `proposals.maxPending` | `true` / `2000` / `8` | auto-captura: proposta de memória pendente após cada compactação bem-sucedida (truncada, uma por sessão); desativar ou ajustar limites |
|
|
98
|
+
|
|
99
|
+
## 🛠 Ferramentas e superfícies
|
|
100
|
+
|
|
101
|
+
- **`memory`** — add/replace/remove/consolidate/query com orientação de Salvar/Pular embutida na descrição (salve preferências do usuário, correções, fatos do ambiente, convenções, lições; pule trivialidades, fatos rederiváveis, despejos, caminhos de uso único). Escritas passam pelo portão de aprovação; leituras são livres; replace/remove miram uma **substring única** (correspondências ambíguas falham com a lista de candidatos); consolidate mescla 1..20 entradas em uma com uma única aprovação e uma escrita atômica.
|
|
102
|
+
- **`memory_recall`** — recuperação em duas partes: correspondências de memória limitadas **mais** correspondências recentes do histórico da sessão via `ctx.sessionQuery` (degrada graciosamente para somente memória onde o serviço está ausente).
|
|
103
|
+
- **`/memory`** — comando acionado pelo usuário (não um turno do modelo): `list` · `query <word>` · `add [--track=user|agent] [--scope=user-global|workspace] <text>` · `remove [flags] <substring>` · `consolidate [flags] <substring...> => <text>` · `proposals [approve|dismiss <id>]` · `budgets` · `audit` · `export`. Escritas por comando passam pela mesma cascata + política; a auditoria cai na tabela de auditoria do plugin + `command/done`. `export` é somente leitura e despeja todas as entradas + orçamentos como um documento JSON (backup / migração).
|
|
104
|
+
- **Propostas auto-capturadas** — após uma compactação de sessão bem-sucedida, o resumo vira uma proposta de memória pendente (`agent/workspace`); aprovar a escreve pelo portão de aprovação, descartar a remove. Propostas pendentes aparecem no snapshot congelado e no painel.
|
|
105
|
+
- **Painel Web** — gaveta `dsh.client` sem build: navegue pelas entradas por trilha/camada, pesquise, veja barras de orçamento e o fim da auditoria. Somente leitura por design: escritas e aprovação acontecem pela ferramenta `memory` e pela UI de aprovação embutida.
|
|
106
|
+
|
|
107
|
+
## 🎓 O que aprendemos com as memórias de terminal
|
|
108
|
+
|
|
109
|
+
dsh-memento não é um port do Claude Code, do Codex ou do Hermes — mas seu design absorveu deliberadamente as partes que cada um acertou e recusou as partes que machucam:
|
|
110
|
+
|
|
111
|
+
| Memória de terminal | O que acertou | O que o dsh-memento adotou |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| **Claude Code** — `CLAUDE.md` | **arquivos de memória em texto puro** hierárquicos (nível usuário → nível projeto), legíveis e editáveis por humanos, e mesclados automaticamente a cada sessão — memória que você mesmo pode ler e corrigir | entradas em texto puro; camadas `user-global` / `workspace` mescladas por sessão; um armazenamento que você pode navegar, `export`ar e auditar — transparência como recurso |
|
|
114
|
+
| **Codex** — `AGENTS.md` | **instruções com escopo por diretório** autodescobertas e injetadas sem fricção do modelo — localidade vale mais que volume; nenhuma chamada de ferramenta é necessária para "carregar" memória | camada `workspace` vinculada ao cwd da sessão (insensível a maiúsculas no Windows); o snapshot congelado é injetado automaticamente no início da sessão |
|
|
115
|
+
| **Hermes** — `memory.md` | **gravações de memória proativas** (salvar/atualizar/apagar) e, na [issue #48181](https://github.com/NousResearch/hermes-agent/issues/48181), a lição de segurança de que um portão imposto apenas na camada de ferramentas é contornável por injeção tardia de ferramentas — imponha-o onde todas as rotas de escrita convergem | a ferramenta `memory` com orientação explícita de Salvar/Pular + propostas de auto-captura com portão de aprovação; o portão de aprovação vive **dentro** dos métodos de escrita de `ctx.memory`, não na camada de ferramentas |
|
|
116
|
+
|
|
117
|
+
Fontes: [memória do Claude Code](https://code.claude.com/docs/en/memory) · [AGENTS.md do Codex](https://developers.openai.com/codex/cli/agents-md) · [memória do Hermes](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/memory.md) · [Hermes #48181](https://github.com/NousResearch/hermes-agent/issues/48181).
|
|
118
|
+
|
|
119
|
+
E as partes que recusamos deliberadamente: auto-resumir de forma oculta para estado privado do modelo (aqui os resumos de compactação viram **propostas pendentes** que aguardam um aprovar/descartar humano), ambições de armazém/vetorial, e qualquer escrita sem aprovação ou trilha de auditoria visível ao humano. Também adotamos a ressalva documentada do Hermes: dois processos compartilhando um diretório home escrevem o mesmo arquivo de memória — veja Limites de segurança.
|
|
120
|
+
|
|
121
|
+
## 🆚 Como ele é diferente
|
|
122
|
+
|
|
123
|
+
| Plugin | O que é | A diferença do dsh-memento |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| dsh-memory-evolve | armazém de memória / loops de evolução | uma emenda de serviço tipada, portão de aprovação e auditoria de log de sessão; sem ambição de armazém |
|
|
126
|
+
| dsh-mnemon | helper de armazenamento de memória | protocolo + portão + auditoria, não mais um armazenamento |
|
|
127
|
+
| dsh-kb-sieve | peneiramento de base de conhecimento | sem engenharia de recuperação: busca por substring em corpus pequeno, recuperação entre sessões via `session_search`/`sessionQuery` |
|
|
128
|
+
| dsh-tdai-memory | ferramentas de memória orientadas a tarefas | orçamentos são por trilha×camada e impostos no serviço, não best-effort |
|
|
129
|
+
| claude-bridge | ponte para o Claude Code | nativo de DSH; um futuro caminho `seed(source:'claude')` permite que uma ponte alimente o mesmo armazenamento |
|
|
130
|
+
| dsh-external/Recall | memória de agente externo | local em primeiro lugar, zero rede, usa a própria emenda de aprovação do DSH |
|
|
131
|
+
| Exemplos oficiais de memória MCP | a posição declarada do DSH de "memória = MCP externo" | o complemento **nativo de primeira parte**: mesmo objetivo, sem servidor externo; ambos coexistem |
|
|
132
|
+
|
|
133
|
+
O nome é **`dsh-memento`** (livre no npm e no GitHub). Não `dsh-recall` (confundível com dsh-external/Recall), não o nome legado excluído `dsh-memory`.
|
|
134
|
+
|
|
135
|
+
## 🔒 Limites de segurança
|
|
136
|
+
|
|
137
|
+
- **Somente serviços públicos** (`tools`, `systemPrompt`, a emenda de aprovação). Sem mudanças em engine / agent-loop / apiproxy / UI oficial.
|
|
138
|
+
- **Zero rede, zero credenciais.** Banco de dados local; modo de arquivo POSIX `0600`.
|
|
139
|
+
- **Falhar ruidosamente.** Banco de dados corrompido ou schema mais novo falha no carregamento; orçamentos cheios e correspondências de substring ambíguas falham com erros estruturados. Nada é silenciosamente engolido ou truncado.
|
|
140
|
+
- **Um processo, um armazenamento.** Múltiplas sessões em um processo compartilham o armazenamento SQLite (escritas serializadas, auditoria por sessão). Dois **processos** compartilhando um `$DSH_HOME` gravam o mesmo arquivo: vence o último gravador sob o locking do SQLite — não execute duas instâncias do harness em um `$DSH_HOME` se você precisa de consistência entre processos (a mesma ressalva que o projeto Hermes documenta).
|
|
141
|
+
|
|
142
|
+
## ⚠️ Limitações conhecidas
|
|
143
|
+
|
|
144
|
+
- **O vocabulário de eventos de sessão é declarado, ainda não emitido (rc.6).** `memory/added|updated|removed|recalled|snapshot` são declarados por merge em `types.d.ts`, mas o rc.6 não tem superfície de registro para tipos de evento fora do repositório (appends não registrados tornariam sessões persistidas incapazes de carregar). A completude da auditoria vem do par de aprovação + a tabela de auditoria; a emissão liga automaticamente assim que um build do harness registra os tipos. Veja [ARCHITECTURE.md](ARCHITECTURE.md) decisão 4.
|
|
145
|
+
- **A política `ask` precisa de um answerer.** Sem um answerer de UI/ACP composto, as escritas falham fechado (`unavailable`) — por design, a postura fail-closed da emenda de aprovação.
|
|
146
|
+
- **Sem índice FTS5.** A busca por substring usa `instr` insensível a maiúsculas (correto para CJK); o ranking de recuperação usa contadores de acertos por entrada. O tokenizador trigram do FTS5 não indexa caracteres CJK de um único caractere, então não é usado — veja [ARCHITECTURE.md](ARCHITECTURE.md), decisão 10.
|
|
147
|
+
|
|
148
|
+
## 🧪 Desenvolvimento
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
npm install
|
|
152
|
+
npm test # node --test: 103 testes — orçamento, substring única, política do portão, armazenamento, snapshot, integração com mock-ctx (invariantes S2/S3), comando/recuperação/painel V2
|
|
153
|
+
npm run typecheck # portão tsc --checkJs sobre index.mjs / lib / scripts
|
|
154
|
+
npm run check:coverage # portão de cobertura de linhas: lib ≥90%, index.mjs ≥85%, todos ≥90%
|
|
155
|
+
npm run check:readmes # portão de coerência dos cinco README
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`lib/` tem zero dependência de DSH (somente builtins do node:); imports de DSH existem apenas em `index.mjs`. Disciplina completa em [AGENTS.md](AGENTS.md); decisões de design em [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
159
|
+
|
|
160
|
+
## 🏷 Tópicos
|
|
161
|
+
|
|
162
|
+
Tópicos sugeridos para o GitHub: `dsh` · `dsh-plugin` · `deepseek-harness` · `memory` · `agent-memory` · `approval` · `audit` · `sqlite` · `cordis` · `llm`
|
|
163
|
+
|
|
164
|
+
## 📄 Licença
|
|
165
|
+
|
|
166
|
+
Apache License 2.0 — veja [LICENSE](LICENSE). Nenhum código de terceiros é redistribuído; veja [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|