fix(converters): preserve Codex agent sidecar scripts (#563)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import fs, { type Dirent } from "fs"
|
||||
import path from "path"
|
||||
import { formatFrontmatter } from "../utils/frontmatter"
|
||||
import { type ClaudeAgent, type ClaudeCommand, type ClaudePlugin, type ClaudeSkill, filterSkillsByPlatform } from "../types/claude"
|
||||
import type { CodexBundle, CodexGeneratedSkill } from "../types/codex"
|
||||
import type { CodexBundle, CodexGeneratedSkill, CodexGeneratedSkillSidecarDir } from "../types/codex"
|
||||
import type { ClaudeToOpenCodeOptions } from "./claude-to-opencode"
|
||||
import {
|
||||
normalizeCodexName,
|
||||
@@ -122,7 +124,7 @@ function convertAgent(
|
||||
}
|
||||
|
||||
const content = formatFrontmatter(frontmatter, body)
|
||||
return { name, content }
|
||||
return { name, content, sidecarDirs: collectReferencedSidecarDirs(agent) }
|
||||
}
|
||||
|
||||
function convertCommandSkill(
|
||||
@@ -215,3 +217,22 @@ function uniqueName(base: string, used: Set<string>): string {
|
||||
used.add(name)
|
||||
return name
|
||||
}
|
||||
|
||||
function collectReferencedSidecarDirs(agent: ClaudeAgent): CodexGeneratedSkillSidecarDir[] {
|
||||
const sourceDir = path.dirname(agent.sourcePath)
|
||||
let entries: Dirent[]
|
||||
|
||||
try {
|
||||
entries = fs.readdirSync(sourceDir, { withFileTypes: true })
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
return entries
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.filter((entry) => agent.body.includes(`${entry.name}/`) || agent.body.includes(`\`${entry.name}\``))
|
||||
.map((entry) => ({
|
||||
sourceDir: path.join(sourceDir, entry.name),
|
||||
targetName: entry.name,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { backupFile, copySkillDir, ensureDir, sanitizePathName, writeText, writeTextSecure } from "../utils/files"
|
||||
import { backupFile, copyDir, copySkillDir, ensureDir, sanitizePathName, writeText, writeTextSecure } from "../utils/files"
|
||||
import type { CodexBundle } from "../types/codex"
|
||||
import type { ClaudeMcpServer } from "../types/claude"
|
||||
import { transformContentForCodex } from "../utils/codex-content"
|
||||
@@ -39,7 +39,11 @@ export async function writeCodexBundle(outputRoot: string, bundle: CodexBundle):
|
||||
if (bundle.generatedSkills.length > 0) {
|
||||
const skillsRoot = path.join(codexRoot, "skills")
|
||||
for (const skill of bundle.generatedSkills) {
|
||||
await writeText(path.join(skillsRoot, sanitizePathName(skill.name), "SKILL.md"), skill.content + "\n")
|
||||
const skillDir = path.join(skillsRoot, sanitizePathName(skill.name))
|
||||
await writeText(path.join(skillDir, "SKILL.md"), skill.content + "\n")
|
||||
for (const sidecar of skill.sidecarDirs ?? []) {
|
||||
await copyDir(sidecar.sourceDir, path.join(skillDir, sidecar.targetName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ export type CodexSkillDir = {
|
||||
export type CodexGeneratedSkill = {
|
||||
name: string
|
||||
content: string
|
||||
sidecarDirs?: CodexGeneratedSkillSidecarDir[]
|
||||
}
|
||||
|
||||
export type CodexGeneratedSkillSidecarDir = {
|
||||
sourceDir: string
|
||||
targetName: string
|
||||
}
|
||||
|
||||
export type CodexBundle = {
|
||||
|
||||
@@ -41,7 +41,7 @@ export function transformContentForCodex(
|
||||
: `${prefix}Use the $${skillName} skill`
|
||||
})
|
||||
|
||||
const slashCommandPattern = /(?<![:\w])\/([a-z][a-z0-9_:-]*?)(?=[\s,."')\]}`]|$)/gi
|
||||
const slashCommandPattern = /(?<![:\w>}\]\)])\/([a-z][a-z0-9_:-]*?)(?=[\s,."')\]}`]|$)/gi
|
||||
result = result.replace(slashCommandPattern, (match, commandName: string) => {
|
||||
if (commandName.includes("/")) return match
|
||||
if (["dev", "tmp", "etc", "usr", "var", "bin", "home"].includes(commandName)) return match
|
||||
|
||||
Reference in New Issue
Block a user