Files
deepseek-harness/scripts/gen-official-bundle-catalog.ts
T
Turtle 9b4aacb41a refactor(util): collect hardcoded official plugin lists in dsh-official-bundles
Move @deepseek-ai/dsh-official-bundles from packages/boot to packages/util
and move the plugin manager's protected plugin list and the Web plugin
page's hidden, ordered, and experimental bundle lists into it, so editing
any of these lists no longer touches app-boot or either plugin manager
package.
2026-10-23 12:12:38 +08:00

130 lines
7.2 KiB
TypeScript

/** Embed package-owned display metadata for Official bundles whose providers install on demand. */
import { globSync, readFileSync, writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'
import ts from 'typescript'
import type { LocalizedText } from '../packages/util/package-manifest/src/types.ts'
import { ON_DEMAND_BUNDLES } from '../packages/util/official-bundles/src/bundles.ts'
import type { OfficialBundleCatalogEntry } from '../packages/util/official-bundles/src/index.ts'
import { readPluginMeta, resolvePluginResource } from '../packages/boot/app-boot/src/package-meta.ts'
import { SHIPPED_LOCALE_IDS } from './shipped-locales.ts'
const OUTPUT = 'packages/util/official-bundles/src/catalog.generated.ts'
/**
* Read complete metadata without importing or activating any provider code.
* @param root - Repository root containing the catalog's public packages.
* @param names - Catalog admission list; defaults to the installation-owned list.
* @returns Offline entries in admission order, with metadata from the owning packages.
*/
export function generateOfficialBundleCatalog(root: string, names: readonly string[] = ON_DEMAND_BUNDLES): OfficialBundleCatalogEntry[] {
if (names.length === 0 || new Set(names).size !== names.length) throw new Error('Official on-demand catalog must contain distinct package names')
const manifests = new Map<string, { path: string; private: boolean; bundle: boolean; runtime: string[] }>()
for (const path of globSync(['packages/*/*/package.json', 'apps/*/package.json', 'vendor/*/package.json'], { cwd: root }).map(path => path.replaceAll('\\', '/')).sort()) {
const manifest = JSON.parse(readFileSync(resolve(root, path), 'utf8')) as {
name: string
private?: boolean
dependencies?: Record<string, string>
optionalDependencies?: Record<string, string>
peerDependencies?: Record<string, string>
dsh?: { bundle?: { patch?: unknown } }
}
if (manifests.has(manifest.name)) throw new Error(`duplicate workspace package ${manifest.name}`)
const runtime = ['dependencies', 'optionalDependencies', 'peerDependencies'] as const
manifests.set(manifest.name, { path, private: manifest.private === true, bundle: manifest.dsh?.bundle?.patch !== undefined,
runtime: runtime.flatMap(section => Object.keys(manifest[section] ?? {})) })
}
const visited = new Set<string>()
const checkInstallation = (name: string): void => {
if (visited.has(name)) return
visited.add(name)
if (names.includes(name)) throw new Error(`${name}: on-demand providers must not be installed by the DSH distribution`)
for (const dependency of manifests.get(name)?.runtime ?? []) checkInstallation(dependency)
}
if (!manifests.has('@deepseek-ai/dsh')) throw new Error('Official catalog requires the DSH installation manifest')
checkInstallation('@deepseek-ai/dsh')
return names.map((packageName) => {
const entry = manifests.get(packageName)
if (entry === undefined || !entry.path.startsWith('packages/') || !packageName.startsWith('@deepseek-ai/dsh-') || entry.private || !entry.bundle) {
throw new Error(`${packageName}: Official catalog entries must be public DSH bundle packages`)
}
const parentURL = pathToFileURL(resolve(root, entry.path)).href
for (const language of SHIPPED_LOCALE_IDS) {
const file = resolvePluginResource(`${packageName}/locale/${language}.json`, parentURL)
const dictionary = JSON.parse(readFileSync(file, 'utf8')) as { meta?: { title?: unknown; description?: unknown } }
if (typeof dictionary.meta?.title !== 'string' || dictionary.meta.title.trim() === ''
|| typeof dictionary.meta.description !== 'string' || dictionary.meta.description.trim() === '') {
throw new Error(`${packageName}: Official metadata requires explicit ${language} title and description`)
}
}
const meta = readPluginMeta(packageName, parentURL)
if (meta?.error !== undefined) throw new Error(`${packageName}: ${meta.error}`)
if (meta?.icon === undefined || typeof meta.title !== 'object' || typeof meta.description !== 'object') {
throw new Error(`${packageName}: Official catalog entries require an icon and localized title and description`)
}
for (const value of [meta.title, meta.description]) {
for (const language of SHIPPED_LOCALE_IDS) {
if (typeof value[language] !== 'string' || value[language].trim() === '') {
throw new Error(`${packageName}: Official metadata requires ${language} text`)
}
}
}
return { packageName, meta: { title: meta.title, description: meta.description, icon: meta.icon } }
})
}
/**
* Render a source-plane catalog with no package imports or pinned runtime version.
* @param entries - Validated metadata in catalog order.
* @returns Deterministic TypeScript source for the official-bundles generated module.
*/
export function renderOfficialBundleCatalog(entries: readonly OfficialBundleCatalogEntry[]): string {
return '/** Generated offline Official bundle metadata. Run pnpm gen-official-bundle-catalog; do not edit. */\n\n'
+ "import type { OfficialBundleCatalogEntry } from './index.ts'\n\n"
+ '/** Official on-demand entries, independent of installed packages and registry availability. */\n'
+ 'export const OFFICIAL_ON_DEMAND_CATALOG: readonly OfficialBundleCatalogEntry[] = [\n'
+ entries.map(entry => ' {\n'
+ ` packageName: ${quote(entry.packageName)},\n`
+ ' meta: {\n'
+ ` title: ${localized(entry.meta.title)},\n`
+ ` description: ${localized(entry.meta.description)},\n`
+ ` icon: ${quote(entry.meta.icon)},\n`
+ ' },\n },\n').join('')
+ ']\n'
}
const printer = ts.createPrinter()
const sourceFile = ts.createSourceFile('catalog.ts', '', ts.ScriptTarget.Latest)
function quote(value: string): string {
return printer.printNode(ts.EmitHint.Expression, ts.factory.createStringLiteral(value, true), sourceFile)
}
function localized(value: LocalizedText): string {
if (typeof value === 'string') return quote(value)
return `{ ${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([language, text]) => `${quote(language)}: ${quote(text)}`).join(', ')} }`
}
/**
* Write changed metadata or freshness-check it against the owning package resources.
* @param root - Repository root containing source and metadata resources.
* @param check - Reject drift without changing the generated file.
*/
export function syncOfficialBundleCatalog(root: string, check: boolean): void {
const source = renderOfficialBundleCatalog(generateOfficialBundleCatalog(root))
const path = resolve(root, OUTPUT)
let current: string | undefined
try { current = readFileSync(path, 'utf8') }
catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error }
if (current === source) return
if (check) throw new Error(`${OUTPUT} is stale; run pnpm gen-official-bundle-catalog`)
writeFileSync(path, source)
}
if (process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
syncOfficialBundleCatalog(resolve(import.meta.dirname, '..'), process.argv.includes('--check'))
console.log('Official on-demand catalog matches package-owned metadata.')
}