dsh-lite-memory 0.18.42 → 0.18.44

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.
@@ -1,68 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
-
6
- process.env.DSH_HOME = fs.mkdtempSync(path.join(os.tmpdir(), 'lite-memory-lexical-'));
7
- const store = await import('../store.js');
8
- const view = await import('../view.js');
9
-
10
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lite-memory-lexical-scope-'));
11
- const scope = store.scopeOf(dir);
12
- const add = (title, extra = {}) => store.upsert(scope, {
13
- applicability: 'all_in_scope',
14
- body: `正文:${title}`,
15
- summary: extra.summary || `${title}的摘要`,
16
- tags: extra.tags || [],
17
- resolution: 'distinct',
18
- title,
19
- });
20
- add('digital signal 调试', { tags: ['音频'] });
21
- add('怎么做发布检查', { tags: ['发布'] });
22
- add('git 提交前跑检查', { tags: ['git'] });
23
- add('插件改名与合并', { tags: ['插件开发', '启动失败'], summary: '改包名要同步 factory ID,否则启动失败' });
24
- add('启动服务器', { tags: ['启动'] });
25
-
26
- /* 英文按整词:git 不能因为共享 gi/it 命中 digital。 */
27
- assert.equal(store.search(scope, 'git', 5).some((row) => row.title.includes('digital')), false);
28
- assert.equal(store.search(scope, 'digital', 5).some((row) => row.title.includes('digital')), true);
29
- /* 中英混排同样按整词:英文词没出现,中文词重合再多也不能替它作证。 */
30
- assert.equal(store.search(scope, '排查 git', 5).some((row) => row.title.includes('digital')), false);
31
- assert.equal(store.search(scope, '排查 git', 5).some((row) => row.title.includes('git 提交前跑检查')), true);
32
-
33
- /* 只重合「怎么」这类高频词不算命中。 */
34
- assert.equal(store.search(scope, '这个怎么弄', 5).length, 0);
35
-
36
- /* 实词仍然命中。 */
37
- assert.equal(store.search(scope, '发布检查', 5).some((row) => row.title.includes('怎么做发布检查')), true);
38
-
39
- /* 「启动」只是「启动失败」的一半,不能把改包名的记忆带进自动提示。 */
40
- const renameRecord = store.search(scope, '插件改名与合并', 1)[0];
41
- const serverRecord = store.search(scope, '启动服务器', 5).find((row) => row.title === '启动服务器');
42
- assert.equal(view.matchScore(renameRecord, '启动服务器').score < view.MATCH_FLOOR, true);
43
- assert.equal(view.matchScore(serverRecord, '启动服务器').score >= view.MATCH_FLOOR, true);
44
- /* 两个词都落在同一个标签上才继续算命中。 */
45
- assert.equal(store.search(scope, '启动失败怎么查', 5).some((row) => row.title === '插件改名与合并'), true);
46
-
47
- /* 续说一句没有检索词:只有明确的「继续/然后」才沿用上一轮,别把短问题也接上去。 */
48
- for (const text of ['继续', '继续。', '然后呢?', '接着', 'go on', 'continue']) {
49
- assert.equal(view.isContinuationQuery(text), true, text);
50
- }
51
- for (const text of ['继续优化轻量化记忆与前端展示逻辑', '然后发布', '样式', 'next steps for release']) {
52
- assert.equal(view.isContinuationQuery(text), false, text);
53
- }
54
- /* 短续句只由通用动作词组成、没点名新对象:沿用上一句,但不把带对象的长句也算进来。 */
55
- for (const text of ['继续优化收敛', '继续打磨', '接着改', '继续看看']) {
56
- assert.equal(view.isEllipticalContinuation(text), true, text);
57
- }
58
- for (const text of ['继续优化轻量化记忆与前端展示逻辑', '继续优化数据库连接池', '接着改数据库', '然后发布']) {
59
- assert.equal(view.isEllipticalContinuation(text), false, text);
60
- }
61
-
62
- /* 明确换任务:换做/先别管,或点了一个上一句没有的英文对象。 */
63
- assert.equal(view.isExplicitSwitch('改用 PostgreSQL 先看连接池', '把前端按钮颜色调一下'), true);
64
- assert.equal(view.isExplicitSwitch('先别管这个了,帮我看看 nginx 502', '把前端按钮颜色调一下'), true);
65
- assert.equal(view.isExplicitSwitch('继续优化收敛', '把前端按钮颜色调一下'), false);
66
- assert.equal(view.isExplicitSwitch('继续优化数据库连接池', '把前端按钮颜色调一下'), false);
67
-
68
- console.log('lexical.test.mjs: all passed');
@@ -1,104 +0,0 @@
1
- import assert from 'node:assert/strict';
2
-
3
- let seen = null;
4
- const makeNode = (type, props, ...children) => ({ type, props: props || {}, children: children.flat(Infinity) });
5
- const fakeReact = {
6
- createElement: makeNode,
7
- useRef: (value) => ({ current: value }),
8
- useState: (value) => [value, () => {}],
9
- useEffect: () => {},
10
- useMemo: (fn) => fn(),
11
- };
12
- globalThis.window = {
13
- __ModuleLoader__: {
14
- load: (definition) => {
15
- definition.factory((name) => (name === 'react' ? fakeReact : null));
16
- },
17
- },
18
- };
19
- globalThis.__LITE_MEMORY_TEST__ = (helpers) => { seen = helpers; };
20
- await import('../client.js');
21
- assert.ok(seen, 'client test seam missing');
22
-
23
- const {
24
- MemoryPalace, MemoryPanel, viewModeOf, palaceRoomsOf, palaceRoomPageOf,
25
- palacePageWindow, palaceToggleOf, palaceMotionOf, palaceRoomIdOf,
26
- } = seen;
27
-
28
- const record = (id, kind, title = id) => ({ id, kind, title });
29
-
30
- // 房间按固定顺序归类,未知类型落到「其他记录」,不丢记录。
31
- const rooms = palaceRoomsOf([
32
- record('mem_1', 'note'),
33
- record('mem_2', 'pointer'),
34
- record('mem_3', 'procedure'),
35
- record('mem_4', 'preference'),
36
- record('mem_5', 'convention'),
37
- record('mem_6', 'pitfall'),
38
- record('mem_7', 'credential_hint'),
39
- record('mem_8', 'unknown_kind'),
40
- ]);
41
- assert.deepEqual(rooms.map((room) => room.name), ['习惯与规范', '方法与经验', '资料与入口', '其他记录']);
42
- assert.deepEqual(rooms.map((room) => room.total), [2, 2, 2, 2]);
43
- assert.equal(palaceRoomIdOf('unknown_kind'), 'notes');
44
- assert.deepEqual(palaceRoomsOf([record('mem_9', 'note')]).map((room) => room.total), [0, 0, 0, 1], '空房间保留位置');
45
-
46
- // 一页固定 24 个槽位,页码夹在有效范围内。
47
- const many = Array.from({ length: 25 }, (_, index) => record(`mem_${index}`, 'preference', `P${index}`));
48
- const manyRooms = palaceRoomsOf(many);
49
- assert.equal(manyRooms.length, 4);
50
- assert.equal(manyRooms[0].total, 25);
51
- assert.equal(manyRooms[0].pages, 2);
52
- const first = palaceRoomPageOf(many, 'habits', 1);
53
- assert.equal(first.items.length, 24);
54
- assert.equal(first.page, 1);
55
- const second = palaceRoomPageOf(many, 'habits', 2);
56
- assert.equal(second.items.length, 1);
57
- assert.equal(second.page, 2);
58
- assert.equal(palaceRoomPageOf(many, 'habits', 99).page, 2);
59
- assert.equal(palaceRoomPageOf(many, 'habits', 0).page, 1);
60
- assert.deepEqual(palacePageWindow(1, 3), [1, 2, 3]);
61
- assert.deepEqual(palacePageWindow(5, 12), [2, 3, 4, 5, 6, 7, 8]);
62
- assert.equal(palacePageWindow(12, 12).includes(12), true);
63
-
64
- // 同一时刻只展开一间:再点已展开的房间会收起。
65
- assert.equal(palaceToggleOf('', 'methods'), 'methods');
66
- assert.equal(palaceToggleOf('methods', 'methods'), '');
67
- assert.equal(palaceToggleOf('methods', 'habits'), 'habits');
68
-
69
- // 视图开关关闭时回列表,关闭的宫殿不进入组件树。
70
- assert.equal(viewModeOf({ graph: true, palace: false }, 'palace'), 'list');
71
- assert.equal(viewModeOf({ graph: false, palace: true }, 'palace'), 'palace');
72
- assert.equal(viewModeOf({ graph: false, palace: false }, 'graph'), 'list');
73
-
74
- // 减少动态时无动画,普通情况 180ms。
75
- assert.equal(palaceMotionOf(true).duration, 0);
76
- assert.equal(palaceMotionOf(false).duration, 180);
77
-
78
- // 点击展品只把 record.id 交给现有详情入口,不另造详情。
79
- let picked = '';
80
- const tree = MemoryPalace({
81
- records: [record('mem_a', 'preference', 'A')],
82
- selectedId: '', onPick: (id) => { picked = id; }, emptyText: '这个项目还没有记忆',
83
- });
84
- const walk = (node, out = [], expand = false) => {
85
- if (!node || typeof node !== 'object') return out;
86
- if (expand && typeof node.type === 'function') return walk(node.type(node.props), out, true);
87
- out.push(node);
88
- for (const child of node.children || []) walk(child, out, expand);
89
- return out;
90
- };
91
- const exhibit = walk(tree, [], true).find((node) => node.type === 'button' && node.props.title === 'A');
92
- assert.ok(exhibit, '展品应是原生按钮');
93
- const beforeClick = JSON.stringify(tree);
94
- exhibit.props.onClick();
95
- assert.equal(picked, 'mem_a');
96
- assert.equal(JSON.stringify(tree), beforeClick, '点开展品只换详情,不改宫殿里的记录');
97
-
98
- // 首帧列表视图不挂载宫殿;空数据时给下一步提示。
99
- const firstPaint = MemoryPanel({ sessionId: 'demo', onClose: () => {} });
100
- assert.equal(walk(firstPaint).some((node) => node.type === MemoryPalace), false);
101
- const emptyTree = MemoryPalace({ records: [], selectedId: '', onPick: () => {}, emptyText: '这个项目还没有记忆' });
102
- assert.equal(walk(emptyTree).some((node) => node.children.includes('这个项目还没有记忆')), true);
103
-
104
- console.log('palace.test.mjs: all passed');