feat: expand novel IP and production workflows

This commit is contained in:
www
2026-09-18 08:14:05 +02:00
parent b2ae4600b4
commit d9c81a3ac0
235 changed files with 117971 additions and 2721 deletions
@@ -0,0 +1,96 @@
import { describe, expect, it } from 'vitest';
import {
beginAiRequestInspection,
clearAiRequestInspections,
completeAiRequestInspection,
isInspectableAiRequest,
subscribeAiRequestInspections,
type AiRequestInspectionRecord
} from '../../../shared/frontend/ai-request-inspector/ai-request-inspector';
describe('AI request inspector route matching', () => {
it.each([
['/provider-lab/runs', 'POST'],
['/projects/p1/reviews/text', 'POST'],
['/assets/a1/review', 'POST'],
['/admin/novel-creation-wizard/proposals/jobs', 'POST'],
['/projects/p1/novel-generation/plans/n1/ip-bible/jobs', 'POST'],
['/projects/p1/novel-generation/plans/n1/chapters/2/run/jobs', 'POST'],
['/projects/p1/novel-generation/plans/n1/chapters/batch/jobs', 'POST'],
['/admin/hit-analyses', 'POST'],
['/admin/hit-analyses/h1/analyze', 'POST'],
['/admin/hit-analyses/h1/patterns', 'POST'],
['/admin/providers/provider-1/test', 'POST'],
['/projects/p1/story-bible/generate', 'POST'],
['/projects/p1/characters/extract', 'POST'],
['/characters/c1/anchor-video-test', 'POST'],
['/characters/c1/generate-images', 'POST'],
['/characters/c1/images/i1/review-visual', 'POST'],
['/projects/p1/episodes/plan-request-preview', 'POST'],
['/episodes/e1/script/request-preview', 'POST'],
['/episodes/e1/script/generate', 'POST'],
['/episodes/e1/audio/segments/2/retry', 'POST'],
['/episodes/e1/live-action/shots/prepare', 'POST'],
['/episodes/e1/live-action/video-clips/preflight?provider_code=kling', 'GET'],
['/episodes/e1/live-action/video-clips/cost-estimate?provider_code=kling', 'GET'],
['/live-action/video-clips/v1/quality-check', 'POST'],
['/episodes/e1/live-action/render', 'POST']
])('captures %s %s', (path, method) => {
expect(isInspectableAiRequest(path, method)).toBe(true);
});
it.each([
['/projects/p1', 'PATCH'],
['/projects/p1/novel-generation/plans', 'POST'],
['/projects/p1/novel-generation/plans/n1', 'PATCH'],
['/projects/p1/story-bible/confirm', 'POST'],
['/characters/c1/set-anchor', 'POST'],
['/episodes/e1/live-action/shots/s1/prompt', 'POST'],
['/live-action/video-clips/v1/manual-review', 'POST'],
['/live-action/video-clips/v1/select-candidate', 'POST'],
['/assets/a1', 'GET']
])('ignores non-AI mutation %s %s', (path, method) => {
expect(isInspectableAiRequest(path, method)).toBe(false);
});
it('records path, query and body while redacting secrets', () => {
clearAiRequestInspections();
let latest: AiRequestInspectionRecord[] = [];
const unsubscribe = subscribeAiRequestInspections((records) => { latest = records; });
beginAiRequestInspection({
path: '/episodes/e1/live-action/video-clips/preflight?provider_code=kling&image_id=1&image_id=2',
method: 'GET',
body: { prompt: '测试提示词', api_key: 'must-not-leak' }
});
expect(latest[0]?.request_body).toEqual({
path_params: '/episodes/e1/live-action/video-clips/preflight',
query_params: { provider_code: 'kling', image_id: ['1', '2'] },
body: { prompt: '测试提示词', api_key: '[已隐藏敏感字段]' }
});
unsubscribe();
clearAiRequestInspections();
});
it('keeps the complete response from request previews as execution evidence', () => {
clearAiRequestInspections();
let latest: AiRequestInspectionRecord[] = [];
const unsubscribe = subscribeAiRequestInspections((records) => { latest = records; });
const id = beginAiRequestInspection({
path: '/episodes/e1/script/request-preview',
method: 'POST',
body: { provider_code: 'text-provider' }
});
completeAiRequestInspection(id, {
requestId: 'req-1',
responseData: { compiled_prompt: '完整剧本提示词', temperature: 0.4 }
});
expect(latest[0]?.execution_evidence).toEqual({
compiled_prompt: '完整剧本提示词',
temperature: 0.4
});
unsubscribe();
clearAiRequestInspections();
});
});