@nextclaw/openclaw-compat 0.3.34 → 0.3.36

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 +80 -45
  2. package/dist/index.js +672 -46
  3. package/package.json +15 -15
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nextclaw_core from '@nextclaw/core';
2
- import { Config, ExtensionChannel, AgentEngineFactory } from '@nextclaw/core';
2
+ import { Config, ExtensionChannel, ProviderRuntimeResolution, AgentEngineFactory } from '@nextclaw/core';
3
3
  import { NcpAgentRuntime } from '@nextclaw/ncp';
4
4
  import { RuntimeFactoryParams } from '@nextclaw/ncp-toolkit';
5
5
 
@@ -328,6 +328,21 @@ type PluginReplyDispatchParams = {
328
328
  };
329
329
  type PluginRuntime = {
330
330
  version: string;
331
+ agent: {
332
+ defaults: {
333
+ model: string;
334
+ workspace: string;
335
+ maxToolIterations: number;
336
+ };
337
+ resolveWorkspacePath: (workspace?: string) => string;
338
+ resolveProviderRuntime: (model?: string) => ProviderRuntimeResolution;
339
+ buildRuntimeUserPrompt: (params: {
340
+ workspace?: string;
341
+ sessionKey?: string;
342
+ metadata?: Record<string, unknown>;
343
+ userMessage: string;
344
+ }) => string;
345
+ };
331
346
  config: {
332
347
  loadConfig: () => Record<string, unknown>;
333
348
  writeConfigFile: (next: Record<string, unknown>) => Promise<void>;
@@ -644,6 +659,69 @@ declare function installPluginFromPath(params: {
644
659
 
645
660
  declare function buildPluginLoaderAliases(pluginRoot?: string): Record<string, string>;
646
661
 
662
+ type PluginRegisterRuntime = {
663
+ config: Config;
664
+ workspaceDir: string;
665
+ logger: PluginLogger;
666
+ registry: PluginRegistry;
667
+ toolNameOwners: Map<string, string>;
668
+ channelIdOwners: Map<string, string>;
669
+ providerIdOwners: Map<string, string>;
670
+ engineKindOwners: Map<string, string>;
671
+ ncpAgentRuntimeKindOwners: Map<string, string>;
672
+ resolvedToolNames: Set<string>;
673
+ reservedToolNames: Set<string>;
674
+ reservedChannelIds: Set<string>;
675
+ reservedProviderIds: Set<string>;
676
+ reservedEngineKinds: Set<string>;
677
+ reservedNcpAgentRuntimeKinds: Set<string>;
678
+ };
679
+ declare function createPluginRegisterRuntime(params: {
680
+ config: Config;
681
+ workspaceDir: string;
682
+ logger: PluginLogger;
683
+ registry: PluginRegistry;
684
+ reservedToolNames: Set<string>;
685
+ reservedChannelIds: Set<string>;
686
+ reservedProviderIds: Set<string>;
687
+ reservedEngineKinds: Set<string>;
688
+ reservedNcpAgentRuntimeKinds: Set<string>;
689
+ }): PluginRegisterRuntime;
690
+ declare function registerPluginWithApi(params: {
691
+ runtime: PluginRegisterRuntime;
692
+ record: PluginRecord;
693
+ pluginId: string;
694
+ source: string;
695
+ rootDir: string;
696
+ register: (api: OpenClawPluginApi) => void | Promise<void>;
697
+ pluginConfig?: Record<string, unknown>;
698
+ }): {
699
+ ok: true;
700
+ } | {
701
+ ok: false;
702
+ error: string;
703
+ };
704
+
705
+ type ProgressivePluginLoadOptions = {
706
+ config: Config;
707
+ workspaceDir?: string;
708
+ logger?: PluginLogger;
709
+ mode?: "full" | "validate";
710
+ excludeRoots?: string[];
711
+ reservedToolNames?: string[];
712
+ reservedChannelIds?: string[];
713
+ reservedProviderIds?: string[];
714
+ reservedEngineKinds?: string[];
715
+ reservedNcpAgentRuntimeKinds?: string[];
716
+ onPluginProcessed?: (params: {
717
+ loadedPluginCount: number;
718
+ pluginId?: string;
719
+ }) => void;
720
+ yieldToEventLoop?: () => Promise<void>;
721
+ };
722
+
723
+ declare function loadOpenClawPluginsProgressively(options: ProgressivePluginLoadOptions): Promise<PluginRegistry>;
724
+
647
725
  type PluginLoadOptions = {
648
726
  config: Config;
649
727
  workspaceDir?: string;
@@ -724,49 +802,6 @@ declare function createPluginRuntime(params: {
724
802
  config?: Config;
725
803
  }): PluginRuntime;
726
804
 
727
- type PluginRegisterRuntime = {
728
- config: Config;
729
- workspaceDir: string;
730
- logger: PluginLogger;
731
- registry: PluginRegistry;
732
- toolNameOwners: Map<string, string>;
733
- channelIdOwners: Map<string, string>;
734
- providerIdOwners: Map<string, string>;
735
- engineKindOwners: Map<string, string>;
736
- ncpAgentRuntimeKindOwners: Map<string, string>;
737
- resolvedToolNames: Set<string>;
738
- reservedToolNames: Set<string>;
739
- reservedChannelIds: Set<string>;
740
- reservedProviderIds: Set<string>;
741
- reservedEngineKinds: Set<string>;
742
- reservedNcpAgentRuntimeKinds: Set<string>;
743
- };
744
- declare function createPluginRegisterRuntime(params: {
745
- config: Config;
746
- workspaceDir: string;
747
- logger: PluginLogger;
748
- registry: PluginRegistry;
749
- reservedToolNames: Set<string>;
750
- reservedChannelIds: Set<string>;
751
- reservedProviderIds: Set<string>;
752
- reservedEngineKinds: Set<string>;
753
- reservedNcpAgentRuntimeKinds: Set<string>;
754
- }): PluginRegisterRuntime;
755
- declare function registerPluginWithApi(params: {
756
- runtime: PluginRegisterRuntime;
757
- record: PluginRecord;
758
- pluginId: string;
759
- source: string;
760
- rootDir: string;
761
- register: (api: OpenClawPluginApi) => void | Promise<void>;
762
- pluginConfig?: Record<string, unknown>;
763
- }): {
764
- ok: true;
765
- } | {
766
- ok: false;
767
- error: string;
768
- };
769
-
770
805
  declare function validateJsonSchemaValue(params: {
771
806
  schema: Record<string, unknown>;
772
807
  cacheKey: string;
@@ -838,4 +873,4 @@ declare function uninstallPlugin(params: {
838
873
  extensionsDir?: string;
839
874
  }): Promise<UninstallPluginResult>;
840
875
 
841
- 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 };
876
+ 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 ProgressivePluginLoadOptions, 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, loadOpenClawPluginsProgressively, 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
@@ -1204,10 +1204,10 @@ async function installPluginFromPath(params) {
1204
1204
  }
1205
1205
 
1206
1206
  // src/plugins/loader.ts
1207
- import fs6 from "fs";
1208
- import path7 from "path";
1209
- import { createRequire as createRequire2 } from "module";
1210
- import { getWorkspacePathFromConfig } from "@nextclaw/core";
1207
+ import fs7 from "fs";
1208
+ import path8 from "path";
1209
+ import { createRequire as createRequire3 } from "module";
1210
+ import { getWorkspacePathFromConfig as getWorkspacePathFromConfig2 } from "@nextclaw/core";
1211
1211
 
1212
1212
  // src/plugins/bundled-channel-plugin-packages.constants.ts
1213
1213
  var BUNDLED_CHANNEL_PLUGIN_PACKAGES = [
@@ -1576,12 +1576,12 @@ function buildPluginLoaderAliases(pluginRoot) {
1576
1576
  }
1577
1577
 
1578
1578
  // src/plugins/bundled-plugin-loader.ts
1579
- function resolveBundledPluginEntry(require2, packageName, diagnostics, resolvePackageRootFromEntry3) {
1579
+ function resolveBundledPluginEntry(require2, packageName, diagnostics, resolvePackageRootFromEntry4) {
1580
1580
  try {
1581
1581
  const entryFile = require2.resolve(packageName);
1582
1582
  return {
1583
1583
  entryFile,
1584
- rootDir: resolvePackageRootFromEntry3(entryFile)
1584
+ rootDir: resolvePackageRootFromEntry4(entryFile)
1585
1585
  };
1586
1586
  } catch (err) {
1587
1587
  diagnostics.push({
@@ -1611,9 +1611,9 @@ function formatAjvErrors(errors) {
1611
1611
  return ["invalid config"];
1612
1612
  }
1613
1613
  return errors.map((error) => {
1614
- const path10 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
1614
+ const path11 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
1615
1615
  const message = error.message ?? "invalid";
1616
- return `${path10}: ${message}`;
1616
+ return `${path11}: ${message}`;
1617
1617
  });
1618
1618
  }
1619
1619
  function validateJsonSchemaValue(params) {
@@ -1775,6 +1775,13 @@ function registerPluginNcpAgentRuntime(params) {
1775
1775
 
1776
1776
  // src/plugins/runtime.ts
1777
1777
  import { randomUUID as randomUUID2 } from "crypto";
1778
+ import {
1779
+ buildBootstrapAwareUserPrompt,
1780
+ getWorkspacePath,
1781
+ readRequestedSkillsFromMetadata,
1782
+ resolveProviderRuntime,
1783
+ SkillsLoader
1784
+ } from "@nextclaw/core";
1778
1785
  import { getPackageVersion } from "@nextclaw/core";
1779
1786
  import { MemoryGetTool, MemorySearchTool } from "@nextclaw/core";
1780
1787
 
@@ -2318,9 +2325,52 @@ async function dispatchReplyWithFallback(params) {
2318
2325
  }
2319
2326
  await bridge.dispatchReplyWithBufferedBlockDispatcher(params);
2320
2327
  }
2328
+ function createRuntimeUserPromptBuilder(params) {
2329
+ const skillLoaders = /* @__PURE__ */ new Map();
2330
+ return ({ workspace, sessionKey, metadata, userMessage }) => {
2331
+ const resolvedWorkspace = getWorkspacePath(workspace ?? params.defaultWorkspace);
2332
+ let skills = skillLoaders.get(resolvedWorkspace);
2333
+ if (!skills) {
2334
+ skills = new SkillsLoader(resolvedWorkspace);
2335
+ skillLoaders.set(resolvedWorkspace, skills);
2336
+ }
2337
+ return buildBootstrapAwareUserPrompt({
2338
+ workspace: resolvedWorkspace,
2339
+ contextConfig: params.config?.agents?.context,
2340
+ sessionKey,
2341
+ skills,
2342
+ skillNames: readRequestedSkillsFromMetadata(metadata),
2343
+ userMessage
2344
+ });
2345
+ };
2346
+ }
2321
2347
  function createPluginRuntime(params) {
2348
+ const defaultModel = params.config?.agents?.defaults?.model ?? "";
2349
+ const maxToolIterations = Math.max(
2350
+ 0,
2351
+ Math.trunc(params.config?.agents?.defaults?.maxToolIterations ?? 0)
2352
+ );
2353
+ const buildRuntimeUserPrompt = createRuntimeUserPromptBuilder({
2354
+ config: params.config,
2355
+ defaultWorkspace: params.workspace
2356
+ });
2322
2357
  return {
2323
2358
  version: getPackageVersion(),
2359
+ agent: {
2360
+ defaults: {
2361
+ model: defaultModel,
2362
+ workspace: params.workspace,
2363
+ maxToolIterations
2364
+ },
2365
+ resolveWorkspacePath: (workspace) => getWorkspacePath(workspace ?? params.workspace),
2366
+ resolveProviderRuntime: (model) => {
2367
+ if (!params.config) {
2368
+ throw new Error("plugin runtime agent.resolveProviderRuntime requires host config");
2369
+ }
2370
+ return resolveProviderRuntime(params.config, model);
2371
+ },
2372
+ buildRuntimeUserPrompt
2373
+ },
2324
2374
  config: {
2325
2375
  loadConfig: () => loadConfigWithFallback(params.config),
2326
2376
  writeConfigFile: async (next) => writeConfigWithFallback(next)
@@ -2742,16 +2792,31 @@ function registerPluginWithApi(params) {
2742
2792
  }
2743
2793
  }
2744
2794
 
2745
- // src/plugins/loader.ts
2795
+ // src/plugins/loader/progressive-bundled-plugin-loader.ts
2796
+ import { createRequire as createRequire2 } from "module";
2797
+
2798
+ // src/plugins/loader/progressive-plugin-loader-context.ts
2799
+ import fs6 from "fs";
2800
+ import path7 from "path";
2801
+ import { setImmediate as waitForNextTick } from "timers/promises";
2802
+ import { getWorkspacePathFromConfig } from "@nextclaw/core";
2746
2803
  var defaultLogger2 = {
2747
2804
  info: (message) => console.log(message),
2748
2805
  warn: (message) => console.warn(message),
2749
2806
  error: (message) => console.error(message),
2750
2807
  debug: (message) => console.debug(message)
2751
2808
  };
2809
+ var STARTUP_TRACE_ENABLED = process.env.NEXTCLAW_STARTUP_TRACE === "1";
2810
+ function logPluginStartupTrace(step, fields) {
2811
+ if (!STARTUP_TRACE_ENABLED) {
2812
+ return;
2813
+ }
2814
+ const suffix = Object.entries(fields ?? {}).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}=${String(value)}`).join(" ");
2815
+ console.log(`[startup-trace] ${step}${suffix ? ` ${suffix}` : ""}`);
2816
+ }
2752
2817
  function resolvePackageRootFromEntry(entryFile) {
2753
2818
  let cursor = path7.dirname(entryFile);
2754
- for (let i = 0; i < 8; i += 1) {
2819
+ for (let index = 0; index < 8; index += 1) {
2755
2820
  const candidate = path7.join(cursor, "package.json");
2756
2821
  if (fs6.existsSync(candidate)) {
2757
2822
  return cursor;
@@ -2780,14 +2845,552 @@ function resolvePluginModuleExport(moduleExport) {
2780
2845
  }
2781
2846
  return {};
2782
2847
  }
2783
- function appendBundledChannelPlugins(params) {
2848
+ function loadExternalPluginModule(candidateSource, pluginRoot) {
2849
+ const pluginJiti = createPluginJiti(buildPluginLoaderAliases(pluginRoot));
2850
+ return pluginJiti(candidateSource);
2851
+ }
2852
+ function createEmptyPluginRegistry() {
2853
+ return {
2854
+ plugins: [],
2855
+ tools: [],
2856
+ channels: [],
2857
+ providers: [],
2858
+ engines: [],
2859
+ ncpAgentRuntimes: [],
2860
+ diagnostics: [],
2861
+ resolvedTools: []
2862
+ };
2863
+ }
2864
+ function createRegisterRuntimeFromOptions(options, registry, workspaceDir) {
2865
+ const logger = options.logger ?? defaultLogger2;
2866
+ return createPluginRegisterRuntime({
2867
+ config: options.config,
2868
+ workspaceDir,
2869
+ logger,
2870
+ registry,
2871
+ reservedToolNames: new Set(options.reservedToolNames ?? []),
2872
+ reservedChannelIds: new Set(options.reservedChannelIds ?? []),
2873
+ reservedProviderIds: new Set(options.reservedProviderIds ?? []),
2874
+ reservedEngineKinds: new Set((options.reservedEngineKinds ?? ["native"]).map((entry) => entry.toLowerCase())),
2875
+ reservedNcpAgentRuntimeKinds: new Set(
2876
+ (options.reservedNcpAgentRuntimeKinds ?? ["native"]).map((entry) => entry.toLowerCase())
2877
+ )
2878
+ });
2879
+ }
2880
+ function createProgressivePluginLoadContext(options) {
2881
+ const workspaceDir = options.workspaceDir?.trim() || getWorkspacePathFromConfig(options.config);
2882
+ const normalizedConfig = normalizePluginsConfig(options.config.plugins);
2883
+ const registry = createEmptyPluginRegistry();
2884
+ return {
2885
+ options,
2886
+ workspaceDir,
2887
+ normalizedConfig,
2888
+ mode: options.mode ?? "full",
2889
+ registry,
2890
+ registerRuntime: createRegisterRuntimeFromOptions(options, registry, workspaceDir),
2891
+ tracker: {
2892
+ loadedPluginCount: 0,
2893
+ onPluginProcessed: options.onPluginProcessed,
2894
+ yieldToEventLoop: options.yieldToEventLoop ?? (() => waitForNextTick())
2895
+ }
2896
+ };
2897
+ }
2898
+ async function markPluginProcessed(tracker, pluginId) {
2899
+ tracker.loadedPluginCount += 1;
2900
+ tracker.onPluginProcessed?.({
2901
+ loadedPluginCount: tracker.loadedPluginCount,
2902
+ ...pluginId ? { pluginId } : {}
2903
+ });
2904
+ await tracker.yieldToEventLoop();
2905
+ }
2906
+
2907
+ // src/plugins/loader/progressive-bundled-plugin-loader.ts
2908
+ function pushBundledPluginLoadError(registry, entryFile, error) {
2909
+ registry.diagnostics.push({
2910
+ level: "error",
2911
+ source: entryFile,
2912
+ message: `failed to load bundled plugin: ${String(error)}`
2913
+ });
2914
+ }
2915
+ function buildBundledPluginRecord(params) {
2916
+ return createPluginRecord({
2917
+ id: params.pluginId,
2918
+ name: params.definition?.name ?? params.pluginId,
2919
+ description: params.definition?.description,
2920
+ version: params.definition?.version,
2921
+ kind: params.definition?.kind,
2922
+ source: params.entryFile,
2923
+ origin: "bundled",
2924
+ workspaceDir: params.context.registerRuntime.workspaceDir,
2925
+ enabled: true,
2926
+ configSchema: Boolean(params.definition?.configSchema),
2927
+ configJsonSchema: params.definition?.configSchema
2928
+ });
2929
+ }
2930
+ function disableBundledPluginRecord(record, reason) {
2931
+ record.status = "disabled";
2932
+ record.error = reason;
2933
+ return record;
2934
+ }
2935
+ function markBundledPluginError(params) {
2936
+ params.record.status = "error";
2937
+ params.record.error = params.message;
2938
+ params.registry.diagnostics.push({
2939
+ level: "error",
2940
+ pluginId: params.pluginId,
2941
+ source: params.entryFile,
2942
+ message: params.message
2943
+ });
2944
+ return params.record;
2945
+ }
2946
+ function finalizeBundledPluginRecord(params) {
2947
+ if (params.record) {
2948
+ params.context.registry.plugins.push(params.record);
2949
+ }
2950
+ logPluginStartupTrace("plugin.loader.bundled_plugin", {
2951
+ package: params.packageName,
2952
+ plugin_id: params.pluginId,
2953
+ duration_ms: Date.now() - params.packageStartedAt
2954
+ });
2955
+ }
2956
+ function resolveBundledPluginRegistrationCandidate(params) {
2957
+ const resolvedEntry = resolveBundledPluginEntry(
2958
+ params.require,
2959
+ params.packageName,
2960
+ params.context.registry.diagnostics,
2961
+ resolvePackageRootFromEntry
2962
+ );
2963
+ if (!resolvedEntry) {
2964
+ return { done: true };
2965
+ }
2966
+ const { entryFile, rootDir } = resolvedEntry;
2967
+ let loadedModule;
2968
+ try {
2969
+ loadedModule = loadBundledPluginModule(entryFile, rootDir);
2970
+ } catch (error) {
2971
+ pushBundledPluginLoadError(params.context.registry, entryFile, error);
2972
+ return { done: true };
2973
+ }
2974
+ const resolved = resolvePluginModuleExport(loadedModule);
2975
+ const pluginId = typeof resolved.definition?.id === "string" ? resolved.definition.id.trim() : "";
2976
+ if (!pluginId) {
2977
+ params.context.registry.diagnostics.push({
2978
+ level: "error",
2979
+ source: entryFile,
2980
+ message: "bundled plugin definition missing id"
2981
+ });
2982
+ return { done: true };
2983
+ }
2984
+ const enableState = resolveEnableState(pluginId, params.context.normalizedConfig);
2985
+ const record = buildBundledPluginRecord({
2986
+ pluginId,
2987
+ definition: resolved.definition,
2988
+ entryFile,
2989
+ context: params.context
2990
+ });
2991
+ if (!enableState.enabled) {
2992
+ finalizeBundledPluginRecord({
2993
+ packageName: params.packageName,
2994
+ pluginId,
2995
+ record: disableBundledPluginRecord(record, enableState.reason ?? "disabled"),
2996
+ context: params.context,
2997
+ packageStartedAt: params.packageStartedAt
2998
+ });
2999
+ return { done: true, pluginId };
3000
+ }
3001
+ if (typeof resolved.register !== "function") {
3002
+ finalizeBundledPluginRecord({
3003
+ packageName: params.packageName,
3004
+ pluginId,
3005
+ record: markBundledPluginError({
3006
+ record,
3007
+ registry: params.context.registry,
3008
+ pluginId,
3009
+ entryFile,
3010
+ message: "plugin export missing register/activate"
3011
+ }),
3012
+ context: params.context,
3013
+ packageStartedAt: params.packageStartedAt
3014
+ });
3015
+ return { done: true, pluginId };
3016
+ }
3017
+ return {
3018
+ done: false,
3019
+ entryFile,
3020
+ rootDir,
3021
+ pluginId,
3022
+ record,
3023
+ register: resolved.register
3024
+ };
3025
+ }
3026
+ async function processBundledPluginPackage(context, require2, packageName) {
3027
+ const packageStartedAt = Date.now();
3028
+ const candidate = resolveBundledPluginRegistrationCandidate({
3029
+ context,
3030
+ require: require2,
3031
+ packageName,
3032
+ packageStartedAt
3033
+ });
3034
+ if (candidate.done) {
3035
+ await markPluginProcessed(context.tracker, candidate.pluginId);
3036
+ return;
3037
+ }
3038
+ const result = registerPluginWithApi({
3039
+ runtime: context.registerRuntime,
3040
+ record: candidate.record,
3041
+ pluginId: candidate.pluginId,
3042
+ source: candidate.entryFile,
3043
+ rootDir: candidate.rootDir,
3044
+ register: candidate.register,
3045
+ pluginConfig: void 0
3046
+ });
3047
+ if (!result.ok) {
3048
+ markBundledPluginError({
3049
+ record: candidate.record,
3050
+ registry: context.registry,
3051
+ pluginId: candidate.pluginId,
3052
+ entryFile: candidate.entryFile,
3053
+ message: result.error
3054
+ });
3055
+ }
3056
+ finalizeBundledPluginRecord({
3057
+ packageName,
3058
+ pluginId: candidate.pluginId,
3059
+ record: candidate.record,
3060
+ context,
3061
+ packageStartedAt
3062
+ });
3063
+ await markPluginProcessed(context.tracker, candidate.pluginId);
3064
+ }
3065
+ async function appendBundledChannelPluginsProgressively(context) {
2784
3066
  const require2 = createRequire2(import.meta.url);
2785
3067
  for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
3068
+ await processBundledPluginPackage(context, require2, packageName);
3069
+ }
3070
+ }
3071
+
3072
+ // src/plugins/loader/progressive-external-plugin-loader.ts
3073
+ function createManifestPluginRecord(manifest, candidate, enabled) {
3074
+ return createPluginRecord({
3075
+ id: manifest.id,
3076
+ name: manifest.name ?? manifest.id,
3077
+ description: manifest.description,
3078
+ version: manifest.version,
3079
+ kind: manifest.kind,
3080
+ source: candidate.source,
3081
+ origin: candidate.origin,
3082
+ workspaceDir: candidate.workspaceDir,
3083
+ enabled,
3084
+ configSchema: Boolean(manifest.configSchema),
3085
+ configUiHints: manifest.configUiHints,
3086
+ configJsonSchema: manifest.configSchema
3087
+ });
3088
+ }
3089
+ async function finalizeExternalPluginRecord(params) {
3090
+ params.context.registry.plugins.push(params.record);
3091
+ if (params.pluginId && params.seenIds && params.origin) {
3092
+ params.seenIds.set(params.pluginId, params.origin);
3093
+ }
3094
+ await markPluginProcessed(params.context.tracker, params.pluginId);
3095
+ }
3096
+ async function finalizeExternalPluginError(params) {
3097
+ params.record.status = "error";
3098
+ params.record.error = params.message;
3099
+ params.context.registry.diagnostics.push({
3100
+ level: "error",
3101
+ pluginId: params.pluginId,
3102
+ source: params.candidate.source,
3103
+ message: params.message
3104
+ });
3105
+ await finalizeExternalPluginRecord({
3106
+ context: params.context,
3107
+ record: params.record,
3108
+ pluginId: params.pluginId,
3109
+ seenIds: params.seenIds,
3110
+ origin: params.candidate.origin
3111
+ });
3112
+ }
3113
+ async function finalizeDisabledExternalPlugin(params) {
3114
+ params.record.status = "disabled";
3115
+ params.record.error = params.reason;
3116
+ await finalizeExternalPluginRecord({
3117
+ context: params.context,
3118
+ record: params.record,
3119
+ pluginId: params.pluginId,
3120
+ seenIds: params.seenIds,
3121
+ origin: params.candidate.origin
3122
+ });
3123
+ }
3124
+ function applyDefinitionMetadata(record, definition) {
3125
+ record.name = definition?.name ?? record.name;
3126
+ record.description = definition?.description ?? record.description;
3127
+ record.version = definition?.version ?? record.version;
3128
+ record.kind = definition?.kind ?? record.kind;
3129
+ }
3130
+ function loadExternalPluginDefinition(params) {
3131
+ const moduleLoadStartedAt = Date.now();
3132
+ const loadedModule = loadExternalPluginModule(params.candidate.source, params.candidate.rootDir);
3133
+ logPluginStartupTrace("plugin.loader.external_module_loaded", {
3134
+ plugin_id: params.pluginId,
3135
+ duration_ms: Date.now() - moduleLoadStartedAt,
3136
+ source: params.candidate.source
3137
+ });
3138
+ return resolvePluginModuleExport(loadedModule);
3139
+ }
3140
+ function pushDefinitionMismatchWarning(context, candidate, pluginId, definitionId) {
3141
+ if (!definitionId || definitionId === pluginId) {
3142
+ return;
3143
+ }
3144
+ context.registry.diagnostics.push({
3145
+ level: "warn",
3146
+ pluginId,
3147
+ source: candidate.source,
3148
+ message: `plugin id mismatch (manifest uses "${pluginId}", export uses "${definitionId}")`
3149
+ });
3150
+ }
3151
+ async function loadAndRegisterExternalPlugin(params) {
3152
+ let resolved;
3153
+ try {
3154
+ resolved = loadExternalPluginDefinition({
3155
+ context: params.context,
3156
+ candidate: params.candidate,
3157
+ pluginId: params.pluginId
3158
+ });
3159
+ } catch (error) {
3160
+ await finalizeExternalPluginError({
3161
+ context: params.context,
3162
+ record: params.record,
3163
+ candidate: params.candidate,
3164
+ pluginId: params.pluginId,
3165
+ seenIds: params.seenIds,
3166
+ message: `failed to load plugin: ${String(error)}`
3167
+ });
3168
+ return;
3169
+ }
3170
+ pushDefinitionMismatchWarning(params.context, params.candidate, params.pluginId, resolved.definition?.id);
3171
+ applyDefinitionMetadata(params.record, resolved.definition);
3172
+ if (typeof resolved.register !== "function") {
3173
+ await finalizeExternalPluginError({
3174
+ context: params.context,
3175
+ record: params.record,
3176
+ candidate: params.candidate,
3177
+ pluginId: params.pluginId,
3178
+ seenIds: params.seenIds,
3179
+ message: "plugin export missing register/activate"
3180
+ });
3181
+ return;
3182
+ }
3183
+ const registerResult = registerPluginWithApi({
3184
+ runtime: params.context.registerRuntime,
3185
+ record: params.record,
3186
+ pluginId: params.pluginId,
3187
+ source: params.candidate.source,
3188
+ rootDir: params.candidate.rootDir,
3189
+ register: resolved.register,
3190
+ pluginConfig: params.validatedConfig.value
3191
+ });
3192
+ logPluginStartupTrace("plugin.loader.external_plugin_registered", {
3193
+ plugin_id: params.pluginId,
3194
+ duration_ms: Date.now() - params.candidateStartedAt,
3195
+ source: params.candidate.source
3196
+ });
3197
+ if (!registerResult.ok) {
3198
+ await finalizeExternalPluginError({
3199
+ context: params.context,
3200
+ record: params.record,
3201
+ candidate: params.candidate,
3202
+ pluginId: params.pluginId,
3203
+ seenIds: params.seenIds,
3204
+ message: registerResult.error
3205
+ });
3206
+ return;
3207
+ }
3208
+ await finalizeExternalPluginRecord({
3209
+ context: params.context,
3210
+ record: params.record,
3211
+ pluginId: params.pluginId,
3212
+ seenIds: params.seenIds,
3213
+ origin: params.candidate.origin
3214
+ });
3215
+ }
3216
+ async function processExternalPluginCandidate(params) {
3217
+ const candidateStartedAt = Date.now();
3218
+ const pluginId = params.manifest.id;
3219
+ const existingOrigin = params.seenIds.get(pluginId);
3220
+ if (existingOrigin) {
3221
+ const overriddenRecord = createManifestPluginRecord(params.manifest, params.candidate, false);
3222
+ overriddenRecord.status = "disabled";
3223
+ overriddenRecord.error = `overridden by ${existingOrigin} plugin`;
3224
+ await finalizeExternalPluginRecord({
3225
+ context: params.context,
3226
+ record: overriddenRecord,
3227
+ pluginId
3228
+ });
3229
+ return;
3230
+ }
3231
+ const enableState = resolveEnableState(pluginId, params.context.normalizedConfig);
3232
+ const record = createManifestPluginRecord(params.manifest, params.candidate, enableState.enabled);
3233
+ if (!enableState.enabled) {
3234
+ await finalizeDisabledExternalPlugin({
3235
+ context: params.context,
3236
+ record,
3237
+ candidate: params.candidate,
3238
+ pluginId,
3239
+ seenIds: params.seenIds,
3240
+ reason: enableState.reason ?? "disabled"
3241
+ });
3242
+ return;
3243
+ }
3244
+ if (!params.manifest.configSchema) {
3245
+ await finalizeExternalPluginError({
3246
+ context: params.context,
3247
+ record,
3248
+ candidate: params.candidate,
3249
+ pluginId,
3250
+ seenIds: params.seenIds,
3251
+ message: "missing config schema"
3252
+ });
3253
+ return;
3254
+ }
3255
+ const validatedConfig = validatePluginConfig({
3256
+ schema: params.manifest.configSchema,
3257
+ cacheKey: params.manifest.schemaCacheKey,
3258
+ value: params.context.normalizedConfig.entries[pluginId]?.config
3259
+ });
3260
+ if (!validatedConfig.ok) {
3261
+ await finalizeExternalPluginError({
3262
+ context: params.context,
3263
+ record,
3264
+ candidate: params.candidate,
3265
+ pluginId,
3266
+ seenIds: params.seenIds,
3267
+ message: `invalid config: ${validatedConfig.errors.join(", ")}`
3268
+ });
3269
+ return;
3270
+ }
3271
+ if (params.context.mode === "validate") {
3272
+ await finalizeExternalPluginRecord({
3273
+ context: params.context,
3274
+ record,
3275
+ pluginId,
3276
+ seenIds: params.seenIds,
3277
+ origin: params.candidate.origin
3278
+ });
3279
+ return;
3280
+ }
3281
+ await loadAndRegisterExternalPlugin({
3282
+ context: params.context,
3283
+ candidate: params.candidate,
3284
+ record,
3285
+ pluginId,
3286
+ seenIds: params.seenIds,
3287
+ validatedConfig,
3288
+ candidateStartedAt
3289
+ });
3290
+ }
3291
+ async function appendExternalPluginsProgressively(context) {
3292
+ const discovery = discoverOpenClawPlugins({
3293
+ config: context.options.config,
3294
+ workspaceDir: context.workspaceDir,
3295
+ extraPaths: context.normalizedConfig.loadPaths
3296
+ });
3297
+ const filteredCandidates = filterPluginCandidatesByExcludedRoots(discovery.candidates, context.options.excludeRoots ?? []);
3298
+ const manifestRegistry = loadPluginManifestRegistry({
3299
+ config: context.options.config,
3300
+ workspaceDir: context.workspaceDir,
3301
+ candidates: filteredCandidates,
3302
+ diagnostics: discovery.diagnostics
3303
+ });
3304
+ context.registry.diagnostics.push(...manifestRegistry.diagnostics);
3305
+ const manifestByRoot = new Map(manifestRegistry.plugins.map((entry) => [entry.rootDir, entry]));
3306
+ const seenIds = new Map(
3307
+ context.registry.plugins.map((entry) => [entry.id, entry.origin])
3308
+ );
3309
+ for (const candidate of filteredCandidates) {
3310
+ const manifest = manifestByRoot.get(candidate.rootDir);
3311
+ if (!manifest) {
3312
+ await markPluginProcessed(context.tracker);
3313
+ continue;
3314
+ }
3315
+ await processExternalPluginCandidate({
3316
+ context,
3317
+ candidate,
3318
+ manifest,
3319
+ seenIds
3320
+ });
3321
+ }
3322
+ }
3323
+
3324
+ // src/plugins/loader/progressive-plugin-loader.ts
3325
+ async function loadOpenClawPluginsProgressively(options) {
3326
+ const startedAt = Date.now();
3327
+ const context = createProgressivePluginLoadContext(options);
3328
+ await appendBundledChannelPluginsProgressively(context);
3329
+ if (process.env.NEXTCLAW_ENABLE_OPENCLAW_PLUGINS !== "0") {
3330
+ await appendExternalPluginsProgressively(context);
3331
+ }
3332
+ logPluginStartupTrace("plugin.loader.total", {
3333
+ duration_ms: Date.now() - startedAt,
3334
+ plugin_count: context.registry.plugins.length
3335
+ });
3336
+ return context.registry;
3337
+ }
3338
+
3339
+ // src/plugins/loader.ts
3340
+ var defaultLogger3 = {
3341
+ info: (message) => console.log(message),
3342
+ warn: (message) => console.warn(message),
3343
+ error: (message) => console.error(message),
3344
+ debug: (message) => console.debug(message)
3345
+ };
3346
+ var STARTUP_TRACE_ENABLED2 = process.env.NEXTCLAW_STARTUP_TRACE === "1";
3347
+ function logPluginStartupTrace2(step, fields) {
3348
+ if (!STARTUP_TRACE_ENABLED2) {
3349
+ return;
3350
+ }
3351
+ const suffix = Object.entries(fields ?? {}).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}=${String(value)}`).join(" ");
3352
+ console.log(`[startup-trace] ${step}${suffix ? ` ${suffix}` : ""}`);
3353
+ }
3354
+ function resolvePackageRootFromEntry2(entryFile) {
3355
+ let cursor = path8.dirname(entryFile);
3356
+ for (let i = 0; i < 8; i += 1) {
3357
+ const candidate = path8.join(cursor, "package.json");
3358
+ if (fs7.existsSync(candidate)) {
3359
+ return cursor;
3360
+ }
3361
+ const parent = path8.dirname(cursor);
3362
+ if (parent === cursor) {
3363
+ break;
3364
+ }
3365
+ cursor = parent;
3366
+ }
3367
+ return path8.dirname(entryFile);
3368
+ }
3369
+ function resolvePluginModuleExport2(moduleExport) {
3370
+ const resolved = moduleExport && typeof moduleExport === "object" && "default" in moduleExport ? moduleExport.default : moduleExport;
3371
+ if (typeof resolved === "function") {
3372
+ return {
3373
+ register: resolved
3374
+ };
3375
+ }
3376
+ if (resolved && typeof resolved === "object") {
3377
+ const definition = resolved;
3378
+ return {
3379
+ definition,
3380
+ register: definition.register ?? definition.activate
3381
+ };
3382
+ }
3383
+ return {};
3384
+ }
3385
+ function appendBundledChannelPlugins(params) {
3386
+ const require2 = createRequire3(import.meta.url);
3387
+ for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
3388
+ const packageStartedAt = Date.now();
2786
3389
  const resolvedEntry = resolveBundledPluginEntry(
2787
3390
  require2,
2788
3391
  packageName,
2789
3392
  params.registry.diagnostics,
2790
- resolvePackageRootFromEntry
3393
+ resolvePackageRootFromEntry2
2791
3394
  );
2792
3395
  if (!resolvedEntry) {
2793
3396
  continue;
@@ -2804,7 +3407,7 @@ function appendBundledChannelPlugins(params) {
2804
3407
  });
2805
3408
  continue;
2806
3409
  }
2807
- const resolved = resolvePluginModuleExport(moduleExport);
3410
+ const resolved = resolvePluginModuleExport2(moduleExport);
2808
3411
  const definition = resolved.definition;
2809
3412
  const register = resolved.register;
2810
3413
  const pluginId = typeof definition?.id === "string" ? definition.id.trim() : "";
@@ -2869,16 +3472,22 @@ function appendBundledChannelPlugins(params) {
2869
3472
  });
2870
3473
  }
2871
3474
  params.registry.plugins.push(record);
3475
+ logPluginStartupTrace2("plugin.loader.bundled_plugin", {
3476
+ package: packageName,
3477
+ plugin_id: pluginId,
3478
+ duration_ms: Date.now() - packageStartedAt
3479
+ });
2872
3480
  }
2873
3481
  }
2874
- function loadExternalPluginModule(candidateSource, pluginRoot) {
3482
+ function loadExternalPluginModule2(candidateSource, pluginRoot) {
2875
3483
  const pluginJiti = createPluginJiti(buildPluginLoaderAliases(pluginRoot));
2876
3484
  return pluginJiti(candidateSource);
2877
3485
  }
2878
3486
  function loadOpenClawPlugins(options) {
3487
+ const startedAt = Date.now();
2879
3488
  const loadExternalPlugins = process.env.NEXTCLAW_ENABLE_OPENCLAW_PLUGINS !== "0";
2880
- const logger = options.logger ?? defaultLogger2;
2881
- const workspaceDir = options.workspaceDir?.trim() || getWorkspacePathFromConfig(options.config);
3489
+ const logger = options.logger ?? defaultLogger3;
3490
+ const workspaceDir = options.workspaceDir?.trim() || getWorkspacePathFromConfig2(options.config);
2882
3491
  const normalized = normalizePluginsConfig(options.config.plugins);
2883
3492
  const mode = options.mode ?? "full";
2884
3493
  const registry = {
@@ -2935,6 +3544,7 @@ function loadOpenClawPlugins(options) {
2935
3544
  registry.plugins.map((entry) => [entry.id, entry.origin])
2936
3545
  );
2937
3546
  for (const candidate of filteredCandidates) {
3547
+ const candidateStartedAt = Date.now();
2938
3548
  const manifest = manifestByRoot.get(candidate.rootDir);
2939
3549
  if (!manifest) {
2940
3550
  continue;
@@ -3022,7 +3632,13 @@ function loadOpenClawPlugins(options) {
3022
3632
  }
3023
3633
  let moduleExport = null;
3024
3634
  try {
3025
- moduleExport = loadExternalPluginModule(candidate.source, candidate.rootDir);
3635
+ const moduleLoadStartedAt = Date.now();
3636
+ moduleExport = loadExternalPluginModule2(candidate.source, candidate.rootDir);
3637
+ logPluginStartupTrace2("plugin.loader.external_module_loaded", {
3638
+ plugin_id: pluginId,
3639
+ duration_ms: Date.now() - moduleLoadStartedAt,
3640
+ source: candidate.source
3641
+ });
3026
3642
  } catch (err) {
3027
3643
  record.status = "error";
3028
3644
  record.error = `failed to load plugin: ${String(err)}`;
@@ -3036,7 +3652,7 @@ function loadOpenClawPlugins(options) {
3036
3652
  });
3037
3653
  continue;
3038
3654
  }
3039
- const resolved = resolvePluginModuleExport(moduleExport);
3655
+ const resolved = resolvePluginModuleExport2(moduleExport);
3040
3656
  const definition = resolved.definition;
3041
3657
  const register = resolved.register;
3042
3658
  if (definition?.id && definition.id !== pluginId) {
@@ -3073,6 +3689,11 @@ function loadOpenClawPlugins(options) {
3073
3689
  register,
3074
3690
  pluginConfig: validatedConfig.value
3075
3691
  });
3692
+ logPluginStartupTrace2("plugin.loader.external_plugin_registered", {
3693
+ plugin_id: pluginId,
3694
+ duration_ms: Date.now() - candidateStartedAt,
3695
+ source: candidate.source
3696
+ });
3076
3697
  if (!registerResult.ok) {
3077
3698
  record.status = "error";
3078
3699
  record.error = registerResult.error;
@@ -3089,15 +3710,19 @@ function loadOpenClawPlugins(options) {
3089
3710
  registry.plugins.push(record);
3090
3711
  seenIds.set(pluginId, candidate.origin);
3091
3712
  }
3713
+ logPluginStartupTrace2("plugin.loader.total", {
3714
+ duration_ms: Date.now() - startedAt,
3715
+ plugin_count: registry.plugins.length
3716
+ });
3092
3717
  return registry;
3093
3718
  }
3094
3719
 
3095
3720
  // src/plugins/status.ts
3096
- import fs7 from "fs";
3097
- import { createRequire as createRequire3 } from "module";
3098
- import path8 from "path";
3099
- import { getWorkspacePathFromConfig as getWorkspacePathFromConfig2 } from "@nextclaw/core";
3100
- function createEmptyPluginRegistry() {
3721
+ import fs8 from "fs";
3722
+ import { createRequire as createRequire4 } from "module";
3723
+ import path9 from "path";
3724
+ import { getWorkspacePathFromConfig as getWorkspacePathFromConfig3 } from "@nextclaw/core";
3725
+ function createEmptyPluginRegistry2() {
3101
3726
  return {
3102
3727
  plugins: [],
3103
3728
  tools: [],
@@ -3109,23 +3734,23 @@ function createEmptyPluginRegistry() {
3109
3734
  resolvedTools: []
3110
3735
  };
3111
3736
  }
3112
- function resolvePackageRootFromEntry2(entryFile) {
3113
- let cursor = path8.dirname(entryFile);
3737
+ function resolvePackageRootFromEntry3(entryFile) {
3738
+ let cursor = path9.dirname(entryFile);
3114
3739
  for (let index = 0; index < 8; index += 1) {
3115
- const candidate = path8.join(cursor, "package.json");
3116
- if (fs7.existsSync(candidate)) {
3740
+ const candidate = path9.join(cursor, "package.json");
3741
+ if (fs8.existsSync(candidate)) {
3117
3742
  return cursor;
3118
3743
  }
3119
- const parent = path8.dirname(cursor);
3744
+ const parent = path9.dirname(cursor);
3120
3745
  if (parent === cursor) {
3121
3746
  break;
3122
3747
  }
3123
3748
  cursor = parent;
3124
3749
  }
3125
- return path8.dirname(entryFile);
3750
+ return path9.dirname(entryFile);
3126
3751
  }
3127
3752
  function discoverBundledPluginCandidates(workspaceDir, diagnostics) {
3128
- const require2 = createRequire3(import.meta.url);
3753
+ const require2 = createRequire4(import.meta.url);
3129
3754
  const candidates = [];
3130
3755
  for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
3131
3756
  try {
@@ -3133,7 +3758,7 @@ function discoverBundledPluginCandidates(workspaceDir, diagnostics) {
3133
3758
  candidates.push({
3134
3759
  idHint: packageName.split("/").pop() ?? packageName,
3135
3760
  source: entryFile,
3136
- rootDir: resolvePackageRootFromEntry2(entryFile),
3761
+ rootDir: resolvePackageRootFromEntry3(entryFile),
3137
3762
  origin: "bundled",
3138
3763
  workspaceDir,
3139
3764
  packageName
@@ -3215,7 +3840,7 @@ function finalizeDiscoveredManifestRecord(params) {
3215
3840
  };
3216
3841
  }
3217
3842
  function discoverPluginStatusReport(params) {
3218
- const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig2(params.config);
3843
+ const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig3(params.config);
3219
3844
  const normalized = normalizePluginsConfig(params.config.plugins);
3220
3845
  const discovery = discoverOpenClawPlugins({
3221
3846
  config: params.config,
@@ -3230,7 +3855,7 @@ function discoverPluginStatusReport(params) {
3230
3855
  candidates: [...bundledCandidates, ...discovery.candidates],
3231
3856
  diagnostics: [...bundledDiagnostics, ...discovery.diagnostics]
3232
3857
  });
3233
- const registry = createEmptyPluginRegistry();
3858
+ const registry = createEmptyPluginRegistry2();
3234
3859
  const seenIds = /* @__PURE__ */ new Map();
3235
3860
  registry.diagnostics.push(...manifestRegistry.diagnostics);
3236
3861
  for (const manifest of manifestRegistry.plugins) {
@@ -3256,7 +3881,7 @@ function discoverPluginStatusReport(params) {
3256
3881
  };
3257
3882
  }
3258
3883
  function buildPluginStatusReport(params) {
3259
- const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig2(params.config);
3884
+ const workspaceDir = params.workspaceDir?.trim() || getWorkspacePathFromConfig3(params.config);
3260
3885
  const registry = loadOpenClawPlugins({
3261
3886
  config: params.config,
3262
3887
  workspaceDir,
@@ -3274,10 +3899,10 @@ function buildPluginStatusReport(params) {
3274
3899
  }
3275
3900
 
3276
3901
  // src/plugins/uninstall.ts
3277
- import fs8 from "fs/promises";
3902
+ import fs9 from "fs/promises";
3278
3903
  import { existsSync as existsSync2, statSync } from "fs";
3279
- import path9 from "path";
3280
- import { getWorkspacePathFromConfig as getWorkspacePathFromConfig3 } from "@nextclaw/core";
3904
+ import path10 from "path";
3905
+ import { getWorkspacePathFromConfig as getWorkspacePathFromConfig4 } from "@nextclaw/core";
3281
3906
  function isLinkedPathInstall(record) {
3282
3907
  if (!record || record.source !== "path") {
3283
3908
  return false;
@@ -3285,13 +3910,13 @@ function isLinkedPathInstall(record) {
3285
3910
  if (!record.sourcePath || !record.installPath) {
3286
3911
  return true;
3287
3912
  }
3288
- return path9.resolve(record.sourcePath) === path9.resolve(record.installPath);
3913
+ return path10.resolve(record.sourcePath) === path10.resolve(record.installPath);
3289
3914
  }
3290
3915
  function pushUniquePath(targets, candidate) {
3291
3916
  if (!candidate) {
3292
3917
  return;
3293
3918
  }
3294
- const resolved = path9.resolve(candidate);
3919
+ const resolved = path10.resolve(candidate);
3295
3920
  if (!targets.includes(resolved)) {
3296
3921
  targets.push(resolved);
3297
3922
  }
@@ -3313,7 +3938,7 @@ function resolveUninstallDirectoryTarget(params) {
3313
3938
  if (!configuredPath) {
3314
3939
  return defaultPath;
3315
3940
  }
3316
- if (path9.resolve(configuredPath) === path9.resolve(defaultPath)) {
3941
+ if (path10.resolve(configuredPath) === path10.resolve(defaultPath)) {
3317
3942
  return configuredPath;
3318
3943
  }
3319
3944
  return defaultPath;
@@ -3333,8 +3958,8 @@ function resolveUninstallDirectoryTargets(params) {
3333
3958
  })
3334
3959
  );
3335
3960
  pushUniquePath(targets, params.installRecord?.installPath);
3336
- const workspaceDir = getWorkspacePathFromConfig3(params.config);
3337
- pushUniquePath(targets, path9.join(workspaceDir, ".nextclaw", "extensions", params.pluginId));
3961
+ const workspaceDir = getWorkspacePathFromConfig4(params.config);
3962
+ pushUniquePath(targets, path10.join(workspaceDir, ".nextclaw", "extensions", params.pluginId));
3338
3963
  return targets;
3339
3964
  }
3340
3965
  function removePluginFromConfig(config, pluginId) {
@@ -3415,13 +4040,13 @@ function matchesPluginLoadPath(rawPath, pluginId) {
3415
4040
  if (!normalizedPath) {
3416
4041
  return false;
3417
4042
  }
3418
- const resolvedPath = path9.resolve(normalizedPath);
4043
+ const resolvedPath = path10.resolve(normalizedPath);
3419
4044
  if (!existsSync2(resolvedPath)) {
3420
4045
  return false;
3421
4046
  }
3422
4047
  const candidateRoot = (() => {
3423
4048
  try {
3424
- return statSync(resolvedPath).isDirectory() ? resolvedPath : path9.dirname(resolvedPath);
4049
+ return statSync(resolvedPath).isDirectory() ? resolvedPath : path10.dirname(resolvedPath);
3425
4050
  } catch {
3426
4051
  return null;
3427
4052
  }
@@ -3455,9 +4080,9 @@ async function uninstallPlugin(params) {
3455
4080
  extensionsDir
3456
4081
  }) : [];
3457
4082
  for (const deleteTarget of deleteTargets) {
3458
- const existed = await fs8.access(deleteTarget).then(() => true).catch(() => false);
4083
+ const existed = await fs9.access(deleteTarget).then(() => true).catch(() => false);
3459
4084
  try {
3460
- await fs8.rm(deleteTarget, { recursive: true, force: true });
4085
+ await fs9.rm(deleteTarget, { recursive: true, force: true });
3461
4086
  actions.directory = actions.directory || existed;
3462
4087
  } catch (error) {
3463
4088
  warnings.push(
@@ -3500,6 +4125,7 @@ export {
3500
4125
  installPluginFromNpmSpec,
3501
4126
  installPluginFromPath,
3502
4127
  loadOpenClawPlugins,
4128
+ loadOpenClawPluginsProgressively,
3503
4129
  loadPluginManifest,
3504
4130
  loadPluginManifestRegistry,
3505
4131
  loadPluginUiMetadata,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/openclaw-compat",
3
- "version": "0.3.34",
3
+ "version": "0.3.36",
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.17",
23
- "@nextclaw/channel-plugin-discord": "0.2.17",
24
- "@nextclaw/channel-plugin-email": "0.2.17",
25
- "@nextclaw/channel-plugin-feishu": "0.2.21",
26
- "@nextclaw/channel-plugin-mochat": "0.2.17",
27
- "@nextclaw/channel-plugin-qq": "0.2.17",
28
- "@nextclaw/channel-plugin-slack": "0.2.17",
29
- "@nextclaw/channel-plugin-telegram": "0.2.17",
30
- "@nextclaw/channel-plugin-weixin": "0.1.10",
31
- "@nextclaw/channel-plugin-wecom": "0.2.17",
32
- "@nextclaw/channel-plugin-whatsapp": "0.2.17",
33
- "@nextclaw/channel-runtime": "0.4.3",
34
- "@nextclaw/core": "0.11.2",
22
+ "@nextclaw/channel-plugin-dingtalk": "0.2.18",
23
+ "@nextclaw/channel-plugin-discord": "0.2.18",
24
+ "@nextclaw/channel-plugin-email": "0.2.18",
25
+ "@nextclaw/channel-plugin-mochat": "0.2.18",
26
+ "@nextclaw/channel-plugin-qq": "0.2.18",
27
+ "@nextclaw/channel-plugin-slack": "0.2.18",
28
+ "@nextclaw/channel-plugin-telegram": "0.2.18",
29
+ "@nextclaw/channel-plugin-weixin": "0.1.11",
30
+ "@nextclaw/channel-runtime": "0.4.4",
31
+ "@nextclaw/core": "0.11.3",
32
+ "@nextclaw/ncp-toolkit": "0.4.4",
35
33
  "@nextclaw/ncp": "0.4.0",
36
- "@nextclaw/ncp-toolkit": "0.4.4"
34
+ "@nextclaw/channel-plugin-feishu": "0.2.21",
35
+ "@nextclaw/channel-plugin-whatsapp": "0.2.18",
36
+ "@nextclaw/channel-plugin-wecom": "0.2.18"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^20.17.6",