feat: sync shared skills contract and graph-first discipline
This commit is contained in:
@@ -15,7 +15,6 @@ export interface DatabaseEvent {
|
||||
| 'AGENT_UPDATED'
|
||||
| 'AGENT_DELEGATION_CREATED'
|
||||
| 'AGENT_DELEGATION_UPDATED'
|
||||
| 'GUIDE_UPDATED'
|
||||
| 'SKILL_UPDATED'
|
||||
| 'QUICK_ADD_COMPLETED'
|
||||
| 'QUICK_ADD_FAILED'
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
export {
|
||||
listSkills as listGuides,
|
||||
readSkill as readGuide,
|
||||
writeSkill as writeGuide,
|
||||
deleteSkill as deleteGuide,
|
||||
getUserSkillCount as getUserGuideCount,
|
||||
getSkillStats as getGuideStats,
|
||||
} from '@/services/skills/skillService';
|
||||
|
||||
export type {
|
||||
SkillMeta as GuideMeta,
|
||||
Skill as Guide,
|
||||
} from '@/services/skills/skillService';
|
||||
@@ -2,16 +2,9 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import matter from 'gray-matter';
|
||||
import type { Skill, SkillMeta } from '@/types/skills';
|
||||
|
||||
export interface SkillMeta {
|
||||
name: string;
|
||||
description: string;
|
||||
immutable: boolean;
|
||||
}
|
||||
|
||||
export interface Skill extends SkillMeta {
|
||||
content: string;
|
||||
}
|
||||
export type { Skill, SkillMeta } from '@/types/skills';
|
||||
|
||||
const SKILLS_DIR = path.join(
|
||||
os.homedir(),
|
||||
@@ -29,18 +22,6 @@ const BUNDLED_SKILLS_DIR = path.join(
|
||||
);
|
||||
const SEED_MIGRATION_FLAG = path.join(SKILLS_DIR, '.seed-migrated-2026-03-07-skills-overhaul');
|
||||
|
||||
const SEEDED_SKILL_IDS = new Set([
|
||||
'db-operations',
|
||||
'create-skill',
|
||||
'audit',
|
||||
'traverse',
|
||||
'onboarding',
|
||||
'persona',
|
||||
'calibration',
|
||||
'connect',
|
||||
'node-context-enrichment',
|
||||
]);
|
||||
|
||||
const DEPRECATED_SKILL_IDS = new Set([
|
||||
'start-here',
|
||||
'schema',
|
||||
@@ -58,6 +39,13 @@ const DEPRECATED_SKILL_IDS = new Set([
|
||||
'research',
|
||||
'survey',
|
||||
'traverse-graph',
|
||||
'audit',
|
||||
'calibration',
|
||||
'connect',
|
||||
'db-operations',
|
||||
'node-context-enrichment',
|
||||
'persona',
|
||||
'traverse',
|
||||
]);
|
||||
|
||||
function ensureSkillsDir(): void {
|
||||
@@ -85,6 +73,16 @@ function listMarkdownFiles(dir: string): string[] {
|
||||
return fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
|
||||
}
|
||||
|
||||
function getBundledSkillFiles(): Map<string, string> {
|
||||
const bundledById = new Map<string, string>();
|
||||
|
||||
for (const file of listMarkdownFiles(BUNDLED_SKILLS_DIR)) {
|
||||
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
|
||||
}
|
||||
|
||||
return bundledById;
|
||||
}
|
||||
|
||||
function migrateLegacyGuides(): void {
|
||||
const guideFiles = listMarkdownFiles(LEGACY_GUIDES_DIR);
|
||||
for (const file of guideFiles) {
|
||||
@@ -96,17 +94,9 @@ function migrateLegacyGuides(): void {
|
||||
}
|
||||
|
||||
function seedSkills(): void {
|
||||
const bundledFiles = listMarkdownFiles(BUNDLED_SKILLS_DIR);
|
||||
const bundledById = new Map<string, string>();
|
||||
|
||||
for (const file of bundledFiles) {
|
||||
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
|
||||
}
|
||||
|
||||
for (const skillId of SEEDED_SKILL_IDS) {
|
||||
const source = bundledById.get(skillId);
|
||||
if (!source) continue;
|
||||
const bundledById = getBundledSkillFiles();
|
||||
|
||||
for (const [skillId, source] of bundledById.entries()) {
|
||||
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
|
||||
if (!fs.existsSync(dest)) {
|
||||
fs.copyFileSync(source, dest);
|
||||
@@ -119,15 +109,9 @@ function migrateSeededBaseline(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const bundledFiles = listMarkdownFiles(BUNDLED_SKILLS_DIR);
|
||||
const bundledById = new Map<string, string>();
|
||||
for (const file of bundledFiles) {
|
||||
bundledById.set(normalizeSkillId(file), path.join(BUNDLED_SKILLS_DIR, file));
|
||||
}
|
||||
const bundledById = getBundledSkillFiles();
|
||||
|
||||
for (const skillId of SEEDED_SKILL_IDS) {
|
||||
const source = bundledById.get(skillId);
|
||||
if (!source) continue;
|
||||
for (const [skillId, source] of bundledById.entries()) {
|
||||
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
|
||||
fs.copyFileSync(source, dest);
|
||||
}
|
||||
@@ -148,7 +132,6 @@ function pruneDeprecatedSkills(): void {
|
||||
function resolveSkillFilename(name: string): string | null {
|
||||
const files = listMarkdownFiles(SKILLS_DIR);
|
||||
const normalizedInput = normalizeSkillId(name);
|
||||
|
||||
const directCandidates = [
|
||||
`${name}.md`,
|
||||
`${name.toLowerCase()}.md`,
|
||||
@@ -210,7 +193,9 @@ export function readSkill(name: string): Skill | null {
|
||||
init();
|
||||
|
||||
const filename = resolveSkillFilename(name);
|
||||
if (!filename) return null;
|
||||
if (!filename) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filepath = path.join(SKILLS_DIR, filename);
|
||||
const raw = fs.readFileSync(filepath, 'utf-8');
|
||||
@@ -261,25 +246,3 @@ export function getSkillStats(): { userSkills: number; maxUserSkills: number; sy
|
||||
systemSkills: 0,
|
||||
};
|
||||
}
|
||||
|
||||
// Compatibility aliases for legacy guide-first code paths.
|
||||
export type GuideMeta = SkillMeta;
|
||||
export type Guide = Skill;
|
||||
|
||||
export const listGuides = listSkills;
|
||||
export const readGuide = readSkill;
|
||||
export const writeGuide = writeSkill;
|
||||
export const deleteGuide = deleteSkill;
|
||||
|
||||
export function getUserGuideCount(): number {
|
||||
return getUserSkillCount();
|
||||
}
|
||||
|
||||
export function getGuideStats(): { userGuides: number; maxUserGuides: number; systemGuides: number } {
|
||||
const stats = getSkillStats();
|
||||
return {
|
||||
userGuides: stats.userSkills,
|
||||
maxUserGuides: stats.maxUserSkills,
|
||||
systemGuides: stats.systemSkills,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user