type IngestTextArgs = { fileSource: string; text: string; }; type IngestTextResult = { trackId: string | null; skipped?: boolean; reason?: string; }; export function isLightRagEnabled(): boolean { return Boolean((process.env.LIGHTRAG_URL || "").trim()); } export async function lightragIngestText(args: IngestTextArgs): Promise { const baseUrl = (process.env.LIGHTRAG_URL || "").trim().replace(/\/+$/, ""); if (!baseUrl) { // 说明:LightRAG 未配置时不应让任务系统持续报错;直接降级为“跳过入库”。 return { trackId: null, skipped: true, reason: "missing_env_LIGHTRAG_URL" }; } const fileSource = String(args.fileSource ?? "").trim(); if (!fileSource) { throw new Error("缺少 fileSource"); } const text = String(args.text ?? ""); if (!text.trim()) { return { trackId: null, skipped: true, reason: "empty_text" }; } const apiKey = (process.env.LIGHTRAG_API_KEY || "").trim(); const headers: Record = { "Content-Type": "application/json" }; if (apiKey) { headers["X-API-Key"] = apiKey; } // 说明:LightRAG(>=1.4.x) 使用 /documents/text 作为“文本入库”接口。 const resp = await fetch(`${baseUrl}/documents/text`, { method: "POST", headers, body: JSON.stringify({ text, file_source: fileSource }), }); if (!resp.ok) { const raw = await resp.text().catch(() => ""); throw new Error(`LightRAG 入库失败:HTTP ${resp.status} ${raw.slice(0, 500)}`); } const data = (await resp.json().catch(() => null)) as unknown; const trackId = (() => { if (!data || typeof data !== "object") return null; const v = (data as Record).track_id; return typeof v === "string" ? v : null; })(); return { trackId }; }