mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:50:45 +00:00
test(plugins): route tts contract helper changes narrowly
This commit is contained in:
@@ -215,6 +215,15 @@ const BROAD_CHANGED_RERUN_PATTERNS = [
|
||||
/^test\/vitest\/vitest\.(?:config|shared\.config|scoped-config|performance-config)\.ts$/u,
|
||||
/^test\/helpers\//u,
|
||||
];
|
||||
const PRECISE_SOURCE_TEST_TARGETS = new Map([
|
||||
[
|
||||
"test/helpers/plugins/tts-contract-suites.ts",
|
||||
[
|
||||
"src/plugins/contracts/core-extension-facade-boundary.test.ts",
|
||||
"src/plugins/contracts/tts.contract.test.ts",
|
||||
],
|
||||
],
|
||||
]);
|
||||
const TOOLING_SOURCE_TEST_TARGETS = new Map([
|
||||
["scripts/changed-lanes.mjs", ["test/scripts/changed-lanes.test.ts"]],
|
||||
["scripts/check-changed.mjs", ["test/scripts/changed-lanes.test.ts"]],
|
||||
@@ -239,6 +248,7 @@ const TOOLING_TEST_TARGETS = new Map([
|
||||
],
|
||||
]);
|
||||
const SOURCE_TEST_TARGETS = new Map([
|
||||
...PRECISE_SOURCE_TEST_TARGETS,
|
||||
["src/agents/live-model-turn-probes.ts", ["src/agents/live-model-turn-probes.test.ts"]],
|
||||
[
|
||||
"src/auto-reply/reply/dispatch-from-config.ts",
|
||||
@@ -487,15 +497,16 @@ function stripChangedArgs(args) {
|
||||
|
||||
function shouldKeepBroadChangedRun(changedPaths) {
|
||||
return changedPaths.some((changedPath) =>
|
||||
BROAD_CHANGED_RERUN_PATTERNS.some((pattern) => pattern.test(changedPath)),
|
||||
PRECISE_SOURCE_TEST_TARGETS.has(changedPath)
|
||||
? false
|
||||
: BROAD_CHANGED_RERUN_PATTERNS.some((pattern) => pattern.test(changedPath)),
|
||||
);
|
||||
}
|
||||
|
||||
function resolveToolingChangedTestTargets(changedPaths) {
|
||||
const targets = [];
|
||||
for (const changedPath of changedPaths) {
|
||||
const testTargets =
|
||||
TOOLING_SOURCE_TEST_TARGETS.get(changedPath) ?? TOOLING_TEST_TARGETS.get(changedPath);
|
||||
const testTargets = resolveToolingTestTargets(changedPath);
|
||||
if (!testTargets) {
|
||||
return null;
|
||||
}
|
||||
@@ -504,6 +515,10 @@ function resolveToolingChangedTestTargets(changedPaths) {
|
||||
return [...new Set(targets)];
|
||||
}
|
||||
|
||||
function resolveToolingTestTargets(changedPath) {
|
||||
return TOOLING_SOURCE_TEST_TARGETS.get(changedPath) ?? TOOLING_TEST_TARGETS.get(changedPath);
|
||||
}
|
||||
|
||||
function isRoutableChangedTarget(changedPath) {
|
||||
if (GENERATED_CHANGED_TEST_TARGETS.has(changedPath)) {
|
||||
return false;
|
||||
@@ -530,7 +545,8 @@ export function resolveChangedTestTargetPlan(changedPaths) {
|
||||
return { mode: "broad", targets: [] };
|
||||
}
|
||||
const targets = changedPaths.flatMap((changedPath) => {
|
||||
const mappedTargets = SOURCE_TEST_TARGETS.get(changedPath);
|
||||
const mappedTargets =
|
||||
resolveToolingTestTargets(changedPath) ?? SOURCE_TEST_TARGETS.get(changedPath);
|
||||
if (mappedTargets) {
|
||||
return mappedTargets;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export type BundledPluginContractSnapshot = {
|
||||
pluginId: string;
|
||||
cliBackendIds: string[];
|
||||
providerIds: string[];
|
||||
providerAuthEnvVars: Record<string, string[]>;
|
||||
speechProviderIds: string[];
|
||||
realtimeTranscriptionProviderIds: string[];
|
||||
realtimeVoiceProviderIds: string[];
|
||||
@@ -47,6 +48,7 @@ export type BundledCapabilityManifest = Pick<
|
||||
| "cliBackends"
|
||||
| "contracts"
|
||||
| "legacyPluginIds"
|
||||
| "providerAuthEnvVars"
|
||||
| "providers"
|
||||
>;
|
||||
|
||||
@@ -98,6 +100,26 @@ function listBundledCapabilityManifests(): readonly BundledCapabilityManifest[]
|
||||
|
||||
const BUNDLED_CAPABILITY_MANIFESTS = listBundledCapabilityManifests();
|
||||
|
||||
function normalizeStringListRecord(record: unknown): Record<string, string[]> {
|
||||
if (!record || typeof record !== "object" || Array.isArray(record)) {
|
||||
return {};
|
||||
}
|
||||
return Object.fromEntries(
|
||||
Object.entries(record)
|
||||
.map(
|
||||
([key, values]) =>
|
||||
[
|
||||
key.trim(),
|
||||
uniqueStrings(Array.isArray(values) ? values : [], (value) =>
|
||||
typeof value === "string" ? value.trim() : "",
|
||||
),
|
||||
] as const,
|
||||
)
|
||||
.filter(([key, values]) => key && values.length > 0)
|
||||
.toSorted(([left], [right]) => left.localeCompare(right)),
|
||||
);
|
||||
}
|
||||
|
||||
export function buildBundledPluginContractSnapshot(
|
||||
manifest: BundledCapabilityManifest,
|
||||
): BundledPluginContractSnapshot {
|
||||
@@ -105,6 +127,7 @@ export function buildBundledPluginContractSnapshot(
|
||||
pluginId: manifest.id,
|
||||
cliBackendIds: uniqueStrings(manifest.cliBackends, (value) => value.trim()),
|
||||
providerIds: uniqueStrings(manifest.providers, (value) => value.trim()),
|
||||
providerAuthEnvVars: normalizeStringListRecord(manifest.providerAuthEnvVars),
|
||||
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders, (value) => value.trim()),
|
||||
realtimeTranscriptionProviderIds: uniqueStrings(
|
||||
manifest.contracts?.realtimeTranscriptionProviders,
|
||||
@@ -188,8 +211,13 @@ export const BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS = Object.fromEntries(
|
||||
).toSorted(([left], [right]) => left.localeCompare(right)),
|
||||
) as Readonly<Record<string, string>>;
|
||||
|
||||
type BundledContractIdSnapshotKey = Exclude<
|
||||
keyof Omit<BundledPluginContractSnapshot, "pluginId">,
|
||||
"providerAuthEnvVars"
|
||||
>;
|
||||
|
||||
export function resolveBundledContractSnapshotPluginIds(
|
||||
key: keyof Omit<BundledPluginContractSnapshot, "pluginId">,
|
||||
key: BundledContractIdSnapshotKey,
|
||||
): string[] {
|
||||
return BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.filter((entry) => entry[key].length > 0)
|
||||
.map((entry) => entry.pluginId)
|
||||
|
||||
@@ -75,12 +75,24 @@ type ManifestContractKey =
|
||||
|
||||
type ManifestRegistryContractKey = "webFetchProviders" | "webSearchProviders";
|
||||
|
||||
function normalizeProviderAuthEnvVars(
|
||||
providerAuthEnvVars: Record<string, string[]> | undefined,
|
||||
): Record<string, string[]> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(providerAuthEnvVars ?? {}).map(([providerId, envVars]) => [
|
||||
providerId,
|
||||
uniqueStrings(envVars),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
function resolveBundledManifestContracts(): PluginRegistrationContractEntry[] {
|
||||
if (process.env.VITEST) {
|
||||
return BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.map((entry) => ({
|
||||
pluginId: entry.pluginId,
|
||||
cliBackendIds: [...entry.cliBackendIds],
|
||||
providerIds: [...entry.providerIds],
|
||||
providerAuthEnvVars: normalizeProviderAuthEnvVars(entry.providerAuthEnvVars),
|
||||
speechProviderIds: [...entry.speechProviderIds],
|
||||
realtimeTranscriptionProviderIds: [...entry.realtimeTranscriptionProviderIds],
|
||||
realtimeVoiceProviderIds: [...entry.realtimeVoiceProviderIds],
|
||||
@@ -118,6 +130,7 @@ function resolveBundledManifestContracts(): PluginRegistrationContractEntry[] {
|
||||
pluginId: plugin.id,
|
||||
cliBackendIds: uniqueStrings(plugin.cliBackends),
|
||||
providerIds: uniqueStrings(plugin.providers),
|
||||
providerAuthEnvVars: normalizeProviderAuthEnvVars(plugin.providerAuthEnvVars),
|
||||
speechProviderIds: uniqueStrings(plugin.contracts?.speechProviders ?? []),
|
||||
realtimeTranscriptionProviderIds: uniqueStrings(
|
||||
plugin.contracts?.realtimeTranscriptionProviders ?? [],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS } from "../../../src/plugins/contracts/inventory/bundled-capability-metadata.js";
|
||||
import { createEmptyPluginRegistry } from "../../../src/plugins/registry-empty.js";
|
||||
import { setActivePluginRegistry } from "../../../src/plugins/runtime.js";
|
||||
import type { SpeechProviderPlugin } from "../../../src/plugins/types.js";
|
||||
@@ -37,16 +38,12 @@ let formatTtsProviderError: TtsRuntimeModule["_test"]["formatTtsProviderError"];
|
||||
let sanitizeTtsErrorForLog: TtsRuntimeModule["_test"]["sanitizeTtsErrorForLog"];
|
||||
|
||||
const SPEECH_PROVIDER_ENV_KEYS = [
|
||||
"ELEVENLABS_API_KEY",
|
||||
"GEMINI_API_KEY",
|
||||
"GOOGLE_API_KEY",
|
||||
"GRADIUM_API_KEY",
|
||||
"MINIMAX_API_KEY",
|
||||
"OPENAI_API_KEY",
|
||||
"VYDRA_API_KEY",
|
||||
"XAI_API_KEY",
|
||||
"XI_API_KEY",
|
||||
] as const;
|
||||
...new Set(
|
||||
BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.flatMap((entry) =>
|
||||
entry.speechProviderIds.flatMap((providerId) => entry.providerAuthEnvVars[providerId] ?? []),
|
||||
),
|
||||
),
|
||||
].toSorted((left, right) => left.localeCompare(right));
|
||||
|
||||
function isolatedSpeechProviderEnv(
|
||||
overrides: Record<string, string | undefined> = {},
|
||||
|
||||
@@ -137,6 +137,17 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("routes precise plugin contract helpers without broad-running every shard", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"test/helpers/plugins/tts-contract-suites.ts",
|
||||
]),
|
||||
).toEqual([
|
||||
"src/plugins/contracts/core-extension-facade-boundary.test.ts",
|
||||
"src/plugins/contracts/tts.contract.test.ts",
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run for unknown root surfaces", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
|
||||
|
||||
Reference in New Issue
Block a user