feat(vscode): add archive all sessions action (#1262)
* feat(vscode): add archive all sessions action * Update packages/ui/src/components/layout/VSCodeLayout.tsx Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com> * fix: Fail-open default archives all sessions when workspace can't be resolved * fix: Already-archived descendants are included in the archive call * fix: add i18n for the newly added toasts * Restore icon name from 'add-line' to 'add' Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com> * update: fix merge conflict and update code structure into components --------- Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
bba4b02dca
commit
5589ca991a
@@ -5,11 +5,13 @@ import { SessionDialogs } from '@/components/session/SessionDialogs';
|
|||||||
import { ChatView } from '@/components/views/ChatView';
|
import { ChatView } from '@/components/views/ChatView';
|
||||||
import { useSessionUIStore } from '@/sync/session-ui-store';
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
||||||
import { useViewportStore } from '@/sync/viewport-store';
|
import { useViewportStore } from '@/sync/viewport-store';
|
||||||
import { useDirectorySync, useSessionMessages, useSessionMessagesResolved } from '@/sync/sync-context';
|
import { useSessions, useDirectorySync, useSessionMessages, useSessionMessagesResolved } from '@/sync/sync-context';
|
||||||
import { useConfigStore } from '@/stores/useConfigStore';
|
import { useConfigStore } from '@/stores/useConfigStore';
|
||||||
|
import { resolveGlobalSessionDirectory, useGlobalSessionsStore } from '@/stores/useGlobalSessionsStore';
|
||||||
import { ContextUsageDisplay } from '@/components/ui/ContextUsageDisplay';
|
import { ContextUsageDisplay } from '@/components/ui/ContextUsageDisplay';
|
||||||
import { McpDropdown } from '@/components/mcp/McpDropdown';
|
import { McpDropdown } from '@/components/mcp/McpDropdown';
|
||||||
import { SessionSwitcherDropdown } from '@/components/session/SessionSwitcherDropdown';
|
import { SessionSwitcherDropdown } from '@/components/session/SessionSwitcherDropdown';
|
||||||
|
import { SessionsTabTitle } from '@/components/session/SessionsTabTitle';
|
||||||
import { useProjectsStore } from '@/stores/useProjectsStore';
|
import { useProjectsStore } from '@/stores/useProjectsStore';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import {
|
import {
|
||||||
@@ -22,6 +24,7 @@ import {
|
|||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
|
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
|
||||||
import { useI18n } from '@/lib/i18n';
|
import { useI18n } from '@/lib/i18n';
|
||||||
|
import { toast } from '@/components/ui';
|
||||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||||
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
||||||
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
||||||
@@ -32,7 +35,7 @@ import { useUpdateStore } from '@/stores/useUpdateStore';
|
|||||||
import { updateDesktopSettings } from '@/lib/persistence';
|
import { updateDesktopSettings } from '@/lib/persistence';
|
||||||
import { formatTimeForPreference } from '@/lib/timeFormat';
|
import { formatTimeForPreference } from '@/lib/timeFormat';
|
||||||
import { lazyWithChunkRecovery } from '@/lib/chunkLoadRecovery';
|
import { lazyWithChunkRecovery } from '@/lib/chunkLoadRecovery';
|
||||||
import type { UsageWindow } from '@/types';
|
import type { Session, UsageWindow } from '@/types';
|
||||||
import type { SessionContextUsage } from '@/stores/types/sessionTypes';
|
import type { SessionContextUsage } from '@/stores/types/sessionTypes';
|
||||||
import { useUIStore, type TimeFormatPreference } from '@/stores/useUIStore';
|
import { useUIStore, type TimeFormatPreference } from '@/stores/useUIStore';
|
||||||
|
|
||||||
@@ -56,6 +59,15 @@ const SESSIONS_SIDEBAR_WIDTH = 280;
|
|||||||
const SESSIONS_SIDEBAR_MIN_WIDTH = Math.round(SESSIONS_SIDEBAR_WIDTH * 0.7);
|
const SESSIONS_SIDEBAR_MIN_WIDTH = Math.round(SESSIONS_SIDEBAR_WIDTH * 0.7);
|
||||||
const SESSIONS_SIDEBAR_MAX_WIDTH = 520;
|
const SESSIONS_SIDEBAR_MAX_WIDTH = 520;
|
||||||
|
|
||||||
|
const normalizePath = (value?: string | null): string | null => {
|
||||||
|
if (typeof value !== 'string') return null;
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (!trimmed) return null;
|
||||||
|
const replaced = trimmed.replace(/\\/g, '/');
|
||||||
|
if (replaced === '/') return '/';
|
||||||
|
return replaced.length > 1 ? replaced.replace(/\/+$/, '') : replaced;
|
||||||
|
};
|
||||||
|
|
||||||
type VSCodeView = 'sessions' | 'chat' | 'settings';
|
type VSCodeView = 'sessions' | 'chat' | 'settings';
|
||||||
|
|
||||||
export const VSCodeLayout: React.FC = () => {
|
export const VSCodeLayout: React.FC = () => {
|
||||||
@@ -135,6 +147,18 @@ export const VSCodeLayout: React.FC = () => {
|
|||||||
const expandedSidebarResizeStartWidthRef = React.useRef(SESSIONS_SIDEBAR_WIDTH);
|
const expandedSidebarResizeStartWidthRef = React.useRef(SESSIONS_SIDEBAR_WIDTH);
|
||||||
const expandedSidebarResizePointerIdRef = React.useRef<number | null>(null);
|
const expandedSidebarResizePointerIdRef = React.useRef<number | null>(null);
|
||||||
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
|
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
|
||||||
|
const sessions = useSessions();
|
||||||
|
const globalActiveSessions = useGlobalSessionsStore((state) => state.activeSessions);
|
||||||
|
const globalArchivedSessions = useGlobalSessionsStore((state) => state.archivedSessions);
|
||||||
|
const projects = useProjectsStore((state) => state.projects);
|
||||||
|
const activeProjectId = useProjectsStore((state) => state.activeProjectId);
|
||||||
|
|
||||||
|
const activeWorkspacePath = React.useMemo(() => {
|
||||||
|
const activeProject = activeProjectId
|
||||||
|
? projects.find((project) => project.id === activeProjectId) ?? null
|
||||||
|
: projects[0] ?? null;
|
||||||
|
return normalizePath(activeProject?.path ?? null);
|
||||||
|
}, [activeProjectId, projects]);
|
||||||
const newSessionDraftOpen = useSessionUIStore((state) => Boolean(state.newSessionDraft?.open));
|
const newSessionDraftOpen = useSessionUIStore((state) => Boolean(state.newSessionDraft?.open));
|
||||||
const activeSessionTitleValue = useDirectorySync(
|
const activeSessionTitleValue = useDirectorySync(
|
||||||
React.useCallback((state) => {
|
React.useCallback((state) => {
|
||||||
@@ -249,6 +273,82 @@ export const VSCodeLayout: React.FC = () => {
|
|||||||
setCurrentView('sessions');
|
setCurrentView('sessions');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const isSessionInActiveWorkspace = React.useCallback((session: Session): boolean => {
|
||||||
|
if (!activeWorkspacePath) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionDirectory = resolveGlobalSessionDirectory(session);
|
||||||
|
if (sessionDirectory) {
|
||||||
|
return sessionDirectory.toLowerCase() === activeWorkspacePath.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}, [activeWorkspacePath]);
|
||||||
|
|
||||||
|
const traversalSessions = React.useMemo(() => {
|
||||||
|
const byId = new Map<string, Session>();
|
||||||
|
for (const session of sessions) byId.set(session.id, session);
|
||||||
|
for (const session of globalActiveSessions) byId.set(session.id, session);
|
||||||
|
for (const session of globalArchivedSessions) byId.set(session.id, session);
|
||||||
|
return Array.from(byId.values());
|
||||||
|
}, [globalActiveSessions, globalArchivedSessions, sessions]);
|
||||||
|
|
||||||
|
/** Collect root session IDs and all descendants (subagent sessions). */
|
||||||
|
const collectSessionIdsWithDescendants = React.useCallback(
|
||||||
|
(allSessions: Session[], rootSessions: Session[]): string[] => {
|
||||||
|
const byId = new Map<string, Session>();
|
||||||
|
for (const session of allSessions) byId.set(session.id, session);
|
||||||
|
|
||||||
|
const childrenMap = new Map<string, string[]>();
|
||||||
|
for (const session of allSessions) {
|
||||||
|
const parentID = session.parentID;
|
||||||
|
if (parentID) {
|
||||||
|
const list = childrenMap.get(parentID) ?? [];
|
||||||
|
list.push(session.id);
|
||||||
|
childrenMap.set(parentID, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ids = new Set<string>();
|
||||||
|
const addDescendants = (sessionId: string, visited: Set<string>) => {
|
||||||
|
if (visited.has(sessionId)) return; // cycle guard
|
||||||
|
visited.add(sessionId);
|
||||||
|
const children = childrenMap.get(sessionId) ?? [];
|
||||||
|
for (const childId of children) {
|
||||||
|
const child = byId.get(childId);
|
||||||
|
if (child?.time?.archived) continue; // skip already-archived children
|
||||||
|
ids.add(childId);
|
||||||
|
addDescendants(childId, visited);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const session of rootSessions) {
|
||||||
|
ids.add(session.id);
|
||||||
|
addDescendants(session.id, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(ids);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleArchiveAll = React.useCallback(async () => {
|
||||||
|
const store = useSessionUIStore.getState();
|
||||||
|
const rootSessions = traversalSessions.filter((session) => !session.time?.archived && isSessionInActiveWorkspace(session));
|
||||||
|
const allIds = collectSessionIdsWithDescendants(traversalSessions, rootSessions);
|
||||||
|
if (allIds.length === 0) return;
|
||||||
|
|
||||||
|
const { archivedIds, failedIds } = await store.archiveSessions(allIds);
|
||||||
|
if (archivedIds.length > 0) {
|
||||||
|
toast.success(t('vscodeLayout.actions.archiveAllSuccess', { count: archivedIds.length }));
|
||||||
|
}
|
||||||
|
if (failedIds.length > 0) {
|
||||||
|
toast.error(t('vscodeLayout.actions.archiveAllError', { count: failedIds.length }));
|
||||||
|
}
|
||||||
|
}, [collectSessionIdsWithDescendants, isSessionInActiveWorkspace, traversalSessions, t]);
|
||||||
|
|
||||||
|
|
||||||
// Listen for connection status changes
|
// Listen for connection status changes
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// Catch up with the latest status even if the extension posted the connection message
|
// Catch up with the latest status even if the extension posted the connection message
|
||||||
@@ -519,6 +619,7 @@ export const VSCodeLayout: React.FC = () => {
|
|||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
<VSCodeHeader
|
<VSCodeHeader
|
||||||
title={t('vscodeLayout.title.sessions')}
|
title={t('vscodeLayout.title.sessions')}
|
||||||
|
onArchiveAll={handleArchiveAll}
|
||||||
/>
|
/>
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<SessionSidebar
|
<SessionSidebar
|
||||||
@@ -559,6 +660,7 @@ interface VSCodeHeaderProps {
|
|||||||
title: string;
|
title: string;
|
||||||
showBack?: boolean;
|
showBack?: boolean;
|
||||||
onBack?: () => void;
|
onBack?: () => void;
|
||||||
|
onArchiveAll?: () => void;
|
||||||
onNewSession?: () => void;
|
onNewSession?: () => void;
|
||||||
onSettings?: () => void;
|
onSettings?: () => void;
|
||||||
onAgentManager?: () => void;
|
onAgentManager?: () => void;
|
||||||
@@ -568,7 +670,8 @@ interface VSCodeHeaderProps {
|
|||||||
enableSessionSwitcher?: boolean;
|
enableSessionSwitcher?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VSCodeHeader: React.FC<VSCodeHeaderProps> = ({ title, showBack, onBack, onNewSession, onSettings, onAgentManager, showMcp, showContextUsage, showRateLimits, enableSessionSwitcher }) => {
|
|
||||||
|
const VSCodeHeader: React.FC<VSCodeHeaderProps> = ({ title, showBack, onBack, onArchiveAll, onNewSession, onSettings, onAgentManager, showMcp, showContextUsage, showRateLimits, enableSessionSwitcher }) => {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const getCurrentModel = useConfigStore((state) => state.getCurrentModel);
|
const getCurrentModel = useConfigStore((state) => state.getCurrentModel);
|
||||||
const providers = useConfigStore((state) => state.providers);
|
const providers = useConfigStore((state) => state.providers);
|
||||||
@@ -744,7 +847,7 @@ const VSCodeHeader: React.FC<VSCodeHeaderProps> = ({ title, showBack, onBack, on
|
|||||||
</button>
|
</button>
|
||||||
</SessionSwitcherDropdown>
|
</SessionSwitcherDropdown>
|
||||||
) : (
|
) : (
|
||||||
<h1 className="text-sm font-medium truncate flex-1" title={title}>{title}</h1>
|
<SessionsTabTitle title={title} onArchiveAll={onArchiveAll} />
|
||||||
)}
|
)}
|
||||||
<div className="min-w-0 flex-1" />
|
<div className="min-w-0 flex-1" />
|
||||||
{onNewSession && (
|
{onNewSession && (
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
|
import { Icon } from '@/components/icon/Icon';
|
||||||
|
import { useI18n } from '@/lib/i18n';
|
||||||
|
|
||||||
|
interface ArchiveAllDropdownProps {
|
||||||
|
onArchiveAll?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArchiveAllDropdown: React.FC<ArchiveAllDropdownProps> = ({ onArchiveAll }) => {
|
||||||
|
const { t } = useI18n();
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="inline-flex h-8 w-8 items-center justify-center p-2 text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
|
||||||
|
aria-label={t('vscodeLayout.actions.archiveAllAria')}
|
||||||
|
>
|
||||||
|
<Icon name="archive" className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="bottom" sideOffset={4}><p>{t('vscodeLayout.actions.archiveAllAria')}</p></TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
<DropdownMenuContent align="end" className="min-w-[160px]">
|
||||||
|
<DropdownMenuItem onSelect={onArchiveAll}>
|
||||||
|
{t('vscodeLayout.actions.archiveAllConfirm')}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>{t('vscodeLayout.actions.cancel')}</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { ArchiveAllDropdown };
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ArchiveAllDropdown } from '@/components/session/ArchiveAllDropdown';
|
||||||
|
|
||||||
|
interface SessionsTabTitleProps {
|
||||||
|
title: string;
|
||||||
|
onArchiveAll?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SessionsTabTitle: React.FC<SessionsTabTitleProps> = ({ title, onArchiveAll }) => (
|
||||||
|
<>
|
||||||
|
<h1 className="text-sm font-medium truncate flex-1" title={title}>{title}</h1>
|
||||||
|
{onArchiveAll && <ArchiveAllDropdown onArchiveAll={onArchiveAll} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export { SessionsTabTitle };
|
||||||
@@ -821,7 +821,7 @@ function SessionNodeItemComponent(props: Props): React.ReactNode {
|
|||||||
|
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem className="text-destructive focus:text-destructive [&>svg]:mr-1" onClick={() => handleDeleteSession(session, { archivedBucket })}>
|
<DropdownMenuItem className="text-destructive focus:text-destructive [&>svg]:mr-1" onClick={() => handleDeleteSession(session, { archivedBucket })}>
|
||||||
<Icon name="delete-bin" className="mr-1 h-4 w-4" />
|
<Icon name={archivedBucket ? "delete-bin" : "archive"} className="mr-1 h-4 w-4" />
|
||||||
{archivedBucket ? t('sessions.sidebar.bulkActions.delete') : t('sessions.sidebar.bulkActions.archive')}
|
{archivedBucket ? t('sessions.sidebar.bulkActions.delete') : t('sessions.sidebar.bulkActions.archive')}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
@@ -2421,6 +2421,11 @@ export const dict = {
|
|||||||
'vscodeLayout.title.sessions': 'Sessions',
|
'vscodeLayout.title.sessions': 'Sessions',
|
||||||
'vscodeLayout.title.sessionFallback': 'Session',
|
'vscodeLayout.title.sessionFallback': 'Session',
|
||||||
'vscodeLayout.actions.backToSessionsAria': 'Back to sessions',
|
'vscodeLayout.actions.backToSessionsAria': 'Back to sessions',
|
||||||
|
'vscodeLayout.actions.archiveAllAria': 'Archive all sessions',
|
||||||
|
'vscodeLayout.actions.archiveAllConfirm': 'Archive all',
|
||||||
|
'vscodeLayout.actions.archiveAllSuccess': 'Archived {count} session(s)',
|
||||||
|
'vscodeLayout.actions.archiveAllError': 'Failed to archive {count} session(s)',
|
||||||
|
'vscodeLayout.actions.cancel': 'Cancel',
|
||||||
'vscodeLayout.actions.newSessionAria': 'New session',
|
'vscodeLayout.actions.newSessionAria': 'New session',
|
||||||
'vscodeLayout.actions.openAgentManagerAria': 'Open Agent Manager',
|
'vscodeLayout.actions.openAgentManagerAria': 'Open Agent Manager',
|
||||||
'vscodeLayout.actions.resizeSessionsSidebarAria': 'Resize sessions sidebar',
|
'vscodeLayout.actions.resizeSessionsSidebarAria': 'Resize sessions sidebar',
|
||||||
|
|||||||
@@ -2388,6 +2388,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"vscodeLayout.title.sessionFallback": "Sesión",
|
"vscodeLayout.title.sessionFallback": "Sesión",
|
||||||
"vscodeLayout.actions.backToSessionsAria": "Volver a sesiones",
|
"vscodeLayout.actions.backToSessionsAria": "Volver a sesiones",
|
||||||
"vscodeLayout.actions.newSessionAria": "Nueva sesión",
|
"vscodeLayout.actions.newSessionAria": "Nueva sesión",
|
||||||
|
"vscodeLayout.actions.archiveAllAria": "Archivar todas las sesiones",
|
||||||
|
"vscodeLayout.actions.archiveAllConfirm": "Archivar todo",
|
||||||
|
"vscodeLayout.actions.archiveAllSuccess": "{count} sesión(es) archivada(s)",
|
||||||
|
"vscodeLayout.actions.archiveAllError": "Error al archivar {count} sesión(es)",
|
||||||
|
"vscodeLayout.actions.cancel": "Cancelar",
|
||||||
"vscodeLayout.actions.openAgentManagerAria": "Abrir gestor de agentes",
|
"vscodeLayout.actions.openAgentManagerAria": "Abrir gestor de agentes",
|
||||||
"vscodeLayout.actions.resizeSessionsSidebarAria": "Ajustar tamaño del panel de sesiones",
|
"vscodeLayout.actions.resizeSessionsSidebarAria": "Ajustar tamaño del panel de sesiones",
|
||||||
"vscodeLayout.actions.settingsAria": "Configuración",
|
"vscodeLayout.actions.settingsAria": "Configuración",
|
||||||
|
|||||||
@@ -2421,6 +2421,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'vscodeLayout.title.sessions': '세션',
|
'vscodeLayout.title.sessions': '세션',
|
||||||
'vscodeLayout.title.sessionFallback': '세션',
|
'vscodeLayout.title.sessionFallback': '세션',
|
||||||
'vscodeLayout.actions.backToSessionsAria': '세션으로 돌아가기',
|
'vscodeLayout.actions.backToSessionsAria': '세션으로 돌아가기',
|
||||||
|
'vscodeLayout.actions.archiveAllAria': '모든 세션 보관',
|
||||||
|
'vscodeLayout.actions.archiveAllConfirm': '모두 보관',
|
||||||
|
'vscodeLayout.actions.archiveAllSuccess': '{count}개 세션 보관됨',
|
||||||
|
'vscodeLayout.actions.archiveAllError': '{count}개 세션 보관 실패',
|
||||||
|
'vscodeLayout.actions.cancel': '취소',
|
||||||
'vscodeLayout.actions.newSessionAria': '새 세션',
|
'vscodeLayout.actions.newSessionAria': '새 세션',
|
||||||
'vscodeLayout.actions.openAgentManagerAria': '에이전트 관리자 열기',
|
'vscodeLayout.actions.openAgentManagerAria': '에이전트 관리자 열기',
|
||||||
'vscodeLayout.actions.resizeSessionsSidebarAria': '세션 사이드바 크기 조정',
|
'vscodeLayout.actions.resizeSessionsSidebarAria': '세션 사이드바 크기 조정',
|
||||||
|
|||||||
@@ -2448,6 +2448,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'opencodeUpdate.toast.failed.description': 'Aktualizacja OpenCode nie powiodła się.',
|
'opencodeUpdate.toast.failed.description': 'Aktualizacja OpenCode nie powiodła się.',
|
||||||
'opencodeUpdate.toast.reload.message': 'Ponowne uruchamianie OpenCode...',
|
'opencodeUpdate.toast.reload.message': 'Ponowne uruchamianie OpenCode...',
|
||||||
'vscodeLayout.actions.backToSessionsAria': 'Powrót do sesji',
|
'vscodeLayout.actions.backToSessionsAria': 'Powrót do sesji',
|
||||||
|
'vscodeLayout.actions.archiveAllAria': 'Archiwizuj wszystkie sesje',
|
||||||
|
'vscodeLayout.actions.archiveAllConfirm': 'Archiwizować wszystko',
|
||||||
|
'vscodeLayout.actions.archiveAllSuccess': 'Zarchiwizowano {count} sesji',
|
||||||
|
'vscodeLayout.actions.archiveAllError': 'Nie udało się zarchiwizować {count} sesji',
|
||||||
|
'vscodeLayout.actions.cancel': 'Anuluj',
|
||||||
'vscodeLayout.actions.newSessionAria': 'Nowa sesja',
|
'vscodeLayout.actions.newSessionAria': 'Nowa sesja',
|
||||||
'vscodeLayout.actions.openAgentManagerAria': 'Otwórz menedżer agentów',
|
'vscodeLayout.actions.openAgentManagerAria': 'Otwórz menedżer agentów',
|
||||||
'vscodeLayout.actions.resizeSessionsSidebarAria': 'Zmień rozmiar panelu sesji',
|
'vscodeLayout.actions.resizeSessionsSidebarAria': 'Zmień rozmiar panelu sesji',
|
||||||
|
|||||||
@@ -2387,6 +2387,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"vscodeLayout.title.sessions": "Sessões",
|
"vscodeLayout.title.sessions": "Sessões",
|
||||||
"vscodeLayout.title.sessionFallback": "Sessão",
|
"vscodeLayout.title.sessionFallback": "Sessão",
|
||||||
"vscodeLayout.actions.backToSessionsAria": "Voltar para sessões",
|
"vscodeLayout.actions.backToSessionsAria": "Voltar para sessões",
|
||||||
|
"vscodeLayout.actions.archiveAllAria": "Arquivar todas as sessões",
|
||||||
|
"vscodeLayout.actions.archiveAllConfirm": "Arquivar tudo",
|
||||||
|
"vscodeLayout.actions.archiveAllSuccess": "{count} sessão(ões) arquivada(s)",
|
||||||
|
"vscodeLayout.actions.archiveAllError": "Falha ao arquivar {count} sessão(ões)",
|
||||||
|
"vscodeLayout.actions.cancel": "Cancelar",
|
||||||
"vscodeLayout.actions.newSessionAria": "Nova sessão",
|
"vscodeLayout.actions.newSessionAria": "Nova sessão",
|
||||||
"vscodeLayout.actions.openAgentManagerAria": "Abrir gerenciador de agentes",
|
"vscodeLayout.actions.openAgentManagerAria": "Abrir gerenciador de agentes",
|
||||||
"vscodeLayout.actions.resizeSessionsSidebarAria": "Ajustar tamanho do painel de sessões",
|
"vscodeLayout.actions.resizeSessionsSidebarAria": "Ajustar tamanho do painel de sessões",
|
||||||
|
|||||||
@@ -2387,6 +2387,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"vscodeLayout.title.sessions": "Сесії",
|
"vscodeLayout.title.sessions": "Сесії",
|
||||||
"vscodeLayout.title.sessionFallback": "Сесія",
|
"vscodeLayout.title.sessionFallback": "Сесія",
|
||||||
"vscodeLayout.actions.backToSessionsAria": "Назад до сесій",
|
"vscodeLayout.actions.backToSessionsAria": "Назад до сесій",
|
||||||
|
"vscodeLayout.actions.archiveAllAria": "Архівувати всі сесії",
|
||||||
|
"vscodeLayout.actions.archiveAllConfirm": "Архівувати все",
|
||||||
|
"vscodeLayout.actions.archiveAllSuccess": "Заархівовано {count} сесій(ї)",
|
||||||
|
"vscodeLayout.actions.archiveAllError": "Не вдалося заархівувати {count} сесій(ї)",
|
||||||
|
"vscodeLayout.actions.cancel": "Скасувати",
|
||||||
"vscodeLayout.actions.newSessionAria": "Нова сесія",
|
"vscodeLayout.actions.newSessionAria": "Нова сесія",
|
||||||
"vscodeLayout.actions.openAgentManagerAria": "Відкрити менеджер агентів",
|
"vscodeLayout.actions.openAgentManagerAria": "Відкрити менеджер агентів",
|
||||||
"vscodeLayout.actions.resizeSessionsSidebarAria": "Змінити розмір бічної панелі сесій",
|
"vscodeLayout.actions.resizeSessionsSidebarAria": "Змінити розмір бічної панелі сесій",
|
||||||
|
|||||||
@@ -2387,6 +2387,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'vscodeLayout.title.sessions': '会话',
|
'vscodeLayout.title.sessions': '会话',
|
||||||
'vscodeLayout.title.sessionFallback': '会话',
|
'vscodeLayout.title.sessionFallback': '会话',
|
||||||
'vscodeLayout.actions.backToSessionsAria': '返回会话列表',
|
'vscodeLayout.actions.backToSessionsAria': '返回会话列表',
|
||||||
|
"vscodeLayout.actions.archiveAllAria": "归档所有会话",
|
||||||
|
"vscodeLayout.actions.archiveAllConfirm": "归档全部",
|
||||||
|
"vscodeLayout.actions.archiveAllSuccess": "已归档 {count} 个会话",
|
||||||
|
"vscodeLayout.actions.archiveAllError": "归档 {count} 个会话失败",
|
||||||
|
"vscodeLayout.actions.cancel": "取消",
|
||||||
'vscodeLayout.actions.newSessionAria': '新建会话',
|
'vscodeLayout.actions.newSessionAria': '新建会话',
|
||||||
'vscodeLayout.actions.openAgentManagerAria': '打开智能体管理器',
|
'vscodeLayout.actions.openAgentManagerAria': '打开智能体管理器',
|
||||||
'vscodeLayout.actions.resizeSessionsSidebarAria': '调整会话侧边栏大小',
|
'vscodeLayout.actions.resizeSessionsSidebarAria': '调整会话侧边栏大小',
|
||||||
|
|||||||
@@ -2384,6 +2384,11 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'vscodeLayout.title.sessions': '會話',
|
'vscodeLayout.title.sessions': '會話',
|
||||||
'vscodeLayout.title.sessionFallback': '會話',
|
'vscodeLayout.title.sessionFallback': '會話',
|
||||||
'vscodeLayout.actions.backToSessionsAria': '返回會話清單',
|
'vscodeLayout.actions.backToSessionsAria': '返回會話清單',
|
||||||
|
'vscodeLayout.actions.archiveAllAria': '封存所有會話',
|
||||||
|
'vscodeLayout.actions.archiveAllConfirm': '全部封存',
|
||||||
|
'vscodeLayout.actions.archiveAllSuccess': '已封存 {count} 個會話',
|
||||||
|
'vscodeLayout.actions.archiveAllError': '封存 {count} 個會話失敗',
|
||||||
|
'vscodeLayout.actions.cancel': '取消',
|
||||||
'vscodeLayout.actions.newSessionAria': '新增會話',
|
'vscodeLayout.actions.newSessionAria': '新增會話',
|
||||||
'vscodeLayout.actions.openAgentManagerAria': '開啟 Agent 管理器',
|
'vscodeLayout.actions.openAgentManagerAria': '開啟 Agent 管理器',
|
||||||
'vscodeLayout.actions.resizeSessionsSidebarAria': '調整會話側邊欄大小',
|
'vscodeLayout.actions.resizeSessionsSidebarAria': '調整會話側邊欄大小',
|
||||||
|
|||||||
Reference in New Issue
Block a user