From ad8636893a51732a9b05d193bdff25dd687c5c12 Mon Sep 17 00:00:00 2001 From: "haozhe.yang" Date: Thu, 3 Sep 2026 10:22:12 +0800 Subject: [PATCH] feat(agent-core-v2): add depth option to host fs watch HostFsWatchOptions gains a depth field, passed through to chokidar's depth option, so watchers can bound recursion (0 = only the directory itself) instead of always watching whole trees. --- .../backends/node-local/hostFsWatchService.ts | 2 +- .../src/os/interface/hostFsWatch.ts | 1 + .../node-local/hostFsWatchService.test.ts | 20 ++++++++++++++----- pnpm-lock.yaml | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/agent-core-v2/src/os/backends/node-local/hostFsWatchService.ts b/packages/agent-core-v2/src/os/backends/node-local/hostFsWatchService.ts index 17fc565b18d..446562df84f 100644 --- a/packages/agent-core-v2/src/os/backends/node-local/hostFsWatchService.ts +++ b/packages/agent-core-v2/src/os/backends/node-local/hostFsWatchService.ts @@ -99,7 +99,7 @@ class HostFsWatchHandle implements IHostFsWatchHandle { ignoreInitial: true, persistent: false, followSymlinks: false, - depth: options?.recursive === false ? 0 : undefined, + depth: options?.depth ?? (options?.recursive === false ? 0 : undefined), ignored: options?.ignored ?? DEFAULT_IGNORED, }); this.watcher.on('all', (eventName: string, absPath: string) => { diff --git a/packages/agent-core-v2/src/os/interface/hostFsWatch.ts b/packages/agent-core-v2/src/os/interface/hostFsWatch.ts index bf59a2caaa6..5ff45b06b8a 100644 --- a/packages/agent-core-v2/src/os/interface/hostFsWatch.ts +++ b/packages/agent-core-v2/src/os/interface/hostFsWatch.ts @@ -14,6 +14,7 @@ export interface HostFsChange { export interface HostFsWatchOptions { readonly recursive?: boolean; readonly ignored?: (path: string) => boolean; + readonly depth?: number; readonly signal?: boolean; } diff --git a/packages/agent-core-v2/test/os/backends/node-local/hostFsWatchService.test.ts b/packages/agent-core-v2/test/os/backends/node-local/hostFsWatchService.test.ts index aef8e4f3ab9..15e721c8bea 100644 --- a/packages/agent-core-v2/test/os/backends/node-local/hostFsWatchService.test.ts +++ b/packages/agent-core-v2/test/os/backends/node-local/hostFsWatchService.test.ts @@ -237,6 +237,8 @@ describe('host filesystem change notifications', () => { it('reports create / modify / delete for a file', async () => { root = await mkdtemp(join(tmpdir(), 'hostfswatch-')); + const preexisting = join(root, 'pre.txt'); + await writeFile(preexisting, 'v0'); const events = await start(); const file = join(root, 'a.txt'); @@ -247,6 +249,7 @@ describe('host filesystem change notifications', () => { await rm(file); await wait(300); + expect(events.some((e) => e.path === preexisting)).toBe(false); const actions = events.filter((e) => e.path === file).map((e) => e.action); expect(actions).toContain('created'); expect(actions).toContain('modified'); @@ -265,15 +268,22 @@ describe('host filesystem change notifications', () => { expect(events.some((e) => e.path.includes('/.git/') || e.path.endsWith('/.git'))).toBe(false); }); - it('does not fire for pre-existing files (ignoreInitial)', async () => { + it('does not report changes below the configured depth', async () => { root = await mkdtemp(join(tmpdir(), 'hostfswatch-')); - const preexisting = join(root, 'pre.txt'); - await writeFile(preexisting, 'v0'); + const events: HostFsChange[] = []; + const svc = new HostFsWatchService(); + handle = svc.watch(root, { depth: 0 }); + handle.onDidChange((e) => events.push(e)); + await handle.ready; - const events = await start(); + await mkdir(join(root, 'sub')); + await writeFile(join(root, 'top.txt'), 'x'); + await writeFile(join(root, 'sub', 'nested.txt'), 'x'); await wait(300); - expect(events.some((e) => e.path === preexisting)).toBe(false); + expect(events.some((e) => e.path === join(root, 'top.txt'))).toBe(true); + expect(events.some((e) => e.path === join(root, 'sub'))).toBe(true); + expect(events.some((e) => e.path.endsWith('nested.txt'))).toBe(false); }); it('stops firing after the handle is disposed', async () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da5d1b62fb3..f4e61c19698 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13439,7 +13439,7 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@22.19.17)(@vitest/coverage-v8@4.1.4)(jsdom@30.0.1)(msw@2.15.0(@types/node@22.19.17)(typescript@6.0.2))(vite@6.4.2(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@types/node@22.19.17)(@vitest/coverage-v8@4.1.4)(jsdom@30.0.1)(msw@2.15.0(@types/node@22.19.17)(typescript@6.0.2))(vite@8.0.8(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/expect@4.1.4': dependencies: