@nextclaw/openclaw-compat 0.3.18 → 0.3.20

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +8 -2
  2. package/dist/index.js +391 -109
  3. package/package.json +14 -14
package/dist/index.d.ts CHANGED
@@ -562,6 +562,8 @@ declare function installPluginFromPath(params: {
562
562
  expectedPluginId?: string;
563
563
  }): Promise<InstallPluginResult>;
564
564
 
565
+ declare function buildPluginLoaderAliases(pluginRoot?: string): Record<string, string>;
566
+
565
567
  type PluginLoadOptions = {
566
568
  config: Config;
567
569
  workspaceDir?: string;
@@ -574,7 +576,7 @@ type PluginLoadOptions = {
574
576
  reservedEngineKinds?: string[];
575
577
  reservedNcpAgentRuntimeKinds?: string[];
576
578
  };
577
- declare function buildPluginLoaderAliases(): Record<string, string>;
579
+
578
580
  declare function loadOpenClawPlugins(options: PluginLoadOptions): PluginRegistry;
579
581
 
580
582
  type PluginManifestRecord = {
@@ -699,6 +701,10 @@ declare function validateJsonSchemaValue(params: {
699
701
  type PluginStatusReport = PluginRegistry & {
700
702
  workspaceDir: string;
701
703
  };
704
+ declare function discoverPluginStatusReport(params: {
705
+ config: Config;
706
+ workspaceDir?: string;
707
+ }): PluginStatusReport;
702
708
  declare function buildPluginStatusReport(params: {
703
709
  config: Config;
704
710
  workspaceDir?: string;
@@ -752,4 +758,4 @@ declare function uninstallPlugin(params: {
752
758
  extensionsDir?: string;
753
759
  }): Promise<UninstallPluginResult>;
754
760
 
755
- export { DEFAULT_ACCOUNT_ID, type InstallPluginResult, type NormalizedPluginsConfig, type OpenClawChannelAgentPrompt, type OpenClawChannelAuth, type OpenClawChannelAuthLoginResult, type OpenClawChannelAuthPollResult, type OpenClawChannelAuthStartResult, type OpenClawChannelConfigAdapter, type OpenClawChannelConfigSchema, type OpenClawChannelGateway, type OpenClawChannelGatewayStartContext, type OpenClawChannelPlugin, type OpenClawChannelSetup, type OpenClawPluginApi, type OpenClawPluginChannelRegistration, type OpenClawPluginConfigSchema, type OpenClawPluginDefinition, type OpenClawPluginEngineOptions, type OpenClawPluginModule, type OpenClawPluginNcpAgentRuntimeRegistration, type OpenClawPluginTool, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OpenClawProviderPlugin, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PackageManifest, type PluginCandidate, type PluginChannelBinding, type PluginChannelGatewayHandle, type PluginChannelRegistration, type PluginConfigUiHint, type PluginDiagnostic, type PluginDiscoveryResult, type PluginEngineRegistration, type PluginInstallLogger, type PluginInstallSource, type PluginInstallUpdate, type PluginKind, type PluginLoadOptions, type PluginLogger, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRecord, type PluginManifestRegistry, type PluginNcpAgentRuntimeRegistration, type PluginOrigin, type PluginProviderRegistration, type PluginRecord, type PluginRegisterRuntime, type PluginRegistry, type PluginReplyDispatchParams, type PluginRuntime, type PluginRuntimeBridge, type PluginStatusReport, type PluginToolRegistration, type PluginUiMetadata, type UninstallActions, type UninstallPluginResult, type _CompatOnly, __nextclawPluginSdkCompat, addPluginLoadPath, buildChannelConfigSchema, buildOauthProviderAuthResult, buildPluginLoaderAliases, buildPluginStatusReport, createNextclawBuiltinChannelPlugin, createPluginRegisterRuntime, createPluginRuntime, disablePluginInConfig, discoverOpenClawPlugins, emptyPluginConfigSchema, enablePluginInConfig, getPackageManifestMetadata, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromArchive, installPluginFromDir, installPluginFromFile, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, loadPluginManifestRegistry, loadPluginUiMetadata, mergePluginConfigView, normalizeAccountId, normalizePluginHttpPath, normalizePluginsConfig, recordPluginInstall, registerPluginWithApi, removePluginFromConfig, resolveEnableState, resolvePluginChannelMessageToolHints, resolvePluginInstallDir, resolvePluginManifestPath, resolveUninstallDirectoryTarget, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, sleep, startPluginChannelGateways, stopPluginChannelGateways, toPluginConfigView, toPluginUiMetadata, uninstallPlugin, validateJsonSchemaValue };
761
+ export { DEFAULT_ACCOUNT_ID, type InstallPluginResult, type NormalizedPluginsConfig, type OpenClawChannelAgentPrompt, type OpenClawChannelAuth, type OpenClawChannelAuthLoginResult, type OpenClawChannelAuthPollResult, type OpenClawChannelAuthStartResult, type OpenClawChannelConfigAdapter, type OpenClawChannelConfigSchema, type OpenClawChannelGateway, type OpenClawChannelGatewayStartContext, type OpenClawChannelPlugin, type OpenClawChannelSetup, type OpenClawPluginApi, type OpenClawPluginChannelRegistration, type OpenClawPluginConfigSchema, type OpenClawPluginDefinition, type OpenClawPluginEngineOptions, type OpenClawPluginModule, type OpenClawPluginNcpAgentRuntimeRegistration, type OpenClawPluginTool, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OpenClawProviderPlugin, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PackageManifest, type PluginCandidate, type PluginChannelBinding, type PluginChannelGatewayHandle, type PluginChannelRegistration, type PluginConfigUiHint, type PluginDiagnostic, type PluginDiscoveryResult, type PluginEngineRegistration, type PluginInstallLogger, type PluginInstallSource, type PluginInstallUpdate, type PluginKind, type PluginLoadOptions, type PluginLogger, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRecord, type PluginManifestRegistry, type PluginNcpAgentRuntimeRegistration, type PluginOrigin, type PluginProviderRegistration, type PluginRecord, type PluginRegisterRuntime, type PluginRegistry, type PluginReplyDispatchParams, type PluginRuntime, type PluginRuntimeBridge, type PluginStatusReport, type PluginToolRegistration, type PluginUiMetadata, type UninstallActions, type UninstallPluginResult, type _CompatOnly, __nextclawPluginSdkCompat, addPluginLoadPath, buildChannelConfigSchema, buildOauthProviderAuthResult, buildPluginLoaderAliases, buildPluginStatusReport, createNextclawBuiltinChannelPlugin, createPluginRegisterRuntime, createPluginRuntime, disablePluginInConfig, discoverOpenClawPlugins, discoverPluginStatusReport, emptyPluginConfigSchema, enablePluginInConfig, getPackageManifestMetadata, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromArchive, installPluginFromDir, installPluginFromFile, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, loadPluginManifestRegistry, loadPluginUiMetadata, mergePluginConfigView, normalizeAccountId, normalizePluginHttpPath, normalizePluginsConfig, recordPluginInstall, registerPluginWithApi, removePluginFromConfig, resolveEnableState, resolvePluginChannelMessageToolHints, resolvePluginInstallDir, resolvePluginManifestPath, resolveUninstallDirectoryTarget, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, sleep, startPluginChannelGateways, stopPluginChannelGateways, toPluginConfigView, toPluginUiMetadata, uninstallPlugin, validateJsonSchemaValue };
package/dist/index.js CHANGED
@@ -1137,10 +1137,9 @@ async function installPluginFromPath(params) {
1137
1137
  }
1138
1138
 
1139
1139
  // src/plugins/loader.ts
1140
- import fs5 from "fs";
1141
- import path6 from "path";
1142
- import { fileURLToPath } from "url";
1143
- import { createRequire } from "module";
1140
+ import fs6 from "fs";
1141
+ import path7 from "path";
1142
+ import { createRequire as createRequire2 } from "module";
1144
1143
  import { getWorkspacePathFromConfig } from "@nextclaw/core";
1145
1144
 
1146
1145
  // src/plugins/bundled-channel-plugin-packages.constants.ts
@@ -1331,6 +1330,7 @@ var createJiti = createJitiImport;
1331
1330
  function createPluginJiti(aliases) {
1332
1331
  return createJiti(import.meta.url, {
1333
1332
  interopDefault: true,
1333
+ esmResolve: true,
1334
1334
  extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs", ".json"],
1335
1335
  alias: aliases,
1336
1336
  // Plugin install/upgrade is expected to hot-apply at runtime. Disable
@@ -1341,6 +1341,195 @@ function createPluginJiti(aliases) {
1341
1341
  });
1342
1342
  }
1343
1343
 
1344
+ // src/plugins/plugin-loader-aliases.ts
1345
+ import fs5 from "fs";
1346
+ import path5 from "path";
1347
+ import { createRequire } from "module";
1348
+ import { fileURLToPath } from "url";
1349
+ function resolvePluginSdkAliasFile(params) {
1350
+ try {
1351
+ const modulePath = fileURLToPath(import.meta.url);
1352
+ const isProduction = process.env.NODE_ENV === "production";
1353
+ let cursor = path5.dirname(modulePath);
1354
+ for (let i = 0; i < 6; i += 1) {
1355
+ const srcCandidate = path5.join(cursor, "src", "plugin-sdk", params.srcFile);
1356
+ const distCandidate = path5.join(cursor, "dist", "plugin-sdk", params.distFile);
1357
+ const candidates = isProduction ? [distCandidate, srcCandidate] : [srcCandidate, distCandidate];
1358
+ for (const candidate of candidates) {
1359
+ if (fs5.existsSync(candidate)) {
1360
+ return candidate;
1361
+ }
1362
+ }
1363
+ const parent = path5.dirname(cursor);
1364
+ if (parent === cursor) {
1365
+ break;
1366
+ }
1367
+ cursor = parent;
1368
+ }
1369
+ } catch {
1370
+ return null;
1371
+ }
1372
+ return null;
1373
+ }
1374
+ function resolvePluginSdkAlias() {
1375
+ return resolvePluginSdkAliasFile({ srcFile: "index.ts", distFile: "index.js" });
1376
+ }
1377
+ function resolvePluginShimFile(relativePath) {
1378
+ try {
1379
+ const modulePath = fileURLToPath(import.meta.url);
1380
+ const isProduction = process.env.NODE_ENV === "production";
1381
+ let cursor = path5.dirname(modulePath);
1382
+ for (let i = 0; i < 6; i += 1) {
1383
+ const srcCandidate = path5.join(cursor, "src", "plugins", "shims", relativePath);
1384
+ const distCandidate = path5.join(cursor, "dist", "plugins", "shims", relativePath.replace(/\.ts$/, ".js"));
1385
+ const candidates = isProduction ? [distCandidate, srcCandidate] : [srcCandidate, distCandidate];
1386
+ for (const candidate of candidates) {
1387
+ if (fs5.existsSync(candidate)) {
1388
+ return candidate;
1389
+ }
1390
+ }
1391
+ const parent = path5.dirname(cursor);
1392
+ if (parent === cursor) {
1393
+ break;
1394
+ }
1395
+ cursor = parent;
1396
+ }
1397
+ } catch {
1398
+ return null;
1399
+ }
1400
+ return null;
1401
+ }
1402
+ function collectExportStringValues(value, values) {
1403
+ if (typeof value === "string") {
1404
+ values.push(value);
1405
+ return;
1406
+ }
1407
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1408
+ return;
1409
+ }
1410
+ for (const child of Object.values(value)) {
1411
+ collectExportStringValues(child, values);
1412
+ }
1413
+ }
1414
+ function resolveLocalPackageDir(pluginRoot, packageName) {
1415
+ const segments = packageName.split("/");
1416
+ return path5.join(pluginRoot, "node_modules", ...segments);
1417
+ }
1418
+ function isRunnableEntryFile(filePath) {
1419
+ const normalized = filePath.toLowerCase();
1420
+ if (normalized.endsWith(".d.ts") || normalized.endsWith(".map")) {
1421
+ return false;
1422
+ }
1423
+ return fs5.existsSync(filePath);
1424
+ }
1425
+ function hasRunnableLocalPackage(pluginRoot, packageName) {
1426
+ try {
1427
+ const packageDir = resolveLocalPackageDir(pluginRoot, packageName);
1428
+ const packageJsonPath = path5.join(packageDir, "package.json");
1429
+ if (!fs5.existsSync(packageJsonPath)) {
1430
+ return false;
1431
+ }
1432
+ const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf-8"));
1433
+ const entryCandidates = [];
1434
+ collectExportStringValues(packageJson.exports, entryCandidates);
1435
+ if (typeof packageJson.module === "string") {
1436
+ entryCandidates.push(packageJson.module);
1437
+ }
1438
+ if (typeof packageJson.main === "string") {
1439
+ entryCandidates.push(packageJson.main);
1440
+ }
1441
+ if (entryCandidates.length === 0) {
1442
+ entryCandidates.push("index.js", "index.mjs", "index.cjs");
1443
+ }
1444
+ return entryCandidates.some((candidate) => {
1445
+ const resolved = path5.resolve(packageDir, candidate);
1446
+ return resolved.startsWith(`${path5.resolve(packageDir)}${path5.sep}`) && isRunnableEntryFile(resolved);
1447
+ });
1448
+ } catch {
1449
+ return false;
1450
+ }
1451
+ }
1452
+ function readScopeEntries(scopeDir) {
1453
+ try {
1454
+ return fs5.readdirSync(scopeDir, { withFileTypes: true });
1455
+ } catch {
1456
+ return [];
1457
+ }
1458
+ }
1459
+ function isAliasablePackageEntry(entry) {
1460
+ return entry.isDirectory() || entry.isSymbolicLink();
1461
+ }
1462
+ function shouldAliasHostPackage(pluginRoot, packageName) {
1463
+ return !pluginRoot || !hasRunnableLocalPackage(pluginRoot, packageName);
1464
+ }
1465
+ function appendScopeAliases(params) {
1466
+ for (const entry of readScopeEntries(params.scopeDir)) {
1467
+ if (!isAliasablePackageEntry(entry)) {
1468
+ continue;
1469
+ }
1470
+ const packageName = `${params.scope}/${entry.name}`;
1471
+ if (!shouldAliasHostPackage(params.pluginRoot, packageName)) {
1472
+ continue;
1473
+ }
1474
+ try {
1475
+ params.aliases[packageName] = params.require.resolve(packageName);
1476
+ } catch {
1477
+ }
1478
+ }
1479
+ }
1480
+ function buildScopedPackageAliases(scope, pluginRoot) {
1481
+ const aliases = {};
1482
+ const require2 = createRequire(import.meta.url);
1483
+ let cursor = path5.dirname(fileURLToPath(import.meta.url));
1484
+ for (let i = 0; i < 8; i += 1) {
1485
+ const scopeDir = path5.join(cursor, "node_modules", scope);
1486
+ if (fs5.existsSync(scopeDir)) {
1487
+ appendScopeAliases({ aliases, scopeDir, scope, pluginRoot, require: require2 });
1488
+ }
1489
+ const parent = path5.dirname(cursor);
1490
+ if (parent === cursor) {
1491
+ break;
1492
+ }
1493
+ cursor = parent;
1494
+ }
1495
+ return aliases;
1496
+ }
1497
+ function buildPluginLoaderAliases(pluginRoot) {
1498
+ const aliases = buildScopedPackageAliases("@nextclaw", pluginRoot);
1499
+ const pluginSdkAlias = resolvePluginSdkAlias();
1500
+ const shouldUseCompatPluginSdkAlias = shouldAliasHostPackage(pluginRoot, "openclaw");
1501
+ if (pluginSdkAlias && shouldUseCompatPluginSdkAlias) {
1502
+ aliases["openclaw/plugin-sdk"] = pluginSdkAlias;
1503
+ }
1504
+ const piCodingAgentShim = resolvePluginShimFile("pi-coding-agent.ts");
1505
+ if (piCodingAgentShim) {
1506
+ aliases["@mariozechner/pi-coding-agent"] = piCodingAgentShim;
1507
+ }
1508
+ return aliases;
1509
+ }
1510
+
1511
+ // src/plugins/bundled-plugin-loader.ts
1512
+ function resolveBundledPluginEntry(require2, packageName, diagnostics, resolvePackageRootFromEntry3) {
1513
+ try {
1514
+ const entryFile = require2.resolve(packageName);
1515
+ return {
1516
+ entryFile,
1517
+ rootDir: resolvePackageRootFromEntry3(entryFile)
1518
+ };
1519
+ } catch (err) {
1520
+ diagnostics.push({
1521
+ level: "error",
1522
+ source: packageName,
1523
+ message: `bundled plugin package not resolvable: ${String(err)}`
1524
+ });
1525
+ return null;
1526
+ }
1527
+ }
1528
+ function loadBundledPluginModule(entryFile, rootDir) {
1529
+ const pluginJiti = createPluginJiti(buildPluginLoaderAliases(rootDir));
1530
+ return pluginJiti(entryFile);
1531
+ }
1532
+
1344
1533
  // src/plugins/schema-validator.ts
1345
1534
  import AjvPkg from "ajv";
1346
1535
  var AjvCtor = AjvPkg;
@@ -1355,9 +1544,9 @@ function formatAjvErrors(errors) {
1355
1544
  return ["invalid config"];
1356
1545
  }
1357
1546
  return errors.map((error) => {
1358
- const path8 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
1547
+ const path10 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
1359
1548
  const message = error.message ?? "invalid";
1360
- return `${path8}: ${message}`;
1549
+ return `${path10}: ${message}`;
1361
1550
  });
1362
1551
  }
1363
1552
  function validateJsonSchemaValue(params) {
@@ -1427,7 +1616,7 @@ function validatePluginConfig(params) {
1427
1616
  }
1428
1617
 
1429
1618
  // src/plugins/registry.ts
1430
- import path5 from "path";
1619
+ import path6 from "path";
1431
1620
  import { expandHome as expandHome2 } from "@nextclaw/core";
1432
1621
 
1433
1622
  // src/plugins/plugin-capability-registration.ts
@@ -1881,10 +2070,10 @@ function registerPluginWithApi(params) {
1881
2070
  if (!trimmed) {
1882
2071
  return params.rootDir;
1883
2072
  }
1884
- if (path5.isAbsolute(trimmed)) {
1885
- return path5.resolve(expandHome2(trimmed));
2073
+ if (path6.isAbsolute(trimmed)) {
2074
+ return path6.resolve(expandHome2(trimmed));
1886
2075
  }
1887
- return path5.resolve(params.rootDir, trimmed);
2076
+ return path6.resolve(params.rootDir, trimmed);
1888
2077
  }
1889
2078
  };
1890
2079
  try {
@@ -1912,87 +2101,19 @@ var defaultLogger2 = {
1912
2101
  debug: (message) => console.debug(message)
1913
2102
  };
1914
2103
  function resolvePackageRootFromEntry(entryFile) {
1915
- let cursor = path6.dirname(entryFile);
2104
+ let cursor = path7.dirname(entryFile);
1916
2105
  for (let i = 0; i < 8; i += 1) {
1917
- const candidate = path6.join(cursor, "package.json");
1918
- if (fs5.existsSync(candidate)) {
2106
+ const candidate = path7.join(cursor, "package.json");
2107
+ if (fs6.existsSync(candidate)) {
1919
2108
  return cursor;
1920
2109
  }
1921
- const parent = path6.dirname(cursor);
1922
- if (parent === cursor) {
1923
- break;
1924
- }
1925
- cursor = parent;
1926
- }
1927
- return path6.dirname(entryFile);
1928
- }
1929
- function resolvePluginSdkAliasFile(params) {
1930
- try {
1931
- const modulePath = fileURLToPath(import.meta.url);
1932
- const isProduction = process.env.NODE_ENV === "production";
1933
- let cursor = path6.dirname(modulePath);
1934
- for (let i = 0; i < 6; i += 1) {
1935
- const srcCandidate = path6.join(cursor, "src", "plugin-sdk", params.srcFile);
1936
- const distCandidate = path6.join(cursor, "dist", "plugin-sdk", params.distFile);
1937
- const candidates = isProduction ? [distCandidate, srcCandidate] : [srcCandidate, distCandidate];
1938
- for (const candidate of candidates) {
1939
- if (fs5.existsSync(candidate)) {
1940
- return candidate;
1941
- }
1942
- }
1943
- const parent = path6.dirname(cursor);
1944
- if (parent === cursor) {
1945
- break;
1946
- }
1947
- cursor = parent;
1948
- }
1949
- } catch {
1950
- return null;
1951
- }
1952
- return null;
1953
- }
1954
- function resolvePluginSdkAlias() {
1955
- return resolvePluginSdkAliasFile({ srcFile: "index.ts", distFile: "index.js" });
1956
- }
1957
- function buildScopedPackageAliases(scope) {
1958
- const aliases = {};
1959
- const require2 = createRequire(import.meta.url);
1960
- let cursor = path6.dirname(fileURLToPath(import.meta.url));
1961
- for (let i = 0; i < 8; i += 1) {
1962
- const scopeDir = path6.join(cursor, "node_modules", scope);
1963
- if (fs5.existsSync(scopeDir)) {
1964
- let entries = [];
1965
- try {
1966
- entries = fs5.readdirSync(scopeDir, { withFileTypes: true });
1967
- } catch {
1968
- entries = [];
1969
- }
1970
- for (const entry of entries) {
1971
- if (!entry.isDirectory() && !entry.isSymbolicLink()) {
1972
- continue;
1973
- }
1974
- const packageName = `${scope}/${entry.name}`;
1975
- try {
1976
- aliases[packageName] = require2.resolve(packageName);
1977
- } catch {
1978
- }
1979
- }
1980
- }
1981
- const parent = path6.dirname(cursor);
2110
+ const parent = path7.dirname(cursor);
1982
2111
  if (parent === cursor) {
1983
2112
  break;
1984
2113
  }
1985
2114
  cursor = parent;
1986
2115
  }
1987
- return aliases;
1988
- }
1989
- function buildPluginLoaderAliases() {
1990
- const aliases = buildScopedPackageAliases("@nextclaw");
1991
- const pluginSdkAlias = resolvePluginSdkAlias();
1992
- if (pluginSdkAlias) {
1993
- aliases["openclaw/plugin-sdk"] = pluginSdkAlias;
1994
- }
1995
- return aliases;
2116
+ return path7.dirname(entryFile);
1996
2117
  }
1997
2118
  function resolvePluginModuleExport(moduleExport) {
1998
2119
  const resolved = moduleExport && typeof moduleExport === "object" && "default" in moduleExport ? moduleExport.default : moduleExport;
@@ -2011,24 +2132,21 @@ function resolvePluginModuleExport(moduleExport) {
2011
2132
  return {};
2012
2133
  }
2013
2134
  function appendBundledChannelPlugins(params) {
2014
- const require2 = createRequire(import.meta.url);
2135
+ const require2 = createRequire2(import.meta.url);
2015
2136
  for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
2016
- let entryFile = "";
2017
- let rootDir = "";
2018
- try {
2019
- entryFile = require2.resolve(packageName);
2020
- rootDir = resolvePackageRootFromEntry(entryFile);
2021
- } catch (err) {
2022
- params.registry.diagnostics.push({
2023
- level: "error",
2024
- source: packageName,
2025
- message: `bundled plugin package not resolvable: ${String(err)}`
2026
- });
2137
+ const resolvedEntry = resolveBundledPluginEntry(
2138
+ require2,
2139
+ packageName,
2140
+ params.registry.diagnostics,
2141
+ resolvePackageRootFromEntry
2142
+ );
2143
+ if (!resolvedEntry) {
2027
2144
  continue;
2028
2145
  }
2146
+ const { entryFile, rootDir } = resolvedEntry;
2029
2147
  let moduleExport = null;
2030
2148
  try {
2031
- moduleExport = params.jiti(entryFile);
2149
+ moduleExport = loadBundledPluginModule(entryFile, rootDir);
2032
2150
  } catch (err) {
2033
2151
  params.registry.diagnostics.push({
2034
2152
  level: "error",
@@ -2104,6 +2222,10 @@ function appendBundledChannelPlugins(params) {
2104
2222
  params.registry.plugins.push(record);
2105
2223
  }
2106
2224
  }
2225
+ function loadExternalPluginModule(candidateSource, pluginRoot) {
2226
+ const pluginJiti = createPluginJiti(buildPluginLoaderAliases(pluginRoot));
2227
+ return pluginJiti(candidateSource);
2228
+ }
2107
2229
  function loadOpenClawPlugins(options) {
2108
2230
  const loadExternalPlugins = process.env.NEXTCLAW_ENABLE_OPENCLAW_PLUGINS !== "0";
2109
2231
  const logger = options.logger ?? defaultLogger2;
@@ -2138,11 +2260,9 @@ function loadOpenClawPlugins(options) {
2138
2260
  reservedEngineKinds,
2139
2261
  reservedNcpAgentRuntimeKinds
2140
2262
  });
2141
- const jiti = createPluginJiti(buildPluginLoaderAliases());
2142
2263
  appendBundledChannelPlugins({
2143
2264
  registry,
2144
2265
  runtime: registerRuntime,
2145
- jiti,
2146
2266
  normalizedConfig: normalized
2147
2267
  });
2148
2268
  if (!loadExternalPlugins) {
@@ -2253,7 +2373,7 @@ function loadOpenClawPlugins(options) {
2253
2373
  }
2254
2374
  let moduleExport = null;
2255
2375
  try {
2256
- moduleExport = jiti(candidate.source);
2376
+ moduleExport = loadExternalPluginModule(candidate.source, candidate.rootDir);
2257
2377
  } catch (err) {
2258
2378
  record.status = "error";
2259
2379
  record.error = `failed to load plugin: ${String(err)}`;
@@ -2324,7 +2444,168 @@ function loadOpenClawPlugins(options) {
2324
2444
  }
2325
2445
 
2326
2446
  // src/plugins/status.ts
2447
+ import fs7 from "fs";
2448
+ import { createRequire as createRequire3 } from "module";
2449
+ import path8 from "path";
2327
2450
  import { getWorkspacePathFromConfig as getWorkspacePathFromConfig2 } from "@nextclaw/core";
2451
+ function createEmptyPluginRegistry() {
2452
+ return {
2453
+ plugins: [],
2454
+ tools: [],
2455
+ channels: [],
2456
+ providers: [],
2457
+ engines: [],
2458
+ ncpAgentRuntimes: [],
2459
+ diagnostics: [],
2460
+ resolvedTools: []
2461
+ };
2462
+ }
2463
+ function resolvePackageRootFromEntry2(entryFile) {
2464
+ let cursor = path8.dirname(entryFile);
2465
+ for (let index = 0; index < 8; index += 1) {
2466
+ const candidate = path8.join(cursor, "package.json");
2467
+ if (fs7.existsSync(candidate)) {
2468
+ return cursor;
2469
+ }
2470
+ const parent = path8.dirname(cursor);
2471
+ if (parent === cursor) {
2472
+ break;
2473
+ }
2474
+ cursor = parent;
2475
+ }
2476
+ return path8.dirname(entryFile);
2477
+ }
2478
+ function discoverBundledPluginCandidates(workspaceDir, diagnostics) {
2479
+ const require2 = createRequire3(import.meta.url);
2480
+ const candidates = [];
2481
+ for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
2482
+ try {
2483
+ const entryFile = require2.resolve(packageName);
2484
+ candidates.push({
2485
+ idHint: packageName.split("/").pop() ?? packageName,
2486
+ source: entryFile,
2487
+ rootDir: resolvePackageRootFromEntry2(entryFile),
2488
+ origin: "bundled",
2489
+ workspaceDir,
2490
+ packageName
2491
+ });
2492
+ } catch (error) {
2493
+ diagnostics.push({
2494
+ level: "error",
2495
+ source: packageName,
2496
+ message: `bundled plugin package not resolvable: ${String(error)}`
2497
+ });
2498
+ }
2499
+ }
2500
+ return candidates;
2501
+ }
2502
+ function createRecordFromManifest(manifest, enabled) {
2503
+ return createPluginRecord({
2504
+ id: manifest.id,
2505
+ name: manifest.name ?? manifest.id,
2506
+ description: manifest.description,
2507
+ version: manifest.version,
2508
+ kind: manifest.kind,
2509
+ source: manifest.source,
2510
+ origin: manifest.origin,
2511
+ workspaceDir: manifest.workspaceDir,
2512
+ enabled,
2513
+ configSchema: Boolean(manifest.configSchema),
2514
+ configUiHints: manifest.configUiHints,
2515
+ configJsonSchema: manifest.configSchema
2516
+ });
2517
+ }
2518
+ function createOverriddenManifestRecord(manifest, existingOrigin) {
2519
+ const record = createRecordFromManifest(manifest, false);
2520
+ record.status = "disabled";
2521
+ record.error = `overridden by ${existingOrigin} plugin`;
2522
+ return record;
2523
+ }
2524
+ function finalizeDiscoveredManifestRecord(params) {
2525
+ const record = createRecordFromManifest(params.manifest, params.enabled);
2526
+ if (!params.enabled) {
2527
+ record.status = "disabled";
2528
+ record.error = params.disabledReason;
2529
+ return { record, diagnostics: [] };
2530
+ }
2531
+ if (!params.manifest.configSchema) {
2532
+ record.status = "error";
2533
+ record.error = "missing config schema";
2534
+ return {
2535
+ record,
2536
+ diagnostics: [
2537
+ {
2538
+ level: "error",
2539
+ pluginId: params.manifest.id,
2540
+ source: params.manifest.source,
2541
+ message: record.error
2542
+ }
2543
+ ]
2544
+ };
2545
+ }
2546
+ const validatedConfig = validatePluginConfig({
2547
+ schema: params.manifest.configSchema,
2548
+ cacheKey: params.manifest.schemaCacheKey,
2549
+ value: params.normalizedEntries[params.manifest.id]?.config
2550
+ });
2551
+ if (validatedConfig.ok) {
2552
+ return { record, diagnostics: [] };
2553
+ }
2554
+ record.status = "error";
2555
+ record.error = `invalid config: ${validatedConfig.errors.join(", ")}`;
2556
+ return {
2557
+ record,
2558
+ diagnostics: [
2559
+ {
2560
+ level: "error",
2561
+ pluginId: params.manifest.id,
2562
+ source: params.manifest.source,
2563
+ message: record.error
2564
+ }
2565
+ ]
2566
+ };
2567
+ }
2568
+ function discoverPluginStatusReport(params) {
2569
+ const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig2(params.config);
2570
+ const normalized = normalizePluginsConfig(params.config.plugins);
2571
+ const discovery = discoverOpenClawPlugins({
2572
+ config: params.config,
2573
+ workspaceDir,
2574
+ extraPaths: normalized.loadPaths
2575
+ });
2576
+ const bundledDiagnostics = [];
2577
+ const bundledCandidates = discoverBundledPluginCandidates(workspaceDir, bundledDiagnostics);
2578
+ const manifestRegistry = loadPluginManifestRegistry({
2579
+ config: params.config,
2580
+ workspaceDir,
2581
+ candidates: [...bundledCandidates, ...discovery.candidates],
2582
+ diagnostics: [...bundledDiagnostics, ...discovery.diagnostics]
2583
+ });
2584
+ const registry = createEmptyPluginRegistry();
2585
+ const seenIds = /* @__PURE__ */ new Map();
2586
+ registry.diagnostics.push(...manifestRegistry.diagnostics);
2587
+ for (const manifest of manifestRegistry.plugins) {
2588
+ const existingOrigin = seenIds.get(manifest.id);
2589
+ if (existingOrigin) {
2590
+ registry.plugins.push(createOverriddenManifestRecord(manifest, existingOrigin));
2591
+ continue;
2592
+ }
2593
+ const enableState = resolveEnableState(manifest.id, normalized);
2594
+ const { record, diagnostics } = finalizeDiscoveredManifestRecord({
2595
+ manifest,
2596
+ normalizedEntries: normalized.entries,
2597
+ enabled: enableState.enabled,
2598
+ disabledReason: enableState.reason
2599
+ });
2600
+ registry.plugins.push(record);
2601
+ registry.diagnostics.push(...diagnostics);
2602
+ seenIds.set(manifest.id, manifest.origin);
2603
+ }
2604
+ return {
2605
+ workspaceDir,
2606
+ ...registry
2607
+ };
2608
+ }
2328
2609
  function buildPluginStatusReport(params) {
2329
2610
  const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig2(params.config);
2330
2611
  const registry = loadOpenClawPlugins({
@@ -2344,9 +2625,9 @@ function buildPluginStatusReport(params) {
2344
2625
  }
2345
2626
 
2346
2627
  // src/plugins/uninstall.ts
2347
- import fs6 from "fs/promises";
2628
+ import fs8 from "fs/promises";
2348
2629
  import { existsSync, statSync } from "fs";
2349
- import path7 from "path";
2630
+ import path9 from "path";
2350
2631
  import { getWorkspacePathFromConfig as getWorkspacePathFromConfig3 } from "@nextclaw/core";
2351
2632
  function isLinkedPathInstall(record) {
2352
2633
  if (!record || record.source !== "path") {
@@ -2355,13 +2636,13 @@ function isLinkedPathInstall(record) {
2355
2636
  if (!record.sourcePath || !record.installPath) {
2356
2637
  return true;
2357
2638
  }
2358
- return path7.resolve(record.sourcePath) === path7.resolve(record.installPath);
2639
+ return path9.resolve(record.sourcePath) === path9.resolve(record.installPath);
2359
2640
  }
2360
2641
  function pushUniquePath(targets, candidate) {
2361
2642
  if (!candidate) {
2362
2643
  return;
2363
2644
  }
2364
- const resolved = path7.resolve(candidate);
2645
+ const resolved = path9.resolve(candidate);
2365
2646
  if (!targets.includes(resolved)) {
2366
2647
  targets.push(resolved);
2367
2648
  }
@@ -2383,7 +2664,7 @@ function resolveUninstallDirectoryTarget(params) {
2383
2664
  if (!configuredPath) {
2384
2665
  return defaultPath;
2385
2666
  }
2386
- if (path7.resolve(configuredPath) === path7.resolve(defaultPath)) {
2667
+ if (path9.resolve(configuredPath) === path9.resolve(defaultPath)) {
2387
2668
  return configuredPath;
2388
2669
  }
2389
2670
  return defaultPath;
@@ -2404,7 +2685,7 @@ function resolveUninstallDirectoryTargets(params) {
2404
2685
  );
2405
2686
  pushUniquePath(targets, params.installRecord?.installPath);
2406
2687
  const workspaceDir = getWorkspacePathFromConfig3(params.config);
2407
- pushUniquePath(targets, path7.join(workspaceDir, ".nextclaw", "extensions", params.pluginId));
2688
+ pushUniquePath(targets, path9.join(workspaceDir, ".nextclaw", "extensions", params.pluginId));
2408
2689
  return targets;
2409
2690
  }
2410
2691
  function removePluginFromConfig(config, pluginId) {
@@ -2485,13 +2766,13 @@ function matchesPluginLoadPath(rawPath, pluginId) {
2485
2766
  if (!normalizedPath) {
2486
2767
  return false;
2487
2768
  }
2488
- const resolvedPath = path7.resolve(normalizedPath);
2769
+ const resolvedPath = path9.resolve(normalizedPath);
2489
2770
  if (!existsSync(resolvedPath)) {
2490
2771
  return false;
2491
2772
  }
2492
2773
  const candidateRoot = (() => {
2493
2774
  try {
2494
- return statSync(resolvedPath).isDirectory() ? resolvedPath : path7.dirname(resolvedPath);
2775
+ return statSync(resolvedPath).isDirectory() ? resolvedPath : path9.dirname(resolvedPath);
2495
2776
  } catch {
2496
2777
  return null;
2497
2778
  }
@@ -2525,9 +2806,9 @@ async function uninstallPlugin(params) {
2525
2806
  extensionsDir
2526
2807
  }) : [];
2527
2808
  for (const deleteTarget of deleteTargets) {
2528
- const existed = await fs6.access(deleteTarget).then(() => true).catch(() => false);
2809
+ const existed = await fs8.access(deleteTarget).then(() => true).catch(() => false);
2529
2810
  try {
2530
- await fs6.rm(deleteTarget, { recursive: true, force: true });
2811
+ await fs8.rm(deleteTarget, { recursive: true, force: true });
2531
2812
  actions.directory = actions.directory || existed;
2532
2813
  } catch (error) {
2533
2814
  warnings.push(
@@ -2558,6 +2839,7 @@ export {
2558
2839
  createPluginRuntime,
2559
2840
  disablePluginInConfig,
2560
2841
  discoverOpenClawPlugins,
2842
+ discoverPluginStatusReport,
2561
2843
  emptyPluginConfigSchema,
2562
2844
  enablePluginInConfig,
2563
2845
  getPackageManifestMetadata,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/openclaw-compat",
3
- "version": "0.3.18",
3
+ "version": "0.3.20",
4
4
  "private": false,
5
5
  "description": "OpenClaw plugin compatibility layer for NextClaw.",
6
6
  "type": "module",
@@ -19,21 +19,21 @@
19
19
  "jiti": "^1.21.7",
20
20
  "jszip": "^3.10.1",
21
21
  "tar": "^7.4.3",
22
- "@nextclaw/channel-plugin-dingtalk": "0.2.12",
23
- "@nextclaw/channel-plugin-discord": "0.2.12",
24
- "@nextclaw/channel-plugin-feishu": "0.2.12",
25
- "@nextclaw/channel-plugin-email": "0.2.12",
26
- "@nextclaw/channel-plugin-qq": "0.2.12",
27
- "@nextclaw/channel-plugin-slack": "0.2.12",
28
- "@nextclaw/channel-plugin-telegram": "0.2.12",
29
- "@nextclaw/channel-plugin-wecom": "0.2.12",
30
- "@nextclaw/channel-plugin-weixin": "0.1.6",
31
- "@nextclaw/channel-runtime": "0.2.12",
22
+ "@nextclaw/channel-plugin-dingtalk": "0.2.13",
23
+ "@nextclaw/channel-plugin-email": "0.2.13",
24
+ "@nextclaw/channel-plugin-mochat": "0.2.13",
25
+ "@nextclaw/channel-plugin-feishu": "0.2.14",
26
+ "@nextclaw/channel-plugin-qq": "0.2.13",
27
+ "@nextclaw/channel-plugin-telegram": "0.2.13",
28
+ "@nextclaw/channel-plugin-discord": "0.2.13",
29
+ "@nextclaw/channel-plugin-slack": "0.2.13",
30
+ "@nextclaw/channel-plugin-whatsapp": "0.2.13",
32
31
  "@nextclaw/ncp": "0.3.2",
32
+ "@nextclaw/core": "0.10.0",
33
+ "@nextclaw/channel-runtime": "0.3.0",
33
34
  "@nextclaw/ncp-toolkit": "0.4.2",
34
- "@nextclaw/core": "0.9.12",
35
- "@nextclaw/channel-plugin-whatsapp": "0.2.12",
36
- "@nextclaw/channel-plugin-mochat": "0.2.12"
35
+ "@nextclaw/channel-plugin-weixin": "0.1.7",
36
+ "@nextclaw/channel-plugin-wecom": "0.2.13"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^20.17.6",