refactor(plugin-sdk): remove private testing barrel ahead of window (#108020)

This commit is contained in:
Peter Steinberger
2026-07-14 22:13:37 -07:00
committed by GitHub
parent 290836cafd
commit e9fc23ad1f
36 changed files with 97 additions and 356 deletions
+10 -1
View File
@@ -546,7 +546,6 @@ SDK.
| `plugin-sdk/memory-host-markdown` | Managed markdown helpers | Shared managed-markdown helpers for memory-adjacent plugins |
| `plugin-sdk/memory-host-search` | Active memory search facade | Lazy active-memory search-manager runtime facade |
| `plugin-sdk/memory-host-status` | Deprecated memory host status alias | Use `plugin-sdk/memory-core-host-status` |
| `plugin-sdk/testing` | Test utilities | Repo-local deprecated compatibility barrel; use focused repo-local test subpaths such as `plugin-sdk/plugin-test-runtime`, `plugin-sdk/channel-test-helpers`, `plugin-sdk/channel-target-testing`, `plugin-sdk/test-env`, and `plugin-sdk/test-fixtures` |
</Accordion>
This table is the common migration subset, not the full SDK surface. The
@@ -565,6 +564,16 @@ Use the narrowest import that matches the job. If you cannot find an export,
check the source at `src/plugin-sdk/` or ask maintainers which generic
contract should own it.
## Removed compatibility surfaces
### Private testing barrel
`openclaw/plugin-sdk/testing` was repo-local and excluded from shipped package
artifacts, so it was removed before its 2026-07-28 `removeAfter` date. Repository
tests use focused subpaths such as `plugin-sdk/plugin-test-runtime`,
`plugin-sdk/channel-test-helpers`, `plugin-sdk/channel-target-testing`,
`plugin-sdk/test-env`, and `plugin-sdk/test-fixtures`.
## Active deprecations
Narrower deprecations across the plugin SDK, provider contract, runtime
-1
View File
@@ -369,7 +369,6 @@ usage endpoint failed or returned no usable usage data.
| `plugin-sdk/webhook-path` | Deprecated compatibility alias; use `plugin-sdk/webhook-ingress` |
| `plugin-sdk/web-media` | Shared remote/local media loading helpers |
| `plugin-sdk/zod` | Deprecated compatibility re-export; import `zod` from `zod` directly |
| `plugin-sdk/testing` | Repo-local deprecated compatibility barrel for legacy OpenClaw tests. New repo tests should import focused local test subpaths such as `plugin-sdk/agent-runtime-test-contracts`, `plugin-sdk/plugin-test-runtime`, `plugin-sdk/channel-test-helpers`, `plugin-sdk/test-env`, or `plugin-sdk/test-fixtures` instead |
| `plugin-sdk/plugin-test-api` | Repo-local minimal `createTestPluginApi` helper for direct plugin registration unit tests without importing repo test helper bridges |
| `plugin-sdk/agent-runtime-test-contracts` | Repo-local native agent-runtime adapter contract fixtures for auth, delivery, fallback, tool-hook, prompt-overlay, schema, and transcript projection tests |
| `plugin-sdk/channel-test-helpers` | Repo-local channel-oriented test helpers for generic actions/setup/status contracts, directory assertions, account startup lifecycle, send-config threading, runtime mocks, status issues, outbound delivery, and hook registration |
+11 -11
View File
@@ -46,12 +46,12 @@ import {
import { mockNodeBuiltinModule } from "openclaw/plugin-sdk/test-node-mocks";
```
Prefer these focused subpaths for new bundled plugin tests. The broad
`openclaw/plugin-sdk/testing` barrel and `openclaw/plugin-sdk/test-utils` alias
are legacy compatibility only: `pnpm run lint:plugins:no-extension-test-core-imports`
(`scripts/check-no-extension-test-core-imports.ts`) rejects new imports of
either from extension test files, and both remain solely for
compatibility-record tests.
Use these focused subpaths for bundled plugin tests. The former
`openclaw/plugin-sdk/testing` barrel was repo-local, excluded from shipped
packages, and has been removed. The legacy `openclaw/plugin-sdk/test-utils`
alias remains repo-local; `pnpm run lint:plugins:no-extension-test-core-imports`
(`scripts/check-no-extension-test-core-imports.ts`) rejects new extension-test
imports of that alias.
### Available exports
@@ -335,11 +335,11 @@ pnpm test src/plugins/contracts/runtime-seams.contract.test.ts
`scripts/run-additional-boundary-checks.mjs` runs a set of `lint:plugins:*`
import-boundary checks in CI; each can also be run standalone locally:
| Command | Enforces |
| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `pnpm run lint:plugins:no-monolithic-plugin-sdk-entry-imports` | Bundled plugins cannot import the monolithic `openclaw/plugin-sdk` root barrel. |
| `pnpm run lint:plugins:no-extension-src-imports` | Production extension files cannot import the repo `src/**` tree directly (`../../src/...`). |
| `pnpm run lint:plugins:no-extension-test-core-imports` | Extension test files cannot import `openclaw/plugin-sdk/testing`, `plugin-sdk/test-utils`, or other core-only test helpers. |
| Command | Enforces |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `pnpm run lint:plugins:no-monolithic-plugin-sdk-entry-imports` | Bundled plugins cannot import the monolithic `openclaw/plugin-sdk` root barrel. |
| `pnpm run lint:plugins:no-extension-src-imports` | Production extension files cannot import the repo `src/**` tree directly (`../../src/...`). |
| `pnpm run lint:plugins:no-extension-test-core-imports` | Extension test files cannot import `plugin-sdk/test-utils` or other core-only test helpers. |
External plugins are not subject to these lint rules, but following the same
patterns is recommended.
@@ -56,9 +56,6 @@
"openclaw/plugin-sdk/test-node-mocks": [
"../packages/plugin-sdk/dist/src/plugin-sdk/test-node-mocks.d.ts"
],
"openclaw/plugin-sdk/testing": [
"../packages/plugin-sdk/dist/src/plugin-sdk/testing.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
-3
View File
@@ -57,9 +57,6 @@
"openclaw/plugin-sdk/test-node-mocks": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/test-node-mocks.d.ts"
],
"openclaw/plugin-sdk/testing": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/testing.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
-2
View File
@@ -70,8 +70,6 @@
"!dist/plugin-sdk/test-node-mocks.d.ts",
"!dist/plugin-sdk/test-utils.js",
"!dist/plugin-sdk/test-utils.d.ts",
"!dist/plugin-sdk/testing.js",
"!dist/plugin-sdk/testing.d.ts",
"!dist/plugin-sdk/src/agents/test-helpers/**",
"!dist/plugin-sdk/src/test-helpers/**",
"!dist/plugin-sdk/src/test-utils/**",
-4
View File
@@ -236,10 +236,6 @@
"types": "./dist/src/plugin-sdk/tts-runtime.d.ts",
"default": "./src/tts-runtime.ts"
},
"./testing": {
"types": "./dist/src/plugin-sdk/testing.d.ts",
"default": "./src/testing.ts"
},
"./text-runtime": {
"types": "./dist/src/plugin-sdk/text-runtime.d.ts",
"default": "./src/text-runtime.ts"
-2
View File
@@ -1,2 +0,0 @@
// Plugin SDK module implements testing behavior.
export * from "../../../src/plugin-sdk/testing.js";
-1
View File
@@ -217,7 +217,6 @@ const rules = [
"src/plugin-sdk/inbound-reply-dispatch.ts",
"src/plugin-sdk/outbound-runtime.ts",
"src/plugin-sdk/test-helpers/outbound-delivery.ts",
"src/plugin-sdk/testing.ts",
],
message: "use sendDurableMessageBatch or deliverInboundReplyWithMessageSendContext",
},
@@ -14,10 +14,6 @@ const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
pattern: /["']openclaw\/plugin-sdk\/test-utils["']/,
hint: "Use a focused plugin-sdk test subpath for the public extension test surface.",
},
{
pattern: /["']openclaw\/plugin-sdk\/testing["']/,
hint: "Use a focused plugin-sdk test subpath instead of the broad compatibility testing barrel.",
},
{
pattern: /["']openclaw\/plugin-sdk\/compat["']/,
hint: "Use a focused public plugin-sdk subpath instead of compat.",
@@ -59,7 +59,6 @@
"test-env",
"test-fixtures",
"test-node-mocks",
"testing",
"text-runtime",
"webhook-path",
"zalouser",
-1
View File
@@ -138,7 +138,6 @@
"test-env",
"test-fixtures",
"test-node-mocks",
"testing",
"temp-path",
"time-runtime",
"logging-core",
@@ -20,6 +20,5 @@
"test-env",
"test-fixtures",
"test-node-mocks",
"test-utils",
"testing"
"test-utils"
]
+2 -2
View File
@@ -16,10 +16,10 @@ import { parseModelRef } from "../agents/model-selection.js";
import { clearRuntimeConfigSnapshot, type OpenClawConfig } from "../config/config.js";
import { isTruthyEnvValue } from "../infra/env.js";
import {
createMockPluginRegistry,
initializeGlobalHookRunner,
resetGlobalHookRunner,
} from "../plugin-sdk/testing.js";
} from "../plugins/hook-runner-global.js";
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
import { setTestEnvValue } from "../test-utils/env.js";
import {
applyCliBackendLiveEnv,
-2
View File
@@ -62,8 +62,6 @@ const OMITTED_PLUGIN_SDK_TEST_FILES = new Set([
"dist/plugin-sdk/test-fixtures.js",
"dist/plugin-sdk/test-node-mocks.d.ts",
"dist/plugin-sdk/test-node-mocks.js",
"dist/plugin-sdk/testing.d.ts",
"dist/plugin-sdk/testing.js",
]);
const OMITTED_PLUGIN_SDK_TEST_PREFIXES = [
"dist/plugin-sdk/src/agents/test-helpers/",
@@ -1,17 +1,16 @@
/**
* Core plugin SDK contract-test fixture builders and registration helpers.
*/
import type { OpenClawConfig } from "../../config/config.js";
import type { PluginRegistryParams } from "../../plugins/registry-types.js";
import type { OpenClawPluginApi } from "../plugin-entry.js";
import { createPluginRegistry, type PluginRecord } from "../../plugins/registry.js";
import type { PluginRuntime } from "../../plugins/runtime/types.js";
import { createPluginRecord } from "../../plugins/status.test-helpers.js";
import {
createPluginRecord,
createPluginRegistry,
registerProviderPlugins as registerProviders,
requireRegisteredProvider as requireProvider,
type OpenClawConfig,
type PluginRecord,
type PluginRuntime,
} from "../testing.js";
} from "../../test-utils/plugin-registration.js";
import type { OpenClawPluginApi } from "../plugin-entry.js";
export { assertNoImportTimeSideEffects } from "./import-side-effects.js";
import { uniqueSortedStrings } from "./string-utils.js";
@@ -1,6 +1,6 @@
// Onboard config test helpers build model/provider config fixtures for plugin tests.
import type { OpenClawConfig } from "../../config/config.js";
import type { ModelApi } from "../provider-model-shared.js";
import type { OpenClawConfig } from "../testing.js";
export const EXPECTED_FALLBACKS = ["anthropic/claude-opus-4-5"] as const;
@@ -1,14 +1,15 @@
// Outbound delivery test helpers re-export channel delivery fixtures for plugin tests.
export {
addTestHook,
createEmptyPluginRegistry,
createOutboundTestPlugin,
createTestRegistry,
initializeGlobalHookRunner,
releasePinnedPluginChannelRegistry,
resetGlobalHookRunner,
} from "../../plugins/hook-runner-global.js";
export { addTestHook } from "../../plugins/hooks.test-helpers.js";
export type { PluginHookRegistration } from "../../plugins/hook-types.js";
export { createEmptyPluginRegistry } from "../../plugins/registry.js";
export {
releasePinnedPluginChannelRegistry,
setActivePluginRegistry,
type PluginHookRegistration,
} from "../testing.js";
} from "../../plugins/runtime.js";
export { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js";
/** @deprecated Direct outbound delivery is runtime substrate; use channel message runtime helpers. */
export { deliverOutboundPayloads } from "../testing.js";
export { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
@@ -4,7 +4,8 @@
import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { isAtLeast, parseMinHostVersionRequirement, parseSemver } from "../testing.js";
import { isAtLeast, parseSemver } from "../../infra/runtime-guard.js";
import { parseMinHostVersionRequirement } from "../../plugins/min-host-version.js";
type PackageManifest = {
dependencies?: Record<string, string>;
@@ -2,7 +2,8 @@
* Contract suite for bundled plugin registration ownership and manifest auth metadata.
*/
import { describe, expect, it } from "vitest";
import { loadPluginManifestRegistry, pluginRegistrationContractRegistry } from "../testing.js";
import { pluginRegistrationContractRegistry } from "../../plugins/contracts/registry.js";
import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js";
type PluginRegistrationContractParams = {
pluginId: string;
@@ -4,19 +4,19 @@ import {
normalizeInboundTextNewlines,
sanitizeInboundSystemTags,
} from "../../auto-reply/reply/inbound-text.js";
import { resolveSessionEntryResetFreshness } from "../../config/sessions/entry-freshness.js";
import { createChannelRuntimeContextRegistry } from "../../plugins/runtime/channel-runtime-contexts.js";
import {
implicitMentionKindWhen,
resolveInboundMentionDecision,
} from "../channel-mention-gating.js";
import {
createAckReactionHandle,
removeAckReactionAfterReply,
removeAckReactionHandleAfterReply,
shouldAckReaction,
} from "../testing.js";
import type { PluginRuntime } from "../testing.js";
} from "../../channels/ack-reactions.js";
import { resolveSessionEntryResetFreshness } from "../../config/sessions/entry-freshness.js";
import { createChannelRuntimeContextRegistry } from "../../plugins/runtime/channel-runtime-contexts.js";
import type { PluginRuntime } from "../../plugins/runtime/types.js";
import {
implicitMentionKindWhen,
resolveInboundMentionDecision,
} from "../channel-mention-gating.js";
const DEFAULT_PROVIDER = "openai";
const DEFAULT_MODEL = "gpt-5.6-sol";
@@ -6,7 +6,7 @@ export {
expectedAugmentedOpenaiCodexCatalogEntriesWithGpt55,
expectedOpenaiPluginCodexCatalogEntriesWithGpt55,
expectCodexMissingAuthHint,
} from "../testing.js";
} from "../../plugins/provider-runtime.test-support.js";
export type { ProviderPlugin } from "../provider-model-shared.js";
export {
loadBundledPluginPublicSurface,
@@ -1,9 +1,9 @@
// Provider contract suites provide shared assertions for provider plugin behavior.
import { expect, it } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { ProviderPlugin } from "../provider-model-shared.js";
import type { WebFetchProviderPlugin } from "../provider-web-fetch-contract.js";
import type { WebSearchProviderPlugin } from "../provider-web-search-contract.js";
import type { OpenClawConfig } from "../testing.js";
type Lazy<T> = T | (() => T);
@@ -1,11 +1,11 @@
// Provider discovery contract helpers define reusable discovery tests for provider plugins.
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { AuthProfileStore, OpenClawConfig } from "../provider-auth.js";
import { runProviderCatalog } from "../../plugins/provider-discovery.js";
import {
registerProviderPlugins as registerProviders,
requireRegisteredProvider as requireProvider,
runProviderCatalog,
} from "../testing.js";
} from "../../test-utils/plugin-registration.js";
import type { AuthProfileStore, OpenClawConfig } from "../provider-auth.js";
const resolveCopilotApiTokenMock = vi.hoisted(() => vi.fn());
const buildVllmProviderMock = vi.hoisted(() => vi.fn());
@@ -2,12 +2,12 @@
* Shared assertions for provider onboarding config migration and fallback behavior.
*/
import { expect } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import {
resolveAgentModelFallbackValues,
resolveAgentModelPrimaryValue,
} from "../provider-onboard.js";
import type { ModelApi } from "../provider-onboard.js";
import type { OpenClawConfig } from "../testing.js";
import {
createConfigWithFallbacks,
createLegacyProviderConfig,
@@ -2,15 +2,15 @@
* Contract suites for provider setup wizard choices, options, and model pickers.
*/
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ProviderAuthMethod } from "../plugin-entry.js";
import type { ProviderPlugin } from "../provider-model-shared.js";
import { resolveProviderPluginChoice } from "../../plugins/provider-auth-choice.runtime.js";
import {
buildProviderPluginMethodChoice,
resolveProviderModelPickerEntries,
resolveProviderPluginChoice,
resolveProviderWizardOptions,
setProviderWizardProvidersResolverForTest,
} from "../testing.js";
} from "../../plugins/provider-wizard.js";
import type { ProviderAuthMethod } from "../plugin-entry.js";
import type { ProviderPlugin } from "../provider-model-shared.js";
const resolvePluginProvidersMock = vi.fn();
let restoreProviderResolver: (() => void) | undefined;
@@ -2,13 +2,11 @@
* Test helper for constructing a channel account startup context.
*/
import { vi } from "vitest";
import { createRuntimeEnv } from "../testing.js";
import type {
ChannelAccountSnapshot,
ChannelGatewayContext,
OpenClawConfig,
RuntimeEnv,
} from "../testing.js";
import type { ChannelGatewayContext } from "../../channels/plugins/types.adapters.js";
import type { ChannelAccountSnapshot } from "../../channels/plugins/types.public.js";
import type { OpenClawConfig } from "../../config/config.js";
import type { RuntimeEnv } from "../../runtime.js";
import { createRuntimeEnv } from "../../test-utils/plugin-runtime-env.js";
/** Creates a minimal ChannelGatewayContext with mutable status for startAccount tests. */
export function createStartAccountContext<TAccount extends { accountId: string }>(params: {
@@ -2,7 +2,8 @@
* Shared assertions for channel account startup lifecycle behavior.
*/
import { expect, vi } from "vitest";
import type { ChannelAccountSnapshot, ChannelGatewayContext } from "../testing.js";
import type { ChannelGatewayContext } from "../../channels/plugins/types.adapters.js";
import type { ChannelAccountSnapshot } from "../../channels/plugins/types.public.js";
import { createStartAccountContext } from "./start-account-context.js";
export function startAccountAndTrackLifecycle<TAccount extends { accountId: string }>(params: {
+2 -7
View File
@@ -1,7 +1,2 @@
/**
* @deprecated Compatibility alias for the legacy `plugin-sdk/testing` barrel.
*
* Prefer focused `openclaw/plugin-sdk/*` test subpaths for public test helpers.
*/
export * from "./testing.js";
/** @deprecated Prefer the focused `plugin-test-runtime` subpath. */
export * from "./plugin-test-runtime.js";
-214
View File
@@ -1,214 +0,0 @@
/**
* @deprecated Broad compatibility barrel for older plugin tests.
*
* New tests should import focused `openclaw/plugin-sdk/*` test subpaths such as
* `plugin-test-runtime`, `channel-test-helpers`, `test-env`, or `test-fixtures`.
*/
export {
createAckReactionHandle,
removeAckReactionAfterReply,
removeAckReactionHandleAfterReply,
shouldAckReaction,
} from "../channels/ack-reactions.js";
export {
expectChannelInboundContextContract,
expectChannelTurnDispatchResultContract,
primeChannelOutboundSendMock,
} from "../channels/plugins/contracts/test-helpers.js";
export {
installChannelOutboundPayloadContractSuite,
type OutboundPayloadHarnessParams,
} from "../channels/plugins/contracts/outbound-payload-testkit.js";
export { buildDispatchInboundCaptureMock } from "../channels/plugins/contracts/inbound-testkit.js";
export {
createCliRuntimeCapture,
firstWrittenJsonArg,
spyRuntimeErrors,
spyRuntimeJson,
spyRuntimeLogs,
} from "../cli/test-runtime-capture.js";
export type { CliMockOutputRuntime, CliRuntimeCapture } from "../cli/test-runtime-capture.js";
export { setDefaultChannelPluginRegistryForTests } from "../commands/channel-test-registry.js";
export type { ChannelAccountSnapshot } from "../channels/plugins/types.public.js";
export type { ChannelGatewayContext } from "../channels/plugins/types.adapters.js";
export type { OpenClawConfig } from "../config/config.js";
export { isAtLeast, parseSemver } from "../infra/runtime-guard.js";
export { callGateway } from "../gateway/call.js";
/** @deprecated Direct outbound delivery is runtime substrate; use channel message runtime helpers. */
export { deliverOutboundPayloads } from "../infra/outbound/deliver.js";
export {
createEmptyPluginRegistry,
createPluginRegistry,
type PluginRecord,
} from "../plugins/registry.js";
export {
providerContractLoadError,
pluginRegistrationContractRegistry,
resolveProviderContractProvidersForPluginIds,
resolveWebFetchProviderContractEntriesForPluginId,
resolveWebSearchProviderContractEntriesForPluginId,
} from "../plugins/contracts/registry.js";
export { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
export { parseMinHostVersionRequirement } from "../plugins/min-host-version.js";
export { resolveBundledExplicitProviderContractsFromPublicArtifacts } from "../plugins/provider-contract-public-artifacts.js";
export {
expectAugmentedCodexCatalog,
expectedAugmentedOpenaiCodexCatalogEntriesWithGpt55,
expectedOpenaiPluginCodexCatalogEntriesWithGpt55,
expectCodexMissingAuthHint,
} from "../plugins/provider-runtime.test-support.js";
export {
initializeGlobalHookRunner,
resetGlobalHookRunner,
} from "../plugins/hook-runner-global.js";
export { addTestHook } from "../plugins/hooks.test-helpers.js";
export {
assertUniqueValues,
BUNDLED_RUNTIME_SIDECAR_PATHS,
} from "../plugins/runtime-sidecar-paths.js";
export { createPluginRecord } from "../plugins/status.test-helpers.js";
export {
resolveBundledExplicitWebFetchProvidersFromPublicArtifacts,
resolveBundledExplicitWebSearchProvidersFromPublicArtifacts,
} from "../plugins/web-provider-public-artifacts.explicit.js";
export {
getActivePluginRegistry,
releasePinnedPluginChannelRegistry,
resetPluginRuntimeStateForTest,
setActivePluginRegistry,
} from "../plugins/runtime.js";
export {
listImportedBundledPluginFacadeIds,
resetFacadeRuntimeStateForTest,
} from "./facade-runtime.js";
export { capturePluginRegistration } from "../plugins/captured-registration.js";
export { runProviderCatalog } from "../plugins/provider-discovery.js";
export {
buildProviderPluginMethodChoice,
resolveProviderModelPickerEntries,
resolveProviderWizardOptions,
setProviderWizardProvidersResolverForTest,
} from "../plugins/provider-wizard.js";
export { resolveProviderPluginChoice } from "../plugins/provider-auth-choice.runtime.js";
export type { PluginRuntime } from "../plugins/runtime/types.js";
export type { PluginHookRegistration } from "../plugins/hook-types.js";
export type { RuntimeEnv } from "../runtime.js";
export type { MockFn } from "../test-utils/vitest-mock-fn.js";
export {
createAuthCaptureJsonFetch,
createRequestCaptureJsonFetch,
installPinnedHostnameTestHooks,
} from "../media-understanding/audio.test-helpers.ts";
export {
createSingleUserPromptMessage,
extractNonEmptyAssistantText,
isLiveProfileKeyModeEnabled,
isLiveTestEnabled,
} from "../agents/live-test-helpers.js";
export { createSandboxTestContext } from "../agents/sandbox/test-fixtures.js";
export { writeSkill } from "../skills/test-support/e2e-test-helpers.js";
export {
castAgentMessage,
makeAgentAssistantMessage,
makeAgentUserMessage,
} from "../agents/test-helpers/agent-message-fixtures.js";
export { collectProviderApiKeys } from "../agents/live-auth-keys.js";
export { isModelNotFoundErrorMessage } from "../agents/live-model-errors.js";
export {
isAuthErrorMessage,
isBillingErrorMessage,
isOverloadedErrorMessage,
isServerErrorMessage,
isTimeoutErrorMessage,
} from "../agents/embedded-agent-helpers/failover-matches.js";
export { maybeLoadShellEnvForGenerationProviders } from "../test-utils/generation-live-test-helpers.js";
export { testing, testing as __testing } from "../acp/control-plane/manager.js";
export { testing as acpManagerTesting } from "../acp/control-plane/manager.js";
export { runAcpRuntimeAdapterContract } from "../acp/runtime/adapter-contract.testkit.js";
export { handleAcpCommand } from "../auto-reply/reply/commands-acp.js";
export { buildCommandTestParams } from "../auto-reply/reply/commands-spawn.test-harness.js";
export { peekSystemEvents, resetSystemEventsForTest } from "../infra/system-events.js";
export { isTruthyEnvValue } from "../infra/env.js";
export { getShellEnvAppliedKeys } from "../infra/shell-env.js";
export { encodePngRgba, fillPixel } from "../media/png-encode.js";
export {
parseLiveCsvFilter as parseCsvFilter,
parseProviderModelMap,
redactLiveApiKey,
} from "../media-generation/live-test-helpers.js";
export {
DEFAULT_LIVE_MUSIC_MODELS,
resolveConfiguredLiveMusicModels,
resolveLiveMusicAuthStore,
} from "../music-generation/live-test-helpers.js";
export {
canRunBufferBackedImageToVideoLiveLane,
canRunBufferBackedVideoToVideoLiveLane,
DEFAULT_LIVE_VIDEO_MODELS,
resolveConfiguredLiveVideoModels,
resolveLiveVideoAuthStore,
resolveLiveVideoResolution,
} from "../video-generation/live-test-helpers.js";
export { normalizeVideoGenerationDuration } from "../video-generation/duration-support.js";
export { parseVideoGenerationModelRef } from "../video-generation/model-ref.js";
export type {
GeneratedVideoAsset,
VideoGenerationMode,
VideoGenerationModeCapabilities,
VideoGenerationProvider,
VideoGenerationRequest,
} from "../video-generation/types.js";
export { jsonResponse, requestBodyText, requestUrl } from "../test-helpers/http.js";
export { mockPinnedHostnameResolution } from "../test-helpers/ssrf.js";
export { createOutboundTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js";
export { createWindowsCmdShimFixture } from "../test-helpers/windows-cmd-shim.js";
export { installCommonResolveTargetErrorCases } from "../test-helpers/resolve-target-error-cases.js";
export { sanitizeTerminalText } from "../../packages/terminal-core/src/safe-text.js";
export { withStateDirEnv } from "../test-helpers/state-dir-env.js";
export { countLines, hasBalancedFences } from "../test-utils/chunk-test-helpers.js";
export { expectGeneratedTokenPersistedToGatewayAuth } from "../test-utils/auth-token-assertions.js";
export { captureEnv, withEnv, withEnvAsync } from "../test-utils/env.js";
export { withFetchPreconnect, type FetchMock } from "../test-utils/fetch-mock.js";
export { createMockServerResponse } from "../test-utils/mock-http-response.js";
export {
registerProviderPlugin,
registerProviderPlugins,
registerSingleProviderPlugin,
requireRegisteredProvider,
type RegisteredProviderCollections,
} from "../test-utils/plugin-registration.js";
export { createTempHomeEnv, type TempHomeEnv } from "../test-utils/temp-home.js";
export { withTempDir } from "../test-utils/temp-dir.js";
export { typedCases } from "../test-utils/typed-cases.js";
export { createProviderUsageFetch, makeResponse } from "../test-utils/provider-usage-fetch.js";
export { useFrozenTime, useRealTime } from "../test-utils/frozen-time.js";
export {
createNonExitingRuntimeEnv,
createNonExitingTypedRuntimeEnv,
createRuntimeEnv,
createTypedRuntimeEnv,
} from "../test-utils/plugin-runtime-env.js";
export {
createPluginSetupWizardAdapter,
createPluginSetupWizardConfigure,
createPluginSetupWizardStatus,
createQueuedWizardPrompter,
createSetupWizardAdapter,
createTestWizardPrompter,
promptSetupWizardAllowFrom,
resolveSetupWizardAllowFromEntries,
resolveSetupWizardGroupAllowlist,
runSetupWizardConfigure,
runSetupWizardFinalize,
runSetupWizardPrepare,
selectFirstWizardOption,
type WizardPrompter,
} from "../test-utils/plugin-setup-wizard.js";
export { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
export { buildPluginApi } from "../plugins/api-builder.js";
export {
createCapturedPluginRegistration,
type CapturedPluginRegistration,
} from "../plugins/captured-registration.js";
export { createRuntimeTaskFlow } from "../plugins/runtime/runtime-taskflow.js";
+5 -7
View File
@@ -293,7 +293,7 @@ const PLUGIN_COMPAT_RECORDS = [
},
{
code: "plugin-sdk-testing-barrel",
status: "deprecated",
status: "removed",
owner: "sdk",
introduced: "2026-04-28",
deprecated: "2026-04-28",
@@ -301,14 +301,12 @@ const PLUGIN_COMPAT_RECORDS = [
removeAfter: "2026-07-28",
replacement:
"focused `openclaw/plugin-sdk/*` test subpaths such as `plugin-test-runtime`, `channel-test-helpers`, `test-env`, and `test-fixtures`",
docsPath: "/plugins/sdk-migration",
docsPath: "/plugins/sdk-migration#private-testing-barrel",
surfaces: ["openclaw/plugin-sdk/testing"],
diagnostics: ["plugin SDK compatibility warning"],
tests: [
"src/plugins/compat/registry.test.ts",
"scripts/check-no-extension-test-core-imports.ts",
"test/extension-test-boundary.test.ts",
],
tests: ["src/plugins/compat/registry.test.ts"],
releaseNote:
"The testing subpath was private-local-only and pack-excluded in shipped stables v2026.6.5 and v2026.7.1, so it was safely removed before its removeAfter date.",
},
{
code: "channel-route-key-aliases",
@@ -305,7 +305,7 @@ describe("plugin entry guardrails", () => {
import "./setup.js";
export { x };
export * from "./barrel.js";
import { y } from "openclaw/plugin-sdk/testing";
import { y } from "openclaw/plugin-sdk/core";
`,
}).relativeSpecifiers.toSorted(),
).toEqual(["./barrel.js", "./safe.js", "./setup.js"]);
@@ -43,19 +43,12 @@ const DEPRECATED_EXTENSION_SDK_SPECIFIERS = new Set([
"openclaw/plugin-sdk/channel-config-primitives",
"openclaw/plugin-sdk/channel-config-schema-legacy",
"openclaw/plugin-sdk/compat",
"openclaw/plugin-sdk/testing",
"openclaw/plugin-sdk/test-utils",
]);
const DEPRECATED_TEST_BARREL_SPECIFIERS = new Set([
"openclaw/plugin-sdk/testing",
"openclaw/plugin-sdk/test-utils",
]);
const DEPRECATED_TEST_BARREL_ALLOWED_REFERENCE_FILES = new Set([
"src/plugin-sdk/testing.ts",
const DEPRECATED_TEST_ALIAS_SPECIFIERS = new Set(["openclaw/plugin-sdk/test-utils"]);
const DEPRECATED_TEST_ALIAS_ALLOWED_REFERENCE_FILES = new Set([
"src/plugin-sdk/test-utils.ts",
"packages/plugin-sdk/src/testing.ts",
"src/plugins/compat/registry.ts",
"src/plugins/contracts/plugin-entry-guardrails.test.ts",
"src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts",
]);
const LEGACY_MEMORY_EMBEDDING_PROVIDER_API_FILES = new Set([
@@ -485,24 +478,24 @@ function collectCodeFiles(dir: string): string[] {
return files;
}
function collectDeprecatedTestBarrelImports(): string[] {
function collectDeprecatedTestAliasImports(): string[] {
const leaks: Array<{ file: string; specifier: string }> = [];
const importPatterns = [
/\b(?:import|export)\b[\s\S]*?\bfrom\s*["'](openclaw\/plugin-sdk\/(?:testing|test-utils))["']/g,
/\bimport\s*\(\s*["'](openclaw\/plugin-sdk\/(?:testing|test-utils))["']\s*\)/g,
/\bvi\.(?:mock|doMock)\s*\(\s*["'](openclaw\/plugin-sdk\/(?:testing|test-utils))["']/g,
/\b(?:import|export)\b[\s\S]*?\bfrom\s*["'](openclaw\/plugin-sdk\/test-utils)["']/g,
/\bimport\s*\(\s*["'](openclaw\/plugin-sdk\/test-utils)["']\s*\)/g,
/\bvi\.(?:mock|doMock)\s*\(\s*["'](openclaw\/plugin-sdk\/test-utils)["']/g,
];
for (const root of ["src", "test", "extensions", "packages"]) {
for (const file of collectCodeFiles(resolve(REPO_ROOT, root))) {
const repoRelativePath = toRepoRelativePath(file);
if (DEPRECATED_TEST_BARREL_ALLOWED_REFERENCE_FILES.has(repoRelativePath)) {
if (DEPRECATED_TEST_ALIAS_ALLOWED_REFERENCE_FILES.has(repoRelativePath)) {
continue;
}
const source = fs.readFileSync(file, "utf8");
for (const importPattern of importPatterns) {
for (const match of source.matchAll(importPattern)) {
const specifier = match[1];
if (!specifier || !DEPRECATED_TEST_BARREL_SPECIFIERS.has(specifier)) {
if (!specifier || !DEPRECATED_TEST_ALIAS_SPECIFIERS.has(specifier)) {
continue;
}
leaks.push({
@@ -516,17 +509,6 @@ function collectDeprecatedTestBarrelImports(): string[] {
return leaks.map((entry) => `${entry.file}: ${entry.specifier}`).toSorted();
}
function collectDeprecatedPackageTestingBridgeDrift(): string[] {
const source = fs
.readFileSync(resolve(REPO_ROOT, "packages/plugin-sdk/src/testing.ts"), "utf8")
.split("\n")
.map((line) => line.trim())
.filter((line) => line && !line.startsWith("//"));
return source.length === 1 && source[0] === 'export * from "../../../src/plugin-sdk/testing.js";'
? []
: ["packages/plugin-sdk/src/testing.ts"];
}
function parseTestApiNamedExports(source: string): string[] {
const exports = new Set<string>();
const declarationPattern =
@@ -730,11 +712,11 @@ function collectExtensionProductionSdkSubpathImports(subpaths: ReadonlySet<strin
}
describe("plugin-sdk package contract guardrails", () => {
let deprecatedTestBarrelImports: string[] = [];
let deprecatedTestAliasImports: string[] = [];
let unusedReservedSdkSubpaths: string[] = [];
beforeAll(() => {
deprecatedTestBarrelImports = collectDeprecatedTestBarrelImports();
deprecatedTestAliasImports = collectDeprecatedTestAliasImports();
const usedReserved = new Set(collectReservedSdkSubpathImports());
unusedReservedSdkSubpaths = reservedBundledPluginSdkEntrypoints.filter(
(entrypoint) => !usedReserved.has(entrypoint),
@@ -774,7 +756,7 @@ describe("plugin-sdk package contract guardrails", () => {
const localOnly = new Set(privateLocalOnlyPluginSdkEntrypoints);
expect(
["plugin-test-contracts", "provider-test-contracts", "testing"].every((entrypoint) =>
["plugin-test-contracts", "provider-test-contracts"].every((entrypoint) =>
localOnly.has(entrypoint),
),
).toBe(true);
@@ -955,12 +937,8 @@ describe("plugin-sdk package contract guardrails", () => {
});
});
it("keeps real tests off deprecated plugin-sdk testing barrels", () => {
expect(deprecatedTestBarrelImports).toStrictEqual([]);
});
it("keeps the package testing barrel as a single deprecated bridge", () => {
expect(collectDeprecatedPackageTestingBridgeDrift()).toStrictEqual([]);
it("keeps real tests off the deprecated plugin-sdk test-utils alias", () => {
expect(deprecatedTestAliasImports).toStrictEqual([]);
});
it(
+1 -2
View File
@@ -333,9 +333,8 @@ describe("non-extension test boundaries", () => {
expect(offenders).toStrictEqual([]);
});
it("keeps extension tests off legacy broad testing barrels and repo helper bridges", () => {
it("keeps extension tests off the legacy test alias and repo helper bridges", () => {
const bannedPatterns = [
/["']openclaw\/plugin-sdk\/testing["']/u,
/["']openclaw\/plugin-sdk\/test-utils["']/u,
/["'](?:\.\.\/)+(?:test\/helpers\/channels\/)[^"']+["']/u,
/["'](?:\.\.\/)+(?:src\/channels\/plugins\/contracts\/test-helpers\/)[^"']+["']/u,
+4 -4
View File
@@ -668,14 +668,14 @@ describe("collectForbiddenPackPaths", () => {
try {
mkdirSync(join(tempRoot, "dist", "plugin-sdk"), { recursive: true });
writeFileSync(
join(tempRoot, "dist", "plugin-sdk", "testing.d.ts"),
join(tempRoot, "dist", "plugin-sdk", "channel-test-helpers.d.ts"),
"//#region src/plugin-sdk/test-helpers/session.ts\n",
"utf8",
);
expect(collectForbiddenPackContentPaths(["dist/plugin-sdk/testing.d.ts"], tempRoot)).toEqual([
"dist/plugin-sdk/testing.d.ts",
]);
expect(
collectForbiddenPackContentPaths(["dist/plugin-sdk/channel-test-helpers.d.ts"], tempRoot),
).toEqual(["dist/plugin-sdk/channel-test-helpers.d.ts"]);
} finally {
rmSync(tempRoot, { recursive: true, force: true });
}
@@ -592,7 +592,7 @@ describe("bundled plugin postinstall", () => {
it("omits unpacked plugin-sdk test helpers from the package dist inventory", async () => {
const packageRoot = await createTempDirAsync("openclaw-packaged-inventory-");
const runtimeFile = path.join(packageRoot, "dist", "plugin-sdk", "runtime.js");
const testHelperFile = path.join(packageRoot, "dist", "plugin-sdk", "testing.js");
const testHelperFile = path.join(packageRoot, "dist", "plugin-sdk", "channel-test-helpers.js");
const nestedTestHelperFile = path.join(
packageRoot,
"dist",
@@ -611,7 +611,7 @@ describe("bundled plugin postinstall", () => {
const inventory = await writePackageDistInventory(packageRoot);
expect(inventory).toContain("dist/plugin-sdk/runtime.js");
expect(inventory).not.toContain("dist/plugin-sdk/testing.js");
expect(inventory).not.toContain("dist/plugin-sdk/channel-test-helpers.js");
expect(inventory).not.toContain(
"dist/plugin-sdk/src/plugin-sdk/test-helpers/provider-contract.d.ts",
);