fix(agent-manager): preserve scoped history activation

This commit is contained in:
marius-kilocode
2026-08-25 14:55:44 +02:00
parent b0100195f5
commit 0f576d0866
5 changed files with 38 additions and 4 deletions
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---
Fix project-scoped Agent Manager history activation and session placement.
@@ -45,6 +45,8 @@ export interface ProjectMessageDeps {
expand: (ctx: ProjectContext) => void
/** Push the current project snapshots to the webview. */
push: () => void
/** Push one project's managed state to the webview. */
pushState?: (ctx: ProjectContext) => void
/** Acknowledge an atomically validated sidebar selection. */
selected: (target: SidebarTarget) => void
/** Show a user-facing error. */
@@ -156,6 +158,7 @@ async function openSessionLocally(projectId: string, sessionId: string, deps: Pr
}
state?.moveSession(sessionId, null)
deps.routeSession?.(projectId, sessionId, ctx.root, ctx.generation)
deps.pushState?.(ctx)
deps.push()
finish({ projectId, kind: "session", sessionId }, deps)
}
@@ -67,6 +67,7 @@ export function createProjectWiring(opts: {
expand: opts.expand,
ready: opts.ready,
push: opts.push,
pushState: opts.pushState,
selected: opts.selected,
routeSession: opts.routeSession,
error: (message) => opts.host.showError(message),
@@ -19,6 +19,7 @@ function fakeState(persisted?: { current?: unknown }) {
return {
getWorktree: (id: string) => (id === "wt1" ? { path: "/repo/prj-extra/wt1" } : undefined),
getSession: (id: string) => (id === "sess1" ? {} : undefined),
moveSession: () => {},
getActiveTarget: () => store.current,
setActiveTarget: (target: unknown) => {
store.current = target
@@ -172,6 +173,27 @@ describe("activateSelection — cross-project selection", () => {
expect(calls.error).toEqual([])
})
it("pushes moved-session state before acknowledging local activation", async () => {
const { contexts, deps, calls, extra } = setup()
const ctx = contexts.expand(extra)!
ctx.stateManager()
await ctx.ensureReady(async () => ({ ok: true, refsFixed: 0 }))
contexts.activate(extra)
const order: string[] = []
deps.push = () => order.push("projects")
deps.pushState = () => order.push("state")
deps.selected = () => order.push("selected")
await handleProjectMessage(
{ type: "agentManager.openSessionLocally", projectId: extra, sessionId: "sess1" } as never,
deps,
)
expect(order).toEqual(["state", "projects", "projects", "selected"])
expect(calls.error).toEqual([])
})
it("restores the persisted target when the selection asks for it", async () => {
const persisted = { current: undefined as unknown }
const { contexts, deps, calls, extra } = setup({ state: () => fakeState(persisted) })
@@ -300,13 +300,18 @@ const AgentManagerContent: Component = () => {
const [history, setHistory] = createSignal(false)
/** Project whose sessions the history view is scoped to (multi-project). */
const [historyProject, setHistoryProject] = createSignal<string | undefined>()
const [historySwitch, setHistorySwitch] = createSignal<string | undefined>()
const closeHistory = () => {
setHistory(false)
setHistoryProject(undefined)
setHistorySwitch(undefined)
}
/** Open the sessions view; a project id scopes it and activates that project. */
const openHistory = (pid?: string) => {
const scoped = pid !== undefined && multiProject()
setHistorySwitch(scoped && currentProjectId() !== pid ? pid : undefined)
setHistoryProject(scoped ? pid : undefined)
setHistory(true)
if (scoped) {
// Activating the target project first lets the shared session store and
// the pick routing operate in that project only.
@@ -315,8 +320,6 @@ const AgentManagerContent: Component = () => {
target: { projectId: pid, kind: "local" },
} as never)
}
setHistoryProject(scoped ? pid : undefined)
setHistory(true)
}
const [sidePanel, setSidePanel] = createSignal<SidePanelState>(null)
const diffOpen = () => sidePanel() === SidePanel.Diff
@@ -765,7 +768,7 @@ const AgentManagerContent: Component = () => {
const pid = historyProject()
if (!pid || !multiProject()) return undefined
const sessions = projectSessionsLive()[pid]
if (!sessions) return undefined
if (!sessions) return new Set<string>()
return new Set(sessions.filter(isKnownRootSession).map((s) => s.id))
})
@@ -1161,7 +1164,7 @@ const AgentManagerContent: Component = () => {
first: () => undefined,
close: () => setReviewActive(false),
hide: () => setSidePanel(null),
history: () => closeHistory(),
history: () => (historySwitch() === state.projectId ? setHistorySwitch(undefined) : closeHistory()),
reset: subagents.reset,
})
}