Files
santifer--career-ops/scaffolder/bin/skill-entrypoints.mjs
T
wehub-resource-sync d083df1fdb
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 2s
Web CI / web typecheck + build (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
CodeQL Analysis / Analyze (go) (push) Failing after 16s
chore: import upstream snapshot with attribution
2026-07-13 12:02:43 +08:00

116 lines
3.1 KiB
JavaScript

// Shared CLI skill entrypoint bootstrap — used by npx init and update-system.
// Ensures every supported CLI gets .*/skills/career-ops/SKILL.md even when the
// cloned release predates a CLI (e.g. Grok on v1.13.0). Materializes pointer
// files to canonical content on filesystems without symlink support.
import { readFileSync, writeFileSync, existsSync, mkdirSync, lstatSync } from 'node:fs';
import { join, dirname } from 'node:path';
export const CANONICAL_SKILL_PATH = '.agents/skills/career-ops/SKILL.md';
export const SKILL_ENTRYPOINTS = [
{
path: '.claude/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md',
},
{
path: '.opencode/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md',
},
{
path: '.qwen/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md',
},
{
path: '.antigravitycli/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md',
},
{
path: '.grok/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md',
},
];
function repoPath(root, path) {
return join(root, ...path.split('/'));
}
function readCanonical(root) {
const canonicalPath = repoPath(root, CANONICAL_SKILL_PATH);
if (!existsSync(canonicalPath)) return null;
try {
return readFileSync(canonicalPath, 'utf-8');
} catch {
return null;
}
}
export function materializeSkillEntrypoints(root) {
const canonicalContent = readCanonical(root);
if (canonicalContent === null) return [];
const materialized = [];
for (const entry of SKILL_ENTRYPOINTS) {
const entryPath = repoPath(root, entry.path);
if (!existsSync(entryPath)) continue;
let stat = null;
try {
stat = lstatSync(entryPath);
} catch {
continue;
}
if (stat.isSymbolicLink()) continue;
if (!stat.isFile()) continue;
try {
const content = readFileSync(entryPath, 'utf-8').trim();
if (content !== entry.pointer) continue;
writeFileSync(entryPath, canonicalContent);
} catch {
continue;
}
materialized.push(entry.path);
}
return materialized;
}
export function ensureSkillEntrypoints(root) {
const canonicalContent = readCanonical(root);
if (canonicalContent === null) return [];
const touched = [];
for (const entry of SKILL_ENTRYPOINTS) {
const entryPath = repoPath(root, entry.path);
if (!existsSync(entryPath)) {
try {
mkdirSync(dirname(entryPath), { recursive: true });
writeFileSync(entryPath, entry.pointer);
touched.push(entry.path);
} catch {
continue;
}
}
let stat = null;
try {
stat = lstatSync(entryPath);
} catch {
continue;
}
if (stat.isSymbolicLink()) continue;
if (!stat.isFile()) continue;
try {
const content = readFileSync(entryPath, 'utf-8').trim();
if (content !== entry.pointer) continue;
writeFileSync(entryPath, canonicalContent);
if (!touched.includes(entry.path)) touched.push(entry.path);
} catch {
continue;
}
}
return touched;
}