@modusensus/dsh-mneme 0.1.3 → 0.1.5
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/README.md +13 -3
- package/lib/api.js +196 -10
- package/lib/client.js +311 -37
- package/lib/commands.js +64 -0
- package/lib/embedding.js +97 -0
- package/lib/index.js +28 -3
- package/lib/inject.js +33 -8
- package/lib/service.js +17 -0
- package/lib/settings.js +142 -0
- package/lib/store.js +84 -5
- package/package.json +58 -58
- package/src/api.js +196 -10
- package/src/commands.js +64 -0
- package/src/embedding.js +97 -0
- package/src/index.js +28 -3
- package/src/inject.js +33 -8
- package/src/service.js +17 -0
- package/src/settings.js +142 -0
- package/src/store.js +84 -5
package/lib/inject.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function createInjector(ctx, service, config) {
|
|
1
|
+
export function createInjector(ctx, service, settings, config) {
|
|
2
2
|
const maxItems = config.maxInjectedItems ?? 5;
|
|
3
3
|
const threshold = config.importanceThreshold ?? 3;
|
|
4
4
|
|
|
@@ -11,12 +11,37 @@ export function createInjector(ctx, service, config) {
|
|
|
11
11
|
return lines.join("\n");
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
// User profile + rules: injected ahead of the memory block because they are
|
|
15
|
+
// always-relevant instructions the agent should follow every turn.
|
|
16
|
+
function renderUserSettings() {
|
|
17
|
+
const profile = settings.getProfile().trim();
|
|
18
|
+
const rules = settings.getRules();
|
|
19
|
+
if (!profile && !rules.length) return "";
|
|
20
|
+
const lines = ["[用户设置] 来自 dsh-mneme 的用户画像与规则:"];
|
|
21
|
+
if (profile) lines.push(`- 用户画像:${profile}`);
|
|
22
|
+
for (const rule of rules) lines.push(`- 规则:${rule}`);
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const disposers = [
|
|
27
|
+
ctx.systemPrompt.context({
|
|
28
|
+
name: "memory",
|
|
29
|
+
order: 90,
|
|
30
|
+
text: () => {
|
|
31
|
+
const candidates = service.injectCandidates({ maxItems, threshold });
|
|
32
|
+
return render(candidates);
|
|
33
|
+
}
|
|
34
|
+
}),
|
|
35
|
+
ctx.systemPrompt.context({
|
|
36
|
+
name: "user-settings",
|
|
37
|
+
order: 85,
|
|
38
|
+
text: renderUserSettings
|
|
39
|
+
})
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
return () => {
|
|
43
|
+
for (const dispose of disposers) {
|
|
44
|
+
if (typeof dispose === "function") dispose();
|
|
20
45
|
}
|
|
21
|
-
}
|
|
46
|
+
};
|
|
22
47
|
}
|
package/lib/service.js
CHANGED
|
@@ -6,6 +6,17 @@ export function createService({ store, mirror, config, onWrite }) {
|
|
|
6
6
|
// passed in the constructor). Fired on the same write events as onWrite.
|
|
7
7
|
let dreamHook = null;
|
|
8
8
|
|
|
9
|
+
// Optional vector embedder, installed via setEmbedder after creation. After
|
|
10
|
+
// any content write it fire-and-forgets a re-embed of the row so vector
|
|
11
|
+
// search stays in sync; failures are swallowed inside the embedder.
|
|
12
|
+
let embedder = null;
|
|
13
|
+
|
|
14
|
+
function scheduleEmbed(memory) {
|
|
15
|
+
if (embedder && memory?.id) {
|
|
16
|
+
try { embedder.schedule(memory); } catch { /* ignore */ }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
/**
|
|
10
21
|
* Fire-and-forget write notification; errors are swallowed to keep write
|
|
11
22
|
* paths clean. The store mutation has already committed, so a throwing
|
|
@@ -38,6 +49,7 @@ export function createService({ store, mirror, config, onWrite }) {
|
|
|
38
49
|
});
|
|
39
50
|
syncMirror();
|
|
40
51
|
notifyWrite();
|
|
52
|
+
scheduleEmbed(merged);
|
|
41
53
|
return { action: "merged", memory: merged };
|
|
42
54
|
}
|
|
43
55
|
const created = store.save({
|
|
@@ -50,6 +62,7 @@ export function createService({ store, mirror, config, onWrite }) {
|
|
|
50
62
|
});
|
|
51
63
|
syncMirror();
|
|
52
64
|
notifyWrite();
|
|
65
|
+
scheduleEmbed(created);
|
|
53
66
|
return { action: "created", memory: created };
|
|
54
67
|
}
|
|
55
68
|
|
|
@@ -126,8 +139,11 @@ export function createService({ store, mirror, config, onWrite }) {
|
|
|
126
139
|
mergeHumanEdits,
|
|
127
140
|
toApiList,
|
|
128
141
|
setDreamHook(fn) { dreamHook = fn; },
|
|
142
|
+
setEmbedder(emb) { embedder = emb; },
|
|
129
143
|
// passthroughs used by tools and api layers; mutations keep the mirror in sync
|
|
130
144
|
search: (q, o) => store.search(q, o),
|
|
145
|
+
searchVector: (v, o) => store.searchVector(v, o),
|
|
146
|
+
embeddedCount: () => store.embeddedCount(),
|
|
131
147
|
list: (o) => store.list(o),
|
|
132
148
|
all: () => store.all(),
|
|
133
149
|
count: (type) => store.count(type),
|
|
@@ -141,6 +157,7 @@ export function createService({ store, mirror, config, onWrite }) {
|
|
|
141
157
|
const updated = store.update(id, p);
|
|
142
158
|
syncMirror();
|
|
143
159
|
notifyWrite();
|
|
160
|
+
scheduleEmbed(updated);
|
|
144
161
|
return updated;
|
|
145
162
|
},
|
|
146
163
|
setForget: (id, f) => {
|
package/lib/settings.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// User-configurable settings: profile (user self-description), rules (behavior
|
|
2
|
+
// rules the agent must follow), and custom slash commands. Stored in the same
|
|
3
|
+
// SQLite database via dedicated tables, isolated from the memories store.
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
|
|
6
|
+
const SCHEMA = `
|
|
7
|
+
CREATE TABLE IF NOT EXISTS user_settings (
|
|
8
|
+
key TEXT PRIMARY KEY,
|
|
9
|
+
value TEXT NOT NULL
|
|
10
|
+
);
|
|
11
|
+
CREATE TABLE IF NOT EXISTS custom_commands (
|
|
12
|
+
id TEXT PRIMARY KEY,
|
|
13
|
+
name TEXT NOT NULL UNIQUE,
|
|
14
|
+
description TEXT NOT NULL DEFAULT '',
|
|
15
|
+
instruction TEXT NOT NULL,
|
|
16
|
+
created_at TEXT NOT NULL,
|
|
17
|
+
updated_at TEXT NOT NULL
|
|
18
|
+
);
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
// DSH command names must match this (lowercase, start with a letter).
|
|
22
|
+
const COMMAND_NAME = /^[a-z][a-z0-9_-]*$/;
|
|
23
|
+
|
|
24
|
+
/** Parse a JSON array out of a stored string, tolerant of corruption. */
|
|
25
|
+
function parseList(raw) {
|
|
26
|
+
try {
|
|
27
|
+
const value = JSON.parse(raw);
|
|
28
|
+
return Array.isArray(value) ? value : [];
|
|
29
|
+
} catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createSettings(db) {
|
|
35
|
+
db.exec(SCHEMA);
|
|
36
|
+
|
|
37
|
+
function getSetting(key) {
|
|
38
|
+
const row = db.prepare("SELECT value FROM user_settings WHERE key = ?").get(key);
|
|
39
|
+
return row?.value ?? undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function setSetting(key, value) {
|
|
43
|
+
db.prepare(
|
|
44
|
+
`INSERT INTO user_settings (key, value) VALUES (?, ?)
|
|
45
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
46
|
+
).run(key, value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function toCommand(row) {
|
|
50
|
+
if (!row) return undefined;
|
|
51
|
+
return {
|
|
52
|
+
id: row.id,
|
|
53
|
+
name: row.name,
|
|
54
|
+
description: row.description,
|
|
55
|
+
instruction: row.instruction,
|
|
56
|
+
created_at: row.created_at,
|
|
57
|
+
updated_at: row.updated_at
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
/** The user's self-description (free text) or "" when unset. */
|
|
63
|
+
getProfile() {
|
|
64
|
+
return getSetting("profile") ?? "";
|
|
65
|
+
},
|
|
66
|
+
setProfile(text) {
|
|
67
|
+
setSetting("profile", String(text ?? ""));
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
/** Behavior rules as an array of strings. */
|
|
71
|
+
getRules() {
|
|
72
|
+
return parseList(getSetting("rules") ?? "[]").filter((r) => typeof r === "string");
|
|
73
|
+
},
|
|
74
|
+
setRules(rules) {
|
|
75
|
+
const list = Array.isArray(rules) ? rules.filter((r) => typeof r === "string") : [];
|
|
76
|
+
setSetting("rules", JSON.stringify(list));
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/** All custom commands, sorted by name. */
|
|
80
|
+
listCommands() {
|
|
81
|
+
const rows = db.prepare("SELECT * FROM custom_commands ORDER BY name ASC").all();
|
|
82
|
+
return rows.map(toCommand);
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Add or replace a custom command by name.
|
|
87
|
+
* @returns the stored command.
|
|
88
|
+
* @throws when name is invalid or does not match DSH's command-name grammar.
|
|
89
|
+
*/
|
|
90
|
+
addCommand({ name, description = "", instruction }) {
|
|
91
|
+
const cmdName = String(name ?? "").trim();
|
|
92
|
+
if (!COMMAND_NAME.test(cmdName)) {
|
|
93
|
+
throw new Error(`invalid command name "${cmdName}": must match /^[a-z][a-z0-9_-]*$/`);
|
|
94
|
+
}
|
|
95
|
+
if (typeof instruction !== "string" || !instruction.trim()) {
|
|
96
|
+
throw new Error("command instruction must be a non-empty string");
|
|
97
|
+
}
|
|
98
|
+
const now = new Date().toISOString();
|
|
99
|
+
const existing = db.prepare("SELECT id FROM custom_commands WHERE name = ?").get(cmdName);
|
|
100
|
+
if (existing) {
|
|
101
|
+
db.prepare(
|
|
102
|
+
"UPDATE custom_commands SET description = ?, instruction = ?, updated_at = ? WHERE id = ?"
|
|
103
|
+
).run(String(description ?? ""), instruction, now, existing.id);
|
|
104
|
+
return toCommand(db.prepare("SELECT * FROM custom_commands WHERE id = ?").get(existing.id));
|
|
105
|
+
}
|
|
106
|
+
const id = randomUUID();
|
|
107
|
+
db.prepare(
|
|
108
|
+
`INSERT INTO custom_commands (id, name, description, instruction, created_at, updated_at)
|
|
109
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
110
|
+
).run(id, cmdName, String(description ?? ""), instruction, now, now);
|
|
111
|
+
return toCommand(db.prepare("SELECT * FROM custom_commands WHERE id = ?").get(id));
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/** Remove a custom command by id; returns true when removed. */
|
|
115
|
+
removeCommand(id) {
|
|
116
|
+
const result = db.prepare("DELETE FROM custom_commands WHERE id = ?").run(id);
|
|
117
|
+
return result.changes > 0;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/** Vector-search provider config (OpenAI-compatible embeddings endpoint). */
|
|
121
|
+
getVectorConfig() {
|
|
122
|
+
const raw = getSetting("vector");
|
|
123
|
+
if (!raw) return undefined;
|
|
124
|
+
try {
|
|
125
|
+
const cfg = JSON.parse(raw);
|
|
126
|
+
return typeof cfg === "object" && cfg !== null ? cfg : undefined;
|
|
127
|
+
} catch {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
setVectorConfig({ enabled, baseUrl, apiKey, model }) {
|
|
132
|
+
const cfg = {
|
|
133
|
+
enabled: enabled === true || enabled === 1,
|
|
134
|
+
baseUrl: String(baseUrl ?? "").trim().replace(/\/+$/, ""),
|
|
135
|
+
apiKey: String(apiKey ?? "").trim(),
|
|
136
|
+
model: String(model ?? "").trim()
|
|
137
|
+
};
|
|
138
|
+
setSetting("vector", JSON.stringify(cfg));
|
|
139
|
+
return cfg;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
package/lib/store.js
CHANGED
|
@@ -12,6 +12,7 @@ CREATE TABLE IF NOT EXISTS memories (
|
|
|
12
12
|
forgotten INTEGER NOT NULL DEFAULT 0,
|
|
13
13
|
archived INTEGER NOT NULL DEFAULT 0,
|
|
14
14
|
source TEXT,
|
|
15
|
+
embedding TEXT,
|
|
15
16
|
created_at TEXT NOT NULL,
|
|
16
17
|
updated_at TEXT NOT NULL
|
|
17
18
|
);
|
|
@@ -64,11 +65,14 @@ export function createStore(path) {
|
|
|
64
65
|
db.exec("PRAGMA journal_mode = WAL;");
|
|
65
66
|
db.exec(SCHEMA);
|
|
66
67
|
|
|
67
|
-
// Schema
|
|
68
|
+
// Schema migrations for legacy databases (idempotent).
|
|
68
69
|
const columns = db.prepare("PRAGMA table_info(memories)").all().map((c) => c.name);
|
|
69
70
|
if (!columns.includes("archived")) {
|
|
70
71
|
db.exec("ALTER TABLE memories ADD COLUMN archived INTEGER NOT NULL DEFAULT 0");
|
|
71
72
|
}
|
|
73
|
+
if (!columns.includes("embedding")) {
|
|
74
|
+
db.exec("ALTER TABLE memories ADD COLUMN embedding TEXT");
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
// Per-instance monotonic timestamp guard: consecutive writes within the same
|
|
74
78
|
// millisecond must still produce strictly increasing timestamps (test asserts
|
|
@@ -117,10 +121,13 @@ export function createStore(path) {
|
|
|
117
121
|
const now = nowIso();
|
|
118
122
|
const tags = JSON.stringify(memory.tags ?? []);
|
|
119
123
|
const importance = Number.isInteger(memory.importance) ? memory.importance : 3;
|
|
124
|
+
const embedding = Array.isArray(memory.embedding) && memory.embedding.length
|
|
125
|
+
? JSON.stringify(memory.embedding)
|
|
126
|
+
: null;
|
|
120
127
|
db.prepare(
|
|
121
|
-
`INSERT INTO memories (id, type, title, content, tags, importance, forgotten, source, created_at, updated_at)
|
|
122
|
-
VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?)`
|
|
123
|
-
).run(id, type, memory.title, memory.content, tags, importance, memory.source ?? null, now, now);
|
|
128
|
+
`INSERT INTO memories (id, type, title, content, tags, importance, forgotten, source, embedding, created_at, updated_at)
|
|
129
|
+
VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?)`
|
|
130
|
+
).run(id, type, memory.title, memory.content, tags, importance, memory.source ?? null, embedding, now, now);
|
|
124
131
|
return getById(id);
|
|
125
132
|
}
|
|
126
133
|
|
|
@@ -133,8 +140,11 @@ export function createStore(path) {
|
|
|
133
140
|
throw new Error("tags must be an array");
|
|
134
141
|
}
|
|
135
142
|
const now = nowIso();
|
|
143
|
+
const embedding = patch.embedding !== undefined
|
|
144
|
+
? (Array.isArray(patch.embedding) && patch.embedding.length ? JSON.stringify(patch.embedding) : null)
|
|
145
|
+
: existing.embedding ?? null;
|
|
136
146
|
db.prepare(
|
|
137
|
-
`UPDATE memories SET type=?, title=?, content=?, tags=?, importance=?, source=?, updated_at=? WHERE id=?`
|
|
147
|
+
`UPDATE memories SET type=?, title=?, content=?, tags=?, importance=?, source=?, embedding=?, updated_at=? WHERE id=?`
|
|
138
148
|
).run(
|
|
139
149
|
type,
|
|
140
150
|
patch.title ?? existing.title,
|
|
@@ -142,6 +152,7 @@ export function createStore(path) {
|
|
|
142
152
|
JSON.stringify(patch.tags ?? existing.tags),
|
|
143
153
|
Number.isInteger(patch.importance) ? patch.importance : existing.importance,
|
|
144
154
|
patch.source !== undefined ? patch.source : (existing.source ?? null),
|
|
155
|
+
embedding,
|
|
145
156
|
now,
|
|
146
157
|
id
|
|
147
158
|
);
|
|
@@ -190,6 +201,27 @@ export function createStore(path) {
|
|
|
190
201
|
return rows.map(toRow);
|
|
191
202
|
}
|
|
192
203
|
|
|
204
|
+
/** Set (or clear with null) the embedding vector of a memory. */
|
|
205
|
+
function setEmbedding(id, vector) {
|
|
206
|
+
const json = Array.isArray(vector) && vector.length ? JSON.stringify(vector) : null;
|
|
207
|
+
db.prepare("UPDATE memories SET embedding = ? WHERE id = ?").run(json, id);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function embeddedCount() {
|
|
211
|
+
return db.prepare(
|
|
212
|
+
"SELECT count(*) AS c FROM memories WHERE embedding IS NOT NULL AND embedding != ''"
|
|
213
|
+
).get().c;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Candidate rows still missing an embedding, for incremental re-indexing. */
|
|
217
|
+
function needsEmbedding(limit = 50) {
|
|
218
|
+
return db.prepare(
|
|
219
|
+
`SELECT id, title, content FROM memories
|
|
220
|
+
WHERE embedding IS NULL OR embedding = ''
|
|
221
|
+
ORDER BY updated_at DESC LIMIT ?`
|
|
222
|
+
).all(limit);
|
|
223
|
+
}
|
|
224
|
+
|
|
193
225
|
function search(query, { limit = 20, includeArchived = false } = {}) {
|
|
194
226
|
const q = String(query).trim();
|
|
195
227
|
if (!q) return [];
|
|
@@ -212,6 +244,49 @@ export function createStore(path) {
|
|
|
212
244
|
return rows.map(toRow);
|
|
213
245
|
}
|
|
214
246
|
|
|
247
|
+
// --- vector search ------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
function cosine(a, b) {
|
|
250
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length || !a.length) return 0;
|
|
251
|
+
let dot = 0;
|
|
252
|
+
let na = 0;
|
|
253
|
+
let nb = 0;
|
|
254
|
+
for (let i = 0; i < a.length; i++) {
|
|
255
|
+
dot += a[i] * b[i];
|
|
256
|
+
na += a[i] * a[i];
|
|
257
|
+
nb += b[i] * b[i];
|
|
258
|
+
}
|
|
259
|
+
if (na === 0 || nb === 0) return 0;
|
|
260
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Brute-force cosine similarity over embedded rows. Returns rows decorated
|
|
265
|
+
* with a `score` (0..1). Only rows with a stored embedding participate.
|
|
266
|
+
*/
|
|
267
|
+
function searchVector(vector, { limit = 20, includeArchived = false, threshold = 0 } = {}) {
|
|
268
|
+
if (!Array.isArray(vector) || !vector.length) return [];
|
|
269
|
+
const archivedFilter = includeArchived ? "" : "archived = 0 AND ";
|
|
270
|
+
const rows = db.prepare(
|
|
271
|
+
`SELECT * FROM memories
|
|
272
|
+
WHERE ${archivedFilter}forgotten = 0 AND embedding IS NOT NULL AND embedding != ''`
|
|
273
|
+
).all();
|
|
274
|
+
const scored = [];
|
|
275
|
+
for (const row of rows) {
|
|
276
|
+
let v;
|
|
277
|
+
try {
|
|
278
|
+
v = JSON.parse(row.embedding);
|
|
279
|
+
} catch {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const score = cosine(vector, v);
|
|
283
|
+
if (score >= threshold) scored.push({ row, score });
|
|
284
|
+
}
|
|
285
|
+
scored.sort((a, b) => b.score - a.score);
|
|
286
|
+
const { limit: lim } = sanitizePage(limit, 0, 20);
|
|
287
|
+
return scored.slice(0, lim).map(({ row, score }) => ({ ...toRow(row), score }));
|
|
288
|
+
}
|
|
289
|
+
|
|
215
290
|
return {
|
|
216
291
|
db,
|
|
217
292
|
count,
|
|
@@ -224,6 +299,10 @@ export function createStore(path) {
|
|
|
224
299
|
list,
|
|
225
300
|
all,
|
|
226
301
|
search,
|
|
302
|
+
setEmbedding,
|
|
303
|
+
embeddedCount,
|
|
304
|
+
needsEmbedding,
|
|
305
|
+
searchVector,
|
|
227
306
|
close() {
|
|
228
307
|
db.close();
|
|
229
308
|
}
|
package/package.json
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@modusensus/dsh-mneme",
|
|
3
|
-
"description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 6 model tools, automatic injection, session summarization, and a Web GUI panel",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "lib/index.js",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"default": "./lib/index.js"
|
|
11
|
-
},
|
|
12
|
-
"./client": {
|
|
13
|
-
"default": "./lib/client.js"
|
|
14
|
-
},
|
|
15
|
-
"./package.json": "./package.json"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"lib",
|
|
19
|
-
"src",
|
|
20
|
-
"cordis.patch.yml"
|
|
21
|
-
],
|
|
22
|
-
"dsh": {
|
|
23
|
-
"client": {
|
|
24
|
-
"inject": [
|
|
25
|
-
"slots",
|
|
26
|
-
"locale",
|
|
27
|
-
"layout",
|
|
28
|
-
"connection"
|
|
29
|
-
],
|
|
30
|
-
"platform": "web"
|
|
31
|
-
},
|
|
32
|
-
"bundle": {
|
|
33
|
-
"patch": "./cordis.patch.yml"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"peerDependencies": {
|
|
37
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
39
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
40
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
41
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
42
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
46
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
47
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
48
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
49
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
50
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
51
|
-
},
|
|
52
|
-
"scripts": {
|
|
53
|
-
"sync": "node scripts/sync-lib.js",
|
|
54
|
-
"prepack": "npm run sync",
|
|
55
|
-
"test": "node --test --test-isolation=none test/*.test.js",
|
|
56
|
-
"e2e": "node scripts/e2e-dsh.js"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@modusensus/dsh-mneme",
|
|
3
|
+
"description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 6 model tools, automatic injection, session summarization, and a Web GUI panel",
|
|
4
|
+
"version": "0.1.5",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"default": "./lib/client.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"lib",
|
|
19
|
+
"src",
|
|
20
|
+
"cordis.patch.yml"
|
|
21
|
+
],
|
|
22
|
+
"dsh": {
|
|
23
|
+
"client": {
|
|
24
|
+
"inject": [
|
|
25
|
+
"slots",
|
|
26
|
+
"locale",
|
|
27
|
+
"layout",
|
|
28
|
+
"connection"
|
|
29
|
+
],
|
|
30
|
+
"platform": "web"
|
|
31
|
+
},
|
|
32
|
+
"bundle": {
|
|
33
|
+
"patch": "./cordis.patch.yml"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
39
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
40
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
41
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
42
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
46
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
47
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
48
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
49
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
50
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"sync": "node scripts/sync-lib.js",
|
|
54
|
+
"prepack": "npm run sync",
|
|
55
|
+
"test": "node --test --test-isolation=none test/*.test.js",
|
|
56
|
+
"e2e": "node scripts/e2e-dsh.js"
|
|
57
|
+
}
|
|
58
|
+
}
|