Align marketplace categories with Codex taxonomy

Constraint: Keep one EAPIL marketplace while using official Codex category metadata and stable plugin IDs.

Rejected: One marketplace per category | Codex groups the UI by marketplace source, which would require users to add multiple markets and change install selectors.

Confidence: high

Scope-risk: moderate

Directive: Keep localized plugins in the same functional category and distinguish them with a language suffix such as -zh.

Tested: Marketplace validation, all manifest/category consistency checks, KeyInfo market tests, frontend lint and production build.
This commit is contained in:
KeyInfo Bot
2026-07-14 10:48:25 +08:00
parent 59c6b9f6cb
commit 93eeb27a5c
37 changed files with 647 additions and 557 deletions
+51 -6
View File
@@ -503,9 +503,34 @@ function Merge-Hashtable {
function Get-SourceCategory {
param([object]$Source)
if ($Source.PSObject.Properties.Name -contains "marketplace" -and $Source.marketplace -and $Source.marketplace.category) {
return $Source.marketplace.category
return ConvertTo-OfficialCategory $Source.marketplace.category
}
return $Source.category
return ConvertTo-OfficialCategory $Source.category
}
function ConvertTo-OfficialCategory {
param([string]$Category)
$aliases = @{
"文档处理" = "Productivity"
"工具" = "Productivity"
"翻译与本地化" = "Productivity"
"开发工具" = "Developer Tools"
"测试与质量" = "Developer Tools"
"MCP" = "Developer Tools"
"设计" = "Creativity"
"多媒体与生成" = "Creativity"
"数据分析" = "Data & Analytics"
"知识库与检索" = "Education & Research"
}
$official = @(
"Productivity", "Developer Tools", "Engineering", "Creativity",
"Data & Analytics", "Education & Research", "Communication", "Finance",
"Business & Operations", "Travel", "Security", "Other"
)
if ($official -contains $Category) { return $Category }
if ($aliases.ContainsKey($Category)) { return $aliases[$Category] }
if ([string]::IsNullOrWhiteSpace($Category)) { return "" }
return "Other"
}
function ConvertTo-YamlDoubleQuoted {
@@ -566,12 +591,15 @@ function Apply-LocalOverrides {
[object]$Source
)
$manifestPath = Join-Path $PluginDir ".codex-plugin\plugin.json"
$manifest = ConvertTo-Hashtable (Read-JsonFile $manifestPath)
if ($Source.PSObject.Properties.Name -contains "manifestOverrides" -and $Source.manifestOverrides) {
$manifestPath = Join-Path $PluginDir ".codex-plugin\plugin.json"
$manifest = ConvertTo-Hashtable (Read-JsonFile $manifestPath)
$manifest = Merge-Hashtable -Base $manifest -Override $Source.manifestOverrides
Write-JsonFile -Path $manifestPath -Value $manifest
}
if ($manifest.interface -and $manifest.interface.category) {
$manifest.interface.category = ConvertTo-OfficialCategory ([string]$manifest.interface.category)
}
Write-JsonFile -Path $manifestPath -Value $manifest
if ($Source.PSObject.Properties.Name -contains "skillDescriptions" -and $Source.skillDescriptions) {
$skillsRoot = Join-Path $PluginDir "skills"
@@ -923,6 +951,7 @@ function Update-Marketplace {
$plugins = @()
foreach ($plugin in $marketplace.plugins) {
if ($sourceNames -notcontains $plugin.name) {
$plugin.category = ConvertTo-OfficialCategory ([string]$plugin.category)
$plugins += $plugin
}
}
@@ -940,7 +969,23 @@ function Update-Marketplace {
category = (Get-SourceCategory $source)
}
}
$marketplace.plugins = $plugins
$categoryOrder = @{
"Productivity" = 0
"Developer Tools" = 1
"Engineering" = 2
"Creativity" = 3
"Data & Analytics" = 4
"Education & Research" = 5
"Communication" = 6
"Finance" = 7
"Business & Operations" = 8
"Travel" = 9
"Security" = 10
"Other" = 11
}
$marketplace.plugins = @($plugins | Sort-Object `
@{ Expression = { if ($categoryOrder.ContainsKey([string]$_.category)) { $categoryOrder[[string]$_.category] } else { 99 } } }, `
@{ Expression = { [string]$_.name } })
Write-JsonFile -Path $MarketplacePath -Value $marketplace
}