mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
feat(session-search): count sessions plainly and offer Show more when the scan fills its depth
This commit is contained in:
@@ -173,7 +173,7 @@ it('shows the whole history and no offer while the box is empty', async () => {
|
||||
expect(screen.getByText('Rename the bar widget')).toBeTruthy()
|
||||
expect(searchSessions).not.toHaveBeenCalled()
|
||||
// The same bar serves both modes; browsing it reports the history counts and its own sort.
|
||||
expect(screen.getByText('2 shown · 2 recent')).toBeTruthy()
|
||||
expect(screen.getByText('2 sessions')).toBeTruthy()
|
||||
expect(screen.getByRole('button', { name: 'Sort sessions: Last updated' })).toBeTruthy()
|
||||
expect(screen.queryByText('2 results')).toBeNull()
|
||||
expect(screen.queryByRole('button', { name: /^Sort results:/ })).toBeNull()
|
||||
|
||||
@@ -39,14 +39,10 @@ import { AiVaultPanelHeader } from './AiVaultPanelHeader'
|
||||
import {
|
||||
AiVaultResultCountLabel,
|
||||
AiVaultSessionListBar,
|
||||
AiVaultShownCountLabel
|
||||
AiVaultSessionCountLabel
|
||||
} from './AiVaultSessionListBar'
|
||||
import {
|
||||
aiVaultBrowseSortAriaLabel,
|
||||
aiVaultBrowseSortOptions,
|
||||
aiVaultSearchSortAriaLabel,
|
||||
aiVaultSearchSortOptions
|
||||
} from './ai-vault-sort-options'
|
||||
import { aiVaultBrowseSortMenu, aiVaultSearchSortMenu } from './ai-vault-sort-options'
|
||||
import { AiVaultShowMoreSessionsRow } from './AiVaultSessionLimitMenu'
|
||||
import { AiVaultSessionVirtualList } from './AiVaultSessionVirtualList'
|
||||
import { useAiVaultSessionRefresh } from './ai-vault-session-refresh'
|
||||
import {
|
||||
@@ -342,18 +338,19 @@ export default function AiVaultPanel(): React.JSX.Element {
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultResultCountLabel count={filteredSessions.length} />}
|
||||
value={searchSort}
|
||||
options={aiVaultSearchSortOptions()}
|
||||
sortAriaLabel={aiVaultSearchSortAriaLabel}
|
||||
menu={aiVaultSearchSortMenu()}
|
||||
onChange={setSearchSort}
|
||||
/>
|
||||
) : (
|
||||
<AiVaultSessionListBar
|
||||
label={
|
||||
<AiVaultShownCountLabel shown={filteredSessions.length} recent={sessions.length} />
|
||||
<AiVaultSessionCountLabel
|
||||
shown={filteredSessions.length}
|
||||
loaded={sessions.length}
|
||||
/>
|
||||
}
|
||||
value={sort}
|
||||
options={aiVaultBrowseSortOptions()}
|
||||
sortAriaLabel={aiVaultBrowseSortAriaLabel}
|
||||
menu={aiVaultBrowseSortMenu()}
|
||||
onChange={setSort}
|
||||
/>
|
||||
))}
|
||||
@@ -408,6 +405,13 @@ export default function AiVaultPanel(): React.JSX.Element {
|
||||
onRequestDelete={(session) => void requestDelete(session)}
|
||||
/>
|
||||
)}
|
||||
{!searching && (
|
||||
<AiVaultShowMoreSessionsRow
|
||||
loaded={sessions.length}
|
||||
sessionLimit={sessionLimit}
|
||||
onSessionLimitChange={setSessionLimit}
|
||||
/>
|
||||
)}
|
||||
</AiVaultPanelSearch>
|
||||
{launchActions.continuationRequest && (
|
||||
<AgentSessionContinuationDialog
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { cleanup, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import { AiVaultShowMoreSessionsRow } from './AiVaultSessionLimitMenu'
|
||||
|
||||
afterEach(cleanup)
|
||||
|
||||
it('steps the history depth up once the scan filled it', async () => {
|
||||
const onSessionLimitChange = vi.fn()
|
||||
render(
|
||||
<AiVaultShowMoreSessionsRow
|
||||
loaded={250}
|
||||
sessionLimit={250}
|
||||
onSessionLimitChange={onSessionLimitChange}
|
||||
/>
|
||||
)
|
||||
await userEvent.setup().click(screen.getByRole('button', { name: 'Show more sessions' }))
|
||||
expect(onSessionLimitChange).toHaveBeenCalledWith(500)
|
||||
})
|
||||
|
||||
it('stays hidden while the scan has room or is already unlimited', () => {
|
||||
render(
|
||||
<AiVaultShowMoreSessionsRow loaded={12} sessionLimit={250} onSessionLimitChange={vi.fn()} />
|
||||
)
|
||||
render(
|
||||
<AiVaultShowMoreSessionsRow
|
||||
loaded={5000}
|
||||
sessionLimit="unlimited"
|
||||
onSessionLimitChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
expect(screen.queryByRole('button')).toBeNull()
|
||||
})
|
||||
@@ -7,13 +7,43 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import {
|
||||
AI_VAULT_SESSION_LIMITS,
|
||||
DEFAULT_AI_VAULT_SESSION_LIMIT,
|
||||
nextAiVaultSessionLimit,
|
||||
type AiVaultSessionLimit
|
||||
} from './ai-vault-session-limit'
|
||||
|
||||
/** Footer row once the scan filled its History depth; steps the same setting the menu edits. */
|
||||
export function AiVaultShowMoreSessionsRow({
|
||||
loaded,
|
||||
sessionLimit,
|
||||
onSessionLimitChange
|
||||
}: {
|
||||
loaded: number
|
||||
sessionLimit: AiVaultSessionLimit
|
||||
onSessionLimitChange: (limit: AiVaultSessionLimit) => void
|
||||
}): React.JSX.Element | null {
|
||||
const next = nextAiVaultSessionLimit(sessionLimit)
|
||||
if (next === null || typeof sessionLimit !== 'number' || loaded < sessionLimit) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<div className="border-t border-sidebar-border p-2">
|
||||
<Button
|
||||
className="w-full"
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
onClick={() => onSessionLimitChange(next)}
|
||||
>
|
||||
{translate('sessionSearch.panel.showMoreSessions', 'Show more sessions')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function AiVaultSessionLimitMenu({
|
||||
sessionLimit,
|
||||
onSessionLimitChange
|
||||
|
||||
@@ -2,16 +2,11 @@
|
||||
import { cleanup, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
aiVaultBrowseSortAriaLabel,
|
||||
aiVaultBrowseSortOptions,
|
||||
aiVaultSearchSortAriaLabel,
|
||||
aiVaultSearchSortOptions
|
||||
} from './ai-vault-sort-options'
|
||||
import { aiVaultBrowseSortMenu, aiVaultSearchSortMenu } from './ai-vault-sort-options'
|
||||
import {
|
||||
AiVaultResultCountLabel,
|
||||
AiVaultSessionListBar,
|
||||
AiVaultShownCountLabel
|
||||
AiVaultSessionCountLabel
|
||||
} from './AiVaultSessionListBar'
|
||||
|
||||
afterEach(cleanup)
|
||||
@@ -21,8 +16,7 @@ it('reports how many hits are shown and which order produced them', () => {
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultResultCountLabel count={1} />}
|
||||
value="relevance"
|
||||
options={aiVaultSearchSortOptions()}
|
||||
sortAriaLabel={aiVaultSearchSortAriaLabel}
|
||||
menu={aiVaultSearchSortMenu()}
|
||||
onChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
@@ -33,8 +27,7 @@ it('reports how many hits are shown and which order produced them', () => {
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultResultCountLabel count={20} />}
|
||||
value="newest"
|
||||
options={aiVaultSearchSortOptions()}
|
||||
sortAriaLabel={aiVaultSearchSortAriaLabel}
|
||||
menu={aiVaultSearchSortMenu()}
|
||||
onChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
@@ -45,18 +38,28 @@ it('reports how many hits are shown and which order produced them', () => {
|
||||
it('reports how much of the browsed history is shown and its order', () => {
|
||||
render(
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultShownCountLabel shown={4} recent={12} />}
|
||||
label={<AiVaultSessionCountLabel shown={4} loaded={12} />}
|
||||
value="created"
|
||||
options={aiVaultBrowseSortOptions()}
|
||||
sortAriaLabel={aiVaultBrowseSortAriaLabel}
|
||||
menu={aiVaultBrowseSortMenu()}
|
||||
onChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
expect(screen.getByText('4 shown · 12 recent')).toBeTruthy()
|
||||
expect(screen.getByText('4 shown')).toBeTruthy()
|
||||
expect(screen.getByText('4 of 12 sessions')).toBeTruthy()
|
||||
expect(screen.getByRole('button', { name: 'Sort sessions: Created' })).toBeTruthy()
|
||||
})
|
||||
|
||||
it('counts plainly when filters hide nothing', () => {
|
||||
render(
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultSessionCountLabel shown={12} loaded={12} />}
|
||||
value="updated"
|
||||
menu={aiVaultBrowseSortMenu()}
|
||||
onChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
expect(screen.getByText('12 sessions')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('hands the picked search order back to the caller', async () => {
|
||||
const onChange = vi.fn()
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 })
|
||||
@@ -64,8 +67,7 @@ it('hands the picked search order back to the caller', async () => {
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultResultCountLabel count={20} />}
|
||||
value="relevance"
|
||||
options={aiVaultSearchSortOptions()}
|
||||
sortAriaLabel={aiVaultSearchSortAriaLabel}
|
||||
menu={aiVaultSearchSortMenu()}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)
|
||||
@@ -81,10 +83,9 @@ it('hands the picked browse order back to the caller', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 })
|
||||
render(
|
||||
<AiVaultSessionListBar
|
||||
label={<AiVaultShownCountLabel shown={4} recent={12} />}
|
||||
label={<AiVaultSessionCountLabel shown={4} loaded={12} />}
|
||||
value="updated"
|
||||
options={aiVaultBrowseSortOptions()}
|
||||
sortAriaLabel={aiVaultBrowseSortAriaLabel}
|
||||
menu={aiVaultBrowseSortMenu()}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { AiVaultSortOption } from './ai-vault-sort-options'
|
||||
import type { AiVaultSortMenu } from './ai-vault-sort-options'
|
||||
|
||||
/** Left-hand label while searching: how many hits the list is showing. */
|
||||
export function AiVaultResultCountLabel({ count }: { count: number }): React.JSX.Element {
|
||||
@@ -23,31 +23,29 @@ export function AiVaultResultCountLabel({ count }: { count: number }): React.JSX
|
||||
)
|
||||
}
|
||||
|
||||
/** Left-hand label while browsing: how much of the scanned history the list is showing. */
|
||||
export function AiVaultShownCountLabel({
|
||||
/** Left-hand label while browsing: the count, and how much of the scan filters hid. */
|
||||
export function AiVaultSessionCountLabel({
|
||||
shown,
|
||||
recent
|
||||
loaded
|
||||
}: {
|
||||
shown: number
|
||||
recent: number
|
||||
loaded: number
|
||||
}): React.JSX.Element {
|
||||
if (shown !== loaded) {
|
||||
return (
|
||||
<>
|
||||
{translate('sessionSearch.panel.sessionsOfLoaded', '{{value0}} of {{value1}} sessions', {
|
||||
value0: shown,
|
||||
value1: loaded
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{/* Why: below 300px the bar competes with the sort menu, so compact copy prevents overlap. */}
|
||||
<span className="@max-[300px]/ai-vault:hidden">
|
||||
{translate(
|
||||
'auto.components.right.sidebar.AiVaultPanel.shownRecent',
|
||||
'{{value0}} shown · {{value1}} recent',
|
||||
{ value0: shown, value1: recent }
|
||||
)}
|
||||
</span>
|
||||
<span className="hidden @max-[300px]/ai-vault:inline">
|
||||
{translate(
|
||||
'auto.components.right.sidebar.AiVaultPanel.sessionsShownCompact',
|
||||
'{{value0}} shown',
|
||||
{ value0: shown }
|
||||
)}
|
||||
</span>
|
||||
{shown === 1
|
||||
? translate('sessionSearch.panel.sessionsOne', '{{count}} session', { count: shown })
|
||||
: translate('sessionSearch.panel.sessionsOther', '{{count}} sessions', { count: shown })}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -59,17 +57,15 @@ export function AiVaultShownCountLabel({
|
||||
export function AiVaultSessionListBar<Value extends string>({
|
||||
label,
|
||||
value,
|
||||
options,
|
||||
sortAriaLabel,
|
||||
menu,
|
||||
onChange
|
||||
}: {
|
||||
label: ReactNode
|
||||
value: Value
|
||||
options: readonly AiVaultSortOption<Value>[]
|
||||
sortAriaLabel: (selectedLabel: string) => string
|
||||
menu: AiVaultSortMenu<Value>
|
||||
onChange: (value: Value) => void
|
||||
}): React.JSX.Element {
|
||||
const selected = options.find((option) => option.value === value)
|
||||
const selected = menu.options.find((option) => option.value === value)
|
||||
return (
|
||||
<div className="flex h-8 shrink-0 items-center gap-2 border-y border-sidebar-border bg-sidebar-accent/60 pl-3 pr-1.5">
|
||||
<span className="min-w-0 flex-1 truncate text-xs font-semibold tabular-nums text-foreground">
|
||||
@@ -81,7 +77,7 @@ export function AiVaultSessionListBar<Value extends string>({
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="shrink-0"
|
||||
aria-label={sortAriaLabel(selected?.label ?? '')}
|
||||
aria-label={menu.ariaLabel(selected?.label ?? '')}
|
||||
>
|
||||
{selected?.label}
|
||||
<ChevronDown className="text-muted-foreground" />
|
||||
@@ -92,13 +88,13 @@ export function AiVaultSessionListBar<Value extends string>({
|
||||
value={value}
|
||||
// Radix hands back a bare string; the option list is what narrows it.
|
||||
onValueChange={(next) => {
|
||||
const picked = options.find((option) => option.value === next)
|
||||
const picked = menu.options.find((option) => option.value === next)
|
||||
if (picked) {
|
||||
onChange(picked.value)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{options.map((option) => (
|
||||
{menu.options.map((option) => (
|
||||
<DropdownMenuRadioItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</DropdownMenuRadioItem>
|
||||
|
||||
@@ -9,3 +9,8 @@ export function normalizeAiVaultSessionLimit(value: unknown): AiVaultSessionLimi
|
||||
? (value as AiVaultSessionLimit)
|
||||
: DEFAULT_AI_VAULT_SESSION_LIMIT
|
||||
}
|
||||
|
||||
/** The next History depth step, or null once the scan is already unlimited. */
|
||||
export function nextAiVaultSessionLimit(limit: AiVaultSessionLimit): AiVaultSessionLimit | null {
|
||||
return AI_VAULT_SESSION_LIMITS[AI_VAULT_SESSION_LIMITS.indexOf(limit) + 1] ?? null
|
||||
}
|
||||
|
||||
@@ -3,37 +3,46 @@ import type { AiVaultSearchSort, AiVaultSort } from '../../../../shared/ai-vault
|
||||
|
||||
export type AiVaultSortOption<Value extends string> = { value: Value; label: string }
|
||||
|
||||
export function aiVaultBrowseSortOptions(): readonly AiVaultSortOption<AiVaultSort>[] {
|
||||
return [
|
||||
{
|
||||
value: 'updated',
|
||||
label: translate(
|
||||
'auto.components.right.sidebar.AiVaultPanelControls.lastUpdated',
|
||||
'Last updated'
|
||||
)
|
||||
},
|
||||
{
|
||||
value: 'created',
|
||||
label: translate('auto.components.right.sidebar.AiVaultPanelControls.created', 'Created')
|
||||
}
|
||||
]
|
||||
/** One mode's sort menu: its choices, and the accessible name of the trigger showing one. */
|
||||
export type AiVaultSortMenu<Value extends string> = {
|
||||
options: readonly AiVaultSortOption<Value>[]
|
||||
ariaLabel: (selectedLabel: string) => string
|
||||
}
|
||||
|
||||
export function aiVaultSearchSortOptions(): readonly AiVaultSortOption<AiVaultSearchSort>[] {
|
||||
return [
|
||||
{ value: 'relevance', label: translate('sessionSearch.panel.sortRelevance', 'Most relevant') },
|
||||
{ value: 'newest', label: translate('sessionSearch.panel.sortNewest', 'Newest') }
|
||||
]
|
||||
export function aiVaultBrowseSortMenu(): AiVaultSortMenu<AiVaultSort> {
|
||||
return {
|
||||
options: [
|
||||
{
|
||||
value: 'updated',
|
||||
label: translate(
|
||||
'auto.components.right.sidebar.AiVaultPanelControls.lastUpdated',
|
||||
'Last updated'
|
||||
)
|
||||
},
|
||||
{
|
||||
value: 'created',
|
||||
label: translate('auto.components.right.sidebar.AiVaultPanelControls.created', 'Created')
|
||||
}
|
||||
],
|
||||
ariaLabel: (selectedLabel) =>
|
||||
translate('sessionSearch.panel.sortSessionsAriaLabel', 'Sort sessions: {{value0}}', {
|
||||
value0: selectedLabel
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function aiVaultBrowseSortAriaLabel(selectedLabel: string): string {
|
||||
return translate('sessionSearch.panel.sortSessionsAriaLabel', 'Sort sessions: {{value0}}', {
|
||||
value0: selectedLabel
|
||||
})
|
||||
}
|
||||
|
||||
export function aiVaultSearchSortAriaLabel(selectedLabel: string): string {
|
||||
return translate('sessionSearch.panel.sortResultsAriaLabel', 'Sort results: {{value0}}', {
|
||||
value0: selectedLabel
|
||||
})
|
||||
export function aiVaultSearchSortMenu(): AiVaultSortMenu<AiVaultSearchSort> {
|
||||
return {
|
||||
options: [
|
||||
{
|
||||
value: 'relevance',
|
||||
label: translate('sessionSearch.panel.sortRelevance', 'Most relevant')
|
||||
},
|
||||
{ value: 'newest', label: translate('sessionSearch.panel.sortNewest', 'Newest') }
|
||||
],
|
||||
ariaLabel: (selectedLabel) =>
|
||||
translate('sessionSearch.panel.sortResultsAriaLabel', 'Sort results: {{value0}}', {
|
||||
value0: selectedLabel
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13201,8 +13201,6 @@
|
||||
"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",
|
||||
@@ -18021,7 +18019,11 @@
|
||||
"enable": "Enable",
|
||||
"retry": "Try again",
|
||||
"scopeUnknown": "This computer does not have this workspace or project. Switch the scope to All to search everything on it.",
|
||||
"sortSessionsAriaLabel": "Sort sessions: {{value0}}"
|
||||
"sortSessionsAriaLabel": "Sort sessions: {{value0}}",
|
||||
"sessionsOne": "{{count}} session",
|
||||
"sessionsOther": "{{count}} sessions",
|
||||
"sessionsOfLoaded": "{{value0}} of {{value1}} sessions",
|
||||
"showMoreSessions": "Show more sessions"
|
||||
}
|
||||
},
|
||||
"sessionHistory": {
|
||||
|
||||
@@ -11376,7 +11376,6 @@
|
||||
"localWorkspacesOnly": "Reanudar desde el historial solo está disponible en espacios de trabajo locales.",
|
||||
"agentSessionQueued": "Sesión de {{value0}} en cola",
|
||||
"sessionHistory": "Historial de sesiones de agentes",
|
||||
"shownRecent": "{{value0}} mostradas · {{value1}} recientes",
|
||||
"resumePastSessions": "Reanudar sesiones anteriores",
|
||||
"refreshSessionHistory": "Actualizar historial de sesiones",
|
||||
"searchSessions": "Buscar sesiones",
|
||||
@@ -11389,7 +11388,6 @@
|
||||
"sessionId": "ID de sesión",
|
||||
"logPath": "Ruta del log",
|
||||
"agents": "Agentes",
|
||||
"sessionsShownCompact": "{{value0}} mostradas",
|
||||
"originalPaneUnavailable": "El panel original ya no está disponible.",
|
||||
"worktreeUnavailable": "El worktree ya no está disponible.",
|
||||
"openSupportedWorkspace": "Abre un workspace antes de reanudar una sesión.",
|
||||
|
||||
@@ -12503,8 +12503,6 @@
|
||||
"agentSessionQueued": "Session {{value0}} en file d'attente",
|
||||
"sessionHistory": "Historique des sessions d'agent",
|
||||
"agents": "Agents",
|
||||
"shownRecent": "{{value0}} affichées · {{value1}} récentes",
|
||||
"sessionsShownCompact": "{{value0}} affichées",
|
||||
"resumePastSessions": "Reprendre les sessions passées",
|
||||
"refreshSessionHistory": "Actualiser l'historique des sessions",
|
||||
"searchSessions": "Rechercher des sessions",
|
||||
|
||||
@@ -11376,7 +11376,6 @@
|
||||
"localWorkspacesOnly": "履歴からの再開はローカルワークスペースでのみ利用できます。",
|
||||
"agentSessionQueued": "{{value0}} 件のセッションが順番待ち",
|
||||
"sessionHistory": "Agent セッション履歴",
|
||||
"shownRecent": "{{value0}}表示 · {{value1}}最近",
|
||||
"resumePastSessions": "過去のセッションを再開",
|
||||
"refreshSessionHistory": "セッション履歴を更新",
|
||||
"searchSessions": "セッションを検索",
|
||||
@@ -11389,7 +11388,6 @@
|
||||
"sessionId": "セッション ID",
|
||||
"logPath": "ログパス",
|
||||
"agents": "Agent",
|
||||
"sessionsShownCompact": "{{value0}} 件表示",
|
||||
"originalPaneUnavailable": "元のペインは利用できなくなりました。",
|
||||
"worktreeUnavailable": "ワークツリーは利用できなくなりました。",
|
||||
"openSupportedWorkspace": "セッションを再開する前に、ワークスペースを開いてください。",
|
||||
|
||||
@@ -11418,7 +11418,6 @@
|
||||
"localWorkspacesOnly": "기록에서 재개하기는 로컬 워크스페이스에서만 사용할 수 있습니다.",
|
||||
"agentSessionQueued": "{{value0}} 세션이 대기열에 추가됨",
|
||||
"sessionHistory": "Agent 세션 기록",
|
||||
"shownRecent": "{{value0}}개 표시 · 최근 {{value1}}개",
|
||||
"resumePastSessions": "이전 세션 재개",
|
||||
"refreshSessionHistory": "세션 기록 새로고침",
|
||||
"searchSessions": "세션 검색",
|
||||
@@ -11431,7 +11430,6 @@
|
||||
"sessionId": "세션 ID",
|
||||
"logPath": "로그 경로",
|
||||
"agents": "에이전트",
|
||||
"sessionsShownCompact": "{{value0}} 표시됨",
|
||||
"originalPaneUnavailable": "원래 창은 더 이상 사용할 수 없습니다.",
|
||||
"worktreeUnavailable": "워크트리는 더 이상 사용할 수 없습니다.",
|
||||
"openSupportedWorkspace": "세션을 재개하기 전에 워크스페이스를 여세요.",
|
||||
|
||||
@@ -11456,7 +11456,6 @@
|
||||
"localWorkspacesOnly": "从历史记录恢复仅适用于本地工作区。",
|
||||
"agentSessionQueued": "{{value0}} 会话已排队",
|
||||
"sessionHistory": "智能体会话历史",
|
||||
"shownRecent": "已显示 {{value0}} 项 · 最近 {{value1}} 项",
|
||||
"resumePastSessions": "恢复过往会话",
|
||||
"refreshSessionHistory": "刷新会话历史",
|
||||
"searchSessions": "搜索会话",
|
||||
@@ -11469,7 +11468,6 @@
|
||||
"sessionId": "会话 ID",
|
||||
"logPath": "日志路径",
|
||||
"agents": "智能体",
|
||||
"sessionsShownCompact": "已显示 {{value0}} 个",
|
||||
"originalPaneUnavailable": "原始面板不再可用。",
|
||||
"worktreeUnavailable": "工作树不再可用。",
|
||||
"openSupportedWorkspace": "在恢复会话之前,请先打开一个工作区。",
|
||||
|
||||
Reference in New Issue
Block a user