Fixes #250 - All SDKs Validate Session Config Model#378
Fixes #250 - All SDKs Validate Session Config Model#378john-mckillip wants to merge 12 commits intogithub:mainfrom
Conversation
Validate that SessionConfig.Model is a valid model name before creating a session. When an invalid model is specified, throw an ArgumentException with the invalid model name and list of available models. Fixes github#250
There was a problem hiding this comment.
Pull request overview
This PR adds model validation to the .NET SDK's CreateSessionAsync method to ensure that only valid model IDs are used when creating sessions. The implementation throws an ArgumentException with a helpful error message listing available models when an invalid model is specified.
Changes:
- Added validation logic in
Client.csto verify the model ID exists in the list of available models before creating a session - Updated existing test to use a valid model name (
claude-sonnet-4.5) instead of a placeholder - Added new test to verify that invalid model names trigger an
ArgumentExceptionwith appropriate error details
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| dotnet/src/Client.cs | Implements model validation by checking the provided model against available models and throwing ArgumentException if invalid |
| dotnet/test/SessionTests.cs | Updates test with valid model name and adds new test case for invalid model validation |
…larifying the minimal performance overhead
Validate that the model specified in SessionConfig exists in the list of available models before creating a session. Raises ValueError with the invalid model name and available alternatives. Uses list_models() which caches results after the first call, so validation adds minimal overhead. Fixes github#250
Validate that the specified model exists in the available models list when creating a new session. This brings the Go SDK in line with the Python and .NET implementations. Changes: - Add model validation in Client.CreateSession that checks against ListModels output using case-insensitive comparison - Return descriptive error listing available models on validation failure - Add TestClient_CreateSession_WithInvalidModel unit test - Refactor to use strings.ToLower and strings.Join directly for performance - Reuse cached model list from ListModels to minimize overhead The validation ensures users receive immediate feedback if they specify an invalid model name, rather than encountering errors later in the session lifecycle.
Validate that the specified model exists in the available models list when creating a new session. This brings the Node.js SDK in line with the Python, .NET, and Go implementations. Changes: - Add model validation in CopilotClient.createSession that checks against listModels output using case-insensitive comparison - Throw descriptive error listing available models on validation failure - Add unit test "throws error when creating session with invalid model" in client.test.ts - Optimize performance using Array.some() for short-circuit search and single lowercase conversion of input model - Reuse cached model list from listModels() to minimize overhead The validation ensures users receive immediate feedback if they specify an invalid model name, rather than encountering errors later in the session lifecycle.
Replace HashSet-based model validation with a more idiomatic LINQ Any() expression using case-insensitive string comparison. This improves readability and aligns with other SDK implementations. - Remove intermediate HashSet creation and validModelIds variable - Use string.Equals with StringComparison.OrdinalIgnoreCase for consistency - Update error message to use availableModels.Select(m => m.Id) inline
| { | ||
| throw new ArgumentException( | ||
| $"Invalid model '{config.Model}'. Available models: {string.Join(", ", availableModels.Select(m => m.Id))}", | ||
| nameof(config)); |
There was a problem hiding this comment.
The nameof(config) should be nameof(config.Model) since the validation is specifically for the Model property, not the entire config object. This provides more precise error information to the caller.
| nameof(config)); | |
| nameof(config.Model)); |
There was a problem hiding this comment.
Thanks for the review! However, I need to push back on this suggestion. The ArgumentException
constructor's paramName parameter should reference the actual method parameter name, not a
property of that parameter.
According to Microsoft's ArgumentException documentation,
the paramName should be "the name of the parameter that caused the current exception."
In this case:
- The method parameter is
config(of typeSessionConfig?) - There is no parameter named
Modelin the method signature - Using
nameof(config.Model)causes SonarQube warning: "The parameter name 'Model' is not
declared in the argument list"
The error message itself already clearly indicates which property is invalid:
"Invalid model '{config.Model}'. Available models: ..."
This is consistent with standard .NET practices where you reference the parameter, and the
error message provides the specific details about what's wrong with it.
…nAsync in the dotnet SDK client.
|
I'm worried about the interaction between this and BYOK. @jmoseley is this something you can look at? |
|
I agree with @friggeri . We cannot assume that, for the BYOK scenario, Can you help me understand the need here? |
|
The original intent for using listModels was to validate the model being passed when a session is created. The current functionality is a bit confusing because it allows you to pass anything for the model name. I didn't consider BYOK at all. It makes sense that my fix here would not work if that is being used. I apologize if I wasted anyone's time with this PR. |
|
Hello again. Thinking about this more. I could check if the ProviderConfig has a value and ensure that BYOK is not being utilized before calling listModels and validating the session config model that is set. Let the other providers handle the validation on their end. Let me know if that sounds viable! |
|
‰PNG
IHDR ë ë ˆ
aÕ sRGB ®Î é IDATx^í ázÚJ D“÷ èÜ ¤— ¼këà‘í4§ +di4#i ïooo o þ÷ñ±
ïýý½-âÑón ›=“ÄG} ’œù˜ ’ÀŠ>s Kg ¤6 8µ‘ò ã ë ë7”© k ¢Šµ†Óš•b}BG±.éâdÝ/´„
ŪX7y¤X7!:Ä@±*ÖM¢)ÖMˆ 1 Š5Q =¹$ ¶ q¤|Ïü ó0ñ±vaFrêäɨÆG?ï†Eç3ée—b}BìŒF@„F/jè
\±>" X Œ "!¶„|k 'Q´„Ð >œ¬KVtr*ÅA'«“•rénŸh`d <úy®Á“ê ÎFl) Ïðí \›tŠuð¡ˆNPH'
u¶3 •À$±Â&|¸ ךà ž¬”(#aÒ «ßˆ&r$Ó?Ñ4Èó^9Ç“›Ü §Èf’ ÝÍn† :³&€U¬T*×½ $µ$¶û
úûjÒØè¶v† kŠ ßüt “ 0•Z‚È ˜8Y œÑM\ƒ ¬¯6 ÒØ
‰ÆI ˜“•"\°§E(¸¼› ¿k¶ "wbâdu²¾ÌõNb*ÖzY V‰†T ìË’òäGNV
¹ $ NÅAâ£Ï$ùPÂÒXFö Ï$¾‰í- 3Ž„Šõ‰A„Ü ²¾²~’ç’|(aI ´!‘¸ ¾iîŠu€z¢h¤˜
Ï£äî$ÄÑSŽÔ`mE$ ['ëä{•:ÅCÞ¼'$IÙ*Ö}H [ŪX ÌT¬Šõ; ¿âÌJHOoèÈûÀÔ÷ˆª
³5³sº$6$RGºJwæ>k9´–еxÁDŠIléJE LˆrFÜdv*VðW7 ¬Äd8º#S18Ykr;ºŽNÖÀ—k'ÄP£Ç_+Òd ñ
1¡HŽ®ÁK uÖŒl7k›–k°kð NÂ:Y—’¥ƒA±*VÅ
…Þ3œ2YéúIìIW'¶$†µ"Ð.HŸ[=ßÓÜÉz|• © h܉{†D}g>f5C“õŒ ¶S ¿D¶~ÒºÓZ {ÅZD‹ ˆ¡
ÂÝL±Ö s²ÖpŠY ‘ [ õX) öThÕã =ÒкïËzýÕNÖ"º´hе ìÄL±. Q¬EN)Ö:yŠ
®š)Ö:ÞÿÔ¯ÈÑÂw qÌÖ¸ßì;ÕHIÝ
)åC±>!™ Äo Tg“IÔæ ŸbMµ '? Ø„H „HÄÑIúŸê;Q ÅÚ$T
lB$ B$âø©‚êŒ;Q Ê©Fjc×®Á®Áw ®Þd ëàOä°ä _à ü îÕ ådí ÃûGâÏ!úâ z>ú½Í gi§ 5ò
õÜST MšÖ! ãÑ~ káBK±ÞNKÇþS¬K¼ «b}ùÌÚ)_ŪX7ùEWØ‘CꃜD\ƒ7K¸Ù|ê ®eédu²n’»³A ó&
ƒ4ÁkÉr
+ «kê$â¸Å–XµHŽg ‚`•"7yf ºÉt>sä;…‡b}B7 lŠô R‘|Rq“g&rT¬ E ÀvM?'ë²ÀеÞ: V
ÝÜ"s²:Y7Ϭu
Y¦ÈY}. U¿kvŠu€Ž“u µˆp ×¢"ÏÜ—Ý׫ «kðË<J‘þå ¾½ ' 7yf"Ç_-ÖÄ ¦ Ká “Ÿ âÚ)
KB˜ä¶•Ä—àüÚ”OÄ=<³& '@ýä•J±vI°î—ò5"œÀO”Ò¸ ëSåÈ”›uR:ÍÈ3i ¤±Ô%2?+
[JzÅZ$=-N'ÙF± á(Ö ZÎ {ÅZ¼™½™ À¢ `VEÅúˆ ŵ ? K‹R_ø '«“õŽ ™æT 4 "( ñMl ¬`²
`;'è ä![E'©h
ŽÆŠæNšL" Å›ØÏb‰\0‘@ ë B6B⵺ gvÖ—l ³8 ¹(VPå E ! š:YkˆQ1
$êNã«eýš•“õ5Ü6_¥X7!š6µÛ 8Y—ø)Ö §°•bAF'—“u âÑ· R`kåZ·"Åé<»Ð\ k
1Ê)‡_³ ß6‘ Ü×_Y "¦¤ =“ û ˆäClgçõ*—þ·#B£¸v®Ø$–D
Ÿx+ÖGzQÂ*V*ÏG{ÅZÇO±>a¥X—äIM† - «b}@ Aˆ„
zY¾,É3g¾Ió!¶®Áõ/>O5;'«“õŽ€bíÙ*bbMüÖMâF”N ½+Uâytº$&å q§žytÍHó! Fk[ ñCEŒ¾0
¬Z4 !Î C¢8‰Ü© 7õMì;k¦X •p²ÖèÙIÌZ ë#b Ä0¢>œ¬”åÅ3îÑ+ Mƒ’“ú¯Úw60'«“õ
BúNbVÅñ¿ ‰›ú&ö ˜(VŪX‰ 7l ë Y“‰¬Á¤v¤Û‘ µ :⇒§ó¼Nb¡¸^e² îÌl N7
¤f„;¯ppä_±îÜ HÑèÅA‚„е.{ÅZÄŠ’Štž«tXÅZ$CÈì*uw² ***@***.***Å RaÑ b- EÍœ¬uÄ )®žY
ë@°ž {_ dsô‚é DÑœ¬õ†”°ì¬ ¹«h ëèïYSd %Úéû* 5 ò$rY› G׆bB&N‚S4>²™Ðø¦öŠõ‘
‰uòŒÂÓ X{Öà ®Šµ¸o)Ö%PdФ6 'ë NV'ëÿ ÐuØÿ>Íè¶¡X ë&¿œ¬NÖM’¬ü Öákp%Ø-›D' ]
tN€¼žÿ ] ;ó!¾‰íÚ´$ï_ÓæHëSµ§5«úMm ŸZ ßnxJ€ƒ_˜¦¤"qS[ÅZ›Ä´f©f_§b"µb—èÒ 0¦.
«bÝâWªñ8Y· Þø ŪX·(¤X u®2³‚(VŪXÿ à ¼E…õÿ'gEbë S½.§LÖÔCGi’©x•8èM Éqæ›Þž
{bûy;9¸ü£˜Ì(O°¢|H òL’Ëj $·Á$Àzßù²$ ]% JL’£bÝÿ ÷¤ ¤¶Š½ƒH±‚Α !ÉZhä<œ ”Ô
”¡µy;YI%v^ 9Y— *Ö: k «¡%™hŠU±~G€òA±*ÖM HCòÌê™õ™P‘ E
³ÕŒÑ¤;RÒoªè›Á•ÖÉDÜäüLs'ñ%êNŸGÎÔĶûBt ‹b}b %,iTÔ7!'iv3²uƧXëÕT¬E¬(a k ؉
m2äidZ ['ëÇG¹ ®Áõ &×à Vе,?öM еFÀ5ø 7¢ ¼SS'ë ×à"³\ƒëä)Bºj¦Xëx ¿781¹(é
4nrÞ$Ĥ¹ {Jn²Þ%ð#k÷Í–äCré>W >¤pU¬O¨S`GE#â[#,YU "¡¹w
m” b N‹– ¬“µ¶ ¬M—ÄVAb¡BS¬ >|(Ö TÎhTd (Ö¾OA¹ ä¤BKL—ÄV¡XkÔ§Ó™ð ð¬ í_+
Çê±h4Y;Ï? PhÑH>D8© Rü ~³‰{Fî©|ö®ÍTPg ÛÐ¯È ‘ [BVºÚù& 8‰| „H‘û*¹§òQ¬Å›R²N&Š“
Ε¦ iV ü®”{* ŪXï $ „“u))ÅZoÕ®ÁOX qn«—‹}ˆà' k½úŠU±Þ 8£Q)V Vò“ äVµ
ºe¢˜d…¥«*9¯'n )®4Ÿ‘ÿN “|H ×." 9’¸Su þñ9 H‚ ©„޾hP¬Ç C ëÛÛâ I
k½o*VÅZgË£%Ö™kð#€tKP¬ŠU±þA€v ×à}Í'qžKÔlo =³NZ F¤ %
OÎ:4 '«“•ðù»-å6ú{V✠d-Y" zkI@&¾ NgåNb$5 … žœá#ñÌ V3ߊµ¨XÅZ jbFð»¹H4“N
ŠuPhÒÕ)! ýˆoB 'ëøoN † áP ÔžpÍÉJÐ Ø*Ö} üœ¬ã æ \ä ! ™
NV'ë3 œ¬EQ&.H ký†8±Nžá#ñÌÈ ÓN^ ¾œœ5מ— ~" ***@***.*** ùOøHr³Š9ÅujO¾Ö¥ \ "
Ú©H>$ J*ÅZ« ŵ“ µˆ¿¬ +@+! ÅZ œ|P¤ WÅZ¬YB ôV°³8 ¤JaU,ÍÔŒN r¾OLÅ„ äÖWÅ›âê
\Evb§Xë :Y ±º”XÉd ¤§“’úøK`ݲ3÷TŒÄO—àI k¶‰)Oy‚¾Ö…ŠgdOI5ò‘ Š®C$nZ„
H|4÷D|Ô‡b]"¦X‹,"bP¬EPWÌ «b}@€ˆJ±î ñ X «býƒ iTDd)[ŪX «b ô“Ľ m˜‘3kâ ˆ
NVÒŸp™’`Oêí £k™È}æƒò¤+wZ›éEîÑ 7L N‹@ A'y:}S\ †tŠ\ o’ãT ï쯂F¹ÓÚ(ÖN¥\À7%
!²b] ˜àMlרä | ¡%B „P¬5Ô ŠÖÆÉZ«Í µ¢„P¬µR+Ö NäœCˆæ ;su]²Ô¤‘µ¢<éÊ
6R4Yi7ÉBüè-q`O äH ÏÍ/‰ ú&q“8ˆßnÛ &4w¢ b‹Ï¬)ç‰")Öíæ•À™6 Ô3 ~ ë EÚ}º
A׊£ã¦ä!ñQߤ $ â·Û6 Í 4bëdýXüP^+ (y Q¨o’(‰ƒøí¶M`Bs' $¶ŠU±–ôB [rz€‘bu
~™f”<D$Ô7I‚ÄAüvÛ&0¡¹“iIlW'k×ï³Òs%)(õM 1Š… NlIÞ7ÛNß ±PA j–Ê
\ZRLˆ=Íçö&\Ë/ŸSA‘$©oÅJÐÛ ²)Ö%® ¿ÏFXkä$À ÛÚÓÿZuúîŒE±*Ö :‰L| ÛN PßÔžä©X
***@***.***ÕW¬ }ö¤Ùá5˜vÇQ*”Tä™ô,›ˆ ” gð·”)ü¨Ÿ½—n §Ÿ`Kk™È Y‰pfÁQ’ g*Öý« !Õ
„%ñuÚž‘»b}ª(m&„ ´À‰· è3;ó!¾¯nÛ‰ë,wŪX_ÖÅ „}9Øð ÏÈ]±*Ö—i| a_ 6üÂ3rW¬Šõe ŸAØ—ƒ
¿ðŒÜ#b%ç<raD/©(€äLH}“ÛÓ H
nÏ#¹Óø 5&Ïü×rŸ^”’O0]…°ôÖ—Ø Û ¡ Q:ILâP¬Ë¯º¡øM/ &_]šh>NÖâ |•FE·
Bª+ 6A»“uP9²
*Öº|:7ˆQ ´É º×³þ²Lä®X ë W', ‰b-’ûŒs[ê\I ëdË'1]êOc÷ ?Ἆ&+
Šž¡(éIái‡íº±íl&´64 ²f’ÚPžÐ<I- OÎÈqöÌá S (J jOHEòé,Ng£¢b y&jCã#5# IWÚ iÜŠõ
1BbJ@źDŒL9*`Š7™Î$ 𣓵ˆ®b ª «b¹VÍ k Eº:Q{×àZ!:qU¬ûj Yƒi Gö‰Bv¯™‰µ‡¬8´Ó“Ûê
mÖR5ëâC‚— œÖ| ša>t}Ü0Ux2AiòŠõ TÍ ë#®©&ÓöqÃTá kð‰‰‘ª™bÕŒ źó6Ø5¸v!•h ©
•hlä¼™Š[±*Ö; AÝœ9Y ¬w R Ê3«gÖô”½Ì IŒîãd ·Ä q§¦ 9›wæC Xç ‘#ñA
@Â7å<ZƒI€Š• 5¶%b …'¾ µLø 9’
(Ö Z„$·—“ÉE}'¦ ‰ gvö£> "¹Š Å ø ¹ é …P¬K ¯"´D ŽÐ#T¢ S^¢Ï S犕λšýUê
Z‡bu²>p€’*Ñyi·¯IýËŠæÓÕx q(V V x'‰ Y×lÉû ä "1 )1 Ï$õ¥ à'ð!Á« §¦µÿ‰Ÿ
N€:»ÀI 6! Åšªò±~ k Þ `É›à‰4h3!Ϥ¾‰½“uY ÚÔÑû¬ÿZq ë# H}]ƒÇm0Á)×à ` ¬µ‰ádá´¶
9YŸÐIL ºÞt®ª ¾ VŠ5 Ö Nf ¦ ÛTá ©'&k‚ôä¶
@ýiJ}ÿD\)&gÔì]±Ò2mŸó(YÏ(<ÉZ±.Ñ:£fŠ•°v`ëdÝ¿Þ Jp4®” еˆ˜kp] ***@***.***‡t]½Â ý
¯b76 R b»V³¶oä'‰¯Ùv jvqBÉÝ ß :åfØv½m••ä>Ë‘ˆ„ØÒ&Hk6µ }Ü0%´„ŸN1 Â
ÒÓ¼Iƒ …'q§ ›ÀU± 6JÅú
ÎlŠ(Ö WŪX HL€ÎÉO ***@***.***§Óœø& bM6 bë <© -Põ (u¶êŒO±>"@±& $¶ŠU±–† ržY— ÉŸÀ›ú@
L´ƒ•X¶aD; y&ñý¯“ µ¤X‘šuÚ&0!¹ÓçÍ|£ òw H Eã ¾I è* è°‰ø(~3{ Kê¹{ýPñ £ 9ºP\ ë
b”€ + ñMÖݽdÿÿõ «Ôs÷úQ¬; $Ó >Šø¦ $‚r²ÒÊõØ+Ö ¸ AÑG ߊµŽ.Ūî¹×R±îÄ— Š>Šø¦
t²Òjœoÿ+ÄJ‰L ÛG ê Ûè™tUí¤ ! ÍѾ;㣠5W© ]0QÀ +-Ç£ýÑ‚J‘žl c ¾Ò
’šQߊõ 1'ë’B”ôŠ•Ê°f¯X ë&S ë&Dw 'ë V òxf]þeŒkp]” ëû´ ‰ŸÏ
)Ò5³s¥ò‚©V¹DsLø¨Eû׊>“ú'w2 ß¿b
NtÁÄmubE:ƒ€”hGçI ©ûl[£øýêɪXSt©ùQ¬5œ¨•“µˆ é°Ä¶øø»™“u‰˜“uÀ¢
Q(°‰3«“•¶„}öNÖ}ø¹ ¤"Ó’ØÒ²& &}&µ'¸N‰ù~[újÿè ðÌZÃ5ò»)T Ô¾˜Ê§YâF™
ûè\Ö°Hˆ„l=´QuâJê ŠûŸ:³Rò b’ Ð ! i:³Æ£XÇïG“:(V°Ö ` W¬õ ÖÉ
.Ìþ¥ EtŠÄÉ
H Î›Š àªXé,}´÷ÌºÄ ®}Õ ê— sèöEìSq{fݧU/˜ øQr*ÖG ¦ "™¬;y½úrÒ©h
¾i,{íi.D8©cD×¶Ar¡8“)üÊe ‰G±‚ ) ìÑ¶Šµ qÅ
p¥$ ®§¿QJ DžÙeKq"ÓÈÉZ¯ ÁµîõËÒÉêdÝäŒbÝ„èn X› E§Q½dÇ[Ò\ © k½ž ׺W'«kp‘-е
Ôäc¦õW¯[¢58õЄ r®¼ÒÔ!¹ ‘ [ ÃêYiò!‡DmhŒ#{ ÇíõgLÅDžÃ÷Y ŽS>H!
ë>Ôi#HÔf_ÄëkãÌ·bM ¾ó̪X÷ A±îÃom;ÙïùíÍÉZD‘ ¹èöÓŒø&¶$
%敦ٕb!5R¬E´®"’«Ä¡XÇÄ!Gƒ"õîfеˆØUDr•8 ëñbý ó¿m4 zQ IEND®B`‚
…On Thu, Feb 5, 2026 at 5:58 PM Copilot ***@***.***> wrote:
***@***.**** commented on this pull request.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and
generated 2 comments.
------------------------------
In go/client_test.go
<#378 (comment)>:
> +// contains checks if a string contains a substring (case-insensitive)
+func contains(s, substr string) bool {
+ return strings.Contains(strings.ToLower(s), strings.ToLower(substr))
+}
The function name contains conflicts with an existing function defined
elsewhere in the codebase (see context excerpt). This newly introduced
helper should be renamed to avoid confusion, such as containsIgnoreCase
or containsCaseInsensitive to clearly indicate its case-insensitive
behavior.
------------------------------
In nodejs/test/client.test.ts
<#378 (comment)>:
> + await expect(
+ client.createSession({ model: "INVALID_MODEL_THAT_DOES_NOT_EXIST" })
+ ).rejects.toThrow(/Invalid model/);
+
+ await expect(
+ client.createSession({ model: "INVALID_MODEL_THAT_DOES_NOT_EXIST" })
+ ).rejects.toThrow(/INVALID_MODEL_THAT_DOES_NOT_EXIST/);
The test makes two identical calls to createSession with the same invalid
model. Since model validation happens synchronously before any session
creation, the second call is redundant. Consider combining both assertions
into a single expect call that checks the error message contains both
'Invalid model' and the invalid model name.
—
Reply to this email directly, view it on GitHub
<#378 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/B3I5BLYWMQW5BH2YMZXHIML4KPRMTAVCNFSM6AAAAACUBFMPLKVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTONRQGE3DKMBQHA>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
This pull request introduces model validation when creating a session in the Copilot SDK clients across all supported languages (Node.js, Python, Go, and .NET). Now, if a user attempts to create a session with a model name that does not exist, a clear and descriptive error is thrown, listing available models. Additionally, comprehensive tests have been added to ensure this validation works as intended. Some test cases have also been updated to use a real model name instead of a placeholder.
Model validation and error handling improvements:
nodejs,python,go,dotnet) now validate themodelparameter increateSession/CreateSessionAsync/CreateSessionmethods. If an invalid model is specified, an informative error is thrown, listing available models. [1] [2] [3] [4]Testing enhancements:
Test updates for valid model usage:
"claude-sonnet-4.5"instead of the placeholder"fake-test-model". [1] [2] [3] [4] [5]Utility improvements (Go SDK):
containsfor case-insensitive substring checks in Go tests.These changes improve the robustness and user experience of the Copilot SDKs by ensuring that only valid models can be used when creating sessions and by providing clear feedback when an invalid model is specified.