// File: SclPromptBuilder.cs using System; using System.Collections.Generic; using System.Text; namespace AI.Client.SCL { /// /// Represents a definition of an SCL command to be taught to the AI. /// public class SclCommandDefinition { /// /// The alphanumeric identifier for the command (e.g., "ls", "wr"). /// public string CommandId { get; set; } /// /// A brief description of what the command does. /// public string Description { get; set; } /// /// A list of parameter names expected by the command. /// public List Parameters { get; set; } public SclCommandDefinition(string commandId, string description, params string[] parameters) { CommandId = commandId; Description = description; Parameters = new List(); if (parameters != null) { Parameters.AddRange(parameters); } } } /// /// A utility class to programmatically generate the System Instructions prompt for the AI, /// injecting custom SCL commands dynamically. /// public class SclPromptBuilder { private readonly List _commands; private string _agentRole; public SclPromptBuilder() { _commands = new List(); _agentRole = "You are a strict, machine-to-machine execution engine equipped with the Synapse Command Language (SCL). SCL allows you to interact directly with the user's local system via a client program that parses your output."; } /// /// Overrides the default agent persona/role at the very beginning of the prompt. /// /// The custom role description. public void SetAgentRole(string roleDescription) { if (!string.IsNullOrWhiteSpace(roleDescription)) { _agentRole = roleDescription; } } /// /// Registers a command definition to be included in the generated prompt. /// /// The command identifier (e.g., "ls"). /// What the command does. /// The names of the parameters (e.g., "file_path", "content"). public void AddCommand(string commandId, string description, params string[] parameters) { _commands.Add(new SclCommandDefinition(commandId, description, parameters)); } /// /// Generates the complete System Instructions prompt text. /// /// A formatted string ready to be sent to the AI as System Instructions. public string GeneratePrompt() { StringBuilder sb = new StringBuilder(); // 1. Agent Role sb.AppendLine(_agentRole); sb.AppendLine(); // 2. Core SCL Protocol Rules sb.AppendLine("### SCL Protocol Rules (CRITICAL)"); sb.AppendLine("You MUST use SCL to perform actions. SCL is designed to be extremely token-efficient."); sb.AppendLine("ABSOLUTELY NO JSON, XML, MARKDOWN, OR RAW SHELL COMMANDS ARE ALLOWED. You must use the exact syntax below."); sb.AppendLine(); sb.AppendLine("1. ISSUING COMMANDS (Action Trigger: ~)"); sb.AppendLine("Syntax: ~command_name[parameter1|parameter2]"); sb.AppendLine("* Commands start with a tilde (~)."); sb.AppendLine("* Parameters are enclosed in square brackets [ ]."); sb.AppendLine("* Multiple parameters are separated by a pipe (|)."); sb.AppendLine("* If a parameter contains a literal ], |, or \\, you must escape it with a backslash (e.g., \\], \\|, \\\\)."); sb.AppendLine(); sb.AppendLine("2. RECEIVING RESULTS (Result Trigger: ^)"); sb.AppendLine("The client program will reply to your commands in the next prompt using this syntax:"); sb.AppendLine("Syntax: ^command_name[status_code|output_data]"); sb.AppendLine("* Status 0 means success. Status 1 means error."); sb.AppendLine("* You must wait for the ^ result before assuming a command succeeded, UNLESS the command launches a background/GUI application, in which case the client may omit the response to save tokens and end the interaction."); sb.AppendLine(); // 3. Dynamic Available Commands sb.AppendLine("### Available Client Commands"); sb.AppendLine("(Note: The client program currently supports the following commands. You may use them at any time to fulfill the user's requests.)"); sb.AppendLine(); if (_commands.Count == 0) { sb.AppendLine("* (No commands are currently registered by the client program.)"); } else { foreach (var cmd in _commands) { string paramString = string.Join("|", cmd.Parameters); sb.AppendLine($"* ~{cmd.CommandId}[{paramString}] : {cmd.Description}"); } } sb.AppendLine(); // 4. Execution Guidelines & Strict Constraints sb.AppendLine("### Execution Guidelines & CRITICAL CONSTRAINTS"); sb.AppendLine("* ALL INPUT PROMPT WILL BE ENCODED AS BASE64 STRINGS: Any input prompt you receive will be encoded as a base64 string. Make sure you decode the base64 string before processing it."); sb.AppendLine("* STOP AFTER ISSUING A COMMAND: If you issue a command that expects an output result, you MUST STOP generating text and wait for the program to reply with the `^` result."); sb.AppendLine("* NO RAW COMMANDS: NEVER output raw shell commands like `start notepad.exe` or `EXECUTE(notepad)`. You MUST wrap them in the appropriate SCL command, e.g., `~cmd[start notepad.exe]`."); sb.AppendLine("* NO MARKDOWN: NEVER wrap your SCL commands in backticks (`) or markdown code blocks (```)."); sb.AppendLine("* NO CONVERSATION: You may NOT output conversational text alongside an SCL command to explain your thought process to the user. ONLY output the SCL command by itself and nothing else."); sb.AppendLine("* Do NOT chain multiple commands together (e.g., do not issue an `ls` and an `rd` in the same response). Issue the first command, wait for the result, and then issue the next."); sb.AppendLine("* If a command fails (returns status 1), analyze the error data provided in the result and attempt to fix the issue or notify the user."); sb.AppendLine(); // 5. Example Scenario sb.AppendLine("### Example Scenario"); sb.AppendLine("User: \"Open notepad\""); sb.AppendLine("WRONG: start notepad.exe"); sb.AppendLine("WRONG: ```~cmd[start notepad.exe]```"); sb.AppendLine("WRONG: EXECUTE(notepad.exe)"); sb.AppendLine("CORRECT: ~cmd[start notepad.exe]"); sb.AppendLine(); sb.AppendLine("User: \"Check what is in C:\\Temp and delete old.txt\""); sb.AppendLine("You: ~cmd[dir C:\\Temp]"); sb.AppendLine("Program: ^cmd[0|old.txt\\nnew.txt\\nconfig.ini]"); sb.AppendLine("You: ~cmd[del C:\\Temp\\old.txt]"); sb.AppendLine("Program: ^cmd[0|Success]"); sb.AppendLine("You: The file old.txt has been successfully deleted."); return sb.ToString(); } } }