import { useDeferredValue, useMemo, useState } from 'react'; import { Link, useSearchParams } from 'react-router-dom'; import { VirtuosoGrid } from 'react-virtuoso'; import packageMetadata from '../../../../package.json'; import { Icon } from '../components/ui/Icon'; import { useSkills } from '../context/SkillContext'; import { usePageMeta } from '../hooks/usePageMeta'; import type { RiskLevel, Skill } from '../types'; import { WORKBENCH_HOSTS, buildInstallerCommand, collectSelectionEvidence, getHostCompatibility, getRecordedProvenance, getSetupType, isWorkbenchHost, matchesWorkbenchFilters, normalizeSelectedIds, parseSelectedIds, type CompatibilityFacet, type ProvenanceFacet, type RiskFacet, type SetupFacet, type WorkbenchHost, } from '../utils/skillWorkbench'; const riskStyles: Record = { none: 'border-emerald-300 bg-emerald-50 text-emerald-800 dark:border-emerald-800 dark:bg-emerald-950/50 dark:text-emerald-300', safe: 'border-teal-300 bg-teal-50 text-teal-800 dark:border-teal-800 dark:bg-teal-950/50 dark:text-teal-300', unknown: 'border-amber-300 bg-amber-50 text-amber-900 dark:border-amber-800 dark:bg-amber-950/50 dark:text-amber-300', critical: 'border-orange-300 bg-orange-50 text-orange-900 dark:border-orange-800 dark:bg-orange-950/50 dark:text-orange-300', offensive: 'border-rose-300 bg-rose-50 text-rose-900 dark:border-rose-800 dark:bg-rose-950/50 dark:text-rose-300', }; const evidenceToneStyles = { rose: 'border-rose-900/70 bg-rose-950/35 text-rose-200', orange: 'border-orange-900/70 bg-orange-950/30 text-orange-200', amber: 'border-amber-900/70 bg-amber-950/25 text-amber-200', violet: 'border-violet-900/70 bg-violet-950/25 text-violet-200', slate: 'border-slate-700 bg-slate-900 text-slate-300', } as const; function recordedRisk(skill: Skill): RiskLevel { return skill.risk ?? 'unknown'; } function EvidenceBucket({ summary, entries, tone, }: { summary: string; entries: string[]; tone: keyof typeof evidenceToneStyles; }): React.ReactElement | null { if (entries.length === 0) return null; return (

{entries.length} {summary}.

); } function buildWorkbenchQuery(selectedIds: Iterable, host: WorkbenchHost): URLSearchParams { const query = new URLSearchParams(); const normalized = normalizeSelectedIds(selectedIds); if (normalized.length > 0) query.set('selected', normalized.join(',')); query.set('host', host); return query; } function WorkbenchCard({ skill, selected, host, onToggle, }: { skill: Skill; selected: boolean; host: WorkbenchHost; onToggle: (skillId: string) => void; }): React.ReactElement { const compatibility = getHostCompatibility(skill, host); const provenance = getRecordedProvenance(skill); const setup = getSetupType(skill); const risk = recordedRisk(skill); const recordedOrigin = skill.source_repo || skill.source || 'not recorded'; return (

{skill.category}

{skill.name}

{skill.description}

risk: {risk} source: {provenance} host: {compatibility} {setup === 'manual' && ( manual setup )}
{skill.tags && skill.tags.length > 0 && (

{skill.tags.map((tag) => `#${tag}`).join(' ')}

)}

origin: {recordedOrigin}

{setup === 'manual' && skill.plugin?.setup?.summary && (

setup: {skill.plugin.setup.summary}

)} {compatibility === 'blocked' && skill.plugin?.reasons?.length ? (

recorded note: {skill.plugin.reasons.join(' ')}

) : null} Inspect canonical skill
); } export function Workbench(): React.ReactElement { const { skills, loading, error, refreshSkills } = useSkills(); const [searchParams, setSearchParams] = useSearchParams(); const [search, setSearch] = useState(''); const [category, setCategory] = useState('all'); const [risk, setRisk] = useState('all'); const [provenance, setProvenance] = useState('all'); const [compatibility, setCompatibility] = useState('all'); const [setup, setSetup] = useState('all'); const [copied, setCopied] = useState<'preview' | 'install' | 'share' | null>(null); const deferredSearch = useDeferredValue(search); usePageMeta(useMemo(() => ({ title: 'Skill Workbench | Agentic Awesome Skills', description: 'Filter canonical skill evidence, compose an exact host-aware set, and preview a version-pinned install without filesystem writes.', canonicalPath: '/workbench', }), [])); const hostParam = searchParams.get('host'); const host: WorkbenchHost = isWorkbenchHost(hostParam) ? hostParam : 'codex'; const selectedIds = useMemo( () => parseSelectedIds(searchParams.get('selected')), [searchParams], ); const skillsById = useMemo(() => new Map(skills.map((skill) => [skill.id, skill])), [skills]); const selectedSkills = useMemo( () => selectedIds.flatMap((skillId) => { const skill = skillsById.get(skillId); return skill ? [skill] : []; }), [selectedIds, skillsById], ); const missingSelectedIds = useMemo( () => selectedIds.filter((skillId) => !skillsById.has(skillId)), [selectedIds, skillsById], ); const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]); const categories = useMemo( () => ['all', ...new Set(skills.map((skill) => skill.category).filter(Boolean))].sort((a, b) => { if (a === 'all') return -1; if (b === 'all') return 1; return a.localeCompare(b); }), [skills], ); const filteredSkills = useMemo( () => skills.filter((skill) => matchesWorkbenchFilters(skill, { search: deferredSearch, category, risk, provenance, compatibility, setup, }, host)), [category, compatibility, deferredSearch, host, provenance, risk, setup, skills], ); const evidence = useMemo( () => collectSelectionEvidence(selectedSkills, host), [host, selectedSkills], ); const commands = useMemo(() => { if (selectedIds.length === 0 || missingSelectedIds.length > 0) return null; return { preview: buildInstallerCommand({ skillIds: selectedIds, host, version: packageMetadata.version, dryRun: true }), install: buildInstallerCommand({ skillIds: selectedIds, host, version: packageMetadata.version, dryRun: false }), }; }, [host, missingSelectedIds.length, selectedIds]); const installBlocked = missingSelectedIds.length > 0 || evidence.blockedForHost.length > 0; const updateUrlState = (nextSelectedIds: string[], nextHost = host) => { setSearchParams(buildWorkbenchQuery(nextSelectedIds, nextHost), { replace: true }); }; const toggleSkill = (skillId: string) => { const next = new Set(selectedIds); if (next.has(skillId)) next.delete(skillId); else next.add(skillId); updateUrlState([...next]); }; const changeHost = (nextHost: WorkbenchHost) => { updateUrlState(selectedIds, nextHost); setCompatibility('all'); }; const copyText = async (kind: 'preview' | 'install' | 'share', value: string) => { await navigator.clipboard.writeText(value); setCopied(kind); window.setTimeout(() => setCopied(null), 1800); }; const copyShareLink = async () => { const query = buildWorkbenchQuery(selectedIds, host).toString(); const relative = `${import.meta.env.BASE_URL}workbench${query ? `?${query}` : ''}`; await copyText('share', new URL(relative, window.location.origin).toString()); }; const resetFilters = () => { setSearch(''); setCategory('all'); setRisk('all'); setProvenance('all'); setCompatibility('all'); setSetup('all'); }; return (

Expert registry control bench

Build a precise, inspectable skill set

Query recorded catalog evidence, select exact canonical IDs, expose host and risk conflicts, then preview a pinned install before it touches a target directory.

catalog
{skills.length.toLocaleString('en-US')}
visible
{filteredSkills.length.toLocaleString('en-US')}
selected
{selectedSkills.length}

{filteredSkills.length.toLocaleString('en-US')} matching canonical skills

{selectedIds.length > 0 && ( )}
{loading ? (
{[...Array(8)].map((_, index) =>
)}
) : error && skills.length === 0 ? (

Unable to load the canonical catalog

{error}

) : filteredSkills.length === 0 ? (

No exact matches

Reset one or more recorded-data filters.

) : ( { const skill = filteredSkills[index]; return ; }} /> )}
); } export default Workbench;