Files
memind/deep-search-llm-gateway.mjs
T
2026-07-24 09:40:58 +08:00

64 lines
2.2 KiB
JavaScript

import crypto from 'node:crypto';
function secureEqual(left, right) {
const a = Buffer.from(String(left ?? ''));
const b = Buffer.from(String(right ?? ''));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
function normalizeMessages(value) {
if (!Array.isArray(value) || !value.length || value.length > 20) return null;
const messages = value.map((message) => ({
role: ['system', 'user', 'assistant'].includes(message?.role) ? message.role : '',
content: String(message?.content ?? '').trim(),
}));
if (messages.some((message) => !message.role || !message.content || message.content.length > 120_000)) {
return null;
}
if (messages.reduce((total, message) => total + message.content.length, 0) > 150_000) return null;
return messages;
}
export async function executeDeepSearchLlmGateway({
llmProviderService,
expectedSecret,
providedSecret,
input = {},
} = {}) {
if (!expectedSecret || !secureEqual(expectedSecret, providedSecret)) {
return { status: 401, body: { ok: false, message: 'Deep Search LLM gateway credential is invalid' } };
}
if (!llmProviderService?.createChatCompletion) {
return { status: 503, body: { ok: false, message: 'LLM provider service is unavailable' } };
}
const providerKeyId = String(input.providerKeyId ?? '').trim();
const model = String(input.model ?? '').trim();
const messages = normalizeMessages(input.messages);
if (!/^[a-zA-Z0-9._:-]{1,128}$/.test(providerKeyId) || !model || model.length > 200 || !messages) {
return { status: 400, body: { ok: false, message: 'Invalid Deep Search LLM request' } };
}
const result = await llmProviderService.createChatCompletion({
providerKeyId,
model,
messages,
temperature: Math.max(0, Math.min(1, Number(input.temperature ?? 0.2) || 0.2)),
});
if (!result?.ok) {
return {
status: Number(result?.status) >= 400 ? Number(result.status) : 502,
body: { ok: false, message: result?.message || 'Deep Search LLM request failed' },
};
}
return {
status: 200,
body: {
ok: true,
reply: result.reply,
providerKeyId: result.providerKeyId,
providerId: result.providerId,
model: result.model,
usage: result.usage ?? null,
},
};
}