|
7 | 7 | import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; |
8 | 8 | import { AgentOSOrchestrator } from '../../src/api/AgentOSOrchestrator'; |
9 | 9 | import type { AgentOSInput, ProcessingOptions } from '../../src/api/types/AgentOSInput'; |
| 10 | +import { AgentOSResponseChunkType } from '../../src/api/types/AgentOSResponse'; |
| 11 | +import { GMIOutputChunkType } from '../../src/cognitive_substrate/IGMI'; |
10 | 12 | import type { |
11 | 13 | GMITurnInput, |
12 | 14 | IGMI, |
13 | 15 | GMIOutputChunk, |
14 | | - GMIOutputChunkType, |
15 | 16 | } from '../../src/cognitive_substrate/IGMI'; |
16 | 17 | import type { GMIManager } from '../../src/cognitive_substrate/GMIManager'; |
17 | 18 | import type { IToolOrchestrator } from '../../src/core/tools/IToolOrchestrator'; |
@@ -73,25 +74,26 @@ describe('AgentOSOrchestrator (API layer)', () => { |
73 | 74 | // Capture the input for assertions |
74 | 75 | capturedGMIInput = input; |
75 | 76 | yield { |
76 | | - type: 'TEXT_DELTA' as GMIOutputChunkType, |
| 77 | + type: GMIOutputChunkType.TEXT_DELTA, |
77 | 78 | content: 'Hello', |
78 | 79 | interactionId: 'interaction-1', |
79 | 80 | timestamp: new Date(), |
80 | 81 | } as GMIOutputChunk; |
81 | 82 | yield { |
82 | | - type: 'FINAL_RESPONSE_MARKER' as GMIOutputChunkType, |
| 83 | + type: GMIOutputChunkType.FINAL_RESPONSE_MARKER, |
83 | 84 | content: { finalResponseText: 'Hello' }, |
84 | 85 | interactionId: 'interaction-1', |
85 | 86 | timestamp: new Date(), |
| 87 | + isFinal: true, |
86 | 88 | } as GMIOutputChunk; |
87 | 89 | return { |
88 | 90 | isFinal: true, |
89 | | - finalResponseText: 'Hello', |
| 91 | + responseText: 'Hello', |
90 | 92 | }; |
91 | 93 | }), |
92 | 94 | handleToolResult: vi.fn().mockImplementation(async function* () { |
93 | 95 | yield { |
94 | | - type: 'TEXT_DELTA' as GMIOutputChunkType, |
| 96 | + type: GMIOutputChunkType.TEXT_DELTA, |
95 | 97 | content: 'Tool result processed', |
96 | 98 | interactionId: 'interaction-1', |
97 | 99 | timestamp: new Date(), |
@@ -308,5 +310,47 @@ describe('AgentOSOrchestrator (API layer)', () => { |
308 | 310 |
|
309 | 311 | expect(capturedGMIInput?.metadata?.gmiId).toBe('gmi-1'); |
310 | 312 | }); |
| 313 | + |
| 314 | + it('uses the AsyncGenerator return value for finalResponseText (not the FINAL_RESPONSE_MARKER content)', async () => { |
| 315 | + // Simulate the real-world scenario: the marker content is a status string, while the |
| 316 | + // actual assistant response is returned via the generator return value. |
| 317 | + (mockGMI.processTurnStream as any).mockImplementation(async function* (_input: GMITurnInput) { |
| 318 | + yield { |
| 319 | + type: GMIOutputChunkType.TEXT_DELTA, |
| 320 | + content: 'Here are three tips: ', |
| 321 | + interactionId: 'interaction-1', |
| 322 | + timestamp: new Date(), |
| 323 | + } as GMIOutputChunk; |
| 324 | + yield { |
| 325 | + type: GMIOutputChunkType.FINAL_RESPONSE_MARKER, |
| 326 | + content: 'Turn processing sequence complete.', |
| 327 | + interactionId: 'interaction-1', |
| 328 | + timestamp: new Date(), |
| 329 | + isFinal: true, |
| 330 | + } as GMIOutputChunk; |
| 331 | + return { |
| 332 | + isFinal: true, |
| 333 | + responseText: 'Here are three tips: 1) Do X 2) Do Y 3) Do Z', |
| 334 | + }; |
| 335 | + }); |
| 336 | + |
| 337 | + const input: AgentOSInput = { |
| 338 | + userId: 'test-user', |
| 339 | + sessionId: 'test-session', |
| 340 | + textInput: 'Give me 3 tips', |
| 341 | + selectedPersonaId: 'persona-1', |
| 342 | + }; |
| 343 | + |
| 344 | + await orchestrator.orchestrateTurn(input); |
| 345 | + await new Promise((resolve) => setTimeout(resolve, 100)); |
| 346 | + |
| 347 | + const pushedChunks = (mockStreamingManager.pushChunk as any).mock.calls.map((call: any[]) => call[1]); |
| 348 | + const finalChunk = pushedChunks.find((c: any) => c.type === AgentOSResponseChunkType.FINAL_RESPONSE); |
| 349 | + |
| 350 | + expect(finalChunk).toBeTruthy(); |
| 351 | + expect(finalChunk.finalResponseText).toBe('Here are three tips: 1) Do X 2) Do Y 3) Do Z'); |
| 352 | + expect(String(finalChunk.finalResponseText).toLowerCase()).not.toContain('turn processing sequence complete'); |
| 353 | + expect(mockStreamingManager.closeStream).toHaveBeenCalled(); |
| 354 | + }); |
311 | 355 | }); |
312 | 356 | }); |
0 commit comments