mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
test: stabilize slow extension gates
This commit is contained in:
@@ -3,8 +3,8 @@ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entr
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./channel-plugin-api.js",
|
||||
exportName: "qaChannelPlugin",
|
||||
specifier: "./setup-plugin-api.js",
|
||||
exportName: "qaChannelSetupPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
|
||||
3
extensions/qa-channel/setup-plugin-api.ts
Normal file
3
extensions/qa-channel/setup-plugin-api.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// Keep bundled setup entry imports narrow so setup loads do not pull the
|
||||
// broader QA channel runtime and gateway surface.
|
||||
export { qaChannelSetupPlugin } from "./src/channel.setup.js";
|
||||
43
extensions/qa-channel/src/channel.setup.ts
Normal file
43
extensions/qa-channel/src/channel.setup.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { getChatChannelMeta } from "openclaw/plugin-sdk/channel-plugin-common";
|
||||
import {
|
||||
listQaChannelAccountIds,
|
||||
resolveDefaultQaChannelAccountId,
|
||||
resolveQaChannelAccount,
|
||||
type ResolvedQaChannelAccount,
|
||||
} from "./accounts.js";
|
||||
import { qaChannelPluginConfigSchema } from "./config-schema.js";
|
||||
import type { ChannelPlugin } from "./runtime-api.js";
|
||||
import { applyQaSetup } from "./setup.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
|
||||
const CHANNEL_ID = "qa-channel" as const;
|
||||
const meta = { ...getChatChannelMeta(CHANNEL_ID) };
|
||||
|
||||
export const qaChannelSetupPlugin: ChannelPlugin<ResolvedQaChannelAccount> = {
|
||||
id: CHANNEL_ID,
|
||||
meta,
|
||||
capabilities: {
|
||||
chatTypes: ["direct", "group"],
|
||||
},
|
||||
reload: { configPrefixes: ["channels.qa-channel"] },
|
||||
configSchema: qaChannelPluginConfigSchema,
|
||||
setup: {
|
||||
applyAccountConfig: ({ cfg, accountId, input }) =>
|
||||
applyQaSetup({
|
||||
cfg,
|
||||
accountId,
|
||||
input: input as Record<string, unknown>,
|
||||
}),
|
||||
},
|
||||
config: {
|
||||
listAccountIds: (cfg) => listQaChannelAccountIds(cfg as CoreConfig),
|
||||
resolveAccount: (cfg, accountId) =>
|
||||
resolveQaChannelAccount({ cfg: cfg as CoreConfig, accountId }),
|
||||
defaultAccountId: (cfg) => resolveDefaultQaChannelAccountId(cfg as CoreConfig),
|
||||
isConfigured: (account) => account.configured,
|
||||
resolveAllowFrom: ({ cfg, accountId }) =>
|
||||
resolveQaChannelAccount({ cfg: cfg as CoreConfig, accountId }).config.allowFrom,
|
||||
resolveDefaultTo: ({ cfg, accountId }) =>
|
||||
resolveQaChannelAccount({ cfg: cfg as CoreConfig, accountId }).config.defaultTo,
|
||||
},
|
||||
};
|
||||
@@ -130,30 +130,33 @@ async function startQaGatewayLoop(params: { state: QaBusState; baseUrl: string }
|
||||
const cfg = createQaLabConfig(params.baseUrl);
|
||||
const account = qaChannelPlugin.config.resolveAccount(cfg, "default");
|
||||
const abort = new AbortController();
|
||||
const task = qaChannelPlugin.gateway?.startAccount?.({
|
||||
accountId: account.accountId,
|
||||
account,
|
||||
cfg,
|
||||
runtime: {
|
||||
log: () => undefined,
|
||||
error: () => undefined,
|
||||
exit: () => undefined,
|
||||
},
|
||||
abortSignal: abort.signal,
|
||||
log: {
|
||||
info: () => undefined,
|
||||
warn: () => undefined,
|
||||
error: () => undefined,
|
||||
debug: () => undefined,
|
||||
},
|
||||
getStatus: () => ({
|
||||
accountId: account.accountId,
|
||||
configured: true,
|
||||
enabled: true,
|
||||
running: true,
|
||||
}),
|
||||
setStatus: () => undefined,
|
||||
});
|
||||
const task = Promise.resolve().then(
|
||||
async () =>
|
||||
await qaChannelPlugin.gateway?.startAccount?.({
|
||||
accountId: account.accountId,
|
||||
account,
|
||||
cfg,
|
||||
runtime: {
|
||||
log: () => undefined,
|
||||
error: () => undefined,
|
||||
exit: () => undefined,
|
||||
},
|
||||
abortSignal: abort.signal,
|
||||
log: {
|
||||
info: () => undefined,
|
||||
warn: () => undefined,
|
||||
error: () => undefined,
|
||||
debug: () => undefined,
|
||||
},
|
||||
getStatus: () => ({
|
||||
accountId: account.accountId,
|
||||
configured: true,
|
||||
enabled: true,
|
||||
running: true,
|
||||
}),
|
||||
setStatus: () => undefined,
|
||||
}),
|
||||
);
|
||||
return {
|
||||
cfg,
|
||||
async stop() {
|
||||
|
||||
@@ -20,7 +20,7 @@ export {
|
||||
searchQaBusMessages,
|
||||
sendQaBusMessage,
|
||||
setQaChannelRuntime,
|
||||
} from "openclaw/plugin-sdk/qa-channel";
|
||||
} from "@openclaw/qa-channel/api.js";
|
||||
export type {
|
||||
QaBusAttachment,
|
||||
QaBusConversation,
|
||||
|
||||
@@ -1135,12 +1135,8 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
await sleep(statusReactionTiming.errorHoldMs);
|
||||
if (anyReplyDelivered) {
|
||||
await statusReactions.clear();
|
||||
return;
|
||||
}
|
||||
await statusReactions.restoreInitial();
|
||||
})();
|
||||
} else {
|
||||
void statusReactions.restoreInitial();
|
||||
}
|
||||
} else if (anyReplyDelivered) {
|
||||
await statusReactions.setDone();
|
||||
|
||||
@@ -404,7 +404,7 @@ const IMPORT_SPECIFIER_PATTERN =
|
||||
const BROAD_CHANGED_ENV_KEY = "OPENCLAW_TEST_CHANGED_BROAD";
|
||||
const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
|
||||
const VITEST_NO_OUTPUT_RETRY_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_RETRY";
|
||||
export const DEFAULT_TEST_PROJECTS_VITEST_NO_OUTPUT_TIMEOUT_MS = "180000";
|
||||
export const DEFAULT_TEST_PROJECTS_VITEST_NO_OUTPUT_TIMEOUT_MS = "300000";
|
||||
const VITEST_CONFIG_TARGET_KIND_BY_PATH = new Map(
|
||||
Object.entries(VITEST_CONFIG_BY_KIND).map(([kind, config]) => [config, kind]),
|
||||
);
|
||||
|
||||
@@ -564,6 +564,8 @@ describe("buildStatusReply subagent summary", () => {
|
||||
{
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: bundledDir,
|
||||
OPENCLAW_STATE_DIR: stateDir,
|
||||
ANTHROPIC_API_KEY: undefined,
|
||||
ANTHROPIC_OAUTH_TOKEN: undefined,
|
||||
WORKSPACE_STATUS_CREDENTIALS: credentialPath,
|
||||
},
|
||||
async () => {
|
||||
|
||||
@@ -24,6 +24,7 @@ const PRIVATE_BUNDLED_SDK_SURFACE_PATTERN =
|
||||
const GENERIC_CORE_HELPER_FILES = ["src/polls.ts", "src/poll-params.ts"] as const;
|
||||
const GENERIC_CORE_PLUGIN_OWNER_NAME_PATTERN =
|
||||
/\b(?:bluebubbles|discord|feishu|googlechat|matrix|mattermost|msteams|slack|telegram|whatsapp|zalo|zalouser)\b/gi;
|
||||
const PACKAGE_CONTRACT_SCAN_TIMEOUT_MS = 240_000;
|
||||
const DEPRECATED_EXTENSION_SDK_SPECIFIERS = new Set([
|
||||
"openclaw/plugin-sdk",
|
||||
"openclaw/plugin-sdk/channel-config-schema-legacy",
|
||||
@@ -655,9 +656,13 @@ describe("plugin-sdk package contract guardrails", () => {
|
||||
expect(collectDeprecatedPackageTestingBridgeDrift()).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps extension test-api exports consumed", () => {
|
||||
expect(collectUnusedExtensionTestApiExports()).toEqual([]);
|
||||
});
|
||||
it(
|
||||
"keeps extension test-api exports consumed",
|
||||
() => {
|
||||
expect(collectUnusedExtensionTestApiExports()).toEqual([]);
|
||||
},
|
||||
PACKAGE_CONTRACT_SCAN_TIMEOUT_MS,
|
||||
);
|
||||
|
||||
it("keeps reserved SDK compatibility subpaths inside their owning bundled plugins", () => {
|
||||
expect(collectCrossOwnerReservedSdkImports()).toEqual([]);
|
||||
|
||||
@@ -54,6 +54,7 @@ function loadCoverageRegistryEntries(): SecretRegistryEntry[] {
|
||||
|
||||
const COVERAGE_REGISTRY_ENTRIES = loadCoverageRegistryEntries();
|
||||
const DEBUG_COVERAGE_BATCHES = process.env.OPENCLAW_DEBUG_RUNTIME_COVERAGE === "1";
|
||||
const RUNTIME_COVERAGE_TEST_TIMEOUT_MS = 240_000;
|
||||
const COVERAGE_LOADABLE_PLUGIN_ORIGINS =
|
||||
buildCoverageLoadablePluginOrigins(COVERAGE_REGISTRY_ENTRIES);
|
||||
const PLUGIN_OWNED_OPENCLAW_COVERAGE_EXCLUSIONS = new Set([
|
||||
@@ -564,19 +565,27 @@ describe("secrets runtime target coverage", () => {
|
||||
({ resolveSecretRefValues } = resolver);
|
||||
});
|
||||
|
||||
it("handles every core and channel openclaw.json registry target when configured as active", async () => {
|
||||
await expectOpenClawCoverageEntriesResolved(
|
||||
"openclaw.json core",
|
||||
collectOpenClawCoverageEntries({ includePluginEntries: false }),
|
||||
);
|
||||
});
|
||||
it(
|
||||
"handles every core and channel openclaw.json registry target when configured as active",
|
||||
async () => {
|
||||
await expectOpenClawCoverageEntriesResolved(
|
||||
"openclaw.json core",
|
||||
collectOpenClawCoverageEntries({ includePluginEntries: false }),
|
||||
);
|
||||
},
|
||||
RUNTIME_COVERAGE_TEST_TIMEOUT_MS,
|
||||
);
|
||||
|
||||
it("handles every plugin openclaw.json registry target when configured as active", async () => {
|
||||
await expectOpenClawCoverageEntriesResolved(
|
||||
"openclaw.json plugins",
|
||||
collectOpenClawCoverageEntries({ includePluginEntries: true }),
|
||||
);
|
||||
});
|
||||
it(
|
||||
"handles every plugin openclaw.json registry target when configured as active",
|
||||
async () => {
|
||||
await expectOpenClawCoverageEntriesResolved(
|
||||
"openclaw.json plugins",
|
||||
collectOpenClawCoverageEntries({ includePluginEntries: true }),
|
||||
);
|
||||
},
|
||||
RUNTIME_COVERAGE_TEST_TIMEOUT_MS,
|
||||
);
|
||||
|
||||
it("handles every auth-profiles registry target", async () => {
|
||||
const entries = COVERAGE_REGISTRY_ENTRIES.filter(
|
||||
|
||||
Reference in New Issue
Block a user