mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
66e4061274
- chatExtractionEnabled now defaults OFF (explicit opt-in only); it gates the regex pack, chat-form profile capture, and LLM extractor together while leaving memory injection untouched - add a one-time boot migration (memory-cleanup.ts) that deletes regex-pack artifacts by name+template fingerprint, prunes user_profile to the canonical field set the settings editor writes, and forces the legacy config flag off once; marker-gated so a conscious re-opt-in sticks - persist writer provenance (frontmatter source:) on every new entry so future audits can tell auto-extracted facts from hand-written ones - LLM-extracted entries are deliberately kept: on-disk they are indistinguishable from hand-written prose, and they are the least harmful of the retired pipelines' output Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
71 lines
2.7 KiB
TypeScript
71 lines
2.7 KiB
TypeScript
import { promises as fsp } from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
extractFromMessage,
|
|
listMemoryEntries,
|
|
readMemoryConfig,
|
|
writeMemoryConfig,
|
|
} from '../src/memory.js';
|
|
|
|
let dataDir = '';
|
|
|
|
beforeEach(async () => {
|
|
dataDir = await fsp.mkdtemp(path.join(os.tmpdir(), 'od-memory-default-'));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await fsp.rm(dataDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('chat auto-extraction default', () => {
|
|
it('defaults chatExtractionEnabled to OFF when no config exists', async () => {
|
|
const cfg = await readMemoryConfig(dataDir);
|
|
expect(cfg.enabled).toBe(true);
|
|
expect(cfg.chatExtractionEnabled).toBe(false);
|
|
// Injection-side hooks stay on: memory the user typed still reaches
|
|
// the prompt; only the extraction pipelines are retired.
|
|
expect(cfg.profileEnabled).toBe(true);
|
|
});
|
|
|
|
it('defaults chatExtractionEnabled to OFF for configs written before the flag existed', async () => {
|
|
await fsp.mkdir(path.join(dataDir, 'memory'), { recursive: true });
|
|
await fsp.writeFile(
|
|
path.join(dataDir, 'memory', '.config.json'),
|
|
JSON.stringify({ enabled: true }),
|
|
);
|
|
const cfg = await readMemoryConfig(dataDir);
|
|
expect(cfg.chatExtractionEnabled).toBe(false);
|
|
});
|
|
|
|
it('writes nothing for marker-looking chat messages under the default config', async () => {
|
|
// Real production false positives from the retired regex pack: the
|
|
// progressive-aspect "我在…" and the form round-trip both minted junk
|
|
// "user location" / "user goal" entries.
|
|
const changed = await extractFromMessage(
|
|
dataDir,
|
|
'别问了,给我在首屏补一张决定性 hero 图,直接开做:',
|
|
);
|
|
expect(changed).toEqual([]);
|
|
expect(await listMemoryEntries(dataDir)).toEqual([]);
|
|
});
|
|
|
|
it('still honors an explicit opt-in', async () => {
|
|
await writeMemoryConfig(dataDir, { chatExtractionEnabled: true });
|
|
const changed = await extractFromMessage(dataDir, '记住:主色永远用品牌绿');
|
|
expect(changed.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('round-trips an explicit opt-in through writeMemoryConfig', async () => {
|
|
await writeMemoryConfig(dataDir, { chatExtractionEnabled: true });
|
|
expect((await readMemoryConfig(dataDir)).chatExtractionEnabled).toBe(true);
|
|
// Patching an unrelated flag must not silently re-enable extraction.
|
|
await writeMemoryConfig(dataDir, { verifyEnabled: false });
|
|
expect((await readMemoryConfig(dataDir)).chatExtractionEnabled).toBe(true);
|
|
await writeMemoryConfig(dataDir, { chatExtractionEnabled: false });
|
|
expect((await readMemoryConfig(dataDir)).chatExtractionEnabled).toBe(false);
|
|
});
|
|
});
|