/** * Agents page functionality */ import { createChoices, getChoicesValues, type Choices } from '../choices'; import { FuzzySearch } from '../search'; import { fetchData, debounce, escapeHtml, getGitHubUrl, getVSCodeInstallUrl } from '../utils'; import { setupModal, openFileModal } from '../modal'; interface Agent { title: string; description?: string; path: string; model?: string; tools?: string[]; hasHandoffs?: boolean; } interface AgentsData { items: Agent[]; filters: { models: string[]; tools: string[]; }; } const resourceType = 'agent'; let allItems: Agent[] = []; let search = new FuzzySearch(); let modelSelect: Choices; let toolSelect: Choices; let currentFilters = { models: [] as string[], tools: [] as string[], hasHandoffs: false, }; function applyFiltersAndRender(): void { const searchInput = document.getElementById('search-input') as HTMLInputElement; const countEl = document.getElementById('results-count'); const query = searchInput?.value || ''; let results = query ? search.search(query) : [...allItems]; if (currentFilters.models.length > 0) { results = results.filter(item => { if (currentFilters.models.includes('(none)') && !item.model) { return true; } return item.model && currentFilters.models.includes(item.model); }); } if (currentFilters.tools.length > 0) { results = results.filter(item => item.tools?.some(tool => currentFilters.tools.includes(tool)) ); } if (currentFilters.hasHandoffs) { results = results.filter(item => item.hasHandoffs); } renderItems(results, query); const activeFilters: string[] = []; if (currentFilters.models.length > 0) activeFilters.push(`models: ${currentFilters.models.length}`); if (currentFilters.tools.length > 0) activeFilters.push(`tools: ${currentFilters.tools.length}`); if (currentFilters.hasHandoffs) activeFilters.push('has handoffs'); let countText = `${results.length} of ${allItems.length} agents`; if (activeFilters.length > 0) { countText += ` (filtered by ${activeFilters.join(', ')})`; } if (countEl) countEl.textContent = countText; } function renderItems(items: Agent[], query = ''): void { const list = document.getElementById('resource-list'); if (!list) return; if (items.length === 0) { list.innerHTML = `

No agents found

Try a different search term or adjust filters

`; return; } list.innerHTML = items.map(item => `
${query ? search.highlight(item.title, query) : escapeHtml(item.title)}
${escapeHtml(item.description || 'No description')}
${item.model ? `${escapeHtml(item.model)}` : ''} ${item.tools?.slice(0, 3).map(t => `${escapeHtml(t)}`).join('') || ''} ${item.tools && item.tools.length > 3 ? `+${item.tools.length - 3} more` : ''} ${item.hasHandoffs ? `handoffs` : ''}
VS Code Insiders GitHub
`).join(''); // Add click handlers list.querySelectorAll('.resource-item').forEach(el => { el.addEventListener('click', () => { const path = (el as HTMLElement).dataset.path; if (path) openFileModal(path, resourceType); }); }); } export async function initAgentsPage(): Promise { const list = document.getElementById('resource-list'); const searchInput = document.getElementById('search-input') as HTMLInputElement; const handoffsCheckbox = document.getElementById('filter-handoffs') as HTMLInputElement; const clearFiltersBtn = document.getElementById('clear-filters'); const data = await fetchData('agents.json'); if (!data || !data.items) { if (list) list.innerHTML = '

Failed to load data

'; return; } allItems = data.items; search.setItems(allItems); // Initialize Choices.js for model filter modelSelect = createChoices('#filter-model', { placeholderValue: 'All Models' }); modelSelect.setChoices(data.filters.models.map(m => ({ value: m, label: m })), 'value', 'label', true); document.getElementById('filter-model')?.addEventListener('change', () => { currentFilters.models = getChoicesValues(modelSelect); applyFiltersAndRender(); }); // Initialize Choices.js for tool filter toolSelect = createChoices('#filter-tool', { placeholderValue: 'All Tools' }); toolSelect.setChoices(data.filters.tools.map(t => ({ value: t, label: t })), 'value', 'label', true); document.getElementById('filter-tool')?.addEventListener('change', () => { currentFilters.tools = getChoicesValues(toolSelect); applyFiltersAndRender(); }); applyFiltersAndRender(); searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200)); handoffsCheckbox?.addEventListener('change', () => { currentFilters.hasHandoffs = handoffsCheckbox.checked; applyFiltersAndRender(); }); clearFiltersBtn?.addEventListener('click', () => { currentFilters = { models: [], tools: [], hasHandoffs: false }; modelSelect.removeActiveItems(); toolSelect.removeActiveItems(); if (handoffsCheckbox) handoffsCheckbox.checked = false; if (searchInput) searchInput.value = ''; applyFiltersAndRender(); }); setupModal(); } // Auto-initialize when DOM is ready document.addEventListener('DOMContentLoaded', initAgentsPage);