feat(heal): add server-side AI inpainting endpoint via ONNX Runtime
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { runServerInpaint } from './inpaintService';
|
||||
import { recipeFile } from './recipeFile';
|
||||
import { sendVerificationMail } from './mailer';
|
||||
import { placeName } from './place';
|
||||
@@ -425,6 +426,43 @@ async function lookupGeo(ip: string): Promise<GeoPlace | null> {
|
||||
// ---- routes ----
|
||||
app.get('/api/health', async () => ({ ok: true }));
|
||||
|
||||
// AI Inpainting endpoint (Hybrid Option 2)
|
||||
app.post('/api/inpaint', { bodyLimit: 10 * 1024 * 1024 }, async (req, reply) => {
|
||||
const b = bodyOf(req) as {
|
||||
src?: string;
|
||||
mask?: string;
|
||||
w?: number;
|
||||
h?: number;
|
||||
};
|
||||
if (!b || !b.src || !b.mask || typeof b.w !== 'number' || typeof b.h !== 'number') {
|
||||
return reply.status(400).send({ ok: false, error: 'Missing src, mask, w, or h' });
|
||||
}
|
||||
|
||||
const { w, h } = b;
|
||||
const srcBuf = Buffer.from(b.src, 'base64');
|
||||
const maskBuf = Buffer.from(b.mask, 'base64');
|
||||
|
||||
if (srcBuf.length !== 3 * w * h || maskBuf.length !== w * h) {
|
||||
return reply.status(400).send({ ok: false, error: 'Dimension mismatch' });
|
||||
}
|
||||
|
||||
try {
|
||||
const patch = await runServerInpaint(new Uint8Array(srcBuf), new Uint8Array(maskBuf), w, h);
|
||||
if (!patch) {
|
||||
return reply.status(503).send({ ok: false, error: 'Inpaint model unavailable' });
|
||||
}
|
||||
return reply.send({
|
||||
ok: true,
|
||||
patch: Buffer.from(patch).toString('base64'),
|
||||
w,
|
||||
h,
|
||||
});
|
||||
} catch (err: any) {
|
||||
req.log.error(err, 'Inpaint inference error');
|
||||
return reply.status(500).send({ ok: false, error: String(err?.message || err) });
|
||||
}
|
||||
});
|
||||
|
||||
// Native file manager launcher (Open in window explorer)
|
||||
app.post('/api/open-explorer', async (req, reply) => {
|
||||
const b = bodyOf(req);
|
||||
|
||||
Reference in New Issue
Block a user