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