diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 779a80a9dd3..c04d818b4b8 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -4765,16 +4765,28 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper const part = event.properties.part as { type?: string metadata?: Record - state?: { input?: Record; metadata?: Record } + state?: { status?: string; input?: Record; metadata?: Record } } - if (part.type !== "tool") return + if (part.type !== "tool" || part.state?.status !== "completed") return const values = [part.metadata?.filepath, part.state?.metadata?.filepath, part.state?.input?.filePath] const file = values.find((value): value is string => typeof value === "string" && value.length > 0) if (!file) return const base = this.getWorkspaceDirectory(sessionID) const value = file.split(",")[0].trim() const pathName = path.isAbsolute(value) ? value : path.resolve(base, value) - void this.refreshGitStatus(path.dirname(pathName)) + const directory = path.dirname(pathName) + if (!this.isCurrentProjectGitDirectory(directory, sessionID)) return + void this.refreshGitStatus(directory) + } + + private isCurrentProjectGitDirectory(directory: string, sessionID?: string): boolean { + const roots = this.opts.projectQualifier?.() + ? [this.getRootDirectory(), ...(this.opts.worktreeDirectories?.() ?? [])] + : [this.getWorkspaceDirectory(sessionID)] + return roots.some((root) => { + const rel = path.relative(canonicalizePath(root), canonicalizePath(directory)) + return rel === "" || (!path.isAbsolute(rel) && rel !== ".." && !rel.startsWith(`..${path.sep}`)) + }) } public async refreshGitStatus(directory = this.getWorkspaceDirectory()): Promise { diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts index 035630cb8ef..29be0ad5b20 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts @@ -181,6 +181,7 @@ describe("KiloProvider follow-up sessions", () => { sessionID, part: { type: "tool", + state: { status: "completed" }, metadata: { filepath: "/workspace/frontend/src/app.ts" }, }, }, @@ -191,6 +192,39 @@ describe("KiloProvider follow-up sessions", () => { expect(dirs).toEqual(["/workspace/frontend/src"]) }) + it("ignores completed tool paths outside the active project", () => { + const service = connection() + const provider = new KiloProvider({} as never, service as never, undefined, { + rootDirectory: () => "/workspace", + projectQualifier: () => ({ projectId: "workspace" }), + }) + const internal = provider as unknown as Internals + const dirs: string[] = [] + const sessionID = "ses-external-edit" + internal.currentSession = info({ id: sessionID, projectID: "backend-workspace", directory: "/workspace" }) + internal.trackedSessionIds.add(sessionID) + internal.refreshGitStatus = async (directory) => { + if (directory) dirs.push(directory) + } + + internal.handleEvent( + { + type: "message.part.updated", + properties: { + sessionID, + part: { + type: "tool", + state: { status: "completed" }, + metadata: { filepath: "/other-repo/src/app.ts" }, + }, + }, + } as Event, + "/workspace", + ) + + expect(dirs).toEqual([]) + }) + it("ignores subagents before adopting pending follow-up sessions", async () => { const service = connection() const provider = new KiloProvider({} as never, service as never)