返回 oh-my-ppt
style-switch-job-flow.ts
根目录 / src / main / edit-jobs / style-switch-job-flow.ts
1 import fs from 'fs'
2 import { runDeepAgentEdit } from '../generation/agent-runner'
3 import { buildDeckEditPageUserMessage } from '../generation/edit-deck-batch-flow'
4 import { validateChangedPages } from '../generation/generation-utils'
5 import type { GenerateChunkEvent } from '@shared/generation'
6 import type {
7 ActiveStyleSwitchJob,
8 StyleSwitchFileSnapshot,
9 StyleSwitchPageRef
10 } from './style-switch-job-types'
11 import type { IpcContext } from '../ipc/context'
12 import { readStyleSwitchFileSnapshot } from './style-switch-job-files'
13 import { LAYOUT_SLOT_PRESERVATION_REQUIREMENT } from '../generation/layout-slot-validator'
14
15 export async function runStyleSwitchPageFlow(args: {
16 ctx: IpcContext
17 job: ActiveStyleSwitchJob
18 page: StyleSwitchPageRef
19 indexPath: string
20 indexSnapshot: StyleSwitchFileSnapshot
21 emitProgress: (chunk: GenerateChunkEvent) => void
22 }): Promise<string> {
23 const { ctx, job, page, indexPath, indexSnapshot, emitProgress } = args
24 await runDeepAgentEdit({
25 sessionId: job.sessionId,
26 provider: job.context.provider,
27 apiKey: job.context.apiKey,
28 model: job.context.model,
29 baseUrl: job.context.providerBaseUrl,
30 maxTokens: job.context.maxTokens,
31 modelTimeoutMs: job.context.modelTimeouts.agent,
32 temperature: ctx.PAGE_EDIT_DEFAULT_TEMPERATURE,
33 styleId: job.context.styleId,
34 styleSkillPrompt: job.context.styleSkill.prompt,
35 styleKey: job.context.styleKey,
36 styleName: job.context.styleName,
37 styleVersion: job.context.styleVersion,
38 slideSize: job.context.slideSize,
39 appLocale: job.context.appLocale,
40 topic: job.context.topic,
41 deckTitle: job.context.deckTitle,
42 userMessage: [
43 buildDeckEditPageUserMessage({
44 originalUserMessage: job.context.userMessage,
45 pageId: page.pageId
46 }),
47 LAYOUT_SLOT_PRESERVATION_REQUIREMENT
48 ].join('\n\n'),
49 outlineTitles: job.pageRefs.map((item) => item.title),
50 outlineItems: job.pageRefs.map((item) => ({
51 title: item.title,
52 contentOutline: item.contentOutline,
53 layoutIntent: item.layoutIntent,
54 layoutId: item.layoutId || undefined
55 })),
56 sourceDocumentPaths: job.context.sourceDocumentPaths,
57 projectDir: job.context.projectDir,
58 indexPath,
59 pageFileMap: { [page.pageId]: page.htmlPath },
60 selectPageIds: [page.pageId],
61 designContract: job.context.designContract,
62 existingPageIds: [page.pageId],
63 agentManager: ctx.agentManager,
64 runId: job.runId,
65 signal: job.context.abortSignal,
66 emit: emitProgress,
67 editScope: 'page',
68 selectedPageId: page.pageId,
69 selectedPageNumber: page.pageNumber
70 })
71 if (job.lease.signal.aborted) throw new Error('生成已取消')
72 const currentIndex = await readStyleSwitchFileSnapshot(indexPath)
73 if (
74 currentIndex.exists !== indexSnapshot.exists ||
75 currentIndex.content !== indexSnapshot.content
76 ) {
77 throw new Error('风格切换不允许修改 index.html')
78 }
79 const html = await fs.promises.readFile(page.htmlPath, 'utf-8')
80 const invalidPages = validateChangedPages([{ ...page, html }])
81 if (invalidPages.length > 0) throw new Error(invalidPages.map((item) => item.reason).join(';'))
82 return html
83 }
84
84 lines TYPESCRIPT