mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:00:42 +00:00
perf: speed up hot test paths
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { type ConfigUiHints } from "../shared/config-ui-hints-types.js";
|
||||
import {
|
||||
hasSensitiveUrlHintTag,
|
||||
isSensitiveUrlConfigPath,
|
||||
@@ -10,7 +11,7 @@ import {
|
||||
shouldFallbackToStructuredRawRedaction,
|
||||
} from "./redact-snapshot.raw.js";
|
||||
import { isSecretRefShape, redactSecretRefId } from "./redact-snapshot.secret-ref.js";
|
||||
import { isSensitiveConfigPath, type ConfigUiHints } from "./schema.hints.js";
|
||||
import { isSensitiveConfigPath } from "./sensitive-paths.js";
|
||||
import type { ConfigFileSnapshot } from "./types.openclaw.js";
|
||||
|
||||
const log = createSubsystemLogger("config/redaction");
|
||||
|
||||
@@ -5,10 +5,10 @@ import {
|
||||
isSensitiveUrlConfigPath,
|
||||
SENSITIVE_URL_HINT_TAG,
|
||||
} from "../shared/net/redact-sensitive-url.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { FIELD_HELP } from "./schema.help.js";
|
||||
import { FIELD_LABELS } from "./schema.labels.js";
|
||||
import { applyDerivedTags } from "./schema.tags.js";
|
||||
import { isSensitiveConfigPath } from "./sensitive-paths.js";
|
||||
import { sensitive } from "./zod-schema.sensitive.js";
|
||||
|
||||
let log: ReturnType<typeof createSubsystemLogger> | null = null;
|
||||
@@ -111,49 +111,7 @@ export function isPluginOwnedChannelHintPath(path: string): boolean {
|
||||
return !isKernelOwnedChannelHintPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-sensitive field names that happen to match sensitive patterns.
|
||||
* These are explicitly excluded from redaction (plugin config) and
|
||||
* warnings about not being marked sensitive (base config).
|
||||
*/
|
||||
const SENSITIVE_KEY_WHITELIST_SUFFIXES = [
|
||||
"maxtokens",
|
||||
"maxoutputtokens",
|
||||
"maxinputtokens",
|
||||
"maxcompletiontokens",
|
||||
"contexttokens",
|
||||
"totaltokens",
|
||||
"tokencount",
|
||||
"tokenlimit",
|
||||
"tokenbudget",
|
||||
"passwordFile",
|
||||
] as const;
|
||||
const NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES = SENSITIVE_KEY_WHITELIST_SUFFIXES.map((suffix) =>
|
||||
normalizeLowercaseStringOrEmpty(suffix),
|
||||
);
|
||||
|
||||
const SENSITIVE_PATTERNS = [
|
||||
/token$/i,
|
||||
/password/i,
|
||||
/secret/i,
|
||||
/api.?key/i,
|
||||
/encrypt.?key/i,
|
||||
/private.?key/i,
|
||||
/serviceaccount(?:ref)?$/i,
|
||||
];
|
||||
|
||||
function isWhitelistedSensitivePath(path: string): boolean {
|
||||
const lowerPath = normalizeLowercaseStringOrEmpty(path);
|
||||
return NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES.some((suffix) => lowerPath.endsWith(suffix));
|
||||
}
|
||||
|
||||
function matchesSensitivePattern(path: string): boolean {
|
||||
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));
|
||||
}
|
||||
|
||||
export function isSensitiveConfigPath(path: string): boolean {
|
||||
return !isWhitelistedSensitivePath(path) && matchesSensitivePattern(path);
|
||||
}
|
||||
export { isSensitiveConfigPath };
|
||||
|
||||
export function buildBaseHints(): ConfigUiHints {
|
||||
const hints: ConfigUiHints = {};
|
||||
|
||||
46
src/config/sensitive-paths.ts
Normal file
46
src/config/sensitive-paths.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
/**
|
||||
* Non-sensitive field names that happen to match sensitive patterns.
|
||||
* These are explicitly excluded from redaction (plugin config) and
|
||||
* warnings about not being marked sensitive (base config).
|
||||
*/
|
||||
const SENSITIVE_KEY_WHITELIST_SUFFIXES = [
|
||||
"maxtokens",
|
||||
"maxoutputtokens",
|
||||
"maxinputtokens",
|
||||
"maxcompletiontokens",
|
||||
"contexttokens",
|
||||
"totaltokens",
|
||||
"tokencount",
|
||||
"tokenlimit",
|
||||
"tokenbudget",
|
||||
"passwordFile",
|
||||
] as const;
|
||||
|
||||
const NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES = SENSITIVE_KEY_WHITELIST_SUFFIXES.map((suffix) =>
|
||||
normalizeLowercaseStringOrEmpty(suffix),
|
||||
);
|
||||
|
||||
const SENSITIVE_PATTERNS = [
|
||||
/token$/i,
|
||||
/password/i,
|
||||
/secret/i,
|
||||
/api.?key/i,
|
||||
/encrypt.?key/i,
|
||||
/private.?key/i,
|
||||
/serviceaccount(?:ref)?$/i,
|
||||
];
|
||||
|
||||
function isWhitelistedSensitivePath(path: string): boolean {
|
||||
const lowerPath = normalizeLowercaseStringOrEmpty(path);
|
||||
return NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES.some((suffix) => lowerPath.endsWith(suffix));
|
||||
}
|
||||
|
||||
function matchesSensitivePattern(path: string): boolean {
|
||||
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));
|
||||
}
|
||||
|
||||
export function isSensitiveConfigPath(path: string): boolean {
|
||||
return !isWhitelistedSensitivePath(path) && matchesSensitivePattern(path);
|
||||
}
|
||||
@@ -9,6 +9,8 @@ export type OsSummary = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
const cachedOsSummaryByKey = new Map<string, OsSummary>();
|
||||
|
||||
function macosVersion(): string {
|
||||
const res = spawnSync("sw_vers", ["-productVersion"], { encoding: "utf-8" });
|
||||
const out = normalizeOptionalString(res.stdout) ?? "";
|
||||
@@ -19,6 +21,11 @@ export function resolveOsSummary(): OsSummary {
|
||||
const platform = os.platform();
|
||||
const release = os.release();
|
||||
const arch = os.arch();
|
||||
const cacheKey = `${platform}\0${release}\0${arch}`;
|
||||
const cached = cachedOsSummaryByKey.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const label = (() => {
|
||||
if (platform === "darwin") {
|
||||
return `macos ${macosVersion()} (${arch})`;
|
||||
@@ -28,5 +35,7 @@ export function resolveOsSummary(): OsSummary {
|
||||
}
|
||||
return `${platform} ${release} (${arch})`;
|
||||
})();
|
||||
return { platform, arch, release, label };
|
||||
const summary = { platform, arch, release, label };
|
||||
cachedOsSummaryByKey.set(cacheKey, summary);
|
||||
return summary;
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ describe("buildSessionEntry", () => {
|
||||
|
||||
it("does not split surrogate pairs when hard-wrapping astral unicode without spaces", async () => {
|
||||
const astralChar = "\u{20000}";
|
||||
const giantToken = astralChar.repeat(1200);
|
||||
const giantToken = astralChar.repeat(410);
|
||||
const jsonlLines = [
|
||||
JSON.stringify({
|
||||
type: "message",
|
||||
|
||||
@@ -41,6 +41,10 @@ const BUILT_IN_PLUGIN_ALIAS_FALLBACKS: ReadonlyArray<readonly [alias: string, pl
|
||||
["minimax-portal", "minimax"],
|
||||
["minimax-portal-auth", "minimax"],
|
||||
] as const;
|
||||
const BUILT_IN_PLUGIN_ALIAS_LOOKUP = new Map<string, string>([
|
||||
...BUILT_IN_PLUGIN_ALIAS_FALLBACKS,
|
||||
...BUILT_IN_PLUGIN_ALIAS_FALLBACKS.map(([, pluginId]) => [pluginId, pluginId] as const),
|
||||
]);
|
||||
|
||||
function getBundledPluginAliasLookup(): ReadonlyMap<string, string> {
|
||||
if (bundledPluginAliasLookupCache) {
|
||||
@@ -79,6 +83,10 @@ function getBundledPluginAliasLookup(): ReadonlyMap<string, string> {
|
||||
export function normalizePluginId(id: string): string {
|
||||
const trimmed = normalizeOptionalString(id) ?? "";
|
||||
const normalized = normalizeOptionalLowercaseString(trimmed) ?? "";
|
||||
const builtInAlias = BUILT_IN_PLUGIN_ALIAS_LOOKUP.get(normalized);
|
||||
if (builtInAlias) {
|
||||
return builtInAlias;
|
||||
}
|
||||
return getBundledPluginAliasLookup().get(normalized) ?? trimmed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { REDACTED_SENTINEL } from "../config/redact-snapshot.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
|
||||
const loadPluginManifestRegistry = vi.hoisted(() => vi.fn(() => ({ plugins: [] })));
|
||||
|
||||
vi.mock("../infra/git-commit.js", () => ({
|
||||
resolveCommitHash: () => "abcdef0",
|
||||
}));
|
||||
|
||||
vi.mock("../infra/os-summary.js", () => ({
|
||||
resolveOsSummary: () => ({
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
release: "test-release",
|
||||
label: "test-os",
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/manifest-registry.js", () => ({
|
||||
loadPluginManifestRegistry,
|
||||
}));
|
||||
|
||||
import { buildTrajectoryArtifacts, buildTrajectoryRunMetadata } from "./metadata.js";
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
Reference in New Issue
Block a user