diff --git a/src/core/task-persistence/taskMetadata.ts b/src/core/task-persistence/taskMetadata.ts index 8044acd8ba..1759a72f47 100644 --- a/src/core/task-persistence/taskMetadata.ts +++ b/src/core/task-persistence/taskMetadata.ts @@ -8,6 +8,7 @@ import { combineCommandSequences } from "../../shared/combineCommandSequences" import { getApiMetrics } from "../../shared/getApiMetrics" import { findLastIndex } from "../../shared/array" import { getTaskDirectoryPath } from "../../utils/storage" +import { t } from "../../i18n" const taskSizeCache = new NodeCache({ stdTTL: 30, checkperiod: 5 * 60 }) @@ -27,29 +28,63 @@ export async function taskMetadata({ workspace, }: TaskMetadataOptions) { const taskDir = await getTaskDirectoryPath(globalStoragePath, taskId) - 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"))] + // Determine message availability upfront + const hasMessages = messages && messages.length > 0 - let taskDirSize = taskSizeCache.get(taskDir) + // Pre-calculate all values based on availability + let timestamp: number + let tokenUsage: ReturnType + let taskDirSize: number + let taskMessage: ClineMessage | undefined - if (taskDirSize === undefined) { - try { - taskDirSize = await getFolderSize.loose(taskDir) - taskSizeCache.set(taskDir, taskDirSize) - } catch (error) { - taskDirSize = 0 + if (!hasMessages) { + // Handle no messages case + timestamp = Date.now() + tokenUsage = { + totalTokensIn: 0, + totalTokensOut: 0, + totalCacheWrites: 0, + totalCacheReads: 0, + totalCost: 0, + contextTokens: 0, } - } + taskDirSize = 0 + } else { + // Handle messages case + 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"))] || + taskMessage + + timestamp = lastRelevantMessage.ts + + tokenUsage = getApiMetrics(combineApiRequests(combineCommandSequences(messages.slice(1)))) - const tokenUsage = getApiMetrics(combineApiRequests(combineCommandSequences(messages.slice(1)))) + // Get task directory size + const cachedSize = taskSizeCache.get(taskDir) + + if (cachedSize === undefined) { + try { + taskDirSize = await getFolderSize.loose(taskDir) + taskSizeCache.set(taskDir, taskDirSize) + } catch (error) { + taskDirSize = 0 + } + } else { + taskDirSize = cachedSize + } + } + // Create historyItem once with pre-calculated values const historyItem: HistoryItem = { id: taskId, number: taskNumber, - ts: lastRelevantMessage.ts, - task: taskMessage.text ?? "", + ts: timestamp, + task: hasMessages + ? taskMessage!.text?.trim() || t("common:tasks.incomplete", { taskNumber }) + : t("common:tasks.no_messages", { taskNumber }), tokensIn: tokenUsage.totalTokensIn, tokensOut: tokenUsage.totalTokensOut, cacheWrites: tokenUsage.totalCacheWrites, diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index d372a57ce6..04733b0cb6 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -101,7 +101,9 @@ }, "tasks": { "canceled": "Error de tasca: Ha estat aturada i cancel·lada per l'usuari.", - "deleted": "Fallada de tasca: Ha estat aturada i eliminada per l'usuari." + "deleted": "Fallada de tasca: Ha estat aturada i eliminada per l'usuari.", + "incomplete": "Tasca #{{taskNumber}} (Incompleta)", + "no_messages": "Tasca #{{taskNumber}} (Sense missatges)" }, "storage": { "prompt_custom_path": "Introdueix una ruta d'emmagatzematge personalitzada per a l'historial de converses o deixa-ho buit per utilitzar la ubicació predeterminada", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index d34d266e44..cf9f363c57 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Aufgabenfehler: Die Aufgabe wurde vom Benutzer gestoppt und abgebrochen.", - "deleted": "Aufgabenfehler: Die Aufgabe wurde vom Benutzer gestoppt und gelöscht." + "deleted": "Aufgabenfehler: Die Aufgabe wurde vom Benutzer gestoppt und gelöscht.", + "incomplete": "Aufgabe #{{taskNumber}} (Unvollständig)", + "no_messages": "Aufgabe #{{taskNumber}} (Keine Nachrichten)" }, "storage": { "prompt_custom_path": "Gib den benutzerdefinierten Speicherpfad für den Gesprächsverlauf ein, leer lassen für Standardspeicherort", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 0de1a25354..63468914ee 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Task error: It was stopped and canceled by the user.", - "deleted": "Task failure: It was stopped and deleted by the user." + "deleted": "Task failure: It was stopped and deleted by the user.", + "incomplete": "Task #{{taskNumber}} (Incomplete)", + "no_messages": "Task #{{taskNumber}} (No messages)" }, "storage": { "prompt_custom_path": "Enter custom conversation history storage path, leave empty to use default location", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 6da86eb225..97076b442c 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Error de tarea: Fue detenida y cancelada por el usuario.", - "deleted": "Fallo de tarea: Fue detenida y eliminada por el usuario." + "deleted": "Fallo de tarea: Fue detenida y eliminada por el usuario.", + "incomplete": "Tarea #{{taskNumber}} (Incompleta)", + "no_messages": "Tarea #{{taskNumber}} (Sin mensajes)" }, "storage": { "prompt_custom_path": "Ingresa la ruta de almacenamiento personalizada para el historial de conversaciones, déjala vacía para usar la ubicación predeterminada", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 1875bb94a7..c9531d07c3 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Erreur de tâche : Elle a été arrêtée et annulée par l'utilisateur.", - "deleted": "Échec de la tâche : Elle a été arrêtée et supprimée par l'utilisateur." + "deleted": "Échec de la tâche : Elle a été arrêtée et supprimée par l'utilisateur.", + "incomplete": "Tâche #{{taskNumber}} (Incomplète)", + "no_messages": "Tâche #{{taskNumber}} (Aucun message)" }, "storage": { "prompt_custom_path": "Entrez le chemin de stockage personnalisé pour l'historique des conversations, laissez vide pour utiliser l'emplacement par défaut", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index b991b167fe..20e0c1f518 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "टास्क त्रुटि: इसे उपयोगकर्ता द्वारा रोका और रद्द किया गया था।", - "deleted": "टास्क विफलता: इसे उपयोगकर्ता द्वारा रोका और हटाया गया था।" + "deleted": "टास्क विफलता: इसे उपयोगकर्ता द्वारा रोका और हटाया गया था।", + "incomplete": "टास्क #{{taskNumber}} (अधूरा)", + "no_messages": "टास्क #{{taskNumber}} (कोई संदेश नहीं)" }, "storage": { "prompt_custom_path": "वार्तालाप इतिहास के लिए कस्टम स्टोरेज पाथ दर्ज करें, डिफ़ॉल्ट स्थान का उपयोग करने के लिए खाली छोड़ दें", diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index f961b88bed..319c3f9674 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Error tugas: Dihentikan dan dibatalkan oleh pengguna.", - "deleted": "Kegagalan tugas: Dihentikan dan dihapus oleh pengguna." + "deleted": "Kegagalan tugas: Dihentikan dan dihapus oleh pengguna.", + "incomplete": "Tugas #{{taskNumber}} (Tidak lengkap)", + "no_messages": "Tugas #{{taskNumber}} (Tidak ada pesan)" }, "storage": { "prompt_custom_path": "Masukkan path penyimpanan riwayat percakapan kustom, biarkan kosong untuk menggunakan lokasi default", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index 0cf42e2cbd..ea919162e4 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Errore attività: È stata interrotta e annullata dall'utente.", - "deleted": "Fallimento attività: È stata interrotta ed eliminata dall'utente." + "deleted": "Fallimento attività: È stata interrotta ed eliminata dall'utente.", + "incomplete": "Attività #{{taskNumber}} (Incompleta)", + "no_messages": "Attività #{{taskNumber}} (Nessun messaggio)" }, "storage": { "prompt_custom_path": "Inserisci il percorso di archiviazione personalizzato per la cronologia delle conversazioni, lascia vuoto per utilizzare la posizione predefinita", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index 9e1107332b..916f9b2f45 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "タスクエラー:ユーザーによって停止およびキャンセルされました。", - "deleted": "タスク失敗:ユーザーによって停止および削除されました。" + "deleted": "タスク失敗:ユーザーによって停止および削除されました。", + "incomplete": "タスク #{{taskNumber}} (未完了)", + "no_messages": "タスク #{{taskNumber}} (メッセージなし)" }, "storage": { "prompt_custom_path": "会話履歴のカスタムストレージパスを入力してください。デフォルトの場所を使用する場合は空のままにしてください", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 51614261c1..bad3facfd6 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "작업 오류: 사용자에 의해 중지 및 취소되었습니다.", - "deleted": "작업 실패: 사용자에 의해 중지 및 삭제되었습니다." + "deleted": "작업 실패: 사용자에 의해 중지 및 삭제되었습니다.", + "incomplete": "작업 #{{taskNumber}} (미완료)", + "no_messages": "작업 #{{taskNumber}} (메시지 없음)" }, "storage": { "prompt_custom_path": "대화 내역을 위한 사용자 지정 저장 경로를 입력하세요. 기본 위치를 사용하려면 비워두세요", diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index 973f7331a8..a90ff3d00f 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Taakfout: gestopt en geannuleerd door gebruiker.", - "deleted": "Taakfout: gestopt en verwijderd door gebruiker." + "deleted": "Taakfout: gestopt en verwijderd door gebruiker.", + "incomplete": "Taak #{{taskNumber}} (Onvolledig)", + "no_messages": "Taak #{{taskNumber}} (Geen berichten)" }, "storage": { "prompt_custom_path": "Voer een aangepast opslagpad voor gespreksgeschiedenis in, laat leeg voor standaardlocatie", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index 71a044ba40..d6cb5cb809 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Błąd zadania: Zostało zatrzymane i anulowane przez użytkownika.", - "deleted": "Niepowodzenie zadania: Zostało zatrzymane i usunięte przez użytkownika." + "deleted": "Niepowodzenie zadania: Zostało zatrzymane i usunięte przez użytkownika.", + "incomplete": "Zadanie #{{taskNumber}} (Niekompletne)", + "no_messages": "Zadanie #{{taskNumber}} (Brak wiadomości)" }, "storage": { "prompt_custom_path": "Wprowadź niestandardową ścieżkę przechowywania dla historii konwersacji lub pozostaw puste, aby użyć lokalizacji domyślnej", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index f67383024a..941dd0f86d 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -101,7 +101,9 @@ }, "tasks": { "canceled": "Erro na tarefa: Foi interrompida e cancelada pelo usuário.", - "deleted": "Falha na tarefa: Foi interrompida e excluída pelo usuário." + "deleted": "Falha na tarefa: Foi interrompida e excluída pelo usuário.", + "incomplete": "Tarefa #{{taskNumber}} (Incompleta)", + "no_messages": "Tarefa #{{taskNumber}} (Sem mensagens)" }, "storage": { "prompt_custom_path": "Digite o caminho de armazenamento personalizado para o histórico de conversas, deixe em branco para usar o local padrão", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 8a3798307c..646d5d3b6b 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Ошибка задачи: Она была остановлена и отменена пользователем.", - "deleted": "Сбой задачи: Она была остановлена и удалена пользователем." + "deleted": "Сбой задачи: Она была остановлена и удалена пользователем.", + "incomplete": "Задача #{{taskNumber}} (Незавершенная)", + "no_messages": "Задача #{{taskNumber}} (Нет сообщений)" }, "storage": { "prompt_custom_path": "Введите пользовательский путь хранения истории разговоров, оставьте пустым для использования расположения по умолчанию", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 9902896503..368934fdcc 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Görev hatası: Kullanıcı tarafından durduruldu ve iptal edildi.", - "deleted": "Görev başarısız: Kullanıcı tarafından durduruldu ve silindi." + "deleted": "Görev başarısız: Kullanıcı tarafından durduruldu ve silindi.", + "incomplete": "Görev #{{taskNumber}} (Tamamlanmamış)", + "no_messages": "Görev #{{taskNumber}} (Mesaj yok)" }, "storage": { "prompt_custom_path": "Konuşma geçmişi için özel depolama yolunu girin, varsayılan konumu kullanmak için boş bırakın", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 93fa9b689b..9d43acc45a 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "Lỗi nhiệm vụ: Nó đã bị dừng và hủy bởi người dùng.", - "deleted": "Nhiệm vụ thất bại: Nó đã bị dừng và xóa bởi người dùng." + "deleted": "Nhiệm vụ thất bại: Nó đã bị dừng và xóa bởi người dùng.", + "incomplete": "Nhiệm vụ #{{taskNumber}} (Chưa hoàn thành)", + "no_messages": "Nhiệm vụ #{{taskNumber}} (Không có tin nhắn)" }, "storage": { "prompt_custom_path": "Nhập đường dẫn lưu trữ tùy chỉnh cho lịch sử hội thoại, để trống để sử dụng vị trí mặc định", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index f2fedd3c1b..d21c9ef9b7 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -102,7 +102,9 @@ }, "tasks": { "canceled": "任务错误:它已被用户停止并取消。", - "deleted": "任务失败:它已被用户停止并删除。" + "deleted": "任务失败:它已被用户停止并删除。", + "incomplete": "任务 #{{taskNumber}} (未完成)", + "no_messages": "任务 #{{taskNumber}} (无消息)" }, "storage": { "prompt_custom_path": "输入自定义会话历史存储路径,留空以使用默认位置", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 43f44a47b3..164df43cc8 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -97,7 +97,9 @@ }, "tasks": { "canceled": "工作錯誤:它已被使用者停止並取消。", - "deleted": "工作失敗:它已被使用者停止並刪除。" + "deleted": "工作失敗:它已被使用者停止並刪除。", + "incomplete": "工作 #{{taskNumber}} (未完成)", + "no_messages": "工作 #{{taskNumber}} (無訊息)" }, "storage": { "prompt_custom_path": "輸入自訂會話歷史儲存路徑,留空以使用預設位置",