| 1 | import {describe, expect, it} from 'vitest'; |
| 2 | import {applyAgentEvent, appendLocalUser, composeAgentPrompt, createChatState, humanize} from './events'; |
| 3 | |
| 4 | describe('agent event mapping', () => { |
| 5 | it('streams assistant text into one message', () => { |
| 6 | let state = appendLocalUser(createChatState(), 'Make a short film'); |
| 7 | state = applyAgentEvent(state, {type: 'turn', turn_id: 'turn-1'}); |
| 8 | state = applyAgentEvent(state, {type: 'token', turn_id: 'turn-1', delta: 'Planning'}); |
| 9 | state = applyAgentEvent(state, {type: 'token', turn_id: 'turn-1', delta: ' ready'}); |
| 10 | state = applyAgentEvent(state, {type: 'done', turn_id: 'turn-1'}); |
| 11 | expect(state.messages.at(-1)).toMatchObject({role: 'assistant', text: 'Planning ready'}); |
| 12 | expect(state.busy).toBe(false); |
| 13 | }); |
| 14 | |
| 15 | it('updates a running tool instead of appending every progress event', () => { |
| 16 | let state = createChatState(); |
| 17 | state = applyAgentEvent(state, {type: 'tool_start', turn_id: 'turn-1', tool: {id: 'tool-1', name: 'vimax_render_video'}}); |
| 18 | state = applyAgentEvent(state, {type: 'tool_progress', turn_id: 'turn-1', tool: {name: 'vimax_render_video'}, progress: {stage: 'generate_frames', message: 'Generating frames'}}); |
| 19 | state = applyAgentEvent(state, {type: 'tool_result', turn_id: 'turn-1', tool_result: {name: 'vimax_render_video', ok: true}}); |
| 20 | expect(state.messages).toHaveLength(1); |
| 21 | expect(state.messages[0]).toMatchObject({tool: 'vimax_render_video', status: 'done', text: 'Completed'}); |
| 22 | }); |
| 23 | |
| 24 | it('keeps each composer submission on one stdin line', () => { |
| 25 | expect(composeAgentPrompt('first line\nsecond line')).toBe('first line second line'); |
| 26 | expect(composeAgentPrompt('Use these references', ['uploads/script.txt', 'uploads/look.png'])) |
| 27 | .toBe('Use these references <workspace_uploads>["uploads/script.txt","uploads/look.png"]</workspace_uploads>'); |
| 28 | expect(humanize('vimax_narrative_planning')).toBe('ViMax Narrative Planning'); |
| 29 | }); |
| 30 | |
| 31 | it('ends running tools when the agent process stops', () => { |
| 32 | let state = applyAgentEvent(createChatState(), { |
| 33 | type: 'tool_start', |
| 34 | turn_id: 'turn-1', |
| 35 | tool: {id: 'tool-1', name: 'vimax_render_video'}, |
| 36 | }); |
| 37 | state = applyAgentEvent(state, { |
| 38 | type: 'bridge_status', |
| 39 | status: 'stopped', |
| 40 | message: 'Configuration updated', |
| 41 | }); |
| 42 | expect(state.busy).toBe(false); |
| 43 | expect(state.messages[0]).toMatchObject({ |
| 44 | tool: 'vimax_render_video', |
| 45 | status: 'error', |
| 46 | stage: 'interrupted', |
| 47 | text: 'Configuration updated', |
| 48 | }); |
| 49 | }); |
| 50 | }); |
| 51 |