@@ -800,42 +800,100 @@ export async function promptSkills(project) {
800800
801801// Known model fingerprints -- maps regex patterns to canonical model info.
802802// This allows recognizing models even through custom providers (e.g. Bedrock, Azure).
803+ // Families sourced from https://models.dev (anomalyco/models.dev)
803804const MODEL_FINGERPRINTS = [
804- // Anthropic
805- { pattern : / c l a u d e .* o p u s .* 4 / i, canonical : 'claude-opus-4' , family : 'anthropic' , tier : 'frontier' , coding : 95 , cost : 'high' } ,
806- { pattern : / c l a u d e .* s o n n e t .* 4 / i, canonical : 'claude-sonnet-4' , family : 'anthropic' , tier : 'strong' , coding : 90 , cost : 'medium' } ,
807- { pattern : / c l a u d e .* h a i k u .* 4 / i, canonical : 'claude-haiku-4' , family : 'anthropic' , tier : 'fast' , coding : 75 , cost : 'low' } ,
808- { pattern : / c l a u d e .* o p u s .* 3 / i, canonical : 'claude-opus-3' , family : 'anthropic' , tier : 'strong' , coding : 80 , cost : 'high' } ,
809- { pattern : / c l a u d e .* s o n n e t .* 3 / i, canonical : 'claude-sonnet-3' , family : 'anthropic' , tier : 'strong' , coding : 78 , cost : 'medium' } ,
810- { pattern : / c l a u d e .* h a i k u .* 3 / i, canonical : 'claude-haiku-3' , family : 'anthropic' , tier : 'fast' , coding : 60 , cost : 'low' } ,
811- // OpenAI -- order matters: most specific patterns first
812- { pattern : / g p t .* 5 \. ? 3 .* c o d e x / i, canonical : 'gpt-5.3-codex' , family : 'openai' , tier : 'frontier' , coding : 96 , cost : 'very-high' } ,
813- { pattern : / g p t .* 5 \. ? 3 .* c h a t / i, canonical : 'gpt-5.3-chat' , family : 'openai' , tier : 'frontier' , coding : 94 , cost : 'high' } ,
814- { pattern : / g p t .* 5 \. ? 3 / i, canonical : 'gpt-5.3' , family : 'openai' , tier : 'frontier' , coding : 94 , cost : 'high' } ,
815- { pattern : / g p t .* 5 \. ? 2 / i, canonical : 'gpt-5.2' , family : 'openai' , tier : 'frontier' , coding : 93 , cost : 'high' } ,
816- { pattern : / g p t .* 5 \. ? 1 .* c o d e x / i, canonical : 'gpt-5.1-codex' , family : 'openai' , tier : 'strong' , coding : 88 , cost : 'medium' } ,
817- { pattern : / g p t .* 5 \. ? 1 / i, canonical : 'gpt-5.1' , family : 'openai' , tier : 'strong' , coding : 85 , cost : 'medium' } ,
818- { pattern : / g p t .* 5 / i, canonical : 'gpt-5' , family : 'openai' , tier : 'strong' , coding : 85 , cost : 'medium' } ,
819- { pattern : / g p t .* 4 o [ \b - ] / i, canonical : 'gpt-4o' , family : 'openai' , tier : 'strong' , coding : 80 , cost : 'medium' } ,
820- { pattern : / g p t .* 4 o .* m i n i / i, canonical : 'gpt-4o-mini' , family : 'openai' , tier : 'fast' , coding : 65 , cost : 'low' } ,
821- { pattern : / o 3 / i, canonical : 'o3' , family : 'openai' , tier : 'frontier' , coding : 96 , cost : 'very-high' } ,
822- { pattern : / o 4 .* m i n i / i, canonical : 'o4-mini' , family : 'openai' , tier : 'strong' , coding : 88 , cost : 'medium' } ,
823- // Google
824- { pattern : / g e m i n i .* 3 .* p r o / i, canonical : 'gemini-3-pro' , family : 'google' , tier : 'strong' , coding : 82 , cost : 'medium' } ,
825- { pattern : / g e m i n i .* 2 \. ? 5 .* p r o / i, canonical : 'gemini-2.5-pro' , family : 'google' , tier : 'strong' , coding : 80 , cost : 'medium' } ,
826- { pattern : / g e m i n i .* 2 \. ? 5 .* f l a s h / i, canonical : 'gemini-2.5-flash' , family : 'google' , tier : 'fast' , coding : 72 , cost : 'low' } ,
827- { pattern : / g e m i n i .* 2 .* f l a s h / i, canonical : 'gemini-2-flash' , family : 'google' , tier : 'fast' , coding : 68 , cost : 'low' } ,
828- // DeepSeek
829- { pattern : / d e e p s e e k .* v 3 / i, canonical : 'deepseek-v3' , family : 'deepseek' , tier : 'strong' , coding : 82 , cost : 'low' } ,
830- { pattern : / d e e p s e e k .* r 1 / i, canonical : 'deepseek-r1' , family : 'deepseek' , tier : 'strong' , coding : 85 , cost : 'low' } ,
831- // Meta
832- { pattern : / l l a m a .* 4 .* m a v e r i c k / i, canonical : 'llama-4-maverick' , family : 'meta' , tier : 'strong' , coding : 78 , cost : 'low' } ,
833- { pattern : / l l a m a .* 4 .* s c o u t / i, canonical : 'llama-4-scout' , family : 'meta' , tier : 'fast' , coding : 70 , cost : 'very-low' } ,
834- { pattern : / l l a m a .* 3 .* 4 0 5 / i, canonical : 'llama-3-405b' , family : 'meta' , tier : 'strong' , coding : 75 , cost : 'low' } ,
835- { pattern : / l l a m a .* 3 .* 7 0 / i, canonical : 'llama-3-70b' , family : 'meta' , tier : 'fast' , coding : 65 , cost : 'very-low' } ,
836- // Mistral
837- { pattern : / m i s t r a l .* l a r g e / i, canonical : 'mistral-large' , family : 'mistral' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
838- { pattern : / c o d e s t r a l / i, canonical : 'codestral' , family : 'mistral' , tier : 'strong' , coding : 78 , cost : 'low' } ,
805+ // ── Anthropic ─────────────────────────────────────────────────────────────
806+ { pattern : / c l a u d e .* o p u s .* 4 / i, canonical : 'claude-opus-4' , family : 'anthropic' , tier : 'frontier' , coding : 95 , cost : 'high' } ,
807+ { pattern : / c l a u d e .* s o n n e t .* 4 / i, canonical : 'claude-sonnet-4' , family : 'anthropic' , tier : 'strong' , coding : 90 , cost : 'medium' } ,
808+ { pattern : / c l a u d e .* h a i k u .* 4 / i, canonical : 'claude-haiku-4' , family : 'anthropic' , tier : 'fast' , coding : 75 , cost : 'low' } ,
809+ { pattern : / c l a u d e .* o p u s .* 3 / i, canonical : 'claude-opus-3' , family : 'anthropic' , tier : 'strong' , coding : 80 , cost : 'high' } ,
810+ { pattern : / c l a u d e .* s o n n e t .* 3 / i, canonical : 'claude-sonnet-3' , family : 'anthropic' , tier : 'strong' , coding : 78 , cost : 'medium' } ,
811+ { pattern : / c l a u d e .* h a i k u .* 3 / i, canonical : 'claude-haiku-3' , family : 'anthropic' , tier : 'fast' , coding : 60 , cost : 'low' } ,
812+ // ── OpenAI (most specific first) ──────────────────────────────────────────
813+ { pattern : / g p t .* 5 \. ? 3 .* c o d e x / i, canonical : 'gpt-5.3-codex' , family : 'openai' , tier : 'frontier' , coding : 96 , cost : 'very-high' } ,
814+ { pattern : / g p t .* 5 \. ? 3 .* c h a t / i, canonical : 'gpt-5.3-chat' , family : 'openai' , tier : 'frontier' , coding : 94 , cost : 'high' } ,
815+ { pattern : / g p t .* 5 \. ? 3 / i, canonical : 'gpt-5.3' , family : 'openai' , tier : 'frontier' , coding : 94 , cost : 'high' } ,
816+ { pattern : / g p t .* 5 \. ? 2 / i, canonical : 'gpt-5.2' , family : 'openai' , tier : 'frontier' , coding : 93 , cost : 'high' } ,
817+ { pattern : / g p t .* 5 \. ? 1 .* c o d e x / i, canonical : 'gpt-5.1-codex' , family : 'openai' , tier : 'strong' , coding : 88 , cost : 'medium' } ,
818+ { pattern : / g p t .* 5 \. ? 1 / i, canonical : 'gpt-5.1' , family : 'openai' , tier : 'strong' , coding : 85 , cost : 'medium' } ,
819+ { pattern : / g p t .* 5 .* c o d e x / i, canonical : 'gpt-5-codex' , family : 'openai' , tier : 'strong' , coding : 86 , cost : 'medium' } ,
820+ { pattern : / g p t .* 5 .* m i n i / i, canonical : 'gpt-5-mini' , family : 'openai' , tier : 'fast' , coding : 72 , cost : 'low' } ,
821+ { pattern : / g p t .* 5 / i, canonical : 'gpt-5' , family : 'openai' , tier : 'strong' , coding : 85 , cost : 'medium' } ,
822+ { pattern : / g p t .* 4 \. ? 1 .* n a n o / i, canonical : 'gpt-4.1-nano' , family : 'openai' , tier : 'fast' , coding : 60 , cost : 'very-low' } ,
823+ { pattern : / g p t .* 4 \. ? 1 .* m i n i / i, canonical : 'gpt-4.1-mini' , family : 'openai' , tier : 'fast' , coding : 68 , cost : 'low' } ,
824+ { pattern : / g p t .* 4 \. ? 1 / i, canonical : 'gpt-4.1' , family : 'openai' , tier : 'strong' , coding : 82 , cost : 'medium' } ,
825+ { pattern : / g p t .* 4 o .* m i n i / i, canonical : 'gpt-4o-mini' , family : 'openai' , tier : 'fast' , coding : 65 , cost : 'low' } ,
826+ { pattern : / g p t .* 4 o / i, canonical : 'gpt-4o' , family : 'openai' , tier : 'strong' , coding : 80 , cost : 'medium' } ,
827+ { pattern : / g p t .* 4 .* t u r b o / i, canonical : 'gpt-4-turbo' , family : 'openai' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
828+ { pattern : / c o d e x .* m i n i / i, canonical : 'codex-mini' , family : 'openai' , tier : 'fast' , coding : 70 , cost : 'low' } ,
829+ { pattern : / o 4 .* m i n i / i, canonical : 'o4-mini' , family : 'openai' , tier : 'strong' , coding : 88 , cost : 'medium' } ,
830+ { pattern : / o 3 [ \b \- ] | ^ o 3 $ / i, canonical : 'o3' , family : 'openai' , tier : 'frontier' , coding : 96 , cost : 'very-high' } ,
831+ // ── Google ────────────────────────────────────────────────────────────────
832+ { pattern : / g e m i n i .* 3 .* p r o / i, canonical : 'gemini-3-pro' , family : 'google' , tier : 'strong' , coding : 82 , cost : 'medium' } ,
833+ { pattern : / g e m i n i .* 2 \. ? 5 .* p r o / i, canonical : 'gemini-2.5-pro' , family : 'google' , tier : 'strong' , coding : 80 , cost : 'medium' } ,
834+ { pattern : / g e m i n i .* 2 \. ? 5 .* f l a s h .* l i t e / i, canonical : 'gemini-2.5-flash-lite' , family : 'google' , tier : 'fast' , coding : 62 , cost : 'very-low' } ,
835+ { pattern : / g e m i n i .* 2 \. ? 5 .* f l a s h / i, canonical : 'gemini-2.5-flash' , family : 'google' , tier : 'fast' , coding : 72 , cost : 'low' } ,
836+ { pattern : / g e m i n i .* 2 .* f l a s h .* l i t e / i, canonical : 'gemini-2-flash-lite' , family : 'google' , tier : 'fast' , coding : 58 , cost : 'very-low' } ,
837+ { pattern : / g e m i n i .* 2 .* f l a s h / i, canonical : 'gemini-2-flash' , family : 'google' , tier : 'fast' , coding : 68 , cost : 'low' } ,
838+ { pattern : / g e m i n i .* 1 \. ? 5 .* p r o / i, canonical : 'gemini-1.5-pro' , family : 'google' , tier : 'strong' , coding : 72 , cost : 'medium' } ,
839+ { pattern : / g e m i n i .* 1 \. ? 5 .* f l a s h / i, canonical : 'gemini-1.5-flash' , family : 'google' , tier : 'fast' , coding : 60 , cost : 'low' } ,
840+ // ── DeepSeek ──────────────────────────────────────────────────────────────
841+ { pattern : / d e e p s e e k .* r 1 / i, canonical : 'deepseek-r1' , family : 'deepseek' , tier : 'strong' , coding : 85 , cost : 'low' } ,
842+ { pattern : / d e e p s e e k .* v 3 | d e e p s e e k .* c h a t / i, canonical : 'deepseek-v3' , family : 'deepseek' , tier : 'strong' , coding : 82 , cost : 'low' } ,
843+ // ── Meta / Llama ──────────────────────────────────────────────────────────
844+ { pattern : / l l a m a .* 4 .* m a v e r i c k / i, canonical : 'llama-4-maverick' , family : 'meta' , tier : 'strong' , coding : 78 , cost : 'low' } ,
845+ { pattern : / l l a m a .* 4 .* s c o u t / i, canonical : 'llama-4-scout' , family : 'meta' , tier : 'fast' , coding : 70 , cost : 'very-low' } ,
846+ { pattern : / l l a m a .* 3 .* 4 0 5 / i, canonical : 'llama-3-405b' , family : 'meta' , tier : 'strong' , coding : 75 , cost : 'low' } ,
847+ { pattern : / l l a m a .* 3 .* 7 0 / i, canonical : 'llama-3-70b' , family : 'meta' , tier : 'fast' , coding : 65 , cost : 'very-low' } ,
848+ { pattern : / l l a m a .* 3 .* 8 / i, canonical : 'llama-3-8b' , family : 'meta' , tier : 'fast' , coding : 50 , cost : 'very-low' } ,
849+ // ── Mistral ───────────────────────────────────────────────────────────────
850+ { pattern : / d e v s t r a l .* m e d i u m / i, canonical : 'devstral-medium' , family : 'mistral' , tier : 'strong' , coding : 82 , cost : 'medium' } ,
851+ { pattern : / d e v s t r a l .* s m a l l / i, canonical : 'devstral-small' , family : 'mistral' , tier : 'fast' , coding : 72 , cost : 'low' } ,
852+ { pattern : / d e v s t r a l / i, canonical : 'devstral' , family : 'mistral' , tier : 'strong' , coding : 78 , cost : 'low' } ,
853+ { pattern : / m a g i s t r a l .* m e d i u m / i, canonical : 'magistral-medium' , family : 'mistral' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
854+ { pattern : / m a g i s t r a l .* s m a l l / i, canonical : 'magistral-small' , family : 'mistral' , tier : 'fast' , coding : 65 , cost : 'low' } ,
855+ { pattern : / m i s t r a l .* l a r g e / i, canonical : 'mistral-large' , family : 'mistral' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
856+ { pattern : / c o d e s t r a l / i, canonical : 'codestral' , family : 'mistral' , tier : 'strong' , coding : 78 , cost : 'low' } ,
857+ { pattern : / m i n i s t r a l .* 8 / i, canonical : 'ministral-8b' , family : 'mistral' , tier : 'fast' , coding : 55 , cost : 'very-low' } ,
858+ { pattern : / m i n i s t r a l .* 3 / i, canonical : 'ministral-3b' , family : 'mistral' , tier : 'fast' , coding : 45 , cost : 'very-low' } ,
859+ // ── xAI / Grok ───────────────────────────────────────────────────────────
860+ { pattern : / g r o k .* 4 / i, canonical : 'grok-4' , family : 'xai' , tier : 'frontier' , coding : 92 , cost : 'high' } ,
861+ { pattern : / g r o k .* 3 .* m i n i .* f a s t / i, canonical : 'grok-3-mini-fast' , family : 'xai' , tier : 'fast' , coding : 70 , cost : 'low' } ,
862+ { pattern : / g r o k .* 3 .* m i n i / i, canonical : 'grok-3-mini' , family : 'xai' , tier : 'fast' , coding : 72 , cost : 'low' } ,
863+ { pattern : / g r o k .* 3 .* f a s t / i, canonical : 'grok-3-fast' , family : 'xai' , tier : 'strong' , coding : 82 , cost : 'medium' } ,
864+ { pattern : / g r o k .* 3 / i, canonical : 'grok-3' , family : 'xai' , tier : 'strong' , coding : 85 , cost : 'medium' } ,
865+ { pattern : / g r o k .* 2 / i, canonical : 'grok-2' , family : 'xai' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
866+ // ── Cohere ────────────────────────────────────────────────────────────────
867+ { pattern : / c o m m a n d .* a .* r e a s o n / i, canonical : 'command-a-reasoning' , family : 'cohere' , tier : 'strong' , coding : 78 , cost : 'medium' } ,
868+ { pattern : / c o m m a n d .* a / i, canonical : 'command-a' , family : 'cohere' , tier : 'strong' , coding : 75 , cost : 'medium' } ,
869+ { pattern : / c o m m a n d .* r .* p l u s / i, canonical : 'command-r-plus' , family : 'cohere' , tier : 'strong' , coding : 70 , cost : 'medium' } ,
870+ { pattern : / c o m m a n d .* r 7 b / i, canonical : 'command-r7b' , family : 'cohere' , tier : 'fast' , coding : 55 , cost : 'very-low' } ,
871+ { pattern : / c o m m a n d .* r \b / i, canonical : 'command-r' , family : 'cohere' , tier : 'fast' , coding : 60 , cost : 'low' } ,
872+ // ── Perplexity ────────────────────────────────────────────────────────────
873+ { pattern : / s o n a r .* d e e p / i, canonical : 'sonar-deep-research' , family : 'perplexity' , tier : 'strong' , coding : 72 , cost : 'medium' } ,
874+ { pattern : / s o n a r .* p r o / i, canonical : 'sonar-pro' , family : 'perplexity' , tier : 'strong' , coding : 68 , cost : 'medium' } ,
875+ { pattern : / s o n a r .* r e a s o n / i, canonical : 'sonar-reasoning' , family : 'perplexity' , tier : 'strong' , coding : 70 , cost : 'medium' } ,
876+ { pattern : / s o n a r / i, canonical : 'sonar' , family : 'perplexity' , tier : 'fast' , coding : 60 , cost : 'low' } ,
877+ // ── Alibaba / Qwen ────────────────────────────────────────────────────────
878+ { pattern : / q w e n .* 3 .* 2 3 5 / i, canonical : 'qwen-3-235b' , family : 'alibaba' , tier : 'strong' , coding : 80 , cost : 'low' } ,
879+ { pattern : / q w e n .* 3 .* 3 2 / i, canonical : 'qwen-3-32b' , family : 'alibaba' , tier : 'fast' , coding : 68 , cost : 'very-low' } ,
880+ { pattern : / q w e n .* 2 \. ? 5 .* c o d e r / i, canonical : 'qwen-2.5-coder' , family : 'alibaba' , tier : 'strong' , coding : 78 , cost : 'low' } ,
881+ { pattern : / q w e n .* c o d e r / i, canonical : 'qwen-coder' , family : 'alibaba' , tier : 'strong' , coding : 75 , cost : 'low' } ,
882+ { pattern : / q w e n / i, canonical : 'qwen' , family : 'alibaba' , tier : 'strong' , coding : 72 , cost : 'low' } ,
883+ // ── MiniMax ───────────────────────────────────────────────────────────────
884+ { pattern : / m i n i m a x / i, canonical : 'minimax' , family : 'minimax' , tier : 'strong' , coding : 70 , cost : 'low' } ,
885+ // ── ZhipuAI / GLM ────────────────────────────────────────────────────────
886+ { pattern : / g l m .* 4 / i, canonical : 'glm-4' , family : 'zhipuai' , tier : 'strong' , coding : 72 , cost : 'low' } ,
887+ // ── Nvidia / Nemotron ─────────────────────────────────────────────────────
888+ { pattern : / n e m o t r o n / i, canonical : 'nemotron' , family : 'nvidia' , tier : 'strong' , coding : 70 , cost : 'low' } ,
889+ // ── Moonshot / Kimi ───────────────────────────────────────────────────────
890+ { pattern : / k i m i | m o o n s h o t / i, canonical : 'kimi' , family : 'moonshot' , tier : 'strong' , coding : 68 , cost : 'low' } ,
891+ // ── Cerebras ──────────────────────────────────────────────────────────────
892+ { pattern : / c e r e b r a s / i, canonical : 'cerebras' , family : 'cerebras' , tier : 'fast' , coding : 65 , cost : 'low' } ,
893+ // ── StepFun ───────────────────────────────────────────────────────────────
894+ { pattern : / s t e p / i, canonical : 'step' , family : 'stepfun' , tier : 'strong' , coding : 65 , cost : 'low' } ,
895+ // ── Inception / Mercury ───────────────────────────────────────────────────
896+ { pattern : / m e r c u r y / i, canonical : 'mercury' , family : 'inception' , tier : 'strong' , coding : 72 , cost : 'low' } ,
839897] ;
840898
841899const COST_LABELS = { 'very-low' : '$' , 'low' : '$$' , 'medium' : '$$$' , 'high' : '$$$$' , 'very-high' : '$$$$$' } ;
0 commit comments