dsh-prime-memory 0.26.4 → 0.26.5-beta.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/dist/clients/drsc.d.ts +93 -0
- package/dist/clients/drsc.js +139 -0
- package/dist/drs-anchor-backfill.d.ts +88 -0
- package/dist/drs-anchor-backfill.js +150 -0
- package/dist/hooks/capture.d.ts +4 -4
- package/dist/hooks/capture.js +34 -27
- package/dist/index.js +43 -18
- package/dist/pipeline/runner.d.ts +17 -4
- package/dist/pipeline/runner.js +33 -6
- package/dist/store/embedding-source.d.ts +1 -3
- package/dist/store/embedding-source.js +6 -13
- package/dist/store/l0-watermark.d.ts +46 -0
- package/dist/store/l0-watermark.js +93 -0
- package/dist/store/l0.d.ts +12 -42
- package/dist/store/l0.js +2 -208
- package/dist/store/sqlite.d.ts +3 -0
- package/dist/store/sqlite.js +7 -0
- package/dist/tools/index.d.ts +3 -2
- package/dist/tools/index.js +27 -10
- package/dsh.plugin.json +1 -1
- package/package.json +8 -4
package/dist/store/l0.js
CHANGED
|
@@ -1,121 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* L0 原始对话存储(双写架构):
|
|
3
|
-
* - conversations/YYYY-MM-DD.jsonl:追加式事实源;
|
|
4
|
-
* - MemoryDb(SQLite):主检索引擎——检索不再按天扫文件、现建内存索引。
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, promises as fs } from 'node:fs';
|
|
7
|
-
import * as path from 'node:path';
|
|
8
|
-
import { EmbedHelper, NoopEmbeddingService } from './embedding.js';
|
|
9
|
-
import { appendJsonl, dayKey, ensureDir, nowIso, readJsonl } from '../util/io.js';
|
|
10
|
-
import { rrfMerge } from './search-utils.js';
|
|
11
|
-
import { isZeroVector } from './sqlite.js';
|
|
12
|
-
/** 官方过度召回倍数(conversation-search:limit × 3)。 */
|
|
13
|
-
const CANDIDATE_MULTIPLIER = 3;
|
|
14
1
|
export class L0Store {
|
|
15
2
|
db;
|
|
16
|
-
|
|
17
|
-
legacyDir;
|
|
18
|
-
helper;
|
|
19
|
-
embedSvc;
|
|
20
|
-
logger;
|
|
21
|
-
constructor(dataDir, db, embed = new NoopEmbeddingService(), logger) {
|
|
3
|
+
constructor(db) {
|
|
22
4
|
this.db = db;
|
|
23
|
-
this.dir = path.join(dataDir, 'conversations');
|
|
24
|
-
this.legacyDir = path.join(dataDir, 'l0');
|
|
25
|
-
this.embedSvc = embed;
|
|
26
|
-
this.helper = new EmbedHelper(embed, logger);
|
|
27
|
-
this.logger = logger;
|
|
28
5
|
}
|
|
29
|
-
|
|
30
|
-
await ensureDir(this.dir);
|
|
31
|
-
await this.importLegacy();
|
|
32
|
-
}
|
|
33
|
-
/** 旧版 l0/*.jsonl 一次性导入检索库,成功后目录改名 l0.imported/。 */
|
|
34
|
-
async importLegacy() {
|
|
35
|
-
if (!existsSync(this.legacyDir))
|
|
36
|
-
return;
|
|
37
|
-
try {
|
|
38
|
-
const files = await fs.readdir(this.legacyDir).catch(() => []);
|
|
39
|
-
let imported = 0;
|
|
40
|
-
let total = 0;
|
|
41
|
-
for (const f of files.sort()) {
|
|
42
|
-
if (!f.endsWith('.jsonl'))
|
|
43
|
-
continue;
|
|
44
|
-
const records = await readJsonl(path.join(this.legacyDir, f));
|
|
45
|
-
// 最小有效性门(同 L1 的 importLegacy):坏行读取时丢弃,按 valid 数判迁移完成
|
|
46
|
-
const valid = records.filter((r) => r && typeof r.id === 'string' && r.content);
|
|
47
|
-
const badCount = records.length - valid.length;
|
|
48
|
-
if (badCount > 0) {
|
|
49
|
-
this.logger?.warn(`[memory] 旧版 L0 文件 ${f} 丢弃 ${badCount} 条坏行(缺 id/content)`);
|
|
50
|
-
}
|
|
51
|
-
if (valid.length > 0) {
|
|
52
|
-
total += valid.length;
|
|
53
|
-
if (this.db.upsertL0Batch(valid))
|
|
54
|
-
imported += valid.length;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// 只有全部批次入库成功(或目录为空)才改名,避免数据被改名带走
|
|
58
|
-
if (imported === total) {
|
|
59
|
-
const renamed = await fs
|
|
60
|
-
.rename(this.legacyDir, `${this.legacyDir}.imported`)
|
|
61
|
-
.then(() => true, () => false);
|
|
62
|
-
if (renamed) {
|
|
63
|
-
this.logger?.info(`[memory] 旧版 L0 数据已导入检索库 ${imported} 条(l0/ → l0.imported/)`);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.logger?.warn('[memory] 旧版 L0 导入完成但改名失败(l0.imported/ 已存在?),下次启动会重复导入(幂等,无害)');
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
this.logger?.warn(`[memory] 旧版 L0 导入不完整(${imported}/${total}),保留原目录下次重试`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
this.logger?.warn(`[memory] 旧版 L0 数据导入失败: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async append(sessionId, messages) {
|
|
78
|
-
if (messages.length === 0)
|
|
79
|
-
return;
|
|
80
|
-
const records = messages.map((m) => {
|
|
81
|
-
const rec = {
|
|
82
|
-
sessionId,
|
|
83
|
-
recordedAt: nowIso(),
|
|
84
|
-
id: m.id,
|
|
85
|
-
role: m.role,
|
|
86
|
-
content: m.content,
|
|
87
|
-
timestamp: m.timestamp,
|
|
88
|
-
};
|
|
89
|
-
// R7:锚点摊平到事实源与 DB 两处(事实源可跨进程重建,DB 供按坐标查询)。
|
|
90
|
-
// 无锚点时**不写键**——旧行与新增的无坐标消息保持同形。
|
|
91
|
-
if (m.anchor !== undefined) {
|
|
92
|
-
rec.turn = m.anchor.turn;
|
|
93
|
-
if (m.anchor.step !== undefined)
|
|
94
|
-
rec.step = m.anchor.step;
|
|
95
|
-
}
|
|
96
|
-
return rec;
|
|
97
|
-
});
|
|
98
|
-
// 事实源:按天追加
|
|
99
|
-
const byDay = new Map();
|
|
100
|
-
for (const r of records) {
|
|
101
|
-
const k = dayKey(r.timestamp);
|
|
102
|
-
const arr = byDay.get(k) ?? [];
|
|
103
|
-
arr.push(r);
|
|
104
|
-
byDay.set(k, arr);
|
|
105
|
-
}
|
|
106
|
-
for (const [day, list] of byDay) {
|
|
107
|
-
await appendJsonl(path.join(this.dir, `${day}.jsonl`), list);
|
|
108
|
-
}
|
|
109
|
-
// 检索引擎:DB + 向量(嵌入失败只跳过向量,不影响元数据/FTS,backfill 补齐)。
|
|
110
|
-
// 双写失败闭环:JSONL 事实源已先行追加,DB 缺行 = 这些消息检索不可见
|
|
111
|
-
// (conversation_search / 蒸馏背景参考都查不到)——升 error 并给自愈指引。
|
|
112
|
-
const vecs = await this.helper.batch(records.map((r) => r.content));
|
|
113
|
-
if (!this.db.upsertL0Batch(records, vecs)) {
|
|
114
|
-
this.logger?.error(`[memory] L0 检索库批量写入失败(${records.length} 条,JSONL 事实源完好),` +
|
|
115
|
-
'这些消息暂不可检索;可在设置页运行「重建记忆」修复');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
/** 今日已捕获消息数(SQL 计数,不再读整文件)。 */
|
|
6
|
+
/** 今日已捕获消息数(SQL 计数,不再读整文件;写停后归零,面板口径保留)。 */
|
|
119
7
|
async countToday() {
|
|
120
8
|
const d = new Date();
|
|
121
9
|
return this.db.countL0Since(new Date(d.getFullYear(), d.getMonth(), d.getDate()).toISOString());
|
|
@@ -124,98 +12,4 @@ export class L0Store {
|
|
|
124
12
|
async countBySession(sessionId) {
|
|
125
13
|
return this.db.countL0BySession(sessionId);
|
|
126
14
|
}
|
|
127
|
-
/** 该会话最近 n 条消息(时间升序;蒸馏背景参考用,按会话现查——ADR-0003)。 */
|
|
128
|
-
async recentBySession(sessionId, limit) {
|
|
129
|
-
return this.db.recentL0BySession(sessionId, limit);
|
|
130
|
-
}
|
|
131
|
-
/** §A 水位线:该会话 L0 已落盘的最大 turn(空会话 undefined;委托 MemoryDb)。 */
|
|
132
|
-
maxCapturedTurn(sessionId) {
|
|
133
|
-
return this.db.maxCapturedTurn(sessionId);
|
|
134
|
-
}
|
|
135
|
-
/** §A 幂等检查:该 (session, turn) 是否已有任意 L0 行(委托 MemoryDb)。 */
|
|
136
|
-
hasAnyL0Message(sessionId, turn) {
|
|
137
|
-
return this.db.hasAnyL0Message(sessionId, turn);
|
|
138
|
-
}
|
|
139
|
-
/** 检索:FTS + 向量 hybrid(RRF 融合),返回按相关性排序的消息。 */
|
|
140
|
-
async search(query, limit) {
|
|
141
|
-
const caps = this.db.getCapabilities();
|
|
142
|
-
if (!caps.ftsSearch && !caps.vectorSearch)
|
|
143
|
-
return [];
|
|
144
|
-
const candidateK = limit * CANDIDATE_MULTIPLIER;
|
|
145
|
-
if (caps.vectorSearch && this.helper.vectorReady()) {
|
|
146
|
-
const [ftsRaw, vec] = await Promise.all([
|
|
147
|
-
Promise.resolve(this.db.searchL0Fts(query, candidateK)),
|
|
148
|
-
this.helper.query(query),
|
|
149
|
-
]);
|
|
150
|
-
const vecList = vec ? this.db.searchL0Vector(vec, candidateK) : [];
|
|
151
|
-
const merged = rrfMerge([ftsRaw, vecList], (h) => h.id);
|
|
152
|
-
return merged.map(({ rrfScore: _rrf, ...r }) => r).slice(0, limit);
|
|
153
|
-
}
|
|
154
|
-
return this.db.searchL0Fts(query, limit).map(({ score: _score, ...r }) => r);
|
|
155
|
-
}
|
|
156
|
-
/** 活切换嵌入源:同步换底层服务(嵌入源三态切换用)。 */
|
|
157
|
-
setEmbeddingService(svc) {
|
|
158
|
-
this.embedSvc = svc;
|
|
159
|
-
this.helper.setService(svc);
|
|
160
|
-
}
|
|
161
|
-
/** 向量写入能力是否就绪。`reindex` 在未就绪时**静默短路**成 0/0/0
|
|
162
|
-
* (见本文件 `reindex` 首行),调用方必须自己问这里——否则"根本没跑"
|
|
163
|
-
* 会长得和"跑完了、零条待补"一模一样。 */
|
|
164
|
-
vectorsReady() {
|
|
165
|
-
return this.helper.vectorReady();
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* 增量重嵌入(同 L1Store.reindex:只补缺失向量,零向量记 skipped 并入 skip 集,
|
|
169
|
-
* 不算失败、不阻塞同步标记——保证补齐判据收敛)。onProgress/shouldCancel
|
|
170
|
-
* 供活切换的进度展示与取消。
|
|
171
|
-
*/
|
|
172
|
-
async reindex(opts) {
|
|
173
|
-
if (!this.helper.vectorReady())
|
|
174
|
-
return { written: 0, failed: 0, skipped: 0 };
|
|
175
|
-
const items = this.db.getL0ForReindex(this.db.getVecSkipSet('l0'));
|
|
176
|
-
const total = items.length;
|
|
177
|
-
let done = 0;
|
|
178
|
-
let written = 0;
|
|
179
|
-
let failed = 0;
|
|
180
|
-
let skipped = 0;
|
|
181
|
-
let cancelled = false;
|
|
182
|
-
const skippedNow = [];
|
|
183
|
-
const CHUNK = 32;
|
|
184
|
-
for (let i = 0; i < items.length; i += CHUNK) {
|
|
185
|
-
if (opts?.shouldCancel?.()) {
|
|
186
|
-
cancelled = true;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
const chunk = items.slice(i, i + CHUNK);
|
|
190
|
-
let vecs;
|
|
191
|
-
try {
|
|
192
|
-
vecs = await this.embedSvc.embedBatch(chunk.map((c) => c.text));
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
failed += chunk.length;
|
|
196
|
-
done += chunk.length;
|
|
197
|
-
opts?.onProgress?.(done, total);
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
const pending = [];
|
|
201
|
-
chunk.forEach((c, j) => {
|
|
202
|
-
if (isZeroVector(vecs[j])) {
|
|
203
|
-
skipped++;
|
|
204
|
-
skippedNow.push(c.id);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
pending.push({ id: c.id, embedding: vecs[j] });
|
|
208
|
-
});
|
|
209
|
-
if (pending.length > 0) {
|
|
210
|
-
const ok = this.db.updateL0VecBatch(pending, '');
|
|
211
|
-
written += ok;
|
|
212
|
-
failed += pending.length - ok;
|
|
213
|
-
}
|
|
214
|
-
done += chunk.length;
|
|
215
|
-
opts?.onProgress?.(done, total);
|
|
216
|
-
}
|
|
217
|
-
if (skippedNow.length > 0)
|
|
218
|
-
this.db.addVecSkippedIds('l0', skippedNow);
|
|
219
|
-
return { written, failed, skipped, cancelled };
|
|
220
|
-
}
|
|
221
15
|
}
|
package/dist/store/sqlite.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface StoreCapabilities {
|
|
|
12
12
|
}
|
|
13
13
|
import { CostLedger } from './cost-ledger.js';
|
|
14
14
|
import type { BucketRow, CostAggregate, CostByLayer } from './cost-ledger.js';
|
|
15
|
+
import { L0WatermarkStore } from './l0-watermark.js';
|
|
15
16
|
export type { BucketRow, CostAggregate, CostByLayer } from './cost-ledger.js';
|
|
16
17
|
import type { CostByModel } from '../contract.js';
|
|
17
18
|
import { GraphStore } from './graph-store.js';
|
|
@@ -57,6 +58,8 @@ export declare class MemoryDb {
|
|
|
57
58
|
readonly costLedger: CostLedger;
|
|
58
59
|
/** 图谱存储(graph_* 表族;init 独立 try/catch,失败仅图谱 no-op)。 */
|
|
59
60
|
readonly graphStore: GraphStore;
|
|
61
|
+
/** L0 水位表(T8.4 写停;§A 恢复幂等判据的数据源,init 内建表+基线物化)。 */
|
|
62
|
+
readonly l0Watermark: L0WatermarkStore;
|
|
60
63
|
private stmtUpsertL0;
|
|
61
64
|
private stmtGetL0;
|
|
62
65
|
private stmtL0Exists;
|
package/dist/store/sqlite.js
CHANGED
|
@@ -45,6 +45,8 @@ function retiredL1Sql(alias) {
|
|
|
45
45
|
// 成本账本(token_cost 表族)独立职责,此处 re-export 不断裂既有引用;
|
|
46
46
|
// MemoryDb 的四个公开方法为一行委托。
|
|
47
47
|
import { CostLedger } from './cost-ledger.js';
|
|
48
|
+
// L0 水位表(T8.4 写停后 §A 恢复幂等的唯一数据源;正文三表退役,见 l0-watermark.ts)
|
|
49
|
+
import { L0WatermarkStore } from './l0-watermark.js';
|
|
48
50
|
// 图谱存储(graph_* 表族)同为独立职责类;init 失败仅图谱 no-op,不传染主库降级
|
|
49
51
|
import { GraphStore } from './graph-store.js';
|
|
50
52
|
import { RECEIPTS_MAX_RUNS, RECEIPTS_QUERY_LIMIT_MAX } from './receipts.js';
|
|
@@ -88,6 +90,8 @@ export class MemoryDb {
|
|
|
88
90
|
costLedger = new CostLedger();
|
|
89
91
|
/** 图谱存储(graph_* 表族;init 独立 try/catch,失败仅图谱 no-op)。 */
|
|
90
92
|
graphStore = new GraphStore();
|
|
93
|
+
/** L0 水位表(T8.4 写停;§A 恢复幂等判据的数据源,init 内建表+基线物化)。 */
|
|
94
|
+
l0Watermark = new L0WatermarkStore();
|
|
91
95
|
stmtUpsertL0;
|
|
92
96
|
stmtGetL0;
|
|
93
97
|
stmtL0Exists;
|
|
@@ -547,6 +551,8 @@ export class MemoryDb {
|
|
|
547
551
|
this.prepareL0VecStatements();
|
|
548
552
|
// ── token_cost:蒸馏成本明细表(成本账本自治) ──
|
|
549
553
|
this.costLedger.init(this.db, this.logger);
|
|
554
|
+
// ── l0_watermark:写停后的 §A 恢复水位(建表 + 从存量 l0_conversations 基线物化) ──
|
|
555
|
+
this.l0Watermark.init(this.db, this.logger);
|
|
550
556
|
// ── graph_*:知识图谱投影表族(GraphStore.init 自带 try/catch,失败仅图谱 no-op) ──
|
|
551
557
|
// §F 节点向量列的维度**复用既有探测结果**(`vecLoaded` / `dimensions` 由
|
|
552
558
|
// `prepareL1VecStatements` 之前的探测决定),不新增一套能力探测。探测未通过 →
|
|
@@ -2657,6 +2663,7 @@ export class MemoryDb {
|
|
|
2657
2663
|
}
|
|
2658
2664
|
}
|
|
2659
2665
|
close() {
|
|
2666
|
+
this.l0Watermark.close();
|
|
2660
2667
|
try {
|
|
2661
2668
|
this.db.close();
|
|
2662
2669
|
}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { MemoryConfig } from '../config.js';
|
|
|
3
3
|
import type { LiveSettingsHandle } from '../settings.js';
|
|
4
4
|
import type { RuminateController } from '../pipeline/ruminate.js';
|
|
5
5
|
import type { GraphStore } from '../store/graph-store.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { DrscClient } from '../clients/drsc.js';
|
|
7
7
|
import type { L1Store } from '../store/l1.js';
|
|
8
8
|
import type { PersonaStore } from '../store/persona.js';
|
|
9
9
|
import type { SceneStore } from '../store/scenes.js';
|
|
@@ -20,7 +20,8 @@ export interface ToolSealRegistry {
|
|
|
20
20
|
reg(group: string, make: () => () => void): void;
|
|
21
21
|
}
|
|
22
22
|
export declare function registerMemoryTools(ctx: Context, cfg: MemoryConfig, stores: {
|
|
23
|
-
|
|
23
|
+
/** DRSC 客户端(T8.4 读切):conversation_search 的历史供给面;缺席=显式报错。 */
|
|
24
|
+
drsc?: DrscClient;
|
|
24
25
|
l1: L1Store;
|
|
25
26
|
scenes: Record<MemoryFamily, SceneStore>;
|
|
26
27
|
persona: Record<MemoryFamily, PersonaStore>;
|
package/dist/tools/index.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { createHash } from 'node:crypto';
|
|
15
15
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
16
16
|
import { DOWNGRADE_TARGET, familyOf, isKnownType, typeEnumSep } from '../memory-types.js';
|
|
17
|
+
import { drscRoleOf } from '../clients/drsc.js';
|
|
17
18
|
import { RECEIPTS_QUERY_LIMIT_MAX, dimensionOf, toReceiptView } from '../store/receipts.js';
|
|
18
19
|
import { listConflictPairs, renderConflictResolution, renderConflicts, resolveConflictPair } from '../conflict-service.js';
|
|
19
20
|
import { WING_CATALOG, WING_FALLBACK, normPersistence, normScope, resolveRecordScope } from '../types.js';
|
|
@@ -399,7 +400,7 @@ roomRegistry) {
|
|
|
399
400
|
// ── conversation_search: L0 原始对话 ──
|
|
400
401
|
ctx.tools.register(defineTool({
|
|
401
402
|
name: 'conversation_search',
|
|
402
|
-
description: '
|
|
403
|
+
description: '搜索原始对话历史。返回带时间戳的原始消息节选(已脱敏),适用于查找具体消息原文、时间线、上下文细节。',
|
|
403
404
|
parameters: {
|
|
404
405
|
query: { type: 'string', required: true, description: '搜索查询文本' },
|
|
405
406
|
limit: { type: 'number', description: '最大返回条数(默认 5)' },
|
|
@@ -433,15 +434,31 @@ roomRegistry) {
|
|
|
433
434
|
if (familyOfCaller(exec) === null)
|
|
434
435
|
return { items: [], notice: blockNoticeOf(exec) };
|
|
435
436
|
const limit = Math.min(Math.max(args.limit ?? 5, 1), 20);
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
437
|
+
// T8.4 读切(spec R7):检索命中走 DRSC 原文 fts,返回文本取 redact=1 脱敏列。
|
|
438
|
+
// 硬依赖无本地回退(l0 本地检索已退役)——collector 缺席/故障显式报错给模型,
|
|
439
|
+
// 与「空结果」口径分清,不抛穿主流程。
|
|
440
|
+
const drsc = stores.drsc;
|
|
441
|
+
if (!drsc) {
|
|
442
|
+
return { items: [], notice: '历史对话检索不可用:DRSC collector 未装配(本地 L0 检索已退役,无回退)。' };
|
|
443
|
+
}
|
|
444
|
+
try {
|
|
445
|
+
const hits = await drsc.search(args.query, limit);
|
|
446
|
+
return {
|
|
447
|
+
items: hits
|
|
448
|
+
.map((h) => ({ h, role: drscRoleOf(h.kind) }))
|
|
449
|
+
.filter((e) => e.role !== undefined)
|
|
450
|
+
.map(({ h, role }) => ({
|
|
451
|
+
session_id: h.session_id,
|
|
452
|
+
role,
|
|
453
|
+
content: h.snippet,
|
|
454
|
+
timestamp: h.time,
|
|
455
|
+
})),
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
460
|
+
return { items: [], notice: `历史对话检索暂不可用(DRSC collector: ${detail})。` };
|
|
461
|
+
}
|
|
445
462
|
},
|
|
446
463
|
}));
|
|
447
464
|
// ── memory_read_scene: 读取 L2 场景块 / L3 画像 ──
|
package/dsh.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-prime-memory",
|
|
3
3
|
"name": "dsh-prime-memory",
|
|
4
|
-
"version": "0.26.
|
|
4
|
+
"version": "0.26.5-beta.0",
|
|
5
5
|
"description": {
|
|
6
6
|
"en": "Layered distilled memory plugin (L0 capture → L1 atomic memory → L2 scenes → L3 persona) with automatic recall injection before each model step.",
|
|
7
7
|
"zh": "L0~L3 分层蒸馏记忆插件:自动捕获对话、抽取原子记忆、整合场景块、蒸馏核心画像,并在模型步骤前自动召回注入。"
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-prime-memory",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.5-beta.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org",
|
|
6
6
|
"access": "public",
|
|
7
|
-
"tag": "
|
|
7
|
+
"tag": "beta"
|
|
8
8
|
},
|
|
9
9
|
"description": "L0~L3 分层蒸馏记忆插件 for DeepSeek Harness:自动捕获对话(L0)、抽取原子记忆(L1)、整合场景块(L2)、蒸馏核心画像/团队方法论(L3),并在模型步骤前自动召回注入。移植自 MemoryCore (TencentDB Agent Memory) 的管线设计。",
|
|
10
10
|
"type": "module",
|
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
"@deepseek-ai/dsh-client-ui-primitives"
|
|
28
28
|
],
|
|
29
29
|
"platform": "web"
|
|
30
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"pluginDependencies": [
|
|
32
|
+
"dsh-reference-session-collector"
|
|
33
|
+
]
|
|
31
34
|
},
|
|
32
35
|
"files": [
|
|
33
36
|
"dist",
|
|
@@ -80,7 +83,8 @@
|
|
|
80
83
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
81
84
|
"@node-rs/jieba": "^2.0.2",
|
|
82
85
|
"sqlite-vec": "^0.1.7-alpha.2",
|
|
83
|
-
"undici": "^7.29.0"
|
|
86
|
+
"undici": "^7.29.0",
|
|
87
|
+
"dsh-reference-session-collector": ">=0.2.0-beta.0 <0.3.0"
|
|
84
88
|
},
|
|
85
89
|
"peerDependencies": {
|
|
86
90
|
"@deepseek-ai/cordis": "^4.0.1",
|