11import { execFileSync } from "node:child_process" ;
2- import { mkdirSync , writeFileSync } from "node:fs" ;
2+ import { mkdirSync , readFileSync , writeFileSync } from "node:fs" ;
33import { join } from "node:path" ;
44import { afterEach , describe , expect , it } from "vitest" ;
55import {
@@ -11,7 +11,10 @@ import {
1111 resolveSelectedClawHubPublishablePluginPackages ,
1212 type PublishablePluginPackage ,
1313} from "../scripts/lib/plugin-clawhub-release.ts" ;
14- import { OPENCLAW_PLUGIN_NPM_REPOSITORY_URL } from "../scripts/lib/plugin-npm-release.ts" ;
14+ import {
15+ collectPublishablePluginPackages ,
16+ OPENCLAW_PLUGIN_NPM_REPOSITORY_URL ,
17+ } from "../scripts/lib/plugin-npm-release.ts" ;
1518import { cleanupTempDirs , makeTempRepoRoot } from "./helpers/temp-repo.js" ;
1619
1720const tempDirs : string [ ] = [ ] ;
@@ -101,6 +104,60 @@ describe("collectClawHubPublishablePluginPackages", () => {
101104 } ) ;
102105} ) ;
103106
107+ describe ( "OpenClaw ClawHub-preferred plugin metadata" , ( ) => {
108+ const clawHubPreferredPlugins = [
109+ {
110+ extensionId : "diagnostics-otel" ,
111+ packageName : "@openclaw/diagnostics-otel" ,
112+ } ,
113+ {
114+ extensionId : "diagnostics-prometheus" ,
115+ packageName : "@openclaw/diagnostics-prometheus" ,
116+ } ,
117+ ] as const ;
118+
119+ it ( "keeps diagnostics plugins selectable through both ClawHub and npm release paths" , ( ) => {
120+ const packageNames = clawHubPreferredPlugins . map ( ( plugin ) => plugin . packageName ) ;
121+ const clawHubPublishable = collectClawHubPublishablePluginPackages ( undefined , {
122+ packageNames,
123+ } ) ;
124+ const npmPublishable = collectPublishablePluginPackages ( undefined , {
125+ packageNames,
126+ } ) ;
127+
128+ expect ( clawHubPublishable . map ( ( plugin ) => plugin . packageName ) ) . toEqual ( packageNames ) ;
129+ expect ( npmPublishable . map ( ( plugin ) => plugin . packageName ) ) . toEqual ( packageNames ) ;
130+
131+ for ( const plugin of clawHubPreferredPlugins ) {
132+ const packageJson = JSON . parse (
133+ readFileSync ( `extensions/${ plugin . extensionId } /package.json` , "utf8" ) ,
134+ ) as {
135+ openclaw ?: {
136+ install ?: {
137+ clawhubSpec ?: string ;
138+ defaultChoice ?: string ;
139+ npmSpec ?: string ;
140+ } ;
141+ release ?: {
142+ publishToClawHub ?: boolean ;
143+ publishToNpm ?: boolean ;
144+ } ;
145+ } ;
146+ } ;
147+
148+ expect ( packageJson . openclaw ?. install ) . toMatchObject ( {
149+ clawhubSpec : `clawhub:${ plugin . packageName } ` ,
150+ defaultChoice : "clawhub" ,
151+ npmSpec : plugin . packageName ,
152+ } ) ;
153+ expect ( packageJson . openclaw ?. release ) . toMatchObject ( {
154+ publishToClawHub : true ,
155+ publishToNpm : true ,
156+ } ) ;
157+ }
158+ } ) ;
159+ } ) ;
160+
104161describe ( "collectClawHubVersionGateErrors" , ( ) => {
105162 it ( "requires a version bump when a publishable plugin changes" , ( ) => {
106163 const repoDir = createTempPluginRepo ( ) ;
0 commit comments