build: native subagent pipeline + Codex-only asset producer

Adds an agent cross-compile pipeline alongside the existing skill
pipeline. Sources live at skill/agents/*.md; providers that declare
agentFormat (codex-toml, claude-md) emit native subagent files. An
optional providers: <list> field on an agent gates which harnesses
get a copy; default (no field) ships everywhere.

The impeccable-asset-producer agent is opt-in to Codex only. It's
useful for Codex's native image generation path and is untested
elsewhere; Claude has no native image gen anyway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-05-12 22:46:55 -07:00
co-authored by Claude Opus 4.7
parent b03d7515c8
commit fd3eed9f3b
10 changed files with 421 additions and 7 deletions
+35 -1
View File
@@ -203,6 +203,39 @@ export function readSourceFiles(rootDir) {
}
}
const agents = [];
const agentsDir = path.join(skillDir, 'agents');
if (fs.existsSync(agentsDir)) {
const agentFiles = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
for (const agentFile of agentFiles) {
const agentPath = path.join(agentsDir, agentFile);
const agentContent = fs.readFileSync(agentPath, 'utf-8');
const { frontmatter: agentFrontmatter, body: agentBody } = parseFrontmatter(agentContent);
const name = agentFrontmatter.name || path.basename(agentFile, '.md');
const providersRaw = agentFrontmatter.providers;
let providers = null;
if (Array.isArray(providersRaw)) {
providers = providersRaw.map(p => String(p).trim()).filter(Boolean);
} else if (typeof providersRaw === 'string' && providersRaw.trim()) {
providers = providersRaw.split(',').map(p => p.trim()).filter(Boolean);
}
agents.push({
name,
codexName: agentFrontmatter['codex-name'] || name.replace(/-/g, '_'),
claudeName: agentFrontmatter['claude-name'] || name,
description: agentFrontmatter.description || '',
tools: agentFrontmatter.tools || '',
model: agentFrontmatter.model || '',
effort: agentFrontmatter.effort || '',
maxTurns: agentFrontmatter['max-turns'] ? Number(agentFrontmatter['max-turns']) : '',
nicknameCandidates: agentFrontmatter['nickname-candidates'] || [],
providers,
body: agentBody,
filePath: agentPath,
});
}
}
skills.push({
name: frontmatter.name || 'impeccable',
description: frontmatter.description || '',
@@ -216,7 +249,8 @@ export function readSourceFiles(rootDir) {
body,
filePath: skillMdPath,
references,
scripts
scripts,
agents
});
return { skills };