nextclaw 0.18.4 → 0.18.6

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 (41) hide show
  1. package/dist/cli/app/index.js +87 -372
  2. package/package.json +6 -6
  3. package/ui-dist/assets/{api-DnPN4SyA.js → api-C51456xV.js} +1 -1
  4. package/ui-dist/assets/{app-manager-provider-M7TngYxx.js → app-manager-provider-D_cKqqRG.js} +1 -1
  5. package/ui-dist/assets/{app-navigation.config-B5YIdRju.js → app-navigation.config-Dve1W20Y.js} +1 -1
  6. package/ui-dist/assets/{channels-list-page-Cm-Bbu6u.js → channels-list-page-WJ7d4zMI.js} +1 -1
  7. package/ui-dist/assets/{chat-C0ZNZtS3.js → chat-BxA-mw53.js} +2 -2
  8. package/ui-dist/assets/{chat-page-CGHNhXaw.js → chat-page-DLFTPfmu.js} +1 -1
  9. package/ui-dist/assets/{chunk-JZWAC4HX-BJer-fqD.js → chunk-JZWAC4HX-ptDyT_1C.js} +1 -1
  10. package/ui-dist/assets/{desktop-update-config-Dfh-3uma.js → desktop-update-config-CzGi43xw.js} +1 -1
  11. package/ui-dist/assets/{dialog-D-I7ONHQ.js → dialog-BHcaU6NE.js} +1 -1
  12. package/ui-dist/assets/{dist-DreLBS93.js → dist-DtBFqZ6_.js} +1 -1
  13. package/ui-dist/assets/{es2015-DMSUl3fm.js → es2015-BlNhrQUG.js} +1 -1
  14. package/ui-dist/assets/{index-Bc6c1kIx.js → index-CAYF44Dz.js} +2 -2
  15. package/ui-dist/assets/marketplace-page-0sEdt5sA.js +1 -0
  16. package/ui-dist/assets/{marketplace-page-BCrS-jH6.js → marketplace-page-DiqqX25V.js} +1 -1
  17. package/ui-dist/assets/mcp-marketplace-page-B8vmu9xe.js +1 -0
  18. package/ui-dist/assets/{mcp-marketplace-page-CjrxT6wI.js → mcp-marketplace-page-C_akqPwv.js} +1 -1
  19. package/ui-dist/assets/{model-config-D4myteLK.js → model-config-B0L43HTL.js} +1 -1
  20. package/ui-dist/assets/{notice-card-DX_NEZTQ.js → notice-card-C9PFAR67.js} +1 -1
  21. package/ui-dist/assets/{popover-Dm_NQ3Cs.js → popover-B8msg2FQ.js} +1 -1
  22. package/ui-dist/assets/{provider-scoped-model-input-BLHImwI5.js → provider-scoped-model-input-DeAo2Y65.js} +1 -1
  23. package/ui-dist/assets/{providers-list-DsBFslNi.js → providers-list-5_VShcn7.js} +1 -1
  24. package/ui-dist/assets/remote-pzp4oLcL.js +1 -0
  25. package/ui-dist/assets/{runtime-config-page-Bz9r68Rf.js → runtime-config-page-B-y_0HIS.js} +1 -1
  26. package/ui-dist/assets/{search-config-C-6KpgRQ.js → search-config-DJTm9Fno.js} +1 -1
  27. package/ui-dist/assets/{secrets-config-MiMElvpm.js → secrets-config-DKFeFii1.js} +1 -1
  28. package/ui-dist/assets/{select-RgeHgn_-.js → select-DRDejPLk.js} +1 -1
  29. package/ui-dist/assets/{sessions-config-page-0KNW9QC_.js → sessions-config-page-CZGqS32n.js} +1 -1
  30. package/ui-dist/assets/{setting-row-vwm4XKv2.js → setting-row-BcF6eTW0.js} +1 -1
  31. package/ui-dist/assets/{tag-chip-DGqz3TON.js → tag-chip-CVIqyMv7.js} +1 -1
  32. package/ui-dist/assets/{theme-provider-CUppbOyN.js → theme-provider-dHqcWU-j.js} +1 -1
  33. package/ui-dist/assets/{tooltip-DQlSKhZ_.js → tooltip-C6VPreZ7.js} +1 -1
  34. package/ui-dist/assets/{use-config-CrsavfWZ.js → use-config-DFja1sda.js} +1 -1
  35. package/ui-dist/assets/{use-confirm-dialog-D1AnLFlc.js → use-confirm-dialog-DvIbSUX3.js} +1 -1
  36. package/ui-dist/assets/{use-infinite-scroll-loader-DZhv-rmv.js → use-infinite-scroll-loader-D8h0k-iL.js} +1 -1
  37. package/ui-dist/assets/{use-viewport-layout-CytJAPWM.js → use-viewport-layout-D-pjxsyz.js} +1 -1
  38. package/ui-dist/index.html +16 -16
  39. package/ui-dist/assets/marketplace-page-DVrlpB68.js +0 -1
  40. package/ui-dist/assets/mcp-marketplace-page-pQ_A38fH.js +0 -1
  41. package/ui-dist/assets/remote-CQQykOYe.js +0 -1
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
3
  import * as NextclawCore from "@nextclaw/core";
