Path: blob/main/src/vs/platform/agentHost/test/node/reducers.test.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';7import { sessionReducer } from '../../common/state/protocol/reducers.js';8import { ActionType } from '../../common/state/sessionActions.js';9import { SessionInputAnswerState, SessionInputAnswerValueKind, SessionInputQuestionKind, SessionInputResponseKind, SessionLifecycle, SessionStatus, ToolCallConfirmationReason, type SessionState } from '../../common/state/sessionState.js';1011function makeSession(): SessionState {12return {13summary: {14resource: 'copilot:/test',15provider: 'copilot',16title: 'Test',17status: SessionStatus.Idle,18createdAt: Date.now(),19modifiedAt: Date.now(),20project: { uri: 'file:///test-project', displayName: 'Test Project' },21},22lifecycle: SessionLifecycle.Ready,23turns: [],24};25}2627function withActiveTurnAndToolCall(state: SessionState): SessionState {28state = sessionReducer(state, {29type: ActionType.SessionTurnStarted,30session: 'copilot:/test',31turnId: 'turn-1',32userMessage: { text: 'hello' },33});34state = sessionReducer(state, {35type: ActionType.SessionToolCallStart,36session: 'copilot:/test',37turnId: 'turn-1',38toolCallId: 'tc-1',39toolName: 'readFile',40displayName: 'Read File',41});42return state;43}4445suite('sessionReducer – summaryStatus with tool call confirmations and input requests', () => {4647ensureNoDisposablesAreLeakedInTestSuite();4849test('SessionStatus is InputNeeded when a tool call is PendingConfirmation', () => {50let state = withActiveTurnAndToolCall(makeSession());5152// Transition to PendingConfirmation (no `confirmed` field)53state = sessionReducer(state, {54type: ActionType.SessionToolCallReady,55session: 'copilot:/test',56turnId: 'turn-1',57toolCallId: 'tc-1',58invocationMessage: 'Read file?',59toolInput: '/foo.ts',60});6162assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);63});6465test('SessionStatus is InputNeeded when a tool call is PendingResultConfirmation', () => {66let state = withActiveTurnAndToolCall(makeSession());6768// Transition to Running first69state = sessionReducer(state, {70type: ActionType.SessionToolCallReady,71session: 'copilot:/test',72turnId: 'turn-1',73toolCallId: 'tc-1',74invocationMessage: 'Read file',75toolInput: '/foo.ts',76confirmed: ToolCallConfirmationReason.NotNeeded,77});7879// Then complete with requiresResultConfirmation80state = sessionReducer(state, {81type: ActionType.SessionToolCallComplete,82session: 'copilot:/test',83turnId: 'turn-1',84toolCallId: 'tc-1',85requiresResultConfirmation: true,86result: {87success: true,88pastTenseMessage: 'Read file',89},90});9192assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);93});9495test('SessionStatus transitions from InputNeeded to InProgress when tool call is confirmed', () => {96let state = withActiveTurnAndToolCall(makeSession());9798// Transition to PendingConfirmation99state = sessionReducer(state, {100type: ActionType.SessionToolCallReady,101session: 'copilot:/test',102turnId: 'turn-1',103toolCallId: 'tc-1',104invocationMessage: 'Read file?',105toolInput: '/foo.ts',106});107assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);108109// Confirm it110state = sessionReducer(state, {111type: ActionType.SessionToolCallConfirmed,112session: 'copilot:/test',113turnId: 'turn-1',114toolCallId: 'tc-1',115approved: true,116confirmed: ToolCallConfirmationReason.UserAction,117});118119assert.strictEqual(state.summary.status, SessionStatus.InProgress);120});121122test('SessionStatus is InputNeeded with inputRequests', () => {123let state = withActiveTurnAndToolCall(makeSession());124125state = sessionReducer(state, {126type: ActionType.SessionInputRequested,127session: 'copilot:/test',128request: {129id: 'req-1',130message: 'What is your name?',131questions: [{132kind: SessionInputQuestionKind.Text,133id: 'q-1',134message: 'What is your name?',135required: true,136}],137},138});139140assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);141});142143test('SessionStatus transitions from InputNeeded to InProgress after SessionInputCompleted', () => {144let state = withActiveTurnAndToolCall(makeSession());145146// Add an input request147state = sessionReducer(state, {148type: ActionType.SessionInputRequested,149session: 'copilot:/test',150request: {151id: 'req-1',152message: 'What is your name?',153questions: [{154kind: SessionInputQuestionKind.Text,155id: 'q-1',156message: 'What is your name?',157required: true,158}],159},160});161assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);162163// Complete the input request164state = sessionReducer(state, {165type: ActionType.SessionInputCompleted,166session: 'copilot:/test',167requestId: 'req-1',168response: SessionInputResponseKind.Accept,169answers: { 'q-1': { state: SessionInputAnswerState.Submitted, value: { kind: SessionInputAnswerValueKind.Text, value: 'Alice' } } },170});171172assert.strictEqual(state.summary.status, SessionStatus.InProgress);173});174175test('Tool call transition to PendingConfirmation updates summary status to InputNeeded', () => {176let state = withActiveTurnAndToolCall(makeSession());177178// After SessionToolCallStart, status should be InProgress (tool is Streaming)179assert.strictEqual(state.summary.status, SessionStatus.InProgress);180181// Transition to PendingConfirmation via SessionToolCallReady (no confirmed)182state = sessionReducer(state, {183type: ActionType.SessionToolCallReady,184session: 'copilot:/test',185turnId: 'turn-1',186toolCallId: 'tc-1',187invocationMessage: 'Read file?',188toolInput: '/foo.ts',189});190191assert.strictEqual(state.summary.status, SessionStatus.InputNeeded);192});193});194195196