mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:40:44 +00:00
fix: scope cold plugin manifests to index
This commit is contained in:
@@ -30,6 +30,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Plugins/startup: normalize startup and provider plugin enablement through registry aliases so boot paths do not need the legacy manifest alias scan. Thanks @vincentkoc.
|
||||
- Providers/plugins: resolve provider ownership, provider discovery scopes, and catalog-hook provider ids from the cold plugin registry instead of rescanning manifests on those paths. Thanks @vincentkoc.
|
||||
- Plugins/registry: keep installed plugin index records focused on install/state/load paths and resolve plugin capabilities from manifests scoped to indexed plugins. Thanks @shakkernerd.
|
||||
- Plugins/registry: route cold manifest and capability lookups through the installed plugin index so setup, channels, config, secrets, doctor, and provider metadata paths avoid broad plugin-root scans before runtime execution. Thanks @shakkernerd.
|
||||
- Plugins/chat commands: refresh the persisted plugin registry after `/plugins enable` and `/plugins disable`, matching the CLI mutation path. Thanks @vincentkoc.
|
||||
- Plugins/compat: mark `OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY` as a deprecated break-glass switch and point operators at registry repair instead. Thanks @vincentkoc.
|
||||
- Plugins/registry: ignore stale persisted registry reads when plugin policy no longer matches current config, and stamp generated registry files with a do-not-edit warning. Thanks @vincentkoc.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { SecretRefSource } from "../config/types.secrets.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { listKnownProviderEnvApiKeyNames } from "./model-auth-env-vars.js";
|
||||
|
||||
export const MINIMAX_OAUTH_MARKER = "minimax-oauth";
|
||||
@@ -45,20 +44,14 @@ function listKnownEnvApiKeyMarkers(): Set<string> {
|
||||
}
|
||||
|
||||
export function listKnownNonSecretApiKeyMarkers(): string[] {
|
||||
knownNonSecretApiKeyMarkersCache ??= (() => {
|
||||
const index = loadPluginRegistrySnapshot({});
|
||||
return [
|
||||
...new Set([
|
||||
...CORE_NON_SECRET_API_KEY_MARKERS,
|
||||
...loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
includeDisabled: true,
|
||||
}).plugins.flatMap((plugin) =>
|
||||
plugin.origin === "bundled" ? (plugin.nonSecretAuthMarkers ?? []) : [],
|
||||
),
|
||||
]),
|
||||
];
|
||||
})();
|
||||
knownNonSecretApiKeyMarkersCache ??= [
|
||||
...new Set([
|
||||
...CORE_NON_SECRET_API_KEY_MARKERS,
|
||||
...loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true }).plugins.flatMap(
|
||||
(plugin) => (plugin.origin === "bundled" ? (plugin.nonSecretAuthMarkers ?? []) : []),
|
||||
),
|
||||
]),
|
||||
];
|
||||
return [...knownNonSecretApiKeyMarkersCache];
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,8 @@ import {
|
||||
normalizePluginsConfigWithResolver,
|
||||
resolveEffectivePluginActivationState,
|
||||
} from "../plugins/config-policy.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import { loadEmbeddedPiMcpConfig } from "./embedded-pi-mcp.js";
|
||||
|
||||
@@ -105,12 +104,7 @@ export function loadEnabledBundlePiSettingsSnapshot(params: {
|
||||
if (!workspaceDir) {
|
||||
return {};
|
||||
}
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
workspaceDir,
|
||||
config: params.cfg,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir,
|
||||
config: params.cfg,
|
||||
includeDisabled: true,
|
||||
|
||||
@@ -45,9 +45,39 @@ vi.mock("../plugins/manifest-registry-installed.js", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/plugin-registry.js", () => ({
|
||||
loadPluginRegistrySnapshot: () => ({ plugins: [] }),
|
||||
}));
|
||||
vi.mock("../plugins/plugin-registry.js", async () => {
|
||||
const fs = await import("node:fs");
|
||||
const path = await import("node:path");
|
||||
const loadRegistry = (params: { workspaceDir?: string }) => {
|
||||
const rootDir = path.join(
|
||||
params.workspaceDir ?? "",
|
||||
".openclaw",
|
||||
"extensions",
|
||||
"claude-bundle",
|
||||
);
|
||||
if (!fs.existsSync(path.join(rootDir, ".claude-plugin", "plugin.json"))) {
|
||||
return { plugins: [], diagnostics: [] };
|
||||
}
|
||||
const resolvedRootDir = fs.realpathSync(rootDir);
|
||||
return {
|
||||
diagnostics: [],
|
||||
plugins: [
|
||||
{
|
||||
id: "claude-bundle",
|
||||
origin: "workspace",
|
||||
format: "bundle",
|
||||
bundleFormat: "claude",
|
||||
settingsFiles: ["settings.json"],
|
||||
rootDir: resolvedRootDir,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
return {
|
||||
loadPluginManifestRegistryForPluginRegistry: loadRegistry,
|
||||
loadPluginRegistrySnapshot: () => ({ plugins: [] }),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./embedded-pi-mcp.js", async () => {
|
||||
const fs = await import("node:fs");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
@@ -209,11 +208,7 @@ function isManifestProviderEndpointClass(value: string): value is ProviderEndpoi
|
||||
|
||||
function loadManifestProviderEndpointCache(): ManifestProviderEndpointCacheEntry[] {
|
||||
if (!manifestProviderEndpointCache) {
|
||||
const index = loadPluginRegistrySnapshot({ cache: true });
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true });
|
||||
const entries: ManifestProviderEndpointCacheEntry[] = [];
|
||||
for (const plugin of registry.plugins) {
|
||||
for (const endpoint of plugin.providerEndpoints ?? []) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
const pluginRegistryMocks = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
const pluginRegistryMocks = vi.hoisted(() => {
|
||||
const loadManifestRegistry = vi.fn();
|
||||
return {
|
||||
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
|
||||
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
loadPluginManifestRegistryForInstalledIndex:
|
||||
@@ -11,6 +15,8 @@ vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry:
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
|
||||
import {
|
||||
isWorkspacePluginAllowedByConfig,
|
||||
normalizePluginConfigId,
|
||||
} from "../plugins/plugin-config-trust.js";
|
||||
import type { PluginOrigin } from "../plugins/plugin-origin.types.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { normalizeProviderId } from "./provider-id.js";
|
||||
|
||||
export type ProviderAuthAliasLookupParams = {
|
||||
@@ -84,13 +83,7 @@ function setPreferredAlias(params: {
|
||||
export function resolveProviderAuthAliasMap(
|
||||
params?: ProviderAuthAliasLookupParams,
|
||||
): Record<string, string> {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
|
||||
@@ -5,16 +5,21 @@ import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { PluginManifestRegistry } from "../../plugins/manifest-registry.js";
|
||||
import { createTrackedTempDirs } from "../../test-utils/tracked-temp-dirs.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const loadManifestRegistry = vi.fn();
|
||||
return {
|
||||
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
|
||||
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../plugins/manifest-registry-installed.js", () => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: hoisted.loadPluginManifestRegistryForInstalledIndex,
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry: hoisted.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: hoisted.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ import {
|
||||
resolveEffectivePluginActivationState,
|
||||
resolveMemorySlotDecision,
|
||||
} from "../../plugins/config-policy.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRegistry } from "../../plugins/manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "../../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../../plugins/plugin-registry.js";
|
||||
import { hasKind } from "../../plugins/slots.js";
|
||||
import { isPathInsideWithRealpath } from "../../security/scan-paths.js";
|
||||
|
||||
@@ -50,12 +49,7 @@ export function resolvePluginSkillDirs(params: {
|
||||
if (!workspaceDir) {
|
||||
return [];
|
||||
}
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
workspaceDir,
|
||||
config: params.config,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir,
|
||||
config: params.config,
|
||||
includeDisabled: true,
|
||||
|
||||
@@ -7,9 +7,8 @@ import {
|
||||
resolveDiscoverableScopedChannelPluginIds,
|
||||
} from "../../plugins/channel-plugin-ids.js";
|
||||
import { loadOpenClawPlugins } from "../../plugins/loader.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "../../plugins/manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "../../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../../plugins/plugin-registry.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
|
||||
import { sanitizeForLog } from "../../terminal/ansi.js";
|
||||
import { getBundledChannelSetupPlugin } from "./bundled.js";
|
||||
@@ -521,17 +520,11 @@ export function resolveReadOnlyChannelPluginsForConfig(
|
||||
): ReadOnlyChannelPluginResolution {
|
||||
const env = options.env ?? process.env;
|
||||
const workspaceDir = resolveReadOnlyWorkspaceDir(cfg, options);
|
||||
const pluginIndex = loadPluginRegistrySnapshot({
|
||||
const manifestRecords = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: cfg,
|
||||
workspaceDir,
|
||||
env,
|
||||
cache: options.cache,
|
||||
});
|
||||
const manifestRecords = loadPluginManifestRegistryForInstalledIndex({
|
||||
index: pluginIndex,
|
||||
config: cfg,
|
||||
workspaceDir,
|
||||
env,
|
||||
includeDisabled: true,
|
||||
}).plugins;
|
||||
const externalManifestRecords = listExternalChannelManifestRecords(manifestRecords);
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
normalizePluginsConfig,
|
||||
resolveEffectivePluginActivationState,
|
||||
} from "../../../plugins/config-state.js";
|
||||
import { loadPluginManifestRegistry } from "../../../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../../../plugins/plugin-registry.js";
|
||||
import { sanitizeForLog } from "../../../terminal/ansi.js";
|
||||
|
||||
export type ChannelPluginBlockerHit = {
|
||||
@@ -45,9 +45,10 @@ export function scanConfiguredChannelPluginBlockers(
|
||||
}
|
||||
|
||||
const pluginsConfig = normalizePluginsConfig(cfg.plugins);
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: cfg,
|
||||
env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const hits: ChannelPluginBlockerHit[] = [];
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../agents/agent-scope.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import { normalizePluginId } from "../../../plugins/config-state.js";
|
||||
import { loadPluginManifestRegistry } from "../../../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../../../plugins/plugin-registry.js";
|
||||
import { sanitizeForLog } from "../../../terminal/ansi.js";
|
||||
import { asObjectRecord } from "./object.js";
|
||||
|
||||
@@ -23,10 +23,11 @@ function collectPluginRegistryState(
|
||||
env?: NodeJS.ProcessEnv,
|
||||
): StalePluginRegistryState {
|
||||
const workspaceDir = resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg));
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: cfg,
|
||||
workspaceDir: workspaceDir ?? undefined,
|
||||
env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
return {
|
||||
knownIds: new Set(registry.plugins.map((plugin) => plugin.id)),
|
||||
|
||||
@@ -6,11 +6,10 @@ import {
|
||||
} from "../channels/config-presence.js";
|
||||
import { getChatChannelMeta, normalizeChatChannelId } from "../channels/registry.js";
|
||||
import {
|
||||
loadPluginManifestRegistry,
|
||||
resolveManifestContractOwnerPluginId,
|
||||
type PluginManifestRecord,
|
||||
type PluginManifestRegistry,
|
||||
} from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { resolveOwningPluginIdsForModelRef } from "../plugins/providers.js";
|
||||
import { resolvePluginSetupAutoEnableReasons } from "../plugins/setup-registry.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
@@ -211,12 +210,20 @@ function resolvePluginIdForConfiguredWebFetchProvider(
|
||||
providerId: string | undefined,
|
||||
env: NodeJS.ProcessEnv,
|
||||
): string | undefined {
|
||||
return resolveManifestContractOwnerPluginId({
|
||||
contract: "webFetchProviders",
|
||||
value: normalizeOptionalLowercaseString(providerId) ?? "",
|
||||
origin: "bundled",
|
||||
const normalizedProviderId = normalizeOptionalLowercaseString(providerId);
|
||||
if (!normalizedProviderId) {
|
||||
return undefined;
|
||||
}
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
env,
|
||||
});
|
||||
includeDisabled: true,
|
||||
}).plugins.find(
|
||||
(plugin) =>
|
||||
plugin.origin === "bundled" &&
|
||||
(plugin.contracts?.webFetchProviders ?? []).some(
|
||||
(candidate) => normalizeOptionalLowercaseString(candidate) === normalizedProviderId,
|
||||
),
|
||||
)?.id;
|
||||
}
|
||||
|
||||
function normalizeManifestChannelId(channelId: string): string {
|
||||
@@ -785,7 +792,11 @@ export function resolvePluginAutoEnableManifestRegistry(params: {
|
||||
return (
|
||||
params.manifestRegistry ??
|
||||
(configMayNeedPluginManifestRegistry(params.config, params.env)
|
||||
? loadPluginManifestRegistry({ config: params.config, env: params.env })
|
||||
? loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
})
|
||||
: EMPTY_PLUGIN_MANIFEST_REGISTRY)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import {
|
||||
collectChannelSchemaMetadata,
|
||||
collectPluginSchemaMetadata,
|
||||
@@ -10,11 +10,12 @@ import { buildConfigSchema, type ConfigSchemaResponse } from "./schema.js";
|
||||
|
||||
function loadManifestRegistry(config: OpenClawConfig, env?: NodeJS.ProcessEnv) {
|
||||
const workspaceDir = resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config));
|
||||
return loadPluginManifestRegistry({
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config,
|
||||
cache: false,
|
||||
env,
|
||||
workspaceDir,
|
||||
includeDisabled: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,8 @@ import {
|
||||
listPluginDoctorLegacyConfigRules,
|
||||
} from "../plugins/doctor-contract-registry.js";
|
||||
import { resolveManifestCommandAliasOwner } from "../plugins/manifest-command-aliases.runtime.js";
|
||||
import {
|
||||
loadPluginManifestRegistry,
|
||||
resolveManifestContractPluginIds,
|
||||
} from "../plugins/manifest-registry.js";
|
||||
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { validateJsonSchemaValue } from "../plugins/schema-validator.js";
|
||||
import { hasKind } from "../plugins/slots.js";
|
||||
import { collectLegacySecretRefEnvMarkerCandidates } from "../secrets/legacy-secretref-env-marker.js";
|
||||
@@ -760,7 +758,7 @@ function validateConfigObjectWithPluginsBase(
|
||||
};
|
||||
|
||||
type RegistryInfo = {
|
||||
registry: ReturnType<typeof loadPluginManifestRegistry>;
|
||||
registry: PluginManifestRegistry;
|
||||
knownIds?: Set<string>;
|
||||
overriddenPluginIds?: Set<string>;
|
||||
normalizedPlugins?: ReturnType<typeof normalizePluginsConfig>;
|
||||
@@ -788,24 +786,27 @@ function validateConfigObjectWithPluginsBase(
|
||||
return compatPluginIds;
|
||||
}
|
||||
const workspaceDir = resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config));
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config,
|
||||
workspaceDir: workspaceDir ?? undefined,
|
||||
env: opts.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const overriddenBundledPluginIds = new Set(
|
||||
loadPluginManifestRegistry({
|
||||
config,
|
||||
workspaceDir: workspaceDir ?? undefined,
|
||||
env: opts.env,
|
||||
})
|
||||
.diagnostics.filter((diag) => diag.message.includes("duplicate plugin id detected"))
|
||||
registry.diagnostics
|
||||
.filter((diag) => diag.message.includes("duplicate plugin id detected"))
|
||||
.map((diag) => diag.pluginId)
|
||||
.filter((pluginId): pluginId is string => typeof pluginId === "string" && pluginId !== ""),
|
||||
);
|
||||
compatPluginIds = new Set(
|
||||
resolveManifestContractPluginIds({
|
||||
contract: "webSearchProviders",
|
||||
origin: "bundled",
|
||||
config,
|
||||
workspaceDir: workspaceDir ?? undefined,
|
||||
env: opts.env,
|
||||
}).filter((pluginId) => !overriddenBundledPluginIds.has(pluginId)),
|
||||
registry.plugins
|
||||
.filter(
|
||||
(plugin) =>
|
||||
plugin.origin === "bundled" &&
|
||||
(plugin.contracts?.webSearchProviders?.length ?? 0) > 0 &&
|
||||
!overriddenBundledPluginIds.has(plugin.id),
|
||||
)
|
||||
.map((plugin) => plugin.id),
|
||||
);
|
||||
return compatPluginIds;
|
||||
};
|
||||
@@ -838,10 +839,11 @@ function validateConfigObjectWithPluginsBase(
|
||||
effectiveConfig,
|
||||
resolveDefaultAgentId(effectiveConfig),
|
||||
);
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: effectiveConfig,
|
||||
workspaceDir: workspaceDir ?? undefined,
|
||||
env: opts.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
for (const diag of registry.diagnostics) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
resolveEffectivePluginActivationState,
|
||||
resolveMemorySlotDecision,
|
||||
} from "../plugins/config-state.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { hasKind } from "../plugins/slots.js";
|
||||
import { isPathInsideWithRealpath } from "../security/scan-paths.js";
|
||||
|
||||
@@ -26,11 +26,12 @@ export function resolvePluginHookDirs(params: {
|
||||
if (!workspaceDir) {
|
||||
return [];
|
||||
}
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir,
|
||||
config: params.config,
|
||||
// Hook discovery should reflect freshly written bundle manifests immediately.
|
||||
cache: false,
|
||||
includeDisabled: true,
|
||||
});
|
||||
if (registry.plugins.length === 0) {
|
||||
return [];
|
||||
|
||||
@@ -17,10 +17,8 @@ import {
|
||||
isActivatedManifestOwner,
|
||||
passesManifestOwnerBasePolicy,
|
||||
} from "../plugins/manifest-owner-policy.js";
|
||||
import {
|
||||
loadPluginManifestRegistry,
|
||||
type PluginManifestRecord,
|
||||
} from "../plugins/manifest-registry.js";
|
||||
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { resolveProviderUsageAuthWithPlugin } from "../plugins/provider-runtime.js";
|
||||
import { resolveProviderAuthEnvVarCandidates } from "../secrets/provider-env-vars.js";
|
||||
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
|
||||
@@ -183,9 +181,10 @@ function resolveUsageCredentialProviderIds(params: {
|
||||
const providerIds = new Set(normalizeProviderIds([params.provider]));
|
||||
const providerIdSet = new Set(providerIds);
|
||||
try {
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.state.cfg,
|
||||
env: params.state.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
for (const plugin of registry.plugins) {
|
||||
const pluginProviderIds = normalizeProviderIds(plugin.providers);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { normalizeMediaProviderId } from "./provider-id.js";
|
||||
import type { MediaUnderstandingProvider } from "./types.js";
|
||||
|
||||
@@ -7,9 +7,10 @@ export function buildMediaUnderstandingManifestMetadataRegistry(
|
||||
cfg?: OpenClawConfig,
|
||||
): Map<string, MediaUnderstandingProvider> {
|
||||
const registry = new Map<string, MediaUnderstandingProvider>();
|
||||
for (const plugin of loadPluginManifestRegistry({
|
||||
for (const plugin of loadPluginManifestRegistryForPluginRegistry({
|
||||
config: cfg,
|
||||
env: process.env,
|
||||
includeDisabled: true,
|
||||
}).plugins) {
|
||||
const declaredProviders = new Set(
|
||||
(plugin.contracts?.mediaUnderstandingProviders ?? []).map((providerId) =>
|
||||
|
||||
@@ -8,6 +8,11 @@ vi.mock("./manifest-registry.js", () => ({
|
||||
loadPluginManifestRegistry: (...args: unknown[]) => mocks.loadPluginManifestRegistry(...args),
|
||||
}));
|
||||
|
||||
vi.mock("./plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry: (...args: unknown[]) =>
|
||||
mocks.loadPluginManifestRegistry(...args),
|
||||
}));
|
||||
|
||||
let resolveManifestActivationPluginIds: typeof import("./activation-planner.js").resolveManifestActivationPluginIds;
|
||||
let resolveManifestActivationPlan: typeof import("./activation-planner.js").resolveManifestActivationPlan;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { normalizeProviderId } from "../agents/provider-id.js";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import { loadPluginManifestRegistry, type PluginManifestRecord } from "./manifest-registry.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import type { PluginDiagnostic } from "./manifest-types.js";
|
||||
import type { PluginManifestActivationCapability } from "./manifest.js";
|
||||
import type { PluginOrigin } from "./plugin-origin.types.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { createPluginIdScopeSet, normalizePluginIdScope } from "./plugin-scope.js";
|
||||
|
||||
export type PluginActivationPlannerTrigger =
|
||||
@@ -65,11 +66,12 @@ export function resolveManifestActivationPlan(
|
||||
const onlyPluginIdSet = createPluginIdScopeSet(normalizePluginIdScope(params.onlyPluginIds));
|
||||
const registry = params.manifestRecords
|
||||
? { plugins: params.manifestRecords, diagnostics: [] }
|
||||
: loadPluginManifestRegistry({
|
||||
: loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
cache: params.cache,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const entries = registry.plugins
|
||||
.flatMap((plugin) => {
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
normalizePluginsConfig,
|
||||
resolveEffectivePluginActivationState,
|
||||
} from "./config-state.js";
|
||||
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
export type ClaudeBundleCommandSpec = {
|
||||
pluginId: string;
|
||||
@@ -176,10 +176,11 @@ export function loadEnabledClaudeBundleCommands(params: {
|
||||
if (!hasExplicitPluginConfig(params.cfg?.plugins)) {
|
||||
return [];
|
||||
}
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir: params.workspaceDir,
|
||||
config: params.cfg,
|
||||
cache: false,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const normalizedPlugins = normalizePluginsConfig(params.cfg?.plugins);
|
||||
const commands: ClaudeBundleCommandSpec[] = [];
|
||||
|
||||
@@ -5,8 +5,8 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { matchBoundaryFileOpenFailure, openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import { normalizePluginsConfig, resolveEffectivePluginActivationState } from "./config-state.js";
|
||||
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
||||
import type { PluginBundleFormat } from "./manifest-types.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
type ReadBundleJsonResult =
|
||||
| { ok: true; raw: Record<string, unknown> }
|
||||
@@ -107,9 +107,10 @@ export function loadEnabledBundleConfig<TConfig, TDiagnostic>(params: {
|
||||
return { config: params.createEmptyConfig(), diagnostics: [] };
|
||||
}
|
||||
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir: params.workspaceDir,
|
||||
config: params.cfg,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const diagnostics: TDiagnostic[] = [];
|
||||
let merged = params.createEmptyConfig();
|
||||
|
||||
@@ -15,10 +15,10 @@ const mocks = vi.hoisted(() => ({
|
||||
resolveRuntimePluginRegistry: vi.fn<
|
||||
(params?: unknown) => ReturnType<typeof createEmptyPluginRegistry> | undefined
|
||||
>(() => undefined),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
loadPluginManifestRegistry: vi.fn<() => MockManifestRegistry>(() =>
|
||||
createEmptyMockManifestRegistry(),
|
||||
loadPluginManifestRegistry: vi.fn<(params?: Record<string, unknown>) => MockManifestRegistry>(
|
||||
() => createEmptyMockManifestRegistry(),
|
||||
),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
withBundledPluginAllowlistCompat: vi.fn(
|
||||
({ config, pluginIds }: { config?: OpenClawConfig; pluginIds: string[] }) =>
|
||||
({
|
||||
@@ -41,9 +41,21 @@ vi.mock("./manifest-registry-installed.js", () => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: mocks.loadPluginManifestRegistry,
|
||||
}));
|
||||
|
||||
vi.mock("./plugin-registry.js", () => ({
|
||||
loadPluginRegistrySnapshot: mocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
vi.mock("./plugin-registry.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("./plugin-registry.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadPluginRegistrySnapshot: mocks.loadPluginRegistrySnapshot,
|
||||
loadPluginManifestRegistryForPluginRegistry: (
|
||||
...args: Parameters<typeof mocks.loadPluginManifestRegistry>
|
||||
) => {
|
||||
const [{ includeDisabled: _includeDisabled, ...params } = {}] = args as [
|
||||
Record<string, unknown>?,
|
||||
];
|
||||
return mocks.loadPluginManifestRegistry(params);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./bundled-compat.js", () => ({
|
||||
withBundledPluginAllowlistCompat: mocks.withBundledPluginAllowlistCompat,
|
||||
@@ -73,10 +85,8 @@ function expectBundledCompatLoadPath(params: {
|
||||
};
|
||||
}) {
|
||||
expect(mocks.loadPluginManifestRegistry).toHaveBeenCalledWith({
|
||||
index: expect.anything(),
|
||||
config: params.cfg,
|
||||
env: process.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
expect(mocks.withBundledPluginEnablementCompat).toHaveBeenCalledWith({
|
||||
config: params.allowlistCompat,
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
} from "./bundled-compat.js";
|
||||
import { hasExplicitPluginConfig } from "./config-policy.js";
|
||||
import { resolveRuntimePluginRegistry } from "./loader.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import type { PluginRegistry } from "./registry-types.js";
|
||||
|
||||
type CapabilityProviderRegistryKey =
|
||||
@@ -50,12 +49,7 @@ function resolveBundledCapabilityCompatPluginIds(params: {
|
||||
providerId?: string;
|
||||
}): string[] {
|
||||
const contractKey = CAPABILITY_CONTRACT_KEY[params.key];
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.cfg,
|
||||
env: process.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.cfg,
|
||||
env: process.env,
|
||||
includeDisabled: true,
|
||||
|
||||
@@ -19,9 +19,8 @@ import {
|
||||
isBundledManifestOwner,
|
||||
passesManifestOwnerBasePolicy,
|
||||
} from "./manifest-owner-policy.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
const IGNORED_CHANNEL_CONFIG_KEYS = new Set(["defaults", "modelByChannel"]);
|
||||
|
||||
@@ -348,17 +347,11 @@ function loadInstalledChannelManifestRecords(params: {
|
||||
env: NodeJS.ProcessEnv;
|
||||
cache?: boolean;
|
||||
}): readonly PluginManifestRecord[] {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
cache: params.cache,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
}).plugins;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { PluginManifestRegistry } from "./manifest-registry.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
findBundledPluginMetadataById: vi.fn(),
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
const mocks = vi.hoisted(() => {
|
||||
const loadManifestRegistry = vi.fn();
|
||||
return {
|
||||
findBundledPluginMetadataById: vi.fn(),
|
||||
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
|
||||
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./bundled-plugin-metadata.js", () => ({
|
||||
findBundledPluginMetadataById: mocks.findBundledPluginMetadataById,
|
||||
@@ -16,6 +20,7 @@ vi.mock("./manifest-registry-installed.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("./plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry: mocks.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: mocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import { findBundledPluginMetadataById } from "./bundled-plugin-metadata.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestConfigContracts } from "./manifest.js";
|
||||
import type { PluginOrigin } from "./plugin-origin.types.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
export type PluginConfigContractMatch = {
|
||||
path: string;
|
||||
@@ -115,17 +114,11 @@ export function resolvePluginConfigContractsById(params: {
|
||||
}
|
||||
|
||||
const resolvedPluginIds = new Set<string>();
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
cache: params.cache,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
for (const plugin of registry.plugins) {
|
||||
|
||||
@@ -4,10 +4,10 @@ import { fileURLToPath } from "node:url";
|
||||
import type { LegacyConfigRule } from "../config/legacy.shared.js";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import { asNullableRecord } from "../shared/record-coerce.js";
|
||||
import { discoverOpenClawPlugins } from "./discovery.js";
|
||||
import { getCachedPluginJitiLoader, type PluginJitiLoaderCache } from "./jiti-loader-cache.js";
|
||||
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
||||
import type { PluginManifestRegistry } from "./manifest-registry.js";
|
||||
import { tryNativeRequireJavaScriptModule } from "./native-module-require.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { resolvePluginCacheInputs, type PluginSourceRoots } from "./roots.js";
|
||||
|
||||
const CONTRACT_API_EXTENSIONS = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"] as const;
|
||||
@@ -36,9 +36,7 @@ type PluginDoctorContractEntry = {
|
||||
normalizeCompatibilityConfig?: PluginDoctorCompatibilityNormalizer;
|
||||
};
|
||||
|
||||
type PluginManifestRegistryRecord = ReturnType<
|
||||
typeof loadPluginManifestRegistry
|
||||
>["plugins"][number];
|
||||
type PluginManifestRegistryRecord = PluginManifestRegistry["plugins"][number];
|
||||
|
||||
const jitiLoaders: PluginJitiLoaderCache = new Map();
|
||||
const doctorContractCache = new Map<string, PluginDoctorContractEntry[]>();
|
||||
@@ -285,17 +283,11 @@ function resolvePluginDoctorContracts(params?: {
|
||||
return [];
|
||||
}
|
||||
|
||||
const discovery = discoverOpenClawPlugins({
|
||||
const manifestRegistry = loadPluginManifestRegistryForPluginRegistry({
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env,
|
||||
cache: true,
|
||||
});
|
||||
const manifestRegistry = loadPluginManifestRegistry({
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env,
|
||||
cache: true,
|
||||
candidates: discovery.candidates,
|
||||
diagnostics: discovery.diagnostics,
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
const entries: PluginDoctorContractEntry[] = [];
|
||||
|
||||
@@ -7,9 +7,8 @@ import {
|
||||
} from "./config-state.js";
|
||||
import { loadBundledDocumentExtractorEntriesFromDir } from "./document-extractor-public-artifacts.js";
|
||||
import type { PluginDocumentExtractorEntry } from "./document-extractor-types.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
function compareExtractors(
|
||||
left: PluginDocumentExtractorEntry,
|
||||
@@ -31,13 +30,7 @@ function resolveBundledDocumentExtractorCompatPluginIds(params: {
|
||||
}): string[] {
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
@@ -82,13 +75,7 @@ function resolveEnabledBundledDocumentExtractorPlugins(params: {
|
||||
});
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: activation.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: activation.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
|
||||
@@ -4,8 +4,7 @@ import {
|
||||
type PluginManifestCommandAliasRegistry,
|
||||
type PluginManifestCommandAliasRecord,
|
||||
} from "./manifest-command-aliases.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
export function resolveManifestCommandAliasOwner(params: {
|
||||
command: string | undefined;
|
||||
@@ -16,20 +15,12 @@ export function resolveManifestCommandAliasOwner(params: {
|
||||
}): PluginManifestCommandAliasRecord | undefined {
|
||||
const registry =
|
||||
params.registry ??
|
||||
(() => {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
})();
|
||||
loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
return resolveManifestCommandAliasOwnerInRegistry({
|
||||
command: params.command,
|
||||
registry,
|
||||
|
||||
@@ -5,7 +5,9 @@ import {
|
||||
type NormalizedPluginsConfig,
|
||||
} from "./config-normalization-shared.js";
|
||||
import {
|
||||
inspectPersistedInstalledPluginIndex,
|
||||
readPersistedInstalledPluginIndexSync,
|
||||
refreshPersistedInstalledPluginIndex,
|
||||
type InstalledPluginIndexStoreInspection,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store.js";
|
||||
@@ -61,6 +63,11 @@ export type PluginRegistryContributionOptions = LoadPluginRegistryParams & {
|
||||
includeDisabled?: boolean;
|
||||
};
|
||||
|
||||
export type LoadPluginRegistryManifestParams = LoadPluginRegistryParams & {
|
||||
includeDisabled?: boolean;
|
||||
pluginIds?: readonly string[];
|
||||
};
|
||||
|
||||
export type GetPluginRecordParams = LoadPluginRegistryParams & {
|
||||
pluginId: string;
|
||||
};
|
||||
@@ -190,6 +197,20 @@ function loadContributionManifestRegistry(
|
||||
});
|
||||
}
|
||||
|
||||
export function loadPluginManifestRegistryForPluginRegistry(
|
||||
params: LoadPluginRegistryManifestParams = {},
|
||||
): PluginManifestRegistry {
|
||||
const index = resolveSnapshot(params);
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
pluginIds: params.pluginIds,
|
||||
includeDisabled: params.includeDisabled,
|
||||
});
|
||||
}
|
||||
|
||||
export function createPluginRegistryIdNormalizer(
|
||||
index: PluginRegistrySnapshot,
|
||||
): (pluginId: string) => string {
|
||||
@@ -422,15 +443,11 @@ export function resolveSetupProviderOwners(
|
||||
export function inspectPluginRegistry(
|
||||
params: LoadInstalledPluginIndexParams & InstalledPluginIndexStoreOptions = {},
|
||||
): Promise<PluginRegistryInspection> {
|
||||
return import("./installed-plugin-index-store.js").then((store) =>
|
||||
store.inspectPersistedInstalledPluginIndex(params),
|
||||
);
|
||||
return inspectPersistedInstalledPluginIndex(params);
|
||||
}
|
||||
|
||||
export function refreshPluginRegistry(
|
||||
params: RefreshInstalledPluginIndexParams & InstalledPluginIndexStoreOptions,
|
||||
): Promise<PluginRegistrySnapshot> {
|
||||
return import("./installed-plugin-index-store.js").then((store) =>
|
||||
store.refreshPersistedInstalledPluginIndex(params),
|
||||
);
|
||||
return refreshPersistedInstalledPluginIndex(params);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const pluginRegistryMocks = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
|
||||
loadPluginManifestRegistryForPluginRegistry: vi.fn(),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
|
||||
@@ -11,6 +12,8 @@ vi.mock("./manifest-registry-installed.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("./plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry:
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
@@ -37,6 +40,9 @@ function setManifestPlugins(plugins: Array<Record<string, unknown>>) {
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForInstalledIndex.mockReturnValue({
|
||||
plugins,
|
||||
});
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry.mockReturnValue({
|
||||
plugins,
|
||||
});
|
||||
}
|
||||
|
||||
function expectResolvedProviderAuthChoices(params: {
|
||||
@@ -66,6 +72,10 @@ describe("provider auth choice manifest helpers", () => {
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForInstalledIndex.mockReturnValue({
|
||||
plugins: [],
|
||||
});
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry.mockReset();
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry.mockReturnValue({
|
||||
plugins: [],
|
||||
});
|
||||
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReset();
|
||||
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReturnValue({ plugins: [] });
|
||||
});
|
||||
|
||||
@@ -2,10 +2,9 @@ import { resolveProviderIdForAuth } from "../agents/provider-auth-aliases.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { sanitizeForLog } from "../terminal/ansi.js";
|
||||
import { normalizePluginsConfig, resolveEffectiveEnableState } from "./config-state.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import type { PluginOrigin } from "./plugin-origin.types.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
|
||||
export type ProviderAuthChoiceMetadata = {
|
||||
pluginId: string;
|
||||
@@ -181,13 +180,7 @@ function resolveManifestProviderAuthChoiceCandidates(params?: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
includeUntrustedWorkspacePlugins?: boolean;
|
||||
}): ProviderAuthChoiceCandidate[] {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistry, type PluginManifestRecord } from "./manifest-registry.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { resolveDiscoveredProviderPluginIds } from "./providers.js";
|
||||
import { resolvePluginProviders } from "./providers.runtime.js";
|
||||
import { createPluginSourceLoader } from "./source-loader.js";
|
||||
@@ -77,9 +78,11 @@ function resolveProviderDiscoveryEntryPlugins(params: {
|
||||
}): ProviderDiscoveryEntryResult {
|
||||
const pluginIds = resolveDiscoveredProviderPluginIds(params);
|
||||
const pluginIdSet = new Set(pluginIds);
|
||||
const pluginRecords = loadPluginManifestRegistry(params).plugins.filter((plugin) =>
|
||||
pluginIdSet.has(plugin.id),
|
||||
);
|
||||
const pluginRecords = loadPluginManifestRegistryForPluginRegistry({
|
||||
...params,
|
||||
pluginIds,
|
||||
includeDisabled: true,
|
||||
}).plugins.filter((plugin) => pluginIdSet.has(plugin.id));
|
||||
const entryRecords = pluginRecords.filter((plugin) => plugin.providerDiscoverySource);
|
||||
const entryPluginIds = new Set(entryRecords.map((plugin) => plugin.id));
|
||||
if (entryRecords.length === 0) {
|
||||
|
||||
@@ -6,9 +6,8 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { buildPluginApi } from "./api-builder.js";
|
||||
import { collectPluginConfigContractMatches } from "./config-contracts.js";
|
||||
import { getCachedPluginJitiLoader, type PluginJitiLoaderCache } from "./jiti-loader-cache.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { resolvePluginCacheInputs } from "./roots.js";
|
||||
import type { PluginRuntime } from "./runtime/types.js";
|
||||
import { listSetupCliBackendIds, listSetupProviderIds } from "./setup-descriptors.js";
|
||||
@@ -252,6 +251,7 @@ function resolveRelevantSetupMigrationPluginIds(params: {
|
||||
}): string[] {
|
||||
const ids = new Set<string>(collectConfiguredPluginEntryIds(params.config));
|
||||
const registry = loadSetupManifestRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
@@ -376,15 +376,14 @@ function matchesProvider(provider: ProviderPlugin, providerId: string): boolean
|
||||
);
|
||||
}
|
||||
|
||||
function loadSetupManifestRegistry(params?: { workspaceDir?: string; env?: NodeJS.ProcessEnv }) {
|
||||
function loadSetupManifestRegistry(params?: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}) {
|
||||
const env = params?.env ?? process.env;
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env,
|
||||
cache: true,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env,
|
||||
includeDisabled: true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { normalizeProviderId } from "../agents/provider-id.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { getPluginRegistryState } from "./runtime-state.js";
|
||||
|
||||
function uniqueProviderRefs(values: readonly string[]): string[] {
|
||||
@@ -19,12 +18,10 @@ function uniqueProviderRefs(values: readonly string[]): string[] {
|
||||
}
|
||||
|
||||
function resolveManifestSyntheticAuthProviderRefs(): string[] {
|
||||
const index = loadPluginRegistrySnapshot({ cache: true });
|
||||
return uniqueProviderRefs(
|
||||
loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
includeDisabled: true,
|
||||
}).plugins.flatMap((plugin) => plugin.syntheticAuthRefs ?? []),
|
||||
loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true }).plugins.flatMap(
|
||||
(plugin) => plugin.syntheticAuthRefs ?? [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,18 @@ vi.mock("../manifest-registry-installed.js", () => ({
|
||||
) => registryJitiMocks.loadPluginManifestRegistry(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugin-registry.js", () => ({
|
||||
loadPluginRegistrySnapshot: (
|
||||
...args: Parameters<typeof registryJitiMocks.loadPluginRegistrySnapshot>
|
||||
) => registryJitiMocks.loadPluginRegistrySnapshot(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugin-registry.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugin-registry.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadPluginRegistrySnapshot: (
|
||||
...args: Parameters<typeof registryJitiMocks.loadPluginRegistrySnapshot>
|
||||
) => registryJitiMocks.loadPluginRegistrySnapshot(...args),
|
||||
loadPluginManifestRegistryForPluginRegistry: (
|
||||
...args: Parameters<typeof registryJitiMocks.loadPluginManifestRegistry>
|
||||
) => registryJitiMocks.loadPluginManifestRegistry(...args),
|
||||
};
|
||||
});
|
||||
export function resetRegistryJitiMocks(): void {
|
||||
registryJitiMocks.createJiti.mockReset();
|
||||
registryJitiMocks.discoverOpenClawPlugins.mockReset();
|
||||
|
||||
@@ -5,9 +5,8 @@ import {
|
||||
normalizePluginsConfig,
|
||||
resolveEffectivePluginActivationState,
|
||||
} from "./config-state.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { loadBundledWebContentExtractorEntriesFromDir } from "./web-content-extractor-public-artifacts.js";
|
||||
import type { PluginWebContentExtractorEntry } from "./web-content-extractor-types.js";
|
||||
|
||||
@@ -31,13 +30,7 @@ function resolveBundledWebContentExtractorCompatPluginIds(params: {
|
||||
}): string[] {
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
@@ -82,13 +75,7 @@ function resolveEnabledBundledExtractorPlugins(params: {
|
||||
});
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: activation.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: activation.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import path from "node:path";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import type { PluginWebFetchProviderEntry, PluginWebSearchProviderEntry } from "./types.js";
|
||||
import { resolveBundledWebFetchResolutionConfig } from "./web-fetch-providers.shared.js";
|
||||
import {
|
||||
@@ -57,14 +56,8 @@ function resolveBundledManifestRecordsByPluginId(params: {
|
||||
onlyPluginIds: readonly string[];
|
||||
}) {
|
||||
const allowedPluginIds = new Set(params.onlyPluginIds);
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return new Map(
|
||||
loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { resolveBundledPluginCompatibleLoadValues } from "./activation-context.js";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import {
|
||||
createPluginIdScopeSet,
|
||||
normalizePluginIdScope,
|
||||
@@ -65,13 +64,7 @@ function loadInstalledWebProviderManifestRecords(params: {
|
||||
workspaceDir?: string;
|
||||
env?: PluginLoadOptions["env"];
|
||||
}): readonly PluginManifestRecord[] {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
|
||||
import { resolvePluginWebSearchProviders } from "./web-search-providers.runtime.js";
|
||||
|
||||
function hasConfiguredCredentialValue(value: unknown): boolean {
|
||||
@@ -44,12 +43,7 @@ function hasManifestWebSearchEnvCredentialCandidate(params: {
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params.config,
|
||||
env,
|
||||
});
|
||||
return loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
return loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
env,
|
||||
includeDisabled: true,
|
||||
|
||||
@@ -9,13 +9,17 @@ type MockManifestRegistry = {
|
||||
diagnostics: unknown[];
|
||||
};
|
||||
|
||||
const pluginRegistryMocks = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn<() => MockManifestRegistry>(() => ({
|
||||
const pluginRegistryMocks = vi.hoisted(() => {
|
||||
const loadManifestRegistry = vi.fn<() => MockManifestRegistry>(() => ({
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
})),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
}));
|
||||
return {
|
||||
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
|
||||
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
loadPluginManifestRegistryForInstalledIndex:
|
||||
@@ -23,6 +27,8 @@ vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry:
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
export { isSafeChannelEnvVarTriggerName } from "./channel-env-var-names.js";
|
||||
|
||||
type ChannelEnvVarLookupParams = {
|
||||
@@ -33,13 +32,7 @@ function appendUniqueEnvVarCandidates(
|
||||
export function resolveChannelEnvVars(
|
||||
params?: ChannelEnvVarLookupParams,
|
||||
): Record<string, readonly string[]> {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
|
||||
@@ -25,13 +25,17 @@ type MockManifestRegistry = {
|
||||
diagnostics: unknown[];
|
||||
};
|
||||
|
||||
const pluginRegistryMocks = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistryForInstalledIndex: vi.fn<() => MockManifestRegistry>(() => ({
|
||||
const pluginRegistryMocks = vi.hoisted(() => {
|
||||
const loadManifestRegistry = vi.fn<() => MockManifestRegistry>(() => ({
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
})),
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
}));
|
||||
}));
|
||||
return {
|
||||
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
|
||||
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
|
||||
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
loadPluginManifestRegistryForInstalledIndex:
|
||||
@@ -39,6 +43,8 @@ vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry:
|
||||
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry,
|
||||
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { resolveProviderAuthAliasMap } from "../agents/provider-auth-aliases.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
|
||||
import {
|
||||
isWorkspacePluginAllowedByConfig,
|
||||
normalizePluginConfigId,
|
||||
} from "../plugins/plugin-config-trust.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { hasKind } from "../plugins/slots.js";
|
||||
|
||||
const CORE_PROVIDER_AUTH_ENV_VAR_CANDIDATES = {
|
||||
@@ -77,13 +76,7 @@ function appendUniqueEnvVarCandidates(
|
||||
function resolveManifestProviderAuthEnvVarCandidates(
|
||||
params?: ProviderEnvVarLookupParams,
|
||||
): Record<string, string[]> {
|
||||
const index = loadPluginRegistrySnapshot({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
});
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params?.config,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
env: params?.env,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { loadPluginManifestRegistryForInstalledIndex } from "../plugins/manifest-registry-installed.js";
|
||||
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginRegistrySnapshot } from "../plugins/plugin-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { loadBundledChannelSecretContractApi } from "./channel-contract-api.js";
|
||||
import type { SecretTargetRegistryEntry } from "./target-registry-types.js";
|
||||
|
||||
@@ -50,11 +49,8 @@ function hasWebProviderContract(
|
||||
|
||||
function listBundledWebProviderSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
|
||||
const entries: SecretTargetRegistryEntry[] = [];
|
||||
const index = loadPluginRegistrySnapshot({});
|
||||
for (const record of loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
includeDisabled: true,
|
||||
}).plugins) {
|
||||
for (const record of loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true })
|
||||
.plugins) {
|
||||
if (record.origin !== "bundled") {
|
||||
continue;
|
||||
}
|
||||
@@ -73,11 +69,8 @@ function listBundledWebProviderSecretTargetRegistryEntries(): SecretTargetRegist
|
||||
function listChannelSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
|
||||
const entries: SecretTargetRegistryEntry[] = [];
|
||||
|
||||
const index = loadPluginRegistrySnapshot({});
|
||||
for (const record of loadPluginManifestRegistryForInstalledIndex({
|
||||
index,
|
||||
includeDisabled: true,
|
||||
}).plugins) {
|
||||
for (const record of loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true })
|
||||
.plugins) {
|
||||
if (record.origin !== "bundled") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
sanitizeSupportSnapshotValue,
|
||||
type SupportRedactionContext,
|
||||
} from "../logging/diagnostic-support-redaction.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
|
||||
import { getActivePluginRegistry, listImportedRuntimePluginIds } from "../plugins/runtime.js";
|
||||
import { VERSION } from "../version.js";
|
||||
|
||||
@@ -136,10 +136,11 @@ function buildPluginsFromManifest(params: {
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}) {
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
return {
|
||||
source: "manifest-registry",
|
||||
|
||||
@@ -16,13 +16,13 @@ export type ConfigurablePlugin = {
|
||||
jsonSchema?: JsonSchemaObject;
|
||||
};
|
||||
|
||||
type ManifestRegistryModule = typeof import("../plugins/manifest-registry.js");
|
||||
type PluginRegistryModule = typeof import("../plugins/plugin-registry.js");
|
||||
|
||||
let manifestRegistryModulePromise: Promise<ManifestRegistryModule> | undefined;
|
||||
let pluginRegistryModulePromise: Promise<PluginRegistryModule> | undefined;
|
||||
|
||||
function loadManifestRegistryModule(): Promise<ManifestRegistryModule> {
|
||||
manifestRegistryModulePromise ??= import("../plugins/manifest-registry.js");
|
||||
return manifestRegistryModulePromise;
|
||||
function loadPluginRegistryModule(): Promise<PluginRegistryModule> {
|
||||
pluginRegistryModulePromise ??= import("../plugins/plugin-registry.js");
|
||||
return pluginRegistryModulePromise;
|
||||
}
|
||||
|
||||
type JsonSchemaProperty = {
|
||||
@@ -299,10 +299,11 @@ export async function setupPluginConfig(params: {
|
||||
prompter: WizardPrompter;
|
||||
workspaceDir?: string;
|
||||
}): Promise<OpenClawConfig> {
|
||||
const { loadPluginManifestRegistry } = await loadManifestRegistryModule();
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const { loadPluginManifestRegistryForPluginRegistry } = await loadPluginRegistryModule();
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
const unconfigured = discoverUnconfiguredPlugins({
|
||||
@@ -361,10 +362,11 @@ export async function configurePluginConfig(params: {
|
||||
prompter: WizardPrompter;
|
||||
workspaceDir?: string;
|
||||
}): Promise<OpenClawConfig> {
|
||||
const { loadPluginManifestRegistry } = await loadManifestRegistryModule();
|
||||
const registry = loadPluginManifestRegistry({
|
||||
const { loadPluginManifestRegistryForPluginRegistry } = await loadPluginRegistryModule();
|
||||
const registry = loadPluginManifestRegistryForPluginRegistry({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
const configurable = discoverConfigurablePlugins({
|
||||
|
||||
Reference in New Issue
Block a user