mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
Merge pull request #12845 from Kilo-Org/agent-manager-12806-navigation
fix(vscode): add project-local navigation hints
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Show previous and next navigation hints using each project's own Agent Manager sidebar order.
|
||||
@@ -0,0 +1,25 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { projectAdjacentHint } from "../../webview-ui/agent-manager/project-local-navigation"
|
||||
|
||||
describe("projectAdjacentHint", () => {
|
||||
it("does not leak a hint to another project with the same raw ID", () => {
|
||||
expect(projectAdjacentHint("project-a", "project-a", "shared", "local", ["local", "shared"], "prev", "next")).toBe(
|
||||
"next",
|
||||
)
|
||||
expect(projectAdjacentHint("project-b", "project-a", "shared", "local", ["local", "shared"], "prev", "next")).toBe(
|
||||
"",
|
||||
)
|
||||
})
|
||||
|
||||
it("uses the active project's local sidebar order", () => {
|
||||
expect(projectAdjacentHint("project-a", "project-a", "shared", "local", ["local", "shared"], "prev", "next")).toBe(
|
||||
"next",
|
||||
)
|
||||
expect(projectAdjacentHint("project-a", "project-a", "local", "shared", ["local", "shared"], "prev", "next")).toBe(
|
||||
"prev",
|
||||
)
|
||||
expect(
|
||||
projectAdjacentHint("project-b", "project-b", "shared", "local", ["local", "other", "shared"], "prev", "next"),
|
||||
).toBe("")
|
||||
})
|
||||
})
|
||||
@@ -218,6 +218,7 @@ export const ProjectList: Component<Props> = (props) => {
|
||||
sessions={props.sessions[project.id]}
|
||||
selectedProject={props.selectedProject}
|
||||
selection={props.selection}
|
||||
currentSessionID={props.currentSessionID}
|
||||
bindings={props.bindings}
|
||||
t={props.t}
|
||||
onSelectLocal={(projectId) => select({ projectId, kind: "local" })}
|
||||
|
||||
@@ -20,6 +20,7 @@ import type {
|
||||
} from "../src/types/messages"
|
||||
import type { LanguageContextValue } from "../src/context/language"
|
||||
import { useVSCode } from "../src/context/vscode"
|
||||
import { projectAdjacentHint, projectSidebarOrder } from "./project-local-navigation"
|
||||
import SectionHeader from "./SectionHeader"
|
||||
import { WorktreeItem } from "./WorktreeItem"
|
||||
import { UnassignedSessionsSection } from "./UnassignedSessionsSection"
|
||||
@@ -44,6 +45,7 @@ interface Props {
|
||||
sessions?: ProjectSessionInfo[]
|
||||
selectedProject?: string
|
||||
selection?: string
|
||||
currentSessionID?: () => string | undefined
|
||||
bindings: Record<string, string>
|
||||
t: LanguageContextValue["t"]
|
||||
onSelectLocal: (projectId: string) => void
|
||||
@@ -100,9 +102,23 @@ export const ProjectSidebarBody: Component<Props> = (props) => {
|
||||
const members = (sectionId: string) => sorted().filter((wt) => wt.sectionId === sectionId)
|
||||
const ungrouped = createMemo(() => sorted().filter((wt) => !wt.sectionId))
|
||||
const top = createMemo(() => buildTopLevelItems(sections(), ungrouped(), sorted(), order()))
|
||||
const sidebarOrder = createMemo(() =>
|
||||
projectSidebarOrder(top(), sorted(), sections(), members, state()?.sessionsCollapsed ? [] : localSessions()),
|
||||
)
|
||||
const post = (message: Record<string, unknown>) =>
|
||||
vscode.postMessage({ ...message, projectId: props.project.id } as never)
|
||||
|
||||
const navHint = (id: string) =>
|
||||
projectAdjacentHint(
|
||||
props.project.id,
|
||||
props.selectedProject,
|
||||
id,
|
||||
props.selection ?? props.currentSessionID?.(),
|
||||
sidebarOrder(),
|
||||
props.bindings.previousSession ?? "",
|
||||
props.bindings.nextSession ?? "",
|
||||
)
|
||||
|
||||
const scope = (kind: "section" | "worktree", id: string) => `${props.project.id}:${kind}:${id}`
|
||||
const parse = (kind: "section" | "worktree", value: unknown) => {
|
||||
if (typeof value !== "string") return
|
||||
@@ -226,6 +242,7 @@ export const ProjectSidebarBody: Component<Props> = (props) => {
|
||||
working={runs()[worktree.id]?.state === "running"}
|
||||
stale={state()?.staleWorktreeIds?.includes(worktree.id) === true}
|
||||
stats={props.stats?.[worktree.id]}
|
||||
navHint={navHint(worktree.id)}
|
||||
sessions={sessions(worktree.id).length}
|
||||
grouped={isGrouped(worktree)}
|
||||
groupStart={isGroupStart(worktree, idx(), list)}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { adjacentHint } from "./navigate"
|
||||
import { buildSidebarOrder } from "./section-helpers"
|
||||
|
||||
export function projectSidebarOrder(...args: Parameters<typeof buildSidebarOrder>): string[] {
|
||||
return buildSidebarOrder(...args).map((item) => item.id)
|
||||
}
|
||||
|
||||
export function projectAdjacentHint(
|
||||
projectId: string,
|
||||
activeProjectId: string | undefined,
|
||||
itemId: string,
|
||||
activeId: string | undefined,
|
||||
flatIds: string[],
|
||||
prev: string,
|
||||
next: string,
|
||||
): string {
|
||||
if (projectId !== activeProjectId) return ""
|
||||
return adjacentHint(itemId, activeId, flatIds, prev, next)
|
||||
}
|
||||
Reference in New Issue
Block a user