mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix: bound skills watcher traversal
Signed-off-by: sallyom <somalley@redhat.com>
This commit is contained in:
@@ -160,6 +160,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Cron: make rejected `payload.model` errors show the configured `agents.defaults.models` allowlist instead of echoing the rejected model twice. Fixes #79058.
|
||||
- Agents/subagents: retry parent wake announces when the announce-summary model run fails with fallback cooldown exhaustion instead of dropping the wake on the first transient provider overload. Refs #78581.
|
||||
- Providers/network: honor IPv4 CIDR and octet-wildcard `NO_PROXY` entries such as `100.64.0.0/10` and `100.64.*` before enabling trusted env-proxy mode for model-provider requests. Fixes #79030.
|
||||
- Skills: cap skills watcher directory traversal at the same depth used by skill discovery so large non-skill trees under configured skill roots do not exhaust file descriptors on startup. Fixes #75501. Thanks @wzq-xzwj.
|
||||
- Docs/Docker: document a local Compose override for Docker Desktop DNS failures in the shared-network `openclaw-cli` sidecar, keeping the default compose setup hardened while unblocking `openclaw plugins install` when users opt in. Fixes #79018. Thanks @Jason-Vaughan.
|
||||
- Installer: when npm installs `openclaw` outside the parent shell PATH, print follow-up commands with the resolved binary path instead of telling users to run `openclaw` from a shell that will report `command not found`. Fixes #72382. Thanks @jbob762.
|
||||
- Compute plugin callback authorization dynamically [AI]. (#78866) Thanks @pgondhi987.
|
||||
|
||||
@@ -60,12 +60,13 @@ describe("ensureSkillsWatcher", () => {
|
||||
|
||||
expect(watchMock).toHaveBeenCalledTimes(1);
|
||||
const firstCall = (
|
||||
watchMock.mock.calls as unknown as Array<[string[], { ignored?: unknown }]>
|
||||
watchMock.mock.calls as unknown as Array<[string[], { depth?: number; ignored?: unknown }]>
|
||||
)[0];
|
||||
const targets = firstCall?.[0] ?? [];
|
||||
const opts = firstCall?.[1] ?? {};
|
||||
|
||||
expect(opts.ignored).toBe(refreshModule.shouldIgnoreSkillsWatchPath);
|
||||
expect(opts.depth).toBe(2);
|
||||
const posix = (p: string) => p.replaceAll("\\", "/");
|
||||
expect(targets).toEqual(
|
||||
expect.arrayContaining([
|
||||
@@ -100,6 +101,34 @@ describe("ensureSkillsWatcher", () => {
|
||||
expect(ignored("/tmp/workspace/skills/my-skill/SKILL.md", {})).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps grouped skill folders within the watcher traversal depth", async () => {
|
||||
vi.useFakeTimers();
|
||||
const seen: SkillsChangeEvent[] = [];
|
||||
refreshModule.registerSkillsChangeListener((change) => {
|
||||
seen.push(change);
|
||||
});
|
||||
refreshModule.ensureSkillsWatcher({
|
||||
workspaceDir: "/tmp/workspace",
|
||||
config: { skills: { load: { watchDebounceMs: 10 } } },
|
||||
});
|
||||
|
||||
const firstCall = (
|
||||
watchMock.mock.calls as unknown as Array<[string[], { depth?: number; ignored?: unknown }]>
|
||||
)[0];
|
||||
expect(firstCall?.[1]?.depth).toBe(2);
|
||||
|
||||
createdWatchers[0]?.emit("change", "/tmp/workspace/skills/group/demo/SKILL.md");
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
|
||||
expect(seen).toEqual([
|
||||
{
|
||||
workspaceDir: "/tmp/workspace",
|
||||
reason: "watch",
|
||||
changedPath: "/tmp/workspace/skills/group/demo/SKILL.md",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it.each(["add", "change", "unlink", "unlinkDir"] as const)(
|
||||
"refreshes skills snapshots on %s",
|
||||
async (event) => {
|
||||
|
||||
@@ -141,6 +141,8 @@ export function ensureSkillsWatcher(params: { workspaceDir: string; config?: Ope
|
||||
|
||||
const watcher = chokidar.watch(watchTargets, {
|
||||
ignoreInitial: true,
|
||||
// Skill discovery reads root skills, direct child skills, and one grouped skill level.
|
||||
depth: 2,
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: debounceMs,
|
||||
pollInterval: 100,
|
||||
|
||||
Reference in New Issue
Block a user