import assert from 'node:assert/strict'; import test from 'node:test'; import { reconcileSessionEventRequestContext, resolvePostAgentRunChatState, shouldKeepStreamingAfterRunError, shouldPromoteSessionIdToStreaming, } from './chat-agent-run-gate.mjs'; test('resolvePostAgentRunChatState keeps idle when Finish beat agent-run gate', () => { assert.equal( resolvePostAgentRunChatState({ chatState: 'idle', finishedViaPortalDirectChat: false }), 'idle', ); }); test('resolvePostAgentRunChatState returns streaming while still waiting for session Finish', () => { assert.equal(resolvePostAgentRunChatState({ chatState: 'waiting' }), 'streaming'); assert.equal(resolvePostAgentRunChatState({ chatState: 'streaming' }), 'streaming'); }); test('resolvePostAgentRunChatState prefers portal direct chat completion', () => { assert.equal( resolvePostAgentRunChatState({ chatState: 'streaming', finishedViaPortalDirectChat: true }), 'idle', ); }); test('resolvePostAgentRunChatState idles after worker-side agent run success', () => { assert.equal( resolvePostAgentRunChatState({ chatState: 'waiting', agentRunSucceeded: true }), 'idle', ); assert.equal( resolvePostAgentRunChatState({ chatState: 'streaming', agentRunSucceeded: true }), 'idle', ); }); test('completed run wins when the direct-chat snapshot is not ready', () => { assert.equal( resolvePostAgentRunChatState({ chatState: 'streaming', finishedViaPortalDirectChat: false, agentRunSucceeded: true, }), 'idle', ); }); test('only ambiguous transport failures keep the chat streaming', () => { assert.equal(shouldKeepStreamingAfterRunError(0), true); assert.equal(shouldKeepStreamingAfterRunError(409), true); assert.equal(shouldKeepStreamingAfterRunError(503), true); assert.equal(shouldKeepStreamingAfterRunError(400), false); assert.equal(shouldKeepStreamingAfterRunError(undefined), false); assert.equal( shouldKeepStreamingAfterRunError( undefined, 'Session already has an active request. Cancel it first.', ), true, ); assert.equal(shouldKeepStreamingAfterRunError(undefined, '后台任务失败'), false); }); test('shouldPromoteSessionIdToStreaming skips re-streaming after Finish', () => { assert.equal(shouldPromoteSessionIdToStreaming('idle'), false); assert.equal(shouldPromoteSessionIdToStreaming('waiting'), true); assert.equal(shouldPromoteSessionIdToStreaming('streaming'), true); }); test('reconcileSessionEventRequestContext adopts Goose request id while agent-run gate waits', () => { assert.deepEqual( reconcileSessionEventRequestContext({ activeRequestId: 'portal-req', chatState: 'waiting', eventType: 'ActiveRequests', activeRequestIds: ['goose-req'], }), { activeRequestId: 'goose-req', promoteStreaming: true, allowMissingGrace: false }, ); assert.deepEqual( reconcileSessionEventRequestContext({ activeRequestId: 'portal-req', chatState: 'waiting', eventType: 'Message', eventRequestId: 'goose-req', }), { activeRequestId: 'goose-req', promoteStreaming: true, allowMissingGrace: false }, ); });