11import { describe , expect , test } from 'bun:test'
22
3+ import { freebuffLegacyModelDigest } from '../types/freebuff-model-catalog'
34import {
5+ FREEBUFF_DEEPSEEK_V4_FLASH_FAST_MODEL_ID ,
46 FREEBUFF_DEEPSEEK_V4_FLASH_MODEL_ID ,
57 FREEBUFF_GEMINI_38_FLASH_MODEL_ID ,
68 FREEBUFF_GLM_V53_FLASH_MODEL_ID ,
79 FREEBUFF_GPT_6_LUNA_MODEL_ID ,
10+ FREEBUFF_MIMO_V26_PRO_MODEL_ID ,
811 FREEBUFF_MODELS ,
912 FREEBUFF_MUSE_SPARK_MODEL_IDS ,
1013 FREEBUFF_MUSE_SPARK_13_CONTRIBUTOR_MODEL_ID ,
1114 FREEBUFF_SOLAR_PRO_4_MODEL_ID ,
1215 FREEBUFF_WEB_PREMIUM_MODEL_IDS ,
1316} from '../constants/freebuff-models'
1417import {
18+ FREEBUFF_CLAUDE_HAIKU_55_CATALOG_KEY ,
19+ FREEBUFF_CLAUDE_HAIKU_55_MODEL_ID ,
1520 FREEBUFF_DESKTOP_UNCAPPED_TAB_LIMIT ,
1621 freebuffDesktopConcurrencyLimits ,
1722 freebuffDesktopModelTabLimit ,
@@ -49,14 +54,20 @@ describe('Freebuff Desktop session concurrency', () => {
4954
5055 test ( 'classifies models by tier and plan' , ( ) => {
5156 const cases = [
52- [
53- // GPT-6 Luna since 2026-09-22, when it took 5.6's slot-bound entry.
54- `${ FREEBUFF_GPT_6_LUNA_MODEL_ID } -20260922` ,
55- 'full' ,
56- false ,
57- 'slot-bound' ,
58- ] ,
5957 [ FREEBUFF_GEMINI_38_FLASH_MODEL_ID , 'full' , false , 'slot-bound' ] ,
58+ [ `${ FREEBUFF_GEMINI_38_FLASH_MODEL_ID } -20260922` , 'full' , true , 'slot-bound' ] ,
59+ // Claude Haiku 5.5 with full context is slot-bound since 2026-10-14,
60+ // under both of its names; its 100k-context row is not.
61+ [ FREEBUFF_CLAUDE_HAIKU_55_MODEL_ID , 'full' , false , 'slot-bound' ] ,
62+ [ FREEBUFF_CLAUDE_HAIKU_55_MODEL_ID , 'full' , true , 'slot-bound' ] ,
63+ [ FREEBUFF_CLAUDE_HAIKU_55_CATALOG_KEY , 'full' , true , 'slot-bound' ] ,
64+ [ `${ FREEBUFF_CLAUDE_HAIKU_55_MODEL_ID } -100k` , 'full' , true , 'multi-tab' ] ,
65+ // GPT-6 Luna, MiMo 2.6 Pro and DeepSeek Flash fast mode are multi-tab
66+ // since 2026-10-14.
67+ [ `${ FREEBUFF_GPT_6_LUNA_MODEL_ID } -20260922` , 'full' , false , 'multi-tab' ] ,
68+ [ FREEBUFF_MIMO_V26_PRO_MODEL_ID , 'full' , true , 'multi-tab' ] ,
69+ [ FREEBUFF_DEEPSEEK_V4_FLASH_FAST_MODEL_ID , 'full' , false , 'multi-tab' ] ,
70+ [ FREEBUFF_GPT_6_LUNA_MODEL_ID , 'limited' , false , 'slot-bound' ] ,
6071 [ FREEBUFF_GLM_V53_FLASH_MODEL_ID , 'full' , false , 'multi-tab' ] ,
6172 [ FREEBUFF_SOLAR_PRO_4_MODEL_ID , 'full' , false , 'multi-tab' ] ,
6273 [ FREEBUFF_SOLAR_PRO_4_MODEL_ID , 'limited' , false , 'slot-bound' ] ,
@@ -74,14 +85,30 @@ describe('Freebuff Desktop session concurrency', () => {
7485 )
7586 }
7687
88+ // Premium rows are slot-bound unless named multi-tab here, so a new
89+ // premium row takes one tab until someone decides otherwise.
90+ const multiTabPremium = new Set < string > ( [
91+ FREEBUFF_GPT_6_LUNA_MODEL_ID ,
92+ FREEBUFF_MIMO_V26_PRO_MODEL_ID ,
93+ FREEBUFF_DEEPSEEK_V4_FLASH_FAST_MODEL_ID ,
94+ ] )
7795 const desktopModels = new Set < string > ( FREEBUFF_MODELS . map ( ( { id } ) => id ) )
7896 for ( const id of FREEBUFF_WEB_PREMIUM_MODEL_IDS ) {
7997 if ( desktopModels . has ( id ) ) {
80- expect ( getFreebuffDesktopConcurrency ( id , 'full' ) ) . toBe ( 'slot-bound' )
98+ expect ( getFreebuffDesktopConcurrency ( id , 'full' ) ) . toBe (
99+ multiTabPremium . has ( id ) ? 'multi-tab' : 'slot-bound' ,
100+ )
81101 }
82102 }
83103 for ( const id of FREEBUFF_MUSE_SPARK_MODEL_IDS ) {
84104 expect ( getFreebuffDesktopConcurrency ( id , 'full' ) ) . toBe ( 'multi-tab' )
85105 }
86106 } )
107+
108+ test ( "Haiku 5.5's catalog key is the default catalog's key for its id" , ( ) => {
109+ // packages/internal's defaultCatalogKey, which common cannot import.
110+ expect ( FREEBUFF_CLAUDE_HAIKU_55_CATALOG_KEY ) . toBe (
111+ `m-${ freebuffLegacyModelDigest ( `key:${ FREEBUFF_CLAUDE_HAIKU_55_MODEL_ID } ` ) . slice ( 0 , 10 ) } ` ,
112+ )
113+ } )
87114} )
0 commit comments