feat: add getLatestFindings tool

This commit is contained in:
Chandrapal Badshah
2025-06-27 15:10:13 +05:30
parent e19ed30ac7
commit 2caf001e21
4 changed files with 126 additions and 12 deletions
+78
View File
@@ -0,0 +1,78 @@
"use server";
import { apiBaseUrl, getAuthHeaders, parseStringify } from "@/lib";
export const getLighthouseFindings = async ({
page = 1,
pageSize = 10,
query = "",
sort = "",
filters = {},
}) => {
const headers = await getAuthHeaders({ contentType: false });
// For lighthouse usage, handle invalid page numbers by defaulting to 1
const validPage = isNaN(Number(page)) || page < 1 ? 1 : page;
const url = new URL(`${apiBaseUrl}/findings`);
if (validPage) url.searchParams.append("page[number]", validPage.toString());
if (pageSize) url.searchParams.append("page[size]", pageSize.toString());
if (query) url.searchParams.append("filter[search]", query);
if (sort) url.searchParams.append("sort", sort);
Object.entries(filters).forEach(([key, value]) => {
url.searchParams.append(key, String(value));
});
try {
const findings = await fetch(url.toString(), {
headers,
});
const data = await findings.json();
const parsedData = parseStringify(data);
return parsedData;
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error fetching lighthouse findings:", error);
return undefined;
}
};
export const getLighthouseLatestFindings = async ({
page = 1,
pageSize = 10,
query = "",
sort = "",
filters = {},
}) => {
const headers = await getAuthHeaders({ contentType: false });
const validPage = isNaN(Number(page)) || page < 1 ? 1 : page;
const url = new URL(`${apiBaseUrl}/findings/latest`);
if (validPage) url.searchParams.append("page[number]", validPage.toString());
if (pageSize) url.searchParams.append("page[size]", pageSize.toString());
if (query) url.searchParams.append("filter[search]", query);
if (sort) url.searchParams.append("sort", sort);
Object.entries(filters).forEach(([key, value]) => {
url.searchParams.append(key, String(value));
});
try {
const findings = await fetch(url.toString(), {
headers,
});
const data = await findings.json();
const parsedData = parseStringify(data);
return parsedData;
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error fetching lighthouse latest findings:", error);
return undefined;
}
};
+31 -2
View File
@@ -1,11 +1,21 @@
import { tool } from "@langchain/core/tools";
import { getFindings, getMetadataInfo } from "@/actions/findings";
import { getMetadataInfo } from "@/actions/findings";
import {
getLighthouseFindings,
getLighthouseLatestFindings,
} from "@/actions/lighthouse/findings";
import { getFindingsSchema, getMetadataInfoSchema } from "@/types/lighthouse";
export const getFindingsTool = tool(
async ({ page, pageSize, query, sort, filters }) => {
return await getFindings({ page, pageSize, query, sort, filters });
return await getLighthouseFindings({
page,
pageSize,
query,
sort,
filters,
});
},
{
name: "getFindings",
@@ -15,6 +25,25 @@ export const getFindingsTool = tool(
},
);
export const getLatestFindingsTool = tool(
async ({ page, pageSize, query, sort, filters }) => {
return await getLighthouseLatestFindings({
page,
pageSize,
query,
sort,
filters,
});
},
{
name: "getLatestFindings",
description:
"Retrieves a list of the latest findings from the latest scans of all providers with options for filtering by various criteria.",
// getLatestFindings uses the same schema as getFindings
schema: getFindingsSchema,
},
);
export const getMetadataInfoTool = tool(
async ({ query, sort, filters }) => {
return await getMetadataInfo({ query, sort, filters });
+2
View File
@@ -24,6 +24,7 @@ import {
} from "@/lib/lighthouse/tools/compliances";
import {
getFindingsTool,
getLatestFindingsTool,
getMetadataInfoTool,
} from "@/lib/lighthouse/tools/findings";
import {
@@ -101,6 +102,7 @@ export async function initLighthouseWorkflow() {
llm: llm,
tools: [
getFindingsTool,
getLatestFindingsTool,
getMetadataInfoTool,
getProviderChecksTool,
getProviderCheckDetailsTool,
+15 -10
View File
@@ -71,21 +71,12 @@ export const getFindingsSchema = z.object({
.optional()
.describe("Comma-separated list of UUID values"),
// Impact and Severity filters
// Impact filters
"filter[impact]": impactEnum.optional(),
"filter[impact__in]": z
.string()
.optional()
.describe("Comma-separated list of impact values"),
"filter[severity]": z
.enum(["critical", "high", "medium", "low", "informational"])
.optional(),
"filter[severity__in]": z
.string()
.optional()
.describe(
"Comma-separated list of severity values. Do not use it with severity filter.",
),
// Date filters
"filter[inserted_at]": z
@@ -105,6 +96,9 @@ export const getFindingsSchema = z.object({
.optional()
.describe("Date in format YYYY-MM-DD"),
// Muted filter
"filter[muted]": z.boolean().optional(),
// Provider filters
"filter[provider]": z.string().optional().describe("Provider UUID"),
"filter[provider__in]": z
@@ -176,6 +170,17 @@ export const getFindingsSchema = z.object({
.optional()
.describe("Comma-separated list of service values"),
// Severity filters
"filter[severity]": z
.enum(["critical", "high", "medium", "low", "informational"])
.optional(),
"filter[severity__in]": z
.string()
.optional()
.describe(
"Comma-separated list of severity values. Do not use it with severity filter.",
),
// Status filters
"filter[status]": statusEnum.optional(),
"filter[status__in]": z