mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 23:20:22 +00:00
fix(ci): stabilize bundle hooks and mcp path seams
This commit is contained in:
@@ -223,10 +223,10 @@ bundledChannelRuntimeSetters.setLineRuntime({
|
||||
},
|
||||
} as never);
|
||||
|
||||
vi.mock("../../../../extensions/matrix/src/matrix/send.js", async () => {
|
||||
vi.mock("../../../../extensions/matrix/runtime-api.js", async () => {
|
||||
const actual = await vi.importActual<
|
||||
typeof import("../../../../extensions/matrix/src/matrix/send.js")
|
||||
>("../../../../extensions/matrix/src/matrix/send.js");
|
||||
typeof import("../../../../extensions/matrix/runtime-api.js")
|
||||
>("../../../../extensions/matrix/runtime-api.js");
|
||||
return {
|
||||
...actual,
|
||||
sendMessageMatrix: sendMessageMatrixMock,
|
||||
|
||||
@@ -28,6 +28,11 @@ type HookPackageManifest = {
|
||||
} & Partial<Record<typeof MANIFEST_KEY, { hooks?: string[] }>>;
|
||||
const log = createSubsystemLogger("hooks/workspace");
|
||||
|
||||
type LoadedHook = {
|
||||
hook: Hook;
|
||||
frontmatter: ParsedHookFrontmatter;
|
||||
};
|
||||
|
||||
function filterHookEntries(
|
||||
entries: HookEntry[],
|
||||
config?: OpenClawConfig,
|
||||
@@ -79,7 +84,7 @@ function loadHookFromDir(params: {
|
||||
source: HookSource;
|
||||
pluginId?: string;
|
||||
nameHint?: string;
|
||||
}): Hook | null {
|
||||
}): LoadedHook | null {
|
||||
const hookMdPath = path.join(params.hookDir, "HOOK.md");
|
||||
const content = readBoundaryFileUtf8({
|
||||
absolutePath: hookMdPath,
|
||||
@@ -123,13 +128,16 @@ function loadHookFromDir(params: {
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
source: params.source,
|
||||
pluginId: params.pluginId,
|
||||
filePath: hookMdPath,
|
||||
baseDir,
|
||||
handlerPath,
|
||||
hook: {
|
||||
name,
|
||||
description,
|
||||
source: params.source,
|
||||
pluginId: params.pluginId,
|
||||
filePath: hookMdPath,
|
||||
baseDir,
|
||||
handlerPath,
|
||||
},
|
||||
frontmatter,
|
||||
};
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
||||
@@ -141,7 +149,11 @@ function loadHookFromDir(params: {
|
||||
/**
|
||||
* Scan a directory for hooks (subdirectories containing HOOK.md)
|
||||
*/
|
||||
function loadHooksFromDir(params: { dir: string; source: HookSource; pluginId?: string }): Hook[] {
|
||||
function loadHooksFromDir(params: {
|
||||
dir: string;
|
||||
source: HookSource;
|
||||
pluginId?: string;
|
||||
}): LoadedHook[] {
|
||||
const { dir, source, pluginId } = params;
|
||||
|
||||
if (!fs.existsSync(dir)) {
|
||||
@@ -153,7 +165,7 @@ function loadHooksFromDir(params: { dir: string; source: HookSource; pluginId?:
|
||||
return [];
|
||||
}
|
||||
|
||||
const hooks: Hook[] = [];
|
||||
const hooks: LoadedHook[] = [];
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
@@ -211,16 +223,7 @@ export function loadHookEntriesFromDir(params: {
|
||||
source: params.source,
|
||||
pluginId: params.pluginId,
|
||||
});
|
||||
return hooks.map((hook) => {
|
||||
let frontmatter: ParsedHookFrontmatter = {};
|
||||
const raw = readBoundaryFileUtf8({
|
||||
absolutePath: hook.filePath,
|
||||
rootPath: hook.baseDir,
|
||||
boundaryLabel: "hook directory",
|
||||
});
|
||||
if (raw !== null) {
|
||||
frontmatter = parseFrontmatter(raw);
|
||||
}
|
||||
return hooks.map(({ hook, frontmatter }) => {
|
||||
const entry: HookEntry = {
|
||||
hook: {
|
||||
...hook,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { clearPluginDiscoveryCache } from "./discovery.js";
|
||||
import { clearPluginManifestRegistryCache } from "./manifest-registry.js";
|
||||
|
||||
export function createBundleMcpTempHarness() {
|
||||
@@ -13,6 +14,7 @@ export function createBundleMcpTempHarness() {
|
||||
return dir;
|
||||
},
|
||||
async cleanup() {
|
||||
clearPluginDiscoveryCache();
|
||||
clearPluginManifestRegistryCache();
|
||||
await Promise.all(
|
||||
tempDirs
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
} from "./bundle-manifest.js";
|
||||
import { normalizePluginsConfig, resolveEffectiveEnableState } from "./config-state.js";
|
||||
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
||||
import { safeRealpathSync } from "./path-safety.js";
|
||||
import type { PluginBundleFormat } from "./types.js";
|
||||
|
||||
export type BundleMcpServerConfig = Record<string, unknown>;
|
||||
@@ -122,8 +121,8 @@ function expandBundleRootPlaceholders(value: string, rootDir: string): string {
|
||||
return value.split(CLAUDE_PLUGIN_ROOT_PLACEHOLDER).join(rootDir);
|
||||
}
|
||||
|
||||
function canonicalizeBundlePath(targetPath: string): string {
|
||||
return path.normalize(safeRealpathSync(targetPath) ?? path.resolve(targetPath));
|
||||
function normalizeBundlePath(targetPath: string): string {
|
||||
return path.normalize(path.resolve(targetPath));
|
||||
}
|
||||
|
||||
function normalizeExpandedAbsolutePath(value: string): string {
|
||||
@@ -194,7 +193,7 @@ function loadBundleFileBackedMcpConfig(params: {
|
||||
rootDir: string;
|
||||
relativePath: string;
|
||||
}): BundleMcpConfig {
|
||||
const rootDir = canonicalizeBundlePath(params.rootDir);
|
||||
const rootDir = normalizeBundlePath(params.rootDir);
|
||||
const absolutePath = path.resolve(rootDir, params.relativePath);
|
||||
const opened = openBoundaryFileSync({
|
||||
absolutePath,
|
||||
@@ -212,7 +211,7 @@ function loadBundleFileBackedMcpConfig(params: {
|
||||
}
|
||||
const raw = JSON.parse(fs.readFileSync(opened.fd, "utf-8")) as unknown;
|
||||
const servers = extractMcpServerMap(raw);
|
||||
const baseDir = canonicalizeBundlePath(path.dirname(absolutePath));
|
||||
const baseDir = normalizeBundlePath(path.dirname(absolutePath));
|
||||
return {
|
||||
mcpServers: Object.fromEntries(
|
||||
Object.entries(servers).map(([serverName, server]) => [
|
||||
@@ -233,7 +232,7 @@ function loadBundleInlineMcpConfig(params: {
|
||||
if (!isRecord(params.raw.mcpServers)) {
|
||||
return { mcpServers: {} };
|
||||
}
|
||||
const baseDir = canonicalizeBundlePath(params.baseDir);
|
||||
const baseDir = normalizeBundlePath(params.baseDir);
|
||||
const servers = extractMcpServerMap(params.raw.mcpServers);
|
||||
return {
|
||||
mcpServers: Object.fromEntries(
|
||||
|
||||
Reference in New Issue
Block a user