mirror of
https://github.com/supabase/agent-skills.git
synced 2026-03-27 10:09:26 +08:00
improve postgres best practices and add evals
This commit is contained in:
102
packages/skills-build/src/profiles.ts
Normal file
102
packages/skills-build/src/profiles.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type { Profile, Rule } from "./types.js";
|
||||
|
||||
/**
|
||||
* Load a profile from the profiles directory
|
||||
*/
|
||||
export function loadProfile(profilesDir: string, profileName: string): Profile | null {
|
||||
const profileFile = join(profilesDir, `${profileName}.json`);
|
||||
if (!existsSync(profileFile)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(readFileSync(profileFile, "utf-8"));
|
||||
} catch (error) {
|
||||
console.error(`Error loading profile ${profileName}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available profiles in the profiles directory
|
||||
*/
|
||||
export function listProfiles(profilesDir: string): string[] {
|
||||
if (!existsSync(profilesDir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return readdirSync(profilesDir)
|
||||
.filter((f) => f.endsWith(".json"))
|
||||
.map((f) => f.replace(".json", ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare version strings (e.g., "9.5", "11", "14.2")
|
||||
* Returns: negative if a < b, 0 if equal, positive if a > b
|
||||
*/
|
||||
function compareVersions(a: string, b: string): number {
|
||||
const partsA = a.split(".").map(Number);
|
||||
const partsB = b.split(".").map(Number);
|
||||
|
||||
const maxLen = Math.max(partsA.length, partsB.length);
|
||||
for (let i = 0; i < maxLen; i++) {
|
||||
const numA = partsA[i] || 0;
|
||||
const numB = partsB[i] || 0;
|
||||
if (numA !== numB) {
|
||||
return numA - numB;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a rule is compatible with a profile
|
||||
*/
|
||||
export function isRuleCompatibleWithProfile(rule: Rule, profile: Profile): boolean {
|
||||
// Check version requirement
|
||||
if (rule.minVersion) {
|
||||
if (compareVersions(rule.minVersion, profile.minVersion) > 0) {
|
||||
// Rule requires a higher version than profile supports
|
||||
return false;
|
||||
}
|
||||
if (profile.maxVersion && compareVersions(rule.minVersion, profile.maxVersion) > 0) {
|
||||
// Rule requires a version higher than profile's max
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check extension requirements
|
||||
if (rule.extensions && rule.extensions.length > 0) {
|
||||
const allExtensions = [
|
||||
...(profile.extensions.available || []),
|
||||
...(profile.extensions.installable || []),
|
||||
];
|
||||
|
||||
for (const ext of rule.extensions) {
|
||||
if (profile.extensions.unavailable?.includes(ext)) {
|
||||
// Extension is explicitly unavailable in this profile
|
||||
return false;
|
||||
}
|
||||
if (!allExtensions.includes(ext)) {
|
||||
// Extension is not available or installable
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if rule is explicitly excluded
|
||||
if (profile.excludeRules?.includes(rule.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter rules based on profile constraints
|
||||
*/
|
||||
export function filterRulesForProfile(rules: Rule[], profile: Profile): Rule[] {
|
||||
return rules.filter((rule) => isRuleCompatibleWithProfile(rule, profile));
|
||||
}
|
||||
Reference in New Issue
Block a user