← back to Designer Wallcoverings
DW-Agents/dw-agents/agent-parallel-processes/shared-task-reporter.ts
230 lines
/**
* Shared Task Orchestrator Reporter
*
* This module provides a simple interface for all agents to report their
* tasks to the central task orchestrator (port 9900).
*
* Usage:
* import { reportTaskStart, reportTaskComplete, reportTaskFailed } from './shared-task-reporter';
*
* // When starting work
* const taskId = await reportTaskStart('Process York Products', 'Processing 500 York products', 'high', 'york');
*
* // When work completes
* await reportTaskComplete(taskId, 'Processed 500 products successfully');
*
* // If work fails
* await reportTaskFailed(taskId, 'Failed due to API error');
*/
const TASK_ORCHESTRATOR_URL = 'http://localhost:9900';
interface TaskMetadata {
agentPort?: number;
url?: string;
workProgress?: {
current: number;
total: number;
};
[key: string]: any;
}
/**
* Report that a task has started
*/
export async function reportTaskStart(
title: string,
description: string,
priority: 'low' | 'medium' | 'high' | 'critical' = 'medium',
agentName: string,
metadata: TaskMetadata = {}
): Promise<string | null> {
try {
const response = await fetch(`${TASK_ORCHESTRATOR_URL}/api/webhook/task`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title,
description,
priority,
source: agentName,
metadata: {
...metadata,
autoStarted: true,
startedAt: new Date().toISOString()
}
})
});
if (response.ok) {
const result = await response.json();
console.log(`✅ Task reported to orchestrator: ${result.taskId}`);
// Immediately update to in_progress
if (result.taskId) {
await updateTaskStatus(result.taskId, 'in_progress');
}
return result.taskId;
} else {
console.error('❌ Failed to report task to orchestrator:', response.statusText);
return null;
}
} catch (error) {
console.error('❌ Error reporting task to orchestrator:', error);
return null;
}
}
/**
* Update task status
*/
export async function updateTaskStatus(
taskId: string,
status: 'pending' | 'assigned' | 'in_progress' | 'blocked' | 'completed' | 'failed',
details?: string
): Promise<boolean> {
try {
const response = await fetch(`${TASK_ORCHESTRATOR_URL}/api/tasks/${taskId}/status`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status, details })
});
if (response.ok) {
console.log(`✅ Task ${taskId} updated to ${status}`);
return true;
} else {
console.error(`❌ Failed to update task ${taskId}:`, response.statusText);
return false;
}
} catch (error) {
console.error(`❌ Error updating task ${taskId}:`, error);
return false;
}
}
/**
* Update work progress (e.g., 44/2000 products processed)
*/
export async function updateTaskProgress(
taskId: string,
current: number,
total: number,
details?: string
): Promise<boolean> {
try {
const response = await fetch(`${TASK_ORCHESTRATOR_URL}/api/tasks/${taskId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
metadata: {
workProgress: { current, total }
},
...(details && { details })
})
});
if (response.ok) {
return true;
}
return false;
} catch (error) {
console.error(`❌ Error updating task progress ${taskId}:`, error);
return false;
}
}
/**
* Report that a task has completed successfully
*/
export async function reportTaskComplete(
taskId: string | null,
details: string = 'Task completed successfully'
): Promise<boolean> {
if (!taskId) {
console.warn('⚠️ No taskId provided, skipping completion report');
return false;
}
return await updateTaskStatus(taskId, 'completed', details);
}
/**
* Report that a task has failed
*/
export async function reportTaskFailed(
taskId: string | null,
details: string = 'Task failed'
): Promise<boolean> {
if (!taskId) {
console.warn('⚠️ No taskId provided, skipping failure report');
return false;
}
return await updateTaskStatus(taskId, 'failed', details);
}
/**
* Report that a task is blocked
*/
export async function reportTaskBlocked(
taskId: string | null,
reason: string
): Promise<boolean> {
if (!taskId) {
console.warn('⚠️ No taskId provided, skipping blocked report');
return false;
}
return await updateTaskStatus(taskId, 'blocked', reason);
}
/**
* Convenience function for long-running operations
* Automatically reports start, progress, and completion
*/
export class TaskReporter {
private taskId: string | null = null;
private title: string;
private agentName: string;
constructor(title: string, description: string, agentName: string, priority: 'low' | 'medium' | 'high' | 'critical' = 'medium', metadata: TaskMetadata = {}) {
this.title = title;
this.agentName = agentName;
// Start the task immediately
reportTaskStart(title, description, priority, agentName, metadata).then(taskId => {
this.taskId = taskId;
});
}
async updateProgress(current: number, total: number, details?: string): Promise<void> {
if (this.taskId) {
await updateTaskProgress(this.taskId, current, total, details);
}
}
async complete(details?: string): Promise<void> {
if (this.taskId) {
await reportTaskComplete(this.taskId, details || `${this.title} completed successfully`);
}
}
async fail(details?: string): Promise<void> {
if (this.taskId) {
await reportTaskFailed(this.taskId, details || `${this.title} failed`);
}
}
async block(reason: string): Promise<void> {
if (this.taskId) {
await reportTaskBlocked(this.taskId, reason);
}
}
getTaskId(): string | null {
return this.taskId;
}
}