mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 17:51:22 +00:00
refactor: dedupe plugin contract string normalization
This commit is contained in:
@@ -5,41 +5,48 @@ import {
|
||||
BUNDLED_LEGACY_PLUGIN_ID_ALIASES,
|
||||
BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS,
|
||||
} from "./contracts/inventory/bundled-capability-metadata.js";
|
||||
|
||||
function uniqueStrings(values: readonly string[] | undefined): string[] {
|
||||
const result: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const value of values ?? []) {
|
||||
const normalized = value.trim();
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
result.push(normalized);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
import { uniqueStrings } from "./contracts/shared.js";
|
||||
|
||||
describe("bundled capability metadata", () => {
|
||||
it("keeps contract snapshots aligned with bundled plugin manifests", () => {
|
||||
const expected = listBundledPluginMetadata()
|
||||
.map(({ manifest }) => ({
|
||||
pluginId: manifest.id,
|
||||
providerIds: uniqueStrings(manifest.providers),
|
||||
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders),
|
||||
providerIds: uniqueStrings(manifest.providers, (value) => value.trim()),
|
||||
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
realtimeTranscriptionProviderIds: uniqueStrings(
|
||||
manifest.contracts?.realtimeTranscriptionProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
realtimeVoiceProviderIds: uniqueStrings(
|
||||
manifest.contracts?.realtimeVoiceProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
realtimeVoiceProviderIds: uniqueStrings(manifest.contracts?.realtimeVoiceProviders),
|
||||
mediaUnderstandingProviderIds: uniqueStrings(
|
||||
manifest.contracts?.mediaUnderstandingProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
imageGenerationProviderIds: uniqueStrings(manifest.contracts?.imageGenerationProviders),
|
||||
videoGenerationProviderIds: uniqueStrings(manifest.contracts?.videoGenerationProviders),
|
||||
musicGenerationProviderIds: uniqueStrings(manifest.contracts?.musicGenerationProviders),
|
||||
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders),
|
||||
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders),
|
||||
toolNames: uniqueStrings(manifest.contracts?.tools),
|
||||
imageGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.imageGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
videoGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.videoGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
musicGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.musicGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
toolNames: uniqueStrings(manifest.contracts?.tools, (value) => value.trim()),
|
||||
}))
|
||||
.filter(
|
||||
(entry) =>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { listBundledPluginMetadata } from "../../bundled-plugin-metadata.js";
|
||||
import { uniqueStrings } from "../shared.js";
|
||||
|
||||
// Build/test inventory only.
|
||||
// Runtime code should prefer manifest/runtime registry queries instead of these snapshots.
|
||||
@@ -19,20 +20,6 @@ export type BundledPluginContractSnapshot = {
|
||||
toolNames: string[];
|
||||
};
|
||||
|
||||
function uniqueStrings(values: readonly string[] | undefined): string[] {
|
||||
const result: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const value of values ?? []) {
|
||||
const normalized = value.trim();
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
result.push(normalized);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const BUNDLED_PLUGIN_METADATA_FOR_CAPABILITIES = listBundledPluginMetadata({
|
||||
includeChannelConfigs: false,
|
||||
includeSyntheticChannelConfigs: false,
|
||||
@@ -41,20 +28,39 @@ const BUNDLED_PLUGIN_METADATA_FOR_CAPABILITIES = listBundledPluginMetadata({
|
||||
export const BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS: readonly BundledPluginContractSnapshot[] =
|
||||
BUNDLED_PLUGIN_METADATA_FOR_CAPABILITIES.map(({ manifest }) => ({
|
||||
pluginId: manifest.id,
|
||||
cliBackendIds: uniqueStrings(manifest.cliBackends),
|
||||
providerIds: uniqueStrings(manifest.providers),
|
||||
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders),
|
||||
cliBackendIds: uniqueStrings(manifest.cliBackends, (value) => value.trim()),
|
||||
providerIds: uniqueStrings(manifest.providers, (value) => value.trim()),
|
||||
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders, (value) => value.trim()),
|
||||
realtimeTranscriptionProviderIds: uniqueStrings(
|
||||
manifest.contracts?.realtimeTranscriptionProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
realtimeVoiceProviderIds: uniqueStrings(manifest.contracts?.realtimeVoiceProviders),
|
||||
mediaUnderstandingProviderIds: uniqueStrings(manifest.contracts?.mediaUnderstandingProviders),
|
||||
imageGenerationProviderIds: uniqueStrings(manifest.contracts?.imageGenerationProviders),
|
||||
videoGenerationProviderIds: uniqueStrings(manifest.contracts?.videoGenerationProviders),
|
||||
musicGenerationProviderIds: uniqueStrings(manifest.contracts?.musicGenerationProviders),
|
||||
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders),
|
||||
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders),
|
||||
toolNames: uniqueStrings(manifest.contracts?.tools),
|
||||
realtimeVoiceProviderIds: uniqueStrings(manifest.contracts?.realtimeVoiceProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
mediaUnderstandingProviderIds: uniqueStrings(
|
||||
manifest.contracts?.mediaUnderstandingProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
imageGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.imageGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
videoGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.videoGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
musicGenerationProviderIds: uniqueStrings(
|
||||
manifest.contracts?.musicGenerationProviders,
|
||||
(value) => value.trim(),
|
||||
),
|
||||
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders, (value) =>
|
||||
value.trim(),
|
||||
),
|
||||
toolNames: uniqueStrings(manifest.contracts?.tools, (value) => value.trim()),
|
||||
}))
|
||||
.filter(
|
||||
(entry) =>
|
||||
|
||||
@@ -16,6 +16,7 @@ import type {
|
||||
WebSearchProviderPlugin,
|
||||
} from "../types.js";
|
||||
import { BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS } from "./inventory/bundled-capability-metadata.js";
|
||||
import { uniqueStrings } from "./shared.js";
|
||||
import {
|
||||
loadVitestImageGenerationProviderContractRegistry,
|
||||
loadVitestMediaUnderstandingProviderContractRegistry,
|
||||
@@ -79,19 +80,6 @@ type ManifestContractKey =
|
||||
|
||||
type ManifestRegistryContractKey = "webFetchProviders" | "webSearchProviders";
|
||||
|
||||
function uniqueStrings(values: readonly string[]): string[] {
|
||||
const result: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const value of values) {
|
||||
if (seen.has(value)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(value);
|
||||
result.push(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function resolveBundledManifestContracts(): PluginRegistrationContractEntry[] {
|
||||
if (process.env.VITEST) {
|
||||
return BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.map((entry) => ({
|
||||
|
||||
16
src/plugins/contracts/shared.ts
Normal file
16
src/plugins/contracts/shared.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export function uniqueStrings(
|
||||
values: readonly string[] | undefined,
|
||||
normalize: (value: string) => string = (value) => value,
|
||||
): string[] {
|
||||
const result: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const value of values ?? []) {
|
||||
const normalized = normalize(value);
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
result.push(normalized);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user