feat(skills): reload registry on watcher change events

This commit is contained in:
William Valentin
2026-02-12 17:30:23 -08:00
parent b773e2bbf3
commit 2fb5c9adab
5 changed files with 90 additions and 8 deletions
+45 -2
View File
@@ -1,5 +1,5 @@
import { afterEach, describe, expect, it } from 'vitest';
import { mkdtempSync, mkdirSync, rmSync } from 'fs';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { configSchema } from '../config/schema.js';
@@ -10,11 +10,18 @@ describe('initSkills watcher wiring', () => {
const roots: string[] = [];
afterEach(() => {
vi.useRealTimers();
for (const root of roots.splice(0)) {
rmSync(root, { recursive: true, force: true });
}
});
function writeSkill(rootDir: string, name: string): void {
const skillDir = join(rootDir, name);
mkdirSync(skillDir, { recursive: true });
writeFileSync(join(skillDir, 'SKILL.md'), `# ${name}\n\nTest skill.`);
}
function makeConfig(overrides: Record<string, unknown> = {}) {
return configSchema.parse({
telegram: { bot_token: 'test-token', allowed_chat_ids: [1] },
@@ -54,4 +61,40 @@ describe('initSkills watcher wiring', () => {
await lifecycle.shutdown();
expect(result.skillsWatcher?.isRunning).toBe(false);
});
it('reloads registry from disk when watcher callback fires', () => {
vi.useFakeTimers();
const root = mkdtempSync(join(tmpdir(), 'flynn-services-'));
roots.push(root);
const managedDir = join(root, 'skills');
mkdirSync(managedDir, { recursive: true });
writeSkill(managedDir, 'alpha');
const config = makeConfig({
skills: {
managed_dir: managedDir,
load: { watch: true, watch_debounce_ms: 20 },
},
});
const lifecycle = new Lifecycle();
const result = initSkills(config, lifecycle);
expect(result.skillRegistry.get('alpha')).toBeDefined();
expect(result.skillRegistry.get('beta')).toBeUndefined();
writeSkill(managedDir, 'beta');
result.skillsWatcher?.notifyPathChanged(join(managedDir, 'beta', 'SKILL.md'));
vi.advanceTimersByTime(20);
expect(result.skillRegistry.get('beta')).toBeDefined();
rmSync(join(managedDir, 'alpha'), { recursive: true, force: true });
result.skillsWatcher?.notifyPathChanged(join(managedDir, 'alpha'));
vi.advanceTimersByTime(20);
expect(result.skillRegistry.get('alpha')).toBeUndefined();
expect(result.skillRegistry.get('beta')).toBeDefined();
result.skillsWatcher?.stop();
});
});