@supericons/mcp 0.4.9 → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/remote-server.js CHANGED
@@ -48,17 +48,31 @@ const LIBRARIES = [
48
48
  ['material', 'Material Symbols', 'Google Material Symbols'],
49
49
  ['mingcute', 'MingCute', 'Modern interface icons'],
50
50
  ['phosphor', 'Phosphor', 'Flexible icon family'],
51
+ ['si', 'Supericons', 'AI and developer tool logos curated for agentic app builders'],
51
52
  ['simpleicons', 'Simple Icons', 'Brand and product icons'],
52
53
  ['tabler', 'Tabler', 'Large open-source SVG icon library'],
53
54
  ];
55
+ const libraryCounts = new Map(
56
+ (Array.isArray(iconIndex?.libraries) ? iconIndex.libraries : []).map((entry) => [
57
+ entry.id,
58
+ Number(entry.count || 0),
59
+ ])
60
+ );
54
61
 
55
62
  const libraryKeysDescription =
56
- 'Supported values include lucide, tabler, phosphor, heroicons, bootstrap, iconoir, ionicons, material, simpleicons, and mingcute.';
63
+ 'Supported values include si, lucide, tabler, phosphor, heroicons, bootstrap, iconoir, ionicons, material, simpleicons, and mingcute.';
57
64
  const multilingualLocaleValues = ['zh-Hans', 'zh-Hant', 'ja', 'ko', 'es', 'de', 'pt', 'ar', 'hi', 'vi', 'th'];
58
65
  const multilingualLocaleDescription =
59
66
  'Optional locale for multilingual search terms. Supported values: zh-Hans, zh-Hant, ja, ko, es, de, pt, ar, hi, vi, th.';
60
67
 
