|
1 | 1 | import { Cline } from '../Cline'; |
2 | 2 | import { ClineProvider } from '../webview/ClineProvider'; |
3 | 3 | import { ApiConfiguration } from '../../shared/api'; |
| 4 | +import { ApiStreamChunk } from '../../api/transform/stream'; |
4 | 5 | import * as vscode from 'vscode'; |
5 | 6 |
|
6 | 7 | // Mock all MCP-related modules |
@@ -419,5 +420,84 @@ describe('Cline', () => { |
419 | 420 | expect(details).toContain('# Current Time'); |
420 | 421 | expect(details).toMatch(/1\/1\/2024.*5:00:00 AM.*\(America\/Los_Angeles, UTC-7:00\)/); // Full time string format |
421 | 422 | }); |
| 423 | + |
| 424 | + describe('API conversation handling', () => { |
| 425 | + it('should clean conversation history before sending to API', async () => { |
| 426 | + const cline = new Cline( |
| 427 | + mockProvider, |
| 428 | + mockApiConfig, |
| 429 | + undefined, |
| 430 | + false, |
| 431 | + undefined, |
| 432 | + 'test task' |
| 433 | + ); |
| 434 | + |
| 435 | + // Mock the API's createMessage method to capture the conversation history |
| 436 | + const createMessageSpy = jest.fn(); |
| 437 | + const mockStream = { |
| 438 | + async *[Symbol.asyncIterator]() { |
| 439 | + yield { type: 'text', text: '' }; |
| 440 | + }, |
| 441 | + async next() { |
| 442 | + return { done: true, value: undefined }; |
| 443 | + }, |
| 444 | + async return() { |
| 445 | + return { done: true, value: undefined }; |
| 446 | + }, |
| 447 | + async throw(e: any) { |
| 448 | + throw e; |
| 449 | + }, |
| 450 | + async [Symbol.asyncDispose]() { |
| 451 | + // Cleanup |
| 452 | + } |
| 453 | + } as AsyncGenerator<ApiStreamChunk>; |
| 454 | + |
| 455 | + jest.spyOn(cline.api, 'createMessage').mockImplementation((...args) => { |
| 456 | + createMessageSpy(...args); |
| 457 | + return mockStream; |
| 458 | + }); |
| 459 | + |
| 460 | + // Add a message with extra properties to the conversation history |
| 461 | + const messageWithExtra = { |
| 462 | + role: 'user' as const, |
| 463 | + content: [{ type: 'text' as const, text: 'test message' }], |
| 464 | + ts: Date.now(), |
| 465 | + extraProp: 'should be removed' |
| 466 | + }; |
| 467 | + cline.apiConversationHistory = [messageWithExtra]; |
| 468 | + |
| 469 | + // Trigger an API request |
| 470 | + await cline.recursivelyMakeClineRequests([ |
| 471 | + { type: 'text', text: 'test request' } |
| 472 | + ]); |
| 473 | + |
| 474 | + // Get all calls to createMessage |
| 475 | + const calls = createMessageSpy.mock.calls; |
| 476 | + |
| 477 | + // Find the call that includes our test message |
| 478 | + const relevantCall = calls.find(call => |
| 479 | + call[1]?.some((msg: any) => |
| 480 | + msg.content?.[0]?.text === 'test message' |
| 481 | + ) |
| 482 | + ); |
| 483 | + |
| 484 | + // Verify the conversation history was cleaned in the relevant call |
| 485 | + expect(relevantCall?.[1]).toEqual( |
| 486 | + expect.arrayContaining([ |
| 487 | + { |
| 488 | + role: 'user', |
| 489 | + content: [{ type: 'text', text: 'test message' }] |
| 490 | + } |
| 491 | + ]) |
| 492 | + ); |
| 493 | + |
| 494 | + // Verify extra properties were removed |
| 495 | + const passedMessage = relevantCall?.[1].find((msg: any) => |
| 496 | + msg.content?.[0]?.text === 'test message' |
| 497 | + ); |
| 498 | + expect(passedMessage).not.toHaveProperty('ts'); |
| 499 | + expect(passedMessage).not.toHaveProperty('extraProp'); |
| 500 | + }); |
| 501 | + }); |
422 | 502 | }); |
423 | 503 | }); |
0 commit comments