feat(mcps): add kabelfachmann MCP with Kabelhandbuch integration and remove legacy PM2 orchestration
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧪 Test (push) Successful in 1m6s
Monorepo Pipeline / 🏗️ Build (push) Successful in 2m52s
Monorepo Pipeline / 🧹 Lint (push) Successful in 3m1s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 4s

This commit is contained in:
2026-03-08 01:01:43 +01:00
parent 048fafa3db
commit 541f1c17b7
16 changed files with 866 additions and 254 deletions

View File

@@ -1,75 +1,108 @@
import { PayloadRequest } from 'payload'
import { PayloadRequest } from "payload";
import { parseMarkdownToLexical } from "../utils/lexicalParser.js";
export const optimizePostEndpoint = async (req: PayloadRequest) => {
try {
let body: any = {};
try {
const { draftContent, instructions } = (await req.json?.() || {}) as { draftContent: string; instructions?: string };
if (!draftContent) {
return Response.json({ error: 'Missing draftContent' }, { status: 400 })
}
const globalAiSettings = (await req.payload.findGlobal({ slug: "ai-settings" })) as any;
const customSources =
globalAiSettings?.customSources?.map((s: any) => s.sourceName) || [];
const OPENROUTER_KEY =
process.env.OPENROUTER_KEY || process.env.OPENROUTER_API_KEY;
const REPLICATE_KEY = process.env.REPLICATE_API_KEY;
if (!OPENROUTER_KEY) {
return Response.json({ error: "OPENROUTER_KEY not found in environment." }, { status: 500 })
}
// Dynamically import to avoid bundling it into client components that might accidentally import this file
const importDynamic = new Function("modulePath", "return import(modulePath)");
const { AiBlogPostOrchestrator } = await importDynamic("@mintel/content-engine");
const orchestrator = new AiBlogPostOrchestrator({
apiKey: OPENROUTER_KEY,
replicateApiKey: REPLICATE_KEY,
model: "google/gemini-3-flash-preview",
});
const contextDocsData = await req.payload.find({
collection: "context-files" as any,
limit: 100,
});
const projectContext = contextDocsData.docs.map((doc: any) => doc.content);
const optimizedMarkdown = await orchestrator.optimizeDocument({
content: draftContent,
projectContext,
availableComponents: [],
instructions,
internalLinks: [],
customSources,
});
if (!optimizedMarkdown || typeof optimizedMarkdown !== "string") {
return Response.json({ error: "AI returned invalid markup." }, { status: 500 })
}
const blocks = parseMarkdownToLexical(optimizedMarkdown);
return Response.json({
success: true,
lexicalAST: {
root: {
type: "root",
format: "",
indent: 0,
version: 1,
children: blocks,
direction: "ltr",
},
},
})
} catch (error: any) {
console.error("Failed to optimize post in endpoint:", error);
return Response.json({
success: false,
error: error.message || "An unknown error occurred during optimization.",
}, { status: 500 })
if (req.body) {
// req.json() acts as a method in Next.js/Payload req wrapper
body = (await req.json?.()) || {};
}
} catch (e) {
// Ignore JSON parse error, body remains empty
}
}
const { draftContent, instructions } = body as {
draftContent?: string;
instructions?: string;
};
if (!draftContent) {
return Response.json(
{ success: false, error: "Missing draftContent" },
{ status: 400 },
);
}
const globalAiSettings = (await req.payload.findGlobal({
slug: "ai-settings",
})) as any;
const customSources =
globalAiSettings?.customSources?.map((s: any) => s.sourceName) || [];
const OPENROUTER_KEY =
process.env.OPENROUTER_KEY || process.env.OPENROUTER_API_KEY;
const REPLICATE_KEY = process.env.REPLICATE_API_KEY;
if (!OPENROUTER_KEY) {
return Response.json(
{ error: "OPENROUTER_KEY not found in environment." },
{ status: 500 },
);
}
// Dynamically import to avoid bundling it into client components that might accidentally import this file
const importDynamic = new Function(
"modulePath",
"return import(modulePath)",
);
const { AiBlogPostOrchestrator } = await importDynamic(
"@mintel/content-engine",
);
const orchestrator = new AiBlogPostOrchestrator({
apiKey: OPENROUTER_KEY,
replicateApiKey: REPLICATE_KEY,
model: "google/gemini-3-flash-preview",
});
const contextDocsData = await req.payload.find({
collection: "context-files" as any,
limit: 100,
});
const projectContext = contextDocsData.docs.map((doc: any) => doc.content);
const optimizedMarkdown = await orchestrator.optimizeDocument({
content: draftContent,
projectContext,
availableComponents: [],
instructions,
internalLinks: [],
customSources,
});
if (!optimizedMarkdown || typeof optimizedMarkdown !== "string") {
return Response.json(
{ error: "AI returned invalid markup." },
{ status: 500 },
);
}
const blocks = parseMarkdownToLexical(optimizedMarkdown);
return Response.json({
success: true,
lexicalAST: {
root: {
type: "root",
format: "",
indent: 0,
version: 1,
children: blocks,
direction: "ltr",
},
},
});
} catch (error: any) {
console.error("Failed to optimize post in endpoint:", error);
return Response.json(
{
success: false,
error:
error.message || "An unknown error occurred during optimization.",
},
{ status: 500 },
);
}
};