perf(tests): trim hot wizard and infra setup work

This commit is contained in:
Vincent Koc
2026-04-14 22:42:21 +01:00
parent 85eac42d34
commit c6c222ba84
8 changed files with 134 additions and 104 deletions

View File

@@ -0,0 +1,87 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { isRecord } from "../utils.js";
export type CodexNativeSearchMode = "cached" | "live";
export type CodexNativeSearchContextSize = "low" | "medium" | "high";
export type CodexNativeSearchUserLocation = {
country?: string;
region?: string;
city?: string;
timezone?: string;
};
export type ResolvedCodexNativeWebSearchConfig = {
enabled: boolean;
mode: CodexNativeSearchMode;
allowedDomains?: string[];
contextSize?: CodexNativeSearchContextSize;
userLocation?: CodexNativeSearchUserLocation;
};
function normalizeAllowedDomains(value: unknown): string[] | undefined {
if (!Array.isArray(value)) {
return undefined;
}
const deduped = [
...new Set(
value
.map((entry) => (typeof entry === "string" ? entry.trim() : null))
.filter((entry): entry is string => Boolean(entry)),
),
];
return deduped.length > 0 ? deduped : undefined;
}
function normalizeContextSize(value: unknown): CodexNativeSearchContextSize | undefined {
if (value === "low" || value === "medium" || value === "high") {
return value;
}
return undefined;
}
function normalizeMode(value: unknown): CodexNativeSearchMode {
return value === "live" ? "live" : "cached";
}
function normalizeUserLocation(value: unknown): CodexNativeSearchUserLocation | undefined {
if (!isRecord(value)) {
return undefined;
}
const location = {
country: typeof value.country === "string" ? value.country.trim() || undefined : undefined,
region: typeof value.region === "string" ? value.region.trim() || undefined : undefined,
city: typeof value.city === "string" ? value.city.trim() || undefined : undefined,
timezone: typeof value.timezone === "string" ? value.timezone.trim() || undefined : undefined,
};
return location.country || location.region || location.city || location.timezone
? location
: undefined;
}
export function resolveCodexNativeWebSearchConfig(
config: OpenClawConfig | undefined,
): ResolvedCodexNativeWebSearchConfig {
const nativeConfig = config?.tools?.web?.search?.openaiCodex;
return {
enabled: nativeConfig?.enabled === true,
mode: normalizeMode(nativeConfig?.mode),
allowedDomains: normalizeAllowedDomains(nativeConfig?.allowedDomains),
contextSize: normalizeContextSize(nativeConfig?.contextSize),
userLocation: normalizeUserLocation(nativeConfig?.userLocation),
};
}
export function describeCodexNativeWebSearch(
config: OpenClawConfig | undefined,
): string | undefined {
if (config?.tools?.web?.search?.enabled === false) {
return undefined;
}
const nativeConfig = resolveCodexNativeWebSearchConfig(config);
if (!nativeConfig.enabled) {
return undefined;
}
return `Codex native search: ${nativeConfig.mode} for Codex-capable models`;
}

View File

