nextclaw 0.5.6 → 0.6.1

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
@@ -6,13 +6,13 @@ import { APP_NAME as APP_NAME5, APP_TAGLINE } from "@nextclaw/core";
6
6
 
7
7
  // src/cli/runtime.ts
8
8
  import {
9
- loadConfig as loadConfig6,
10
- saveConfig as saveConfig5,
9
+ loadConfig as loadConfig5,
10
+ saveConfig as saveConfig3,
11
11
  getConfigPath as getConfigPath3,
12
12
  getDataDir as getDataDir6,
13
13
  ConfigSchema as ConfigSchema2,
14
- getWorkspacePath as getWorkspacePath5,
15
- expandHome as expandHome2,
14
+ getWorkspacePath as getWorkspacePath3,
15
+ expandHome,
16
16
  MessageBus as MessageBus2,
17
17
  AgentLoop as AgentLoop2,
18
18
  ProviderManager as ProviderManager2,
@@ -20,10 +20,9 @@ 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";
24
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
25
- import { join as join6, resolve as resolve8 } from "path";
26
- import { createInterface as createInterface2 } from "readline";
23
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
24
+ import { join as join6, resolve as resolve7 } from "path";
25
+ import { createInterface } from "readline";
27
26
  import { fileURLToPath as fileURLToPath3 } from "url";
28
27
  import { spawn as spawn3 } from "child_process";
29
28
 
@@ -255,7 +254,7 @@ async function waitForExit(pid, timeoutMs) {
255
254
  if (!isProcessRunning(pid)) {
256
255
  return true;
257
256
  }
258
- await new Promise((resolve9) => setTimeout(resolve9, 200));
257
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
259
258
  }
260
259
  return !isProcessRunning(pid);
261
260
  }
