This commit is contained in:
marko-kraemer 2025-07-09 21:35:06 +02:00
parent 2a4c45a4e4
commit 92214e5894
8 changed files with 10 additions and 331 deletions

View File

@ -1,19 +1,6 @@
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
webpack: (config) => {
// This rule prevents issues with pdf.js and canvas
config.externals = [...(config.externals || []), { canvas: 'canvas' }];
// Ensure node native modules are ignored
config.resolve.fallback = {
...config.resolve.fallback,
canvas: false,
};
return config;
},
productionBrowserSourceMaps: true,
};
export default nextConfig;

View File

@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",

View File

@ -10,9 +10,6 @@ interface ResultsInfoProps {
isLoading: boolean;
totalAgents: number;
filteredCount: number;
searchQuery: string;
activeFiltersCount: number;
clearFilters: () => void;
currentPage?: number;
totalPages?: number;
}
@ -21,9 +18,6 @@ export const ResultsInfo = ({
isLoading,
totalAgents,
filteredCount,
searchQuery,
activeFiltersCount,
clearFilters,
currentPage,
totalPages
}: ResultsInfoProps) => {
@ -57,10 +51,6 @@ export const ResultsInfo = ({
}
};
const handleMyTemplates = () => {
router.push('/marketplace/my-templates');
};
if (isLoading || totalAgents === 0) {
return null;
}
@ -76,33 +66,7 @@ export const ResultsInfo = ({
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>
{showingText()}
{searchQuery && ` for "${searchQuery}"`}
</span>
<div className="flex items-center gap-2">
{activeFiltersCount > 0 && (
<Button variant="ghost" size="sm" onClick={clearFilters} className="h-auto p-0">
Clear all filters
</Button>
)}
<Button variant="outline" size="sm" onClick={handleMyTemplates}>
<FileText className="h-4 w-4" />
My Templates
</Button>
<Button
size="sm"
onClick={handleCreateNewAgent}
disabled={createAgentMutation.isPending}
>
{createAgentMutation.isPending ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<>
<Plus className="h-4 w-4" />
New Agent
</>
)}
</Button>
</div>
</div>
);
}

View File

