combine to /src/utils/profiles.js; add codex and claude code profiles

This commit is contained in:
Joe Danziger
2025-05-27 15:45:08 -04:00
parent 9681c9171c
commit 08ad455463
20 changed files with 587 additions and 253 deletions

View File

@@ -29,7 +29,7 @@ import {
convertAllRulesToProfileRules,
getRulesProfile
} from '../src/utils/rule-transformer.js';
import { runInteractiveRulesSetup } from '../src/utils/rules-setup.js';
import { runInteractiveRulesSetup } from '../src/utils/profiles.js';
import { execSync } from 'child_process';
const __filename = fileURLToPath(import.meta.url);

View File

@@ -75,7 +75,7 @@ import {
import {
wouldRemovalLeaveNoProfiles,
getInstalledProfiles
} from '../../src/utils/profile-detection.js';
} from '../../src/utils/profiles.js';
import { initializeProject } from '../init.js';
import {
@@ -102,7 +102,13 @@ import {
isValidProfile,
getRulesProfile
} from '../../src/utils/rule-transformer.js';
import { runInteractiveRulesSetup } from '../../src/utils/rules-setup.js';
import {
runInteractiveRulesSetup,
generateProfileSummary,
categorizeProfileResults,
generateProfileRemovalSummary,
categorizeRemovalResults
} from '../../src/utils/profiles.js';
/**
* Runs the interactive setup process for model configuration.
@@ -2701,7 +2707,7 @@ Examples:
for (const profile of selectedRulesProfiles) {
if (!isValidProfile(profile)) {
console.warn(
`Rules profile for "${profile}" not found. Valid profiles: ${RULE_PROFILES.join(', ')}. Skipping.`
`Rule profile for "${profile}" not found. Valid profiles: ${RULE_PROFILES.join(', ')}. Skipping.`
);
continue;
}
@@ -2713,18 +2719,15 @@ Examples:
if (typeof profileConfig.onAddRulesProfile === 'function') {
profileConfig.onAddRulesProfile(projectDir);
}
console.log(
chalk.green(
`Summary for ${profile}: ${addResult.success} rules added, ${addResult.failed} failed.`
)
);
console.log(chalk.green(generateProfileSummary(profile, addResult)));
}
return;
}
if (!profiles || profiles.length === 0) {
console.error(
'Please specify at least one rules profile (e.g., windsurf, roo).'
'Please specify at least one rule profile (e.g., windsurf, roo).'
);
process.exit(1);
}
@@ -2760,7 +2763,7 @@ Examples:
for (const profile of expandedProfiles) {
if (!isValidProfile(profile)) {
console.warn(
`Rules profile for "${profile}" not found. Valid profiles: ${RULE_PROFILES.join(', ')}. Skipping.`
`Rule profile for "${profile}" not found. Valid profiles: ${RULE_PROFILES.join(', ')}. Skipping.`
);
continue;
}
@@ -2786,16 +2789,14 @@ Examples:
failed: addResult.failed
});
console.log(
chalk.green(
`Summary for ${profile}: ${addResult.success} rules added, ${addResult.failed} failed.`
)
);
console.log(chalk.green(generateProfileSummary(profile, addResult)));
} else if (action === RULES_ACTIONS.REMOVE) {
console.log(chalk.blue(`Removing rules for profile: ${profile}...`));
const result = removeProfileRules(projectDir, profileConfig);
removalResults.push(result);
console.log(chalk.blue(`Completed removal for profile: ${profile}`));
console.log(
chalk.green(generateProfileRemovalSummary(profile, result))
);
} else {
console.error(
`Unknown action. Use "${RULES_ACTIONS.ADD}" or "${RULES_ACTIONS.REMOVE}".`
@@ -2806,67 +2807,91 @@ Examples:
// Print summary for additions
if (action === RULES_ACTIONS.ADD && addResults.length > 0) {
const totalSuccess = addResults.reduce((sum, r) => sum + r.success, 0);
const totalFailed = addResults.reduce((sum, r) => sum + r.failed, 0);
const successfulProfiles = addResults
.filter((r) => r.success > 0)
.map((r) => r.profileName);
const {
allSuccessfulProfiles,
totalSuccess,
totalFailed,
simpleProfiles
} = categorizeProfileResults(addResults);
if (successfulProfiles.length > 0) {
if (allSuccessfulProfiles.length > 0) {
console.log(
chalk.green(
`\nSuccessfully added rules for: ${successfulProfiles.join(', ')}`
)
);
console.log(
chalk.green(
`Total: ${totalSuccess} rules added, ${totalFailed} failed.`
`\nSuccessfully added rules for: ${allSuccessfulProfiles.join(', ')}`
)
);
// Create a more descriptive summary
if (totalSuccess > 0 && simpleProfiles.length > 0) {
console.log(
chalk.green(
`Total: ${totalSuccess} rules added, ${totalFailed} failed, ${simpleProfiles.length} integration guide(s) copied.`
)
);
} else if (totalSuccess > 0) {
console.log(
chalk.green(
`Total: ${totalSuccess} rules added, ${totalFailed} failed.`
)
);
} else if (simpleProfiles.length > 0) {
console.log(
chalk.green(
`Total: ${simpleProfiles.length} integration guide(s) copied.`
)
);
}
}
}
// Print summary for removals
if (action === RULES_ACTIONS.REMOVE) {
const successes = removalResults
.filter((r) => r.success)
.map((r) => r.profileName);
const skipped = removalResults
.filter((r) => r.skipped)
.map((r) => r.profileName);
const errors = removalResults.filter(
(r) => r.error && !r.success && !r.skipped
);
const withNotices = removalResults.filter((r) => r.notice);
if (action === RULES_ACTIONS.REMOVE && removalResults.length > 0) {
const {
successfulRemovals,
skippedRemovals,
failedRemovals,
removalsWithNotices
} = categorizeRemovalResults(removalResults);
if (successes.length > 0) {
if (successfulRemovals.length > 0) {
console.log(
chalk.green(
`Successfully removed Task Master rules: ${successes.join(', ')}`
`\nSuccessfully removed rules for: ${successfulRemovals.join(', ')}`
)
);
}
if (skipped.length > 0) {
if (skippedRemovals.length > 0) {
console.log(
chalk.yellow(
`Skipped (default or protected): ${skipped.join(', ')}`
`Skipped (default or protected): ${skippedRemovals.join(', ')}`
)
);
}
if (errors.length > 0) {
errors.forEach((r) => {
console.log(
chalk.red(`Error removing ${r.profileName}: ${r.error}`)
);
if (failedRemovals.length > 0) {
console.log(chalk.red('\nErrors occurred:'));
failedRemovals.forEach((r) => {
console.log(chalk.red(` ${r.profileName}: ${r.error}`));
});
}
// Display notices about preserved files/configurations
if (withNotices.length > 0) {
if (removalsWithNotices.length > 0) {
console.log(chalk.cyan('\nNotices:'));
withNotices.forEach((r) => {
removalsWithNotices.forEach((r) => {
console.log(chalk.cyan(` ${r.profileName}: ${r.notice}`));
});
}
// Overall summary
const totalProcessed = removalResults.length;
const totalSuccessful = successfulRemovals.length;
const totalSkipped = skippedRemovals.length;
const totalFailed = failedRemovals.length;
console.log(
chalk.blue(
`\nTotal: ${totalProcessed} profile(s) processed - ${totalSuccessful} removed, ${totalSkipped} skipped, ${totalFailed} failed.`
)
);
}
});

View File

@@ -0,0 +1,62 @@
// Claude Code profile for rule-transformer
import path from 'path';
import fs from 'fs';
import { isSilentMode, log } from '../modules/utils.js';
// Lifecycle functions for Claude Code profile
function onAddRulesProfile(targetDir) {
const sourceFile = path.join(process.cwd(), 'assets', 'AGENTS.md');
const destFile = path.join(targetDir, 'CLAUDE.md');
if (fs.existsSync(sourceFile)) {
try {
fs.copyFileSync(sourceFile, destFile);
log('debug', `[Claude] Copied AGENTS.md to ${destFile}`);
} catch (err) {
log('debug', `[Claude] Failed to copy AGENTS.md: ${err.message}`);
}
} else {
log('debug', `[Claude] AGENTS.md not found at ${sourceFile}`);
}
}
function onRemoveRulesProfile(targetDir) {
log('debug', `[Claude] onRemoveRulesProfile called for ${targetDir}`);
const claudeFile = path.join(targetDir, 'CLAUDE.md');
if (fs.existsSync(claudeFile)) {
try {
fs.rmSync(claudeFile, { force: true });
log('debug', `[Claude] Removed CLAUDE.md from ${targetDir}`);
} catch (err) {
log('debug', `[Claude] Failed to remove CLAUDE.md: ${err.message}`);
}
}
log('debug', `[Claude] onRemoveRulesProfile completed for ${targetDir}`);
}
function onPostConvertRulesProfile(targetDir) {
onAddRulesProfile(targetDir);
}
// Simple filename function
function getTargetRuleFilename(sourceFilename) {
return sourceFilename;
}
// Simple profile configuration - bypasses base-profile system
export const claudeProfile = {
profileName: 'claude',
displayName: 'Claude Code',
profileDir: '.', // Root directory
rulesDir: '.', // No rules directory needed
mcpConfig: false, // No MCP config needed
mcpConfigName: null,
mcpConfigPath: null,
conversionConfig: {},
fileMap: {},
globalReplacements: [],
getTargetRuleFilename,
onAddRulesProfile,
onRemoveRulesProfile,
onPostConvertRulesProfile
};

62
scripts/profiles/codex.js Normal file
View File

@@ -0,0 +1,62 @@
// Codex profile for rule-transformer
import path from 'path';
import fs from 'fs';
import { isSilentMode, log } from '../modules/utils.js';
// Lifecycle functions for Codex profile
function onAddRulesProfile(targetDir) {
const sourceFile = path.join(process.cwd(), 'assets', 'AGENTS.md');
const destFile = path.join(targetDir, 'AGENTS.md');
if (fs.existsSync(sourceFile)) {
try {
fs.copyFileSync(sourceFile, destFile);
log('debug', `[Codex] Copied AGENTS.md to ${destFile}`);
} catch (err) {
log('debug', `[Codex] Failed to copy AGENTS.md: ${err.message}`);
}
} else {
log('debug', `[Codex] AGENTS.md not found at ${sourceFile}`);
}
}
function onRemoveRulesProfile(targetDir) {
log('debug', `[Codex] onRemoveRulesProfile called for ${targetDir}`);
const agentsFile = path.join(targetDir, 'AGENTS.md');
if (fs.existsSync(agentsFile)) {
try {
fs.rmSync(agentsFile, { force: true });
log('debug', `[Codex] Removed AGENTS.md from ${targetDir}`);
} catch (err) {
log('debug', `[Codex] Failed to remove AGENTS.md: ${err.message}`);
}
}
log('debug', `[Codex] onRemoveRulesProfile completed for ${targetDir}`);
}
function onPostConvertRulesProfile(targetDir) {
onAddRulesProfile(targetDir);
}
// Simple filename function
function getTargetRuleFilename(sourceFilename) {
return sourceFilename;
}
// Simple profile configuration - bypasses base-profile system
export const codexProfile = {
profileName: 'codex',
displayName: 'Codex',
profileDir: '.', // Root directory
rulesDir: '.', // No rules directory needed
mcpConfig: false, // No MCP config needed
mcpConfigName: null,
mcpConfigPath: null,
conversionConfig: {},
fileMap: {},
globalReplacements: [],
getTargetRuleFilename,
onAddRulesProfile,
onRemoveRulesProfile,
onPostConvertRulesProfile
};

View File

@@ -1,6 +1,8 @@
// Profile exports for centralized importing
export * as clineProfile from './cline.js';
export * as cursorProfile from './cursor.js';
export * as rooProfile from './roo.js';
export * as traeProfile from './trae.js';
export * as windsurfProfile from './windsurf.js';
export { claudeProfile } from './claude.js';
export { clineProfile } from './cline.js';
export { codexProfile } from './codex.js';
export { cursorProfile } from './cursor.js';
export { rooProfile } from './roo.js';
export { traeProfile } from './trae.js';
export { windsurfProfile } from './windsurf.js';