sfdx-hardis
Version:
Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards
171 lines (160 loc) • 8.97 kB
JavaScript
/* jscpd:ignore-start */
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import fs from 'fs-extra';
import c from "chalk";
import * as path from "path";
import { Messages } from '@salesforce/core';
import { uxLog } from '../../../common/utils/index.js';
import { PROMPT_TEMPLATES } from '../../../common/aiProvider/promptTemplates/index.js';
import { PROMPT_VARIABLES } from '../../../common/aiProvider/promptTemplates/variablesIndex.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sfdx-hardis', 'org');
export default class OverridePrompts extends SfCommand {
static title = 'Override AI Prompt Templates';
static description = `
## Command Behavior
**Creates local override files for AI prompt templates and variables, allowing for customization of sfdx-hardis AI interactions.**
This command sets up a \`config/prompt-templates/\` folder within your project. It populates this folder with \`.txt\` files containing the default AI prompt templates and variables used by sfdx-hardis. This enables you to tailor the AI's behavior and responses to your organization's specific needs, terminology, and coding standards.
Key functionalities:
- **Template Customization:** Modify templates used for generating documentation, solving deployment errors, and describing Salesforce metadata.
- **Variable Customization:** Adjust common instruction patterns (e.g., role definitions, formatting requirements, security cautions) that are reused across multiple templates.
- **Persistent Overrides:** Once created, these local files will override the default sfdx-hardis templates and variables, and they will not be overwritten by future sfdx-hardis updates unless explicitly requested with the \`--overwrite\` flag.
**Important:** After running this command, you can modify any of the \`.txt\` files in \`config/prompt-templates/\` to customize the AI's behavior.
Available templates:
${Object.keys(PROMPT_TEMPLATES).map(name => `- ${name}`).join('\\n')}
Available variables:
${Object.keys(PROMPT_VARIABLES).map(name => `- ${name}`).join('\\n')}
More info on [AI Prompts documentation](https://sfdx-hardis.cloudity.com/salesforce-ai-prompts/)
<details markdown="1">
<summary>Technical explanations</summary>
The command's technical implementation involves:
- **Directory Creation:** Ensures the \`config/prompt-templates/\` directory exists using \`fs.ensureDirSync()\`.
- **File Copying:** Iterates through predefined \`PROMPT_TEMPLATES\` and \`PROMPT_VARIABLES\` objects. For each template/variable, it extracts the English text content and writes it to a corresponding \`.txt\` file in the \`config/prompt-templates/\` directory.
- **Overwrite Logic:** Checks if a file already exists. If the \`--overwrite\` flag is provided, it overwrites the existing file; otherwise, it skips the file and logs a message.
- **User Feedback:** Provides detailed logs about created, overwritten, and skipped files, along with instructions on how to use the customized prompts and variables.
- **Dynamic Content:** The description itself dynamically lists available templates and variables by iterating over \`PROMPT_TEMPLATES\` and \`PROMPT_VARIABLES\` objects.
</details>
`;
static examples = [
'$ sf hardis:doc:override-prompts',
'$ sf hardis:doc:override-prompts --overwrite',
];
static flags = {
overwrite: Flags.boolean({
default: false,
description: 'Overwrite existing template files if they already exist',
}),
debug: Flags.boolean({
char: 'd',
default: false,
description: messages.getMessage('debugMode'),
}),
websocket: Flags.string({
description: messages.getMessage('websocket'),
}),
skipauth: Flags.boolean({
description: 'Skip authentication check when a default username is required',
})
};
// Set this to true if your command requires a project workspace; 'requiresProject' is false by default
static requiresProject = false;
debugMode = false;
/* jscpd:ignore-end */
async run() {
const { flags } = await this.parse(OverridePrompts);
this.debugMode = flags.debug || false;
// Create config/prompt-templates folder
const configDir = path.join(process.cwd(), 'config');
const promptTemplatesDir = path.join(configDir, 'prompt-templates');
uxLog("action", this, c.cyan('Creating prompt templates directory.'));
fs.ensureDirSync(promptTemplatesDir);
let createdCount = 0;
let overwrittenCount = 0;
let skippedCount = 0;
uxLog("action", this, c.cyan('Creating prompt templates and variables.'));
// Copy all prompt templates as .txt files
for (const [templateName, templateDefinition] of Object.entries(PROMPT_TEMPLATES)) {
const targetFile = path.join(promptTemplatesDir, `${templateName}.txt`);
if (fs.existsSync(targetFile)) {
if (flags.overwrite) {
// Get the English text from the template
const promptText = templateDefinition.text.en;
// Overwrite the existing file
fs.writeFileSync(targetFile, promptText);
uxLog("log", this, c.grey(`Overwritten: ${templateName}.txt`));
overwrittenCount++;
}
else {
uxLog("warning", this, c.yellow(`Template already exists: ${templateName}.txt`));
skippedCount++;
}
continue;
}
// Get the English text from the template
const promptText = templateDefinition.text.en;
// Write the prompt text to the .txt file
fs.writeFileSync(targetFile, promptText);
uxLog("success", this, c.green(`Created: ${templateName}.txt`));
createdCount++;
}
// Copy all prompt variables as .txt files
for (const [variableName, variableDefinition] of Object.entries(PROMPT_VARIABLES)) {
const targetFile = path.join(promptTemplatesDir, `${variableName}.txt`);
if (fs.existsSync(targetFile)) {
if (flags.overwrite) {
// Get the English text from the variable
const variableText = variableDefinition.text.en;
// Overwrite the existing file
fs.writeFileSync(targetFile, variableText);
uxLog("log", this, c.grey(`Overwritten: ${variableName}.txt`));
overwrittenCount++;
}
else {
uxLog("warning", this, c.yellow(`Variable already exists: ${variableName}.txt`));
skippedCount++;
}
continue;
}
// Get the English text from the variable
const variableText = variableDefinition.text.en;
// Write the variable text to the .txt file
fs.writeFileSync(targetFile, variableText);
uxLog("success", this, c.green(`Created: ${variableName}.txt`));
createdCount++;
} // Summary
uxLog("other", this, '');
const actionMessage = overwrittenCount > 0 ?
`Created ${createdCount} and overwritten ${overwrittenCount} prompt template and variable files.` :
`Created ${createdCount} prompt template and variable files.`;
uxLog("action", this, c.cyan(actionMessage));
if (overwrittenCount > 0) {
uxLog("warning", this, c.yellow(`Overwritten ${overwrittenCount} existing files.`));
}
if (skippedCount > 0) {
uxLog("warning", this, c.yellow(`Skipped ${skippedCount} existing files.`));
}
const usageMessage = [
'',
'Prompt templates and variables location:',
` ${promptTemplatesDir}`,
'',
'Usage:',
' - Edit template .txt files to customize AI prompts',
' - Edit variable .txt files to customize common instruction patterns',
' - Use {{VARIABLE_NAME}} placeholders for dynamic content',
' - Templates can reference variables with {{VARIABLE_NAME}} syntax',
' - Your custom prompts and variables will override the defaults automatically',
].join('\n');
uxLog("log", this, c.grey(usageMessage));
uxLog("log", this, c.grey('Documentation: https://sfdx-hardis.cloudity.com/salesforce-ai-prompts/.'));
return {
status: 'success',
message: `${actionMessage} in ${promptTemplatesDir}`,
createdCount,
overwrittenCount,
skippedCount,
outputDir: promptTemplatesDir
};
}
}
//# sourceMappingURL=override-prompts.js.map