@@ -84,6 +84,16 @@ export type OfficialExternalPluginCatalogEntry = {
8484 kind ?: string ;
8585} & Partial < Record < ManifestKey , OfficialExternalPluginCatalogManifest > > ;
8686
87+ /** Feed-shaped wrapper used by the bundled external plugin catalog fallback. */
88+ export type OfficialExternalPluginCatalogFeed = {
89+ schemaVersion : number ;
90+ id : string ;
91+ generatedAt : string ;
92+ sequence : number ;
93+ description ?: string ;
94+ entries : readonly OfficialExternalPluginCatalogEntry [ ] ;
95+ } ;
96+
8797type OfficialExternalProviderContract =
8898 | "embeddingProviders"
8999 | "mediaUnderstandingProviders"
@@ -97,13 +107,45 @@ const OFFICIAL_CATALOG_SOURCES = [
97107 officialExternalPluginCatalog ,
98108] as const ;
99109
100- function parseCatalogEntries ( raw : unknown ) : OfficialExternalPluginCatalogEntry [ ] {
110+ const OFFICIAL_EXTERNAL_CATALOG_FEED_SCHEMA_VERSION = 1 ;
111+
112+ export function isOfficialExternalPluginCatalogFeed (
113+ raw : unknown ,
114+ ) : raw is OfficialExternalPluginCatalogFeed {
115+ if ( ! isRecord ( raw ) ) {
116+ return false ;
117+ }
118+ const sequence = raw . sequence ;
119+ return (
120+ raw . schemaVersion === OFFICIAL_EXTERNAL_CATALOG_FEED_SCHEMA_VERSION &&
121+ typeof raw . id === "string" &&
122+ raw . id . trim ( ) . length > 0 &&
123+ typeof raw . generatedAt === "string" &&
124+ raw . generatedAt . trim ( ) . length > 0 &&
125+ typeof sequence === "number" &&
126+ Number . isInteger ( sequence ) &&
127+ sequence >= 0 &&
128+ Array . isArray ( raw . entries )
129+ ) ;
130+ }
131+
132+ export function parseOfficialExternalPluginCatalogEntries (
133+ raw : unknown ,
134+ ) : OfficialExternalPluginCatalogEntry [ ] {
101135 if ( Array . isArray ( raw ) ) {
102136 return raw . filter ( ( entry ) : entry is OfficialExternalPluginCatalogEntry => isRecord ( entry ) ) ;
103137 }
138+ if ( isOfficialExternalPluginCatalogFeed ( raw ) ) {
139+ return raw . entries . filter ( ( entry ) : entry is OfficialExternalPluginCatalogEntry =>
140+ isRecord ( entry ) ,
141+ ) ;
142+ }
104143 if ( ! isRecord ( raw ) ) {
105144 return [ ] ;
106145 }
146+ if ( "schemaVersion" in raw ) {
147+ return [ ] ;
148+ }
107149 const list = raw . entries ?? raw . packages ?? raw . plugins ;
108150 if ( ! Array . isArray ( list ) ) {
109151 return [ ] ;
@@ -191,7 +233,9 @@ export function resolveOfficialExternalPluginInstall(
191233}
192234
193235export function listOfficialExternalPluginCatalogEntries ( ) : OfficialExternalPluginCatalogEntry [ ] {
194- const entries = OFFICIAL_CATALOG_SOURCES . flatMap ( ( source ) => parseCatalogEntries ( source ) ) ;
236+ const entries = OFFICIAL_CATALOG_SOURCES . flatMap ( ( source ) =>
237+ parseOfficialExternalPluginCatalogEntries ( source ) ,
238+ ) ;
195239 const resolved = new Map < string , OfficialExternalPluginCatalogEntry > ( ) ;
196240 for ( const entry of entries ) {
197241 const pluginId = resolveOfficialExternalPluginId ( entry ) ;
0 commit comments