61
- const readOnlySearchAnnotations = {
68
+ const auditedSearchAnnotations = {
69
+ readOnlyHint: false,
70
+ destructiveHint: false,
71
+ idempotentHint: false,
72
+ openWorldHint: false,
73
+ };
74
+
75
+ const readOnlyLookupAnnotations = {
62
76
  readOnlyHint: true,
63
77
  destructiveHint: false,
64
78
  idempotentHint: true,
@@ -79,6 +93,7 @@ const libraryResultSchema = z.object({
79
93
  id: z.string().describe('Library key used in tool calls.'),
80
94
  name: z.string().describe('Human-readable library name.'),
81
95
  description: z.string().describe('Brief public description of the icon library.'),
96
+ count: z.number().describe('Number of icons in the library.'),
82
97
  });
83
98
 
84
99
  const searchIconsOutputSchema = {
@@ -240,7 +255,7 @@ function createServer() {
240
255
  'search_icons',
241
256
  {
242
257
  title: 'Search Icons',
243
- description: `Search ${freeIconCountLabel} by meaning, label, visual description, tags, and synonyms. Use this when the user describes an icon concept such as "database", "user profile", "chill", "security", or "AI model". Returns matching icons with SVG code and public semantic guidance.`,
258
+ description: `Search ${freeIconCountLabel} by meaning, label, visual description, tags, and synonyms. Use this when the user describes an icon concept such as "database", "user profile", "chill", "security", "AI model", or "OpenAI Codex logo". Returns matching icons with SVG code and public semantic guidance.`,
244
259
  inputSchema: {
245
260
  query: z.string().describe('Icon concept or search phrase, for example "database", "user profile", "chill", "trash", "upload cloud", "AI model", or "beautiful".'),
246
261
  library: z.string().optional().describe(`Optional library key. ${libraryKeysDescription}`),
@@ -249,7 +264,7 @@ function createServer() {
249
264
  limit: z.number().min(1).max(50).optional().default(10).describe('Maximum number of icons to return. Use 5-10 for browsing and 1-3 for quick agent choices.'),
250
265
  },
251
266
  outputSchema: searchIconsOutputSchema,
252
- annotations: readOnlySearchAnnotations,
267
+ annotations: auditedSearchAnnotations,
253
268
  },
254
269
  async ({ query, library, style, locale, limit }) => {
255
270
  const results = await searchHostedIcons({ query, library, style, locale, limit });
@@ -274,7 +289,7 @@ function createServer() {
274
289
  response_mode: z.enum(['plan', 'assets', 'full']).optional().default('plan').describe('Response size mode. Use plan for compact icon IDs and reasons, assets to include SVG only for each top recommendation, or full to include SVG and semantic payloads for all returned choices.'),
275
290
  },
276
291
  outputSchema: recommendIconsOutputSchema,
277
- annotations: readOnlySearchAnnotations,
292
+ annotations: auditedSearchAnnotations,
278
293
  },
279
294
  async ({ task, slots, library, style, locale, limit_per_slot, response_mode }) => {
280
295
  const payload = await recommendIconsForTask({
@@ -305,7 +320,7 @@ function createServer() {
305
320
  style: z.enum(['any', 'outline', 'solid']).optional().default('any').describe('Optional style preference. Use "any" unless the caller needs a specific variant.'),
306
321
  },
307
322
  outputSchema: getIconOutputSchema,
308
- annotations: readOnlySearchAnnotations,
323
+ annotations: auditedSearchAnnotations,
309
324
  },
310
325
  async ({ id, library, style }) => {
311
326
  const candidates = await searchHostedIcons({
@@ -335,13 +350,14 @@ function createServer() {
335
350
  title: 'List Libraries',
336
351
  description: 'List the free icon libraries available through the hosted Supericons MCP server. Use this before filtering by library or when a user asks which icon libraries are supported.',
337
352
  outputSchema: listLibrariesOutputSchema,
338
- annotations: readOnlySearchAnnotations,
353
+ annotations: readOnlyLookupAnnotations,
339
354
  },
340
355
  async () => asStructured({
341
356
  libraries: LIBRARIES.map(([id, name, description]) => ({
342
357
  id,
343
358
  name,
344
359
  description,
360
+ count: libraryCounts.get(id) || 0,
345
361
  })),
346
362
  publicRecordCount: registrySummary.publicRecordCount,
347
363
  })
@@ -1,6 +1,12 @@
1
- export const JOB_LIBRARY_PREFIX = 'job:';
2
-
1
+ import {
2
+ SUPERICONS_AI_CATEGORY_DEFINITIONS,
3
+ buildSupericonsAiTaxonomyEntries,
4
+ } from './supericons-ai-taxonomy.js';
5
+
6
+ export const JOB_LIBRARY_PREFIX = 'job:';
7
+
3
8
  export const JOB_CATEGORY_DEFINITIONS = [
9
+ ...SUPERICONS_AI_CATEGORY_DEFINITIONS,
4
10
  {
5
11
  id: 'ai-agent-workflows',
6
12
  label: 'AI & Automation',
@@ -110,6 +116,8 @@ export const JOB_CATEGORY_DEFINITIONS = [
110
116
  sidebarGlyph: 'wb_sunny',
111
117
  },
112
118
  ];
119
+
120
+ const JOB_CATEGORY_IDS = new Set(JOB_CATEGORY_DEFINITIONS.map((category) => category.id));
113
121
 
114
122
  const NAVIGATION_ICON_IDS = [
115
123
  'material:menu',
@@ -285,6 +293,7 @@ function buildEntries(jobCategory, iconIds, secondaryCategories) {
285
293
  }
286
294
 
287
295
  export const JOB_ICON_TAXONOMY_SEED = [
296
+ ...buildSupericonsAiTaxonomyEntries(),
288
297
  ...buildEntries('ai-agent-workflows', AI_AGENT_ICON_IDS, ['ai', 'agents', 'automation']),
289
298
  ...buildEntries('navigation-wayfinding', NAVIGATION_ICON_IDS, ['navigation', 'wayfinding', 'layout']),
290
299
  ...buildEntries('status-feedback', STATUS_ICON_IDS, ['status', 'feedback', 'signals']),
@@ -307,6 +316,11 @@ function iconText(icon = {}) {
307
316
  icon.name,
308
317
  icon.style,
309
318
  icon.type,
319
+ icon.aiCategory,
320
+ icon.jobCategory,
321
+ ...(Array.isArray(icon.aiFilterTags) ? icon.aiFilterTags : []),
322
+ ...(Array.isArray(icon.semanticTags) ? icon.semanticTags : []),
323
+ ...(Array.isArray(icon.secondaryCategories) ? icon.secondaryCategories : []),
310
324
  ].filter(Boolean).join(' '));
311
325
  }
312
326
 
@@ -404,6 +418,20 @@ const PURPOSE_INFERENCE_RULES = [
404
418
  ];
405
419
 
406
420
  function inferTaxonomyEntry(icon, index = 0) {
421
+ const explicitJobCategory = String(icon?.jobCategory || icon?.aiCategory || '').trim();
422
+ if (explicitJobCategory && JOB_CATEGORY_IDS.has(explicitJobCategory)) {
423
+ return {
424
+ iconId: `${icon.lib}:${icon.id}`,
425
+ sourceLibrary: icon.lib,
426
+ jobCategory: explicitJobCategory,
427
+ secondaryCategories: [
428
+ ...(Array.isArray(icon.secondaryCategories) ? icon.secondaryCategories : []),
429
+ ...(Array.isArray(icon.aiFilterTags) ? icon.aiFilterTags : []),
430
+ ],
431
+ rank: 4000 + index,
432
+ };
433
+ }
434
+
407
435
  const text = iconText(icon);
408
436
  if (!text) return null;
409
437
 
@@ -0,0 +1,403 @@
1
+ const BASE_FILTER_TAGS = Object.freeze(['agentic-ai-tools-pack', 'brand-logo']);
2
+
3
+ export const SUPERICONS_AI_CATEGORY_DEFINITIONS = Object.freeze([
4
+ {
5
+ id: 'ai-app-builders',
6
+ label: 'AI App Builders',
7
+ description: 'Text-to-app, text-to-site, no-code, low-code, and vibe-coding products.',
8
+ sidebarGlyph: 'auto_fix_high',
9
+ },
10
+ {
11
+ id: 'coding-agents-dev-environments',
12
+ label: 'Coding Agents & Dev Environments',
13
+ description: 'Agentic IDEs, coding assistants, developer agents, and software-building workspaces.',
14
+ sidebarGlyph: 'terminal',
15
+ },
16
+ {
17
+ id: 'model-platforms-ai-labs',
18
+ label: 'Model Platforms & AI Labs',
19
+ description: 'Foundation model providers, model studios, AI labs, and model API platforms.',
20
+ sidebarGlyph: 'model_training',
21
+ },
22
+ {
23
+ id: 'ai-search-research-evaluation',
24
+ label: 'AI Search, Research & Evaluation',
25
+ description: 'AI-native search, research, retrieval, benchmarking, ranking, and evaluation tools.',
26
+ sidebarGlyph: 'database_search',
27
+ },
28
+ {
29
+ id: 'generative-media-creative-ai',
30
+ label: 'Generative Media & Creative AI',
31
+ description: 'AI video, image, avatar, creative studio, and synthetic media products.',
32
+ sidebarGlyph: 'movie',
33
+ },
34
+ {
35
+ id: 'voice-audio-ai',
36
+ label: 'Voice & Audio AI',
37
+ description: 'Speech, voice, music, audio generation, and audio model products.',
38
+ sidebarGlyph: 'graphic_eq',
39
+ },
40
+ {
41
+ id: 'agent-infrastructure-runtime',
42
+ label: 'Agent Infrastructure & Runtime',
43
+ description: 'Agent runtime, browser automation, memory, vector storage, workflow, and observability infrastructure.',
44
+ sidebarGlyph: 'account_tree',
45
+ },
46
+ {
47
+ id: 'mcp-tooling-protocols',
48
+ label: 'MCP, Tooling & Protocols',
49
+ description: 'MCP servers, tool directories, context services, protocol tooling, and agent tool distribution.',
50
+ sidebarGlyph: 'hub',
51
+ },
52
+ {
53
+ id: 'general-agents-assistants',
54
+ label: 'General Agents & Assistants',
55
+ description: 'General-purpose assistants, autonomous task agents, local agents, and multi-step AI workers.',
56
+ sidebarGlyph: 'smart_toy',
57
+ },
58
+ {
59
+ id: 'design-ui-intelligence',
60
+ label: 'Design & UI Intelligence',
61
+ description: 'Design references, UI kits, component systems, creative assets, and visual product intelligence.',
62
+ sidebarGlyph: 'palette',
63
+ },
64
+ {
65
+ id: 'agent-business-monetization',
66
+ label: 'Agent Business & Monetization',
67
+ description: 'Revenue, referrals, commerce, affiliate, and monetization tools for agent ecosystems.',
68
+ sidebarGlyph: 'payments',
69
+ },
70
+ ]);
71
+
72
+ const CATEGORY_LABEL_BY_ID = new Map(SUPERICONS_AI_CATEGORY_DEFINITIONS.map((category) => [category.id, category.label]));
73
+
74
+ function taxonomy(jobCategory, secondaryCategories, aiFilterTags = []) {
75
+ return Object.freeze({
76
+ jobCategory,
77
+ secondaryCategories: Object.freeze([...secondaryCategories]),
78
+ aiFilterTags: Object.freeze([...aiFilterTags]),
79
+ });
80
+ }
81
+
82
+ export const SUPERICONS_AI_ICON_TAXONOMY = Object.freeze({
83
+ 'si:artificial-analysis': taxonomy(
84
+ 'ai-search-research-evaluation',
85
+ ['model-benchmarking', 'ai-evaluation', 'provider-comparison'],
86
+ ['ai-benchmarking', 'llm-leaderboard', 'provider-comparison']
87
+ ),
88
+ 'si:base44': taxonomy(
89
+ 'ai-app-builders',
90
+ ['ai-app-builder', 'no-code-low-code', 'vibe-coding'],
91
+ ['text-to-app', 'app-generation', 'vibe-coding']
92
+ ),
93
+ 'si:bolt': taxonomy(
94
+ 'ai-app-builders',
95
+ ['ai-app-builder', 'browser-app-builder', 'vibe-coding'],
96
+ ['bolt-new', 'web-app-generation', 'vibe-coding']
97
+ ),
98
+ 'si:bridgemind-ai': taxonomy(
99
+ 'coding-agents-dev-environments',
100
+ ['coding-agent', 'developer-tooling', 'code-assistant'],
101
+ ['ai-development', 'developer-agent', 'code-workflow']
102
+ ),
103
+ 'si:browserbase': taxonomy(
104
+ 'agent-infrastructure-runtime',
105
+ ['browser-automation', 'web-agent-runtime', 'agent-infrastructure'],
106
+ ['headless-browser', 'web-automation', 'agent-runtime']
107
+ ),
108
+ 'si:capcut': taxonomy(
109
+ 'generative-media-creative-ai',
110
+ ['video-editing', 'short-form-video', 'creative-ai'],
111
+ ['creator-tools', 'video-editor', 'social-video']
112
+ ),
113
+ 'si:cartesia': taxonomy(
114
+ 'voice-audio-ai',
115
+ ['voice-ai', 'speech-generation', 'audio-models'],
116
+ ['text-to-speech', 'voice-models', 'real-time-audio']
117
+ ),
118
+ 'si:cohere': taxonomy(
119
+ 'model-platforms-ai-labs',
120
+ ['enterprise-llm', 'reranking', 'model-api'],
121
+ ['foundation-models', 'embedding-models', 'enterprise-ai']
122
+ ),
123
+ 'si:context7': taxonomy(
124
+ 'mcp-tooling-protocols',
125
+ ['mcp-docs', 'developer-context', 'tool-protocol'],
126
+ ['context-server', 'developer-docs', 'mcp']
127
+ ),
128
+ 'si:devin': taxonomy(
129
+ 'coding-agents-dev-environments',
130
+ ['coding-agent', 'software-engineering-agent', 'autonomous-development'],
131
+ ['developer-agent', 'engineering-automation', 'ai-coding']
132
+ ),
133
+ 'si:exa': taxonomy(
134
+ 'ai-search-research-evaluation',
135
+ ['ai-search', 'web-search-api', 'research-retrieval'],
136
+ ['semantic-search', 'web-retrieval', 'research-api']
137
+ ),
138
+ 'si:factory-ai': taxonomy(
139
+ 'coding-agents-dev-environments',
140
+ ['coding-agent', 'software-development', 'engineering-automation'],
141
+ ['developer-agent', 'ai-engineering', 'code-automation']
142
+ ),
143
+ 'si:fal-ai': taxonomy(
144
+ 'generative-media-creative-ai',
145
+ ['image-video-generation', 'model-inference', 'creative-api'],
146
+ ['media-models', 'inference-api', 'creative-infrastructure']
147
+ ),
148
+ 'si:firecrawl': taxonomy(
149
+ 'agent-infrastructure-runtime',
150
+ ['web-crawling', 'agent-ingestion', 'data-extraction'],
151
+ ['web-scraping', 'site-ingestion', 'agent-data']
152
+ ),
153
+ 'si:glama': taxonomy(
154
+ 'mcp-tooling-protocols',
155
+ ['mcp-directory', 'tool-discovery', 'agent-tools'],
156
+ ['mcp', 'tool-registry', 'agent-tooling']
157
+ ),
158
+ 'si:google-ai-studio': taxonomy(
159
+ 'model-platforms-ai-labs',
160
+ ['model-studio', 'gemini', 'prompt-prototyping'],
161
+ ['google-ai', 'model-prototyping', 'ai-studio']
162
+ ),
163
+ 'si:google-antigravity': taxonomy(
164
+ 'coding-agents-dev-environments',
165
+ ['agentic-ide', 'coding-agent', 'developer-environment'],
166
+ ['google-ai', 'developer-workspace', 'ai-coding']
167
+ ),
168
+ 'si:goose': taxonomy(
169
+ 'general-agents-assistants',
170
+ ['local-agent', 'desktop-agent', 'task-automation'],
171
+ ['agent-assistant', 'local-automation', 'multi-step-agent']
172
+ ),
173
+ 'si:hermes-agent': taxonomy(
174
+ 'general-agents-assistants',
175
+ ['general-agent', 'browser-agent', 'task-agent'],
176
+ ['autonomous-agent', 'ai-assistant', 'agent-worker']
177
+ ),
178
+ 'si:heygen': taxonomy(
179
+ 'generative-media-creative-ai',
180
+ ['avatar-video', 'synthetic-video', 'ai-video'],
181
+ ['video-generation', 'avatar-generation', 'creative-ai']
182
+ ),
183
+ 'si:higgsfield': taxonomy(
184
+ 'generative-media-creative-ai',
185
+ ['ai-video', 'motion-generation', 'creative-ai'],
186
+ ['video-generation', 'image-to-video', 'cinematic-ai']
187
+ ),
188
+ 'si:inngest': taxonomy(
189
+ 'agent-infrastructure-runtime',
190
+ ['workflow-orchestration', 'durable-functions', 'event-driven-agents'],
191
+ ['background-jobs', 'agent-workflows', 'workflow-engine']
192
+ ),
193
+ 'si:kickbacks-ai': taxonomy(
194
+ 'agent-business-monetization',
195
+ ['affiliate-monetization', 'agent-commerce', 'referrals'],
196
+ ['revenue-tools', 'agent-marketplace', 'affiliate-ai']
197
+ ),
198
+ 'si:kilo-code': taxonomy(
199
+ 'coding-agents-dev-environments',
200
+ ['coding-agent', 'open-source-ide', 'developer-agent'],
201
+ ['ai-coding', 'code-assistant', 'developer-workspace']
202
+ ),
203
+ 'si:kimi': taxonomy(
204
+ 'model-platforms-ai-labs',
205
+ ['chat-assistant', 'long-context', 'foundation-model'],
206
+ ['model-platform', 'llm-assistant', 'ai-lab']
207
+ ),
208
+ 'si:kling-ai': taxonomy(
209
+ 'generative-media-creative-ai',
210
+ ['ai-video', 'image-to-video', 'generative-media'],
211
+ ['video-generation', 'creative-ai', 'synthetic-video']
212
+ ),
213
+ 'si:lovable': taxonomy(
214
+ 'ai-app-builders',
215
+ ['ai-app-builder', 'vibe-coding', 'web-app-generation'],
216
+ ['text-to-app', 'product-builder', 'frontend-generation']
217
+ ),
218
+ 'si:luma-ai': taxonomy(
219
+ 'generative-media-creative-ai',
220
+ ['ai-video', '3d-generation', 'creative-ai'],
221
+ ['dream-machine', 'video-generation', 'world-model']
222
+ ),
223
+ 'si:manus-ai': taxonomy(
224
+ 'general-agents-assistants',
225
+ ['general-agent', 'autonomous-agent', 'multi-step-tasks'],
226
+ ['ai-assistant', 'agent-worker', 'task-automation']
227
+ ),
228
+ 'si:mobbin': taxonomy(
229
+ 'design-ui-intelligence',
230
+ ['design-inspiration', 'ui-reference', 'product-design'],
231
+ ['screen-library', 'design-research', 'ui-patterns']
232
+ ),
233
+ 'si:openai-codex-app': taxonomy(
234
+ 'coding-agents-dev-environments',
235
+ ['coding-agent', 'software-engineering-agent', 'developer-environment'],
236
+ ['ai-coding', 'developer-agent', 'code-generation']
237
+ ),
238
+ 'si:openclaw': taxonomy(
239
+ 'general-agents-assistants',
240
+ ['general-agent', 'open-source-agent', 'desktop-agent'],
241
+ ['autonomous-agent', 'agent-assistant', 'local-agent']
242
+ ),
243
+ 'si:opencode': taxonomy(
244
+ 'coding-agents-dev-environments',
245
+ ['terminal-coding-agent', 'developer-cli', 'coding-agent'],
246
+ ['ai-coding', 'command-line-agent', 'code-assistant']
247
+ ),
248
+ 'si:pika': taxonomy(
249
+ 'generative-media-creative-ai',
250
+ ['ai-video', 'generative-video', 'creative-ai'],
251
+ ['video-generation', 'text-to-video', 'synthetic-video']
252
+ ),
253
+ 'si:pinecone': taxonomy(
254
+ 'agent-infrastructure-runtime',
255
+ ['vector-database', 'retrieval-memory', 'agent-memory'],
256
+ ['embeddings', 'semantic-retrieval', 'rag-infrastructure']
257
+ ),
258
+ 'si:pixverse': taxonomy(
259
+ 'generative-media-creative-ai',
260
+ ['ai-video', 'generative-video', 'creative-ai'],
261
+ ['video-generation', 'text-to-video', 'synthetic-video']
262
+ ),
263
+ 'si:portkey': taxonomy(
264
+ 'agent-infrastructure-runtime',
265
+ ['ai-gateway', 'llm-observability', 'model-routing'],
266
+ ['model-gateway', 'ai-observability', 'llm-routing']
267
+ ),
268
+ 'si:runway': taxonomy(
269
+ 'generative-media-creative-ai',
270
+ ['ai-video', 'creative-studio', 'generative-media'],
271
+ ['video-generation', 'film-tools', 'synthetic-media']
272
+ ),
273
+ 'si:shadcn-ui': taxonomy(
274
+ 'design-ui-intelligence',
275
+ ['ui-components', 'design-system', 'frontend-ui'],
276
+ ['component-library', 'design-system', 'interface-building']
277
+ ),
278
+ 'si:smithery': taxonomy(
279
+ 'mcp-tooling-protocols',
280
+ ['mcp-directory', 'mcp-server-hosting', 'tool-registry'],
281
+ ['mcp', 'agent-tools', 'server-directory']
282
+ ),
283
+ 'si:stagehand': taxonomy(
284
+ 'agent-infrastructure-runtime',
285
+ ['browser-automation', 'web-agent-runtime', 'agent-testing'],
286
+ ['web-automation', 'browser-agent', 'agent-runtime']
287
+ ),
288
+ 'si:stepfun': taxonomy(
289
+ 'model-platforms-ai-labs',
290
+ ['foundation-model', 'chat-assistant', 'model-platform'],
291
+ ['llm', 'ai-lab', 'model-api']
292
+ ),
293
+ 'si:suno-ai': taxonomy(
294
+ 'voice-audio-ai',
295
+ ['music-generation', 'audio-generation', 'voice-audio-ai'],
296
+ ['ai-music', 'song-generation', 'audio-models']
297
+ ),
298
+ 'si:supericons': taxonomy(
299
+ 'design-ui-intelligence',
300
+ ['ai-icon-library', 'design-assets', 'ui-icons'],
301
+ ['icon-system', 'brand-icons', 'design-tooling']
302
+ ),
303
+ 'si:temporal': taxonomy(
304
+ 'agent-infrastructure-runtime',
305
+ ['durable-workflows', 'workflow-orchestration', 'agent-runtime'],
306
+ ['workflow-engine', 'long-running-tasks', 'reliable-execution']
307
+ ),
308
+ 'si:trae': taxonomy(
309
+ 'coding-agents-dev-environments',
310
+ ['agentic-ide', 'coding-agent', 'developer-environment'],
311
+ ['ai-coding', 'developer-workspace', 'code-assistant']
312
+ ),
313
+ 'si:vercel-eve': taxonomy(
314
+ 'agent-infrastructure-runtime',
315
+ ['agent-runtime', 'web-agent', 'deployment-platform'],
316
+ ['ai-agent', 'vercel-platform', 'web-runtime']
317
+ ),
318
+ 'si:x-ai': taxonomy(
319
+ 'model-platforms-ai-labs',
320
+ ['foundation-model', 'grok', 'ai-lab'],
321
+ ['model-provider', 'llm', 'xai']
322
+ ),
323
+ 'si:xiaomi-mimo': taxonomy(
324
+ 'model-platforms-ai-labs',
325
+ ['foundation-model', 'edge-ai', 'ai-lab'],
326
+ ['model-provider', 'mobile-ai', 'xiaomi-ai']
327
+ ),
328
+ 'si:z-ai': taxonomy(
329
+ 'model-platforms-ai-labs',
330
+ ['foundation-model', 'open-model', 'ai-lab'],
331
+ ['model-provider', 'llm', 'zai']
332
+ ),
333
+ });
334
+
335
+ function uniqueStrings(values) {
336
+ const seen = new Set();
337
+ const normalized = [];
338
+ for (const value of values || []) {
339
+ if (typeof value !== 'string') continue;
340
+ const trimmed = value.trim();
341
+ if (!trimmed || seen.has(trimmed)) continue;
342
+ seen.add(trimmed);
343
+ normalized.push(trimmed);
344
+ }
345
+ return normalized;
346
+ }
347
+
348
+ function normalizeSupericonsIconId(iconId) {
349
+ const value = String(iconId || '').trim();
350
+ if (!value) return '';
351
+ return value.includes(':') ? value : `si:${value}`;
352
+ }
353
+
354
+ export function getSupericonsAiCategoryLabel(categoryId) {
355
+ return CATEGORY_LABEL_BY_ID.get(categoryId) || null;
356
+ }
357
+
358
+ export function getSupericonsAiTaxonomy(iconId) {
359
+ return SUPERICONS_AI_ICON_TAXONOMY[normalizeSupericonsIconId(iconId)] || null;
360
+ }
361
+
362
+ export function getSupericonsAiMetadata(iconId) {
363
+ const entry = getSupericonsAiTaxonomy(iconId);
364
+ if (!entry) return null;
365
+
366
+ const aiFilterTags = uniqueStrings([
367
+ ...BASE_FILTER_TAGS,
368
+ entry.jobCategory,
369
+ ...entry.secondaryCategories,
370
+ ...entry.aiFilterTags,
371
+ ]);
372
+
373
+ return {
374
+ aiCategory: entry.jobCategory,
375
+ aiCategoryLabel: getSupericonsAiCategoryLabel(entry.jobCategory),
376
+ aiFilterTags,
377
+ jobCategory: entry.jobCategory,
378
+ secondaryCategories: uniqueStrings([...entry.secondaryCategories, ...entry.aiFilterTags]),
379
+ };
380
+ }
381
+
382
+ export function getSupericonsAiRegistryPatch(iconId) {
383
+ const metadata = getSupericonsAiMetadata(iconId);
384
+ if (!metadata) return null;
385
+
386
+ return {
387
+ ai_category: metadata.aiCategory,
388
+ ai_category_label: metadata.aiCategoryLabel,
389
+ ai_filter_tags: metadata.aiFilterTags,
390
+ job_category: metadata.jobCategory,
391
+ secondary_categories: metadata.secondaryCategories,
392
+ };
393
+ }
394
+
395
+ export function buildSupericonsAiTaxonomyEntries() {
396
+ return Object.entries(SUPERICONS_AI_ICON_TAXONOMY).map(([iconId, entry], index) => ({
397
+ iconId,
398
+ sourceLibrary: 'si',
399
+ jobCategory: entry.jobCategory,
400
+ secondaryCategories: uniqueStrings([...entry.secondaryCategories, ...entry.aiFilterTags]),
401
+ rank: 1000 + index,
402
+ }));
403
+ }