@@ -12,16 +12,14 @@ vi.mock("vscode", () => {
1212 constructor (
1313 public callId : string ,
1414 public name : string ,
15- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16- public input : any ,
15+ public input : object ,
1716 ) { }
1817 }
1918
2019 return {
2120 workspace : {
2221 getConfiguration : vi . fn ( ( ) => ( {
23- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24- get : vi . fn ( ( key : string , defaultValue : any ) => defaultValue ) ,
22+ get : vi . fn ( ( key : string , defaultValue : unknown ) => defaultValue ) ,
2523 } ) ) ,
2624 onDidChangeConfiguration : vi . fn ( ( _callback ) => ( {
2725 dispose : vi . fn ( ) ,
@@ -503,8 +501,7 @@ describe("VsCodeLmHandler", () => {
503501 mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
504502 stream : ( async function * ( ) {
505503 // Yield an unknown chunk type (not TextPart, not ToolCallPart)
506- // eslint-disable-next-line @typescript-eslint/no-explicit-any
507- yield { type : "unknown" , foo : "bar" } as any
504+ yield { type : "unknown" , foo : "bar" } as unknown as vscode . LanguageModelTextPart
508505 return
509506 } ) ( ) ,
510507 text : ( async function * ( ) {
@@ -533,8 +530,7 @@ describe("VsCodeLmHandler", () => {
533530 const consoleWarnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
534531
535532 // Create a TextPart with a non-string value (number)
536- // eslint-disable-next-line @typescript-eslint/no-explicit-any
537- const badTextPart = new vscode . LanguageModelTextPart ( 42 as any )
533+ const badTextPart = new vscode . LanguageModelTextPart ( 42 as unknown as string )
538534 mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
539535 stream : ( async function * ( ) {
540536 yield badTextPart
@@ -566,8 +562,7 @@ describe("VsCodeLmHandler", () => {
566562 const consoleWarnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
567563
568564 // Create a ToolCallPart with a non-string callId
569- // eslint-disable-next-line @typescript-eslint/no-explicit-any
570- const badToolCall = new vscode . LanguageModelToolCallPart ( 123 as any , "valid-name" , { } )
565+ const badToolCall = new vscode . LanguageModelToolCallPart ( 123 as unknown as string , "valid-name" , { } )
571566 mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
572567 stream : ( async function * ( ) {
573568 yield badToolCall
@@ -599,8 +594,11 @@ describe("VsCodeLmHandler", () => {
599594 const consoleWarnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
600595
601596 // Create a ToolCallPart with a string input (not an object)
602- // eslint-disable-next-line @typescript-eslint/no-explicit-any
603- const badToolCall = new vscode . LanguageModelToolCallPart ( "call-1" , "valid-name" , "not-an-object" as any )
597+ const badToolCall = new vscode . LanguageModelToolCallPart (
598+ "call-1" ,
599+ "valid-name" ,
600+ "not-an-object" as unknown as object ,
601+ )
604602 mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
605603 stream : ( async function * ( ) {
606604 yield badToolCall
@@ -632,8 +630,7 @@ describe("VsCodeLmHandler", () => {
632630 const consoleErrorSpy = vi . spyOn ( console , "error" ) . mockImplementation ( ( ) => { } )
633631
634632 // Create a ToolCallPart with circular input that will throw on JSON.stringify
635- // eslint-disable-next-line @typescript-eslint/no-explicit-any
636- const circularInput : any = { name : "circular" }
633+ const circularInput : Record < string , unknown > = { name : "circular" }
637634 circularInput . self = circularInput
638635
639636 const badToolCall = new vscode . LanguageModelToolCallPart ( "call-1" , "valid-name" , circularInput )
@@ -909,8 +906,7 @@ describe("VsCodeLmHandler", () => {
909906 cancel : vi . fn ( ) ,
910907 dispose : vi . fn ( ) ,
911908 }
912- // eslint-disable-next-line @typescript-eslint/no-explicit-any
913- handler [ "currentRequestCancellation" ] = mockCancellation as any
909+ handler [ "currentRequestCancellation" ] = mockCancellation as unknown as vscode . CancellationTokenSource
914910
915911 mockLanguageModelChat . countTokens . mockResolvedValueOnce ( 50 )
916912
@@ -970,8 +966,7 @@ describe("VsCodeLmHandler", () => {
970966 handler [ "currentRequestCancellation" ] = null
971967 const consoleWarnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
972968
973- // eslint-disable-next-line @typescript-eslint/no-explicit-any
974- mockLanguageModelChat . countTokens . mockResolvedValueOnce ( "not-a-number" as any )
969+ mockLanguageModelChat . countTokens . mockResolvedValueOnce ( "not-a-number" as unknown as number )
975970
976971 const content : Anthropic . Messages . ContentBlockParam [ ] = [ { type : "text" , text : "test" } ]
977972 const result = await handler . countTokens ( content )
@@ -1043,4 +1038,40 @@ describe("VsCodeLmHandler", () => {
10431038 await expect ( promise ) . rejects . toThrow ( "VSCode LM completion error: Completion failed" )
10441039 } )
10451040 } )
1041+
1042+ describe ( "cleanMessageContent / deepClean" , ( ) => {
1043+ it ( "passes through string content unchanged" , ( ) => {
1044+ const result = handler [ "cleanMessageContent" ] ( "hello" )
1045+ expect ( result ) . toBe ( "hello" )
1046+ } )
1047+
1048+ it ( "returns falsy values as-is" , ( ) => {
1049+ expect ( handler [ "cleanMessageContent" ] ( "" ) ) . toBe ( "" )
1050+ } )
1051+
1052+ it ( "recursively cleans array content" , ( ) => {
1053+ const input : Anthropic . Messages . MessageParam [ "content" ] = [ { type : "text" , text : "hi" } ]
1054+ const result = handler [ "cleanMessageContent" ] ( input )
1055+ expect ( result ) . toEqual ( [ { type : "text" , text : "hi" } ] )
1056+ } )
1057+
1058+ it ( "recursively cleans nested objects within array items" , ( ) => {
1059+ const input : Anthropic . Messages . MessageParam [ "content" ] = [
1060+ { type : "text" , text : "hello" } ,
1061+ { type : "text" , text : "world" } ,
1062+ ]
1063+ const result = handler [ "cleanMessageContent" ] ( input )
1064+ expect ( result ) . toEqual ( input )
1065+ } )
1066+
1067+ it ( "preserves primitive values other than strings inside objects" , ( ) => {
1068+ // deepClean hits the final `return value` branch for non-string primitives
1069+ // Exercise via a nested object whose property value is a number
1070+ const input = [
1071+ { type : "text" , text : "x" , extra : 42 } ,
1072+ ] as unknown as Anthropic . Messages . MessageParam [ "content" ]
1073+ const result = handler [ "cleanMessageContent" ] ( input ) as unknown as Array < Record < string , unknown > >
1074+ expect ( result [ 0 ] . extra ) . toBe ( 42 )
1075+ } )
1076+ } )
10461077} )
0 commit comments