feat(agent-manager): open pull requests with keyboard shortcut

This commit is contained in:
marius-kilocode
2026-06-17 14:49:27 +02:00
parent fb6b5ed63f
commit 1933cf7cab
28 changed files with 73 additions and 5 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"kilo-code": minor
---
Open the selected Agent Manager worktree's pull request with Cmd/Ctrl+Shift+R.
+11
View File
@@ -289,6 +289,11 @@
"title": "Agent Manager: Open Worktree",
"category": "Kilo Code"
},
{
"command": "kilo-code.new.agentManager.openPR",
"title": "Agent Manager: Open Pull Request",
"category": "Kilo Code"
},
{
"command": "kilo-code.new.agentManager.closeWorktree",
"title": "Agent Manager: Close Worktree",
@@ -694,6 +699,12 @@
"mac": "cmd+shift+o",
"when": "activeWebviewPanelId == 'kilo-code.new.AgentManagerPanel'"
},
{
"command": "kilo-code.new.agentManager.openPR",
"key": "ctrl+shift+r",
"mac": "cmd+shift+r",
"when": "activeWebviewPanelId == 'kilo-code.new.AgentManagerPanel'"
},
{
"command": "kilo-code.new.agentManager.closeWorktree",
"key": "ctrl+shift+w",
+3
View File
@@ -468,6 +468,9 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand("kilo-code.new.agentManager.openWorktree", () => {
agentManagerProvider.postMessage({ type: "action", action: "openWorktree" })
}),
vscode.commands.registerCommand("kilo-code.new.agentManager.openPR", () => {
agentManagerProvider.postMessage({ type: "action", action: "openPR" })
}),
vscode.commands.registerCommand("kilo-code.new.agentManager.closeWorktree", () => {
agentManagerProvider.postMessage({ type: "action", action: "closeWorktree" })
}),
@@ -114,6 +114,17 @@ describe("Extension — package.json command sync", () => {
when: "activeWebviewPanelId == 'kilo-code.new.AgentManagerPanel' && !terminalFocus",
})
})
it("scopes the open PR shortcut to Agent Manager", () => {
const binding = pkg.contributes?.keybindings?.find(
(item: { command: string }) => item.command === "kilo-code.new.agentManager.openPR",
)
expect(binding).toMatchObject({
key: "ctrl+shift+r",
mac: "cmd+shift+r",
when: "activeWebviewPanelId == 'kilo-code.new.AgentManagerPanel'",
})
})
})
// ---------------------------------------------------------------------------
@@ -143,12 +143,20 @@ describe("buildSidebarSearch", () => {
})
})
describe("sidebar search shortcut", () => {
it("appears in the quick-switch keyboard shortcuts section", () => {
describe("Agent Manager shortcut map", () => {
it("includes sidebar search in the quick-switch section", () => {
const categories = buildShortcutCategories({ search: "⌘F", jumpTo1: "⌘1" }, (key) => key)
expect(categories[0]?.shortcuts[0]).toEqual({
label: "agentManager.sidebarSearch.label",
binding: "⌘F",
})
})
it("includes open pull request in the sidebar section", () => {
const categories = buildShortcutCategories({ openPR: "⌘⇧R" }, (key) => key)
expect(categories[1]?.shortcuts).toContainEqual({
label: "agentManager.shortcuts.openPR",
binding: "⌘⇧R",
})
})
})
@@ -185,6 +185,7 @@ const defaultBindings: Record<string, string> = {
advancedWorktree: isMac ? "⌘⇧N" : "Ctrl+Shift+N",
closeWorktree: isMac ? "⌘⇧W" : "Ctrl+Shift+W",
openWorktree: isMac ? "⌘⇧O" : "Ctrl+Shift+O",
openPR: isMac ? "⌘⇧R" : "Ctrl+Shift+R",
agentManagerOpen: isMac ? "⌘⇧M" : "Ctrl+Shift+M",
cycleAgentMode: isMac ? "⌘." : "Ctrl+.",
cyclePreviousAgentMode: isMac ? "⌘⇧." : "Ctrl+Shift+.",
@@ -506,6 +507,13 @@ const AgentManagerContent: Component = () => {
}
const openWindow = metrics.click("open_worktree_window", "tab_toolbar", openWorktreeDirectory)
const openSelectedPR = () => {
const sel = selection()
if (!sel || sel === LOCAL || !prStatuses()[sel]) return
metrics.track("open_pull_request", "keyboard_shortcut")
vscode.postMessage({ type: "agentManager.openPR", worktreeId: sel })
}
const runWorktree = (id: string) => {
const state = runStatuses()[id]?.state ?? "idle"
if (state === "running" || state === "stopping") {
@@ -1047,6 +1055,7 @@ const AgentManagerContent: Component = () => {
else if (msg.action === "closeTab") closeActiveTab()
else if (msg.action === "newWorktree") handleNewWorktreeOrPromote()
else if (msg.action === "openWorktree") openWorktreeDirectory()
else if (msg.action === "openPR") openSelectedPR()
else if (msg.action === "runScript") runSelected()
else if (msg.action === "advancedWorktree") showAdvancedWorktreeDialog()
else if (msg.action === "closeWorktree") closeSelectedWorktree()
@@ -1076,8 +1085,8 @@ const AgentManagerContent: Component = () => {
if (["t", "w", "n", "d", "e", "f"].includes(e.key.toLowerCase()) && !e.shiftKey) {
e.preventDefault()
}
// Prevent defaults for shift variants (close worktree, advanced/new open worktree)
if (["w", "n", "o"].includes(e.key.toLowerCase()) && e.shiftKey) {
// Prevent defaults for shift variants (close worktree, advanced/new/open worktree, open PR)
if (["w", "n", "o", "r"].includes(e.key.toLowerCase()) && e.shiftKey) {
e.preventDefault()
}
// Prevent browser defaults for shortcuts help (Cmd/Ctrl+Shift+/)
@@ -79,6 +79,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "العنصر التالي",
"agentManager.shortcuts.newWorktree": "Worktree جديد",
"agentManager.shortcuts.openWorktree": "فتح Worktree",
"agentManager.shortcuts.openPR": "فتح طلب السحب",
"agentManager.shortcuts.advancedWorktree": "تكوين worktree جديد",
"agentManager.shortcuts.deleteWorktree": "حذف Worktree",
"agentManager.shortcuts.previousTab": "علامة التبويب السابقة",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Próximo item",
"agentManager.shortcuts.newWorktree": "Novo Worktree",
"agentManager.shortcuts.openWorktree": "Abrir Worktree",
"agentManager.shortcuts.openPR": "Abrir PR",
"agentManager.shortcuts.advancedWorktree": "Configurar novo worktree",
"agentManager.shortcuts.deleteWorktree": "Excluir Worktree",
"agentManager.shortcuts.previousTab": "Aba anterior",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Sljedeći element",
"agentManager.shortcuts.newWorktree": "Novi Worktree",
"agentManager.shortcuts.openWorktree": "Otvori worktree",
"agentManager.shortcuts.openPR": "Otvori PR",
"agentManager.shortcuts.advancedWorktree": "Konfiguriši novi worktree",
"agentManager.shortcuts.deleteWorktree": "Obriši Worktree",
"agentManager.shortcuts.previousTab": "Prethodna kartica",
@@ -82,6 +82,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Næste element",
"agentManager.shortcuts.newWorktree": "Nyt Worktree",
"agentManager.shortcuts.openWorktree": "Åbn Worktree",
"agentManager.shortcuts.openPR": "Åbn PR",
"agentManager.shortcuts.advancedWorktree": "Konfigurer nyt worktree",
"agentManager.shortcuts.deleteWorktree": "Slet Worktree",
"agentManager.shortcuts.previousTab": "Forrige fane",
@@ -82,6 +82,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Nächstes Element",
"agentManager.shortcuts.newWorktree": "Neuer Worktree",
"agentManager.shortcuts.openWorktree": "Worktree öffnen",
"agentManager.shortcuts.openPR": "Pull Request öffnen",
"agentManager.shortcuts.advancedWorktree": "Neuen Worktree konfigurieren",
"agentManager.shortcuts.deleteWorktree": "Worktree löschen",
"agentManager.shortcuts.previousTab": "Vorheriger Tab",
@@ -85,6 +85,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Next item",
"agentManager.shortcuts.newWorktree": "New worktree",
"agentManager.shortcuts.openWorktree": "Open worktree",
"agentManager.shortcuts.openPR": "Open pull request",
"agentManager.shortcuts.advancedWorktree": "Configure new worktree",
"agentManager.shortcuts.deleteWorktree": "Delete worktree",
"agentManager.shortcuts.previousTab": "Previous tab",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Siguiente elemento",
"agentManager.shortcuts.newWorktree": "Nuevo Worktree",
"agentManager.shortcuts.openWorktree": "Abrir Worktree",
"agentManager.shortcuts.openPR": "Abrir pull request",
"agentManager.shortcuts.advancedWorktree": "Configurar nuevo worktree",
"agentManager.shortcuts.deleteWorktree": "Eliminar Worktree",
"agentManager.shortcuts.previousTab": "Pestaña anterior",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Élément suivant",
"agentManager.shortcuts.newWorktree": "Nouveau Worktree",
"agentManager.shortcuts.openWorktree": "Ouvrir le worktree",
"agentManager.shortcuts.openPR": "Ouvrir la pull request",
"agentManager.shortcuts.advancedWorktree": "Configurer un nouveau worktree",
"agentManager.shortcuts.deleteWorktree": "Supprimer le Worktree",
"agentManager.shortcuts.previousTab": "Onglet précédent",
@@ -86,6 +86,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Elemento successivo",
"agentManager.shortcuts.newWorktree": "Nuovo worktree",
"agentManager.shortcuts.openWorktree": "Apri worktree",
"agentManager.shortcuts.openPR": "Apri pull request",
"agentManager.shortcuts.advancedWorktree": "Configura nuovo worktree",
"agentManager.shortcuts.deleteWorktree": "Elimina worktree",
"agentManager.shortcuts.previousTab": "Scheda precedente",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "次の項目",
"agentManager.shortcuts.newWorktree": "新しいWorktree",
"agentManager.shortcuts.openWorktree": "Worktreeを開く",
"agentManager.shortcuts.openPR": "PRを開く",
"agentManager.shortcuts.advancedWorktree": "新規 worktree の構成",
"agentManager.shortcuts.deleteWorktree": "Worktreeを削除",
"agentManager.shortcuts.previousTab": "前のタブ",
@@ -80,6 +80,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "다음 항목",
"agentManager.shortcuts.newWorktree": "새 Worktree",
"agentManager.shortcuts.openWorktree": "Worktree 열기",
"agentManager.shortcuts.openPR": "PR 열기",
"agentManager.shortcuts.advancedWorktree": "새 worktree 구성",
"agentManager.shortcuts.deleteWorktree": "Worktree 삭제",
"agentManager.shortcuts.previousTab": "이전 탭",
@@ -85,6 +85,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Volgend item",
"agentManager.shortcuts.newWorktree": "Nieuwe worktree",
"agentManager.shortcuts.openWorktree": "Worktree openen",
"agentManager.shortcuts.openPR": "Pull request openen",
"agentManager.shortcuts.advancedWorktree": "Nieuwe worktree configureren",
"agentManager.shortcuts.deleteWorktree": "Worktree verwijderen",
"agentManager.shortcuts.previousTab": "Vorig tabblad",
@@ -80,6 +80,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Neste element",
"agentManager.shortcuts.newWorktree": "Nytt Worktree",
"agentManager.shortcuts.openWorktree": "Åpne Worktree",
"agentManager.shortcuts.openPR": "Åpne pull request",
"agentManager.shortcuts.advancedWorktree": "Konfigurer nytt worktree",
"agentManager.shortcuts.deleteWorktree": "Slett Worktree",
"agentManager.shortcuts.previousTab": "Forrige fane",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Następny element",
"agentManager.shortcuts.newWorktree": "Nowy Worktree",
"agentManager.shortcuts.openWorktree": "Otwórz Worktree",
"agentManager.shortcuts.openPR": "Otwórz pull request",
"agentManager.shortcuts.advancedWorktree": "Skonfiguruj nowe worktree",
"agentManager.shortcuts.deleteWorktree": "Usuń Worktree",
"agentManager.shortcuts.previousTab": "Poprzednia karta",
@@ -81,6 +81,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Следующий элемент",
"agentManager.shortcuts.newWorktree": "Новый Worktree",
"agentManager.shortcuts.openWorktree": "Открыть Worktree",
"agentManager.shortcuts.openPR": "Открыть PR",
"agentManager.shortcuts.advancedWorktree": "Настроить новое worktree",
"agentManager.shortcuts.deleteWorktree": "Удалить Worktree",
"agentManager.shortcuts.previousTab": "Предыдущая вкладка",
@@ -77,6 +77,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "รายการถัดไป",
"agentManager.shortcuts.newWorktree": "Worktree ใหม่",
"agentManager.shortcuts.openWorktree": "เปิด Worktree",
"agentManager.shortcuts.openPR": "เปิด Pull Request",
"agentManager.shortcuts.advancedWorktree": "กำหนดค่า worktree ใหม่",
"agentManager.shortcuts.deleteWorktree": "ลบ Worktree",
"agentManager.shortcuts.previousTab": "แท็บก่อนหน้า",
@@ -86,6 +86,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Sonraki öğe",
"agentManager.shortcuts.newWorktree": "Yeni worktree",
"agentManager.shortcuts.openWorktree": "Worktree aç",
"agentManager.shortcuts.openPR": "Pull request'i aç",
"agentManager.shortcuts.advancedWorktree": "Yeni worktree yapılandır",
"agentManager.shortcuts.deleteWorktree": "Worktree'yi sil",
"agentManager.shortcuts.previousTab": "Önceki sekme",
@@ -87,6 +87,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "Наступний елемент",
"agentManager.shortcuts.newWorktree": "Нове робоче дерево",
"agentManager.shortcuts.openWorktree": "Відкрити робоче дерево",
"agentManager.shortcuts.openPR": "Відкрити PR",
"agentManager.shortcuts.advancedWorktree": "Налаштувати нове worktree",
"agentManager.shortcuts.deleteWorktree": "Видалити робоче дерево",
"agentManager.shortcuts.previousTab": "Попередня вкладка",
@@ -77,6 +77,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "下一项",
"agentManager.shortcuts.newWorktree": "新建 Worktree",
"agentManager.shortcuts.openWorktree": "打开 Worktree",
"agentManager.shortcuts.openPR": "打开 PR",
"agentManager.shortcuts.advancedWorktree": "配置新 worktree",
"agentManager.shortcuts.deleteWorktree": "删除 Worktree",
"agentManager.shortcuts.previousTab": "上一个标签页",
@@ -77,6 +77,7 @@ export const dict = {
"agentManager.shortcuts.nextItem": "下一個項目",
"agentManager.shortcuts.newWorktree": "新建 Worktree",
"agentManager.shortcuts.openWorktree": "開啟 Worktree",
"agentManager.shortcuts.openPR": "開啟 PR",
"agentManager.shortcuts.advancedWorktree": "配置新 worktree",
"agentManager.shortcuts.deleteWorktree": "刪除 Worktree",
"agentManager.shortcuts.previousTab": "上一個分頁",
@@ -36,6 +36,7 @@ export function buildShortcutCategories(
{ label: t("agentManager.shortcuts.advancedWorktree"), binding: bindings.advancedWorktree ?? "" },
{ label: t("agentManager.shortcuts.deleteWorktree"), binding: bindings.closeWorktree ?? "" },
{ label: t("agentManager.shortcuts.openWorktree"), binding: bindings.openWorktree ?? "" },
{ label: t("agentManager.shortcuts.openPR"), binding: bindings.openPR ?? "" },
],
},
{
@@ -110,7 +110,7 @@ function isAgentManagerShortcut(e: KeyboardEvent): boolean {
const key = e.key.toLowerCase()
if (e.altKey && ["arrowleft", "arrowright", "arrowup", "arrowdown"].includes(key)) return true
if (["t", "w", "n", "d", "e", "f"].includes(key)) return true
if (e.shiftKey && ["w", "n", "o", "m", "/", "?"].includes(key)) return true
if (e.shiftKey && ["w", "n", "o", "r", "m", "/", "?"].includes(key)) return true
if (/^[1-9]$/.test(key)) return true
if (key === "/") return true
return false