@nextclaw/openclaw-compat 0.2.7 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +32 -1
- package/dist/index.js +311 -143
- package/package.json +15 -13
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as _nextclaw_core from '@nextclaw/core';
|
|
2
2
|
import { Config, ExtensionChannel, AgentEngineFactory } from '@nextclaw/core';
|
|
3
|
+
import { NcpAgentRuntime } from '@nextclaw/ncp';
|
|
4
|
+
import { RuntimeFactoryParams } from '@nextclaw/ncp-toolkit';
|
|
3
5
|
|
|
4
6
|
type PluginConfigUiHint = {
|
|
5
7
|
label?: string;
|
|
@@ -54,6 +56,11 @@ type OpenClawPluginToolOptions = {
|
|
|
54
56
|
type OpenClawPluginEngineOptions = {
|
|
55
57
|
kind: string;
|
|
56
58
|
};
|
|
59
|
+
type OpenClawPluginNcpAgentRuntimeRegistration = {
|
|
60
|
+
kind: string;
|
|
61
|
+
label?: string;
|
|
62
|
+
createRuntime: (params: RuntimeFactoryParams) => NcpAgentRuntime;
|
|
63
|
+
};
|
|
57
64
|
type OpenClawProviderPlugin = {
|
|
58
65
|
id: string;
|
|
59
66
|
label?: string;
|
|
@@ -175,6 +182,7 @@ type PluginRecord = {
|
|
|
175
182
|
channelIds: string[];
|
|
176
183
|
providerIds: string[];
|
|
177
184
|
engineKinds: string[];
|
|
185
|
+
ncpAgentRuntimeKinds: string[];
|
|
178
186
|
configSchema: boolean;
|
|
179
187
|
configUiHints?: Record<string, PluginConfigUiHint>;
|
|
180
188
|
configJsonSchema?: Record<string, unknown>;
|
|
@@ -202,6 +210,13 @@ type PluginEngineRegistration = {
|
|
|
202
210
|
factory: AgentEngineFactory;
|
|
203
211
|
source: string;
|
|
204
212
|
};
|
|
213
|
+
type PluginNcpAgentRuntimeRegistration = {
|
|
214
|
+
pluginId: string;
|
|
215
|
+
kind: string;
|
|
216
|
+
label: string;
|
|
217
|
+
createRuntime: (params: RuntimeFactoryParams) => NcpAgentRuntime;
|
|
218
|
+
source: string;
|
|
219
|
+
};
|
|
205
220
|
type PluginReplyDispatchParams = {
|
|
206
221
|
ctx: {
|
|
207
222
|
Body?: string;
|
|
@@ -264,6 +279,7 @@ type OpenClawPluginApi = {
|
|
|
264
279
|
registerChannel: (registration: OpenClawPluginChannelRegistration) => void;
|
|
265
280
|
registerProvider: (provider: OpenClawProviderPlugin) => void;
|
|
266
281
|
registerEngine: (factory: AgentEngineFactory, opts: OpenClawPluginEngineOptions) => void;
|
|
282
|
+
registerNcpAgentRuntime: (registration: OpenClawPluginNcpAgentRuntimeRegistration) => void;
|
|
267
283
|
registerHook: (_events: string | string[], _handler: unknown, _opts?: unknown) => void;
|
|
268
284
|
registerGatewayMethod: (_method: string, _handler: unknown) => void;
|
|
269
285
|
registerCli: (_registrar: unknown, _opts?: unknown) => void;
|
|
@@ -282,6 +298,7 @@ type PluginRegistry = {
|
|
|
282
298
|
channels: PluginChannelRegistration[];
|
|
283
299
|
providers: PluginProviderRegistration[];
|
|
284
300
|
engines: PluginEngineRegistration[];
|
|
301
|
+
ncpAgentRuntimes: PluginNcpAgentRuntimeRegistration[];
|
|
285
302
|
diagnostics: PluginDiagnostic[];
|
|
286
303
|
resolvedTools: OpenClawPluginTool[];
|
|
287
304
|
};
|
|
@@ -473,11 +490,14 @@ type PluginLoadOptions = {
|
|
|
473
490
|
workspaceDir?: string;
|
|
474
491
|
logger?: PluginLogger;
|
|
475
492
|
mode?: "full" | "validate";
|
|
493
|
+
excludeRoots?: string[];
|
|
476
494
|
reservedToolNames?: string[];
|
|
477
495
|
reservedChannelIds?: string[];
|
|
478
496
|
reservedProviderIds?: string[];
|
|
479
497
|
reservedEngineKinds?: string[];
|
|
498
|
+
reservedNcpAgentRuntimeKinds?: string[];
|
|
480
499
|
};
|
|
500
|
+
declare function buildPluginLoaderAliases(): Record<string, string>;
|
|
481
501
|
declare function loadOpenClawPlugins(options: PluginLoadOptions): PluginRegistry;
|
|
482
502
|
|
|
483
503
|
type PluginManifestRecord = {
|
|
@@ -554,11 +574,13 @@ type PluginRegisterRuntime = {
|
|
|
554
574
|
channelIdOwners: Map<string, string>;
|
|
555
575
|
providerIdOwners: Map<string, string>;
|
|
556
576
|
engineKindOwners: Map<string, string>;
|
|
577
|
+
ncpAgentRuntimeKindOwners: Map<string, string>;
|
|
557
578
|
resolvedToolNames: Set<string>;
|
|
558
579
|
reservedToolNames: Set<string>;
|
|
559
580
|
reservedChannelIds: Set<string>;
|
|
560
581
|
reservedProviderIds: Set<string>;
|
|
561
582
|
reservedEngineKinds: Set<string>;
|
|
583
|
+
reservedNcpAgentRuntimeKinds: Set<string>;
|
|
562
584
|
};
|
|
563
585
|
declare function createPluginRegisterRuntime(params: {
|
|
564
586
|
config: Config;
|
|
@@ -569,6 +591,7 @@ declare function createPluginRegisterRuntime(params: {
|
|
|
569
591
|
reservedChannelIds: Set<string>;
|
|
570
592
|
reservedProviderIds: Set<string>;
|
|
571
593
|
reservedEngineKinds: Set<string>;
|
|
594
|
+
reservedNcpAgentRuntimeKinds: Set<string>;
|
|
572
595
|
}): PluginRegisterRuntime;
|
|
573
596
|
declare function registerPluginWithApi(params: {
|
|
574
597
|
runtime: PluginRegisterRuntime;
|
|
@@ -607,6 +630,7 @@ declare function buildPluginStatusReport(params: {
|
|
|
607
630
|
reservedChannelIds?: string[];
|
|
608
631
|
reservedProviderIds?: string[];
|
|
609
632
|
reservedEngineKinds?: string[];
|
|
633
|
+
reservedNcpAgentRuntimeKinds?: string[];
|
|
610
634
|
}): PluginStatusReport;
|
|
611
635
|
|
|
612
636
|
type UninstallActions = {
|
|
@@ -633,6 +657,13 @@ declare function resolveUninstallDirectoryTarget(params: {
|
|
|
633
657
|
installRecord?: PluginInstallRecord;
|
|
634
658
|
extensionsDir?: string;
|
|
635
659
|
}): string | null;
|
|
660
|
+
declare function resolveUninstallDirectoryTargets(params: {
|
|
661
|
+
config: Config;
|
|
662
|
+
pluginId: string;
|
|
663
|
+
hasInstall: boolean;
|
|
664
|
+
installRecord?: PluginInstallRecord;
|
|
665
|
+
extensionsDir?: string;
|
|
666
|
+
}): string[];
|
|
636
667
|
declare function removePluginFromConfig(config: Config, pluginId: string): {
|
|
637
668
|
config: Config;
|
|
638
669
|
actions: Omit<UninstallActions, "directory">;
|
|
@@ -644,4 +675,4 @@ declare function uninstallPlugin(params: {
|
|
|
644
675
|
extensionsDir?: string;
|
|
645
676
|
}): Promise<UninstallPluginResult>;
|
|
646
677
|
|
|
647
|
-
export { DEFAULT_ACCOUNT_ID, type InstallPluginResult, type NormalizedPluginsConfig, type OpenClawChannelAgentPrompt, type OpenClawChannelConfigAdapter, type OpenClawChannelConfigSchema, type OpenClawChannelGateway, type OpenClawChannelGatewayStartContext, type OpenClawChannelPlugin, type OpenClawChannelSetup, type OpenClawPluginApi, type OpenClawPluginChannelRegistration, type OpenClawPluginConfigSchema, type OpenClawPluginDefinition, type OpenClawPluginEngineOptions, type OpenClawPluginModule, type OpenClawPluginTool, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OpenClawProviderPlugin, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PackageManifest, type PluginCandidate, type PluginChannelBinding, type PluginChannelGatewayHandle, type PluginChannelRegistration, type PluginConfigUiHint, type PluginDiagnostic, type PluginDiscoveryResult, type PluginEngineRegistration, type PluginInstallLogger, type PluginInstallSource, type PluginInstallUpdate, type PluginKind, type PluginLoadOptions, type PluginLogger, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRecord, type PluginManifestRegistry, type PluginOrigin, type PluginProviderRegistration, type PluginRecord, type PluginRegisterRuntime, type PluginRegistry, type PluginReplyDispatchParams, type PluginRuntime, type PluginRuntimeBridge, type PluginStatusReport, type PluginToolRegistration, type PluginUiMetadata, type UninstallActions, type UninstallPluginResult, type _CompatOnly, __nextclawPluginSdkCompat, addPluginLoadPath, buildChannelConfigSchema, buildOauthProviderAuthResult, buildPluginStatusReport, createNextclawBuiltinChannelPlugin, createPluginRegisterRuntime, createPluginRuntime, disablePluginInConfig, discoverOpenClawPlugins, emptyPluginConfigSchema, enablePluginInConfig, getPackageManifestMetadata, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromArchive, installPluginFromDir, installPluginFromFile, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, loadPluginManifestRegistry, loadPluginUiMetadata, normalizeAccountId, normalizePluginHttpPath, normalizePluginsConfig, recordPluginInstall, registerPluginWithApi, removePluginFromConfig, resolveEnableState, resolvePluginChannelMessageToolHints, resolvePluginInstallDir, resolvePluginManifestPath, resolveUninstallDirectoryTarget, setPluginRuntimeBridge, sleep, startPluginChannelGateways, stopPluginChannelGateways, toPluginUiMetadata, uninstallPlugin, validateJsonSchemaValue };
|
|
678
|
+
export { DEFAULT_ACCOUNT_ID, type InstallPluginResult, type NormalizedPluginsConfig, type OpenClawChannelAgentPrompt, type OpenClawChannelConfigAdapter, type OpenClawChannelConfigSchema, type OpenClawChannelGateway, type OpenClawChannelGatewayStartContext, type OpenClawChannelPlugin, type OpenClawChannelSetup, type OpenClawPluginApi, type OpenClawPluginChannelRegistration, type OpenClawPluginConfigSchema, type OpenClawPluginDefinition, type OpenClawPluginEngineOptions, type OpenClawPluginModule, type OpenClawPluginNcpAgentRuntimeRegistration, type OpenClawPluginTool, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OpenClawProviderPlugin, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PackageManifest, type PluginCandidate, type PluginChannelBinding, type PluginChannelGatewayHandle, type PluginChannelRegistration, type PluginConfigUiHint, type PluginDiagnostic, type PluginDiscoveryResult, type PluginEngineRegistration, type PluginInstallLogger, type PluginInstallSource, type PluginInstallUpdate, type PluginKind, type PluginLoadOptions, type PluginLogger, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRecord, type PluginManifestRegistry, type PluginNcpAgentRuntimeRegistration, type PluginOrigin, type PluginProviderRegistration, type PluginRecord, type PluginRegisterRuntime, type PluginRegistry, type PluginReplyDispatchParams, type PluginRuntime, type PluginRuntimeBridge, type PluginStatusReport, type PluginToolRegistration, type PluginUiMetadata, type UninstallActions, type UninstallPluginResult, type _CompatOnly, __nextclawPluginSdkCompat, addPluginLoadPath, buildChannelConfigSchema, buildOauthProviderAuthResult, buildPluginLoaderAliases, buildPluginStatusReport, createNextclawBuiltinChannelPlugin, createPluginRegisterRuntime, createPluginRuntime, disablePluginInConfig, discoverOpenClawPlugins, emptyPluginConfigSchema, enablePluginInConfig, getPackageManifestMetadata, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromArchive, installPluginFromDir, installPluginFromFile, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, loadPluginManifestRegistry, loadPluginUiMetadata, normalizeAccountId, normalizePluginHttpPath, normalizePluginsConfig, recordPluginInstall, registerPluginWithApi, removePluginFromConfig, resolveEnableState, resolvePluginChannelMessageToolHints, resolvePluginInstallDir, resolvePluginManifestPath, resolveUninstallDirectoryTarget, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, sleep, startPluginChannelGateways, stopPluginChannelGateways, toPluginUiMetadata, uninstallPlugin, validateJsonSchemaValue };
|
package/dist/index.js
CHANGED
|
@@ -1068,12 +1068,34 @@ async function installPluginFromPath(params) {
|
|
|
1068
1068
|
|
|
1069
1069
|
// src/plugins/loader.ts
|
|
1070
1070
|
import fs5 from "fs";
|
|
1071
|
-
import
|
|
1071
|
+
import path6 from "path";
|
|
1072
1072
|
import { fileURLToPath } from "url";
|
|
1073
1073
|
import { createRequire } from "module";
|
|
1074
1074
|
import createJitiImport from "jiti";
|
|
1075
1075
|
import { getWorkspacePathFromConfig } from "@nextclaw/core";
|
|
1076
1076
|
|
|
1077
|
+
// src/plugins/candidate-filter.ts
|
|
1078
|
+
import path4 from "path";
|
|
1079
|
+
function isPathInsideRoot(candidatePath, rootPath) {
|
|
1080
|
+
const normalizedCandidate = path4.resolve(candidatePath);
|
|
1081
|
+
const normalizedRoot = path4.resolve(rootPath);
|
|
1082
|
+
return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(`${normalizedRoot}${path4.sep}`);
|
|
1083
|
+
}
|
|
1084
|
+
function filterPluginCandidatesByExcludedRoots(candidates, excludedRoots) {
|
|
1085
|
+
const normalizedRoots = excludedRoots.map((entry) => path4.resolve(entry));
|
|
1086
|
+
if (normalizedRoots.length === 0) {
|
|
1087
|
+
return [...candidates];
|
|
1088
|
+
}
|
|
1089
|
+
return candidates.filter((candidate) => {
|
|
1090
|
+
const candidatePaths = [candidate.source, candidate.rootDir, candidate.packageDir].filter(
|
|
1091
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
1092
|
+
);
|
|
1093
|
+
return !normalizedRoots.some(
|
|
1094
|
+
(rootPath) => candidatePaths.some((candidatePath) => isPathInsideRoot(candidatePath, rootPath))
|
|
1095
|
+
);
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1077
1099
|
// src/plugins/manifest-registry.ts
|
|
1078
1100
|
import fs4 from "fs";
|
|
1079
1101
|
var PLUGIN_ORIGIN_RANK = {
|
|
@@ -1233,9 +1255,9 @@ function formatAjvErrors(errors) {
|
|
|
1233
1255
|
return ["invalid config"];
|
|
1234
1256
|
}
|
|
1235
1257
|
return errors.map((error) => {
|
|
1236
|
-
const
|
|
1258
|
+
const path8 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
|
|
1237
1259
|
const message = error.message ?? "invalid";
|
|
1238
|
-
return `${
|
|
1260
|
+
return `${path8}: ${message}`;
|
|
1239
1261
|
});
|
|
1240
1262
|
}
|
|
1241
1263
|
function validateJsonSchemaValue(params) {
|
|
@@ -1252,10 +1274,148 @@ function validateJsonSchemaValue(params) {
|
|
|
1252
1274
|
return { ok: false, errors: formatAjvErrors(cached.validate.errors) };
|
|
1253
1275
|
}
|
|
1254
1276
|
|
|
1277
|
+
// src/plugins/plugin-loader-utils.ts
|
|
1278
|
+
function createPluginRecord(params) {
|
|
1279
|
+
return {
|
|
1280
|
+
id: params.id,
|
|
1281
|
+
name: params.name ?? params.id,
|
|
1282
|
+
description: params.description,
|
|
1283
|
+
version: params.version,
|
|
1284
|
+
kind: params.kind,
|
|
1285
|
+
source: params.source,
|
|
1286
|
+
origin: params.origin,
|
|
1287
|
+
workspaceDir: params.workspaceDir,
|
|
1288
|
+
enabled: params.enabled,
|
|
1289
|
+
status: params.enabled ? "loaded" : "disabled",
|
|
1290
|
+
toolNames: [],
|
|
1291
|
+
channelIds: [],
|
|
1292
|
+
providerIds: [],
|
|
1293
|
+
engineKinds: [],
|
|
1294
|
+
ncpAgentRuntimeKinds: [],
|
|
1295
|
+
configSchema: params.configSchema,
|
|
1296
|
+
configUiHints: params.configUiHints,
|
|
1297
|
+
configJsonSchema: params.configJsonSchema
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
function isPlaceholderConfigSchema(schema) {
|
|
1301
|
+
if (!schema || typeof schema !== "object") {
|
|
1302
|
+
return false;
|
|
1303
|
+
}
|
|
1304
|
+
const type = schema.type;
|
|
1305
|
+
const isObjectType = type === "object" || Array.isArray(type) && type.includes("object");
|
|
1306
|
+
if (!isObjectType) {
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
const properties = schema.properties;
|
|
1310
|
+
const noProperties = !properties || typeof properties === "object" && !Array.isArray(properties) && Object.keys(properties).length === 0;
|
|
1311
|
+
return noProperties && schema.additionalProperties === false;
|
|
1312
|
+
}
|
|
1313
|
+
function validatePluginConfig(params) {
|
|
1314
|
+
if (!params.schema || isPlaceholderConfigSchema(params.schema)) {
|
|
1315
|
+
return { ok: true, value: params.value };
|
|
1316
|
+
}
|
|
1317
|
+
const cacheKey = params.cacheKey ?? JSON.stringify(params.schema);
|
|
1318
|
+
const result = validateJsonSchemaValue({
|
|
1319
|
+
schema: params.schema,
|
|
1320
|
+
cacheKey,
|
|
1321
|
+
value: params.value ?? {}
|
|
1322
|
+
});
|
|
1323
|
+
if (result.ok) {
|
|
1324
|
+
return { ok: true, value: params.value };
|
|
1325
|
+
}
|
|
1326
|
+
return { ok: false, errors: result.errors };
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1255
1329
|
// src/plugins/registry.ts
|
|
1256
|
-
import
|
|
1330
|
+
import path5 from "path";
|
|
1257
1331
|
import { expandHome as expandHome2 } from "@nextclaw/core";
|
|
1258
1332
|
|
|
1333
|
+
// src/plugins/plugin-capability-registration.ts
|
|
1334
|
+
function ensureUniqueNames(params) {
|
|
1335
|
+
const accepted = [];
|
|
1336
|
+
for (const rawName of params.names) {
|
|
1337
|
+
const name = rawName.trim();
|
|
1338
|
+
if (!name) {
|
|
1339
|
+
continue;
|
|
1340
|
+
}
|
|
1341
|
+
if (params.reserved.has(name)) {
|
|
1342
|
+
params.diagnostics.push({
|
|
1343
|
+
level: "error",
|
|
1344
|
+
pluginId: params.pluginId,
|
|
1345
|
+
source: params.source,
|
|
1346
|
+
message: `${params.kind} already registered by core: ${name}`
|
|
1347
|
+
});
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
const owner = params.owners.get(name);
|
|
1351
|
+
if (owner && owner !== params.pluginId) {
|
|
1352
|
+
params.diagnostics.push({
|
|
1353
|
+
level: "error",
|
|
1354
|
+
pluginId: params.pluginId,
|
|
1355
|
+
source: params.source,
|
|
1356
|
+
message: `${params.kind} already registered: ${name} (${owner})`
|
|
1357
|
+
});
|
|
1358
|
+
continue;
|
|
1359
|
+
}
|
|
1360
|
+
params.owners.set(name, params.pluginId);
|
|
1361
|
+
accepted.push(name);
|
|
1362
|
+
}
|
|
1363
|
+
return accepted;
|
|
1364
|
+
}
|
|
1365
|
+
function registerPluginEngine(params) {
|
|
1366
|
+
const accepted = ensureUniqueNames({
|
|
1367
|
+
names: [params.kind],
|
|
1368
|
+
pluginId: params.pluginId,
|
|
1369
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1370
|
+
source: params.source,
|
|
1371
|
+
owners: params.runtime.engineKindOwners,
|
|
1372
|
+
reserved: params.runtime.reservedEngineKinds,
|
|
1373
|
+
kind: "engine"
|
|
1374
|
+
});
|
|
1375
|
+
if (accepted.length === 0) {
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
params.runtime.registry.engines.push({
|
|
1379
|
+
pluginId: params.pluginId,
|
|
1380
|
+
kind: accepted[0],
|
|
1381
|
+
factory: params.factory,
|
|
1382
|
+
source: params.source
|
|
1383
|
+
});
|
|
1384
|
+
params.record.engineKinds.push(accepted[0]);
|
|
1385
|
+
}
|
|
1386
|
+
function registerPluginNcpAgentRuntime(params) {
|
|
1387
|
+
const rawKind = params.registration.kind?.trim().toLowerCase();
|
|
1388
|
+
if (!rawKind) {
|
|
1389
|
+
params.runtime.registry.diagnostics.push({
|
|
1390
|
+
level: "error",
|
|
1391
|
+
pluginId: params.pluginId,
|
|
1392
|
+
source: params.source,
|
|
1393
|
+
message: "registerNcpAgentRuntime requires registration.kind"
|
|
1394
|
+
});
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
const accepted = ensureUniqueNames({
|
|
1398
|
+
names: [rawKind],
|
|
1399
|
+
pluginId: params.pluginId,
|
|
1400
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1401
|
+
source: params.source,
|
|
1402
|
+
owners: params.runtime.ncpAgentRuntimeKindOwners,
|
|
1403
|
+
reserved: params.runtime.reservedNcpAgentRuntimeKinds,
|
|
1404
|
+
kind: "ncp-runtime"
|
|
1405
|
+
});
|
|
1406
|
+
if (accepted.length === 0) {
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
params.runtime.registry.ncpAgentRuntimes.push({
|
|
1410
|
+
pluginId: params.pluginId,
|
|
1411
|
+
kind: accepted[0],
|
|
1412
|
+
label: params.registration.label?.trim() || accepted[0],
|
|
1413
|
+
createRuntime: params.registration.createRuntime,
|
|
1414
|
+
source: params.source
|
|
1415
|
+
});
|
|
1416
|
+
params.record.ncpAgentRuntimeKinds.push(accepted[0]);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1259
1419
|
// src/plugins/runtime.ts
|
|
1260
1420
|
import { getPackageVersion } from "@nextclaw/core";
|
|
1261
1421
|
import { MemoryGetTool, MemorySearchTool } from "@nextclaw/core";
|
|
@@ -1318,37 +1478,6 @@ function buildPluginLogger(base, pluginId) {
|
|
|
1318
1478
|
debug: base.debug ? (message) => base.debug?.(withPrefix(message)) : void 0
|
|
1319
1479
|
};
|
|
1320
1480
|
}
|
|
1321
|
-
function ensureUniqueNames(params) {
|
|
1322
|
-
const accepted = [];
|
|
1323
|
-
for (const rawName of params.names) {
|
|
1324
|
-
const name = rawName.trim();
|
|
1325
|
-
if (!name) {
|
|
1326
|
-
continue;
|
|
1327
|
-
}
|
|
1328
|
-
if (params.reserved.has(name)) {
|
|
1329
|
-
params.diagnostics.push({
|
|
1330
|
-
level: "error",
|
|
1331
|
-
pluginId: params.pluginId,
|
|
1332
|
-
source: params.source,
|
|
1333
|
-
message: `${params.kind} already registered by core: ${name}`
|
|
1334
|
-
});
|
|
1335
|
-
continue;
|
|
1336
|
-
}
|
|
1337
|
-
const owner = params.owners.get(name);
|
|
1338
|
-
if (owner && owner !== params.pluginId) {
|
|
1339
|
-
params.diagnostics.push({
|
|
1340
|
-
level: "error",
|
|
1341
|
-
pluginId: params.pluginId,
|
|
1342
|
-
source: params.source,
|
|
1343
|
-
message: `${params.kind} already registered: ${name} (${owner})`
|
|
1344
|
-
});
|
|
1345
|
-
continue;
|
|
1346
|
-
}
|
|
1347
|
-
params.owners.set(name, params.pluginId);
|
|
1348
|
-
accepted.push(name);
|
|
1349
|
-
}
|
|
1350
|
-
return accepted;
|
|
1351
|
-
}
|
|
1352
1481
|
function normalizeToolList(value) {
|
|
1353
1482
|
if (!value) {
|
|
1354
1483
|
return [];
|
|
@@ -1372,11 +1501,13 @@ function createPluginRegisterRuntime(params) {
|
|
|
1372
1501
|
channelIdOwners: /* @__PURE__ */ new Map(),
|
|
1373
1502
|
providerIdOwners: /* @__PURE__ */ new Map(),
|
|
1374
1503
|
engineKindOwners: /* @__PURE__ */ new Map(),
|
|
1504
|
+
ncpAgentRuntimeKindOwners: /* @__PURE__ */ new Map(),
|
|
1375
1505
|
resolvedToolNames: /* @__PURE__ */ new Set(),
|
|
1376
1506
|
reservedToolNames: params.reservedToolNames,
|
|
1377
1507
|
reservedChannelIds: params.reservedChannelIds,
|
|
1378
1508
|
reservedProviderIds: params.reservedProviderIds,
|
|
1379
|
-
reservedEngineKinds: params.reservedEngineKinds
|
|
1509
|
+
reservedEngineKinds: params.reservedEngineKinds,
|
|
1510
|
+
reservedNcpAgentRuntimeKinds: params.reservedNcpAgentRuntimeKinds
|
|
1380
1511
|
};
|
|
1381
1512
|
}
|
|
1382
1513
|
function registerPluginTool(params) {
|
|
@@ -1558,27 +1689,6 @@ function registerPluginProvider(params) {
|
|
|
1558
1689
|
});
|
|
1559
1690
|
params.record.providerIds.push(accepted[0]);
|
|
1560
1691
|
}
|
|
1561
|
-
function registerPluginEngine(params) {
|
|
1562
|
-
const accepted = ensureUniqueNames({
|
|
1563
|
-
names: [params.kind],
|
|
1564
|
-
pluginId: params.pluginId,
|
|
1565
|
-
diagnostics: params.runtime.registry.diagnostics,
|
|
1566
|
-
source: params.source,
|
|
1567
|
-
owners: params.runtime.engineKindOwners,
|
|
1568
|
-
reserved: params.runtime.reservedEngineKinds,
|
|
1569
|
-
kind: "engine"
|
|
1570
|
-
});
|
|
1571
|
-
if (accepted.length === 0) {
|
|
1572
|
-
return;
|
|
1573
|
-
}
|
|
1574
|
-
params.runtime.registry.engines.push({
|
|
1575
|
-
pluginId: params.pluginId,
|
|
1576
|
-
kind: accepted[0],
|
|
1577
|
-
factory: params.factory,
|
|
1578
|
-
source: params.source
|
|
1579
|
-
});
|
|
1580
|
-
params.record.engineKinds.push(accepted[0]);
|
|
1581
|
-
}
|
|
1582
1692
|
function registerPluginWithApi(params) {
|
|
1583
1693
|
const pluginRuntime = createPluginRuntime({ workspace: params.runtime.workspaceDir, config: params.runtime.config });
|
|
1584
1694
|
const pluginLogger = buildPluginLogger(params.runtime.logger, params.pluginId);
|
|
@@ -1649,6 +1759,15 @@ function registerPluginWithApi(params) {
|
|
|
1649
1759
|
factory
|
|
1650
1760
|
});
|
|
1651
1761
|
},
|
|
1762
|
+
registerNcpAgentRuntime: (registration) => {
|
|
1763
|
+
registerPluginNcpAgentRuntime({
|
|
1764
|
+
runtime: params.runtime,
|
|
1765
|
+
record: params.record,
|
|
1766
|
+
pluginId: params.pluginId,
|
|
1767
|
+
source: params.source,
|
|
1768
|
+
registration
|
|
1769
|
+
});
|
|
1770
|
+
},
|
|
1652
1771
|
registerHook: () => pushUnsupported("registerHook"),
|
|
1653
1772
|
registerGatewayMethod: () => pushUnsupported("registerGatewayMethod"),
|
|
1654
1773
|
registerCli: () => pushUnsupported("registerCli"),
|
|
@@ -1661,10 +1780,10 @@ function registerPluginWithApi(params) {
|
|
|
1661
1780
|
if (!trimmed) {
|
|
1662
1781
|
return params.rootDir;
|
|
1663
1782
|
}
|
|
1664
|
-
if (
|
|
1665
|
-
return
|
|
1783
|
+
if (path5.isAbsolute(trimmed)) {
|
|
1784
|
+
return path5.resolve(expandHome2(trimmed));
|
|
1666
1785
|
}
|
|
1667
|
-
return
|
|
1786
|
+
return path5.resolve(params.rootDir, trimmed);
|
|
1668
1787
|
}
|
|
1669
1788
|
};
|
|
1670
1789
|
try {
|
|
@@ -1705,35 +1824,35 @@ var BUNDLED_CHANNEL_PLUGIN_PACKAGES = [
|
|
|
1705
1824
|
"@nextclaw/channel-plugin-qq"
|
|
1706
1825
|
];
|
|
1707
1826
|
function resolvePackageRootFromEntry(entryFile) {
|
|
1708
|
-
let cursor =
|
|
1827
|
+
let cursor = path6.dirname(entryFile);
|
|
1709
1828
|
for (let i = 0; i < 8; i += 1) {
|
|
1710
|
-
const candidate =
|
|
1829
|
+
const candidate = path6.join(cursor, "package.json");
|
|
1711
1830
|
if (fs5.existsSync(candidate)) {
|
|
1712
1831
|
return cursor;
|
|
1713
1832
|
}
|
|
1714
|
-
const parent =
|
|
1833
|
+
const parent = path6.dirname(cursor);
|
|
1715
1834
|
if (parent === cursor) {
|
|
1716
1835
|
break;
|
|
1717
1836
|
}
|
|
1718
1837
|
cursor = parent;
|
|
1719
1838
|
}
|
|
1720
|
-
return
|
|
1839
|
+
return path6.dirname(entryFile);
|
|
1721
1840
|
}
|
|
1722
1841
|
function resolvePluginSdkAliasFile(params) {
|
|
1723
1842
|
try {
|
|
1724
1843
|
const modulePath = fileURLToPath(import.meta.url);
|
|
1725
1844
|
const isProduction = process.env.NODE_ENV === "production";
|
|
1726
|
-
let cursor =
|
|
1845
|
+
let cursor = path6.dirname(modulePath);
|
|
1727
1846
|
for (let i = 0; i < 6; i += 1) {
|
|
1728
|
-
const srcCandidate =
|
|
1729
|
-
const distCandidate =
|
|
1847
|
+
const srcCandidate = path6.join(cursor, "src", "plugin-sdk", params.srcFile);
|
|
1848
|
+
const distCandidate = path6.join(cursor, "dist", "plugin-sdk", params.distFile);
|
|
1730
1849
|
const candidates = isProduction ? [distCandidate, srcCandidate] : [srcCandidate, distCandidate];
|
|
1731
1850
|
for (const candidate of candidates) {
|
|
1732
1851
|
if (fs5.existsSync(candidate)) {
|
|
1733
1852
|
return candidate;
|
|
1734
1853
|
}
|
|
1735
1854
|
}
|
|
1736
|
-
const parent =
|
|
1855
|
+
const parent = path6.dirname(cursor);
|
|
1737
1856
|
if (parent === cursor) {
|
|
1738
1857
|
break;
|
|
1739
1858
|
}
|
|
@@ -1747,6 +1866,46 @@ function resolvePluginSdkAliasFile(params) {
|
|
|
1747
1866
|
function resolvePluginSdkAlias() {
|
|
1748
1867
|
return resolvePluginSdkAliasFile({ srcFile: "index.ts", distFile: "index.js" });
|
|
1749
1868
|
}
|
|
1869
|
+
function buildScopedPackageAliases(scope) {
|
|
1870
|
+
const aliases = {};
|
|
1871
|
+
const require2 = createRequire(import.meta.url);
|
|
1872
|
+
let cursor = path6.dirname(fileURLToPath(import.meta.url));
|
|
1873
|
+
for (let i = 0; i < 8; i += 1) {
|
|
1874
|
+
const scopeDir = path6.join(cursor, "node_modules", scope);
|
|
1875
|
+
if (fs5.existsSync(scopeDir)) {
|
|
1876
|
+
let entries = [];
|
|
1877
|
+
try {
|
|
1878
|
+
entries = fs5.readdirSync(scopeDir, { withFileTypes: true });
|
|
1879
|
+
} catch {
|
|
1880
|
+
entries = [];
|
|
1881
|
+
}
|
|
1882
|
+
for (const entry of entries) {
|
|
1883
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
const packageName = `${scope}/${entry.name}`;
|
|
1887
|
+
try {
|
|
1888
|
+
aliases[packageName] = require2.resolve(packageName);
|
|
1889
|
+
} catch {
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
const parent = path6.dirname(cursor);
|
|
1894
|
+
if (parent === cursor) {
|
|
1895
|
+
break;
|
|
1896
|
+
}
|
|
1897
|
+
cursor = parent;
|
|
1898
|
+
}
|
|
1899
|
+
return aliases;
|
|
1900
|
+
}
|
|
1901
|
+
function buildPluginLoaderAliases() {
|
|
1902
|
+
const aliases = buildScopedPackageAliases("@nextclaw");
|
|
1903
|
+
const pluginSdkAlias = resolvePluginSdkAlias();
|
|
1904
|
+
if (pluginSdkAlias) {
|
|
1905
|
+
aliases["openclaw/plugin-sdk"] = pluginSdkAlias;
|
|
1906
|
+
}
|
|
1907
|
+
return aliases;
|
|
1908
|
+
}
|
|
1750
1909
|
function resolvePluginModuleExport(moduleExport) {
|
|
1751
1910
|
const resolved = moduleExport && typeof moduleExport === "object" && "default" in moduleExport ? moduleExport.default : moduleExport;
|
|
1752
1911
|
if (typeof resolved === "function") {
|
|
@@ -1763,55 +1922,6 @@ function resolvePluginModuleExport(moduleExport) {
|
|
|
1763
1922
|
}
|
|
1764
1923
|
return {};
|
|
1765
1924
|
}
|
|
1766
|
-
function createPluginRecord(params) {
|
|
1767
|
-
return {
|
|
1768
|
-
id: params.id,
|
|
1769
|
-
name: params.name ?? params.id,
|
|
1770
|
-
description: params.description,
|
|
1771
|
-
version: params.version,
|
|
1772
|
-
kind: params.kind,
|
|
1773
|
-
source: params.source,
|
|
1774
|
-
origin: params.origin,
|
|
1775
|
-
workspaceDir: params.workspaceDir,
|
|
1776
|
-
enabled: params.enabled,
|
|
1777
|
-
status: params.enabled ? "loaded" : "disabled",
|
|
1778
|
-
toolNames: [],
|
|
1779
|
-
channelIds: [],
|
|
1780
|
-
providerIds: [],
|
|
1781
|
-
engineKinds: [],
|
|
1782
|
-
configSchema: params.configSchema,
|
|
1783
|
-
configUiHints: params.configUiHints,
|
|
1784
|
-
configJsonSchema: params.configJsonSchema
|
|
1785
|
-
};
|
|
1786
|
-
}
|
|
1787
|
-
function isPlaceholderConfigSchema(schema) {
|
|
1788
|
-
if (!schema || typeof schema !== "object") {
|
|
1789
|
-
return false;
|
|
1790
|
-
}
|
|
1791
|
-
const type = schema.type;
|
|
1792
|
-
const isObjectType = type === "object" || Array.isArray(type) && type.includes("object");
|
|
1793
|
-
if (!isObjectType) {
|
|
1794
|
-
return false;
|
|
1795
|
-
}
|
|
1796
|
-
const properties = schema.properties;
|
|
1797
|
-
const noProperties = !properties || typeof properties === "object" && !Array.isArray(properties) && Object.keys(properties).length === 0;
|
|
1798
|
-
return noProperties && schema.additionalProperties === false;
|
|
1799
|
-
}
|
|
1800
|
-
function validatePluginConfig(params) {
|
|
1801
|
-
if (!params.schema || isPlaceholderConfigSchema(params.schema)) {
|
|
1802
|
-
return { ok: true, value: params.value };
|
|
1803
|
-
}
|
|
1804
|
-
const cacheKey = params.cacheKey ?? JSON.stringify(params.schema);
|
|
1805
|
-
const result = validateJsonSchemaValue({
|
|
1806
|
-
schema: params.schema,
|
|
1807
|
-
cacheKey,
|
|
1808
|
-
value: params.value ?? {}
|
|
1809
|
-
});
|
|
1810
|
-
if (result.ok) {
|
|
1811
|
-
return { ok: true, value: params.value };
|
|
1812
|
-
}
|
|
1813
|
-
return { ok: false, errors: result.errors };
|
|
1814
|
-
}
|
|
1815
1925
|
function appendBundledChannelPlugins(params) {
|
|
1816
1926
|
const require2 = createRequire(import.meta.url);
|
|
1817
1927
|
for (const packageName of BUNDLED_CHANNEL_PLUGIN_PACKAGES) {
|
|
@@ -1918,6 +2028,7 @@ function loadOpenClawPlugins(options) {
|
|
|
1918
2028
|
channels: [],
|
|
1919
2029
|
providers: [],
|
|
1920
2030
|
engines: [],
|
|
2031
|
+
ncpAgentRuntimes: [],
|
|
1921
2032
|
diagnostics: [],
|
|
1922
2033
|
resolvedTools: []
|
|
1923
2034
|
};
|
|
@@ -1925,6 +2036,9 @@ function loadOpenClawPlugins(options) {
|
|
|
1925
2036
|
const reservedChannelIds = new Set(options.reservedChannelIds ?? []);
|
|
1926
2037
|
const reservedProviderIds = new Set(options.reservedProviderIds ?? []);
|
|
1927
2038
|
const reservedEngineKinds = new Set((options.reservedEngineKinds ?? ["native"]).map((entry) => entry.toLowerCase()));
|
|
2039
|
+
const reservedNcpAgentRuntimeKinds = new Set(
|
|
2040
|
+
(options.reservedNcpAgentRuntimeKinds ?? ["native"]).map((entry) => entry.toLowerCase())
|
|
2041
|
+
);
|
|
1928
2042
|
const registerRuntime = createPluginRegisterRuntime({
|
|
1929
2043
|
config: options.config,
|
|
1930
2044
|
workspaceDir,
|
|
@@ -1933,17 +2047,13 @@ function loadOpenClawPlugins(options) {
|
|
|
1933
2047
|
reservedToolNames,
|
|
1934
2048
|
reservedChannelIds,
|
|
1935
2049
|
reservedProviderIds,
|
|
1936
|
-
reservedEngineKinds
|
|
2050
|
+
reservedEngineKinds,
|
|
2051
|
+
reservedNcpAgentRuntimeKinds
|
|
1937
2052
|
});
|
|
1938
|
-
const pluginSdkAlias = resolvePluginSdkAlias();
|
|
1939
2053
|
const jiti = createJiti(import.meta.url, {
|
|
1940
2054
|
interopDefault: true,
|
|
1941
2055
|
extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs", ".json"],
|
|
1942
|
-
|
|
1943
|
-
alias: {
|
|
1944
|
-
"openclaw/plugin-sdk": pluginSdkAlias
|
|
1945
|
-
}
|
|
1946
|
-
} : {}
|
|
2056
|
+
alias: buildPluginLoaderAliases()
|
|
1947
2057
|
});
|
|
1948
2058
|
appendBundledChannelPlugins({
|
|
1949
2059
|
registry,
|
|
@@ -1959,10 +2069,11 @@ function loadOpenClawPlugins(options) {
|
|
|
1959
2069
|
workspaceDir,
|
|
1960
2070
|
extraPaths: normalized.loadPaths
|
|
1961
2071
|
});
|
|
2072
|
+
const filteredCandidates = filterPluginCandidatesByExcludedRoots(discovery.candidates, options.excludeRoots ?? []);
|
|
1962
2073
|
const manifestRegistry = loadPluginManifestRegistry({
|
|
1963
2074
|
config: options.config,
|
|
1964
2075
|
workspaceDir,
|
|
1965
|
-
candidates:
|
|
2076
|
+
candidates: filteredCandidates,
|
|
1966
2077
|
diagnostics: discovery.diagnostics
|
|
1967
2078
|
});
|
|
1968
2079
|
registry.diagnostics.push(...manifestRegistry.diagnostics);
|
|
@@ -1970,7 +2081,7 @@ function loadOpenClawPlugins(options) {
|
|
|
1970
2081
|
const seenIds = new Map(
|
|
1971
2082
|
registry.plugins.map((entry) => [entry.id, entry.origin])
|
|
1972
2083
|
);
|
|
1973
|
-
for (const candidate of
|
|
2084
|
+
for (const candidate of filteredCandidates) {
|
|
1974
2085
|
const manifest = manifestByRoot.get(candidate.rootDir);
|
|
1975
2086
|
if (!manifest) {
|
|
1976
2087
|
continue;
|
|
@@ -2139,7 +2250,8 @@ function buildPluginStatusReport(params) {
|
|
|
2139
2250
|
reservedToolNames: params.reservedToolNames,
|
|
2140
2251
|
reservedChannelIds: params.reservedChannelIds,
|
|
2141
2252
|
reservedProviderIds: params.reservedProviderIds,
|
|
2142
|
-
reservedEngineKinds: params.reservedEngineKinds
|
|
2253
|
+
reservedEngineKinds: params.reservedEngineKinds,
|
|
2254
|
+
reservedNcpAgentRuntimeKinds: params.reservedNcpAgentRuntimeKinds
|
|
2143
2255
|
});
|
|
2144
2256
|
return {
|
|
2145
2257
|
workspaceDir,
|
|
@@ -2149,7 +2261,9 @@ function buildPluginStatusReport(params) {
|
|
|
2149
2261
|
|
|
2150
2262
|
// src/plugins/uninstall.ts
|
|
2151
2263
|
import fs6 from "fs/promises";
|
|
2152
|
-
import
|
|
2264
|
+
import { existsSync, statSync } from "fs";
|
|
2265
|
+
import path7 from "path";
|
|
2266
|
+
import { getWorkspacePathFromConfig as getWorkspacePathFromConfig3 } from "@nextclaw/core";
|
|
2153
2267
|
function isLinkedPathInstall(record) {
|
|
2154
2268
|
if (!record || record.source !== "path") {
|
|
2155
2269
|
return false;
|
|
@@ -2157,7 +2271,16 @@ function isLinkedPathInstall(record) {
|
|
|
2157
2271
|
if (!record.sourcePath || !record.installPath) {
|
|
2158
2272
|
return true;
|
|
2159
2273
|
}
|
|
2160
|
-
return
|
|
2274
|
+
return path7.resolve(record.sourcePath) === path7.resolve(record.installPath);
|
|
2275
|
+
}
|
|
2276
|
+
function pushUniquePath(targets, candidate) {
|
|
2277
|
+
if (!candidate) {
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
const resolved = path7.resolve(candidate);
|
|
2281
|
+
if (!targets.includes(resolved)) {
|
|
2282
|
+
targets.push(resolved);
|
|
2283
|
+
}
|
|
2161
2284
|
}
|
|
2162
2285
|
function resolveUninstallDirectoryTarget(params) {
|
|
2163
2286
|
if (!params.hasInstall) {
|
|
@@ -2176,11 +2299,30 @@ function resolveUninstallDirectoryTarget(params) {
|
|
|
2176
2299
|
if (!configuredPath) {
|
|
2177
2300
|
return defaultPath;
|
|
2178
2301
|
}
|
|
2179
|
-
if (
|
|
2302
|
+
if (path7.resolve(configuredPath) === path7.resolve(defaultPath)) {
|
|
2180
2303
|
return configuredPath;
|
|
2181
2304
|
}
|
|
2182
2305
|
return defaultPath;
|
|
2183
2306
|
}
|
|
2307
|
+
function resolveUninstallDirectoryTargets(params) {
|
|
2308
|
+
if (!params.hasInstall || isLinkedPathInstall(params.installRecord)) {
|
|
2309
|
+
return [];
|
|
2310
|
+
}
|
|
2311
|
+
const targets = [];
|
|
2312
|
+
pushUniquePath(
|
|
2313
|
+
targets,
|
|
2314
|
+
resolveUninstallDirectoryTarget({
|
|
2315
|
+
pluginId: params.pluginId,
|
|
2316
|
+
hasInstall: params.hasInstall,
|
|
2317
|
+
installRecord: params.installRecord,
|
|
2318
|
+
extensionsDir: params.extensionsDir
|
|
2319
|
+
})
|
|
2320
|
+
);
|
|
2321
|
+
pushUniquePath(targets, params.installRecord?.installPath);
|
|
2322
|
+
const workspaceDir = getWorkspacePathFromConfig3(params.config);
|
|
2323
|
+
pushUniquePath(targets, path7.join(workspaceDir, ".nextclaw", "extensions", params.pluginId));
|
|
2324
|
+
return targets;
|
|
2325
|
+
}
|
|
2184
2326
|
function removePluginFromConfig(config, pluginId) {
|
|
2185
2327
|
const actions = {
|
|
2186
2328
|
entry: false,
|
|
@@ -2213,14 +2355,15 @@ function removePluginFromConfig(config, pluginId) {
|
|
|
2213
2355
|
actions.allowlist = true;
|
|
2214
2356
|
}
|
|
2215
2357
|
let load = pluginsConfig.load;
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
}
|
|
2358
|
+
const configuredLoadPaths = Array.isArray(load?.paths) ? load.paths : [];
|
|
2359
|
+
const nextLoadPaths = configuredLoadPaths.filter((entry) => !matchesPluginLoadPath(entry, pluginId));
|
|
2360
|
+
if (nextLoadPaths.length !== configuredLoadPaths.length) {
|
|
2361
|
+
load = nextLoadPaths.length > 0 ? { ...load, paths: nextLoadPaths } : void 0;
|
|
2362
|
+
actions.loadPath = true;
|
|
2363
|
+
} else if (installRecord?.source === "path" && installRecord.sourcePath && configuredLoadPaths.includes(installRecord.sourcePath)) {
|
|
2364
|
+
const filteredLoadPaths = configuredLoadPaths.filter((entry) => entry !== installRecord.sourcePath);
|
|
2365
|
+
load = filteredLoadPaths.length > 0 ? { ...load, paths: filteredLoadPaths } : void 0;
|
|
2366
|
+
actions.loadPath = true;
|
|
2224
2367
|
}
|
|
2225
2368
|
const nextPlugins = {
|
|
2226
2369
|
...pluginsConfig
|
|
@@ -2253,6 +2396,28 @@ function removePluginFromConfig(config, pluginId) {
|
|
|
2253
2396
|
actions
|
|
2254
2397
|
};
|
|
2255
2398
|
}
|
|
2399
|
+
function matchesPluginLoadPath(rawPath, pluginId) {
|
|
2400
|
+
const normalizedPath = rawPath.trim();
|
|
2401
|
+
if (!normalizedPath) {
|
|
2402
|
+
return false;
|
|
2403
|
+
}
|
|
2404
|
+
const resolvedPath = path7.resolve(normalizedPath);
|
|
2405
|
+
if (!existsSync(resolvedPath)) {
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2408
|
+
const candidateRoot = (() => {
|
|
2409
|
+
try {
|
|
2410
|
+
return statSync(resolvedPath).isDirectory() ? resolvedPath : path7.dirname(resolvedPath);
|
|
2411
|
+
} catch {
|
|
2412
|
+
return null;
|
|
2413
|
+
}
|
|
2414
|
+
})();
|
|
2415
|
+
if (!candidateRoot) {
|
|
2416
|
+
return false;
|
|
2417
|
+
}
|
|
2418
|
+
const manifest = loadPluginManifest(candidateRoot);
|
|
2419
|
+
return manifest.ok && manifest.manifest.id === pluginId;
|
|
2420
|
+
}
|
|
2256
2421
|
async function uninstallPlugin(params) {
|
|
2257
2422
|
const { config, pluginId, deleteFiles = true, extensionsDir } = params;
|
|
2258
2423
|
const hasEntry = pluginId in (config.plugins.entries ?? {});
|
|
@@ -2268,17 +2433,18 @@ async function uninstallPlugin(params) {
|
|
|
2268
2433
|
directory: false
|
|
2269
2434
|
};
|
|
2270
2435
|
const warnings = [];
|
|
2271
|
-
const
|
|
2436
|
+
const deleteTargets = deleteFiles && !isLinked ? resolveUninstallDirectoryTargets({
|
|
2437
|
+
config,
|
|
2272
2438
|
pluginId,
|
|
2273
2439
|
hasInstall,
|
|
2274
2440
|
installRecord,
|
|
2275
2441
|
extensionsDir
|
|
2276
|
-
}) :
|
|
2277
|
-
|
|
2278
|
-
const existed = await fs6.access(deleteTarget).then(() => true).catch(() => false)
|
|
2442
|
+
}) : [];
|
|
2443
|
+
for (const deleteTarget of deleteTargets) {
|
|
2444
|
+
const existed = await fs6.access(deleteTarget).then(() => true).catch(() => false);
|
|
2279
2445
|
try {
|
|
2280
2446
|
await fs6.rm(deleteTarget, { recursive: true, force: true });
|
|
2281
|
-
actions.directory = existed;
|
|
2447
|
+
actions.directory = actions.directory || existed;
|
|
2282
2448
|
} catch (error) {
|
|
2283
2449
|
warnings.push(
|
|
2284
2450
|
`Failed to remove plugin directory ${deleteTarget}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -2301,6 +2467,7 @@ export {
|
|
|
2301
2467
|
addPluginLoadPath,
|
|
2302
2468
|
buildChannelConfigSchema,
|
|
2303
2469
|
buildOauthProviderAuthResult,
|
|
2470
|
+
buildPluginLoaderAliases,
|
|
2304
2471
|
buildPluginStatusReport,
|
|
2305
2472
|
createNextclawBuiltinChannelPlugin,
|
|
2306
2473
|
createPluginRegisterRuntime,
|
|
@@ -2332,6 +2499,7 @@ export {
|
|
|
2332
2499
|
resolvePluginInstallDir,
|
|
2333
2500
|
resolvePluginManifestPath,
|
|
2334
2501
|
resolveUninstallDirectoryTarget,
|
|
2502
|
+
resolveUninstallDirectoryTargets,
|
|
2335
2503
|
setPluginRuntimeBridge,
|
|
2336
2504
|
sleep,
|
|
2337
2505
|
startPluginChannelGateways,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/openclaw-compat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OpenClaw plugin compatibility layer for NextClaw.",
|
|
6
6
|
"type": "module",
|
|
@@ -19,18 +19,20 @@
|
|
|
19
19
|
"jiti": "^1.21.7",
|
|
20
20
|
"jszip": "^3.10.1",
|
|
21
21
|
"tar": "^7.4.3",
|
|
22
|
-
"@nextclaw/channel-plugin-dingtalk": "0.
|
|
23
|
-
"@nextclaw/channel-plugin-discord": "0.
|
|
24
|
-
"@nextclaw/channel-plugin-email": "0.
|
|
25
|
-
"@nextclaw/channel-plugin-feishu": "0.
|
|
26
|
-
"@nextclaw/channel-plugin-mochat": "0.
|
|
27
|
-
"@nextclaw/channel-plugin-
|
|
28
|
-
"@nextclaw/channel-plugin-
|
|
29
|
-
"@nextclaw/channel-plugin-telegram": "0.
|
|
30
|
-
"@nextclaw/channel-plugin-wecom": "0.
|
|
31
|
-
"@nextclaw/channel-plugin-whatsapp": "0.
|
|
32
|
-
"@nextclaw/channel-runtime": "0.
|
|
33
|
-
"@nextclaw/core": "0.
|
|
22
|
+
"@nextclaw/channel-plugin-dingtalk": "0.2.0",
|
|
23
|
+
"@nextclaw/channel-plugin-discord": "0.2.0",
|
|
24
|
+
"@nextclaw/channel-plugin-email": "0.2.0",
|
|
25
|
+
"@nextclaw/channel-plugin-feishu": "0.2.0",
|
|
26
|
+
"@nextclaw/channel-plugin-mochat": "0.2.0",
|
|
27
|
+
"@nextclaw/channel-plugin-slack": "0.2.0",
|
|
28
|
+
"@nextclaw/channel-plugin-qq": "0.2.0",
|
|
29
|
+
"@nextclaw/channel-plugin-telegram": "0.2.0",
|
|
30
|
+
"@nextclaw/channel-plugin-wecom": "0.2.0",
|
|
31
|
+
"@nextclaw/channel-plugin-whatsapp": "0.2.0",
|
|
32
|
+
"@nextclaw/channel-runtime": "0.2.0",
|
|
33
|
+
"@nextclaw/core": "0.9.0",
|
|
34
|
+
"@nextclaw/ncp": "0.3.0",
|
|
35
|
+
"@nextclaw/ncp-toolkit": "0.4.0"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
38
|
"@types/node": "^20.17.6",
|