47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
// apps/web/server/api/mcp/screenshot.post.ts
|
|||
import { defineEventHandler, readBody, createError } from 'h3';
|
|||
import { sendToClient, getLastActiveClientId, isClientConnected } from '../../utils/mcp-sync-state';
|
|||
import {
|
|||
allocateRequestId,
|
|||
registerPending,
|
|||
type ScreenshotRequestBody,
|
|||
} from '../../utils/mcp-screenshot-rpc';
|
|||
|
|||
export default defineEventHandler(async (event) => {
|
|||
const body = (await readBody(event)) as ScreenshotRequestBody;
|
|||
const timeoutMs = Math.min(body.timeoutMs ?? 15000, 60000);
|
|||
|
|||
// 1. Resolve target renderer — fail fast if none
|
|||
const targetClientId = getLastActiveClientId();
|
|||
if (!targetClientId || !isClientConnected(targetClientId)) {
|
|||
throw createError({
|
|||
statusCode: 503,
|
|||
statusMessage:
|
|||
'No active editor client — make sure an Electron window or /editor tab is open and focused.',
|
|||
});
|
|||
}
|
|||
|
|||
// 2. Allocate request id and try to send
|
|||
const requestId = allocateRequestId();
|
|||
const sent = sendToClient(targetClientId, {
|
|||
type: 'screenshot:request',
|
|||
requestId,
|
|||
bounds: body.bounds,
|
|||
nodeId: body.nodeId,
|
|||
opts: body.opts,
|
|||
timeoutMs,
|
|||
});
|
|||
|
|||
// 3. Only register pending + start timeout AFTER successful send (Q3 decision)
|
|||
if (!sent) {
|
|||
throw createError({
|
|||
statusCode: 503,
|
|||
statusMessage:
|
|||
'Failed to deliver screenshot request — target editor client disconnected between check and send.',
|
|||
});
|
|||
}
|
|||
|
|||
// 4. Await renderer response (or timeout)
|
|||
return await registerPending(requestId, timeoutMs);
|
|||
});
|