diff --git a/src/main/pty/windows-environment-path.ts b/src/main/pty/windows-environment-path.ts index c0538c40a21..283367c1c68 100644 --- a/src/main/pty/windows-environment-path.ts +++ b/src/main/pty/windows-environment-path.ts @@ -112,7 +112,7 @@ export function __resetPersistedWindowsPathCacheForTests(): void { } export function mergePersistedWindowsPath( - env: Record, + env: NodeJS.ProcessEnv, options: ReadWindowsPathOptions = {} ): void { const platform = options.platform ?? process.platform diff --git a/src/renderer/src/components/right-sidebar/AiVaultPanel.tsx b/src/renderer/src/components/right-sidebar/AiVaultPanel.tsx index daeff3ff60a..c96cc6fe0e0 100644 --- a/src/renderer/src/components/right-sidebar/AiVaultPanel.tsx +++ b/src/renderer/src/components/right-sidebar/AiVaultPanel.tsx @@ -220,7 +220,7 @@ export default function AiVaultPanel(): React.JSX.Element { }, []) return ( -
+
-
+
- {translate( - 'auto.components.right.sidebar.AiVaultPanel.sessionHistory', - 'Agent Session History' - )} + {/* Why: below 300px the header competes with fixed controls, so compact copy prevents overlap. */} + + {translate( + 'auto.components.right.sidebar.AiVaultPanel.sessionHistory', + 'Agent Session History' + )} + + + {translate('auto.components.right.sidebar.AiVaultPanel.agents', 'Agents')} +
- {hasScanResult - ? translate( - 'auto.components.right.sidebar.AiVaultPanel.shownRecent', - '{{value0}} shown · {{value1}} recent', - { value0: shownCount, value1: sessionCount } - ) - : translate( - 'auto.components.right.sidebar.AiVaultPanel.resumePastSessions', - 'Resume past sessions' - )} + {hasScanResult ? ( + <> + + {translate( + 'auto.components.right.sidebar.AiVaultPanel.shownRecent', + '{{value0}} shown · {{value1}} recent', + { value0: shownCount, value1: sessionCount } + )} + + + {translate( + 'auto.components.right.sidebar.AiVaultPanel.sessionsShownCompact', + '{{value0}} shown', + { value0: shownCount } + )} + + + ) : ( + translate( + 'auto.components.right.sidebar.AiVaultPanel.resumePastSessions', + 'Resume past sessions' + ) + )}
-
+
-
-
- - - -
-
- {session.title} -
-
- {agentLabel(session.agent)} -
-
-
- - -
- - - {session.branch ? ( - - ) : null} - {session.model ? ( - - ) : null} - 0 - ? translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.tokenSuffix', - ' · {{value0}} tok', - { value0: formatTokenCount(session.totalTokens) } - ) - : '' - } - )} - /> - -
-
- -
-
- {translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.latestLog', - 'Latest log' - )} -
- {session.previewMessages.length > 0 ? ( -
- {session.previewMessages.map((message, index) => ( -
-
- {previewRoleLabel(message.role)} -
-
- {message.text} -
-
- ))} -
- ) : ( -
- {translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.noReadablePreview', - 'No readable message preview in this transcript.' - )} -
- )} -
- -
-
- {translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.resumeCommand', - 'Resume command' - )} -
-
- {resumeCommand} -
-
-
- - ) -} - -function DetailLine({ - label, - value, - mono = false -}: { - label: string - value: string - mono?: boolean -}): React.JSX.Element { - const handleCopy = useCallback(() => { - void window.api.ui.writeClipboardText(value).then(() => { - toast.success( - translate('auto.components.right.sidebar.AiVaultPanel.valueCopied', '{{value0}} copied', { - value0: label - }) - ) - }) - }, [label, value]) - - return ( -
- {label} - - - - - - {value} - - -
- ) -} - -export function MetaDot(): React.JSX.Element { - return · -} - -export function SessionActionsMenu({ +export function SessionInlineDetails({ + id, session, onResume, onCopyResume, - onCopyId, - onCopyPath, - onOpenLog, - onRevealLog, - onOpenCwd, resumeDisabled }: { + id: string session: AiVaultSession onResume: () => void onCopyResume: () => void - onCopyId: () => void - onCopyPath: () => void - onOpenLog: () => void - onRevealLog: () => void - onOpenCwd?: () => void resumeDisabled: boolean }): React.JSX.Element { + const updatedAt = session.updatedAt ?? session.modifiedAt + const usage = translate( + 'auto.components.right.sidebar.AiVaultSessionDetails.usageValue', + '{{value0}} msgs{{value1}}', + { + value0: session.messageCount, + value1: + session.totalTokens > 0 + ? translate( + 'auto.components.right.sidebar.AiVaultSessionDetails.tokenSuffix', + ' · {{value0}} tok', + { value0: formatTokenCount(session.totalTokens) } + ) + : '' + } + ) + return ( - - +
event.stopPropagation()} + onClick={(event) => event.stopPropagation()} + onDoubleClick={(event) => event.stopPropagation()} + onDragStart={(event) => { + event.preventDefault() + event.stopPropagation() + }} + > +
+ + + +
+
+ {session.title} +
+
+ {agentLabel(session.agent)} +
+
+
+ +
+ + + {session.model ? ( + + ) : null} + {session.branch ? ( + + ) : null} + + +
+ +
- - - {translate( 'auto.components.right.sidebar.AiVaultSessionDetails.resumeInNewTab', 'Resume in New Tab' )} - - + + +
+
+ ) +} + +function SessionDetailCopyRow({ + label, + copyLabel = label, + value, + mono = false +}: { + label: string + copyLabel?: string + value: string + mono?: boolean +}): React.JSX.Element { + const handleCopy = (event: React.MouseEvent): void => { + event.stopPropagation() + void window.api.ui + .writeClipboardText(value) + .then(() => { + toast.success( + translate('auto.components.right.sidebar.AiVaultPanel.valueCopied', '{{value0}} copied', { + value0: copyLabel + }) + ) + }) + .catch(() => { + toast.error( + translate( + 'auto.components.right.sidebar.AiVaultPanel.valueCopyFailed', + 'Unable to copy {{value0}}', + { value0: copyLabel } + ) + ) + }) + } + + return ( +
+ {label} + + {value} + + + + + + {translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.copySessionId', - 'Copy Session ID' + 'auto.components.right.sidebar.AiVaultSessionDetails.copyDetailValue', + 'Copy {{value0}}', + { value0: copyLabel } )} - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionDetails.copyLogPath', - 'Copy Log Path' - )} - - - + + +
) } @@ -344,22 +261,6 @@ function formatDateTime(value: string | null): string { return new Date(timestamp).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }) } -function previewRoleLabel(role: AiVaultSession['previewMessages'][number]['role']): string { - if (role === 'user') { - return translate('auto.components.right.sidebar.AiVaultSessionDetails.user', 'User') - } - if (role === 'assistant') { - return translate('auto.components.right.sidebar.AiVaultSessionDetails.assistant', 'Assistant') - } - if (role === 'tool') { - return translate('auto.components.right.sidebar.AiVaultSessionDetails.tool', 'Tool') - } - if (role === 'system') { - return translate('auto.components.right.sidebar.AiVaultSessionDetails.system', 'System') - } - return translate('auto.components.right.sidebar.AiVaultSessionDetails.log', 'Log') -} - function formatTimeAgo(timestamp: number): string { const diffMs = Date.now() - timestamp if (diffMs < 60_000) { diff --git a/src/renderer/src/components/right-sidebar/AiVaultSessionRow.tsx b/src/renderer/src/components/right-sidebar/AiVaultSessionRow.tsx index e0050be98f0..751afcf20b8 100644 --- a/src/renderer/src/components/right-sidebar/AiVaultSessionRow.tsx +++ b/src/renderer/src/components/right-sidebar/AiVaultSessionRow.tsx @@ -1,7 +1,14 @@ import type React from 'react' -import { Copy, FileJson, FolderOpen, Play } from 'lucide-react' +import { ChevronDown, Copy, FileJson, FolderOpen, MoreHorizontal, Play } from 'lucide-react' import { Button } from '@/components/ui/button' -import { HoverCard, HoverCardTrigger } from '@/components/ui/hover-card' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger +} from '@/components/ui/dropdown-menu' import { ContextMenu, ContextMenuContent, @@ -19,18 +26,14 @@ import { import type { AiVaultSession } from '../../../../shared/ai-vault-types' import { agentLabel } from './ai-vault-session-filters' import { translate } from '@/i18n/i18n' -import { - formatTokenCount, - MetaDot, - SessionActionsMenu, - SessionDetailsHoverCard, - SessionTime -} from './AiVaultSessionDetails' +import { SessionInlineDetails, SessionTime } from './AiVaultSessionDetails' export function VaultSessionRow({ session, resumeCommand, + detailsExpanded, resumeDisabled, + onToggleDetails, onResume, onCopyResume, onCopyId, @@ -41,7 +44,9 @@ export function VaultSessionRow({ }: { session: AiVaultSession resumeCommand: string + detailsExpanded: boolean resumeDisabled: boolean + onToggleDetails: () => void onResume: () => void onCopyResume: () => void onCopyId: () => void @@ -51,51 +56,62 @@ export function VaultSessionRow({ onOpenCwd?: () => void }): React.JSX.Element { const updatedAt = session.updatedAt ?? session.modifiedAt + const detailsId = getSessionDetailsId(session.id) + const detailsTooltip = detailsExpanded + ? translate('auto.components.right.sidebar.AiVaultSessionRow.hideDetails', 'Hide Details') + : translate('auto.components.right.sidebar.AiVaultSessionRow.showDetails', 'Show Details') return ( - - - - -
{ - if (resumeDisabled) { - event.preventDefault() - return - } - writeAiVaultSessionDragData(event.dataTransfer, { - agent: session.agent, - sessionId: session.sessionId, - title: session.title, - command: resumeCommand - }) - window.dispatchEvent(new Event(AI_VAULT_SESSION_DRAG_START_EVENT)) - }} - onDragEnd={() => { - window.dispatchEvent(new Event(AI_VAULT_SESSION_DRAG_END_EVENT)) - }} - onDoubleClick={() => { - if (!resumeDisabled) { - onResume() - } - }} - > -
-
- {session.title} -
- + + +
{ + if (resumeDisabled) { + event.preventDefault() + return + } + writeAiVaultSessionDragData(event.dataTransfer, { + agent: session.agent, + sessionId: session.sessionId, + title: session.title, + command: resumeCommand + }) + window.dispatchEvent(new Event(AI_VAULT_SESSION_DRAG_START_EVENT)) + }} + onDragEnd={() => { + window.dispatchEvent(new Event(AI_VAULT_SESSION_DRAG_END_EVENT)) + }} + onDoubleClick={() => { + if (!resumeDisabled) { + onResume() + } + }} + > +
+
+
+ {session.title}
- -
+ +
+ +
+
event.stopPropagation()} + onDoubleClick={(event) => event.stopPropagation()} + onDragStart={(event) => { + event.preventDefault() + event.stopPropagation() + }} + > + + - + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.resumeInNewTab', + 'Resume in New Tab' + )} + + + + + + + + {detailsTooltip} + + + + + + + + + + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.moreActions', + 'More Actions' + )} + + + + -
-
- - - - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.resumeInNewTab', - 'Resume in New Tab' - )} - - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.copyResumeCommand', - 'Copy Resume Command' - )} - - - - - {translate('auto.components.right.sidebar.AiVaultSessionRow.openLog', 'Open Log')} - - - - {translate('auto.components.right.sidebar.AiVaultSessionRow.revealLog', 'Reveal Log')} - - {onOpenCwd ? ( - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.openWorkingDirectory', - 'Open Working Directory' - )} - + + +
+ {detailsExpanded ? ( + ) : null} - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.copySessionId', - 'Copy Session ID' - )} - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.copyLogPath', - 'Copy Log Path' - )} - - -
- - +
+ + + + + ) } +function SessionActionMenuItems({ + menuKind = 'dropdown', + resumeDisabled, + onResume, + onCopyResume, + onCopyId, + onCopyPath, + onOpenLog, + onRevealLog, + onOpenCwd +}: { + menuKind?: 'dropdown' | 'context' + resumeDisabled: boolean + onResume: () => void + onCopyResume: () => void + onCopyId: () => void + onCopyPath: () => void + onOpenLog: () => void + onRevealLog: () => void + onOpenCwd?: () => void +}): React.JSX.Element { + const Item = menuKind === 'context' ? ContextMenuItem : DropdownMenuItem + const Separator = menuKind === 'context' ? ContextMenuSeparator : DropdownMenuSeparator + + return ( + <> + + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.resumeInNewTab', + 'Resume in New Tab' + )} + + + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.copyResumeCommand', + 'Copy Resume Command' + )} + + + + + {translate('auto.components.right.sidebar.AiVaultSessionRow.openLog', 'Open Log')} + + + + {translate('auto.components.right.sidebar.AiVaultSessionRow.revealLog', 'Reveal Log')} + + {onOpenCwd ? ( + + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.openWorkingDirectory', + 'Open Working Directory' + )} + + ) : null} + + + {translate( + 'auto.components.right.sidebar.AiVaultSessionRow.copySessionId', + 'Copy Session ID' + )} + + + {translate('auto.components.right.sidebar.AiVaultSessionRow.copyLogPath', 'Copy Log Path')} + + + ) +} + +function getSessionDetailsId(sessionId: string): string { + return `ai-vault-session-details-${sessionId.replace(/[^A-Za-z0-9_-]/g, '-')}` +} + function SessionMetadata({ session }: { session: AiVaultSession }): React.JSX.Element { return (
- {session.model ? ( - <> - - {session.model} - - ) : null} - {session.branch ? ( - <> - - {session.branch} - - ) : null} - - + {agentLabel(session.agent)} + {translate( 'auto.components.right.sidebar.AiVaultSessionRow.messageCount', '{{value0}} msgs', { value0: session.messageCount } )} - {session.totalTokens > 0 ? ( - <> - - - {translate( - 'auto.components.right.sidebar.AiVaultSessionRow.tokenCount', - '{{value0}} tok', - { value0: formatTokenCount(session.totalTokens) } - )} - - - ) : null}
) } diff --git a/src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.tsx b/src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.tsx index 642e160fae6..7b1746bc725 100644 --- a/src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.tsx +++ b/src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.tsx @@ -1,5 +1,5 @@ import { useVirtualizer } from '@tanstack/react-virtual' -import { useCallback, useMemo, useRef } from 'react' +import { useCallback, useMemo, useRef, useState } from 'react' import type { AiVaultSession } from '../../../../shared/ai-vault-types' import { cn } from '@/lib/utils' import { translate } from '@/i18n/i18n' @@ -15,6 +15,7 @@ import { } from './ai-vault-virtual-rows' const VAULT_ROW_OVERSCAN = 8 +const VAULT_EXPANDED_SESSION_ROW_ESTIMATED_HEIGHT = 360 type AiVaultListRow = | { type: 'group'; group: AiVaultSessionGroup } @@ -58,6 +59,7 @@ export function AiVaultSessionVirtualList({ const listScrollRef = useRef(null) const stickyRangeStartIndexRef = useRef(0) const activeStickyHeaderIndexRef = useRef(null) + const [expandedSessionIds, setExpandedSessionIds] = useState>(() => new Set()) const vaultRows = useMemo(() => { const rows: AiVaultListRow[] = [] @@ -77,8 +79,16 @@ export function AiVaultSessionVirtualList({ const virtualizer = useVirtualizer({ count: vaultRows.length, getScrollElement: () => listScrollRef.current, - estimateSize: (index) => - vaultRows[index]?.type === 'group' ? VAULT_GROUP_HEADER_ROW_HEIGHT : VAULT_SESSION_ROW_HEIGHT, + estimateSize: (index) => { + const row = vaultRows[index] + if (row?.type === 'group') { + return VAULT_GROUP_HEADER_ROW_HEIGHT + } + if (row?.type === 'session' && expandedSessionIds.has(row.session.id)) { + return VAULT_EXPANDED_SESSION_ROW_ESTIMATED_HEIGHT + } + return VAULT_SESSION_ROW_HEIGHT + }, overscan: VAULT_ROW_OVERSCAN, // Why: keep the active group header mounted so CSS sticky can pin it while // its sessions scroll underneath in the virtual list. @@ -98,6 +108,18 @@ export function AiVaultSessionVirtualList({ } }) + const toggleSessionDetails = useCallback((sessionId: string) => { + setExpandedSessionIds((current) => { + const next = new Set(current) + if (next.has(sessionId)) { + next.delete(sessionId) + } else { + next.add(sessionId) + } + return next + }) + }, []) + const virtualItems = virtualizer.getVirtualItems() activeStickyHeaderIndexRef.current = getActiveStickyHeaderIndexForScroll({ rangeStartIndex: stickyRangeStartIndexRef.current, @@ -139,9 +161,11 @@ export function AiVaultSessionVirtualList({ activeStickyHeaderIndex={activeStickyHeaderIndexRef.current} measureElement={virtualizer.measureElement} collapsedGroups={collapsedGroups} + expandedSessionIds={expandedSessionIds} resumeDisabled={resumeDisabled} buildResumeCommand={buildResumeCommand} onToggleGroup={onToggleGroup} + onToggleSessionDetails={toggleSessionDetails} onResume={onResume} onCopyResume={onCopyResume} onCopyId={onCopyId} @@ -164,9 +188,11 @@ function AiVaultVirtualRow({ activeStickyHeaderIndex, measureElement, collapsedGroups, + expandedSessionIds, resumeDisabled, buildResumeCommand, onToggleGroup, + onToggleSessionDetails, onResume, onCopyResume, onCopyId, @@ -181,9 +207,11 @@ function AiVaultVirtualRow({ activeStickyHeaderIndex: number | null measureElement: (node: Element | null) => void collapsedGroups: ReadonlySet + expandedSessionIds: ReadonlySet resumeDisabled: boolean buildResumeCommand: (session: AiVaultSession) => string onToggleGroup: (key: string) => void + onToggleSessionDetails: (sessionId: string) => void onResume: (session: AiVaultSession) => void onCopyResume: (session: AiVaultSession) => void onCopyId: (session: AiVaultSession) => void @@ -218,7 +246,9 @@ function AiVaultVirtualRow({ onToggleSessionDetails(row.session.id)} onResume={() => onResume(row.session)} onCopyResume={() => onCopyResume(row.session)} onCopyId={() => onCopyId(row.session)} diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 120165cbc99..50676f3366c 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -8703,11 +8703,14 @@ "AiVaultPanel": { "resumeCommandCopied": "Resume command copied", "valueCopied": "{{value0}} copied", + "valueCopyFailed": "Unable to copy {{value0}}", "openWorkspaceBeforeResuming": "Open a workspace before resuming a session.", "localWorkspacesOnly": "Resume from history is only available in local workspaces.", "agentSessionQueued": "{{value0}} session queued", "sessionHistory": "Agent Session History", + "agents": "Agents", "shownRecent": "{{value0}} shown · {{value1}} recent", + "sessionsShownCompact": "{{value0}} shown", "resumePastSessions": "Resume past sessions", "refreshSessionHistory": "Refresh Session History", "searchSessions": "Search sessions", @@ -8756,6 +8759,7 @@ "usageValue": "{{value0}} msgs{{value1}}", "tokenSuffix": " · {{value0}} tok", "session": "Session", + "sessionId": "Session ID", "copyDetailValue": "Copy {{value0}}", "latestLog": "Latest log", "noReadablePreview": "No readable message preview in this transcript.", @@ -8785,6 +8789,7 @@ "AiVaultSessionRow": { "resumeAgentSession": "Resume {{value0}} session", "resumeInNewTab": "Resume in New Tab", + "toggleSessionDetails": "{{value0}} session details", "copyResumeCommand": "Copy Resume Command", "openLog": "Open Log", "revealLog": "Reveal Log", @@ -8792,7 +8797,11 @@ "copySessionId": "Copy Session ID", "copyLogPath": "Copy Log Path", "messageCount": "{{value0}} msgs", - "tokenCount": "{{value0}} tok" + "tokenCount": "{{value0}} tok", + "hideDetails": "Hide Details", + "showDetails": "Show Details", + "moreSessionActions": "More Session Actions", + "moreActions": "More Actions" }, "FileExplorerNameFilter": { "26fb73c6e3": "Find files", diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index ab05f5b6ab4..38e18bebf7b 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -8703,6 +8703,7 @@ "AiVaultPanel": { "resumeCommandCopied": "Resume command copied", "valueCopied": "{{value0}} copied", + "valueCopyFailed": "No se pudo copiar {{value0}}", "openWorkspaceBeforeResuming": "Open a workspace before resuming a session.", "localWorkspacesOnly": "Resume from history is only available in local workspaces.", "agentSessionQueued": "{{value0}} session queued", @@ -8716,8 +8717,10 @@ "transcriptsSkipped": "{{count}} transcript skipped", "noAgentSessionsFound": "No agent sessions found", "noSessionsMatchFilters": "No sessions match the current filters", - "sessionId": "Session ID", - "logPath": "Log path" + "sessionId": "ID de sesión", + "logPath": "Ruta del registro", + "agents": "Agentes", + "sessionsShownCompact": "{{value0}} mostradas" }, "AiVaultPanelControls": { "scanningSessions": "Scanning sessions", @@ -8780,7 +8783,8 @@ "hoursAgo": "{{value0}}h ago", "daysAgo": "{{value0}}d ago", "monthsAgo": "{{value0}}mo ago", - "yearsAgo": "{{value0}}y ago" + "yearsAgo": "{{value0}}y ago", + "sessionId": "ID de sesión" }, "AiVaultSessionRow": { "resumeAgentSession": "Resume {{value0}} session", @@ -8792,7 +8796,12 @@ "copySessionId": "Copy Session ID", "copyLogPath": "Copy Log Path", "messageCount": "{{value0}} msgs", - "tokenCount": "{{value0}} tok" + "tokenCount": "{{value0}} tok", + "toggleSessionDetails": "Detalles de sesión de {{value0}}", + "hideDetails": "Ocultar detalles", + "showDetails": "Mostrar detalles", + "moreSessionActions": "Más acciones de sesión", + "moreActions": "Más acciones" }, "FileExplorerNameFilter": { "26fb73c6e3": "Buscar archivos", diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index 55fd9585070..43f1fd9cfc7 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -8703,6 +8703,7 @@ "AiVaultPanel": { "resumeCommandCopied": "Resume command copied", "valueCopied": "{{value0}} copied", + "valueCopyFailed": "{{value0}} をコピーできません", "openWorkspaceBeforeResuming": "Open a workspace before resuming a session.", "localWorkspacesOnly": "Resume from history is only available in local workspaces.", "agentSessionQueued": "{{value0}} session queued", @@ -8716,8 +8717,10 @@ "transcriptsSkipped": "{{count}} transcript skipped", "noAgentSessionsFound": "No agent sessions found", "noSessionsMatchFilters": "No sessions match the current filters", - "sessionId": "Session ID", - "logPath": "Log path" + "sessionId": "セッション ID", + "logPath": "ログパス", + "agents": "エージェント", + "sessionsShownCompact": "{{value0}} 件表示" }, "AiVaultPanelControls": { "scanningSessions": "Scanning sessions", @@ -8780,7 +8783,8 @@ "hoursAgo": "{{value0}}h ago", "daysAgo": "{{value0}}d ago", "monthsAgo": "{{value0}}mo ago", - "yearsAgo": "{{value0}}y ago" + "yearsAgo": "{{value0}}y ago", + "sessionId": "セッション ID" }, "AiVaultSessionRow": { "resumeAgentSession": "Resume {{value0}} session", @@ -8792,7 +8796,12 @@ "copySessionId": "Copy Session ID", "copyLogPath": "Copy Log Path", "messageCount": "{{value0}} msgs", - "tokenCount": "{{value0}} tok" + "tokenCount": "{{value0}} tok", + "toggleSessionDetails": "{{value0}} のセッション詳細", + "hideDetails": "詳細を非表示", + "showDetails": "詳細を表示", + "moreSessionActions": "セッションのその他の操作", + "moreActions": "その他の操作" }, "FileExplorerNameFilter": { "26fb73c6e3": "ファイルを検索", diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index cdbc8105335..6b8ea9e5a3c 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -8703,6 +8703,7 @@ "AiVaultPanel": { "resumeCommandCopied": "Resume command copied", "valueCopied": "{{value0}} copied", + "valueCopyFailed": "{{value0}}을(를) 복사할 수 없습니다", "openWorkspaceBeforeResuming": "Open a workspace before resuming a session.", "localWorkspacesOnly": "Resume from history is only available in local workspaces.", "agentSessionQueued": "{{value0}} session queued", @@ -8716,8 +8717,10 @@ "transcriptsSkipped": "{{count}} transcript skipped", "noAgentSessionsFound": "No agent sessions found", "noSessionsMatchFilters": "No sessions match the current filters", - "sessionId": "Session ID", - "logPath": "Log path" + "sessionId": "세션 ID", + "logPath": "로그 경로", + "agents": "에이전트", + "sessionsShownCompact": "{{value0}} 표시됨" }, "AiVaultPanelControls": { "scanningSessions": "Scanning sessions", @@ -8780,7 +8783,8 @@ "hoursAgo": "{{value0}}h ago", "daysAgo": "{{value0}}d ago", "monthsAgo": "{{value0}}mo ago", - "yearsAgo": "{{value0}}y ago" + "yearsAgo": "{{value0}}y ago", + "sessionId": "세션 ID" }, "AiVaultSessionRow": { "resumeAgentSession": "Resume {{value0}} session", @@ -8792,7 +8796,12 @@ "copySessionId": "Copy Session ID", "copyLogPath": "Copy Log Path", "messageCount": "{{value0}} msgs", - "tokenCount": "{{value0}} tok" + "tokenCount": "{{value0}} tok", + "toggleSessionDetails": "{{value0}} 세션 세부정보", + "hideDetails": "세부정보 숨기기", + "showDetails": "세부정보 표시", + "moreSessionActions": "세션 추가 작업", + "moreActions": "추가 작업" }, "FileExplorerNameFilter": { "26fb73c6e3": "파일 찾기", diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index 3f954750f5b..e73594f462d 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -8703,6 +8703,7 @@ "AiVaultPanel": { "resumeCommandCopied": "Resume command copied", "valueCopied": "{{value0}} copied", + "valueCopyFailed": "无法复制 {{value0}}", "openWorkspaceBeforeResuming": "Open a workspace before resuming a session.", "localWorkspacesOnly": "Resume from history is only available in local workspaces.", "agentSessionQueued": "{{value0}} session queued", @@ -8716,8 +8717,10 @@ "transcriptsSkipped": "{{count}} transcript skipped", "noAgentSessionsFound": "No agent sessions found", "noSessionsMatchFilters": "No sessions match the current filters", - "sessionId": "Session ID", - "logPath": "Log path" + "sessionId": "会话 ID", + "logPath": "日志路径", + "agents": "智能体", + "sessionsShownCompact": "已显示 {{value0}} 个" }, "AiVaultPanelControls": { "scanningSessions": "Scanning sessions", @@ -8780,7 +8783,8 @@ "hoursAgo": "{{value0}}h ago", "daysAgo": "{{value0}}d ago", "monthsAgo": "{{value0}}mo ago", - "yearsAgo": "{{value0}}y ago" + "yearsAgo": "{{value0}}y ago", + "sessionId": "会话 ID" }, "AiVaultSessionRow": { "resumeAgentSession": "Resume {{value0}} session", @@ -8792,7 +8796,12 @@ "copySessionId": "Copy Session ID", "copyLogPath": "Copy Log Path", "messageCount": "{{value0}} msgs", - "tokenCount": "{{value0}} tok" + "tokenCount": "{{value0}} tok", + "toggleSessionDetails": "{{value0}} 会话详情", + "hideDetails": "隐藏详情", + "showDetails": "显示详情", + "moreSessionActions": "更多会话操作", + "moreActions": "更多操作" }, "FileExplorerNameFilter": { "26fb73c6e3": "查找文件",