| 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 | |
| 14 | export async function runStyleSwitchPageFlow(args: { |
| 15 | ctx: IpcContext |
| 16 | job: ActiveStyleSwitchJob |
| 17 | page: StyleSwitchPageRef |
| 18 | indexPath: string |
| 19 | indexSnapshot: StyleSwitchFileSnapshot |
| 20 | emitProgress: (chunk: GenerateChunkEvent) => void |
| 21 | }): Promise<string> { |
| 22 | const { ctx, job, page, indexPath, indexSnapshot, emitProgress } = args |
| 23 | await runDeepAgentEdit({ |
| 24 | sessionId: job.sessionId, |
| 25 | provider: job.context.provider, |
| 26 | apiKey: job.context.apiKey, |
| 27 | model: job.context.model, |
| 28 | baseUrl: job.context.providerBaseUrl, |
| 29 | maxTokens: job.context.maxTokens, |
| 30 | modelTimeoutMs: job.context.modelTimeouts.agent, |
| 31 | temperature: ctx.PAGE_EDIT_DEFAULT_TEMPERATURE, |
| 32 | styleId: job.context.styleId, |
| 33 | styleSkillPrompt: job.context.styleSkill.prompt, |
| 34 | styleKey: job.context.styleKey, |
| 35 | styleName: job.context.styleName, |
| 36 | styleVersion: job.context.styleVersion, |
| 37 | slideSize: job.context.slideSize, |
| 38 | appLocale: job.context.appLocale, |
| 39 | topic: job.context.topic, |
| 40 | deckTitle: job.context.deckTitle, |
| 41 | userMessage: buildDeckEditPageUserMessage({ |
| 42 | originalUserMessage: job.context.userMessage, |
| 43 | pageId: page.pageId |
| 44 | }), |
| 45 | outlineTitles: job.pageRefs.map((item) => item.title), |
| 46 | outlineItems: job.pageRefs.map((item) => ({ |
| 47 | title: item.title, |
| 48 | contentOutline: item.contentOutline, |
| 49 | layoutIntent: item.layoutIntent |
| 50 | })), |
| 51 | sourceDocumentPaths: job.context.sourceDocumentPaths, |
| 52 | projectDir: job.context.projectDir, |
| 53 | indexPath, |
| 54 | pageFileMap: { [page.pageId]: page.htmlPath }, |
| 55 | selectPageIds: [page.pageId], |
| 56 | designContract: job.context.designContract, |
| 57 | existingPageIds: [page.pageId], |
| 58 | agentManager: ctx.agentManager, |
| 59 | runId: job.runId, |
| 60 | signal: job.context.abortSignal, |
| 61 | emit: emitProgress, |
| 62 | editScope: 'page', |
| 63 | selectedPageId: page.pageId, |
| 64 | selectedPageNumber: page.pageNumber |
| 65 | }) |
| 66 | if (job.lease.signal.aborted) throw new Error('生成已取消') |
| 67 | const currentIndex = await readStyleSwitchFileSnapshot(indexPath) |
| 68 | if ( |
| 69 | currentIndex.exists !== indexSnapshot.exists || |
| 70 | currentIndex.content !== indexSnapshot.content |
| 71 | ) { |
| 72 | throw new Error('风格切换不允许修改 index.html') |
| 73 | } |
| 74 | const html = await fs.promises.readFile(page.htmlPath, 'utf-8') |
| 75 | const invalidPages = validateChangedPages([{ ...page, html }]) |
| 76 | if (invalidPages.length > 0) throw new Error(invalidPages.map((item) => item.reason).join(';')) |
| 77 | return html |
| 78 | } |
| 79 |