nextclaw 0.6.32 → 0.6.34
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 +69 -48
- package/package.json +4 -4
- package/templates/USAGE.md +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -614,8 +614,7 @@ function mergePluginConfigView(baseConfig, pluginViewConfig, bindings) {
|
|
|
614
614
|
return next;
|
|
615
615
|
}
|
|
616
616
|
var PluginCommands = class {
|
|
617
|
-
constructor(
|
|
618
|
-
this.deps = deps;
|
|
617
|
+
constructor() {
|
|
619
618
|
}
|
|
620
619
|
pluginsList(opts = {}) {
|
|
621
620
|
const config2 = loadConfig();
|
|
@@ -745,19 +744,15 @@ var PluginCommands = class {
|
|
|
745
744
|
const config2 = loadConfig();
|
|
746
745
|
const next = enablePluginInConfig(config2, id);
|
|
747
746
|
saveConfig(next);
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
manualMessage: `Enabled plugin "${id}". Restart the gateway to apply.`
|
|
751
|
-
});
|
|
747
|
+
console.log(`Enabled plugin "${id}".`);
|
|
748
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
752
749
|
}
|
|
753
750
|
async pluginsDisable(id) {
|
|
754
751
|
const config2 = loadConfig();
|
|
755
752
|
const next = disablePluginInConfig(config2, id);
|
|
756
753
|
saveConfig(next);
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
manualMessage: `Disabled plugin "${id}". Restart the gateway to apply.`
|
|
760
|
-
});
|
|
754
|
+
console.log(`Disabled plugin "${id}".`);
|
|
755
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
761
756
|
}
|
|
762
757
|
async pluginsUninstall(id, opts = {}) {
|
|
763
758
|
const config2 = loadConfig();
|
|
@@ -854,10 +849,7 @@ var PluginCommands = class {
|
|
|
854
849
|
removed.push("directory");
|
|
855
850
|
}
|
|
856
851
|
console.log(`Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`);
|
|
857
|
-
|
|
858
|
-
reason: `plugin uninstalled: ${pluginId}`,
|
|
859
|
-
manualMessage: "Restart the gateway to apply changes."
|
|
860
|
-
});
|
|
852
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
861
853
|
}
|
|
862
854
|
async pluginsInstall(pathOrSpec, opts = {}) {
|
|
863
855
|
const fileSpec = this.resolveFileNpmSpecToLocalPath(pathOrSpec);
|
|
@@ -886,10 +878,7 @@ var PluginCommands = class {
|
|
|
886
878
|
});
|
|
887
879
|
saveConfig(next3);
|
|
888
880
|
console.log(`Linked plugin path: ${resolved}`);
|
|
889
|
-
|
|
890
|
-
reason: `plugin linked: ${probe.pluginId}`,
|
|
891
|
-
manualMessage: "Restart the gateway to load plugins."
|
|
892
|
-
});
|
|
881
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
893
882
|
return;
|
|
894
883
|
}
|
|
895
884
|
const result2 = await installPluginFromPath({
|
|
@@ -913,10 +902,7 @@ var PluginCommands = class {
|
|
|
913
902
|
});
|
|
914
903
|
saveConfig(next2);
|
|
915
904
|
console.log(`Installed plugin: ${result2.pluginId}`);
|
|
916
|
-
|
|
917
|
-
reason: `plugin installed: ${result2.pluginId}`,
|
|
918
|
-
manualMessage: "Restart the gateway to load plugins."
|
|
919
|
-
});
|
|
905
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
920
906
|
return;
|
|
921
907
|
}
|
|
922
908
|
if (opts.link) {
|
|
@@ -948,10 +934,7 @@ var PluginCommands = class {
|
|
|
948
934
|
});
|
|
949
935
|
saveConfig(next);
|
|
950
936
|
console.log(`Installed plugin: ${result.pluginId}`);
|
|
951
|
-
|
|
952
|
-
reason: `plugin installed: ${result.pluginId}`,
|
|
953
|
-
manualMessage: "Restart the gateway to load plugins."
|
|
954
|
-
});
|
|
937
|
+
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
955
938
|
}
|
|
956
939
|
pluginsDoctor() {
|
|
957
940
|
const config2 = loadConfig();
|
|
@@ -2194,6 +2177,9 @@ var ConfigReloader = class {
|
|
|
2194
2177
|
setApplyAgentRuntimeConfig(callback) {
|
|
2195
2178
|
this.options.applyAgentRuntimeConfig = callback;
|
|
2196
2179
|
}
|
|
2180
|
+
setReloadPlugins(callback) {
|
|
2181
|
+
this.options.reloadPlugins = callback;
|
|
2182
|
+
}
|
|
2197
2183
|
async applyReloadPlan(nextConfig) {
|
|
2198
2184
|
const changedPaths = diffConfigPaths2(this.currentConfig, nextConfig);
|
|
2199
2185
|
if (!changedPaths.length) {
|
|
@@ -2202,6 +2188,10 @@ var ConfigReloader = class {
|
|
|
2202
2188
|
this.currentConfig = nextConfig;
|
|
2203
2189
|
this.options.providerManager?.setConfig(nextConfig);
|
|
2204
2190
|
const plan = buildReloadPlan2(changedPaths);
|
|
2191
|
+
if (plan.reloadPlugins) {
|
|
2192
|
+
await this.reloadPlugins(nextConfig);
|
|
2193
|
+
console.log("Config reload: plugins reloaded.");
|
|
2194
|
+
}
|
|
2205
2195
|
if (plan.restartChannels) {
|
|
2206
2196
|
await this.reloadChannels(nextConfig);
|
|
2207
2197
|
console.log("Config reload: channels restarted.");
|
|
@@ -2297,6 +2287,12 @@ var ConfigReloader = class {
|
|
|
2297
2287
|
this.providerReloadTask = null;
|
|
2298
2288
|
}
|
|
2299
2289
|
}
|
|
2290
|
+
async reloadPlugins(nextConfig) {
|
|
2291
|
+
if (!this.options.reloadPlugins) {
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
await this.options.reloadPlugins(nextConfig);
|
|
2295
|
+
}
|
|
2300
2296
|
};
|
|
2301
2297
|
|
|
2302
2298
|
// src/cli/missing-provider.ts
|
|
@@ -2381,6 +2377,10 @@ var GatewayAgentRuntimePool = class {
|
|
|
2381
2377
|
this.routeResolver.updateConfig(config2);
|
|
2382
2378
|
this.rebuild(config2);
|
|
2383
2379
|
}
|
|
2380
|
+
applyExtensionRegistry(extensionRegistry) {
|
|
2381
|
+
this.options.extensionRegistry = extensionRegistry;
|
|
2382
|
+
this.rebuild(this.options.config);
|
|
2383
|
+
}
|
|
2384
2384
|
async processDirect(params) {
|
|
2385
2385
|
const message = {
|
|
2386
2386
|
channel: params.channel ?? "cli",
|
|
@@ -2497,8 +2497,8 @@ var ServiceCommands = class {
|
|
|
2497
2497
|
async startGateway(options = {}) {
|
|
2498
2498
|
const config2 = loadConfig5();
|
|
2499
2499
|
const workspace = getWorkspacePath5(config2.agents.defaults.workspace);
|
|
2500
|
-
|
|
2501
|
-
|
|
2500
|
+
let pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
2501
|
+
let extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
2502
2502
|
logPluginDiagnostics(pluginRegistry);
|
|
2503
2503
|
const bus = new MessageBus();
|
|
2504
2504
|
const provider = options.allowMissingProvider === true ? this.makeProvider(config2, { allowMissing: true }) : this.makeProvider(config2);
|
|
@@ -2507,6 +2507,24 @@ var ServiceCommands = class {
|
|
|
2507
2507
|
config: config2
|
|
2508
2508
|
});
|
|
2509
2509
|
const sessionManager = new SessionManager(workspace);
|
|
2510
|
+
let pluginGatewayHandles = [];
|
|
2511
|
+
const pluginGatewayLogger = {
|
|
2512
|
+
info: (message) => console.log(`[plugins] ${message}`),
|
|
2513
|
+
warn: (message) => console.warn(`[plugins] ${message}`),
|
|
2514
|
+
error: (message) => console.error(`[plugins] ${message}`),
|
|
2515
|
+
debug: (message) => console.debug(`[plugins] ${message}`)
|
|
2516
|
+
};
|
|
2517
|
+
const logPluginGatewayDiagnostics = (diagnostics) => {
|
|
2518
|
+
for (const diag of diagnostics) {
|
|
2519
|
+
const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
|
|
2520
|
+
const text = `${prefix}${diag.message}`;
|
|
2521
|
+
if (diag.level === "error") {
|
|
2522
|
+
console.error(`[plugins] ${text}`);
|
|
2523
|
+
} else {
|
|
2524
|
+
console.warn(`[plugins] ${text}`);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
};
|
|
2510
2528
|
const cronStorePath = join4(getDataDir5(), "cron", "jobs.json");
|
|
2511
2529
|
const cron2 = new CronService2(cronStorePath);
|
|
2512
2530
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
@@ -2568,7 +2586,26 @@ var ServiceCommands = class {
|
|
|
2568
2586
|
})
|
|
2569
2587
|
});
|
|
2570
2588
|
reloader.setApplyAgentRuntimeConfig((nextConfig) => runtimePool.applyRuntimeConfig(nextConfig));
|
|
2571
|
-
|
|
2589
|
+
reloader.setReloadPlugins(async (nextConfig) => {
|
|
2590
|
+
const nextWorkspace = getWorkspacePath5(nextConfig.agents.defaults.workspace);
|
|
2591
|
+
const nextPluginRegistry = loadPluginRegistry(nextConfig, nextWorkspace);
|
|
2592
|
+
const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
|
|
2593
|
+
logPluginDiagnostics(nextPluginRegistry);
|
|
2594
|
+
await stopPluginChannelGateways(pluginGatewayHandles);
|
|
2595
|
+
const startedPluginGateways = await startPluginChannelGateways({
|
|
2596
|
+
registry: nextPluginRegistry,
|
|
2597
|
+
logger: pluginGatewayLogger
|
|
2598
|
+
});
|
|
2599
|
+
pluginGatewayHandles = startedPluginGateways.handles;
|
|
2600
|
+
logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
|
|
2601
|
+
pluginRegistry = nextPluginRegistry;
|
|
2602
|
+
extensionRegistry = nextExtensionRegistry;
|
|
2603
|
+
pluginChannelBindings = getPluginChannelBindings2(nextPluginRegistry);
|
|
2604
|
+
runtimePool.applyExtensionRegistry(nextExtensionRegistry);
|
|
2605
|
+
runtimePool.applyRuntimeConfig(nextConfig);
|
|
2606
|
+
console.log("Config reload: plugin channel gateways restarted.");
|
|
2607
|
+
});
|
|
2608
|
+
let pluginChannelBindings = getPluginChannelBindings2(pluginRegistry);
|
|
2572
2609
|
setPluginRuntimeBridge({
|
|
2573
2610
|
loadConfig: () => toPluginConfigView(loadConfig5(), pluginChannelBindings),
|
|
2574
2611
|
writeConfigFile: async (nextConfigView) => {
|
|
@@ -2658,27 +2695,13 @@ var ServiceCommands = class {
|
|
|
2658
2695
|
watcher.on("unlink", () => reloader.scheduleReload("config unlink"));
|
|
2659
2696
|
await cron2.start();
|
|
2660
2697
|
await heartbeat.start();
|
|
2661
|
-
let pluginGatewayHandles = [];
|
|
2662
2698
|
try {
|
|
2663
2699
|
const startedPluginGateways = await startPluginChannelGateways({
|
|
2664
2700
|
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
|
-
}
|
|
2701
|
+
logger: pluginGatewayLogger
|
|
2671
2702
|
});
|
|
2672
2703
|
pluginGatewayHandles = startedPluginGateways.handles;
|
|
2673
|
-
|
|
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
|
-
}
|
|
2704
|
+
logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
|
|
2682
2705
|
await reloader.getChannels().startAll();
|
|
2683
2706
|
await this.wakeFromRestartSentinel({ bus, sessionManager });
|
|
2684
2707
|
await runtimePool.run();
|
|
@@ -3236,9 +3259,7 @@ var CliRuntime = class {
|
|
|
3236
3259
|
this.configCommands = new ConfigCommands({
|
|
3237
3260
|
requestRestart: (params) => this.requestRestart(params)
|
|
3238
3261
|
});
|
|
3239
|
-
this.pluginCommands = new PluginCommands(
|
|
3240
|
-
requestRestart: (params) => this.requestRestart(params)
|
|
3241
|
-
});
|
|
3262
|
+
this.pluginCommands = new PluginCommands();
|
|
3242
3263
|
this.channelCommands = new ChannelCommands({
|
|
3243
3264
|
logo: this.logo,
|
|
3244
3265
|
getBridgeDir: () => this.workspaceManager.getBridgeDir(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nextclaw",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.34",
|
|
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.
|
|
42
|
-
"@nextclaw/server": "^0.4.
|
|
43
|
-
"@nextclaw/openclaw-compat": "^0.1.
|
|
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",
|
package/templates/USAGE.md
CHANGED
|
@@ -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:
|
|
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
|
|