refactor: move Telegram and iMessage config schemas to plugins (#112850)

* refactor: move telegram and imessage schemas to plugins

* test: allow bundled schema facade regression coverage

* refactor: remove orphaned command config helper
This commit is contained in:
Peter Steinberger
2026-07-22 23:01:47 -04:00
committed by GitHub
parent 099d6351b3
commit ebec398543
22 changed files with 640 additions and 707 deletions

View File

@@ -10,8 +10,8 @@ const REPO_ROOT = resolve(SRC_ROOT, "..");
const BUNDLED_EXTENSION_CONFIG_IMPORT_GUARDS = [
{
path: "extensions/telegram/src/config-schema.ts",
allowedSpecifier: "../config-api.js",
forbiddenSpecifier: "openclaw/plugin-sdk/channel-config-schema",
allowedSpecifier: "openclaw/plugin-sdk/channel-config-schema",
forbiddenSpecifier: "openclaw/plugin-sdk/bundled-channel-config-schema",
},
{
path: "extensions/discord/src/config-schema.ts",
@@ -30,8 +30,8 @@ const BUNDLED_EXTENSION_CONFIG_IMPORT_GUARDS = [
},
{
path: "extensions/imessage/src/config-schema.ts",
allowedSpecifier: "../config-api.js",
forbiddenSpecifier: "openclaw/plugin-sdk/channel-config-schema",
allowedSpecifier: "openclaw/plugin-sdk/channel-config-schema",
forbiddenSpecifier: "openclaw/plugin-sdk/bundled-channel-config-schema",
},
{
path: "extensions/whatsapp/src/config-schema.ts",

View File

@@ -140,16 +140,16 @@ describe("config footprint guardrails", () => {
});
it("keeps canonical nested streaming paths in channel-owned schemas", () => {
const source = readSource("src/config/zod-schema.providers-core.ts");
const telegramSource = readSource("extensions/telegram/src/config-schema.ts");
const discordSource = readSource("extensions/discord/src/config-schema.ts");
const msTeamsSource = readSource("extensions/msteams/src/config-schema.ts");
const slackSource = readSource("extensions/slack/src/config-schema.ts");
expect(source).toContain("streaming: TelegramPreviewStreamingConfigSchema.optional(),");
expect(telegramSource).toContain("streaming: TelegramPreviewStreamingConfigSchema.optional(),");
expect(discordSource).toContain("streaming: DiscordPreviewStreamingConfigSchema.optional(),");
expect(msTeamsSource).toContain("streaming: ChannelPreviewStreamingConfigSchema.optional(),");
expect(slackSource).toContain("streaming: SlackStreamingConfigSchema.optional(),");
for (const schemaSource of [source, discordSource, msTeamsSource, slackSource]) {
for (const schemaSource of [telegramSource, discordSource, msTeamsSource, slackSource]) {
expect(schemaSource).not.toContain(
'streamMode: z.enum(["replace", "status_final", "append"])',
);
@@ -196,18 +196,23 @@ describe("config footprint guardrails", () => {
);
const bundledSchemaExportBlocks = Array.from(
bundledSection.matchAll(
/export \{(?<exports>[^}]*)\} from "\.\.\/config\/zod-schema\.providers-(?:core|googlechat|whatsapp)\.js";/g,
/export \{(?<exports>[^}]*)\} from "\.\.\/config\/zod-schema\.providers-(?:googlechat|whatsapp)\.js";/g,
),
)
.map((match) => match.groups?.exports)
.filter((block): block is string => Boolean(block));
expect(bundledSchemaExportBlocks).toHaveLength(3);
const exportedSchemaNames = Array.from(
bundledSchemaExportBlocks.join("\n").matchAll(/\b([A-Z][A-Za-z0-9]+ConfigSchema)\b/g),
)
.map((match) => match[1])
.filter((name): name is string => Boolean(name))
.toSorted((left, right) => left.localeCompare(right));
expect(bundledSchemaExportBlocks).toHaveLength(2);
const lazySchemaNames = Array.from(
bundledSection.matchAll(/\bexport const ([A-Z][A-Za-z0-9]+ConfigSchema)\b/g),
(match) => match[1],
).filter((name): name is string => Boolean(name));
const exportedSchemaNames = [
...Array.from(
bundledSchemaExportBlocks.join("\n").matchAll(/\b([A-Z][A-Za-z0-9]+ConfigSchema)\b/g),
(match) => match[1],
).filter((name): name is string => Boolean(name)),
...lazySchemaNames,
].toSorted((left, right) => left.localeCompare(right));
expect(exportedSchemaNames).toEqual([
"GoogleChatConfigSchema",
@@ -220,6 +225,12 @@ describe("config footprint guardrails", () => {
}
expect(bundledSource).toContain("Bundled-channel config schemas");
expect(bundledSource).toContain("openclaw/plugin-sdk/channel-config-schema");
expect(bundledSource).toMatch(
/loadBundledConfigSchema<[^;]+?>\(\s*"imessage",\s*"IMessageConfigSchema",?\s*\)/u,
);
expect(bundledSource).toMatch(
/loadBundledConfigSchema<[^;]+?>\(\s*"telegram",\s*"TelegramConfigSchema",?\s*\)/u,
);
// The primitives facade re-exports the canonical channel-config-schema
// module; only bundled provider schemas bypass it.
const primitivesSource = readSource("src/plugin-sdk/channel-config-primitives.ts");
@@ -234,6 +245,8 @@ describe("config footprint guardrails", () => {
// channel-config-schema is the canonical internal module; the primitives
// and bundled shells stay export-compatible for plugins only.
const allowedShellImporters = new Set([
// The facade's focused regression test is its only internal consumer.
"src/plugin-sdk/bundled-channel-config-schema.test.ts",
// This guardrail file embeds facade specifiers in shell-shape assertions.
"src/plugins/contracts/config-footprint-guardrails.test.ts",
]);