Files
pbakaus_impeccable/scripts/lib/openai-plugin.js
T
Paul BakausandClaude Fable 5 90f9eeb99b Split service layer into private impeccable-site repo
The public repo keeps the OSS promise surface: skill, CLI, extension,
tests, and the provider build. The site, labs, concept/composition
catalogs, image pipeline, Cloudflare functions, and authoring guide move
to pbakaus/impeccable-site.

concept-seed tests run against a synthetic fixture catalog; the plugin
icon and skill categories moved in-repo; build validation narrows to
README prose and non-site counts; release notes read from a sibling
impeccable-site checkout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:41:53 -07:00

62 lines
2.1 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { buildCodexPluginManifest } from './codex-plugin.js';
import { buildCodexPluginHooksManifest } from './transformers/hooks.js';
function requirePath(absPath, label) {
if (!fs.existsSync(absPath)) {
throw new Error(`Cannot build OpenAI plugin: missing ${label}: ${absPath}`);
}
}
function writeJson(absPath, value) {
fs.mkdirSync(path.dirname(absPath), { recursive: true });
fs.writeFileSync(absPath, `${JSON.stringify(value, null, 2)}\n`);
}
/**
* Stage the public OpenAI plugin from the Codex-transformed skill payload.
*
* The tracked ./plugin subtree is a Claude Code marketplace artifact. Reusing
* its shared skills/ directory here silently ships Claude paths and slash
* commands inside a Codex plugin. Keep this stage independent so each plugin
* receives the provider transform it was built for.
*/
export function stageOpenAIPlugin(rootDir, distDir) {
const rootManifestPath = path.join(rootDir, '.claude-plugin', 'plugin.json');
const codexSkillSrc = path.join(distDir, 'codex', '.codex', 'skills', 'impeccable');
const iconSrc = path.join(rootDir, 'scripts', 'lib', 'assets', 'plugin-icon.png');
requirePath(rootManifestPath, 'root plugin manifest');
requirePath(codexSkillSrc, 'Codex skill payload');
requirePath(iconSrc, 'plugin icon');
const pluginRoot = path.join(distDir, 'openai', 'impeccable');
fs.rmSync(pluginRoot, { recursive: true, force: true });
fs.mkdirSync(pluginRoot, { recursive: true });
const rootManifest = JSON.parse(fs.readFileSync(rootManifestPath, 'utf8'));
writeJson(
path.join(pluginRoot, '.codex-plugin', 'plugin.json'),
buildCodexPluginManifest(rootManifest),
);
fs.mkdirSync(path.join(pluginRoot, 'assets'), { recursive: true });
fs.copyFileSync(iconSrc, path.join(pluginRoot, 'assets', 'icon.png'));
fs.mkdirSync(path.join(pluginRoot, 'skills'), { recursive: true });
fs.cpSync(
codexSkillSrc,
path.join(pluginRoot, 'skills', 'impeccable'),
{ recursive: true },
);
writeJson(
path.join(pluginRoot, 'hooks', 'hooks.json'),
buildCodexPluginHooksManifest(),
);
return pluginRoot;
}