@nextclaw/openclaw-compat 0.1.6 → 0.1.7
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 +38 -1
- package/dist/index.js +437 -567
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -520,6 +520,43 @@ declare function createPluginRuntime(params: {
|
|
|
520
520
|
config?: Config;
|
|
521
521
|
}): PluginRuntime;
|
|
522
522
|
|
|
523
|
+
type PluginRegisterRuntime = {
|
|
524
|
+
config: Config;
|
|
525
|
+
workspaceDir: string;
|
|
526
|
+
logger: PluginLogger;
|
|
527
|
+
registry: PluginRegistry;
|
|
528
|
+
toolNameOwners: Map<string, string>;
|
|
529
|
+
channelIdOwners: Map<string, string>;
|
|
530
|
+
providerIdOwners: Map<string, string>;
|
|
531
|
+
resolvedToolNames: Set<string>;
|
|
532
|
+
reservedToolNames: Set<string>;
|
|
533
|
+
reservedChannelIds: Set<string>;
|
|
534
|
+
reservedProviderIds: Set<string>;
|
|
535
|
+
};
|
|
536
|
+
declare function createPluginRegisterRuntime(params: {
|
|
537
|
+
config: Config;
|
|
538
|
+
workspaceDir: string;
|
|
539
|
+
logger: PluginLogger;
|
|
540
|
+
registry: PluginRegistry;
|
|
541
|
+
reservedToolNames: Set<string>;
|
|
542
|
+
reservedChannelIds: Set<string>;
|
|
543
|
+
reservedProviderIds: Set<string>;
|
|
544
|
+
}): PluginRegisterRuntime;
|
|
545
|
+
declare function registerPluginWithApi(params: {
|
|
546
|
+
runtime: PluginRegisterRuntime;
|
|
547
|
+
record: PluginRecord;
|
|
548
|
+
pluginId: string;
|
|
549
|
+
source: string;
|
|
550
|
+
rootDir: string;
|
|
551
|
+
register: (api: OpenClawPluginApi) => void | Promise<void>;
|
|
552
|
+
pluginConfig?: Record<string, unknown>;
|
|
553
|
+
}): {
|
|
554
|
+
ok: true;
|
|
555
|
+
} | {
|
|
556
|
+
ok: false;
|
|
557
|
+
error: string;
|
|
558
|
+
};
|
|
559
|
+
|
|
523
560
|
declare function validateJsonSchemaValue(params: {
|
|
524
561
|
schema: Record<string, unknown>;
|
|
525
562
|
cacheKey: string;
|
|
@@ -578,4 +615,4 @@ declare function uninstallPlugin(params: {
|
|
|
578
615
|
extensionsDir?: string;
|
|
579
616
|
}): Promise<UninstallPluginResult>;
|
|
580
617
|
|
|
581
|
-
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 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 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 PluginRegistry, type PluginReplyDispatchParams, type PluginRuntime, type PluginRuntimeBridge, type PluginStatusReport, type PluginToolRegistration, type PluginUiMetadata, type UninstallActions, type UninstallPluginResult, type _CompatOnly, __nextclawPluginSdkCompat, addPluginLoadPath, buildChannelConfigSchema, buildOauthProviderAuthResult, buildPluginStatusReport, createPluginRuntime, disablePluginInConfig, discoverOpenClawPlugins, emptyPluginConfigSchema, enablePluginInConfig, getPackageManifestMetadata, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromArchive, installPluginFromDir, installPluginFromFile, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, loadPluginManifestRegistry, loadPluginUiMetadata, normalizeAccountId, normalizePluginHttpPath, normalizePluginsConfig, recordPluginInstall, removePluginFromConfig, resolveEnableState, resolvePluginChannelMessageToolHints, resolvePluginInstallDir, resolvePluginManifestPath, resolveUninstallDirectoryTarget, setPluginRuntimeBridge, sleep, startPluginChannelGateways, stopPluginChannelGateways, toPluginUiMetadata, uninstallPlugin, validateJsonSchemaValue };
|
|
618
|
+
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 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 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, 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 };
|
package/dist/index.js
CHANGED
|
@@ -1057,11 +1057,10 @@ async function installPluginFromPath(params) {
|
|
|
1057
1057
|
|
|
1058
1058
|
// src/plugins/loader.ts
|
|
1059
1059
|
import fs5 from "fs";
|
|
1060
|
-
import
|
|
1060
|
+
import path5 from "path";
|
|
1061
1061
|
import { fileURLToPath } from "url";
|
|
1062
1062
|
import createJitiImport from "jiti";
|
|
1063
1063
|
import { getWorkspacePathFromConfig } from "@nextclaw/core";
|
|
1064
|
-
import { expandHome as expandHome2 } from "@nextclaw/core";
|
|
1065
1064
|
|
|
1066
1065
|
// src/plugins/manifest-registry.ts
|
|
1067
1066
|
import fs4 from "fs";
|
|
@@ -1208,58 +1207,6 @@ function loadPluginUiMetadata(params) {
|
|
|
1208
1207
|
return toPluginUiMetadata(registry.plugins);
|
|
1209
1208
|
}
|
|
1210
1209
|
|
|
1211
|
-
// src/plugins/runtime.ts
|
|
1212
|
-
import { getPackageVersion } from "@nextclaw/core";
|
|
1213
|
-
import { MemoryGetTool, MemorySearchTool } from "@nextclaw/core";
|
|
1214
|
-
var bridge = {};
|
|
1215
|
-
function setPluginRuntimeBridge(next) {
|
|
1216
|
-
bridge = next ?? {};
|
|
1217
|
-
}
|
|
1218
|
-
function toPluginTool(tool) {
|
|
1219
|
-
return {
|
|
1220
|
-
name: tool.name,
|
|
1221
|
-
description: tool.description,
|
|
1222
|
-
parameters: tool.parameters,
|
|
1223
|
-
execute: (params) => tool.execute(params)
|
|
1224
|
-
};
|
|
1225
|
-
}
|
|
1226
|
-
function loadConfigWithFallback(config) {
|
|
1227
|
-
if (bridge.loadConfig) {
|
|
1228
|
-
return bridge.loadConfig();
|
|
1229
|
-
}
|
|
1230
|
-
return config ?? {};
|
|
1231
|
-
}
|
|
1232
|
-
async function writeConfigWithFallback(next) {
|
|
1233
|
-
if (!bridge.writeConfigFile) {
|
|
1234
|
-
throw new Error("plugin runtime config.writeConfigFile is unavailable outside gateway runtime");
|
|
1235
|
-
}
|
|
1236
|
-
await bridge.writeConfigFile(next);
|
|
1237
|
-
}
|
|
1238
|
-
async function dispatchReplyWithFallback(params) {
|
|
1239
|
-
if (!bridge.dispatchReplyWithBufferedBlockDispatcher) {
|
|
1240
|
-
throw new Error("plugin runtime channel.reply dispatcher is unavailable outside gateway runtime");
|
|
1241
|
-
}
|
|
1242
|
-
await bridge.dispatchReplyWithBufferedBlockDispatcher(params);
|
|
1243
|
-
}
|
|
1244
|
-
function createPluginRuntime(params) {
|
|
1245
|
-
return {
|
|
1246
|
-
version: getPackageVersion(),
|
|
1247
|
-
config: {
|
|
1248
|
-
loadConfig: () => loadConfigWithFallback(params.config),
|
|
1249
|
-
writeConfigFile: async (next) => writeConfigWithFallback(next)
|
|
1250
|
-
},
|
|
1251
|
-
tools: {
|
|
1252
|
-
createMemorySearchTool: () => toPluginTool(new MemorySearchTool(params.workspace)),
|
|
1253
|
-
createMemoryGetTool: () => toPluginTool(new MemoryGetTool(params.workspace))
|
|
1254
|
-
},
|
|
1255
|
-
channel: {
|
|
1256
|
-
reply: {
|
|
1257
|
-
dispatchReplyWithBufferedBlockDispatcher: async (dispatchParams) => dispatchReplyWithFallback(dispatchParams)
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
1210
|
// src/plugins/schema-validator.ts
|
|
1264
1211
|
import AjvPkg from "ajv";
|
|
1265
1212
|
var AjvCtor = AjvPkg;
|
|
@@ -1274,9 +1221,9 @@ function formatAjvErrors(errors) {
|
|
|
1274
1221
|
return ["invalid config"];
|
|
1275
1222
|
}
|
|
1276
1223
|
return errors.map((error) => {
|
|
1277
|
-
const
|
|
1224
|
+
const path7 = error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>";
|
|
1278
1225
|
const message = error.message ?? "invalid";
|
|
1279
|
-
return `${
|
|
1226
|
+
return `${path7}: ${message}`;
|
|
1280
1227
|
});
|
|
1281
1228
|
}
|
|
1282
1229
|
function validateJsonSchemaValue(params) {
|
|
@@ -1419,6 +1366,395 @@ function listBundledChannelPluginDefinitions() {
|
|
|
1419
1366
|
}
|
|
1420
1367
|
var BUNDLED_CHANNEL_PLUGIN_IDS = BUNDLED_CHANNEL_PLUGINS.map((plugin10) => plugin10.id).filter((id) => typeof id === "string" && id.trim().length > 0);
|
|
1421
1368
|
|
|
1369
|
+
// src/plugins/registry.ts
|
|
1370
|
+
import path4 from "path";
|
|
1371
|
+
import { expandHome as expandHome2 } from "@nextclaw/core";
|
|
1372
|
+
|
|
1373
|
+
// src/plugins/runtime.ts
|
|
1374
|
+
import { getPackageVersion } from "@nextclaw/core";
|
|
1375
|
+
import { MemoryGetTool, MemorySearchTool } from "@nextclaw/core";
|
|
1376
|
+
var bridge = {};
|
|
1377
|
+
function setPluginRuntimeBridge(next) {
|
|
1378
|
+
bridge = next ?? {};
|
|
1379
|
+
}
|
|
1380
|
+
function toPluginTool(tool) {
|
|
1381
|
+
return {
|
|
1382
|
+
name: tool.name,
|
|
1383
|
+
description: tool.description,
|
|
1384
|
+
parameters: tool.parameters,
|
|
1385
|
+
execute: (params) => tool.execute(params)
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
function loadConfigWithFallback(config) {
|
|
1389
|
+
if (bridge.loadConfig) {
|
|
1390
|
+
return bridge.loadConfig();
|
|
1391
|
+
}
|
|
1392
|
+
return config ?? {};
|
|
1393
|
+
}
|
|
1394
|
+
async function writeConfigWithFallback(next) {
|
|
1395
|
+
if (!bridge.writeConfigFile) {
|
|
1396
|
+
throw new Error("plugin runtime config.writeConfigFile is unavailable outside gateway runtime");
|
|
1397
|
+
}
|
|
1398
|
+
await bridge.writeConfigFile(next);
|
|
1399
|
+
}
|
|
1400
|
+
async function dispatchReplyWithFallback(params) {
|
|
1401
|
+
if (!bridge.dispatchReplyWithBufferedBlockDispatcher) {
|
|
1402
|
+
throw new Error("plugin runtime channel.reply dispatcher is unavailable outside gateway runtime");
|
|
1403
|
+
}
|
|
1404
|
+
await bridge.dispatchReplyWithBufferedBlockDispatcher(params);
|
|
1405
|
+
}
|
|
1406
|
+
function createPluginRuntime(params) {
|
|
1407
|
+
return {
|
|
1408
|
+
version: getPackageVersion(),
|
|
1409
|
+
config: {
|
|
1410
|
+
loadConfig: () => loadConfigWithFallback(params.config),
|
|
1411
|
+
writeConfigFile: async (next) => writeConfigWithFallback(next)
|
|
1412
|
+
},
|
|
1413
|
+
tools: {
|
|
1414
|
+
createMemorySearchTool: () => toPluginTool(new MemorySearchTool(params.workspace)),
|
|
1415
|
+
createMemoryGetTool: () => toPluginTool(new MemoryGetTool(params.workspace))
|
|
1416
|
+
},
|
|
1417
|
+
channel: {
|
|
1418
|
+
reply: {
|
|
1419
|
+
dispatchReplyWithBufferedBlockDispatcher: async (dispatchParams) => dispatchReplyWithFallback(dispatchParams)
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// src/plugins/registry.ts
|
|
1426
|
+
function buildPluginLogger(base, pluginId) {
|
|
1427
|
+
const withPrefix = (message) => `[plugins:${pluginId}] ${message}`;
|
|
1428
|
+
return {
|
|
1429
|
+
info: (message) => base.info(withPrefix(message)),
|
|
1430
|
+
warn: (message) => base.warn(withPrefix(message)),
|
|
1431
|
+
error: (message) => base.error(withPrefix(message)),
|
|
1432
|
+
debug: base.debug ? (message) => base.debug?.(withPrefix(message)) : void 0
|
|
1433
|
+
};
|
|
1434
|
+
}
|
|
1435
|
+
function ensureUniqueNames(params) {
|
|
1436
|
+
const accepted = [];
|
|
1437
|
+
for (const rawName of params.names) {
|
|
1438
|
+
const name = rawName.trim();
|
|
1439
|
+
if (!name) {
|
|
1440
|
+
continue;
|
|
1441
|
+
}
|
|
1442
|
+
if (params.reserved.has(name)) {
|
|
1443
|
+
params.diagnostics.push({
|
|
1444
|
+
level: "error",
|
|
1445
|
+
pluginId: params.pluginId,
|
|
1446
|
+
source: params.source,
|
|
1447
|
+
message: `${params.kind} already registered by core: ${name}`
|
|
1448
|
+
});
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const owner = params.owners.get(name);
|
|
1452
|
+
if (owner && owner !== params.pluginId) {
|
|
1453
|
+
params.diagnostics.push({
|
|
1454
|
+
level: "error",
|
|
1455
|
+
pluginId: params.pluginId,
|
|
1456
|
+
source: params.source,
|
|
1457
|
+
message: `${params.kind} already registered: ${name} (${owner})`
|
|
1458
|
+
});
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
params.owners.set(name, params.pluginId);
|
|
1462
|
+
accepted.push(name);
|
|
1463
|
+
}
|
|
1464
|
+
return accepted;
|
|
1465
|
+
}
|
|
1466
|
+
function normalizeToolList(value) {
|
|
1467
|
+
if (!value) {
|
|
1468
|
+
return [];
|
|
1469
|
+
}
|
|
1470
|
+
const list = Array.isArray(value) ? value : [value];
|
|
1471
|
+
return list.filter((entry) => {
|
|
1472
|
+
if (!entry || typeof entry !== "object") {
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
const candidate = entry;
|
|
1476
|
+
return typeof candidate.name === "string" && candidate.name.trim().length > 0 && candidate.parameters !== void 0 && typeof candidate.execute === "function";
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
function createPluginRegisterRuntime(params) {
|
|
1480
|
+
return {
|
|
1481
|
+
config: params.config,
|
|
1482
|
+
workspaceDir: params.workspaceDir,
|
|
1483
|
+
logger: params.logger,
|
|
1484
|
+
registry: params.registry,
|
|
1485
|
+
toolNameOwners: /* @__PURE__ */ new Map(),
|
|
1486
|
+
channelIdOwners: /* @__PURE__ */ new Map(),
|
|
1487
|
+
providerIdOwners: /* @__PURE__ */ new Map(),
|
|
1488
|
+
resolvedToolNames: /* @__PURE__ */ new Set(),
|
|
1489
|
+
reservedToolNames: params.reservedToolNames,
|
|
1490
|
+
reservedChannelIds: params.reservedChannelIds,
|
|
1491
|
+
reservedProviderIds: params.reservedProviderIds
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
function registerPluginTool(params) {
|
|
1495
|
+
const toolInput = params.tool;
|
|
1496
|
+
const normalizedNames = [];
|
|
1497
|
+
if (Array.isArray(params.opts?.names)) {
|
|
1498
|
+
for (const name of params.opts?.names ?? []) {
|
|
1499
|
+
const trimmed = String(name).trim();
|
|
1500
|
+
if (trimmed) {
|
|
1501
|
+
normalizedNames.push(trimmed);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
} else if (params.opts?.name && String(params.opts.name).trim()) {
|
|
1505
|
+
normalizedNames.push(String(params.opts.name).trim());
|
|
1506
|
+
}
|
|
1507
|
+
if (typeof toolInput !== "function") {
|
|
1508
|
+
const intrinsic = toolInput.name.trim();
|
|
1509
|
+
if (intrinsic) {
|
|
1510
|
+
normalizedNames.push(intrinsic);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
const acceptedNames = ensureUniqueNames({
|
|
1514
|
+
names: normalizedNames,
|
|
1515
|
+
pluginId: params.pluginId,
|
|
1516
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1517
|
+
source: params.source,
|
|
1518
|
+
owners: params.runtime.toolNameOwners,
|
|
1519
|
+
reserved: params.runtime.reservedToolNames,
|
|
1520
|
+
kind: "tool"
|
|
1521
|
+
});
|
|
1522
|
+
if (acceptedNames.length === 0) {
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
const factory = typeof toolInput === "function" ? toolInput : () => toolInput;
|
|
1526
|
+
const registration = {
|
|
1527
|
+
pluginId: params.pluginId,
|
|
1528
|
+
factory,
|
|
1529
|
+
names: acceptedNames,
|
|
1530
|
+
optional: params.opts?.optional === true,
|
|
1531
|
+
source: params.source
|
|
1532
|
+
};
|
|
1533
|
+
params.runtime.registry.tools.push(registration);
|
|
1534
|
+
params.record.toolNames.push(...acceptedNames);
|
|
1535
|
+
if (typeof toolInput === "function") {
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
if (!params.runtime.resolvedToolNames.has(toolInput.name)) {
|
|
1539
|
+
params.runtime.resolvedToolNames.add(toolInput.name);
|
|
1540
|
+
params.runtime.registry.resolvedTools.push(toolInput);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
function registerPluginChannel(params) {
|
|
1544
|
+
const normalizedChannel = params.registration && typeof params.registration === "object" && "plugin" in params.registration ? params.registration.plugin : params.registration;
|
|
1545
|
+
if (!normalizedChannel || typeof normalizedChannel !== "object") {
|
|
1546
|
+
params.runtime.registry.diagnostics.push({
|
|
1547
|
+
level: "error",
|
|
1548
|
+
pluginId: params.pluginId,
|
|
1549
|
+
source: params.source,
|
|
1550
|
+
message: "channel registration missing plugin object"
|
|
1551
|
+
});
|
|
1552
|
+
return;
|
|
1553
|
+
}
|
|
1554
|
+
const channelObj = normalizedChannel;
|
|
1555
|
+
const rawId = typeof channelObj.id === "string" ? channelObj.id : String(channelObj.id ?? "");
|
|
1556
|
+
const accepted = ensureUniqueNames({
|
|
1557
|
+
names: [rawId],
|
|
1558
|
+
pluginId: params.pluginId,
|
|
1559
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1560
|
+
source: params.source,
|
|
1561
|
+
owners: params.runtime.channelIdOwners,
|
|
1562
|
+
reserved: params.runtime.reservedChannelIds,
|
|
1563
|
+
kind: "channel"
|
|
1564
|
+
});
|
|
1565
|
+
if (accepted.length === 0) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
const channelPlugin = normalizedChannel;
|
|
1569
|
+
params.runtime.registry.channels.push({
|
|
1570
|
+
pluginId: params.pluginId,
|
|
1571
|
+
channel: channelPlugin,
|
|
1572
|
+
source: params.source
|
|
1573
|
+
});
|
|
1574
|
+
const channelId = accepted[0];
|
|
1575
|
+
params.record.channelIds.push(channelId);
|
|
1576
|
+
const configSchema = channelPlugin.configSchema;
|
|
1577
|
+
if (configSchema && typeof configSchema === "object") {
|
|
1578
|
+
const schema = configSchema.schema;
|
|
1579
|
+
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
1580
|
+
params.record.configJsonSchema = schema;
|
|
1581
|
+
params.record.configSchema = true;
|
|
1582
|
+
}
|
|
1583
|
+
const uiHints = configSchema.uiHints;
|
|
1584
|
+
if (uiHints && typeof uiHints === "object" && !Array.isArray(uiHints)) {
|
|
1585
|
+
params.record.configUiHints = {
|
|
1586
|
+
...params.record.configUiHints ?? {},
|
|
1587
|
+
...uiHints
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
const pushChannelTools = (value, optional, sourceLabel, resolveValue) => {
|
|
1592
|
+
const previewTools = normalizeToolList(value);
|
|
1593
|
+
if (previewTools.length === 0) {
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
const declaredNames = previewTools.map((tool) => tool.name);
|
|
1597
|
+
const acceptedNames = ensureUniqueNames({
|
|
1598
|
+
names: declaredNames,
|
|
1599
|
+
pluginId: params.pluginId,
|
|
1600
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1601
|
+
source: params.source,
|
|
1602
|
+
owners: params.runtime.toolNameOwners,
|
|
1603
|
+
reserved: params.runtime.reservedToolNames,
|
|
1604
|
+
kind: "tool"
|
|
1605
|
+
});
|
|
1606
|
+
if (acceptedNames.length === 0) {
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
const factory = (ctx) => {
|
|
1610
|
+
const tools = normalizeToolList(resolveValue(ctx));
|
|
1611
|
+
if (tools.length === 0) {
|
|
1612
|
+
return [];
|
|
1613
|
+
}
|
|
1614
|
+
const byName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
1615
|
+
return acceptedNames.map((name) => byName.get(name)).filter(Boolean);
|
|
1616
|
+
};
|
|
1617
|
+
params.runtime.registry.tools.push({
|
|
1618
|
+
pluginId: params.pluginId,
|
|
1619
|
+
factory,
|
|
1620
|
+
names: acceptedNames,
|
|
1621
|
+
optional,
|
|
1622
|
+
source: params.source
|
|
1623
|
+
});
|
|
1624
|
+
params.record.toolNames.push(...acceptedNames);
|
|
1625
|
+
const previewByName = new Map(previewTools.map((tool) => [tool.name, tool]));
|
|
1626
|
+
for (const name of acceptedNames) {
|
|
1627
|
+
const resolvedTool = previewByName.get(name);
|
|
1628
|
+
if (!resolvedTool || params.runtime.resolvedToolNames.has(resolvedTool.name)) {
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
params.runtime.resolvedToolNames.add(resolvedTool.name);
|
|
1632
|
+
params.runtime.registry.resolvedTools.push(resolvedTool);
|
|
1633
|
+
}
|
|
1634
|
+
params.runtime.registry.diagnostics.push({
|
|
1635
|
+
level: "warn",
|
|
1636
|
+
pluginId: params.pluginId,
|
|
1637
|
+
source: params.source,
|
|
1638
|
+
message: `${sourceLabel} registered channel-owned tools: ${acceptedNames.join(", ")}`
|
|
1639
|
+
});
|
|
1640
|
+
};
|
|
1641
|
+
const agentTools = channelPlugin.agentTools;
|
|
1642
|
+
if (typeof agentTools === "function") {
|
|
1643
|
+
pushChannelTools(
|
|
1644
|
+
normalizeToolList(agentTools()),
|
|
1645
|
+
false,
|
|
1646
|
+
`channel "${channelId}"`,
|
|
1647
|
+
() => agentTools()
|
|
1648
|
+
);
|
|
1649
|
+
} else if (agentTools) {
|
|
1650
|
+
pushChannelTools(normalizeToolList(agentTools), false, `channel "${channelId}"`, () => agentTools);
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
function registerPluginProvider(params) {
|
|
1654
|
+
const accepted = ensureUniqueNames({
|
|
1655
|
+
names: [params.provider.id],
|
|
1656
|
+
pluginId: params.pluginId,
|
|
1657
|
+
diagnostics: params.runtime.registry.diagnostics,
|
|
1658
|
+
source: params.source,
|
|
1659
|
+
owners: params.runtime.providerIdOwners,
|
|
1660
|
+
reserved: params.runtime.reservedProviderIds,
|
|
1661
|
+
kind: "provider"
|
|
1662
|
+
});
|
|
1663
|
+
if (accepted.length === 0) {
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
params.runtime.registry.providers.push({
|
|
1667
|
+
pluginId: params.pluginId,
|
|
1668
|
+
provider: params.provider,
|
|
1669
|
+
source: params.source
|
|
1670
|
+
});
|
|
1671
|
+
params.record.providerIds.push(accepted[0]);
|
|
1672
|
+
}
|
|
1673
|
+
function registerPluginWithApi(params) {
|
|
1674
|
+
const pluginRuntime = createPluginRuntime({ workspace: params.runtime.workspaceDir, config: params.runtime.config });
|
|
1675
|
+
const pluginLogger = buildPluginLogger(params.runtime.logger, params.pluginId);
|
|
1676
|
+
const pushUnsupported = (capability) => {
|
|
1677
|
+
params.runtime.registry.diagnostics.push({
|
|
1678
|
+
level: "warn",
|
|
1679
|
+
pluginId: params.pluginId,
|
|
1680
|
+
source: params.source,
|
|
1681
|
+
message: `${capability} is not supported by nextclaw compat layer yet`
|
|
1682
|
+
});
|
|
1683
|
+
pluginLogger.warn(`${capability} is ignored (not supported yet)`);
|
|
1684
|
+
};
|
|
1685
|
+
const api = {
|
|
1686
|
+
id: params.pluginId,
|
|
1687
|
+
name: params.record.name,
|
|
1688
|
+
version: params.record.version,
|
|
1689
|
+
description: params.record.description,
|
|
1690
|
+
source: params.source,
|
|
1691
|
+
config: params.runtime.config,
|
|
1692
|
+
pluginConfig: params.pluginConfig,
|
|
1693
|
+
runtime: pluginRuntime,
|
|
1694
|
+
logger: pluginLogger,
|
|
1695
|
+
registerTool: (tool, opts) => {
|
|
1696
|
+
registerPluginTool({
|
|
1697
|
+
runtime: params.runtime,
|
|
1698
|
+
record: params.record,
|
|
1699
|
+
pluginId: params.pluginId,
|
|
1700
|
+
source: params.source,
|
|
1701
|
+
tool,
|
|
1702
|
+
opts
|
|
1703
|
+
});
|
|
1704
|
+
},
|
|
1705
|
+
registerChannel: (registration) => {
|
|
1706
|
+
registerPluginChannel({
|
|
1707
|
+
runtime: params.runtime,
|
|
1708
|
+
record: params.record,
|
|
1709
|
+
pluginId: params.pluginId,
|
|
1710
|
+
source: params.source,
|
|
1711
|
+
registration
|
|
1712
|
+
});
|
|
1713
|
+
},
|
|
1714
|
+
registerProvider: (provider) => {
|
|
1715
|
+
registerPluginProvider({
|
|
1716
|
+
runtime: params.runtime,
|
|
1717
|
+
record: params.record,
|
|
1718
|
+
pluginId: params.pluginId,
|
|
1719
|
+
source: params.source,
|
|
1720
|
+
provider
|
|
1721
|
+
});
|
|
1722
|
+
},
|
|
1723
|
+
registerHook: () => pushUnsupported("registerHook"),
|
|
1724
|
+
registerGatewayMethod: () => pushUnsupported("registerGatewayMethod"),
|
|
1725
|
+
registerCli: () => pushUnsupported("registerCli"),
|
|
1726
|
+
registerService: () => pushUnsupported("registerService"),
|
|
1727
|
+
registerCommand: () => pushUnsupported("registerCommand"),
|
|
1728
|
+
registerHttpHandler: () => pushUnsupported("registerHttpHandler"),
|
|
1729
|
+
registerHttpRoute: () => pushUnsupported("registerHttpRoute"),
|
|
1730
|
+
resolvePath: (input) => {
|
|
1731
|
+
const trimmed = input.trim();
|
|
1732
|
+
if (!trimmed) {
|
|
1733
|
+
return params.rootDir;
|
|
1734
|
+
}
|
|
1735
|
+
if (path4.isAbsolute(trimmed)) {
|
|
1736
|
+
return path4.resolve(expandHome2(trimmed));
|
|
1737
|
+
}
|
|
1738
|
+
return path4.resolve(params.rootDir, trimmed);
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1741
|
+
try {
|
|
1742
|
+
const result = params.register(api);
|
|
1743
|
+
if (result && typeof result === "object" && "then" in result) {
|
|
1744
|
+
params.runtime.registry.diagnostics.push({
|
|
1745
|
+
level: "warn",
|
|
1746
|
+
pluginId: params.pluginId,
|
|
1747
|
+
source: params.source,
|
|
1748
|
+
message: "plugin register returned a promise; async registration is ignored"
|
|
1749
|
+
});
|
|
1750
|
+
}
|
|
1751
|
+
return { ok: true };
|
|
1752
|
+
} catch (err) {
|
|
1753
|
+
const error = `plugin failed during register: ${String(err)}`;
|
|
1754
|
+
return { ok: false, error };
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1422
1758
|
// src/plugins/loader.ts
|
|
1423
1759
|
var createJiti = createJitiImport;
|
|
1424
1760
|
var defaultLogger2 = {
|
|
@@ -1431,17 +1767,17 @@ function resolvePluginSdkAliasFile(params) {
|
|
|
1431
1767
|
try {
|
|
1432
1768
|
const modulePath = fileURLToPath(import.meta.url);
|
|
1433
1769
|
const isProduction = process.env.NODE_ENV === "production";
|
|
1434
|
-
let cursor =
|
|
1770
|
+
let cursor = path5.dirname(modulePath);
|
|
1435
1771
|
for (let i = 0; i < 6; i += 1) {
|
|
1436
|
-
const srcCandidate =
|
|
1437
|
-
const distCandidate =
|
|
1772
|
+
const srcCandidate = path5.join(cursor, "src", "plugin-sdk", params.srcFile);
|
|
1773
|
+
const distCandidate = path5.join(cursor, "dist", "plugin-sdk", params.distFile);
|
|
1438
1774
|
const candidates = isProduction ? [distCandidate, srcCandidate] : [srcCandidate, distCandidate];
|
|
1439
1775
|
for (const candidate of candidates) {
|
|
1440
1776
|
if (fs5.existsSync(candidate)) {
|
|
1441
1777
|
return candidate;
|
|
1442
1778
|
}
|
|
1443
1779
|
}
|
|
1444
|
-
const parent =
|
|
1780
|
+
const parent = path5.dirname(cursor);
|
|
1445
1781
|
if (parent === cursor) {
|
|
1446
1782
|
break;
|
|
1447
1783
|
}
|
|
@@ -1471,19 +1807,6 @@ function resolvePluginModuleExport(moduleExport) {
|
|
|
1471
1807
|
}
|
|
1472
1808
|
return {};
|
|
1473
1809
|
}
|
|
1474
|
-
function normalizeToolList(value) {
|
|
1475
|
-
if (!value) {
|
|
1476
|
-
return [];
|
|
1477
|
-
}
|
|
1478
|
-
const list = Array.isArray(value) ? value : [value];
|
|
1479
|
-
return list.filter((entry) => {
|
|
1480
|
-
if (!entry || typeof entry !== "object") {
|
|
1481
|
-
return false;
|
|
1482
|
-
}
|
|
1483
|
-
const candidate = entry;
|
|
1484
|
-
return typeof candidate.name === "string" && candidate.name.trim().length > 0 && candidate.parameters !== void 0 && typeof candidate.execute === "function";
|
|
1485
|
-
});
|
|
1486
|
-
}
|
|
1487
1810
|
function createPluginRecord(params) {
|
|
1488
1811
|
return {
|
|
1489
1812
|
id: params.id,
|
|
@@ -1504,46 +1827,6 @@ function createPluginRecord(params) {
|
|
|
1504
1827
|
configJsonSchema: params.configJsonSchema
|
|
1505
1828
|
};
|
|
1506
1829
|
}
|
|
1507
|
-
function buildPluginLogger(base, pluginId) {
|
|
1508
|
-
const withPrefix = (message) => `[plugins:${pluginId}] ${message}`;
|
|
1509
|
-
return {
|
|
1510
|
-
info: (message) => base.info(withPrefix(message)),
|
|
1511
|
-
warn: (message) => base.warn(withPrefix(message)),
|
|
1512
|
-
error: (message) => base.error(withPrefix(message)),
|
|
1513
|
-
debug: base.debug ? (message) => base.debug?.(withPrefix(message)) : void 0
|
|
1514
|
-
};
|
|
1515
|
-
}
|
|
1516
|
-
function ensureUniqueNames(params) {
|
|
1517
|
-
const accepted = [];
|
|
1518
|
-
for (const rawName of params.names) {
|
|
1519
|
-
const name = rawName.trim();
|
|
1520
|
-
if (!name) {
|
|
1521
|
-
continue;
|
|
1522
|
-
}
|
|
1523
|
-
if (params.reserved.has(name)) {
|
|
1524
|
-
params.diagnostics.push({
|
|
1525
|
-
level: "error",
|
|
1526
|
-
pluginId: params.pluginId,
|
|
1527
|
-
source: params.source,
|
|
1528
|
-
message: `${params.kind} already registered by core: ${name}`
|
|
1529
|
-
});
|
|
1530
|
-
continue;
|
|
1531
|
-
}
|
|
1532
|
-
const owner = params.owners.get(name);
|
|
1533
|
-
if (owner && owner !== params.pluginId) {
|
|
1534
|
-
params.diagnostics.push({
|
|
1535
|
-
level: "error",
|
|
1536
|
-
pluginId: params.pluginId,
|
|
1537
|
-
source: params.source,
|
|
1538
|
-
message: `${params.kind} already registered: ${name} (${owner})`
|
|
1539
|
-
});
|
|
1540
|
-
continue;
|
|
1541
|
-
}
|
|
1542
|
-
params.owners.set(name, params.pluginId);
|
|
1543
|
-
accepted.push(name);
|
|
1544
|
-
}
|
|
1545
|
-
return accepted;
|
|
1546
|
-
}
|
|
1547
1830
|
function isPlaceholderConfigSchema(schema) {
|
|
1548
1831
|
if (!schema || typeof schema !== "object") {
|
|
1549
1832
|
return false;
|
|
@@ -1592,7 +1875,7 @@ function appendBundledChannelPlugins(params) {
|
|
|
1592
1875
|
kind: definition.kind,
|
|
1593
1876
|
source,
|
|
1594
1877
|
origin: "bundled",
|
|
1595
|
-
workspaceDir: params.workspaceDir,
|
|
1878
|
+
workspaceDir: params.runtime.workspaceDir,
|
|
1596
1879
|
enabled: true,
|
|
1597
1880
|
configSchema: Boolean(definition.configSchema),
|
|
1598
1881
|
configJsonSchema: definition.configSchema
|
|
@@ -1610,203 +1893,26 @@ function appendBundledChannelPlugins(params) {
|
|
|
1610
1893
|
});
|
|
1611
1894
|
continue;
|
|
1612
1895
|
}
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
level: "warn",
|
|
1618
|
-
pluginId,
|
|
1619
|
-
source,
|
|
1620
|
-
message: `${capability} is not supported by nextclaw compat layer yet`
|
|
1621
|
-
});
|
|
1622
|
-
pluginLogger.warn(`${capability} is ignored (not supported yet)`);
|
|
1623
|
-
};
|
|
1624
|
-
const api = {
|
|
1625
|
-
id: pluginId,
|
|
1626
|
-
name: record.name,
|
|
1627
|
-
version: record.version,
|
|
1628
|
-
description: record.description,
|
|
1896
|
+
const result = registerPluginWithApi({
|
|
1897
|
+
runtime: params.runtime,
|
|
1898
|
+
record,
|
|
1899
|
+
pluginId,
|
|
1629
1900
|
source,
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
registerChannel: (registration) => {
|
|
1636
|
-
const normalizedChannel = registration && typeof registration === "object" && "plugin" in registration ? registration.plugin : registration;
|
|
1637
|
-
if (!normalizedChannel || typeof normalizedChannel !== "object") {
|
|
1638
|
-
params.registry.diagnostics.push({
|
|
1639
|
-
level: "error",
|
|
1640
|
-
pluginId,
|
|
1641
|
-
source,
|
|
1642
|
-
message: "channel registration missing plugin object"
|
|
1643
|
-
});
|
|
1644
|
-
return;
|
|
1645
|
-
}
|
|
1646
|
-
const channelObj = normalizedChannel;
|
|
1647
|
-
const rawId = typeof channelObj.id === "string" ? channelObj.id : String(channelObj.id ?? "");
|
|
1648
|
-
const accepted = ensureUniqueNames({
|
|
1649
|
-
names: [rawId],
|
|
1650
|
-
pluginId,
|
|
1651
|
-
diagnostics: params.registry.diagnostics,
|
|
1652
|
-
source,
|
|
1653
|
-
owners: params.channelIdOwners,
|
|
1654
|
-
reserved: params.reservedChannelIds,
|
|
1655
|
-
kind: "channel"
|
|
1656
|
-
});
|
|
1657
|
-
if (accepted.length === 0) {
|
|
1658
|
-
return;
|
|
1659
|
-
}
|
|
1660
|
-
const channelPlugin = normalizedChannel;
|
|
1661
|
-
params.registry.channels.push({
|
|
1662
|
-
pluginId,
|
|
1663
|
-
channel: channelPlugin,
|
|
1664
|
-
source
|
|
1665
|
-
});
|
|
1666
|
-
const channelId = accepted[0];
|
|
1667
|
-
record.channelIds.push(channelId);
|
|
1668
|
-
const configSchema = channelPlugin.configSchema;
|
|
1669
|
-
if (configSchema && typeof configSchema === "object") {
|
|
1670
|
-
const schema = configSchema.schema;
|
|
1671
|
-
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
1672
|
-
record.configJsonSchema = schema;
|
|
1673
|
-
record.configSchema = true;
|
|
1674
|
-
}
|
|
1675
|
-
const uiHints = configSchema.uiHints;
|
|
1676
|
-
if (uiHints && typeof uiHints === "object" && !Array.isArray(uiHints)) {
|
|
1677
|
-
record.configUiHints = {
|
|
1678
|
-
...record.configUiHints ?? {},
|
|
1679
|
-
...uiHints
|
|
1680
|
-
};
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
const pushChannelTools = (value, optional, sourceLabel, resolveValue) => {
|
|
1684
|
-
const previewTools = normalizeToolList(value);
|
|
1685
|
-
if (previewTools.length === 0) {
|
|
1686
|
-
return;
|
|
1687
|
-
}
|
|
1688
|
-
const declaredNames = previewTools.map((tool) => tool.name);
|
|
1689
|
-
const acceptedNames = ensureUniqueNames({
|
|
1690
|
-
names: declaredNames,
|
|
1691
|
-
pluginId,
|
|
1692
|
-
diagnostics: params.registry.diagnostics,
|
|
1693
|
-
source,
|
|
1694
|
-
owners: params.toolNameOwners,
|
|
1695
|
-
reserved: params.reservedToolNames,
|
|
1696
|
-
kind: "tool"
|
|
1697
|
-
});
|
|
1698
|
-
if (acceptedNames.length === 0) {
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1701
|
-
const factory = (ctx) => {
|
|
1702
|
-
const tools = normalizeToolList(resolveValue(ctx));
|
|
1703
|
-
if (tools.length === 0) {
|
|
1704
|
-
return [];
|
|
1705
|
-
}
|
|
1706
|
-
const byName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
1707
|
-
return acceptedNames.map((name) => byName.get(name)).filter(Boolean);
|
|
1708
|
-
};
|
|
1709
|
-
params.registry.tools.push({
|
|
1710
|
-
pluginId,
|
|
1711
|
-
factory,
|
|
1712
|
-
names: acceptedNames,
|
|
1713
|
-
optional,
|
|
1714
|
-
source
|
|
1715
|
-
});
|
|
1716
|
-
record.toolNames.push(...acceptedNames);
|
|
1717
|
-
const previewByName = new Map(previewTools.map((tool) => [tool.name, tool]));
|
|
1718
|
-
for (const name of acceptedNames) {
|
|
1719
|
-
const resolvedTool = previewByName.get(name);
|
|
1720
|
-
if (!resolvedTool || params.resolvedToolNames.has(resolvedTool.name)) {
|
|
1721
|
-
continue;
|
|
1722
|
-
}
|
|
1723
|
-
params.resolvedToolNames.add(resolvedTool.name);
|
|
1724
|
-
params.registry.resolvedTools.push(resolvedTool);
|
|
1725
|
-
}
|
|
1726
|
-
params.registry.diagnostics.push({
|
|
1727
|
-
level: "warn",
|
|
1728
|
-
pluginId,
|
|
1729
|
-
source,
|
|
1730
|
-
message: `${sourceLabel} registered channel-owned tools: ${acceptedNames.join(", ")}`
|
|
1731
|
-
});
|
|
1732
|
-
};
|
|
1733
|
-
const agentTools = channelPlugin.agentTools;
|
|
1734
|
-
if (typeof agentTools === "function") {
|
|
1735
|
-
pushChannelTools(
|
|
1736
|
-
normalizeToolList(agentTools()),
|
|
1737
|
-
false,
|
|
1738
|
-
`channel "${channelId}"`,
|
|
1739
|
-
() => agentTools()
|
|
1740
|
-
);
|
|
1741
|
-
} else if (agentTools) {
|
|
1742
|
-
pushChannelTools(
|
|
1743
|
-
normalizeToolList(agentTools),
|
|
1744
|
-
false,
|
|
1745
|
-
`channel "${channelId}"`,
|
|
1746
|
-
() => agentTools
|
|
1747
|
-
);
|
|
1748
|
-
}
|
|
1749
|
-
},
|
|
1750
|
-
registerProvider: (provider) => {
|
|
1751
|
-
const accepted = ensureUniqueNames({
|
|
1752
|
-
names: [provider.id],
|
|
1753
|
-
pluginId,
|
|
1754
|
-
diagnostics: params.registry.diagnostics,
|
|
1755
|
-
source,
|
|
1756
|
-
owners: params.providerIdOwners,
|
|
1757
|
-
reserved: params.reservedProviderIds,
|
|
1758
|
-
kind: "provider"
|
|
1759
|
-
});
|
|
1760
|
-
if (accepted.length === 0) {
|
|
1761
|
-
return;
|
|
1762
|
-
}
|
|
1763
|
-
params.registry.providers.push({
|
|
1764
|
-
pluginId,
|
|
1765
|
-
provider,
|
|
1766
|
-
source
|
|
1767
|
-
});
|
|
1768
|
-
record.providerIds.push(accepted[0]);
|
|
1769
|
-
},
|
|
1770
|
-
registerHook: () => pushUnsupported("registerHook"),
|
|
1771
|
-
registerGatewayMethod: () => pushUnsupported("registerGatewayMethod"),
|
|
1772
|
-
registerCli: () => pushUnsupported("registerCli"),
|
|
1773
|
-
registerService: () => pushUnsupported("registerService"),
|
|
1774
|
-
registerCommand: () => pushUnsupported("registerCommand"),
|
|
1775
|
-
registerHttpHandler: () => pushUnsupported("registerHttpHandler"),
|
|
1776
|
-
registerHttpRoute: () => pushUnsupported("registerHttpRoute"),
|
|
1777
|
-
resolvePath: (input) => {
|
|
1778
|
-
const trimmed = input.trim();
|
|
1779
|
-
if (!trimmed) {
|
|
1780
|
-
return params.workspaceDir;
|
|
1781
|
-
}
|
|
1782
|
-
if (path4.isAbsolute(trimmed)) {
|
|
1783
|
-
return path4.resolve(expandHome2(trimmed));
|
|
1784
|
-
}
|
|
1785
|
-
return path4.resolve(params.workspaceDir, trimmed);
|
|
1786
|
-
}
|
|
1787
|
-
};
|
|
1788
|
-
try {
|
|
1789
|
-
const result = register(api);
|
|
1790
|
-
if (result && typeof result === "object" && "then" in result) {
|
|
1791
|
-
params.registry.diagnostics.push({
|
|
1792
|
-
level: "warn",
|
|
1793
|
-
pluginId,
|
|
1794
|
-
source,
|
|
1795
|
-
message: "plugin register returned a promise; async registration is ignored"
|
|
1796
|
-
});
|
|
1797
|
-
}
|
|
1798
|
-
params.registry.plugins.push(record);
|
|
1799
|
-
} catch (err) {
|
|
1901
|
+
rootDir: params.runtime.workspaceDir,
|
|
1902
|
+
register,
|
|
1903
|
+
pluginConfig: void 0
|
|
1904
|
+
});
|
|
1905
|
+
if (!result.ok) {
|
|
1800
1906
|
record.status = "error";
|
|
1801
|
-
record.error =
|
|
1802
|
-
params.registry.plugins.push(record);
|
|
1907
|
+
record.error = result.error;
|
|
1803
1908
|
params.registry.diagnostics.push({
|
|
1804
1909
|
level: "error",
|
|
1805
1910
|
pluginId,
|
|
1806
1911
|
source,
|
|
1807
|
-
message:
|
|
1912
|
+
message: result.error
|
|
1808
1913
|
});
|
|
1809
1914
|
}
|
|
1915
|
+
params.registry.plugins.push(record);
|
|
1810
1916
|
}
|
|
1811
1917
|
}
|
|
1812
1918
|
function loadOpenClawPlugins(options) {
|
|
@@ -1823,26 +1929,22 @@ function loadOpenClawPlugins(options) {
|
|
|
1823
1929
|
diagnostics: [],
|
|
1824
1930
|
resolvedTools: []
|
|
1825
1931
|
};
|
|
1826
|
-
const toolNameOwners = /* @__PURE__ */ new Map();
|
|
1827
|
-
const channelIdOwners = /* @__PURE__ */ new Map();
|
|
1828
|
-
const providerIdOwners = /* @__PURE__ */ new Map();
|
|
1829
|
-
const resolvedToolNames = /* @__PURE__ */ new Set();
|
|
1830
1932
|
const reservedToolNames = new Set(options.reservedToolNames ?? []);
|
|
1831
1933
|
const reservedChannelIds = new Set(options.reservedChannelIds ?? []);
|
|
1832
1934
|
const reservedProviderIds = new Set(options.reservedProviderIds ?? []);
|
|
1833
|
-
|
|
1834
|
-
registry,
|
|
1935
|
+
const registerRuntime = createPluginRegisterRuntime({
|
|
1835
1936
|
config: options.config,
|
|
1836
|
-
logger,
|
|
1837
1937
|
workspaceDir,
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
providerIdOwners,
|
|
1841
|
-
resolvedToolNames,
|
|
1938
|
+
logger,
|
|
1939
|
+
registry,
|
|
1842
1940
|
reservedToolNames,
|
|
1843
1941
|
reservedChannelIds,
|
|
1844
1942
|
reservedProviderIds
|
|
1845
1943
|
});
|
|
1944
|
+
appendBundledChannelPlugins({
|
|
1945
|
+
registry,
|
|
1946
|
+
runtime: registerRuntime
|
|
1947
|
+
});
|
|
1846
1948
|
if (!loadExternalPlugins) {
|
|
1847
1949
|
return registry;
|
|
1848
1950
|
}
|
|
@@ -2000,264 +2102,30 @@ function loadOpenClawPlugins(options) {
|
|
|
2000
2102
|
});
|
|
2001
2103
|
continue;
|
|
2002
2104
|
}
|
|
2003
|
-
const
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
level: "warn",
|
|
2008
|
-
pluginId,
|
|
2009
|
-
source: candidate.source,
|
|
2010
|
-
message: `${capability} is not supported by nextclaw compat layer yet`
|
|
2011
|
-
});
|
|
2012
|
-
pluginLogger.warn(`${capability} is ignored (not supported yet)`);
|
|
2013
|
-
};
|
|
2014
|
-
const api = {
|
|
2015
|
-
id: pluginId,
|
|
2016
|
-
name: record.name,
|
|
2017
|
-
version: record.version,
|
|
2018
|
-
description: record.description,
|
|
2105
|
+
const registerResult = registerPluginWithApi({
|
|
2106
|
+
runtime: registerRuntime,
|
|
2107
|
+
record,
|
|
2108
|
+
pluginId,
|
|
2019
2109
|
source: candidate.source,
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
const declaredNames = opts && Array.isArray(opts.names) ? opts.names : [];
|
|
2026
|
-
const names = [...declaredNames, ...opts && opts.name ? [opts.name] : []];
|
|
2027
|
-
if (typeof tool !== "function" && typeof tool.name === "string") {
|
|
2028
|
-
names.push(tool.name);
|
|
2029
|
-
}
|
|
2030
|
-
const uniqueNames = Array.from(new Set(names.map((name) => name.trim()).filter(Boolean)));
|
|
2031
|
-
const acceptedNames = ensureUniqueNames({
|
|
2032
|
-
names: uniqueNames,
|
|
2033
|
-
pluginId,
|
|
2034
|
-
diagnostics: registry.diagnostics,
|
|
2035
|
-
source: candidate.source,
|
|
2036
|
-
owners: toolNameOwners,
|
|
2037
|
-
reserved: reservedToolNames,
|
|
2038
|
-
kind: "tool"
|
|
2039
|
-
});
|
|
2040
|
-
if (acceptedNames.length === 0) {
|
|
2041
|
-
registry.diagnostics.push({
|
|
2042
|
-
level: "warn",
|
|
2043
|
-
pluginId,
|
|
2044
|
-
source: candidate.source,
|
|
2045
|
-
message: "tool registration skipped: no available tool names"
|
|
2046
|
-
});
|
|
2047
|
-
return;
|
|
2048
|
-
}
|
|
2049
|
-
const factory = typeof tool === "function" ? tool : (_ctx) => tool;
|
|
2050
|
-
registry.tools.push({
|
|
2051
|
-
pluginId,
|
|
2052
|
-
factory,
|
|
2053
|
-
names: acceptedNames,
|
|
2054
|
-
optional: opts?.optional === true,
|
|
2055
|
-
source: candidate.source
|
|
2056
|
-
});
|
|
2057
|
-
record.toolNames.push(...acceptedNames);
|
|
2058
|
-
try {
|
|
2059
|
-
const previewTools = normalizeToolList(
|
|
2060
|
-
factory({
|
|
2061
|
-
config: options.config,
|
|
2062
|
-
workspaceDir,
|
|
2063
|
-
sandboxed: false
|
|
2064
|
-
})
|
|
2065
|
-
);
|
|
2066
|
-
const byName = new Map(previewTools.map((entry2) => [entry2.name, entry2]));
|
|
2067
|
-
for (const name of acceptedNames) {
|
|
2068
|
-
const resolvedTool = byName.get(name);
|
|
2069
|
-
if (!resolvedTool || resolvedToolNames.has(resolvedTool.name)) {
|
|
2070
|
-
continue;
|
|
2071
|
-
}
|
|
2072
|
-
resolvedToolNames.add(resolvedTool.name);
|
|
2073
|
-
registry.resolvedTools.push(resolvedTool);
|
|
2074
|
-
}
|
|
2075
|
-
} catch (err) {
|
|
2076
|
-
registry.diagnostics.push({
|
|
2077
|
-
level: "warn",
|
|
2078
|
-
pluginId,
|
|
2079
|
-
source: candidate.source,
|
|
2080
|
-
message: `tool preview failed: ${String(err)}`
|
|
2081
|
-
});
|
|
2082
|
-
}
|
|
2083
|
-
},
|
|
2084
|
-
registerChannel: (registration) => {
|
|
2085
|
-
const normalizedChannel = registration && typeof registration === "object" && "plugin" in registration ? registration.plugin : registration;
|
|
2086
|
-
if (!normalizedChannel || typeof normalizedChannel !== "object") {
|
|
2087
|
-
registry.diagnostics.push({
|
|
2088
|
-
level: "error",
|
|
2089
|
-
pluginId,
|
|
2090
|
-
source: candidate.source,
|
|
2091
|
-
message: "channel registration missing plugin object"
|
|
2092
|
-
});
|
|
2093
|
-
return;
|
|
2094
|
-
}
|
|
2095
|
-
const channelObj = normalizedChannel;
|
|
2096
|
-
const rawId = typeof channelObj.id === "string" ? channelObj.id : String(channelObj.id ?? "");
|
|
2097
|
-
const accepted = ensureUniqueNames({
|
|
2098
|
-
names: [rawId],
|
|
2099
|
-
pluginId,
|
|
2100
|
-
diagnostics: registry.diagnostics,
|
|
2101
|
-
source: candidate.source,
|
|
2102
|
-
owners: channelIdOwners,
|
|
2103
|
-
reserved: reservedChannelIds,
|
|
2104
|
-
kind: "channel"
|
|
2105
|
-
});
|
|
2106
|
-
if (accepted.length === 0) {
|
|
2107
|
-
return;
|
|
2108
|
-
}
|
|
2109
|
-
const channelPlugin = normalizedChannel;
|
|
2110
|
-
registry.channels.push({
|
|
2111
|
-
pluginId,
|
|
2112
|
-
channel: channelPlugin,
|
|
2113
|
-
source: candidate.source
|
|
2114
|
-
});
|
|
2115
|
-
const channelId = accepted[0];
|
|
2116
|
-
record.channelIds.push(channelId);
|
|
2117
|
-
const configSchema = channelPlugin.configSchema;
|
|
2118
|
-
if (configSchema && typeof configSchema === "object") {
|
|
2119
|
-
const schema = configSchema.schema;
|
|
2120
|
-
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
2121
|
-
record.configJsonSchema = schema;
|
|
2122
|
-
record.configSchema = true;
|
|
2123
|
-
}
|
|
2124
|
-
const uiHints = configSchema.uiHints;
|
|
2125
|
-
if (uiHints && typeof uiHints === "object" && !Array.isArray(uiHints)) {
|
|
2126
|
-
record.configUiHints = {
|
|
2127
|
-
...record.configUiHints ?? {},
|
|
2128
|
-
...uiHints
|
|
2129
|
-
};
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
const pushChannelTools = (value, optional, sourceLabel, resolveValue) => {
|
|
2133
|
-
const previewTools = normalizeToolList(value);
|
|
2134
|
-
if (previewTools.length === 0) {
|
|
2135
|
-
return;
|
|
2136
|
-
}
|
|
2137
|
-
const declaredNames = previewTools.map((tool) => tool.name);
|
|
2138
|
-
const acceptedNames = ensureUniqueNames({
|
|
2139
|
-
names: declaredNames,
|
|
2140
|
-
pluginId,
|
|
2141
|
-
diagnostics: registry.diagnostics,
|
|
2142
|
-
source: candidate.source,
|
|
2143
|
-
owners: toolNameOwners,
|
|
2144
|
-
reserved: reservedToolNames,
|
|
2145
|
-
kind: "tool"
|
|
2146
|
-
});
|
|
2147
|
-
if (acceptedNames.length === 0) {
|
|
2148
|
-
return;
|
|
2149
|
-
}
|
|
2150
|
-
const factory = (ctx) => {
|
|
2151
|
-
const tools = normalizeToolList(resolveValue(ctx));
|
|
2152
|
-
if (tools.length === 0) {
|
|
2153
|
-
return [];
|
|
2154
|
-
}
|
|
2155
|
-
const byName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
2156
|
-
return acceptedNames.map((name) => byName.get(name)).filter(Boolean);
|
|
2157
|
-
};
|
|
2158
|
-
registry.tools.push({
|
|
2159
|
-
pluginId,
|
|
2160
|
-
factory,
|
|
2161
|
-
names: acceptedNames,
|
|
2162
|
-
optional,
|
|
2163
|
-
source: candidate.source
|
|
2164
|
-
});
|
|
2165
|
-
record.toolNames.push(...acceptedNames);
|
|
2166
|
-
const previewByName = new Map(previewTools.map((tool) => [tool.name, tool]));
|
|
2167
|
-
for (const name of acceptedNames) {
|
|
2168
|
-
const resolvedTool = previewByName.get(name);
|
|
2169
|
-
if (!resolvedTool || resolvedToolNames.has(resolvedTool.name)) {
|
|
2170
|
-
continue;
|
|
2171
|
-
}
|
|
2172
|
-
resolvedToolNames.add(resolvedTool.name);
|
|
2173
|
-
registry.resolvedTools.push(resolvedTool);
|
|
2174
|
-
}
|
|
2175
|
-
registry.diagnostics.push({
|
|
2176
|
-
level: "warn",
|
|
2177
|
-
pluginId,
|
|
2178
|
-
source: candidate.source,
|
|
2179
|
-
message: `${sourceLabel} registered channel-owned tools: ${acceptedNames.join(", ")}`
|
|
2180
|
-
});
|
|
2181
|
-
};
|
|
2182
|
-
const agentTools = channelPlugin.agentTools;
|
|
2183
|
-
if (typeof agentTools === "function") {
|
|
2184
|
-
pushChannelTools(
|
|
2185
|
-
normalizeToolList(agentTools()),
|
|
2186
|
-
false,
|
|
2187
|
-
`channel "${channelId}"`,
|
|
2188
|
-
() => agentTools()
|
|
2189
|
-
);
|
|
2190
|
-
} else if (agentTools) {
|
|
2191
|
-
pushChannelTools(
|
|
2192
|
-
normalizeToolList(agentTools),
|
|
2193
|
-
false,
|
|
2194
|
-
`channel "${channelId}"`,
|
|
2195
|
-
() => agentTools
|
|
2196
|
-
);
|
|
2197
|
-
}
|
|
2198
|
-
},
|
|
2199
|
-
registerProvider: (provider) => {
|
|
2200
|
-
const accepted = ensureUniqueNames({
|
|
2201
|
-
names: [provider.id],
|
|
2202
|
-
pluginId,
|
|
2203
|
-
diagnostics: registry.diagnostics,
|
|
2204
|
-
source: candidate.source,
|
|
2205
|
-
owners: providerIdOwners,
|
|
2206
|
-
reserved: reservedProviderIds,
|
|
2207
|
-
kind: "provider"
|
|
2208
|
-
});
|
|
2209
|
-
if (accepted.length === 0) {
|
|
2210
|
-
return;
|
|
2211
|
-
}
|
|
2212
|
-
registry.providers.push({
|
|
2213
|
-
pluginId,
|
|
2214
|
-
provider,
|
|
2215
|
-
source: candidate.source
|
|
2216
|
-
});
|
|
2217
|
-
record.providerIds.push(accepted[0]);
|
|
2218
|
-
},
|
|
2219
|
-
registerHook: () => pushUnsupported("registerHook"),
|
|
2220
|
-
registerGatewayMethod: () => pushUnsupported("registerGatewayMethod"),
|
|
2221
|
-
registerCli: () => pushUnsupported("registerCli"),
|
|
2222
|
-
registerService: () => pushUnsupported("registerService"),
|
|
2223
|
-
registerCommand: () => pushUnsupported("registerCommand"),
|
|
2224
|
-
registerHttpHandler: () => pushUnsupported("registerHttpHandler"),
|
|
2225
|
-
registerHttpRoute: () => pushUnsupported("registerHttpRoute"),
|
|
2226
|
-
resolvePath: (input) => {
|
|
2227
|
-
const trimmed = input.trim();
|
|
2228
|
-
if (!trimmed) {
|
|
2229
|
-
return candidate.rootDir;
|
|
2230
|
-
}
|
|
2231
|
-
if (path4.isAbsolute(trimmed)) {
|
|
2232
|
-
return path4.resolve(expandHome2(trimmed));
|
|
2233
|
-
}
|
|
2234
|
-
return path4.resolve(candidate.rootDir, trimmed);
|
|
2235
|
-
}
|
|
2236
|
-
};
|
|
2237
|
-
try {
|
|
2238
|
-
const result = register(api);
|
|
2239
|
-
if (result && typeof result === "object" && "then" in result) {
|
|
2240
|
-
registry.diagnostics.push({
|
|
2241
|
-
level: "warn",
|
|
2242
|
-
pluginId,
|
|
2243
|
-
source: candidate.source,
|
|
2244
|
-
message: "plugin register returned a promise; async registration is ignored"
|
|
2245
|
-
});
|
|
2246
|
-
}
|
|
2247
|
-
registry.plugins.push(record);
|
|
2248
|
-
seenIds.set(pluginId, candidate.origin);
|
|
2249
|
-
} catch (err) {
|
|
2110
|
+
rootDir: candidate.rootDir,
|
|
2111
|
+
register,
|
|
2112
|
+
pluginConfig: validatedConfig.value
|
|
2113
|
+
});
|
|
2114
|
+
if (!registerResult.ok) {
|
|
2250
2115
|
record.status = "error";
|
|
2251
|
-
record.error =
|
|
2252
|
-
registry.plugins.push(record);
|
|
2253
|
-
seenIds.set(pluginId, candidate.origin);
|
|
2116
|
+
record.error = registerResult.error;
|
|
2254
2117
|
registry.diagnostics.push({
|
|
2255
2118
|
level: "error",
|
|
2256
2119
|
pluginId,
|
|
2257
2120
|
source: candidate.source,
|
|
2258
|
-
message:
|
|
2121
|
+
message: registerResult.error
|
|
2259
2122
|
});
|
|
2123
|
+
registry.plugins.push(record);
|
|
2124
|
+
seenIds.set(pluginId, candidate.origin);
|
|
2125
|
+
continue;
|
|
2260
2126
|
}
|
|
2127
|
+
registry.plugins.push(record);
|
|
2128
|
+
seenIds.set(pluginId, candidate.origin);
|
|
2261
2129
|
}
|
|
2262
2130
|
return registry;
|
|
2263
2131
|
}
|
|
@@ -2282,7 +2150,7 @@ function buildPluginStatusReport(params) {
|
|
|
2282
2150
|
|
|
2283
2151
|
// src/plugins/uninstall.ts
|
|
2284
2152
|
import fs6 from "fs/promises";
|
|
2285
|
-
import
|
|
2153
|
+
import path6 from "path";
|
|
2286
2154
|
function isLinkedPathInstall(record) {
|
|
2287
2155
|
if (!record || record.source !== "path") {
|
|
2288
2156
|
return false;
|
|
@@ -2290,7 +2158,7 @@ function isLinkedPathInstall(record) {
|
|
|
2290
2158
|
if (!record.sourcePath || !record.installPath) {
|
|
2291
2159
|
return true;
|
|
2292
2160
|
}
|
|
2293
|
-
return
|
|
2161
|
+
return path6.resolve(record.sourcePath) === path6.resolve(record.installPath);
|
|
2294
2162
|
}
|
|
2295
2163
|
function resolveUninstallDirectoryTarget(params) {
|
|
2296
2164
|
if (!params.hasInstall) {
|
|
@@ -2309,7 +2177,7 @@ function resolveUninstallDirectoryTarget(params) {
|
|
|
2309
2177
|
if (!configuredPath) {
|
|
2310
2178
|
return defaultPath;
|
|
2311
2179
|
}
|
|
2312
|
-
if (
|
|
2180
|
+
if (path6.resolve(configuredPath) === path6.resolve(defaultPath)) {
|
|
2313
2181
|
return configuredPath;
|
|
2314
2182
|
}
|
|
2315
2183
|
return defaultPath;
|
|
@@ -2435,6 +2303,7 @@ export {
|
|
|
2435
2303
|
buildChannelConfigSchema,
|
|
2436
2304
|
buildOauthProviderAuthResult,
|
|
2437
2305
|
buildPluginStatusReport,
|
|
2306
|
+
createPluginRegisterRuntime,
|
|
2438
2307
|
createPluginRuntime,
|
|
2439
2308
|
disablePluginInConfig,
|
|
2440
2309
|
discoverOpenClawPlugins,
|
|
@@ -2456,6 +2325,7 @@ export {
|
|
|
2456
2325
|
normalizePluginHttpPath,
|
|
2457
2326
|
normalizePluginsConfig,
|
|
2458
2327
|
recordPluginInstall,
|
|
2328
|
+
registerPluginWithApi,
|
|
2459
2329
|
removePluginFromConfig,
|
|
2460
2330
|
resolveEnableState,
|
|
2461
2331
|
resolvePluginChannelMessageToolHints,
|