@@ -345,8 +344,8 @@ function printAgentResponse(response) {
345
344
  async function prompt(rl, question) {
346
345
  rl.setPrompt(question);
347
346
  rl.prompt();
348
- return new Promise((resolve9) => {
349
- rl.once("line", (line) => resolve9(line));
347
+ return new Promise((resolve8) => {
348
+ rl.once("line", (line) => resolve8(line));
350
349
  });
351
350
  }
352
351
 
@@ -392,549 +391,8 @@ function runSelfUpdate(options = {}) {
392
391
  return { ok: false, error: "no update strategy available", strategy: "none", steps };
393
392
  }
394
393
 
395
- // src/cli/commands/plugins.ts
396
- import {
397
- addPluginLoadPath,
398
- buildPluginStatusReport,
399
- disablePluginInConfig,
400
- enablePluginInConfig,
401
- installPluginFromNpmSpec,
402
- installPluginFromPath,
403
- loadOpenClawPlugins,
404
- recordPluginInstall,
405
- resolveUninstallDirectoryTarget,
406
- uninstallPlugin
407
- } from "@nextclaw/openclaw-compat";
408
- import {
409
- loadConfig,
410
- saveConfig,
411
- getWorkspacePath,
412
- PROVIDERS,
413
- expandHome
414
- } from "@nextclaw/core";
415
- import { createInterface } from "readline";
416
- import { existsSync as existsSync3 } from "fs";
417
- import { resolve as resolve4 } from "path";
418
- function loadPluginRegistry(config2, workspaceDir) {
419
- return loadOpenClawPlugins({
420
- config: config2,
421
- workspaceDir,
422
- reservedToolNames: [
423
- "read_file",
424
- "write_file",
425
- "edit_file",
426
- "list_dir",
427
- "exec",
428
- "web_search",
429
- "web_fetch",
430
- "message",
431
- "spawn",
432
- "sessions_list",
433
- "sessions_history",
434
- "sessions_send",
435
- "memory_search",
436
- "memory_get",
437
- "subagents",
438
- "gateway",
439
- "cron"
440
- ],
441
- reservedChannelIds: Object.keys(config2.channels),
442
- reservedProviderIds: PROVIDERS.map((provider) => provider.name),
443
- logger: {
444
- info: (message) => console.log(message),
445
- warn: (message) => console.warn(message),
446
- error: (message) => console.error(message),
447
- debug: (message) => console.debug(message)
448
- }
449
- });
450
- }
451
- function toExtensionRegistry(pluginRegistry) {
452
- return {
453
- tools: pluginRegistry.tools.map((tool) => ({
454
- extensionId: tool.pluginId,
455
- factory: tool.factory,
456
- names: tool.names,
457
- optional: tool.optional,
458
- source: tool.source
459
- })),
460
- channels: pluginRegistry.channels.map((channel) => ({
461
- extensionId: channel.pluginId,
462
- channel: channel.channel,
463
- source: channel.source
464
- })),
465
- diagnostics: pluginRegistry.diagnostics.map((diag) => ({
466
- level: diag.level,
467
- message: diag.message,
468
- extensionId: diag.pluginId,
469
- source: diag.source
470
- }))
471
- };
472
- }
473
- function logPluginDiagnostics(registry) {
474
- for (const diag of registry.diagnostics) {
475
- const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
476
- const text = `${prefix}${diag.message}`;
477
- if (diag.level === "error") {
478
- console.error(`[plugins] ${text}`);
479
- } else {
480
- console.warn(`[plugins] ${text}`);
481
- }
482
- }
483
- }
484
- function toPluginConfigView(config2, bindings) {
485
- const view = JSON.parse(JSON.stringify(config2));
486
- const channels2 = view.channels && typeof view.channels === "object" && !Array.isArray(view.channels) ? { ...view.channels } : {};
487
- for (const binding of bindings) {
488
- const pluginConfig = config2.plugins.entries?.[binding.pluginId]?.config;
489
- if (!pluginConfig || typeof pluginConfig !== "object" || Array.isArray(pluginConfig)) {
490
- continue;
491
- }
492
- channels2[binding.channelId] = JSON.parse(JSON.stringify(pluginConfig));
493
- }
494
- view.channels = channels2;
495
- return view;
496
- }
497
- function mergePluginConfigView(baseConfig, pluginViewConfig, bindings) {
498
- const next = JSON.parse(JSON.stringify(baseConfig));
499
- const pluginChannels = pluginViewConfig.channels && typeof pluginViewConfig.channels === "object" && !Array.isArray(pluginViewConfig.channels) ? pluginViewConfig.channels : {};
500
- const entries = { ...next.plugins.entries ?? {} };
501
- for (const binding of bindings) {
502
- if (!Object.prototype.hasOwnProperty.call(pluginChannels, binding.channelId)) {
503
- continue;
504
- }
505
- const channelConfig = pluginChannels[binding.channelId];
506
- if (!channelConfig || typeof channelConfig !== "object" || Array.isArray(channelConfig)) {
507
- continue;
508
- }
509
- entries[binding.pluginId] = {
510
- ...entries[binding.pluginId] ?? {},
511
- config: channelConfig
512
- };
513
- }
514
- next.plugins = {
515
- ...next.plugins,
516
- entries
517
- };
518
- return next;
519
- }
520
- var PluginCommands = class {
521
- constructor(deps) {
522
- this.deps = deps;
523
- }
524
- pluginsList(opts = {}) {
525
- const config2 = loadConfig();
526
- const workspaceDir = getWorkspacePath(config2.agents.defaults.workspace);
527
- const report = buildPluginStatusReport({
528
- config: config2,
529
- workspaceDir,
530
- reservedChannelIds: Object.keys(config2.channels),
531
- reservedProviderIds: PROVIDERS.map((provider) => provider.name)
532
- });
533
- const list = opts.enabled ? report.plugins.filter((plugin) => plugin.status === "loaded") : report.plugins;
534
- if (opts.json) {
535
- console.log(
536
- JSON.stringify(
537
- {
538
- workspaceDir,
539
- plugins: list,
540
- diagnostics: report.diagnostics
541
- },
542
- null,
543
- 2
544
- )
545
- );
546
- return;
547
- }
548
- if (list.length === 0) {
549
- console.log("No plugins discovered.");
550
- return;
551
- }
552
- for (const plugin of list) {
553
- const status = plugin.status === "loaded" ? "loaded" : plugin.status === "disabled" ? "disabled" : "error";
554
- const title = plugin.name && plugin.name !== plugin.id ? `${plugin.name} (${plugin.id})` : plugin.id;
555
- if (!opts.verbose) {
556
- const desc = plugin.description ? plugin.description.length > 80 ? `${plugin.description.slice(0, 77)}...` : plugin.description : "(no description)";
557
- console.log(`${title} ${status} - ${desc}`);
558
- continue;
559
- }
560
- console.log(`${title} ${status}`);
561
- console.log(` source: ${plugin.source}`);
562
- console.log(` origin: ${plugin.origin}`);
563
- if (plugin.version) {
564
- console.log(` version: ${plugin.version}`);
565
- }
566
- if (plugin.toolNames.length > 0) {
567
- console.log(` tools: ${plugin.toolNames.join(", ")}`);
568
- }
569
- if (plugin.channelIds.length > 0) {
570
- console.log(` channels: ${plugin.channelIds.join(", ")}`);
571
- }
572
- if (plugin.providerIds.length > 0) {
573
- console.log(` providers: ${plugin.providerIds.join(", ")}`);
574
- }
575
- if (plugin.error) {
576
- console.log(` error: ${plugin.error}`);
577
- }
578
- console.log("");
579
- }
580
- }
581
- pluginsInfo(id, opts = {}) {
582
- const config2 = loadConfig();
583
- const workspaceDir = getWorkspacePath(config2.agents.defaults.workspace);
584
- const report = buildPluginStatusReport({
585
- config: config2,
586
- workspaceDir,
587
- reservedChannelIds: Object.keys(config2.channels),
588
- reservedProviderIds: PROVIDERS.map((provider) => provider.name)
589
- });
590
- const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
591
- if (!plugin) {
592
- console.error(`Plugin not found: ${id}`);
593
- process.exit(1);
594
- }
595
- if (opts.json) {
596
- console.log(JSON.stringify(plugin, null, 2));
597
- return;
598
- }
599
- const install = config2.plugins.installs?.[plugin.id];
600
- const lines = [];
601
- lines.push(plugin.name || plugin.id);
602
- if (plugin.name && plugin.name !== plugin.id) {
603
- lines.push(`id: ${plugin.id}`);
604
- }
605
- if (plugin.description) {
606
- lines.push(plugin.description);
607
- }
608
- lines.push("");
609
- lines.push(`Status: ${plugin.status}`);
610
- lines.push(`Source: ${plugin.source}`);
611
- lines.push(`Origin: ${plugin.origin}`);
612
- if (plugin.version) {
613
- lines.push(`Version: ${plugin.version}`);
614
- }
615
- if (plugin.toolNames.length > 0) {
616
- lines.push(`Tools: ${plugin.toolNames.join(", ")}`);
617
- }
618
- if (plugin.channelIds.length > 0) {
619
- lines.push(`Channels: ${plugin.channelIds.join(", ")}`);
620
- }
621
- if (plugin.providerIds.length > 0) {
622
- lines.push(`Providers: ${plugin.providerIds.join(", ")}`);
623
- }
624
- if (plugin.error) {
625
- lines.push(`Error: ${plugin.error}`);
626
- }
627
- if (install) {
628
- lines.push("");
629
- lines.push(`Install: ${install.source}`);
630
- if (install.spec) {
631
- lines.push(`Spec: ${install.spec}`);
632
- }
633
- if (install.sourcePath) {
634
- lines.push(`Source path: ${install.sourcePath}`);
635
- }
636
- if (install.installPath) {
637
- lines.push(`Install path: ${install.installPath}`);
638
- }
639
- if (install.version) {
640
- lines.push(`Recorded version: ${install.version}`);
641
- }
642
- if (install.installedAt) {
643
- lines.push(`Installed at: ${install.installedAt}`);
644
- }
645
- }
646
- console.log(lines.join("\n"));
647
- }
648
- async pluginsEnable(id) {
649
- const config2 = loadConfig();
650
- const next = enablePluginInConfig(config2, id);
651
- saveConfig(next);
652
- await this.deps.requestRestart({
653
- reason: `plugin enabled: ${id}`,
654
- manualMessage: `Enabled plugin "${id}". Restart the gateway to apply.`
655
- });
656
- }
657
- async pluginsDisable(id) {
658
- const config2 = loadConfig();
659
- const next = disablePluginInConfig(config2, id);
660
- saveConfig(next);
661
- await this.deps.requestRestart({
662
- reason: `plugin disabled: ${id}`,
663
- manualMessage: `Disabled plugin "${id}". Restart the gateway to apply.`
664
- });
665
- }
666
- async pluginsUninstall(id, opts = {}) {
667
- const config2 = loadConfig();
668
- const workspaceDir = getWorkspacePath(config2.agents.defaults.workspace);
669
- const report = buildPluginStatusReport({
670
- config: config2,
671
- workspaceDir,
672
- reservedChannelIds: Object.keys(config2.channels),
673
- reservedProviderIds: PROVIDERS.map((provider) => provider.name)
674
- });
675
- const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
676
- if (opts.keepConfig) {
677
- console.log("`--keep-config` is deprecated, use `--keep-files`.");
678
- }
679
- const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
680
- const pluginId = plugin?.id ?? id;
681
- const hasEntry = pluginId in (config2.plugins.entries ?? {});
682
- const hasInstall = pluginId in (config2.plugins.installs ?? {});
683
- if (!hasEntry && !hasInstall) {
684
- if (plugin) {
685
- console.error(
686
- `Plugin "${pluginId}" is not managed by plugins config/install records and cannot be uninstalled.`
687
- );
688
- } else {
689
- console.error(`Plugin not found: ${id}`);
690
- }
691
- process.exit(1);
692
- }
693
- const install = config2.plugins.installs?.[pluginId];
694
- const isLinked = install?.source === "path" && (!install.installPath || !install.sourcePath || resolve4(install.installPath) === resolve4(install.sourcePath));
695
- const preview = [];
696
- if (hasEntry) {
697
- preview.push("config entry");
698
- }
699
- if (hasInstall) {
700
- preview.push("install record");
701
- }
702
- if (config2.plugins.allow?.includes(pluginId)) {
703
- preview.push("allowlist entry");
704
- }
705
- if (isLinked && install?.sourcePath && config2.plugins.load?.paths?.includes(install.sourcePath)) {
706
- preview.push("load path");
707
- }
708
- const deleteTarget = !keepFiles ? resolveUninstallDirectoryTarget({
709
- pluginId,
710
- hasInstall,
711
- installRecord: install
712
- }) : null;
713
- if (deleteTarget) {
714
- preview.push(`directory: ${deleteTarget}`);
715
- }
716
- const pluginName = plugin?.name || pluginId;
717
- const pluginTitle = pluginName !== pluginId ? `${pluginName} (${pluginId})` : pluginName;
718
- console.log(`Plugin: ${pluginTitle}`);
719
- console.log(`Will remove: ${preview.length > 0 ? preview.join(", ") : "(nothing)"}`);
720
- if (opts.dryRun) {
721
- console.log("Dry run, no changes made.");
722
- return;
723
- }
724
- if (!opts.force) {
725
- const confirmed = await this.confirmYesNo(`Uninstall plugin "${pluginId}"?`);
726
- if (!confirmed) {
727
- console.log("Cancelled.");
728
- return;
729
- }
730
- }
731
- const result = await uninstallPlugin({
732
- config: config2,
733
- pluginId,
734
- deleteFiles: !keepFiles
735
- });
736
- if (!result.ok) {
737
- console.error(result.error);
738
- process.exit(1);
739
- }
740
- for (const warning of result.warnings) {
741
- console.warn(warning);
742
- }
743
- saveConfig(result.config);
744
- const removed = [];
745
- if (result.actions.entry) {
746
- removed.push("config entry");
747
- }
748
- if (result.actions.install) {
749
- removed.push("install record");
750
- }
751
- if (result.actions.allowlist) {
752
- removed.push("allowlist");
753
- }
754
- if (result.actions.loadPath) {
755
- removed.push("load path");
756
- }
757
- if (result.actions.directory) {
758
- removed.push("directory");
759
- }
760
- console.log(`Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`);
761
- await this.deps.requestRestart({
762
- reason: `plugin uninstalled: ${pluginId}`,
763
- manualMessage: "Restart the gateway to apply changes."
764
- });
765
- }
766
- async pluginsInstall(pathOrSpec, opts = {}) {
767
- const fileSpec = this.resolveFileNpmSpecToLocalPath(pathOrSpec);
768
- if (fileSpec && !fileSpec.ok) {
769
- console.error(fileSpec.error);
770
- process.exit(1);
771
- }
772
- const normalized = fileSpec && fileSpec.ok ? fileSpec.path : pathOrSpec;
773
- const resolved = resolve4(expandHome(normalized));
774
- const config2 = loadConfig();
775
- if (existsSync3(resolved)) {
776
- if (opts.link) {
777
- const probe = await installPluginFromPath({ path: resolved, dryRun: true });
778
- if (!probe.ok) {
779
- console.error(probe.error);
780
- process.exit(1);
781
- }
782
- let next3 = addPluginLoadPath(config2, resolved);
783
- next3 = enablePluginInConfig(next3, probe.pluginId);
784
- next3 = recordPluginInstall(next3, {
785
- pluginId: probe.pluginId,
786
- source: "path",
787
- sourcePath: resolved,
788
- installPath: resolved,
789
- version: probe.version
790
- });
791
- saveConfig(next3);
792
- console.log(`Linked plugin path: ${resolved}`);
793
- await this.deps.requestRestart({
794
- reason: `plugin linked: ${probe.pluginId}`,
795
- manualMessage: "Restart the gateway to load plugins."
796
- });
797
- return;
798
- }
799
- const result2 = await installPluginFromPath({
800
- path: resolved,
801
- logger: {
802
- info: (message) => console.log(message),
803
- warn: (message) => console.warn(message)
804
- }
805
- });
806
- if (!result2.ok) {
807
- console.error(result2.error);
808
- process.exit(1);
809
- }
810
- let next2 = enablePluginInConfig(config2, result2.pluginId);
811
- next2 = recordPluginInstall(next2, {
812
- pluginId: result2.pluginId,
813
- source: this.isArchivePath(resolved) ? "archive" : "path",
814
- sourcePath: resolved,
815
- installPath: result2.targetDir,
816
- version: result2.version
817
- });
818
- saveConfig(next2);
819
- console.log(`Installed plugin: ${result2.pluginId}`);
820
- await this.deps.requestRestart({
821
- reason: `plugin installed: ${result2.pluginId}`,
822
- manualMessage: "Restart the gateway to load plugins."
823
- });
824
- return;
825
- }
826
- if (opts.link) {
827
- console.error("`--link` requires a local path.");
828
- process.exit(1);
829
- }
830
- if (this.looksLikePath(pathOrSpec)) {
831
- console.error(`Path not found: ${resolved}`);
832
- process.exit(1);
833
- }
834
- const result = await installPluginFromNpmSpec({
835
- spec: pathOrSpec,
836
- logger: {
837
- info: (message) => console.log(message),
838
- warn: (message) => console.warn(message)
839
- }
840
- });
841
- if (!result.ok) {
842
- console.error(result.error);
843
- process.exit(1);
844
- }
845
- let next = enablePluginInConfig(config2, result.pluginId);
846
- next = recordPluginInstall(next, {
847
- pluginId: result.pluginId,
848
- source: "npm",
849
- spec: pathOrSpec,
850
- installPath: result.targetDir,
851
- version: result.version
852
- });
853
- saveConfig(next);
854
- console.log(`Installed plugin: ${result.pluginId}`);
855
- await this.deps.requestRestart({
856
- reason: `plugin installed: ${result.pluginId}`,
857
- manualMessage: "Restart the gateway to load plugins."
858
- });
859
- }
860
- pluginsDoctor() {
861
- const config2 = loadConfig();
862
- const workspaceDir = getWorkspacePath(config2.agents.defaults.workspace);
863
- const report = buildPluginStatusReport({
864
- config: config2,
865
- workspaceDir,
866
- reservedChannelIds: Object.keys(config2.channels),
867
- reservedProviderIds: PROVIDERS.map((provider) => provider.name)
868
- });
869
- const pluginErrors = report.plugins.filter((plugin) => plugin.status === "error");
870
- const diagnostics = report.diagnostics.filter((diag) => diag.level === "error");
871
- if (pluginErrors.length === 0 && diagnostics.length === 0) {
872
- console.log("No plugin issues detected.");
873
- return;
874
- }
875
- if (pluginErrors.length > 0) {
876
- console.log("Plugin errors:");
877
- for (const entry of pluginErrors) {
878
- console.log(`- ${entry.id}: ${entry.error ?? "failed to load"} (${entry.source})`);
879
- }
880
- }
881
- if (diagnostics.length > 0) {
882
- if (pluginErrors.length > 0) {
883
- console.log("");
884
- }
885
- console.log("Diagnostics:");
886
- for (const diag of diagnostics) {
887
- const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
888
- console.log(`- ${prefix}${diag.message}`);
889
- }
890
- }
891
- }
892
- async confirmYesNo(question) {
893
- const rl = createInterface({
894
- input: process.stdin,
895
- output: process.stdout
896
- });
897
- const answer = await new Promise((resolve9) => {
898
- rl.question(`${question} [y/N] `, (line) => resolve9(line));
899
- });
900
- rl.close();
901
- const normalized = answer.trim().toLowerCase();
902
- return normalized === "y" || normalized === "yes";
903
- }
904
- resolveFileNpmSpecToLocalPath(raw) {
905
- const trimmed = raw.trim();
906
- if (!trimmed.toLowerCase().startsWith("file:")) {
907
- return null;
908
- }
909
- const rest = trimmed.slice("file:".length);
910
- if (!rest) {
911
- return { ok: false, error: "unsupported file: spec: missing path" };
912
- }
913
- if (rest.startsWith("///")) {
914
- return { ok: true, path: rest.slice(2) };
915
- }
916
- if (rest.startsWith("//localhost/")) {
917
- return { ok: true, path: rest.slice("//localhost".length) };
918
- }
919
- if (rest.startsWith("//")) {
920
- return {
921
- ok: false,
922
- error: 'unsupported file: URL host (expected "file:<path>" or "file:///abs/path")'
923
- };
924
- }
925
- return { ok: true, path: rest };
926
- }
927
- looksLikePath(raw) {
928
- return raw.startsWith(".") || raw.startsWith("~") || raw.startsWith("/") || raw.endsWith(".ts") || raw.endsWith(".js") || raw.endsWith(".mjs") || raw.endsWith(".cjs") || raw.endsWith(".tgz") || raw.endsWith(".tar.gz") || raw.endsWith(".tar") || raw.endsWith(".zip");
929
- }
930
- isArchivePath(filePath) {
931
- const lower = filePath.toLowerCase();
932
- return lower.endsWith(".zip") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz") || lower.endsWith(".tar");
933
- }
934
- };
935
-
936
394
  // src/cli/commands/config.ts
937
- import { buildReloadPlan, diffConfigPaths, loadConfig as loadConfig2, saveConfig as saveConfig2 } from "@nextclaw/core";
395
+ import { buildReloadPlan, diffConfigPaths, loadConfig, saveConfig } from "@nextclaw/core";
938
396
 
939
397
  // src/cli/config-path.ts
940
398
  function isIndexSegment(raw) {
@@ -1129,7 +587,7 @@ var ConfigCommands = class {
1129
587
  this.deps = deps;
1130
588
  }
1131
589
  configGet(pathExpr, opts = {}) {
1132
- const config2 = loadConfig2();
590
+ const config2 = loadConfig();
1133
591
  let parsedPath;
1134
592
  try {
1135
593
  parsedPath = parseRequiredConfigPath(pathExpr);
@@ -1171,7 +629,7 @@ var ConfigCommands = class {
1171
629
  process.exit(1);
1172
630
  return;
1173
631
  }
1174
- const prevConfig = loadConfig2();
632
+ const prevConfig = loadConfig();
1175
633
  const nextConfig = structuredClone(prevConfig);
1176
634
  try {
1177
635
  setAtConfigPath(nextConfig, parsedPath, parsedValue);
@@ -1180,7 +638,7 @@ var ConfigCommands = class {
1180
638
  process.exit(1);
1181
639
  return;
1182
640
  }
1183
- saveConfig2(nextConfig);
641
+ saveConfig(nextConfig);
1184
642
  await this.requestRestartForConfigDiff({
1185
643
  prevConfig,
1186
644
  nextConfig,
@@ -1197,7 +655,7 @@ var ConfigCommands = class {
1197
655
  process.exit(1);
1198
656
  return;
1199
657
  }
1200
- const prevConfig = loadConfig2();
658
+ const prevConfig = loadConfig();
1201
659
  const nextConfig = structuredClone(prevConfig);
1202
660
  const removed = unsetAtConfigPath(nextConfig, parsedPath);
1203
661
  if (!removed) {
@@ -1205,7 +663,7 @@ var ConfigCommands = class {
1205
663
  process.exit(1);
1206
664
  return;
1207
665
  }
1208
- saveConfig2(nextConfig);
666
+ saveConfig(nextConfig);
1209
667
  await this.requestRestartForConfigDiff({
1210
668
  prevConfig,
1211
669
  nextConfig,
@@ -1231,14 +689,13 @@ var ConfigCommands = class {
1231
689
 
1232
690
  // src/cli/commands/channels.ts
1233
691
  import { spawnSync as spawnSync3 } from "child_process";
1234
- import { getWorkspacePath as getWorkspacePath2, loadConfig as loadConfig3, saveConfig as saveConfig3, PROVIDERS as PROVIDERS2 } from "@nextclaw/core";
1235
- import { buildPluginStatusReport as buildPluginStatusReport2, enablePluginInConfig as enablePluginInConfig2, getPluginChannelBindings } from "@nextclaw/openclaw-compat";
692
+ import { loadConfig as loadConfig2 } from "@nextclaw/core";
1236
693
  var ChannelCommands = class {
1237
694
  constructor(deps) {
1238
695
  this.deps = deps;
1239
696
  }
1240
697
  channelsStatus() {
1241
- const config2 = loadConfig3();
698
+ const config2 = loadConfig2();
1242
699
  console.log("Channel Status");
1243
700
  console.log(`WhatsApp: ${config2.channels.whatsapp.enabled ? "\u2713" : "\u2717"}`);
1244
701
  console.log(`Discord: ${config2.channels.discord.enabled ? "\u2713" : "\u2717"}`);
@@ -1247,21 +704,6 @@ var ChannelCommands = class {
1247
704
  console.log(`Telegram: ${config2.channels.telegram.enabled ? "\u2713" : "\u2717"}`);
1248
705
  console.log(`Slack: ${config2.channels.slack.enabled ? "\u2713" : "\u2717"}`);
1249
706
  console.log(`QQ: ${config2.channels.qq.enabled ? "\u2713" : "\u2717"}`);
1250
- const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
1251
- const report = buildPluginStatusReport2({
1252
- config: config2,
1253
- workspaceDir,
1254
- reservedChannelIds: Object.keys(config2.channels),
1255
- reservedProviderIds: PROVIDERS2.map((provider) => provider.name)
1256
- });
1257
- const pluginChannels = report.plugins.filter((plugin) => plugin.status === "loaded" && plugin.channelIds.length > 0);
1258
- if (pluginChannels.length > 0) {
1259
- console.log("Plugin Channels:");
1260
- for (const plugin of pluginChannels) {
1261
- const channels2 = plugin.channelIds.join(", ");
1262
- console.log(`- ${channels2} (plugin: ${plugin.id})`);
1263
- }
1264
- }
1265
707
  }
1266
708
  channelsLogin() {
1267
709
  const bridgeDir = this.deps.getBridgeDir();
@@ -1272,62 +714,6 @@ var ChannelCommands = class {
1272
714
  console.error(`Bridge failed: ${result.status ?? 1}`);
1273
715
  }
1274
716
  }
1275
- async channelsAdd(opts) {
1276
- const channelId = opts.channel?.trim();
1277
- if (!channelId) {
1278
- console.error("--channel is required");
1279
- process.exit(1);
1280
- }
1281
- const config2 = loadConfig3();
1282
- const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
1283
- const pluginRegistry = loadPluginRegistry(config2, workspaceDir);
1284
- const bindings = getPluginChannelBindings(pluginRegistry);
1285
- const binding = bindings.find((entry) => entry.channelId === channelId || entry.pluginId === channelId);
1286
- if (!binding) {
1287
- console.error(`No plugin channel found for: ${channelId}`);
1288
- process.exit(1);
1289
- }
1290
- const setup = binding.channel.setup;
1291
- if (!setup?.applyAccountConfig) {
1292
- console.error(`Channel "${binding.channelId}" does not support setup.`);
1293
- process.exit(1);
1294
- }
1295
- const input = {
1296
- name: opts.name,
1297
- token: opts.token,
1298
- code: opts.code,
1299
- url: opts.url,
1300
- httpUrl: opts.httpUrl
1301
- };
1302
- const currentView = toPluginConfigView(config2, bindings);
1303
- const accountId = binding.channel.config?.defaultAccountId?.(currentView) ?? "default";
1304
- const validateError = setup.validateInput?.({
1305
- cfg: currentView,
1306
- input,
1307
- accountId
1308
- });
1309
- if (validateError) {
1310
- console.error(`Channel setup validation failed: ${validateError}`);
1311
- process.exit(1);
1312
- }
1313
- const nextView = setup.applyAccountConfig({
1314
- cfg: currentView,
1315
- input,
1316
- accountId
1317
- });
1318
- if (!nextView || typeof nextView !== "object" || Array.isArray(nextView)) {
1319
- console.error("Channel setup returned invalid config payload.");
1320
- process.exit(1);
1321
- }
1322
- let next = mergePluginConfigView(config2, nextView, bindings);
1323
- next = enablePluginInConfig2(next, binding.pluginId);
1324
- saveConfig3(next);
1325
- console.log(`Configured channel "${binding.channelId}" via plugin "${binding.pluginId}".`);
1326
- await this.deps.requestRestart({
1327
- reason: `channel configured via plugin: ${binding.pluginId}`,
1328
- manualMessage: "Restart the gateway to apply changes."
1329
- });
1330
- }
1331
717
  };
1332
718
 
1333
719
  // src/cli/commands/cron.ts
@@ -1408,15 +794,15 @@ var CronCommands = class {
1408
794
 
1409
795
  // src/cli/commands/diagnostics.ts
1410
796
  import { createServer as createNetServer } from "net";
1411
- import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
1412
- import { resolve as resolve5 } from "path";
797
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
798
+ import { resolve as resolve4 } from "path";
1413
799
  import {
1414
800
  APP_NAME,
1415
801
  getConfigPath,
1416
802
  getDataDir as getDataDir3,
1417
- getWorkspacePath as getWorkspacePath3,
1418
- loadConfig as loadConfig4,
1419
- PROVIDERS as PROVIDERS3
803
+ getWorkspacePath,
804
+ loadConfig as loadConfig3,
805
+ PROVIDERS
1420
806
  } from "@nextclaw/core";
1421
807
  var DiagnosticsCommands = class {
1422
808
  constructor(deps) {
@@ -1577,9 +963,9 @@ var DiagnosticsCommands = class {
1577
963
  }
1578
964
  async collectRuntimeStatus(params) {
1579
965
  const configPath = getConfigPath();
1580
- const config2 = loadConfig4();
1581
- const workspacePath = getWorkspacePath3(config2.agents.defaults.workspace);
1582
- const serviceStatePath = resolve5(getDataDir3(), "run", "service.json");
966
+ const config2 = loadConfig3();
967
+ const workspacePath = getWorkspacePath(config2.agents.defaults.workspace);
968
+ const serviceStatePath = resolve4(getDataDir3(), "run", "service.json");
1583
969
  const fixActions = [];
1584
970
  let serviceState = readServiceState();
1585
971
  if (params.fix && serviceState && !isProcessRunning(serviceState.pid)) {
@@ -1598,7 +984,7 @@ var DiagnosticsCommands = class {
1598
984
  const managedHealth = running && managedApiUrl ? await this.probeApiHealth(`${managedApiUrl}/health`) : { state: "unreachable", detail: "service not running" };
1599
985
  const configuredHealth = await this.probeApiHealth(`${configuredApiUrl}/health`, 900);
1600
986
  const orphanSuspected = !running && configuredHealth.state === "ok";
1601
- const providers = PROVIDERS3.map((spec) => {
987
+ const providers = PROVIDERS.map((spec) => {
1602
988
  const provider = config2.providers[spec.name];
1603
989
  if (!provider) {
1604
990
  return { name: spec.displayName ?? spec.name, configured: false, detail: "missing config" };
@@ -1618,11 +1004,11 @@ var DiagnosticsCommands = class {
1618
1004
  });
1619
1005
  const issues = [];
1620
1006
  const recommendations = [];
1621
- if (!existsSync4(configPath)) {
1007
+ if (!existsSync3(configPath)) {
1622
1008
  issues.push("Config file is missing.");
1623
1009
  recommendations.push(`Run ${APP_NAME} init to create config files.`);
1624
1010
  }
1625
- if (!existsSync4(workspacePath)) {
1011
+ if (!existsSync3(workspacePath)) {
1626
1012
  issues.push("Workspace directory does not exist.");
1627
1013
  recommendations.push(`Run ${APP_NAME} init to create workspace templates.`);
1628
1014
  }
@@ -1650,13 +1036,13 @@ var DiagnosticsCommands = class {
1650
1036
  return {
1651
1037
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1652
1038
  configPath,
1653
- configExists: existsSync4(configPath),
1039
+ configExists: existsSync3(configPath),
1654
1040
  workspacePath,
1655
- workspaceExists: existsSync4(workspacePath),
1041
+ workspaceExists: existsSync3(workspacePath),
1656
1042
  model: config2.agents.defaults.model,
1657
1043
  providers,
1658
1044
  serviceStatePath,
1659
- serviceStateExists: existsSync4(serviceStatePath),
1045
+ serviceStateExists: existsSync3(serviceStatePath),
1660
1046
  fixActions,
1661
1047
  process: {
1662
1048
  managedByState,
@@ -1706,7 +1092,7 @@ var DiagnosticsCommands = class {
1706
1092
  }
1707
1093
  }
1708
1094
  readLogTail(path, maxLines = 25) {
1709
- if (!existsSync4(path)) {
1095
+ if (!existsSync3(path)) {
1710
1096
  return [];
1711
1097
  }
1712
1098
  try {
@@ -1720,17 +1106,17 @@ var DiagnosticsCommands = class {
1720
1106
  }
1721
1107
  }
1722
1108
  async checkPortAvailability(params) {
1723
- return await new Promise((resolve9) => {
1109
+ return await new Promise((resolve8) => {
1724
1110
  const server = createNetServer();
1725
1111
  server.once("error", (error) => {
1726
- resolve9({
1112
+ resolve8({
1727
1113
  available: false,
1728
1114
  detail: `bind failed on ${params.host}:${params.port} (${String(error)})`
1729
1115
  });
1730
1116
  });
1731
1117
  server.listen(params.port, params.host, () => {
1732
1118
  server.close(() => {
1733
- resolve9({
1119
+ resolve8({
1734
1120
  available: true,
1735
1121
  detail: `bind ok on ${params.host}:${params.port}`
1736
1122
  });
@@ -1751,43 +1137,35 @@ import {
1751
1137
  getDataDir as getDataDir4,
1752
1138
  getProvider,
1753
1139
  getProviderName,
1754
- getWorkspacePath as getWorkspacePath4,
1140
+ getWorkspacePath as getWorkspacePath2,
1755
1141
  HeartbeatService,
1756
1142
  LiteLLMProvider,
1757
- loadConfig as loadConfig5,
1143
+ loadConfig as loadConfig4,
1758
1144
  MessageBus,
1759
1145
  ProviderManager,
1760
- saveConfig as saveConfig4,
1146
+ saveConfig as saveConfig2,
1761
1147
  SessionManager
1762
1148
  } from "@nextclaw/core";
1763
- import {
1764
- getPluginChannelBindings as getPluginChannelBindings2,
1765
- getPluginUiMetadataFromRegistry,
1766
- resolvePluginChannelMessageToolHints,
1767
- setPluginRuntimeBridge,
1768
- startPluginChannelGateways,
1769
- stopPluginChannelGateways
1770
- } from "@nextclaw/openclaw-compat";
1771
1149
  import { startUiServer } from "@nextclaw/server";
1772
1150
  import { closeSync, mkdirSync as mkdirSync2, openSync } from "fs";
1773
- import { join as join4, resolve as resolve6 } from "path";
1151
+ import { join as join4, resolve as resolve5 } from "path";
1774
1152
  import { spawn as spawn2 } from "child_process";
1775
1153
  import chokidar from "chokidar";
1776
1154
 
1777
1155
  // src/cli/gateway/controller.ts
1778
1156
  import { createHash } from "crypto";
1779
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
1157
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1780
1158
  import {
1781
1159
  buildConfigSchema,
1782
1160
  ConfigSchema,
1783
1161
  redactConfigObject
1784
1162
  } from "@nextclaw/core";
1785
1163
  var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
1786
- var readConfigSnapshot = (getConfigPath4, plugins2) => {
1164
+ var readConfigSnapshot = (getConfigPath4) => {
1787
1165
  const path = getConfigPath4();
1788
1166
  let raw = "";
1789
1167
  let parsed = {};
1790
- if (existsSync5(path)) {
1168
+ if (existsSync4(path)) {
1791
1169
  raw = readFileSync3(path, "utf-8");
1792
1170
  try {
1793
1171
  parsed = JSON.parse(raw);
@@ -1807,12 +1185,12 @@ var readConfigSnapshot = (getConfigPath4, plugins2) => {
1807
1185
  raw = JSON.stringify(config2, null, 2);
1808
1186
  }
1809
1187
  const hash = hashRaw(raw);
1810
- const schema = buildConfigSchema({ version: getPackageVersion(), plugins: plugins2 });
1188
+ const schema = buildConfigSchema({ version: getPackageVersion() });
1811
1189
  const redacted = redactConfigObject(config2, schema.uiHints);
1812
1190
  return { raw: valid ? JSON.stringify(redacted, null, 2) : null, hash: valid ? hash : null, config: config2, redacted, valid };
1813
1191
  };
1814
- var redactValue = (value, plugins2) => {
1815
- const schema = buildConfigSchema({ version: getPackageVersion(), plugins: plugins2 });
1192
+ var redactValue = (value) => {
1193
+ const schema = buildConfigSchema({ version: getPackageVersion() });
1816
1194
  return redactConfigObject(value, schema.uiHints);
1817
1195
  };
1818
1196
  var mergeDeep = (base, patch) => {
@@ -1861,8 +1239,7 @@ var GatewayControllerImpl = class {
1861
1239
  return "Restart scheduled";
1862
1240
  }
1863
1241
  async getConfig() {
1864
- const plugins2 = this.deps.getPluginUiMetadata?.() ?? [];
1865
- const snapshot = readConfigSnapshot(this.deps.getConfigPath, plugins2);
1242
+ const snapshot = readConfigSnapshot(this.deps.getConfigPath);
1866
1243
  return {
1867
1244
  raw: snapshot.raw,
1868
1245
  hash: snapshot.hash,
@@ -1874,11 +1251,10 @@ var GatewayControllerImpl = class {
1874
1251
  };
1875
1252
  }
1876
1253
  async getConfigSchema() {
1877
- return buildConfigSchema({ version: getPackageVersion(), plugins: this.deps.getPluginUiMetadata?.() ?? [] });
1254
+ return buildConfigSchema({ version: getPackageVersion() });
1878
1255
  }
1879
1256
  async applyConfig(params) {
1880
- const plugins2 = this.deps.getPluginUiMetadata?.() ?? [];
1881
- const snapshot = readConfigSnapshot(this.deps.getConfigPath, plugins2);
1257
+ const snapshot = readConfigSnapshot(this.deps.getConfigPath);
1882
1258
  if (!params.baseHash) {
1883
1259
  return { ok: false, error: "config base hash required; re-run config.get and retry" };
1884
1260
  }
@@ -1907,13 +1283,12 @@ var GatewayControllerImpl = class {
1907
1283
  ok: true,
1908
1284
  note: params.note ?? null,
1909
1285
  path: this.deps.getConfigPath(),
1910
- config: redactValue(validated, plugins2),
1286
+ config: redactValue(validated),
1911
1287
  restart: { scheduled: true, delayMs }
1912
1288
  };
1913
1289
  }
1914
1290
  async patchConfig(params) {
1915
- const plugins2 = this.deps.getPluginUiMetadata?.() ?? [];
1916
- const snapshot = readConfigSnapshot(this.deps.getConfigPath, plugins2);
1291
+ const snapshot = readConfigSnapshot(this.deps.getConfigPath);
1917
1292
  if (!params.baseHash) {
1918
1293
  return { ok: false, error: "config base hash required; re-run config.get and retry" };
1919
1294
  }
@@ -1943,7 +1318,7 @@ var GatewayControllerImpl = class {
1943
1318
  ok: true,
1944
1319
  note: params.note ?? null,
1945
1320
  path: this.deps.getConfigPath(),
1946
- config: redactValue(validated, plugins2),
1321
+ config: redactValue(validated),
1947
1322
  restart: { scheduled: true, delayMs }
1948
1323
  };
1949
1324
  }
@@ -2116,24 +1491,20 @@ var ServiceCommands = class {
2116
1491
  this.deps = deps;
2117
1492
  }
2118
1493
  async startGateway(options = {}) {
2119
- const config2 = loadConfig5();
2120
- const workspace = getWorkspacePath4(config2.agents.defaults.workspace);
2121
- const pluginRegistry = loadPluginRegistry(config2, workspace);
2122
- const extensionRegistry = toExtensionRegistry(pluginRegistry);
2123
- logPluginDiagnostics(pluginRegistry);
1494
+ const config2 = loadConfig4();
1495
+ const workspace = getWorkspacePath2(config2.agents.defaults.workspace);
2124
1496
  const bus = new MessageBus();
2125
1497
  const provider = options.allowMissingProvider === true ? this.makeProvider(config2, { allowMissing: true }) : this.makeProvider(config2);
2126
1498
  const providerManager = new ProviderManager(provider ?? this.makeMissingProvider(config2));
2127
1499
  const sessionManager = new SessionManager(workspace);
2128
1500
  const cronStorePath = join4(getDataDir4(), "cron", "jobs.json");
2129
1501
  const cron2 = new CronService2(cronStorePath);
2130
- const pluginUiMetadata = getPluginUiMetadataFromRegistry(pluginRegistry);
2131
1502
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
2132
1503
  const uiStaticDir = options.uiStaticDir === void 0 ? resolveUiStaticDir() : options.uiStaticDir;
2133
1504
  if (!provider) {
2134
1505
  console.warn("Warning: No API key configured. The gateway is running, but agent replies are disabled until provider config is set.");
2135
1506
  }
2136
- const channels2 = new ChannelManager2(config2, bus, sessionManager, extensionRegistry.channels);
1507
+ const channels2 = new ChannelManager2(config2, bus, sessionManager, []);
2137
1508
  const reloader = new ConfigReloader({
2138
1509
  initialConfig: config2,
2139
1510
  channels: channels2,
@@ -2141,8 +1512,7 @@ var ServiceCommands = class {
2141
1512
  sessionManager,
2142
1513
  providerManager,
2143
1514
  makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
2144
- loadConfig: loadConfig5,
2145
- getExtensionChannels: () => extensionRegistry.channels,
1515
+ loadConfig: loadConfig4,
2146
1516
  onRestartRequired: (paths) => {
2147
1517
  void this.deps.requestRestart({
2148
1518
  reason: `config reload requires restart: ${paths.join(", ")}`,
@@ -2155,8 +1525,7 @@ var ServiceCommands = class {
2155
1525
  reloader,
2156
1526
  cron: cron2,
2157
1527
  getConfigPath: getConfigPath2,
2158
- saveConfig: saveConfig4,
2159
- getPluginUiMetadata: () => pluginUiMetadata,
1528
+ saveConfig: saveConfig2,
2160
1529
  requestRestart: async (options2) => {
2161
1530
  await this.deps.requestRestart({
2162
1531
  reason: options2?.reason ?? "gateway tool restart",
@@ -2182,55 +1551,9 @@ var ServiceCommands = class {
2182
1551
  sessionManager,
2183
1552
  contextConfig: config2.agents.context,
2184
1553
  gatewayController,
2185
- config: config2,
2186
- extensionRegistry,
2187
- resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
2188
- registry: pluginRegistry,
2189
- channel,
2190
- cfg: loadConfig5(),
2191
- accountId
2192
- })
1554
+ config: config2
2193
1555
  });
2194
1556
  reloader.setApplyAgentRuntimeConfig((nextConfig) => agent.applyRuntimeConfig(nextConfig));
2195
- const pluginChannelBindings = getPluginChannelBindings2(pluginRegistry);
2196
- setPluginRuntimeBridge({
2197
- loadConfig: () => toPluginConfigView(loadConfig5(), pluginChannelBindings),
2198
- writeConfigFile: async (nextConfigView) => {
2199
- if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
2200
- throw new Error("plugin runtime writeConfigFile expects an object config");
2201
- }
2202
- const current = loadConfig5();
2203
- const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
2204
- saveConfig4(next);
2205
- },
2206
- dispatchReplyWithBufferedBlockDispatcher: async ({ ctx, dispatcherOptions }) => {
2207
- const bodyForAgent = typeof ctx.BodyForAgent === "string" ? ctx.BodyForAgent : "";
2208
- const body = typeof ctx.Body === "string" ? ctx.Body : "";
2209
- const content = (bodyForAgent || body).trim();
2210
- if (!content) {
2211
- return;
2212
- }
2213
- const sessionKey = typeof ctx.SessionKey === "string" && ctx.SessionKey.trim().length > 0 ? ctx.SessionKey : `plugin:${typeof ctx.OriginatingChannel === "string" ? ctx.OriginatingChannel : "channel"}:${typeof ctx.SenderId === "string" ? ctx.SenderId : "unknown"}`;
2214
- const channel = typeof ctx.OriginatingChannel === "string" && ctx.OriginatingChannel.trim().length > 0 ? ctx.OriginatingChannel : "cli";
2215
- const chatId = typeof ctx.OriginatingTo === "string" && ctx.OriginatingTo.trim().length > 0 ? ctx.OriginatingTo : typeof ctx.SenderId === "string" && ctx.SenderId.trim().length > 0 ? ctx.SenderId : "direct";
2216
- try {
2217
- const response = await agent.processDirect({
2218
- content,
2219
- sessionKey,
2220
- channel,
2221
- chatId,
2222
- metadata: typeof ctx.AccountId === "string" && ctx.AccountId.trim().length > 0 ? { account_id: ctx.AccountId } : {}
2223
- });
2224
- const replyText = typeof response === "string" ? response : String(response ?? "");
2225
- if (replyText.trim()) {
2226
- await dispatcherOptions.deliver({ text: replyText }, { kind: "final" });
2227
- }
2228
- } catch (error) {
2229
- dispatcherOptions.onError?.(error);
2230
- throw error;
2231
- }
2232
- }
2233
- });
2234
1557
  cron2.onJob = async (job) => {
2235
1558
  const response = await agent.processDirect({
2236
1559
  content: job.payload.message,
@@ -2276,35 +1599,10 @@ var ServiceCommands = class {
2276
1599
  watcher.on("unlink", () => reloader.scheduleReload("config unlink"));
2277
1600
  await cron2.start();
2278
1601
  await heartbeat.start();
2279
- let pluginGatewayHandles = [];
2280
- try {
2281
- const startedPluginGateways = await startPluginChannelGateways({
2282
- registry: pluginRegistry,
2283
- logger: {
2284
- info: (message) => console.log(`[plugins] ${message}`),
2285
- warn: (message) => console.warn(`[plugins] ${message}`),
2286
- error: (message) => console.error(`[plugins] ${message}`),
2287
- debug: (message) => console.debug(`[plugins] ${message}`)
2288
- }
2289
- });
2290
- pluginGatewayHandles = startedPluginGateways.handles;
2291
- for (const diag of startedPluginGateways.diagnostics) {
2292
- const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
2293
- const text = `${prefix}${diag.message}`;
2294
- if (diag.level === "error") {
2295
- console.error(`[plugins] ${text}`);
2296
- } else {
2297
- console.warn(`[plugins] ${text}`);
2298
- }
2299
- }
2300
- await Promise.allSettled([agent.run(), reloader.getChannels().startAll()]);
2301
- } finally {
2302
- await stopPluginChannelGateways(pluginGatewayHandles);
2303
- setPluginRuntimeBridge(null);
2304
- }
1602
+ await Promise.allSettled([agent.run(), reloader.getChannels().startAll()]);
2305
1603
  }
2306
1604
  async runForeground(options) {
2307
- const config2 = loadConfig5();
1605
+ const config2 = loadConfig4();
2308
1606
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
2309
1607
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
2310
1608
  if (options.open) {
@@ -2317,7 +1615,7 @@ var ServiceCommands = class {
2317
1615
  });
2318
1616
  }
2319
1617
  async startService(options) {
2320
- const config2 = loadConfig5();
1618
+ const config2 = loadConfig4();
2321
1619
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
2322
1620
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
2323
1621
  const apiUrl = `${uiUrl}/api`;
@@ -2366,7 +1664,7 @@ var ServiceCommands = class {
2366
1664
  console.log("Warning: UI frontend not found in package assets.");
2367
1665
  }
2368
1666
  const logPath = resolveServiceLogPath();
2369
- const logDir = resolve6(logPath, "..");
1667
+ const logDir = resolve5(logPath, "..");
2370
1668
  mkdirSync2(logDir, { recursive: true });
2371
1669
  const logFd = openSync(logPath, "a");
2372
1670
  const serveArgs = buildServeArgs({
@@ -2461,22 +1759,22 @@ var ServiceCommands = class {
2461
1759
  try {
2462
1760
  const response = await fetch(params.healthUrl, { method: "GET" });
2463
1761
  if (!response.ok) {
2464
- await new Promise((resolve9) => setTimeout(resolve9, 200));
1762
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
2465
1763
  continue;
2466
1764
  }
2467
1765
  const payload = await response.json();
2468
1766
  const healthy = payload?.ok === true && payload?.data?.status === "ok";
2469
1767
  if (!healthy) {
2470
- await new Promise((resolve9) => setTimeout(resolve9, 200));
1768
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
2471
1769
  continue;
2472
1770
  }
2473
- await new Promise((resolve9) => setTimeout(resolve9, 300));
1771
+ await new Promise((resolve8) => setTimeout(resolve8, 300));
2474
1772
  if (isProcessRunning(params.pid)) {
2475
1773
  return true;
2476
1774
  }
2477
1775
  } catch {
2478
1776
  }
2479
- await new Promise((resolve9) => setTimeout(resolve9, 200));
1777
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
2480
1778
  }
2481
1779
  return false;
2482
1780
  }
@@ -2549,9 +1847,9 @@ var ServiceCommands = class {
2549
1847
  };
2550
1848
 
2551
1849
  // src/cli/workspace.ts
2552
- import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
1850
+ import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
2553
1851
  import { createRequire } from "module";
2554
- import { dirname, join as join5, resolve as resolve7 } from "path";
1852
+ import { dirname, join as join5, resolve as resolve6 } from "path";
2555
1853
  import { fileURLToPath as fileURLToPath2 } from "url";
2556
1854
  import { APP_NAME as APP_NAME3, getDataDir as getDataDir5 } from "@nextclaw/core";
2557
1855
  import { spawnSync as spawnSync4 } from "child_process";
@@ -2582,11 +1880,11 @@ var WorkspaceManager = class {
2582
1880
  ];
2583
1881
  for (const entry of templateFiles) {
2584
1882
  const filePath = join5(workspace, entry.target);
2585
- if (!force && existsSync6(filePath)) {
1883
+ if (!force && existsSync5(filePath)) {
2586
1884
  continue;
2587
1885
  }
2588
1886
  const templatePath = join5(templateDir, entry.source);
2589
- if (!existsSync6(templatePath)) {
1887
+ if (!existsSync5(templatePath)) {
2590
1888
  console.warn(`Warning: Template file missing: ${templatePath}`);
2591
1889
  continue;
2592
1890
  }
@@ -2597,12 +1895,12 @@ var WorkspaceManager = class {
2597
1895
  created.push(entry.target);
2598
1896
  }
2599
1897
  const memoryDir = join5(workspace, "memory");
2600
- if (!existsSync6(memoryDir)) {
1898
+ if (!existsSync5(memoryDir)) {
2601
1899
  mkdirSync3(memoryDir, { recursive: true });
2602
1900
  created.push(join5("memory", ""));
2603
1901
  }
2604
1902
  const skillsDir = join5(workspace, "skills");
2605
- if (!existsSync6(skillsDir)) {
1903
+ if (!existsSync5(skillsDir)) {
2606
1904
  mkdirSync3(skillsDir, { recursive: true });
2607
1905
  created.push(join5("skills", ""));
2608
1906
  }
@@ -2624,11 +1922,11 @@ var WorkspaceManager = class {
2624
1922
  continue;
2625
1923
  }
2626
1924
  const src = join5(sourceDir, entry.name);
2627
- if (!existsSync6(join5(src, "SKILL.md"))) {
1925
+ if (!existsSync5(join5(src, "SKILL.md"))) {
2628
1926
  continue;
2629
1927
  }
2630
1928
  const dest = join5(targetDir, entry.name);
2631
- if (!force && existsSync6(dest)) {
1929
+ if (!force && existsSync5(dest)) {
2632
1930
  continue;
2633
1931
  }
2634
1932
  cpSync(src, dest, { recursive: true, force: true });
@@ -2640,13 +1938,13 @@ var WorkspaceManager = class {
2640
1938
  try {
2641
1939
  const require2 = createRequire(import.meta.url);
2642
1940
  const entry = require2.resolve("@nextclaw/core");
2643
- const pkgRoot = resolve7(dirname(entry), "..");
1941
+ const pkgRoot = resolve6(dirname(entry), "..");
2644
1942
  const distSkills = join5(pkgRoot, "dist", "skills");
2645
- if (existsSync6(distSkills)) {
1943
+ if (existsSync5(distSkills)) {
2646
1944
  return distSkills;
2647
1945
  }
2648
1946
  const srcSkills = join5(pkgRoot, "src", "agent", "skills");
2649
- if (existsSync6(srcSkills)) {
1947
+ if (existsSync5(srcSkills)) {
2650
1948
  return srcSkills;
2651
1949
  }
2652
1950
  return null;
@@ -2659,11 +1957,11 @@ var WorkspaceManager = class {
2659
1957
  if (override) {
2660
1958
  return override;
2661
1959
  }
2662
- const cliDir = resolve7(fileURLToPath2(new URL(".", import.meta.url)));
2663
- const pkgRoot = resolve7(cliDir, "..", "..");
1960
+ const cliDir = resolve6(fileURLToPath2(new URL(".", import.meta.url)));
1961
+ const pkgRoot = resolve6(cliDir, "..", "..");
2664
1962
  const candidates = [join5(pkgRoot, "templates")];
2665
1963
  for (const candidate of candidates) {
2666
- if (existsSync6(candidate)) {
1964
+ if (existsSync5(candidate)) {
2667
1965
  return candidate;
2668
1966
  }
2669
1967
  }
@@ -2671,21 +1969,21 @@ var WorkspaceManager = class {
2671
1969
  }
2672
1970
  getBridgeDir() {
2673
1971
  const userBridge = join5(getDataDir5(), "bridge");
2674
- if (existsSync6(join5(userBridge, "dist", "index.js"))) {
1972
+ if (existsSync5(join5(userBridge, "dist", "index.js"))) {
2675
1973
  return userBridge;
2676
1974
  }
2677
1975
  if (!which("npm")) {
2678
1976
  console.error("npm not found. Please install Node.js >= 18.");
2679
1977
  process.exit(1);
2680
1978
  }
2681
- const cliDir = resolve7(fileURLToPath2(new URL(".", import.meta.url)));
2682
- const pkgRoot = resolve7(cliDir, "..", "..");
1979
+ const cliDir = resolve6(fileURLToPath2(new URL(".", import.meta.url)));
1980
+ const pkgRoot = resolve6(cliDir, "..", "..");
2683
1981
  const pkgBridge = join5(pkgRoot, "bridge");
2684
1982
  const srcBridge = join5(pkgRoot, "..", "..", "bridge");
2685
1983
  let source = null;
2686
- if (existsSync6(join5(pkgBridge, "package.json"))) {
1984
+ if (existsSync5(join5(pkgBridge, "package.json"))) {
2687
1985
  source = pkgBridge;
2688
- } else if (existsSync6(join5(srcBridge, "package.json"))) {
1986
+ } else if (existsSync5(join5(srcBridge, "package.json"))) {
2689
1987
  source = srcBridge;
2690
1988
  }
2691
1989
  if (!source) {
@@ -2693,8 +1991,8 @@ var WorkspaceManager = class {
2693
1991
  process.exit(1);
2694
1992
  }
2695
1993
  console.log(`${this.logo} Setting up bridge...`);
2696
- mkdirSync3(resolve7(userBridge, ".."), { recursive: true });
2697
- if (existsSync6(userBridge)) {
1994
+ mkdirSync3(resolve6(userBridge, ".."), { recursive: true });
1995
+ if (existsSync5(userBridge)) {
2698
1996
  rmSync2(userBridge, { recursive: true, force: true });
2699
1997
  }
2700
1998
  cpSync(source, userBridge, {
@@ -2734,7 +2032,6 @@ var CliRuntime = class {
2734
2032
  workspaceManager;
2735
2033
  serviceCommands;
2736
2034
  configCommands;
2737
- pluginCommands;
2738
2035
  channelCommands;
2739
2036
  cronCommands;
2740
2037
  diagnosticsCommands;
@@ -2747,13 +2044,9 @@ var CliRuntime = class {
2747
2044
  this.configCommands = new ConfigCommands({
2748
2045
  requestRestart: (params) => this.requestRestart(params)
2749
2046
  });
2750
- this.pluginCommands = new PluginCommands({
2751
- requestRestart: (params) => this.requestRestart(params)
2752
- });
2753
2047
  this.channelCommands = new ChannelCommands({
2754
2048
  logo: this.logo,
2755
- getBridgeDir: () => this.workspaceManager.getBridgeDir(),
2756
- requestRestart: (params) => this.requestRestart(params)
2049
+ getBridgeDir: () => this.workspaceManager.getBridgeDir()
2757
2050
  });
2758
2051
  this.cronCommands = new CronCommands();
2759
2052
  this.diagnosticsCommands = new DiagnosticsCommands({ logo: this.logo });
@@ -2819,7 +2112,7 @@ var CliRuntime = class {
2819
2112
  const delayMs = typeof params.delayMs === "number" && Number.isFinite(params.delayMs) ? Math.max(0, Math.floor(params.delayMs)) : 100;
2820
2113
  const cliPath = process.env.NEXTCLAW_SELF_RELAUNCH_CLI?.trim() || fileURLToPath3(new URL("./index.js", import.meta.url));
2821
2114
  const startArgs = [cliPath, "start", "--ui-port", String(uiPort)];
2822
- const serviceStatePath = resolve8(getDataDir6(), "run", "service.json");
2115
+ const serviceStatePath = resolve7(getDataDir6(), "run", "service.json");
2823
2116
  const helperScript = [
2824
2117
  'const { spawnSync } = require("node:child_process");',
2825
2118
  'const { readFileSync } = require("node:fs");',
@@ -2924,15 +2217,15 @@ var CliRuntime = class {
2924
2217
  const force = Boolean(options.force);
2925
2218
  const configPath = getConfigPath3();
2926
2219
  let createdConfig = false;
2927
- if (!existsSync7(configPath)) {
2220
+ if (!existsSync6(configPath)) {
2928
2221
  const config3 = ConfigSchema2.parse({});
2929
- saveConfig5(config3);
2222
+ saveConfig3(config3);
2930
2223
  createdConfig = true;
2931
2224
  }
2932
- const config2 = loadConfig6();
2225
+ const config2 = loadConfig5();
2933
2226
  const workspaceSetting = config2.agents.defaults.workspace;
2934
- const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join6(getDataDir6(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
2935
- const workspaceExisted = existsSync7(workspacePath);
2227
+ const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join6(getDataDir6(), DEFAULT_WORKSPACE_DIR) : expandHome(workspaceSetting);
2228
+ const workspaceExisted = existsSync6(workspacePath);
2936
2229
  mkdirSync4(workspacePath, { recursive: true });
2937
2230
  const templateResult = this.workspaceManager.createWorkspaceTemplates(workspacePath, { force });
2938
2231
  if (createdConfig) {
@@ -3029,11 +2322,8 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3029
2322
  await this.serviceCommands.stopService();
3030
2323
  }
3031
2324
  async agent(opts) {
3032
- const config2 = loadConfig6();
3033
- const workspace = getWorkspacePath5(config2.agents.defaults.workspace);
3034
- const pluginRegistry = loadPluginRegistry(config2, workspace);
3035
- const extensionRegistry = toExtensionRegistry(pluginRegistry);
3036
- logPluginDiagnostics(pluginRegistry);
2325
+ const config2 = loadConfig5();
2326
+ const workspace = getWorkspacePath3(config2.agents.defaults.workspace);
3037
2327
  const bus = new MessageBus2();
3038
2328
  const provider = this.serviceCommands.createProvider(config2) ?? this.serviceCommands.createMissingProvider(config2);
3039
2329
  const providerManager = new ProviderManager2(provider);
@@ -3049,14 +2339,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3049
2339
  execConfig: config2.tools.exec,
3050
2340
  restrictToWorkspace: config2.tools.restrictToWorkspace,
3051
2341
  contextConfig: config2.agents.context,
3052
- config: config2,
3053
- extensionRegistry,
3054
- resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
3055
- registry: pluginRegistry,
3056
- channel,
3057
- cfg: loadConfig6(),
3058
- accountId
3059
- })
2342
+ config: config2
3060
2343
  });
3061
2344
  if (opts.message) {
3062
2345
  const response = await agentLoop.processDirect({
@@ -3071,10 +2354,10 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3071
2354
  console.log(`${this.logo} Interactive mode (type exit or Ctrl+C to quit)
3072
2355
  `);
3073
2356
  const historyFile = join6(getDataDir6(), "history", "cli_history");
3074
- const historyDir = resolve8(historyFile, "..");
2357
+ const historyDir = resolve7(historyFile, "..");
3075
2358
  mkdirSync4(historyDir, { recursive: true });
3076
- const history = existsSync7(historyFile) ? readFileSync5(historyFile, "utf-8").split("\n").filter(Boolean) : [];
3077
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
2359
+ const history = existsSync6(historyFile) ? readFileSync5(historyFile, "utf-8").split("\n").filter(Boolean) : [];
2360
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3078
2361
  rl.on("close", () => {
3079
2362
  const merged = history.concat(rl.history ?? []);
3080
2363
  writeFileSync3(historyFile, merged.join("\n"));
@@ -3134,27 +2417,6 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3134
2417
  console.log(`Tip: restart ${APP_NAME4} to apply the update.`);
3135
2418
  }
3136
2419
  }
3137
- pluginsList(opts = {}) {
3138
- this.pluginCommands.pluginsList(opts);
3139
- }
3140
- pluginsInfo(id, opts = {}) {
3141
- this.pluginCommands.pluginsInfo(id, opts);
3142
- }
3143
- async pluginsEnable(id) {
3144
- await this.pluginCommands.pluginsEnable(id);
3145
- }
3146
- async pluginsDisable(id) {
3147
- await this.pluginCommands.pluginsDisable(id);
3148
- }
3149
- async pluginsUninstall(id, opts = {}) {
3150
- await this.pluginCommands.pluginsUninstall(id, opts);
3151
- }
3152
- async pluginsInstall(pathOrSpec, opts = {}) {
3153
- await this.pluginCommands.pluginsInstall(pathOrSpec, opts);
3154
- }
3155
- pluginsDoctor() {
3156
- this.pluginCommands.pluginsDoctor();
3157
- }
3158
2420
  configGet(pathExpr, opts = {}) {
3159
2421
  this.configCommands.configGet(pathExpr, opts);
3160
2422
  }
@@ -3170,9 +2432,6 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3170
2432
  channelsLogin() {
3171
2433
  this.channelCommands.channelsLogin();
3172
2434
  }
3173
- async channelsAdd(opts) {
3174
- await this.channelCommands.channelsAdd(opts);
3175
- }
3176
2435
  cronList(opts) {
3177
2436
  this.cronCommands.cronList(opts);
3178
2437
  }
@@ -3195,7 +2454,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
3195
2454
  await this.diagnosticsCommands.doctor(opts);
3196
2455
  }
3197
2456
  async skillsInstall(options) {
3198
- const workdir = options.workdir ? expandHome2(options.workdir) : getWorkspacePath5();
2457
+ const workdir = options.workdir ? expandHome(options.workdir) : getWorkspacePath3();
3199
2458
  const result = await installClawHubSkill({
3200
2459
  slug: options.slug,
3201
2460
  version: options.version,
@@ -3238,20 +2497,11 @@ var skills = program.command("skills").description("Manage skills");
3238
2497
  registerClawHubInstall(skills);
3239
2498
  var clawhub = program.command("clawhub").description("Install skills from ClawHub");
3240
2499
  registerClawHubInstall(clawhub);
3241
- var plugins = program.command("plugins").description("Manage OpenClaw-compatible plugins");
3242
- plugins.command("list").description("List discovered plugins").option("--json", "Print JSON").option("--enabled", "Only show enabled plugins", false).option("--verbose", "Show detailed entries", false).action((opts) => runtime.pluginsList(opts));
3243
- plugins.command("info <id>").description("Show plugin details").option("--json", "Print JSON").action((id, opts) => runtime.pluginsInfo(id, opts));
3244
- plugins.command("enable <id>").description("Enable a plugin in config").action((id) => runtime.pluginsEnable(id));
3245
- plugins.command("disable <id>").description("Disable a plugin in config").action((id) => runtime.pluginsDisable(id));
3246
- plugins.command("uninstall <id>").description("Uninstall a plugin").option("--keep-files", "Keep installed files on disk", false).option("--keep-config", "Deprecated alias for --keep-files", false).option("--force", "Skip confirmation prompt", false).option("--dry-run", "Show what would be removed without making changes", false).action(async (id, opts) => runtime.pluginsUninstall(id, opts));
3247
- plugins.command("install <path-or-spec>").description("Install a plugin (path, archive, or npm spec)").option("-l, --link", "Link a local path instead of copying", false).action(async (pathOrSpec, opts) => runtime.pluginsInstall(pathOrSpec, opts));
3248
- plugins.command("doctor").description("Report plugin load issues").action(() => runtime.pluginsDoctor());
3249
2500
  var config = program.command("config").description("Manage config values");
3250
2501
  config.command("get <path>").description("Get a config value by dot path").option("--json", "Output JSON", false).action((path, opts) => runtime.configGet(path, opts));
3251
2502
  config.command("set <path> <value>").description("Set a config value by dot path").option("--json", "Parse value as JSON", false).action((path, value, opts) => runtime.configSet(path, value, opts));
3252
2503
  config.command("unset <path>").description("Remove a config value by dot path").action((path) => runtime.configUnset(path));
3253
2504
  var channels = program.command("channels").description("Manage channels");
3254
- channels.command("add").description("Configure a plugin channel (OpenClaw-compatible setup)").requiredOption("--channel <id>", "Plugin channel id").option("--code <code>", "Pairing code").option("--token <token>", "Connector token").option("--name <name>", "Display name").option("--url <url>", "API base URL").option("--http-url <url>", "Alias for --url").action((opts) => runtime.channelsAdd(opts));
3255
2505
  channels.command("status").description("Show channel status").action(() => runtime.channelsStatus());
3256
2506
  channels.command("login").description("Link device via QR code").action(() => runtime.channelsLogin());
3257
2507
  var cron = program.command("cron").description("Manage scheduled tasks");