diff --git a/web/src/components/ai-proposals/alert-identifier.spec.ts b/web/src/components/agentic-runs/alert-identifier.spec.ts similarity index 88% rename from web/src/components/ai-proposals/alert-identifier.spec.ts rename to web/src/components/agentic-runs/alert-identifier.spec.ts index 07d337542..2a06a1ae3 100644 --- a/web/src/components/ai-proposals/alert-identifier.spec.ts +++ b/web/src/components/agentic-runs/alert-identifier.spec.ts @@ -6,7 +6,7 @@ import { Alert, AlertStates, K8sResourceCommon } from '@openshift-console/dynami import { computeAlertFingerprint, getAlertFingerprintPrefix, - matchesProposal, + matchesAgenticRun, } from './alert-identifier'; const makeAlert = (labels: Record): Alert => @@ -17,9 +17,9 @@ const makeAlert = (labels: Record): Alert => rule: { id: '1', alerts: [], labels: {}, name: 'TestAlert', query: '', duration: 0 }, }) as unknown as Alert; -const makeProposal = (labels: Record): K8sResourceCommon => ({ +const makeAgenticRun = (labels: Record): K8sResourceCommon => ({ apiVersion: 'agentic.openshift.io/v1alpha1', - kind: 'Proposal', + kind: 'AgenticRun', metadata: { name: 'test-proposal', namespace: 'openshift-lightspeed', @@ -72,28 +72,28 @@ describe('matchesProposal', () => { it('matches by fingerprint prefix', () => { const alert = makeAlert({ severity: 'critical' }); const fp8 = getAlertFingerprintPrefix(alert.labels); - const proposal = makeProposal({ + const proposal = makeAgenticRun({ 'agentic.openshift.io/alert-fingerprint': fp8, 'agentic.openshift.io/source': 'alertmanager', }); - expect(matchesProposal(alert, proposal)).toBe(true); + expect(matchesAgenticRun(alert, proposal)).toBe(true); }); it('does not match when fingerprint differs', () => { const alert = makeAlert({ severity: 'critical' }); - const proposal = makeProposal({ + const proposal = makeAgenticRun({ 'agentic.openshift.io/alert-fingerprint': 'deadbeef', 'agentic.openshift.io/source': 'alertmanager', }); - expect(matchesProposal(alert, proposal)).toBe(false); + expect(matchesAgenticRun(alert, proposal)).toBe(false); }); it('does not match when proposal has no fingerprint label', () => { const alert = makeAlert({ severity: 'warning' }); - const proposal = makeProposal({ + const proposal = makeAgenticRun({ 'agentic.openshift.io/alert-name': 'testalert', 'agentic.openshift.io/alert-severity': 'warning', }); - expect(matchesProposal(alert, proposal)).toBe(false); + expect(matchesAgenticRun(alert, proposal)).toBe(false); }); }); diff --git a/web/src/components/ai-proposals/alert-identifier.ts b/web/src/components/agentic-runs/alert-identifier.ts similarity index 88% rename from web/src/components/ai-proposals/alert-identifier.ts rename to web/src/components/agentic-runs/alert-identifier.ts index 7e5979358..4b96765ba 100644 --- a/web/src/components/ai-proposals/alert-identifier.ts +++ b/web/src/components/agentic-runs/alert-identifier.ts @@ -3,7 +3,7 @@ import { FINGERPRINT_PREFIX_LEN, FNV_OFFSET_BASIS, FNV_PRIME, - PROPOSAL_LABEL_FINGERPRINT, + AGENTIC_RUN_LABEL_FINGERPRINT, SEPARATOR_BYTE, UINT64_MASK, } from './constants'; @@ -44,8 +44,8 @@ export const computeAlertFingerprint = (labels: Record): string export const getAlertFingerprintPrefix = (labels: Record): string => computeAlertFingerprint(labels).slice(0, FINGERPRINT_PREFIX_LEN); -export const matchesProposal = (alert: Alert, proposal: K8sResourceCommon): boolean => { - const proposalFp = proposal.metadata?.labels?.[PROPOSAL_LABEL_FINGERPRINT]; +export const matchesAgenticRun = (alert: Alert, proposal: K8sResourceCommon): boolean => { + const proposalFp = proposal.metadata?.labels?.[AGENTIC_RUN_LABEL_FINGERPRINT]; if (!proposalFp) { return false; } diff --git a/web/src/components/agentic-runs/constants.ts b/web/src/components/agentic-runs/constants.ts new file mode 100644 index 000000000..233e6b8ec --- /dev/null +++ b/web/src/components/agentic-runs/constants.ts @@ -0,0 +1,15 @@ +// FNV-1a 64-bit hash constants (Prometheus alerts fingerprint algorithm) +export const SEPARATOR_BYTE = 0xff; +export const FNV_OFFSET_BASIS = 14695981039346656037n; +export const FNV_PRIME = 1099511628211n; +export const UINT64_MASK = (1n << 64n) - 1n; +export const FINGERPRINT_PREFIX_LEN = 8; + +// Proposal CR label keys +export const AGENTIC_RUN_LABEL_FINGERPRINT = 'agentic.openshift.io/alert-fingerprint'; +export const AGENTIC_RUN_LABEL_SOURCE = 'agentic.openshift.io/source'; + +// Proposal CR values +export const AGENTIC_RUN_SOURCE_ALERTMANAGER = 'alertmanager'; +export const AGENTIC_RUN_NAMESPACE = 'openshift-lightspeed'; +export const AGENTIC_RUN_STALE_TIME = 30 * 1000; diff --git a/web/src/components/ai-proposals/useProposalCheck.ts b/web/src/components/agentic-runs/useAgenticRunCheck.ts similarity index 66% rename from web/src/components/ai-proposals/useProposalCheck.ts rename to web/src/components/agentic-runs/useAgenticRunCheck.ts index fc421c3da..a2b208d6b 100644 --- a/web/src/components/ai-proposals/useProposalCheck.ts +++ b/web/src/components/agentic-runs/useAgenticRunCheck.ts @@ -2,34 +2,34 @@ import { Alert, K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk' import { k8sListResourceItems } from '@openshift-console/dynamic-plugin-sdk/lib/utils/k8s'; import { useQuery } from '@tanstack/react-query'; import { useCallback, useMemo, useState } from 'react'; -import { ProposalModel } from '../console/models'; +import { AgenticRunModel } from '../console/models'; import { getAlertFingerprintPrefix } from './alert-identifier'; import { - PROPOSAL_LABEL_FINGERPRINT, - PROPOSAL_LABEL_SOURCE, - PROPOSAL_NAMESPACE, - PROPOSAL_SOURCE_ALERTMANAGER, - PROPOSAL_STALE_TIME, + AGENTIC_RUN_LABEL_FINGERPRINT, + AGENTIC_RUN_LABEL_SOURCE, + AGENTIC_RUN_NAMESPACE, + AGENTIC_RUN_SOURCE_ALERTMANAGER, + AGENTIC_RUN_STALE_TIME, } from './constants'; const buildQueryFn = (namespace: string, alertFingerprint: string) => () => k8sListResourceItems({ - model: ProposalModel, + model: AgenticRunModel, queryParams: { ns: namespace, labelSelector: { matchLabels: { - [PROPOSAL_LABEL_FINGERPRINT]: alertFingerprint, - [PROPOSAL_LABEL_SOURCE]: PROPOSAL_SOURCE_ALERTMANAGER, + [AGENTIC_RUN_LABEL_FINGERPRINT]: alertFingerprint, + [AGENTIC_RUN_LABEL_SOURCE]: AGENTIC_RUN_SOURCE_ALERTMANAGER, }, }, }, }); -export const useProposalCheck = (alert: Alert) => { +export const useAgenticRunCheck = (alert: Alert) => { const alertFingerprint = useMemo(() => getAlertFingerprintPrefix(alert.labels), [alert.labels]); const alertNamespace = alert.labels?.namespace; - const hasDistinctAlertNamespace = !!alertNamespace && alertNamespace !== PROPOSAL_NAMESPACE; + const hasDistinctAlertNamespace = !!alertNamespace && alertNamespace !== AGENTIC_RUN_NAMESPACE; const [shouldFetch, setShouldFetch] = useState(false); const { @@ -37,10 +37,10 @@ export const useProposalCheck = (alert: Alert) => { isFetching: defaultNsFetching, isError: defaultNsError, } = useQuery({ - queryKey: ['proposal-check', PROPOSAL_NAMESPACE, alertFingerprint], - queryFn: buildQueryFn(PROPOSAL_NAMESPACE, alertFingerprint), + queryKey: ['agentic-run-check', AGENTIC_RUN_NAMESPACE, alertFingerprint], + queryFn: buildQueryFn(AGENTIC_RUN_NAMESPACE, alertFingerprint), enabled: shouldFetch, - staleTime: PROPOSAL_STALE_TIME, + staleTime: AGENTIC_RUN_STALE_TIME, retry: false, }); @@ -49,18 +49,18 @@ export const useProposalCheck = (alert: Alert) => { isFetching: alertNsFetching, isError: alertNsError, } = useQuery({ - queryKey: ['proposal-check', alertNamespace, alertFingerprint], + queryKey: ['agentic-run-check', alertNamespace, alertFingerprint], queryFn: buildQueryFn(alertNamespace!, alertFingerprint), enabled: shouldFetch && hasDistinctAlertNamespace, - staleTime: PROPOSAL_STALE_TIME, + staleTime: AGENTIC_RUN_STALE_TIME, retry: false, }); const prefetch = useCallback(() => setShouldFetch(true), []); - const proposals = useMemo(() => { + const agenticRuns = useMemo(() => { const matchesFp = (p: K8sResourceCommon) => - p.metadata?.labels?.[PROPOSAL_LABEL_FINGERPRINT] === alertFingerprint; + p.metadata?.labels?.[AGENTIC_RUN_LABEL_FINGERPRINT] === alertFingerprint; return [...(defaultNsData ?? []).filter(matchesFp), ...(alertNsData ?? []).filter(matchesFp)]; }, [defaultNsData, alertNsData, alertFingerprint]); @@ -69,8 +69,8 @@ export const useProposalCheck = (alert: Alert) => { const isError = defaultNsError && (hasDistinctAlertNamespace ? alertNsError : true); return { - proposals, - hasProposal: proposals.length > 0, + agenticRuns, + hasAgenticRun: agenticRuns.length > 0, isFetching, isError, prefetch, diff --git a/web/src/components/ai-proposals/constants.ts b/web/src/components/ai-proposals/constants.ts deleted file mode 100644 index e8c4772f0..000000000 --- a/web/src/components/ai-proposals/constants.ts +++ /dev/null @@ -1,17 +0,0 @@ -// FNV-1a 64-bit hash constants (Prometheus alerts fingerprint algorithm) -export const SEPARATOR_BYTE = 0xff; -export const FNV_OFFSET_BASIS = 14695981039346656037n; -export const FNV_PRIME = 1099511628211n; -export const UINT64_MASK = (1n << 64n) - 1n; -export const FINGERPRINT_PREFIX_LEN = 8; - -// Proposal CR label keys -export const PROPOSAL_LABEL_FINGERPRINT = 'agentic.openshift.io/alert-fingerprint'; -export const PROPOSAL_LABEL_SOURCE = 'agentic.openshift.io/source'; -export const PROPOSAL_LABEL_ALERT_NAME = 'agentic.openshift.io/alert-name'; -export const PROPOSAL_LABEL_ALERT_SEVERITY = 'agentic.openshift.io/alert-severity'; - -// Proposal CR values -export const PROPOSAL_SOURCE_ALERTMANAGER = 'alertmanager'; -export const PROPOSAL_NAMESPACE = 'openshift-lightspeed'; -export const PROPOSAL_STALE_TIME = 30 * 1000; diff --git a/web/src/components/alerting/AlertList/AlertTableRow.tsx b/web/src/components/alerting/AlertList/AlertTableRow.tsx index 87295aa94..59f89da14 100644 --- a/web/src/components/alerting/AlertList/AlertTableRow.tsx +++ b/web/src/components/alerting/AlertList/AlertTableRow.tsx @@ -30,11 +30,11 @@ import { } from '../../../components/hooks/usePerspective'; import { useMonitoringNamespace } from '../../hooks/useMonitoringNamespace'; import { DataTestIDs } from '../../data-test'; -import { useProposalCheck } from '../../ai-proposals/useProposalCheck'; +import { useAgenticRunCheck } from '../../agentic-runs/useAgenticRunCheck'; import CustomIcon from '../../CustomIcon'; -const getProposalUrl = (namespace: string, name: string): string => { - return `/lightspeed/proposals/${namespace}/${name}`; +const getAgenticRunUrl = (namespace: string, name: string): string => { + return `/lightspeed/runs/${namespace}/${name}`; }; const AlertTableRow: FC<{ alert: Alert }> = ({ alert }) => { @@ -42,9 +42,8 @@ const AlertTableRow: FC<{ alert: Alert }> = ({ alert }) => { const { perspective } = usePerspective(); const navigate = useNavigate(); const { namespace } = useMonitoringNamespace(); - const state = alertState(alert); - const { proposals, hasProposal, prefetch, isFetching } = useProposalCheck(alert); + const { agenticRuns, hasAgenticRun, prefetch, isFetching } = useAgenticRunCheck(alert); const title: string = alert.annotations?.description || alert.annotations?.message; @@ -62,16 +61,16 @@ const AlertTableRow: FC<{ alert: Alert }> = ({ alert }) => { ); } - if (hasProposal) { - const proposal = proposals[0]; - const proposalName = proposal.metadata?.name; - if (proposalName) { - const proposalUrl = getProposalUrl(proposal.metadata.namespace, proposalName); + if (hasAgenticRun) { + const run = agenticRuns[0]; + const runName = run.metadata?.name; + if (runName) { + const runUrl = getAgenticRunUrl(run.metadata.namespace, runName); dropdownItems.push( } - onClick={() => navigate(proposalUrl)} + onClick={() => navigate(runUrl)} data-test={DataTestIDs.ViewAIInvestigationDropdownItem} > {t('View AI Investigation')} diff --git a/web/src/components/console/models/index.ts b/web/src/components/console/models/index.ts index 294511c33..90da18cf2 100644 --- a/web/src/components/console/models/index.ts +++ b/web/src/components/console/models/index.ts @@ -92,16 +92,16 @@ export const StatefulSetModel = { kind: 'StatefulSet', }; -export const ProposalModel: K8sModel = { - kind: 'Proposal', - label: 'Proposal', - labelKey: 'Proposal', - labelPlural: 'Proposals', - labelPluralKey: 'Proposals', +export const AgenticRunModel: K8sModel = { + kind: 'AgenticRun', + label: 'AgenticRun', + labelKey: 'AgenticRun', + labelPlural: 'AgenticRuns', + labelPluralKey: 'AgenticRuns', apiGroup: 'agentic.openshift.io', apiVersion: 'v1alpha1', - abbr: 'PP', + abbr: 'AGR', namespaced: true, crd: true, - plural: 'proposals', + plural: 'agenticruns', };