Files
Genarrative/src/services/storyEngine/knowledgeGraph.test.ts
T
kdletters cbc27bad4a
CI / verify (push) Has been cancelled
init with react+axum+spacetimedb
2026-04-26 18:06:23 +08:00

119 lines
3.8 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { type CustomWorldProfile,WorldType } from '../../types';
import { buildKnowledgeGraph } from './knowledgeGraph';
const profile: CustomWorldProfile = {
id: 'world-1',
settingText: '裂潮边城',
name: '裂潮边城',
subtitle: '旧案回响',
summary: '一座在裂潮和旧案之间摇摇欲坠的边城。',
tone: '紧张、克制、暗流涌动',
playerGoal: '查清封桥旧令',
templateWorldType: WorldType.WUXIA,
majorFactions: ['巡边司'],
coreConflicts: ['封桥旧案再起'],
attributeSchema: {
id: 'schema',
worldId: 'world-1',
schemaVersion: 1,
generatedFrom: {
worldType: WorldType.CUSTOM,
worldName: '裂潮边城',
settingSummary: '裂潮边城',
tone: '紧张、克制、暗流涌动',
conflictCore: '封桥旧案再起',
},
slots: [],
},
playableNpcs: [],
storyNpcs: [
{
id: 'npc-1',
name: '梁砺',
title: '断桥巡守',
role: '巡守',
description: '守着断桥与旧哨火的巡守。',
backstory: '旧案爆发时,他是最后一个封桥的人。',
personality: '警觉直接,不喜欢绕弯。',
motivation: '不想让旧案再次借裂潮翻上来。',
combatStyle: '长兵先压,再卡住路口。',
initialAffinity: 6,
relationshipHooks: ['封桥', '旧哨火'],
tags: ['巡守', '断桥'],
backstoryReveal: {
publicSummary: '他只承认自己还在守桥。',
chapters: [
{
id: 'surface',
title: '表层来意',
affinityRequired: 0,
teaser: '桥还不能放开。',
content: '他总先谈桥和路。',
contextSnippet: '桥还不能放开。',
},
],
},
skills: [],
initialItems: [],
narrativeProfile: {
publicMask: '他只承认自己还在守桥。',
firstContactMask: '先别问旧案,桥口还不能放开。',
visibleLine: '他把全部注意力都压在桥口和来路上。',
hiddenLine: '他真正盯着的是封桥旧令背后的名字。',
contradiction: '嘴上只说守桥,提到名单时却会明显收紧语气。',
debtOrBurden: '封桥那夜的后果还压在他身上。',
taboo: '封桥令',
immediatePressure: '裂潮再逼桥口,他不敢轻易放人过去。',
relatedThreadIds: ['thread-1'],
relatedScarIds: ['scar-1'],
reactionHooks: ['名单', '旧哨火'],
},
},
],
items: [],
landmarks: [],
themePack: null,
storyGraph: {
visibleThreads: [
{
id: 'thread-1',
title: '封桥旧案',
visibility: 'visible',
summary: '封桥旧案再次被人提起。',
conflictType: '调查',
stakes: '边城安稳',
involvedFactionIds: [],
involvedActorIds: ['npc-1'],
relatedLocationIds: ['bridge'],
},
],
hiddenThreads: [],
scars: [
{
id: 'scar-1',
title: '断桥旧痕',
pastEvent: '封桥夜留下的旧痕。',
publicResidue: '桥柱上还留着旧封痕。',
hiddenTruth: '封桥令另有来头。',
relatedActorIds: ['npc-1'],
relatedLocationIds: ['bridge'],
},
],
motifs: [],
},
knowledgeFacts: null,
threadContracts: null,
};
describe('buildKnowledgeGraph', () => {
it('builds actor facts from narrative profile and backstory chapters', () => {
const facts = buildKnowledgeGraph(profile);
expect(facts.some((fact) => fact.title.includes('公开面'))).toBe(true);
expect(facts.some((fact) => fact.title.includes('禁区') && fact.visibility === 'forbidden')).toBe(true);
expect(facts.some((fact) => fact.title === '表层来意')).toBe(true);
});
});