refactor(deadcode): privatize runtime test seams (#108338)

* refactor(sessions): privatize runtime test seams

* refactor(commitments): privatize extraction test seams

* refactor(flows): privatize doctor health seams

* refactor(tasks): privatize registry test seams

* build(commitments): bundle Docker test support

* chore(deadcode): shrink runtime export baseline
This commit is contained in:
Peter Steinberger
2026-07-15 07:27:10 -07:00
committed by GitHub
parent 8d5592548b
commit 3d76a4af92
78 changed files with 679 additions and 220 deletions
-21
View File
@@ -85,10 +85,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/commands/sessions-tail.ts: setSessionsTailFollowIntervalMsForTests",
"src/commands/sessions.ts: testing",
"src/commands/status.command.ts: resolvePairingRecoveryContext",
"src/commitments/extraction.ts: validateCommitmentCandidates",
"src/commitments/runtime.ts: configureCommitmentExtractionRuntime",
"src/commitments/runtime.ts: drainCommitmentExtractionQueue",
"src/commitments/runtime.ts: resetCommitmentExtractionRuntimeForTests",
"src/cron/isolated-agent/delivery-dispatch.ts: getCompletedDirectCronDeliveriesCountForTests",
"src/cron/isolated-agent/delivery-dispatch.ts: resetCompletedDirectCronDeliveriesForTests",
"src/cron/schedule.ts: clearCronScheduleCacheForTest",
@@ -100,24 +96,7 @@ 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/flows/doctor-health-contributions.ts: createDoctorHealthContribution",
"src/flows/doctor-health-contributions.ts: resolveDoctorHealthContributions",
"src/logging/redact-internal.ts: withFullContextToolPayloadRedaction",
"src/sessions/session-lifecycle-admission.ts: runExclusiveSessionLifecycle",
"src/sessions/session-upstream-monitor.ts: runSessionUpstreamMonitorTick",
"src/sessions/user-turn-transcript.ts: persistUserTurnTranscript",
"src/tasks/detached-task-runtime.ts: resetDetachedTaskLifecycleRuntimeForTests",
"src/tasks/detached-task-runtime.ts: setDetachedTaskLifecycleRuntime",
"src/tasks/generated-media-task-activity.ts: resetGeneratedMediaTaskActivityForTests",
"src/tasks/task-flow-registry.store.ts: configureTaskFlowRegistryRuntime",
"src/tasks/task-flow-registry.ts: createFlowRecord",
"src/tasks/task-flow-registry.ts: resetTaskFlowRegistryForTests",
"src/tasks/task-registry.ts: maybeDeliverTaskStateChangeUpdate",
"src/tasks/task-registry.ts: resetTaskRegistryControlRuntimeForTests",
"src/tasks/task-registry.ts: resetTaskRegistryDeliveryRuntimeForTests",
"src/tasks/task-registry.ts: resetTaskRegistryForTests",
"src/tasks/task-registry.ts: setTaskRegistryControlRuntimeForTests",
"src/tasks/task-registry.ts: setTaskRegistryDeliveryRuntimeForTests",
];
// Platform-variant findings. Allowed when present; never required.
@@ -4,12 +4,12 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { DatabaseSync } from "node:sqlite";
import { enqueueCommitmentExtraction } from "../../dist/commitments/runtime.js";
import {
configureCommitmentExtractionRuntime,
drainCommitmentExtractionQueue,
enqueueCommitmentExtraction,
resetCommitmentExtractionRuntimeForTests,
} from "../../dist/commitments/runtime.js";
} from "../../dist/commitments/runtime.test-support.js";
import {
listCommitments,
listDueCommitmentsForSession,
+1
View File
@@ -23,6 +23,7 @@ set +e
docker_e2e_run_with_harness \
--name "$CONTAINER_NAME" \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e OPENCLAW_COMMITMENTS_SAFETY_E2E=1 \
"$IMAGE_NAME" \
bash -lc 'set -euo pipefail; tsx scripts/e2e/commitments-safety-docker-client.ts' \
>"$RUN_LOG" 2>&1
@@ -20,10 +20,8 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { createUserTurnTranscriptRecorder } from "../../sessions/user-turn-transcript.js";
import { createTestUserTurnTranscriptTarget } from "../../sessions/user-turn-transcript.test-support.js";
import { closeOpenClawAgentDatabasesForTest } from "../../state/openclaw-agent-db.js";
import {
registerGeneratedMediaTaskActivity,
resetGeneratedMediaTaskActivityForTests,
} from "../../tasks/generated-media-task-activity.js";
import { registerGeneratedMediaTaskActivity } from "../../tasks/generated-media-task-activity.js";
import { resetGeneratedMediaTaskActivityForTests } from "../../tasks/task-runtime.test-helpers.js";
import { captureEnv, setTestEnvValue } from "../../test-utils/env.js";
import { saveAuthProfileStore } from "../auth-profiles/store.js";
import type { EmbeddedAgentRunResult } from "../embedded-agent.js";
@@ -8,14 +8,14 @@ import { enqueueCommandInLane, markGatewayDraining } from "../../process/command
import * as commandQueueModule from "../../process/command-queue.js";
import { resetCommandQueueStateForTest } from "../../process/command-queue.test-support.js";
import { createQueuedTaskRun as createQueuedTaskRunOrNull } from "../../tasks/task-executor.js";
import { getTaskFlowById, resetTaskFlowRegistryForTests } from "../../tasks/task-flow-registry.js";
import { getTaskFlowById } from "../../tasks/task-flow-registry.js";
import { getTaskById, listTasksForOwnerKey } from "../../tasks/task-registry.js";
import type { TaskRecord } from "../../tasks/task-registry.types.js";
import {
getTaskById,
listTasksForOwnerKey,
resetTaskFlowRegistryForTests,
resetTaskRegistryForTests,
setTaskRegistryDeliveryRuntimeForTests,
} from "../../tasks/task-registry.js";
import type { TaskRecord } from "../../tasks/task-registry.types.js";
} from "../../tasks/task-runtime.test-helpers.js";
import { withStateDirEnv } from "../../test-helpers/state-dir-env.js";
import { castAgentMessage } from "../test-helpers/agent-message-fixtures.js";
import { resolveSessionLane } from "./lanes.js";
@@ -5,7 +5,7 @@ import {
createRunningTaskRun,
} from "../../../tasks/detached-task-runtime.js";
import type { TaskRecord } from "../../../tasks/runtime-internal.js";
import { resetTaskRegistryForTests } from "../../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../../tasks/task-runtime.test-helpers.js";
import {
requiresCompletionRequiredAsyncTaskWait,
shouldWaitForCompletionRequiredAsyncTasks,
@@ -29,9 +29,9 @@ import type { Context, Model } from "../../../llm/types.js";
import {
createUserTurnTranscriptRecorder,
mergePreparedUserTurnMessageForRuntime,
persistUserTurnTranscript,
type UserTurnInput,
} from "../../../sessions/user-turn-transcript.js";
import { persistUserTurnTranscript } from "../../../sessions/user-turn-transcript.test-support.js";
import {
OPENCLAW_RUNTIME_CONTEXT_CUSTOM_TYPE,
relocateCurrentRuntimeContextCarrierToTail,
@@ -13,8 +13,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { setRuntimeConfigSnapshot } from "../config/config.js";
import { callGateway } from "../gateway/call.js";
import { createRunningTaskRun } from "../tasks/detached-task-runtime.js";
import { resetTaskFlowRegistryForTests } from "../tasks/task-flow-registry.js";
import { findTaskByRunId, resetTaskRegistryForTests } from "../tasks/task-registry.js";
import { findTaskByRunId } from "../tasks/task-registry.js";
import {
resetTaskFlowRegistryForTests,
resetTaskRegistryForTests,
} from "../tasks/task-runtime.test-helpers.js";
import { captureEnv } from "../test-utils/env.js";
import { cleanupSessionStateForTest } from "../test-utils/session-state-cleanup.js";
import { recoverOrphanedSubagentSessions } from "./subagent-orphan-recovery.js";
@@ -6,11 +6,11 @@ import path from "node:path";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { callGateway } from "../gateway/call.js";
import { SUBAGENT_KILL_TASK_ERROR } from "../tasks/detached-task-runtime-contract.js";
import { getDetachedTaskLifecycleRuntime } from "../tasks/detached-task-runtime.js";
import {
getDetachedTaskLifecycleRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "../tasks/detached-task-runtime.js";
} from "../tasks/task-runtime.test-helpers.js";
const taskRuntimeMocks = vi.hoisted(() => ({
finalizeTaskRunByRunId: vi.fn<(_params: unknown) => unknown[]>(() => [{}]),
@@ -4,10 +4,8 @@
import { expectDefined } from "@openclaw/normalization-core";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { ContextEngine } from "../context-engine/types.js";
import {
getDetachedTaskLifecycleRuntime,
setDetachedTaskLifecycleRuntime,
} from "../tasks/detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "../tasks/detached-task-runtime.js";
import { setDetachedTaskLifecycleRuntime } from "../tasks/task-runtime.test-helpers.js";
import { findTaskByRunIdForStatus } from "../tasks/task-status-access.js";
const noop = () => {};
+6 -4
View File
@@ -23,11 +23,13 @@ import {
findDetachedTaskRun,
finalizeTaskRunByRunId,
getDetachedTaskLifecycleRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "../tasks/detached-task-runtime.js";
import { resetTaskFlowRegistryForTests } from "../tasks/task-flow-registry.js";
import { resetTaskRegistryForTests } from "../tasks/task-registry.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskFlowRegistryForTests,
resetTaskRegistryForTests,
setDetachedTaskLifecycleRuntime,
} from "../tasks/task-runtime.test-helpers.js";
import { findTaskByRunIdForStatus } from "../tasks/task-status-access.js";
import {
SUBAGENT_ENDED_REASON_COMPLETE,
@@ -2,7 +2,7 @@
// wake delivery, and direct media fallback behavior.
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { SessionEntry } from "../../config/sessions/types.js";
import { resetGeneratedMediaTaskActivityForTests } from "../../tasks/generated-media-task-activity.js";
import { resetGeneratedMediaTaskActivityForTests } from "../../tasks/task-runtime.test-helpers.js";
import { hasPendingGeneratedMediaTaskForSessionKey } from "../../tasks/task-status-access.js";
const subagentAnnounceDeliveryMocks = vi.hoisted(() => ({
+2 -2
View File
@@ -147,8 +147,8 @@ const { buildCommandTestParams } = await import("./commands-spawn.test-harness.j
const { testing: acpManagerTesting } = await import("../../acp/control-plane/manager.js");
const { testing: acpResetTargetTesting, resolveEffectiveResetTargetSessionKey } =
await import("./acp-reset-target.js");
const { createTaskRecord, resetTaskRegistryForTests } =
await import("../../tasks/task-registry.js");
const { createTaskRecord } = await import("../../tasks/task-registry.js");
const { resetTaskRegistryForTests } = await import("../../tasks/task-runtime.test-helpers.js");
const { configureTaskRegistryRuntime } = await import("../../tasks/task-registry.store.js");
const { failTaskRunByRunId } = await import("../../tasks/task-executor.js");
+1 -1
View File
@@ -20,7 +20,7 @@ import {
createRunningTaskRun,
failTaskRunByRunId,
} from "../../tasks/task-executor.js";
import { resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { withEnvAsync } from "../../test-utils/env.js";
import { buildStatusPluginsReply, buildStatusReply, buildStatusText } from "./commands-status.js";
import {
@@ -9,7 +9,8 @@ import {
import type { SubagentRunRecord } from "../../agents/subagent-registry.types.js";
import type { OpenClawConfig } from "../../config/config.js";
import { failTaskRunByRunId } from "../../tasks/task-executor.js";
import { createTaskRecord, resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import { createTaskRecord } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import type { ReplyPayload } from "../types.js";
import { handleSubagentsInfoAction } from "./commands-subagents/action-info.js";
import {
+1 -1
View File
@@ -7,7 +7,7 @@ import {
createRunningTaskRun,
failTaskRunByRunId,
} from "../../tasks/task-executor.js";
import { resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { handleTasksCommand } from "./commands-tasks.js";
import {
baseCommandTestConfig,
+4 -6
View File
@@ -2,16 +2,14 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { RuntimeEnv } from "../runtime.js";
import { createRunningTaskRun as createRunningTaskRunOrNull } from "../tasks/task-executor.js";
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
resetTaskFlowRegistryForTests,
} from "../tasks/task-flow-registry.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "../tasks/task-flow-registry.js";
import type { TaskFlowRecord } from "../tasks/task-flow-registry.types.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
import {
resetTaskFlowRegistryForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "../tasks/task-registry.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
} from "../tasks/task-runtime.test-helpers.js";
import { captureEnv } from "../test-utils/env.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import { flowsCancelCommand, flowsListCommand, flowsShowCommand } from "./flows.js";
+6 -8
View File
@@ -1,18 +1,16 @@
// Tasks JSON tests cover structured task command output and managed task flow state.
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { RuntimeEnv } from "../runtime.js";
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
resetTaskFlowRegistryForTests,
} from "../tasks/task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "../tasks/task-flow-registry.store.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "../tasks/task-flow-registry.js";
import type { TaskFlowRecord } from "../tasks/task-flow-registry.types.js";
import { createTaskRecord as createTaskRecordOrNull } from "../tasks/task-registry.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
import {
createTaskRecord as createTaskRecordOrNull,
configureTaskFlowRegistryRuntime,
resetTaskFlowRegistryForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "../tasks/task-registry.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
} from "../tasks/task-runtime.test-helpers.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import { tasksAuditJsonCommand, tasksListJsonCommand } from "./tasks-json.js";
+8 -8
View File
@@ -7,22 +7,22 @@ import type { SessionEntry } from "../config/sessions/types.js";
import { saveCronStore } from "../cron/store.js";
import type { RuntimeEnv } from "../runtime.js";
import { closeOpenClawAgentDatabasesForTest } from "../state/openclaw-agent-db.js";
import { resetDetachedTaskLifecycleRuntimeForTests } from "../tasks/detached-task-runtime.js";
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
resetTaskFlowRegistryForTests,
} from "../tasks/task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "../tasks/task-flow-registry.store.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "../tasks/task-flow-registry.js";
import type { TaskFlowRecord } from "../tasks/task-flow-registry.types.js";
import {
createTaskRecord as createTaskRecordOrNull,
getTaskById,
reloadTaskRegistryFromStore,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "../tasks/task-registry.js";
import * as taskRegistryMaintenance from "../tasks/task-registry.maintenance.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskFlowRegistryForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "../tasks/task-runtime.test-helpers.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import type { OpenClawTestState } from "../test-utils/openclaw-test-state.js";
import type { TaskSystemAuditCode, TaskSystemAuditSeverity } from "./tasks-audit-system.js";
@@ -9,12 +9,12 @@ import {
} from "../infra/heartbeat-runner.test-utils.js";
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { withEnvAsync } from "../test-utils/env.js";
import { enqueueCommitmentExtraction } from "./runtime.js";
import {
configureCommitmentExtractionRuntime,
drainCommitmentExtractionQueue,
enqueueCommitmentExtraction,
resetCommitmentExtractionRuntimeForTests,
} from "./runtime.js";
} from "./runtime.test-support.js";
import { readCommitmentsForTest } from "./store.test-utils.js";
import type { CommitmentExtractionBatchResult, CommitmentExtractionItem } from "./types.js";
@@ -0,0 +1,40 @@
import type { OpenClawConfig } from "../config/config.js";
import "./extraction.js";
import type {
CommitmentCandidate,
CommitmentExtractionBatchResult,
CommitmentExtractionItem,
} from "./types.js";
type ValidatedCommitmentCandidate = {
item: CommitmentExtractionItem;
candidate: CommitmentCandidate;
earliestMs: number;
latestMs: number;
timezone: string;
};
type CommitmentExtractionTestApi = {
validateCommitmentCandidates(params: {
cfg?: OpenClawConfig;
items: CommitmentExtractionItem[];
result: CommitmentExtractionBatchResult;
nowMs?: number;
}): ValidatedCommitmentCandidate[];
};
function getTestApi(): CommitmentExtractionTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.commitmentExtractionTestApi")
];
if (!api) {
throw new Error("commitment extraction test API is unavailable");
}
return api as CommitmentExtractionTestApi;
}
export function validateCommitmentCandidates(
params: Parameters<CommitmentExtractionTestApi["validateCommitmentCandidates"]>[0],
): ValidatedCommitmentCandidate[] {
return getTestApi().validateCommitmentCandidates(params);
}
+1 -1
View File
@@ -10,8 +10,8 @@ import {
buildCommitmentExtractionPrompt,
parseCommitmentExtractionOutput,
persistCommitmentExtractionResult,
validateCommitmentCandidates,
} from "./extraction.js";
import { validateCommitmentCandidates } from "./extraction.test-support.js";
import { readCommitmentsForTest } from "./store.test-utils.js";
import type { CommitmentCandidate, CommitmentExtractionItem } from "./types.js";
+6 -1
View File
@@ -273,7 +273,7 @@ function resolveMinimumDueMs(params: {
return params.nowMs + intervalMs;
}
export function validateCommitmentCandidates(params: {
function validateCommitmentCandidates(params: {
cfg?: OpenClawConfig;
items: CommitmentExtractionItem[];
result: CommitmentExtractionBatchResult;
@@ -370,3 +370,8 @@ export async function persistCommitmentExtractionResult(params: {
}
return created;
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.commitmentExtractionTestApi")] =
{ validateCommitmentCandidates };
}
+47
View File
@@ -0,0 +1,47 @@
import type { OpenClawConfig } from "../config/config.js";
import "./runtime.js";
import type { CommitmentExtractionBatchResult, CommitmentExtractionItem } from "./types.js";
type TimerHandle = ReturnType<typeof setTimeout>;
type CommitmentExtractionRuntime = {
extractBatch?: (params: {
cfg?: OpenClawConfig;
items: CommitmentExtractionItem[];
}) => Promise<CommitmentExtractionBatchResult>;
resolveDefaultModel?: (params: { cfg: OpenClawConfig; agentId?: string }) => {
provider: string;
model: string;
};
setTimer?: (callback: () => void, delayMs: number) => TimerHandle;
clearTimer?: (timer: TimerHandle) => void;
forceInTests?: boolean;
};
type CommitmentRuntimeTestApi = {
configureCommitmentExtractionRuntime(next: CommitmentExtractionRuntime): void;
drainCommitmentExtractionQueue(): Promise<number>;
resetCommitmentExtractionRuntimeForTests(): void;
};
function getTestApi(): CommitmentRuntimeTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.commitmentRuntimeTestApi")
];
if (!api) {
throw new Error("commitment runtime test API is unavailable");
}
return api as CommitmentRuntimeTestApi;
}
export function configureCommitmentExtractionRuntime(next: CommitmentExtractionRuntime): void {
getTestApi().configureCommitmentExtractionRuntime(next);
}
export async function drainCommitmentExtractionQueue(): Promise<number> {
return await getTestApi().drainCommitmentExtractionQueue();
}
export function resetCommitmentExtractionRuntimeForTests(): void {
getTestApi().resetCommitmentExtractionRuntimeForTests();
}
+2 -2
View File
@@ -6,12 +6,12 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { captureEnv, setTestEnvValue } from "../test-utils/env.js";
import { enqueueCommitmentExtraction } from "./runtime.js";
import {
configureCommitmentExtractionRuntime,
drainCommitmentExtractionQueue,
enqueueCommitmentExtraction,
resetCommitmentExtractionRuntimeForTests,
} from "./runtime.js";
} from "./runtime.test-support.js";
import { readCommitmentsForTest, seedCommitmentsForTest } from "./store.test-utils.js";
import type { CommitmentExtractionBatchResult, CommitmentExtractionItem } from "./types.js";
+15 -3
View File
@@ -91,12 +91,12 @@ function scheduleDrainSoon(debounceMs: number): void {
}
/** Installs runtime hooks for extraction tests or alternate batch extraction. */
export function configureCommitmentExtractionRuntime(next: CommitmentExtractionRuntime): void {
function configureCommitmentExtractionRuntime(next: CommitmentExtractionRuntime): void {
runtime = next;
}
/** Clears queued work, timers, and injected hooks for isolated tests. */
export function resetCommitmentExtractionRuntimeForTests(): void {
function resetCommitmentExtractionRuntimeForTests(): void {
if (timer) {
clearTimer(timer);
}
@@ -299,7 +299,7 @@ function takeAgentBatch(
}
/** Drains queued extraction work in batches and returns processed item count. */
export async function drainCommitmentExtractionQueue(): Promise<number> {
async function drainCommitmentExtractionQueue(): Promise<number> {
if (draining) {
return 0;
}
@@ -357,3 +357,15 @@ export async function drainCommitmentExtractionQueue(): Promise<number> {
draining = false;
}
}
if (
process.env.VITEST ||
process.env.NODE_ENV === "test" ||
process.env.OPENCLAW_COMMITMENTS_SAFETY_E2E === "1"
) {
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.commitmentRuntimeTestApi")] = {
configureCommitmentExtractionRuntime,
drainCommitmentExtractionQueue,
resetCommitmentExtractionRuntimeForTests,
};
}
+2 -5
View File
@@ -4,11 +4,8 @@ import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { runOpenClawStateWriteTransaction } from "../../state/openclaw-state-db.js";
import * as taskExecutor from "../../tasks/task-executor.js";
import {
findTaskByRunId,
listTaskRecordsUnsorted,
resetTaskRegistryForTests,
} from "../../tasks/task-registry.js";
import { findTaskByRunId, listTaskRecordsUnsorted } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { formatTaskStatusDetail } from "../../tasks/task-status.js";
import { withEnvAsync } from "../../test-utils/env.js";
import * as cronSchedule from "../schedule.js";
+7 -6
View File
@@ -1,14 +1,15 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import {
getDetachedTaskLifecycleRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "../../tasks/detached-task-runtime.js";
import * as taskExecutor from "../../tasks/task-executor.js";
import { finalizeTaskRunByRunId } from "../../tasks/task-executor.js";
import * as taskRegistry from "../../tasks/task-registry.js";
import { markTaskLostById, resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import { markTaskLostById } from "../../tasks/task-registry.js";
import { listTaskRegistryRecordsByRuntimeSourceIdFromSqlite } from "../../tasks/task-registry.store.sqlite.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskRegistryForTests,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/task-runtime.test-helpers.js";
import { withOpenClawTestState } from "../../test-utils/openclaw-test-state.js";
import { cronStoreKey } from "../store/key.js";
import { readCronTaskRunHistoryPage } from "../task-run-history.js";
@@ -3,7 +3,7 @@
// computed in memory by applyJobResult.
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import { resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { withEnvAsync } from "../../test-utils/env.js";
import { setupCronServiceSuite, writeCronStoreSnapshot } from "../service.test-harness.js";
import { loadCronStore } from "../store.js";
+2 -3
View File
@@ -13,13 +13,12 @@ import {
import { HEARTBEAT_SKIP_LANES_BUSY, type HeartbeatRunResult } from "../../infra/heartbeat-wake.js";
import { enqueueCommandInLane } from "../../process/command-queue.js";
import { CommandLane } from "../../process/lanes.js";
import { cancelTaskById, listTaskRecords } from "../../tasks/task-registry.js";
import {
cancelTaskById,
listTaskRecords,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryForTests,
setTaskRegistryControlRuntimeForTests,
} from "../../tasks/task-registry.js";
} from "../../tasks/task-runtime.test-helpers.js";
import {
advanceCronActiveJobGeneration,
clearCronJobActive,
+2 -5
View File
@@ -10,11 +10,8 @@ import { loadCronStore } from "../../cron/store.js";
import { cronStoreKey } from "../../cron/store/key.js";
import type { CronJob } from "../../cron/types.js";
import * as taskExecutor from "../../tasks/task-executor.js";
import {
findTaskByRunId,
listTaskRecordsUnsorted,
resetTaskRegistryForTests,
} from "../../tasks/task-registry.js";
import { findTaskByRunId, listTaskRecordsUnsorted } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { formatTaskStatusDetail } from "../../tasks/task-status.js";
const { logger, makeStorePath } = setupCronServiceSuite({
+1 -1
View File
@@ -1,8 +1,8 @@
import { expectDefined } from "@openclaw/normalization-core";
import { describe, expect, it, vi } from "vitest";
import { resetTaskRegistryForTests } from "../tasks/task-registry.js";
import { saveTaskRegistryStateToSqlite } from "../tasks/task-registry.store.sqlite.js";
import type { TaskRecord } from "../tasks/task-registry.types.js";
import { resetTaskRegistryForTests } from "../tasks/task-runtime.test-helpers.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import type { CronRunLogEntry } from "./run-log-types.js";
import { CronService } from "./service.js";
@@ -0,0 +1,57 @@
import type { DoctorHealthFlowContext } from "./doctor-health-contributions.js";
import "./doctor-health-contributions.js";
import type { HealthCheckInput, RunnableHealthCheck } from "./health-check-runner-types.js";
import type { HealthCheck } from "./health-checks.js";
import type { FlowContribution } from "./types.js";
type DoctorContributionHealthCheck =
| (Omit<HealthCheck, "id" | "kind" | "source"> & {
readonly id?: string;
readonly kind?: "core";
readonly source?: string;
})
| (Omit<RunnableHealthCheck, "id" | "kind" | "source"> & {
readonly id?: string;
readonly kind?: "core";
readonly source?: string;
});
type DoctorHealthContribution = FlowContribution & {
kind: "core";
surface: "health";
healthChecks: readonly HealthCheckInput[];
healthCheckIds: readonly string[];
run: (ctx: DoctorHealthFlowContext) => Promise<void>;
};
type DoctorHealthContributionTestApi = {
createDoctorHealthContribution(params: {
id: string;
label: string;
healthCheckIds?: readonly string[];
healthChecks?: DoctorContributionHealthCheck | readonly DoctorContributionHealthCheck[];
hint?: string;
run?: (ctx: DoctorHealthFlowContext) => Promise<void>;
}): DoctorHealthContribution;
resolveDoctorHealthContributions(): DoctorHealthContribution[];
};
function getTestApi(): DoctorHealthContributionTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.doctorHealthContributionsTestApi")
];
if (!api) {
throw new Error("doctor health contributions test API is unavailable");
}
return api as DoctorHealthContributionTestApi;
}
export function createDoctorHealthContribution(
params: Parameters<DoctorHealthContributionTestApi["createDoctorHealthContribution"]>[0],
): DoctorHealthContribution {
return getTestApi().createDoctorHealthContribution(params);
}
export function resolveDoctorHealthContributions(): DoctorHealthContribution[] {
return getTestApi().resolveDoctorHealthContributions();
}
@@ -7,11 +7,11 @@ import type { DoctorPrompter } from "../commands/doctor-prompter.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { CORE_HEALTH_CHECKS } from "./doctor-core-checks.js";
import "./doctor-tool-result-cap-advice.js";
import { resolveDoctorContributionHealthChecks } from "./doctor-health-contributions.js";
import {
createDoctorHealthContribution,
resolveDoctorContributionHealthChecks,
resolveDoctorHealthContributions,
} from "./doctor-health-contributions.js";
} from "./doctor-health-contributions.test-support.js";
import { runDoctorLintChecks } from "./doctor-lint-flow.js";
import type { HealthCheck, HealthFinding } from "./health-checks.js";
+8 -2
View File
@@ -113,7 +113,7 @@ function shouldSkipLegacyUpdateDoctorConfigWrite(params: { env: NodeJS.ProcessEn
return true;
}
export function createDoctorHealthContribution(params: {
function createDoctorHealthContribution(params: {
id: string;
label: string;
healthCheckIds?: readonly string[];
@@ -1529,7 +1529,7 @@ async function runSkillWorkshopToolPolicyHealth(ctx: DoctorHealthFlowContext): P
await runCoreHealthFindingNote(ctx, "core/doctor/skill-workshop-tool-policy");
}
export function resolveDoctorHealthContributions(): DoctorHealthContribution[] {
function resolveDoctorHealthContributions(): DoctorHealthContribution[] {
return [
createDoctorHealthContribution({
id: "doctor:gateway-config",
@@ -2282,4 +2282,10 @@ export async function runDoctorHealthContributions(ctx: DoctorHealthFlowContext)
await contribution.run(ctx);
}
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.doctorHealthContributionsTestApi")
] = { createDoctorHealthContribution, resolveDoctorHealthContributions };
}
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
@@ -13,11 +13,9 @@ import {
resumeGatewaySuspend,
} from "../../infra/gateway-suspend-coordinator.js";
import { resetGatewayWorkAdmission } from "../../process/gateway-work-admission.js";
import {
getDetachedTaskLifecycleRuntime,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "../../tasks/detached-task-runtime.js";
import { findTaskByRunId } from "../../tasks/task-registry.js";
import { setDetachedTaskLifecycleRuntime } from "../../tasks/task-runtime.test-helpers.js";
import {
getAgentTestMocks,
makeContext,
@@ -9,16 +9,16 @@ import {
resetSubagentRegistryForTests,
testing as subagentRegistryTesting,
} from "../../agents/subagent-registry.test-helpers.js";
import {
getDetachedTaskLifecycleRuntime,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "../../tasks/detached-task-runtime.js";
import {
findTaskByRunId,
listTaskRecords,
markTaskTerminalById,
resetTaskRegistryForTests,
} from "../../tasks/task-registry.js";
import {
resetTaskRegistryForTests,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/task-runtime.test-helpers.js";
import { withTempDir } from "../../test-helpers/temp-dir.js";
import {
getAgentTestMocks,
@@ -12,8 +12,10 @@ import type { SessionEntry } from "../../config/sessions.js";
import type { SessionTranscriptStats } from "../../config/sessions/session-accessor.js";
import { parseSqliteSessionFileMarker } from "../../config/sessions/sqlite-marker.js";
import { resetDiagnosticEventsForTest } from "../../infra/diagnostic-events.js";
import { resetDetachedTaskLifecycleRuntimeForTests } from "../../tasks/detached-task-runtime.js";
import { resetTaskRegistryForTests } from "../../tasks/task-registry.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskRegistryForTests,
} from "../../tasks/task-runtime.test-helpers.js";
import { captureEnv, setTestEnvValue } from "../../test-utils/env.js";
import { agentHandlers } from "./agent.js";
import { suspendHandlers } from "./suspend.js";
+4 -4
View File
@@ -13,14 +13,14 @@ import {
markTaskTerminalById,
recordTaskProgressByRunId,
} from "../../tasks/runtime-internal.js";
import { reloadTaskRegistryFromStore } from "../../tasks/task-registry.js";
import { saveTaskRegistryStateToSqlite } from "../../tasks/task-registry.store.sqlite.js";
import type { TaskRecord } from "../../tasks/task-registry.types.js";
import {
reloadTaskRegistryFromStore,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryForTests,
setTaskRegistryControlRuntimeForTests,
} from "../../tasks/task-registry.js";
import { saveTaskRegistryStateToSqlite } from "../../tasks/task-registry.store.sqlite.js";
import type { TaskRecord } from "../../tasks/task-registry.types.js";
} from "../../tasks/task-runtime.test-helpers.js";
import { captureEnv, setTestEnvValue } from "../../test-utils/env.js";
import { tasksHandlers } from "./tasks.js";
import type { RespondFn } from "./types.js";
@@ -11,8 +11,9 @@ import {
emitSessionTranscriptUpdate,
type InternalSessionTranscriptUpdate,
} from "../sessions/transcript-events.js";
import { createTaskRecord, resetTaskRegistryForTests } from "../tasks/task-registry.js";
import { createTaskRecord } from "../tasks/task-registry.js";
import { getTaskRegistryObservers } from "../tasks/task-registry.store.js";
import { resetTaskRegistryForTests } from "../tasks/task-runtime.test-helpers.js";
import { installInMemoryTaskRegistryRuntime } from "../test-utils/task-registry-runtime.js";
import {
createChatRunState,
@@ -16,9 +16,9 @@ import type { SessionAcpMeta } from "../config/sessions/types.js";
import { enqueueSystemEvent, peekSystemEvents } from "../infra/system-events.js";
import {
beginSessionWorkAdmission,
runExclusiveSessionLifecycle,
runExclusiveSessionLifecycleMutation,
} from "../sessions/session-lifecycle-admission.js";
import { runExclusiveSessionLifecycle } from "../sessions/session-lifecycle-admission.test-support.js";
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { embeddedRunMock, testState, writeSessionStore } from "./test-helpers.js";
import {
@@ -8,7 +8,7 @@ import {
closeOpenClawStateDatabaseForTest,
openOpenClawStateDatabase,
} from "../state/openclaw-state-db.js";
import { resetTaskRegistryForTests } from "../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../tasks/task-runtime.test-helpers.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
const CRON_RUN_LOG_TASK_IMPORT_MIGRATION_ID = "state:cron-run-logs-to-task-runs:v1";
@@ -1,7 +1,7 @@
// Runtime task test harness helpers build mocked plugin runtimes for task-flow tests.
import { vi } from "vitest";
import { resetDetachedTaskLifecycleRuntimeForTests } from "../../tasks/detached-task-runtime.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskFlowRegistryForTests,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
+2 -4
View File
@@ -1,9 +1,7 @@
// Runtime task tests cover plugin task runtime registration, invocation, and cleanup.
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
getDetachedTaskLifecycleRuntime,
setDetachedTaskLifecycleRuntime,
} from "../../tasks/detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "../../tasks/detached-task-runtime.js";
import { setDetachedTaskLifecycleRuntime } from "../../tasks/task-runtime.test-helpers.js";
import {
getRuntimeTaskMocks,
installRuntimeTaskDeliveryMock,
@@ -0,0 +1,24 @@
import "./session-lifecycle-admission.js";
type RunExclusiveSessionLifecycleParams<T> = {
scope: string;
identities: Iterable<string | undefined>;
signal?: AbortSignal;
run: () => Promise<T>;
};
type SessionLifecycleAdmissionTestApi = {
runExclusiveSessionLifecycle<T>(params: RunExclusiveSessionLifecycleParams<T>): Promise<T>;
};
function getTestApi(): SessionLifecycleAdmissionTestApi {
return (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.sessionLifecycleAdmissionTestApi")
] as SessionLifecycleAdmissionTestApi;
}
export async function runExclusiveSessionLifecycle<T>(
params: RunExclusiveSessionLifecycleParams<T>,
): Promise<T> {
return await getTestApi().runExclusiveSessionLifecycle(params);
}
+7 -1
View File
@@ -168,7 +168,7 @@ async function waitForNormalizedSessionLifecycleMutationIdle(
}
}
export async function runExclusiveSessionLifecycle<T>(params: {
async function runExclusiveSessionLifecycle<T>(params: {
scope: string;
identities: Iterable<string | undefined>;
signal?: AbortSignal;
@@ -524,3 +524,9 @@ export async function interruptSessionWorkAdmissions(params: {
}
}
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.sessionLifecycleAdmissionTestApi")
] = { runExclusiveSessionLifecycle };
}
@@ -0,0 +1,42 @@
import type { isEmbeddedAgentRunActive } from "../agents/embedded-agent.js";
import type { loadSessionEntry } from "../config/sessions/session-accessor.js";
import type { SessionEntry } from "../config/sessions/types.js";
import type { SessionCatalogProvider, SessionUpstreamProbe } from "../plugins/session-catalog.js";
import type { OpenClawStateDatabaseOptions } from "../state/openclaw-state-db.js";
import "./session-upstream-monitor.js";
type SessionUpstreamMonitorOptions = OpenClawStateDatabaseOptions & {
providers?: readonly SessionCatalogProvider[];
now?: () => number;
loadEntry?: typeof loadSessionEntry;
isRunActive?: typeof isEmbeddedAgentRunActive;
loadOwnRecentUserTexts?: (params: {
entry: SessionEntry;
probe: Omit<SessionUpstreamProbe, "ownRecentUserTexts">;
}) => Promise<string[]>;
};
type SessionUpstreamMissingCounter = {
count: number;
linkUpdatedAt: number;
};
type SessionUpstreamMonitorTestApi = {
runSessionUpstreamMonitorTick(
options?: SessionUpstreamMonitorOptions,
missingCounts?: Map<string, SessionUpstreamMissingCounter>,
): Promise<void>;
};
function getTestApi(): SessionUpstreamMonitorTestApi {
return (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.sessionUpstreamMonitorTestApi")
] as SessionUpstreamMonitorTestApi;
}
export async function runSessionUpstreamMonitorTick(
options: SessionUpstreamMonitorOptions = {},
missingCounts: Map<string, SessionUpstreamMissingCounter> = new Map(),
): Promise<void> {
await getTestApi().runSessionUpstreamMonitorTick(options, missingCounts);
}
@@ -15,7 +15,7 @@ import {
readSessionUpstreamLink,
upsertSessionUpstreamLink,
} from "./session-upstream-links.js";
import { runSessionUpstreamMonitorTick } from "./session-upstream-monitor.js";
import { runSessionUpstreamMonitorTick } from "./session-upstream-monitor.test-support.js";
const tempDirs: string[] = [];
const watcherSessionKey = "agent:main:main";
+7 -1
View File
@@ -131,7 +131,7 @@ async function probeProvenanceUnchanged(
);
}
export async function runSessionUpstreamMonitorTick(
async function runSessionUpstreamMonitorTick(
options: SessionUpstreamMonitorOptions = {},
missingCounts: Map<string, SessionUpstreamMissingCounter> = new Map(),
): Promise<void> {
@@ -374,3 +374,9 @@ export function startSessionUpstreamMonitor(
},
};
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.sessionUpstreamMonitorTestApi")
] = { runSessionUpstreamMonitorTick };
}
@@ -1,4 +1,27 @@
import type { UserTurnTranscriptTarget } from "./user-turn-transcript.types.js";
import "./user-turn-transcript.js";
import type {
PersistUserTurnTranscriptParams,
UserTurnTranscriptPersistResult,
UserTurnTranscriptTarget,
} from "./user-turn-transcript.types.js";
type UserTurnTranscriptTestApi = {
persistUserTurnTranscript(
params: PersistUserTurnTranscriptParams,
): Promise<UserTurnTranscriptPersistResult | undefined>;
};
function getTestApi(): UserTurnTranscriptTestApi {
return (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.userTurnTranscriptTestApi")
] as UserTurnTranscriptTestApi;
}
export async function persistUserTurnTranscript(
params: PersistUserTurnTranscriptParams,
): Promise<UserTurnTranscriptPersistResult | undefined> {
return await getTestApi().persistUserTurnTranscript(params);
}
/** Creates a store-backed transcript target for tests that do not own runtime session setup. */
export function createTestUserTurnTranscriptTarget(
+1 -1
View File
@@ -16,10 +16,10 @@ import {
buildPersistedUserTurnMediaInputsFromFields,
createUserTurnTranscriptRecorder,
mergePreparedUserTurnMessageForRuntime,
persistUserTurnTranscript,
resolvePersistedUserTurnText,
type UserTurnInput,
} from "./user-turn-transcript.js";
import { persistUserTurnTranscript } from "./user-turn-transcript.test-support.js";
describe("user turn transcript persistence", () => {
const tempDirs: string[] = [];
+7 -1
View File
@@ -411,7 +411,7 @@ export function preparePersistedUserTurnMessageForTranscriptWrite(
// Store-backed persistence resolves the current session transcript file lazily
// so callers can pass a session entry/store without knowing the final path.
export async function persistUserTurnTranscript(
async function persistUserTurnTranscript(
params: PersistUserTurnTranscriptParams,
): Promise<UserTurnTranscriptPersistResult | undefined> {
const message = resolvePersistedUserTurnMessage(params);
@@ -710,3 +710,9 @@ export function createUserTurnTranscriptRecorder(
}),
};
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.userTurnTranscriptTestApi")] = {
persistUserTurnTranscript,
};
}
@@ -0,0 +1,13 @@
import type { DetachedTaskLifecycleRuntime } from "./detached-task-runtime-contract.js";
import {
clearDetachedTaskLifecycleRuntimeRegistration,
registerDetachedTaskLifecycleRuntime,
} from "./detached-task-runtime-state.js";
export function setDetachedTaskLifecycleRuntime(runtime: DetachedTaskLifecycleRuntime): void {
registerDetachedTaskLifecycleRuntime("__test__", runtime);
}
export function resetDetachedTaskLifecycleRuntimeForTests(): void {
clearDetachedTaskLifecycleRuntimeRegistration();
}
+4 -2
View File
@@ -13,13 +13,15 @@ import {
finalizeTaskRunByRunId,
getDetachedTaskLifecycleRuntime,
recordTaskRunProgressByRunId,
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
setDetachedTaskDeliveryStatusByRunId,
startTaskRunByRunId,
tryRecoverTaskBeforeMarkLost,
} from "./detached-task-runtime.js";
import type { TaskRecord } from "./task-registry.types.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "./task-runtime.test-helpers.js";
const { mockFindTaskByRunIdForStatus, mockListTasksForSessionKeyForStatus, mockLogWarn } =
vi.hoisted(() => ({
+1 -13
View File
@@ -8,11 +8,7 @@ import type {
DetachedTaskFinalizeParams,
DetachedTaskLifecycleRuntime,
} from "./detached-task-runtime-contract.js";
import {
clearDetachedTaskLifecycleRuntimeRegistration,
getRegisteredDetachedTaskLifecycleRuntime,
registerDetachedTaskLifecycleRuntime,
} from "./detached-task-runtime-state.js";
import { getRegisteredDetachedTaskLifecycleRuntime } from "./detached-task-runtime-state.js";
import { cancelTaskById as cancelDetachedTaskRunByIdInCore } from "./runtime-internal.js";
import {
completeTaskRunByRunId as completeTaskRunByRunIdFromExecutor,
@@ -74,14 +70,6 @@ export function getDetachedTaskLifecycleRuntime(): DetachedTaskLifecycleRuntime
return getRegisteredDetachedTaskLifecycleRuntime() ?? DEFAULT_DETACHED_TASK_LIFECYCLE_RUNTIME;
}
export function setDetachedTaskLifecycleRuntime(runtime: DetachedTaskLifecycleRuntime): void {
registerDetachedTaskLifecycleRuntime("__test__", runtime);
}
export function resetDetachedTaskLifecycleRuntimeForTests(): void {
clearDetachedTaskLifecycleRuntimeRegistration();
}
export function createQueuedTaskRun(
...args: Parameters<DetachedTaskLifecycleRuntime["createQueuedTaskRun"]>
): ReturnType<DetachedTaskLifecycleRuntime["createQueuedTaskRun"]> {
@@ -0,0 +1,19 @@
import "./generated-media-task-activity.js";
type GeneratedMediaTaskActivityTestApi = {
resetGeneratedMediaTaskActivityForTests(): void;
};
function getTestApi(): GeneratedMediaTaskActivityTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.generatedMediaTaskActivityTestApi")
];
if (!api) {
throw new Error("generated media task activity test API is unavailable");
}
return api as GeneratedMediaTaskActivityTestApi;
}
export function resetGeneratedMediaTaskActivityForTests(): void {
getTestApi().resetGeneratedMediaTaskActivityForTests();
}
+7 -1
View File
@@ -54,7 +54,13 @@ export function getLatestGeneratedMediaTaskAdmissionIdForSessionKey(
return getLatestGeneratedMediaTaskAdmissions().get(sessionKey);
}
export function resetGeneratedMediaTaskActivityForTests(): void {
function resetGeneratedMediaTaskActivityForTests(): void {
getActiveGeneratedMediaTasks().clear();
getLatestGeneratedMediaTaskAdmissions().clear();
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.generatedMediaTaskActivityTestApi")
] = { resetGeneratedMediaTaskActivityForTests };
}
+10 -10
View File
@@ -5,11 +5,7 @@ import { resetSystemEventsForTest } from "../infra/system-events.js";
import { withStateDirEnv } from "../test-helpers/state-dir-env.js";
import { captureEnv } from "../test-utils/env.js";
import { SUBAGENT_KILL_TASK_ERROR } from "./detached-task-runtime-contract.js";
import {
getDetachedTaskLifecycleRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "./detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "./detached-task-runtime.js";
import {
cancelFlowById,
cancelFlowByIdForOwner,
@@ -27,22 +23,26 @@ import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
getTaskFlowById,
listTaskFlowRecords,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import {
setTaskRegistryDeliveryRuntimeForTests,
getTaskById,
findTaskByRunId,
listTasksForFlowId,
markTaskTerminalById,
} from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
resetDetachedTaskLifecycleRuntimeForTests,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
resetTaskFlowRegistryForTests,
setDetachedTaskLifecycleRuntime,
setTaskRegistryControlRuntimeForTests,
} from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
setTaskRegistryDeliveryRuntimeForTests,
} from "./task-runtime.test-helpers.js";
const ORIGINAL_ENV = captureEnv(["OPENCLAW_STATE_DIR"]);
+5 -5
View File
@@ -6,12 +6,12 @@ import {
listTaskFlowsForOwner,
resolveTaskFlowForLookupTokenForOwner,
} from "./task-flow-owner-access.js";
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "./task-flow-registry.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
resetTaskFlowRegistryForTests,
} from "./task-runtime.test-helpers.js";
function createManagedTaskFlow(
params: Parameters<typeof createManagedTaskFlowOrNull>[0],
+4 -4
View File
@@ -15,16 +15,16 @@ import {
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
requestFlowCancel,
resetTaskFlowRegistryForTests,
setFlowWaiting,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import type { TaskRecord } from "./task-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
resetTaskFlowRegistryForTests,
} from "./task-runtime.test-helpers.js";
const ORIGINAL_ENV = captureEnv(["OPENCLAW_STATE_DIR"]);
@@ -5,12 +5,10 @@ import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import { SUBAGENT_KILL_TASK_ERROR } from "./detached-task-runtime-contract.js";
import { createRunningTaskRun as createRunningTaskRunOrNull } from "./task-executor.js";
import {
createFlowRecord as createFlowRecordOrNull,
createManagedTaskFlow as createManagedTaskFlowOrNull,
getTaskFlowById,
listTaskFlowRecords,
requestFlowCancel,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.js";
import {
getInspectableTaskFlowAuditSummary,
@@ -18,12 +16,14 @@ import {
runTaskFlowRegistryMaintenance,
} from "./task-flow-registry.maintenance.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import { finalizeTaskRunByRunId } from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
import {
finalizeTaskRunByRunId,
createFlowRecord as createFlowRecordOrNull,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
} from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
resetTaskFlowRegistryForTests,
} from "./task-runtime.test-helpers.js";
const ORIGINAL_ENV = captureEnv(["OPENCLAW_STATE_DIR"]);
@@ -0,0 +1,35 @@
import type { TaskFlowRegistryObserverEvent } from "./task-flow-registry.store.js";
import type { TaskFlowRegistryStoreSnapshot } from "./task-flow-registry.store.types.js";
import "./task-flow-registry.store.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
type TaskFlowRegistryStore = {
loadSnapshot: () => TaskFlowRegistryStoreSnapshot;
saveSnapshot: (snapshot: TaskFlowRegistryStoreSnapshot) => void;
upsertFlow?: (flow: TaskFlowRecord) => void;
deleteFlow?: (flowId: string) => void;
close?: () => void;
};
type TaskFlowRegistryStoreTestApi = {
configureTaskFlowRegistryRuntime(params: {
store?: TaskFlowRegistryStore;
observers?: { onEvent?: (event: TaskFlowRegistryObserverEvent) => void } | null;
}): void;
};
function getTestApi(): TaskFlowRegistryStoreTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.taskFlowRegistryStoreTestApi")
];
if (!api) {
throw new Error("task flow registry store test API is unavailable");
}
return api as TaskFlowRegistryStoreTestApi;
}
export function configureTaskFlowRegistryRuntime(
params: Parameters<TaskFlowRegistryStoreTestApi["configureTaskFlowRegistryRuntime"]>[0],
): void {
getTestApi().configureTaskFlowRegistryRuntime(params);
}
+4 -2
View File
@@ -11,10 +11,8 @@ import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
getTaskFlowById,
requestFlowCancel,
resetTaskFlowRegistryForTests,
setFlowWaiting,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import {
loadTaskFlowRegistryStateFromSqlite,
saveTaskFlowRegistryStateToSqlite,
@@ -25,6 +23,10 @@ import {
type TaskFlowRecord,
} from "./task-flow-registry.types.js";
import { parseTaskNotifyPolicy } from "./task-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
resetTaskFlowRegistryForTests,
} from "./task-runtime.test-helpers.js";
function createManagedTaskFlow(
params: Parameters<typeof createManagedTaskFlowOrNull>[0],
+7 -1
View File
@@ -57,7 +57,7 @@ export function getTaskFlowRegistryObservers(): TaskFlowRegistryObservers | null
return configuredFlowRegistryObservers;
}
export function configureTaskFlowRegistryRuntime(params: {
function configureTaskFlowRegistryRuntime(params: {
store?: TaskFlowRegistryStore;
observers?: TaskFlowRegistryObservers | null;
}) {
@@ -74,3 +74,9 @@ export function resetTaskFlowRegistryRuntimeForTests() {
configuredFlowRegistryStore = defaultFlowRegistryStore;
configuredFlowRegistryObservers = null;
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.taskFlowRegistryStoreTestApi")
] = { configureTaskFlowRegistryRuntime };
}
@@ -0,0 +1,51 @@
import type {
JsonValue,
TaskFlowRecord,
TaskFlowStatus,
TaskFlowSyncMode,
} from "./task-flow-registry.types.js";
import "./task-flow-registry.js";
import type { TaskNotifyPolicy } from "./task-registry.types.js";
type CreateFlowRecordParams = {
ownerKey: string;
requesterOrigin?: TaskFlowRecord["requesterOrigin"];
status?: TaskFlowStatus;
notifyPolicy?: TaskNotifyPolicy;
goal: string;
currentStep?: string | null;
blockedTaskId?: string | null;
blockedSummary?: string | null;
stateJson?: JsonValue | null;
waitJson?: JsonValue | null;
cancelRequestedAt?: number | null;
createdAt?: number;
updatedAt?: number;
endedAt?: number | null;
syncMode?: TaskFlowSyncMode;
controllerId?: string | null;
revision?: number;
};
type TaskFlowRegistryTestApi = {
createFlowRecord(params: CreateFlowRecordParams): TaskFlowRecord | null;
resetTaskFlowRegistryForTests(opts?: { persist?: boolean }): void;
};
function getTestApi(): TaskFlowRegistryTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.taskFlowRegistryTestApi")
];
if (!api) {
throw new Error("task flow registry test API is unavailable");
}
return api as TaskFlowRegistryTestApi;
}
export function createFlowRecord(params: CreateFlowRecordParams): TaskFlowRecord | null {
return getTestApi().createFlowRecord(params);
}
export function resetTaskFlowRegistryForTests(opts?: { persist?: boolean }): void {
getTestApi().resetTaskFlowRegistryForTests(opts);
}
+5 -3
View File
@@ -2,7 +2,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import {
createFlowRecord as createFlowRecordOrNull,
createTaskFlowForTask as createTaskFlowForTaskOrNull,
createManagedTaskFlow as createManagedTaskFlowOrNull,
deleteTaskFlowRecordById,
@@ -12,14 +11,17 @@ import {
listTaskFlowRecords,
requestFlowCancel,
reloadTaskFlowRegistryFromStore,
resetTaskFlowRegistryForTests,
resumeFlow,
setFlowWaiting,
syncFlowFromTaskResult,
updateFlowRecordByIdExpectedRevision,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
createFlowRecord as createFlowRecordOrNull,
resetTaskFlowRegistryForTests,
} from "./task-runtime.test-helpers.js";
function createFlowRecord(params: Parameters<typeof createFlowRecordOrNull>[0]): TaskFlowRecord {
const flow = createFlowRecordOrNull(params);
+9 -2
View File
@@ -468,7 +468,7 @@ function writeFlowRecord(next: TaskFlowRecord, previous?: TaskFlowRecord): TaskF
return cloneFlowRecord(next);
}
export function createFlowRecord(params: CreateFlowRecordParams): TaskFlowRecord | null {
function createFlowRecord(params: CreateFlowRecordParams): TaskFlowRecord | null {
ensureTaskFlowRegistryReady();
const record = buildFlowRecord(params);
return writeFlowRecord(record);
@@ -812,7 +812,7 @@ export function deleteTaskFlowRecordById(flowId: string): boolean {
return true;
}
export function resetTaskFlowRegistryForTests(opts?: { persist?: boolean }) {
function resetTaskFlowRegistryForTests(opts?: { persist?: boolean }) {
flows = new Map();
taskFlowRegistryRestoreState = { status: "uninitialized" };
resetTaskFlowRegistryRuntimeForTests();
@@ -821,4 +821,11 @@ export function resetTaskFlowRegistryForTests(opts?: { persist?: boolean }) {
}
getTaskFlowRegistryStore().close?.();
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.taskFlowRegistryTestApi")] = {
createFlowRecord,
resetTaskFlowRegistryForTests,
};
}
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
+2 -4
View File
@@ -8,11 +8,9 @@ import {
getTaskByIdForOwner,
resolveTaskForLookupTokenForOwner,
} from "./task-owner-access.js";
import {
createTaskRecord as createTaskRecordOrNull,
resetTaskRegistryForTests,
} from "./task-registry.js";
import { createTaskRecord as createTaskRecordOrNull } from "./task-registry.js";
import type { TaskRecord } from "./task-registry.types.js";
import { resetTaskRegistryForTests } from "./task-runtime.test-helpers.js";
const ORIGINAL_ENV = captureEnv(["OPENCLAW_STATE_DIR"]);
@@ -3,11 +3,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import type { AcpSessionStoreEntry } from "../acp/runtime/session-meta.js";
import type { SessionEntry } from "../config/sessions.js";
import type { ParsedAgentSessionKey } from "../routing/session-key.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
getDetachedTaskLifecycleRuntime,
} from "./detached-task-runtime.js";
import { getDetachedTaskLifecycleRuntime } from "./detached-task-runtime.js";
import {
CRON_HISTORY_KEEP_PER_JOB,
getInspectableActiveTaskRestartBlockers,
@@ -20,6 +16,10 @@ import {
stopTaskRegistryMaintenance,
} from "./task-registry.maintenance.js";
import type { TaskRecord } from "./task-registry.types.js";
import {
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "./task-runtime.test-helpers.js";
const GRACE_EXPIRED_MS = 10 * 60_000;
+6 -6
View File
@@ -22,10 +22,7 @@ import {
import { resolveOpenClawStateSqlitePath } from "../state/openclaw-state-db.paths.js";
import { captureEnv } from "../test-utils/env.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "./task-flow-registry.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import {
createTaskRecord as createTaskRecordOrNull,
@@ -34,9 +31,7 @@ import {
getTaskById,
listFreshTasksForOwnerKey,
markTaskTerminalById,
maybeDeliverTaskStateChangeUpdate,
reloadTaskRegistryFromStore,
resetTaskRegistryForTests,
updateTaskNotifyPolicyById,
} from "./task-registry.js";
import {
@@ -56,6 +51,11 @@ import {
parseTaskScopeKind,
parseTaskStatus,
} from "./task-registry.types.js";
import {
maybeDeliverTaskStateChangeUpdate,
resetTaskFlowRegistryForTests,
resetTaskRegistryForTests,
} from "./task-runtime.test-helpers.js";
const ORIGINAL_ENV = captureEnv(["OPENCLAW_STATE_DIR"]);
+57
View File
@@ -0,0 +1,57 @@
import type { TaskRegistryControlRuntime } from "./task-registry-control.types.js";
import type { TaskEventRecord, TaskRecord } from "./task-registry.types.js";
import "./task-registry.js";
type TaskRegistryDeliveryRuntime = Pick<
typeof import("./task-registry-delivery-runtime.js"),
"sendMessage"
>;
type TaskRegistryTestApi = {
maybeDeliverTaskStateChangeUpdate(
taskId: string,
latestEvent?: TaskEventRecord,
): Promise<TaskRecord | null>;
resetTaskRegistryForTests(opts?: { persist?: boolean }): void;
resetTaskRegistryDeliveryRuntimeForTests(): void;
setTaskRegistryDeliveryRuntimeForTests(runtime: TaskRegistryDeliveryRuntime): void;
resetTaskRegistryControlRuntimeForTests(): void;
setTaskRegistryControlRuntimeForTests(runtime: TaskRegistryControlRuntime): void;
};
function getTestApi(): TaskRegistryTestApi {
const api = (globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.taskRegistryTestApi")
];
if (!api) {
throw new Error("task registry test API is unavailable");
}
return api as TaskRegistryTestApi;
}
export async function maybeDeliverTaskStateChangeUpdate(
taskId: string,
latestEvent?: TaskEventRecord,
): Promise<TaskRecord | null> {
return await getTestApi().maybeDeliverTaskStateChangeUpdate(taskId, latestEvent);
}
export function resetTaskRegistryForTests(opts?: { persist?: boolean }): void {
getTestApi().resetTaskRegistryForTests(opts);
}
export function resetTaskRegistryDeliveryRuntimeForTests(): void {
getTestApi().resetTaskRegistryDeliveryRuntimeForTests();
}
export function setTaskRegistryDeliveryRuntimeForTests(runtime: TaskRegistryDeliveryRuntime): void {
getTestApi().setTaskRegistryDeliveryRuntimeForTests(runtime);
}
export function resetTaskRegistryControlRuntimeForTests(): void {
getTestApi().resetTaskRegistryControlRuntimeForTests();
}
export function setTaskRegistryControlRuntimeForTests(runtime: TaskRegistryControlRuntime): void {
getTestApi().setTaskRegistryControlRuntimeForTests(runtime);
}
+10 -8
View File
@@ -32,9 +32,7 @@ import {
createManagedTaskFlow as createManagedTaskFlowOrNull,
getTaskFlowById,
requestFlowCancel,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.js";
import type { TaskFlowRecord } from "./task-flow-registry.types.js";
import {
cancelTaskById,
@@ -49,18 +47,12 @@ import {
listTasksForRelatedSessionKey,
listTaskRecords,
linkTaskToFlowById,
maybeDeliverTaskStateChangeUpdate,
maybeDeliverTaskTerminalUpdate,
markTaskRunningByRunId,
markTaskTerminalById,
recordTaskProgressByRunId,
reloadTaskRegistryFromStore,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
resolveTaskForLookupToken,
setTaskRegistryControlRuntimeForTests,
setTaskRegistryDeliveryRuntimeForTests,
updateTaskNotifyPolicyById,
} from "./task-registry.js";
import {
@@ -80,6 +72,16 @@ import {
import { configureTaskRegistryRuntime } from "./task-registry.store.js";
import { summarizeTaskRecords } from "./task-registry.summary.js";
import type { TaskDeliveryState, TaskRecord } from "./task-registry.types.js";
import {
configureTaskFlowRegistryRuntime,
maybeDeliverTaskStateChangeUpdate,
resetTaskFlowRegistryForTests,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
setTaskRegistryControlRuntimeForTests,
setTaskRegistryDeliveryRuntimeForTests,
} from "./task-runtime.test-helpers.js";
const DEFAULT_TASK_RETENTION_MS = 7 * 24 * 60 * 60_000;
const LOST_TASK_RETENTION_MS = 24 * 60 * 60_000;
+17 -6
View File
@@ -1607,7 +1607,7 @@ async function maybeDeliverTaskTerminalUpdateUnderAdmission(
}
}
export async function maybeDeliverTaskStateChangeUpdate(
async function maybeDeliverTaskStateChangeUpdate(
taskId: string,
latestEvent?: TaskEventRecord,
): Promise<TaskRecord | null> {
@@ -2735,7 +2735,7 @@ export function deleteTaskRecordById(taskId: string): boolean {
return true;
}
export function resetTaskRegistryForTests(opts?: { persist?: boolean }) {
function resetTaskRegistryForTests(opts?: { persist?: boolean }) {
clearTaskRegistryMemory();
taskRegistryRestoreState = { status: "uninitialized" };
resetTaskRegistryRuntimeForTests();
@@ -2754,31 +2754,42 @@ export function resetTaskRegistryForTests(opts?: { persist?: boolean }) {
getTaskRegistryStore().close?.();
}
export function resetTaskRegistryDeliveryRuntimeForTests() {
function resetTaskRegistryDeliveryRuntimeForTests() {
(globalThis as TaskRegistryGlobalWithRuntimeOverrides)[
TASK_REGISTRY_DELIVERY_RUNTIME_OVERRIDE_KEY
] = null;
deliveryRuntimeLoader.clear();
}
export function setTaskRegistryDeliveryRuntimeForTests(runtime: TaskRegistryDeliveryRuntime): void {
function setTaskRegistryDeliveryRuntimeForTests(runtime: TaskRegistryDeliveryRuntime): void {
(globalThis as TaskRegistryGlobalWithRuntimeOverrides)[
TASK_REGISTRY_DELIVERY_RUNTIME_OVERRIDE_KEY
] = runtime;
deliveryRuntimeLoader.clear();
}
export function resetTaskRegistryControlRuntimeForTests() {
function resetTaskRegistryControlRuntimeForTests() {
(globalThis as TaskRegistryGlobalWithRuntimeOverrides)[
TASK_REGISTRY_CONTROL_RUNTIME_OVERRIDE_KEY
] = null;
controlRuntimeLoader.clear();
}
export function setTaskRegistryControlRuntimeForTests(runtime: TaskRegistryControlRuntime): void {
function setTaskRegistryControlRuntimeForTests(runtime: TaskRegistryControlRuntime): void {
(globalThis as TaskRegistryGlobalWithRuntimeOverrides)[
TASK_REGISTRY_CONTROL_RUNTIME_OVERRIDE_KEY
] = runtime;
controlRuntimeLoader.clear();
}
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("openclaw.taskRegistryTestApi")] = {
maybeDeliverTaskStateChangeUpdate,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
setTaskRegistryControlRuntimeForTests,
setTaskRegistryDeliveryRuntimeForTests,
};
}
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
+12 -2
View File
@@ -1,9 +1,19 @@
// Test-only access to task registry reset and runtime-injection hooks.
export { resetTaskFlowRegistryForTests } from "./task-flow-registry.js";
export {
resetDetachedTaskLifecycleRuntimeForTests,
setDetachedTaskLifecycleRuntime,
} from "./detached-task-runtime.test-support.js";
export { resetGeneratedMediaTaskActivityForTests } from "./generated-media-task-activity.test-support.js";
export { configureTaskFlowRegistryRuntime } from "./task-flow-registry.store.test-support.js";
export {
createFlowRecord,
resetTaskFlowRegistryForTests,
} from "./task-flow-registry.test-support.js";
export {
maybeDeliverTaskStateChangeUpdate,
resetTaskRegistryControlRuntimeForTests,
resetTaskRegistryDeliveryRuntimeForTests,
resetTaskRegistryForTests,
setTaskRegistryControlRuntimeForTests,
setTaskRegistryDeliveryRuntimeForTests,
} from "./task-registry.js";
} from "./task-registry.test-support.js";
+1 -1
View File
@@ -2,8 +2,8 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import {
clearGeneratedMediaTaskActivity,
registerGeneratedMediaTaskActivity,
resetGeneratedMediaTaskActivityForTests,
} from "./generated-media-task-activity.js";
import { resetGeneratedMediaTaskActivityForTests } from "./task-runtime.test-helpers.js";
import {
getGeneratedMediaTaskIdsForSessionKey,
hasNewGeneratedMediaTaskForSessionKey,
+6 -3
View File
@@ -1,7 +1,10 @@
// ACP manager task state helper resets task flow state for ACP tests.
import { resetTaskFlowRegistryForTests } from "../../src/tasks/task-flow-registry.js";
import { configureTaskFlowRegistryRuntime } from "../../src/tasks/task-flow-registry.store.js";
import { findTaskByRunId, resetTaskRegistryForTests } from "../../src/tasks/task-registry.js";
import { findTaskByRunId } from "../../src/tasks/task-registry.js";
import {
configureTaskFlowRegistryRuntime,
resetTaskFlowRegistryForTests,
resetTaskRegistryForTests,
} from "../../src/tasks/task-runtime.test-helpers.js";
import { withTempDir } from "../../src/test-helpers/temp-dir.js";
import { captureEnv, setTestEnvValue } from "../../src/test-utils/env.js";
import { installInMemoryTaskRegistryRuntime } from "../../src/test-utils/task-registry-runtime.js";
+1
View File
@@ -11,6 +11,7 @@ describe("Docker E2E client scripts", () => {
const source = readScript("scripts/e2e/commitments-safety-docker-client.ts");
expect(source).toContain("../../dist/commitments/runtime.js");
expect(source).toContain("../../dist/commitments/runtime.test-support.js");
expect(source).toContain("../../dist/commitments/store.js");
expect(source).toContain("verifyQueueCap()");
expect(source).toContain("verifyExtractionStoresTypedMetadataOnly()");
+1
View File
@@ -323,6 +323,7 @@ function buildDockerE2eHarnessEntries(): Record<string, string> {
"auto-reply/reply/commands-system-agent": "src/auto-reply/reply/commands-system-agent.ts",
"cli/run-main": "src/cli/run-main.ts",
"commitments/runtime": "src/commitments/runtime.ts",
"commitments/runtime.test-support": "src/commitments/runtime.test-support.ts",
"commitments/store": "src/commitments/store.ts",
"config/config": "src/config/config.ts",
"system-agent/system-agent": "src/system-agent/system-agent.ts",