mirror of
https://github.com/prowler-cloud/prowler.git
synced 2025-12-19 05:17:47 +00:00
156 lines
4.1 KiB
TypeScript
156 lines
4.1 KiB
TypeScript
import { createAgent } from "langchain";
|
|
|
|
import {
|
|
getProviderCredentials,
|
|
getTenantConfig,
|
|
} from "@/actions/lighthouse/lighthouse";
|
|
import { TOOLS_UNAVAILABLE_MESSAGE } from "@/lib/lighthouse/constants";
|
|
import type { ProviderType } from "@/lib/lighthouse/llm-factory";
|
|
import { createLLM } from "@/lib/lighthouse/llm-factory";
|
|
import {
|
|
getMCPTools,
|
|
initializeMCPClient,
|
|
isMCPAvailable,
|
|
} from "@/lib/lighthouse/mcp-client";
|
|
import {
|
|
generateUserDataSection,
|
|
LIGHTHOUSE_SYSTEM_PROMPT_TEMPLATE,
|
|
} from "@/lib/lighthouse/system-prompt";
|
|
import { describeTool, executeTool } from "@/lib/lighthouse/tools/meta-tool";
|
|
import { getModelParams } from "@/lib/lighthouse/utils";
|
|
|
|
export interface RuntimeConfig {
|
|
model?: string;
|
|
provider?: string;
|
|
businessContext?: string;
|
|
currentData?: string;
|
|
}
|
|
|
|
/**
|
|
* Truncate description to specified length
|
|
*/
|
|
function truncateDescription(desc: string | undefined, maxLen: number): string {
|
|
if (!desc) return "No description available";
|
|
|
|
const cleaned = desc.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
|
|
|
|
if (cleaned.length <= maxLen) return cleaned;
|
|
|
|
return cleaned.substring(0, maxLen) + "...";
|
|
}
|
|
|
|
/**
|
|
* Tools that are blocked from being listed and executed by the LLM.
|
|
* These are destructive or sensitive operations that should only be
|
|
* performed through the UI with explicit user action.
|
|
*/
|
|
const BLOCKED_TOOLS = new Set([
|
|
"prowler_app_connect_provider",
|
|
"prowler_app_delete_provider",
|
|
"prowler_app_trigger_scan",
|
|
"prowler_app_schedule_daily_scan",
|
|
"prowler_app_update_scan",
|
|
"prowler_app_delete_mutelist",
|
|
"prowler_app_set_mutelist",
|
|
"prowler_app_create_mute_rule",
|
|
"prowler_app_update_mute_rule",
|
|
"prowler_app_delete_mute_rule",
|
|
]);
|
|
|
|
/**
|
|
* Check if a tool is blocked
|
|
*/
|
|
export function isBlockedTool(toolName: string): boolean {
|
|
return BLOCKED_TOOLS.has(toolName);
|
|
}
|
|
|
|
/**
|
|
* Generate dynamic tool listing from MCP tools
|
|
* Filters out blocked/destructive tools
|
|
*/
|
|
function generateToolListing(): string {
|
|
if (!isMCPAvailable()) {
|
|
return TOOLS_UNAVAILABLE_MESSAGE;
|
|
}
|
|
|
|
const mcpTools = getMCPTools();
|
|
|
|
if (mcpTools.length === 0) {
|
|
return TOOLS_UNAVAILABLE_MESSAGE;
|
|
}
|
|
|
|
// Filter out blocked tools
|
|
const safeTools = mcpTools.filter((tool) => !isBlockedTool(tool.name));
|
|
|
|
let listing = "\n## Available Prowler Tools\n\n";
|
|
listing += `${safeTools.length} tools loaded from Prowler MCP\n\n`;
|
|
|
|
for (const tool of safeTools) {
|
|
const desc = truncateDescription(tool.description, 150);
|
|
listing += `- **${tool.name}**: ${desc}\n`;
|
|
}
|
|
|
|
listing +=
|
|
"\nUse describe_tool with exact tool name to see full schema and parameters.\n";
|
|
|
|
return listing;
|
|
}
|
|
|
|
export async function initLighthouseWorkflow(runtimeConfig?: RuntimeConfig) {
|
|
await initializeMCPClient();
|
|
|
|
const toolListing = generateToolListing();
|
|
|
|
let systemPrompt = LIGHTHOUSE_SYSTEM_PROMPT_TEMPLATE.replace(
|
|
"{{TOOL_LISTING}}",
|
|
toolListing,
|
|
);
|
|
|
|
// Add user-provided data section if available
|
|
const userDataSection = generateUserDataSection(
|
|
runtimeConfig?.businessContext,
|
|
runtimeConfig?.currentData,
|
|
);
|
|
|
|
if (userDataSection) {
|
|
systemPrompt += userDataSection;
|
|
}
|
|
|
|
const tenantConfigResult = await getTenantConfig();
|
|
const tenantConfig = tenantConfigResult?.data?.attributes;
|
|
|
|
const defaultProvider = tenantConfig?.default_provider || "openai";
|
|
const defaultModels = tenantConfig?.default_models || {};
|
|
const defaultModel = defaultModels[defaultProvider] || "gpt-5.2";
|
|
|
|
const providerType = (runtimeConfig?.provider ||
|
|
defaultProvider) as ProviderType;
|
|
const modelId = runtimeConfig?.model || defaultModel;
|
|
|
|
// Get credentials
|
|
const providerConfig = await getProviderCredentials(providerType);
|
|
const { credentials, base_url: baseUrl } = providerConfig;
|
|
|
|
// Get model params
|
|
const modelParams = getModelParams({ model: modelId });
|
|
|
|
// Initialize LLM
|
|
const llm = createLLM({
|
|
provider: providerType,
|
|
model: modelId,
|
|
credentials,
|
|
baseUrl,
|
|
streaming: true,
|
|
tags: ["lighthouse-agent"],
|
|
modelParams,
|
|
});
|
|
|
|
const agent = createAgent({
|
|
model: llm,
|
|
tools: [describeTool, executeTool],
|
|
systemPrompt,
|
|
});
|
|
|
|
return agent;
|
|
}
|