#include #include #include #include #include #define MAX_COMMAND_LEN 4096 #define MAX_DIRECTIVES 16 #define MAX_VALUE_LEN 1024 typedef enum { UI_NONE, UI_STREAMLIT, UI_GRADIO, UI_HTML } UiShell; typedef enum { MEDIA_NONE, MEDIA_TEXT_TO_IMAGE, MEDIA_IMAGE_TO_IMAGE, MEDIA_IMAGE_TO_VIDEO, MEDIA_TEXT_TO_VIDEO } MediaType; typedef struct { char main_prompt[MAX_COMMAND_LEN]; UiShell ui_shell; bool web_search_enabled; char model_id[MAX_VALUE_LEN]; struct { MediaType type; char prompt[MAX_COMMAND_LEN]; } media_ops[MAX_DIRECTIVES]; int media_count; char url_redesign[MAX_VALUE_LEN]; char source_image[MAX_VALUE_LEN]; char reference_doc[MAX_VALUE_LEN]; char others[MAX_DIRECTIVES][MAX_VALUE_LEN]; int other_count; } CommandSpec; typedef struct { char message[MAX_VALUE_LEN]; char type[32]; // "missing-url", "missing-image", "unknown-directive", "empty-value" } Validation; // Helper: trim whitespace from start and end of string void trim(char *str) { char *end; while (isspace(*str)) str++; if (*str == '\0') return; end = str + strlen(str) - 1; while (end > str && isspace(*end)) end--; *(end + 1) = '\0'; } // Helper: check if string starts with prefix (case-insensitive) bool starts_with(const char *str, const char *prefix) { size_t len = strlen(prefix); if (strlen(str) < len) return false; for (size_t i = 0; i < len; i++) { if (tolower(str[i]) != tolower(prefix[i])) return false; } return true; } // Helper: extract value after colon (trim whitespace) char* extract_value(const char *directive) { char *colon = strchr(directive, ':'); if (!colon) return NULL; char *value = colon + 1; while (*value && isspace(*value)) value++; return value; } // Split command by top-level commas (ignore commas inside URLs) int split_command(const char *input, char *parts[], int max_parts) { int count = 0; char *buf = strdup(input); char *ptr = buf; bool in_url = false; char quote = '\0'; for (int i = 0; ptr[i] != '\0'; i++) { if (ptr[i] == '"' || ptr[i] == '\'') { if (quote == '\0') quote = ptr[i]; else if (quote == ptr[i]) quote = '\0'; } if (quote == '\0' && ptr[i] == ':' && i > 0 && ptr[i-1] == 'h') { // Look ahead for http(s):// if (i >= 4 && strncmp(&ptr[i-4], "http", 4) == 0) in_url = true; } if (quote == '\0' && !in_url && ptr[i] == ',' && i > 0 && ptr[i-1] != '\\') { ptr[i] = '\0'; if (count < max_parts) { parts[count] = ptr; trim(parts[count]); count++; } ptr = &ptr[i+1]; i = -1; // reset to re-check from start of new segment } if (in_url && ptr[i] == ' ') in_url = false; // URL ends at space } if (count < max_parts && strlen(ptr) > 0) { parts[count] = ptr; trim(parts[count]); count++; } free(buf); return count; } // Parse a single directive bool parse_directive(const char *directive, CommandSpec *spec) { char lower_dir[1024]; strcpy(lower_dir, directive); for (int i = 0; lower_dir[i]; i++) lower_dir[i] = tolower(lower_dir[i]); if (starts_with(lower_dir, "use streamlit")) { spec->ui_shell = UI_STREAMLIT; return true; } if (starts_with(lower_dir, "use gradio")) { spec->ui_shell = UI_GRADIO; return true; } if (starts_with(lower_dir, "use html")) { spec->ui_shell = UI_HTML; return true; } if (starts_with(lower_dir, "enable web search")) { spec->web_search_enabled = true; return true; } if (starts_with(lower_dir, "disable web search")) { spec->web_search_enabled = false; return true; } if (starts_with(lower_dir, "model:")) { char *val = extract_value(directive); if (val && strlen(val) > 0) { strncpy(spec->model_id, val, MAX_VALUE_LEN - 1); spec->model_id[MAX_VALUE_LEN - 1] = '\0'; return true; } else { return false; // empty value } } if (starts_with(lower_dir, "redesign ")) { char *url = extract_value(directive); if (url && strlen(url) > 0) { strncpy(spec->url_redesign, url, MAX_VALUE_LEN - 1); spec->url_redesign[MAX_VALUE_LEN - 1] = '\0'; return true; } else { return false; // missing URL } } if (starts_with(lower_dir, "generate images:")) { if (spec->media_count < MAX_DIRECTIVES) { char *prompt = extract_value(directive); if (prompt && strlen(prompt) > 0) { spec->media_ops[spec->media_count].type = MEDIA_TEXT_TO_IMAGE; strncpy(spec->media_ops[spec->media_count].prompt, prompt, MAX_COMMAND_LEN - 1); spec->media_ops[spec->media_count].prompt[MAX_COMMAND_LEN - 1] = '\0'; spec->media_count++; return true; } } return false; } if (starts_with(lower_dir, "image to image:")) { if (spec->media_count < MAX_DIRECTIVES) { char *prompt = extract_value(directive); if (prompt && strlen(prompt) > 0) { spec->media_ops[spec->media_count].type = MEDIA_IMAGE_TO_IMAGE; strncpy(spec->media_ops[spec->media_count].prompt, prompt, MAX_COMMAND_LEN - 1); spec->media_ops[spec->media_count].prompt[MAX_COMMAND_LEN - 1] = '\0'; spec->media_count++; return true; } } return false; } if (starts_with(lower_dir, "image to video:")) { if (spec->media_count < MAX_DIRECTIVES) { char *prompt = extract_value(directive); if (prompt && strlen(prompt) > 0) { spec->media_ops[spec->media_count].type = MEDIA_IMAGE_TO_VIDEO; strncpy(spec->media_ops[spec->media_count].prompt, prompt, MAX_COMMAND_LEN - 1); spec->media_ops[spec->media_count].prompt[MAX_COMMAND_LEN - 1] = '\0'; spec->media_count++; return true; } } return false; } if (starts_with(lower_dir, "text to video:")) { if (spec->media_count < MAX_DIRECTIVES) { char *prompt = extract_value(directive); if (prompt && strlen(prompt) > 0) { spec->media_ops[spec->media_count].type = MEDIA_TEXT_TO_VIDEO; strncpy(spec->media_ops[spec->media_count].prompt, prompt, MAX_COMMAND_LEN - 1); spec->media_ops[spec->media_count].prompt[MAX_COMMAND_LEN - 1] = '\0'; spec->media_count++; return true; } } return false; } // Unknown directive - treat as part of main prompt (non-fatal) return false; } // Parse entire command string into CommandSpec CommandSpec parse_command(const char *input) { CommandSpec spec = {0}; strcpy(spec.main_prompt, input); char *parts[MAX_DIRECTIVES + 1]; int n = split_command(input, parts, MAX_DIRECTIVES + 1); if (n == 0) return spec; // First part is main prompt (unless it's a redesign) bool found_redesign = false; for (int i = 0; i < n; i++) { if (starts_with(parts[i], "redesign ")) { parse_directive(parts[i], &spec); found_redesign = true; } } if (!found_redesign) { // Extract main prompt as everything before first directive char *first = parts[0]; if (strlen(first) > 0) { strncpy(spec.main_prompt, first, MAX_COMMAND_LEN - 1); spec.main_prompt[MAX_COMMAND_LEN - 1] = '\0'; } } // Parse modifiers for (int i = 0; i < n; i++) { if (starts_with(parts[i], "redesign ")) continue; // Already handled if (!parse_directive(parts[i], &spec)) { // Unknown directive — do nothing (per spec: non-fatal, kept in main prompt) } } // Default model if not set if (strlen(spec.model_id) == 0) { strcpy(spec.model_id, "default-model"); } return spec; } // Validate command against attachments (simplified mock) Validation validate_command(CommandSpec *spec, bool has_source_image) { Validation v = {0}; if (strlen(spec->url_redesign) > 0 && !strstr(spec->url_redesign, "http")) { strcpy(v.message, "URL required for redesign"); strcpy(v.type, "missing-url"); return v; } for (int i = 0; i < spec->media_count; i++) { if ((spec->media_ops[i].type == MEDIA_IMAGE_TO_IMAGE || spec->media_ops[i].type == MEDIA_IMAGE_TO_VIDEO) && !has_source_image) { strcpy(v.message, "No source image attached"); strcpy(v.type, "missing-image"); return v; } } // No errors v.type[0] = '\0'; return v; } // Apply command to system state (mock implementation) void apply_command(CommandSpec *spec) { printf("[APPLYING COMMAND]\n"); printf("Main Prompt: %s\n", spec->main_prompt); printf("UI Shell: "); switch (spec->ui_shell) { case UI_STREAMLIT: printf("Streamlit\n"); break; case UI_GRADIO: printf("Gradio\n"); break; case UI_HTML: printf("HTML\n"); break; default: printf("None\n"); break; } printf("Web Search: %s\n", spec->web_search_enabled ? "Enabled" : "Disabled"); printf("Model: %s\n", spec->model_id); if (strlen(spec->url_redesign) > 0) { printf("Redesign URL: %s\n", spec->url_redesign); } for (int i = 0; i < spec->media_count; i++) { char *type_str = "unknown"; switch (spec->media_ops[i].type) { case MEDIA_TEXT_TO_IMAGE: type_str = "Text→Image"; break; case MEDIA_IMAGE_TO_IMAGE: type_str = "Image→Image"; break; case MEDIA_IMAGE_TO_VIDEO: type_str = "Image→Video"; break; case MEDIA_TEXT_TO_VIDEO: type_str = "Text→Video"; break; } printf("Media: %s → \"%s\"\n", type_str, spec->media_ops[i].prompt); } } // Main CLI entry point int main() { char command[MAX_COMMAND_LEN]; printf("Command Palette DSL (Type 'quit' to exit)\n"); while (true) { printf("> "); if (!fgets(command, sizeof(command), stdin)) break; command[strcspn(command, "\n")] = 0; // remove newline if (strcmp(command, "quit") == 0) break; CommandSpec spec = parse_command(command); Validation validation = validate_command(&spec, false); // Mock: no image attached if (validation.type[0] != '\0') { printf("❌ Validation Error: [%s] %s\n", validation.type, validation.message); } apply_command(&spec); printf("\n"); } return 0; }