diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 23df05cc626..4d446daeaa8 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -18,6 +18,7 @@ import { formatPathTooltip } from "@src/utils/formatPathTooltip" import { ToolUseBlock, ToolUseBlockHeader } from "../common/ToolUseBlock" import UpdateTodoListToolBlock from "./UpdateTodoListToolBlock" +import { TodoChangeDisplay } from "./TodoChangeDisplay" import CodeAccordian from "../common/CodeAccordian" import MarkdownBlock from "../common/MarkdownBlock" import { ReasoningBlock } from "./ReasoningBlock" @@ -62,6 +63,39 @@ import { import { cn } from "@/lib/utils" import { PathTooltip } from "../ui/PathTooltip" +// Helper function to get previous todos before a specific message +function getPreviousTodos(messages: ClineMessage[], currentMessageTs: number): any[] { + // Find the previous updateTodoList message before the current one + const previousUpdateIndex = messages + .slice() + .reverse() + .findIndex((msg) => { + if (msg.ts >= currentMessageTs) return false + if (msg.type === "ask" && msg.ask === "tool") { + try { + const tool = JSON.parse(msg.text || "{}") + return tool.tool === "updateTodoList" + } catch { + return false + } + } + return false + }) + + if (previousUpdateIndex !== -1) { + const previousMessage = messages.slice().reverse()[previousUpdateIndex] + try { + const tool = JSON.parse(previousMessage.text || "{}") + return tool.todos || [] + } catch { + return [] + } + } + + // If no previous updateTodoList message, return empty array + return [] +} + interface ChatRowProps { message: ClineMessage lastModifiedMessage?: ClineMessage @@ -127,11 +161,10 @@ export const ChatRowContent = ({ onFollowUpUnmount, onBatchFileResponse, isFollowUpAnswered, - editable, }: ChatRowContentProps) => { const { t } = useTranslation() - const { mcpServers, alwaysAllowMcp, currentCheckpoint, mode, apiConfiguration } = useExtensionState() + const { mcpServers, alwaysAllowMcp, currentCheckpoint, mode, apiConfiguration, clineMessages } = useExtensionState() const { info: model } = useSelectedModel(apiConfiguration) const [isEditing, setIsEditing] = useState(false) const [editedContent, setEditedContent] = useState("") @@ -503,18 +536,11 @@ export const ChatRowContent = ({ } case "updateTodoList" as any: { const todos = (tool as any).todos || [] - return ( - { - if (typeof vscode !== "undefined" && vscode?.postMessage) { - vscode.postMessage({ type: "updateTodoList", payload: { todos: updatedTodos } }) - } - }} - editable={editable && isLast} - /> - ) + + // Get previous todos from the latest todos in the task context + const previousTodos = getPreviousTodos(clineMessages, message.ts) + + return } case "newFileCreated": return ( diff --git a/webview-ui/src/components/chat/CloudTaskButton.tsx b/webview-ui/src/components/chat/CloudTaskButton.tsx index 1cc2d9d675f..672bf020bb1 100644 --- a/webview-ui/src/components/chat/CloudTaskButton.tsx +++ b/webview-ui/src/components/chat/CloudTaskButton.tsx @@ -1,14 +1,15 @@ import { useState, useEffect, useCallback } from "react" import { useTranslation } from "react-i18next" -import { CloudUpload, Copy, Check } from "lucide-react" +import { Copy, Check, CloudUploadIcon } from "lucide-react" import QRCode from "qrcode" import type { HistoryItem } from "@roo-code/types" import { useExtensionState } from "@/context/ExtensionStateContext" import { useCopyToClipboard } from "@/utils/clipboard" -import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, Input, StandardTooltip } from "@/components/ui" +import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, Input } from "@/components/ui" import { vscode } from "@/utils/vscode" +import { LucideIconButton } from "./LucideIconButton" interface CloudTaskButtonProps { item?: HistoryItem @@ -83,18 +84,12 @@ export const CloudTaskButton = ({ item, disabled = false }: CloudTaskButtonProps return ( <> - - - + setDialogOpen(true)}> diff --git a/webview-ui/src/components/chat/LucideIconButton.tsx b/webview-ui/src/components/chat/LucideIconButton.tsx new file mode 100644 index 00000000000..5e5137f16be --- /dev/null +++ b/webview-ui/src/components/chat/LucideIconButton.tsx @@ -0,0 +1,50 @@ +import { cn } from "@src/lib/utils" +import { Button, StandardTooltip } from "@src/components/ui" +import { Loader2, LucideIcon } from "lucide-react" + +interface LucideIconButtonProps extends React.ButtonHTMLAttributes { + icon: LucideIcon + title: string + disabled?: boolean + tooltip?: boolean + isLoading?: boolean + style?: React.CSSProperties +} + +export const LucideIconButton: React.FC = ({ + icon, + title, + className, + disabled, + tooltip = true, + isLoading, + onClick, + style, + ...props +}) => { + const Icon = icon + return ( + + + + ) +} diff --git a/webview-ui/src/components/chat/Mention.tsx b/webview-ui/src/components/chat/Mention.tsx index 764c0272031..00130756554 100644 --- a/webview-ui/src/components/chat/Mention.tsx +++ b/webview-ui/src/components/chat/Mention.tsx @@ -21,7 +21,7 @@ export const Mention = ({ text, withShadow = false }: MentionProps) => { return ( vscode.postMessage({ type: "openMention", text: part })}> @{part} diff --git a/webview-ui/src/components/chat/ShareButton.tsx b/webview-ui/src/components/chat/ShareButton.tsx index 74bb25a21e5..06aa46a459b 100644 --- a/webview-ui/src/components/chat/ShareButton.tsx +++ b/webview-ui/src/components/chat/ShareButton.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react" import { useTranslation } from "react-i18next" -import { Share2 } from "lucide-react" +import { Share2Icon } from "lucide-react" import { type HistoryItem, type ShareVisibility, TelemetryEventName } from "@roo-code/types" @@ -10,7 +10,6 @@ import { useExtensionState } from "@/context/ExtensionStateContext" import { useCloudUpsell } from "@/hooks/useCloudUpsell" import { CloudUpsellDialog } from "@/components/cloud/CloudUpsellDialog" import { - Button, Popover, PopoverContent, PopoverTrigger, @@ -20,14 +19,14 @@ import { CommandGroup, StandardTooltip, } from "@/components/ui" +import { LucideIconButton } from "./LucideIconButton" interface ShareButtonProps { item?: HistoryItem disabled?: boolean - showLabel?: boolean } -export const ShareButton = ({ item, disabled = false, showLabel = false }: ShareButtonProps) => { +export const ShareButton = ({ item, disabled = false }: ShareButtonProps) => { const [shareDropdownOpen, setShareDropdownOpen] = useState(false) const [shareSuccess, setShareSuccess] = useState<{ visibility: ShareVisibility; url: string } | null>(null) const [wasConnectInitiatedFromShare, setWasConnectInitiatedFromShare] = useState(false) @@ -153,20 +152,13 @@ export const ShareButton = ({ item, disabled = false, showLabel = false }: Share - + data-testid="share-button" + title={t("chat:task.share")}> @@ -221,22 +213,12 @@ export const ShareButton = ({ item, disabled = false, showLabel = false }: Share ) : ( - - - + )} {/* Connect to Cloud Modal */} diff --git a/webview-ui/src/components/chat/TaskActions.tsx b/webview-ui/src/components/chat/TaskActions.tsx index a6954c5ef3f..70a8c62c030 100644 --- a/webview-ui/src/components/chat/TaskActions.tsx +++ b/webview-ui/src/components/chat/TaskActions.tsx @@ -7,9 +7,10 @@ import { vscode } from "@/utils/vscode" import { useCopyToClipboard } from "@/utils/clipboard" import { DeleteTaskDialog } from "../history/DeleteTaskDialog" -import { IconButton } from "./IconButton" import { ShareButton } from "./ShareButton" import { CloudTaskButton } from "./CloudTaskButton" +import { CopyIcon, DownloadIcon, Trash2Icon } from "lucide-react" +import { LucideIconButton } from "./LucideIconButton" interface TaskActionsProps { item?: HistoryItem @@ -19,40 +20,38 @@ interface TaskActionsProps { export const TaskActions = ({ item, buttonsDisabled }: TaskActionsProps) => { const [deleteTaskId, setDeleteTaskId] = useState(null) const { t } = useTranslation() - const { copyWithFeedback, showCopyFeedback } = useCopyToClipboard() + const { copyWithFeedback } = useCopyToClipboard() return ( -
- + vscode.postMessage({ type: "exportCurrentTask" })} /> + {item?.task && ( - copyWithFeedback(item.task, e)} /> )} {!!item?.size && item.size > 0 && ( <> -
- { - e.stopPropagation() - - if (e.shiftKey) { - vscode.postMessage({ type: "deleteTaskWithId", text: item.id }) - } else { - setDeleteTaskId(item.id) - } - }} - /> -
+ { + e.stopPropagation() + if (e.shiftKey) { + vscode.postMessage({ type: "deleteTaskWithId", text: item.id }) + } else { + setDeleteTaskId(item.id) + } + }} + /> {deleteTaskId && ( { )} )} - +
) diff --git a/webview-ui/src/components/chat/TaskHeader.tsx b/webview-ui/src/components/chat/TaskHeader.tsx index 71a4fbba828..242db5bb911 100644 --- a/webview-ui/src/components/chat/TaskHeader.tsx +++ b/webview-ui/src/components/chat/TaskHeader.tsx @@ -3,7 +3,15 @@ import { useTranslation } from "react-i18next" import { useCloudUpsell } from "@src/hooks/useCloudUpsell" import { CloudUpsellDialog } from "@src/components/cloud/CloudUpsellDialog" import DismissibleUpsell from "@src/components/common/DismissibleUpsell" -import { FoldVertical, ChevronUp, ChevronDown } from "lucide-react" +import { + ChevronUp, + ChevronDown, + SquarePen, + Coins, + HardDriveDownload, + HardDriveUpload, + FoldVerticalIcon, +} from "lucide-react" import prettyBytes from "pretty-bytes" import type { ClineMessage } from "@roo-code/types" @@ -23,6 +31,7 @@ import { TaskActions } from "./TaskActions" import { ContextWindowProgress } from "./ContextWindowProgress" import { Mention } from "./Mention" import { TodoListDisplay } from "./TodoListDisplay" +import { LucideIconButton } from "./LucideIconButton" export interface TaskHeaderProps { task: ClineMessage @@ -87,20 +96,18 @@ const TaskHeader = ({ const contextWindow = model?.contextWindow || 1 const condenseButton = ( - - - + currentTaskItem && handleCondenseContext(currentTaskItem.id)} + /> ) const hasTodos = todos && Array.isArray(todos) && todos.length > 0 return ( -
+
{showLongRunningTaskMessage && !isTaskComplete && ( { + // Don't expand if clicking on todos section + if (e.target instanceof Element && e.target.closest("[data-todo-list]")) { + return + } + // Don't expand if clicking on buttons or interactive elements if ( e.target instanceof Element && @@ -142,12 +154,14 @@ const TaskHeader = ({ }}>
-
+
{isTaskExpanded && {t("chat:task.title")}} {!isTaskExpanded && ( -
- {t("chat:task.title")} - +
+ + + +
)}
@@ -156,7 +170,11 @@ const TaskHeader = ({
@@ -166,6 +184,7 @@ const TaskHeader = ({
e.stopPropagation()}> + @@ -220,7 +239,7 @@ const TaskHeader = ({ className="text-vscode-font-size overflow-y-auto break-words break-anywhere relative">
{task.images && task.images.length > 0 && } -
- +
e.stopPropagation()}> + +
+ +
+
{contextWindow > 0 && ( - - - - @@ -299,10 +328,10 @@ const TaskHeader = ({ {!!totalCost && ( - - @@ -311,24 +340,22 @@ const TaskHeader = ({ {/* Size display */} {!!currentTaskItem?.size && currentTaskItem.size > 0 && ( - - + )}
{t("chat:task.contextWindow")} -
+
+
-
+ {t("chat:task.tokens")} +
{typeof tokensIn === "number" && tokensIn > 0 && ( ↑ {formatLargeNumber(tokensIn)} @@ -281,16 +304,22 @@ const TaskHeader = ({ {((typeof cacheReads === "number" && cacheReads > 0) || (typeof cacheWrites === "number" && cacheWrites > 0)) && (
+ {t("chat:task.cache")} +
{typeof cacheWrites === "number" && cacheWrites > 0 && ( - ↑ {formatLargeNumber(cacheWrites)} + <> + + {formatLargeNumber(cacheWrites)} + )} {typeof cacheReads === "number" && cacheReads > 0 && ( - ↓ {formatLargeNumber(cacheReads)} + <> + + {formatLargeNumber(cacheReads)} + )}
+ {t("chat:task.apiCost")} + ${totalCost?.toFixed(2)}
+ {t("chat:task.size")} {prettyBytes(currentTaskItem.size)} + {prettyBytes(currentTaskItem.size)} +
- - {/* Footer with task management buttons */} -
e.stopPropagation()}> - -
)} + {/* Todo list - always shown at bottom when todos exist */} + {hasTodos && }
-
) diff --git a/webview-ui/src/components/chat/TodoChangeDisplay.tsx b/webview-ui/src/components/chat/TodoChangeDisplay.tsx new file mode 100644 index 00000000000..0525bf64ee5 --- /dev/null +++ b/webview-ui/src/components/chat/TodoChangeDisplay.tsx @@ -0,0 +1,131 @@ +import { t } from "i18next" +import { ArrowRight, Check, ListChecks, SquareDashed } from "lucide-react" + +type TodoStatus = "completed" | "in_progress" | "pending" + +interface TodoItem { + id?: string + content: string + status?: TodoStatus | string +} + +interface TodoChangeDisplayProps { + previousTodos: TodoItem[] + newTodos: TodoItem[] +} + +interface TodoGroup { + todos: TodoItem[] + status: TodoStatus | null + keyPrefix: string + className?: string +} + +function getTodoIcon(status: TodoStatus | null) { + switch (status) { + case "completed": + return + case "in_progress": + return + default: + return + } +} + +function TodoList({ todos, status, keyPrefix, className }: TodoGroup) { + if (todos.length === 0) return null + + return ( +
    + {todos.map((todo) => { + const icon = getTodoIcon(status) + return ( +
  • + {icon} + {todo.content} +
  • + ) + })} +
+ ) +} + +export function TodoChangeDisplay({ previousTodos, newTodos }: TodoChangeDisplayProps) { + const isInitialState = previousTodos.length === 0 + + // Determine which todos to display + let todoGroups: TodoGroup[] + + if (isInitialState && newTodos.length > 0) { + // For initial state, show all todos grouped by status + todoGroups = [ + { + todos: newTodos.filter((todo) => !todo.status || todo.status === "pending"), + status: null, + keyPrefix: "pending", + }, + { + todos: newTodos.filter((todo) => todo.status === "in_progress"), + status: "in_progress", + keyPrefix: "in-progress", + className: "text-vscode-charts-yellow", + }, + { + todos: newTodos.filter((todo) => todo.status === "completed"), + status: "completed", + keyPrefix: "completed", + }, + ] + } else { + // For updates, only show changes + const completedTodos = newTodos.filter((newTodo) => { + if (newTodo.status !== "completed") return false + const previousTodo = previousTodos.find((p) => p.id === newTodo.id || p.content === newTodo.content) + return !previousTodo || previousTodo.status !== "completed" + }) + + const startedTodos = newTodos.filter((newTodo) => { + if (newTodo.status !== "in_progress") return false + const previousTodo = previousTodos.find((p) => p.id === newTodo.id || p.content === newTodo.content) + return !previousTodo || previousTodo.status !== "in_progress" + }) + + todoGroups = [ + { + todos: completedTodos, + status: "completed", + keyPrefix: "completed", + }, + { + todos: startedTodos, + status: "in_progress", + keyPrefix: "started", + className: "text-vscode-charts-yellow", + }, + ] + } + + // If no todos to display, don't render anything + if (todoGroups.every((group) => group.todos.length === 0)) { + return null + } + + return ( +
+
+ + + {t("chat:todo.updated")} + +
+ +
+ {todoGroups.map((group, index) => ( + + ))} +
+
+ ) +} diff --git a/webview-ui/src/components/chat/TodoListDisplay.tsx b/webview-ui/src/components/chat/TodoListDisplay.tsx index c9a4d8f4d04..f2dbbc4d80d 100644 --- a/webview-ui/src/components/chat/TodoListDisplay.tsx +++ b/webview-ui/src/components/chat/TodoListDisplay.tsx @@ -1,5 +1,21 @@ +import { cn } from "@/lib/utils" +import { t } from "i18next" +import { ArrowRight, Check, ListChecks, SquareDashed } from "lucide-react" import { useState, useRef, useMemo, useEffect } from "react" +type TodoStatus = "completed" | "in_progress" | "pending" + +function getTodoIcon(status: TodoStatus | null) { + switch (status) { + case "completed": + return + case "in_progress": + return + default: + return + } +} + export function TodoListDisplay({ todos }: { todos: any[] }) { const [isCollapsed, setIsCollapsed] = useState(true) const ulRef = useRef(null) @@ -37,317 +53,50 @@ export function TodoListDisplay({ todos }: { todos: any[] }) { const allCompleted = completedCount === totalCount && totalCount > 0 - // Create the status icon for the most important todo - const getMostImportantTodoIcon = () => { - if (allCompleted) { - return ( - - ) - } - - if (!mostImportantTodo) { - return ( - - ) - } - - if (mostImportantTodo.status === "completed") { - return ( - - ) - } - - if (mostImportantTodo.status === "in_progress") { - return ( - - ) - } - - // Default not-started todo - return ( - - ) - } - return ( -
+
setIsCollapsed((v) => !v)}> - {getMostImportantTodoIcon()} - - {allCompleted ? "All tasks completed!" : mostImportantTodo?.content || "No pending tasks"} + + + {isCollapsed + ? allCompleted + ? t("chat:todo.complete", { total: completedCount }) + : mostImportantTodo?.content // show current todo while not done + : t("chat:todo.partial", { completed: completedCount, total: totalCount })} -
- - + {isCollapsed && completedCount < totalCount && ( +
{completedCount}/{totalCount} - -
+
+ )}
- {/* Floating panel for expanded state */} + {/* Inline expanded list */} {!isCollapsed && ( - <> - {/* Backdrop */} -
setIsCollapsed(true)} - /> - {/* Floating panel */} -
- {/* Panel header */} -
-
- - Todo List - - {completedCount}/{totalCount} - -
- { - e.stopPropagation() - setIsCollapsed(true) - }} - onMouseEnter={(e) => { - e.currentTarget.style.opacity = "1" - e.currentTarget.style.background = "var(--vscode-toolbar-hoverBackground)" - }} - onMouseLeave={(e) => { - e.currentTarget.style.opacity = "0.7" - e.currentTarget.style.background = "transparent" - }} - /> -
- {/* Todo list */} -
    - {todos.map((todo: any, idx: number) => { - let icon - if (todo.status === "completed") { - icon = ( - - ) - } else if (todo.status === "in_progress") { - icon = ( - - ) - } else { - icon = ( - - ) - } - return ( -
  • (itemRefs.current[idx] = el)} - style={{ - marginBottom: 8, - display: "flex", - alignItems: "flex-start", - minHeight: 20, - lineHeight: "1.4", - }}> - {icon} - - {todo.content} - -
  • - ) - })} -
-
- +
    + {todos.map((todo: any, idx: number) => { + const icon = getTodoIcon(todo.status as TodoStatus) + return ( +
  • (itemRefs.current[idx] = el)} + className={cn( + "font-light flex flex-row gap-2 items-start min-h-[20px] leading-normal mb-2", + todo.status === "in_progress" && "text-vscode-charts-yellow", + todo.status !== "in_progress" && todo.status !== "completed" && "opacity-60", + )}> + {icon} + {todo.content} +
  • + ) + })} +
)}
) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index f4ddb8becef..63c2ffdc6b2 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -423,5 +423,12 @@ "terminal": "Terminal", "url": "Enganxa la URL per obtenir-ne el contingut" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} de {{total}} tasques pendents fetes", + "complete": "{{total}} tasques pendents fetes", + "updated": "S'ha actualitzat la llista de tasques pendents", + "completed": "Completat", + "started": "Iniciat" + } } diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 09366e7493a..d6347886068 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo möchte einen Slash-Befehl ausführen", "didRun": "Roo hat einen Slash-Befehl ausgeführt" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} von {{total}} To-Dos erledigt", + "complete": "{{total}} To-Dos erledigt", + "updated": "Die To-Do-Liste wurde aktualisiert", + "completed": "Abgeschlossen", + "started": "Gestartet" + } } diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 959dff03218..7e03a008d63 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -414,5 +414,12 @@ "problems": "Problems", "terminal": "Terminal", "url": "Paste URL to fetch contents" + }, + "todo": { + "partial": "{{completed}} of {{total}} to-dos done", + "complete": "{{total}} to-dos done", + "updated": "Updated the to-do list", + "completed": "Completed", + "started": "Started" } } diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 95d8838b6c1..a9b54bfccc1 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo quiere ejecutar un comando slash", "didRun": "Roo ejecutó un comando slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} de {{total}} tareas pendientes realizadas", + "complete": "{{total}} tareas pendientes realizadas", + "updated": "Se actualizó la lista de tareas pendientes", + "completed": "Completado", + "started": "Iniciado" + } } diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 6eb4161b690..8d5374d3110 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo veut exécuter une commande slash", "didRun": "Roo a exécuté une commande slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} sur {{total}} tâches terminées", + "complete": "{{total}} tâches terminées", + "updated": "La liste des tâches a été mise à jour", + "completed": "Terminé", + "started": "Commencé" + } } diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 30b5f374319..d3f76ec7a0a 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo एक स्लैश कमांड चलाना चाहता है", "didRun": "Roo ने एक स्लैश कमांड चलाया" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{total}} में से {{completed}} टू-डू हो गए", + "complete": "{{total}} टू-डू हो गए", + "updated": "टू-डू सूची अपडेट की गई", + "completed": "पूरा हुआ", + "started": "शुरू हुआ" + } } diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 1745c8981c8..7c1c5a3e7f2 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -429,5 +429,12 @@ "wantsToRun": "Roo ingin menjalankan perintah slash", "didRun": "Roo telah menjalankan perintah slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} dari {{total}} to-do selesai", + "complete": "{{total}} to-do selesai", + "updated": "Memperbarui daftar to-do", + "completed": "Selesai", + "started": "Dimulai" + } } diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 22afc218415..df24cd24f57 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo vuole eseguire un comando slash", "didRun": "Roo ha eseguito un comando slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} di {{total}} cose da fare completate", + "complete": "{{total}} cose da fare completate", + "updated": "Aggiornata la lista delle cose da fare", + "completed": "Completato", + "started": "Iniziato" + } } diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 1802bbe7540..ac1a2d2c37d 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Rooはスラッシュコマンドを実行したい", "didRun": "Rooはスラッシュコマンドを実行しました" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{total}}件中{{completed}}件のTo-Doが完了", + "complete": "{{total}}件のTo-Doが完了", + "updated": "To-Doリストを更新しました", + "completed": "完了", + "started": "開始" + } } diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index ba13cb83bf5..56e29a5f035 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo가 슬래시 명령어를 실행하려고 합니다", "didRun": "Roo가 슬래시 명령어를 실행했습니다" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{total}}개의 할 일 중 {{completed}}개 완료", + "complete": "{{total}}개의 할 일 완료", + "updated": "할 일 목록을 업데이트했습니다", + "completed": "완료됨", + "started": "시작됨" + } } diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index f6ee8ba7ce6..e89205f5d52 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo wil een slash commando uitvoeren", "didRun": "Roo heeft een slash commando uitgevoerd" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} van {{total}} to-do's voltooid", + "complete": "{{total}} to-do's voltooid", + "updated": "De to-do-lijst is bijgewerkt", + "completed": "Voltooid", + "started": "Gestart" + } } diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 8e165a0d03a..7fbd929502a 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo chce uruchomić komendę slash", "didRun": "Roo uruchomił komendę slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "Ukończono {{completed}} z {{total}} zadań do wykonania", + "complete": "Ukończono {{total}} zadań do wykonania", + "updated": "Zaktualizowano listę zadań do wykonania", + "completed": "Ukończono", + "started": "Rozpoczęto" + } } diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 8841b81c773..a0a93cddc28 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -423,5 +423,12 @@ "wantsToRun": "Roo quer executar um comando slash", "didRun": "Roo executou um comando slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} de {{total}} tarefas concluídas", + "complete": "{{total}} tarefas concluídas", + "updated": "A lista de tarefas foi atualizada", + "completed": "Concluído", + "started": "Iniciado" + } } diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 02b79efbc66..0b81fa13b89 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -424,5 +424,12 @@ "wantsToRun": "Roo хочет выполнить слеш-команду", "didRun": "Roo выполнил слеш-команду" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} из {{total}} задач выполнено", + "complete": "{{total}} задач выполнено", + "updated": "Список задач обновлен", + "completed": "Завершено", + "started": "Начато" + } } diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index dceb5c43f05..2e546dc2438 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -424,5 +424,12 @@ "wantsToRun": "Roo bir slash komutu çalıştırmak istiyor", "didRun": "Roo bir slash komutu çalıştırdı" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{total}} yapılacaklar listesinden {{completed}} tanesi tamamlandı", + "complete": "{{total}} yapılacaklar listesi tamamlandı", + "updated": "Yapılacaklar listesi güncellendi", + "completed": "Tamamlandı", + "started": "Başladı" + } } diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index da88a413f79..6974db049d9 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -424,5 +424,12 @@ "wantsToRun": "Roo muốn chạy lệnh slash", "didRun": "Roo đã chạy lệnh slash" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "{{completed}} trong tổng số {{total}} công việc đã hoàn thành", + "complete": "{{total}} công việc đã hoàn thành", + "updated": "Đã cập nhật danh sách công việc", + "completed": "Đã hoàn thành", + "started": "Đã bắt đầu" + } } diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index cde60f5e301..86ba0a12e8e 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -424,5 +424,12 @@ "wantsToRun": "Roo 想要运行斜杠命令", "didRun": "Roo 运行了斜杠命令" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "已完成 {{completed}} / {{total}} 个待办事项", + "complete": "已完成 {{total}} 个待办事项", + "updated": "已更新待办事项列表", + "completed": "已完成", + "started": "已开始" + } } diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 9dd210b8960..9bc5038ec2b 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -424,5 +424,12 @@ "wantsToRun": "Roo 想要執行斜線指令", "didRun": "Roo 執行了斜線指令" }, - "docs": "Check our docs to learn more." + "docs": "Check our docs to learn more.", + "todo": { + "partial": "已完成 {{completed}} / {{total}} 個待辦事項", + "complete": "已完成 {{total}} 個待辦事項", + "updated": "已更新待辦事項列表", + "completed": "已完成", + "started": "已開始" + } } diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index eacc86f371f..46a84df0d6b 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -388,14 +388,18 @@ vscode-dropdown::part(listbox) { } .mention-context-highlight { - background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent); - border-radius: 3px; + background-color: color-mix(in srgb, var(--vscode-badge-foreground) 15%, transparent); + border-radius: 6px; + padding: 1px 4px; + font-family: var(--font-mono); } .mention-context-highlight-with-shadow { - background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent); + background-color: color-mix(in srgb, var(--vscode-badge-foreground) 15%, transparent); border-radius: 3px; + padding: 1px 4px; box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent); + font-family: var(--font-mono); } /**