Makelore 2.0 initial clean snapshot

This commit is contained in:
inman
2026-07-29 17:22:35 +08:00
commit b8ca3f8eea
694 changed files with 139782 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
import { describe, expect, it } from 'vitest';
import {
buildGameAssetReviewBatchMessage,
buildGameAssetReviewActionMessage,
buildGameAssetReviewMarker,
buildGameAssetConfirmationMessage,
findGameAssetRoundConfirmation,
GAME_ASSET_SELECTION_MARKER,
hasGameAssetReviewContent,
hasGameAssetSelectionMarker,
parseGameAssetReviewAction,
parseGameAssetReviewActions,
parseGameAssetReviewInvocation,
stripGameAssetSelectionMarker,
} from '@/lib/game-asset-selection-message';
describe('conversation-guided game asset selection', () => {
it('detects and hides the assistant selection marker', () => {
const message = { role: 'assistant' as const, content: `候选准备好了。\n${GAME_ASSET_SELECTION_MARKER}` };
expect(hasGameAssetSelectionMarker(message)).toBe(true);
expect(stripGameAssetSelectionMarker(String(message.content))).toBe('候选准备好了。');
});
it('round-trips an Agent-filled review marker and user action', () => {
const assistant = { role: 'assistant' as const, content: `候选准备好了。\n${buildGameAssetReviewMarker('review-1', ['hero', 'jump'])}` };
expect(hasGameAssetSelectionMarker(assistant)).toBe(true);
expect(parseGameAssetReviewInvocation(assistant)).toEqual({ invocationId: 'review-1', candidateIds: ['hero', 'jump'] });
expect(stripGameAssetSelectionMarker(String(assistant.content))).toBe('候选准备好了。');
const user = { role: 'user' as const, content: buildGameAssetReviewActionMessage({ invocationId: 'review-1', asset: { id: 'hero', name: '主角' }, action: 'approve' }) };
expect(parseGameAssetReviewAction(user)).toEqual({ invocationId: 'review-1', assetId: 'hero', action: 'approve' });
});
it('round-trips one grouped user message for the complete review batch', () => {
const message = {
role: 'user' as const,
content: buildGameAssetReviewBatchMessage({
invocationId: 'review-batch',
decisions: [
{ asset: { id: 'hero', name: '主角' }, action: 'approve' },
{ asset: { id: 'jump', name: '跳跃音效' }, action: 'discard' },
{ asset: { id: 'background', name: '背景' }, action: 'replace' },
],
}),
};
expect(message.content).toContain('游戏素材审核结果(本轮一次性提交)');
expect(message.content).toContain('纳入开发:');
expect(message.content).toContain('舍弃:');
expect(message.content).toContain('不合适,重新寻找:');
expect(parseGameAssetReviewActions(message)).toEqual({
invocationId: 'review-batch',
decisions: [
{ assetId: 'hero', action: 'approve' },
{ assetId: 'jump', action: 'discard' },
{ assetId: 'background', action: 'replace' },
],
});
});
it('detects a concrete preview list when the Agent omitted the review marker', () => {
const assistant = {
role: 'assistant' as const,
content: '已经找到 7 个素材候选。\n\n| 预览文件 | 是什么 |\n| --- | --- |\n| C-001-flappy-bird.png | 小鸟和管子 |',
};
expect(hasGameAssetReviewContent(assistant)).toBe(true);
expect(hasGameAssetReviewContent({ role: 'assistant', content: '我正在整理素材方向,暂时没有候选。' })).toBe(false);
});
it('builds a real user confirmation and associates it with the latest round', () => {
const confirmation = buildGameAssetConfirmationMessage([
{ id: 'hero', name: '主角' },
{ id: 'jump', name: '跳跃音效' },
]);
const messages = [
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
{ role: 'user' as const, content: confirmation },
];
expect(confirmation).toContain('「主角」hero、「跳跃音效」jump');
expect(findGameAssetRoundConfirmation(messages, 0)).toBe(messages[1]);
});
it('does not let a later round confirmation collapse an older unanswered round', () => {
const messages = [
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
{ role: 'user' as const, content: '换一批' },
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
{ role: 'user' as const, content: buildGameAssetConfirmationMessage([{ id: 'new', name: '新素材' }]) },
];
expect(findGameAssetRoundConfirmation(messages, 0)).toBeNull();
expect(findGameAssetRoundConfirmation(messages, 2)).toBe(messages[3]);
});
});