@ -6,7 +6,7 @@ import { Input } from '@/components/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenuCheckboxItem } from '@/components/ui/dropdown-menu';
type SortOption = 'name' | 'created_at' | 'updated_at' | 'tools_count';
type AgentSortOption = 'name' | 'created_at' | 'updated_at' | 'tools_count';
type SortOrder = 'asc' | 'desc';
type ViewMode = 'grid' | 'list';
@ -20,8 +20,8 @@ interface FilterOptions {
interface SearchAndFiltersProps {
searchQuery: string;
setSearchQuery: (query: string) => void;
sortBy: SortOption;
setSortBy: (sort: SortOption) => void;
sortBy: AgentSortOption;
setSortBy: (sort: AgentSortOption) => void;
sortOrder: SortOrder;
setSortOrder: (order: SortOrder) => void;
filters: FilterOptions;

View File

@ -20,7 +20,6 @@ import { StylePicker } from '../../_components/style-picker';
import { useSidebar } from '@/components/ui/sidebar';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { AgentBuilderChat } from '../../_components/agent-builder-chat';
import { useFeatureAlertHelpers } from '@/hooks/use-feature-alerts';
import { AgentTriggersConfiguration } from '@/components/agents/triggers/agent-triggers-configuration';
import { AgentKnowledgeBaseManager } from '@/components/agents/knowledge-base/agent-knowledge-base-manager';
import { AgentWorkflowsConfiguration } from '@/components/agents/workflows/agent-workflows-configuration';

View File

@ -42,7 +42,8 @@ import { DEFAULT_AGENTPRESS_TOOLS } from './_data/tools';
import { AgentsParams } from '@/hooks/react-query/agents/utils';
type ViewMode = 'grid' | 'list';
type SortOption = 'name' | 'created_at' | 'updated_at' | 'tools_count' | 'newest' | 'popular' | 'most_downloaded';
type AgentSortOption = 'name' | 'created_at' | 'updated_at' | 'tools_count';
type MarketplaceSortOption = 'newest' | 'popular' | 'most_downloaded' | 'name';
type SortOrder = 'asc' | 'desc';
interface FilterOptions {
@ -924,7 +925,7 @@ export default function AgentsPage() {
// My Agents state
const [agentsPage, setAgentsPage] = useState(1);
const [agentsSearchQuery, setAgentsSearchQuery] = useState('');
const [agentsSortBy, setAgentsSortBy] = useState<SortOption>('created_at');
const [agentsSortBy, setAgentsSortBy] = useState<AgentSortOption>('created_at');
const [agentsSortOrder, setAgentsSortOrder] = useState<SortOrder>('desc');
const [agentsFilters, setAgentsFilters] = useState<FilterOptions>({
hasDefaultAgent: false,
@ -937,7 +938,7 @@ export default function AgentsPage() {
const [marketplacePage, setMarketplacePage] = useState(1);
const [marketplaceSearchQuery, setMarketplaceSearchQuery] = useState('');
const [marketplaceSelectedTags, setMarketplaceSelectedTags] = useState<string[]>([]);
const [marketplaceSortBy, setMarketplaceSortBy] = useState<SortOption>('newest');
const [marketplaceSortBy, setMarketplaceSortBy] = useState<MarketplaceSortOption>('newest');
const [installingItemId, setInstallingItemId] = useState<string | null>(null);
const [selectedItem, setSelectedItem] = useState<MarketplaceTemplate | null>(null);
const [showInstallDialog, setShowInstallDialog] = useState(false);
@ -1460,9 +1461,6 @@ export default function AgentsPage() {
isLoading={agentsLoading}
totalAgents={agentsPagination?.total || 0}
filteredCount={agents.length}
searchQuery={agentsSearchQuery}
activeFiltersCount={agentsActiveFiltersCount}
clearFilters={clearAgentsFilters}
currentPage={agentsPagination?.page || 1}
totalPages={agentsPagination?.pages || 1}
/>

View File

@ -141,7 +141,7 @@ export function SidebarLeft({
</span>
</SidebarMenuButton>
</Link>
{!flagsLoading && marketplaceEnabled && (
{/* {!flagsLoading && marketplaceEnabled && (
<Link href="/marketplace">
<SidebarMenuButton className={cn({
'bg-accent text-accent-foreground font-medium': pathname === '/marketplace',
@ -152,7 +152,7 @@ export function SidebarLeft({
</span>
</SidebarMenuButton>
</Link>
)}
)} */}
{!flagsLoading && customAgentsEnabled && (
<Link href="/agents">
<SidebarMenuButton className={cn({

View File

@ -1,269 +0,0 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export interface FeatureAlert {
id: string;
title: string;
description: string;
content?: React.ReactNode;
type: 'feature' | 'update' | 'announcement' | 'celebration';
priority: 'low' | 'medium' | 'high';
showOnce?: boolean; // Show only once per user
version?: string; // Track by app version
targetPath?: string; // Show only on specific routes
delay?: number; // Delay before showing (ms)
autoClose?: number; // Auto close after X seconds
actions?: {
primary?: {
label: string;
action: () => void;
};
secondary?: {
label: string;
action: () => void;
};
};
metadata?: Record<string, any>;
}
interface FeatureAlertStore {
alerts: FeatureAlert[];
currentAlert: FeatureAlert | null;
isOpen: boolean;
seenAlerts: Set<string>;
// Core methods
addAlert: (alert: Omit<FeatureAlert, 'id'>) => string;
showAlert: (id: string) => void;
dismissAlert: (id: string) => void;
closeDialog: () => void;
// Utility methods
hasUnseenAlerts: () => boolean;
getAlertsForPath: (path: string) => FeatureAlert[];
markAsSeen: (id: string) => void;
clearAllAlerts: () => void;
// Auto-show methods
checkAndShowAlerts: (currentPath?: string) => void;
}
export const useFeatureAlerts = create<FeatureAlertStore>()(
persist(
(set, get) => ({
alerts: [],
currentAlert: null,
isOpen: false,
seenAlerts: new Set<string>(),
addAlert: (alert) => {
const id = `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const newAlert: FeatureAlert = {
...alert,
id,
};
set((state) => ({
alerts: [...state.alerts, newAlert]
}));
return id;
},
showAlert: (id) => {
const alert = get().alerts.find(a => a.id === id);
if (!alert) return;
// Check if alert should only show once and has been seen
if (alert.showOnce && get().seenAlerts.has(id)) {
return;
}
const showAlertNow = () => {
set({
currentAlert: alert,
isOpen: true
});
// Auto close if specified
if (alert.autoClose) {
setTimeout(() => {
get().closeDialog();
}, alert.autoClose * 1000);
}
};
// Apply delay if specified
if (alert.delay) {
setTimeout(showAlertNow, alert.delay);
} else {
showAlertNow();
}
},
dismissAlert: (id) => {
get().markAsSeen(id);
const current = get().currentAlert;
if (current?.id === id) {
get().closeDialog();
}
},
closeDialog: () => {
const current = get().currentAlert;
if (current) {
get().markAsSeen(current.id);
}
set({
isOpen: false,
currentAlert: null
});
},
hasUnseenAlerts: () => {
const { alerts, seenAlerts } = get();
return alerts.some(alert =>
!seenAlerts.has(alert.id) &&
(!alert.showOnce || !seenAlerts.has(alert.id))
);
},
getAlertsForPath: (path) => {
const { alerts, seenAlerts } = get();
return alerts
.filter(alert => {
// Filter by path if specified
if (alert.targetPath && !path.includes(alert.targetPath)) {
return false;
}
// Filter out seen alerts if they should only show once
if (alert.showOnce && seenAlerts.has(alert.id)) {
return false;
}
return true;
})
.sort((a, b) => {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return priorityOrder[b.priority] - priorityOrder[a.priority];
});
},
markAsSeen: (id) => {
set((state) => ({
seenAlerts: new Set([...state.seenAlerts, id])
}));
},
clearAllAlerts: () => {
set({
alerts: [],
currentAlert: null,
isOpen: false
});
},
checkAndShowAlerts: (currentPath = '') => {
const alertsForPath = get().getAlertsForPath(currentPath);
if (alertsForPath.length > 0) {
// Show the highest priority alert
const alertToShow = alertsForPath[0];
get().showAlert(alertToShow.id);
}
},
}),
{
name: 'feature-alerts-storage',
partialize: (state) => ({
seenAlerts: Array.from(state.seenAlerts),
alerts: state.alerts // Persist all alerts
}),
onRehydrateStorage: () => (state) => {
if (state) {
state.seenAlerts = new Set(state.seenAlerts || []);
}
}
}
)
);
export const FEATURE_ALERTS = {
CONFIGURABLE_AGENTS: {
title: "🤖 New: Configurable Agents",
description: "Create and customize AI agents with your own configurations, prompts, and behaviors.",
type: 'feature' as const,
priority: 'high' as const,
showOnce: true,
delay: 1000,
actions: {
primary: {
label: "Explore Agents",
action: () => {
window.location.href = '/agents';
}
},
secondary: {
label: "Learn More",
action: () => {
window.open('/docs/agents', '_blank');
}
}
}
},
AGENTS_MARKETPLACE: {
title: "🏪 Agents Marketplace",
description: "Discover and install pre-built agents from our community marketplace.",
type: 'feature' as const,
priority: 'high' as const,
showOnce: true,
delay: 1500,
targetPath: '/marketplace',
actions: {
primary: {
label: "Browse Marketplace",
action: () => {
window.location.href = '/marketplace';
}
},
secondary: {
label: "Submit Agent",
action: () => {
window.location.href = '/marketplace/submit';
}
}
}
}
} as const;
export const useFeatureAlertHelpers = () => {
const { addAlert, showAlert, checkAndShowAlerts } = useFeatureAlerts();
const showConfigurableAgentsAlert = () => {
const id = addAlert(FEATURE_ALERTS.CONFIGURABLE_AGENTS);
showAlert(id);
};
const showAgentsMarketplaceAlert = () => {
const id = addAlert(FEATURE_ALERTS.AGENTS_MARKETPLACE);
showAlert(id);
};
const initializeFeatureAlerts = (currentPath?: string) => {
const existingAlerts = useFeatureAlerts.getState().alerts;
if (!existingAlerts.some(a => a.title === FEATURE_ALERTS.CONFIGURABLE_AGENTS.title)) {
addAlert(FEATURE_ALERTS.CONFIGURABLE_AGENTS);
}
if (!existingAlerts.some(a => a.title === FEATURE_ALERTS.AGENTS_MARKETPLACE.title)) {
addAlert(FEATURE_ALERTS.AGENTS_MARKETPLACE);
}
checkAndShowAlerts(currentPath);
};
return {
showConfigurableAgentsAlert,
showAgentsMarketplaceAlert,
initializeFeatureAlerts,
};
};