mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 05:51:12 +00:00
refactor(deadcode): privatize core test seams (#108325)
* refactor(entry): privatize compile cache internals * refactor(logging): privatize diagnostic test seams * refactor(plugin-state): privatize store test seams * refactor(skills): privatize lifecycle test seams * refactor(node-host): privatize invoke test seam * refactor(system-agent): privatize turn test seam * chore(deadcode): shrink core test seam baseline
This commit is contained in:
committed by
GitHub
parent
20bf422cc7
commit
674dd37cd0
@@ -100,32 +100,12 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/cron/service/timer.ts: executeJobCore",
|
||||
"src/cron/service/timer.ts: onTimer",
|
||||
"src/cron/session-reaper.ts: resetReaperThrottle",
|
||||
"src/entry.compile-cache.ts: buildOpenClawCompileCacheRespawnPlan",
|
||||
"src/entry.compile-cache.ts: isNodeVersionAffectedByCompileCacheDeadlock",
|
||||
"src/entry.compile-cache.ts: isSourceCheckoutInstallRoot",
|
||||
"src/entry.compile-cache.ts: resolveOpenClawCompileCacheDirectory",
|
||||
"src/entry.compile-cache.ts: runOpenClawCompileCacheRespawnPlan",
|
||||
"src/entry.compile-cache.ts: shouldEnableOpenClawCompileCache",
|
||||
"src/flows/doctor-health-contributions.ts: createDoctorHealthContribution",
|
||||
"src/flows/doctor-health-contributions.ts: resolveDoctorHealthContributions",
|
||||
"src/logging/diagnostic-run-activity.ts: markDiagnosticModelStartedForTest",
|
||||
"src/logging/diagnostic-run-activity.ts: markDiagnosticRunProgressForTest",
|
||||
"src/logging/diagnostic-run-activity.ts: markDiagnosticToolStartedForTest",
|
||||
"src/logging/redact-internal.ts: withFullContextToolPayloadRedaction",
|
||||
"src/logging/secret-redaction-registry.ts: resetSecretRedactionRegistryForTest",
|
||||
"src/node-host/invoke.ts: testing",
|
||||
"src/plugin-state/plugin-state-store.sqlite.ts: probePluginStateStore",
|
||||
"src/plugin-state/plugin-state-store.sqlite.ts: seedPluginStateDatabaseEntriesForTests",
|
||||
"src/plugin-state/plugin-state-store.sqlite.ts: setMaxPluginStateEntriesPerPluginForTests",
|
||||
"src/plugin-state/plugin-state-store.ts: clearPluginStateStoreForTests",
|
||||
"src/sessions/session-lifecycle-admission.ts: runExclusiveSessionLifecycle",
|
||||
"src/sessions/session-upstream-monitor.ts: runSessionUpstreamMonitorTick",
|
||||
"src/sessions/user-turn-transcript.ts: persistUserTurnTranscript",
|
||||
"src/skills/lifecycle/install.ts: testing",
|
||||
"src/skills/lifecycle/upload-store.ts: createSkillUploadStore",
|
||||
"src/skills/runtime/refresh.ts: resetSkillsRefreshForTest",
|
||||
"src/skills/runtime/remote-skills.ts: resetRemoteNodeSkillsForTests",
|
||||
"src/system-agent/agent-turn.ts: runSystemAgentTurnWithDeps",
|
||||
"src/tasks/detached-task-runtime.ts: resetDetachedTaskLifecycleRuntimeForTests",
|
||||
"src/tasks/detached-task-runtime.ts: setDetachedTaskLifecycleRuntime",
|
||||
"src/tasks/generated-media-task-activity.ts: resetGeneratedMediaTaskActivityForTests",
|
||||
|
||||
@@ -11,10 +11,8 @@ import {
|
||||
isReplyRunActiveForSessionId,
|
||||
} from "../../auto-reply/reply/reply-run-registry.js";
|
||||
import { setDiagnosticsEnabledForProcess } from "../../infra/diagnostic-events.js";
|
||||
import {
|
||||
markDiagnosticToolStartedForTest,
|
||||
resetDiagnosticRunActivityForTest,
|
||||
} from "../../logging/diagnostic-run-activity.js";
|
||||
import { resetDiagnosticRunActivityForTest } from "../../logging/diagnostic-run-activity.js";
|
||||
import { markDiagnosticToolStartedForTest } from "../../logging/diagnostic-run-activity.test-support.js";
|
||||
import {
|
||||
getDiagnosticSessionState,
|
||||
resetDiagnosticSessionStateForTest,
|
||||
|
||||
@@ -63,8 +63,10 @@ describe("mcp connection resolver helpers", () => {
|
||||
});
|
||||
|
||||
it("registers resolved header and signed-URL credentials for redaction", async () => {
|
||||
const { isSecretValueRegisteredForRedaction, resetSecretRedactionRegistryForTest } =
|
||||
const { isSecretValueRegisteredForRedaction } =
|
||||
await import("../logging/secret-redaction-registry.js");
|
||||
const { resetSecretRedactionRegistryForTest } =
|
||||
await import("../logging/secret-redaction-registry.test-support.js");
|
||||
resetSecretRedactionRegistryForTest();
|
||||
testing.setMcpServerConnectionResolversForTest([
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { AddressInfo } from "node:net";
|
||||
import type { Model } from "openclaw/plugin-sdk/llm";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { redactSensitiveText } from "../logging/redact.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.test-support.js";
|
||||
import { mintSecretSentinel } from "../secrets/sentinel.js";
|
||||
import { buildGuardedModelFetch } from "./provider-transport-fetch.js";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import type { ProviderPlugin } from "../plugins/types.js";
|
||||
import { resetSkillsRefreshForTest } from "../skills/runtime/refresh.js";
|
||||
import { resetSkillsRefreshForTest } from "../skills/runtime/refresh.test-support.js";
|
||||
import {
|
||||
clearSessionAuthProfileOverrideMock,
|
||||
compactEmbeddedAgentSessionMock,
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import {
|
||||
markDiagnosticToolStartedForTest,
|
||||
resetDiagnosticRunActivityForTest,
|
||||
RUN_STALE_TAKEOVER_MS,
|
||||
} from "../../logging/diagnostic-run-activity.js";
|
||||
import { markDiagnosticToolStartedForTest } from "../../logging/diagnostic-run-activity.test-support.js";
|
||||
import {
|
||||
interruptSessionWorkAdmissions,
|
||||
runExclusiveSessionLifecycleMutation,
|
||||
|
||||
@@ -14,8 +14,10 @@ import {
|
||||
createPluginStateKeyedStore,
|
||||
resetPluginStateStoreForTests,
|
||||
} from "../plugin-state/plugin-state-store.js";
|
||||
import { setMaxPluginStateEntriesPerPluginForTests } from "../plugin-state/plugin-state-store.sqlite.js";
|
||||
import { seedPluginStateEntriesForTests } from "../plugin-state/plugin-state-store.test-helpers.js";
|
||||
import {
|
||||
seedPluginStateEntriesForTests,
|
||||
setMaxPluginStateEntriesPerPluginForTests,
|
||||
} from "../plugin-state/plugin-state-store.test-helpers.js";
|
||||
import {
|
||||
readPersistedInstalledPluginIndex,
|
||||
writePersistedInstalledPluginIndex,
|
||||
|
||||
80
src/entry.compile-cache.test-support.ts
Normal file
80
src/entry.compile-cache.test-support.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import type { ChildProcess } from "node:child_process";
|
||||
import type { RespawnChildRuntime } from "./process/respawn-child-runner.js";
|
||||
import "./entry.compile-cache.js";
|
||||
|
||||
type CompileCacheParams = {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
installRoot: string;
|
||||
nodeVersion?: string;
|
||||
platform?: NodeJS.Platform;
|
||||
};
|
||||
|
||||
type CompileCacheRespawnPlan = {
|
||||
command: string;
|
||||
args: string[];
|
||||
env: NodeJS.ProcessEnv;
|
||||
detachForProcessTree: boolean;
|
||||
};
|
||||
|
||||
type CompileCacheTestApi = {
|
||||
buildOpenClawCompileCacheRespawnPlan(params: {
|
||||
currentFile: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
execArgv?: string[];
|
||||
execPath?: string;
|
||||
installRoot: string;
|
||||
argv?: string[];
|
||||
compileCacheDir?: string;
|
||||
nodeVersion?: string;
|
||||
platform?: NodeJS.Platform;
|
||||
}): CompileCacheRespawnPlan | undefined;
|
||||
isNodeVersionAffectedByCompileCacheDeadlock(nodeVersion: string | undefined): boolean;
|
||||
isSourceCheckoutInstallRoot(installRoot: string): boolean;
|
||||
resolveOpenClawCompileCacheDirectory(params: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
installRoot: string;
|
||||
}): string;
|
||||
runOpenClawCompileCacheRespawnPlan(
|
||||
plan: CompileCacheRespawnPlan,
|
||||
runtime?: RespawnChildRuntime & { writeError(message: string): void },
|
||||
): ChildProcess;
|
||||
shouldEnableOpenClawCompileCache(params: CompileCacheParams): boolean;
|
||||
};
|
||||
|
||||
function getTestApi(): CompileCacheTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.entryCompileCacheTestApi")
|
||||
] as CompileCacheTestApi;
|
||||
}
|
||||
|
||||
export function buildOpenClawCompileCacheRespawnPlan(
|
||||
params: Parameters<CompileCacheTestApi["buildOpenClawCompileCacheRespawnPlan"]>[0],
|
||||
): CompileCacheRespawnPlan | undefined {
|
||||
return getTestApi().buildOpenClawCompileCacheRespawnPlan(params);
|
||||
}
|
||||
|
||||
export function isNodeVersionAffectedByCompileCacheDeadlock(
|
||||
nodeVersion: string | undefined,
|
||||
): boolean {
|
||||
return getTestApi().isNodeVersionAffectedByCompileCacheDeadlock(nodeVersion);
|
||||
}
|
||||
|
||||
export function isSourceCheckoutInstallRoot(installRoot: string): boolean {
|
||||
return getTestApi().isSourceCheckoutInstallRoot(installRoot);
|
||||
}
|
||||
|
||||
export function resolveOpenClawCompileCacheDirectory(
|
||||
params: Parameters<CompileCacheTestApi["resolveOpenClawCompileCacheDirectory"]>[0],
|
||||
): string {
|
||||
return getTestApi().resolveOpenClawCompileCacheDirectory(params);
|
||||
}
|
||||
|
||||
export function runOpenClawCompileCacheRespawnPlan(
|
||||
...args: Parameters<CompileCacheTestApi["runOpenClawCompileCacheRespawnPlan"]>
|
||||
): ChildProcess {
|
||||
return getTestApi().runOpenClawCompileCacheRespawnPlan(...args);
|
||||
}
|
||||
|
||||
export function shouldEnableOpenClawCompileCache(params: CompileCacheParams): boolean {
|
||||
return getTestApi().shouldEnableOpenClawCompileCache(params);
|
||||
}
|
||||
@@ -5,15 +5,15 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { cleanupTempDirs, makeTempDir } from "../test/helpers/temp-dir.js";
|
||||
import { resolveEntryInstallRoot } from "./entry.compile-cache.js";
|
||||
import {
|
||||
buildOpenClawCompileCacheRespawnPlan,
|
||||
isNodeVersionAffectedByCompileCacheDeadlock,
|
||||
isSourceCheckoutInstallRoot,
|
||||
resolveOpenClawCompileCacheDirectory,
|
||||
resolveEntryInstallRoot,
|
||||
runOpenClawCompileCacheRespawnPlan,
|
||||
shouldEnableOpenClawCompileCache,
|
||||
} from "./entry.compile-cache.js";
|
||||
} from "./entry.compile-cache.test-support.js";
|
||||
|
||||
function requireFirstMockCall(mock: { mock: { calls: unknown[][] } }, label: string): unknown[] {
|
||||
const [call] = mock.mock.calls;
|
||||
|
||||
@@ -24,7 +24,7 @@ export function resolveEntryInstallRoot(entryFile: string): string {
|
||||
return entryParent === "dist" || entryParent === "src" ? path.dirname(entryDir) : entryDir;
|
||||
}
|
||||
|
||||
export function isSourceCheckoutInstallRoot(installRoot: string): boolean {
|
||||
function isSourceCheckoutInstallRoot(installRoot: string): boolean {
|
||||
return (
|
||||
existsSync(path.join(installRoot, ".git")) ||
|
||||
existsSync(path.join(installRoot, "src", "entry.ts"))
|
||||
@@ -39,9 +39,7 @@ function isNodeCompileCacheRequested(env: NodeJS.ProcessEnv | undefined): boolea
|
||||
return env?.NODE_COMPILE_CACHE !== undefined && !isNodeCompileCacheDisabled(env);
|
||||
}
|
||||
|
||||
export function isNodeVersionAffectedByCompileCacheDeadlock(
|
||||
nodeVersion: string | undefined,
|
||||
): boolean {
|
||||
function isNodeVersionAffectedByCompileCacheDeadlock(nodeVersion: string | undefined): boolean {
|
||||
if (!nodeVersion) {
|
||||
return false;
|
||||
}
|
||||
@@ -57,7 +55,7 @@ export function isNodeVersionAffectedByCompileCacheDeadlock(
|
||||
return minor < MIN_COMPILE_CACHE_NODE_24_MINOR;
|
||||
}
|
||||
|
||||
export function shouldEnableOpenClawCompileCache(params: {
|
||||
function shouldEnableOpenClawCompileCache(params: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
installRoot: string;
|
||||
nodeVersion?: string;
|
||||
@@ -98,7 +96,7 @@ function readPackageVersion(packageJsonPath: string): string {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
export function resolveOpenClawCompileCacheDirectory(params: {
|
||||
function resolveOpenClawCompileCacheDirectory(params: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
installRoot: string;
|
||||
}): string {
|
||||
@@ -135,7 +133,7 @@ type OpenClawCompileCacheRespawnRuntime = RespawnChildRuntime & {
|
||||
writeError: (message: string) => void;
|
||||
};
|
||||
|
||||
export function buildOpenClawCompileCacheRespawnPlan(params: {
|
||||
function buildOpenClawCompileCacheRespawnPlan(params: {
|
||||
currentFile: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
execArgv?: string[];
|
||||
@@ -196,7 +194,7 @@ export function respawnWithoutOpenClawCompileCacheIfNeeded(params: {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function runOpenClawCompileCacheRespawnPlan(
|
||||
function runOpenClawCompileCacheRespawnPlan(
|
||||
plan: OpenClawCompileCacheRespawnPlan,
|
||||
runtime: OpenClawCompileCacheRespawnRuntime = {
|
||||
spawn,
|
||||
@@ -234,3 +232,14 @@ export function enableOpenClawCompileCache(params: {
|
||||
// Best-effort only; never block startup.
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.entryCompileCacheTestApi")] = {
|
||||
buildOpenClawCompileCacheRespawnPlan,
|
||||
isNodeVersionAffectedByCompileCacheDeadlock,
|
||||
isSourceCheckoutInstallRoot,
|
||||
resolveOpenClawCompileCacheDirectory,
|
||||
runOpenClawCompileCacheRespawnPlan,
|
||||
shouldEnableOpenClawCompileCache,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
type DiagnosticSecurityEvent,
|
||||
} from "../../infra/diagnostic-events.js";
|
||||
import { approveNodePairing, requestNodePairing } from "../../infra/node-pairing.js";
|
||||
import { resetRemoteNodeSkillsForTests } from "../../skills/runtime/remote-skills.js";
|
||||
import { resetRemoteNodeSkillsForTests } from "../../skills/runtime/remote-skills.test-support.js";
|
||||
import {
|
||||
createOpenClawTestState,
|
||||
type OpenClawTestState,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
isSecretValueRegisteredForRedaction,
|
||||
resetSecretRedactionRegistryForTest,
|
||||
} from "../../logging/secret-redaction-registry.js";
|
||||
import { isSecretValueRegisteredForRedaction } from "../../logging/secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../../logging/secret-redaction-registry.test-support.js";
|
||||
import { createWorkerCredentialMaterial, hashWorkerCredential } from "./credential.js";
|
||||
|
||||
afterEach(resetSecretRedactionRegistryForTest);
|
||||
|
||||
46
src/logging/diagnostic-run-activity.test-support.ts
Normal file
46
src/logging/diagnostic-run-activity.test-support.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import type { DiagnosticEventPayload } from "../infra/diagnostic-events.js";
|
||||
import "./diagnostic-run-activity.js";
|
||||
|
||||
type DiagnosticModelStartedActivityEvent = Pick<
|
||||
Extract<DiagnosticEventPayload, { type: "model.call.started" }>,
|
||||
"runId" | "sessionId" | "sessionKey" | "provider" | "model"
|
||||
> & { seq?: number };
|
||||
|
||||
type DiagnosticRunProgressActivityEvent = Pick<
|
||||
Extract<DiagnosticEventPayload, { type: "run.progress" }>,
|
||||
"runId" | "sessionId" | "sessionKey" | "reason"
|
||||
>;
|
||||
|
||||
type DiagnosticRunActivityTestApi = {
|
||||
markDiagnosticModelStartedForTest(params: DiagnosticModelStartedActivityEvent): void;
|
||||
markDiagnosticRunProgressForTest(params: DiagnosticRunProgressActivityEvent): void;
|
||||
markDiagnosticToolStartedForTest(params: {
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
runId?: string;
|
||||
toolName: string;
|
||||
toolCallId?: string;
|
||||
}): void;
|
||||
};
|
||||
|
||||
function getTestApi(): DiagnosticRunActivityTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.diagnosticRunActivityTestApi")
|
||||
] as DiagnosticRunActivityTestApi;
|
||||
}
|
||||
|
||||
export function markDiagnosticModelStartedForTest(
|
||||
params: DiagnosticModelStartedActivityEvent,
|
||||
): void {
|
||||
getTestApi().markDiagnosticModelStartedForTest(params);
|
||||
}
|
||||
|
||||
export function markDiagnosticRunProgressForTest(params: DiagnosticRunProgressActivityEvent): void {
|
||||
getTestApi().markDiagnosticRunProgressForTest(params);
|
||||
}
|
||||
|
||||
export function markDiagnosticToolStartedForTest(
|
||||
params: Parameters<DiagnosticRunActivityTestApi["markDiagnosticToolStartedForTest"]>[0],
|
||||
): void {
|
||||
getTestApi().markDiagnosticToolStartedForTest(params);
|
||||
}
|
||||
@@ -627,11 +627,11 @@ export function getDiagnosticEmbeddedRunActivitySequence(): number {
|
||||
return embeddedRunSequence;
|
||||
}
|
||||
|
||||
export function markDiagnosticRunProgressForTest(params: DiagnosticRunProgressActivityEvent): void {
|
||||
function markDiagnosticRunProgressForTest(params: DiagnosticRunProgressActivityEvent): void {
|
||||
markDiagnosticRunProgress(params);
|
||||
}
|
||||
|
||||
export function markDiagnosticToolStartedForTest(params: {
|
||||
function markDiagnosticToolStartedForTest(params: {
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
runId?: string;
|
||||
@@ -641,9 +641,7 @@ export function markDiagnosticToolStartedForTest(params: {
|
||||
recordToolStarted(params);
|
||||
}
|
||||
|
||||
export function markDiagnosticModelStartedForTest(
|
||||
params: DiagnosticModelStartedActivityEvent,
|
||||
): void {
|
||||
function markDiagnosticModelStartedForTest(params: DiagnosticModelStartedActivityEvent): void {
|
||||
recordModelStarted(params);
|
||||
}
|
||||
|
||||
@@ -691,3 +689,13 @@ function registerDiagnosticRunActivityListener(): void {
|
||||
}
|
||||
|
||||
registerDiagnosticRunActivityListener();
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.diagnosticRunActivityTestApi")
|
||||
] = {
|
||||
markDiagnosticModelStartedForTest,
|
||||
markDiagnosticRunProgressForTest,
|
||||
markDiagnosticToolStartedForTest,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ import {
|
||||
getDiagnosticSessionActivitySnapshot,
|
||||
markDiagnosticEmbeddedRunEnded,
|
||||
markDiagnosticEmbeddedRunStarted,
|
||||
resetDiagnosticRunActivityForTest,
|
||||
} from "./diagnostic-run-activity.js";
|
||||
import {
|
||||
markDiagnosticModelStartedForTest,
|
||||
markDiagnosticRunProgressForTest,
|
||||
markDiagnosticToolStartedForTest,
|
||||
resetDiagnosticRunActivityForTest,
|
||||
} from "./diagnostic-run-activity.js";
|
||||
} from "./diagnostic-run-activity.test-support.js";
|
||||
import type { SessionAttentionClassification } from "./diagnostic-session-attention.js";
|
||||
import {
|
||||
requestStuckSessionRecovery,
|
||||
|
||||
@@ -15,10 +15,8 @@ import {
|
||||
redactToolPayloadTextWithConfig,
|
||||
resolveRedactOptions,
|
||||
} from "./redact.js";
|
||||
import {
|
||||
registerSecretValueForRedaction,
|
||||
resetSecretRedactionRegistryForTest,
|
||||
} from "./secret-redaction-registry.js";
|
||||
import { registerSecretValueForRedaction } from "./secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "./secret-redaction-registry.test-support.js";
|
||||
|
||||
const defaults = getDefaultRedactPatterns();
|
||||
let tempDirs: string[] = [];
|
||||
|
||||
15
src/logging/secret-redaction-registry.test-support.ts
Normal file
15
src/logging/secret-redaction-registry.test-support.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import "./secret-redaction-registry.js";
|
||||
|
||||
type SecretRedactionRegistryTestApi = {
|
||||
resetSecretRedactionRegistryForTest(): void;
|
||||
};
|
||||
|
||||
function getTestApi(): SecretRedactionRegistryTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.secretRedactionRegistryTestApi")
|
||||
] as SecretRedactionRegistryTestApi;
|
||||
}
|
||||
|
||||
export function resetSecretRedactionRegistryForTest(): void {
|
||||
getTestApi().resetSecretRedactionRegistryForTest();
|
||||
}
|
||||
@@ -87,8 +87,13 @@ export function redactRegisteredSecretValues(
|
||||
return text.replace(compiledMatcher, (value) => mask(value));
|
||||
}
|
||||
|
||||
/** Test-only reset for process-global redaction state. */
|
||||
export function resetSecretRedactionRegistryForTest(): void {
|
||||
function resetSecretRedactionRegistryForTest(): void {
|
||||
registeredValues.clear();
|
||||
rebuildProbe();
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.secretRedactionRegistryTestApi")
|
||||
] = { resetSecretRedactionRegistryForTest };
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/** Tests the built-in node-host MCP invocation command. */
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { GatewayClient } from "../gateway/client.js";
|
||||
import { handleInvoke, testing } from "./invoke.js";
|
||||
import { handleInvoke } from "./invoke.js";
|
||||
import { testing } from "./invoke.test-support.js";
|
||||
import { NodeHostMcpError, type NodeHostMcpManager } from "./mcp.js";
|
||||
|
||||
async function invokeMcp(manager: NodeHostMcpManager, params: unknown) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { testing } from "./invoke.js";
|
||||
import { testing } from "./invoke.test-support.js";
|
||||
|
||||
describe("runCommand", () => {
|
||||
afterEach(() => {
|
||||
|
||||
35
src/node-host/invoke.test-support.ts
Normal file
35
src/node-host/invoke.test-support.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { RunResult } from "./invoke-types.js";
|
||||
import "./invoke.js";
|
||||
|
||||
type NodeHostInvokeTestApi = {
|
||||
readonly MCP_TEXT_CONTENT_MAX_BYTES: number;
|
||||
readonly MCP_INVOKE_PAYLOAD_MAX_BYTES: number;
|
||||
clarifyNodeExecCwdSpawnError(error: NodeJS.ErrnoException, cwd: string | undefined): string;
|
||||
runCommand(
|
||||
argv: string[],
|
||||
cwd: string | undefined,
|
||||
env: Record<string, string> | undefined,
|
||||
timeoutMs: number | undefined,
|
||||
): Promise<RunResult>;
|
||||
};
|
||||
|
||||
function getTestApi(): NodeHostInvokeTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.nodeHostInvokeTestApi")
|
||||
] as NodeHostInvokeTestApi;
|
||||
}
|
||||
|
||||
export const testing: NodeHostInvokeTestApi = {
|
||||
get MCP_TEXT_CONTENT_MAX_BYTES() {
|
||||
return getTestApi().MCP_TEXT_CONTENT_MAX_BYTES;
|
||||
},
|
||||
get MCP_INVOKE_PAYLOAD_MAX_BYTES() {
|
||||
return getTestApi().MCP_INVOKE_PAYLOAD_MAX_BYTES;
|
||||
},
|
||||
clarifyNodeExecCwdSpawnError(error, cwd) {
|
||||
return getTestApi().clarifyNodeExecCwdSpawnError(error, cwd);
|
||||
},
|
||||
runCommand(argv, cwd, env, timeoutMs) {
|
||||
return getTestApi().runCommand(argv, cwd, env, timeoutMs);
|
||||
},
|
||||
};
|
||||
@@ -1075,10 +1075,15 @@ async function sendNodeEvent(client: NodeHostClient, event: string, payload: unk
|
||||
}
|
||||
}
|
||||
|
||||
export const testing = {
|
||||
const testing = {
|
||||
MCP_TEXT_CONTENT_MAX_BYTES,
|
||||
MCP_INVOKE_PAYLOAD_MAX_BYTES,
|
||||
clarifyNodeExecCwdSpawnError,
|
||||
runCommand,
|
||||
} as const;
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.nodeHostInvokeTestApi")] =
|
||||
testing;
|
||||
}
|
||||
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
resetPluginStateStoreForTests,
|
||||
sweepExpiredPluginStateEntries,
|
||||
} from "./plugin-state-store.js";
|
||||
import { probePluginStateStore } from "./plugin-state-store.sqlite.js";
|
||||
import { probePluginStateStore } from "./plugin-state-store.test-helpers.js";
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
|
||||
@@ -905,7 +905,7 @@ export function clearPluginStateDatabaseForTests(): void {
|
||||
);
|
||||
}
|
||||
|
||||
export function setMaxPluginStateEntriesPerPluginForTests(value?: number): void {
|
||||
function setMaxPluginStateEntriesPerPluginForTests(value?: number): void {
|
||||
maxPluginStateEntriesPerPluginForTests = value;
|
||||
}
|
||||
|
||||
@@ -923,7 +923,7 @@ export function countPluginStateLiveEntries(pluginId: string): number {
|
||||
}
|
||||
}
|
||||
|
||||
export function seedPluginStateDatabaseEntriesForTests(
|
||||
function seedPluginStateDatabaseEntriesForTests(
|
||||
entries: readonly PluginStateSeedEntryForTests[],
|
||||
): void {
|
||||
if (entries.length === 0) {
|
||||
@@ -948,7 +948,7 @@ export function seedPluginStateDatabaseEntriesForTests(
|
||||
});
|
||||
}
|
||||
|
||||
export function probePluginStateStore(): PluginStateStoreProbeResult {
|
||||
function probePluginStateStore(): PluginStateStoreProbeResult {
|
||||
const databasePath = resolveOpenClawStateSqlitePath(process.env);
|
||||
const steps: PluginStateStoreProbeStep[] = [];
|
||||
const wasOpen = cachedDatabase !== null;
|
||||
@@ -1039,4 +1039,12 @@ export function closePluginStateDatabase(): void {
|
||||
cachedDatabase = null;
|
||||
closeOpenClawStateDatabase();
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.pluginStateSqliteTestApi")] = {
|
||||
probePluginStateStore,
|
||||
seedPluginStateDatabaseEntriesForTests,
|
||||
setMaxPluginStateEntriesPerPluginForTests,
|
||||
};
|
||||
}
|
||||
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Plugin state test helpers seed SQLite plugin state fixtures.
|
||||
import { seedPluginStateDatabaseEntriesForTests } from "./plugin-state-store.sqlite.js";
|
||||
import type { PluginStateStoreProbeResult } from "./plugin-state-store.types.js";
|
||||
import "./plugin-state-store.js";
|
||||
import "./plugin-state-store.sqlite.js";
|
||||
|
||||
// Test-only seed helpers for plugin state. Values are serialized through the
|
||||
// same JSON storage path used by the production sqlite store.
|
||||
@@ -12,13 +14,56 @@ type PluginStateSeedEntry = {
|
||||
expiresAt?: number | null;
|
||||
};
|
||||
|
||||
type PluginStateDatabaseSeedEntry = {
|
||||
pluginId: string;
|
||||
namespace: string;
|
||||
key: string;
|
||||
valueJson: string;
|
||||
createdAt?: number;
|
||||
expiresAt?: number | null;
|
||||
};
|
||||
|
||||
type PluginStateSqliteTestApi = {
|
||||
probePluginStateStore(): PluginStateStoreProbeResult;
|
||||
seedPluginStateDatabaseEntriesForTests(entries: readonly PluginStateDatabaseSeedEntry[]): void;
|
||||
setMaxPluginStateEntriesPerPluginForTests(value?: number): void;
|
||||
};
|
||||
|
||||
type PluginStateStoreTestApi = {
|
||||
clearPluginStateStoreForTests(): void;
|
||||
};
|
||||
|
||||
function getSqliteTestApi(): PluginStateSqliteTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.pluginStateSqliteTestApi")
|
||||
] as PluginStateSqliteTestApi;
|
||||
}
|
||||
|
||||
function getStoreTestApi(): PluginStateStoreTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.pluginStateStoreTestApi")
|
||||
] as PluginStateStoreTestApi;
|
||||
}
|
||||
|
||||
export function clearPluginStateStoreForTests(): void {
|
||||
getStoreTestApi().clearPluginStateStoreForTests();
|
||||
}
|
||||
|
||||
export function probePluginStateStore(): PluginStateStoreProbeResult {
|
||||
return getSqliteTestApi().probePluginStateStore();
|
||||
}
|
||||
|
||||
export function setMaxPluginStateEntriesPerPluginForTests(value?: number): void {
|
||||
getSqliteTestApi().setMaxPluginStateEntriesPerPluginForTests(value);
|
||||
}
|
||||
|
||||
/** Seeds plugin state entries for tests without opening public store handles. */
|
||||
export function seedPluginStateEntriesForTests(entries: PluginStateSeedEntry[]): void {
|
||||
if (entries.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
seedPluginStateDatabaseEntriesForTests(
|
||||
getSqliteTestApi().seedPluginStateDatabaseEntriesForTests(
|
||||
entries.map((entry) => {
|
||||
const valueJson = JSON.stringify(entry.value);
|
||||
if (valueJson == null) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
type OpenClawTestState,
|
||||
} from "../test-utils/openclaw-test-state.js";
|
||||
import {
|
||||
clearPluginStateStoreForTests,
|
||||
closePluginStateDatabase,
|
||||
createCorePluginStateSyncKeyedStore,
|
||||
createPluginStateKeyedStore,
|
||||
@@ -20,10 +19,11 @@ import {
|
||||
sweepExpiredPluginStateEntries,
|
||||
} from "./plugin-state-store.js";
|
||||
import {
|
||||
clearPluginStateStoreForTests,
|
||||
probePluginStateStore,
|
||||
seedPluginStateEntriesForTests,
|
||||
setMaxPluginStateEntriesPerPluginForTests,
|
||||
} from "./plugin-state-store.sqlite.js";
|
||||
import { seedPluginStateEntriesForTests } from "./plugin-state-store.test-helpers.js";
|
||||
} from "./plugin-state-store.test-helpers.js";
|
||||
import { PluginStateStoreError } from "./plugin-state-store.types.js";
|
||||
|
||||
let testState: OpenClawTestState | undefined;
|
||||
|
||||
@@ -511,7 +511,7 @@ export function createCorePluginStateSyncKeyedStore<T>(
|
||||
}
|
||||
|
||||
/** Clears plugin-state rows and option signatures for tests. */
|
||||
export function clearPluginStateStoreForTests(): void {
|
||||
function clearPluginStateStoreForTests(): void {
|
||||
clearPluginStateDatabaseForTests();
|
||||
namespaceOptionSignatures.clear();
|
||||
}
|
||||
@@ -524,3 +524,9 @@ export function resetPluginStateStoreForTests(options: { closeDatabase?: boolean
|
||||
}
|
||||
namespaceOptionSignatures.clear();
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.pluginStateStoreTestApi")] = {
|
||||
clearPluginStateStoreForTests,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Proxy capture runtime tests cover session creation and capture lifecycle.
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
registerSecretValueForRedaction,
|
||||
resetSecretRedactionRegistryForTest,
|
||||
} from "../logging/secret-redaction-registry.js";
|
||||
import { registerSecretValueForRedaction } from "../logging/secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.test-support.js";
|
||||
import type { DebugProxySettings } from "./env.js";
|
||||
import {
|
||||
captureHttpExchange,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** Tests runtime SecretRef resolution across core config and auth-profile surfaces. */
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { redactSensitiveText } from "../logging/redact.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.test-support.js";
|
||||
import { asConfig, setupSecretsRuntimeSnapshotTestHooks } from "./runtime.test-support.ts";
|
||||
|
||||
const EMPTY_LOADABLE_PLUGIN_ORIGINS = new Map();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { redactSensitiveText } from "../logging/redact.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.js";
|
||||
import { resetSecretRedactionRegistryForTest } from "../logging/secret-redaction-registry.test-support.js";
|
||||
import {
|
||||
looksLikeSecretSentinel,
|
||||
mintSecretSentinel,
|
||||
|
||||
@@ -25,14 +25,11 @@ vi.mock("../loading/workspace.js", () => ({
|
||||
|
||||
let installSkill: typeof import("./install.js").installSkill;
|
||||
let resolveInstallerKindReadiness: typeof import("./install.js").resolveInstallerKindReadiness;
|
||||
let skillsInstallTesting: typeof import("./install.js").testing;
|
||||
let skillsInstallTesting: typeof import("./install.test-support.js").skillsInstallTesting;
|
||||
|
||||
async function loadSkillsInstallModulesForTest() {
|
||||
({
|
||||
installSkill,
|
||||
resolveInstallerKindReadiness,
|
||||
testing: skillsInstallTesting,
|
||||
} = await import("./install.js"));
|
||||
({ installSkill, resolveInstallerKindReadiness } = await import("./install.js"));
|
||||
({ skillsInstallTesting } = await import("./install.test-support.js"));
|
||||
}
|
||||
|
||||
function makeSkillEntry(
|
||||
|
||||
39
src/skills/lifecycle/install.test-support.ts
Normal file
39
src/skills/lifecycle/install.test-support.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { resolveSkillsInstallPreferences } from "../loading/config.js";
|
||||
import type { loadWorkspaceSkillEntries } from "../loading/workspace.js";
|
||||
import "./install.js";
|
||||
|
||||
type SkillsInstallDeps = {
|
||||
hasBinary(bin: string): boolean;
|
||||
loadWorkspaceSkillEntries: typeof loadWorkspaceSkillEntries;
|
||||
resolveNodeInstallStateDir(): string;
|
||||
resolveBrewExecutable(): string | undefined;
|
||||
isContainerEnvironment(): boolean;
|
||||
resolveSkillsInstallPreferences: typeof resolveSkillsInstallPreferences;
|
||||
};
|
||||
|
||||
type ResolveDefaultNodeInstallStateDirParams = {
|
||||
cwd?: string;
|
||||
getuid?: () => number;
|
||||
homedir?: () => string;
|
||||
platform?: NodeJS.Platform;
|
||||
};
|
||||
|
||||
type SkillsInstallTestApi = {
|
||||
resolveDefaultNodeInstallStateDir(params?: ResolveDefaultNodeInstallStateDirParams): string;
|
||||
setDepsForTest(overrides?: Partial<SkillsInstallDeps>): void;
|
||||
};
|
||||
|
||||
function getTestApi(): SkillsInstallTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.skillsInstallTestApi")
|
||||
] as SkillsInstallTestApi;
|
||||
}
|
||||
|
||||
export const skillsInstallTesting: SkillsInstallTestApi = {
|
||||
resolveDefaultNodeInstallStateDir(params) {
|
||||
return getTestApi().resolveDefaultNodeInstallStateDir(params);
|
||||
},
|
||||
setDepsForTest(overrides) {
|
||||
getTestApi().setDepsForTest(overrides);
|
||||
},
|
||||
};
|
||||
@@ -13,7 +13,8 @@ import { resolveOpenClawMetadata, resolveSkillInvocationPolicy } from "../loadin
|
||||
import { loadSkillsFromDirSafe, readSkillFrontmatterSafe } from "../loading/local-loader.js";
|
||||
import { runCommandWithTimeoutMock } from "../test-support/install-test-mocks.js";
|
||||
import type { SkillEntry } from "../types.js";
|
||||
import { installSkill, testing as skillsInstallTesting } from "./install.js";
|
||||
import { installSkill } from "./install.js";
|
||||
import { skillsInstallTesting } from "./install.test-support.js";
|
||||
|
||||
vi.mock("../../process/exec.js", () => ({
|
||||
runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args),
|
||||
|
||||
@@ -819,7 +819,7 @@ export async function installSkill(params: SkillInstallRequest): Promise<SkillIn
|
||||
return withWarnings(normalizedResult, warnings);
|
||||
}
|
||||
|
||||
export const testing = {
|
||||
const testing = {
|
||||
resolveDefaultNodeInstallStateDir,
|
||||
setDepsForTest(overrides?: Partial<SkillsInstallDeps>): void {
|
||||
skillsInstallDeps = {
|
||||
@@ -828,4 +828,9 @@ export const testing = {
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.skillsInstallTestApi")] =
|
||||
testing;
|
||||
}
|
||||
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
|
||||
|
||||
22
src/skills/lifecycle/upload-store.test-support.ts
Normal file
22
src/skills/lifecycle/upload-store.test-support.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { SkillUploadStore } from "./upload-store.js";
|
||||
import "./upload-store.js";
|
||||
|
||||
type SkillUploadStoreTestApi = {
|
||||
createSkillUploadStore(options?: {
|
||||
rootDir?: string;
|
||||
now?: () => number;
|
||||
ttlMs?: number;
|
||||
}): SkillUploadStore;
|
||||
};
|
||||
|
||||
function getTestApi(): SkillUploadStoreTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.skillUploadStoreTestApi")
|
||||
] as SkillUploadStoreTestApi;
|
||||
}
|
||||
|
||||
export function createSkillUploadStore(
|
||||
options?: Parameters<SkillUploadStoreTestApi["createSkillUploadStore"]>[0],
|
||||
): SkillUploadStore {
|
||||
return getTestApi().createSkillUploadStore(options);
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { createSkillUploadStore, SkillUploadRequestError } from "./upload-store.js";
|
||||
import { SkillUploadRequestError } from "./upload-store.js";
|
||||
import { createSkillUploadStore } from "./upload-store.test-support.js";
|
||||
|
||||
const ACTIVE_UPLOAD_LIMIT = 32;
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ async function readCommittedRecord(
|
||||
return record;
|
||||
}
|
||||
|
||||
export function createSkillUploadStore(options?: {
|
||||
function createSkillUploadStore(options?: {
|
||||
rootDir?: string;
|
||||
now?: () => number;
|
||||
ttlMs?: number;
|
||||
@@ -608,3 +608,9 @@ export function createSkillUploadStore(options?: {
|
||||
}
|
||||
|
||||
export const defaultSkillUploadStore = createSkillUploadStore();
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.skillUploadStoreTestApi")] = {
|
||||
createSkillUploadStore,
|
||||
};
|
||||
}
|
||||
|
||||
15
src/skills/runtime/refresh.test-support.ts
Normal file
15
src/skills/runtime/refresh.test-support.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import "./refresh.js";
|
||||
|
||||
type SkillsRefreshTestApi = {
|
||||
resetSkillsRefreshForTest(): Promise<void>;
|
||||
};
|
||||
|
||||
function getTestApi(): SkillsRefreshTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.skillsRefreshTestApi")
|
||||
] as SkillsRefreshTestApi;
|
||||
}
|
||||
|
||||
export async function resetSkillsRefreshForTest(): Promise<void> {
|
||||
await getTestApi().resetSkillsRefreshForTest();
|
||||
}
|
||||
@@ -38,6 +38,7 @@ const watchMock = vi.fn(() => {
|
||||
});
|
||||
|
||||
let refreshModule: typeof import("./refresh.js");
|
||||
let refreshTestSupport: typeof import("./refresh.test-support.js");
|
||||
|
||||
vi.mock("chokidar", () => ({
|
||||
default: { watch: watchMock },
|
||||
@@ -50,6 +51,7 @@ vi.mock("../loading/plugin-skills.js", () => ({
|
||||
describe("ensureSkillsWatcher", () => {
|
||||
beforeAll(async () => {
|
||||
refreshModule = await import("./refresh.js");
|
||||
refreshTestSupport = await import("./refresh.test-support.js");
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -59,7 +61,7 @@ describe("ensureSkillsWatcher", () => {
|
||||
|
||||
afterEach(async () => {
|
||||
vi.useRealTimers();
|
||||
await refreshModule.resetSkillsRefreshForTest();
|
||||
await refreshTestSupport.resetSkillsRefreshForTest();
|
||||
});
|
||||
|
||||
it("watches skill roots and filters non-skill churn", async () => {
|
||||
|
||||
@@ -712,7 +712,7 @@ export function ensureSkillsWatcher(params: { workspaceDir: string; config?: Ope
|
||||
evictIdleWorkspaceWatchStates(now);
|
||||
}
|
||||
|
||||
export async function resetSkillsRefreshForTest(): Promise<void> {
|
||||
async function resetSkillsRefreshForTest(): Promise<void> {
|
||||
resetSkillsRefreshStateForTest();
|
||||
|
||||
const active = Array.from(pathWatchers.values());
|
||||
@@ -733,3 +733,9 @@ export async function resetSkillsRefreshForTest(): Promise<void> {
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.skillsRefreshTestApi")] = {
|
||||
resetSkillsRefreshForTest,
|
||||
};
|
||||
}
|
||||
|
||||
15
src/skills/runtime/remote-skills.test-support.ts
Normal file
15
src/skills/runtime/remote-skills.test-support.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import "./remote-skills.js";
|
||||
|
||||
type RemoteNodeSkillsTestApi = {
|
||||
resetRemoteNodeSkillsForTests(): void;
|
||||
};
|
||||
|
||||
function getTestApi(): RemoteNodeSkillsTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.remoteNodeSkillsTestApi")
|
||||
] as RemoteNodeSkillsTestApi;
|
||||
}
|
||||
|
||||
export function resetRemoteNodeSkillsForTests(): void {
|
||||
getTestApi().resetRemoteNodeSkillsForTests();
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
recordRemoteSkillNodeInfo,
|
||||
removeRemoteNodeSkills,
|
||||
replaceRemoteNodeSkills,
|
||||
resetRemoteNodeSkillsForTests,
|
||||
} from "./remote-skills.js";
|
||||
import { resetRemoteNodeSkillsForTests } from "./remote-skills.test-support.js";
|
||||
|
||||
function content(name: string, description: string, body = "# Instructions"): string {
|
||||
return `---\nname: ${name}\ndescription: ${description}\n---\n\n${body}\n`;
|
||||
|
||||
@@ -246,6 +246,12 @@ export function mergeRemoteNodeSkillEntries(
|
||||
);
|
||||
}
|
||||
|
||||
export function resetRemoteNodeSkillsForTests(): void {
|
||||
function resetRemoteNodeSkillsForTests(): void {
|
||||
remoteSkillNodes.clear();
|
||||
}
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.remoteNodeSkillsTestApi")] = {
|
||||
resetRemoteNodeSkillsForTests,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { NodeRegistry } from "../../gateway/node-registry.js";
|
||||
import { getSkillsSnapshotVersion } from "./refresh-state.js";
|
||||
import { resetSkillsRefreshForTest } from "./refresh.js";
|
||||
import { resetSkillsRefreshForTest } from "./refresh.test-support.js";
|
||||
import {
|
||||
getRemoteSkillEligibility,
|
||||
recordRemoteNodeBins,
|
||||
|
||||
41
src/system-agent/agent-turn.test-support.ts
Normal file
41
src/system-agent/agent-turn.test-support.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { SystemAgentTurnRunner } from "./agent-turn.js";
|
||||
import "./agent-turn.js";
|
||||
import type { SystemAgentVerifiedInferenceDeps } from "./verified-inference.js";
|
||||
|
||||
type SystemAgentRunEmbeddedAgent = (
|
||||
params: Parameters<typeof import("../agents/embedded-agent.js").runEmbeddedAgent>[0] & {
|
||||
systemAgentTool?: import("../agents/tools/system-agent-tool.js").SystemAgentToolOptions;
|
||||
},
|
||||
) => ReturnType<typeof import("../agents/embedded-agent.js").runEmbeddedAgent>;
|
||||
|
||||
type SystemAgentRunCliAgent = (
|
||||
params: Parameters<typeof import("../agents/cli-runner.js").runCliAgent>[0] & {
|
||||
systemAgentTool?: import("../agents/tools/system-agent-tool.js").SystemAgentToolOptions;
|
||||
},
|
||||
) => ReturnType<typeof import("../agents/cli-runner.js").runCliAgent>;
|
||||
|
||||
export type SystemAgentTurnDeps = SystemAgentVerifiedInferenceDeps & {
|
||||
runEmbeddedAgent?: SystemAgentRunEmbeddedAgent;
|
||||
runCliAgent?: SystemAgentRunCliAgent;
|
||||
readConfigFileSnapshot?: typeof import("../config/config.js").readConfigFileSnapshot;
|
||||
};
|
||||
|
||||
type SystemAgentTurnTestApi = {
|
||||
runSystemAgentTurnWithDeps(
|
||||
params: Parameters<SystemAgentTurnRunner>[0],
|
||||
deps?: SystemAgentTurnDeps,
|
||||
): ReturnType<SystemAgentTurnRunner>;
|
||||
};
|
||||
|
||||
function getTestApi(): SystemAgentTurnTestApi {
|
||||
return (globalThis as Record<PropertyKey, unknown>)[
|
||||
Symbol.for("openclaw.systemAgentTurnTestApi")
|
||||
] as SystemAgentTurnTestApi;
|
||||
}
|
||||
|
||||
export function runSystemAgentTurnWithDeps(
|
||||
params: Parameters<SystemAgentTurnRunner>[0],
|
||||
deps: SystemAgentTurnDeps = {},
|
||||
): ReturnType<SystemAgentTurnRunner> {
|
||||
return getTestApi().runSystemAgentTurnWithDeps(params, deps);
|
||||
}
|
||||
@@ -8,9 +8,9 @@ import type { CliBackendConfig, OpenClawConfig } from "../config/types.js";
|
||||
import {
|
||||
cleanupSystemAgentSession,
|
||||
createSystemAgentSession,
|
||||
runSystemAgentTurnWithDeps,
|
||||
type SystemAgentSession,
|
||||
} from "./agent-turn.js";
|
||||
import { runSystemAgentTurnWithDeps, type SystemAgentTurnDeps } from "./agent-turn.test-support.js";
|
||||
import { SystemAgentInferenceUnavailableError } from "./inference-error.js";
|
||||
import { resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route.js";
|
||||
import { createSystemAgentVerifiedInferenceTestFixture } from "./system-agent.test-helpers.js";
|
||||
@@ -29,7 +29,6 @@ vi.mock("../agents/harness/runtime-plugin.js", async (importOriginal) => ({
|
||||
),
|
||||
}));
|
||||
|
||||
type SystemAgentTurnDeps = NonNullable<Parameters<typeof runSystemAgentTurnWithDeps>[1]>;
|
||||
type RunCliAgentParams = Parameters<NonNullable<SystemAgentTurnDeps["runCliAgent"]>>[0];
|
||||
type RunEmbeddedAgentParams = Parameters<NonNullable<SystemAgentTurnDeps["runEmbeddedAgent"]>>[0];
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ async function mirrorSystemAgentToolStateFromEvents(params: {
|
||||
* output failures are typed so callers may try another inference path without
|
||||
* mistaking the failure for deterministic setup authority.
|
||||
*/
|
||||
export async function runSystemAgentTurnWithDeps(
|
||||
async function runSystemAgentTurnWithDeps(
|
||||
params: SystemAgentTurnParams,
|
||||
deps: SystemAgentTurnDeps = {},
|
||||
): Promise<SystemAgentTurnReply | null> {
|
||||
@@ -435,3 +435,9 @@ export async function runSystemAgentTurnWithDeps(
|
||||
|
||||
export const runSystemAgentTurn: SystemAgentTurnRunner = (params) =>
|
||||
runSystemAgentTurnWithDeps(params);
|
||||
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.systemAgentTurnTestApi")] = {
|
||||
runSystemAgentTurnWithDeps,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { hashSystemAgentOperation } from "../agents/tools/system-agent-tool.js";
|
||||
import type { ConfigFileSnapshot, OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import { runSystemAgentTurnWithDeps } from "./agent-turn.js";
|
||||
import { runSystemAgentTurnWithDeps } from "./agent-turn.test-support.js";
|
||||
import { classifySystemAgentApprovalText } from "./approval-intent.js";
|
||||
import {
|
||||
SystemAgentChatEngine as RuntimeSystemAgentChatEngine,
|
||||
|
||||
@@ -32,11 +32,8 @@ import {
|
||||
import { ensurePluginRegistryLoaded } from "../plugins/runtime/runtime-registry-loader.js";
|
||||
import type { ProviderPlugin } from "../plugins/types.js";
|
||||
import { disposeOpenClawAgentDatabaseByPath } from "../state/openclaw-agent-db.js";
|
||||
import {
|
||||
cleanupSystemAgentSession,
|
||||
createSystemAgentSession,
|
||||
runSystemAgentTurnWithDeps,
|
||||
} from "./agent-turn.js";
|
||||
import { cleanupSystemAgentSession, createSystemAgentSession } from "./agent-turn.js";
|
||||
import { runSystemAgentTurnWithDeps } from "./agent-turn.test-support.js";
|
||||
import { resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route.js";
|
||||
import { applySystemAgentModelSelection } from "./setup-apply.js";
|
||||
import { resolveSetupInferenceProbeStreamParams } from "./setup-inference-probe.js";
|
||||
|
||||
Reference in New Issue
Block a user