diff --git a/ui/actions/lighthouse/compliances.ts b/ui/actions/lighthouse/compliances.ts index d61e97e17b..782156d977 100644 --- a/ui/actions/lighthouse/compliances.ts +++ b/ui/actions/lighthouse/compliances.ts @@ -1,6 +1,6 @@ import { apiBaseUrl, getAuthHeaders, parseStringify } from "@/lib/helper"; -export const aiGetCompliancesOverview = async ({ +export const getLighthouseCompliancesOverview = async ({ scanId, // required fields, filters, @@ -63,7 +63,7 @@ export const aiGetCompliancesOverview = async ({ } }; -export const aiGetComplianceOverview = async ({ +export const getLighthouseComplianceOverview = async ({ complianceId, fields, }: { diff --git a/ui/actions/lighthouse/lighthouse.ts b/ui/actions/lighthouse/lighthouse.ts index ce236160a0..92f6bcf738 100644 --- a/ui/actions/lighthouse/lighthouse.ts +++ b/ui/actions/lighthouse/lighthouse.ts @@ -2,7 +2,7 @@ import { apiBaseUrl, getAuthHeaders } from "@/lib/helper"; -const getAIConfigurationId = async (): Promise => { +const getLighthouseConfigId = async (): Promise => { const headers = await getAuthHeaders({ contentType: false }); const url = new URL(`${apiBaseUrl}/lighthouse-config?filter[name]=OpenAI`); try { @@ -28,7 +28,7 @@ const getAIConfigurationId = async (): Promise => { export const getAIKey = async (): Promise => { const headers = await getAuthHeaders({ contentType: false }); - const configId = await getAIConfigurationId(); + const configId = await getLighthouseConfigId(); if (!configId) { return ""; @@ -44,7 +44,7 @@ export const getAIKey = async (): Promise => { return data.data.api_key; }; -export const createAIConfiguration = async (config: { +export const createLighthouseConfig = async (config: { model: string; apiKey: string; businessContext: string; @@ -77,9 +77,9 @@ export const createAIConfiguration = async (config: { } }; -export const getAIConfiguration = async () => { +export const getLighthouseConfig = async () => { const headers = await getAuthHeaders({ contentType: false }); - const configId = await getAIConfigurationId(); + const configId = await getLighthouseConfigId(); if (!configId) { return undefined; @@ -99,13 +99,13 @@ export const getAIConfiguration = async () => { } }; -export const updateAIConfiguration = async (config: { +export const updateLighthouseConfig = async (config: { model: string; apiKey: string; businessContext: string; }) => { const headers = await getAuthHeaders({ contentType: true }); - const configId = await getAIConfigurationId(); + const configId = await getLighthouseConfigId(); if (!configId) { return undefined; diff --git a/ui/actions/lighthouse/resources.ts b/ui/actions/lighthouse/resources.ts index 90f4ce85a4..21beaabc19 100644 --- a/ui/actions/lighthouse/resources.ts +++ b/ui/actions/lighthouse/resources.ts @@ -1,6 +1,6 @@ import { apiBaseUrl, getAuthHeaders, parseStringify } from "@/lib/helper"; -export async function aiGetResources( +export async function getLighthouseResources( page: number = 1, query: string = "", sort: string = "", @@ -46,7 +46,7 @@ export async function aiGetResources( } } -export async function aiGetResource( +export async function getLighthouseResourceById( id: string, fields: string[] = [], include: string[] = [], diff --git a/ui/app/(ai)/analyst/route.ts b/ui/app/(ai)/analyst/route.ts deleted file mode 100644 index 3035bbe920..0000000000 --- a/ui/app/(ai)/analyst/route.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { createReactAgent } from "@langchain/langgraph/prebuilt"; -import { createSupervisor } from "@langchain/langgraph-supervisor"; -import { ChatOpenAI } from "@langchain/openai"; -import { LangChainAdapter, Message } from "ai"; - -import { getAIConfiguration, getAIKey } from "@/actions/lighthouse/lighthouse"; - -import { getUserCache } from "../cache/lib/cache"; -import { getProviderChecksTool } from "./(tools)/checks"; -import { - getComplianceFrameworksTool, - getComplianceOverviewTool, - getCompliancesOverviewTool, -} from "./(tools)/compliances"; -import { getFindingsTool, getMetadataInfoTool } from "./(tools)/findings"; -import { - getFindingsBySeverityTool, - getFindingsByStatusTool, - getProvidersOverviewTool, -} from "./(tools)/overview"; -import { getProvidersTool, getProviderTool } from "./(tools)/providers"; -import { getRolesTool, getRoleTool } from "./(tools)/roles"; -import { getScansTool, getScanTool } from "./(tools)/scans"; -import { getMyProfileInfoTool, getUsersTool } from "./(tools)/users"; -import { - complianceAgentPrompt, - findingsAgentPrompt, - overviewAgentPrompt, - providerAgentPrompt, - rolesAgentPrompt, - scansAgentPrompt, - supervisorPrompt, - userInfoAgentPrompt, -} from "./prompts"; -import { - convertLangChainMessageToVercelMessage, - convertVercelMessageToLangChainMessage, -} from "./utils"; - -// Function to get user and provider data from cache -const getCachedDataSection = async (): Promise => { - try { - const cacheData = await getUserCache(); - if (cacheData) { - return ` -**CURRENT USER DATA:** -Information about the current user interacting with the chatbot: -User: ${cacheData.user.name} -Email: ${cacheData.user.email} -Company: ${cacheData.user.company} - -**CURRENT PROVIDER DATA:** -${cacheData.providers - .map( - (provider, index) => ` -Provider ${index + 1}: -- Name: ${provider.name} -- Type: ${provider.provider_type} -- Alias: ${provider.alias} -- Provider ID: ${provider.id} -- Last Checked: ${provider.last_checked_at} -${ - provider.scan_id - ? `- Latest Scan ID: ${provider.scan_id} -- Scan Duration: ${provider.scan_duration || "Unknown"} -- Resource Count: ${provider.resource_count || "Unknown"}` - : "- No completed scans found" -} -`, - ) - .join("\n")} -`; - } - return ""; - } catch (error) { - console.error("Failed to retrieve cached data:", error); - return "**CURRENT DATA: Not available**"; - } -}; - -const initializeModels = async () => { - const apiKey = await getAIKey(); - const aiConfig = await getAIConfiguration(); - const modelConfig = aiConfig?.data?.attributes; - - // Initialize models without API keys - const llm = new ChatOpenAI({ - model: modelConfig?.model || "gpt-4o", - temperature: modelConfig?.temperature || 0, - maxTokens: modelConfig?.max_tokens || 4000, - apiKey: apiKey, - tags: ["agent"], - }); - - const supervisorllm = new ChatOpenAI({ - model: modelConfig?.model || "gpt-4o", - temperature: modelConfig?.temperature || 0, - maxTokens: modelConfig?.max_tokens || 4000, - apiKey: apiKey, - streaming: true, - tags: ["supervisor"], - }); - - const providerAgent = createReactAgent({ - llm: llm, - tools: [getProvidersTool, getProviderTool], - name: "provider_agent", - prompt: providerAgentPrompt, - }); - - const userInfoAgent = createReactAgent({ - llm: llm, - tools: [getUsersTool, getMyProfileInfoTool], - name: "user_info_agent", - prompt: userInfoAgentPrompt, - }); - - const scansAgent = createReactAgent({ - llm: llm, - tools: [getScansTool, getScanTool], - name: "scans_agent", - prompt: scansAgentPrompt, - }); - - const complianceAgent = createReactAgent({ - llm: llm, - tools: [ - getCompliancesOverviewTool, - getComplianceOverviewTool, - getComplianceFrameworksTool, - ], - name: "compliance_agent", - prompt: complianceAgentPrompt, - }); - - const findingsAgent = createReactAgent({ - llm: llm, - tools: [getFindingsTool, getMetadataInfoTool, getProviderChecksTool], - name: "findings_agent", - prompt: findingsAgentPrompt, - }); - - const overviewAgent = createReactAgent({ - llm: llm, - tools: [ - getProvidersOverviewTool, - getFindingsByStatusTool, - getFindingsBySeverityTool, - ], - name: "overview_agent", - prompt: overviewAgentPrompt, - }); - - const rolesAgent = createReactAgent({ - llm: llm, - tools: [getRolesTool, getRoleTool], - name: "roles_agent", - prompt: rolesAgentPrompt, - }); - - const agents = [ - userInfoAgent, - providerAgent, - overviewAgent, - scansAgent, - complianceAgent, - findingsAgent, - rolesAgent, - ]; - - // Create supervisor workflow - const workflow = createSupervisor({ - agents: agents, - llm: supervisorllm, - prompt: supervisorPrompt, - outputMode: "last_message", - }); - - // Compile and run - const app = workflow.compile(); - return app; -}; - -export async function POST(req: Request) { - try { - const { - messages, - }: { - messages: Message[]; - } = await req.json(); - - if (!messages) { - return Response.json({ error: "No messages provided" }, { status: 400 }); - } - - // Create a new array for processed messages - const processedMessages = [...messages]; - - // Get AI configuration to access business context - const aiConfig = await getAIConfiguration(); - const businessContext = aiConfig?.data?.attributes?.business_context; - - // Get cached data - const cachedData = await getCachedDataSection(); - - // Add context messages at the beginning - const contextMessages: Message[] = []; - - // Add business context if available - if (businessContext) { - contextMessages.push({ - id: "business-context", - role: "assistant", - content: `Business Context Information:\n${businessContext}`, - }); - } - - // Add cached data if available - if (cachedData) { - contextMessages.push({ - id: "cached-data", - role: "assistant", - content: cachedData, - }); - } - - // Insert all context messages at the beginning - processedMessages.unshift(...contextMessages); - - const app = await initializeModels(); - - const agentStream = app.streamEvents( - { - messages: processedMessages - .filter( - (message: Message) => - message.role === "user" || message.role === "assistant", - ) - .map(convertVercelMessageToLangChainMessage), - }, - { - streamMode: ["values", "messages", "custom"], - version: "v2", - }, - ); - - const stream = new ReadableStream({ - async start(controller) { - for await (const { event, data, tags } of agentStream) { - if (event === "on_chat_model_stream") { - if (data.chunk.content && !!tags && tags.includes("supervisor")) { - const chunk = data.chunk; - const aiMessage = convertLangChainMessageToVercelMessage(chunk); - controller.enqueue(aiMessage); - } - } - } - controller.close(); - }, - }); - - return LangChainAdapter.toDataStreamResponse(stream); - } catch (error) { - console.error("Error in POST request:", error); - return Response.json({ error: "An error occurred" }, { status: 500 }); - } -} diff --git a/ui/app/(ai)/cache/api/create/route.ts b/ui/app/(ai)/cache/api/create/route.ts deleted file mode 100644 index 6ef421c8b8..0000000000 --- a/ui/app/(ai)/cache/api/create/route.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { NextResponse } from "next/server"; - -import { createCache, getCurrentUserId } from "@/app/(ai)/cache/lib/cache"; - -export async function POST() { - try { - // Get the current user ID - const userId = await getCurrentUserId(); - - // Initialize the cache - await createCache(userId); - - return NextResponse.json({ - success: true, - message: "Cache created successfully", - timestamp: new Date().toISOString(), - }); - } catch (error) { - console.error("Error creating cache:", error); - - return NextResponse.json( - { - success: false, - message: `Failed to create cache: ${error instanceof Error ? error.message : "Unknown error"}`, - }, - { status: 500 }, - ); - } -} diff --git a/ui/app/(ai)/layout.tsx b/ui/app/(ai)/layout.tsx deleted file mode 100644 index b130139566..0000000000 --- a/ui/app/(ai)/layout.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import "@/styles/globals.css"; - -import { Metadata, Viewport } from "next"; -import React from "react"; - -import { Toaster } from "@/components/ui"; -import { fontSans } from "@/config/fonts"; -import { siteConfig } from "@/config/site"; -import { cn } from "@/lib/utils"; - -import { Providers } from "../providers"; - -export const metadata: Metadata = { - title: { - default: siteConfig.name, - template: `%s - ${siteConfig.name}`, - }, - description: siteConfig.description, - icons: { - icon: "/favicon.ico", - }, -}; - -export const viewport: Viewport = { - themeColor: [ - { media: "(prefers-color-scheme: light)", color: "white" }, - { media: "(prefers-color-scheme: dark)", color: "black" }, - ], -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - - - -
-
- {children} - -
-
-
- - - ); -} diff --git a/ui/app/(prowler)/lighthouse/config/page.tsx b/ui/app/(prowler)/lighthouse/config/page.tsx index 07b019e438..3bff673cef 100644 --- a/ui/app/(prowler)/lighthouse/config/page.tsx +++ b/ui/app/(prowler)/lighthouse/config/page.tsx @@ -8,9 +8,9 @@ import { Controller, useForm } from "react-hook-form"; import * as z from "zod"; import { - createAIConfiguration, - getAIConfiguration, - updateAIConfiguration, + createLighthouseConfig, + getLighthouseConfig, + updateLighthouseConfig, } from "@/actions/lighthouse"; import { useToast } from "@/components/ui"; import { @@ -70,7 +70,7 @@ export default function ChatbotConfig() { setIsFetching(true); try { - const response = await getAIConfiguration(); + const response = await getLighthouseConfig(); if (!isMounted) return; @@ -135,8 +135,8 @@ export default function ChatbotConfig() { // Conditionally use create or update based on whether configuration exists const result = configExists - ? await updateAIConfiguration(configData) - : await createAIConfiguration(configData); + ? await updateLighthouseConfig(configData) + : await createLighthouseConfig(configData); console.log("Operation result:", result); diff --git a/ui/lib/helper.ts b/ui/lib/helper.ts index 50d8c922cb..7a4da7736c 100644 --- a/ui/lib/helper.ts +++ b/ui/lib/helper.ts @@ -270,9 +270,4 @@ export const permissionFormFields: PermissionInfo[] = [ }, ]; -export type ProviderType = - | "aws" - | "gcp" - | "azure" - | "kubernetes" - | "m365"; +export type ProviderType = "aws" | "gcp" | "azure" | "kubernetes" | "m365"; diff --git a/ui/app/(ai)/cache/lib/cache.ts b/ui/lib/lighthouse/cache.ts similarity index 84% rename from ui/app/(ai)/cache/lib/cache.ts rename to ui/lib/lighthouse/cache.ts index e2d5de0094..bf467db85f 100644 --- a/ui/app/(ai)/cache/lib/cache.ts +++ b/ui/lib/lighthouse/cache.ts @@ -15,7 +15,7 @@ type CacheStore = { // In-memory cache store const cacheStore: CacheStore = {}; -// We'll use this to track the cache metadata +// Cache metadata let cacheVersion = Date.now(); let cacheCreatedAt = new Date().toISOString(); let cacheHits = 0; @@ -217,3 +217,43 @@ export const getCacheMetadata = async () => { timestamp: new Date().toISOString(), }; }; + +export async function getCachedDataSection(): Promise { + try { + const cacheData = await getUserCache(); + if (cacheData) { + return ` +**CURRENT USER DATA:** +Information about the current user interacting with the chatbot: +User: ${cacheData.user.name} +Email: ${cacheData.user.email} +Company: ${cacheData.user.company} + +**CURRENT PROVIDER DATA:** +${cacheData.providers + .map( + (provider, index) => ` +Provider ${index + 1}: +- Name: ${provider.name} +- Type: ${provider.provider_type} +- Alias: ${provider.alias} +- Provider ID: ${provider.id} +- Last Checked: ${provider.last_checked_at} +${ + provider.scan_id + ? `- Latest Scan ID: ${provider.scan_id} +- Scan Duration: ${provider.scan_duration || "Unknown"} +- Resource Count: ${provider.resource_count || "Unknown"}` + : "- No completed scans found" +} +`, + ) + .join("\n")} +`; + } + return ""; + } catch (error) { + console.error("Failed to retrieve cached data:", error); + return "**CURRENT DATA: Not available**"; + } +} diff --git a/ui/lib/lighthouse/helperChecks.ts b/ui/lib/lighthouse/helpers/checks.ts similarity index 99% rename from ui/lib/lighthouse/helperChecks.ts rename to ui/lib/lighthouse/helpers/checks.ts index 536aff0ddc..d9e547ab9c 100644 --- a/ui/lib/lighthouse/helperChecks.ts +++ b/ui/lib/lighthouse/helpers/checks.ts @@ -917,6 +917,6 @@ const checksByProvider = async (provider_type: string) => { return checksByProvider[provider_type as ProviderType] || []; }; -export const aiGetProviderChecks = async (provider_type: string) => { +export const getLighthouseProviderChecks = async (provider_type: string) => { return await checksByProvider(provider_type); }; diff --git a/ui/lib/lighthouse/helperComplianceFrameworks.ts b/ui/lib/lighthouse/helpers/complianceframeworks.ts similarity index 95% rename from ui/lib/lighthouse/helperComplianceFrameworks.ts rename to ui/lib/lighthouse/helpers/complianceframeworks.ts index bb85b9a0c0..65f91ec611 100644 --- a/ui/lib/lighthouse/helperComplianceFrameworks.ts +++ b/ui/lib/lighthouse/helpers/complianceframeworks.ts @@ -67,6 +67,8 @@ export const complianceFrameworksByProvider = async (provider_type: string) => { return complianceFrameworks[provider_type as ProviderType] || []; }; -export const aiGetComplianceFrameworks = async (provider_type: string) => { +export const getLighthouseComplianceFrameworks = async ( + provider_type: string, +) => { return await complianceFrameworksByProvider(provider_type); }; diff --git a/ui/app/(ai)/analyst/prompts.ts b/ui/lib/lighthouse/prompts.ts similarity index 100% rename from ui/app/(ai)/analyst/prompts.ts rename to ui/lib/lighthouse/prompts.ts diff --git a/ui/app/(ai)/analyst/(tools)/checks.ts b/ui/lib/lighthouse/tools/checks.ts similarity index 72% rename from ui/app/(ai)/analyst/(tools)/checks.ts rename to ui/lib/lighthouse/tools/checks.ts index 0bd93900e6..aa43b268d0 100644 --- a/ui/app/(ai)/analyst/(tools)/checks.ts +++ b/ui/lib/lighthouse/tools/checks.ts @@ -1,11 +1,11 @@ import { tool } from "@langchain/core/tools"; -import { aiGetProviderChecks } from "@/lib/lighthouse/helperChecks"; +import { getLighthouseProviderChecks } from "@/lib/lighthouse/helpers/checks"; import { checkSchema } from "@/types/lighthouse"; export const getProviderChecksTool = tool( async ({ provider_type }) => { - const checks = await aiGetProviderChecks(provider_type); + const checks = await getLighthouseProviderChecks(provider_type); return checks; }, { diff --git a/ui/app/(ai)/analyst/(tools)/compliances.ts b/ui/lib/lighthouse/tools/compliances.ts similarity index 78% rename from ui/app/(ai)/analyst/(tools)/compliances.ts rename to ui/lib/lighthouse/tools/compliances.ts index f2b09e199a..d5f5b36d6e 100644 --- a/ui/app/(ai)/analyst/(tools)/compliances.ts +++ b/ui/lib/lighthouse/tools/compliances.ts @@ -1,10 +1,10 @@ import { tool } from "@langchain/core/tools"; import { - aiGetComplianceOverview, - aiGetCompliancesOverview, + getLighthouseComplianceOverview, + getLighthouseCompliancesOverview, } from "@/actions/lighthouse/compliances"; -import { aiGetComplianceFrameworks } from "@/lib/lighthouse/helperComplianceFrameworks"; +import { getLighthouseComplianceFrameworks } from "@/lib/lighthouse/helpers/complianceframeworks"; import { getComplianceFrameworksSchema, getComplianceOverviewSchema, @@ -13,7 +13,7 @@ import { export const getCompliancesOverviewTool = tool( async ({ scanId, fields, filters, page, page_size, sort }) => { - return await aiGetCompliancesOverview({ + return await getLighthouseCompliancesOverview({ scanId, fields, filters, @@ -32,7 +32,7 @@ export const getCompliancesOverviewTool = tool( export const getComplianceFrameworksTool = tool( async ({ provider }) => { - return await aiGetComplianceFrameworks(provider); + return await getLighthouseComplianceFrameworks(provider); }, { name: "getComplianceFrameworks", @@ -44,7 +44,7 @@ export const getComplianceFrameworksTool = tool( export const getComplianceOverviewTool = tool( async ({ complianceId, fields }) => { - return await aiGetComplianceOverview({ complianceId, fields }); + return await getLighthouseComplianceOverview({ complianceId, fields }); }, { name: "getComplianceOverview", diff --git a/ui/app/(ai)/analyst/(tools)/findings.ts b/ui/lib/lighthouse/tools/findings.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/findings.ts rename to ui/lib/lighthouse/tools/findings.ts diff --git a/ui/app/(ai)/analyst/(tools)/overview.ts b/ui/lib/lighthouse/tools/overview.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/overview.ts rename to ui/lib/lighthouse/tools/overview.ts diff --git a/ui/app/(ai)/analyst/(tools)/providers.ts b/ui/lib/lighthouse/tools/providers.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/providers.ts rename to ui/lib/lighthouse/tools/providers.ts diff --git a/ui/app/(ai)/analyst/(tools)/resources.ts b/ui/lib/lighthouse/tools/resources.ts similarity index 69% rename from ui/app/(ai)/analyst/(tools)/resources.ts rename to ui/lib/lighthouse/tools/resources.ts index 9c8990670e..62b0bcc2e6 100644 --- a/ui/app/(ai)/analyst/(tools)/resources.ts +++ b/ui/lib/lighthouse/tools/resources.ts @@ -1,11 +1,14 @@ import { tool } from "@langchain/core/tools"; -import { aiGetResource, aiGetResources } from "@/actions/lighthouse/resources"; +import { + getLighthouseResourceById, + getLighthouseResources, +} from "@/actions/lighthouse/resources"; import { getResourceSchema, getResourcesSchema } from "@/types/lighthouse"; export const getResourcesTool = tool( async ({ page, query, sort, filters, fields }) => { - return await aiGetResources(page, query, sort, filters, fields); + return await getLighthouseResources(page, query, sort, filters, fields); }, { name: "getResources", @@ -16,7 +19,7 @@ export const getResourcesTool = tool( export const getResourceTool = tool( async ({ id, fields, include }) => { - return await aiGetResource(id, fields, include); + return await getLighthouseResourceById(id, fields, include); }, { name: "getResource", diff --git a/ui/app/(ai)/analyst/(tools)/roles.ts b/ui/lib/lighthouse/tools/roles.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/roles.ts rename to ui/lib/lighthouse/tools/roles.ts diff --git a/ui/app/(ai)/analyst/(tools)/scans.ts b/ui/lib/lighthouse/tools/scans.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/scans.ts rename to ui/lib/lighthouse/tools/scans.ts diff --git a/ui/app/(ai)/analyst/(tools)/users.ts b/ui/lib/lighthouse/tools/users.ts similarity index 100% rename from ui/app/(ai)/analyst/(tools)/users.ts rename to ui/lib/lighthouse/tools/users.ts diff --git a/ui/app/(ai)/analyst/utils.ts b/ui/lib/lighthouse/utils.ts similarity index 100% rename from ui/app/(ai)/analyst/utils.ts rename to ui/lib/lighthouse/utils.ts diff --git a/ui/lib/lighthouse/workflow.ts b/ui/lib/lighthouse/workflow.ts new file mode 100644 index 0000000000..8cdd920a67 --- /dev/null +++ b/ui/lib/lighthouse/workflow.ts @@ -0,0 +1,143 @@ +import { createReactAgent } from "@langchain/langgraph/prebuilt"; +import { createSupervisor } from "@langchain/langgraph-supervisor"; +import { ChatOpenAI } from "@langchain/openai"; + +import { getAIKey, getLighthouseConfig } from "@/actions/lighthouse/lighthouse"; +import { + complianceAgentPrompt, + findingsAgentPrompt, + overviewAgentPrompt, + providerAgentPrompt, + rolesAgentPrompt, + scansAgentPrompt, + supervisorPrompt, + userInfoAgentPrompt, +} from "@/lib/lighthouse/prompts"; +import { getProviderChecksTool } from "@/lib/lighthouse/tools/checks"; +import { + getComplianceFrameworksTool, + getComplianceOverviewTool, + getCompliancesOverviewTool, +} from "@/lib/lighthouse/tools/compliances"; +import { + getFindingsTool, + getMetadataInfoTool, +} from "@/lib/lighthouse/tools/findings"; +import { + getFindingsBySeverityTool, + getFindingsByStatusTool, + getProvidersOverviewTool, +} from "@/lib/lighthouse/tools/overview"; +import { + getProvidersTool, + getProviderTool, +} from "@/lib/lighthouse/tools/providers"; +import { getRolesTool, getRoleTool } from "@/lib/lighthouse/tools/roles"; +import { getScansTool, getScanTool } from "@/lib/lighthouse/tools/scans"; +import { + getMyProfileInfoTool, + getUsersTool, +} from "@/lib/lighthouse/tools/users"; + +export async function initLighthouseWorkflow() { + const apiKey = await getAIKey(); + const aiConfig = await getLighthouseConfig(); + const modelConfig = aiConfig?.data?.attributes; + + // Initialize models without API keys + const llm = new ChatOpenAI({ + model: modelConfig?.model || "gpt-4o", + temperature: modelConfig?.temperature || 0, + maxTokens: modelConfig?.max_tokens || 4000, + apiKey: apiKey, + tags: ["agent"], + }); + + const supervisorllm = new ChatOpenAI({ + model: modelConfig?.model || "gpt-4o", + temperature: modelConfig?.temperature || 0, + maxTokens: modelConfig?.max_tokens || 4000, + apiKey: apiKey, + streaming: true, + tags: ["supervisor"], + }); + + const providerAgent = createReactAgent({ + llm: llm, + tools: [getProvidersTool, getProviderTool], + name: "provider_agent", + prompt: providerAgentPrompt, + }); + + const userInfoAgent = createReactAgent({ + llm: llm, + tools: [getUsersTool, getMyProfileInfoTool], + name: "user_info_agent", + prompt: userInfoAgentPrompt, + }); + + const scansAgent = createReactAgent({ + llm: llm, + tools: [getScansTool, getScanTool], + name: "scans_agent", + prompt: scansAgentPrompt, + }); + + const complianceAgent = createReactAgent({ + llm: llm, + tools: [ + getCompliancesOverviewTool, + getComplianceOverviewTool, + getComplianceFrameworksTool, + ], + name: "compliance_agent", + prompt: complianceAgentPrompt, + }); + + const findingsAgent = createReactAgent({ + llm: llm, + tools: [getFindingsTool, getMetadataInfoTool, getProviderChecksTool], + name: "findings_agent", + prompt: findingsAgentPrompt, + }); + + const overviewAgent = createReactAgent({ + llm: llm, + tools: [ + getProvidersOverviewTool, + getFindingsByStatusTool, + getFindingsBySeverityTool, + ], + name: "overview_agent", + prompt: overviewAgentPrompt, + }); + + const rolesAgent = createReactAgent({ + llm: llm, + tools: [getRolesTool, getRoleTool], + name: "roles_agent", + prompt: rolesAgentPrompt, + }); + + const agents = [ + userInfoAgent, + providerAgent, + overviewAgent, + scansAgent, + complianceAgent, + findingsAgent, + rolesAgent, + ]; + + // Create supervisor workflow + const workflow = createSupervisor({ + agents: agents, + llm: supervisorllm, + prompt: supervisorPrompt, + outputMode: "last_message", + }); + + // Compile and run + const app = workflow.compile(); + return app; +}