统一 Rust 与 TypeScript 格式化门禁

纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口

完成项目 TypeScript/Prettier 与 Rust 全量格式化

修复 Pingora expected executable 门禁的空白敏感误报

同步开发运维文档与 AGC skill pack 格式化忽略规则
This commit is contained in:
2026-09-01 16:26:20 +08:00
parent ae79d50b14
commit 071faa482c
1051 changed files with 28412 additions and 19834 deletions
+116 -77
View File
@@ -1,4 +1,4 @@
import type {QuestGenerationContext} from '../services/aiTypes';
import type { QuestGenerationContext } from '../services/aiTypes';
import {
buildFallbackActorNarrativeProfile,
normalizeActorNarrativeProfile,
@@ -12,7 +12,11 @@ import type {
RuntimeItemGenerationContext,
ScenePresetInfo,
} from '../types';
import {getCharacterCombatTags, getTimedBuildBuffTags, normalizeBuildTags} from './buildTags';
import {
getCharacterCombatTags,
getTimedBuildBuffTags,
normalizeBuildTags,
} from './buildTags';
type GapDefinition = {
id: string;
@@ -20,46 +24,50 @@ type GapDefinition = {
};
const BUILD_GAP_DEFINITIONS: GapDefinition[] = [
{id: 'survival_gap', tags: ['守御', '护体', '回复', '续战']},
{id: 'mana_gap', tags: ['法力', '冷却', '护持', '过载']},
{id: 'finisher_gap', tags: ['爆发', '重击', '追击', '压制']},
{id: 'mobility_gap', tags: ['突进', '快袭', '风行', '游击']},
{id: 'control_gap', tags: ['控场', '符阵', '镇邪', '反击']},
{ id: 'survival_gap', tags: ['守御', '护体', '回复', '续战'] },
{ id: 'mana_gap', tags: ['法力', '冷却', '护持', '过载'] },
{ id: 'finisher_gap', tags: ['爆发', '重击', '追击', '压制'] },
{ id: 'mobility_gap', tags: ['突进', '快袭', '风行', '游击'] },
{ id: 'control_gap', tags: ['控场', '符阵', '镇邪', '反击'] },
];
function dedupeStrings(values: Array<string | null | undefined | false>) {
return [...new Set(
values
.map(value => typeof value === 'string' ? value.trim() : '')
.filter(Boolean),
)];
return [
...new Set(
values
.map((value) => (typeof value === 'string' ? value.trim() : ''))
.filter(Boolean),
),
];
}
function collectLoadoutBuildTags(loadout: EquipmentLoadout | null | undefined) {
if (!loadout) return [] as string[];
return normalizeBuildTags([
...(loadout.weapon?.buildProfile?.tags ?? []),
loadout.weapon?.buildProfile?.role ?? '',
...(loadout.armor?.buildProfile?.tags ?? []),
loadout.armor?.buildProfile?.role ?? '',
...(loadout.relic?.buildProfile?.tags ?? []),
loadout.relic?.buildProfile?.role ?? '',
], 6);
return normalizeBuildTags(
[
...(loadout.weapon?.buildProfile?.tags ?? []),
loadout.weapon?.buildProfile?.role ?? '',
...(loadout.armor?.buildProfile?.tags ?? []),
loadout.armor?.buildProfile?.role ?? '',
...(loadout.relic?.buildProfile?.tags ?? []),
loadout.relic?.buildProfile?.role ?? '',
],
6,
);
}
function buildSceneTags(scene: Pick<ScenePresetInfo, 'name' | 'description' | 'treasureHints'> | null) {
function buildSceneTags(
scene: Pick<ScenePresetInfo, 'name' | 'description' | 'treasureHints'> | null,
) {
if (!scene) return [] as string[];
const seedParts = dedupeStrings([
scene.name,
...(scene.treasureHints ?? []),
]);
const seedParts = dedupeStrings([scene.name, ...(scene.treasureHints ?? [])]);
return seedParts
.flatMap(part => part.split(/[、,。;:\s/]+/u))
.map(part => part.trim())
.filter(part => part.length >= 2)
.flatMap((part) => part.split(/[、,。;:\s/]+/u))
.map((part) => part.trim())
.filter((part) => part.length >= 2)
.slice(0, 8);
}
@@ -71,16 +79,18 @@ function buildRecentStorySummary(lines: string[]) {
function buildRecentStoryLines(storyHistory: GameState['storyHistory']) {
return storyHistory
.slice(-4)
.map(moment => moment.text.trim())
.map((moment) => moment.text.trim())
.filter(Boolean)
.slice(-3);
}
function derivePlayerBuildGaps(playerBuildTags: string[]) {
const tagSet = new Set(playerBuildTags);
return BUILD_GAP_DEFINITIONS
.filter(definition => definition.tags.filter(tag => tagSet.has(tag)).length <= 0)
.map(definition => definition.id)
return BUILD_GAP_DEFINITIONS.filter(
(definition) =>
definition.tags.filter((tag) => tagSet.has(tag)).length <= 0,
)
.map((definition) => definition.id)
.slice(0, 3);
}
@@ -94,21 +104,22 @@ function resolveRelatedNpcNarrativeProfile(params: {
}
const role =
customWorldProfile.storyNpcs.find((npc) =>
npc.id === encounter.id || npc.name === encounter.npcName,
)
?? customWorldProfile.playableNpcs.find((npc) =>
npc.id === encounter.id || npc.name === encounter.npcName,
customWorldProfile.storyNpcs.find(
(npc) => npc.id === encounter.id || npc.name === encounter.npcName,
) ??
customWorldProfile.playableNpcs.find(
(npc) => npc.id === encounter.id || npc.name === encounter.npcName,
);
if (!role) {
return encounter.narrativeProfile ?? null;
}
const themePack =
customWorldProfile.themePack ?? buildThemePackFromWorldProfile(customWorldProfile);
customWorldProfile.themePack ??
buildThemePackFromWorldProfile(customWorldProfile);
const storyGraph =
customWorldProfile.storyGraph
?? buildFallbackWorldStoryGraph(customWorldProfile, themePack);
customWorldProfile.storyGraph ??
buildFallbackWorldStoryGraph(customWorldProfile, themePack);
return normalizeActorNarrativeProfile(
role.narrativeProfile,
@@ -119,7 +130,9 @@ function resolveRelatedNpcNarrativeProfile(params: {
function resolveActiveThreadIds(params: {
customWorldProfile: GameState['customWorldProfile'];
relatedNpcNarrativeProfile: RuntimeItemGenerationContext['relatedNpcNarrativeProfile'];
storyEngineMemory?: GameState['storyEngineMemory'] | QuestGenerationContext['activeThreadIds'];
storyEngineMemory?:
| GameState['storyEngineMemory']
| QuestGenerationContext['activeThreadIds'];
}) {
const threadSource = params.storyEngineMemory;
if (Array.isArray(threadSource) && threadSource.length > 0) {
@@ -143,11 +156,11 @@ function resolveActiveThreadIds(params: {
}
const themePack =
params.customWorldProfile.themePack
?? buildThemePackFromWorldProfile(params.customWorldProfile);
params.customWorldProfile.themePack ??
buildThemePackFromWorldProfile(params.customWorldProfile);
const storyGraph =
params.customWorldProfile.storyGraph
?? buildFallbackWorldStoryGraph(params.customWorldProfile, themePack);
params.customWorldProfile.storyGraph ??
buildFallbackWorldStoryGraph(params.customWorldProfile, themePack);
return storyGraph.visibleThreads.slice(0, 3).map((thread) => thread.id);
}
@@ -155,10 +168,15 @@ function resolveActiveThreadIds(params: {
function buildBaseRuntimeContext(params: {
worldType: GameState['worldType'];
customWorldProfile: GameState['customWorldProfile'];
scene: Pick<ScenePresetInfo, 'id' | 'name' | 'description' | 'treasureHints'> | null;
scene: Pick<
ScenePresetInfo,
'id' | 'name' | 'description' | 'treasureHints'
> | null;
encounter: GameState['currentEncounter'];
relatedNpcState: GameState['npcStates'][string] | null;
storyEngineMemory?: GameState['storyEngineMemory'] | QuestGenerationContext['activeThreadIds'];
storyEngineMemory?:
| GameState['storyEngineMemory']
| QuestGenerationContext['activeThreadIds'];
storyHistory: GameState['storyHistory'];
playerCharacterId: string;
playerBuildTags: string[];
@@ -198,7 +216,12 @@ function buildBaseRuntimeContext(params: {
sceneTags: buildSceneTags(scene),
treasureHints: [...(scene?.treasureHints ?? [])],
encounter: encounter ?? null,
encounterNpcId: encounter?.id ?? encounter?.characterId ?? encounter?.monsterPresetId ?? encounter?.npcName ?? null,
encounterNpcId:
encounter?.id ??
encounter?.characterId ??
encounter?.monsterPresetId ??
encounter?.npcName ??
null,
encounterNpcName: encounter?.npcName ?? null,
encounterContextText: encounter?.context ?? null,
relatedNpcState,
@@ -218,7 +241,10 @@ function buildBaseRuntimeContext(params: {
export function buildLooseRuntimeItemGenerationContext(params: {
worldType: GameState['worldType'];
customWorldProfile?: GameState['customWorldProfile'];
scene?: Pick<ScenePresetInfo, 'id' | 'name' | 'description' | 'treasureHints'> | null;
scene?: Pick<
ScenePresetInfo,
'id' | 'name' | 'description' | 'treasureHints'
> | null;
encounter?: GameState['currentEncounter'];
relatedNpcState?: GameState['npcStates'][string] | null;
storyHistory?: GameState['storyHistory'];
@@ -233,7 +259,10 @@ export function buildLooseRuntimeItemGenerationContext(params: {
scene: params.scene ?? null,
encounter: params.encounter ?? null,
relatedNpcState: params.relatedNpcState ?? null,
storyEngineMemory: params.customWorldProfile?.storyGraph?.visibleThreads.map((thread) => thread.id) ?? [],
storyEngineMemory:
params.customWorldProfile?.storyGraph?.visibleThreads.map(
(thread) => thread.id,
) ?? [],
storyHistory: params.storyHistory ?? [],
playerCharacterId: params.playerCharacterId ?? 'runtime-loose-player',
playerBuildTags: params.playerBuildTags ?? [],
@@ -248,18 +277,21 @@ export function buildRuntimeItemGenerationContext(params: {
encounter?: GameState['currentEncounter'];
scene?: GameState['currentScenePreset'];
}) {
const {state, generationChannel} = params;
const { state, generationChannel } = params;
const encounter = params.encounter ?? state.currentEncounter;
const scene = params.scene ?? state.currentScenePreset;
const relatedNpcState = encounter
? state.npcStates[encounter.id ?? encounter.npcName] ?? null
? (state.npcStates[encounter.id ?? encounter.npcName] ?? null)
: null;
const playerBuildTags = state.playerCharacter
? normalizeBuildTags([
...getCharacterCombatTags(state.playerCharacter),
...collectLoadoutBuildTags(state.playerEquipment),
...getTimedBuildBuffTags(state.activeBuildBuffs),
], 6)
? normalizeBuildTags(
[
...getCharacterCombatTags(state.playerCharacter),
...collectLoadoutBuildTags(state.playerEquipment),
...getTimedBuildBuffTags(state.activeBuildBuffs),
],
6,
)
: [];
return buildBaseRuntimeContext({
@@ -283,7 +315,10 @@ export function buildQuestRuntimeItemGenerationContext(params: {
issuerNpcId: string;
issuerNpcName: string;
roleText: string;
scene?: Pick<ScenePresetInfo, 'id' | 'name' | 'description' | 'treasureHints'> | null;
scene?: Pick<
ScenePresetInfo,
'id' | 'name' | 'description' | 'treasureHints'
> | null;
}) {
const {
context,
@@ -294,25 +329,28 @@ export function buildQuestRuntimeItemGenerationContext(params: {
generationChannel = 'quest_reward',
} = params;
const playerBuildTags = context.playerCharacter
? normalizeBuildTags([
...getCharacterCombatTags(context.playerCharacter),
...collectLoadoutBuildTags(context.playerEquipment),
], 6)
? normalizeBuildTags(
[
...getCharacterCombatTags(context.playerCharacter),
...collectLoadoutBuildTags(context.playerEquipment),
],
6,
)
: [];
return buildBaseRuntimeContext({
worldType: context.worldType,
customWorldProfile: context.customWorldProfile ?? null,
scene: scene ?? (
context.currentSceneName
scene:
scene ??
(context.currentSceneName
? {
id: context.currentSceneId ?? '',
name: context.currentSceneName,
description: context.currentSceneDescription ?? '',
treasureHints: [],
}
: null
),
: null),
encounter: {
id: issuerNpcId,
kind: 'npc',
@@ -321,17 +359,18 @@ export function buildQuestRuntimeItemGenerationContext(params: {
npcAvatar: '',
context: roleText,
},
relatedNpcState: context.issuerAffinity == null
? null
: {
affinity: context.issuerAffinity,
helpUsed: false,
chattedCount: 0,
giftsGiven: 0,
inventory: [],
recruited: false,
revealedFacts: [],
},
relatedNpcState:
context.issuerAffinity == null
? null
: {
affinity: context.issuerAffinity,
helpUsed: false,
chattedCount: 0,
giftsGiven: 0,
inventory: [],
recruited: false,
revealedFacts: [],
},
storyEngineMemory: context.activeThreadIds,
storyHistory: context.recentStoryMoments ?? [],
playerCharacterId: context.playerCharacter?.id ?? 'quest-player',