4
- import { APP_NAME, APP_TAGLINE, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, ChannelManager, CommandRegistry, ConfigSchema, ContextBuilder, CronService, CronTool, DEFAULT_WORKSPACE_DIR, DEFAULT_WORKSPACE_PATH, DisposableStore, EditFileTool, ExecTool, ExtensionToolAdapter, FileLogSink, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, MemoryGetTool, MemorySearchTool, MessageBus, MessageTool, ProviderManager, ReadFileTool, RequestedSkillsMetadataReader, SessionManager, SessionsHistoryTool, SessionsListTool, SkillsLoader, Tool, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool, buildConfigSchema, buildMinimalSystemExecutionPrompt, buildReloadPlan, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createExternalCommandEnv, createGlobalTypedEventBus, createTypedEventKey, createTypingStopControlMessage, diffConfigPaths, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getLoggingRuntime, getLogsPath, getPackageVersion, getWorkspacePath, hasSecretRef, loadConfig, normalizeInlineSecretRefs, parseAgentScopedSessionKey, parseThinkingLevel, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveAppLogPath, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveLocalUiBaseUrl, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, toDisposable, updateAgentProfile } from "@nextclaw/core";
4
+ import { APP_NAME, APP_TAGLINE, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, ChannelManager, CommandRegistry, ConfigSchema, ContextBuilder, CronService, CronTool, DEFAULT_WORKSPACE_DIR, DEFAULT_WORKSPACE_PATH, DisposableStore, EditFileTool, ExecTool, ExtensionToolAdapter, FileLogSink, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, MemoryGetTool, MemorySearchTool, MessageBus, MessageTool, ProviderManager, ReadFileTool, RequestedSkillsMetadataReader, SessionManager, SessionsHistoryTool, SessionsListTool, SkillsLoader, Tool, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool, buildConfigSchema, buildMinimalSystemExecutionPrompt, buildReloadPlan, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createExternalCommandEnv, createGlobalTypedEventBus, createTypedEventKey, createTypingStopControlMessage, diffConfigPaths, expandHome, findEffectiveAgentProfile, getAppLogger, getConfigPath, getDataDir, getDataPath, getLoggingRuntime, getLogsPath, getPackageVersion, getWorkspacePath, hasSecretRef, loadConfig, normalizeInlineSecretRefs, parseAgentScopedSessionKey, parseThinkingLevel, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveAppLogPath, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveLocalUiBaseUrl, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, toDisposable, updateAgentProfile } from "@nextclaw/core";
5
5
  import { Command } from "commander";
6
6
  import fs, { appendFileSync, closeSync, constants, cpSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, relative, resolve, win32 } from "node:path";
8
8
  import { homedir, hostname, platform } from "node:os";
9
9
  import { ensureUiBridgeSecret, startUiServer } from "@nextclaw/server";
10
- import { addPluginLoadPath, buildPluginStatusReport, disablePluginInConfig, discoverPluginStatusReport, enablePluginInConfig, getPackageManifestExtensions, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, mergePluginConfigView, recordPluginInstall, resolvePluginChannelMessageToolHints, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, stopPluginChannelGateways, toPluginConfigView, toPluginConfigView as toPluginConfigView$1, uninstallPlugin } from "@nextclaw/openclaw-compat";
10
+ import { addPluginLoadPath, buildPluginStatusReport, disablePluginInConfig, discoverPluginStatusReport, enablePluginInConfig, getPackageManifestExtensions, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadOpenClawPluginsProgressively, loadPluginManifest, mergePluginConfigView, recordPluginInstall, resolvePluginChannelMessageToolHints, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, startPluginChannelGateways, stopPluginChannelGateways, toPluginConfigView, toPluginConfigView as toPluginConfigView$1, uninstallPlugin } from "@nextclaw/openclaw-compat";
11
11
  import { fileURLToPath } from "node:url";
12
- import { fork, spawn, spawnSync } from "node:child_process";
12
+ import { spawn, spawnSync } from "node:child_process";
13
13
  import { createServer, isIP } from "node:net";
14
14
  import { BUILTIN_CHANNEL_PLUGIN_IDS, builtinProviderIds, listBuiltinProviders } from "@nextclaw/runtime";
15
15
  import { createInterface } from "node:readline";
@@ -6024,9 +6024,23 @@ function toExtensionRegistry(pluginRegistry) {
6024
6024
  }
6025
6025
  //#endregion
6026
6026
  //#region src/cli/commands/plugin/plugin-registry-loader.ts
6027
+ function createPluginLogger() {
6028
+ return getAppLogger("plugin.registry_loader");
6029
+ }
6027
6030
  function withDevFirstPartyPluginPaths(config) {
6028
6031
  return resolveDevPluginLoadingContext(config, resolveDevFirstPartyPluginDir(process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR));
6029
6032
  }
