From e1624b5bd2b123c604477d7337f6b2e1c24b7c7f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 17 Jul 2026 21:09:41 -0700 Subject: [PATCH] fix: parse private OpenClaw hook names --- CHANGELOG.md | 1 + src/openclaw-target.js | 11 ++++++++++- test/openclaw-target.test.js | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae128ba..55d201f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Parse OpenClaw hook names after their source declaration became private and added a TypeScript `satisfies` constraint. - Run synthetic gateway lifecycle hooks around ordinary probes while preserving capture indexes and report order, so `gateway_stop` teardown cannot invalidate later compatibility checks. - Link isolated plugin workspaces to the OpenClaw checkout without npm normalizing duplicated dependency and peer declarations back to registry ranges. - Keep mocked Zod schemas chainable through unsupported methods such as `pipe()` and `catch()`. diff --git a/src/openclaw-target.js b/src/openclaw-target.js index aaaaaf3..3a31163 100644 --- a/src/openclaw-target.js +++ b/src/openclaw-target.js @@ -37,7 +37,7 @@ export async function readOpenClawTargetSurface(options = {}) { const registrySource = await readFile(registryPath, "utf8"); const compatRecordEntries = parseCompatRecordEntries(registrySource); const hookTypesSource = existsSync(hookTypesPath) ? await readFile(hookTypesPath, "utf8") : ""; - const hookNames = hookTypesSource ? parseExportedStringArray(hookTypesSource, "PLUGIN_HOOK_NAMES") : []; + const hookNames = hookTypesSource ? parseConstStringArray(hookTypesSource, "PLUGIN_HOOK_NAMES") : []; const apiBuilderSource = existsSync(apiBuilderPath) ? await readFile(apiBuilderPath, "utf8") : ""; const apiRegistrars = apiBuilderSource ? parseApiRegistrars(apiBuilderSource) : []; const manifestTypesSource = existsSync(manifestTypesPath) ? await readFile(manifestTypesPath, "utf8") : ""; @@ -198,6 +198,15 @@ export function parsePluginSdkExports(packageJson) { export function parseExportedStringArray(source, exportName) { const match = source.match(new RegExp(`export\\s+const\\s+${exportName}\\s*=\\s*\\[([\\s\\S]*?)\\]\\s+as\\s+const`)); + return parseStringArrayMatch(match); +} + +function parseConstStringArray(source, constName) { + const match = source.match(new RegExp(`(?:export\\s+)?const\\s+${constName}\\s*=\\s*\\[([\\s\\S]*?)\\]\\s+as\\s+const`)); + return parseStringArrayMatch(match); +} + +function parseStringArrayMatch(match) { if (!match) { return []; } diff --git a/test/openclaw-target.test.js b/test/openclaw-target.test.js index 1361c55..c9a1927 100644 --- a/test/openclaw-target.test.js +++ b/test/openclaw-target.test.js @@ -28,7 +28,7 @@ test("OpenClaw target parser reads public target surface facts", async (t) => { ); await writeFile( path.join(targetRoot, "src/plugins/hook-types.ts"), - `export const PLUGIN_HOOK_NAMES = ["before_tool_call", "llm_input"] as const;\n`, + `const PLUGIN_HOOK_NAMES = ["before_tool_call", "llm_input"] as const satisfies readonly PluginHookName[];\n`, "utf8", ); await writeFile(