diff --git a/src/core/task-persistence/taskMetadata.ts b/src/core/task-persistence/taskMetadata.ts index 8044acd8ba0..6c391958fac 100644 --- a/src/core/task-persistence/taskMetadata.ts +++ b/src/core/task-persistence/taskMetadata.ts @@ -27,10 +27,40 @@ export async function taskMetadata({ workspace, }: TaskMetadataOptions) { const taskDir = await getTaskDirectoryPath(globalStoragePath, taskId) + + // Handle edge case where there are no messages at all + if (!messages || messages.length === 0) { + const historyItem: HistoryItem = { + id: taskId, + number: taskNumber, + ts: Date.now(), + task: `Task #${taskNumber} (No messages)`, + tokensIn: 0, + tokensOut: 0, + cacheWrites: 0, + cacheReads: 0, + totalCost: 0, + size: 0, + workspace, + } + return { + historyItem, + tokenUsage: { + totalTokensIn: 0, + totalTokensOut: 0, + totalCacheWrites: 0, + totalCacheReads: 0, + totalCost: 0, + contextTokens: 0, + }, + } + } + const taskMessage = messages[0] // First message is always the task say. const lastRelevantMessage = - messages[findLastIndex(messages, (m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"))] + messages[findLastIndex(messages, (m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"))] || + messages[0] let taskDirSize = taskSizeCache.get(taskDir) @@ -45,11 +75,17 @@ export async function taskMetadata({ const tokenUsage = getApiMetrics(combineApiRequests(combineCommandSequences(messages.slice(1)))) + // Ensure task name is never blank - provide fallback names + let taskName = taskMessage.text?.trim() || "" + if (!taskName) { + taskName = `Task #${taskNumber} (Incomplete)` + } + const historyItem: HistoryItem = { id: taskId, number: taskNumber, ts: lastRelevantMessage.ts, - task: taskMessage.text ?? "", + task: taskName, tokensIn: tokenUsage.totalTokensIn, tokensOut: tokenUsage.totalTokensOut, cacheWrites: tokenUsage.totalCacheWrites,