feat: show backend optimization progress
This commit is contained in:
@@ -21,6 +21,7 @@ vi.mock("../../../lib/llm/client", async () => {
|
||||
import { POST as confirmFactCard } from "../jobs/[jobId]/confirm-fact-card/route";
|
||||
import { GET as downloadExport } from "../jobs/[jobId]/exports/[fileName]/route";
|
||||
import { POST as optimizeJob } from "../jobs/[jobId]/optimize/route";
|
||||
import { GET as getJobProgress } from "../jobs/[jobId]/progress/route";
|
||||
import { POST as createJob } from "../jobs/route";
|
||||
|
||||
const validFactCard = {
|
||||
@@ -236,10 +237,50 @@ describe("job API routes", () => {
|
||||
expect(body.timing.steps.map((step) => step.label)).toEqual([
|
||||
"生成优化稿",
|
||||
"质量检查",
|
||||
"整理结果",
|
||||
]);
|
||||
expect(body.timing.steps.every((step) => step.duration_ms >= 0)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns backend-visible optimization progress after a job runs", async () => {
|
||||
const { job } = await createJobFixture();
|
||||
await confirmFactCard(
|
||||
request(validFactCard),
|
||||
params<{ jobId: string }>({ jobId: job.id }),
|
||||
);
|
||||
|
||||
llmMocks.generateValidatedJson
|
||||
.mockResolvedValueOnce({
|
||||
title: "API LLM Optimized GEO Article",
|
||||
summary:
|
||||
"A official site article for Marketing teams about GEO optimization.",
|
||||
body_markdown:
|
||||
"Example Technology Co., Ltd. has 8 years of GEO optimization experience.",
|
||||
image_suggestions: [],
|
||||
changed_sections: ["title", "body"],
|
||||
requires_user_confirmation: [],
|
||||
})
|
||||
.mockResolvedValueOnce({ checks: [] });
|
||||
|
||||
await optimizeJob(request({}), params<{ jobId: string }>({ jobId: job.id }));
|
||||
|
||||
const response = await getJobProgress(
|
||||
request({}),
|
||||
params<{ jobId: string }>({ jobId: job.id }),
|
||||
);
|
||||
const body = (await response.json()) as {
|
||||
progress: { status: string; steps: Array<{ label: string; status: string }> };
|
||||
};
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(body.progress.status).toBe("completed");
|
||||
expect(body.progress.steps.map((step) => step.label)).toEqual([
|
||||
"生成优化稿",
|
||||
"质量检查",
|
||||
"整理结果",
|
||||
]);
|
||||
});
|
||||
|
||||
it("uses mocked LLM article output during optimize route", async () => {
|
||||
const { job } = await createJobFixture();
|
||||
await confirmFactCard(
|
||||
|
||||
@@ -5,6 +5,10 @@ import { getRepositoryFromRuntime } from "../../../../../lib/db/repository";
|
||||
import { LlmValidationError } from "../../../../../lib/llm/client";
|
||||
import { getExportStoreFromRuntime } from "../../../../../lib/workflow/export-store";
|
||||
import { runOptimizationWorkflow } from "../../../../../lib/workflow/orchestrator";
|
||||
import {
|
||||
recordWorkflowProgress,
|
||||
startWorkflowProgress,
|
||||
} from "../../../../../lib/workflow/progress-store";
|
||||
|
||||
interface RouteContext {
|
||||
params: Promise<{ jobId: string }>;
|
||||
@@ -32,6 +36,7 @@ export async function POST(request: Request, context: RouteContext) {
|
||||
}
|
||||
|
||||
const requestStartedAt = Date.now();
|
||||
startWorkflowProgress(jobId);
|
||||
try {
|
||||
const result = await runOptimizationWorkflow({
|
||||
input: {
|
||||
@@ -42,6 +47,9 @@ export async function POST(request: Request, context: RouteContext) {
|
||||
user_instructions: job.user_instructions,
|
||||
},
|
||||
factCard: factCardRecord,
|
||||
onProgress: (event) => {
|
||||
recordWorkflowProgress(jobId, event);
|
||||
},
|
||||
});
|
||||
const optimizedArticle = await repository.saveOptimizedArticle(
|
||||
jobId,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { requireApiAccess } from "../../../../../lib/api/auth";
|
||||
import { getWorkflowProgress } from "../../../../../lib/workflow/progress-store";
|
||||
|
||||
interface RouteContext {
|
||||
params: Promise<{ jobId: string }>;
|
||||
}
|
||||
|
||||
export async function GET(request: Request, context: RouteContext) {
|
||||
const access = requireApiAccess(request);
|
||||
if (!access.ok) {
|
||||
return access.response;
|
||||
}
|
||||
|
||||
const { jobId } = await context.params;
|
||||
return NextResponse.json({ progress: getWorkflowProgress(jobId) });
|
||||
}
|
||||
Reference in New Issue
Block a user