@openclaw/plugin-inspector 0.3.23 → 0.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.24 - 2026-08-31
6
+
7
+ ### Fixed
8
+
9
+ - Recognize compiled CommonJS plugin factory calls when checking expected channel registrations, preserving source references and excluding factory values passed to wrappers.
10
+ - Classify widget presenters as metadata-only synthetic probes without invoking presentation callbacks.
11
+
5
12
  ## 0.3.23 - 2026-08-30
6
13
 
7
14
  ### Fixed
package/README.md CHANGED
@@ -208,6 +208,8 @@ plugin-inspector --help
208
208
 
209
209
  ## Runtime Capture
210
210
 
211
+ Static inspection recognizes direct plugin factory calls and compiled CommonJS
212
+ calls such as `(0, sdk.defineBundledChannelEntry)(...)` without importing them.
211
213
  Runtime capture imports plugin entrypoints in an isolated subprocess and records
212
214
  what `register(api)` does. Use it when static inspection cannot prove the actual
213
215
  registrations made at runtime.
@@ -230,6 +232,10 @@ That keeps compatibility CI offline and credential-free. It does not call live
230
232
  services, launch OpenClaw, run provider SDKs, or emulate service lifecycle side
231
233
  effects.
232
234
 
235
+ Synthetic probes classify widget presenters as metadata-only. They record the
236
+ registration without calling its match, availability, or presentation callbacks,
237
+ including when channel, provider, or lifecycle execution is enabled.
238
+
233
239
  Use `--real-sdk` only when the plugin workspace already has real SDK
234
240
  dependencies installed and you intentionally want that path.
235
241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/plugin-inspector",
3
- "version": "0.3.23",
3
+ "version": "0.3.24",
4
4
  "private": false,
5
5
  "description": "Offline compatibility inspector for OpenClaw plugins.",
6
6
  "type": "module",
package/src/inspector.js CHANGED
@@ -15,6 +15,9 @@ import { buildCompatibilityReport, buildReport } from "./report.js";
15
15
  import { inspectSdkDeprecations } from "./sdk-deprecation-rules.js";
16
16
 
17
17
  const execFileAsync = promisify(execFile);
18
+ const pluginFactoryNames = "defineBundledChannelEntry|defineChannelPluginEntry|createChatChannelPlugin|definePluginEntry";
19
+ // Bundlers emit unbound calls as (0, sdk.factory)(...), including inline require receivers.
20
+ const compiledFactoryCall = new RegExp(String.raw`\(\s*0\s*,\s*(?:require\s*\(\s*(?:"[^"\r\n]*"|'[^'\r\n]*')\s*\)|[$A-Z_a-z][$\w]*)(?:\s*\.\s*[$A-Z_a-z][$\w]*)*\s*\.\s*(${pluginFactoryNames})\s*\)\s*\(`, "dg");
18
21
  const registrationEquivalents = new Map([
19
22
  ["registerChannel", new Set(["createChatChannelPlugin", "defineBundledChannelEntry", "defineChannelPluginEntry", "registerChannel"])],
20
23
  ]);
@@ -164,10 +167,8 @@ export function inspectSourceText(text, filePath = "source.js") {
164
167
  const hooks = collectDetailedMatches(searchableText, /\bapi\.on\(\s*["'`]([^"'`]+)["'`]/g, filePath, "name");
165
168
  const registrations = [
166
169
  ...collectDetailedMatches(searchableText, /\bapi\.(register[A-Za-z0-9]+)\s*\(/g, filePath, "name"),
167
- ...collectDetailedMatches(searchableText, /\b(defineBundledChannelEntry)\s*\(/g, filePath, "name"),
168
- ...collectDetailedMatches(searchableText, /\b(defineChannelPluginEntry)\s*\(/g, filePath, "name"),
169
- ...collectDetailedMatches(searchableText, /\b(createChatChannelPlugin)\s*\(/g, filePath, "name"),
170
- ...collectDetailedMatches(searchableText, /\b(definePluginEntry)\s*\(/g, filePath, "name"),
170
+ ...collectDetailedMatches(searchableText, new RegExp(String.raw`\b(${pluginFactoryNames})\s*\(`, "g"), filePath, "name"),
171
+ ...collectDetailedMatches(searchableText, compiledFactoryCall, filePath, "name"),
171
172
  ];
172
173
  const sdkImports = collectSdkImports(searchableText, filePath);
173
174
  const sdkDeprecations = inspectSdkDeprecations(searchableText, filePath);
@@ -373,7 +374,7 @@ function emptyInspection(fixture, status) {
373
374
  function collectDetailedMatches(text, regex, filePath, key) {
374
375
  const details = [];
375
376
  for (const match of text.matchAll(regex)) {
376
- const line = lineForOffset(text, match.index ?? 0);
377
+ const line = lineForOffset(text, match.indices?.[1]?.[0] ?? match.index ?? 0);
377
378
  details.push({
378
379
  [key]: match[1],
379
380
  file: filePath,
@@ -295,6 +295,11 @@ export const syntheticRegistrationExecutionProfiles = {
295
295
  callableProperties: [],
296
296
  reason: "web search providers are captured as registration metadata before provider runtime execution",
297
297
  },
298
+ registerWidgetPresenter: {
299
+ mode: "metadata-only",
300
+ callableProperties: [],
301
+ reason: "widget presenters are captured as registration metadata before presentation runtime execution",
302
+ },
298
303
  };
299
304
 
300
305
  export const defaultSyntheticHookEvents = {