import type { ClusterTaskKind, CompleteTaskBody, DescribeTaskResult, TaskErrorResult, } from '../shared/completeTask.js'; import type {DetectionResultJson, DetectionTask} from './types.js'; export type TaskCompleteOutcome = | {status: 'done'; kind: 'detect'; results: DetectionResultJson[]} | {status: 'done'; kind: 'describe'; description: string} | {status: 'error'; error: string}; function parseErrorResult(result: unknown): string { if (result === null || typeof result !== 'object') { throw new Error("Error tasks must include result: { error: string }"); } const error = (result as TaskErrorResult).error; if (typeof error !== 'string' || !error.trim()) { throw new Error("Error tasks must include a non-empty result.error"); } return error.trim(); } function parseDescribeResult(result: unknown): string { if (result === null || typeof result !== 'object') { throw new Error("Describe tasks must include result: { description: string }"); } const description = (result as DescribeTaskResult).description; if (typeof description !== 'string' || !description.trim()) { throw new Error("Describe tasks must include a non-empty result.description"); } return description.trim(); } function parseDetectResult(result: unknown): DetectionResultJson[] { if (!Array.isArray(result)) { throw new Error("Detect tasks must include result as a detection array"); } return result as DetectionResultJson[]; } export function parseCompleteTaskBody( task: DetectionTask, body: CompleteTaskBody, hostModel?: string, ): TaskCompleteOutcome { if (!body.kind) { throw new Error("Complete payload must include 'kind'"); } if (body.kind !== task.kind) { throw new Error( `Task ${task.id} is '${task.kind}' but complete payload kind is '${body.kind}'`, ); } if (body.status === 'error') { return {status: 'error', error: parseErrorResult(body.result)}; } const model = body.model?.trim() || hostModel; if (!model) { throw new Error("Complete payload must include a 'model' field"); } return parseDoneResult(body.kind, body.result); } function parseDoneResult( kind: ClusterTaskKind, result: unknown, ): Extract { if (kind === 'describe') { return {status: 'done', kind: 'describe', description: parseDescribeResult(result)}; } if (kind === 'detect') { return {status: 'done', kind: 'detect', results: parseDetectResult(result)}; } throw new Error(`Unsupported task kind '${kind as string}'`); }