Files

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,
};
}