Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ node_modules/
# EvalServer user uploads (keep directory structure, ignore uploaded files)
EvaluationModule/data/uploads/*
!EvaluationModule/data/uploads/.gitkeep
nul
nul
agent-plan.md
11 changes: 8 additions & 3 deletions Clients/src/application/hooks/usePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,23 @@ export function usePlugins(category?: string) {
])
);

// Merge installation status into marketplace plugins
// Merge installation status into marketplace plugins, normalizing optional array fields
const mergedPlugins = marketplacePlugins.map((plugin) => {
const normalized = {
...plugin,
tags: plugin.tags || [],
features: plugin.features || [],
};
const installation = installedMap.get(plugin.key);
if (installation) {
return {
...plugin,
...normalized,
installationId: installation.installationId,
installationStatus: installation.status as PluginInstallationStatus,
installedAt: installation.installedAt,
};
}
return plugin;
return normalized;
});

setPlugins(mergedPlugins);
Expand Down
4 changes: 2 additions & 2 deletions Clients/src/domain/types/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export interface Plugin {
isBuiltIn?: boolean;
requiresConfiguration: boolean;
installationType: string;
features: PluginFeature[];
tags: string[];
features?: PluginFeature[];
tags?: string[];
pluginPath?: string;
entryPoint?: string;
// Installation-specific fields (when fetching installed plugins)
Expand Down
2 changes: 1 addition & 1 deletion Clients/src/presentation/components/PluginCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ const PluginCard: React.FC<PluginCardProps> = ({

{/* Plugin Features */}
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: "8px" }}>
{plugin.features.slice(0, 2).map((feature, index) => (
{(plugin.features || []).slice(0, 2).map((feature, index) => (
<Chip
key={index}
size="small"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export default function AddRepositoryModal({
value={repositoryUrl}
onChange={(e) => setRepositoryUrl(e.target.value)}
disabled={isEditing}
required
isRequired
/>

<Stack direction="row" spacing={4}>
Expand Down
36 changes: 23 additions & 13 deletions Clients/src/presentation/pages/AIDetection/RepositoriesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ export default function RepositoriesPage() {
>
{/* Error state */}
{error && (
<Alert variant="error" title={error} />
<Alert variant="error" title="Error" body={error} />
)}

{/* Table — always shown, with empty state inside when no repos */}
Expand Down Expand Up @@ -458,15 +458,19 @@ export default function RepositoriesPage() {

{/* Schedule */}
<TableCell sx={bodyCellStyle}>
<Chip
label={formatSchedule(repo)}
variant={repo.schedule_enabled ? "info" : "default"}
<Box
component="span"
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
handleEditSchedule(repo);
}}
sx={{ fontSize: "12px", cursor: "pointer" }}
/>
sx={{ cursor: "pointer" }}
>
<Chip
label={formatSchedule(repo)}
variant={repo.schedule_enabled ? "info" : "default"}
/>
</Box>
</TableCell>

{/* Last scan */}
Expand All @@ -480,7 +484,6 @@ export default function RepositoriesPage() {
<Chip
label={repo.last_scan_status}
variant={getStatusChipColor(repo.last_scan_status)}
sx={{ fontSize: "11px" }}
/>
)}
</Stack>
Expand Down Expand Up @@ -510,7 +513,7 @@ export default function RepositoriesPage() {
size="small"
onClick={() => handleScanNow(repo)}
disabled={isScanning}
sx={{ color: isScanning ? palette.text.accent : palette.primary }}
sx={{ color: isScanning ? palette.text.accent : palette.brand.primary }}
>
{isScanning ? (
<Loader2 size={15} strokeWidth={1.5} style={{ animation: `${spin} 1s linear infinite` }} />
Expand Down Expand Up @@ -592,12 +595,19 @@ export default function RepositoriesPage() {
{/* Delete Confirmation */}
<ConfirmationModal
isOpen={!!deleteTarget && !scanningRepoIds.has(deleteTarget.id)}
onClose={() => setDeleteTarget(null)}
onConfirm={handleDelete}
onCancel={() => setDeleteTarget(null)}
onProceed={handleDelete}
title={`Delete "${deleteTarget?.repository_owner}/${deleteTarget?.repository_name}"?`}
description="This will remove the repository from monitoring. Existing scan history will not be deleted."
confirmButtonText="Delete"
isConfirming={isDeleting}
body={
<Typography fontSize={13}>
This will remove the repository from monitoring. Existing scan history will not be deleted.
</Typography>
}
cancelText="Cancel"
proceedText="Delete"
proceedButtonColor="error"
proceedButtonVariant="contained"
isLoading={isDeleting}
/>
</PageHeaderExtended>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import {
RefreshCw,
Plus,
Sparkles,
X,
} from "lucide-react";
import { CustomizableButton } from "../../components/button/customizable-button";
import Alert from "../../components/Alert";
Expand Down Expand Up @@ -1150,7 +1149,7 @@ export default function ScanDetailsPage() {
showAlert("error", message || "Failed to add risk");
};

const handleIgnoreSuggestion = (reason: string) => {
const handleIgnoreSuggestion = (_reason: string) => {
if (ignoreMenuAnchor) {
smoothRemoveSuggestion(ignoreMenuAnchor.index);
setIgnoreMenuAnchor(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default function SettingsPage() {
const [alert, setAlert] = useState<ToastAlert | null>(null);

// Risk scoring state
const [riskConfig, setRiskConfig] = useState<RiskScoringConfig | null>(null);
const [_riskConfig, setRiskConfig] = useState<RiskScoringConfig | null>(null);
const [riskConfigLoading, setRiskConfigLoading] = useState(false);
const [riskConfigSaving, setRiskConfigSaving] = useState(false);
const [llmEnabled, setLlmEnabled] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { Box, Stack, Typography, Paper, Divider, Button, CircularProgress, IconButton, Select, MenuItem, useTheme } from "@mui/material";
import { Box, Stack, Typography, Paper, Divider, Button, CircularProgress, IconButton, Select, MenuItem, useTheme, Chip } from "@mui/material";
import VWChip from "../../components/Chip";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import {
Expand Down
13 changes: 7 additions & 6 deletions Clients/src/presentation/tools/isoDateToString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ export function formatDate(isoDate: string): string {
* @param {string} isoDate - The ISO date string to be converted.
* @returns {string} The formatted date string in the format (default: DD-MM-YYYY).
*/
export const displayFormattedDate = (isoDate: string): string => {

if (!isoDate || !/^\d{4}-\d{2}-\d{2}/.test(isoDate)) {
console.warn("Invalid ISO date format:", isoDate);
return isoDate;
export const displayFormattedDate = (isoDate: string | Date): string => {
const dateStr = isoDate instanceof Date ? isoDate.toISOString() : isoDate;

if (!dateStr || !/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
console.warn("Invalid ISO date format:", dateStr);
return String(dateStr);
}

let dateFormat = UserDateFormat.DD_MM_YYYY_DASH;
Expand All @@ -46,7 +47,7 @@ export const displayFormattedDate = (isoDate: string): string => {
console.warn("Failed to read date format preference, using default:", error);
}

const formattedDate = dayjs(isoDate).format(dateFormat);
const formattedDate = dayjs(dateStr).format(dateFormat);
return formattedDate;
}
/**
Expand Down
2 changes: 0 additions & 2 deletions Clients/src/presentation/types/riskForm.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import {
AddNewRiskFormCorePropsBase,
IRiskLevelCoreProps,
IRiskLevelFormValues,
IRiskFormValues,
IRiskFormErrors,
} from "../../domain/types/riskForm.types";

// Re-export domain types for convenience
Expand Down
6 changes: 4 additions & 2 deletions Servers/services/plugin/pluginService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export class PluginService {
p.isPublished &&
(p.name.toLowerCase().includes(lowerQuery) ||
p.description.toLowerCase().includes(lowerQuery) ||
p.tags.some((tag) => tag.toLowerCase().includes(lowerQuery)));
(p.tags || []).some((tag) => tag.toLowerCase().includes(lowerQuery)));

// Include built-in plugins in search results
const builtinMatches = (getBuiltinPlugins() as Plugin[]).filter(matchFilter);
Expand Down Expand Up @@ -692,11 +692,13 @@ export class PluginService {

const data = response.data as PluginMarketplace;

// Transform relative iconUrl paths to full URLs
// Transform relative iconUrl paths to full URLs and normalize optional array fields
data.plugins = data.plugins.map((plugin) => {
if (plugin.iconUrl && !plugin.iconUrl.startsWith("http")) {
plugin.iconUrl = `${PLUGIN_MARKETPLACE_BASE_URL}/${plugin.iconUrl}`;
}
plugin.tags = plugin.tags || [];
plugin.features = plugin.features || [];
return plugin;
});

Expand Down
39 changes: 32 additions & 7 deletions agents/agent-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,47 @@ After all four steps are complete, print:

```

Review my components inside the following paths with every single file in it:
This is the feedback message I have from a user:
I can't seem to log an issue against the plugins marketplace: https://github.com/verifywise-ai/plugin-marketplace/issues

1. C:\Workspace\verifywise\Clients\src\presentation\components\Layout
2. C:\Workspace\verifywise\Clients\src\presentation\components\Link
3. C:\Workspace\verifywise\Clients\src\presentation\components\LinkedModelsView
4. C:\Workspace\verifywise\Clients\src\presentation\components\LinkedRisks
5. C:\Workspace\verifywise\Clients\src\presentation\components\LogLine
So, I guess I'll paste here. While trying to deploy the docker image, the plugins page will not load (blank screen), but does pull back the correct plugin info from the backend.

Analyze them and make sure they are following "Coding Standards" from "C:\Workspace\verifywise\CodeRules".
With the help of Claude, here's a bit of debugging info for your tracking (please confirm accuracy):

Root Cause
The plugins dataset-bulk-upload and model-lifecycle in the marketplace JSON don't have a tags field. When the frontend's isFrameworkPlugin() callback runs inside the useMemo → filter chain, it calls .some() on plugin.tags, which is undefined. Although the code uses (plugin.tags || []).some(...), the crash still occurs — likely because the actual frontend build has a slightly different code path or the minified code doesn't match the source exactly.

Options
File an issue/PR on the verifywise-ai/plugin-marketplace repo to add tags: [] to the dataset-bulk-upload and model-lifecycle plugin entries. This is the proper fix.

File an issue/PR on the verifywise-ai/verifywise repo to make the backend normalize the data (add tags: [] default when missing), or make the frontend more defensive.

Workaround: If you have a fork or can host a corrected plugins.json, you could point PLUGIN_MARKETPLACE_URL to your corrected version.

Also for a feature request... it would be nice to include the ability to keep the official martketplace, as well as add one or more custom marketplaces. For the custom marketplace, a GitHub fine-grained PAT would be nice to access private repositories. Similar to your /ai-detection/settings configuration.

The following GitHub link is the Pull request that is trying to resolve this issue:
https://github.com/verifywise-ai/verifywise/pull/3398
https://github.com/verifywise-ai/verifywise/pull/3398/changes

Please review the Pull Request from the link and also my codebase inside the followings:
Frontend: C:\Workspace\verifywise\Clients\src
Backend: C:\Workspace\verifywise\Servers

And perform and in-depth analyze to see if my implemented solution is enough or and and potentially any possible additional actions for it.

Plan out and strategize your implementation and make sure you break your implementation to as many "meaningful git commits" as possible.

Git commit:
1. `git add .`
2. `git commit -m <message>`

before jumping into any possible or required implementation, please get back to me fisrt.

Any questions?

```

---
Expand Down
Loading