83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import type { PublicUsage, SubagentDetailsV1 } from './coding-conversation-contracts';
|
|
|
|
const STATUSES = new Set(['queued', 'running', 'complete', 'error', 'aborted', 'skipped']);
|
|
|
|
function recordValue(value: unknown): Record<string, unknown> | null {
|
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
? value as Record<string, unknown>
|
|
: null;
|
|
}
|
|
|
|
function publicUsage(value: unknown): PublicUsage | undefined {
|
|
const usage = recordValue(value);
|
|
if (!usage
|
|
|| typeof usage.inputTokens !== 'number'
|
|
|| typeof usage.outputTokens !== 'number'
|
|
|| !Number.isFinite(usage.inputTokens)
|
|
|| !Number.isFinite(usage.outputTokens)
|
|
|| usage.inputTokens < 0
|
|
|| usage.outputTokens < 0
|
|
|| (usage.cacheReadTokens !== undefined
|
|
&& (typeof usage.cacheReadTokens !== 'number'
|
|
|| !Number.isFinite(usage.cacheReadTokens)
|
|
|| usage.cacheReadTokens < 0))
|
|
|| (usage.cacheWriteTokens !== undefined
|
|
&& (typeof usage.cacheWriteTokens !== 'number'
|
|
|| !Number.isFinite(usage.cacheWriteTokens)
|
|
|| usage.cacheWriteTokens < 0))) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
inputTokens: usage.inputTokens,
|
|
outputTokens: usage.outputTokens,
|
|
...(typeof usage.cacheReadTokens === 'number' ? { cacheReadTokens: usage.cacheReadTokens } : {}),
|
|
...(typeof usage.cacheWriteTokens === 'number' ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),
|
|
};
|
|
}
|
|
|
|
export function projectSubagentDetailsV1(value: unknown): SubagentDetailsV1 | undefined {
|
|
const record = recordValue(value);
|
|
if (!record
|
|
|| record.schema !== 'subagent.v1'
|
|
|| typeof record.dispatchId !== 'string'
|
|
|| !record.dispatchId.trim()
|
|
|| !['single', 'parallel', 'chain'].includes(String(record.mode))
|
|
|| !Array.isArray(record.tasks)
|
|
|| record.tasks.length === 0
|
|
|| record.tasks.length > 8) return undefined;
|
|
const tasks: SubagentDetailsV1['tasks'] = [];
|
|
for (const value of record.tasks) {
|
|
const task = recordValue(value);
|
|
if (!task
|
|
|| typeof task.taskId !== 'string'
|
|
|| !task.taskId.trim()
|
|
|| typeof task.agentId !== 'string'
|
|
|| !task.agentId.trim()
|
|
|| (task.toolProfile !== 'read-only' && task.toolProfile !== 'coding')
|
|
|| !STATUSES.has(String(task.status))
|
|
|| (task.summary !== undefined && typeof task.summary !== 'string')
|
|
|| (task.errorCode !== undefined && typeof task.errorCode !== 'string')) return undefined;
|
|
const usage = task.usage === undefined ? undefined : publicUsage(task.usage);
|
|
if (task.usage !== undefined && !usage) return undefined;
|
|
tasks.push({
|
|
taskId: task.taskId,
|
|
agentId: task.agentId,
|
|
toolProfile: task.toolProfile,
|
|
status: task.status as SubagentDetailsV1['tasks'][number]['status'],
|
|
...(typeof task.summary === 'string' ? { summary: task.summary.slice(0, 4_000) } : {}),
|
|
...(typeof task.errorCode === 'string' ? { errorCode: task.errorCode.slice(0, 64) } : {}),
|
|
...(usage ? { usage } : {}),
|
|
});
|
|
}
|
|
return {
|
|
schema: 'subagent.v1',
|
|
dispatchId: record.dispatchId,
|
|
mode: record.mode as SubagentDetailsV1['mode'],
|
|
tasks,
|
|
};
|
|
}
|
|
|
|
export function subagentDetailsOfResult(value: unknown): SubagentDetailsV1 | undefined {
|
|
return projectSubagentDetailsV1(recordValue(value)?.details);
|
|
}
|