feat(launch): force-load fleet-critical Pi skills + reconcile skill docs (#555)
This commit was merged in pull request #555.
This commit is contained in:
@@ -455,22 +455,78 @@ function normalizePiSkillMode(env: NodeJS.ProcessEnv): PiSkillMode {
|
||||
return 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fleet-critical Pi skills that are force-loaded on every Pi launch regardless
|
||||
* of MOSAIC_PI_SKILL_MODE. They cover the highest-frequency cross-agent and
|
||||
* git-provider operations where Pi workers historically improvised raw CLIs
|
||||
* (raw `tmux send-keys`, raw `tea`/`gh`/`glab`) instead of the maintained
|
||||
* `~/.config/mosaic/tools/` wrappers.
|
||||
*
|
||||
* An explicit `--skill <dir>` overrides `--no-skills` for that path, so forcing
|
||||
* a single targeted skill surfaces the must-use toolkit without loading the full
|
||||
* ~100-skill catalog (context bloat). Missing skills are skipped silently, so
|
||||
* this is a no-op until the named skill is synced into ~/.config/mosaic/skills/.
|
||||
*
|
||||
* Override with MOSAIC_PI_FORCE_SKILLS (colon-separated skill dir names; set to
|
||||
* an empty string to disable force-loading entirely).
|
||||
*/
|
||||
const DEFAULT_PI_FORCE_SKILLS = ['mosaic-tools'];
|
||||
|
||||
export function piForceSkillNames(env: NodeJS.ProcessEnv): string[] {
|
||||
const override = env['MOSAIC_PI_FORCE_SKILLS'];
|
||||
if (override === undefined) return DEFAULT_PI_FORCE_SKILLS;
|
||||
return override
|
||||
.split(':')
|
||||
.map((name) => name.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function forcedPiSkillArgs(env: NodeJS.ProcessEnv = process.env): string[] {
|
||||
const args: string[] = [];
|
||||
for (const name of piForceSkillNames(env)) {
|
||||
const skillDir = join(MOSAIC_HOME, 'skills', name);
|
||||
if (existsSync(join(skillDir, 'SKILL.md'))) {
|
||||
args.push('--skill', skillDir);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/** Concatenate `--skill <dir>` arg groups, dropping any directory already seen. */
|
||||
function mergeSkillArgs(...groups: string[][]): string[] {
|
||||
const seen = new Set<string>();
|
||||
const out: string[] = [];
|
||||
for (const group of groups) {
|
||||
for (let i = 0; i < group.length; i += 2) {
|
||||
const dir = group[i + 1];
|
||||
if (group[i] !== '--skill' || dir === undefined || seen.has(dir)) continue;
|
||||
seen.add(dir);
|
||||
out.push('--skill', dir);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function buildPiSkillArgs(
|
||||
_runtimeArgs: string[],
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
discoveredSkillArgs: string[] = discoverPiSkills(),
|
||||
forcedSkillArgs: string[] = forcedPiSkillArgs(env),
|
||||
): string[] {
|
||||
const mode = normalizePiSkillMode(env);
|
||||
|
||||
if (mode === 'discover') {
|
||||
return [];
|
||||
// Native Pi discovery handles the rest; still force-load the fleet skills.
|
||||
return [...forcedSkillArgs];
|
||||
}
|
||||
|
||||
if (mode === 'all') {
|
||||
return ['--no-skills', ...discoveredSkillArgs];
|
||||
// 'all' links the full catalog; merge in the forced set so fleet-critical
|
||||
// skills are guaranteed present even if they live only under skills-local/.
|
||||
return ['--no-skills', ...mergeSkillArgs(discoveredSkillArgs, forcedSkillArgs)];
|
||||
}
|
||||
|
||||
return ['--no-skills'];
|
||||
return ['--no-skills', ...forcedSkillArgs];
|
||||
}
|
||||
|
||||
function discoverPiExtension(): string[] {
|
||||
|
||||
Reference in New Issue
Block a user