1+ import { getToolRegistry } from "../tools/toolRegistry.js" ;
2+
13const METADATA_PATH = "./metadata/samples.index.metadata.json" ;
24const PINNED_KEY = "samples-index-pinned" ;
35
@@ -69,7 +71,18 @@ function buildClassTokens(classValues, engineClassesUsed) {
6971 . sort ( ( a , b ) => a . label . localeCompare ( b . label , undefined , { sensitivity : "base" } ) ) ;
7072}
7173
72- function buildSampleRows ( metadata , pinnedSet ) {
74+ function buildToolTokens ( toolHints , toolLabelMap ) {
75+ const deduped = [ ...new Set ( asArray ( toolHints ) . map ( ( entry ) => normalizeToken ( entry ) ) . filter ( Boolean ) ) ] ;
76+ return deduped
77+ . filter ( ( toolId ) => toolId !== "workspace-manager" )
78+ . map ( ( toolId ) => ( {
79+ value : toolId ,
80+ label : toolLabelMap . get ( toolId ) || toolId
81+ } ) )
82+ . sort ( ( a , b ) => a . label . localeCompare ( b . label , undefined , { sensitivity : "base" } ) ) ;
83+ }
84+
85+ function buildSampleRows ( metadata , pinnedSet , toolLabelMap ) {
7386 const phaseInfoMap = new Map (
7487 asArray ( metadata ?. phases )
7588 . map ( ( phase ) => {
@@ -102,6 +115,7 @@ function buildSampleRows(metadata, pinnedSet) {
102115 const href = normalize ( sample ?. href ) || `./phase-${ phase } /${ id } /index.html` ;
103116 const tags = asArray ( sample ?. tags ) . map ( ( tag ) => normalizeTag ( tag ) ) . filter ( Boolean ) ;
104117 const classTokens = buildClassTokens ( sample ?. classValues , sample ?. engineClassesUsed ) ;
118+ const toolTokens = buildToolTokens ( sample ?. toolHints , toolLabelMap ) ;
105119 const previewSrc = normalize ( sample ?. thumbnail ) || normalize ( sample ?. preview ) || "" ;
106120 return {
107121 id,
@@ -113,6 +127,7 @@ function buildSampleRows(metadata, pinnedSet) {
113127 href,
114128 tags,
115129 classTokens,
130+ toolTokens,
116131 previewSrc,
117132 pinned : pinnedSet . has ( id )
118133 } ;
@@ -134,9 +149,14 @@ function buildSampleRows(metadata, pinnedSet) {
134149 ) . entries ( ) ]
135150 . map ( ( [ value , label ] ) => ( { value, label } ) )
136151 . sort ( ( a , b ) => a . label . localeCompare ( b . label , undefined , { sensitivity : "base" } ) ) ;
152+ const tools = [ ...new Map (
153+ sampleRows . flatMap ( ( sample ) => sample . toolTokens ) . map ( ( token ) => [ token . value , token . label ] )
154+ ) . entries ( ) ]
155+ . map ( ( [ value , label ] ) => ( { value, label } ) )
156+ . sort ( ( a , b ) => a . label . localeCompare ( b . label , undefined , { sensitivity : "base" } ) ) ;
137157 const tags = [ ...new Set ( sampleRows . flatMap ( ( sample ) => sample . tags ) ) ] . sort ( ) ;
138158
139- return { sampleRows, phases, phaseOptions, classes, tags, phaseInfoMap } ;
159+ return { sampleRows, phases, phaseOptions, classes, tools , tags, phaseInfoMap } ;
140160}
141161
142162function filterSampleRows ( sampleRows , filterState ) {
@@ -148,14 +168,18 @@ function filterSampleRows(sampleRows, filterState) {
148168 if ( filterState . className && ! sample . classTokens . some ( ( token ) => token . value === filterState . className ) ) {
149169 return false ;
150170 }
171+ if ( filterState . toolId && ! sample . toolTokens . some ( ( token ) => token . value === filterState . toolId ) ) {
172+ return false ;
173+ }
151174 if ( filterState . tag && ! sample . tags . includes ( filterState . tag ) ) {
152175 return false ;
153176 }
154177 if ( ! query ) {
155178 return true ;
156179 }
157180 const classText = sample . classTokens . map ( ( token ) => `${ token . label } ${ token . value } ` ) . join ( " " ) ;
158- const haystack = `${ sample . phase } ${ sample . phaseTitle } ${ sample . id } ${ sample . title } ${ sample . description } ${ sample . tags . join ( " " ) } ${ classText } ` . toLowerCase ( ) ;
181+ const toolText = sample . toolTokens . map ( ( token ) => `${ token . label } ${ token . value } ` ) . join ( " " ) ;
182+ const haystack = `${ sample . phase } ${ sample . phaseTitle } ${ sample . id } ${ sample . title } ${ sample . description } ${ sample . tags . join ( " " ) } ${ classText } ${ toolText } ` . toLowerCase ( ) ;
159183 return haystack . includes ( query ) ;
160184 } ) ;
161185}
@@ -300,10 +324,11 @@ export async function initSamplesIndex() {
300324 const pinnedContainer = document . getElementById ( "samples-pinned-list" ) ;
301325 const phaseSelect = document . getElementById ( "samples-filter-phase" ) ;
302326 const classSelect = document . getElementById ( "samples-filter-class" ) ;
327+ const toolSelect = document . getElementById ( "samples-filter-tool" ) ;
303328 const tagSelect = document . getElementById ( "samples-filter-tag" ) ;
304329 const searchInput = document . getElementById ( "samples-phase-filter-input" ) ;
305330 const statusNode = document . getElementById ( "samples-phase-filter-status" ) ;
306- if ( ! listContainer || ! pinnedContainer || ! phaseSelect || ! classSelect || ! tagSelect || ! searchInput || ! statusNode ) {
331+ if ( ! listContainer || ! pinnedContainer || ! phaseSelect || ! classSelect || ! toolSelect || ! tagSelect || ! searchInput || ! statusNode ) {
307332 return ;
308333 }
309334
@@ -314,8 +339,14 @@ export async function initSamplesIndex() {
314339 }
315340 const metadata = await response . json ( ) ;
316341 let pinnedSet = readPinnedSet ( ) ;
342+ const toolLabelMap = new Map (
343+ getToolRegistry ( )
344+ . filter ( ( tool ) => tool . id !== "workspace-manager" )
345+ . map ( ( tool ) => [ normalizeToken ( tool . id ) , normalize ( tool . displayName ) || normalize ( tool . name ) || normalize ( tool . id ) ] )
346+ . filter ( ( entry ) => entry [ 0 ] && entry [ 1 ] )
347+ ) ;
317348
318- const model = buildSampleRows ( metadata , pinnedSet ) ;
349+ const model = buildSampleRows ( metadata , pinnedSet , toolLabelMap ) ;
319350 setSelectOptions ( phaseSelect , model . phaseOptions . map ( ( entry ) => entry . value ) , ( value ) => {
320351 const found = model . phaseOptions . find ( ( entry ) => entry . value === value ) ;
321352 return found ?. label || `Phase ${ value } ` ;
@@ -324,13 +355,22 @@ export async function initSamplesIndex() {
324355 const found = model . classes . find ( ( entry ) => entry . value === value ) ;
325356 return found ?. label || value . split ( "/" ) . at ( - 1 ) || value ;
326357 } ) ;
358+ setSelectOptions ( toolSelect , model . tools . map ( ( entry ) => entry . value ) , ( value ) => {
359+ const found = model . tools . find ( ( entry ) => entry . value === value ) ;
360+ return found ?. label || value ;
361+ } ) ;
327362 setSelectOptions ( tagSelect , model . tags , ( value ) => value ) ;
363+ const toolQuery = normalizeToken ( new URLSearchParams ( window . location . search ) . get ( "tool" ) ) ;
364+ if ( toolQuery && model . tools . some ( ( entry ) => entry . value === toolQuery ) ) {
365+ toolSelect . value = toolQuery ;
366+ }
328367
329368 const render = ( ) => {
330- const nextModel = buildSampleRows ( metadata , pinnedSet ) ;
369+ const nextModel = buildSampleRows ( metadata , pinnedSet , toolLabelMap ) ;
331370 const filterState = {
332371 phase : normalize ( phaseSelect . value ) ,
333372 className : normalize ( classSelect . value ) ,
373+ toolId : normalizeToken ( toolSelect . value ) ,
334374 tag : normalize ( tagSelect . value ) ,
335375 query : normalize ( searchInput . value )
336376 } ;
@@ -365,6 +405,7 @@ export async function initSamplesIndex() {
365405
366406 phaseSelect . addEventListener ( "change" , render ) ;
367407 classSelect . addEventListener ( "change" , render ) ;
408+ toolSelect . addEventListener ( "change" , render ) ;
368409 tagSelect . addEventListener ( "change" , render ) ;
369410 searchInput . addEventListener ( "input" , render ) ;
370411
0 commit comments