refactor: organize skills subsystem layout

This commit is contained in:
Shakker
2026-05-29 11:28:14 +01:00
committed by Shakker
parent 355fb4d860
commit d9278c8efd
157 changed files with 495 additions and 464 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ async function createAcpClient(opts: AcpClientOptions = {}): Promise<AcpClientHa
const defaultServerArgs = entryPath ? [entryPath, ...serverArgs] : serverArgs;
const serverCommand = opts.serverCommand ?? defaultServerCommand;
const effectiveArgs = opts.serverCommand || !entryPath ? serverArgs : defaultServerArgs;
const { getActiveSkillEnvKeys } = await import("../skills/env-overrides.runtime.js");
const { getActiveSkillEnvKeys } = await import("../skills/runtime/env-overrides.runtime.js");
const stripProviderAuthEnvVars = shouldStripProviderAuthEnvVarsForAcpServer({
serverCommand,
serverArgs: effectiveArgs,
@@ -592,16 +592,16 @@ vi.mock("./provider-auth-aliases.js", () => ({
provider.trim().toLowerCase() === "codex-cli" ? "openai-codex" : provider.trim().toLowerCase(),
}));
vi.mock("../skills/agent-filter.js", () => ({
vi.mock("../skills/discovery/agent-filter.js", () => ({
resolveEffectiveAgentSkillFilter: (_cfg: unknown, agentId: string) =>
state.resolveAgentSkillsFilterMock(_cfg, agentId),
}));
vi.mock("../skills/remote.js", () => ({
vi.mock("../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: () => ({ eligible: false }),
}));
vi.mock("../skills/session-snapshot.js", () => ({
vi.mock("../skills/runtime/session-snapshot.js", () => ({
resolveReusableWorkspaceSkillSnapshot: (params: {
workspaceDir: string;
existingSnapshot?: { resolvedSkills?: unknown };
+5 -5
View File
@@ -39,9 +39,9 @@ import {
import { resolveSendPolicy } from "../sessions/send-policy.js";
import { createLazyImportLoader } from "../shared/lazy-promise.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/agent-filter.js";
import type { getRemoteSkillEligibility } from "../skills/remote.js";
import type { resolveReusableWorkspaceSkillSnapshot } from "../skills/session-snapshot.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/discovery/agent-filter.js";
import type { getRemoteSkillEligibility } from "../skills/runtime/remote.js";
import type { resolveReusableWorkspaceSkillSnapshot } from "../skills/runtime/session-snapshot.js";
import type { SkillSnapshot } from "../skills/types.js";
import { sanitizeForLog } from "../terminal/ansi.js";
import { createTrajectoryRuntimeRecorder } from "../trajectory/runtime.js";
@@ -156,8 +156,8 @@ const execDefaultsRuntimeLoader = createLazyImportLoader<ExecDefaultsRuntime>(
);
const skillsRuntimeLoader = createLazyImportLoader<SkillsRuntime>(async () => {
const [remote, sessionSnapshot] = await Promise.all([
import("../skills/remote.js"),
import("../skills/session-snapshot.js"),
import("../skills/runtime/remote.js"),
import("../skills/runtime/session-snapshot.js"),
]);
return {
getRemoteSkillEligibility: remote.getRemoteSkillEligibility,
+1 -1
View File
@@ -21,7 +21,7 @@ import {
normalizeOptionalString,
resolvePrimaryStringValue,
} from "../shared/string-coerce.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/agent-filter.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/discovery/agent-filter.js";
import { resolveUserPath } from "../utils.js";
import {
listAgentIds,
@@ -13,7 +13,7 @@ import { getGlobalHookRunner } from "../plugins/hook-runner-global.js";
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { setPluginToolMeta } from "../plugins/tools.js";
import { createCanonicalFixtureSkill } from "../skills/test-helpers.js";
import { createCanonicalFixtureSkill } from "../skills/test-support/test-helpers.js";
import {
runBeforeToolCallHook,
wrapToolWithBeforeToolCallHook,
+4 -1
View File
@@ -31,7 +31,10 @@ import {
type PluginHookToolKind,
} from "../plugins/types.js";
import { createLazyRuntimeSurface } from "../shared/lazy-runtime.js";
import { resolveSkillTelemetrySource, resolveSkillTelemetrySourceValue } from "../skills/source.js";
import {
resolveSkillTelemetrySource,
resolveSkillTelemetrySourceValue,
} from "../skills/loading/source.js";
import type { SkillSnapshot, SkillTelemetrySource } from "../skills/types.js";
import { isPlainObject } from "../utils.js";
import { adjustedParamsByToolCallId } from "./agent-tools.before-tool-call.state.js";
@@ -5,7 +5,7 @@ import { describe, expect, it, vi } from "vitest";
import "./test-helpers/fast-coding-tools.js";
import "./test-helpers/fast-openclaw-tools.js";
import type { OpenClawConfig } from "../config/config.js";
import { createCanonicalFixtureSkill } from "../skills/test-helpers.js";
import { createCanonicalFixtureSkill } from "../skills/test-support/test-helpers.js";
import { createOpenClawCodingTools } from "./agent-tools.js";
import { expectReadWriteEditTools, getTextContent } from "./test-helpers/agent-tools-fs-helpers.js";
import { createAgentToolsSandboxContext } from "./test-helpers/agent-tools-sandbox-context.js";
+1 -1
View File
@@ -11,7 +11,7 @@ import { requestHeartbeat as requestHeartbeatImpl } from "../../infra/heartbeat-
import { sanitizeHostExecEnv } from "../../infra/host-env-security.js";
import { enqueueSystemEvent as enqueueSystemEventImpl } from "../../infra/system-events.js";
import { getProcessSupervisor as getProcessSupervisorImpl } from "../../process/supervisor/index.js";
import { applySkillEnvOverridesFromSnapshot } from "../../skills/env-overrides.js";
import { applySkillEnvOverridesFromSnapshot } from "../../skills/runtime/env-overrides.js";
import { appendBootstrapPromptWarning } from "../bootstrap-budget.js";
import {
createCliJsonlStreamingParser,
+1 -1
View File
@@ -21,7 +21,7 @@ import { buildAgentHookContextChannelFields } from "../../plugins/hook-agent-con
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
import { annotateInterSessionPromptText } from "../../sessions/input-provenance.js";
import { uniqueStrings } from "../../shared/string-normalization.js";
import { resolveSkillsPromptForRun } from "../../skills/workspace.js";
import { resolveSkillsPromptForRun } from "../../skills/loading/workspace.js";
import { resolveUserPath } from "../../utils.js";
import { resolveAgentDir, resolveSessionAgentIds } from "../agent-scope.js";
import { externalCliDiscoveryForProviderAuth } from "../auth-profiles/external-cli-discovery.js";
+1 -1
View File
@@ -19,7 +19,7 @@ import {
appendUserTurnTranscriptMessage,
type PersistedUserTurnMessage,
} from "../../sessions/user-turn-transcript.js";
import { buildWorkspaceSkillSnapshot } from "../../skills/service.js";
import { buildWorkspaceSkillSnapshot } from "../../skills/discovery/service.js";
import { sanitizeForLog } from "../../terminal/ansi.js";
import { resolveMessageChannel } from "../../utils/message-channel.js";
import { resolveAuthProfileOrder } from "../auth-profiles/order.js";
@@ -755,9 +755,12 @@ export async function loadCompactHooksHarness(): Promise<{
limitHistoryTurns: vi.fn((msgs: unknown[]) => msgs.slice(0, 2)),
}));
vi.doMock("../../skills/index.js", () => ({
vi.doMock("../../skills/runtime/env-overrides.js", () => ({
applySkillEnvOverrides: vi.fn(() => () => {}),
applySkillEnvOverridesFromSnapshot: vi.fn(() => () => {}),
}));
vi.doMock("../../skills/loading/workspace.js", () => ({
loadWorkspaceSkillEntries: vi.fn(() => []),
resolveSkillsPromptForRun: vi.fn(() => undefined),
}));
+2 -2
View File
@@ -25,11 +25,11 @@ import {
transformProviderSystemPrompt,
} from "../../plugins/provider-runtime.js";
import { isCronSessionKey, isSubagentSessionKey } from "../../routing/session-key.js";
import { resolveSkillsPromptForRun } from "../../skills/loading/workspace.js";
import {
applySkillEnvOverrides,
applySkillEnvOverridesFromSnapshot,
} from "../../skills/env-overrides.js";
import { resolveSkillsPromptForRun } from "../../skills/workspace.js";
} from "../../skills/runtime/env-overrides.js";
import { resolveUserPath } from "../../utils.js";
import { normalizeMessageChannel } from "../../utils/message-channel.js";
import { isReasoningTagProvider } from "../../utils/provider-utils.js";
@@ -379,9 +379,12 @@ vi.mock("../../bootstrap-files.js", async () => {
};
});
vi.mock("../../../skills/index.js", () => ({
vi.mock("../../../skills/runtime/env-overrides.js", () => ({
applySkillEnvOverrides: () => () => {},
applySkillEnvOverridesFromSnapshot: () => () => {},
}));
vi.mock("../../../skills/loading/workspace.js", () => ({
resolveSkillsPromptForRun: (...args: unknown[]) => hoisted.resolveSkillsPromptForRunMock(...args),
}));
@@ -52,11 +52,11 @@ import { getPluginToolMeta } from "../../../plugins/tools.js";
import { isSubagentSessionKey } from "../../../routing/session-key.js";
import { annotateInterSessionPromptText } from "../../../sessions/input-provenance.js";
import { normalizeOptionalString } from "../../../shared/string-coerce.js";
import { resolveSkillsPromptForRun } from "../../../skills/loading/workspace.js";
import {
applySkillEnvOverrides,
applySkillEnvOverridesFromSnapshot,
} from "../../../skills/env-overrides.js";
import { resolveSkillsPromptForRun } from "../../../skills/workspace.js";
} from "../../../skills/runtime/env-overrides.js";
import {
buildTrajectoryArtifacts,
buildTrajectoryRunMetadata,
@@ -3,7 +3,7 @@ import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import { writePluginWithSkill } from "../../skills/skill-plugin-fixtures.test-support.js";
import { writePluginWithSkill } from "../../skills/test-support/skill-plugin-fixtures.test-support.js";
import { resolveEmbeddedRunSkillEntries } from "./skills-runtime.js";
const tempDirs: string[] = [];
@@ -4,8 +4,8 @@ import {
setRuntimeConfigSnapshot,
type OpenClawConfig,
} from "../../config/config.js";
import * as skillsWorkspaceModule from "../../skills/loading/workspace.js";
import type { SkillSnapshot } from "../../skills/types.js";
import * as skillsWorkspaceModule from "../../skills/workspace.js";
import { resolveEmbeddedRunSkillEntries } from "./skills-runtime.js";
describe("resolveEmbeddedRunSkillEntries", () => {
@@ -1,7 +1,7 @@
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolveSkillRuntimeConfig } from "../../skills/runtime-config.js";
import { resolveSkillRuntimeConfig } from "../../skills/loading/runtime-config.js";
import { loadWorkspaceSkillEntries } from "../../skills/loading/workspace.js";
import type { SkillEntry, SkillSnapshot } from "../../skills/types.js";
import { loadWorkspaceSkillEntries } from "../../skills/workspace.js";
export function resolveEmbeddedRunSkillEntries(params: {
workspaceDir: string;
@@ -46,7 +46,7 @@ vi.mock("node:child_process", () => ({
},
}));
vi.mock("../skills/index.js", () => ({
vi.mock("../skills/loading/workspace.js", () => ({
syncSkillsToWorkspace: vi.fn(async () => undefined),
}));
@@ -37,11 +37,11 @@ vi.mock("./exec-defaults.js", () => ({
canExecRequestNode: vi.fn(() => false),
}));
vi.mock("../skills/remote.js", () => ({
vi.mock("../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: vi.fn(() => ({ note: "test-remote" })),
}));
vi.mock("../skills/workspace.js", () => ({
vi.mock("../skills/loading/workspace.js", () => ({
syncSkillsToWorkspace: syncSkillsToWorkspaceMock,
}));
+2 -2
View File
@@ -55,8 +55,8 @@ async function ensureSandboxWorkspaceLayout(params: {
try {
const [{ syncSkillsToWorkspace }, { getRemoteSkillEligibility }, { canExecRequestNode }] =
await Promise.all([
import("../../skills/workspace.js"),
import("../../skills/remote.js"),
import("../../skills/loading/workspace.js"),
import("../../skills/runtime/remote.js"),
import("../exec-defaults.js"),
]);
await syncSkillsToWorkspace({
+1 -1
View File
@@ -38,7 +38,7 @@ export {
type TransportSetting,
type WarningSettings,
} from "./settings-manager.js";
export type { Skill } from "../../skills/session.js";
export type { Skill } from "../../skills/loading/session.js";
export * from "./source-info.js";
export * from "./tools/index.js";
export type * from "./extensions/types.js";
+1 -1
View File
@@ -38,6 +38,6 @@ export {
type TransportSetting,
type WarningSettings,
} from "./settings-manager.js";
export * from "../../skills/session.js";
export * from "../../skills/loading/session.js";
export * from "./source-info.js";
export * from "./tools/index.js";
+2 -2
View File
@@ -8,8 +8,8 @@ import type { ResourceDiagnostic } from "./diagnostics.js";
export type { ResourceCollision, ResourceDiagnostic } from "./diagnostics.js";
import type { Skill } from "../../skills/session.js";
import { loadSkills } from "../../skills/session.js";
import type { Skill } from "../../skills/loading/session.js";
import { loadSkills } from "../../skills/loading/session.js";
import { canonicalizePath, isLocalPath } from "../utils/paths.js";
import { createEventBus, type EventBus } from "./event-bus.js";
import {
+1 -1
View File
@@ -110,7 +110,7 @@ export type {
ToolDefinition,
} from "./extensions/index.js";
export type { PromptTemplate } from "./prompt-templates.js";
export type { Skill } from "../../skills/session.js";
export type { Skill } from "../../skills/loading/session.js";
export type { Tool } from "./tools/index.js";
export {
+1 -1
View File
@@ -1 +1 @@
export * from "../../skills/session.js";
export * from "../../skills/loading/session.js";
+1 -1
View File
@@ -2,7 +2,7 @@
* System prompt construction and project context loading
*/
import { formatSkillsForPrompt, type Skill } from "../../skills/session.js";
import { formatSkillsForPrompt, type Skill } from "../../skills/loading/session.js";
import { getDocsPath, getExamplesPath, getReadmePath } from "../config.js";
export interface BuildSystemPromptOptions {
@@ -7,7 +7,7 @@ import type { PluginProviderRegistration } from "../plugins/registry.js";
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
import type { ProviderPlugin } from "../plugins/types.js";
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
import { resetSkillsRefreshForTest } from "../skills/refresh.js";
import { resetSkillsRefreshForTest } from "../skills/runtime/refresh.js";
import {
clearSessionAuthProfileOverrideMock,
compactEmbeddedAgentSessionMock,
@@ -22,11 +22,11 @@ vi.mock("../../agents/sandbox.js", () => ({
resolveSandboxRuntimeStatus: vi.fn(() => ({ sandboxed: false, mode: "off" })),
}));
vi.mock("../../skills/remote.js", () => ({
vi.mock("../../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: vi.fn(() => false),
}));
vi.mock("../../skills/session-snapshot.js", () => ({
vi.mock("../../skills/runtime/session-snapshot.js", () => ({
resolveReusableWorkspaceSkillSnapshot: vi.fn(() => ({
snapshot: { prompt: "", skills: [], resolvedSkills: [] },
shouldRefresh: false,
@@ -13,8 +13,8 @@ import { buildConfiguredAgentSystemPrompt } from "../../agents/system-prompt-con
import { buildSystemPromptParams } from "../../agents/system-prompt-params.js";
import type { WorkspaceBootstrapFile } from "../../agents/workspace.js";
import { listRegisteredPluginAgentPromptGuidance } from "../../plugins/command-registry-state.js";
import { getRemoteSkillEligibility } from "../../skills/remote.js";
import { resolveReusableWorkspaceSkillSnapshot } from "../../skills/session-snapshot.js";
import { getRemoteSkillEligibility } from "../../skills/runtime/remote.js";
import { resolveReusableWorkspaceSkillSnapshot } from "../../skills/runtime/session-snapshot.js";
import type { HandleCommandsParams } from "./commands-types.js";
import { resolveRuntimePolicySessionKey } from "./runtime-policy-session-key.js";
+4 -4
View File
@@ -53,19 +53,19 @@ vi.mock("../../agents/agent-scope.js", () => ({
resolveSessionAgentId: resolveSessionAgentIdMock,
}));
vi.mock("../../skills/remote.js", () => ({
vi.mock("../../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: getRemoteSkillEligibilityMock,
}));
vi.mock("../../skills/service.js", () => ({
vi.mock("../../skills/discovery/service.js", () => ({
buildWorkspaceSkillSnapshot: buildWorkspaceSkillSnapshotMock,
}));
vi.mock("../../skills/refresh.js", () => ({
vi.mock("../../skills/runtime/refresh.js", () => ({
ensureSkillsWatcher: ensureSkillsWatcherMock,
}));
vi.mock("../../skills/refresh-state.js", () => ({
vi.mock("../../skills/runtime/refresh-state.js", () => ({
getSkillsSnapshotVersion: getSkillsSnapshotVersionMock,
shouldRefreshSnapshotForVersion: shouldRefreshSnapshotForVersionMock,
}));
+3 -3
View File
@@ -20,11 +20,11 @@ import { logVerbose } from "../../globals.js";
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { getRemoteSkillEligibility } from "../../skills/remote.js";
import { resolveReusableWorkspaceSkillSnapshot } from "../../skills/session-snapshot.js";
import { getRemoteSkillEligibility } from "../../skills/runtime/remote.js";
import { resolveReusableWorkspaceSkillSnapshot } from "../../skills/runtime/session-snapshot.js";
import { buildSessionEndHookPayload, buildSessionStartHookPayload } from "./session-hooks.js";
export { drainFormattedSystemEvents } from "./session-system-events.js";
export { resetResolvedSkillsCacheForTests } from "../../skills/session-snapshot.js";
export { resetResolvedSkillsCacheForTests } from "../../skills/runtime/session-snapshot.js";
async function persistSessionEntryUpdate(params: {
sessionStore?: Record<string, SessionEntry>;
+3 -3
View File
@@ -127,15 +127,15 @@ vi.mock("./commands-registry.js", () => ({
listChatCommands: () => [],
}));
vi.mock("../skills/command-specs.js", () => ({
vi.mock("../skills/discovery/command-specs.js", () => ({
buildWorkspaceSkillCommandSpecs,
}));
vi.mock("../skills/remote.js", () => ({
vi.mock("../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: () => ({}),
}));
vi.mock("../skills/agent-filter.js", () => ({
vi.mock("../skills/discovery/agent-filter.js", () => ({
resolveEffectiveAgentSkillFilter: (
cfg: {
agents?: {
+3 -3
View File
@@ -8,9 +8,9 @@ import {
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import { uniqueStrings } from "../shared/string-normalization.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/agent-filter.js";
import { buildWorkspaceSkillCommandSpecs } from "../skills/command-specs.js";
import { getRemoteSkillEligibility } from "../skills/remote.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/discovery/agent-filter.js";
import { buildWorkspaceSkillCommandSpecs } from "../skills/discovery/command-specs.js";
import { getRemoteSkillEligibility } from "../skills/runtime/remote.js";
import type { SkillCommandSpec } from "../skills/types.js";
import { listReservedChatSlashCommandNames } from "./skill-commands-base.js";
export {
+3 -3
View File
@@ -178,7 +178,7 @@ vi.mock("../agents/agent-scope.js", () => ({
mocks.resolveAgentWorkspaceDirMock(config, agentId),
}));
vi.mock("../skills/clawhub.js", () => ({
vi.mock("../skills/lifecycle/clawhub.js", () => ({
searchSkillsFromClawHub: (...args: unknown[]) => mocks.searchSkillsFromClawHubMock(...args),
installSkillFromClawHub: (...args: unknown[]) => mocks.installSkillFromClawHubMock(...args),
updateSkillsFromClawHub: (...args: unknown[]) => mocks.updateSkillsFromClawHubMock(...args),
@@ -194,7 +194,7 @@ vi.mock("../infra/clawhub.js", () => ({
fetchClawHubSkillCard: (...args: unknown[]) => mocks.fetchClawHubSkillCardMock(...args),
}));
vi.mock("../skills/source-install.js", () => ({
vi.mock("../skills/lifecycle/source-install.js", () => ({
installSkillFromSource: (...args: unknown[]) => mocks.installSkillFromSourceMock(...args),
isSkillSourceInstallSpec: (raw: string) =>
raw.startsWith("git:") ||
@@ -204,7 +204,7 @@ vi.mock("../skills/source-install.js", () => ({
raw.startsWith("/"),
}));
vi.mock("../skills/status.js", () => ({
vi.mock("../skills/discovery/status.js", () => ({
buildWorkspaceSkillStatus: (workspaceDir: string, options?: unknown) =>
mocks.buildWorkspaceSkillStatusMock(workspaceDir, options),
}));
+1 -1
View File
@@ -1,4 +1,4 @@
import type { SkillStatusEntry, SkillStatusReport } from "../skills/status.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/discovery/status.js";
import { sanitizeForLog, stripAnsi } from "../terminal/ansi.js";
import { decorativeEmoji, decorativePrefix } from "../terminal/decorative-emoji.js";
import { getTerminalTableWidth, renderTable } from "../terminal/table.js";
+3 -3
View File
@@ -2,9 +2,9 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import type { SkillEntry } from "../skills/index.js";
import { buildWorkspaceSkillStatus } from "../skills/status.js";
import { createCanonicalFixtureSkill } from "../skills/test-helpers.js";
import { buildWorkspaceSkillStatus } from "../skills/discovery/status.js";
import { createCanonicalFixtureSkill } from "../skills/test-support/test-helpers.js";
import type { SkillEntry } from "../skills/types.js";
import { captureEnv } from "../test-utils/env.js";
import { formatSkillInfo, formatSkillsCheck, formatSkillsList } from "./skills-cli.format.js";
+1 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/status.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/discovery/status.js";
import { createEmptyInstallChecks } from "./requirements-test-fixtures.js";
import { formatSkillInfo, formatSkillsCheck, formatSkillsList } from "./skills-cli.format.js";
+7 -4
View File
@@ -18,8 +18,11 @@ import {
resolveClawHubSkillVerificationTarget,
searchSkillsFromClawHub,
updateSkillsFromClawHub,
} from "../skills/clawhub.js";
import { installSkillFromSource, isSkillSourceInstallSpec } from "../skills/source-install.js";
} from "../skills/lifecycle/clawhub.js";
import {
installSkillFromSource,
isSkillSourceInstallSpec,
} from "../skills/lifecycle/source-install.js";
import { formatDocsLink } from "../terminal/links.js";
import { theme } from "../terminal/theme.js";
import { CONFIG_DIR } from "../utils.js";
@@ -35,7 +38,7 @@ export type {
export { formatSkillInfo, formatSkillsCheck, formatSkillsList } from "./skills-cli.format.js";
type SkillStatusReport = Awaited<
ReturnType<(typeof import("../skills/status.js"))["buildWorkspaceSkillStatus"]>
ReturnType<(typeof import("../skills/discovery/status.js"))["buildWorkspaceSkillStatus"]>
>;
type ResolvedClawHubSkillVerificationTarget = Extract<
Awaited<ReturnType<typeof resolveClawHubSkillVerificationTarget>>,
@@ -76,7 +79,7 @@ async function loadSkillsStatusReport(
options?: ResolveSkillsWorkspaceOptions,
): Promise<SkillStatusReport> {
const { config, workspaceDir, agentId } = resolveSkillsWorkspace(options);
const { buildWorkspaceSkillStatus } = await import("../skills/status.js");
const { buildWorkspaceSkillStatus } = await import("../skills/discovery/status.js");
return buildWorkspaceSkillStatus(workspaceDir, { config, agentId });
}
+7 -4
View File
@@ -239,20 +239,23 @@ vi.mock("../agents/workspace.js", () => ({
ensureAgentWorkspace: vi.fn(async ({ dir }: { dir: string }) => ({ dir })),
}));
vi.mock("../skills/index.js", () => ({
vi.mock("../skills/discovery/service.js", () => ({
buildWorkspaceSkillSnapshot: vi.fn(() => undefined),
}));
vi.mock("../skills/loading/workspace.js", () => ({
loadWorkspaceSkillEntries: vi.fn(() => []),
}));
vi.mock("../skills/remote.js", () => ({
vi.mock("../skills/runtime/remote.js", () => ({
getRemoteSkillEligibility: vi.fn(() => undefined),
}));
vi.mock("../skills/agent-filter.js", () => ({
vi.mock("../skills/discovery/agent-filter.js", () => ({
resolveEffectiveAgentSkillFilter: vi.fn(() => undefined),
}));
vi.mock("../skills/session-snapshot.js", () => ({
vi.mock("../skills/runtime/session-snapshot.js", () => ({
resolveReusableWorkspaceSkillSnapshot: vi.fn(
(params?: { existingSnapshot?: unknown; skillFilter?: string[] }) => ({
snapshot: params?.existingSnapshot ?? {
+1 -1
View File
@@ -7,7 +7,7 @@ import type { SessionEntry } from "../config/sessions/types.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { expandHomePrefix } from "../infra/home-dir.js";
import { isRecord } from "../shared/record-coerce.js";
import { resolveBundledSkillsDir } from "../skills/bundled-dir.js";
import { resolveBundledSkillsDir } from "../skills/loading/bundled-dir.js";
import { note } from "../terminal/note.js";
import { shortenHomePath } from "../utils.js";
+1 -1
View File
@@ -1,5 +1,5 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/status.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/discovery/status.js";
export function collectUnavailableAgentSkills(report: SkillStatusReport): SkillStatusEntry[] {
return report.skills.filter(
+2 -2
View File
@@ -1,8 +1,8 @@
import { describe, expect, it } from "vitest";
import { createEmptyInstallChecks } from "../cli/requirements-test-fixtures.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { GhConfigDiscoveryInput } from "../skills/gh-config-discovery.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/status.js";
import type { SkillStatusEntry, SkillStatusReport } from "../skills/discovery/status.js";
import type { GhConfigDiscoveryInput } from "../skills/lifecycle/gh-config-discovery.js";
import {
collectUnavailableAgentSkills,
describeGhConfigDirHintFromDiscovery,
+3 -3
View File
@@ -2,14 +2,14 @@ import { existsSync } from "node:fs";
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
import { formatCliCommand } from "../cli/command-format.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { SkillStatusEntry } from "../skills/discovery/status.js";
import { buildWorkspaceSkillStatus } from "../skills/discovery/status.js";
import {
detectGhConfigDirMismatch,
formatGhConfigDirMismatchHint,
type GhConfigDiscoveryInput,
type GhConfigDiscoveryResult,
} from "../skills/gh-config-discovery.js";
import type { SkillStatusEntry } from "../skills/status.js";
import { buildWorkspaceSkillStatus } from "../skills/status.js";
} from "../skills/lifecycle/gh-config-discovery.js";
import { note } from "../terminal/note.js";
import type { DoctorPrompter } from "./doctor-prompter.js";
import {
+1 -1
View File
@@ -22,7 +22,7 @@ vi.mock("../agents/agent-scope.js", () => ({
resolveDefaultAgentId: (...args: unknown[]) => mocks.resolveDefaultAgentId(...args),
}));
vi.mock("../skills/status.js", () => ({
vi.mock("../skills/discovery/status.js", () => ({
buildWorkspaceSkillStatus: (...args: unknown[]) => mocks.buildWorkspaceSkillStatus(...args),
}));
+1 -1
View File
@@ -5,7 +5,7 @@ import {
buildPluginCompatibilityWarnings,
buildPluginRegistrySnapshotReport,
} from "../plugins/status.js";
import { buildWorkspaceSkillStatus } from "../skills/status.js";
import { buildWorkspaceSkillStatus } from "../skills/discovery/status.js";
import { listTasksForFlowId } from "../tasks/runtime-internal.js";
import { listTaskFlowRecords } from "../tasks/task-flow-runtime-internal.js";
import { note } from "../terminal/note.js";
+1 -1
View File
@@ -242,7 +242,7 @@ vi.mock("@clack/prompts", () => ({
select,
}));
vi.mock("../skills/status.js", () => ({
vi.mock("../skills/discovery/status.js", () => ({
buildWorkspaceSkillStatus: () => ({ skills: [] }),
}));
+2 -2
View File
@@ -17,10 +17,10 @@ const mocks = vi.hoisted(() => ({
}));
// Module under test imports these at module scope.
vi.mock("../skills/status.js", () => ({
vi.mock("../skills/discovery/status.js", () => ({
buildWorkspaceSkillStatus: mocks.buildWorkspaceSkillStatus,
}));
vi.mock("../skills/install.js", () => ({
vi.mock("../skills/lifecycle/install.js", () => ({
installSkill: mocks.installSkill,
}));
vi.mock("../infra/container-environment.js", () => ({
+2 -2
View File
@@ -3,8 +3,8 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
import { resolveBrewExecutable } from "../infra/brew.js";
import { isContainerEnvironment } from "../infra/container-environment.js";
import type { RuntimeEnv } from "../runtime.js";
import { installSkill } from "../skills/install.js";
import { buildWorkspaceSkillStatus } from "../skills/status.js";
import { buildWorkspaceSkillStatus } from "../skills/discovery/status.js";
import { installSkill } from "../skills/lifecycle/install.js";
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
import { t } from "../wizard/i18n/index.js";
import type { WizardPrompter } from "../wizard/prompts.js";
+2 -2
View File
@@ -4,8 +4,8 @@ import { readLastGatewayErrorLine } from "../../daemon/diagnostics.js";
import { inspectPortUsage } from "../../infra/ports.js";
import { readRestartSentinel } from "../../infra/restart-sentinel.js";
import { buildPluginCompatibilityNotices } from "../../plugins/status.js";
import { getRemoteSkillEligibility } from "../../skills/remote.js";
import { buildWorkspaceSkillStatus } from "../../skills/status.js";
import { buildWorkspaceSkillStatus } from "../../skills/discovery/status.js";
import { getRemoteSkillEligibility } from "../../skills/runtime/remote.js";
import { buildStatusAllOverviewRows } from "../status-overview-rows.ts";
import {
buildStatusOverviewSurfaceFromOverview,
@@ -3,12 +3,12 @@ import fs from "node:fs/promises";
import path from "node:path";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveEmbeddedRunSkillEntries } from "../../agents/embedded-agent-runner/skills-runtime.js";
import type { Skill } from "../../skills/skill-contract.js";
import type { Skill } from "../../skills/loading/skill-contract.js";
import {
hydrateResolvedSkills,
hydrateResolvedSkillsAsync,
} from "../../skills/snapshot-hydration.js";
import { createCanonicalFixtureSkill } from "../../skills/test-helpers.js";
} from "../../skills/runtime/snapshot-hydration.js";
import { createCanonicalFixtureSkill } from "../../skills/test-support/test-helpers.js";
import { createSuiteTempRootTracker } from "../../test-helpers/temp-dir.js";
import type { SessionEntry, SessionSkillPromptRef, SessionSkillSnapshot } from "./types.js";
+1 -1
View File
@@ -3,7 +3,7 @@ import type { ChatType } from "../../channels/chat-type.js";
import type { ChannelId } from "../../channels/plugins/channel-id.types.js";
import type { ChannelRouteRef } from "../../plugin-sdk/channel-route.js";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import type { Skill } from "../../skills/skill-contract.js";
import type { Skill } from "../../skills/loading/skill-contract.js";
import type { DeliveryContext } from "../../utils/delivery-context.types.js";
import type { TtsAutoMode } from "../types.tts.js";
@@ -1,4 +1,4 @@
export { canExecRequestNode } from "../../agents/exec-defaults.js";
export { resolveEffectiveAgentSkillFilter } from "../../skills/agent-filter.js";
export { getRemoteSkillEligibility } from "../../skills/remote.js";
export { resolveReusableWorkspaceSkillSnapshot } from "../../skills/session-snapshot.js";
export { resolveEffectiveAgentSkillFilter } from "../../skills/discovery/agent-filter.js";
export { getRemoteSkillEligibility } from "../../skills/runtime/remote.js";
export { resolveReusableWorkspaceSkillSnapshot } from "../../skills/runtime/session-snapshot.js";
+1 -1
View File
@@ -34,7 +34,7 @@ import { formatErrorMessage } from "../infra/errors.js";
import type { ProviderRuntimeModel } from "../plugins/provider-runtime-model.types.js";
import { getPluginToolMeta, setPluginToolMeta } from "../plugins/tools.js";
import { normalizeAgentId } from "../routing/session-key.js";
import { buildWorkspaceSkillStatus, type SkillStatusEntry } from "../skills/status.js";
import { buildWorkspaceSkillStatus, type SkillStatusEntry } from "../skills/discovery/status.js";
import type { HealthFinding } from "./health-checks.js";
type BundleMcpToolRuntime = Awaited<ReturnType<typeof createBundleMcpToolRuntime>>;
+1 -1
View File
@@ -3,7 +3,7 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { SkillStatusEntry } from "../skills/status.js";
import type { SkillStatusEntry } from "../skills/discovery/status.js";
import {
CORE_HEALTH_CHECKS,
createCoreHealthChecks,
+1 -1
View File
@@ -18,7 +18,7 @@ import { hasAmbiguousGatewayAuthModeConfig } from "../gateway/auth-mode-policy.j
import { resolveGatewayAuthToken } from "../gateway/auth-token-resolution.js";
import { resolveGatewayAuth } from "../gateway/auth.js";
import { getSkippedExecRefStaticError } from "../secrets/exec-resolution-policy.js";
import type { SkillStatusEntry } from "../skills/status.js";
import type { SkillStatusEntry } from "../skills/discovery/status.js";
import { registerHealthCheck } from "./health-check-registry.js";
import type { HealthCheck, HealthCheckContext, HealthFinding } from "./health-checks.js";
+1 -1
View File
@@ -16,7 +16,7 @@ import {
import {
getSkillsSnapshotVersion,
resetSkillsRefreshStateForTest,
} from "../skills/refresh-state.js";
} from "../skills/runtime/refresh-state.js";
import { createTestRegistry } from "../test-utils/channel-plugins.js";
import {
buildGatewayReloadPlan,
+1 -1
View File
@@ -8,7 +8,7 @@ import {
loadInstalledPluginIndexInstallRecords,
loadInstalledPluginIndexInstallRecordsSync,
} from "../plugins/installed-plugin-index-records.js";
import { bumpSkillsSnapshotVersion } from "../skills/refresh-state.js";
import { bumpSkillsSnapshotVersion } from "../skills/runtime/refresh-state.js";
import { diffConfigPaths } from "./config-diff.js";
import {
buildGatewayReloadPlan,
+1 -1
View File
@@ -47,7 +47,7 @@ import {
recordRemoteNodeInfo,
refreshRemoteNodeBins,
removeRemoteNodeInfo,
} from "../../skills/remote.js";
} from "../../skills/runtime/remote.js";
import { createKnownNodeCatalog, getKnownNode, listKnownNodes } from "../node-catalog.js";
import {
isForegroundRestrictedPluginNodeCommand,
+5 -2
View File
@@ -12,8 +12,11 @@ import { formatErrorMessage } from "../../infra/errors.js";
import {
areUploadedSkillArchivesEnabled,
UPLOADED_SKILL_ARCHIVES_DISABLED_MESSAGE,
} from "../../skills/upload-install.js";
import { defaultSkillUploadStore, SkillUploadRequestError } from "../../skills/upload-store.js";
} from "../../skills/lifecycle/upload-install.js";
import {
defaultSkillUploadStore,
SkillUploadRequestError,
} from "../../skills/lifecycle/upload-store.js";
import type { GatewayRequestHandlers } from "./types.js";
function uploadErrorShape(
@@ -23,17 +23,17 @@ vi.mock("../../agents/agent-scope.js", () => ({
resolveSessionAgentId: vi.fn(() => undefined),
}));
vi.mock("../../skills/clawhub.js", () => ({
vi.mock("../../skills/lifecycle/clawhub.js", () => ({
installSkillFromClawHub: (...args: unknown[]) => installSkillFromClawHubMock(...args),
readLocalSkillCardContentSync: (...args: unknown[]) => readLocalSkillCardContentSyncMock(...args),
updateSkillsFromClawHub: (...args: unknown[]) => updateSkillsFromClawHubMock(...args),
}));
vi.mock("../../skills/status.js", () => ({
vi.mock("../../skills/discovery/status.js", () => ({
buildWorkspaceSkillStatus: (...args: unknown[]) => buildWorkspaceSkillStatusMock(...args),
}));
vi.mock("../../skills/install.js", () => ({
vi.mock("../../skills/lifecycle/install.js", () => ({
installSkill: (...args: unknown[]) => installSkillMock(...args),
}));
@@ -14,7 +14,7 @@ vi.mock("../../agents/agent-scope.js", () => ({
resolveAgentWorkspaceDir: vi.fn(() => "/tmp/workspace"),
}));
vi.mock("../../skills/clawhub.js", () => ({
vi.mock("../../skills/lifecycle/clawhub.js", () => ({
installSkillFromClawHub: vi.fn(),
updateSkillsFromClawHub: vi.fn(),
searchSkillsFromClawHub: (...args: unknown[]) => searchSkillsFromClawHubMock(...args),
@@ -27,7 +27,7 @@ vi.mock("../../infra/clawhub.js", () => ({
downloadClawHubSkillArchive: vi.fn(),
}));
vi.mock("../../skills/install.js", () => ({
vi.mock("../../skills/lifecycle/install.js", () => ({
installSkill: vi.fn(),
}));
+6 -6
View File
@@ -28,18 +28,18 @@ import {
import { formatErrorMessage } from "../../infra/errors.js";
import { normalizeAgentId } from "../../routing/session-key.js";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { buildWorkspaceSkillStatus } from "../../skills/discovery/status.js";
import {
installSkillFromClawHub,
readLocalSkillCardContentSync,
searchSkillsFromClawHub,
updateSkillsFromClawHub,
} from "../../skills/clawhub.js";
import { installSkill } from "../../skills/install.js";
import { getRemoteSkillEligibility } from "../../skills/remote.js";
import { buildWorkspaceSkillStatus } from "../../skills/status.js";
} from "../../skills/lifecycle/clawhub.js";
import { installSkill } from "../../skills/lifecycle/install.js";
import { installUploadedSkillArchive } from "../../skills/lifecycle/upload-install.js";
import { loadWorkspaceSkillEntries } from "../../skills/loading/workspace.js";
import { getRemoteSkillEligibility } from "../../skills/runtime/remote.js";
import type { SkillEntry } from "../../skills/types.js";
import { installUploadedSkillArchive } from "../../skills/upload-install.js";
import { loadWorkspaceSkillEntries } from "../../skills/workspace.js";
import { updateSkillConfigEntry } from "./skills-config-mutations.js";
import { skillsUploadHandlers } from "./skills-upload.js";
import type { GatewayRequestContext, GatewayRequestHandlers } from "./types.js";
+6 -3
View File
@@ -78,7 +78,7 @@ export async function startGatewayEarlyRuntime(params: {
info: (msg: string) => void;
warn: (msg: string) => void;
};
nodeRegistry: Parameters<typeof import("../skills/remote.js").setSkillsRemoteRegistry>[0];
nodeRegistry: Parameters<typeof import("../skills/runtime/remote.js").setSkillsRemoteRegistry>[0];
pluginRegistry?: PluginRegistry;
broadcast: GatewayMaintenanceParams["broadcast"];
nodeSendToAllSubscribed: Parameters<StartGatewayMaintenanceTimers>[0]["nodeSendToAllSubscribed"];
@@ -111,7 +111,7 @@ export async function startGatewayEarlyRuntime(params: {
const [{ primeRemoteSkillsCache, setSkillsRemoteRegistry }, taskRegistryMaintenance] =
await measureStartup(params.startupTrace, "runtime.early.lazy-runtime-imports", () =>
Promise.all([
import("../skills/remote.js"),
import("../skills/runtime/remote.js"),
import("../tasks/task-registry.maintenance.js"),
]),
);
@@ -130,7 +130,10 @@ export async function startGatewayEarlyRuntime(params: {
? () => {}
: await measureStartup(params.startupTrace, "runtime.early.skills-listener", async () => {
const [{ registerSkillsChangeListener }, { refreshRemoteBinsForConnectedNodes }] =
await Promise.all([import("../skills/refresh.js"), import("../skills/remote.js")]);
await Promise.all([
import("../skills/runtime/refresh.js"),
import("../skills/runtime/remote.js"),
]);
return registerSkillsChangeListener((event) => {
if (event.reason === "remote-node") {
return;
+1 -1
View File
@@ -10,7 +10,7 @@ import { upsertPresence } from "../../infra/system-presence.js";
import { logRejectedLargePayload } from "../../logging/diagnostic-payload.js";
import type { createSubsystemLogger } from "../../logging/subsystem.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { removeRemoteNodeInfo } from "../../skills/remote.js";
import { removeRemoteNodeInfo } from "../../skills/runtime/remote.js";
import { truncateUtf16Safe } from "../../utils.js";
import { isWebchatClient } from "../../utils/message-channel.js";
import type { AuthRateLimiter } from "../auth-rate-limit.js";
@@ -84,7 +84,7 @@ import {
} from "../../../shared/device-bootstrap-profile.js";
import { roleScopesAllow } from "../../../shared/operator-scope-compat.js";
import { uniqueStrings } from "../../../shared/string-normalization.js";
import { recordRemoteNodeInfo, refreshRemoteNodeBins } from "../../../skills/remote.js";
import { recordRemoteNodeInfo, refreshRemoteNodeBins } from "../../../skills/runtime/remote.js";
import {
isBrowserOperatorUiClient,
isGatewayCliClient,
+1 -1
View File
@@ -3,7 +3,7 @@ import path from "node:path";
import { formatErrorMessage } from "../infra/errors.js";
import { resolveExecutable } from "../infra/executable-path.js";
import { runCommandWithTimeout, type SpawnResult } from "../process/exec.js";
import { hasBinary } from "../skills/index.js";
import { hasBinary } from "../skills/loading/config.js";
import { resolveUserPath } from "../utils.js";
import { normalizeServePath } from "./gmail.js";
+1 -1
View File
@@ -16,7 +16,7 @@ vi.mock("node:child_process", async () => {
);
});
vi.mock("../skills/index.js", () => ({
vi.mock("../skills/loading/config.js", () => ({
hasBinary: mocks.hasBinary,
}));
+1 -1
View File
@@ -9,7 +9,7 @@ import { type ChildProcess, spawn } from "node:child_process";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { runCommandWithTimeout } from "../process/exec.js";
import { hasBinary } from "../skills/index.js";
import { hasBinary } from "../skills/loading/config.js";
import { ensureTailscaleEndpoint } from "./gmail-setup-utils.js";
import { isAddressInUseError } from "./gmail-watcher-errors.js";
import {
+1 -1
View File
@@ -99,7 +99,7 @@ export {
resolveSkillCommandInvocation,
} from "../auto-reply/skill-commands.js";
export { getPluginCommandSpecs, listProviderPluginCommandSpecs } from "../plugins/command-specs.js";
export type { SkillCommandSpec } from "../skills/index.js";
export type { SkillCommandSpec } from "../skills/types.js";
export {
buildModelsProviderData,
formatModelsAvailableHeader,
+1 -1
View File
@@ -4,4 +4,4 @@ export {
registerSkillsChangeListener,
shouldRefreshSnapshotForVersion,
type SkillsChangeEvent,
} from "../skills/refresh-state.js";
} from "../skills/runtime/refresh-state.js";
+1 -1
View File
@@ -14,7 +14,7 @@ export {
createSandboxPruneConfig,
createSandboxSshConfig,
} from "./test-helpers/sandbox-fixtures.js";
export { writeSkill } from "../skills/e2e-test-helpers.js";
export { writeSkill } from "../skills/test-support/e2e-test-helpers.js";
export {
castAgentMessage,
makeAgentAssistantMessage,
+1 -1
View File
@@ -107,7 +107,7 @@ export {
isLiveTestEnabled,
} from "../agents/live-test-helpers.js";
export { createSandboxTestContext } from "../agents/sandbox/test-fixtures.js";
export { writeSkill } from "../skills/e2e-test-helpers.js";
export { writeSkill } from "../skills/test-support/e2e-test-helpers.js";
export {
castAgentMessage,
makeAgentAssistantMessage,
+1 -1
View File
@@ -9,7 +9,7 @@ import {
} from "./audit-extra.async.js";
import * as skillScanner from "./skill-scanner.js";
vi.mock("../skills/index.js", () => ({
vi.mock("../skills/loading/workspace.js", () => ({
loadWorkspaceSkillEntries: (workspaceDir: string) => {
const sep = workspaceDir.includes("\\") ? "\\" : "/";
const baseDir = `${workspaceDir}${sep}skills${sep}evil-skill`;
+4 -4
View File
@@ -47,13 +47,13 @@ type ExecDockerRawFn = (
const DEFAULT_SANDBOX_BROWSER_DOCKER_PROBE_TIMEOUT_MS = 5000;
type CodeSafetySummaryCache = Map<string, Promise<unknown>>;
let skillsModulePromise: Promise<typeof import("../skills/index.js")> | undefined;
let skillsModulePromise: Promise<typeof import("../skills/loading/workspace.js")> | undefined;
let configModulePromise: Promise<typeof import("../config/config.js")> | undefined;
let agentScopeModulePromise: Promise<typeof import("../agents/agent-scope.js")> | undefined;
let agentWorkspaceDirsModulePromise:
| Promise<typeof import("../agents/workspace-dirs.js")>
| undefined;
let skillSourceModulePromise: Promise<typeof import("../skills/source.js")> | undefined;
let skillSourceModulePromise: Promise<typeof import("../skills/loading/source.js")> | undefined;
let sandboxDockerModulePromise: Promise<typeof import("../agents/sandbox/docker.js")> | undefined;
let sandboxConstantsModulePromise:
| Promise<typeof import("../agents/sandbox/constants.js")>
@@ -63,7 +63,7 @@ let auditFsModulePromise: Promise<typeof import("./audit-fs.js")> | undefined;
let skillScannerModulePromise: Promise<typeof import("./skill-scanner.js")> | undefined;
function loadSkillsModule() {
skillsModulePromise ??= import("../skills/index.js");
skillsModulePromise ??= import("../skills/loading/workspace.js");
return skillsModulePromise;
}
@@ -88,7 +88,7 @@ function loadAgentWorkspaceDirsModule() {
}
function loadSkillSourceModule() {
skillSourceModulePromise ??= import("../skills/source.js");
skillSourceModulePromise ??= import("../skills/loading/source.js");
return skillSourceModulePromise;
}
@@ -1,5 +1,5 @@
import type { OpenClawConfig } from "../config/types.js";
import { normalizeAgentId } from "../routing/session-key.js";
import type { OpenClawConfig } from "../../config/types.js";
import { normalizeAgentId } from "../../routing/session-key.js";
import { normalizeSkillFilter } from "./filter.js";
type AgentSkillsLimits = {
@@ -1,17 +1,17 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { loadEnabledClaudeBundleCommands } from "../plugins/bundle-commands.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { createSubsystemLogger } from "../../logging/subsystem.js";
import { loadEnabledClaudeBundleCommands } from "../../plugins/bundle-commands.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
import { resolveSkillTelemetrySource } from "./source.js";
import type { SkillEligibilityContext, SkillCommandSpec, SkillEntry } from "./types.js";
} from "../../shared/string-coerce.js";
import { resolveSkillTelemetrySource } from "../loading/source.js";
import {
filterWorkspaceSkillEntriesWithOptions,
loadVisibleWorkspaceSkillEntries,
} from "./workspace.js";
} from "../loading/workspace.js";
import type { SkillEligibilityContext, SkillCommandSpec, SkillEntry } from "../types.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
const skillsLogger = createSubsystemLogger("skills");
const skillCommandDebugOnce = new Set<string>();
@@ -1,4 +1,4 @@
import { normalizeStringEntries, sortUniqueStrings } from "../shared/string-normalization.js";
import { normalizeStringEntries, sortUniqueStrings } from "../../shared/string-normalization.js";
export function normalizeSkillFilter(skillFilter?: ReadonlyArray<unknown>): string[] | undefined {
if (skillFilter === undefined) {
@@ -1,6 +1,6 @@
import type { Skill } from "./skill-contract.js";
import type { Skill } from "../loading/skill-contract.js";
import type { SkillEntry } from "../types.js";
import { resolveSkillTrustInfo, type SkillSourceKind } from "./trust.js";
import type { SkillEntry } from "./types.js";
export type SkillIndexEntry = {
id: string;
@@ -2,12 +2,12 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { writeWorkspaceSkills } from "./e2e-test-helpers.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { buildWorkspaceSkillSnapshot as buildLegacyWorkspaceSkillSnapshot } from "../loading/workspace.js";
import { writeWorkspaceSkills } from "../test-support/e2e-test-helpers.js";
import { createCanonicalFixtureSkill } from "../test-support/test-helpers.js";
import type { SkillEntry } from "../types.js";
import { buildSkillIndexCacheKey, buildWorkspaceSkillSnapshot, SkillsService } from "./service.js";
import { createCanonicalFixtureSkill } from "./test-helpers.js";
import type { SkillEntry } from "./types.js";
import { buildWorkspaceSkillSnapshot as buildLegacyWorkspaceSkillSnapshot } from "./workspace.js";
const tempDirs: string[] = [];
@@ -1,17 +1,17 @@
import crypto from "node:crypto";
import path from "node:path";
import { stableStringify } from "../agents/stable-stringify.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { resolvePluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
import { normalizeSkillFilter } from "./filter.js";
import { getSkillsSnapshotVersion } from "./refresh-state.js";
import { buildSkillIndex, skillIndexEntries, type SkillIndex } from "./registry.js";
import type { SkillEligibilityContext, SkillEntry, SkillSnapshot } from "./types.js";
import { stableStringify } from "../../agents/stable-stringify.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolvePluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.js";
import {
buildWorkspaceSkillSnapshot as buildWorkspaceSkillSnapshotFromEntries,
loadWorkspaceSkillEntries,
} from "./workspace.js";
} from "../loading/workspace.js";
import { getSkillsSnapshotVersion } from "../runtime/refresh-state.js";
import type { SkillEligibilityContext, SkillEntry, SkillSnapshot } from "../types.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
import { normalizeSkillFilter } from "./filter.js";
import { buildSkillIndex, skillIndexEntries, type SkillIndex } from "./registry.js";
const MAX_SKILL_INDEX_CACHE_ENTRIES = 16;
@@ -2,12 +2,12 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { withEnv, withEnvAsync } from "../test-utils/env.js";
import { writeSkill } from "./e2e-test-helpers.js";
import { withEnv, withEnvAsync } from "../../test-utils/env.js";
import { loadWorkspaceSkillEntries } from "../loading/workspace.js";
import { writeSkill } from "../test-support/e2e-test-helpers.js";
import { createCanonicalFixtureSkill } from "../test-support/test-helpers.js";
import type { SkillEntry } from "../types.js";
import { buildWorkspaceSkillStatus } from "./status.js";
import { createCanonicalFixtureSkill } from "./test-helpers.js";
import type { SkillEntry } from "./types.js";
import { loadWorkspaceSkillEntries } from "./workspace.js";
const tempDirs: string[] = [];
@@ -2,10 +2,10 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { readLocalSkillCardContentSync } from "./clawhub.js";
import { readLocalSkillCardContentSync } from "../lifecycle/clawhub.js";
import { createCanonicalFixtureSkill } from "../test-support/test-helpers.js";
import type { SkillEntry } from "../types.js";
import { buildWorkspaceSkillStatus } from "./status.js";
import { createCanonicalFixtureSkill } from "./test-helpers.js";
import type { SkillEntry } from "./types.js";
type SkillStatus = ReturnType<typeof buildWorkspaceSkillStatus>["skills"][number];
@@ -1,10 +1,8 @@
import path from "node:path";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { evaluateEntryRequirementsForCurrentPlatform } from "../shared/entry-status.js";
import type { RequirementConfigCheck, Requirements } from "../shared/requirements.js";
import { CONFIG_DIR } from "../utils.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
import { resolveBundledSkillsContext } from "./bundled-context.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { evaluateEntryRequirementsForCurrentPlatform } from "../../shared/entry-status.js";
import type { RequirementConfigCheck, Requirements } from "../../shared/requirements.js";
import { CONFIG_DIR } from "../../utils.js";
import {
readClawHubSkillsLockfileStatusSync,
resolveClawHubSkillStatusLinkSync,
@@ -12,21 +10,25 @@ import {
type ClawHubSkillStatusLink,
type ClawHubSkillsLockfileStatusRead,
type LocalSkillCardStatus,
} from "./clawhub.js";
} from "../lifecycle/clawhub.js";
import { resolveBundledSkillsContext } from "../loading/bundled-context.js";
import {
hasBinary,
isBundledSkillAllowed,
isConfigPathTruthy,
loadWorkspaceSkillEntries,
resolveBundledAllowlist,
resolveSkillConfig,
resolveSkillsInstallPreferences,
type SkillEntry,
type SkillEligibilityContext,
type SkillInstallSpec,
type SkillsInstallPreferences,
} from "./index.js";
import { resolveSkillSource } from "./source.js";
} from "../loading/config.js";
import { resolveSkillSource } from "../loading/source.js";
import { loadWorkspaceSkillEntries } from "../loading/workspace.js";
import type {
SkillEntry,
SkillEligibilityContext,
SkillInstallSpec,
SkillsInstallPreferences,
} from "../types.js";
import { resolveEffectiveAgentSkillFilter } from "./agent-filter.js";
export type SkillStatusConfigCheck = RequirementConfigCheck;
@@ -1,6 +1,6 @@
import path from "node:path";
import { resolveSkillSource } from "./source.js";
import type { SkillEntry } from "./types.js";
import { resolveSkillSource } from "../loading/source.js";
import type { SkillEntry } from "../types.js";
export type SkillSourceKind =
| "workspace"
+23 -30
View File
@@ -1,10 +1,3 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "../shared/string-coerce.js";
import type { SkillsInstallPreferences } from "./types.js";
export {
hasBinary,
isBundledSkillAllowed,
@@ -13,8 +6,12 @@ export {
resolveConfigPath,
resolveRuntimePlatform,
resolveSkillConfig,
} from "./config.js";
export { applySkillEnvOverrides, applySkillEnvOverridesFromSnapshot } from "./env-overrides.js";
resolveSkillsInstallPreferences,
} from "./loading/config.js";
export {
applySkillEnvOverrides,
applySkillEnvOverridesFromSnapshot,
} from "./runtime/env-overrides.js";
export type {
OpenClawSkillMetadata,
SkillEligibilityContext,
@@ -32,41 +29,37 @@ export {
loadWorkspaceSkillEntries,
resolveSkillsPromptForRun,
syncSkillsToWorkspace,
} from "./workspace.js";
export { buildWorkspaceSkillCommandSpecs } from "./command-specs.js";
} from "./loading/workspace.js";
export { buildWorkspaceSkillCommandSpecs } from "./discovery/command-specs.js";
export type {
LoadSkillsFromDirOptions,
LoadSkillsOptions,
LoadSkillsResult,
Skill,
SkillFrontmatter,
} from "./session.js";
export { formatSkillsForPrompt as formatSessionSkillsForPrompt, loadSkills } from "./session.js";
export type { SkillIndex, SkillIndexEntry } from "./registry.js";
export { buildSkillIndex, skillIndexEntries, skillIndexResolvedSkills } from "./registry.js";
export type { SkillSourceKind, SkillTrustInfo, SkillWritablePolicy } from "./trust.js";
} from "./loading/session.js";
export {
formatSkillsForPrompt as formatSessionSkillsForPrompt,
loadSkills,
} from "./loading/session.js";
export type { SkillIndex, SkillIndexEntry } from "./discovery/registry.js";
export {
buildSkillIndex,
skillIndexEntries,
skillIndexResolvedSkills,
} from "./discovery/registry.js";
export type { SkillSourceKind, SkillTrustInfo, SkillWritablePolicy } from "./discovery/trust.js";
export {
classifySkillSourceKind,
resolveSkillOwner,
resolveSkillTrustInfo,
resolveSkillWritablePolicy,
} from "./trust.js";
export type { SkillIndexRequest, SkillSnapshotBuildOptions } from "./service.js";
} from "./discovery/trust.js";
export type { SkillIndexRequest, SkillSnapshotBuildOptions } from "./discovery/service.js";
export {
SkillsService,
buildSkillIndexCacheKey,
buildSkillSnapshotFromIndex,
buildWorkspaceSkillSnapshot,
skillsService,
} from "./service.js";
export function resolveSkillsInstallPreferences(config?: OpenClawConfig): SkillsInstallPreferences {
const raw = config?.skills?.install;
const preferBrew = raw?.preferBrew ?? true;
const manager = normalizeLowercaseStringOrEmpty(normalizeOptionalString(raw?.nodeManager));
const nodeManager: SkillsInstallPreferences["nodeManager"] =
manager === "pnpm" || manager === "yarn" || manager === "bun" || manager === "npm"
? manager
: "npm";
return { preferBrew, nodeManager };
}
} from "./discovery/service.js";
@@ -2,8 +2,8 @@ import fs from "node:fs/promises";
import path from "node:path";
import JSZip from "jszip";
import { afterEach, describe, expect, it } from "vitest";
import { withExtractedArchiveRoot } from "../infra/install-flow.js";
import { createTrackedTempDirs } from "../test-utils/tracked-temp-dirs.js";
import { withExtractedArchiveRoot } from "../../infra/install-flow.js";
import { createTrackedTempDirs } from "../../test-utils/tracked-temp-dirs.js";
import {
CLAWHUB_SKILL_ARCHIVE_ROOT_MARKERS,
installExtractedSkillRoot,
@@ -1,14 +1,14 @@
import path from "node:path";
import type { ArchiveLogger } from "../infra/archive.js";
import { formatErrorMessage } from "../infra/errors.js";
import { pathExists } from "../infra/fs-safe.js";
import { withExtractedArchiveRoot } from "../infra/install-flow.js";
import { installPackageDir } from "../infra/install-package-dir.js";
import { resolveSafeInstallDir } from "../infra/install-safe-path.js";
import type { ArchiveLogger } from "../../infra/archive.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { pathExists } from "../../infra/fs-safe.js";
import { withExtractedArchiveRoot } from "../../infra/install-flow.js";
import { installPackageDir } from "../../infra/install-package-dir.js";
import { resolveSafeInstallDir } from "../../infra/install-safe-path.js";
import {
scanSkillInstallSource,
type InstallSecurityScanResult,
} from "../plugins/install-security-scan.js";
} from "../../plugins/install-security-scan.js";
const VALID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
const DEFAULT_SKILL_ARCHIVE_ROOT_MARKERS = ["SKILL.md"] as const;
@@ -13,7 +13,7 @@ const withExtractedArchiveRootMock = vi.fn();
const installPackageDirMock = vi.fn();
const pathExistsMock = vi.fn();
vi.mock("../infra/clawhub.js", () => ({
vi.mock("../../infra/clawhub.js", () => ({
fetchClawHubSkillDetail: fetchClawHubSkillDetailMock,
downloadClawHubSkillArchive: downloadClawHubSkillArchiveMock,
listClawHubSkills: listClawHubSkillsMock,
@@ -21,15 +21,15 @@ vi.mock("../infra/clawhub.js", () => ({
searchClawHubSkills: searchClawHubSkillsMock,
}));
vi.mock("../infra/install-flow.js", () => ({
vi.mock("../../infra/install-flow.js", () => ({
withExtractedArchiveRoot: withExtractedArchiveRootMock,
}));
vi.mock("../infra/install-package-dir.js", () => ({
vi.mock("../../infra/install-package-dir.js", () => ({
installPackageDir: installPackageDirMock,
}));
vi.mock("../infra/fs-safe.js", () => ({
vi.mock("../../infra/fs-safe.js", () => ({
pathExists: pathExistsMock,
}));
@@ -7,11 +7,11 @@ import {
searchClawHubSkills,
type ClawHubSkillDetail,
type ClawHubSkillSearchResult,
} from "../infra/clawhub.js";
import { formatErrorMessage } from "../infra/errors.js";
import { pathExists } from "../infra/fs-safe.js";
import { withExtractedArchiveRoot } from "../infra/install-flow.js";
import { readJsonIfExists, tryReadJson, writeJson } from "../infra/json-files.js";
} from "../../infra/clawhub.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { pathExists } from "../../infra/fs-safe.js";
import { withExtractedArchiveRoot } from "../../infra/install-flow.js";
import { readJsonIfExists, tryReadJson, writeJson } from "../../infra/json-files.js";
import {
CLAWHUB_SKILL_ARCHIVE_ROOT_MARKERS,
installExtractedSkillRoot,
@@ -3,26 +3,26 @@ import os from "node:os";
import path from "node:path";
import { Readable } from "node:stream";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { setTempStateDir } from "./install-download-test-utils.js";
import { installDownloadSpec } from "./install-download.js";
import { resolveSkillToolsRootDir } from "../runtime/tools-dir.js";
import { setTempStateDir } from "../test-support/install-download-test-utils.js";
import {
fetchWithSsrFGuardMock,
hasBinaryMock,
runCommandWithTimeoutMock,
} from "./install-test-mocks.js";
import { createCanonicalFixtureSkill } from "./test-helpers.js";
import { resolveSkillToolsRootDir } from "./tools-dir.js";
import type { SkillEntry, SkillInstallSpec } from "./types.js";
} from "../test-support/install-test-mocks.js";
import { createCanonicalFixtureSkill } from "../test-support/test-helpers.js";
import type { SkillEntry, SkillInstallSpec } from "../types.js";
import { installDownloadSpec } from "./install-download.js";
vi.mock("../process/exec.js", () => ({
vi.mock("../../process/exec.js", () => ({
runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args),
}));
vi.mock("../infra/net/fetch-guard.js", () => ({
vi.mock("../../infra/net/fetch-guard.js", () => ({
fetchWithSsrFGuard: (...args: unknown[]) => fetchWithSsrFGuardMock(...args),
}));
vi.mock("./index.js", () => ({
vi.mock("../loading/config.js", () => ({
hasBinary: (bin: string) => hasBinaryMock(bin),
}));
@@ -4,19 +4,19 @@ import path from "node:path";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
import type { ReadableStream as NodeReadableStream } from "node:stream/web";
import { isWindowsDrivePath } from "../infra/archive-path.js";
import { formatErrorMessage } from "../infra/errors.js";
import { root as fsRoot } from "../infra/fs-safe.js";
import { assertCanonicalPathWithinBase } from "../infra/install-safe-path.js";
import { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js";
import { isWithinDir } from "../infra/path-safety.js";
import { createLazyImportLoader } from "../shared/lazy-promise.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { ensureDir, resolveUserPath } from "../utils.js";
import type { SkillEntry, SkillInstallSpec } from "./index.js";
import { isWindowsDrivePath } from "../../infra/archive-path.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { root as fsRoot } from "../../infra/fs-safe.js";
import { assertCanonicalPathWithinBase } from "../../infra/install-safe-path.js";
import { fetchWithSsrFGuard } from "../../infra/net/fetch-guard.js";
import { isWithinDir } from "../../infra/path-safety.js";
import { createLazyImportLoader } from "../../shared/lazy-promise.js";
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
import { ensureDir, resolveUserPath } from "../../utils.js";
import { resolveSkillToolsRootDir } from "../runtime/tools-dir.js";
import type { SkillEntry, SkillInstallSpec } from "../types.js";
import { formatInstallFailureMessage } from "./install-output.js";
import type { SkillInstallResult } from "./install-types.js";
import { resolveSkillToolsRootDir } from "./tools-dir.js";
const extractModuleLoader = createLazyImportLoader(() => import("./install-extract.js"));
@@ -6,11 +6,11 @@ import {
mergeExtractedTreeIntoDestination,
prepareArchiveDestinationDir,
withStagedArchiveDestination,
} from "../infra/archive.js";
import { formatErrorMessage } from "../infra/errors.js";
import { runCommandWithTimeout } from "../process/exec.js";
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { hasBinary } from "./index.js";
} from "../../infra/archive.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { runCommandWithTimeout } from "../../process/exec.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { hasBinary } from "../loading/config.js";
import { parseTarVerboseMetadata } from "./install-tar-verbose.js";
export type ArchiveExtractResult = { stdout: string; stderr: string; code: number | null };
@@ -2,29 +2,25 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { captureEnv } from "../test-utils/env.js";
import type { SkillEntry, SkillInstallSpec } from "./index.js";
import { hasBinaryMock, runCommandWithTimeoutMock } from "./install-test-mocks.js";
import { captureEnv } from "../../test-utils/env.js";
import { hasBinaryMock, runCommandWithTimeoutMock } from "../test-support/install-test-mocks.js";
import type { SkillEntry, SkillInstallSpec } from "../types.js";
const skillsMocks = vi.hoisted(() => ({
loadWorkspaceSkillEntries: vi.fn(),
}));
vi.mock("../process/exec.js", () => ({
vi.mock("../../process/exec.js", () => ({
runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args),
}));
vi.mock("../plugins/install-security-scan.js", () => ({
vi.mock("../../plugins/install-security-scan.js", () => ({
scanSkillInstallSource: vi.fn(async () => undefined),
}));
vi.mock("./index.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./index.js")>();
return {
...actual,
loadWorkspaceSkillEntries: skillsMocks.loadWorkspaceSkillEntries,
};
});
vi.mock("../loading/workspace.js", () => ({
loadWorkspaceSkillEntries: skillsMocks.loadWorkspaceSkillEntries,
}));
let installSkill: typeof import("./install.js").installSkill;
let skillsInstallTesting: typeof import("./install.js").testing;
@@ -1,4 +1,4 @@
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
type InstallCommandResult = {
code: number | null;
@@ -1,4 +1,4 @@
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
const TAR_VERBOSE_MONTHS = new Set([
"Jan",

Some files were not shown because too many files have changed in this diff Show More