





















@@ -1,5 +1,6 @@
1-import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
1+import { listOpenClawPluginManifestMetadata } from "../plugins/manifest-metadata-scan.js";
22import {
3+normalizeLowercaseStringOrEmpty,
34normalizeOptionalLowercaseString,
45normalizeOptionalString,
56} from "../shared/string-coerce.js";
@@ -224,57 +225,123 @@ function isManifestProviderEndpointClass(value: string): value is ProviderEndpoi
224225return MANIFEST_PROVIDER_ENDPOINT_CLASSES.has(value as ProviderEndpointClass);
225226}
226227228+function isRecord(value: unknown): value is Record<string, unknown> {
229+return Boolean(value) && typeof value === "object" && !Array.isArray(value);
230+}
231+232+function normalizeStringList(value: unknown): string[] {
233+if (!Array.isArray(value)) {
234+return [];
235+}
236+return value
237+.map((entry) => normalizeOptionalString(entry))
238+.filter((entry): entry is string => entry !== undefined);
239+}
240+241+function readManifestProviderEndpoints(
242+manifest: Record<string, unknown>,
243+): ManifestProviderEndpointCacheEntry[] {
244+if (!Array.isArray(manifest.providerEndpoints)) {
245+return [];
246+}
247+const entries: ManifestProviderEndpointCacheEntry[] = [];
248+for (const rawEndpoint of manifest.providerEndpoints) {
249+if (!isRecord(rawEndpoint)) {
250+continue;
251+}
252+const endpointClassRaw = normalizeOptionalString(rawEndpoint.endpointClass);
253+if (!endpointClassRaw || !isManifestProviderEndpointClass(endpointClassRaw)) {
254+continue;
255+}
256+entries.push({
257+endpointClass: endpointClassRaw,
258+hosts: normalizeStringList(rawEndpoint.hosts).map((host) => host.toLowerCase()),
259+hostSuffixes: normalizeStringList(rawEndpoint.hostSuffixes).map((host) => host.toLowerCase()),
260+normalizedBaseUrls: normalizeStringList(rawEndpoint.baseUrls)
261+.map((baseUrl) => normalizeComparableBaseUrl(baseUrl))
262+.filter((baseUrl): baseUrl is string => baseUrl !== undefined),
263+ ...(normalizeOptionalString(rawEndpoint.googleVertexRegion)
264+ ? { googleVertexRegion: normalizeOptionalString(rawEndpoint.googleVertexRegion) }
265+ : {}),
266+ ...(normalizeOptionalString(rawEndpoint.googleVertexRegionHostSuffix)
267+ ? {
268+googleVertexRegionHostSuffix: normalizeOptionalString(
269+rawEndpoint.googleVertexRegionHostSuffix,
270+),
271+}
272+ : {}),
273+});
274+}
275+return entries;
276+}
277+278+function readManifestProviderRequests(
279+manifest: Record<string, unknown>,
280+): Array<[string, ManifestProviderRequestCacheEntry]> {
281+const providerRequest = manifest.providerRequest;
282+if (!isRecord(providerRequest) || !isRecord(providerRequest.providers)) {
283+return [];
284+}
285+const entries: Array<[string, ManifestProviderRequestCacheEntry]> = [];
286+for (const [providerRaw, requestRaw] of Object.entries(providerRequest.providers)) {
287+if (!isRecord(requestRaw)) {
288+continue;
289+}
290+const provider = normalizeLowercaseStringOrEmpty(providerRaw);
291+if (!provider) {
292+continue;
293+}
294+const compatibilityFamily =
295+normalizeOptionalString(requestRaw.compatibilityFamily) === "moonshot"
296+ ? "moonshot"
297+ : undefined;
298+const supportsStreamingUsage = isRecord(requestRaw.openAICompletions)
299+ ? requestRaw.openAICompletions.supportsStreamingUsage
300+ : undefined;
301+entries.push([
302+provider,
303+{
304+ ...(normalizeOptionalString(requestRaw.family)
305+ ? { family: normalizeOptionalString(requestRaw.family) }
306+ : {}),
307+ ...(compatibilityFamily ? { compatibilityFamily } : {}),
308+ ...(typeof supportsStreamingUsage === "boolean"
309+ ? { supportsOpenAICompletionsStreamingUsageCompat: supportsStreamingUsage }
310+ : {}),
311+},
312+]);
313+}
314+return entries;
315+}
316+317+function collectManifestProviderEndpoints(): ManifestProviderEndpointCacheEntry[] {
318+const entries: ManifestProviderEndpointCacheEntry[] = [];
319+for (const { manifest } of listOpenClawPluginManifestMetadata()) {
320+entries.push(...readManifestProviderEndpoints(manifest));
321+}
322+return entries;
323+}
324+325+function collectManifestProviderRequests(): Map<string, ManifestProviderRequestCacheEntry> {
326+const entries = new Map<string, ManifestProviderRequestCacheEntry>();
327+for (const { manifest } of listOpenClawPluginManifestMetadata()) {
328+for (const [provider, request] of readManifestProviderRequests(manifest)) {
329+entries.set(provider, request);
330+}
331+}
332+return entries;
333+}
334+227335function loadManifestProviderEndpointCache(): ManifestProviderEndpointCacheEntry[] {
228336if (!manifestProviderEndpointCache) {
229-const registry = loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true });
230-const entries: ManifestProviderEndpointCacheEntry[] = [];
231-for (const plugin of registry.plugins) {
232-for (const endpoint of plugin.providerEndpoints ?? []) {
233-if (!isManifestProviderEndpointClass(endpoint.endpointClass)) {
234-continue;
235-}
236-entries.push({
237-endpointClass: endpoint.endpointClass,
238-hosts: (endpoint.hosts ?? []).map((host) => host.toLowerCase()),
239-hostSuffixes: (endpoint.hostSuffixes ?? []).map((host) => host.toLowerCase()),
240-normalizedBaseUrls: (endpoint.baseUrls ?? [])
241-.map((baseUrl) => normalizeComparableBaseUrl(baseUrl))
242-.filter((baseUrl): baseUrl is string => baseUrl !== undefined),
243- ...(endpoint.googleVertexRegion
244- ? { googleVertexRegion: endpoint.googleVertexRegion }
245- : {}),
246- ...(endpoint.googleVertexRegionHostSuffix
247- ? { googleVertexRegionHostSuffix: endpoint.googleVertexRegionHostSuffix }
248- : {}),
249-});
250-}
251-}
252-manifestProviderEndpointCache = entries;
337+manifestProviderEndpointCache = collectManifestProviderEndpoints();
253338}
254339return manifestProviderEndpointCache;
255340}
256341257342function loadManifestProviderRequestCache(): Map<string, ManifestProviderRequestCacheEntry> {
258343if (!manifestProviderRequestCache) {
259-const registry = loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true });
260-const entries = new Map<string, ManifestProviderRequestCacheEntry>();
261-for (const plugin of registry.plugins) {
262-for (const [provider, request] of Object.entries(plugin.providerRequest?.providers ?? {})) {
263-entries.set(provider, {
264- ...(request.family ? { family: request.family } : {}),
265- ...(request.compatibilityFamily
266- ? { compatibilityFamily: request.compatibilityFamily }
267- : {}),
268- ...(request.openAICompletions?.supportsStreamingUsage !== undefined
269- ? {
270-supportsOpenAICompletionsStreamingUsageCompat:
271-request.openAICompletions.supportsStreamingUsage,
272-}
273- : {}),
274-});
275-}
276-}
277-manifestProviderRequestCache = entries;
344+manifestProviderRequestCache = collectManifestProviderRequests();
278345}
279346return manifestProviderRequestCache;
280347}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。