diff --git a/apps/web/src/components/common/tool-card.tsx b/apps/web/src/components/common/tool-card.tsx index 79b9a52d..32a817ab 100644 --- a/apps/web/src/components/common/tool-card.tsx +++ b/apps/web/src/components/common/tool-card.tsx @@ -1,8 +1,10 @@ import type { Tool } from "@ashim/shared"; -import { FileImage, Star } from "lucide-react"; +import { PYTHON_SIDECAR_TOOLS } from "@ashim/shared"; +import { Download, FileImage, Star } from "lucide-react"; import { Link } from "react-router-dom"; import { ICON_MAP } from "@/lib/icon-map"; import { cn } from "@/lib/utils"; +import { useFeaturesStore } from "@/stores/features-store"; interface ToolCardProps { tool: Tool; @@ -12,6 +14,10 @@ export function ToolCard({ tool }: ToolCardProps) { const IconComponent = (ICON_MAP[tool.icon] as React.ComponentType<{ className?: string }>) ?? FileImage; + const isAiTool = (PYTHON_SIDECAR_TOOLS as readonly string[]).includes(tool.id); + const isInstalled = useFeaturesStore((s) => s.isToolInstalled)(tool.id); + const showDownloadBadge = isAiTool && !isInstalled; + return (
); diff --git a/apps/web/src/components/layout/tool-panel.tsx b/apps/web/src/components/layout/tool-panel.tsx index a7641053..a00bf9d9 100644 --- a/apps/web/src/components/layout/tool-panel.tsx +++ b/apps/web/src/components/layout/tool-panel.tsx @@ -1,5 +1,6 @@ import { CATEGORIES, TOOLS } from "@ashim/shared"; import { useEffect, useMemo, useState } from "react"; +import { useFeaturesStore } from "@/stores/features-store"; import { useSettingsStore } from "@/stores/settings-store"; import { SearchBar } from "../common/search-bar"; import { ToolCard } from "../common/tool-card"; @@ -7,11 +8,16 @@ import { ToolCard } from "../common/tool-card"; export function ToolPanel() { const [search, setSearch] = useState(""); const { disabledTools, experimentalEnabled, loaded, fetch } = useSettingsStore(); + const fetchFeatures = useFeaturesStore((s) => s.fetch); useEffect(() => { fetch(); }, [fetch]); + useEffect(() => { + fetchFeatures(); + }, [fetchFeatures]); + const visibleTools = useMemo(() => { if (!loaded) return []; return TOOLS.filter((t) => { diff --git a/apps/web/src/pages/fullscreen-grid-page.tsx b/apps/web/src/pages/fullscreen-grid-page.tsx index dcca7ff7..d2cf96dc 100644 --- a/apps/web/src/pages/fullscreen-grid-page.tsx +++ b/apps/web/src/pages/fullscreen-grid-page.tsx @@ -7,6 +7,7 @@ import { GemLogo } from "@/components/common/gem-logo"; import { apiGet } from "@/lib/api"; import { ICON_MAP } from "@/lib/icon-map"; import { cn } from "@/lib/utils"; +import { useFeaturesStore } from "@/stores/features-store"; export function FullscreenGridPage() { const [search, setSearch] = useState(""); @@ -14,6 +15,11 @@ export function FullscreenGridPage() { const navigate = useNavigate(); const [disabledTools, setDisabledTools] = useState([]); const [experimentalEnabled, setExperimentalEnabled] = useState(false); + const fetchFeatures = useFeaturesStore((s) => s.fetch); + + useEffect(() => { + fetchFeatures(); + }, [fetchFeatures]); useEffect(() => { apiGet<{ settings: Record }>("/v1/settings")