Files
ClawX/electron/api/routes/media.ts
T
2026-05-25 18:51:03 +08:00

113 lines
3.8 KiB
TypeScript

import type { IncomingMessage, ServerResponse } from 'http';
import type { HostApiContext } from '../context';
import {
CLAWX_OPENAI_IMAGE_DEFAULT_MODEL,
CLAWX_OPENAI_IMAGE_PROVIDER_KEY,
} from '../../utils/openclaw-image-relay-constants';
import { parseJsonBody, sendJson } from '../route-utils';
import {
applyOpenAiImageRelaySettings,
getImageGenerationSettingsSnapshot,
listImageGenerationProvidersFromRuntime,
runImageGenerationTest,
setImageGenerationConfig,
type ImageGenerationModelConfig,
} from '../../utils/openclaw-image-generation';
export async function handleMediaRoutes(
req: IncomingMessage,
res: ServerResponse,
url: URL,
_ctx: HostApiContext,
): Promise<boolean> {
if (url.pathname === '/api/media/image-generation' && req.method === 'GET') {
try {
sendJson(res, 200, { success: true, ...(await getImageGenerationSettingsSnapshot()) });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
}
return true;
}
if (url.pathname === '/api/media/image-generation' && req.method === 'PUT') {
try {
const body = await parseJsonBody<{
timeoutMs?: number | null;
openAiRelayEnabled?: boolean;
openAiRelayBaseUrl?: string | null;
openAiRelayModel?: string | null;
openAiRelayApiKey?: string;
}>(req);
const current = await getImageGenerationSettingsSnapshot();
const normalizeRelayModel = (value: unknown): string => {
const raw = typeof value === 'string' && value.trim()
? value.trim()
: (current.openAiRelay.model || CLAWX_OPENAI_IMAGE_DEFAULT_MODEL);
const slash = raw.indexOf('/');
return (slash > 0 ? raw.slice(slash + 1) : raw).trim() || CLAWX_OPENAI_IMAGE_DEFAULT_MODEL;
};
const relayModel = normalizeRelayModel(body.openAiRelayModel);
let nextPrimary = current.config.primary;
if (body.openAiRelayEnabled === true) {
nextPrimary = `${CLAWX_OPENAI_IMAGE_PROVIDER_KEY}/${relayModel}`;
} else if (body.openAiRelayEnabled === false) {
nextPrimary = null;
}
const next: ImageGenerationModelConfig = {
primary: nextPrimary,
fallbacks: [],
timeoutMs: body.timeoutMs !== undefined
? (typeof body.timeoutMs === 'number' && body.timeoutMs > 0 ? Math.floor(body.timeoutMs) : null)
: current.config.timeoutMs,
};
if (typeof body.openAiRelayEnabled === 'boolean') {
await applyOpenAiImageRelaySettings({
enabled: body.openAiRelayEnabled,
baseUrl: body.openAiRelayBaseUrl,
apiKey: body.openAiRelayApiKey,
model: relayModel,
});
}
const config = await setImageGenerationConfig(next);
sendJson(res, 200, {
success: true,
config,
...(await getImageGenerationSettingsSnapshot()),
});
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
}
return true;
}
if (url.pathname === '/api/media/image-generation/providers' && req.method === 'GET') {
try {
const providers = await listImageGenerationProvidersFromRuntime();
sendJson(res, 200, { success: true, providers });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
}
return true;
}
if (url.pathname === '/api/media/image-generation/test' && req.method === 'POST') {
try {
const body = await parseJsonBody<{
agentId?: string;
prompt?: string;
model?: string;
}>(req);
const result = await runImageGenerationTest(body);
sendJson(res, result.success ? 200 : 500, { success: result.success, ...result });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
}
return true;
}
return false;
}