Publish Next.js Agent Skills
Constraint: Upstream next-skills is a multi-skill collection under skills/*/SKILL.md.\nRejected: Copy upstream README badge/install docs | marketplace README stays install-focused and plugin content avoids nonessential images.\nConfidence: high\nScope-risk: moderate\nDirective: Use skill-collection with skillsPath for repositories organized as direct child skill directories.\nTested: python scripts/validate_marketplace.py; python /Users/eapil/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py plugins/codex/plugins/next-skills; temp CODEX_HOME codex plugin marketplace add/list/add plus debug prompt-input.\nNot-tested: scripts/sync_external_plugins.ps1 execution because pwsh/powershell is not installed.
This commit is contained in:
@@ -702,6 +702,117 @@ function Sync-ClaudeSkill {
|
||||
Write-Provenance -PluginDir $pluginDir -Source $Source -Commit $Commit -SyncedAt $SyncedAt -SourcePath $Source.skillPath
|
||||
}
|
||||
|
||||
function Sync-SkillCollection {
|
||||
param(
|
||||
[object]$Source,
|
||||
[string]$ClonePath,
|
||||
[string]$Commit,
|
||||
[string]$PluginsRoot,
|
||||
[string]$RepoRoot,
|
||||
[string]$SyncedAt
|
||||
)
|
||||
$skillsPath = "skills"
|
||||
if ($Source.PSObject.Properties.Name -contains "skillsPath" -and $Source.skillsPath) {
|
||||
$skillsPath = $Source.skillsPath
|
||||
} elseif ($Source.PSObject.Properties.Name -contains "skillPath" -and $Source.skillPath) {
|
||||
$skillsPath = $Source.skillPath
|
||||
}
|
||||
if ($skillsPath -eq ".") {
|
||||
$sourceSkillsRoot = $ClonePath
|
||||
} else {
|
||||
$sourceSkillsRoot = Join-Path $ClonePath $skillsPath
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $sourceSkillsRoot)) {
|
||||
throw "skill-collection adapter requires a skills directory: $sourceSkillsRoot"
|
||||
}
|
||||
$skillDirs = @(Get-ChildItem -LiteralPath $sourceSkillsRoot -Directory | Where-Object {
|
||||
Test-Path -LiteralPath (Join-Path $_.FullName "SKILL.md")
|
||||
} | Sort-Object Name)
|
||||
if ($skillDirs.Count -eq 0) {
|
||||
throw "skill-collection adapter found no child SKILL.md files: $sourceSkillsRoot"
|
||||
}
|
||||
|
||||
$pluginName = $Source.pluginName
|
||||
$pluginDir = Join-Path $PluginsRoot $pluginName
|
||||
Remove-PathIfExists -Path $pluginDir -Within $RepoRoot
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $pluginDir ".codex-plugin") | Out-Null
|
||||
$skillsRoot = Join-Path $pluginDir "skills"
|
||||
New-Item -ItemType Directory -Force -Path $skillsRoot | Out-Null
|
||||
foreach ($skillDir in $skillDirs) {
|
||||
Copy-DirectoryFiltered -Source $skillDir.FullName -Destination (Join-Path $skillsRoot $skillDir.Name) -Within $RepoRoot
|
||||
}
|
||||
|
||||
$includeRootFiles = @()
|
||||
if ($Source.PSObject.Properties.Name -contains "includeRootFiles" -and $Source.includeRootFiles) {
|
||||
$includeRootFiles = @($Source.includeRootFiles)
|
||||
}
|
||||
foreach ($rootFile in $includeRootFiles) {
|
||||
Copy-PathIfExists -Source (Join-Path $ClonePath $rootFile) -Destination (Join-Path $pluginDir $rootFile) -Within $RepoRoot
|
||||
}
|
||||
Remove-ConfiguredExcludes -Root $pluginDir -ExcludePaths $Source.excludePaths -Within $RepoRoot
|
||||
Remove-ReadmeImageReferences -Root $pluginDir -ImagePathPrefixes $Source.readmeImageExcludes
|
||||
Remove-ReadmeLines -Root $pluginDir -LineExcludes $Source.readmeLineExcludes
|
||||
Compress-ImagesToWebp -Root $pluginDir -CompressPaths $Source.webpCompressPaths
|
||||
|
||||
$metadata = @{}
|
||||
if ($Source.PSObject.Properties.Name -contains "metadata" -and $Source.metadata) {
|
||||
$metadata = ConvertTo-Hashtable $Source.metadata
|
||||
}
|
||||
$description = $metadata.description
|
||||
if (-not $description) {
|
||||
$description = "$pluginName skill collection imported from $($Source.repo)."
|
||||
}
|
||||
$displayName = $metadata.displayName
|
||||
if (-not $displayName) {
|
||||
$displayName = $pluginName
|
||||
}
|
||||
$version = $metadata.version
|
||||
if (-not $version) {
|
||||
$version = "0.1.0"
|
||||
}
|
||||
$homepage = $metadata.homepage
|
||||
if (-not $homepage) {
|
||||
$homepage = $Source.repo -replace "\.git$", ""
|
||||
}
|
||||
$repository = $metadata.repository
|
||||
if (-not $repository) {
|
||||
$repository = $Source.repo -replace "\.git$", ""
|
||||
}
|
||||
$license = $metadata.license
|
||||
if (-not $license) {
|
||||
$license = "UNKNOWN"
|
||||
}
|
||||
|
||||
$manifest = [ordered]@{
|
||||
name = $pluginName
|
||||
version = $version
|
||||
description = $description
|
||||
author = New-AuthorObject $metadata.author
|
||||
homepage = $homepage
|
||||
repository = $repository
|
||||
license = $license
|
||||
keywords = @($metadata.keywords)
|
||||
skills = "./skills/"
|
||||
interface = [ordered]@{
|
||||
displayName = $displayName
|
||||
shortDescription = $description
|
||||
longDescription = $description
|
||||
developerName = (New-AuthorObject $metadata.author).name
|
||||
category = (Get-SourceCategory $Source)
|
||||
capabilities = @("Read", "Write")
|
||||
defaultPrompt = @("Use $displayName for this task.")
|
||||
websiteURL = $homepage
|
||||
privacyPolicyURL = $repository
|
||||
termsOfServiceURL = $repository
|
||||
brandColor = $(if ($Source.PSObject.Properties.Name -contains "brandColor" -and $Source.brandColor) { $Source.brandColor } else { "#2563EB" })
|
||||
screenshots = @()
|
||||
}
|
||||
}
|
||||
Write-JsonFile -Path (Join-Path $pluginDir ".codex-plugin\plugin.json") -Value $manifest
|
||||
Apply-LocalOverrides -PluginDir $pluginDir -Source $Source
|
||||
Write-Provenance -PluginDir $pluginDir -Source $Source -Commit $Commit -SyncedAt $SyncedAt -SourcePath $skillsPath
|
||||
}
|
||||
|
||||
function Update-Marketplace {
|
||||
param(
|
||||
[string]$MarketplacePath,
|
||||
@@ -779,6 +890,9 @@ foreach ($source in $sources) {
|
||||
"claude-skill" {
|
||||
Sync-ClaudeSkill -Source $source -ClonePath $clone.path -Commit $clone.commit -PluginsRoot $pluginsRoot -RepoRoot $repoRoot -SyncedAt $sourceSyncedAt
|
||||
}
|
||||
"skill-collection" {
|
||||
Sync-SkillCollection -Source $source -ClonePath $clone.path -Commit $clone.commit -PluginsRoot $pluginsRoot -RepoRoot $repoRoot -SyncedAt $sourceSyncedAt
|
||||
}
|
||||
default {
|
||||
throw "Unknown adapter '$($source.adapter)' for $($source.id)."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user