refactor(api): remove mode, add colorizeStrength, lower denoise default to 25

This commit is contained in:
SnapOtter
2026-05-13 16:59:13 +08:00
parent 693b441aa0
commit 79cb570a3a
2 changed files with 36 additions and 19 deletions
+7 -10
View File
@@ -19,13 +19,13 @@ import { updateSingleFileProgress } from "../progress.js";
import { registerToolProcessFn } from "../tool-factory.js";
const settingsSchema = z.object({
mode: z.enum(["auto", "light", "heavy"]).default("auto"),
scratchRemoval: z.boolean().default(true),
faceEnhancement: z.boolean().default(true),
fidelity: z.number().min(0).max(1).default(0.7),
denoise: z.boolean().default(true),
denoiseStrength: z.number().min(0).max(100).default(40),
denoiseStrength: z.number().min(0).max(100).default(25),
colorize: z.boolean().default(false),
colorizeStrength: z.number().min(0).max(100).default(85),
});
/**
@@ -153,10 +153,7 @@ export function registerRestorePhoto(app: FastifyInstance) {
}
const log = request.log;
log.info(
{ toolId: "restore-photo", imageSize: originalSize, mode: settings.mode },
"Starting photo restoration",
);
log.info({ toolId: "restore-photo", imageSize: originalSize }, "Starting photo restoration");
// Reply immediately so the HTTP connection closes within proxy timeout limits.
// The result will be delivered via the SSE progress channel.
@@ -178,13 +175,13 @@ export function registerRestorePhoto(app: FastifyInstance) {
fileBuffer,
join(workspacePath, "output"),
{
mode: settings.mode,
scratchRemoval: settings.scratchRemoval,
faceEnhancement: settings.faceEnhancement,
fidelity: settings.fidelity,
denoise: settings.denoise,
denoiseStrength: settings.denoiseStrength,
colorize: settings.colorize,
colorizeStrength: settings.colorizeStrength,
},
onProgress,
);
@@ -257,13 +254,13 @@ export function registerRestorePhoto(app: FastifyInstance) {
registerToolProcessFn({
toolId: "restore-photo",
settingsSchema: z.object({
mode: z.enum(["auto", "light", "heavy"]).default("auto"),
scratchRemoval: z.boolean().default(true),
faceEnhancement: z.boolean().default(true),
fidelity: z.number().min(0).max(1).default(0.7),
denoise: z.boolean().default(true),
denoiseStrength: z.number().min(0).max(100).default(40),
denoiseStrength: z.number().min(0).max(100).default(25),
colorize: z.boolean().default(false),
colorizeStrength: z.number().min(0).max(100).default(85),
}),
process: async (inputBuffer, settings, filename) => {
const s = settings as z.infer<typeof settingsSchema>;
@@ -271,13 +268,13 @@ export function registerRestorePhoto(app: FastifyInstance) {
const jobId = randomUUID();
const workspacePath = await createWorkspace(jobId);
const result = await restorePhoto(orientedBuffer, join(workspacePath, "output"), {
mode: s.mode,
scratchRemoval: s.scratchRemoval,
faceEnhancement: s.faceEnhancement,
fidelity: s.fidelity,
denoise: s.denoise,
denoiseStrength: s.denoiseStrength,
colorize: s.colorize,
colorizeStrength: s.colorizeStrength,
});
const outputFormat = await resolveOutputFormat(inputBuffer, filename);
let outputBuffer = result.buffer;
+29 -9
View File
@@ -83,17 +83,16 @@ describe("Restore Photo", () => {
}
}, 60_000);
it("accepts auto mode with all features enabled", async () => {
it("accepts all features enabled", async () => {
const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "test.png", contentType: "image/png", content: PNG },
{
name: "settings",
content: JSON.stringify({
mode: "auto",
scratchRemoval: true,
faceEnhancement: true,
denoise: true,
denoiseStrength: 40,
denoiseStrength: 25,
}),
},
]);
@@ -111,14 +110,14 @@ describe("Restore Photo", () => {
expect([202, 501]).toContain(res.statusCode);
}, 60_000);
it("accepts heavy mode with colorize enabled", async () => {
it("accepts colorize with custom strength", async () => {
const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "test.png", contentType: "image/png", content: PNG },
{
name: "settings",
content: JSON.stringify({
mode: "heavy",
colorize: true,
colorizeStrength: 50,
fidelity: 0.9,
}),
},
@@ -137,13 +136,12 @@ describe("Restore Photo", () => {
expect([202, 501]).toContain(res.statusCode);
}, 60_000);
it("accepts light mode with features disabled", async () => {
it("accepts all features disabled", async () => {
const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "test.png", contentType: "image/png", content: PNG },
{
name: "settings",
content: JSON.stringify({
mode: "light",
scratchRemoval: false,
faceEnhancement: false,
denoise: false,
@@ -273,12 +271,12 @@ describe("Restore Photo", () => {
}
});
it("rejects invalid mode value", async () => {
it("rejects colorizeStrength out of range", async () => {
const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "test.png", contentType: "image/png", content: PNG },
{
name: "settings",
content: JSON.stringify({ mode: "turbo" }),
content: JSON.stringify({ colorizeStrength: 150 }),
},
]);
@@ -366,4 +364,26 @@ describe("Restore Photo", () => {
expect(res.statusCode).toBe(401);
});
it("ignores old mode field gracefully", async () => {
const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "test.png", contentType: "image/png", content: PNG },
{
name: "settings",
content: JSON.stringify({ mode: "heavy", scratchRemoval: true }),
},
]);
const res = await app.inject({
method: "POST",
url: "/api/v1/tools/restore-photo",
headers: {
authorization: `Bearer ${adminToken}`,
"content-type": contentType,
},
body,
});
expect([202, 501]).toContain(res.statusCode);
}, 60_000);
});