agentic-qe
Version:
Agentic Quality Engineering Fleet System - AI-driven quality management platform
397 lines • 10.7 kB
JavaScript
"use strict";
/**
* Task - Represents a unit of work to be executed by agents
*
* @remarks
* The Task class encapsulates all information needed to execute a unit of work
* in the AQE Fleet, including data, requirements, status tracking, and results.
*
* Tasks are automatically assigned to capable agents by the FleetManager and
* provide event-based progress tracking.
*
* @example
* ```typescript
* // Create a test generation task
* const task = new Task(
* 'test-generation',
* 'Generate unit tests for UserService',
* {
* filePath: './src/services/UserService.ts',
* framework: 'jest',
* coverageTarget: 95
* },
* {
* capabilities: ['ai-test-generation'],
* agentTypes: ['test-generator']
* },
* TaskPriority.HIGH
* );
*
* // Monitor task progress
* task.on('status:changed', (data) => {
* console.log(`Task ${data.taskId} status: ${data.newStatus}`);
* });
*
* await fleet.submitTask(task);
* const result = await task.waitForCompletion();
* ```
*
* @public
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Task = exports.TaskPriority = exports.TaskStatus = void 0;
const uuid_1 = require("uuid");
const events_1 = require("events");
/**
* Current execution status of a task
*
* @public
*/
var TaskStatus;
(function (TaskStatus) {
/** Task has been created but not submitted */
TaskStatus["CREATED"] = "created";
/** Task is queued waiting for an available agent */
TaskStatus["QUEUED"] = "queued";
/** Task has been assigned to an agent */
TaskStatus["ASSIGNED"] = "assigned";
/** Task is currently being executed */
TaskStatus["RUNNING"] = "running";
/** Task completed successfully */
TaskStatus["COMPLETED"] = "completed";
/** Task execution failed */
TaskStatus["FAILED"] = "failed";
/** Task was cancelled before completion */
TaskStatus["CANCELLED"] = "cancelled";
})(TaskStatus || (exports.TaskStatus = TaskStatus = {}));
/**
* Priority level for task execution
*
* @public
*/
var TaskPriority;
(function (TaskPriority) {
/** Low priority task */
TaskPriority[TaskPriority["LOW"] = 0] = "LOW";
/** Medium priority task (default) */
TaskPriority[TaskPriority["MEDIUM"] = 1] = "MEDIUM";
/** High priority task */
TaskPriority[TaskPriority["HIGH"] = 2] = "HIGH";
/** Critical priority task (executed first) */
TaskPriority[TaskPriority["CRITICAL"] = 3] = "CRITICAL";
})(TaskPriority || (exports.TaskPriority = TaskPriority = {}));
class Task extends events_1.EventEmitter {
constructor(type, name, data = {}, requirements = {}, priority = TaskPriority.MEDIUM) {
super();
this.result = null;
this.error = null;
this.id = (0, uuid_1.v4)();
this.type = type;
this.name = name;
this.data = data;
this.requirements = requirements;
this.status = TaskStatus.CREATED;
this.priority = priority;
this.metadata = {
createdAt: new Date(),
retryCount: 0,
maxRetries: 3
};
}
/**
* Get task ID
*
* @returns Unique identifier for this task
* @public
*/
getId() {
return this.id;
}
/**
* Get task type
*
* @returns The type of task (e.g., 'test-generation', 'coverage-analysis')
* @public
*/
getType() {
return this.type;
}
/**
* Get task name
*
* @returns Human-readable name for this task
* @public
*/
getName() {
return this.name;
}
/**
* Get task data
*
* @returns The data payload for task execution
* @public
*/
getData() {
return this.data;
}
/**
* Get task requirements
*/
getRequirements() {
return this.requirements;
}
/**
* Get task status
*/
getStatus() {
return this.status;
}
/**
* Set task status and update metadata
*
* @param status - The new status for the task
* @fires status:changed
* @public
*/
setStatus(status) {
const previousStatus = this.status;
this.status = status;
// Update metadata based on status
switch (status) {
case TaskStatus.RUNNING:
this.metadata.startedAt = new Date();
break;
case TaskStatus.COMPLETED:
case TaskStatus.FAILED:
case TaskStatus.CANCELLED:
this.metadata.completedAt = new Date();
break;
}
this.emit('status:changed', {
taskId: this.id,
previousStatus,
newStatus: status,
timestamp: new Date()
});
}
/**
* Get task priority
*/
getPriority() {
return this.priority;
}
/**
* Set task priority
*/
setPriority(priority) {
this.priority = priority;
this.emit('priority:changed', {
taskId: this.id,
priority,
timestamp: new Date()
});
}
/**
* Get task result
*/
getResult() {
return this.result;
}
/**
* Set task result
*/
setResult(result) {
this.result = result;
this.emit('result:set', {
taskId: this.id,
result,
timestamp: new Date()
});
}
/**
* Get task error
*/
getError() {
return this.error;
}
/**
* Set task error
*/
setError(error) {
this.error = error;
this.emit('error:set', {
taskId: this.id,
error,
timestamp: new Date()
});
}
/**
* Get task metadata
*/
getMetadata() {
return this.metadata;
}
/**
* Assign agent to task
*/
assignAgent(agentId) {
this.metadata.assignedAgent = agentId;
this.setStatus(TaskStatus.ASSIGNED);
this.emit('agent:assigned', {
taskId: this.id,
agentId,
timestamp: new Date()
});
}
/**
* Check if task can be retried
*/
canRetry() {
return this.metadata.retryCount < this.metadata.maxRetries;
}
/**
* Increment retry count
*/
incrementRetry() {
this.metadata.retryCount++;
this.emit('retry:attempted', {
taskId: this.id,
retryCount: this.metadata.retryCount,
timestamp: new Date()
});
}
/**
* Set maximum retries
*/
setMaxRetries(maxRetries) {
this.metadata.maxRetries = maxRetries;
}
/**
* Set timeout for task execution
*/
setTimeout(timeout) {
this.metadata.timeout = timeout;
}
/**
* Check if task has timed out
*/
hasTimedOut() {
if (!this.metadata.timeout || !this.metadata.startedAt) {
return false;
}
const elapsed = Date.now() - this.metadata.startedAt.getTime();
return elapsed > this.metadata.timeout;
}
/**
* Get task execution duration
*/
getExecutionDuration() {
if (!this.metadata.startedAt) {
return null;
}
const endTime = this.metadata.completedAt || new Date();
return endTime.getTime() - this.metadata.startedAt.getTime();
}
/**
* Check if task is complete (either completed or failed)
*/
isComplete() {
return this.status === TaskStatus.COMPLETED ||
this.status === TaskStatus.FAILED ||
this.status === TaskStatus.CANCELLED;
}
/**
* Wait for task completion
*
* @remarks
* Returns a promise that resolves when the task completes successfully
* or rejects if the task fails or is cancelled.
*
* @returns A promise that resolves to the task result
* @throws {Error} If the task fails or is cancelled
*
* @example
* ```typescript
* const task = new Task('test-generation', 'Generate tests', data);
* await fleet.submitTask(task);
* const result = await task.waitForCompletion();
* console.log('Tests generated:', result);
* ```
*
* @public
*/
async waitForCompletion() {
return new Promise((resolve, reject) => {
if (this.isComplete()) {
if (this.status === TaskStatus.COMPLETED) {
resolve(this.result);
}
else {
reject(this.error || new Error(`Task ${this.id} was ${this.status}`));
}
return;
}
const onStatusChange = (data) => {
if (data.taskId === this.id && this.isComplete()) {
this.removeListener('status:changed', onStatusChange);
if (this.status === TaskStatus.COMPLETED) {
resolve(this.result);
}
else {
reject(this.error || new Error(`Task ${this.id} was ${this.status}`));
}
}
};
this.on('status:changed', onStatusChange);
});
}
/**
* Cancel the task
*/
cancel() {
if (!this.isComplete()) {
this.setStatus(TaskStatus.CANCELLED);
this.emit('task:cancelled', {
taskId: this.id,
timestamp: new Date()
});
}
}
/**
* Convert task to JSON representation
*/
toJSON() {
return {
id: this.id,
type: this.type,
name: this.name,
data: this.data,
requirements: this.requirements,
status: this.status,
priority: this.priority,
result: this.result,
error: this.error?.message,
metadata: this.metadata
};
}
/**
* Create task from JSON representation
*/
static fromJSON(json) {
const task = new Task(json.type, json.name, json.data, json.requirements, json.priority);
task.status = json.status;
task.result = json.result;
if (json.error) {
task.error = new Error(json.error);
}
task.metadata = {
...json.metadata,
createdAt: new Date(json.metadata.createdAt),
startedAt: json.metadata.startedAt ? new Date(json.metadata.startedAt) : undefined,
completedAt: json.metadata.completedAt ? new Date(json.metadata.completedAt) : undefined
};
return task;
}
}
exports.Task = Task;
//# sourceMappingURL=Task.js.map