feat(08.1-02): update MockAgentManager to schema-aligned scenarios
- Change MockAgentScenario from outcome-based to status-based discriminated union - Align with agent output schema: done/question/unrecoverable_error - Update completeAgent() to handle new status types - Update resume() to use new scenario format
This commit is contained in:
@@ -26,23 +26,28 @@ import type {
|
||||
|
||||
/**
|
||||
* Scenario configuration for mock agent behavior.
|
||||
* Uses discriminated union on status to match agent output schema.
|
||||
*/
|
||||
export interface MockAgentScenario {
|
||||
/** How agent completes: 'success' | 'crash' | 'waiting_for_input' */
|
||||
outcome: 'success' | 'crash' | 'waiting_for_input';
|
||||
/** Delay before completion (ms). Default 0 for synchronous tests. */
|
||||
delay?: number;
|
||||
/** Result message for success/crash */
|
||||
message?: string;
|
||||
/** Files modified (for success) */
|
||||
filesModified?: string[];
|
||||
/** Question to surface (for waiting_for_input) */
|
||||
question?: string;
|
||||
/** Options for question (for waiting_for_input) */
|
||||
options?: Array<{ label: string; description?: string }>;
|
||||
/** Whether multiple options can be selected (for waiting_for_input) */
|
||||
multiSelect?: boolean;
|
||||
}
|
||||
export type MockAgentScenario =
|
||||
| {
|
||||
status: 'done';
|
||||
result?: string;
|
||||
filesModified?: string[];
|
||||
delay?: number;
|
||||
}
|
||||
| {
|
||||
status: 'question';
|
||||
question: string;
|
||||
options?: Array<{ label: string; description?: string }>;
|
||||
multiSelect?: boolean;
|
||||
delay?: number;
|
||||
}
|
||||
| {
|
||||
status: 'unrecoverable_error';
|
||||
error: string;
|
||||
attempted?: string;
|
||||
delay?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal agent record with scenario and timer tracking.
|
||||
@@ -59,10 +64,10 @@ interface MockAgentRecord {
|
||||
* Default scenario: immediate success with generic message.
|
||||
*/
|
||||
const DEFAULT_SCENARIO: MockAgentScenario = {
|
||||
outcome: 'success',
|
||||
delay: 0,
|
||||
message: 'Task completed successfully',
|
||||
status: 'done',
|
||||
result: 'Task completed successfully',
|
||||
filesModified: [],
|
||||
delay: 0,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -178,7 +183,7 @@ export class MockAgentManager implements AgentManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete agent based on scenario outcome.
|
||||
* Complete agent based on scenario status.
|
||||
*/
|
||||
private completeAgent(agentId: string, scenario: MockAgentScenario): void {
|
||||
const record = this.agents.get(agentId);
|
||||
@@ -186,11 +191,11 @@ export class MockAgentManager implements AgentManager {
|
||||
|
||||
const { info } = record;
|
||||
|
||||
switch (scenario.outcome) {
|
||||
case 'success':
|
||||
switch (scenario.status) {
|
||||
case 'done':
|
||||
record.result = {
|
||||
success: true,
|
||||
message: scenario.message ?? 'Task completed successfully',
|
||||
message: scenario.result ?? 'Task completed successfully',
|
||||
filesModified: scenario.filesModified,
|
||||
};
|
||||
record.info.status = 'idle';
|
||||
@@ -211,10 +216,10 @@ export class MockAgentManager implements AgentManager {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'crash':
|
||||
case 'unrecoverable_error':
|
||||
record.result = {
|
||||
success: false,
|
||||
message: scenario.message ?? 'Agent crashed',
|
||||
message: scenario.error,
|
||||
};
|
||||
record.info.status = 'crashed';
|
||||
record.info.updatedAt = new Date();
|
||||
@@ -227,18 +232,18 @@ export class MockAgentManager implements AgentManager {
|
||||
agentId,
|
||||
name: info.name,
|
||||
taskId: info.taskId,
|
||||
error: scenario.message ?? 'Agent crashed',
|
||||
error: scenario.error,
|
||||
},
|
||||
};
|
||||
this.eventBus.emit(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'waiting_for_input':
|
||||
case 'question':
|
||||
record.info.status = 'waiting_for_input';
|
||||
record.info.updatedAt = new Date();
|
||||
record.pendingQuestion = {
|
||||
question: scenario.question ?? 'User input required',
|
||||
question: scenario.question,
|
||||
options: scenario.options,
|
||||
multiSelect: scenario.multiSelect,
|
||||
};
|
||||
@@ -252,7 +257,7 @@ export class MockAgentManager implements AgentManager {
|
||||
name: info.name,
|
||||
taskId: info.taskId,
|
||||
sessionId: info.sessionId ?? '',
|
||||
question: scenario.question ?? 'User input required',
|
||||
question: scenario.question,
|
||||
options: scenario.options,
|
||||
multiSelect: scenario.multiSelect,
|
||||
},
|
||||
@@ -369,11 +374,14 @@ export class MockAgentManager implements AgentManager {
|
||||
|
||||
// Re-run scenario (after resume, typically completes successfully)
|
||||
// For testing, we use a new scenario that defaults to success
|
||||
// Extract filesModified from original scenario if it was a 'done' type
|
||||
const originalFilesModified =
|
||||
record.scenario.status === 'done' ? record.scenario.filesModified : undefined;
|
||||
const resumeScenario: MockAgentScenario = {
|
||||
outcome: 'success',
|
||||
status: 'done',
|
||||
delay: record.scenario.delay ?? 0,
|
||||
message: 'Resumed and completed successfully',
|
||||
filesModified: record.scenario.filesModified,
|
||||
result: 'Resumed and completed successfully',
|
||||
filesModified: originalFilesModified,
|
||||
};
|
||||
|
||||
this.scheduleCompletion(agentId, resumeScenario);
|
||||
|
||||
Reference in New Issue
Block a user