diff --git a/src/vs/platform/agentHost/test/node/agentService.test.ts b/src/vs/platform/agentHost/test/node/agentService.test.ts index 226f743386b..80150b428a1 100644 --- a/src/vs/platform/agentHost/test/node/agentService.test.ts +++ b/src/vs/platform/agentHost/test/node/agentService.test.ts @@ -4,82 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; -import { Emitter } from '../../../../base/common/event.js'; import { DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js'; import { URI } from '../../../../base/common/uri.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js'; import { NullLogService } from '../../../log/common/log.js'; -import { AgentSession, IAgent, IAgentCreateSessionConfig, IAgentDescriptor, IAgentMessageEvent, IAgentModelInfo, IAgentProgressEvent, IAgentSessionMetadata, IAgentToolCompleteEvent, IAgentToolStartEvent, AgentProvider } from '../../common/agentService.js'; +import { AgentSession } from '../../common/agentService.js'; import { IActionEnvelope } from '../../common/state/sessionActions.js'; import { AgentService } from '../../node/agentService.js'; - -class MockAgent implements IAgent { - private readonly _onDidSessionProgress = new Emitter(); - readonly onDidSessionProgress = this._onDidSessionProgress.event; - - private readonly _sessions = new Map(); - private _nextId = 1; - - readonly setAuthTokenCalls: string[] = []; - readonly sendMessageCalls: { session: URI; prompt: string }[] = []; - readonly disposeSessionCalls: URI[] = []; - - constructor(readonly id: AgentProvider) { } - - getDescriptor(): IAgentDescriptor { - return { provider: this.id, displayName: `Agent ${this.id}`, description: `Test ${this.id} agent`, requiresAuth: this.id === 'copilot' }; - } - - changeModel(session: URI, model: string): Promise { - return Promise.resolve(); - } - - async listModels(): Promise { - return [{ provider: this.id, id: `${this.id}-model`, name: `${this.id} Model`, maxContextWindow: 128000, supportsVision: false, supportsReasoningEffort: false }]; - } - - async listSessions(): Promise { - return [...this._sessions.values()].map(s => ({ session: s, startTime: Date.now(), modifiedTime: Date.now() })); - } - - async createSession(_config?: IAgentCreateSessionConfig): Promise { - const rawId = `${this.id}-session-${this._nextId++}`; - const session = AgentSession.uri(this.id, rawId); - this._sessions.set(rawId, session); - return session; - } - - async sendMessage(session: URI, prompt: string): Promise { - this.sendMessageCalls.push({ session, prompt }); - } - - async getSessionMessages(_session: URI): Promise<(IAgentMessageEvent | IAgentToolStartEvent | IAgentToolCompleteEvent)[]> { - return []; - } - - async disposeSession(session: URI): Promise { - this.disposeSessionCalls.push(session); - this._sessions.delete(AgentSession.id(session)); - } - - async abortSession(_session: URI): Promise { } - - respondToPermissionRequest(_requestId: string, _approved: boolean): void { } - - async setAuthToken(token: string): Promise { - this.setAuthTokenCalls.push(token); - } - - async shutdown(): Promise { } - - fireProgress(event: IAgentProgressEvent): void { - this._onDidSessionProgress.fire(event); - } - - dispose(): void { - this._onDidSessionProgress.dispose(); - } -} +import { MockAgent } from './mockAgent.js'; suite('AgentService (node dispatcher)', () => { diff --git a/src/vs/platform/agentHost/test/node/agentSideEffects.test.ts b/src/vs/platform/agentHost/test/node/agentSideEffects.test.ts index bcc7d02107b..38676453875 100644 --- a/src/vs/platform/agentHost/test/node/agentSideEffects.test.ts +++ b/src/vs/platform/agentHost/test/node/agentSideEffects.test.ts @@ -4,90 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; -import { Emitter } from '../../../../base/common/event.js'; import { DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js'; import { observableValue } from '../../../../base/common/observable.js'; -import { URI } from '../../../../base/common/uri.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js'; import { NullLogService } from '../../../log/common/log.js'; -import { AgentSession, IAgent, IAgentCreateSessionConfig, IAgentDescriptor, IAgentMessageEvent, IAgentModelInfo, IAgentProgressEvent, IAgentSessionMetadata, IAgentToolCompleteEvent, IAgentToolStartEvent, AgentProvider } from '../../common/agentService.js'; +import { AgentSession, IAgent } from '../../common/agentService.js'; import { IActionEnvelope, ISessionAction } from '../../common/state/sessionActions.js'; import { SessionStatus } from '../../common/state/sessionState.js'; import { AgentSideEffects } from '../../node/agentSideEffects.js'; import { SessionStateManager } from '../../node/sessionStateManager.js'; - -// ---- MockAgent -------------------------------------------------------------- - -class MockAgent implements IAgent { - private readonly _onDidSessionProgress = new Emitter(); - readonly onDidSessionProgress = this._onDidSessionProgress.event; - - private readonly _sessions = new Map(); - private _nextId = 1; - - readonly sendMessageCalls: { session: URI; prompt: string }[] = []; - readonly disposeSessionCalls: URI[] = []; - readonly abortSessionCalls: URI[] = []; - readonly respondToPermissionCalls: { requestId: string; approved: boolean }[] = []; - readonly changeModelCalls: { session: URI; model: string }[] = []; - - constructor(readonly id: AgentProvider = 'mock') { } - - getDescriptor(): IAgentDescriptor { - return { provider: this.id, displayName: `Agent ${this.id}`, description: `Test ${this.id} agent`, requiresAuth: false }; - } - - async listModels(): Promise { - return [{ provider: this.id, id: `${this.id}-model`, name: `${this.id} Model`, maxContextWindow: 128000, supportsVision: false, supportsReasoningEffort: false }]; - } - - async listSessions(): Promise { - return [...this._sessions.values()].map(s => ({ session: s, startTime: 1000, modifiedTime: 2000, summary: 'Test session' })); - } - - async createSession(_config?: IAgentCreateSessionConfig): Promise { - const rawId = `${this.id}-session-${this._nextId++}`; - const session = AgentSession.uri(this.id, rawId); - this._sessions.set(rawId, session); - return session; - } - - async sendMessage(session: URI, prompt: string): Promise { - this.sendMessageCalls.push({ session, prompt }); - } - - async getSessionMessages(_session: URI): Promise<(IAgentMessageEvent | IAgentToolStartEvent | IAgentToolCompleteEvent)[]> { - return []; - } - - async disposeSession(session: URI): Promise { - this.disposeSessionCalls.push(session); - this._sessions.delete(AgentSession.id(session)); - } - - async abortSession(session: URI): Promise { - this.abortSessionCalls.push(session); - } - - respondToPermissionRequest(requestId: string, approved: boolean): void { - this.respondToPermissionCalls.push({ requestId, approved }); - } - - async changeModel(session: URI, model: string): Promise { - this.changeModelCalls.push({ session, model }); - } - - async setAuthToken(_token: string): Promise { } - async shutdown(): Promise { } - - fireProgress(event: IAgentProgressEvent): void { - this._onDidSessionProgress.fire(event); - } - - dispose(): void { - this._onDidSessionProgress.dispose(); - } -} +import { MockAgent } from './mockAgent.js'; // ---- Tests ------------------------------------------------------------------ @@ -339,7 +265,7 @@ suite('AgentSideEffects', () => { const sessions = await sideEffects.handleListSessions(); assert.strictEqual(sessions.length, 1); assert.strictEqual(sessions[0].provider, 'mock'); - assert.strictEqual(sessions[0].title, 'Test session'); + assert.strictEqual(sessions[0].title, 'Session'); }); }); diff --git a/src/vs/platform/agentHost/test/node/mockAgent.ts b/src/vs/platform/agentHost/test/node/mockAgent.ts index 851faaff491..6ddf3ac28c3 100644 --- a/src/vs/platform/agentHost/test/node/mockAgent.ts +++ b/src/vs/platform/agentHost/test/node/mockAgent.ts @@ -7,6 +7,85 @@ import { Emitter } from '../../../../base/common/event.js'; import { URI } from '../../../../base/common/uri.js'; import { AgentSession, type AgentProvider, type IAgent, type IAgentAttachment, type IAgentCreateSessionConfig, type IAgentDescriptor, type IAgentMessageEvent, type IAgentModelInfo, type IAgentProgressEvent, type IAgentSessionMetadata, type IAgentToolCompleteEvent, type IAgentToolStartEvent } from '../../common/agentService.js'; +/** + * General-purpose mock agent for unit tests. Tracks all method calls + * for assertion and exposes {@link fireProgress} to inject progress events. + */ +export class MockAgent implements IAgent { + private readonly _onDidSessionProgress = new Emitter(); + readonly onDidSessionProgress = this._onDidSessionProgress.event; + + private readonly _sessions = new Map(); + private _nextId = 1; + + readonly setAuthTokenCalls: string[] = []; + readonly sendMessageCalls: { session: URI; prompt: string }[] = []; + readonly disposeSessionCalls: URI[] = []; + readonly abortSessionCalls: URI[] = []; + readonly respondToPermissionCalls: { requestId: string; approved: boolean }[] = []; + readonly changeModelCalls: { session: URI; model: string }[] = []; + + constructor(readonly id: AgentProvider = 'mock') { } + + getDescriptor(): IAgentDescriptor { + return { provider: this.id, displayName: `Agent ${this.id}`, description: `Test ${this.id} agent`, requiresAuth: this.id === 'copilot' }; + } + + async listModels(): Promise { + return [{ provider: this.id, id: `${this.id}-model`, name: `${this.id} Model`, maxContextWindow: 128000, supportsVision: false, supportsReasoningEffort: false }]; + } + + async listSessions(): Promise { + return [...this._sessions.values()].map(s => ({ session: s, startTime: Date.now(), modifiedTime: Date.now() })); + } + + async createSession(_config?: IAgentCreateSessionConfig): Promise { + const rawId = `${this.id}-session-${this._nextId++}`; + const session = AgentSession.uri(this.id, rawId); + this._sessions.set(rawId, session); + return session; + } + + async sendMessage(session: URI, prompt: string): Promise { + this.sendMessageCalls.push({ session, prompt }); + } + + async getSessionMessages(_session: URI): Promise<(IAgentMessageEvent | IAgentToolStartEvent | IAgentToolCompleteEvent)[]> { + return []; + } + + async disposeSession(session: URI): Promise { + this.disposeSessionCalls.push(session); + this._sessions.delete(AgentSession.id(session)); + } + + async abortSession(session: URI): Promise { + this.abortSessionCalls.push(session); + } + + respondToPermissionRequest(requestId: string, approved: boolean): void { + this.respondToPermissionCalls.push({ requestId, approved }); + } + + async changeModel(session: URI, model: string): Promise { + this.changeModelCalls.push({ session, model }); + } + + async setAuthToken(token: string): Promise { + this.setAuthTokenCalls.push(token); + } + + async shutdown(): Promise { } + + fireProgress(event: IAgentProgressEvent): void { + this._onDidSessionProgress.fire(event); + } + + dispose(): void { + this._onDidSessionProgress.dispose(); + } +} + export class ScriptedMockAgent implements IAgent { readonly id: AgentProvider = 'mock';