dsh-prime-memory 0.22.1 → 0.24.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/CHANGELOG.en.md +401 -0
- package/CHANGELOG.ja.md +401 -0
- package/CHANGELOG.ko.md +401 -0
- package/CHANGELOG.md +100 -0
- package/dist/client.js +1951 -1188
- package/dist/config.d.ts +176 -1240
- package/dist/config.js +113 -2
- package/dist/conflict-service.d.ts +12 -0
- package/dist/conflict-service.js +24 -0
- package/dist/contract.d.ts +327 -0
- package/dist/domain-gate.d.ts +19 -0
- package/dist/domain-gate.js +45 -0
- package/dist/graph/constraints.d.ts +4 -2
- package/dist/graph/constraints.js +4 -2
- package/dist/hooks/obsolete-notice.d.ts +26 -0
- package/dist/hooks/obsolete-notice.js +64 -0
- package/dist/hooks/recall.d.ts +41 -0
- package/dist/hooks/recall.js +127 -28
- package/dist/hooks/skill-recall.d.ts +25 -0
- package/dist/hooks/skill-recall.js +72 -0
- package/dist/index.d.ts +1 -1029
- package/dist/index.js +55 -2
- package/dist/memory-types.d.ts +69 -0
- package/dist/memory-types.js +165 -0
- package/dist/memport/format.d.ts +75 -0
- package/dist/memport/format.js +345 -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.d.ts +44 -2
- package/dist/pipeline/l1.js +177 -9
- package/dist/pipeline/md-sync.d.ts +65 -0
- package/dist/pipeline/md-sync.js +456 -0
- package/dist/pipeline/ruminate.d.ts +46 -1
- package/dist/pipeline/ruminate.js +150 -1
- package/dist/pipeline/runner.d.ts +10 -0
- package/dist/pipeline/runner.js +7 -1
- package/dist/pipeline/slot-migrate.d.ts +45 -0
- package/dist/pipeline/slot-migrate.js +45 -0
- package/dist/pipeline/workspace-relink.d.ts +60 -0
- package/dist/pipeline/workspace-relink.js +73 -0
- package/dist/projection/recall.d.ts +112 -0
- package/dist/projection/recall.js +183 -0
- package/dist/projection/slots.d.ts +5 -0
- package/dist/prompts/examples.d.ts +73 -0
- package/dist/prompts/examples.js +178 -0
- package/dist/prompts/graph-projection.js +3 -0
- package/dist/prompts/l1-dedup.d.ts +9 -3
- package/dist/prompts/l1-dedup.js +34 -13
- package/dist/prompts/l1-extraction.d.ts +9 -4
- package/dist/prompts/l1-extraction.js +76 -8
- package/dist/settings.d.ts +8 -0
- package/dist/settings.js +15 -1
- package/dist/skills/crystallize.d.ts +41 -0
- package/dist/skills/crystallize.js +75 -0
- package/dist/stats.d.ts +30 -1
- package/dist/stats.js +504 -13
- package/dist/store/embedding-source.d.ts +8 -0
- package/dist/store/embedding-source.js +39 -2
- package/dist/store/file-versions.d.ts +4 -0
- package/dist/store/file-versions.js +4 -0
- package/dist/store/graph-store.d.ts +14 -0
- package/dist/store/graph-store.js +35 -0
- package/dist/store/l1-snapshot.d.ts +26 -1
- package/dist/store/l1-snapshot.js +53 -8
- package/dist/store/l1.d.ts +77 -3
- package/dist/store/l1.js +128 -3
- package/dist/store/memory-md-archive.d.ts +84 -0
- package/dist/store/memory-md-archive.js +155 -0
- package/dist/store/memory-md-disable.d.ts +23 -0
- package/dist/store/memory-md-disable.js +106 -0
- package/dist/store/memory-md-export.d.ts +50 -0
- package/dist/store/memory-md-export.js +200 -0
- package/dist/store/memory-md-ledger.d.ts +94 -0
- package/dist/store/memory-md-ledger.js +243 -0
- package/dist/store/memory-md-orphan.d.ts +27 -0
- package/dist/store/memory-md-orphan.js +153 -0
- package/dist/store/memory-md-parse.d.ts +35 -0
- package/dist/store/memory-md-parse.js +85 -0
- package/dist/store/memory-md-skeleton.d.ts +18 -0
- package/dist/store/memory-md-skeleton.js +61 -0
- package/dist/store/memory-md-types.d.ts +174 -0
- package/dist/store/memory-md-types.js +10 -0
- package/dist/store/memory-md.d.ts +108 -0
- package/dist/store/memory-md.js +219 -0
- package/dist/store/memory-sources.d.ts +59 -0
- package/dist/store/memory-sources.js +214 -0
- package/dist/store/obsolete-notices.d.ts +39 -0
- package/dist/store/obsolete-notices.js +153 -0
- package/dist/store/recall-feedback.d.ts +75 -0
- package/dist/store/recall-feedback.js +213 -0
- package/dist/store/recall-usage.d.ts +11 -0
- package/dist/store/recall-usage.js +29 -0
- package/dist/store/session-recalled.d.ts +60 -0
- package/dist/store/session-recalled.js +310 -0
- package/dist/store/skill-store.d.ts +99 -0
- package/dist/store/skill-store.js +330 -0
- package/dist/store/sqlite.d.ts +71 -0
- package/dist/store/sqlite.js +259 -15
- package/dist/store/supersede.d.ts +1 -1
- package/dist/store/supersede.js +1 -1
- package/dist/tools/index.d.ts +4 -13
- package/dist/tools/index.js +80 -12
- package/dist/tools/skills.d.ts +13 -0
- package/dist/tools/skills.js +130 -0
- package/dist/types.d.ts +30 -7
- package/dist/types.js +10 -2
- package/dist/util/maturity.d.ts +44 -0
- package/dist/util/maturity.js +43 -0
- package/dist/util/md-name.d.ts +129 -0
- package/dist/util/md-name.js +366 -0
- package/dist/util/md-normalize.d.ts +23 -0
- package/dist/util/md-normalize.js +131 -0
- package/dist/wing-backfill.js +7 -4
- package/dist/workspace-route.d.ts +22 -0
- package/dist/workspace-route.js +66 -0
- package/dsh.plugin.json +1 -1
- package/package.json +6 -5
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';
|
|
@@ -36,9 +37,18 @@ import { SlotStore } from './store/slots.js';
|
|
|
36
37
|
import { registerMemoryTools } from './tools/index.js';
|
|
37
38
|
import { registerSlotTools } from './tools/slots.js';
|
|
38
39
|
import { registerSlotRecall } from './hooks/slot-recall.js';
|
|
40
|
+
import { registerObsoleteNotice } from './hooks/obsolete-notice.js';
|
|
39
41
|
import { RoomRegistryStore } from './store/rooms-registry.js';
|
|
42
|
+
import { MemorySourceStore } from './store/memory-sources.js';
|
|
43
|
+
import { SkillStore } from './store/skill-store.js';
|
|
44
|
+
import { registerSkillRecall } from './hooks/skill-recall.js';
|
|
45
|
+
import { registerSkillTools } from './tools/skills.js';
|
|
40
46
|
import { RecallUsageStore } from './store/recall-usage.js';
|
|
47
|
+
import { RecallFeedbackStore } from './store/recall-feedback.js';
|
|
48
|
+
import { MdLedgerStore } from './store/memory-md-ledger.js';
|
|
49
|
+
import { ObsoleteNoticeStore } from './store/obsolete-notices.js';
|
|
41
50
|
import { registerSlotsProjection } from './projection/slots.js';
|
|
51
|
+
import { registerRecallProjection } from './projection/recall.js';
|
|
42
52
|
import { errDetail, withFileLog } from './util/filelog.js';
|
|
43
53
|
import { buildRouteChain, resolveModelRoute, invalidateEffortCache } from './llm.js';
|
|
44
54
|
import { effectiveCfg } from './pipeline/runner.js';
|
|
@@ -164,7 +174,10 @@ export async function apply(ctx, config) {
|
|
|
164
174
|
l0: new L0Store(dataDir, db, embed, logger),
|
|
165
175
|
l1: new L1Store(dataDir, db, embed, config.recall.strategy, logger, config.recall.decayHalfLifeDays,
|
|
166
176
|
// §D 第 3 路:图谱回链。图谱不可用时 searchNodes 自带 no-op,不影响双路。
|
|
167
|
-
(query, limit, family) => db.graphStore.searchNodes(query, limit, family ? [family] : undefined)
|
|
177
|
+
(query, limit, family) => db.graphStore.searchNodes(query, limit, family ? [family] : undefined),
|
|
178
|
+
// 投射开着才给没名字的新记录起名(“关时零动作”这条承诺不改)。
|
|
179
|
+
// 传函数而不是布尔:读的是当前配置对象,不把启动那一刻的值钉进 store。
|
|
180
|
+
() => config.memExport?.enabled === true),
|
|
168
181
|
// L2/L3 分族隔离:各自目录与文件(scenes/chat|work、persona-chat|work.md)
|
|
169
182
|
scenes: {
|
|
170
183
|
chat: new SceneStore(dataDir, 'chat', logger),
|
|
@@ -175,6 +188,13 @@ export async function apply(ctx, config) {
|
|
|
175
188
|
work: new PersonaStore(dataDir, 'work', logger),
|
|
176
189
|
},
|
|
177
190
|
state: new StateStore(StateStore.pathFor(dataDir), logger),
|
|
191
|
+
// 会话“活召回集”(G-live):sessionKey → 本会话已注入未压缩的记录 id;持久化,旧会话重开载回。
|
|
192
|
+
recalled: new SessionRecalledStore(dataDir, logger),
|
|
193
|
+
// 召回相关度反馈与过时播报队列(装配于下方,需 await init)。
|
|
194
|
+
feedback: undefined,
|
|
195
|
+
notices: undefined,
|
|
196
|
+
// md 投射指纹账本(N9;装配于下方,需 await init)。
|
|
197
|
+
mdLedger: undefined,
|
|
178
198
|
// 激活槽位(active slot):独立 slots.json,高频小改不拖累 checkpoint 原子写
|
|
179
199
|
slots: new SlotStore(SlotStore.pathFor(dataDir), logger, {
|
|
180
200
|
maxSlots: config.slots.maxSlots,
|
|
@@ -356,6 +376,12 @@ export async function apply(ctx, config) {
|
|
|
356
376
|
// Room 注册表(分类管理 beta.4;损坏降级为纯自生长目录)
|
|
357
377
|
const roomRegistry = new RoomRegistryStore(dataDir, logger);
|
|
358
378
|
await roomRegistry.init();
|
|
379
|
+
// 外部记忆来源注册表(轨3 Connect;默认由 cfg.memport.enabled 关门控,sidecar 本身无条件加载)
|
|
380
|
+
const memorySources = new MemorySourceStore(dataDir, logger);
|
|
381
|
+
await memorySources.init();
|
|
382
|
+
// 技能存储(轨2;sidecar 无条件加载,但工具/注入均由 cfg.skills.enabled 默认关自 no-op)
|
|
383
|
+
const skillStore = new SkillStore(dataDir, logger);
|
|
384
|
+
await skillStore.init();
|
|
359
385
|
const ruminate = storageOk && !db.isDegraded() && ruminateFile
|
|
360
386
|
? new RuminateController(ctx, config, runner, stores, logger, live, ruminateFile, roomRegistry)
|
|
361
387
|
: undefined;
|
|
@@ -367,13 +393,40 @@ export async function apply(ctx, config) {
|
|
|
367
393
|
const recallUsage = new RecallUsageStore(dataDir, logger);
|
|
368
394
|
await recallUsage.init();
|
|
369
395
|
stores.usage = recallUsage;
|
|
396
|
+
// 召回相关度反馈(人在召回卡上打 -1..5)与「已声明过时」待播报队列。
|
|
397
|
+
// 两个都是低频用户动作 → 立即落盘;sidecar 缺席/损坏只降级为只读,不阻断任何读路径。
|
|
398
|
+
const recallFeedback = new RecallFeedbackStore(dataDir, logger);
|
|
399
|
+
await recallFeedback.init();
|
|
400
|
+
stores.feedback = recallFeedback;
|
|
401
|
+
const obsoleteNotices = new ObsoleteNoticeStore(dataDir, logger);
|
|
402
|
+
await obsoleteNotices.init();
|
|
403
|
+
stores.notices = obsoleteNotices;
|
|
404
|
+
// md 投射指纹账本(N9):派生态,缺席/损坏只降级为只读,不弄挂任何读路径。
|
|
405
|
+
// 它与 feedback/notices 同属“库外 sidecar”,不进快照哈希投影。
|
|
406
|
+
const mdLedger = new MdLedgerStore(dataDir, logger);
|
|
407
|
+
await mdLedger.init();
|
|
408
|
+
stores.mdLedger = mdLedger;
|
|
370
409
|
const recall = registerRecall(ctx, config, stores, logger, live, modes, dataDir, recallUsage);
|
|
371
410
|
runner.setAfterRun(recall.invalidateProfile);
|
|
372
411
|
registerMemoryTools(ctx, config, stores, logger, modes, live, ruminate, storageOk ? roomRegistry : undefined);
|
|
373
412
|
// 激活槽位(active slot):工具面 + 常驻注入 + 服务端投影(均走 ctx.effect,可撤销)
|
|
374
413
|
registerSlotTools(ctx, config, stores.slots, logger, modes, live, stores.l1);
|
|
375
414
|
const slotRecall = registerSlotRecall(ctx, config, stores.slots, logger, live);
|
|
415
|
+
// 轨2 技能:工具面与常驻注入(均 cfg.skills.enabled 默认关时自 no-op,零表面积)。
|
|
416
|
+
registerSkillTools(ctx, config, skillStore, logger, live);
|
|
417
|
+
registerSkillRecall(ctx, config, skillStore, logger, live);
|
|
418
|
+
// memorySlots 投影:常驻槽位(手动 pin 的约定)的展示契约,消费方是 dsh-brief-sidebar。
|
|
419
|
+
// 宿主契约(dsh-session-projection/lib/index.js):插件不注册时 key 从快照消失、
|
|
420
|
+
// 客户端读作 capability absence(不会毒化历史加载),所以“摘注册”技术上可行;
|
|
421
|
+
// 但那是把跨插件展示契约直接抽掉,旧版 brief-sidebar 会默默丢分区——隐藏请走它自己的
|
|
422
|
+
// 「记忆槽位分区」开关。本包另提供一个会话感知的 memoryRecall 投影。
|
|
376
423
|
registerSlotsProjection(ctx, stores.slots, stores.l1);
|
|
424
|
+
// memoryRecall 投影:本会话“已注入且未被压缩覆盖”的召回集(会话感知,init 取 header.id),
|
|
425
|
+
// 与常驻槽位是两条轴:那个是手动 pin 的硬注入约定,这个是非常驻的相关性浮现结果。
|
|
426
|
+
// 带上反馈面:条目要显示人已经打过的那一笔(rating)。
|
|
427
|
+
registerRecallProjection(ctx, stores.recalled, stores.l1, recallFeedback);
|
|
428
|
+
// 人打 -1 声明过时后,下一轮向模型一次性播报“这条已退场、别再依据它作答”。
|
|
429
|
+
registerObsoleteNotice(ctx, config, obsoleteNotices, logger);
|
|
377
430
|
void slotRecall;
|
|
378
431
|
registerMemoryRpc(ctx, config, stores, logger, {
|
|
379
432
|
degraded: () => !storageOk || db.isDegraded(),
|
|
@@ -388,7 +441,7 @@ export async function apply(ctx, config) {
|
|
|
388
441
|
runnerView: (sid, mode) => runner.sessionView(sid, mode),
|
|
389
442
|
l0Count: (sid) => stores.l0.countBySession(sid),
|
|
390
443
|
capabilities: () => db.getCapabilities(),
|
|
391
|
-
}, ruminate, storageOk ? roomRegistry : undefined);
|
|
444
|
+
}, ruminate, storageOk ? roomRegistry : undefined, storageOk ? memorySources : undefined, skillStore);
|
|
392
445
|
// bench 控制服务(config.benchControl 门控,默认关):仅基准/调试部署注册,
|
|
393
446
|
// 供同进程的 bench-runner lifecycle 赛道触发 rebuild / 设置会话档位
|
|
394
447
|
// (宿主侧 RPC 无 call(),见 bench-control.ts)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 记忆类型词表的**唯一事实源**(pm-name-distill A 节)。
|
|
3
|
+
*
|
|
4
|
+
* 在此之前,"类型全集"手抄在四处:`MEMORY_TYPE_DIRS`(投射目录)、`ADD_TYPES`(写入白名单)、
|
|
5
|
+
* `TYPE_LABELS`(面板标签)、抽取/去重 prompt 的枚举串。四处各自演化过——宿主记忆分类
|
|
6
|
+
* (29 类)与插件 7 类字面交集为空,`memory_add` 把外部分类**静默改写**成 `episodic`,
|
|
7
|
+
* 而 memport 的警告文案却承诺"按原样透传"。同一件事两套口径,漂移只是时间问题。
|
|
8
|
+
*
|
|
9
|
+
* 词表内容 = **宿主 29 类原名**(与 memport 导入的分类字面一致,不再造 `dev_*`/`exp_*`
|
|
10
|
+
* 那层映射——映射层每多一处就多一处漂移)+ 插件旧 7 类(库里 1166 条正带着它们,
|
|
11
|
+
* 不许一夜之间全变 `unclassified`)+ `unclassified` 兜底目录。
|
|
12
|
+
*
|
|
13
|
+
* 本文件必须**零依赖运行**(不引 node: 模块):client 侧与 server 侧同源消费,
|
|
14
|
+
* prompt 渲染也从这里派生。
|
|
15
|
+
*/
|
|
16
|
+
/** 类型族(与 `types.ts` 的 `MemoryFamily` 同域;这里重述字面量以免运行时循环引用)。 */
|
|
17
|
+
export type TypeFamily = 'chat' | 'work';
|
|
18
|
+
/** 宿主记忆分类的 29 类原名(实测自宿主记忆目录树,条数分布见计划 findings 第一节)。 */
|
|
19
|
+
export declare const HOST_MEMORY_TYPES: readonly string[];
|
|
20
|
+
/** 插件早期 7 类(蒸馏管线现役词表;库里存量正带着,永久保留)。 */
|
|
21
|
+
export declare const LEGACY_MEMORY_TYPES: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* 兜底目录名(不是可赋值类型):不在词表的 `type` 原值照旧写进 frontmatter,
|
|
24
|
+
* 只在**目录层**归这里。归进某个 `work_*` 会静默把这批记录的 family 挑到 work 侧
|
|
25
|
+
* (family 决定共享面),所以它自成一桶、族取 chat。
|
|
26
|
+
*/
|
|
27
|
+
export declare const UNCLASSIFIED_DIR = "unclassified";
|
|
28
|
+
/**
|
|
29
|
+
* 非词表 type 进入写路径时的降级目标。旧代码在 `tools/index.ts` 里把 `'episodic'`
|
|
30
|
+
* 当字面量散写;集中到这里,降级行为至少有一个可 grep 的名字。
|
|
31
|
+
*/
|
|
32
|
+
export declare const DOWNGRADE_TARGET = "episodic";
|
|
33
|
+
/** 可赋值类型全集(宿主 29 + 旧 7 = 36;`unclassified` 不在其中——它是目录,不是类型)。 */
|
|
34
|
+
export declare const MEMORY_TYPE_VOCABULARY: ReadonlySet<string>;
|
|
35
|
+
/**
|
|
36
|
+
* 族映射(新旧同放)。旧 `familyForType` 靠 `type.startsWith('work')` 前缀猜族,
|
|
37
|
+
* 新词表里 `project_*`/`development_*`/`*_experience` 都是 work 族却不带 work 前缀——
|
|
38
|
+
* 前缀判定会把它们静默归进 chat,而 family 决定召回/浏览/去重的共享面。
|
|
39
|
+
*/
|
|
40
|
+
export declare const TYPE_FAMILY_MAP: Readonly<Record<string, TypeFamily>>;
|
|
41
|
+
/** 类型 → 面板中文标签(真源;client 侧经 `list-records` 的 `typeCatalog` 下发消费)。 */
|
|
42
|
+
export declare const MEMORY_TYPE_LABELS: Readonly<Record<string, string>>;
|
|
43
|
+
/** 投射目录全集 = 可赋值类型 + 兜底桶(37 个)。`memory-md.ts` 的白名单从这里派生。 */
|
|
44
|
+
export declare function memoryTypeDirs(): ReadonlySet<string>;
|
|
45
|
+
/** 是否为词表内类型(写路径白名单判据;`unclassified` 不算——没人该主动赋它)。 */
|
|
46
|
+
export declare function isKnownType(type: string): boolean;
|
|
47
|
+
/** 族查询:查表;未知值回落旧前缀规则并交给 `onUnknownFamily` 提醒一次。 */
|
|
48
|
+
export declare function familyOf(type: string): TypeFamily;
|
|
49
|
+
/**
|
|
50
|
+
* CSS 类名用的 slug(`work_fact` → `work-fact`)。
|
|
51
|
+
*
|
|
52
|
+
* 面板标签类名以前直接拼 `type` 原值(下划线),而主题 CSS 定义的是连字符类——
|
|
53
|
+
* `dsh-mem-tag-work_fact` 匹配不上 `.dsh-mem-tag-work-fact`,标签无色(F11 既有断裂)。
|
|
54
|
+
* 拼接点统一走这里,判据只有一份。
|
|
55
|
+
*/
|
|
56
|
+
export declare function slugOf(type: string): string;
|
|
57
|
+
/** 面板词表目录(下发给 client 的 `typeCatalog`;含兜底桶,顺序 = 旧 7 → 宿主 29 → 兜底)。 */
|
|
58
|
+
export declare function typeCatalogEntries(): Array<{
|
|
59
|
+
id: string;
|
|
60
|
+
label: string;
|
|
61
|
+
}>;
|
|
62
|
+
/** chat / work 族的可赋值类型(prompt 枚举串从这里渲染,不再手抄)。 */
|
|
63
|
+
export declare function typesOfFamily(family: TypeFamily): string[];
|
|
64
|
+
/** prompt/工具描述用的枚举串(`|` 或 `/` 连接,顺序稳定:旧 7 在前)。 */
|
|
65
|
+
export declare function typeEnumSep(sep: string, family?: TypeFamily): string;
|
|
66
|
+
/** 测试/宿主接线用:替换未知族的提醒出口(传 undefined 恢复 console)。 */
|
|
67
|
+
export declare function setFamilyWarnSink(sink?: (msg: string) => void): void;
|
|
68
|
+
/** 清空"已提醒"集(用例要能反复断言只 warn 一次)。 */
|
|
69
|
+
export declare function resetFamilyWarned(): void;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 记忆类型词表的**唯一事实源**(pm-name-distill A 节)。
|
|
3
|
+
*
|
|
4
|
+
* 在此之前,"类型全集"手抄在四处:`MEMORY_TYPE_DIRS`(投射目录)、`ADD_TYPES`(写入白名单)、
|
|
5
|
+
* `TYPE_LABELS`(面板标签)、抽取/去重 prompt 的枚举串。四处各自演化过——宿主记忆分类
|
|
6
|
+
* (29 类)与插件 7 类字面交集为空,`memory_add` 把外部分类**静默改写**成 `episodic`,
|
|
7
|
+
* 而 memport 的警告文案却承诺"按原样透传"。同一件事两套口径,漂移只是时间问题。
|
|
8
|
+
*
|
|
9
|
+
* 词表内容 = **宿主 29 类原名**(与 memport 导入的分类字面一致,不再造 `dev_*`/`exp_*`
|
|
10
|
+
* 那层映射——映射层每多一处就多一处漂移)+ 插件旧 7 类(库里 1166 条正带着它们,
|
|
11
|
+
* 不许一夜之间全变 `unclassified`)+ `unclassified` 兜底目录。
|
|
12
|
+
*
|
|
13
|
+
* 本文件必须**零依赖运行**(不引 node: 模块):client 侧与 server 侧同源消费,
|
|
14
|
+
* prompt 渲染也从这里派生。
|
|
15
|
+
*/
|
|
16
|
+
/** 宿主记忆分类的 29 类原名(实测自宿主记忆目录树,条数分布见计划 findings 第一节)。 */
|
|
17
|
+
export const HOST_MEMORY_TYPES = [
|
|
18
|
+
// —— 个人可见(chat 族):用户画像的四类 ——
|
|
19
|
+
'user_info', 'user_hobby', 'user_communication', 'user_behavior',
|
|
20
|
+
// —— 项目轴(work 族)——
|
|
21
|
+
'project_introduction', 'project_tech_stack', 'project_architecture',
|
|
22
|
+
'project_build_configuration', 'project_dependency_configuration', 'project_ide_configuration',
|
|
23
|
+
'project_scm_configuration', 'project_environment_configuration', 'project_rule',
|
|
24
|
+
// —— 开发规范轴(work 族)——
|
|
25
|
+
'development_code_specification', 'development_practice_specification',
|
|
26
|
+
'development_test_specification', 'development_comment_specification',
|
|
27
|
+
// —— 经验轴(work 族)——
|
|
28
|
+
'task_summary_experience', 'task_breakdown_experience', 'task_flow_experience', 'task_experience',
|
|
29
|
+
'tool_experience', 'mcp_experience', 'skill_experience', 'learned_skill_experience',
|
|
30
|
+
'expert_experience', 'important_decision_experience', 'common_pitfalls_experience',
|
|
31
|
+
'history_task_reference_files',
|
|
32
|
+
];
|
|
33
|
+
/** 插件早期 7 类(蒸馏管线现役词表;库里存量正带着,永久保留)。 */
|
|
34
|
+
export const LEGACY_MEMORY_TYPES = [
|
|
35
|
+
'persona', 'episodic', 'instruction', 'work_fact', 'work_task', 'work_method', 'work_artifact',
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* 兜底目录名(不是可赋值类型):不在词表的 `type` 原值照旧写进 frontmatter,
|
|
39
|
+
* 只在**目录层**归这里。归进某个 `work_*` 会静默把这批记录的 family 挑到 work 侧
|
|
40
|
+
* (family 决定共享面),所以它自成一桶、族取 chat。
|
|
41
|
+
*/
|
|
42
|
+
export const UNCLASSIFIED_DIR = 'unclassified';
|
|
43
|
+
/**
|
|
44
|
+
* 非词表 type 进入写路径时的降级目标。旧代码在 `tools/index.ts` 里把 `'episodic'`
|
|
45
|
+
* 当字面量散写;集中到这里,降级行为至少有一个可 grep 的名字。
|
|
46
|
+
*/
|
|
47
|
+
export const DOWNGRADE_TARGET = 'episodic';
|
|
48
|
+
/** 可赋值类型全集(宿主 29 + 旧 7 = 36;`unclassified` 不在其中——它是目录,不是类型)。 */
|
|
49
|
+
export const MEMORY_TYPE_VOCABULARY = new Set([
|
|
50
|
+
...LEGACY_MEMORY_TYPES, ...HOST_MEMORY_TYPES,
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* 族映射(新旧同放)。旧 `familyForType` 靠 `type.startsWith('work')` 前缀猜族,
|
|
54
|
+
* 新词表里 `project_*`/`development_*`/`*_experience` 都是 work 族却不带 work 前缀——
|
|
55
|
+
* 前缀判定会把它们静默归进 chat,而 family 决定召回/浏览/去重的共享面。
|
|
56
|
+
*/
|
|
57
|
+
export const TYPE_FAMILY_MAP = Object.freeze((() => {
|
|
58
|
+
const map = {};
|
|
59
|
+
for (const t of LEGACY_MEMORY_TYPES)
|
|
60
|
+
map[t] = t.startsWith('work') ? 'work' : 'chat';
|
|
61
|
+
for (const t of HOST_MEMORY_TYPES)
|
|
62
|
+
map[t] = t.startsWith('user_') ? 'chat' : 'work';
|
|
63
|
+
map[UNCLASSIFIED_DIR] = 'chat';
|
|
64
|
+
return map;
|
|
65
|
+
})());
|
|
66
|
+
/** 类型 → 面板中文标签(真源;client 侧经 `list-records` 的 `typeCatalog` 下发消费)。 */
|
|
67
|
+
export const MEMORY_TYPE_LABELS = Object.freeze({
|
|
68
|
+
persona: '画像偏好',
|
|
69
|
+
episodic: '客观事件',
|
|
70
|
+
instruction: '全局指令',
|
|
71
|
+
work_fact: '工作事实',
|
|
72
|
+
work_task: '工作任务',
|
|
73
|
+
work_method: '工作方法',
|
|
74
|
+
work_artifact: '工作资产',
|
|
75
|
+
user_info: '用户信息',
|
|
76
|
+
user_hobby: '用户爱好',
|
|
77
|
+
user_communication: '沟通风格',
|
|
78
|
+
user_behavior: '行为规范',
|
|
79
|
+
project_introduction: '项目介绍',
|
|
80
|
+
project_tech_stack: '技术栈',
|
|
81
|
+
project_architecture: '架构设计',
|
|
82
|
+
project_build_configuration: '构建配置',
|
|
83
|
+
project_dependency_configuration: '依赖配置',
|
|
84
|
+
project_ide_configuration: 'IDE 配置',
|
|
85
|
+
project_scm_configuration: '版本控制配置',
|
|
86
|
+
project_environment_configuration: '环境配置',
|
|
87
|
+
project_rule: '项目规则',
|
|
88
|
+
development_code_specification: '代码规范',
|
|
89
|
+
development_practice_specification: '实践规范',
|
|
90
|
+
development_test_specification: '测试规范',
|
|
91
|
+
development_comment_specification: '注释规范',
|
|
92
|
+
task_summary_experience: '任务总结',
|
|
93
|
+
task_breakdown_experience: '任务拆解',
|
|
94
|
+
task_flow_experience: '任务流程',
|
|
95
|
+
task_experience: '任务经验',
|
|
96
|
+
tool_experience: '工具经验',
|
|
97
|
+
mcp_experience: 'MCP 经验',
|
|
98
|
+
skill_experience: '技能经验',
|
|
99
|
+
learned_skill_experience: '习得技能',
|
|
100
|
+
expert_experience: '专家经验',
|
|
101
|
+
important_decision_experience: '重要决策',
|
|
102
|
+
common_pitfalls_experience: '常见陷阱',
|
|
103
|
+
history_task_reference_files: '历史参考文件',
|
|
104
|
+
[UNCLASSIFIED_DIR]: '未分类',
|
|
105
|
+
});
|
|
106
|
+
/** 投射目录全集 = 可赋值类型 + 兜底桶(37 个)。`memory-md.ts` 的白名单从这里派生。 */
|
|
107
|
+
export function memoryTypeDirs() {
|
|
108
|
+
return new Set([...MEMORY_TYPE_VOCABULARY, UNCLASSIFIED_DIR]);
|
|
109
|
+
}
|
|
110
|
+
/** 是否为词表内类型(写路径白名单判据;`unclassified` 不算——没人该主动赋它)。 */
|
|
111
|
+
export function isKnownType(type) {
|
|
112
|
+
return MEMORY_TYPE_VOCABULARY.has(type);
|
|
113
|
+
}
|
|
114
|
+
/** 族查询:查表;未知值回落旧前缀规则并交给 `onUnknownFamily` 提醒一次。 */
|
|
115
|
+
export function familyOf(type) {
|
|
116
|
+
const f = TYPE_FAMILY_MAP[type];
|
|
117
|
+
if (f !== undefined)
|
|
118
|
+
return f;
|
|
119
|
+
noteUnknown(type);
|
|
120
|
+
return type.startsWith('work') ? 'work' : 'chat';
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* CSS 类名用的 slug(`work_fact` → `work-fact`)。
|
|
124
|
+
*
|
|
125
|
+
* 面板标签类名以前直接拼 `type` 原值(下划线),而主题 CSS 定义的是连字符类——
|
|
126
|
+
* `dsh-mem-tag-work_fact` 匹配不上 `.dsh-mem-tag-work-fact`,标签无色(F11 既有断裂)。
|
|
127
|
+
* 拼接点统一走这里,判据只有一份。
|
|
128
|
+
*/
|
|
129
|
+
export function slugOf(type) {
|
|
130
|
+
return type.replace(/_/g, '-');
|
|
131
|
+
}
|
|
132
|
+
/** 面板词表目录(下发给 client 的 `typeCatalog`;含兜底桶,顺序 = 旧 7 → 宿主 29 → 兜底)。 */
|
|
133
|
+
export function typeCatalogEntries() {
|
|
134
|
+
return [...LEGACY_MEMORY_TYPES, ...HOST_MEMORY_TYPES, UNCLASSIFIED_DIR].map((id) => ({
|
|
135
|
+
id,
|
|
136
|
+
label: MEMORY_TYPE_LABELS[id] ?? id,
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
/** chat / work 族的可赋值类型(prompt 枚举串从这里渲染,不再手抄)。 */
|
|
140
|
+
export function typesOfFamily(family) {
|
|
141
|
+
return [...MEMORY_TYPE_VOCABULARY].filter((t) => TYPE_FAMILY_MAP[t] === family);
|
|
142
|
+
}
|
|
143
|
+
/** prompt/工具描述用的枚举串(`|` 或 `/` 连接,顺序稳定:旧 7 在前)。 */
|
|
144
|
+
export function typeEnumSep(sep, family) {
|
|
145
|
+
const list = family === undefined ? [...LEGACY_MEMORY_TYPES, ...HOST_MEMORY_TYPES] : typesOfFamily(family);
|
|
146
|
+
return list.join(sep);
|
|
147
|
+
}
|
|
148
|
+
// —— 未知类型的"只提醒一次":诊断集封到 64 个就不再记录(宁可漏提醒,不让集合无限吃内存)。
|
|
149
|
+
const warnedUnknownFamilies = new Set();
|
|
150
|
+
let warnSink = (msg) => console.warn(msg);
|
|
151
|
+
/** 测试/宿主接线用:替换未知族的提醒出口(传 undefined 恢复 console)。 */
|
|
152
|
+
export function setFamilyWarnSink(sink) {
|
|
153
|
+
warnSink = sink ?? ((msg) => console.warn(msg));
|
|
154
|
+
}
|
|
155
|
+
/** 清空"已提醒"集(用例要能反复断言只 warn 一次)。 */
|
|
156
|
+
export function resetFamilyWarned() {
|
|
157
|
+
warnedUnknownFamilies.clear();
|
|
158
|
+
}
|
|
159
|
+
function noteUnknown(type) {
|
|
160
|
+
if (warnedUnknownFamilies.has(type))
|
|
161
|
+
return;
|
|
162
|
+
if (warnedUnknownFamilies.size < 64)
|
|
163
|
+
warnedUnknownFamilies.add(type);
|
|
164
|
+
warnSink(`[memory] type '${type}' 不在词表,family 按旧前缀规则回落(请核对来源)`);
|
|
165
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
/**
|
|
4
|
+
* 类型码 → 运行时 type(与 memport.py TYPE_CODES 一字不差)。
|
|
5
|
+
*
|
|
6
|
+
* 旧码(插件 7 类)不变;pm-name-distill task_1.7 补进宿主 29 类的新码,使外部包
|
|
7
|
+
* 带来的宿主分类不再被写侧抹平——两实现同表是 `memport-ts-consistency` 的前提。
|
|
8
|
+
*/
|
|
9
|
+
export declare const TYPE_CODES: Record<string, string>;
|
|
10
|
+
/** 持续性取值域:p 时点 / s 已结束区间 / o 仍在持续 / t 无时间性 / ? 未判定。 */
|
|
11
|
+
export declare const PERSISTENCE: readonly ["p", "s", "o", "t", "?"];
|
|
12
|
+
export interface MemRecord {
|
|
13
|
+
seq: number;
|
|
14
|
+
type: string;
|
|
15
|
+
typeFull: string;
|
|
16
|
+
created: string;
|
|
17
|
+
updated: string;
|
|
18
|
+
vf: string;
|
|
19
|
+
vt: string;
|
|
20
|
+
st: string;
|
|
21
|
+
cf: string;
|
|
22
|
+
rw: string;
|
|
23
|
+
tags: Record<string, string>;
|
|
24
|
+
content: string;
|
|
25
|
+
hash: string;
|
|
26
|
+
createdMs: number | null;
|
|
27
|
+
createdPrec: string;
|
|
28
|
+
updatedMs: number | null;
|
|
29
|
+
updatedPrec: string;
|
|
30
|
+
vfMs: number | null;
|
|
31
|
+
vfPrec: string;
|
|
32
|
+
vtMs: number | null;
|
|
33
|
+
vtPrec: string;
|
|
34
|
+
}
|
|
35
|
+
export interface Bundle {
|
|
36
|
+
header: Record<string, string>;
|
|
37
|
+
cols: string[];
|
|
38
|
+
records: MemRecord[];
|
|
39
|
+
errors: string[];
|
|
40
|
+
warnings: string[];
|
|
41
|
+
declaredCount: number | null;
|
|
42
|
+
declaredSha: string | null;
|
|
43
|
+
/** 记录体原始行(未去转义),用于校验和复算——与 Python `body` 对齐。 */
|
|
44
|
+
bodyLines: string[];
|
|
45
|
+
}
|
|
46
|
+
/** NFKC + 空白折叠 + 去首尾(用于哈希与相似度,不改原文)。 */
|
|
47
|
+
export declare function normText(s: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* 内容哈希:sha256(normText + 小写)[:16]。
|
|
50
|
+
* 注意:Python 用 casefold(激进大小写折叠),JS 用 toLowerCase;
|
|
51
|
+
* 对 CJK/ASCII 记忆正文等价,仅极端 Unicode 有别——实际记忆集不含此类,
|
|
52
|
+
* 跨实现金标准走包级 sha256(不逐条折叠),不受影响。
|
|
53
|
+
*/
|
|
54
|
+
export declare function contentHash(s: string): string;
|
|
55
|
+
/** 记录稳定 id:`mp_` + sha256(src|chash)[:16]。 */
|
|
56
|
+
export declare function recordId(src: string, chash: string): string;
|
|
57
|
+
/** 解码内容列:反斜杠+反斜杠 → 单反斜杠;反斜杠+n → 换行(其余反斜杠原样)。 */
|
|
58
|
+
export declare function unescapeContent(s: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* 编码内容列:反斜杠 → 双反斜杠、CRLF → LF、LF → 反斜杠+n。
|
|
61
|
+
* 用 charCode 常量而非控制字符字面量,避免跨工具写盘时 CR/LF 被吞进正则/字符串字面量。
|
|
62
|
+
*/
|
|
63
|
+
export declare function escapeContent(s: string): string;
|
|
64
|
+
/** `k:v;k:v` → 对象(缺冒号的段忽略)。 */
|
|
65
|
+
export declare function parseTags(raw: string): Record<string, string>;
|
|
66
|
+
/** 时间串 → { ms|null, precision }(镜像 Python parse_time;naive 视为本地)。 */
|
|
67
|
+
export declare function parseTime(raw: string): {
|
|
68
|
+
ms: number | null;
|
|
69
|
+
precision: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* 解析整包文本 → Bundle(含结构校验)。镜像 memport.py parse_bundle。
|
|
73
|
+
* 入参是字符串(调用方读文件时自带编码处理);此处容错剥离 BOM。
|
|
74
|
+
*/
|
|
75
|
+
export declare function parseBundle(text: string): Bundle;
|