@@ -1,8 +1,12 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { isRecord } from "../utils.js";
import { ensureAuthProfileStore, listProfilesForProvider } from "./auth-profiles.js";
import { resolveCodexNativeWebSearchConfig } from "./codex-native-web-search.shared.js";
import { resolveDefaultModelForAgent } from "./model-selection.js";
export {
describeCodexNativeWebSearch,
resolveCodexNativeWebSearchConfig,
} from "./codex-native-web-search.shared.js";
export type CodexNativeSearchMode = "cached" | "live";
export type CodexNativeSearchContextSize = "low" | "medium" | "high";
@@ -40,59 +44,6 @@ export type CodexNativeSearchPayloadPatchResult = {
status: "payload_not_object" | "native_tool_already_present" | "injected";
};
function normalizeAllowedDomains(value: unknown): string[] | undefined {
if (!Array.isArray(value)) {
return undefined;
}
const deduped = [
...new Set(
value
.map((entry) => normalizeOptionalString(entry))
.filter((entry): entry is string => typeof entry === "string"),
),
];
return deduped.length > 0 ? deduped : undefined;
}
function normalizeContextSize(value: unknown): CodexNativeSearchContextSize | undefined {
if (value === "low" || value === "medium" || value === "high") {
return value;
}
return undefined;
}
function normalizeMode(value: unknown): CodexNativeSearchMode {
return value === "live" ? "live" : "cached";
}
function normalizeUserLocation(value: unknown): CodexNativeSearchUserLocation | undefined {
if (!isRecord(value)) {
return undefined;
}
const location = {
country: normalizeOptionalString(value.country),
region: normalizeOptionalString(value.region),
city: normalizeOptionalString(value.city),
timezone: normalizeOptionalString(value.timezone),
};
return location.country || location.region || location.city || location.timezone
? location
: undefined;
}
export function resolveCodexNativeWebSearchConfig(
config: OpenClawConfig | undefined,
): ResolvedCodexNativeWebSearchConfig {
const nativeConfig = config?.tools?.web?.search?.openaiCodex;
return {
enabled: nativeConfig?.enabled === true,
mode: normalizeMode(nativeConfig?.mode),
allowedDomains: normalizeAllowedDomains(nativeConfig?.allowedDomains),
contextSize: normalizeContextSize(nativeConfig?.contextSize),
userLocation: normalizeUserLocation(nativeConfig?.userLocation),
};
}
export function isCodexNativeSearchEligibleModel(params: {
modelProvider?: string;
modelApi?: string;
@@ -286,17 +237,3 @@ export function isCodexNativeWebSearchRelevant(params: {
modelApi: configuredModelApi ?? configuredProvider?.api,
});
}
export function describeCodexNativeWebSearch(
config: OpenClawConfig | undefined,
): string | undefined {
if (config?.tools?.web?.search?.enabled === false) {
return undefined;
}
const nativeConfig = resolveCodexNativeWebSearchConfig(config);
if (!nativeConfig.enabled) {
return undefined;
}
return `Codex native search: ${nativeConfig.mode} for Codex-capable models`;
}

View File

@@ -30,7 +30,7 @@ export function resolveOpenAIReasoningEffortMap(
): Record<string, string> {
const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
const builtinMap =
const builtinMap: Record<string, string> =
(provider === "openai" || provider === "openai-codex") &&
OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id)
? { minimal: "medium", low: "medium" }

View File

@@ -754,6 +754,20 @@ function resolveOpenAIReasoningEffort(
) as Exclude<OpenAIApiReasoningEffort, "none">;
}
function coerceOpenAIApiReasoningEffort(effort: string): OpenAIApiReasoningEffort {
const normalized = normalizeOpenAIReasoningEffort(effort);
switch (normalized) {
case "none":
case "low":
case "medium":
case "high":
case "xhigh":
return normalized;
default:
return "high";
}
}
export function buildOpenAIResponsesParams(
model: Model<Api>,
context: Context,
@@ -799,12 +813,17 @@ export function buildOpenAIResponsesParams(
}
if (model.reasoning) {
if (options?.reasoningEffort || options?.reasoning || options?.reasoningSummary) {
const reasoningEffort = mapOpenAIReasoningEffortForModel({
model,
effort: resolveOpenAIReasoningEffort(options),
});
const requestedReasoningEffort = resolveOpenAIReasoningEffort(options);
const reasoningEffort = coerceOpenAIApiReasoningEffort(
mapOpenAIReasoningEffortForModel({
model,
effort: requestedReasoningEffort,
}) ?? requestedReasoningEffort,
);
const normalizedReasoningEffort: Exclude<OpenAIApiReasoningEffort, "none"> =
reasoningEffort === "none" ? "high" : reasoningEffort;
params.reasoning = {
effort: reasoningEffort ?? "high",
effort: normalizedReasoningEffort,
summary: options?.reasoningSummary || "auto",
};
params.include = ["reasoning.encrypted_content"];

View File

@@ -1,5 +1,6 @@
import fsPromises from "node:fs/promises";
import nodePath from "node:path";
import { describeCodexNativeWebSearch } from "../agents/codex-native-web-search.shared.js";
import { formatCliCommand } from "../cli/command-format.js";
import { readConfigFileSnapshot, replaceConfigFile, resolveGatewayPort } from "../config/config.js";
import { logConfigUpdated } from "../config/logging.js";
@@ -165,8 +166,7 @@ async function promptWebToolsConfig(
const existingSearch = nextConfig.tools?.web?.search;
const existingFetch = nextConfig.tools?.web?.fetch;
const { resolveSearchProviderOptions, setupSearch } = await import("./onboard-search.js");
const { describeCodexNativeWebSearch, isCodexNativeWebSearchRelevant } =
await import("../agents/codex-native-web-search.js");
const { isCodexNativeWebSearchRelevant } = await import("../agents/codex-native-web-search.js");
const searchProviderOptions = resolveSearchProviderOptions(nextConfig);
note(

View File

@@ -776,13 +776,20 @@ describe.skipIf(isWindows)("restart-stale-pids", () => {
const stalePid = process.pid + 911;
Object.defineProperty(process, "platform", { value: "win32", configurable: true });
try {
let fakeNow = 0;
__testing.setDateNowOverride(() => fakeNow);
mockReadWindowsListeningPids.mockReturnValue([stalePid]);
mockReadWindowsProcessArgs.mockReturnValue(["openclaw", "gateway"]);
mockReadWindowsProcessArgsResult.mockReturnValue({
ok: true,
args: ["openclaw", "gateway"],
});
mockReadWindowsListeningPidsResult.mockReturnValue({ ok: true, pids: [stalePid] });
mockReadWindowsListeningPidsResult.mockImplementation((_port, timeoutMs) => {
if (timeoutMs === 400) {
fakeNow += 2001;
}
return { ok: true, pids: [stalePid] };
});
mockSpawnSync.mockReturnValue({
error: null,
status: 1,
@@ -803,6 +810,7 @@ describe.skipIf(isWindows)("restart-stale-pids", () => {
expect.objectContaining({ timeout: 5000 }),
);
} finally {
__testing.setDateNowOverride(null);
if (origDescriptor) {
Object.defineProperty(process, "platform", origDescriptor);
}

View File

@@ -1,34 +1,13 @@
import { execFileSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
import type { SecretRefCredentialMatrixDocument } from "./credential-matrix.js";
import {
buildSecretRefCredentialMatrix,
type SecretRefCredentialMatrixDocument,
} from "./credential-matrix.js";
function buildSecretRefCredentialMatrixJson(): string {
const childEnv = { ...process.env };
delete childEnv.NODE_OPTIONS;
delete childEnv.VITEST;
delete childEnv.VITEST_MODE;
delete childEnv.VITEST_POOL_ID;
delete childEnv.VITEST_WORKER_ID;
return execFileSync(
process.execPath,
[
"--import",
"tsx",
"--input-type=module",
"-e",
`import { buildSecretRefCredentialMatrix } from "./src/secrets/credential-matrix.ts";
process.stdout.write(\`\${JSON.stringify(buildSecretRefCredentialMatrix(), null, 2)}\\n\`);`,
],
{
cwd: process.cwd(),
encoding: "utf8",
env: childEnv,
maxBuffer: 10 * 1024 * 1024,
},
);
return `${JSON.stringify(buildSecretRefCredentialMatrix(), null, 2)}\n`;
}
describe("secret target registry docs", () => {

View File

@@ -1,5 +1,6 @@
import fs from "node:fs/promises";
import path from "node:path";
import { describeCodexNativeWebSearch } from "../agents/codex-native-web-search.shared.js";
import { DEFAULT_BOOTSTRAP_FILENAME } from "../agents/workspace.js";
import { formatCliCommand } from "../cli/command-format.js";
import {
@@ -516,7 +517,6 @@ export async function finalizeSetupWizard(
);
}
const { describeCodexNativeWebSearch } = await import("../agents/codex-native-web-search.js");
const codexNativeSummary = describeCodexNativeWebSearch(nextConfig);
const webSearchProvider = nextConfig.tools?.web?.search?.provider;
const webSearchEnabled = nextConfig.tools?.web?.search?.enabled;