42 lines
1.6 KiB
TypeScript
42 lines
1.6 KiB
TypeScript
import type { TaskStateDetailsV1 } from '../../contracts';
|
|
|
|
export interface TaskStateToolResult {
|
|
content: Array<{ type: 'text'; text: string }>;
|
|
details: TaskStateDetailsV1;
|
|
}
|
|
|
|
export function projectTaskState(input: unknown): TaskStateToolResult {
|
|
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Task state is invalid');
|
|
const tasks = (input as { tasks?: unknown }).tasks;
|
|
if (!Array.isArray(tasks) || tasks.length === 0 || tasks.length > 100) {
|
|
throw new Error('Task state requires one to one hundred tasks');
|
|
}
|
|
const ids = new Set<string>();
|
|
const projected: TaskStateDetailsV1['tasks'] = tasks.map((candidate) => {
|
|
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
throw new Error('Task state item is invalid');
|
|
}
|
|
const item = candidate as Record<string, unknown>;
|
|
const id = typeof item.id === 'string' ? item.id.trim() : '';
|
|
const title = typeof item.title === 'string' ? item.title.trim() : '';
|
|
if (!id || id.length > 128 || ids.has(id) || !title || title.length > 500
|
|
|| !['pending', 'running', 'complete', 'error'].includes(String(item.status))) {
|
|
throw new Error('Task state item is invalid');
|
|
}
|
|
ids.add(id);
|
|
return {
|
|
id,
|
|
title,
|
|
status: item.status as TaskStateDetailsV1['tasks'][number]['status'],
|
|
};
|
|
});
|
|
const details: TaskStateDetailsV1 = { schema: 'task-state.v1', tasks: projected };
|
|
return {
|
|
content: [{
|
|
type: 'text',
|
|
text: `${projected.filter(({ status }) => status === 'complete').length}/${projected.length} tasks complete`,
|
|
}],
|
|
details,
|
|
};
|
|
}
|