|
1 | 1 | import os from 'os' |
2 | | -import { watch, type FSWatcher } from 'fs' |
3 | 2 |
|
4 | | -import { loadSkills as sdkLoadSkills, resolveSkillsDirs } from '@codebuff/sdk' |
| 3 | +import { loadSkills as sdkLoadSkills } from '@codebuff/sdk' |
5 | 4 |
|
6 | 5 | import { getProjectRoot, tryGetProjectRoot } from '../project-files' |
7 | 6 | import { logger } from './logger' |
@@ -93,62 +92,11 @@ export async function refreshSkillRegistry(): Promise<boolean> { |
93 | 92 | } |
94 | 93 |
|
95 | 94 | // ============================================================================ |
96 | | -// Live reload (Claude Code parity) |
| 95 | +// Live reload |
97 | 96 | // ============================================================================ |
98 | | -// Claude Code watches skill directories and picks up add/edit/delete within |
99 | | -// the running session. Without this, a skill installed mid-session is |
100 | | -// invisible until restart — the "install every time" complaint. |
101 | | - |
102 | | -const SKILLS_WATCH_DEBOUNCE_MS = 300 |
103 | | - |
104 | | -let skillWatchers: FSWatcher[] = [] |
105 | | - |
106 | | -/** |
107 | | - * Start watching the resolved skill directories (global + project, Claude |
108 | | - * locations included). Idempotent. A directory that does not exist yet is |
109 | | - * skipped — installs that create it later are caught by the refresh when the |
110 | | - * /skills panel opens. |
111 | | - */ |
112 | | -export function startSkillDirWatcher(): void { |
113 | | - if (skillWatchers.length > 0) return |
114 | | - |
115 | | - const cwd = skillsCwd() |
116 | | - const homeDir = os.homedir() |
117 | | - const dirs = resolveSkillsDirs({ cwd, homeDir }) |
118 | | - |
119 | | - let debounceTimer: ReturnType<typeof setTimeout> | null = null |
120 | | - const scheduleRefresh = () => { |
121 | | - if (debounceTimer) clearTimeout(debounceTimer) |
122 | | - debounceTimer = setTimeout(() => { |
123 | | - debounceTimer = null |
124 | | - void refreshSkillRegistry() |
125 | | - }, SKILLS_WATCH_DEBOUNCE_MS) |
126 | | - } |
127 | | - |
128 | | - for (const dir of dirs) { |
129 | | - try { |
130 | | - const watcher = watch(dir, { persistent: false }, () => { |
131 | | - // Filter nothing: skill installs create directories AND write |
132 | | - // SKILL.md inside them, whole-skill deletes only touch the dir name, |
133 | | - // and the refresh itself is a debounced handful of stat+read calls. |
134 | | - // Simpler and correct beats a filename heuristic that misses cases. |
135 | | - scheduleRefresh() |
136 | | - }) |
137 | | - watcher.on('error', (error) => { |
138 | | - logger.warn({ error }, `Skill watcher error for ${dir}`) |
139 | | - }) |
140 | | - skillWatchers.push(watcher) |
141 | | - } catch { |
142 | | - // Directory does not exist (e.g. no ~/.agents/skills yet). Nothing to |
143 | | - // watch; installs create it fresh and a restart picks them up. |
144 | | - } |
145 | | - } |
146 | | -} |
147 | | - |
148 | | -export function stopSkillDirWatcher(): void { |
149 | | - for (const watcher of skillWatchers) watcher.close() |
150 | | - skillWatchers = [] |
151 | | -} |
| 97 | +// Implemented on feat/skills-reload — deliberately not here. Watching skill |
| 98 | +// directories is an independently reviewable feature (recursive watch |
| 99 | +// semantics differ per platform) and lives in its own PR. |
152 | 100 |
|
153 | 101 | /** |
154 | 102 | * Initialize the skill registry by loading skills via the SDK. |
@@ -237,7 +185,6 @@ export function getLoadedSkillsMessage(): string | null { |
237 | 185 | export function __resetSkillRegistryForTests(): void { |
238 | 186 | skillsCache = {} |
239 | 187 | skillsVersion = 0 |
240 | | - stopSkillDirWatcher() |
241 | 188 | } |
242 | 189 |
|
243 | 190 | /** |
|
0 commit comments