6033
+ async function loadPluginRegistryProgressively(config, workspaceDir, options = {}) {
6034
+ const { configWithDevPluginOverrides, excludedRoots } = withDevFirstPartyPluginPaths(config);
6035
+ return await loadOpenClawPluginsProgressively({
6036
+ config: configWithDevPluginOverrides,
6037
+ workspaceDir,
6038
+ excludeRoots: excludedRoots,
6039
+ ...buildReservedPluginLoadOptions(),
6040
+ onPluginProcessed: options.onPluginProcessed,
6041
+ logger: createPluginLogger()
6042
+ });
6043
+ }
6030
6044
  function discoverPluginRegistryStatus(config, workspaceDir) {
6031
6045
  const { configWithDevPluginOverrides } = withDevFirstPartyPluginPaths(config);
6032
6046
  return discoverPluginStatusReport({
@@ -13960,6 +13974,19 @@ var ManagedServiceCommandService = class {
13960
13974
  };
13961
13975
  //#endregion
13962
13976
  //#region src/cli/shared/services/gateway/service-startup-support.ts
13977
+ const pluginGatewayLogger = {
13978
+ info: (message) => console.log(`[plugins] ${message}`),
13979
+ warn: (message) => console.warn(`[plugins] ${message}`),
13980
+ error: (message) => console.error(`[plugins] ${message}`),
13981
+ debug: (message) => console.debug(`[plugins] ${message}`)
13982
+ };
13983
+ function logPluginGatewayDiagnostics(diagnostics) {
13984
+ for (const diag of diagnostics) {
13985
+ const text = `${diag.pluginId ? `${diag.pluginId}: ` : ""}${diag.message}`;
13986
+ if (diag.level === "error") console.error(`[plugins] ${text}`);
13987
+ else console.warn(`[plugins] ${text}`);
13988
+ }
13989
+ }
13963
13990
  async function startGatewaySupportServices(params) {
13964
13991
  if (params.cronJobs > 0) console.log(`✓ Cron: ${params.cronJobs} scheduled jobs`);
13965
13992
  console.log("✓ Heartbeat: every 30m");
@@ -15370,10 +15397,14 @@ var NextclawApp = class {
15370
15397
  await measureStartupAsync("service.deferred_startup.recover_durable_state", async () => await this.ncpAgentRuntime.recoverDurableState());
15371
15398
  };
15372
15399
  warmDerivedCapabilities = async () => {
15400
+ const runtimeWarmupTask = this.kernelReady ? measureStartupAsync("service.deferred_startup.warm_ncp_capabilities", async () => await this.ncpAgentRuntime.warmDerivedCapabilities()).catch((error) => {
15401
+ console.warn(`UI NCP derived capability warmup failed: ${error instanceof Error ? error.message : String(error)}`);
15402
+ }) : Promise.resolve();
15373
15403
  if (this.params.hydrateCapabilities) await measureStartupAsync("service.deferred_startup.hydrate_capabilities", this.params.hydrateCapabilities);
15374
15404
  await measureStartupAsync("service.deferred_startup.start_plugin_gateways", this.params.startPluginGateways);
15375
15405
  await measureStartupAsync("service.deferred_startup.start_channels", this.params.startChannels);
15376
15406
  await measureStartupAsync("service.deferred_startup.wake_restart_sentinel", this.params.wakeFromRestartSentinel);
15407
+ await runtimeWarmupTask;
15377
15408
  };
15378
15409
  handleKernelStartupError(error) {
15379
15410
  this.params.bootstrapStatus.markNcpAgentError(error instanceof Error ? error.message : String(error));
@@ -15875,57 +15906,58 @@ function countEnabledPlugins(config, workspaceDir) {
15875
15906
  return discoverPluginRegistryStatus(config, workspaceDir).plugins.filter((plugin) => plugin.enabled).length;
15876
15907
  }
15877
15908
  async function hydrateServiceCapabilities(params) {
15878
- const { bootstrapStatus, extensionHost, gateway, getLiveUiNcpAgent, state, uiStartup } = params;
15879
- await waitForUiShellGraceWindow(uiStartup);
15880
- const nextConfig = resolveConfigSecrets(loadConfig(), { configPath: gateway.runtimeConfigPath });
15909
+ await waitForUiShellGraceWindow(params.uiStartup);
15910
+ const nextConfig = resolveConfigSecrets(loadConfig(), { configPath: params.gateway.runtimeConfigPath });
15881
15911
  const nextWorkspace = getWorkspacePath(nextConfig.agents.defaults.workspace);
15882
15912
  const totalPluginCount = countEnabledPlugins(nextConfig, nextWorkspace);
15883
15913
  let loadedPluginCount = 0;
15884
- bootstrapStatus.markPluginHydrationRunning({ totalPluginCount });
15885
- bootstrapStatus.markChannelsPending();
15914
+ params.bootstrapStatus.markPluginHydrationRunning({ totalPluginCount });
15915
+ params.bootstrapStatus.markChannelsPending();
15886
15916
  try {
15887
- const nextPluginRegistry = extensionHost.createProxyPluginRegistry(await extensionHost.load({
15888
- config: nextConfig,
15889
- workspaceDir: nextWorkspace
15890
- }));
15891
- loadedPluginCount = loadedPluginCount || nextPluginRegistry.plugins.filter((plugin) => plugin.status === "loaded").length;
15917
+ const nextPluginRegistry = await loadPluginRegistryProgressively(nextConfig, nextWorkspace, { onPluginProcessed: ({ loadedPluginCount: nextCount }) => {
15918
+ loadedPluginCount = nextCount;
15919
+ params.bootstrapStatus.markPluginHydrationProgress({
15920
+ loadedPluginCount: nextCount,
15921
+ totalPluginCount
15922
+ });
15923
+ } });
15892
15924
  logPluginDiagnostics(nextPluginRegistry);
15893
15925
  const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
15894
15926
  const nextPluginChannelBindings = getPluginChannelBindings(nextPluginRegistry);
15895
15927
  const nextPluginUiMetadata = getPluginUiMetadataFromRegistry(nextPluginRegistry);
15896
15928
  const shouldRebuildChannels = shouldRestartChannelsForPluginReload({
15897
15929
  changedPaths: [],
15898
- currentPluginChannelBindings: state.pluginChannelBindings,
15930
+ currentPluginChannelBindings: params.state.pluginChannelBindings,
15899
15931
  nextPluginChannelBindings,
15900
- currentExtensionChannels: state.extensionRegistry.channels,
15932
+ currentExtensionChannels: params.state.extensionRegistry.channels,
15901
15933
  nextExtensionChannels: nextExtensionRegistry.channels
15902
15934
  });
15903
- applyGatewayCapabilityState(gateway, {
15935
+ applyGatewayCapabilityState(params.gateway, {
15904
15936
  pluginRegistry: nextPluginRegistry,
15905
15937
  extensionRegistry: nextExtensionRegistry,
15906
15938
  pluginChannelBindings: nextPluginChannelBindings
15907
15939
  });
15908
- state.pluginRegistry = nextPluginRegistry;
15909
- state.extensionRegistry = nextExtensionRegistry;
15910
- state.pluginChannelBindings = nextPluginChannelBindings;
15911
- state.pluginUiMetadata = nextPluginUiMetadata;
15912
- getLiveUiNcpAgent()?.applyExtensionRegistry?.(nextExtensionRegistry);
15913
- if (shouldRebuildChannels) await gateway.reloader.rebuildChannels(nextConfig, { start: false });
15914
- uiStartup?.publish({
15940
+ params.state.pluginRegistry = nextPluginRegistry;
15941
+ params.state.extensionRegistry = nextExtensionRegistry;
15942
+ params.state.pluginChannelBindings = nextPluginChannelBindings;
15943
+ params.state.pluginUiMetadata = nextPluginUiMetadata;
15944
+ params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(nextExtensionRegistry);
15945
+ if (shouldRebuildChannels) await params.gateway.reloader.rebuildChannels(nextConfig, { start: false });
15946
+ params.uiStartup?.publish({
15915
15947
  type: "config.updated",
15916
15948
  payload: { path: "channels" }
15917
15949
  });
15918
- uiStartup?.publish({
15950
+ params.uiStartup?.publish({
15919
15951
  type: "config.updated",
15920
15952
  payload: { path: "plugins" }
15921
15953
  });
15922
- bootstrapStatus.markPluginHydrationReady({
15954
+ params.bootstrapStatus.markPluginHydrationReady({
15923
15955
  loadedPluginCount: loadedPluginCount || totalPluginCount,
15924
15956
  totalPluginCount
15925
15957
  });
15926
15958
  } catch (error) {
15927
15959
  const message = error instanceof Error ? error.message : String(error);
15928
- bootstrapStatus.markPluginHydrationError(message);
15960
+ params.bootstrapStatus.markPluginHydrationError(message);
15929
15961
  throw error;
15930
15962
  }
15931
15963
  }
@@ -16020,10 +16052,7 @@ function resolvePluginRuntimeAttachments(ctx) {
16020
16052
  //#region src/cli/shared/services/plugin/service-plugin-reload.service.ts
16021
16053
  async function reloadServicePlugins(params) {
16022
16054
  const nextWorkspace = getWorkspacePath(params.nextConfig.agents.defaults.workspace);
16023
- const nextPluginRegistry = params.extensionHost.createProxyPluginRegistry(await params.extensionHost.load({
16024
- config: params.nextConfig,
16025
- workspaceDir: nextWorkspace
16026
- }));
16055
+ const nextPluginRegistry = loadPluginRegistry(params.nextConfig, nextWorkspace);
16027
16056
  const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
16028
16057
  const nextPluginChannelBindings = getPluginChannelBindings(nextPluginRegistry);
16029
16058
  const shouldRestartChannels = shouldRestartChannelsForPluginReload({
@@ -16034,14 +16063,22 @@ async function reloadServicePlugins(params) {
16034
16063
  nextExtensionChannels: nextExtensionRegistry.channels
16035
16064
  });
16036
16065
  logPluginDiagnostics(nextPluginRegistry);
16066
+ let pluginGatewayHandles = params.pluginGatewayHandles;
16037
16067
  if (shouldRestartChannels) {
16038
- await params.extensionHost.stopPluginGateways();
16039
- await params.extensionHost.startPluginGateways(params.nextConfig);
16068
+ await stopPluginChannelGateways(pluginGatewayHandles);
16069
+ const startedPluginGateways = await startPluginChannelGateways({
16070
+ registry: nextPluginRegistry,
16071
+ config: params.nextConfig,
16072
+ logger: params.pluginGatewayLogger
16073
+ });
16074
+ pluginGatewayHandles = startedPluginGateways.handles;
16075
+ params.logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
16040
16076
  }
16041
16077
  return {
16042
16078
  pluginRegistry: nextPluginRegistry,
16043
16079
  extensionRegistry: nextExtensionRegistry,
16044
16080
  pluginChannelBindings: nextPluginChannelBindings,
16081
+ pluginGatewayHandles,
16045
16082
  restartChannels: shouldRestartChannels
16046
16083
  };
16047
16084
  }
@@ -16066,20 +16103,22 @@ function createGatewayRuntimeState(gateway) {
16066
16103
  };
16067
16104
  }
16068
16105
  function applyGatewayRuntimeCapabilityState(params) {
16069
- const { gateway, next, state } = params;
16070
- applyGatewayCapabilityState(gateway, next);
16071
- state.pluginRegistry = next.pluginRegistry;
16072
- state.extensionRegistry = next.extensionRegistry;
16073
- state.pluginChannelBindings = next.pluginChannelBindings;
16106
+ applyGatewayCapabilityState(params.gateway, params.next);
16107
+ params.state.pluginRegistry = params.next.pluginRegistry;
16108
+ params.state.extensionRegistry = params.next.extensionRegistry;
16109
+ params.state.pluginChannelBindings = params.next.pluginChannelBindings;
16074
16110
  }
16075
16111
  function configureGatewayPluginRuntime(params) {
16076
16112
  params.gateway.reloader.setReloadPlugins(async ({ config: nextConfig, changedPaths }) => {
16077
16113
  const result = await reloadServicePlugins({
16078
16114
  nextConfig,
16079
16115
  changedPaths,
16116
+ pluginRegistry: params.state.pluginRegistry,
16080
16117
  extensionRegistry: params.state.extensionRegistry,
16081
16118
  pluginChannelBindings: params.state.pluginChannelBindings,
16082
- extensionHost: params.extensionHost
16119
+ pluginGatewayHandles: params.state.pluginGatewayHandles,
16120
+ pluginGatewayLogger,
16121
+ logPluginGatewayDiagnostics
16083
16122
  });
16084
16123
  applyGatewayRuntimeCapabilityState({
16085
16124
  gateway: params.gateway,
@@ -16091,6 +16130,7 @@ function configureGatewayPluginRuntime(params) {
16091
16130
  }
16092
16131
  });
16093
16132
  params.state.pluginUiMetadata = getPluginUiMetadataFromRegistry(result.pluginRegistry);
16133
+ params.state.pluginGatewayHandles = result.pluginGatewayHandles;
16094
16134
  params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(result.extensionRegistry);
16095
16135
  if (result.restartChannels) console.log("Config reload: plugin channel gateways restarted.");
16096
16136
  return { restartChannels: result.restartChannels };
@@ -16117,12 +16157,17 @@ function createDeferredGatewayStartupHooks(params) {
16117
16157
  gateway: params.gateway,
16118
16158
  state: params.state,
16119
16159
  bootstrapStatus: params.bootstrapStatus,
16120
- getLiveUiNcpAgent: params.getLiveUiNcpAgent,
16121
- extensionHost: params.extensionHost
16160
+ getLiveUiNcpAgent: params.getLiveUiNcpAgent
16122
16161
  });
16123
16162
  },
16124
16163
  startPluginGateways: async () => {
16125
- await params.extensionHost.startPluginGateways(resolveConfigSecrets$2(loadConfig$2(), { configPath: params.gateway.runtimeConfigPath }));
16164
+ const startedPluginGateways = await startPluginChannelGateways({
16165
+ registry: params.state.pluginRegistry,
16166
+ config: resolveConfigSecrets$2(loadConfig$2(), { configPath: params.gateway.runtimeConfigPath }),
16167
+ logger: pluginGatewayLogger
16168
+ });
16169
+ params.state.pluginGatewayHandles = startedPluginGateways.handles;
16170
+ logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
16126
16171
  },
16127
16172
  startChannels: async () => {
16128
16173
  await params.gateway.reloader.getChannels().startAll();
@@ -16157,326 +16202,6 @@ async function cleanupGatewayRuntime(params) {
16157
16202
  setPluginRuntimeBridge(null);
16158
16203
  }
16159
16204
  //#endregion
16160
- //#region src/cli/shared/services/extension-host-proxy-registry.service.ts
16161
- function normalizeSchema(schema) {
16162
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) return {
16163
- type: "object",
16164
- properties: {},
16165
- additionalProperties: true
16166
- };
16167
- return schema;
16168
- }
16169
- function stringifyToolResult(value) {
16170
- if (typeof value === "string") return value;
16171
- if (value === void 0 || value === null) return "";
16172
- try {
16173
- return JSON.stringify(value, null, 2);
16174
- } catch {
16175
- return String(value);
16176
- }
16177
- }
16178
- function pickPreview(params) {
16179
- const { alias, descriptor } = params;
16180
- const byName = descriptor.previews.find((preview) => preview.name === alias);
16181
- if (byName) return byName;
16182
- if (descriptor.previews.length === 1) return descriptor.previews[0] ?? null;
16183
- if (descriptor.previews.length === descriptor.names.length) {
16184
- const index = descriptor.names.indexOf(alias);
16185
- if (index >= 0 && index < descriptor.previews.length) return descriptor.previews[index] ?? null;
16186
- }
16187
- return null;
16188
- }
16189
- var ExtensionHostProxyRuntime = class {
16190
- constructor(params) {
16191
- this.params = params;
16192
- }
16193
- run = (input, options) => this.params.client.runRuntimeStream({
16194
- kind: this.params.kind,
16195
- entry: this.params.entry,
16196
- runtimeParams: this.params.runtimeParams,
16197
- input,
16198
- signal: options?.signal
16199
- });
16200
- };
16201
- var ExtensionHostProxyRegistryService = class {
16202
- constructor(client) {
16203
- this.client = client;
16204
- }
16205
- createPluginRegistry = (snapshot) => ({
16206
- plugins: snapshot.plugins,
16207
- diagnostics: snapshot.diagnostics,
16208
- tools: snapshot.tools.map((descriptor) => ({
16209
- pluginId: descriptor.pluginId,
16210
- source: descriptor.source,
16211
- names: descriptor.names,
16212
- optional: descriptor.optional,
16213
- factory: (context) => this.createProxyTools(descriptor, context)
16214
- })),
16215
- channels: snapshot.channels.map((descriptor) => ({
16216
- pluginId: descriptor.pluginId,
16217
- source: descriptor.source,
16218
- channel: {
16219
- id: descriptor.channel.id,
16220
- ...descriptor.channel.meta ? { meta: descriptor.channel.meta } : {},
16221
- ...descriptor.channel.capabilities ? { capabilities: descriptor.channel.capabilities } : {},
16222
- ...descriptor.channel.configSchema ? { configSchema: descriptor.channel.configSchema } : {},
16223
- outbound: this.createChannelOutbound(descriptor)
16224
- }
16225
- })),
16226
- providers: snapshot.providers.map((descriptor) => ({
16227
- pluginId: descriptor.pluginId,
16228
- source: descriptor.source,
16229
- provider: descriptor.provider
16230
- })),
16231
- ncpAgentRuntimes: snapshot.ncpAgentRuntimes.map((descriptor) => ({
16232
- pluginId: descriptor.pluginId,
16233
- source: descriptor.source,
16234
- kind: descriptor.kind,
16235
- label: descriptor.label,
16236
- createRuntime: (runtimeParams) => new ExtensionHostProxyRuntime({
16237
- client: this.client,
16238
- kind: descriptor.kind,
16239
- runtimeParams
16240
- }),
16241
- createRuntimeForEntry: descriptor.supportsEntryRuntime ? ({ entry, runtimeParams }) => new ExtensionHostProxyRuntime({
16242
- client: this.client,
16243
- kind: descriptor.kind,
16244
- entry,
16245
- runtimeParams
16246
- }) : void 0,
16247
- describeSessionType: async (describeParams) => await this.client.describeRuntime({
16248
- kind: descriptor.kind,
16249
- describeParams
16250
- }),
16251
- describeSessionTypeForEntry: descriptor.supportsEntryDescription ? async ({ entry, describeParams }) => await this.client.describeRuntime({
16252
- kind: descriptor.kind,
16253
- entry,
16254
- describeParams
16255
- }) : void 0
16256
- })),
16257
- resolvedTools: snapshot.tools.flatMap((descriptor) => descriptor.previews.map((preview) => this.createProxyTool(descriptor, preview.name, {}, preview)))
16258
- });
16259
- createChannelOutbound = (descriptor) => ({
16260
- ...descriptor.channel.hasOutboundText ? { sendText: async (ctx) => await this.client.sendChannelOutbound({
16261
- pluginId: descriptor.pluginId,
16262
- channelId: descriptor.channel.id,
16263
- kind: "text",
16264
- cfg: ctx.cfg,
16265
- to: ctx.to,
16266
- text: ctx.text,
16267
- accountId: ctx.accountId
16268
- }) } : {},
16269
- ...descriptor.channel.hasOutboundPayload ? { sendPayload: async (ctx) => await this.client.sendChannelOutbound({
16270
- pluginId: descriptor.pluginId,
16271
- channelId: descriptor.channel.id,
16272
- kind: "payload",
16273
- cfg: ctx.cfg,
16274
- to: ctx.to,
16275
- text: ctx.text,
16276
- payload: ctx.payload,
16277
- accountId: ctx.accountId
16278
- }) } : {}
16279
- });
16280
- createProxyTools = (descriptor, context) => descriptor.names.map((alias) => {
16281
- const preview = pickPreview({
16282
- descriptor,
16283
- alias
16284
- });
16285
- return this.createProxyTool(descriptor, alias, context, preview ?? void 0);
16286
- });
16287
- createProxyTool = (descriptor, alias, context, preview) => ({
16288
- name: preview?.name ?? alias,
16289
- ...preview?.label ? { label: preview.label } : {},
16290
- description: preview?.description ?? `Extension tool '${alias}' from ${descriptor.pluginId}`,
16291
- parameters: normalizeSchema(preview?.parameters),
16292
- execute: async (toolCallIdOrParams, maybeParams) => {
16293
- const hasToolCallId = typeof toolCallIdOrParams === "string";
16294
- const params = hasToolCallId ? maybeParams ?? {} : toolCallIdOrParams;
16295
- const toolCallId = hasToolCallId ? toolCallIdOrParams : void 0;
16296
- return stringifyToolResult(await this.client.executeTool({
16297
- registrationId: descriptor.registrationId,
16298
- alias,
16299
- context,
16300
- params,
16301
- toolCallId
16302
- }));
16303
- }
16304
- });
16305
- };
16306
- //#endregion
16307
- //#region src/cli/shared/services/extension-host-client.service.ts
16308
- function resolveChildEntryPath() {
16309
- const sourcePath = fileURLToPath(new URL("./extension-host-child.service.ts", import.meta.url));
16310
- if (existsSync(sourcePath)) return sourcePath;
16311
- return fileURLToPath(new URL("./extension-host-child.service.js", import.meta.url));
16312
- }
16313
- var ExtensionHostClient = class {
16314
- child = null;
16315
- nextRequestId = 1;
16316
- nextStreamId = 1;
16317
- pending = /* @__PURE__ */ new Map();
16318
- runtimeStreams = /* @__PURE__ */ new Map();
16319
- proxyRegistry = new ExtensionHostProxyRegistryService(this);
16320
- constructor(params = {}) {
16321
- this.params = params;
16322
- }
16323
- load = async (request) => await this.request("load", request);
16324
- startPluginGateways = async (config) => {
16325
- await this.request("channel.startGateways", { config });
16326
- };
16327
- stopPluginGateways = async () => {
16328
- await this.request("channel.stopGateways", void 0);
16329
- };
16330
- executeTool = async (request) => await this.request("tool.execute", request);
16331
- sendChannelOutbound = async (request) => await this.request("channel.outbound", request);
16332
- describeRuntime = async (request) => await this.request("runtime.describe", request);
16333
- createProxyPluginRegistry = (snapshot) => this.proxyRegistry.createPluginRegistry(snapshot);
16334
- runRuntimeStream = async function* (params) {
16335
- const { entry, input, kind, runtimeParams, signal } = params;
16336
- const streamId = `runtime-${this.nextStreamId++}`;
16337
- const state = {
16338
- queue: [],
16339
- wake: null,
16340
- onMetadata: runtimeParams.setSessionMetadata,
16341
- applyStateBatch: async (events) => {
16342
- await runtimeParams.stateManager.dispatchBatch(events);
16343
- }
16344
- };
16345
- this.runtimeStreams.set(streamId, state);
16346
- const abortListener = () => {
16347
- this.request("runtime.abort", {
16348
- streamId,
16349
- reason: typeof signal?.reason === "string" ? signal.reason : void 0
16350
- }).catch(() => void 0);
16351
- };
16352
- signal?.addEventListener("abort", abortListener, { once: true });
16353
- await this.request("runtime.run", {
16354
- streamId,
16355
- kind,
16356
- entry,
16357
- runtimeParams: {
16358
- sessionId: runtimeParams.sessionId,
16359
- agentId: runtimeParams.agentId,
16360
- sessionMetadata: runtimeParams.sessionMetadata,
16361
- ...runtimeParams.resolveTools ? { resolvedTools: Array.from(runtimeParams.resolveTools(input) ?? []) } : {}
16362
- },
16363
- input
16364
- });
16365
- try {
16366
- while (true) {
16367
- const next = await this.nextRuntimeStreamItem(state);
16368
- if (next === null) return;
16369
- if (next instanceof Error) throw next;
16370
- yield next;
16371
- }
16372
- } finally {
16373
- signal?.removeEventListener("abort", abortListener);
16374
- this.runtimeStreams.delete(streamId);
16375
- }
16376
- };
16377
- dispose = async () => {
16378
- await this.stopPluginGateways().catch(() => void 0);
16379
- this.child?.kill();
16380
- this.child = null;
16381
- this.rejectAll(/* @__PURE__ */ new Error("Extension host disposed"));
16382
- };
16383
- request = async (method, payload) => {
16384
- const child = this.ensureChild();
16385
- const id = this.nextRequestId++;
16386
- const promise = new Promise((resolve, reject) => {
16387
- this.pending.set(id, {
16388
- resolve: (value) => resolve(value),
16389
- reject
16390
- });
16391
- });
16392
- child.send?.({
16393
- type: "request",
16394
- id,
16395
- method,
16396
- payload
16397
- });
16398
- return await promise;
16399
- };
16400
- ensureChild = () => {
16401
- if (this.child) return this.child;
16402
- const child = fork(resolveChildEntryPath(), [], {
16403
- env: process.env,
16404
- execArgv: process.execArgv,
16405
- stdio: [
16406
- "ignore",
16407
- "inherit",
16408
- "inherit",
16409
- "ipc"
16410
- ]
16411
- });
16412
- child.on("message", (message) => this.handleMessage(message));
16413
- child.on("exit", (code, signal) => {
16414
- this.child = null;
16415
- this.rejectAll(/* @__PURE__ */ new Error(`Extension host exited: code=${code ?? "null"} signal=${signal ?? "null"}`));
16416
- });
16417
- child.on("error", (error) => {
16418
- this.rejectAll(error);
16419
- });
16420
- this.child = child;
16421
- return child;
16422
- };
16423
- handleMessage = (message) => {
16424
- if (message.type === "response") {
16425
- const pending = this.pending.get(message.id);
16426
- if (!pending) return;
16427
- this.pending.delete(message.id);
16428
- if (message.ok) {
16429
- pending.resolve(message.payload);
16430
- return;
16431
- }
16432
- pending.reject(new Error(message.error));
16433
- return;
16434
- }
16435
- if (message.type !== "event") return;
16436
- if (message.event === "load.progress") {
16437
- this.params.onProgress?.(message.payload);
16438
- return;
16439
- }
16440
- if (message.event === "runtime.state.dispatchBatch") {
16441
- this.runtimeStreams.get(message.payload.streamId)?.applyStateBatch(message.payload.events);
16442
- return;
16443
- }
16444
- const state = this.runtimeStreams.get(message.payload.streamId);
16445
- if (!state) return;
16446
- if (message.event === "runtime.event") {
16447
- this.pushRuntimeStreamItem(state, message.payload.event);
16448
- return;
16449
- }
16450
- if (message.event === "runtime.metadata") {
16451
- state.onMetadata(message.payload.metadata);
16452
- return;
16453
- }
16454
- if (message.event === "runtime.error") {
16455
- this.pushRuntimeStreamItem(state, new Error(message.payload.error));
16456
- return;
16457
- }
16458
- if (message.event === "runtime.done") this.pushRuntimeStreamItem(state, null);
16459
- };
16460
- pushRuntimeStreamItem = (state, item) => {
16461
- state.queue.push(item);
16462
- state.wake?.();
16463
- state.wake = null;
16464
- };
16465
- nextRuntimeStreamItem = async (state) => {
16466
- const queued = state.queue.shift();
16467
- if (queued !== void 0) return queued;
16468
- await new Promise((resolve) => {
16469
- state.wake = resolve;
16470
- });
16471
- return state.queue.shift() ?? null;
16472
- };
16473
- rejectAll = (error) => {
16474
- for (const pending of this.pending.values()) pending.reject(error);
16475
- this.pending.clear();
16476
- for (const state of this.runtimeStreams.values()) this.pushRuntimeStreamItem(state, error);
16477
- };
16478
- };
16479
- //#endregion
16480
16205
  //#region src/cli/shared/services/runtime/runtime-command.service.ts
16481
16206
  const { getApiBase, getConfigPath: getConfigPath$1, getProvider, getProviderName, getWorkspacePath: getWorkspacePath$1, loadConfig: loadConfig$1, LiteLLMProvider, MessageBus: MessageBus$1, resolveConfigSecrets: resolveConfigSecrets$1, SessionManager: SessionManager$1, parseAgentScopedSessionKey: parseAgentScopedSessionKey$1 } = NextclawCore;
16482
16207
  function createSkillsLoader(workspace) {
@@ -16513,12 +16238,6 @@ var RuntimeCommandService = class {
16513
16238
  };
16514
16239
  let runtimeState = null;
16515
16240
  const bootstrapStatus = createBootstrapStatus(shellContext.config.remote.enabled);
16516
- const extensionHost = new ExtensionHostClient({ onProgress: ({ loadedPluginCount, totalPluginCount }) => {
16517
- bootstrapStatus.markPluginHydrationProgress({
16518
- loadedPluginCount,
16519
- totalPluginCount
16520
- });
16521
- } });
16522
16241
  const ncpSessionRealtimeBridge = createServiceNcpSessionRealtimeBridge({ sessionManager: shellContext.sessionManager });
16523
16242
  const marketplaceInstaller = new ServiceMarketplaceInstaller({
16524
16243
  applyLiveConfigReload,
@@ -16585,8 +16304,7 @@ var RuntimeCommandService = class {
16585
16304
  configureGatewayPluginRuntime({
16586
16305
  gateway,
16587
16306
  state: gatewayRuntimeState,
16588
- getLiveUiNcpAgent: () => this.liveUiNcpAgent,
16589
- extensionHost
16307
+ getLiveUiNcpAgent: () => this.liveUiNcpAgent
16590
16308
  });
16591
16309
  console.log("✓ Capability hydration: scheduled in background");
16592
16310
  await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
@@ -16612,7 +16330,6 @@ var RuntimeCommandService = class {
16612
16330
  setLiveUiNcpAgent: (ncpAgent) => {
16613
16331
  this.liveUiNcpAgent = ncpAgent;
16614
16332
  },
16615
- extensionHost,
16616
16333
  wakeFromRestartSentinel: async () => await this.wakeFromRestartSentinel({
16617
16334
  bus: gateway.bus,
16618
16335
  sessionManager: gateway.sessionManager
@@ -16649,8 +16366,6 @@ var RuntimeCommandService = class {
16649
16366
  uiStartup,
16650
16367
  remoteModule: gateway.remoteModule,
16651
16368
  runtimeState
16652
- }).finally(async () => {
16653
- await extensionHost.dispose();
16654
16369
  })
16655
16370
  });
16656
16371
  logStartupTrace("service.start_gateway.end");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -40,19 +40,19 @@
40
40
  "chokidar": "^3.6.0",
41
41
  "commander": "^12.1.0",
42
42
  "yaml": "^2.8.1",
43
- "@nextclaw/ncp": "0.5.5",
44
- "@nextclaw/ncp-agent-runtime": "0.3.15",
45
43
  "@nextclaw/mcp": "0.1.76",
46
44
  "@nextclaw/core": "0.12.11",
45
+ "@nextclaw/ncp": "0.5.5",
47
46
  "@nextclaw/ncp-mcp": "0.1.78",
48
47
  "@nextclaw/ncp-toolkit": "0.5.10",
48
+ "@nextclaw/nextclaw-ncp-runtime-http-client": "0.1.4",
49
49
  "@nextclaw/nextclaw-hermes-acp-bridge": "0.1.4",
50
+ "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.1.5",
50
51
  "@nextclaw/openclaw-compat": "1.0.11",
51
52
  "@nextclaw/remote": "0.1.88",
52
53
  "@nextclaw/runtime": "0.2.43",
53
- "@nextclaw/nextclaw-ncp-runtime-http-client": "0.1.4",
54
54
  "@nextclaw/server": "0.12.11",
55
- "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.1.5"
55
+ "@nextclaw/ncp-agent-runtime": "0.3.15"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/node": "^20.17.6",
@@ -60,7 +60,7 @@
60
60
  "tsx": "^4.19.2",
61
61
  "typescript": "^5.6.3",
62
62
  "vitest": "^4.1.2",
63
- "@nextclaw/ui": "0.12.12"
63
+ "@nextclaw/ui": "0.12.14"
64
64
  },
65
65
  "scripts": {
66
66
  "dev": "tsx watch --tsconfig tsconfig.json src/cli/app/index.ts",