nextclaw 0.6.33 → 0.6.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -20,7 +20,11 @@ import {
20
20
  DEFAULT_WORKSPACE_DIR,
21
21
  DEFAULT_WORKSPACE_PATH
22
22
  } from "@nextclaw/core";
23
- import { resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2 } from "@nextclaw/openclaw-compat";
23
+ import {
24
+ getPluginChannelBindings as getPluginChannelBindings3,
25
+ resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2,
26
+ setPluginRuntimeBridge as setPluginRuntimeBridge2
27
+ } from "@nextclaw/openclaw-compat";
24
28
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
25
29
  import { join as join6, resolve as resolve9 } from "path";
26
30
  import { createInterface as createInterface2 } from "readline";
@@ -614,8 +618,7 @@ function mergePluginConfigView(baseConfig, pluginViewConfig, bindings) {
614
618
  return next;
615
619
  }
616
620
  var PluginCommands = class {
617
- constructor(deps) {
618
- this.deps = deps;
621
+ constructor() {
619
622
  }
620
623
  pluginsList(opts = {}) {
621
624
  const config2 = loadConfig();
@@ -745,19 +748,15 @@ var PluginCommands = class {
745
748
  const config2 = loadConfig();
746
749
  const next = enablePluginInConfig(config2, id);
747
750
  saveConfig(next);
748
- await this.deps.requestRestart({
749
- reason: `plugin enabled: ${id}`,
750
- manualMessage: `Enabled plugin "${id}". Restart the gateway to apply.`
751
- });
751
+ console.log(`Enabled plugin "${id}".`);
752
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
752
753
  }
753
754
  async pluginsDisable(id) {
754
755
  const config2 = loadConfig();
755
756
  const next = disablePluginInConfig(config2, id);
756
757
  saveConfig(next);
757
- await this.deps.requestRestart({
758
- reason: `plugin disabled: ${id}`,
759
- manualMessage: `Disabled plugin "${id}". Restart the gateway to apply.`
760
- });
758
+ console.log(`Disabled plugin "${id}".`);
759
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
761
760
  }
762
761
  async pluginsUninstall(id, opts = {}) {
763
762
  const config2 = loadConfig();
@@ -854,10 +853,7 @@ var PluginCommands = class {
854
853
  removed.push("directory");
855
854
  }
856
855
  console.log(`Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`);
857
- await this.deps.requestRestart({
858
- reason: `plugin uninstalled: ${pluginId}`,
859
- manualMessage: "Restart the gateway to apply changes."
860
- });
856
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
861
857
  }
862
858
  async pluginsInstall(pathOrSpec, opts = {}) {
863
859
  const fileSpec = this.resolveFileNpmSpecToLocalPath(pathOrSpec);
@@ -886,10 +882,7 @@ var PluginCommands = class {
886
882
  });
887
883
  saveConfig(next3);
888
884
  console.log(`Linked plugin path: ${resolved}`);
889
- await this.deps.requestRestart({
890
- reason: `plugin linked: ${probe.pluginId}`,
891
- manualMessage: "Restart the gateway to load plugins."
892
- });
885
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
893
886
  return;
894
887
  }
895
888
  const result2 = await installPluginFromPath({
@@ -913,10 +906,7 @@ var PluginCommands = class {
913
906
  });
914
907
  saveConfig(next2);
915
908
  console.log(`Installed plugin: ${result2.pluginId}`);
916
- await this.deps.requestRestart({
917
- reason: `plugin installed: ${result2.pluginId}`,
918
- manualMessage: "Restart the gateway to load plugins."
919
- });
909
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
920
910
  return;
921
911
  }
922
912
  if (opts.link) {
@@ -948,10 +938,7 @@ var PluginCommands = class {
948
938
  });
949
939
  saveConfig(next);
950
940
  console.log(`Installed plugin: ${result.pluginId}`);
951
- await this.deps.requestRestart({
952
- reason: `plugin installed: ${result.pluginId}`,
953
- manualMessage: "Restart the gateway to load plugins."
954
- });
941
+ console.log("If gateway is running, plugin changes are hot-applied automatically.");
955
942
  }
956
943
  pluginsDoctor() {
957
944
  const config2 = loadConfig();
@@ -2194,6 +2181,9 @@ var ConfigReloader = class {
2194
2181
  setApplyAgentRuntimeConfig(callback) {
2195
2182
  this.options.applyAgentRuntimeConfig = callback;
2196
2183
  }
2184
+ setReloadPlugins(callback) {
2185
+ this.options.reloadPlugins = callback;
2186
+ }
2197
2187
  async applyReloadPlan(nextConfig) {
2198
2188
  const changedPaths = diffConfigPaths2(this.currentConfig, nextConfig);
2199
2189
  if (!changedPaths.length) {
@@ -2202,6 +2192,10 @@ var ConfigReloader = class {
2202
2192
  this.currentConfig = nextConfig;
2203
2193
  this.options.providerManager?.setConfig(nextConfig);
2204
2194
  const plan = buildReloadPlan2(changedPaths);
2195
+ if (plan.reloadPlugins) {
2196
+ await this.reloadPlugins(nextConfig);
2197
+ console.log("Config reload: plugins reloaded.");
2198
+ }
2205
2199
  if (plan.restartChannels) {
2206
2200
  await this.reloadChannels(nextConfig);
2207
2201
  console.log("Config reload: channels restarted.");
@@ -2297,6 +2291,12 @@ var ConfigReloader = class {
2297
2291
  this.providerReloadTask = null;
2298
2292
  }
2299
2293
  }
2294
+ async reloadPlugins(nextConfig) {
2295
+ if (!this.options.reloadPlugins) {
2296
+ return;
2297
+ }
2298
+ await this.options.reloadPlugins(nextConfig);
2299
+ }
2300
2300
  };
2301
2301
 
2302
2302
  // src/cli/missing-provider.ts
@@ -2381,6 +2381,10 @@ var GatewayAgentRuntimePool = class {
2381
2381
  this.routeResolver.updateConfig(config2);
2382
2382
  this.rebuild(config2);
2383
2383
  }
2384
+ applyExtensionRegistry(extensionRegistry) {
2385
+ this.options.extensionRegistry = extensionRegistry;
2386
+ this.rebuild(this.options.config);
2387
+ }
2384
2388
  async processDirect(params) {
2385
2389
  const message = {
2386
2390
  channel: params.channel ?? "cli",
@@ -2497,8 +2501,8 @@ var ServiceCommands = class {
2497
2501
  async startGateway(options = {}) {
2498
2502
  const config2 = loadConfig5();
2499
2503
  const workspace = getWorkspacePath5(config2.agents.defaults.workspace);
2500
- const pluginRegistry = loadPluginRegistry(config2, workspace);
2501
- const extensionRegistry = toExtensionRegistry(pluginRegistry);
2504
+ let pluginRegistry = loadPluginRegistry(config2, workspace);
2505
+ let extensionRegistry = toExtensionRegistry(pluginRegistry);
2502
2506
  logPluginDiagnostics(pluginRegistry);
2503
2507
  const bus = new MessageBus();
2504
2508
  const provider = options.allowMissingProvider === true ? this.makeProvider(config2, { allowMissing: true }) : this.makeProvider(config2);
@@ -2507,6 +2511,24 @@ var ServiceCommands = class {
2507
2511
  config: config2
2508
2512
  });
2509
2513
  const sessionManager = new SessionManager(workspace);
2514
+ let pluginGatewayHandles = [];
2515
+ const pluginGatewayLogger = {
2516
+ info: (message) => console.log(`[plugins] ${message}`),
2517
+ warn: (message) => console.warn(`[plugins] ${message}`),
2518
+ error: (message) => console.error(`[plugins] ${message}`),
2519
+ debug: (message) => console.debug(`[plugins] ${message}`)
2520
+ };
2521
+ const logPluginGatewayDiagnostics = (diagnostics) => {
2522
+ for (const diag of diagnostics) {
2523
+ const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
2524
+ const text = `${prefix}${diag.message}`;
2525
+ if (diag.level === "error") {
2526
+ console.error(`[plugins] ${text}`);
2527
+ } else {
2528
+ console.warn(`[plugins] ${text}`);
2529
+ }
2530
+ }
2531
+ };
2510
2532
  const cronStorePath = join4(getDataDir5(), "cron", "jobs.json");
2511
2533
  const cron2 = new CronService2(cronStorePath);
2512
2534
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
@@ -2568,7 +2590,26 @@ var ServiceCommands = class {
2568
2590
  })
2569
2591
  });
2570
2592
  reloader.setApplyAgentRuntimeConfig((nextConfig) => runtimePool.applyRuntimeConfig(nextConfig));
2571
- const pluginChannelBindings = getPluginChannelBindings2(pluginRegistry);
2593
+ reloader.setReloadPlugins(async (nextConfig) => {
2594
+ const nextWorkspace = getWorkspacePath5(nextConfig.agents.defaults.workspace);
2595
+ const nextPluginRegistry = loadPluginRegistry(nextConfig, nextWorkspace);
2596
+ const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
2597
+ logPluginDiagnostics(nextPluginRegistry);
2598
+ await stopPluginChannelGateways(pluginGatewayHandles);
2599
+ const startedPluginGateways = await startPluginChannelGateways({
2600
+ registry: nextPluginRegistry,
2601
+ logger: pluginGatewayLogger
2602
+ });
2603
+ pluginGatewayHandles = startedPluginGateways.handles;
2604
+ logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
2605
+ pluginRegistry = nextPluginRegistry;
2606
+ extensionRegistry = nextExtensionRegistry;
2607
+ pluginChannelBindings = getPluginChannelBindings2(nextPluginRegistry);
2608
+ runtimePool.applyExtensionRegistry(nextExtensionRegistry);
2609
+ runtimePool.applyRuntimeConfig(nextConfig);
2610
+ console.log("Config reload: plugin channel gateways restarted.");
2611
+ });
2612
+ let pluginChannelBindings = getPluginChannelBindings2(pluginRegistry);
2572
2613
  setPluginRuntimeBridge({
2573
2614
  loadConfig: () => toPluginConfigView(loadConfig5(), pluginChannelBindings),
2574
2615
  writeConfigFile: async (nextConfigView) => {
@@ -2658,27 +2699,13 @@ var ServiceCommands = class {
2658
2699
  watcher.on("unlink", () => reloader.scheduleReload("config unlink"));
2659
2700
  await cron2.start();
2660
2701
  await heartbeat.start();
2661
- let pluginGatewayHandles = [];
2662
2702
  try {
2663
2703
  const startedPluginGateways = await startPluginChannelGateways({
2664
2704
  registry: pluginRegistry,
2665
- logger: {
2666
- info: (message) => console.log(`[plugins] ${message}`),
2667
- warn: (message) => console.warn(`[plugins] ${message}`),
2668
- error: (message) => console.error(`[plugins] ${message}`),
2669
- debug: (message) => console.debug(`[plugins] ${message}`)
2670
- }
2705
+ logger: pluginGatewayLogger
2671
2706
  });
2672
2707
  pluginGatewayHandles = startedPluginGateways.handles;
2673
- for (const diag of startedPluginGateways.diagnostics) {
2674
- const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
2675
- const text = `${prefix}${diag.message}`;
2676
- if (diag.level === "error") {
2677
- console.error(`[plugins] ${text}`);
2678
- } else {
2679
- console.warn(`[plugins] ${text}`);
2680
- }
2681
- }
2708
+ logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
2682
2709
  await reloader.getChannels().startAll();
2683
2710
  await this.wakeFromRestartSentinel({ bus, sessionManager });
2684
2711
  await runtimePool.run();
@@ -3236,9 +3263,7 @@ var CliRuntime = class {
3236
3263
  this.configCommands = new ConfigCommands({
3237
3264
  requestRestart: (params) => this.requestRestart(params)
3238
3265
  });
3239
- this.pluginCommands = new PluginCommands({
3240
- requestRestart: (params) => this.requestRestart(params)
3241
- });
3266
+ this.pluginCommands = new PluginCommands();
3242
3267
  this.channelCommands = new ChannelCommands({
3243
3268
  logo: this.logo,
3244
3269
  getBridgeDir: () => this.workspaceManager.getBridgeDir(),
@@ -3274,7 +3299,9 @@ var CliRuntime = class {
3274
3299
  }
3275
3300
  const uiHost = FORCED_PUBLIC_UI_HOST;
3276
3301
  const uiPort = typeof state.uiPort === "number" && Number.isFinite(state.uiPort) ? state.uiPort : 18791;
3277
- console.log(`Applying changes (${reason}): restarting ${APP_NAME4} background service...`);
3302
+ console.log(
3303
+ `Applying changes (${reason}): restarting ${APP_NAME4} background service...`
3304
+ );
3278
3305
  await this.serviceCommands.stopService();
3279
3306
  await this.serviceCommands.startService({
3280
3307
  uiOverrides: {
@@ -3421,11 +3448,15 @@ var CliRuntime = class {
3421
3448
  }
3422
3449
  });
3423
3450
  } catch (error) {
3424
- console.warn(`Warning: failed to write restart sentinel from exec context: ${String(error)}`);
3451
+ console.warn(
3452
+ `Warning: failed to write restart sentinel from exec context: ${String(error)}`
3453
+ );
3425
3454
  }
3426
3455
  }
3427
3456
  async onboard() {
3428
- console.warn(`Warning: ${APP_NAME4} onboard is deprecated. Use "${APP_NAME4} init" instead.`);
3457
+ console.warn(
3458
+ `Warning: ${APP_NAME4} onboard is deprecated. Use "${APP_NAME4} init" instead.`
3459
+ );
3429
3460
  await this.init({ source: "onboard" });
3430
3461
  }
3431
3462
  async init(options = {}) {
@@ -3444,7 +3475,10 @@ var CliRuntime = class {
3444
3475
  const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join6(getDataDir7(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
3445
3476
  const workspaceExisted = existsSync8(workspacePath);
3446
3477
  mkdirSync5(workspacePath, { recursive: true });
3447
- const templateResult = this.workspaceManager.createWorkspaceTemplates(workspacePath, { force });
3478
+ const templateResult = this.workspaceManager.createWorkspaceTemplates(
3479
+ workspacePath,
3480
+ { force }
3481
+ );
3448
3482
  if (createdConfig) {
3449
3483
  console.log(`\u2713 ${prefix}: created config at ${configPath}`);
3450
3484
  }
@@ -3464,7 +3498,9 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3464
3498
  console.log(` 1. Add your API key to ${configPath}`);
3465
3499
  console.log(` 2. Chat: ${APP_NAME4} agent -m "Hello!"`);
3466
3500
  } else {
3467
- console.log(`Tip: Run "${APP_NAME4} init${force ? " --force" : ""}" to re-run initialization if needed.`);
3501
+ console.log(
3502
+ `Tip: Run "${APP_NAME4} init${force ? " --force" : ""}" to re-run initialization if needed.`
3503
+ );
3468
3504
  }
3469
3505
  }
3470
3506
  async gateway(opts) {
@@ -3491,7 +3527,10 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3491
3527
  if (opts.port) {
3492
3528
  uiOverrides.port = Number(opts.port);
3493
3529
  }
3494
- await this.serviceCommands.startGateway({ uiOverrides, allowMissingProvider: true });
3530
+ await this.serviceCommands.startGateway({
3531
+ uiOverrides,
3532
+ allowMissingProvider: true
3533
+ });
3495
3534
  }
3496
3535
  async start(opts) {
3497
3536
  await this.init({ source: "start", auto: true });
@@ -3545,74 +3584,103 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3545
3584
  const pluginRegistry = loadPluginRegistry(config2, workspace);
3546
3585
  const extensionRegistry = toExtensionRegistry(pluginRegistry);
3547
3586
  logPluginDiagnostics(pluginRegistry);
3548
- const bus = new MessageBus2();
3549
- const provider = this.serviceCommands.createProvider(config2) ?? this.serviceCommands.createMissingProvider(config2);
3550
- const providerManager = new ProviderManager2({
3551
- defaultProvider: provider,
3552
- config: config2
3553
- });
3554
- const agentLoop = new AgentLoop2({
3555
- bus,
3556
- providerManager,
3557
- workspace,
3558
- model: config2.agents.defaults.model,
3559
- maxIterations: config2.agents.defaults.maxToolIterations,
3560
- maxTokens: config2.agents.defaults.maxTokens,
3561
- contextTokens: config2.agents.defaults.contextTokens,
3562
- braveApiKey: config2.tools.web.search.apiKey || void 0,
3563
- execConfig: config2.tools.exec,
3564
- restrictToWorkspace: config2.tools.restrictToWorkspace,
3565
- contextConfig: config2.agents.context,
3566
- config: config2,
3567
- extensionRegistry,
3568
- resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
3569
- registry: pluginRegistry,
3570
- channel,
3571
- cfg: loadConfig6(),
3572
- accountId
3573
- })
3587
+ const pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
3588
+ setPluginRuntimeBridge2({
3589
+ loadConfig: () => toPluginConfigView(loadConfig6(), pluginChannelBindings),
3590
+ writeConfigFile: async (nextConfigView) => {
3591
+ if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
3592
+ throw new Error(
3593
+ "plugin runtime writeConfigFile expects an object config"
3594
+ );
3595
+ }
3596
+ const current = loadConfig6();
3597
+ const next = mergePluginConfigView(
3598
+ current,
3599
+ nextConfigView,
3600
+ pluginChannelBindings
3601
+ );
3602
+ saveConfig5(next);
3603
+ }
3574
3604
  });
3575
- if (opts.message) {
3576
- const response = await agentLoop.processDirect({
3577
- content: opts.message,
3578
- sessionKey: opts.session ?? "cli:default",
3579
- channel: "cli",
3580
- chatId: "direct",
3581
- metadata: typeof opts.model === "string" && opts.model.trim() ? { model: opts.model.trim() } : {}
3605
+ try {
3606
+ const bus = new MessageBus2();
3607
+ const provider = this.serviceCommands.createProvider(config2) ?? this.serviceCommands.createMissingProvider(config2);
3608
+ const providerManager = new ProviderManager2({
3609
+ defaultProvider: provider,
3610
+ config: config2
3582
3611
  });
3583
- printAgentResponse(response);
3584
- return;
3585
- }
3586
- console.log(`${this.logo} Interactive mode (type exit or Ctrl+C to quit)
3587
- `);
3588
- const historyFile = join6(getDataDir7(), "history", "cli_history");
3589
- const historyDir = resolve9(historyFile, "..");
3590
- mkdirSync5(historyDir, { recursive: true });
3591
- const history = existsSync8(historyFile) ? readFileSync6(historyFile, "utf-8").split("\n").filter(Boolean) : [];
3592
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
3593
- rl.on("close", () => {
3594
- const merged = history.concat(rl.history ?? []);
3595
- writeFileSync4(historyFile, merged.join("\n"));
3596
- process.exit(0);
3597
- });
3598
- let running = true;
3599
- while (running) {
3600
- const line = await prompt(rl, "You: ");
3601
- const trimmed = line.trim();
3602
- if (!trimmed) {
3603
- continue;
3604
- }
3605
- if (EXIT_COMMANDS.has(trimmed.toLowerCase())) {
3606
- rl.close();
3607
- running = false;
3608
- break;
3612
+ const agentLoop = new AgentLoop2({
3613
+ bus,
3614
+ providerManager,
3615
+ workspace,
3616
+ model: config2.agents.defaults.model,
3617
+ maxIterations: config2.agents.defaults.maxToolIterations,
3618
+ maxTokens: config2.agents.defaults.maxTokens,
3619
+ contextTokens: config2.agents.defaults.contextTokens,
3620
+ braveApiKey: config2.tools.web.search.apiKey || void 0,
3621
+ execConfig: config2.tools.exec,
3622
+ restrictToWorkspace: config2.tools.restrictToWorkspace,
3623
+ contextConfig: config2.agents.context,
3624
+ config: config2,
3625
+ extensionRegistry,
3626
+ resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
3627
+ registry: pluginRegistry,
3628
+ channel,
3629
+ cfg: loadConfig6(),
3630
+ accountId
3631
+ })
3632
+ });
3633
+ if (opts.message) {
3634
+ const response = await agentLoop.processDirect({
3635
+ content: opts.message,
3636
+ sessionKey: opts.session ?? "cli:default",
3637
+ channel: "cli",
3638
+ chatId: "direct",
3639
+ metadata: typeof opts.model === "string" && opts.model.trim() ? { model: opts.model.trim() } : {}
3640
+ });
3641
+ printAgentResponse(response);
3642
+ return;
3609
3643
  }
3610
- const response = await agentLoop.processDirect({
3611
- content: trimmed,
3612
- sessionKey: opts.session ?? "cli:default",
3613
- metadata: typeof opts.model === "string" && opts.model.trim() ? { model: opts.model.trim() } : {}
3644
+ console.log(
3645
+ `${this.logo} Interactive mode (type exit or Ctrl+C to quit)
3646
+ `
3647
+ );
3648
+ const historyFile = join6(getDataDir7(), "history", "cli_history");
3649
+ const historyDir = resolve9(historyFile, "..");
3650
+ mkdirSync5(historyDir, { recursive: true });
3651
+ const history = existsSync8(historyFile) ? readFileSync6(historyFile, "utf-8").split("\n").filter(Boolean) : [];
3652
+ const rl = createInterface2({
3653
+ input: process.stdin,
3654
+ output: process.stdout
3655
+ });
3656
+ rl.on("close", () => {
3657
+ const merged = history.concat(
3658
+ rl.history ?? []
3659
+ );
3660
+ writeFileSync4(historyFile, merged.join("\n"));
3661
+ process.exit(0);
3614
3662
  });
3615
- printAgentResponse(response);
3663
+ let running = true;
3664
+ while (running) {
3665
+ const line = await prompt(rl, "You: ");
3666
+ const trimmed = line.trim();
3667
+ if (!trimmed) {
3668
+ continue;
3669
+ }
3670
+ if (EXIT_COMMANDS.has(trimmed.toLowerCase())) {
3671
+ rl.close();
3672
+ running = false;
3673
+ break;
3674
+ }
3675
+ const response = await agentLoop.processDirect({
3676
+ content: trimmed,
3677
+ sessionKey: opts.session ?? "cli:default",
3678
+ metadata: typeof opts.model === "string" && opts.model.trim() ? { model: opts.model.trim() } : {}
3679
+ });
3680
+ printAgentResponse(response);
3681
+ }
3682
+ } finally {
3683
+ setPluginRuntimeBridge2(null);
3616
3684
  }
3617
3685
  }
3618
3686
  async update(opts) {
@@ -3620,7 +3688,9 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3620
3688
  if (opts.timeout !== void 0) {
3621
3689
  const parsed = Number(opts.timeout);
3622
3690
  if (!Number.isFinite(parsed) || parsed <= 0) {
3623
- console.error("Invalid --timeout value. Provide milliseconds (e.g. 1200000).");
3691
+ console.error(
3692
+ "Invalid --timeout value. Provide milliseconds (e.g. 1200000)."
3693
+ );
3624
3694
  process.exit(1);
3625
3695
  }
3626
3696
  timeoutMs = parsed;
@@ -3630,7 +3700,9 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3630
3700
  const result = runSelfUpdate({ timeoutMs, cwd: process.cwd() });
3631
3701
  const printSteps = () => {
3632
3702
  for (const step of result.steps) {
3633
- console.log(`- ${step.cmd} ${step.args.join(" ")} (code ${step.code ?? "?"})`);
3703
+ console.log(
3704
+ `- ${step.cmd} ${step.args.join(" ")} (code ${step.code ?? "?"})`
3705
+ );
3634
3706
  if (step.stderr) {
3635
3707
  console.log(` stderr: ${step.stderr}`);
3636
3708
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.6.33",
3
+ "version": "0.6.35",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -38,9 +38,9 @@
38
38
  "dependencies": {
39
39
  "chokidar": "^3.6.0",
40
40
  "commander": "^12.1.0",
41
- "@nextclaw/core": "^0.6.26",
42
- "@nextclaw/server": "^0.4.15",
43
- "@nextclaw/openclaw-compat": "^0.1.19"
41
+ "@nextclaw/core": "^0.6.27",
42
+ "@nextclaw/server": "^0.4.16",
43
+ "@nextclaw/openclaw-compat": "^0.1.20"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^20.17.6",
@@ -136,13 +136,13 @@ When the gateway is already running, config changes from the UI or `nextclaw con
136
136
  - `agents.defaults.contextTokens`
137
137
  - `agents.context.*`
138
138
  - `tools.*`
139
+ - `plugins.*` (v1 hot plugin runtime: plugin registry/channel gateways/channels are hot-reloaded)
139
140
 
140
141
  Restart is still required for:
141
142
 
142
143
  - UI bind port (`--port` / `--ui-port`)
143
- - `plugins.*`
144
144
 
145
- To confirm hot reload succeeded, check gateway console logs or `${NEXTCLAW_HOME:-~/.nextclaw}/logs/service.log` for messages like `Config reload: ... applied.`
145
+ To confirm hot reload succeeded, check gateway console logs or `${NEXTCLAW_HOME:-~/.nextclaw}/logs/service.log` for messages like `Config reload: plugins reloaded.` / `Config reload: plugin channel gateways restarted.` / `Config reload: channels restarted.`
146
146
 
147
147
  UI note: **Model** page save now persists both `agents.defaults.model` and `agents.defaults.maxTokens` (refresh should keep the updated max token value).
148
148