perf(cron): lazy-load skills snapshot runtime

This commit is contained in:
Vincent Koc
2026-04-13 17:00:12 +01:00
parent 2c3871b4b1
commit 019f32cdb8
4 changed files with 35 additions and 19 deletions

View File

@@ -424,7 +424,7 @@ async function prepareCronRunContext(params: {
}
commandBody = appendCronDeliveryInstruction({ commandBody, deliveryRequested });
const skillsSnapshot = resolveCronSkillsSnapshot({
const skillsSnapshot = await resolveCronSkillsSnapshot({
workspaceDir,
config: cfgWithAgentDefaults,
agentId,

View File

@@ -0,0 +1,6 @@
export { canExecRequestNode } from "../../agents/exec-defaults.js";
export {
buildWorkspaceSkillSnapshot,
getRemoteSkillEligibility,
getSkillsSnapshotVersion,
} from "./run.runtime.js";

View File

@@ -2,20 +2,26 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const {
buildWorkspaceSkillSnapshotMock,
canExecRequestNodeMock,
getRemoteSkillEligibilityMock,
getSkillsSnapshotVersionMock,
resolveAgentSkillsFilterMock,
} = vi.hoisted(() => ({
buildWorkspaceSkillSnapshotMock: vi.fn(),
canExecRequestNodeMock: vi.fn().mockReturnValue(false),
getRemoteSkillEligibilityMock: vi.fn(),
getSkillsSnapshotVersionMock: vi.fn(),
resolveAgentSkillsFilterMock: vi.fn(),
}));
vi.mock("./run.runtime.js", () => ({
vi.mock("./skills-snapshot.runtime.js", () => ({
buildWorkspaceSkillSnapshot: buildWorkspaceSkillSnapshotMock,
canExecRequestNode: canExecRequestNodeMock,
getRemoteSkillEligibility: getRemoteSkillEligibilityMock,
getSkillsSnapshotVersion: getSkillsSnapshotVersionMock,
}));
vi.mock("./run.runtime.js", () => ({
resolveAgentSkillsFilter: resolveAgentSkillsFilterMock,
}));
@@ -34,10 +40,10 @@ describe("resolveCronSkillsSnapshot", () => {
buildWorkspaceSkillSnapshotMock.mockReturnValue({ prompt: "fresh", skills: [] });
});
it("refreshes when the cached skill filter changes", () => {
it("refreshes when the cached skill filter changes", async () => {
resolveAgentSkillsFilterMock.mockReturnValue(["docs-search", "github"]);
const result = resolveCronSkillsSnapshot({
const result = await resolveCronSkillsSnapshot({
workspaceDir: "/tmp/workspace",
config: {} as never,
agentId: "writer",
@@ -58,10 +64,10 @@ describe("resolveCronSkillsSnapshot", () => {
expect(result).toEqual({ prompt: "fresh", skills: [] });
});
it("refreshes when the process version resets to 0 but the cached snapshot is stale", () => {
it("refreshes when the process version resets to 0 but the cached snapshot is stale", async () => {
getSkillsSnapshotVersionMock.mockReturnValue(0);
resolveCronSkillsSnapshot({
await resolveCronSkillsSnapshot({
workspaceDir: "/tmp/workspace",
config: {} as never,
agentId: "writer",

View File

@@ -1,27 +1,31 @@
import { canExecRequestNode } from "../../agents/exec-defaults.js";
import type { SkillSnapshot } from "../../agents/skills.js";
import { matchesSkillFilter } from "../../agents/skills/filter.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import {
buildWorkspaceSkillSnapshot,
getRemoteSkillEligibility,
getSkillsSnapshotVersion,
resolveAgentSkillsFilter,
} from "./run.runtime.js";
import { resolveAgentSkillsFilter } from "./run.runtime.js";
export function resolveCronSkillsSnapshot(params: {
let skillsSnapshotRuntimePromise:
| Promise<typeof import("./skills-snapshot.runtime.js")>
| undefined;
async function loadSkillsSnapshotRuntime() {
skillsSnapshotRuntimePromise ??= import("./skills-snapshot.runtime.js");
return await skillsSnapshotRuntimePromise;
}
export async function resolveCronSkillsSnapshot(params: {
workspaceDir: string;
config: OpenClawConfig;
agentId: string;
existingSnapshot?: SkillSnapshot;
isFastTestEnv: boolean;
}): SkillSnapshot {
}): Promise<SkillSnapshot> {
if (params.isFastTestEnv) {
// Fast unit-test mode skips filesystem scans and snapshot refresh writes.
return params.existingSnapshot ?? { prompt: "", skills: [] };
}
const snapshotVersion = getSkillsSnapshotVersion(params.workspaceDir);
const runtime = await loadSkillsSnapshotRuntime();
const snapshotVersion = runtime.getSkillsSnapshotVersion(params.workspaceDir);
const skillFilter = resolveAgentSkillsFilter(params.config, params.agentId);
const existingSnapshot = params.existingSnapshot;
const shouldRefresh =
@@ -32,13 +36,13 @@ export function resolveCronSkillsSnapshot(params: {
return existingSnapshot;
}
return buildWorkspaceSkillSnapshot(params.workspaceDir, {
return runtime.buildWorkspaceSkillSnapshot(params.workspaceDir, {
config: params.config,
agentId: params.agentId,
skillFilter,
eligibility: {
remote: getRemoteSkillEligibility({
advertiseExecNode: canExecRequestNode({
remote: runtime.getRemoteSkillEligibility({
advertiseExecNode: runtime.canExecRequestNode({
cfg: params.config,
agentId: params.agentId,
}),