diff --git a/src/config/doc-baseline.integration.test.ts b/src/config/doc-baseline.integration.test.ts index 1cb81623889..71c95d03f07 100644 --- a/src/config/doc-baseline.integration.test.ts +++ b/src/config/doc-baseline.integration.test.ts @@ -70,6 +70,26 @@ describe("config doc baseline integration", () => { expect(tokenEntry?.tags).toContain("security"); }); + it("uses human-readable channel metadata for top-level channel sections", async () => { + const baseline = await getSharedBaseline(); + const byPath = new Map(baseline.entries.map((entry) => [entry.path, entry])); + + expect(byPath.get("channels.discord")).toMatchObject({ + label: "Discord", + help: "very well supported right now.", + }); + expect(byPath.get("channels.msteams")).toMatchObject({ + label: "Microsoft Teams", + help: "Bot Framework; enterprise support.", + }); + expect(byPath.get("channels.matrix")).toMatchObject({ + label: "Matrix", + help: "open protocol; install the plugin to enable.", + }); + expect(byPath.get("channels.msteams")?.label).not.toContain("@openclaw/"); + expect(byPath.get("channels.matrix")?.help).not.toContain("homeserver"); + }); + it("matches array help hints that still use [] notation", async () => { const baseline = await getSharedBaseline(); const byPath = new Map(baseline.entries.map((entry) => [entry.path, entry])); diff --git a/src/config/doc-baseline.ts b/src/config/doc-baseline.ts index 1603fa3dd1b..1aa996fd5b6 100644 --- a/src/config/doc-baseline.ts +++ b/src/config/doc-baseline.ts @@ -269,7 +269,12 @@ function resolveFirstExistingPath(candidates: string[]): string | null { } async function loadBundledConfigSchemaResponse(): Promise { - const [{ loadPluginManifestRegistry }, { buildConfigSchema }] = await Promise.all([ + const [ + { listChannelPluginCatalogEntries }, + { loadPluginManifestRegistry }, + { buildConfigSchema }, + ] = await Promise.all([ + import("../channels/plugins/catalog.js"), import("../plugins/manifest-registry.js"), import("./schema.js"), ]); @@ -286,6 +291,12 @@ async function loadBundledConfigSchemaResponse(): Promise env, config: {}, }); + const channelCatalogById = new Map( + listChannelPluginCatalogEntries({ + workspaceDir: repoRoot, + env, + }).map((entry) => [entry.id, entry.meta] as const), + ); logConfigDocBaselineDebug(`loaded ${manifestRegistry.plugins.length} bundled plugin manifests`); const bundledChannelPlugins = manifestRegistry.plugins.filter( (plugin) => plugin.origin === "bundled" && plugin.channels.length > 0, @@ -295,16 +306,20 @@ async function loadBundledConfigSchemaResponse(): Promise ? await bundledChannelPlugins.reduce>( async (promise, plugin) => { const loaded = await promise; + const catalogMeta = channelCatalogById.get(plugin.id); + const label = catalogMeta?.label ?? plugin.name ?? plugin.id; + const description = catalogMeta?.blurb ?? plugin.description; loaded.push( (await loadChannelSurfaceMetadata( plugin.rootDir, plugin.id, - plugin.name ?? plugin.id, + label, + description, repoRoot, )) ?? { id: plugin.id, - label: plugin.name ?? plugin.id, - description: plugin.description, + label, + description, configSchema: plugin.configSchema, configUiHints: plugin.configUiHints, }, @@ -314,21 +329,26 @@ async function loadBundledConfigSchemaResponse(): Promise Promise.resolve([]), ) : await Promise.all( - bundledChannelPlugins.map( - async (plugin) => + bundledChannelPlugins.map(async (plugin) => { + const catalogMeta = channelCatalogById.get(plugin.id); + const label = catalogMeta?.label ?? plugin.name ?? plugin.id; + const description = catalogMeta?.blurb ?? plugin.description; + return ( (await loadChannelSurfaceMetadata( plugin.rootDir, plugin.id, - plugin.name ?? plugin.id, + label, + description, repoRoot, )) ?? { id: plugin.id, - label: plugin.name ?? plugin.id, - description: plugin.description, + label, + description, configSchema: plugin.configSchema, configUiHints: plugin.configUiHints, - }, - ), + } + ); + }), ); logConfigDocBaselineDebug( `loaded ${channelPlugins.length} bundled channel entries from channel surfaces`, @@ -359,6 +379,7 @@ async function loadChannelSurfaceMetadata( rootDir: string, id: string, label: string, + description: string | undefined, repoRoot: string, ): Promise { logConfigDocBaselineDebug(`resolve channel config surface ${rootDir}`); @@ -386,6 +407,7 @@ async function loadChannelSurfaceMetadata( return { id, label, + description, configSchema: configSurface.schema, configUiHints: configSurface.uiHints as ConfigSchemaResponse["uiHints"] | undefined, };