dsh-prime-memory 0.21.0 → 0.22.2
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/client.js +1581 -1150
- package/dist/config.d.ts +149 -0
- package/dist/config.js +35 -0
- package/dist/conflict-service.d.ts +8 -0
- package/dist/conflict-service.js +19 -0
- package/dist/contract.d.ts +131 -0
- package/dist/domain-gate.d.ts +8 -0
- package/dist/domain-gate.js +30 -0
- package/dist/graph/constraints.d.ts +4 -2
- package/dist/graph/constraints.js +4 -2
- package/dist/hooks/recall.d.ts +2 -0
- package/dist/hooks/recall.js +21 -2
- package/dist/hooks/skill-recall.d.ts +25 -0
- package/dist/hooks/skill-recall.js +72 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +26 -1
- package/dist/memport/format.d.ts +70 -0
- package/dist/memport/format.js +305 -0
- package/dist/memport/prefilter.d.ts +62 -0
- package/dist/memport/prefilter.js +132 -0
- package/dist/memport/scan.d.ts +13 -0
- package/dist/memport/scan.js +100 -0
- package/dist/metadata-validators.d.ts +22 -0
- package/dist/metadata-validators.js +45 -0
- package/dist/pipeline/l1.js +16 -2
- package/dist/pipeline/ruminate.d.ts +3 -0
- package/dist/pipeline/ruminate.js +50 -1
- package/dist/pipeline/slot-migrate.d.ts +45 -0
- package/dist/pipeline/slot-migrate.js +45 -0
- package/dist/projection/recall.d.ts +74 -0
- package/dist/projection/recall.js +148 -0
- package/dist/projection/slots.d.ts +5 -0
- package/dist/projection/slots.js +9 -2
- package/dist/prompts/graph-projection.js +3 -0
- package/dist/prompts/l1-extraction.d.ts +4 -1
- package/dist/prompts/l1-extraction.js +27 -4
- package/dist/settings.js +106 -11
- package/dist/skills/crystallize.d.ts +41 -0
- package/dist/skills/crystallize.js +75 -0
- package/dist/stats.d.ts +18 -1
- package/dist/stats.js +184 -5
- package/dist/store/file-versions.d.ts +2 -0
- package/dist/store/file-versions.js +2 -0
- package/dist/store/l1.d.ts +2 -0
- package/dist/store/l1.js +4 -0
- package/dist/store/memory-sources.d.ts +59 -0
- package/dist/store/memory-sources.js +214 -0
- package/dist/store/session-recalled.d.ts +25 -0
- package/dist/store/session-recalled.js +163 -0
- package/dist/store/skill-store.d.ts +99 -0
- package/dist/store/skill-store.js +330 -0
- package/dist/store/sqlite.d.ts +5 -0
- package/dist/store/sqlite.js +30 -4
- package/dist/tools/index.d.ts +0 -13
- package/dist/tools/index.js +58 -7
- package/dist/tools/skills.d.ts +13 -0
- package/dist/tools/skills.js +130 -0
- package/dist/types.d.ts +6 -0
- package/dist/util/maturity.d.ts +27 -0
- package/dist/util/maturity.js +26 -0
- package/dist/wing-backfill.js +7 -4
- package/dsh.plugin.json +2 -2
- package/package.json +14 -14
package/dist/hooks/recall.js
CHANGED
|
@@ -11,7 +11,7 @@ import { applyRecallBudget, raceRecallTimeout, RECALL_EMBED_CAP_MS } from '../ut
|
|
|
11
11
|
import { clearProfileShare, emptyOccupancyLedger, estimateInjectedMessageTokens, estimateStableSectionTokens, recordProfileShare, recordRecallInjection, resetForCompaction, } from '../util/context-occupancy.js';
|
|
12
12
|
import { errDetail } from '../util/filelog.js';
|
|
13
13
|
import { blocksToText } from '../util/text.js';
|
|
14
|
-
import { domainGate, formatWeights, hardFilterByWingLock, sortByDomainWeight, WING_ANCHORS } from '../domain-gate.js';
|
|
14
|
+
import { domainGate, formatWeights, hardFilterByWingLock, sortByDomainWeight, sortByUsageScenario, WING_ANCHORS } from '../domain-gate.js';
|
|
15
15
|
const PROFILE_TTL = 60_000;
|
|
16
16
|
/** 存储回填缓存上限(超过即按插入序淘汰最旧;查看会话数为百级,500 足够)。 */
|
|
17
17
|
const STORED_ESTIMATE_CACHE_CAP = 500;
|
|
@@ -209,7 +209,7 @@ usage) {
|
|
|
209
209
|
let ackDegradeWarned = false;
|
|
210
210
|
// §E 压缩感知(memorax-absorb):宿主 `compaction/end`(无 error)→ 该会话下一轮
|
|
211
211
|
// 做一次"定向增强召回"——跳过去重压制、画像立即重注入、占用账本归零;消费即清。
|
|
212
|
-
// 会话级回退路径保留(下方
|
|
212
|
+
// 会话级回退路径保留(下方 agent/created source='compact' 全量重置),两者幂等。
|
|
213
213
|
// 宿主无压缩计数器(compactionId 为 per-transaction UUID),故不做 generation 对账。
|
|
214
214
|
const postCompaction = new PostCompactionTracker();
|
|
215
215
|
ctx.on('session/event', (session, event) => {
|
|
@@ -225,6 +225,7 @@ usage) {
|
|
|
225
225
|
ctx.on('agent/created', async (payload) => {
|
|
226
226
|
if (payload.source === 'compact' || payload.source === 'clear') {
|
|
227
227
|
dedupe.reset(payload.agent.id);
|
|
228
|
+
stores.recalled?.reset(String(payload.agent.session?.id ?? payload.agent.id));
|
|
228
229
|
const led = ledgerFor(payload.agent.id);
|
|
229
230
|
resetForCompaction(led);
|
|
230
231
|
occupancyStore.save(payload.agent.id, led); // stock 归零 ⇒ 流水条目删除
|
|
@@ -372,6 +373,21 @@ usage) {
|
|
|
372
373
|
});
|
|
373
374
|
logger.info(`[memory] repo 软围栏:currentRepo=${currentRepoKey || '(未识别)'} 跨仓乘子=${cfg.recall.scopeFence.crossRepoMultiplier} agent=${payload.agent.id}`);
|
|
374
375
|
}
|
|
376
|
+
// ── G1 使用场景细排(默认关):命中 usageScenario 的记忆上浮,纯函数重排,score 不改写。
|
|
377
|
+
// 关闭时不进本分支(零 getByIds、零重排,召回逐字现状);无场景/未命中保持原序(fail-open)。
|
|
378
|
+
if (cfg.usageScenario?.enabled === true && scoped.length > 1) {
|
|
379
|
+
const scenarioById = new Map(stores.l1.getByIds(scoped.map((h) => h.id)).map((r) => [
|
|
380
|
+
r.id,
|
|
381
|
+
Array.isArray(r.metadata?.dsh_usage_scenario)
|
|
382
|
+
? r.metadata.dsh_usage_scenario
|
|
383
|
+
: [],
|
|
384
|
+
]));
|
|
385
|
+
const before = scoped.map((h) => h.id).join(',');
|
|
386
|
+
scoped = sortByUsageScenario(scoped, (id) => scenarioById.get(id) ?? [], query);
|
|
387
|
+
if (scoped.map((h) => h.id).join(',') !== before) {
|
|
388
|
+
logger.info(`[memory] 使用场景细排生效:agent=${payload.agent.id}`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
375
391
|
// 召回去重:同会话已注入过的记录不再重复注入(模型上下文已持有,省 token)。
|
|
376
392
|
// 纯过滤——剩几条注几条,全量压制(0 条新鲜命中)是正确状态而非未命中。
|
|
377
393
|
// §E:压缩后增强轮跳过压制(压缩把已注入内容逐出了模型上下文)。
|
|
@@ -442,6 +458,9 @@ usage) {
|
|
|
442
458
|
});
|
|
443
459
|
// 使用统计:候选=scoped(尝试),进 topN(注入)=used
|
|
444
460
|
usage?.recordAttempt(scoped.map((h) => h.id), fresh.slice(0, lines.length).map((h) => h.id));
|
|
461
|
+
// G-live:按 **sessionKey**(=agent.session?.id ?? agent.id,与 pill 的 sessionId / 投影 header.id 同源,
|
|
462
|
+
// 非 ownerId)记入本会话“活召回集”,供侧栏卡读取;压缩时同键 reset。
|
|
463
|
+
stores.recalled?.add(sessionKey, fresh.slice(0, lines.length).map((h) => h.id));
|
|
445
464
|
// 入账在成功构造注入消息之后、返回 enter 之前——任何前置抛错路径账目零扰动
|
|
446
465
|
const led = ledgerFor(payload.agent.id);
|
|
447
466
|
recordRecallInjection(led, text.length);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 技能常驻注入 Hook(轨2)。**默认关**(cfg.skills.enabled && cfg.skills.inject)。
|
|
3
|
+
*
|
|
4
|
+
* 完全对齐 `slot-recall.ts` 的范式(同一注入通道范本,不新建入口):
|
|
5
|
+
* - `agent/pre-step`(waterfall,prepend) 注入,`createUserMessage({source:{kind:'plugin:memory',form:'recall'}}})`
|
|
6
|
+
* ——**复用既有 source kind**,自动享受 `isOwnRecallSource` 双形状判据与召回去重/占用账本(S4 红线);
|
|
7
|
+
* - 帧体转义 `<\/system-reminder>` 防正文伪造帧边界;
|
|
8
|
+
* - **独立字节预算**(cfg.skills.maxPerTurnBytes),不与召回 2000 预算抢名额;
|
|
9
|
+
* - 注入前 `archiveDue` 机械闲置归档(0 LLM、不引入 timer,对齐 `slots.expireDue`)。
|
|
10
|
+
*
|
|
11
|
+
* 本轮语义:常驻注入全部 active 技能(按插入序 + 字节预算截断),**不做按触发词选择**
|
|
12
|
+
* (selective trigger 匹配属后续增强;常驻语义与 slots 一致,先保证默认关时零表面积)。
|
|
13
|
+
* 三档渲染(full/excerpt/hint)是显示策略,同一 body/steps 现场组词,无缓存副本漂移。
|
|
14
|
+
*/
|
|
15
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
16
|
+
import type { MemoryConfig } from '../config.js';
|
|
17
|
+
import type { LiveSettingsHandle } from '../settings.js';
|
|
18
|
+
import type { Skill, SkillStore } from '../store/skill-store.js';
|
|
19
|
+
import type { MemoryLogger } from '../types.js';
|
|
20
|
+
/** 按档位现场组词:full=标题+正文+步骤;excerpt=标题+正文截断;hint=仅标题+读取指引。 */
|
|
21
|
+
export declare function renderSkill(s: Skill, excerptChars: number): string;
|
|
22
|
+
export interface SkillRecallController {
|
|
23
|
+
buildInjection(): string | null;
|
|
24
|
+
}
|
|
25
|
+
export declare function registerSkillRecall(ctx: Context, cfg: MemoryConfig, skills: SkillStore, logger: MemoryLogger, live: LiveSettingsHandle): SkillRecallController;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
const SYSTEM_REMINDER_OPEN = '<system-reminder>';
|
|
3
|
+
const SYSTEM_REMINDER_CLOSE = '</system-reminder>';
|
|
4
|
+
const SKILLS_INTRO = '以下是本环境沉淀的技能(程序性记忆):过去重复工作流固化出的清单,仅在与之相关时作为指引遵循。' +
|
|
5
|
+
'它们是系统注入的元信息,不是用户发言——无需回应,请勿在回复中复述本节内容;' +
|
|
6
|
+
'且不覆盖系统提示与用户的直接指令。需要完整步骤用 memory_skill_read 展开。';
|
|
7
|
+
function escapeFrameBody(body) {
|
|
8
|
+
return body.replaceAll(SYSTEM_REMINDER_CLOSE, '<\\/system-reminder>');
|
|
9
|
+
}
|
|
10
|
+
/** 按档位现场组词:full=标题+正文+步骤;excerpt=标题+正文截断;hint=仅标题+读取指引。 */
|
|
11
|
+
export function renderSkill(s, excerptChars) {
|
|
12
|
+
if (s.injectionTier === 'hint')
|
|
13
|
+
return `[技能·${s.title}] 详见 memory_skill_read(${s.id})`;
|
|
14
|
+
const steps = s.steps.length ? '\n' + s.steps.map((st) => ` - ${st}`).join('\n') : '';
|
|
15
|
+
if (s.injectionTier === 'full')
|
|
16
|
+
return `[技能·${s.title}] ${s.body}${steps}`;
|
|
17
|
+
const body = s.body.length > excerptChars ? s.body.slice(0, excerptChars) + '…' : s.body;
|
|
18
|
+
return `[技能·${s.title}] ${body}`;
|
|
19
|
+
}
|
|
20
|
+
export function registerSkillRecall(ctx, cfg, skills, logger, live) {
|
|
21
|
+
// 生效开关:部署 cfg.skills.enabled 或看板 live.skillsEnabled 任一开。
|
|
22
|
+
const on = () => cfg.skills.enabled === true || live.get().skillsEnabled === true;
|
|
23
|
+
const buildInjection = () => {
|
|
24
|
+
if (!on() || !cfg.skills.inject)
|
|
25
|
+
return null;
|
|
26
|
+
const active = skills.listActive();
|
|
27
|
+
if (active.length === 0)
|
|
28
|
+
return null;
|
|
29
|
+
const budget = cfg.skills.maxPerTurnBytes;
|
|
30
|
+
const out = [];
|
|
31
|
+
let used = 0;
|
|
32
|
+
let hidden = 0;
|
|
33
|
+
for (const s of active) {
|
|
34
|
+
const rendered = renderSkill(s, cfg.skills.excerptChars);
|
|
35
|
+
const bytes = Buffer.byteLength(rendered, 'utf8');
|
|
36
|
+
if (used + bytes > budget) {
|
|
37
|
+
hidden++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
out.push(rendered);
|
|
41
|
+
used += bytes;
|
|
42
|
+
}
|
|
43
|
+
if (out.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
if (hidden > 0)
|
|
46
|
+
out.push(`… 另有 ${hidden} 个技能因预算未显示,可用 memory_skill_list 查看`);
|
|
47
|
+
return [SYSTEM_REMINDER_OPEN, SKILLS_INTRO, escapeFrameBody(out.join('\n')), SYSTEM_REMINDER_CLOSE].join('\n');
|
|
48
|
+
};
|
|
49
|
+
ctx.on('agent/pre-step', async (payload, next) => {
|
|
50
|
+
const decision = await next();
|
|
51
|
+
if (decision.kind === 'reject' || (payload.signal && payload.signal.aborted))
|
|
52
|
+
return decision;
|
|
53
|
+
if (!on() || !cfg.skills.inject)
|
|
54
|
+
return decision;
|
|
55
|
+
try {
|
|
56
|
+
await skills.archiveDue(Date.now(), cfg.skills.idleArchiveDays);
|
|
57
|
+
const text = buildInjection();
|
|
58
|
+
if (!text)
|
|
59
|
+
return decision;
|
|
60
|
+
const injection = createUserMessage({
|
|
61
|
+
content: [{ type: 'text', text }],
|
|
62
|
+
source: { kind: 'plugin:memory', form: 'recall' },
|
|
63
|
+
});
|
|
64
|
+
return { kind: 'enter', messages: [injection, ...decision.messages] };
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
logger.warn(`[memory] 技能注入失败(跳过本轮): ${err instanceof Error ? err.message : String(err)}`);
|
|
68
|
+
return decision;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return { buildInjection };
|
|
72
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -84,6 +84,51 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
84
84
|
maxPending: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
85
85
|
timeoutDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
86
86
|
}>>, "plain">;
|
|
87
|
+
memport: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
88
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
89
|
+
scanMaxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
90
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
91
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
92
|
+
scanMaxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
93
|
+
}>>, "plain">;
|
|
94
|
+
skills: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
95
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
96
|
+
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
97
|
+
allowPromote: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
98
|
+
minSessions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
99
|
+
minEvidence: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
100
|
+
maxPerTurnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
101
|
+
maxSkillCatalogBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
102
|
+
excerptChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
103
|
+
idleArchiveDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
104
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
105
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
106
|
+
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
107
|
+
allowPromote: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
108
|
+
minSessions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
109
|
+
minEvidence: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
110
|
+
maxPerTurnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
111
|
+
maxSkillCatalogBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
112
|
+
excerptChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
113
|
+
idleArchiveDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
114
|
+
}>>, "plain">;
|
|
115
|
+
backfill: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
116
|
+
maxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
117
|
+
timeBudgetMs: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
118
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
119
|
+
maxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
120
|
+
timeBudgetMs: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
121
|
+
}>>, "plain">;
|
|
122
|
+
usageScenario: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
123
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
124
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
125
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
126
|
+
}>>, "plain">;
|
|
127
|
+
narrativeTemplates: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
128
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
129
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
130
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
131
|
+
}>>, "plain">;
|
|
87
132
|
recall: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
88
133
|
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
89
134
|
maxResults: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
@@ -315,12 +360,14 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
315
360
|
maxSlots: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
316
361
|
maxAlwaysOnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
317
362
|
maxBodyChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
363
|
+
migrateLegacy: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
318
364
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
319
365
|
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
320
366
|
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
321
367
|
maxSlots: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
322
368
|
maxAlwaysOnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
323
369
|
maxBodyChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
370
|
+
migrateLegacy: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
324
371
|
}>>, "plain">;
|
|
325
372
|
tools: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
326
373
|
benchControl: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -421,6 +468,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
421
468
|
embedRemoteDimensions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
422
469
|
memoryMutate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
423
470
|
conflictFreeze: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
471
|
+
skillsEnabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
424
472
|
toolRoom: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
425
473
|
toolGraph: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
426
474
|
toolRuminate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -523,6 +571,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
523
571
|
embedRemoteDimensions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
524
572
|
memoryMutate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
525
573
|
conflictFreeze: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
574
|
+
skillsEnabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
526
575
|
toolRoom: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
527
576
|
toolGraph: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
528
577
|
toolRuminate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -598,6 +647,51 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
598
647
|
maxPending: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
599
648
|
timeoutDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
600
649
|
}>>, "plain">;
|
|
650
|
+
memport: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
651
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
652
|
+
scanMaxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
653
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
654
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
655
|
+
scanMaxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
656
|
+
}>>, "plain">;
|
|
657
|
+
skills: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
658
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
659
|
+
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
660
|
+
allowPromote: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
661
|
+
minSessions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
662
|
+
minEvidence: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
663
|
+
maxPerTurnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
664
|
+
maxSkillCatalogBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
665
|
+
excerptChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
666
|
+
idleArchiveDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
667
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
668
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
669
|
+
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
670
|
+
allowPromote: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
671
|
+
minSessions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
672
|
+
minEvidence: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
673
|
+
maxPerTurnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
674
|
+
maxSkillCatalogBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
675
|
+
excerptChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
676
|
+
idleArchiveDays: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
677
|
+
}>>, "plain">;
|
|
678
|
+
backfill: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
679
|
+
maxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
680
|
+
timeBudgetMs: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
681
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
682
|
+
maxRecords: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
683
|
+
timeBudgetMs: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
684
|
+
}>>, "plain">;
|
|
685
|
+
usageScenario: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
686
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
687
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
688
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
689
|
+
}>>, "plain">;
|
|
690
|
+
narrativeTemplates: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
691
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
692
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
693
|
+
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
694
|
+
}>>, "plain">;
|
|
601
695
|
recall: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
602
696
|
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
603
697
|
maxResults: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
@@ -829,12 +923,14 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
829
923
|
maxSlots: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
830
924
|
maxAlwaysOnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
831
925
|
maxBodyChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
926
|
+
migrateLegacy: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
832
927
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
833
928
|
enabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
834
929
|
inject: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
835
930
|
maxSlots: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
836
931
|
maxAlwaysOnBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
837
932
|
maxBodyChars: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
933
|
+
migrateLegacy: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
838
934
|
}>>, "plain">;
|
|
839
935
|
tools: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
840
936
|
benchControl: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -935,6 +1031,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
935
1031
|
embedRemoteDimensions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
936
1032
|
memoryMutate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
937
1033
|
conflictFreeze: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1034
|
+
skillsEnabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
938
1035
|
toolRoom: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
939
1036
|
toolGraph: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
940
1037
|
toolRuminate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -1037,6 +1134,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
1037
1134
|
embedRemoteDimensions: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
1038
1135
|
memoryMutate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1039
1136
|
conflictFreeze: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1137
|
+
skillsEnabled: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1040
1138
|
toolRoom: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1041
1139
|
toolGraph: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
1042
1140
|
toolRuminate: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { memorySchema, resolveDataDir } from './config.js';
|
|
|
13
13
|
import { registerBenchControl } from './bench-control.js';
|
|
14
14
|
import { registerCapture } from './hooks/capture.js';
|
|
15
15
|
import { registerRecall } from './hooks/recall.js';
|
|
16
|
+
import { SessionRecalledStore } from './store/session-recalled.js';
|
|
16
17
|
import { MemoryRunner } from './pipeline/runner.js';
|
|
17
18
|
import { RebuildController } from './pipeline/rebuild.js';
|
|
18
19
|
import { RuminateController } from './pipeline/ruminate.js';
|
|
@@ -37,8 +38,13 @@ import { registerMemoryTools } from './tools/index.js';
|
|
|
37
38
|
import { registerSlotTools } from './tools/slots.js';
|
|
38
39
|
import { registerSlotRecall } from './hooks/slot-recall.js';
|
|
39
40
|
import { RoomRegistryStore } from './store/rooms-registry.js';
|
|
41
|
+
import { MemorySourceStore } from './store/memory-sources.js';
|
|
42
|
+
import { SkillStore } from './store/skill-store.js';
|
|
43
|
+
import { registerSkillRecall } from './hooks/skill-recall.js';
|
|
44
|
+
import { registerSkillTools } from './tools/skills.js';
|
|
40
45
|
import { RecallUsageStore } from './store/recall-usage.js';
|
|
41
46
|
import { registerSlotsProjection } from './projection/slots.js';
|
|
47
|
+
import { registerRecallProjection } from './projection/recall.js';
|
|
42
48
|
import { errDetail, withFileLog } from './util/filelog.js';
|
|
43
49
|
import { buildRouteChain, resolveModelRoute, invalidateEffortCache } from './llm.js';
|
|
44
50
|
import { effectiveCfg } from './pipeline/runner.js';
|
|
@@ -175,6 +181,8 @@ export async function apply(ctx, config) {
|
|
|
175
181
|
work: new PersonaStore(dataDir, 'work', logger),
|
|
176
182
|
},
|
|
177
183
|
state: new StateStore(StateStore.pathFor(dataDir), logger),
|
|
184
|
+
// 会话“活召回集”(G-live):sessionKey → 本会话已注入未压缩的记录 id;持久化,旧会话重开载回。
|
|
185
|
+
recalled: new SessionRecalledStore(dataDir, logger),
|
|
178
186
|
// 激活槽位(active slot):独立 slots.json,高频小改不拖累 checkpoint 原子写
|
|
179
187
|
slots: new SlotStore(SlotStore.pathFor(dataDir), logger, {
|
|
180
188
|
maxSlots: config.slots.maxSlots,
|
|
@@ -356,6 +364,12 @@ export async function apply(ctx, config) {
|
|
|
356
364
|
// Room 注册表(分类管理 beta.4;损坏降级为纯自生长目录)
|
|
357
365
|
const roomRegistry = new RoomRegistryStore(dataDir, logger);
|
|
358
366
|
await roomRegistry.init();
|
|
367
|
+
// 外部记忆来源注册表(轨3 Connect;默认由 cfg.memport.enabled 关门控,sidecar 本身无条件加载)
|
|
368
|
+
const memorySources = new MemorySourceStore(dataDir, logger);
|
|
369
|
+
await memorySources.init();
|
|
370
|
+
// 技能存储(轨2;sidecar 无条件加载,但工具/注入均由 cfg.skills.enabled 默认关自 no-op)
|
|
371
|
+
const skillStore = new SkillStore(dataDir, logger);
|
|
372
|
+
await skillStore.init();
|
|
359
373
|
const ruminate = storageOk && !db.isDegraded() && ruminateFile
|
|
360
374
|
? new RuminateController(ctx, config, runner, stores, logger, live, ruminateFile, roomRegistry)
|
|
361
375
|
: undefined;
|
|
@@ -373,7 +387,18 @@ export async function apply(ctx, config) {
|
|
|
373
387
|
// 激活槽位(active slot):工具面 + 常驻注入 + 服务端投影(均走 ctx.effect,可撤销)
|
|
374
388
|
registerSlotTools(ctx, config, stores.slots, logger, modes, live, stores.l1);
|
|
375
389
|
const slotRecall = registerSlotRecall(ctx, config, stores.slots, logger, live);
|
|
390
|
+
// 轨2 技能:工具面与常驻注入(均 cfg.skills.enabled 默认关时自 no-op,零表面积)。
|
|
391
|
+
registerSkillTools(ctx, config, skillStore, logger, live);
|
|
392
|
+
registerSkillRecall(ctx, config, skillStore, logger, live);
|
|
393
|
+
// memorySlots 投影:常驻槽位(手动 pin 的约定)的展示契约,消费方是 dsh-brief-sidebar。
|
|
394
|
+
// 宿主契约(dsh-session-projection/lib/index.js):插件不注册时 key 从快照消失、
|
|
395
|
+
// 客户端读作 capability absence(不会毒化历史加载),所以“摘注册”技术上可行;
|
|
396
|
+
// 但那是把跨插件展示契约直接抽掉,旧版 brief-sidebar 会默默丢分区——隐藏请走它自己的
|
|
397
|
+
// 「记忆槽位分区」开关。本包另提供一个会话感知的 memoryRecall 投影。
|
|
376
398
|
registerSlotsProjection(ctx, stores.slots, stores.l1);
|
|
399
|
+
// memoryRecall 投影:本会话“已注入且未被压缩覆盖”的召回集(会话感知,init 取 header.id),
|
|
400
|
+
// 与常驻槽位是两条轴:那个是手动 pin 的硬注入约定,这个是非常驻的相关性浮现结果。
|
|
401
|
+
registerRecallProjection(ctx, stores.recalled, stores.l1);
|
|
377
402
|
void slotRecall;
|
|
378
403
|
registerMemoryRpc(ctx, config, stores, logger, {
|
|
379
404
|
degraded: () => !storageOk || db.isDegraded(),
|
|
@@ -388,7 +413,7 @@ export async function apply(ctx, config) {
|
|
|
388
413
|
runnerView: (sid, mode) => runner.sessionView(sid, mode),
|
|
389
414
|
l0Count: (sid) => stores.l0.countBySession(sid),
|
|
390
415
|
capabilities: () => db.getCapabilities(),
|
|
391
|
-
}, ruminate, storageOk ? roomRegistry : undefined);
|
|
416
|
+
}, ruminate, storageOk ? roomRegistry : undefined, storageOk ? memorySources : undefined, skillStore);
|
|
392
417
|
// bench 控制服务(config.benchControl 门控,默认关):仅基准/调试部署注册,
|
|
393
418
|
// 供同进程的 bench-runner lifecycle 赛道触发 rebuild / 设置会话档位
|
|
394
419
|
// (宿主侧 RPC 无 call(),见 bench-control.ts)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** MMF v1.1 默认列序(缺 `#cols=` 时按此解析;v1 包缺 vf/vt/st 列按 -/-/? 补齐)。 */
|
|
2
|
+
export declare const DEFAULT_COLS: readonly ["type", "created", "updated", "vf", "vt", "st", "cf", "rw", "tags", "content"];
|
|
3
|
+
/** 类型码 → 运行时 type(与 memport.py TYPE_CODES 一字不差)。 */
|
|
4
|
+
export declare const TYPE_CODES: Record<string, string>;
|
|
5
|
+
/** 持续性取值域:p 时点 / s 已结束区间 / o 仍在持续 / t 无时间性 / ? 未判定。 */
|
|
6
|
+
export declare const PERSISTENCE: readonly ["p", "s", "o", "t", "?"];
|
|
7
|
+
export interface MemRecord {
|
|
8
|
+
seq: number;
|
|
9
|
+
type: string;
|
|
10
|
+
typeFull: string;
|
|
11
|
+
created: string;
|
|
12
|
+
updated: string;
|
|
13
|
+
vf: string;
|
|
14
|
+
vt: string;
|
|
15
|
+
st: string;
|
|
16
|
+
cf: string;
|
|
17
|
+
rw: string;
|
|
18
|
+
tags: Record<string, string>;
|
|
19
|
+
content: string;
|
|
20
|
+
hash: string;
|
|
21
|
+
createdMs: number | null;
|
|
22
|
+
createdPrec: string;
|
|
23
|
+
updatedMs: number | null;
|
|
24
|
+
updatedPrec: string;
|
|
25
|
+
vfMs: number | null;
|
|
26
|
+
vfPrec: string;
|
|
27
|
+
vtMs: number | null;
|
|
28
|
+
vtPrec: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Bundle {
|
|
31
|
+
header: Record<string, string>;
|
|
32
|
+
cols: string[];
|
|
33
|
+
records: MemRecord[];
|
|
34
|
+
errors: string[];
|
|
35
|
+
warnings: string[];
|
|
36
|
+
declaredCount: number | null;
|
|
37
|
+
declaredSha: string | null;
|
|
38
|
+
/** 记录体原始行(未去转义),用于校验和复算——与 Python `body` 对齐。 */
|
|
39
|
+
bodyLines: string[];
|
|
40
|
+
}
|
|
41
|
+
/** NFKC + 空白折叠 + 去首尾(用于哈希与相似度,不改原文)。 */
|
|
42
|
+
export declare function normText(s: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* 内容哈希:sha256(normText + 小写)[:16]。
|
|
45
|
+
* 注意:Python 用 casefold(激进大小写折叠),JS 用 toLowerCase;
|
|
46
|
+
* 对 CJK/ASCII 记忆正文等价,仅极端 Unicode 有别——实际记忆集不含此类,
|
|
47
|
+
* 跨实现金标准走包级 sha256(不逐条折叠),不受影响。
|
|
48
|
+
*/
|
|
49
|
+
export declare function contentHash(s: string): string;
|
|
50
|
+
/** 记录稳定 id:`mp_` + sha256(src|chash)[:16]。 */
|
|
51
|
+
export declare function recordId(src: string, chash: string): string;
|
|
52
|
+
/** 解码内容列:反斜杠+反斜杠 → 单反斜杠;反斜杠+n → 换行(其余反斜杠原样)。 */
|
|
53
|
+
export declare function unescapeContent(s: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* 编码内容列:反斜杠 → 双反斜杠、CRLF → LF、LF → 反斜杠+n。
|
|
56
|
+
* 用 charCode 常量而非控制字符字面量,避免跨工具写盘时 CR/LF 被吞进正则/字符串字面量。
|
|
57
|
+
*/
|
|
58
|
+
export declare function escapeContent(s: string): string;
|
|
59
|
+
/** `k:v;k:v` → 对象(缺冒号的段忽略)。 */
|
|
60
|
+
export declare function parseTags(raw: string): Record<string, string>;
|
|
61
|
+
/** 时间串 → { ms|null, precision }(镜像 Python parse_time;naive 视为本地)。 */
|
|
62
|
+
export declare function parseTime(raw: string): {
|
|
63
|
+
ms: number | null;
|
|
64
|
+
precision: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* 解析整包文本 → Bundle(含结构校验)。镜像 memport.py parse_bundle。
|
|
68
|
+
* 入参是字符串(调用方读文件时自带编码处理);此处容错剥离 BOM。
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseBundle(text: string): Bundle;
|