11// npx vitest run src/api/transform/__tests__/vscode-lm-format.spec.ts
22
33import { Anthropic } from "@anthropic-ai/sdk"
4+ import * as vscode from "vscode"
45
5- import { convertToVsCodeLmMessages , convertToAnthropicRole } from "../vscode-lm-format"
6+ import { convertToVsCodeLmMessages , convertToAnthropicRole , extractTextCountFromMessage } from "../vscode-lm-format"
67
78// Mock crypto using Vitest
89vitest . stubGlobal ( "crypto" , {
@@ -24,8 +25,8 @@ interface MockLanguageModelToolCallPart {
2425
2526interface MockLanguageModelToolResultPart {
2627 type : "tool_result"
27- toolUseId : string
28- parts : MockLanguageModelTextPart [ ]
28+ callId : string
29+ content : MockLanguageModelTextPart [ ]
2930}
3031
3132// Mock vscode namespace
@@ -52,8 +53,8 @@ vitest.mock("vscode", () => {
5253 class MockLanguageModelToolResultPart {
5354 type = "tool_result"
5455 constructor (
55- public toolUseId : string ,
56- public parts : MockLanguageModelTextPart [ ] ,
56+ public callId : string ,
57+ public content : MockLanguageModelTextPart [ ] ,
5758 ) { }
5859 }
5960
@@ -189,3 +190,157 @@ describe("convertToAnthropicRole", () => {
189190 expect ( result ) . toBeNull ( )
190191 } )
191192} )
193+
194+ describe ( "extractTextCountFromMessage" , ( ) => {
195+ it ( "should extract text from simple string content" , ( ) => {
196+ const message = {
197+ role : "user" ,
198+ content : "Hello world" ,
199+ } as any
200+
201+ const result = extractTextCountFromMessage ( message )
202+ expect ( result ) . toBe ( "Hello world" )
203+ } )
204+
205+ it ( "should extract text from LanguageModelTextPart" , ( ) => {
206+ const mockTextPart = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Text content" )
207+ const message = {
208+ role : "user" ,
209+ content : [ mockTextPart ] ,
210+ } as any
211+
212+ const result = extractTextCountFromMessage ( message )
213+ expect ( result ) . toBe ( "Text content" )
214+ } )
215+
216+ it ( "should extract text from multiple LanguageModelTextParts" , ( ) => {
217+ const mockTextPart1 = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "First part" )
218+ const mockTextPart2 = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Second part" )
219+ const message = {
220+ role : "user" ,
221+ content : [ mockTextPart1 , mockTextPart2 ] ,
222+ } as any
223+
224+ const result = extractTextCountFromMessage ( message )
225+ expect ( result ) . toBe ( "First partSecond part" )
226+ } )
227+
228+ it ( "should extract text from LanguageModelToolResultPart" , ( ) => {
229+ const mockTextPart = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Tool result content" )
230+ const mockToolResultPart = new ( vitest . mocked ( vscode ) . LanguageModelToolResultPart ) ( "tool-result-id" , [
231+ mockTextPart ,
232+ ] )
233+ const message = {
234+ role : "user" ,
235+ content : [ mockToolResultPart ] ,
236+ } as any
237+
238+ const result = extractTextCountFromMessage ( message )
239+ expect ( result ) . toBe ( "tool-result-idTool result content" )
240+ } )
241+
242+ it ( "should extract text from LanguageModelToolCallPart without input" , ( ) => {
243+ const mockToolCallPart = new ( vitest . mocked ( vscode ) . LanguageModelToolCallPart ) ( "call-id" , "tool-name" , { } )
244+ const message = {
245+ role : "assistant" ,
246+ content : [ mockToolCallPart ] ,
247+ } as any
248+
249+ const result = extractTextCountFromMessage ( message )
250+ expect ( result ) . toBe ( "tool-namecall-id" )
251+ } )
252+
253+ it ( "should extract text from LanguageModelToolCallPart with input" , ( ) => {
254+ const mockInput = { operation : "add" , numbers : [ 1 , 2 , 3 ] }
255+ const mockToolCallPart = new ( vitest . mocked ( vscode ) . LanguageModelToolCallPart ) (
256+ "call-id" ,
257+ "calculator" ,
258+ mockInput ,
259+ )
260+ const message = {
261+ role : "assistant" ,
262+ content : [ mockToolCallPart ] ,
263+ } as any
264+
265+ const result = extractTextCountFromMessage ( message )
266+ expect ( result ) . toBe ( `calculatorcall-id${ JSON . stringify ( mockInput ) } ` )
267+ } )
268+
269+ it ( "should extract text from LanguageModelToolCallPart with empty input" , ( ) => {
270+ const mockToolCallPart = new ( vitest . mocked ( vscode ) . LanguageModelToolCallPart ) ( "call-id" , "tool-name" , { } )
271+ const message = {
272+ role : "assistant" ,
273+ content : [ mockToolCallPart ] ,
274+ } as any
275+
276+ const result = extractTextCountFromMessage ( message )
277+ expect ( result ) . toBe ( "tool-namecall-id" )
278+ } )
279+
280+ it ( "should extract text from mixed content types" , ( ) => {
281+ const mockTextPart = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Text content" )
282+ const mockToolResultTextPart = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Tool result" )
283+ const mockToolResultPart = new ( vitest . mocked ( vscode ) . LanguageModelToolResultPart ) ( "result-id" , [
284+ mockToolResultTextPart ,
285+ ] )
286+ const mockInput = { param : "value" }
287+ const mockToolCallPart = new ( vitest . mocked ( vscode ) . LanguageModelToolCallPart ) ( "call-id" , "tool" , mockInput )
288+
289+ const message = {
290+ role : "assistant" ,
291+ content : [ mockTextPart , mockToolResultPart , mockToolCallPart ] ,
292+ } as any
293+
294+ const result = extractTextCountFromMessage ( message )
295+ expect ( result ) . toBe ( `Text contentresult-idTool resulttoolcall-id${ JSON . stringify ( mockInput ) } ` )
296+ } )
297+
298+ it ( "should handle empty array content" , ( ) => {
299+ const message = {
300+ role : "user" ,
301+ content : [ ] ,
302+ } as any
303+
304+ const result = extractTextCountFromMessage ( message )
305+ expect ( result ) . toBe ( "" )
306+ } )
307+
308+ it ( "should handle undefined content" , ( ) => {
309+ const message = {
310+ role : "user" ,
311+ content : undefined ,
312+ } as any
313+
314+ const result = extractTextCountFromMessage ( message )
315+ expect ( result ) . toBe ( "" )
316+ } )
317+
318+ it ( "should handle ToolResultPart with multiple text parts" , ( ) => {
319+ const mockTextPart1 = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Part 1" )
320+ const mockTextPart2 = new ( vitest . mocked ( vscode ) . LanguageModelTextPart ) ( "Part 2" )
321+ const mockToolResultPart = new ( vitest . mocked ( vscode ) . LanguageModelToolResultPart ) ( "result-id" , [
322+ mockTextPart1 ,
323+ mockTextPart2 ,
324+ ] )
325+
326+ const message = {
327+ role : "user" ,
328+ content : [ mockToolResultPart ] ,
329+ } as any
330+
331+ const result = extractTextCountFromMessage ( message )
332+ expect ( result ) . toBe ( "result-idPart 1Part 2" )
333+ } )
334+
335+ it ( "should handle ToolResultPart with empty parts array" , ( ) => {
336+ const mockToolResultPart = new ( vitest . mocked ( vscode ) . LanguageModelToolResultPart ) ( "result-id" , [ ] )
337+
338+ const message = {
339+ role : "user" ,
340+ content : [ mockToolResultPart ] ,
341+ } as any
342+
343+ const result = extractTextCountFromMessage ( message )
344+ expect ( result ) . toBe ( "result-id" )
345+ } )
346+ } )
0 commit comments