feat(agent-manager): add close others tab action

This commit is contained in:
kirillk
2026-06-16 21:31:39 -04:00
parent 93dd00b6bc
commit c5bd1b3e09
25 changed files with 59 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"kilo-code": minor
---
Support closing other Agent Manager tabs from the tab context menu.
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "جلسة للقراءة فقط",
"agentManager.session.noSessions": "لا توجد جلسات مفتوحة",
"agentManager.tab.close": "إغلاق",
"agentManager.tab.closeOthers": "إغلاق الآخرين",
"agentManager.tab.closeTab": "إغلاق علامة التبويب",
"agentManager.tab.forkSession": "تفريع الجلسة",
"agentManager.tab.terminal": "الطرفية",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Sessão somente leitura",
"agentManager.session.noSessions": "Nenhuma sessão aberta",
"agentManager.tab.close": "Fechar",
"agentManager.tab.closeOthers": "Fechar outras",
"agentManager.tab.closeTab": "Fechar aba",
"agentManager.tab.forkSession": "Bifurcar sessão",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Sesija samo za čitanje",
"agentManager.session.noSessions": "Nema otvorenih sesija",
"agentManager.tab.close": "Zatvori",
"agentManager.tab.closeOthers": "Zatvori ostale",
"agentManager.tab.closeTab": "Zatvori karticu",
"agentManager.tab.forkSession": "Razdvoji sesiju",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Skrivebeskyttet session",
"agentManager.session.noSessions": "Ingen åbne sessioner",
"agentManager.tab.close": "Luk",
"agentManager.tab.closeOthers": "Luk andre",
"agentManager.tab.closeTab": "Luk fane",
"agentManager.tab.forkSession": "Forgren session",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Schreibgeschützte Sitzung",
"agentManager.session.noSessions": "Keine Sitzungen geöffnet",
"agentManager.tab.close": "Schließen",
"agentManager.tab.closeOthers": "Andere schließen",
"agentManager.tab.closeTab": "Tab schließen",
"agentManager.tab.forkSession": "Sitzung verzweigen",
"agentManager.tab.terminal": "Terminal",
@@ -50,6 +50,7 @@ export const dict = {
"agentManager.session.noSessions": "No sessions open",
"agentManager.tab.close": "Close",
"agentManager.tab.closeOthers": "Close Others",
"agentManager.tab.closeTab": "Close tab",
"agentManager.tab.forkSession": "Fork Session",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Sesión de solo lectura",
"agentManager.session.noSessions": "No hay sesiones abiertas",
"agentManager.tab.close": "Cerrar",
"agentManager.tab.closeOthers": "Cerrar otras",
"agentManager.tab.closeTab": "Cerrar pestaña",
"agentManager.tab.forkSession": "Bifurcar sesión",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Session en lecture seule",
"agentManager.session.noSessions": "Aucune session ouverte",
"agentManager.tab.close": "Fermer",
"agentManager.tab.closeOthers": "Fermer les autres",
"agentManager.tab.closeTab": "Fermer l'onglet",
"agentManager.tab.forkSession": "Dupliquer la session",
"agentManager.tab.terminal": "Terminal",
@@ -50,6 +50,7 @@ export const dict = {
"agentManager.session.noSessions": "Nessuna sessione aperta",
"agentManager.tab.close": "Chiudi",
"agentManager.tab.closeOthers": "Chiudi le altre",
"agentManager.tab.closeTab": "Chiudi scheda",
"agentManager.tab.forkSession": "Forka sessione",
"agentManager.tab.terminal": "Terminale",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "読み取り専用セッション",
"agentManager.session.noSessions": "開いているセッションがありません",
"agentManager.tab.close": "閉じる",
"agentManager.tab.closeOthers": "他を閉じる",
"agentManager.tab.closeTab": "タブを閉じる",
"agentManager.tab.forkSession": "セッションをフォーク",
"agentManager.tab.terminal": "ターミナル",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "읽기 전용 세션",
"agentManager.session.noSessions": "열린 세션 없음",
"agentManager.tab.close": "닫기",
"agentManager.tab.closeOthers": "다른 탭 닫기",
"agentManager.tab.closeTab": "탭 닫기",
"agentManager.tab.forkSession": "세션 포크",
"agentManager.tab.terminal": "터미널",
@@ -50,6 +50,7 @@ export const dict = {
"agentManager.session.noSessions": "Geen open sessies",
"agentManager.tab.close": "Sluiten",
"agentManager.tab.closeOthers": "Andere sluiten",
"agentManager.tab.closeTab": "Tabblad sluiten",
"agentManager.tab.forkSession": "Sessie forken",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Skrivebeskyttet økt",
"agentManager.session.noSessions": "Ingen åpne økter",
"agentManager.tab.close": "Lukk",
"agentManager.tab.closeOthers": "Lukk andre",
"agentManager.tab.closeTab": "Lukk fane",
"agentManager.tab.forkSession": "Forgrein økt",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Sesja tylko do odczytu",
"agentManager.session.noSessions": "Brak otwartych sesji",
"agentManager.tab.close": "Zamknij",
"agentManager.tab.closeOthers": "Zamknij pozostałe",
"agentManager.tab.closeTab": "Zamknij kartę",
"agentManager.tab.forkSession": "Rozgałęź sesję",
"agentManager.tab.terminal": "Terminal",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "Сессия только для чтения",
"agentManager.session.noSessions": "Нет открытых сессий",
"agentManager.tab.close": "Закрыть",
"agentManager.tab.closeOthers": "Закрыть остальные",
"agentManager.tab.closeTab": "Закрыть вкладку",
"agentManager.tab.forkSession": "Ответвить сессию",
"agentManager.tab.terminal": "Терминал",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "เซสชันอ่านอย่างเดียว",
"agentManager.session.noSessions": "ไม่มีเซสชันที่เปิดอยู่",
"agentManager.tab.close": "ปิด",
"agentManager.tab.closeOthers": "ปิดแท็บอื่น",
"agentManager.tab.closeTab": "ปิดแท็บ",
"agentManager.tab.forkSession": "แยกเซสชัน",
"agentManager.tab.terminal": "เทอร์มินัล",
@@ -50,6 +50,7 @@ export const dict = {
"agentManager.session.noSessions": "Açık oturum yok",
"agentManager.tab.close": "Kapat",
"agentManager.tab.closeOthers": "Diğerlerini kapat",
"agentManager.tab.closeTab": "Sekmeyi kapat",
"agentManager.tab.forkSession": "Oturumu Fork'la",
"agentManager.tab.terminal": "Terminal",
@@ -50,6 +50,7 @@ export const dict = {
"agentManager.session.noSessions": "Немає відкритих сесій",
"agentManager.tab.close": "Закрити",
"agentManager.tab.closeOthers": "Закрити інші",
"agentManager.tab.closeTab": "Закрити вкладку",
"agentManager.tab.forkSession": "Розгалужити сесію",
"agentManager.tab.terminal": "Термінал",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "只读会话",
"agentManager.session.noSessions": "没有打开的会话",
"agentManager.tab.close": "关闭",
"agentManager.tab.closeOthers": "关闭其他标签页",
"agentManager.tab.closeTab": "关闭标签页",
"agentManager.tab.forkSession": "复制会话",
"agentManager.tab.terminal": "终端",
@@ -46,6 +46,7 @@ export const dict = {
"agentManager.session.readonly": "唯讀工作階段",
"agentManager.session.noSessions": "沒有開啟的工作階段",
"agentManager.tab.close": "關閉",
"agentManager.tab.closeOthers": "關閉其他分頁",
"agentManager.tab.closeTab": "關閉分頁",
"agentManager.tab.forkSession": "複製工作階段",
"agentManager.tab.terminal": "終端機",
@@ -52,6 +52,7 @@ export const SortableTab: Component<{
onSelect: () => void
onMiddleClick: (e: MouseEvent) => void
onClose: () => void
onCloseOthers: () => void
onFork?: () => void
}> = (props) => {
const { t } = useLanguage()
@@ -130,6 +131,10 @@ export const SortableTab: Component<{
</span>
</Show>
</ContextMenu.Item>
<ContextMenu.Item onSelect={props.onCloseOthers}>
<Icon name="close" size="small" />
<ContextMenu.ItemLabel>{t("agentManager.tab.closeOthers")}</ContextMenu.ItemLabel>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu>
@@ -74,6 +74,7 @@ export function renderTab(id: string, deps: TabRenderDeps): JSX.Element {
onSelect: deps.activateTerminal,
onMiddleClick: deps.terminalMiddleClick,
onClose: deps.closeTerminal,
onCloseOthers: (target) => closeOthers(target, deps),
})
}
if (id === deps.REVIEW_TAB_ID) return renderReviewTab(deps)
@@ -141,11 +142,32 @@ function renderSessionTab(s: SessionInfo, deps: TabRenderDeps): JSX.Element {
}}
onMiddleClick={(e: MouseEvent) => deps.sessionMiddleClick(s.id, e)}
onClose={() => deps.sessionClose(s.id)}
onCloseOthers={() => closeOthers(s.id, deps)}
onFork={pending ? undefined : () => deps.sessionFork(s.id)}
/>
)
}
function closeOthers(target: string, deps: TabRenderDeps) {
for (const id of deps.tabIds()) {
if (id === target) continue
if (isTerminalTabId(id)) {
deps.closeTerminal(id)
continue
}
if (id === deps.REVIEW_TAB_ID) {
deps.closeReview()
continue
}
deps.sessionClose(id)
}
if (isTerminalTabId(target)) {
deps.activateTerminal(target)
return
}
deps.selectSessionTab(target, deps.isPending(target))
}
// Terminal-specific renderers (layer + add button) live in `./terminal/render.tsx`
// and are re-exported for convenience so AgentManagerApp.tsx has a single
// import point for tab rendering.
@@ -33,6 +33,7 @@ export const SortableTerminalTab: Component<{
onSelect: () => void
onMiddleClick: (e: MouseEvent) => void
onClose: (e: MouseEvent) => void
onCloseOthers: () => void
}> = (props) => {
const { t } = useLanguage()
const sortable = createSortable(props.id)
@@ -99,6 +100,10 @@ export const SortableTerminalTab: Component<{
</span>
</Show>
</ContextMenu.Item>
<ContextMenu.Item onSelect={props.onCloseOthers}>
<Icon name="close" size="small" />
<ContextMenu.ItemLabel>{t("agentManager.tab.closeOthers")}</ContextMenu.ItemLabel>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu>
@@ -22,6 +22,7 @@ export interface TerminalTabRenderDeps {
onSelect: (id: string) => void
onMiddleClick: (id: string, e: MouseEvent) => void
onClose: (id: string) => void
onCloseOthers: (id: string) => void
}
/** Render the terminal entry inside the agent-manager tab bar `<For>`. */
@@ -43,6 +44,7 @@ export function renderTerminalTab(deps: TerminalTabRenderDeps): JSX.Element {
e.stopPropagation()
deps.onClose(deps.id)
}}
onCloseOthers={() => deps.onCloseOthers(deps.id)}
/>
)
}