nextclaw 0.11.0 → 0.12.0
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 +1002 -487
- package/package.json +4 -4
- package/ui-dist/assets/ChannelsList-C7F_As4r.js +1 -0
- package/ui-dist/assets/ChatPage-Oo7-OUsx.js +37 -0
- package/ui-dist/assets/{DocBrowser-DDX2HMXW.js → DocBrowser-Dsd8Dlq8.js} +1 -1
- package/ui-dist/assets/{LogoBadge-J53F_3JA.js → LogoBadge-2ChEc_oz.js} +1 -1
- package/ui-dist/assets/{MarketplacePage-0BZ4bza0.js → MarketplacePage-BXck6-X3.js} +3 -3
- package/ui-dist/assets/{ModelConfig-Wzq9wGHV.js → ModelConfig-CgHRSD0b.js} +1 -1
- package/ui-dist/assets/ProvidersList-PPfZucvS.js +1 -0
- package/ui-dist/assets/{RuntimeConfig-N771_AM6.js → RuntimeConfig-ClLEKNTN.js} +1 -1
- package/ui-dist/assets/{SearchConfig-DVt5QVa_.js → SearchConfig-CuXVCbrf.js} +1 -1
- package/ui-dist/assets/{SecretsConfig-CkwauPa8.js → SecretsConfig-udJz6Ake.js} +1 -1
- package/ui-dist/assets/{SessionsConfig-C3mnHzkZ.js → SessionsConfig-C1XnFfiC.js} +2 -2
- package/ui-dist/assets/{chat-message-pxr79GDs.js → chat-message-BETwXLD4.js} +1 -1
- package/ui-dist/assets/{index-GdpEEKnz.js → index-COJdlL0e.js} +1 -1
- package/ui-dist/assets/index-CsvP4CER.js +8 -0
- package/ui-dist/assets/index-D-bXl7qL.css +1 -0
- package/ui-dist/assets/{label-CmksBHgc.js → label-BGL-ztxh.js} +1 -1
- package/ui-dist/assets/{page-layout-Db0GbnhS.js → page-layout-aw88k7tG.js} +1 -1
- package/ui-dist/assets/popover-DyEvzhmV.js +1 -0
- package/ui-dist/assets/{security-config-CjLFME5Q.js → security-config-BuPAQn82.js} +1 -1
- package/ui-dist/assets/skeleton-drzO_tdU.js +1 -0
- package/ui-dist/assets/{switch-C24d-UJU.js → switch-BK8jIzto.js} +1 -1
- package/ui-dist/assets/tabs-custom-Da3cEOji.js +1 -0
- package/ui-dist/assets/{useConfirmDialog-BeP35LcG.js → useConfirmDialog-z0CE92iS.js} +1 -1
- package/ui-dist/assets/{vendor-psXJBy9u.js → vendor-CkJHmX1g.js} +1 -1
- package/ui-dist/index.html +3 -3
- package/ui-dist/assets/ChannelsList-DBcoVJRW.js +0 -1
- package/ui-dist/assets/ChatPage-CD3cxyyM.js +0 -37
- package/ui-dist/assets/ProvidersList-kwzRS8_M.js +0 -1
- package/ui-dist/assets/index-BIvFMkN4.js +0 -1
- package/ui-dist/assets/index-CzkY1reu.js +0 -8
- package/ui-dist/assets/index-RZ0kHHRI.css +0 -1
- package/ui-dist/assets/skeleton-CkpQeVWN.js +0 -1
- package/ui-dist/assets/tabs-custom-D89bh-fc.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -6,12 +6,12 @@ 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
|
|
9
|
+
loadConfig as loadConfig8,
|
|
10
10
|
saveConfig as saveConfig6,
|
|
11
11
|
getConfigPath as getConfigPath4,
|
|
12
12
|
getDataDir as getDataDir8,
|
|
13
13
|
ConfigSchema as ConfigSchema2,
|
|
14
|
-
getWorkspacePath as
|
|
14
|
+
getWorkspacePath as getWorkspacePath9,
|
|
15
15
|
expandHome as expandHome2,
|
|
16
16
|
MessageBus as MessageBus2,
|
|
17
17
|
AgentLoop,
|
|
@@ -22,12 +22,12 @@ import {
|
|
|
22
22
|
DEFAULT_WORKSPACE_PATH
|
|
23
23
|
} from "@nextclaw/core";
|
|
24
24
|
import {
|
|
25
|
-
getPluginChannelBindings as
|
|
25
|
+
getPluginChannelBindings as getPluginChannelBindings4,
|
|
26
26
|
resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2,
|
|
27
27
|
setPluginRuntimeBridge as setPluginRuntimeBridge2
|
|
28
28
|
} from "@nextclaw/openclaw-compat";
|
|
29
29
|
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
30
|
-
import { join as join7, resolve as
|
|
30
|
+
import { join as join7, resolve as resolve12 } from "path";
|
|
31
31
|
import { createInterface as createInterface2 } from "readline";
|
|
32
32
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
33
33
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -115,32 +115,32 @@ function resolveRestartSentinelPath() {
|
|
|
115
115
|
return resolve(getDataDir(), "run", RESTART_SENTINEL_FILENAME);
|
|
116
116
|
}
|
|
117
117
|
async function writeRestartSentinel(payload) {
|
|
118
|
-
const
|
|
119
|
-
mkdirSync(resolve(
|
|
118
|
+
const path2 = resolveRestartSentinelPath();
|
|
119
|
+
mkdirSync(resolve(path2, ".."), { recursive: true });
|
|
120
120
|
const file = {
|
|
121
121
|
version: 1,
|
|
122
122
|
payload
|
|
123
123
|
};
|
|
124
|
-
writeFileSync(
|
|
124
|
+
writeFileSync(path2, `${JSON.stringify(file, null, 2)}
|
|
125
125
|
`, "utf-8");
|
|
126
|
-
return
|
|
126
|
+
return path2;
|
|
127
127
|
}
|
|
128
128
|
async function consumeRestartSentinel() {
|
|
129
|
-
const
|
|
130
|
-
if (!existsSync(
|
|
129
|
+
const path2 = resolveRestartSentinelPath();
|
|
130
|
+
if (!existsSync(path2)) {
|
|
131
131
|
return null;
|
|
132
132
|
}
|
|
133
133
|
try {
|
|
134
|
-
const raw = readFileSync(
|
|
134
|
+
const raw = readFileSync(path2, "utf-8");
|
|
135
135
|
const parsed = JSON.parse(raw);
|
|
136
136
|
if (!parsed || parsed.version !== 1 || !parsed.payload) {
|
|
137
|
-
rmSync(
|
|
137
|
+
rmSync(path2, { force: true });
|
|
138
138
|
return null;
|
|
139
139
|
}
|
|
140
|
-
rmSync(
|
|
140
|
+
rmSync(path2, { force: true });
|
|
141
141
|
return parsed;
|
|
142
142
|
} catch {
|
|
143
|
-
rmSync(
|
|
143
|
+
rmSync(path2, { force: true });
|
|
144
144
|
return null;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
@@ -512,11 +512,11 @@ function collectRelativeFiles(rootDir) {
|
|
|
512
512
|
};
|
|
513
513
|
return walk(rootDir) ? output : null;
|
|
514
514
|
}
|
|
515
|
-
function normalizeMarketplaceRelativePath(
|
|
516
|
-
return
|
|
515
|
+
function normalizeMarketplaceRelativePath(path2) {
|
|
516
|
+
return path2.replace(/\\/g, "/");
|
|
517
517
|
}
|
|
518
|
-
function isIgnorableMarketplaceResidue(
|
|
519
|
-
return
|
|
518
|
+
function isIgnorableMarketplaceResidue(path2) {
|
|
519
|
+
return path2 === ".DS_Store";
|
|
520
520
|
}
|
|
521
521
|
async function publishMarketplaceSkill(options) {
|
|
522
522
|
const skillDir = resolve3(options.skillDir);
|
|
@@ -673,10 +673,10 @@ async function fetchMarketplaceSkillFileBlob(apiBase, slug, file) {
|
|
|
673
673
|
const arrayBuffer = await response.arrayBuffer();
|
|
674
674
|
return Buffer.from(arrayBuffer);
|
|
675
675
|
}
|
|
676
|
-
function decodeMarketplaceFileContent(
|
|
676
|
+
function decodeMarketplaceFileContent(path2, contentBase64) {
|
|
677
677
|
const normalized = contentBase64.replace(/\s+/g, "");
|
|
678
678
|
if (!normalized || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {
|
|
679
|
-
throw new Error(`Invalid marketplace file contentBase64 for path: ${
|
|
679
|
+
throw new Error(`Invalid marketplace file contentBase64 for path: ${path2}`);
|
|
680
680
|
}
|
|
681
681
|
return Buffer.from(normalized, "base64");
|
|
682
682
|
}
|
|
@@ -806,26 +806,26 @@ function buildServeArgs(options) {
|
|
|
806
806
|
return [cliPath, "serve", "--ui-port", String(options.uiPort)];
|
|
807
807
|
}
|
|
808
808
|
function readServiceState() {
|
|
809
|
-
const
|
|
810
|
-
if (!existsSync4(
|
|
809
|
+
const path2 = resolveServiceStatePath();
|
|
810
|
+
if (!existsSync4(path2)) {
|
|
811
811
|
return null;
|
|
812
812
|
}
|
|
813
813
|
try {
|
|
814
|
-
const raw = readFileSync4(
|
|
814
|
+
const raw = readFileSync4(path2, "utf-8");
|
|
815
815
|
return JSON.parse(raw);
|
|
816
816
|
} catch {
|
|
817
817
|
return null;
|
|
818
818
|
}
|
|
819
819
|
}
|
|
820
820
|
function writeServiceState(state) {
|
|
821
|
-
const
|
|
822
|
-
mkdirSync3(resolve4(
|
|
823
|
-
writeFileSync3(
|
|
821
|
+
const path2 = resolveServiceStatePath();
|
|
822
|
+
mkdirSync3(resolve4(path2, ".."), { recursive: true });
|
|
823
|
+
writeFileSync3(path2, JSON.stringify(state, null, 2));
|
|
824
824
|
}
|
|
825
825
|
function clearServiceState() {
|
|
826
|
-
const
|
|
827
|
-
if (existsSync4(
|
|
828
|
-
rmSync3(
|
|
826
|
+
const path2 = resolveServiceStatePath();
|
|
827
|
+
if (existsSync4(path2)) {
|
|
828
|
+
rmSync3(path2, { force: true });
|
|
829
829
|
}
|
|
830
830
|
}
|
|
831
831
|
function resolveServiceStatePath() {
|
|
@@ -848,7 +848,7 @@ async function waitForExit(pid, timeoutMs) {
|
|
|
848
848
|
if (!isProcessRunning(pid)) {
|
|
849
849
|
return true;
|
|
850
850
|
}
|
|
851
|
-
await new Promise((
|
|
851
|
+
await new Promise((resolve13) => setTimeout(resolve13, 200));
|
|
852
852
|
}
|
|
853
853
|
return !isProcessRunning(pid);
|
|
854
854
|
}
|
|
@@ -987,8 +987,8 @@ function printAgentResponse(response) {
|
|
|
987
987
|
async function prompt(rl, question) {
|
|
988
988
|
rl.setPrompt(question);
|
|
989
989
|
rl.prompt();
|
|
990
|
-
return new Promise((
|
|
991
|
-
rl.once("line", (line) =>
|
|
990
|
+
return new Promise((resolve13) => {
|
|
991
|
+
rl.once("line", (line) => resolve13(line));
|
|
992
992
|
});
|
|
993
993
|
}
|
|
994
994
|
|
|
@@ -1043,6 +1043,212 @@ function runSelfUpdate(options = {}) {
|
|
|
1043
1043
|
}
|
|
1044
1044
|
|
|
1045
1045
|
// src/cli/commands/plugins.ts
|
|
1046
|
+
import {
|
|
1047
|
+
buildPluginStatusReport as buildPluginStatusReport2,
|
|
1048
|
+
loadOpenClawPlugins,
|
|
1049
|
+
resolveUninstallDirectoryTargets
|
|
1050
|
+
} from "@nextclaw/openclaw-compat";
|
|
1051
|
+
|
|
1052
|
+
// src/cli/commands/plugin-command-utils.ts
|
|
1053
|
+
import { builtinProviderIds } from "@nextclaw/runtime";
|
|
1054
|
+
var RESERVED_PROVIDER_IDS = builtinProviderIds();
|
|
1055
|
+
var RESERVED_TOOL_NAMES = [
|
|
1056
|
+
"read_file",
|
|
1057
|
+
"write_file",
|
|
1058
|
+
"edit_file",
|
|
1059
|
+
"list_dir",
|
|
1060
|
+
"exec",
|
|
1061
|
+
"web_search",
|
|
1062
|
+
"web_fetch",
|
|
1063
|
+
"message",
|
|
1064
|
+
"spawn",
|
|
1065
|
+
"sessions_list",
|
|
1066
|
+
"sessions_history",
|
|
1067
|
+
"sessions_send",
|
|
1068
|
+
"memory_search",
|
|
1069
|
+
"memory_get",
|
|
1070
|
+
"subagents",
|
|
1071
|
+
"gateway",
|
|
1072
|
+
"cron"
|
|
1073
|
+
];
|
|
1074
|
+
function buildReservedPluginLoadOptions() {
|
|
1075
|
+
return {
|
|
1076
|
+
reservedToolNames: [...RESERVED_TOOL_NAMES],
|
|
1077
|
+
reservedChannelIds: [],
|
|
1078
|
+
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1079
|
+
reservedEngineKinds: ["native"],
|
|
1080
|
+
reservedNcpAgentRuntimeKinds: ["native"]
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function appendPluginCapabilityLines(lines, plugin) {
|
|
1084
|
+
if (plugin.toolNames.length > 0) {
|
|
1085
|
+
lines.push(`Tools: ${plugin.toolNames.join(", ")}`);
|
|
1086
|
+
}
|
|
1087
|
+
if (plugin.channelIds.length > 0) {
|
|
1088
|
+
lines.push(`Channels: ${plugin.channelIds.join(", ")}`);
|
|
1089
|
+
}
|
|
1090
|
+
if (plugin.providerIds.length > 0) {
|
|
1091
|
+
lines.push(`Providers: ${plugin.providerIds.join(", ")}`);
|
|
1092
|
+
}
|
|
1093
|
+
if (plugin.engineKinds.length > 0) {
|
|
1094
|
+
lines.push(`Engines: ${plugin.engineKinds.join(", ")}`);
|
|
1095
|
+
}
|
|
1096
|
+
if (plugin.ncpAgentRuntimeKinds.length > 0) {
|
|
1097
|
+
lines.push(`NCP runtimes: ${plugin.ncpAgentRuntimeKinds.join(", ")}`);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// src/cli/commands/dev-first-party-plugin-load-paths.ts
|
|
1102
|
+
import fs from "fs";
|
|
1103
|
+
import path from "path";
|
|
1104
|
+
var readJsonFile = (filePath) => {
|
|
1105
|
+
try {
|
|
1106
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
1107
|
+
const parsed = JSON.parse(raw);
|
|
1108
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
1109
|
+
} catch {
|
|
1110
|
+
return null;
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
var readString = (value) => {
|
|
1114
|
+
if (typeof value !== "string") {
|
|
1115
|
+
return void 0;
|
|
1116
|
+
}
|
|
1117
|
+
const trimmed = value.trim();
|
|
1118
|
+
return trimmed || void 0;
|
|
1119
|
+
};
|
|
1120
|
+
var hasOpenClawExtensions = (pkg) => {
|
|
1121
|
+
const openclaw = pkg.openclaw;
|
|
1122
|
+
if (!openclaw || typeof openclaw !== "object" || Array.isArray(openclaw)) {
|
|
1123
|
+
return false;
|
|
1124
|
+
}
|
|
1125
|
+
const extensions = openclaw.extensions;
|
|
1126
|
+
return Array.isArray(extensions) && extensions.some((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
1127
|
+
};
|
|
1128
|
+
var normalizePackageSpec = (spec) => {
|
|
1129
|
+
const trimmed = spec.trim();
|
|
1130
|
+
if (!trimmed) {
|
|
1131
|
+
return void 0;
|
|
1132
|
+
}
|
|
1133
|
+
if (trimmed.startsWith("@")) {
|
|
1134
|
+
const slashIndex = trimmed.indexOf("/");
|
|
1135
|
+
if (slashIndex < 0) {
|
|
1136
|
+
return void 0;
|
|
1137
|
+
}
|
|
1138
|
+
const secondAtIndex = trimmed.indexOf("@", slashIndex + 1);
|
|
1139
|
+
return secondAtIndex < 0 ? trimmed : trimmed.slice(0, secondAtIndex);
|
|
1140
|
+
}
|
|
1141
|
+
const versionIndex = trimmed.indexOf("@");
|
|
1142
|
+
return versionIndex < 0 ? trimmed : trimmed.slice(0, versionIndex);
|
|
1143
|
+
};
|
|
1144
|
+
var readWorkspacePluginPackages = (workspaceExtensionsDir) => {
|
|
1145
|
+
if (!workspaceExtensionsDir.trim() || !fs.existsSync(workspaceExtensionsDir)) {
|
|
1146
|
+
return [];
|
|
1147
|
+
}
|
|
1148
|
+
const entries = fs.readdirSync(workspaceExtensionsDir, { withFileTypes: true });
|
|
1149
|
+
const packages = [];
|
|
1150
|
+
for (const entry of entries) {
|
|
1151
|
+
if (!entry.isDirectory()) {
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
const packageDir = path.join(workspaceExtensionsDir, entry.name);
|
|
1155
|
+
const pkg = readJsonFile(path.join(packageDir, "package.json"));
|
|
1156
|
+
if (!pkg || !hasOpenClawExtensions(pkg)) {
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
const packageName = readString(pkg.name);
|
|
1160
|
+
if (!packageName?.startsWith("@nextclaw/")) {
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
packages.push({
|
|
1164
|
+
packageName,
|
|
1165
|
+
dir: packageDir
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
return packages;
|
|
1169
|
+
};
|
|
1170
|
+
var resolveDevFirstPartyPluginLoadPaths = (config2, workspaceExtensionsDir) => {
|
|
1171
|
+
const rootDir = workspaceExtensionsDir?.trim();
|
|
1172
|
+
if (!rootDir) {
|
|
1173
|
+
return [];
|
|
1174
|
+
}
|
|
1175
|
+
const workspacePackages = readWorkspacePluginPackages(rootDir);
|
|
1176
|
+
if (workspacePackages.length === 0) {
|
|
1177
|
+
return [];
|
|
1178
|
+
}
|
|
1179
|
+
const packageDirByName = new Map(workspacePackages.map((entry) => [entry.packageName, entry.dir]));
|
|
1180
|
+
const loadPaths = [];
|
|
1181
|
+
const installs = config2.plugins.installs ?? {};
|
|
1182
|
+
for (const installRecord of Object.values(installs)) {
|
|
1183
|
+
const packageName = normalizePackageSpec(installRecord.spec ?? "");
|
|
1184
|
+
if (!packageName) {
|
|
1185
|
+
continue;
|
|
1186
|
+
}
|
|
1187
|
+
const packageDir = packageDirByName.get(packageName);
|
|
1188
|
+
if (!packageDir || loadPaths.includes(packageDir)) {
|
|
1189
|
+
continue;
|
|
1190
|
+
}
|
|
1191
|
+
loadPaths.push(packageDir);
|
|
1192
|
+
}
|
|
1193
|
+
return loadPaths;
|
|
1194
|
+
};
|
|
1195
|
+
var resolveDevFirstPartyPluginInstallRoots = (config2, workspaceExtensionsDir) => {
|
|
1196
|
+
const rootDir = workspaceExtensionsDir?.trim();
|
|
1197
|
+
if (!rootDir) {
|
|
1198
|
+
return [];
|
|
1199
|
+
}
|
|
1200
|
+
const workspacePackages = readWorkspacePluginPackages(rootDir);
|
|
1201
|
+
if (workspacePackages.length === 0) {
|
|
1202
|
+
return [];
|
|
1203
|
+
}
|
|
1204
|
+
const packageNames = new Set(workspacePackages.map((entry) => entry.packageName));
|
|
1205
|
+
const installRoots = [];
|
|
1206
|
+
for (const installRecord of Object.values(config2.plugins.installs ?? {})) {
|
|
1207
|
+
const packageName = normalizePackageSpec(installRecord.spec ?? "");
|
|
1208
|
+
if (!packageName || !packageNames.has(packageName)) {
|
|
1209
|
+
continue;
|
|
1210
|
+
}
|
|
1211
|
+
const installPath = readString(installRecord.installPath);
|
|
1212
|
+
if (!installPath || installRoots.includes(installPath)) {
|
|
1213
|
+
continue;
|
|
1214
|
+
}
|
|
1215
|
+
installRoots.push(installPath);
|
|
1216
|
+
}
|
|
1217
|
+
return installRoots;
|
|
1218
|
+
};
|
|
1219
|
+
var applyDevFirstPartyPluginLoadPaths = (config2, workspaceExtensionsDir) => {
|
|
1220
|
+
const devLoadPaths = resolveDevFirstPartyPluginLoadPaths(config2, workspaceExtensionsDir);
|
|
1221
|
+
if (devLoadPaths.length === 0) {
|
|
1222
|
+
return config2;
|
|
1223
|
+
}
|
|
1224
|
+
const existingLoadPaths = Array.isArray(config2.plugins.load?.paths) ? config2.plugins.load.paths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
1225
|
+
const mergedLoadPaths = [...devLoadPaths];
|
|
1226
|
+
for (const entry of existingLoadPaths) {
|
|
1227
|
+
if (!mergedLoadPaths.includes(entry)) {
|
|
1228
|
+
mergedLoadPaths.push(entry);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return {
|
|
1232
|
+
...config2,
|
|
1233
|
+
plugins: {
|
|
1234
|
+
...config2.plugins,
|
|
1235
|
+
load: {
|
|
1236
|
+
...config2.plugins.load,
|
|
1237
|
+
paths: mergedLoadPaths
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
};
|
|
1242
|
+
|
|
1243
|
+
// src/cli/commands/plugins.ts
|
|
1244
|
+
import {
|
|
1245
|
+
loadConfig as loadConfig2,
|
|
1246
|
+
getWorkspacePath as getWorkspacePath2
|
|
1247
|
+
} from "@nextclaw/core";
|
|
1248
|
+
import { createInterface } from "readline";
|
|
1249
|
+
import { resolve as resolve7 } from "path";
|
|
1250
|
+
|
|
1251
|
+
// src/cli/commands/plugin-mutation-actions.ts
|
|
1046
1252
|
import {
|
|
1047
1253
|
addPluginLoadPath,
|
|
1048
1254
|
buildPluginStatusReport,
|
|
@@ -1050,48 +1256,203 @@ import {
|
|
|
1050
1256
|
enablePluginInConfig,
|
|
1051
1257
|
installPluginFromNpmSpec,
|
|
1052
1258
|
installPluginFromPath,
|
|
1053
|
-
loadOpenClawPlugins,
|
|
1054
1259
|
recordPluginInstall,
|
|
1055
|
-
resolveUninstallDirectoryTarget,
|
|
1056
1260
|
uninstallPlugin
|
|
1057
1261
|
} from "@nextclaw/openclaw-compat";
|
|
1058
|
-
import {
|
|
1059
|
-
loadConfig,
|
|
1060
|
-
saveConfig,
|
|
1061
|
-
getWorkspacePath,
|
|
1062
|
-
expandHome
|
|
1063
|
-
} from "@nextclaw/core";
|
|
1064
|
-
import { builtinProviderIds } from "@nextclaw/runtime";
|
|
1065
|
-
import { createInterface } from "readline";
|
|
1066
1262
|
import { existsSync as existsSync5 } from "fs";
|
|
1067
1263
|
import { resolve as resolve6 } from "path";
|
|
1068
|
-
|
|
1264
|
+
import { expandHome, getWorkspacePath, loadConfig, saveConfig } from "@nextclaw/core";
|
|
1265
|
+
function resolveFileNpmSpecToLocalPath(raw) {
|
|
1266
|
+
const trimmed = raw.trim();
|
|
1267
|
+
if (!trimmed.toLowerCase().startsWith("file:")) {
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
const rest = trimmed.slice("file:".length);
|
|
1271
|
+
if (!rest) {
|
|
1272
|
+
return { ok: false, error: "unsupported file: spec: missing path" };
|
|
1273
|
+
}
|
|
1274
|
+
if (rest.startsWith("///")) {
|
|
1275
|
+
return { ok: true, path: rest.slice(2) };
|
|
1276
|
+
}
|
|
1277
|
+
if (rest.startsWith("//localhost/")) {
|
|
1278
|
+
return { ok: true, path: rest.slice("//localhost".length) };
|
|
1279
|
+
}
|
|
1280
|
+
if (rest.startsWith("//")) {
|
|
1281
|
+
return {
|
|
1282
|
+
ok: false,
|
|
1283
|
+
error: 'unsupported file: URL host (expected "file:<path>" or "file:///abs/path")'
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
return { ok: true, path: rest };
|
|
1287
|
+
}
|
|
1288
|
+
function looksLikePath(raw) {
|
|
1289
|
+
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");
|
|
1290
|
+
}
|
|
1291
|
+
function isArchivePath(filePath) {
|
|
1292
|
+
const lower = filePath.toLowerCase();
|
|
1293
|
+
return lower.endsWith(".zip") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz") || lower.endsWith(".tar");
|
|
1294
|
+
}
|
|
1295
|
+
async function enablePluginMutation(id) {
|
|
1296
|
+
const config2 = loadConfig();
|
|
1297
|
+
const next = enablePluginInConfig(config2, id);
|
|
1298
|
+
saveConfig(next);
|
|
1299
|
+
return {
|
|
1300
|
+
message: `Enabled plugin "${id}".`
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
async function disablePluginMutation(id) {
|
|
1304
|
+
const config2 = loadConfig();
|
|
1305
|
+
const next = disablePluginInConfig(config2, id);
|
|
1306
|
+
saveConfig(next);
|
|
1307
|
+
return {
|
|
1308
|
+
message: `Disabled plugin "${id}".`
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
async function uninstallPluginMutation(id, opts = {}) {
|
|
1312
|
+
const config2 = loadConfig();
|
|
1313
|
+
const workspaceDir = getWorkspacePath(config2.agents.defaults.workspace);
|
|
1314
|
+
const report = buildPluginStatusReport({
|
|
1315
|
+
config: config2,
|
|
1316
|
+
workspaceDir,
|
|
1317
|
+
...buildReservedPluginLoadOptions()
|
|
1318
|
+
});
|
|
1319
|
+
const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
|
|
1320
|
+
const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
|
|
1321
|
+
const pluginId = plugin?.id ?? id;
|
|
1322
|
+
const hasEntry = pluginId in (config2.plugins.entries ?? {});
|
|
1323
|
+
const hasInstall = pluginId in (config2.plugins.installs ?? {});
|
|
1324
|
+
if (!hasEntry && !hasInstall) {
|
|
1325
|
+
if (plugin) {
|
|
1326
|
+
throw new Error(
|
|
1327
|
+
`Plugin "${pluginId}" is not managed by plugins config/install records and cannot be uninstalled.`
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
throw new Error(`Plugin not found: ${id}`);
|
|
1331
|
+
}
|
|
1332
|
+
const result = await uninstallPlugin({
|
|
1333
|
+
config: config2,
|
|
1334
|
+
pluginId,
|
|
1335
|
+
deleteFiles: !keepFiles
|
|
1336
|
+
});
|
|
1337
|
+
if (!result.ok) {
|
|
1338
|
+
throw new Error(result.error);
|
|
1339
|
+
}
|
|
1340
|
+
saveConfig(result.config);
|
|
1341
|
+
const removed = [];
|
|
1342
|
+
if (result.actions.entry) {
|
|
1343
|
+
removed.push("config entry");
|
|
1344
|
+
}
|
|
1345
|
+
if (result.actions.install) {
|
|
1346
|
+
removed.push("install record");
|
|
1347
|
+
}
|
|
1348
|
+
if (result.actions.allowlist) {
|
|
1349
|
+
removed.push("allowlist");
|
|
1350
|
+
}
|
|
1351
|
+
if (result.actions.loadPath) {
|
|
1352
|
+
removed.push("load path");
|
|
1353
|
+
}
|
|
1354
|
+
if (result.actions.directory) {
|
|
1355
|
+
removed.push("directory");
|
|
1356
|
+
}
|
|
1357
|
+
return {
|
|
1358
|
+
message: `Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`,
|
|
1359
|
+
warnings: result.warnings
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
async function installPluginMutation(pathOrSpec, opts = {}) {
|
|
1363
|
+
const fileSpec = resolveFileNpmSpecToLocalPath(pathOrSpec);
|
|
1364
|
+
if (fileSpec && !fileSpec.ok) {
|
|
1365
|
+
throw new Error(fileSpec.error);
|
|
1366
|
+
}
|
|
1367
|
+
const normalized = fileSpec && fileSpec.ok ? fileSpec.path : pathOrSpec;
|
|
1368
|
+
const resolved = resolve6(expandHome(normalized));
|
|
1369
|
+
const config2 = loadConfig();
|
|
1370
|
+
if (existsSync5(resolved)) {
|
|
1371
|
+
if (opts.link) {
|
|
1372
|
+
const probe = await installPluginFromPath({ path: resolved, dryRun: true });
|
|
1373
|
+
if (!probe.ok) {
|
|
1374
|
+
throw new Error(probe.error);
|
|
1375
|
+
}
|
|
1376
|
+
let next3 = addPluginLoadPath(config2, resolved);
|
|
1377
|
+
next3 = enablePluginInConfig(next3, probe.pluginId);
|
|
1378
|
+
next3 = recordPluginInstall(next3, {
|
|
1379
|
+
pluginId: probe.pluginId,
|
|
1380
|
+
source: "path",
|
|
1381
|
+
sourcePath: resolved,
|
|
1382
|
+
installPath: resolved,
|
|
1383
|
+
version: probe.version
|
|
1384
|
+
});
|
|
1385
|
+
saveConfig(next3);
|
|
1386
|
+
return {
|
|
1387
|
+
message: `Linked plugin path: ${resolved}`
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
const result2 = await installPluginFromPath({
|
|
1391
|
+
path: resolved,
|
|
1392
|
+
logger: {
|
|
1393
|
+
info: (message) => console.log(message),
|
|
1394
|
+
warn: (message) => console.warn(message)
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
if (!result2.ok) {
|
|
1398
|
+
throw new Error(result2.error);
|
|
1399
|
+
}
|
|
1400
|
+
let next2 = enablePluginInConfig(config2, result2.pluginId);
|
|
1401
|
+
next2 = recordPluginInstall(next2, {
|
|
1402
|
+
pluginId: result2.pluginId,
|
|
1403
|
+
source: isArchivePath(resolved) ? "archive" : "path",
|
|
1404
|
+
sourcePath: resolved,
|
|
1405
|
+
installPath: result2.targetDir,
|
|
1406
|
+
version: result2.version
|
|
1407
|
+
});
|
|
1408
|
+
saveConfig(next2);
|
|
1409
|
+
return {
|
|
1410
|
+
message: `Installed plugin: ${result2.pluginId}`
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
if (opts.link) {
|
|
1414
|
+
throw new Error("`--link` requires a local path.");
|
|
1415
|
+
}
|
|
1416
|
+
if (looksLikePath(pathOrSpec)) {
|
|
1417
|
+
throw new Error(`Path not found: ${resolved}`);
|
|
1418
|
+
}
|
|
1419
|
+
const result = await installPluginFromNpmSpec({
|
|
1420
|
+
spec: pathOrSpec,
|
|
1421
|
+
logger: {
|
|
1422
|
+
info: (message) => console.log(message),
|
|
1423
|
+
warn: (message) => console.warn(message)
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1426
|
+
if (!result.ok) {
|
|
1427
|
+
throw new Error(result.error);
|
|
1428
|
+
}
|
|
1429
|
+
let next = enablePluginInConfig(config2, result.pluginId);
|
|
1430
|
+
next = recordPluginInstall(next, {
|
|
1431
|
+
pluginId: result.pluginId,
|
|
1432
|
+
source: "npm",
|
|
1433
|
+
spec: pathOrSpec,
|
|
1434
|
+
installPath: result.targetDir,
|
|
1435
|
+
version: result.version
|
|
1436
|
+
});
|
|
1437
|
+
saveConfig(next);
|
|
1438
|
+
return {
|
|
1439
|
+
message: `Installed plugin: ${result.pluginId}`
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// src/cli/commands/plugins.ts
|
|
1069
1444
|
function loadPluginRegistry(config2, workspaceDir) {
|
|
1445
|
+
const workspaceExtensionsDir = process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR;
|
|
1446
|
+
const configWithDevPluginPaths = applyDevFirstPartyPluginLoadPaths(
|
|
1447
|
+
config2,
|
|
1448
|
+
workspaceExtensionsDir
|
|
1449
|
+
);
|
|
1450
|
+
const excludedRoots = resolveDevFirstPartyPluginInstallRoots(config2, workspaceExtensionsDir);
|
|
1070
1451
|
return loadOpenClawPlugins({
|
|
1071
|
-
config:
|
|
1452
|
+
config: configWithDevPluginPaths,
|
|
1072
1453
|
workspaceDir,
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
"write_file",
|
|
1076
|
-
"edit_file",
|
|
1077
|
-
"list_dir",
|
|
1078
|
-
"exec",
|
|
1079
|
-
"web_search",
|
|
1080
|
-
"web_fetch",
|
|
1081
|
-
"message",
|
|
1082
|
-
"spawn",
|
|
1083
|
-
"sessions_list",
|
|
1084
|
-
"sessions_history",
|
|
1085
|
-
"sessions_send",
|
|
1086
|
-
"memory_search",
|
|
1087
|
-
"memory_get",
|
|
1088
|
-
"subagents",
|
|
1089
|
-
"gateway",
|
|
1090
|
-
"cron"
|
|
1091
|
-
],
|
|
1092
|
-
reservedChannelIds: [],
|
|
1093
|
-
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1094
|
-
reservedEngineKinds: ["native"],
|
|
1454
|
+
excludeRoots: excludedRoots,
|
|
1455
|
+
...buildReservedPluginLoadOptions(),
|
|
1095
1456
|
logger: {
|
|
1096
1457
|
info: (message) => console.log(message),
|
|
1097
1458
|
warn: (message) => console.warn(message),
|
|
@@ -1120,6 +1481,13 @@ function toExtensionRegistry(pluginRegistry) {
|
|
|
1120
1481
|
factory: engine.factory,
|
|
1121
1482
|
source: engine.source
|
|
1122
1483
|
})),
|
|
1484
|
+
ncpAgentRuntimes: pluginRegistry.ncpAgentRuntimes.map((runtime2) => ({
|
|
1485
|
+
pluginId: runtime2.pluginId,
|
|
1486
|
+
kind: runtime2.kind,
|
|
1487
|
+
label: runtime2.label,
|
|
1488
|
+
createRuntime: runtime2.createRuntime,
|
|
1489
|
+
source: runtime2.source
|
|
1490
|
+
})),
|
|
1123
1491
|
diagnostics: pluginRegistry.diagnostics.map((diag) => ({
|
|
1124
1492
|
level: diag.level,
|
|
1125
1493
|
message: diag.message,
|
|
@@ -1178,15 +1546,25 @@ function mergePluginConfigView(baseConfig, pluginViewConfig, bindings) {
|
|
|
1178
1546
|
var PluginCommands = class {
|
|
1179
1547
|
constructor() {
|
|
1180
1548
|
}
|
|
1549
|
+
async enablePlugin(id) {
|
|
1550
|
+
return await enablePluginMutation(id);
|
|
1551
|
+
}
|
|
1552
|
+
async disablePlugin(id) {
|
|
1553
|
+
return await disablePluginMutation(id);
|
|
1554
|
+
}
|
|
1555
|
+
async uninstallPlugin(id, opts = {}) {
|
|
1556
|
+
return await uninstallPluginMutation(id, opts);
|
|
1557
|
+
}
|
|
1558
|
+
async installPlugin(pathOrSpec, opts = {}) {
|
|
1559
|
+
return await installPluginMutation(pathOrSpec, opts);
|
|
1560
|
+
}
|
|
1181
1561
|
pluginsList(opts = {}) {
|
|
1182
|
-
const config2 =
|
|
1183
|
-
const workspaceDir =
|
|
1184
|
-
const report =
|
|
1562
|
+
const config2 = loadConfig2();
|
|
1563
|
+
const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
|
|
1564
|
+
const report = buildPluginStatusReport2({
|
|
1185
1565
|
config: config2,
|
|
1186
1566
|
workspaceDir,
|
|
1187
|
-
|
|
1188
|
-
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1189
|
-
reservedEngineKinds: ["native"]
|
|
1567
|
+
...buildReservedPluginLoadOptions()
|
|
1190
1568
|
});
|
|
1191
1569
|
const list = opts.enabled ? report.plugins.filter((plugin) => plugin.status === "loaded") : report.plugins;
|
|
1192
1570
|
if (opts.json) {
|
|
@@ -1221,17 +1599,10 @@ var PluginCommands = class {
|
|
|
1221
1599
|
if (plugin.version) {
|
|
1222
1600
|
console.log(` version: ${plugin.version}`);
|
|
1223
1601
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
console.log(` channels: ${plugin.channelIds.join(", ")}`);
|
|
1229
|
-
}
|
|
1230
|
-
if (plugin.providerIds.length > 0) {
|
|
1231
|
-
console.log(` providers: ${plugin.providerIds.join(", ")}`);
|
|
1232
|
-
}
|
|
1233
|
-
if (plugin.engineKinds.length > 0) {
|
|
1234
|
-
console.log(` engines: ${plugin.engineKinds.join(", ")}`);
|
|
1602
|
+
const capabilityLines = [];
|
|
1603
|
+
appendPluginCapabilityLines(capabilityLines, plugin);
|
|
1604
|
+
for (const line of capabilityLines) {
|
|
1605
|
+
console.log(` ${line.toLowerCase()}`);
|
|
1235
1606
|
}
|
|
1236
1607
|
if (plugin.error) {
|
|
1237
1608
|
console.log(` error: ${plugin.error}`);
|
|
@@ -1240,14 +1611,12 @@ var PluginCommands = class {
|
|
|
1240
1611
|
}
|
|
1241
1612
|
}
|
|
1242
1613
|
pluginsInfo(id, opts = {}) {
|
|
1243
|
-
const config2 =
|
|
1244
|
-
const workspaceDir =
|
|
1245
|
-
const report =
|
|
1614
|
+
const config2 = loadConfig2();
|
|
1615
|
+
const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
|
|
1616
|
+
const report = buildPluginStatusReport2({
|
|
1246
1617
|
config: config2,
|
|
1247
1618
|
workspaceDir,
|
|
1248
|
-
|
|
1249
|
-
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1250
|
-
reservedEngineKinds: ["native"]
|
|
1619
|
+
...buildReservedPluginLoadOptions()
|
|
1251
1620
|
});
|
|
1252
1621
|
const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
|
|
1253
1622
|
if (!plugin) {
|
|
@@ -1274,18 +1643,7 @@ var PluginCommands = class {
|
|
|
1274
1643
|
if (plugin.version) {
|
|
1275
1644
|
lines.push(`Version: ${plugin.version}`);
|
|
1276
1645
|
}
|
|
1277
|
-
|
|
1278
|
-
lines.push(`Tools: ${plugin.toolNames.join(", ")}`);
|
|
1279
|
-
}
|
|
1280
|
-
if (plugin.channelIds.length > 0) {
|
|
1281
|
-
lines.push(`Channels: ${plugin.channelIds.join(", ")}`);
|
|
1282
|
-
}
|
|
1283
|
-
if (plugin.providerIds.length > 0) {
|
|
1284
|
-
lines.push(`Providers: ${plugin.providerIds.join(", ")}`);
|
|
1285
|
-
}
|
|
1286
|
-
if (plugin.engineKinds.length > 0) {
|
|
1287
|
-
lines.push(`Engines: ${plugin.engineKinds.join(", ")}`);
|
|
1288
|
-
}
|
|
1646
|
+
appendPluginCapabilityLines(lines, plugin);
|
|
1289
1647
|
if (plugin.error) {
|
|
1290
1648
|
lines.push(`Error: ${plugin.error}`);
|
|
1291
1649
|
}
|
|
@@ -1311,33 +1669,37 @@ var PluginCommands = class {
|
|
|
1311
1669
|
console.log(lines.join("\n"));
|
|
1312
1670
|
}
|
|
1313
1671
|
async pluginsEnable(id) {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1672
|
+
try {
|
|
1673
|
+
const result = await this.enablePlugin(id);
|
|
1674
|
+
console.log(result.message);
|
|
1675
|
+
} catch (error) {
|
|
1676
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1677
|
+
process.exit(1);
|
|
1678
|
+
}
|
|
1318
1679
|
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1319
1680
|
}
|
|
1320
1681
|
async pluginsDisable(id) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1682
|
+
try {
|
|
1683
|
+
const result = await this.disablePlugin(id);
|
|
1684
|
+
console.log(result.message);
|
|
1685
|
+
} catch (error) {
|
|
1686
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1687
|
+
process.exit(1);
|
|
1688
|
+
}
|
|
1325
1689
|
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1326
1690
|
}
|
|
1327
1691
|
async pluginsUninstall(id, opts = {}) {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1692
|
+
if (opts.keepConfig) {
|
|
1693
|
+
console.log("`--keep-config` is deprecated, use `--keep-files`.");
|
|
1694
|
+
}
|
|
1695
|
+
const config2 = loadConfig2();
|
|
1696
|
+
const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
|
|
1697
|
+
const report = buildPluginStatusReport2({
|
|
1331
1698
|
config: config2,
|
|
1332
1699
|
workspaceDir,
|
|
1333
|
-
|
|
1334
|
-
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1335
|
-
reservedEngineKinds: ["native"]
|
|
1700
|
+
...buildReservedPluginLoadOptions()
|
|
1336
1701
|
});
|
|
1337
1702
|
const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
|
|
1338
|
-
if (opts.keepConfig) {
|
|
1339
|
-
console.log("`--keep-config` is deprecated, use `--keep-files`.");
|
|
1340
|
-
}
|
|
1341
1703
|
const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
|
|
1342
1704
|
const pluginId = plugin?.id ?? id;
|
|
1343
1705
|
const hasEntry = pluginId in (config2.plugins.entries ?? {});
|
|
@@ -1353,7 +1715,7 @@ var PluginCommands = class {
|
|
|
1353
1715
|
process.exit(1);
|
|
1354
1716
|
}
|
|
1355
1717
|
const install = config2.plugins.installs?.[pluginId];
|
|
1356
|
-
const isLinked = install?.source === "path" && (!install.installPath || !install.sourcePath ||
|
|
1718
|
+
const isLinked = install?.source === "path" && (!install.installPath || !install.sourcePath || resolve7(install.installPath) === resolve7(install.sourcePath));
|
|
1357
1719
|
const preview = [];
|
|
1358
1720
|
if (hasEntry) {
|
|
1359
1721
|
preview.push("config entry");
|
|
@@ -1367,12 +1729,13 @@ var PluginCommands = class {
|
|
|
1367
1729
|
if (isLinked && install?.sourcePath && config2.plugins.load?.paths?.includes(install.sourcePath)) {
|
|
1368
1730
|
preview.push("load path");
|
|
1369
1731
|
}
|
|
1370
|
-
const
|
|
1732
|
+
const deleteTargets = !keepFiles ? resolveUninstallDirectoryTargets({
|
|
1733
|
+
config: config2,
|
|
1371
1734
|
pluginId,
|
|
1372
1735
|
hasInstall,
|
|
1373
1736
|
installRecord: install
|
|
1374
|
-
}) :
|
|
1375
|
-
|
|
1737
|
+
}) : [];
|
|
1738
|
+
for (const deleteTarget of deleteTargets) {
|
|
1376
1739
|
preview.push(`directory: ${deleteTarget}`);
|
|
1377
1740
|
}
|
|
1378
1741
|
const pluginName = plugin?.name || pluginId;
|
|
@@ -1390,132 +1753,35 @@ var PluginCommands = class {
|
|
|
1390
1753
|
return;
|
|
1391
1754
|
}
|
|
1392
1755
|
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1756
|
+
try {
|
|
1757
|
+
const result = await this.uninstallPlugin(id, opts);
|
|
1758
|
+
for (const warning of result.warnings) {
|
|
1759
|
+
console.warn(warning);
|
|
1760
|
+
}
|
|
1761
|
+
console.log(result.message);
|
|
1762
|
+
} catch (error) {
|
|
1763
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1400
1764
|
process.exit(1);
|
|
1401
1765
|
}
|
|
1402
|
-
for (const warning of result.warnings) {
|
|
1403
|
-
console.warn(warning);
|
|
1404
|
-
}
|
|
1405
|
-
saveConfig(result.config);
|
|
1406
|
-
const removed = [];
|
|
1407
|
-
if (result.actions.entry) {
|
|
1408
|
-
removed.push("config entry");
|
|
1409
|
-
}
|
|
1410
|
-
if (result.actions.install) {
|
|
1411
|
-
removed.push("install record");
|
|
1412
|
-
}
|
|
1413
|
-
if (result.actions.allowlist) {
|
|
1414
|
-
removed.push("allowlist");
|
|
1415
|
-
}
|
|
1416
|
-
if (result.actions.loadPath) {
|
|
1417
|
-
removed.push("load path");
|
|
1418
|
-
}
|
|
1419
|
-
if (result.actions.directory) {
|
|
1420
|
-
removed.push("directory");
|
|
1421
|
-
}
|
|
1422
|
-
console.log(`Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`);
|
|
1423
1766
|
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1424
1767
|
}
|
|
1425
1768
|
async pluginsInstall(pathOrSpec, opts = {}) {
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
console.
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
const normalized = fileSpec && fileSpec.ok ? fileSpec.path : pathOrSpec;
|
|
1432
|
-
const resolved = resolve6(expandHome(normalized));
|
|
1433
|
-
const config2 = loadConfig();
|
|
1434
|
-
if (existsSync5(resolved)) {
|
|
1435
|
-
if (opts.link) {
|
|
1436
|
-
const probe = await installPluginFromPath({ path: resolved, dryRun: true });
|
|
1437
|
-
if (!probe.ok) {
|
|
1438
|
-
console.error(probe.error);
|
|
1439
|
-
process.exit(1);
|
|
1440
|
-
}
|
|
1441
|
-
let next3 = addPluginLoadPath(config2, resolved);
|
|
1442
|
-
next3 = enablePluginInConfig(next3, probe.pluginId);
|
|
1443
|
-
next3 = recordPluginInstall(next3, {
|
|
1444
|
-
pluginId: probe.pluginId,
|
|
1445
|
-
source: "path",
|
|
1446
|
-
sourcePath: resolved,
|
|
1447
|
-
installPath: resolved,
|
|
1448
|
-
version: probe.version
|
|
1449
|
-
});
|
|
1450
|
-
saveConfig(next3);
|
|
1451
|
-
console.log(`Linked plugin path: ${resolved}`);
|
|
1452
|
-
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1453
|
-
return;
|
|
1454
|
-
}
|
|
1455
|
-
const result2 = await installPluginFromPath({
|
|
1456
|
-
path: resolved,
|
|
1457
|
-
logger: {
|
|
1458
|
-
info: (message) => console.log(message),
|
|
1459
|
-
warn: (message) => console.warn(message)
|
|
1460
|
-
}
|
|
1461
|
-
});
|
|
1462
|
-
if (!result2.ok) {
|
|
1463
|
-
console.error(result2.error);
|
|
1464
|
-
process.exit(1);
|
|
1465
|
-
}
|
|
1466
|
-
let next2 = enablePluginInConfig(config2, result2.pluginId);
|
|
1467
|
-
next2 = recordPluginInstall(next2, {
|
|
1468
|
-
pluginId: result2.pluginId,
|
|
1469
|
-
source: this.isArchivePath(resolved) ? "archive" : "path",
|
|
1470
|
-
sourcePath: resolved,
|
|
1471
|
-
installPath: result2.targetDir,
|
|
1472
|
-
version: result2.version
|
|
1473
|
-
});
|
|
1474
|
-
saveConfig(next2);
|
|
1475
|
-
console.log(`Installed plugin: ${result2.pluginId}`);
|
|
1476
|
-
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1477
|
-
return;
|
|
1478
|
-
}
|
|
1479
|
-
if (opts.link) {
|
|
1480
|
-
console.error("`--link` requires a local path.");
|
|
1481
|
-
process.exit(1);
|
|
1482
|
-
}
|
|
1483
|
-
if (this.looksLikePath(pathOrSpec)) {
|
|
1484
|
-
console.error(`Path not found: ${resolved}`);
|
|
1485
|
-
process.exit(1);
|
|
1486
|
-
}
|
|
1487
|
-
const result = await installPluginFromNpmSpec({
|
|
1488
|
-
spec: pathOrSpec,
|
|
1489
|
-
logger: {
|
|
1490
|
-
info: (message) => console.log(message),
|
|
1491
|
-
warn: (message) => console.warn(message)
|
|
1492
|
-
}
|
|
1493
|
-
});
|
|
1494
|
-
if (!result.ok) {
|
|
1495
|
-
console.error(result.error);
|
|
1769
|
+
try {
|
|
1770
|
+
const result = await this.installPlugin(pathOrSpec, opts);
|
|
1771
|
+
console.log(result.message);
|
|
1772
|
+
} catch (error) {
|
|
1773
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1496
1774
|
process.exit(1);
|
|
1497
1775
|
}
|
|
1498
|
-
let next = enablePluginInConfig(config2, result.pluginId);
|
|
1499
|
-
next = recordPluginInstall(next, {
|
|
1500
|
-
pluginId: result.pluginId,
|
|
1501
|
-
source: "npm",
|
|
1502
|
-
spec: pathOrSpec,
|
|
1503
|
-
installPath: result.targetDir,
|
|
1504
|
-
version: result.version
|
|
1505
|
-
});
|
|
1506
|
-
saveConfig(next);
|
|
1507
|
-
console.log(`Installed plugin: ${result.pluginId}`);
|
|
1508
1776
|
console.log("If gateway is running, plugin changes are hot-applied automatically.");
|
|
1509
1777
|
}
|
|
1510
1778
|
pluginsDoctor() {
|
|
1511
|
-
const config2 =
|
|
1512
|
-
const workspaceDir =
|
|
1513
|
-
const report =
|
|
1779
|
+
const config2 = loadConfig2();
|
|
1780
|
+
const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
|
|
1781
|
+
const report = buildPluginStatusReport2({
|
|
1514
1782
|
config: config2,
|
|
1515
1783
|
workspaceDir,
|
|
1516
|
-
|
|
1517
|
-
reservedProviderIds: RESERVED_PROVIDER_IDS,
|
|
1518
|
-
reservedEngineKinds: ["native"]
|
|
1784
|
+
...buildReservedPluginLoadOptions()
|
|
1519
1785
|
});
|
|
1520
1786
|
const pluginErrors = report.plugins.filter((plugin) => plugin.status === "error");
|
|
1521
1787
|
const diagnostics = report.diagnostics.filter((diag) => diag.level === "error");
|
|
@@ -1545,47 +1811,17 @@ var PluginCommands = class {
|
|
|
1545
1811
|
input: process.stdin,
|
|
1546
1812
|
output: process.stdout
|
|
1547
1813
|
});
|
|
1548
|
-
const answer = await new Promise((
|
|
1549
|
-
rl.question(`${question} [y/N] `, (line) =>
|
|
1814
|
+
const answer = await new Promise((resolve13) => {
|
|
1815
|
+
rl.question(`${question} [y/N] `, (line) => resolve13(line));
|
|
1550
1816
|
});
|
|
1551
1817
|
rl.close();
|
|
1552
1818
|
const normalized = answer.trim().toLowerCase();
|
|
1553
1819
|
return normalized === "y" || normalized === "yes";
|
|
1554
1820
|
}
|
|
1555
|
-
resolveFileNpmSpecToLocalPath(raw) {
|
|
1556
|
-
const trimmed = raw.trim();
|
|
1557
|
-
if (!trimmed.toLowerCase().startsWith("file:")) {
|
|
1558
|
-
return null;
|
|
1559
|
-
}
|
|
1560
|
-
const rest = trimmed.slice("file:".length);
|
|
1561
|
-
if (!rest) {
|
|
1562
|
-
return { ok: false, error: "unsupported file: spec: missing path" };
|
|
1563
|
-
}
|
|
1564
|
-
if (rest.startsWith("///")) {
|
|
1565
|
-
return { ok: true, path: rest.slice(2) };
|
|
1566
|
-
}
|
|
1567
|
-
if (rest.startsWith("//localhost/")) {
|
|
1568
|
-
return { ok: true, path: rest.slice("//localhost".length) };
|
|
1569
|
-
}
|
|
1570
|
-
if (rest.startsWith("//")) {
|
|
1571
|
-
return {
|
|
1572
|
-
ok: false,
|
|
1573
|
-
error: 'unsupported file: URL host (expected "file:<path>" or "file:///abs/path")'
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
|
-
return { ok: true, path: rest };
|
|
1577
|
-
}
|
|
1578
|
-
looksLikePath(raw) {
|
|
1579
|
-
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");
|
|
1580
|
-
}
|
|
1581
|
-
isArchivePath(filePath) {
|
|
1582
|
-
const lower = filePath.toLowerCase();
|
|
1583
|
-
return lower.endsWith(".zip") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz") || lower.endsWith(".tar");
|
|
1584
|
-
}
|
|
1585
1821
|
};
|
|
1586
1822
|
|
|
1587
1823
|
// src/cli/commands/config.ts
|
|
1588
|
-
import { buildReloadPlan, diffConfigPaths, loadConfig as
|
|
1824
|
+
import { buildReloadPlan, diffConfigPaths, loadConfig as loadConfig3, saveConfig as saveConfig2 } from "@nextclaw/core";
|
|
1589
1825
|
|
|
1590
1826
|
// src/cli/config-path.ts
|
|
1591
1827
|
function isIndexSegment(raw) {
|
|
@@ -1780,7 +2016,7 @@ var ConfigCommands = class {
|
|
|
1780
2016
|
this.deps = deps;
|
|
1781
2017
|
}
|
|
1782
2018
|
configGet(pathExpr, opts = {}) {
|
|
1783
|
-
const config2 =
|
|
2019
|
+
const config2 = loadConfig3();
|
|
1784
2020
|
let parsedPath;
|
|
1785
2021
|
try {
|
|
1786
2022
|
parsedPath = parseRequiredConfigPath(pathExpr);
|
|
@@ -1822,7 +2058,7 @@ var ConfigCommands = class {
|
|
|
1822
2058
|
process.exit(1);
|
|
1823
2059
|
return;
|
|
1824
2060
|
}
|
|
1825
|
-
const prevConfig =
|
|
2061
|
+
const prevConfig = loadConfig3();
|
|
1826
2062
|
const nextConfig = structuredClone(prevConfig);
|
|
1827
2063
|
try {
|
|
1828
2064
|
setAtConfigPath(nextConfig, parsedPath, parsedValue);
|
|
@@ -1848,7 +2084,7 @@ var ConfigCommands = class {
|
|
|
1848
2084
|
process.exit(1);
|
|
1849
2085
|
return;
|
|
1850
2086
|
}
|
|
1851
|
-
const prevConfig =
|
|
2087
|
+
const prevConfig = loadConfig3();
|
|
1852
2088
|
const nextConfig = structuredClone(prevConfig);
|
|
1853
2089
|
const removed = unsetAtConfigPath(nextConfig, parsedPath);
|
|
1854
2090
|
if (!removed) {
|
|
@@ -1886,7 +2122,7 @@ import {
|
|
|
1886
2122
|
buildReloadPlan as buildReloadPlan2,
|
|
1887
2123
|
diffConfigPaths as diffConfigPaths2,
|
|
1888
2124
|
getConfigPath,
|
|
1889
|
-
loadConfig as
|
|
2125
|
+
loadConfig as loadConfig4,
|
|
1890
2126
|
resolveConfigSecrets,
|
|
1891
2127
|
saveConfig as saveConfig3
|
|
1892
2128
|
} from "@nextclaw/core";
|
|
@@ -1939,17 +2175,17 @@ function parseRefsPatch(raw) {
|
|
|
1939
2175
|
throw new Error("refs patch must be an object");
|
|
1940
2176
|
}
|
|
1941
2177
|
const output = {};
|
|
1942
|
-
for (const [
|
|
2178
|
+
for (const [path2, value] of Object.entries(raw)) {
|
|
1943
2179
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1944
|
-
throw new Error(`invalid ref for ${
|
|
2180
|
+
throw new Error(`invalid ref for ${path2}`);
|
|
1945
2181
|
}
|
|
1946
2182
|
const source = normalizeSecretSource(value.source);
|
|
1947
2183
|
const id = normalizeOptionalString(value.id);
|
|
1948
2184
|
const provider = normalizeOptionalString(value.provider);
|
|
1949
2185
|
if (!source || !id) {
|
|
1950
|
-
throw new Error(`invalid ref for ${
|
|
2186
|
+
throw new Error(`invalid ref for ${path2}: source/id is required`);
|
|
1951
2187
|
}
|
|
1952
|
-
output[
|
|
2188
|
+
output[path2] = { source, ...provider ? { provider } : {}, id };
|
|
1953
2189
|
}
|
|
1954
2190
|
return output;
|
|
1955
2191
|
}
|
|
@@ -1982,21 +2218,21 @@ var SecretsCommands = class {
|
|
|
1982
2218
|
this.deps = deps;
|
|
1983
2219
|
}
|
|
1984
2220
|
secretsAudit(opts = {}) {
|
|
1985
|
-
const config2 =
|
|
2221
|
+
const config2 = loadConfig4();
|
|
1986
2222
|
const configPath = getConfigPath();
|
|
1987
2223
|
const refs = config2.secrets.refs;
|
|
1988
2224
|
const items = [];
|
|
1989
|
-
for (const [
|
|
2225
|
+
for (const [path2, ref] of Object.entries(refs)) {
|
|
1990
2226
|
const provider = inferProviderAlias(config2, ref);
|
|
1991
2227
|
const scopedConfig = structuredClone(config2);
|
|
1992
|
-
scopedConfig.secrets.refs = { [
|
|
2228
|
+
scopedConfig.secrets.refs = { [path2]: ref };
|
|
1993
2229
|
try {
|
|
1994
2230
|
const resolved = resolveConfigSecrets(scopedConfig, { configPath });
|
|
1995
|
-
const parsedPath = parseRequiredConfigPath(
|
|
2231
|
+
const parsedPath = parseRequiredConfigPath(path2);
|
|
1996
2232
|
const target = getAtConfigPath(resolved, parsedPath);
|
|
1997
2233
|
if (!target.found) {
|
|
1998
2234
|
items.push({
|
|
1999
|
-
path,
|
|
2235
|
+
path: path2,
|
|
2000
2236
|
source: ref.source,
|
|
2001
2237
|
provider,
|
|
2002
2238
|
id: ref.id,
|
|
@@ -2008,7 +2244,7 @@ var SecretsCommands = class {
|
|
|
2008
2244
|
const resolvedValue = target.value;
|
|
2009
2245
|
const detail = typeof resolvedValue === "string" ? `resolved (length=${resolvedValue.length})` : `resolved (${typeof resolvedValue})`;
|
|
2010
2246
|
items.push({
|
|
2011
|
-
path,
|
|
2247
|
+
path: path2,
|
|
2012
2248
|
source: ref.source,
|
|
2013
2249
|
provider,
|
|
2014
2250
|
id: ref.id,
|
|
@@ -2017,7 +2253,7 @@ var SecretsCommands = class {
|
|
|
2017
2253
|
});
|
|
2018
2254
|
} catch (error) {
|
|
2019
2255
|
items.push({
|
|
2020
|
-
path,
|
|
2256
|
+
path: path2,
|
|
2021
2257
|
source: ref.source,
|
|
2022
2258
|
provider,
|
|
2023
2259
|
id: ref.id,
|
|
@@ -2050,7 +2286,7 @@ var SecretsCommands = class {
|
|
|
2050
2286
|
if (!alias) {
|
|
2051
2287
|
throw new Error("provider alias is required");
|
|
2052
2288
|
}
|
|
2053
|
-
const prevConfig =
|
|
2289
|
+
const prevConfig = loadConfig4();
|
|
2054
2290
|
const nextConfig = structuredClone(prevConfig);
|
|
2055
2291
|
const remove = Boolean(opts.remove);
|
|
2056
2292
|
if (remove) {
|
|
@@ -2071,13 +2307,13 @@ var SecretsCommands = class {
|
|
|
2071
2307
|
...normalizeOptionalString(opts.prefix) ? { prefix: normalizeOptionalString(opts.prefix) } : {}
|
|
2072
2308
|
};
|
|
2073
2309
|
} else if (source === "file") {
|
|
2074
|
-
const
|
|
2075
|
-
if (!
|
|
2310
|
+
const path2 = normalizeOptionalString(opts.path);
|
|
2311
|
+
if (!path2) {
|
|
2076
2312
|
throw new Error("file source requires --path");
|
|
2077
2313
|
}
|
|
2078
2314
|
nextConfig.secrets.providers[alias] = {
|
|
2079
2315
|
source,
|
|
2080
|
-
path,
|
|
2316
|
+
path: path2,
|
|
2081
2317
|
format: "json"
|
|
2082
2318
|
};
|
|
2083
2319
|
} else {
|
|
@@ -2112,7 +2348,7 @@ var SecretsCommands = class {
|
|
|
2112
2348
|
console.log(`Secrets provider ${remove ? "removed" : "configured"}: ${alias}`);
|
|
2113
2349
|
}
|
|
2114
2350
|
async secretsApply(opts) {
|
|
2115
|
-
const prevConfig =
|
|
2351
|
+
const prevConfig = loadConfig4();
|
|
2116
2352
|
const nextConfig = structuredClone(prevConfig);
|
|
2117
2353
|
if (opts.enable && opts.disable) {
|
|
2118
2354
|
throw new Error("cannot set --enable and --disable at the same time");
|
|
@@ -2140,12 +2376,12 @@ var SecretsCommands = class {
|
|
|
2140
2376
|
}
|
|
2141
2377
|
}
|
|
2142
2378
|
if (opts.path) {
|
|
2143
|
-
const
|
|
2144
|
-
if (!
|
|
2379
|
+
const path2 = opts.path.trim();
|
|
2380
|
+
if (!path2) {
|
|
2145
2381
|
throw new Error("path is empty");
|
|
2146
2382
|
}
|
|
2147
2383
|
if (opts.remove) {
|
|
2148
|
-
delete nextConfig.secrets.refs[
|
|
2384
|
+
delete nextConfig.secrets.refs[path2];
|
|
2149
2385
|
} else {
|
|
2150
2386
|
const source = normalizeSecretSource(opts.source);
|
|
2151
2387
|
const id = normalizeOptionalString(opts.id);
|
|
@@ -2153,7 +2389,7 @@ var SecretsCommands = class {
|
|
|
2153
2389
|
throw new Error("apply single ref requires --source and --id");
|
|
2154
2390
|
}
|
|
2155
2391
|
const provider = normalizeOptionalString(opts.provider);
|
|
2156
|
-
nextConfig.secrets.refs[
|
|
2392
|
+
nextConfig.secrets.refs[path2] = {
|
|
2157
2393
|
source,
|
|
2158
2394
|
id,
|
|
2159
2395
|
...provider ? { provider } : {}
|
|
@@ -2177,7 +2413,7 @@ var SecretsCommands = class {
|
|
|
2177
2413
|
console.log("Secrets applied.");
|
|
2178
2414
|
}
|
|
2179
2415
|
async secretsReload(opts = {}) {
|
|
2180
|
-
const config2 =
|
|
2416
|
+
const config2 = loadConfig4();
|
|
2181
2417
|
const configPath = getConfigPath();
|
|
2182
2418
|
resolveConfigSecrets(config2, { configPath });
|
|
2183
2419
|
saveConfig3(config2);
|
|
@@ -2205,9 +2441,9 @@ var SecretsCommands = class {
|
|
|
2205
2441
|
|
|
2206
2442
|
// src/cli/commands/channels.ts
|
|
2207
2443
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
2208
|
-
import { getWorkspacePath as
|
|
2444
|
+
import { getWorkspacePath as getWorkspacePath3, loadConfig as loadConfig5, saveConfig as saveConfig4 } from "@nextclaw/core";
|
|
2209
2445
|
import { BUILTIN_CHANNEL_PLUGIN_IDS, builtinProviderIds as builtinProviderIds2 } from "@nextclaw/runtime";
|
|
2210
|
-
import { buildPluginStatusReport as
|
|
2446
|
+
import { buildPluginStatusReport as buildPluginStatusReport3, enablePluginInConfig as enablePluginInConfig2, getPluginChannelBindings } from "@nextclaw/openclaw-compat";
|
|
2211
2447
|
var CHANNEL_LABELS = {
|
|
2212
2448
|
telegram: "Telegram",
|
|
2213
2449
|
whatsapp: "WhatsApp",
|
|
@@ -2226,7 +2462,7 @@ var ChannelCommands = class {
|
|
|
2226
2462
|
this.deps = deps;
|
|
2227
2463
|
}
|
|
2228
2464
|
channelsStatus() {
|
|
2229
|
-
const config2 =
|
|
2465
|
+
const config2 = loadConfig5();
|
|
2230
2466
|
console.log("Channel Status");
|
|
2231
2467
|
const channelConfig = config2.channels;
|
|
2232
2468
|
for (const channelId of BUILTIN_CHANNEL_PLUGIN_IDS) {
|
|
@@ -2234,8 +2470,8 @@ var ChannelCommands = class {
|
|
|
2234
2470
|
const enabled = channelConfig[channelId]?.enabled === true;
|
|
2235
2471
|
console.log(`${label}: ${enabled ? "\u2713" : "\u2717"}`);
|
|
2236
2472
|
}
|
|
2237
|
-
const workspaceDir =
|
|
2238
|
-
const report =
|
|
2473
|
+
const workspaceDir = getWorkspacePath3(config2.agents.defaults.workspace);
|
|
2474
|
+
const report = buildPluginStatusReport3({
|
|
2239
2475
|
config: config2,
|
|
2240
2476
|
workspaceDir,
|
|
2241
2477
|
reservedChannelIds: [],
|
|
@@ -2265,8 +2501,8 @@ var ChannelCommands = class {
|
|
|
2265
2501
|
console.error("--channel is required");
|
|
2266
2502
|
process.exit(1);
|
|
2267
2503
|
}
|
|
2268
|
-
const config2 =
|
|
2269
|
-
const workspaceDir =
|
|
2504
|
+
const config2 = loadConfig5();
|
|
2505
|
+
const workspaceDir = getWorkspacePath3(config2.agents.defaults.workspace);
|
|
2270
2506
|
const pluginRegistry = loadPluginRegistry(config2, workspaceDir);
|
|
2271
2507
|
const bindings = getPluginChannelBindings(pluginRegistry);
|
|
2272
2508
|
const binding = bindings.find((entry) => entry.channelId === channelId || entry.pluginId === channelId);
|
|
@@ -2396,14 +2632,14 @@ var CronCommands = class {
|
|
|
2396
2632
|
// src/cli/commands/diagnostics.ts
|
|
2397
2633
|
import { createServer as createNetServer } from "net";
|
|
2398
2634
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
2399
|
-
import { resolve as
|
|
2635
|
+
import { resolve as resolve8 } from "path";
|
|
2400
2636
|
import {
|
|
2401
2637
|
APP_NAME,
|
|
2402
2638
|
getConfigPath as getConfigPath2,
|
|
2403
2639
|
getDataDir as getDataDir4,
|
|
2404
|
-
getWorkspacePath as
|
|
2640
|
+
getWorkspacePath as getWorkspacePath4,
|
|
2405
2641
|
hasSecretRef,
|
|
2406
|
-
loadConfig as
|
|
2642
|
+
loadConfig as loadConfig6
|
|
2407
2643
|
} from "@nextclaw/core";
|
|
2408
2644
|
import { listBuiltinProviders } from "@nextclaw/runtime";
|
|
2409
2645
|
var DiagnosticsCommands = class {
|
|
@@ -2565,9 +2801,9 @@ var DiagnosticsCommands = class {
|
|
|
2565
2801
|
}
|
|
2566
2802
|
async collectRuntimeStatus(params) {
|
|
2567
2803
|
const configPath = getConfigPath2();
|
|
2568
|
-
const config2 =
|
|
2569
|
-
const workspacePath =
|
|
2570
|
-
const serviceStatePath =
|
|
2804
|
+
const config2 = loadConfig6();
|
|
2805
|
+
const workspacePath = getWorkspacePath4(config2.agents.defaults.workspace);
|
|
2806
|
+
const serviceStatePath = resolve8(getDataDir4(), "run", "service.json");
|
|
2571
2807
|
const fixActions = [];
|
|
2572
2808
|
let serviceState = readServiceState();
|
|
2573
2809
|
if (params.fix && serviceState && !isProcessRunning(serviceState.pid)) {
|
|
@@ -2699,12 +2935,12 @@ var DiagnosticsCommands = class {
|
|
|
2699
2935
|
clearTimeout(timer);
|
|
2700
2936
|
}
|
|
2701
2937
|
}
|
|
2702
|
-
readLogTail(
|
|
2703
|
-
if (!existsSync6(
|
|
2938
|
+
readLogTail(path2, maxLines = 25) {
|
|
2939
|
+
if (!existsSync6(path2)) {
|
|
2704
2940
|
return [];
|
|
2705
2941
|
}
|
|
2706
2942
|
try {
|
|
2707
|
-
const lines = readFileSync6(
|
|
2943
|
+
const lines = readFileSync6(path2, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
2708
2944
|
if (lines.length <= maxLines) {
|
|
2709
2945
|
return lines;
|
|
2710
2946
|
}
|
|
@@ -2714,17 +2950,17 @@ var DiagnosticsCommands = class {
|
|
|
2714
2950
|
}
|
|
2715
2951
|
}
|
|
2716
2952
|
async checkPortAvailability(params) {
|
|
2717
|
-
return await new Promise((
|
|
2953
|
+
return await new Promise((resolve13) => {
|
|
2718
2954
|
const server = createNetServer();
|
|
2719
2955
|
server.once("error", (error) => {
|
|
2720
|
-
|
|
2956
|
+
resolve13({
|
|
2721
2957
|
available: false,
|
|
2722
2958
|
detail: `bind failed on ${params.host}:${params.port} (${String(error)})`
|
|
2723
2959
|
});
|
|
2724
2960
|
});
|
|
2725
2961
|
server.listen(params.port, params.host, () => {
|
|
2726
2962
|
server.close(() => {
|
|
2727
|
-
|
|
2963
|
+
resolve13({
|
|
2728
2964
|
available: true,
|
|
2729
2965
|
detail: `bind ok on ${params.host}:${params.port}`
|
|
2730
2966
|
});
|
|
@@ -2737,20 +2973,19 @@ var DiagnosticsCommands = class {
|
|
|
2737
2973
|
// src/cli/commands/service.ts
|
|
2738
2974
|
import * as NextclawCore from "@nextclaw/core";
|
|
2739
2975
|
import {
|
|
2740
|
-
getPluginChannelBindings as
|
|
2976
|
+
getPluginChannelBindings as getPluginChannelBindings3,
|
|
2741
2977
|
resolvePluginChannelMessageToolHints,
|
|
2742
2978
|
setPluginRuntimeBridge,
|
|
2743
|
-
startPluginChannelGateways,
|
|
2744
|
-
stopPluginChannelGateways
|
|
2979
|
+
startPluginChannelGateways as startPluginChannelGateways2,
|
|
2980
|
+
stopPluginChannelGateways as stopPluginChannelGateways2
|
|
2745
2981
|
} from "@nextclaw/openclaw-compat";
|
|
2746
2982
|
import { startUiServer } from "@nextclaw/server";
|
|
2747
2983
|
import { appendFileSync, closeSync, cpSync as cpSync2, existsSync as existsSync9, mkdirSync as mkdirSync5, openSync, rmSync as rmSync4 } from "fs";
|
|
2748
|
-
import { dirname as dirname2, join as join5, resolve as
|
|
2984
|
+
import { dirname as dirname2, join as join5, resolve as resolve10 } from "path";
|
|
2749
2985
|
import { spawn as spawn2 } from "child_process";
|
|
2750
2986
|
import { request as httpRequest } from "http";
|
|
2751
2987
|
import { request as httpsRequest } from "https";
|
|
2752
2988
|
import { createServer as createNetServer2 } from "net";
|
|
2753
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2754
2989
|
import chokidar from "chokidar";
|
|
2755
2990
|
|
|
2756
2991
|
// src/cli/gateway/controller.ts
|
|
@@ -2764,11 +2999,11 @@ import {
|
|
|
2764
2999
|
} from "@nextclaw/core";
|
|
2765
3000
|
var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
2766
3001
|
var readConfigSnapshot = (getConfigPath5) => {
|
|
2767
|
-
const
|
|
3002
|
+
const path2 = getConfigPath5();
|
|
2768
3003
|
let raw = "";
|
|
2769
3004
|
let parsed = {};
|
|
2770
|
-
if (existsSync7(
|
|
2771
|
-
raw = readFileSync7(
|
|
3005
|
+
if (existsSync7(path2)) {
|
|
3006
|
+
raw = readFileSync7(path2, "utf-8");
|
|
2772
3007
|
try {
|
|
2773
3008
|
parsed = JSON.parse(raw);
|
|
2774
3009
|
} catch {
|
|
@@ -3079,11 +3314,15 @@ var ConfigReloader = class {
|
|
|
3079
3314
|
this.currentConfig = nextConfig;
|
|
3080
3315
|
this.options.providerManager?.setConfig(nextConfig);
|
|
3081
3316
|
const plan = buildReloadPlan3(changedPaths);
|
|
3317
|
+
let reloadPluginsResult = void 0;
|
|
3082
3318
|
if (plan.reloadPlugins) {
|
|
3083
|
-
await this.reloadPlugins(
|
|
3319
|
+
reloadPluginsResult = await this.reloadPlugins({
|
|
3320
|
+
config: nextConfig,
|
|
3321
|
+
changedPaths
|
|
3322
|
+
});
|
|
3084
3323
|
console.log("Config reload: plugins reloaded.");
|
|
3085
3324
|
}
|
|
3086
|
-
if (plan.restartChannels) {
|
|
3325
|
+
if (plan.restartChannels || reloadPluginsResult?.restartChannels) {
|
|
3087
3326
|
await this.reloadChannels(nextConfig);
|
|
3088
3327
|
console.log("Config reload: channels restarted.");
|
|
3089
3328
|
}
|
|
@@ -3178,11 +3417,11 @@ var ConfigReloader = class {
|
|
|
3178
3417
|
this.providerReloadTask = null;
|
|
3179
3418
|
}
|
|
3180
3419
|
}
|
|
3181
|
-
async reloadPlugins(
|
|
3420
|
+
async reloadPlugins(params) {
|
|
3182
3421
|
if (!this.options.reloadPlugins) {
|
|
3183
3422
|
return;
|
|
3184
3423
|
}
|
|
3185
|
-
await this.options.reloadPlugins(
|
|
3424
|
+
return await this.options.reloadPlugins(params);
|
|
3186
3425
|
}
|
|
3187
3426
|
};
|
|
3188
3427
|
|
|
@@ -3204,6 +3443,104 @@ var MissingProvider = class extends LLMProvider {
|
|
|
3204
3443
|
}
|
|
3205
3444
|
};
|
|
3206
3445
|
|
|
3446
|
+
// src/cli/commands/service-plugin-reload.ts
|
|
3447
|
+
import { getWorkspacePath as getWorkspacePath5 } from "@nextclaw/core";
|
|
3448
|
+
import {
|
|
3449
|
+
getPluginChannelBindings as getPluginChannelBindings2,
|
|
3450
|
+
startPluginChannelGateways,
|
|
3451
|
+
stopPluginChannelGateways
|
|
3452
|
+
} from "@nextclaw/openclaw-compat";
|
|
3453
|
+
|
|
3454
|
+
// src/cli/commands/plugin-reload.ts
|
|
3455
|
+
function buildPluginChannelBindingSignature(binding) {
|
|
3456
|
+
return `${binding.pluginId}:${binding.channelId}`;
|
|
3457
|
+
}
|
|
3458
|
+
function buildSortedBindingSignatures(bindings) {
|
|
3459
|
+
return bindings.map(buildPluginChannelBindingSignature).sort();
|
|
3460
|
+
}
|
|
3461
|
+
function buildSortedExtensionChannelIds(channels2) {
|
|
3462
|
+
return channels2.map((registration) => registration.channel.id).filter((id) => typeof id === "string" && id.trim().length > 0).sort();
|
|
3463
|
+
}
|
|
3464
|
+
function areSortedStringListsEqual(left, right) {
|
|
3465
|
+
if (left.length !== right.length) {
|
|
3466
|
+
return false;
|
|
3467
|
+
}
|
|
3468
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
3469
|
+
if (left[index] !== right[index]) {
|
|
3470
|
+
return false;
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
return true;
|
|
3474
|
+
}
|
|
3475
|
+
function readPluginIdFromPluginsEntryPath(path2) {
|
|
3476
|
+
const prefix = "plugins.entries.";
|
|
3477
|
+
if (!path2.startsWith(prefix)) {
|
|
3478
|
+
return null;
|
|
3479
|
+
}
|
|
3480
|
+
const suffix = path2.slice(prefix.length);
|
|
3481
|
+
const [pluginId] = suffix.split(".");
|
|
3482
|
+
return pluginId?.trim() ? pluginId.trim() : null;
|
|
3483
|
+
}
|
|
3484
|
+
function shouldRestartChannelsForPluginReload(params) {
|
|
3485
|
+
const currentBindingSignatures = buildSortedBindingSignatures(params.currentPluginChannelBindings);
|
|
3486
|
+
const nextBindingSignatures = buildSortedBindingSignatures(params.nextPluginChannelBindings);
|
|
3487
|
+
if (!areSortedStringListsEqual(currentBindingSignatures, nextBindingSignatures)) {
|
|
3488
|
+
return true;
|
|
3489
|
+
}
|
|
3490
|
+
const currentExtensionChannelIds = buildSortedExtensionChannelIds(params.currentExtensionChannels);
|
|
3491
|
+
const nextExtensionChannelIds = buildSortedExtensionChannelIds(params.nextExtensionChannels);
|
|
3492
|
+
if (!areSortedStringListsEqual(currentExtensionChannelIds, nextExtensionChannelIds)) {
|
|
3493
|
+
return true;
|
|
3494
|
+
}
|
|
3495
|
+
const channelPluginIds = /* @__PURE__ */ new Set();
|
|
3496
|
+
for (const binding of params.currentPluginChannelBindings) {
|
|
3497
|
+
channelPluginIds.add(binding.pluginId);
|
|
3498
|
+
}
|
|
3499
|
+
for (const binding of params.nextPluginChannelBindings) {
|
|
3500
|
+
channelPluginIds.add(binding.pluginId);
|
|
3501
|
+
}
|
|
3502
|
+
for (const path2 of params.changedPaths) {
|
|
3503
|
+
const pluginId = readPluginIdFromPluginsEntryPath(path2);
|
|
3504
|
+
if (pluginId && channelPluginIds.has(pluginId)) {
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
return false;
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3511
|
+
// src/cli/commands/service-plugin-reload.ts
|
|
3512
|
+
async function reloadServicePlugins(params) {
|
|
3513
|
+
const nextWorkspace = getWorkspacePath5(params.nextConfig.agents.defaults.workspace);
|
|
3514
|
+
const nextPluginRegistry = loadPluginRegistry(params.nextConfig, nextWorkspace);
|
|
3515
|
+
const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
|
|
3516
|
+
const nextPluginChannelBindings = getPluginChannelBindings2(nextPluginRegistry);
|
|
3517
|
+
const shouldRestartChannels = shouldRestartChannelsForPluginReload({
|
|
3518
|
+
changedPaths: params.changedPaths,
|
|
3519
|
+
currentPluginChannelBindings: params.pluginChannelBindings,
|
|
3520
|
+
nextPluginChannelBindings,
|
|
3521
|
+
currentExtensionChannels: params.extensionRegistry.channels,
|
|
3522
|
+
nextExtensionChannels: nextExtensionRegistry.channels
|
|
3523
|
+
});
|
|
3524
|
+
logPluginDiagnostics(nextPluginRegistry);
|
|
3525
|
+
let pluginGatewayHandles = params.pluginGatewayHandles;
|
|
3526
|
+
if (shouldRestartChannels) {
|
|
3527
|
+
await stopPluginChannelGateways(pluginGatewayHandles);
|
|
3528
|
+
const startedPluginGateways = await startPluginChannelGateways({
|
|
3529
|
+
registry: nextPluginRegistry,
|
|
3530
|
+
logger: params.pluginGatewayLogger
|
|
3531
|
+
});
|
|
3532
|
+
pluginGatewayHandles = startedPluginGateways.handles;
|
|
3533
|
+
params.logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
|
|
3534
|
+
}
|
|
3535
|
+
return {
|
|
3536
|
+
pluginRegistry: nextPluginRegistry,
|
|
3537
|
+
extensionRegistry: nextExtensionRegistry,
|
|
3538
|
+
pluginChannelBindings: nextPluginChannelBindings,
|
|
3539
|
+
pluginGatewayHandles,
|
|
3540
|
+
restartChannels: shouldRestartChannels
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
|
|
3207
3544
|
// src/cli/commands/agent-runtime-pool.ts
|
|
3208
3545
|
import {
|
|
3209
3546
|
NativeAgentEngine,
|
|
@@ -3211,7 +3548,7 @@ import {
|
|
|
3211
3548
|
createAssistantStreamDeltaControlMessage,
|
|
3212
3549
|
createAssistantStreamResetControlMessage,
|
|
3213
3550
|
AgentRouteResolver,
|
|
3214
|
-
getWorkspacePath as
|
|
3551
|
+
getWorkspacePath as getWorkspacePath6,
|
|
3215
3552
|
parseAgentScopedSessionKey
|
|
3216
3553
|
} from "@nextclaw/core";
|
|
3217
3554
|
function normalizeAgentId(value) {
|
|
@@ -3256,7 +3593,7 @@ function resolveAgentProfiles(config2) {
|
|
|
3256
3593
|
}
|
|
3257
3594
|
return Array.from(unique.values()).map((entry) => ({
|
|
3258
3595
|
id: entry.id,
|
|
3259
|
-
workspace:
|
|
3596
|
+
workspace: getWorkspacePath6(entry.workspace ?? defaults.workspace),
|
|
3260
3597
|
model: entry.model ?? defaults.model,
|
|
3261
3598
|
engine: normalizeEngineKind(entry.engine ?? defaults.engine),
|
|
3262
3599
|
engineConfig: entry.engineConfig ?? toRecord(defaults.engineConfig),
|
|
@@ -3521,7 +3858,7 @@ var GatewayAgentRuntimePool = class {
|
|
|
3521
3858
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
3522
3859
|
return this.resolvedProfiles.find((profile) => profile.id === normalizedAgentId) ?? this.resolvedProfiles.find((profile) => profile.id === this.defaultAgentId) ?? this.resolvedProfiles[0] ?? {
|
|
3523
3860
|
id: this.defaultAgentId,
|
|
3524
|
-
workspace:
|
|
3861
|
+
workspace: getWorkspacePath6(this.options.config.agents.defaults.workspace),
|
|
3525
3862
|
model: this.options.config.agents.defaults.model,
|
|
3526
3863
|
maxIterations: this.options.config.agents.defaults.maxToolIterations,
|
|
3527
3864
|
contextTokens: this.options.config.agents.defaults.contextTokens,
|
|
@@ -3698,15 +4035,36 @@ function formatUserFacingError(error, maxChars = 320) {
|
|
|
3698
4035
|
return `${normalized.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
3699
4036
|
}
|
|
3700
4037
|
|
|
4038
|
+
// src/cli/commands/cli-subcommand-launch.ts
|
|
4039
|
+
import { createRequire } from "module";
|
|
4040
|
+
import { extname, resolve as resolve9 } from "path";
|
|
4041
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4042
|
+
var require2 = createRequire(import.meta.url);
|
|
4043
|
+
var resolveCliSubcommandEntry = (params) => {
|
|
4044
|
+
const argvEntry = params.argvEntry?.trim();
|
|
4045
|
+
if (argvEntry) {
|
|
4046
|
+
return resolve9(argvEntry);
|
|
4047
|
+
}
|
|
4048
|
+
return fileURLToPath2(new URL("../index.js", params.importMetaUrl));
|
|
4049
|
+
};
|
|
4050
|
+
|
|
3701
4051
|
// src/cli/commands/ncp/create-ui-ncp-agent.ts
|
|
4052
|
+
import {
|
|
4053
|
+
DisposableStore
|
|
4054
|
+
} from "@nextclaw/core";
|
|
3702
4055
|
import { DefaultNcpAgentRuntime } from "@nextclaw/ncp-agent-runtime";
|
|
4056
|
+
import {
|
|
4057
|
+
readAssistantReasoningNormalizationMode,
|
|
4058
|
+
readAssistantReasoningNormalizationModeFromMetadata,
|
|
4059
|
+
writeAssistantReasoningNormalizationModeToMetadata
|
|
4060
|
+
} from "@nextclaw/ncp";
|
|
3703
4061
|
import { createAgentClientFromServer, DefaultNcpAgentBackend } from "@nextclaw/ncp-toolkit";
|
|
3704
4062
|
|
|
3705
4063
|
// src/cli/commands/ncp/nextclaw-ncp-context-builder.ts
|
|
3706
4064
|
import {
|
|
3707
4065
|
ContextBuilder,
|
|
3708
4066
|
InputBudgetPruner,
|
|
3709
|
-
getWorkspacePath as
|
|
4067
|
+
getWorkspacePath as getWorkspacePath7,
|
|
3710
4068
|
parseThinkingLevel,
|
|
3711
4069
|
resolveThinkingLevel
|
|
3712
4070
|
} from "@nextclaw/core";
|
|
@@ -4191,7 +4549,7 @@ function resolvePrimaryAgentProfile(config2) {
|
|
|
4191
4549
|
const profile = config2.agents.list.find((entry) => entry.id.trim() === configuredDefaultAgentId);
|
|
4192
4550
|
return {
|
|
4193
4551
|
agentId: configuredDefaultAgentId,
|
|
4194
|
-
workspace:
|
|
4552
|
+
workspace: getWorkspacePath7(profile?.workspace ?? config2.agents.defaults.workspace),
|
|
4195
4553
|
model: profile?.model ?? config2.agents.defaults.model,
|
|
4196
4554
|
maxIterations: profile?.maxToolIterations ?? config2.agents.defaults.maxToolIterations,
|
|
4197
4555
|
contextTokens: profile?.contextTokens ?? config2.agents.defaults.contextTokens,
|
|
@@ -4770,13 +5128,116 @@ var ProviderManagerNcpLLMApi = class {
|
|
|
4770
5128
|
}
|
|
4771
5129
|
};
|
|
4772
5130
|
|
|
5131
|
+
// src/cli/commands/ncp/ui-ncp-runtime-registry.ts
|
|
5132
|
+
import { toDisposable } from "@nextclaw/core";
|
|
5133
|
+
var DEFAULT_UI_NCP_RUNTIME_KIND = "native";
|
|
5134
|
+
function normalizeRuntimeKind(value) {
|
|
5135
|
+
if (typeof value !== "string") {
|
|
5136
|
+
return null;
|
|
5137
|
+
}
|
|
5138
|
+
const normalized = value.trim().toLowerCase();
|
|
5139
|
+
return normalized.length > 0 ? normalized : null;
|
|
5140
|
+
}
|
|
5141
|
+
function readRequestedRuntimeKind(sessionMetadata) {
|
|
5142
|
+
return normalizeRuntimeKind(sessionMetadata.session_type) ?? normalizeRuntimeKind(sessionMetadata.sessionType) ?? null;
|
|
5143
|
+
}
|
|
5144
|
+
var UiNcpRuntimeRegistry = class {
|
|
5145
|
+
constructor(defaultKind = DEFAULT_UI_NCP_RUNTIME_KIND) {
|
|
5146
|
+
this.defaultKind = defaultKind;
|
|
5147
|
+
}
|
|
5148
|
+
registrations = /* @__PURE__ */ new Map();
|
|
5149
|
+
register(registration) {
|
|
5150
|
+
const normalizedKind = normalizeRuntimeKind(registration.kind);
|
|
5151
|
+
if (!normalizedKind) {
|
|
5152
|
+
throw new Error("ui ncp runtime kind must be a non-empty string");
|
|
5153
|
+
}
|
|
5154
|
+
const token = Symbol(normalizedKind);
|
|
5155
|
+
this.registrations.set(normalizedKind, {
|
|
5156
|
+
...registration,
|
|
5157
|
+
kind: normalizedKind,
|
|
5158
|
+
token
|
|
5159
|
+
});
|
|
5160
|
+
return toDisposable(() => {
|
|
5161
|
+
const current = this.registrations.get(normalizedKind);
|
|
5162
|
+
if (!current || current.token !== token) {
|
|
5163
|
+
return;
|
|
5164
|
+
}
|
|
5165
|
+
this.registrations.delete(normalizedKind);
|
|
5166
|
+
});
|
|
5167
|
+
}
|
|
5168
|
+
createRuntime(params) {
|
|
5169
|
+
const requestedKind = readRequestedRuntimeKind(params.sessionMetadata) ?? this.defaultKind;
|
|
5170
|
+
const registration = this.registrations.get(requestedKind);
|
|
5171
|
+
if (!registration) {
|
|
5172
|
+
throw new Error(`ncp runtime unavailable: ${requestedKind}`);
|
|
5173
|
+
}
|
|
5174
|
+
const nextSessionMetadata = {
|
|
5175
|
+
...params.sessionMetadata,
|
|
5176
|
+
session_type: registration.kind
|
|
5177
|
+
};
|
|
5178
|
+
params.setSessionMetadata(nextSessionMetadata);
|
|
5179
|
+
return registration.createRuntime({
|
|
5180
|
+
...params,
|
|
5181
|
+
sessionMetadata: nextSessionMetadata
|
|
5182
|
+
});
|
|
5183
|
+
}
|
|
5184
|
+
listSessionTypes() {
|
|
5185
|
+
const options = [...this.registrations.values()].map((registration) => ({
|
|
5186
|
+
value: registration.kind,
|
|
5187
|
+
label: registration.label
|
|
5188
|
+
})).sort((left, right) => {
|
|
5189
|
+
if (left.value === this.defaultKind) {
|
|
5190
|
+
return -1;
|
|
5191
|
+
}
|
|
5192
|
+
if (right.value === this.defaultKind) {
|
|
5193
|
+
return 1;
|
|
5194
|
+
}
|
|
5195
|
+
return left.value.localeCompare(right.value);
|
|
5196
|
+
});
|
|
5197
|
+
return {
|
|
5198
|
+
defaultType: this.defaultKind,
|
|
5199
|
+
options
|
|
5200
|
+
};
|
|
5201
|
+
}
|
|
5202
|
+
};
|
|
5203
|
+
|
|
4773
5204
|
// src/cli/commands/ncp/create-ui-ncp-agent.ts
|
|
5205
|
+
function isRecord5(value) {
|
|
5206
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5207
|
+
}
|
|
5208
|
+
function resolveNativeReasoningNormalizationMode(params) {
|
|
5209
|
+
const runtimeEntry = params.config.ui.ncp.runtimes.native;
|
|
5210
|
+
const runtimeMetadata = isRecord5(runtimeEntry) ? runtimeEntry : {};
|
|
5211
|
+
return readAssistantReasoningNormalizationModeFromMetadata(params.sessionMetadata) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoningNormalization) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoning_normalization) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoningNormalizationMode) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoning_normalization_mode) ?? "think-tags";
|
|
5212
|
+
}
|
|
5213
|
+
function buildPluginRuntimeSnapshotKey(extensionRegistry) {
|
|
5214
|
+
const registrations = extensionRegistry?.ncpAgentRuntimes ?? [];
|
|
5215
|
+
return registrations.map((registration) => [
|
|
5216
|
+
registration.pluginId,
|
|
5217
|
+
registration.kind,
|
|
5218
|
+
registration.label,
|
|
5219
|
+
registration.source
|
|
5220
|
+
].join(":")).join("|");
|
|
5221
|
+
}
|
|
4774
5222
|
async function createUiNcpAgent(params) {
|
|
4775
5223
|
const sessionStore = new NextclawAgentSessionStore(params.sessionManager);
|
|
4776
|
-
const
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
5224
|
+
const runtimeRegistry = new UiNcpRuntimeRegistry();
|
|
5225
|
+
runtimeRegistry.register({
|
|
5226
|
+
kind: "native",
|
|
5227
|
+
label: "Native",
|
|
5228
|
+
createRuntime: ({ stateManager, sessionMetadata, setSessionMetadata }) => {
|
|
5229
|
+
const reasoningNormalizationMode = resolveNativeReasoningNormalizationMode({
|
|
5230
|
+
config: params.getConfig(),
|
|
5231
|
+
sessionMetadata
|
|
5232
|
+
});
|
|
5233
|
+
if (reasoningNormalizationMode !== "off" && readAssistantReasoningNormalizationModeFromMetadata(sessionMetadata) !== reasoningNormalizationMode) {
|
|
5234
|
+
setSessionMetadata(
|
|
5235
|
+
writeAssistantReasoningNormalizationModeToMetadata(
|
|
5236
|
+
sessionMetadata,
|
|
5237
|
+
reasoningNormalizationMode
|
|
5238
|
+
)
|
|
5239
|
+
);
|
|
5240
|
+
}
|
|
4780
5241
|
const toolRegistry = new NextclawNcpToolRegistry({
|
|
4781
5242
|
bus: params.bus,
|
|
4782
5243
|
providerManager: params.providerManager,
|
|
@@ -4795,19 +5256,113 @@ async function createUiNcpAgent(params) {
|
|
|
4795
5256
|
}),
|
|
4796
5257
|
llmApi: new ProviderManagerNcpLLMApi(params.providerManager),
|
|
4797
5258
|
toolRegistry,
|
|
4798
|
-
stateManager
|
|
5259
|
+
stateManager,
|
|
5260
|
+
reasoningNormalizationMode
|
|
4799
5261
|
});
|
|
4800
5262
|
}
|
|
4801
5263
|
});
|
|
5264
|
+
const pluginRuntimeScopes = /* @__PURE__ */ new Map();
|
|
5265
|
+
let pluginRuntimeSnapshotKey = "";
|
|
5266
|
+
let activeExtensionRegistry;
|
|
5267
|
+
const syncPluginRuntimeRegistrations = (extensionRegistry) => {
|
|
5268
|
+
const nextSnapshotKey = buildPluginRuntimeSnapshotKey(extensionRegistry);
|
|
5269
|
+
if (nextSnapshotKey === pluginRuntimeSnapshotKey) {
|
|
5270
|
+
return;
|
|
5271
|
+
}
|
|
5272
|
+
pluginRuntimeSnapshotKey = nextSnapshotKey;
|
|
5273
|
+
for (const scope of pluginRuntimeScopes.values()) {
|
|
5274
|
+
scope.dispose();
|
|
5275
|
+
}
|
|
5276
|
+
pluginRuntimeScopes.clear();
|
|
5277
|
+
for (const registration of extensionRegistry?.ncpAgentRuntimes ?? []) {
|
|
5278
|
+
const pluginId = registration.pluginId.trim() || registration.kind;
|
|
5279
|
+
let scope = pluginRuntimeScopes.get(pluginId);
|
|
5280
|
+
if (!scope) {
|
|
5281
|
+
scope = new DisposableStore();
|
|
5282
|
+
pluginRuntimeScopes.set(pluginId, scope);
|
|
5283
|
+
}
|
|
5284
|
+
scope.add(runtimeRegistry.register({
|
|
5285
|
+
kind: registration.kind,
|
|
5286
|
+
label: registration.label,
|
|
5287
|
+
createRuntime: registration.createRuntime
|
|
5288
|
+
}));
|
|
5289
|
+
}
|
|
5290
|
+
};
|
|
5291
|
+
const resolveActiveExtensionRegistry = () => activeExtensionRegistry ?? params.getExtensionRegistry?.();
|
|
5292
|
+
const refreshPluginRuntimeRegistrations = () => {
|
|
5293
|
+
syncPluginRuntimeRegistrations(resolveActiveExtensionRegistry());
|
|
5294
|
+
};
|
|
5295
|
+
refreshPluginRuntimeRegistrations();
|
|
5296
|
+
const backend = new DefaultNcpAgentBackend({
|
|
5297
|
+
endpointId: "nextclaw-ui-agent",
|
|
5298
|
+
sessionStore,
|
|
5299
|
+
createRuntime: (runtimeParams) => {
|
|
5300
|
+
refreshPluginRuntimeRegistrations();
|
|
5301
|
+
return runtimeRegistry.createRuntime(runtimeParams);
|
|
5302
|
+
}
|
|
5303
|
+
});
|
|
4802
5304
|
await backend.start();
|
|
4803
5305
|
return {
|
|
4804
5306
|
basePath: "/api/ncp/agent",
|
|
4805
5307
|
agentClientEndpoint: createAgentClientFromServer(backend),
|
|
4806
5308
|
streamProvider: backend,
|
|
4807
|
-
sessionApi: backend
|
|
5309
|
+
sessionApi: backend,
|
|
5310
|
+
listSessionTypes: () => {
|
|
5311
|
+
refreshPluginRuntimeRegistrations();
|
|
5312
|
+
return runtimeRegistry.listSessionTypes();
|
|
5313
|
+
},
|
|
5314
|
+
applyExtensionRegistry: (extensionRegistry) => {
|
|
5315
|
+
activeExtensionRegistry = extensionRegistry;
|
|
5316
|
+
syncPluginRuntimeRegistrations(extensionRegistry);
|
|
5317
|
+
}
|
|
4808
5318
|
};
|
|
4809
5319
|
}
|
|
4810
5320
|
|
|
5321
|
+
// src/cli/commands/service-marketplace-helpers.ts
|
|
5322
|
+
var containsAbsoluteFsPath = (line) => {
|
|
5323
|
+
const normalized = line.trim();
|
|
5324
|
+
if (!normalized) {
|
|
5325
|
+
return false;
|
|
5326
|
+
}
|
|
5327
|
+
const lowered = normalized.toLowerCase();
|
|
5328
|
+
if (lowered.includes("http://") || lowered.includes("https://")) {
|
|
5329
|
+
return false;
|
|
5330
|
+
}
|
|
5331
|
+
if (/^[A-Za-z]:\\/.test(normalized)) {
|
|
5332
|
+
return true;
|
|
5333
|
+
}
|
|
5334
|
+
return /(?:^|\s)(?:~\/|\/[^\s]+)/.test(normalized);
|
|
5335
|
+
};
|
|
5336
|
+
var pickUserFacingCommandSummary = (output, fallback) => {
|
|
5337
|
+
const lines = output.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
5338
|
+
if (lines.length === 0) {
|
|
5339
|
+
return fallback;
|
|
5340
|
+
}
|
|
5341
|
+
const visibleLines = lines.filter((line) => {
|
|
5342
|
+
if (/^(path|install path|source path|destination|location)\s*:/i.test(line)) {
|
|
5343
|
+
return false;
|
|
5344
|
+
}
|
|
5345
|
+
if (containsAbsoluteFsPath(line)) {
|
|
5346
|
+
return false;
|
|
5347
|
+
}
|
|
5348
|
+
return true;
|
|
5349
|
+
});
|
|
5350
|
+
if (visibleLines.length === 0) {
|
|
5351
|
+
return fallback;
|
|
5352
|
+
}
|
|
5353
|
+
const preferred = [...visibleLines].reverse().find(
|
|
5354
|
+
(line) => /\b(installed|enabled|disabled|uninstalled|published|updated|already installed|removed)\b/i.test(line)
|
|
5355
|
+
);
|
|
5356
|
+
return preferred ?? visibleLines[visibleLines.length - 1] ?? fallback;
|
|
5357
|
+
};
|
|
5358
|
+
var buildMarketplaceSkillInstallArgs = (params) => {
|
|
5359
|
+
const args = ["skills", "install", params.slug, "--workdir", params.workspace];
|
|
5360
|
+
if (params.force) {
|
|
5361
|
+
args.push("--force");
|
|
5362
|
+
}
|
|
5363
|
+
return args;
|
|
5364
|
+
};
|
|
5365
|
+
|
|
4811
5366
|
// src/cli/commands/ui-chat-run-coordinator.ts
|
|
4812
5367
|
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
4813
5368
|
import { join as join4 } from "path";
|
|
@@ -4825,7 +5380,7 @@ function createRunId() {
|
|
|
4825
5380
|
const rand = Math.random().toString(36).slice(2, 10);
|
|
4826
5381
|
return `run-${now}-${rand}`;
|
|
4827
5382
|
}
|
|
4828
|
-
function
|
|
5383
|
+
function isRecord6(value) {
|
|
4829
5384
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4830
5385
|
}
|
|
4831
5386
|
function readOptionalString(value) {
|
|
@@ -5015,7 +5570,7 @@ var UiChatRunCoordinator = class {
|
|
|
5015
5570
|
const parsedAgentId = parseAgentScopedSessionKey2(sessionKey)?.agentId;
|
|
5016
5571
|
const agentId = explicitAgentId ?? readOptionalString(parsedAgentId);
|
|
5017
5572
|
const model = readOptionalString(input.model);
|
|
5018
|
-
const metadata =
|
|
5573
|
+
const metadata = isRecord6(input.metadata) ? { ...input.metadata } : {};
|
|
5019
5574
|
if (model) {
|
|
5020
5575
|
metadata.model = model;
|
|
5021
5576
|
}
|
|
@@ -5236,14 +5791,14 @@ var UiChatRunCoordinator = class {
|
|
|
5236
5791
|
this.emitRunUpdated(run);
|
|
5237
5792
|
}
|
|
5238
5793
|
waitForRunUpdate(run, signal) {
|
|
5239
|
-
return new Promise((
|
|
5794
|
+
return new Promise((resolve13) => {
|
|
5240
5795
|
const wake = () => {
|
|
5241
5796
|
cleanup();
|
|
5242
|
-
|
|
5797
|
+
resolve13();
|
|
5243
5798
|
};
|
|
5244
5799
|
const onAbort = () => {
|
|
5245
5800
|
cleanup();
|
|
5246
|
-
|
|
5801
|
+
resolve13();
|
|
5247
5802
|
};
|
|
5248
5803
|
const cleanup = () => {
|
|
5249
5804
|
run.waiters.delete(wake);
|
|
@@ -5371,9 +5926,9 @@ var UiChatRunCoordinator = class {
|
|
|
5371
5926
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
5372
5927
|
continue;
|
|
5373
5928
|
}
|
|
5374
|
-
const
|
|
5929
|
+
const path2 = join4(RUNS_DIR, entry.name);
|
|
5375
5930
|
try {
|
|
5376
|
-
const parsed = JSON.parse(readFileSync8(
|
|
5931
|
+
const parsed = JSON.parse(readFileSync8(path2, "utf-8"));
|
|
5377
5932
|
const runId = readOptionalString(parsed.runId);
|
|
5378
5933
|
const sessionKey = readOptionalString(parsed.sessionKey);
|
|
5379
5934
|
if (!runId || !sessionKey) {
|
|
@@ -5436,10 +5991,10 @@ var {
|
|
|
5436
5991
|
getDataDir: getDataDir6,
|
|
5437
5992
|
getProvider,
|
|
5438
5993
|
getProviderName,
|
|
5439
|
-
getWorkspacePath:
|
|
5994
|
+
getWorkspacePath: getWorkspacePath8,
|
|
5440
5995
|
HeartbeatService,
|
|
5441
5996
|
LiteLLMProvider,
|
|
5442
|
-
loadConfig:
|
|
5997
|
+
loadConfig: loadConfig7,
|
|
5443
5998
|
MessageBus,
|
|
5444
5999
|
ProviderManager,
|
|
5445
6000
|
resolveConfigSecrets: resolveConfigSecrets2,
|
|
@@ -5454,64 +6009,18 @@ function createSkillsLoader(workspace) {
|
|
|
5454
6009
|
}
|
|
5455
6010
|
return new ctor(workspace);
|
|
5456
6011
|
}
|
|
5457
|
-
function containsAbsoluteFsPath(line) {
|
|
5458
|
-
const normalized = line.trim();
|
|
5459
|
-
if (!normalized) {
|
|
5460
|
-
return false;
|
|
5461
|
-
}
|
|
5462
|
-
const lowered = normalized.toLowerCase();
|
|
5463
|
-
if (lowered.includes("http://") || lowered.includes("https://")) {
|
|
5464
|
-
return false;
|
|
5465
|
-
}
|
|
5466
|
-
if (/^[A-Za-z]:\\/.test(normalized)) {
|
|
5467
|
-
return true;
|
|
5468
|
-
}
|
|
5469
|
-
return /(?:^|\s)(?:~\/|\/[^\s]+)/.test(normalized);
|
|
5470
|
-
}
|
|
5471
|
-
function pickUserFacingCommandSummary(output, fallback) {
|
|
5472
|
-
const lines = output.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
5473
|
-
if (lines.length === 0) {
|
|
5474
|
-
return fallback;
|
|
5475
|
-
}
|
|
5476
|
-
const visibleLines = lines.filter((line) => {
|
|
5477
|
-
if (/^(path|install path|source path|destination|location)\s*:/i.test(line)) {
|
|
5478
|
-
return false;
|
|
5479
|
-
}
|
|
5480
|
-
if (containsAbsoluteFsPath(line)) {
|
|
5481
|
-
return false;
|
|
5482
|
-
}
|
|
5483
|
-
return true;
|
|
5484
|
-
});
|
|
5485
|
-
if (visibleLines.length === 0) {
|
|
5486
|
-
return fallback;
|
|
5487
|
-
}
|
|
5488
|
-
const preferred = [...visibleLines].reverse().find(
|
|
5489
|
-
(line) => /\b(installed|enabled|disabled|uninstalled|published|updated|already installed|removed)\b/i.test(line)
|
|
5490
|
-
);
|
|
5491
|
-
return preferred ?? visibleLines[visibleLines.length - 1] ?? fallback;
|
|
5492
|
-
}
|
|
5493
|
-
function buildMarketplaceSkillInstallArgs(params) {
|
|
5494
|
-
const args = ["skills", "install", params.slug, "--workdir", params.workspace];
|
|
5495
|
-
if (params.force) {
|
|
5496
|
-
args.push("--force");
|
|
5497
|
-
}
|
|
5498
|
-
return args;
|
|
5499
|
-
}
|
|
5500
|
-
function resolveCliSubcommandEntry(params) {
|
|
5501
|
-
const argvEntry = params.argvEntry?.trim();
|
|
5502
|
-
if (argvEntry) {
|
|
5503
|
-
return resolve8(argvEntry);
|
|
5504
|
-
}
|
|
5505
|
-
return fileURLToPath2(new URL("../index.js", params.importMetaUrl));
|
|
5506
|
-
}
|
|
5507
6012
|
var ServiceCommands = class {
|
|
5508
6013
|
constructor(deps) {
|
|
5509
6014
|
this.deps = deps;
|
|
5510
6015
|
}
|
|
6016
|
+
applyLiveConfigReload = null;
|
|
6017
|
+
liveUiNcpAgent = null;
|
|
5511
6018
|
async startGateway(options = {}) {
|
|
6019
|
+
this.applyLiveConfigReload = null;
|
|
6020
|
+
this.liveUiNcpAgent = null;
|
|
5512
6021
|
const runtimeConfigPath = getConfigPath3();
|
|
5513
|
-
const config2 = resolveConfigSecrets2(
|
|
5514
|
-
const workspace =
|
|
6022
|
+
const config2 = resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath });
|
|
6023
|
+
const workspace = getWorkspacePath8(config2.agents.defaults.workspace);
|
|
5515
6024
|
let pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
5516
6025
|
let extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
5517
6026
|
logPluginDiagnostics(pluginRegistry);
|
|
@@ -5555,7 +6064,7 @@ var ServiceCommands = class {
|
|
|
5555
6064
|
sessionManager,
|
|
5556
6065
|
providerManager,
|
|
5557
6066
|
makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
|
|
5558
|
-
loadConfig: () => resolveConfigSecrets2(
|
|
6067
|
+
loadConfig: () => resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }),
|
|
5559
6068
|
getExtensionChannels: () => extensionRegistry.channels,
|
|
5560
6069
|
onRestartRequired: (paths) => {
|
|
5561
6070
|
void this.deps.requestRestart({
|
|
@@ -5565,6 +6074,9 @@ var ServiceCommands = class {
|
|
|
5565
6074
|
});
|
|
5566
6075
|
}
|
|
5567
6076
|
});
|
|
6077
|
+
this.applyLiveConfigReload = async () => {
|
|
6078
|
+
await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }));
|
|
6079
|
+
};
|
|
5568
6080
|
const gatewayController = new GatewayControllerImpl({
|
|
5569
6081
|
reloader,
|
|
5570
6082
|
cron: cron2,
|
|
@@ -5596,38 +6108,42 @@ var ServiceCommands = class {
|
|
|
5596
6108
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
|
|
5597
6109
|
registry: pluginRegistry,
|
|
5598
6110
|
channel,
|
|
5599
|
-
cfg: resolveConfigSecrets2(
|
|
6111
|
+
cfg: resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }),
|
|
5600
6112
|
accountId
|
|
5601
6113
|
})
|
|
5602
6114
|
});
|
|
5603
6115
|
reloader.setApplyAgentRuntimeConfig((nextConfig) => runtimePool.applyRuntimeConfig(nextConfig));
|
|
5604
|
-
reloader.setReloadPlugins(async (nextConfig) => {
|
|
5605
|
-
const
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
6116
|
+
reloader.setReloadPlugins(async ({ config: nextConfig, changedPaths }) => {
|
|
6117
|
+
const result = await reloadServicePlugins({
|
|
6118
|
+
nextConfig,
|
|
6119
|
+
changedPaths,
|
|
6120
|
+
pluginRegistry,
|
|
6121
|
+
extensionRegistry,
|
|
6122
|
+
pluginChannelBindings,
|
|
6123
|
+
pluginGatewayHandles,
|
|
6124
|
+
pluginGatewayLogger,
|
|
6125
|
+
logPluginGatewayDiagnostics
|
|
5613
6126
|
});
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
6127
|
+
pluginRegistry = result.pluginRegistry;
|
|
6128
|
+
extensionRegistry = result.extensionRegistry;
|
|
6129
|
+
pluginChannelBindings = result.pluginChannelBindings;
|
|
6130
|
+
pluginGatewayHandles = result.pluginGatewayHandles;
|
|
6131
|
+
runtimePool.applyExtensionRegistry(result.extensionRegistry);
|
|
6132
|
+
this.liveUiNcpAgent?.applyExtensionRegistry?.(result.extensionRegistry);
|
|
5620
6133
|
runtimePool.applyRuntimeConfig(nextConfig);
|
|
5621
|
-
|
|
6134
|
+
if (result.restartChannels) {
|
|
6135
|
+
console.log("Config reload: plugin channel gateways restarted.");
|
|
6136
|
+
}
|
|
6137
|
+
return { restartChannels: result.restartChannels };
|
|
5622
6138
|
});
|
|
5623
|
-
let pluginChannelBindings =
|
|
6139
|
+
let pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
|
|
5624
6140
|
setPluginRuntimeBridge({
|
|
5625
|
-
loadConfig: () => toPluginConfigView(resolveConfigSecrets2(
|
|
6141
|
+
loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }), pluginChannelBindings),
|
|
5626
6142
|
writeConfigFile: async (nextConfigView) => {
|
|
5627
6143
|
if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
|
|
5628
6144
|
throw new Error("plugin runtime writeConfigFile expects an object config");
|
|
5629
6145
|
}
|
|
5630
|
-
const current =
|
|
6146
|
+
const current = loadConfig7();
|
|
5631
6147
|
const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
|
|
5632
6148
|
saveConfig5(next);
|
|
5633
6149
|
},
|
|
@@ -5703,12 +6219,12 @@ var ServiceCommands = class {
|
|
|
5703
6219
|
providerManager,
|
|
5704
6220
|
bus,
|
|
5705
6221
|
gatewayController,
|
|
5706
|
-
() => resolveConfigSecrets2(
|
|
6222
|
+
() => resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }),
|
|
5707
6223
|
() => extensionRegistry,
|
|
5708
6224
|
({ channel, accountId }) => resolvePluginChannelMessageToolHints({
|
|
5709
6225
|
registry: pluginRegistry,
|
|
5710
6226
|
channel,
|
|
5711
|
-
cfg: resolveConfigSecrets2(
|
|
6227
|
+
cfg: resolveConfigSecrets2(loadConfig7(), { configPath: runtimeConfigPath }),
|
|
5712
6228
|
accountId
|
|
5713
6229
|
})
|
|
5714
6230
|
);
|
|
@@ -5717,13 +6233,13 @@ var ServiceCommands = class {
|
|
|
5717
6233
|
console.log(`\u2713 Cron: ${cronStatus.jobs} scheduled jobs`);
|
|
5718
6234
|
}
|
|
5719
6235
|
console.log("\u2713 Heartbeat: every 30m");
|
|
5720
|
-
const configPath =
|
|
6236
|
+
const configPath = resolve10(getConfigPath3());
|
|
5721
6237
|
const watcher = chokidar.watch(configPath, {
|
|
5722
6238
|
ignoreInitial: true,
|
|
5723
6239
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
5724
6240
|
});
|
|
5725
6241
|
watcher.on("all", (event, changedPath) => {
|
|
5726
|
-
if (
|
|
6242
|
+
if (resolve10(changedPath) !== configPath) {
|
|
5727
6243
|
return;
|
|
5728
6244
|
}
|
|
5729
6245
|
if (event === "add") {
|
|
@@ -5741,7 +6257,7 @@ var ServiceCommands = class {
|
|
|
5741
6257
|
await cron2.start();
|
|
5742
6258
|
await heartbeat.start();
|
|
5743
6259
|
try {
|
|
5744
|
-
const startedPluginGateways = await
|
|
6260
|
+
const startedPluginGateways = await startPluginChannelGateways2({
|
|
5745
6261
|
registry: pluginRegistry,
|
|
5746
6262
|
logger: pluginGatewayLogger
|
|
5747
6263
|
});
|
|
@@ -5751,7 +6267,9 @@ var ServiceCommands = class {
|
|
|
5751
6267
|
await this.wakeFromRestartSentinel({ bus, sessionManager });
|
|
5752
6268
|
await runtimePool.run();
|
|
5753
6269
|
} finally {
|
|
5754
|
-
|
|
6270
|
+
this.applyLiveConfigReload = null;
|
|
6271
|
+
this.liveUiNcpAgent = null;
|
|
6272
|
+
await stopPluginChannelGateways2(pluginGatewayHandles);
|
|
5755
6273
|
setPluginRuntimeBridge(null);
|
|
5756
6274
|
}
|
|
5757
6275
|
}
|
|
@@ -5815,7 +6333,7 @@ var ServiceCommands = class {
|
|
|
5815
6333
|
if (!sentinel) {
|
|
5816
6334
|
return;
|
|
5817
6335
|
}
|
|
5818
|
-
await new Promise((
|
|
6336
|
+
await new Promise((resolve13) => setTimeout(resolve13, 750));
|
|
5819
6337
|
const payload = sentinel.payload;
|
|
5820
6338
|
const summary = formatRestartSentinelMessage(payload);
|
|
5821
6339
|
const sentinelSessionKey = this.normalizeOptionalString(payload.sessionKey);
|
|
@@ -5861,7 +6379,7 @@ var ServiceCommands = class {
|
|
|
5861
6379
|
});
|
|
5862
6380
|
}
|
|
5863
6381
|
async runForeground(options) {
|
|
5864
|
-
const config2 =
|
|
6382
|
+
const config2 = loadConfig7();
|
|
5865
6383
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
5866
6384
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
5867
6385
|
if (options.open) {
|
|
@@ -5874,7 +6392,7 @@ var ServiceCommands = class {
|
|
|
5874
6392
|
});
|
|
5875
6393
|
}
|
|
5876
6394
|
async startService(options) {
|
|
5877
|
-
const config2 =
|
|
6395
|
+
const config2 = loadConfig7();
|
|
5878
6396
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
5879
6397
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
5880
6398
|
const apiUrl = `${uiUrl}/api`;
|
|
@@ -5934,7 +6452,7 @@ var ServiceCommands = class {
|
|
|
5934
6452
|
return;
|
|
5935
6453
|
}
|
|
5936
6454
|
const logPath = resolveServiceLogPath();
|
|
5937
|
-
const logDir =
|
|
6455
|
+
const logDir = resolve10(logPath, "..");
|
|
5938
6456
|
mkdirSync5(logDir, { recursive: true });
|
|
5939
6457
|
const logFd = openSync(logPath, "a");
|
|
5940
6458
|
const readinessTimeoutMs = this.resolveStartupTimeoutMs(options.startupTimeoutMs);
|
|
@@ -6082,14 +6600,14 @@ var ServiceCommands = class {
|
|
|
6082
6600
|
const probe = await this.probeHealthEndpoint(params.healthUrl);
|
|
6083
6601
|
if (!probe.healthy) {
|
|
6084
6602
|
lastProbeError = probe.error;
|
|
6085
|
-
await new Promise((
|
|
6603
|
+
await new Promise((resolve13) => setTimeout(resolve13, 200));
|
|
6086
6604
|
continue;
|
|
6087
6605
|
}
|
|
6088
|
-
await new Promise((
|
|
6606
|
+
await new Promise((resolve13) => setTimeout(resolve13, 300));
|
|
6089
6607
|
if (isProcessRunning(params.pid)) {
|
|
6090
6608
|
return { ready: true, lastProbeError: null };
|
|
6091
6609
|
}
|
|
6092
|
-
await new Promise((
|
|
6610
|
+
await new Promise((resolve13) => setTimeout(resolve13, 200));
|
|
6093
6611
|
}
|
|
6094
6612
|
return { ready: false, lastProbeError };
|
|
6095
6613
|
}
|
|
@@ -6160,17 +6678,17 @@ var ServiceCommands = class {
|
|
|
6160
6678
|
};
|
|
6161
6679
|
}
|
|
6162
6680
|
async checkPortAvailability(params) {
|
|
6163
|
-
return await new Promise((
|
|
6681
|
+
return await new Promise((resolve13) => {
|
|
6164
6682
|
const server = createNetServer2();
|
|
6165
6683
|
server.once("error", (error) => {
|
|
6166
|
-
|
|
6684
|
+
resolve13({
|
|
6167
6685
|
available: false,
|
|
6168
6686
|
detail: `bind failed on ${params.host}:${params.port} (${String(error)})`
|
|
6169
6687
|
});
|
|
6170
6688
|
});
|
|
6171
6689
|
server.listen(params.port, params.host, () => {
|
|
6172
6690
|
server.close(() => {
|
|
6173
|
-
|
|
6691
|
+
resolve13({
|
|
6174
6692
|
available: true,
|
|
6175
6693
|
detail: `bind ok on ${params.host}:${params.port}`
|
|
6176
6694
|
});
|
|
@@ -6206,7 +6724,7 @@ var ServiceCommands = class {
|
|
|
6206
6724
|
return { healthy: false, error: "invalid health URL" };
|
|
6207
6725
|
}
|
|
6208
6726
|
const requestImpl = parsed.protocol === "https:" ? httpsRequest : httpRequest;
|
|
6209
|
-
return new Promise((
|
|
6727
|
+
return new Promise((resolve13) => {
|
|
6210
6728
|
const req = requestImpl(
|
|
6211
6729
|
{
|
|
6212
6730
|
protocol: parsed.protocol,
|
|
@@ -6242,19 +6760,19 @@ var ServiceCommands = class {
|
|
|
6242
6760
|
if (bodySnippet) {
|
|
6243
6761
|
details.push(`body=${bodySnippet}`);
|
|
6244
6762
|
}
|
|
6245
|
-
|
|
6763
|
+
resolve13({ healthy: false, error: details.join("; ") });
|
|
6246
6764
|
return;
|
|
6247
6765
|
}
|
|
6248
6766
|
try {
|
|
6249
6767
|
const payload = JSON.parse(responseText);
|
|
6250
6768
|
const healthy = payload?.ok === true && payload?.data?.status === "ok";
|
|
6251
6769
|
if (!healthy) {
|
|
6252
|
-
|
|
6770
|
+
resolve13({ healthy: false, error: "health payload not ok" });
|
|
6253
6771
|
return;
|
|
6254
6772
|
}
|
|
6255
|
-
|
|
6773
|
+
resolve13({ healthy: true, error: null });
|
|
6256
6774
|
} catch {
|
|
6257
|
-
|
|
6775
|
+
resolve13({ healthy: false, error: "invalid health JSON response" });
|
|
6258
6776
|
}
|
|
6259
6777
|
});
|
|
6260
6778
|
}
|
|
@@ -6263,7 +6781,7 @@ var ServiceCommands = class {
|
|
|
6263
6781
|
req.destroy(new Error("probe timeout"));
|
|
6264
6782
|
});
|
|
6265
6783
|
req.on("error", (error) => {
|
|
6266
|
-
|
|
6784
|
+
resolve13({ healthy: false, error: error.message || String(error) });
|
|
6267
6785
|
});
|
|
6268
6786
|
req.end();
|
|
6269
6787
|
});
|
|
@@ -6368,13 +6886,7 @@ var ServiceCommands = class {
|
|
|
6368
6886
|
if (sessionType === "native") {
|
|
6369
6887
|
return "Native";
|
|
6370
6888
|
}
|
|
6371
|
-
|
|
6372
|
-
return "Codex";
|
|
6373
|
-
}
|
|
6374
|
-
if (sessionType === "claude-agent-sdk") {
|
|
6375
|
-
return "Claude Code";
|
|
6376
|
-
}
|
|
6377
|
-
return sessionType;
|
|
6889
|
+
return sessionType.trim().split(/[-_]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ") || sessionType;
|
|
6378
6890
|
};
|
|
6379
6891
|
let publishUiEvent = null;
|
|
6380
6892
|
runtimePool.setSystemSessionUpdatedHandler(({ sessionKey, message }) => {
|
|
@@ -6412,6 +6924,7 @@ var ServiceCommands = class {
|
|
|
6412
6924
|
accountId
|
|
6413
6925
|
})
|
|
6414
6926
|
});
|
|
6927
|
+
this.liveUiNcpAgent = ncpAgent;
|
|
6415
6928
|
const uiServer = startUiServer({
|
|
6416
6929
|
host: uiConfig.host,
|
|
6417
6930
|
port: uiConfig.port,
|
|
@@ -6510,9 +7023,9 @@ var ServiceCommands = class {
|
|
|
6510
7023
|
}
|
|
6511
7024
|
}
|
|
6512
7025
|
async installMarketplacePlugin(spec) {
|
|
6513
|
-
const
|
|
6514
|
-
|
|
6515
|
-
return { message:
|
|
7026
|
+
const result = await installPluginMutation(spec);
|
|
7027
|
+
await this.applyLiveConfigReload?.();
|
|
7028
|
+
return { message: result.message };
|
|
6516
7029
|
}
|
|
6517
7030
|
async installMarketplaceSkill(params) {
|
|
6518
7031
|
if (params.kind === "builtin") {
|
|
@@ -6525,7 +7038,7 @@ var ServiceCommands = class {
|
|
|
6525
7038
|
if (params.kind && params.kind !== "marketplace") {
|
|
6526
7039
|
throw new Error(`Unsupported marketplace skill kind: ${params.kind}`);
|
|
6527
7040
|
}
|
|
6528
|
-
const workspace =
|
|
7041
|
+
const workspace = getWorkspacePath8(loadConfig7().agents.defaults.workspace);
|
|
6529
7042
|
const args = buildMarketplaceSkillInstallArgs({
|
|
6530
7043
|
slug: params.slug,
|
|
6531
7044
|
workspace,
|
|
@@ -6544,22 +7057,24 @@ var ServiceCommands = class {
|
|
|
6544
7057
|
}
|
|
6545
7058
|
}
|
|
6546
7059
|
async enableMarketplacePlugin(id) {
|
|
6547
|
-
const
|
|
6548
|
-
|
|
6549
|
-
return { message:
|
|
7060
|
+
const result = await enablePluginMutation(id);
|
|
7061
|
+
await this.applyLiveConfigReload?.();
|
|
7062
|
+
return { message: result.message };
|
|
6550
7063
|
}
|
|
6551
7064
|
async disableMarketplacePlugin(id) {
|
|
6552
|
-
const
|
|
6553
|
-
|
|
6554
|
-
return { message:
|
|
7065
|
+
const result = await disablePluginMutation(id);
|
|
7066
|
+
await this.applyLiveConfigReload?.();
|
|
7067
|
+
return { message: result.message };
|
|
6555
7068
|
}
|
|
6556
7069
|
async uninstallMarketplacePlugin(id) {
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
7070
|
+
await disablePluginMutation(id);
|
|
7071
|
+
await this.applyLiveConfigReload?.();
|
|
7072
|
+
const result = await uninstallPluginMutation(id, { force: true });
|
|
7073
|
+
await this.applyLiveConfigReload?.();
|
|
7074
|
+
return { message: result.message };
|
|
6560
7075
|
}
|
|
6561
7076
|
async uninstallMarketplaceSkill(slug) {
|
|
6562
|
-
const workspace =
|
|
7077
|
+
const workspace = getWorkspacePath8(loadConfig7().agents.defaults.workspace);
|
|
6563
7078
|
const targetDir = join5(workspace, "skills", slug);
|
|
6564
7079
|
if (!existsSync9(targetDir)) {
|
|
6565
7080
|
throw new Error(`Skill not installed in workspace: ${slug}`);
|
|
@@ -6570,7 +7085,7 @@ var ServiceCommands = class {
|
|
|
6570
7085
|
};
|
|
6571
7086
|
}
|
|
6572
7087
|
installBuiltinMarketplaceSkill(slug, force) {
|
|
6573
|
-
const workspace =
|
|
7088
|
+
const workspace = getWorkspacePath8(loadConfig7().agents.defaults.workspace);
|
|
6574
7089
|
const destination = join5(workspace, "skills", slug);
|
|
6575
7090
|
const destinationSkillFile = join5(destination, "SKILL.md");
|
|
6576
7091
|
if (existsSync9(destinationSkillFile) && !force) {
|
|
@@ -6649,8 +7164,8 @@ ${stderr}`.trim();
|
|
|
6649
7164
|
|
|
6650
7165
|
// src/cli/workspace.ts
|
|
6651
7166
|
import { cpSync as cpSync3, existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync9, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
6652
|
-
import { createRequire } from "module";
|
|
6653
|
-
import { dirname as dirname3, join as join6, resolve as
|
|
7167
|
+
import { createRequire as createRequire2 } from "module";
|
|
7168
|
+
import { dirname as dirname3, join as join6, resolve as resolve11 } from "path";
|
|
6654
7169
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6655
7170
|
import { APP_NAME as APP_NAME3, getDataDir as getDataDir7 } from "@nextclaw/core";
|
|
6656
7171
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -6742,9 +7257,9 @@ var WorkspaceManager = class {
|
|
|
6742
7257
|
}
|
|
6743
7258
|
resolveBuiltinSkillsDir() {
|
|
6744
7259
|
try {
|
|
6745
|
-
const
|
|
6746
|
-
const entry =
|
|
6747
|
-
const pkgRoot =
|
|
7260
|
+
const require3 = createRequire2(import.meta.url);
|
|
7261
|
+
const entry = require3.resolve("@nextclaw/core");
|
|
7262
|
+
const pkgRoot = resolve11(dirname3(entry), "..");
|
|
6748
7263
|
const distSkills = join6(pkgRoot, "dist", "skills");
|
|
6749
7264
|
if (existsSync10(distSkills)) {
|
|
6750
7265
|
return distSkills;
|
|
@@ -6763,8 +7278,8 @@ var WorkspaceManager = class {
|
|
|
6763
7278
|
if (override) {
|
|
6764
7279
|
return override;
|
|
6765
7280
|
}
|
|
6766
|
-
const cliDir =
|
|
6767
|
-
const pkgRoot =
|
|
7281
|
+
const cliDir = resolve11(fileURLToPath3(new URL(".", import.meta.url)));
|
|
7282
|
+
const pkgRoot = resolve11(cliDir, "..", "..");
|
|
6768
7283
|
const candidates = [join6(pkgRoot, "templates")];
|
|
6769
7284
|
for (const candidate of candidates) {
|
|
6770
7285
|
if (existsSync10(candidate)) {
|
|
@@ -6782,8 +7297,8 @@ var WorkspaceManager = class {
|
|
|
6782
7297
|
console.error("npm not found. Please install Node.js >= 18.");
|
|
6783
7298
|
process.exit(1);
|
|
6784
7299
|
}
|
|
6785
|
-
const cliDir =
|
|
6786
|
-
const pkgRoot =
|
|
7300
|
+
const cliDir = resolve11(fileURLToPath3(new URL(".", import.meta.url)));
|
|
7301
|
+
const pkgRoot = resolve11(cliDir, "..", "..");
|
|
6787
7302
|
const pkgBridge = join6(pkgRoot, "bridge");
|
|
6788
7303
|
const srcBridge = join6(pkgRoot, "..", "..", "bridge");
|
|
6789
7304
|
let source = null;
|
|
@@ -6797,7 +7312,7 @@ var WorkspaceManager = class {
|
|
|
6797
7312
|
process.exit(1);
|
|
6798
7313
|
}
|
|
6799
7314
|
console.log(`${this.logo} Setting up bridge...`);
|
|
6800
|
-
mkdirSync6(
|
|
7315
|
+
mkdirSync6(resolve11(userBridge, ".."), { recursive: true });
|
|
6801
7316
|
if (existsSync10(userBridge)) {
|
|
6802
7317
|
rmSync5(userBridge, { recursive: true, force: true });
|
|
6803
7318
|
}
|
|
@@ -6834,7 +7349,7 @@ function resolveSkillsInstallWorkdir(params) {
|
|
|
6834
7349
|
if (params.explicitWorkdir) {
|
|
6835
7350
|
return expandHome2(params.explicitWorkdir);
|
|
6836
7351
|
}
|
|
6837
|
-
return
|
|
7352
|
+
return getWorkspacePath9(params.configuredWorkspace);
|
|
6838
7353
|
}
|
|
6839
7354
|
var CliRuntime = class {
|
|
6840
7355
|
logo;
|
|
@@ -6933,7 +7448,7 @@ var CliRuntime = class {
|
|
|
6933
7448
|
const delayMs = typeof params.delayMs === "number" && Number.isFinite(params.delayMs) ? Math.max(0, Math.floor(params.delayMs)) : 100;
|
|
6934
7449
|
const cliPath = process.env.NEXTCLAW_SELF_RELAUNCH_CLI?.trim() || fileURLToPath4(new URL("./index.js", import.meta.url));
|
|
6935
7450
|
const startArgs = [cliPath, "start", "--ui-port", String(uiPort)];
|
|
6936
|
-
const serviceStatePath =
|
|
7451
|
+
const serviceStatePath = resolve12(getDataDir8(), "run", "service.json");
|
|
6937
7452
|
const helperScript = [
|
|
6938
7453
|
'const { spawnSync } = require("node:child_process");',
|
|
6939
7454
|
'const { readFileSync } = require("node:fs");',
|
|
@@ -7068,7 +7583,7 @@ var CliRuntime = class {
|
|
|
7068
7583
|
saveConfig6(config3);
|
|
7069
7584
|
createdConfig = true;
|
|
7070
7585
|
}
|
|
7071
|
-
const config2 =
|
|
7586
|
+
const config2 = loadConfig8();
|
|
7072
7587
|
const workspaceSetting = config2.agents.defaults.workspace;
|
|
7073
7588
|
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join7(getDataDir8(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
|
|
7074
7589
|
const workspaceExisted = existsSync11(workspacePath);
|
|
@@ -7104,7 +7619,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7104
7619
|
async login(opts = {}) {
|
|
7105
7620
|
await this.init({ source: "login", auto: true });
|
|
7106
7621
|
const configPath = getConfigPath4();
|
|
7107
|
-
const config2 =
|
|
7622
|
+
const config2 = loadConfig8(configPath);
|
|
7108
7623
|
const providers = config2.providers;
|
|
7109
7624
|
const nextclawProvider = providers.nextclaw ?? {
|
|
7110
7625
|
displayName: "",
|
|
@@ -7261,15 +7776,15 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7261
7776
|
}
|
|
7262
7777
|
async agent(opts) {
|
|
7263
7778
|
const configPath = getConfigPath4();
|
|
7264
|
-
const config2 = resolveConfigSecrets3(
|
|
7265
|
-
const workspace =
|
|
7779
|
+
const config2 = resolveConfigSecrets3(loadConfig8(), { configPath });
|
|
7780
|
+
const workspace = getWorkspacePath9(config2.agents.defaults.workspace);
|
|
7266
7781
|
const pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
7267
7782
|
const extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
7268
7783
|
logPluginDiagnostics(pluginRegistry);
|
|
7269
|
-
const pluginChannelBindings =
|
|
7784
|
+
const pluginChannelBindings = getPluginChannelBindings4(pluginRegistry);
|
|
7270
7785
|
setPluginRuntimeBridge2({
|
|
7271
7786
|
loadConfig: () => toPluginConfigView(
|
|
7272
|
-
resolveConfigSecrets3(
|
|
7787
|
+
resolveConfigSecrets3(loadConfig8(), { configPath }),
|
|
7273
7788
|
pluginChannelBindings
|
|
7274
7789
|
),
|
|
7275
7790
|
writeConfigFile: async (nextConfigView) => {
|
|
@@ -7278,7 +7793,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7278
7793
|
"plugin runtime writeConfigFile expects an object config"
|
|
7279
7794
|
);
|
|
7280
7795
|
}
|
|
7281
|
-
const current =
|
|
7796
|
+
const current = loadConfig8();
|
|
7282
7797
|
const next = mergePluginConfigView(
|
|
7283
7798
|
current,
|
|
7284
7799
|
nextConfigView,
|
|
@@ -7310,7 +7825,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7310
7825
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
|
|
7311
7826
|
registry: pluginRegistry,
|
|
7312
7827
|
channel,
|
|
7313
|
-
cfg: resolveConfigSecrets3(
|
|
7828
|
+
cfg: resolveConfigSecrets3(loadConfig8(), { configPath }),
|
|
7314
7829
|
accountId
|
|
7315
7830
|
})
|
|
7316
7831
|
});
|
|
@@ -7330,7 +7845,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7330
7845
|
`
|
|
7331
7846
|
);
|
|
7332
7847
|
const historyFile = join7(getDataDir8(), "history", "cli_history");
|
|
7333
|
-
const historyDir =
|
|
7848
|
+
const historyDir = resolve12(historyFile, "..");
|
|
7334
7849
|
mkdirSync7(historyDir, { recursive: true });
|
|
7335
7850
|
const history = existsSync11(historyFile) ? readFileSync10(historyFile, "utf-8").split("\n").filter(Boolean) : [];
|
|
7336
7851
|
const rl = createInterface2({
|
|
@@ -7487,7 +8002,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
7487
8002
|
await this.diagnosticsCommands.doctor(opts);
|
|
7488
8003
|
}
|
|
7489
8004
|
async skillsInstall(options) {
|
|
7490
|
-
const config2 =
|
|
8005
|
+
const config2 = loadConfig8();
|
|
7491
8006
|
const workdir = resolveSkillsInstallWorkdir({
|
|
7492
8007
|
explicitWorkdir: options.workdir,
|
|
7493
8008
|
configuredWorkspace: config2.agents.defaults.workspace
|
|
@@ -7577,9 +8092,9 @@ plugins.command("uninstall <id>").description("Uninstall a plugin").option("--ke
|
|
|
7577
8092
|
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));
|
|
7578
8093
|
plugins.command("doctor").description("Report plugin load issues").action(() => runtime.pluginsDoctor());
|
|
7579
8094
|
var config = program.command("config").description("Manage config values");
|
|
7580
|
-
config.command("get <path>").description("Get a config value by dot path").option("--json", "Output JSON", false).action((
|
|
7581
|
-
config.command("set <path> <value>").description("Set a config value by dot path").option("--json", "Parse value as JSON", false).action((
|
|
7582
|
-
config.command("unset <path>").description("Remove a config value by dot path").action((
|
|
8095
|
+
config.command("get <path>").description("Get a config value by dot path").option("--json", "Output JSON", false).action((path2, opts) => runtime.configGet(path2, opts));
|
|
8096
|
+
config.command("set <path> <value>").description("Set a config value by dot path").option("--json", "Parse value as JSON", false).action((path2, value, opts) => runtime.configSet(path2, value, opts));
|
|
8097
|
+
config.command("unset <path>").description("Remove a config value by dot path").action((path2) => runtime.configUnset(path2));
|
|
7583
8098
|
var secrets = program.command("secrets").description("Manage secrets refs/providers");
|
|
7584
8099
|
secrets.command("audit").description("Audit secret refs resolution status").option("--json", "Output JSON", false).option("--strict", "Exit non-zero when unresolved refs exist", false).action((opts) => runtime.secretsAudit(opts));
|
|
7585
8100
|
secrets.command("configure").description("Configure a secret provider alias").requiredOption("--provider <alias>", "Provider alias").option("--source <source>", "Provider source (env|file|exec)").option("--prefix <prefix>", "Env key prefix (env source)").option("--path <path>", "Secret JSON file path (file source)").option("--command <command>", "Command for exec source").option(
|