ai-engine
Last commit date
app
10 months ago
archives
11 months ago
classes
10 months ago
common
10 months ago
constants
10 months ago
images
11 months ago
labs
10 months ago
themes
10 months ago
vendor
11 months ago
ai-engine.php
10 months ago
blueprint.json
2 years ago
dev-notes.md
11 months ago
readme.txt
10 months ago
uninstall.php
11 months ago
dev-notes.md
1544 lines
| 1 | # AI Engine - Developer Documentation |
| 2 | |
| 3 | This documentation is for developers who want to extend AI Engine with custom functionality. AI Engine provides multiple extension points through filters and APIs that allow you to enhance chatbots, add custom AI tools, and integrate with WordPress in powerful ways. |
| 4 | |
| 5 | ## Table of Contents |
| 6 | - [](#wordpress-hooks-referenceWordPress Hooks Reference](#wordpress-hooks-reference](#wordpress-hooks-reference) - Complete list of filters and actions |
| 7 | - [](#chatbot-actionsChatbot Actions](#chatbot-actions](#chatbot-actions) - Execute client-side functions from AI responses |
| 8 | - [](#chatbot-shortcutsChatbot Shortcuts](#chatbot-shortcuts](#chatbot-shortcuts) - Dynamic quick-action buttons in chatbots |
| 9 | - [](#chatbot-blocksChatbot Blocks](#chatbot-blocks](#chatbot-blocks) - Interactive HTML content in chat conversations |
| 10 | - [](#mcp-model-context-protocolMCP (Model Context Protocol)](#mcp-model-context-protocol](#mcp-model-context-protocol) - Enable AI agents to interact with WordPress |
| 11 | - [](#discussion-context-menuDiscussion Context Menu](#discussion-context-menu](#discussion-context-menu) - Customize the discussions interface |
| 12 | |
| 13 | --- |
| 14 | |
| 15 | # WordPress Hooks Reference |
| 16 | |
| 17 | AI Engine provides numerous WordPress filters and actions that allow developers to customize and extend its functionality. This section documents the most useful hooks for developers. |
| 18 | |
| 19 | ## Core AI Filters |
| 20 | |
| 21 | ### Query and Reply Processing |
| 22 | |
| 23 | ```php |
| 24 | // Modify AI query before it's sent |
| 25 | add_filter( 'mwai_ai_query', function( $query ) { |
| 26 | // Modify the query object |
| 27 | return $query; |
| 28 | }); |
| 29 | |
| 30 | // Modify AI reply after it's received |
| 31 | add_filter( 'mwai_ai_reply', function( $reply, $query ) { |
| 32 | // Process or modify the reply |
| 33 | return $reply; |
| 34 | }, 10, 2 ); |
| 35 | |
| 36 | // Control whether a query is allowed |
| 37 | add_filter( 'mwai_ai_allowed', function( $allowed, $query, $limits ) { |
| 38 | // Return true to allow, false to block, or a string error message |
| 39 | if ( /* some condition */ ) { |
| 40 | return 'Query blocked due to rate limits'; |
| 41 | } |
| 42 | return $allowed; |
| 43 | }, 10, 3 ); |
| 44 | |
| 45 | // Modify AI instructions/context |
| 46 | add_filter( 'mwai_ai_instructions', function( $instructions, $query ) { |
| 47 | // Add or modify system instructions |
| 48 | $instructions .= "\nAlways be polite and helpful."; |
| 49 | return $instructions; |
| 50 | }, 10, 2 ); |
| 51 | ``` |
| 52 | |
| 53 | ### Error Handling |
| 54 | |
| 55 | ```php |
| 56 | // Customize error messages shown to users |
| 57 | add_filter( 'mwai_ai_exception', function( $message ) { |
| 58 | // Hide technical details from users |
| 59 | if ( strpos( $message, 'API' ) !== false ) { |
| 60 | return 'Service temporarily unavailable. Please try again.'; |
| 61 | } |
| 62 | return $message; |
| 63 | }); |
| 64 | ``` |
| 65 | |
| 66 | ## Chatbot Filters |
| 67 | |
| 68 | ### Chatbot Parameters and Behavior |
| 69 | |
| 70 | ```php |
| 71 | // Modify chatbot parameters |
| 72 | add_filter( 'mwai_chatbot_params', function( $params ) { |
| 73 | // Force specific settings |
| 74 | $params['temperature'] = 0.7; |
| 75 | $params['max_tokens'] = 500; |
| 76 | return $params; |
| 77 | }); |
| 78 | |
| 79 | // Takeover chatbot response (bypass AI) |
| 80 | add_filter( 'mwai_chatbot_takeover', function( $takeover, $query, $params ) { |
| 81 | // Check for specific triggers |
| 82 | if ( strpos( $query->get_message(), 'current time' ) !== false ) { |
| 83 | return 'The current time is ' . current_time( 'mysql' ); |
| 84 | } |
| 85 | return $takeover; |
| 86 | }, 10, 3 ); |
| 87 | |
| 88 | // Modify chatbot query before processing |
| 89 | add_filter( 'mwai_chatbot_query', function( $query, $params ) { |
| 90 | // Add context or modify the query |
| 91 | return $query; |
| 92 | }, 10, 2 ); |
| 93 | |
| 94 | // Process chatbot reply before sending to user |
| 95 | add_filter( 'mwai_chatbot_reply', function( $reply, $query, $params, $extra ) { |
| 96 | // Add custom formatting or processing |
| 97 | return $reply; |
| 98 | }, 10, 4 ); |
| 99 | ``` |
| 100 | |
| 101 | ### Dynamic UI Elements |
| 102 | |
| 103 | ```php |
| 104 | // Add chatbot shortcuts dynamically |
| 105 | add_filter( 'mwai_chatbot_shortcuts', function( $shortcuts, $args ) { |
| 106 | $shortcuts[] = [ |
| 107 | 'type' => 'message', |
| 108 | 'data' => [ |
| 109 | 'label' => 'Help', |
| 110 | 'message' => 'I need help', |
| 111 | 'variant' => 'info' |
| 112 | ] |
| 113 | ]; |
| 114 | return $shortcuts; |
| 115 | }, 10, 2 ); |
| 116 | |
| 117 | // Add chatbot blocks (HTML content) |
| 118 | add_filter( 'mwai_chatbot_blocks', function( $blocks, $args ) { |
| 119 | $blocks[] = [ |
| 120 | 'type' => 'content', |
| 121 | 'data' => [ |
| 122 | 'html' => '<div>Custom content</div>', |
| 123 | 'script' => 'console.log("Block loaded");' |
| 124 | ] |
| 125 | ]; |
| 126 | return $blocks; |
| 127 | }, 10, 2 ); |
| 128 | |
| 129 | // Add chatbot actions (function calls) |
| 130 | add_filter( 'mwai_chatbot_actions', function( $actions, $args ) { |
| 131 | $actions[] = [ |
| 132 | 'name' => 'custom_action', |
| 133 | 'data' => ['param' => 'value'] |
| 134 | ]; |
| 135 | return $actions; |
| 136 | }, 10, 2 ); |
| 137 | ``` |
| 138 | |
| 139 | ## Discussion Filters |
| 140 | |
| 141 | ### Discussion Metadata Display |
| 142 | |
| 143 | These filters allow you to customize how discussion metadata is displayed in the discussion list. |
| 144 | |
| 145 | ```php |
| 146 | // Customize the start date display |
| 147 | add_filter( 'mwai_discussion_metadata_start_date', function( $formatted_date, $discussion ) { |
| 148 | // $formatted_date is already formatted (e.g., "5m ago", "Jan 20th") |
| 149 | // $discussion contains the full discussion data |
| 150 | |
| 151 | // Example: Add emoji for recent discussions |
| 152 | $created_time = strtotime( $discussion['created'] ); |
| 153 | $hours_ago = ( time() - $created_time ) / 3600; |
| 154 | |
| 155 | if ( $hours_ago < 1 ) { |
| 156 | return '🔥 ' . $formatted_date; |
| 157 | } elseif ( $hours_ago < 24 ) { |
| 158 | return '✨ ' . $formatted_date; |
| 159 | } |
| 160 | |
| 161 | return $formatted_date; |
| 162 | }, 10, 2 ); |
| 163 | |
| 164 | // Customize the last update display |
| 165 | add_filter( 'mwai_discussion_metadata_last_update', function( $formatted_date, $discussion ) { |
| 166 | // Example: Show activity status instead of time |
| 167 | $updated_time = strtotime( $discussion['updated'] ); |
| 168 | $days_ago = ( time() - $updated_time ) / 86400; |
| 169 | |
| 170 | if ( $days_ago < 1 ) { |
| 171 | return '🟢 Active today'; |
| 172 | } elseif ( $days_ago < 7 ) { |
| 173 | return '🟡 This week'; |
| 174 | } else { |
| 175 | return '⚪ ' . $formatted_date; |
| 176 | } |
| 177 | }, 10, 2 ); |
| 178 | |
| 179 | // Customize the message count display |
| 180 | add_filter( 'mwai_discussion_metadata_message_count', function( $count, $discussion ) { |
| 181 | // Example: Format with descriptive text |
| 182 | if ( $count == 0 ) { |
| 183 | return 'No messages'; |
| 184 | } elseif ( $count == 1 ) { |
| 185 | return '1 message'; |
| 186 | } elseif ( $count > 50 ) { |
| 187 | return $count . ' messages 🔥'; |
| 188 | } |
| 189 | |
| 190 | return $count . ' messages'; |
| 191 | }, 10, 2 ); |
| 192 | |
| 193 | // Complete example: Custom badges based on discussion data |
| 194 | add_filter( 'mwai_discussion_metadata_start_date', function( $formatted_date, $discussion ) { |
| 195 | // Access discussion properties |
| 196 | $message_count = count( json_decode( $discussion['messages'], true ) ); |
| 197 | $has_title = !empty( $discussion['title'] ); |
| 198 | |
| 199 | // Add badges based on conditions |
| 200 | $badges = []; |
| 201 | if ( $message_count > 20 ) { |
| 202 | $badges[] = '💬'; |
| 203 | } |
| 204 | if ( $has_title ) { |
| 205 | $badges[] = '📝'; |
| 206 | } |
| 207 | |
| 208 | $badge_string = !empty( $badges ) ? implode( '', $badges ) . ' ' : ''; |
| 209 | return $badge_string . $formatted_date; |
| 210 | }, 10, 2 ); |
| 211 | ``` |
| 212 | |
| 213 | ### Available Discussion Data |
| 214 | |
| 215 | The `$discussion` parameter contains: |
| 216 | - `id` - Discussion ID |
| 217 | - `chatId` - Unique chat identifier |
| 218 | - `botId` - Associated bot ID |
| 219 | - `title` - Discussion title (may be empty) |
| 220 | - `created` - Creation timestamp |
| 221 | - `updated` - Last update timestamp |
| 222 | - `messages` - JSON string of messages (decode to access) |
| 223 | - `extra` - JSON string of extra data |
| 224 | |
| 225 | ## Embeddings and Vector Database |
| 226 | |
| 227 | ```php |
| 228 | // Add custom vector to database |
| 229 | add_filter( 'mwai_embeddings_add_vector', function( $success, $vector, $options ) { |
| 230 | // Implement custom vector storage |
| 231 | return $success; |
| 232 | }, 10, 3 ); |
| 233 | |
| 234 | // Query vectors from database |
| 235 | add_filter( 'mwai_embeddings_query_vectors', function( $results, $searchVectors, $options ) { |
| 236 | // Implement custom vector search |
| 237 | return $results; |
| 238 | }, 10, 3 ); |
| 239 | |
| 240 | // Delete vectors |
| 241 | add_filter( 'mwai_embeddings_delete_vectors', function( $vectorIds, $options ) { |
| 242 | // Handle vector deletion |
| 243 | return $vectorIds; |
| 244 | }, 10, 2 ); |
| 245 | |
| 246 | // Modify context search results |
| 247 | add_filter( 'mwai_context_search', function( $context, $query, $options ) { |
| 248 | // Add or modify context from embeddings |
| 249 | return $context; |
| 250 | }, 10, 3 ); |
| 251 | ``` |
| 252 | |
| 253 | ## Content Processing |
| 254 | |
| 255 | ```php |
| 256 | // Modify content before AI processing |
| 257 | add_filter( 'mwai_contentaware_content', function( $content, $post ) { |
| 258 | // Clean or enhance content |
| 259 | $content = strip_shortcodes( $content ); |
| 260 | return $content; |
| 261 | }, 10, 2 ); |
| 262 | |
| 263 | // Customize prompt templates |
| 264 | add_filter( 'mwai_prompt_suggestTitles', function( $prompt, $args ) { |
| 265 | return "Generate 5 SEO-optimized titles for:\n\n"; |
| 266 | }, 10, 2 ); |
| 267 | |
| 268 | add_filter( 'mwai_prompt_translateText', function( $prompt, $args ) { |
| 269 | return "Translate to {$args['language']} maintaining tone:\n\n"; |
| 270 | }, 10, 2 ); |
| 271 | ``` |
| 272 | |
| 273 | ## AI Forms |
| 274 | |
| 275 | ```php |
| 276 | // Modify form parameters |
| 277 | add_filter( 'mwai_form_params', function( $params ) { |
| 278 | $params['submit_label'] = 'Generate Content'; |
| 279 | return $params; |
| 280 | }); |
| 281 | |
| 282 | // Takeover form submission |
| 283 | add_filter( 'mwai_form_takeover', function( $takeover, $query, $params ) { |
| 284 | // Handle form submission custom logic |
| 285 | return $takeover; |
| 286 | }, 10, 3 ); |
| 287 | |
| 288 | // Process form reply |
| 289 | add_filter( 'mwai_form_reply', function( $reply, $query, $params, $extra ) { |
| 290 | // Format or process the reply |
| 291 | return $reply; |
| 292 | }, 10, 4 ); |
| 293 | |
| 294 | // Customize form field parameters |
| 295 | add_filter( 'mwai_forms_field_params', function( $params ) { |
| 296 | // Modify field settings |
| 297 | return $params; |
| 298 | }); |
| 299 | |
| 300 | // Add custom form styles |
| 301 | add_filter( 'mwai_forms_style', function( $styles, $formId ) { |
| 302 | $styles .= "\n.mwai-form-{$formId} { border: 2px solid blue; }"; |
| 303 | return $styles; |
| 304 | }, 10, 2 ); |
| 305 | ``` |
| 306 | |
| 307 | ## Function Calling |
| 308 | |
| 309 | ```php |
| 310 | // Register custom functions for AI to call |
| 311 | add_filter( 'mwai_functions_list', function( $functions ) { |
| 312 | $functions[] = [ |
| 313 | 'name' => 'get_weather', |
| 314 | 'description' => 'Get current weather', |
| 315 | 'parameters' => [ |
| 316 | 'type' => 'object', |
| 317 | 'properties' => [ |
| 318 | 'location' => [ |
| 319 | 'type' => 'string', |
| 320 | 'description' => 'City name' |
| 321 | ] |
| 322 | ] |
| 323 | ] |
| 324 | ]; |
| 325 | return $functions; |
| 326 | }); |
| 327 | |
| 328 | // Handle function execution |
| 329 | add_filter( 'mwai_ai_feedback', function( $result, $function, $args ) { |
| 330 | if ( $function['name'] === 'get_weather' ) { |
| 331 | // Execute function and return result |
| 332 | return "Sunny, 25°C in " . $args['location']; |
| 333 | } |
| 334 | return $result; |
| 335 | }, 10, 3 ); |
| 336 | ``` |
| 337 | |
| 338 | ## Statistics and Usage |
| 339 | |
| 340 | ```php |
| 341 | // Modify usage statistics |
| 342 | add_filter( 'mwai_stats_credits', function( $credits, $userId ) { |
| 343 | // Implement custom credit system |
| 344 | return $credits; |
| 345 | }, 10, 2 ); |
| 346 | |
| 347 | // Customize pricing calculations |
| 348 | add_filter( 'mwai_stats_coins', function( $price, $stats, $atts ) { |
| 349 | // Apply custom pricing logic |
| 350 | return $price; |
| 351 | }, 10, 3 ); |
| 352 | |
| 353 | // Access logs |
| 354 | add_filter( 'mwai_stats_logs_list', function( $logs, $offset, $limit, $filters, $sort ) { |
| 355 | // Filter or modify logs |
| 356 | return $logs; |
| 357 | }, 10, 5 ); |
| 358 | ``` |
| 359 | |
| 360 | ## MCP (Model Context Protocol) |
| 361 | |
| 362 | ```php |
| 363 | // Register MCP tools |
| 364 | add_filter( 'mwai_mcp_tools', function( $tools ) { |
| 365 | $tools[] = [ |
| 366 | 'name' => 'custom_tool', |
| 367 | 'description' => 'My custom tool', |
| 368 | 'inputSchema' => [/* ... */] |
| 369 | ]; |
| 370 | return $tools; |
| 371 | }); |
| 372 | |
| 373 | // Handle MCP tool execution |
| 374 | add_filter( 'mwai_mcp_callback', function( $result, $tool, $args, $id ) { |
| 375 | if ( $tool === 'custom_tool' ) { |
| 376 | // Execute and return result |
| 377 | return ['success' => true, 'data' => 'result']; |
| 378 | } |
| 379 | return $result; |
| 380 | }, 10, 4 ); |
| 381 | |
| 382 | // Control MCP access |
| 383 | add_filter( 'mwai_allow_mcp', function( $allowed, $userId ) { |
| 384 | // Implement custom access control |
| 385 | return $allowed; |
| 386 | }, 10, 2 ); |
| 387 | ``` |
| 388 | |
| 389 | ## Engine Configuration |
| 390 | |
| 391 | ```php |
| 392 | // Customize AI engine initialization |
| 393 | add_filter( 'mwai_init_engine', function( $engine, $core, $env ) { |
| 394 | // Return custom engine implementation |
| 395 | return $engine; |
| 396 | }, 10, 3 ); |
| 397 | |
| 398 | // Modify model lists |
| 399 | add_filter( 'mwai_openai_models', function( $models ) { |
| 400 | // Add custom models |
| 401 | $models[] = 'custom-model-id'; |
| 402 | return $models; |
| 403 | }); |
| 404 | |
| 405 | // Customize API endpoints |
| 406 | add_filter( 'mwai_openai_endpoint', function( $endpoint, $env ) { |
| 407 | // Use custom endpoint |
| 408 | return 'https://custom-api.example.com/v1'; |
| 409 | }, 10, 2 ); |
| 410 | ``` |
| 411 | |
| 412 | ## Actions |
| 413 | |
| 414 | ```php |
| 415 | // Scheduled tasks |
| 416 | add_action( 'mwai_tasks_run', function() { |
| 417 | // Run scheduled maintenance tasks |
| 418 | // This runs on WP cron |
| 419 | }); |
| 420 | ``` |
| 421 | |
| 422 | ## Best Practices |
| 423 | |
| 424 | 1. **Priority Matters**: Use appropriate priority values (default is 10) to control execution order |
| 425 | 2. **Return Values**: Always return the filtered value, even if unchanged |
| 426 | 3. **Error Handling**: Use try-catch blocks in your filters to prevent breaking the plugin |
| 427 | 4. **Performance**: Keep filter callbacks lightweight, especially for frequently called filters |
| 428 | 5. **Documentation**: Document your custom filters for other developers on your team |
| 429 | |
| 430 | --- |
| 431 | |
| 432 | # Chatbot Actions |
| 433 | |
| 434 | Actions allow AI models to trigger client-side JavaScript functions during chat conversations. This enables dynamic interactions like form submissions, API calls, or UI updates directly from the AI's response. |
| 435 | |
| 436 | ## How Actions Work |
| 437 | |
| 438 | When the AI includes a specific action in its response, the chatbot automatically executes the corresponding JavaScript function on the client side. This is particularly useful for: |
| 439 | - Triggering form submissions |
| 440 | - Making API calls |
| 441 | - Updating UI elements |
| 442 | - Collecting user data |
| 443 | - Integrating with third-party services |
| 444 | |
| 445 | ## Implementation |
| 446 | |
| 447 | ### Step 1: Create a Callable Action in Code Engine |
| 448 | |
| 449 | 1. Go to **AI Engine → Code Engine** |
| 450 | 2. Create a new snippet with: |
| 451 | - **Type**: Callable Action |
| 452 | - **Target**: JS |
| 453 | - **Name**: Your action name (e.g., `submit_form`) |
| 454 | |
| 455 | ### Step 2: Write Your JavaScript Function |
| 456 | |
| 457 | ```javascript |
| 458 | // This function will be called when the AI triggers the action |
| 459 | function submit_form(args) { |
| 460 | // Access chatbot context |
| 461 | const chatbot = args.chatbot; |
| 462 | const message = args.message; |
| 463 | |
| 464 | // Your custom logic |
| 465 | const formData = { |
| 466 | name: args.name, |
| 467 | email: args.email, |
| 468 | message: args.userMessage |
| 469 | }; |
| 470 | |
| 471 | // Example: Submit to an API |
| 472 | fetch('/wp-json/custom/v1/submit', { |
| 473 | method: 'POST', |
| 474 | headers: { 'Content-Type': 'application/json' }, |
| 475 | body: JSON.stringify(formData) |
| 476 | }) |
| 477 | .then(response => response.json()) |
| 478 | .then(data => { |
| 479 | // Send response back to chat |
| 480 | chatbot.addMessage({ |
| 481 | role: 'assistant', |
| 482 | content: 'Form submitted successfully!' |
| 483 | }); |
| 484 | }); |
| 485 | } |
| 486 | ``` |
| 487 | |
| 488 | ### Step 3: Configure AI to Use the Action |
| 489 | |
| 490 | In your AI assistant or system prompt, instruct the model to use the action: |
| 491 | |
| 492 | ``` |
| 493 | When the user wants to submit a contact form, use the submit_form action with their name, email, and message. |
| 494 | |
| 495 | Example response format: |
| 496 | "I'll submit that form for you now." |
| 497 | [Action: submit_form, Args: {"name": "John", "email": "john@example.com", "userMessage": "Hello!"}] |
| 498 | ``` |
| 499 | |
| 500 | ## Action Response Format |
| 501 | |
| 502 | The AI should include actions in this format: |
| 503 | ```json |
| 504 | { |
| 505 | "type": "function", |
| 506 | "data": { |
| 507 | "name": "action_name", |
| 508 | "args": { |
| 509 | "param1": "value1", |
| 510 | "param2": "value2" |
| 511 | } |
| 512 | } |
| 513 | } |
| 514 | ``` |
| 515 | |
| 516 | ## Complete Example: Calculator Action |
| 517 | |
| 518 | ```javascript |
| 519 | // Code Engine Callable Action: "calculate" |
| 520 | function calculate(args) { |
| 521 | const { operation, a, b, chatbot } = args; |
| 522 | let result; |
| 523 | |
| 524 | switch(operation) { |
| 525 | case 'add': |
| 526 | result = a + b; |
| 527 | break; |
| 528 | case 'multiply': |
| 529 | result = a * b; |
| 530 | break; |
| 531 | case 'divide': |
| 532 | result = b !== 0 ? a / b : 'Cannot divide by zero'; |
| 533 | break; |
| 534 | } |
| 535 | |
| 536 | // Display result in chat |
| 537 | chatbot.addMessage({ |
| 538 | role: 'assistant', |
| 539 | content: `The result is: ${result}` |
| 540 | }); |
| 541 | } |
| 542 | ``` |
| 543 | |
| 544 | AI Assistant instruction: |
| 545 | ``` |
| 546 | When asked to perform calculations, use the calculate action. |
| 547 | Example: "What is 5 plus 3?" |
| 548 | Response: "Let me calculate that for you." [Action: calculate, Args: {"operation": "add", "a": 5, "b": 3}] |
| 549 | ``` |
| 550 | |
| 551 | --- |
| 552 | |
| 553 | # Chatbot Shortcuts |
| 554 | |
| 555 | Shortcuts are dynamic quick-action buttons that appear in the chatbot interface. They provide users with suggested actions or common questions, improving the chat experience by offering one-click interactions. |
| 556 | |
| 557 | ## What Are Shortcuts? |
| 558 | |
| 559 | Shortcuts appear as clickable buttons above the chat input. When clicked, they can: |
| 560 | - Send predefined messages to the chatbot |
| 561 | - Trigger specific conversations |
| 562 | - Guide users through common workflows |
| 563 | - Provide contextual suggestions based on the conversation |
| 564 | |
| 565 | ## Adding Shortcuts via JavaScript |
| 566 | |
| 567 | ### Basic Example |
| 568 | |
| 569 | ```javascript |
| 570 | // Add shortcuts to all chatbots |
| 571 | MwaiAPI.chatbots.forEach(chatbot => { |
| 572 | chatbot.setShortcuts([ |
| 573 | { |
| 574 | type: 'message', |
| 575 | data: { |
| 576 | label: 'Get Started', |
| 577 | message: 'Hello! What can you help me with?', |
| 578 | variant: 'success', |
| 579 | icon: '👋' |
| 580 | } |
| 581 | }, |
| 582 | { |
| 583 | type: 'message', |
| 584 | data: { |
| 585 | label: 'Contact Support', |
| 586 | message: 'I need help with a technical issue', |
| 587 | variant: 'warning', |
| 588 | icon: '🛠️' |
| 589 | } |
| 590 | } |
| 591 | ]); |
| 592 | }); |
| 593 | ``` |
| 594 | |
| 595 | ### Dynamic Shortcuts Based on Context |
| 596 | |
| 597 | ```javascript |
| 598 | // Listen for messages and update shortcuts dynamically |
| 599 | MwaiAPI.chatbots.forEach(chatbot => { |
| 600 | chatbot.on('message', (message) => { |
| 601 | if (message.content.includes('products')) { |
| 602 | chatbot.setShortcuts([ |
| 603 | { |
| 604 | type: 'message', |
| 605 | data: { |
| 606 | label: 'View Catalog', |
| 607 | message: 'Show me your product catalog', |
| 608 | variant: 'info' |
| 609 | } |
| 610 | }, |
| 611 | { |
| 612 | type: 'message', |
| 613 | data: { |
| 614 | label: 'Best Sellers', |
| 615 | message: 'What are your best selling products?', |
| 616 | variant: 'success' |
| 617 | } |
| 618 | } |
| 619 | ]); |
| 620 | } |
| 621 | }); |
| 622 | }); |
| 623 | ``` |
| 624 | |
| 625 | ## Adding Shortcuts via PHP |
| 626 | |
| 627 | ### Basic Implementation |
| 628 | |
| 629 | ```php |
| 630 | add_filter( 'mwai_chatbot_shortcuts', function ( $shortcuts, $args ) { |
| 631 | // Add shortcuts for all chatbots |
| 632 | $shortcuts[] = [ |
| 633 | 'type' => 'message', |
| 634 | 'data' => [ |
| 635 | 'label' => 'FAQ', |
| 636 | 'message' => 'Show me frequently asked questions', |
| 637 | 'variant' => 'info', |
| 638 | 'icon' => '❓' |
| 639 | ] |
| 640 | ]; |
| 641 | |
| 642 | $shortcuts[] = [ |
| 643 | 'type' => 'message', |
| 644 | 'data' => [ |
| 645 | 'label' => 'Pricing', |
| 646 | 'message' => 'Tell me about your pricing plans', |
| 647 | 'variant' => 'success', |
| 648 | 'icon' => '💰' |
| 649 | ] |
| 650 | ]; |
| 651 | |
| 652 | return $shortcuts; |
| 653 | }, 10, 2); |
| 654 | ``` |
| 655 | |
| 656 | ### Conditional Shortcuts |
| 657 | |
| 658 | ```php |
| 659 | add_filter( 'mwai_chatbot_shortcuts', function ( $shortcuts, $args ) { |
| 660 | // Show shortcuts based on conversation content |
| 661 | $hasQuery = isset($args['newMessage']) ? $args['newMessage'] : ''; |
| 662 | $hasReply = isset($args['reply']) ? $args['reply'] : ''; |
| 663 | |
| 664 | // E-commerce shortcuts when products are mentioned |
| 665 | if (stripos($hasQuery . $hasReply, 'product') !== false) { |
| 666 | $shortcuts[] = [ |
| 667 | 'type' => 'message', |
| 668 | 'data' => [ |
| 669 | 'label' => '🛒 Cart', |
| 670 | 'message' => 'Show my shopping cart', |
| 671 | 'variant' => 'info' |
| 672 | ] |
| 673 | ]; |
| 674 | |
| 675 | $shortcuts[] = [ |
| 676 | 'type' => 'message', |
| 677 | 'data' => [ |
| 678 | 'label' => '📦 Track Order', |
| 679 | 'message' => 'I want to track my order', |
| 680 | 'variant' => 'warning' |
| 681 | ] |
| 682 | ]; |
| 683 | } |
| 684 | |
| 685 | // Support shortcuts when help is needed |
| 686 | if (stripos($hasQuery . $hasReply, 'help') !== false || |
| 687 | stripos($hasQuery . $hasReply, 'support') !== false) { |
| 688 | $shortcuts[] = [ |
| 689 | 'type' => 'message', |
| 690 | 'data' => [ |
| 691 | 'label' => '📧 Email Support', |
| 692 | 'message' => 'I need to contact support via email', |
| 693 | 'variant' => 'danger' |
| 694 | ] |
| 695 | ]; |
| 696 | |
| 697 | $shortcuts[] = [ |
| 698 | 'type' => 'message', |
| 699 | 'data' => [ |
| 700 | 'label' => '📞 Call Us', |
| 701 | 'message' => 'What is your support phone number?', |
| 702 | 'variant' => 'success' |
| 703 | ] |
| 704 | ]; |
| 705 | } |
| 706 | |
| 707 | return $shortcuts; |
| 708 | }, 10, 2); |
| 709 | ``` |
| 710 | |
| 711 | ### User-Specific Shortcuts |
| 712 | |
| 713 | ```php |
| 714 | add_filter( 'mwai_chatbot_shortcuts', function ( $shortcuts, $args ) { |
| 715 | // Show different shortcuts based on user role |
| 716 | if (is_user_logged_in()) { |
| 717 | $user = wp_get_current_user(); |
| 718 | |
| 719 | if (in_array('customer', $user->roles)) { |
| 720 | $shortcuts[] = [ |
| 721 | 'type' => 'message', |
| 722 | 'data' => [ |
| 723 | 'label' => 'My Orders', |
| 724 | 'message' => 'Show me my recent orders', |
| 725 | 'variant' => 'info' |
| 726 | ] |
| 727 | ]; |
| 728 | } |
| 729 | |
| 730 | if (in_array('administrator', $user->roles)) { |
| 731 | $shortcuts[] = [ |
| 732 | 'type' => 'message', |
| 733 | 'data' => [ |
| 734 | 'label' => 'Admin Stats', |
| 735 | 'message' => 'Show me the site statistics', |
| 736 | 'variant' => 'warning' |
| 737 | ] |
| 738 | ]; |
| 739 | } |
| 740 | } else { |
| 741 | $shortcuts[] = [ |
| 742 | 'type' => 'message', |
| 743 | 'data' => [ |
| 744 | 'label' => 'Sign Up', |
| 745 | 'message' => 'How do I create an account?', |
| 746 | 'variant' => 'success' |
| 747 | ] |
| 748 | ]; |
| 749 | } |
| 750 | |
| 751 | return $shortcuts; |
| 752 | }, 10, 2); |
| 753 | ``` |
| 754 | |
| 755 | ## Shortcut Properties |
| 756 | |
| 757 | - **type**: Always 'message' for shortcuts |
| 758 | - **data.label**: Button text displayed to user |
| 759 | - **data.message**: Message sent when clicked |
| 760 | - **data.variant**: Button style ('success', 'warning', 'danger', 'info') |
| 761 | - **data.icon**: Optional emoji or icon |
| 762 | |
| 763 | --- |
| 764 | |
| 765 | # Chatbot Blocks |
| 766 | |
| 767 | Blocks allow you to inject interactive HTML content directly into chat conversations. Unlike simple text responses, blocks can contain forms, buttons, custom UI elements, and even executable JavaScript. |
| 768 | |
| 769 | ## What Are Blocks? |
| 770 | |
| 771 | Blocks are custom HTML elements that can: |
| 772 | - Display forms for data collection |
| 773 | - Show interactive widgets |
| 774 | - Present rich media content |
| 775 | - Lock the chatbot until user interaction |
| 776 | - Execute custom JavaScript code |
| 777 | |
| 778 | ## Adding Blocks via JavaScript |
| 779 | |
| 780 | ### Simple Content Block |
| 781 | |
| 782 | ```javascript |
| 783 | // Display a welcome message with custom styling |
| 784 | MwaiAPI.getChatbot().setBlocks([ |
| 785 | { |
| 786 | type: 'content', |
| 787 | data: { |
| 788 | html: ` |
| 789 | <div style="background: #f0f0f0; padding: 20px; border-radius: 10px;"> |
| 790 | <h3>Welcome to Our Support Chat!</h3> |
| 791 | <p>How can we help you today?</p> |
| 792 | <ul> |
| 793 | <li>Technical Support</li> |
| 794 | <li>Billing Questions</li> |
| 795 | <li>Product Information</li> |
| 796 | </ul> |
| 797 | </div> |
| 798 | ` |
| 799 | } |
| 800 | } |
| 801 | ]); |
| 802 | ``` |
| 803 | |
| 804 | ### Interactive Form Block |
| 805 | |
| 806 | ```javascript |
| 807 | // Create a form that locks the chatbot until completed |
| 808 | MwaiAPI.getChatbot().setBlocks([ |
| 809 | { |
| 810 | type: 'content', |
| 811 | data: { |
| 812 | html: ` |
| 813 | <div class="custom-form-block"> |
| 814 | <h4>Quick Survey</h4> |
| 815 | <p>Please help us improve by answering this question:</p> |
| 816 | <form id="surveyForm"> |
| 817 | <label>How satisfied are you with our service?</label><br> |
| 818 | <select id="satisfaction" required> |
| 819 | <option value="">Choose...</option> |
| 820 | <option value="very-satisfied">Very Satisfied</option> |
| 821 | <option value="satisfied">Satisfied</option> |
| 822 | <option value="neutral">Neutral</option> |
| 823 | <option value="unsatisfied">Unsatisfied</option> |
| 824 | </select><br><br> |
| 825 | <button type="submit">Submit</button> |
| 826 | </form> |
| 827 | </div> |
| 828 | `, |
| 829 | script: ` |
| 830 | const chatbot = MwaiAPI.getChatbot(); |
| 831 | chatbot.lock(); // Prevent further messages |
| 832 | |
| 833 | document.getElementById('surveyForm').addEventListener('submit', function(e) { |
| 834 | e.preventDefault(); |
| 835 | const satisfaction = document.getElementById('satisfaction').value; |
| 836 | |
| 837 | // Send the response as a message |
| 838 | chatbot.ask('My satisfaction level is: ' + satisfaction, true); |
| 839 | |
| 840 | // Remove the block and unlock |
| 841 | chatbot.setBlocks([]); |
| 842 | chatbot.unlock(); |
| 843 | }); |
| 844 | ` |
| 845 | } |
| 846 | } |
| 847 | ]); |
| 848 | ``` |
| 849 | |
| 850 | ## Adding Blocks via PHP |
| 851 | |
| 852 | ### Conditional Block Display |
| 853 | |
| 854 | ```php |
| 855 | add_filter( 'mwai_chatbot_blocks', function ( $blocks, $args ) { |
| 856 | // Show block when specific keywords are detected |
| 857 | $message = $args['newMessage'] ?? ''; |
| 858 | $reply = $args['reply'] ?? ''; |
| 859 | |
| 860 | // Show appointment form when appointment is mentioned |
| 861 | if (stripos($message . $reply, 'appointment') !== false) { |
| 862 | $blocks[] = [ |
| 863 | 'type' => 'content', |
| 864 | 'data' => [ |
| 865 | 'html' => ' |
| 866 | <div class="appointment-block"> |
| 867 | <h4>Book an Appointment</h4> |
| 868 | <form id="appointmentForm"> |
| 869 | <label>Select Date:</label> |
| 870 | <input type="date" id="apptDate" required><br><br> |
| 871 | |
| 872 | <label>Select Time:</label> |
| 873 | <select id="apptTime" required> |
| 874 | <option value="9:00">9:00 AM</option> |
| 875 | <option value="10:00">10:00 AM</option> |
| 876 | <option value="14:00">2:00 PM</option> |
| 877 | <option value="15:00">3:00 PM</option> |
| 878 | </select><br><br> |
| 879 | |
| 880 | <label>Your Name:</label> |
| 881 | <input type="text" id="apptName" required><br><br> |
| 882 | |
| 883 | <button type="submit">Book Now</button> |
| 884 | </form> |
| 885 | </div> |
| 886 | ', |
| 887 | 'script' => ' |
| 888 | const chatbot = MwaiAPI.getChatbot("' . $args['botId'] . '"); |
| 889 | chatbot.lock(); |
| 890 | |
| 891 | document.getElementById("appointmentForm").addEventListener("submit", function(e) { |
| 892 | e.preventDefault(); |
| 893 | |
| 894 | const date = document.getElementById("apptDate").value; |
| 895 | const time = document.getElementById("apptTime").value; |
| 896 | const name = document.getElementById("apptName").value; |
| 897 | |
| 898 | // Send appointment details |
| 899 | chatbot.ask(`Book appointment for ${name} on ${date} at ${time}`, true); |
| 900 | |
| 901 | // Show confirmation |
| 902 | chatbot.setBlocks([{ |
| 903 | type: "content", |
| 904 | data: { |
| 905 | html: "<div style=\"color: green; padding: 10px;\">� |
| 906 | Appointment request sent!</div>" |
| 907 | } |
| 908 | }]); |
| 909 | |
| 910 | chatbot.unlock(); |
| 911 | |
| 912 | // Clear confirmation after 3 seconds |
| 913 | setTimeout(() => chatbot.setBlocks([]), 3000); |
| 914 | }); |
| 915 | ' |
| 916 | ] |
| 917 | ]; |
| 918 | } |
| 919 | |
| 920 | return $blocks; |
| 921 | }, 10, 2); |
| 922 | ``` |
| 923 | |
| 924 | ### Product Showcase Block |
| 925 | |
| 926 | ```php |
| 927 | add_filter( 'mwai_chatbot_blocks', function ( $blocks, $args ) { |
| 928 | // Show products when requested |
| 929 | if (stripos($args['reply'], 'here are our products') !== false) { |
| 930 | $products = wc_get_products(['limit' => 3, 'status' => 'publish']); |
| 931 | |
| 932 | $html = '<div class="products-showcase">'; |
| 933 | $html .= '<h4>Featured Products</h4>'; |
| 934 | $html .= '<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;">'; |
| 935 | |
| 936 | foreach ($products as $product) { |
| 937 | $html .= sprintf( |
| 938 | '<div style="border: 1px solid #ddd; padding: 10px; text-align: center;"> |
| 939 | <img src="%s" style="width: 100%%; height: 100px; object-fit: cover;"> |
| 940 | <h5>%s</h5> |
| 941 | <p>%s</p> |
| 942 | <button onclick="MwaiAPI.getChatbot(\'%s\').ask(\'Tell me more about %s\', true)">Learn More</button> |
| 943 | </div>', |
| 944 | wp_get_attachment_url($product->get_image_id()), |
| 945 | esc_html($product->get_name()), |
| 946 | wc_price($product->get_price()), |
| 947 | $args['botId'], |
| 948 | esc_html($product->get_name()) |
| 949 | ); |
| 950 | } |
| 951 | |
| 952 | $html .= '</div></div>'; |
| 953 | |
| 954 | $blocks[] = [ |
| 955 | 'type' => 'content', |
| 956 | 'data' => ['html' => $html] |
| 957 | ]; |
| 958 | } |
| 959 | |
| 960 | return $blocks; |
| 961 | }, 10, 2); |
| 962 | ``` |
| 963 | |
| 964 | ### Data Collection Wizard |
| 965 | |
| 966 | ```php |
| 967 | add_filter( 'mwai_chatbot_blocks', function ( $blocks, $args ) { |
| 968 | // Multi-step form wizard |
| 969 | if (stripos($args['newMessage'], 'start wizard') !== false) { |
| 970 | $blocks[] = [ |
| 971 | 'type' => 'content', |
| 972 | 'data' => [ |
| 973 | 'html' => ' |
| 974 | <div id="wizard" data-step="1"> |
| 975 | <div class="step" id="step1"> |
| 976 | <h4>Step 1: Your Information</h4> |
| 977 | <input type="text" id="userName" placeholder="Your name"> |
| 978 | <button onclick="nextStep()">Next</button> |
| 979 | </div> |
| 980 | |
| 981 | <div class="step" id="step2" style="display:none;"> |
| 982 | <h4>Step 2: Your Interest</h4> |
| 983 | <select id="interest"> |
| 984 | <option>Product Information</option> |
| 985 | <option>Technical Support</option> |
| 986 | <option>Pricing</option> |
| 987 | </select> |
| 988 | <button onclick="prevStep()">Back</button> |
| 989 | <button onclick="nextStep()">Next</button> |
| 990 | </div> |
| 991 | |
| 992 | <div class="step" id="step3" style="display:none;"> |
| 993 | <h4>Step 3: Summary</h4> |
| 994 | <div id="summary"></div> |
| 995 | <button onclick="prevStep()">Back</button> |
| 996 | <button onclick="submitWizard()">Submit</button> |
| 997 | </div> |
| 998 | </div> |
| 999 | ', |
| 1000 | 'script' => ' |
| 1001 | const chatbot = MwaiAPI.getChatbot("' . $args['botId'] . '"); |
| 1002 | chatbot.lock(); |
| 1003 | |
| 1004 | window.nextStep = function() { |
| 1005 | const wizard = document.getElementById("wizard"); |
| 1006 | const currentStep = parseInt(wizard.dataset.step); |
| 1007 | |
| 1008 | // Hide current step |
| 1009 | document.getElementById("step" + currentStep).style.display = "none"; |
| 1010 | |
| 1011 | // Show next step |
| 1012 | const nextStep = currentStep + 1; |
| 1013 | document.getElementById("step" + nextStep).style.display = "block"; |
| 1014 | wizard.dataset.step = nextStep; |
| 1015 | |
| 1016 | // Update summary on last step |
| 1017 | if (nextStep === 3) { |
| 1018 | const name = document.getElementById("userName").value; |
| 1019 | const interest = document.getElementById("interest").value; |
| 1020 | document.getElementById("summary").innerHTML = |
| 1021 | `<p>Name: ${name}</p><p>Interest: ${interest}</p>`; |
| 1022 | } |
| 1023 | }; |
| 1024 | |
| 1025 | window.prevStep = function() { |
| 1026 | const wizard = document.getElementById("wizard"); |
| 1027 | const currentStep = parseInt(wizard.dataset.step); |
| 1028 | document.getElementById("step" + currentStep).style.display = "none"; |
| 1029 | const prevStep = currentStep - 1; |
| 1030 | document.getElementById("step" + prevStep).style.display = "block"; |
| 1031 | wizard.dataset.step = prevStep; |
| 1032 | }; |
| 1033 | |
| 1034 | window.submitWizard = function() { |
| 1035 | const name = document.getElementById("userName").value; |
| 1036 | const interest = document.getElementById("interest").value; |
| 1037 | |
| 1038 | chatbot.ask(`Wizard completed. Name: ${name}, Interest: ${interest}`, true); |
| 1039 | chatbot.setBlocks([]); |
| 1040 | chatbot.unlock(); |
| 1041 | }; |
| 1042 | ' |
| 1043 | ] |
| 1044 | ]; |
| 1045 | } |
| 1046 | |
| 1047 | return $blocks; |
| 1048 | }, 10, 2); |
| 1049 | ``` |
| 1050 | |
| 1051 | ## Block Best Practices |
| 1052 | |
| 1053 | 1. **Always unlock the chatbot** when done with user interaction |
| 1054 | 2. **Clean up blocks** after they're no longer needed |
| 1055 | 3. **Use unique IDs** for form elements to avoid conflicts |
| 1056 | 4. **Test across devices** - ensure blocks work on mobile |
| 1057 | 5. **Provide fallbacks** for users who might have JavaScript disabled |
| 1058 | 6. **Keep scripts focused** - each block should have a single purpose |
| 1059 | |
| 1060 | --- |
| 1061 | |
| 1062 | # MCP (Model Context Protocol) |
| 1063 | |
| 1064 | The Model Context Protocol (MCP) enables AI agents like Claude to interact with WordPress sites through a standardized tool interface. AI Engine provides a comprehensive MCP implementation that allows developers to extend WordPress functionality accessible to AI. |
| 1065 | |
| 1066 | ## Overview |
| 1067 | |
| 1068 | MCP is a protocol that allows AI models to use tools (functions) to interact with external systems. In AI Engine, this means Claude can manage WordPress content, upload media, analyze images, and perform custom operations defined by developers. |
| 1069 | |
| 1070 | ## Adding Custom MCP Functions |
| 1071 | |
| 1072 | ### Basic Example |
| 1073 | |
| 1074 | ```php |
| 1075 | // 1. Register your tool |
| 1076 | add_filter( 'mwai_mcp_tools', function( $tools ) { |
| 1077 | $tools[] = [ |
| 1078 | 'name' => 'get_weather', |
| 1079 | 'description' => 'Get current weather for a city. Returns temperature and conditions.', |
| 1080 | 'inputSchema' => [ |
| 1081 | 'type' => 'object', |
| 1082 | 'properties' => [ |
| 1083 | 'city' => [ |
| 1084 | 'type' => 'string', |
| 1085 | 'description' => 'City name (e.g., "New York", "London")' |
| 1086 | ], |
| 1087 | 'units' => [ |
| 1088 | 'type' => 'string', |
| 1089 | 'enum' => ['celsius', 'fahrenheit'], |
| 1090 | 'default' => 'celsius', |
| 1091 | 'description' => 'Temperature units' |
| 1092 | ] |
| 1093 | ], |
| 1094 | 'required' => ['city'] |
| 1095 | ] |
| 1096 | ]; |
| 1097 | return $tools; |
| 1098 | }); |
| 1099 | |
| 1100 | // 2. Handle execution |
| 1101 | add_filter( 'mwai_mcp_callback', function( $result, $tool, $args, $id ) { |
| 1102 | if ( $tool !== 'get_weather' ) { |
| 1103 | return $result; |
| 1104 | } |
| 1105 | |
| 1106 | // Your logic here |
| 1107 | $city = $args['city']; |
| 1108 | $units = $args['units'] ?? 'celsius'; |
| 1109 | |
| 1110 | // Simulated weather data |
| 1111 | $weather = [ |
| 1112 | 'city' => $city, |
| 1113 | 'temperature' => rand(15, 30), |
| 1114 | 'units' => $units, |
| 1115 | 'conditions' => 'Partly cloudy' |
| 1116 | ]; |
| 1117 | |
| 1118 | return $weather; // AI Engine handles JSON-RPC wrapping |
| 1119 | }, 10, 4 ); |
| 1120 | ``` |
| 1121 | |
| 1122 | ### WordPress Integration Example |
| 1123 | |
| 1124 | ```php |
| 1125 | // Register a tool for custom post type management |
| 1126 | add_filter( 'mwai_mcp_tools', function( $tools ) { |
| 1127 | $tools[] = [ |
| 1128 | 'name' => 'manage_products', |
| 1129 | 'description' => 'Create, update, or search WooCommerce products. Can handle inventory, pricing, and product details.', |
| 1130 | 'inputSchema' => [ |
| 1131 | 'type' => 'object', |
| 1132 | 'properties' => [ |
| 1133 | 'action' => [ |
| 1134 | 'type' => 'string', |
| 1135 | 'enum' => ['create', 'update', 'search'], |
| 1136 | 'description' => 'Action to perform' |
| 1137 | ], |
| 1138 | 'title' => [ |
| 1139 | 'type' => 'string', |
| 1140 | 'description' => 'Product title (for create/update)' |
| 1141 | ], |
| 1142 | 'price' => [ |
| 1143 | 'type' => 'number', |
| 1144 | 'description' => 'Product price' |
| 1145 | ], |
| 1146 | 'sku' => [ |
| 1147 | 'type' => 'string', |
| 1148 | 'description' => 'Product SKU' |
| 1149 | ], |
| 1150 | 'stock' => [ |
| 1151 | 'type' => 'integer', |
| 1152 | 'description' => 'Stock quantity' |
| 1153 | ], |
| 1154 | 'search_term' => [ |
| 1155 | 'type' => 'string', |
| 1156 | 'description' => 'Search term (for search action)' |
| 1157 | ], |
| 1158 | 'product_id' => [ |
| 1159 | 'type' => 'integer', |
| 1160 | 'description' => 'Product ID (for update action)' |
| 1161 | ] |
| 1162 | ], |
| 1163 | 'required' => ['action'] |
| 1164 | ] |
| 1165 | ]; |
| 1166 | return $tools; |
| 1167 | }); |
| 1168 | |
| 1169 | add_filter( 'mwai_mcp_callback', function( $result, $tool, $args, $id ) { |
| 1170 | if ( $tool !== 'manage_products' ) return $result; |
| 1171 | |
| 1172 | switch ( $args['action'] ) { |
| 1173 | case 'create': |
| 1174 | $product = new WC_Product_Simple(); |
| 1175 | $product->set_name( $args['title'] ); |
| 1176 | $product->set_regular_price( $args['price'] ); |
| 1177 | if ( isset($args['sku']) ) $product->set_sku( $args['sku'] ); |
| 1178 | if ( isset($args['stock']) ) { |
| 1179 | $product->set_manage_stock( true ); |
| 1180 | $product->set_stock_quantity( $args['stock'] ); |
| 1181 | } |
| 1182 | $product->save(); |
| 1183 | |
| 1184 | return [ |
| 1185 | 'success' => true, |
| 1186 | 'product_id' => $product->get_id(), |
| 1187 | 'message' => "Product '{$args['title']}' created successfully" |
| 1188 | ]; |
| 1189 | |
| 1190 | case 'search': |
| 1191 | $products = wc_get_products([ |
| 1192 | 's' => $args['search_term'], |
| 1193 | 'limit' => 10 |
| 1194 | ]); |
| 1195 | |
| 1196 | return array_map( function($p) { |
| 1197 | return [ |
| 1198 | 'id' => $p->get_id(), |
| 1199 | 'title' => $p->get_name(), |
| 1200 | 'price' => $p->get_price(), |
| 1201 | 'stock' => $p->get_stock_quantity() |
| 1202 | ]; |
| 1203 | }, $products ); |
| 1204 | |
| 1205 | case 'update': |
| 1206 | // Update logic here |
| 1207 | break; |
| 1208 | } |
| 1209 | }, 10, 4 ); |
| 1210 | ``` |
| 1211 | |
| 1212 | ## Best Practices for Tool Descriptions |
| 1213 | |
| 1214 | **EXTREMELY IMPORTANT**: Write clear, detailed descriptions that help AI understand exactly what your tool does and when to use it. |
| 1215 | |
| 1216 | ### Good Description Examples |
| 1217 | |
| 1218 | ```php |
| 1219 | // � |
| 1220 | GOOD - Clear, specific, and actionable |
| 1221 | 'description' => 'Search and filter WooCommerce products by name, SKU, or category. Returns product details including price, stock, and variations.' |
| 1222 | |
| 1223 | // � |
| 1224 | GOOD - Explains capabilities and use cases |
| 1225 | 'description' => 'Analyze website performance metrics including page load times, database queries, and memory usage. Useful for debugging slow pages.' |
| 1226 | |
| 1227 | // ❌ BAD - Too vague |
| 1228 | 'description' => 'Handle products' |
| 1229 | |
| 1230 | // ❌ BAD - No context about what it returns |
| 1231 | 'description' => 'Get data from API' |
| 1232 | ``` |
| 1233 | |
| 1234 | ### Parameter Descriptions |
| 1235 | |
| 1236 | Always describe parameters clearly: |
| 1237 | |
| 1238 | ```php |
| 1239 | 'properties' => [ |
| 1240 | 'post_id' => [ |
| 1241 | 'type' => 'integer', |
| 1242 | 'description' => 'WordPress post ID. Use 0 to get the current post.' |
| 1243 | ], |
| 1244 | 'meta_key' => [ |
| 1245 | 'type' => 'string', |
| 1246 | 'description' => 'Custom field name (e.g., "_price", "custom_color")' |
| 1247 | ], |
| 1248 | 'format' => [ |
| 1249 | 'type' => 'string', |
| 1250 | 'enum' => ['raw', 'formatted'], |
| 1251 | 'default' => 'formatted', |
| 1252 | 'description' => 'Output format. "raw" returns database value, "formatted" applies WordPress filters.' |
| 1253 | ] |
| 1254 | ] |
| 1255 | ``` |
| 1256 | |
| 1257 | ## Error Handling |
| 1258 | |
| 1259 | ```php |
| 1260 | add_filter( 'mwai_mcp_callback', function( $result, $tool, $args, $id ) { |
| 1261 | if ( $tool !== 'your_tool' ) return $result; |
| 1262 | |
| 1263 | try { |
| 1264 | // Validate inputs |
| 1265 | if ( empty($args['required_param']) ) { |
| 1266 | throw new Exception('Missing required parameter: required_param'); |
| 1267 | } |
| 1268 | |
| 1269 | // Check permissions |
| 1270 | if ( !current_user_can('edit_posts') ) { |
| 1271 | throw new Exception('Insufficient permissions to perform this action'); |
| 1272 | } |
| 1273 | |
| 1274 | // Your logic here |
| 1275 | $data = process_something($args); |
| 1276 | |
| 1277 | if ( !$data ) { |
| 1278 | throw new Exception('Failed to process request: No data returned'); |
| 1279 | } |
| 1280 | |
| 1281 | return $data; |
| 1282 | |
| 1283 | } catch ( Exception $e ) { |
| 1284 | // Exception message will be properly formatted as JSON-RPC error |
| 1285 | throw $e; |
| 1286 | } |
| 1287 | }, 10, 4 ); |
| 1288 | ``` |
| 1289 | |
| 1290 | ## Built-in Tools Reference |
| 1291 | |
| 1292 | AI Engine includes 40+ built-in tools. Key categories: |
| 1293 | |
| 1294 | - **Posts**: create_post, read_post, update_post, delete_post, search_posts |
| 1295 | - **Media**: upload_media, get_media_url, delete_attachment |
| 1296 | - **Users**: create_user, update_user, get_current_user |
| 1297 | - **Options**: get_option, update_option |
| 1298 | - **AI Features**: vision (image analysis), imagine (image generation) |
| 1299 | |
| 1300 | See implementation examples in: |
| 1301 | - `labs/mcp-core.php` - Core WordPress tools |
| 1302 | - `labs/mcp-rest.php` - REST API integration |
| 1303 | - `premium/mcp_plugin.php` - Plugin management |
| 1304 | - `premium/mcp_theme.php` - Theme management |
| 1305 | |
| 1306 | ## Testing Your MCP Tools |
| 1307 | |
| 1308 | 1. **Enable MCP** in AI Engine settings |
| 1309 | 2. **Get your Bearer token** from the MCP section |
| 1310 | 3. **Add to Claude**: Use the MCP server URL with your token |
| 1311 | 4. **Test with Claude**: Ask Claude to use your custom tool |
| 1312 | |
| 1313 | Example Claude prompt: |
| 1314 | ``` |
| 1315 | "Can you search for products with 'laptop' in the name and show me their prices?" |
| 1316 | ``` |
| 1317 | |
| 1318 | ## Advanced Features |
| 1319 | |
| 1320 | ### Conditional Tool Registration |
| 1321 | |
| 1322 | ```php |
| 1323 | add_filter( 'mwai_mcp_tools', function( $tools ) { |
| 1324 | // Only add tool if WooCommerce is active |
| 1325 | if ( class_exists('WooCommerce') ) { |
| 1326 | $tools[] = [ |
| 1327 | 'name' => 'woo_reports', |
| 1328 | 'description' => 'Generate WooCommerce sales reports', |
| 1329 | // ... rest of tool definition |
| 1330 | ]; |
| 1331 | } |
| 1332 | |
| 1333 | // Add tool based on user capabilities |
| 1334 | if ( current_user_can('manage_options') ) { |
| 1335 | $tools[] = [ |
| 1336 | 'name' => 'admin_tasks', |
| 1337 | 'description' => 'Perform administrative tasks', |
| 1338 | // ... rest of tool definition |
| 1339 | ]; |
| 1340 | } |
| 1341 | |
| 1342 | return $tools; |
| 1343 | }); |
| 1344 | ``` |
| 1345 | |
| 1346 | ### Complex Return Values |
| 1347 | |
| 1348 | ```php |
| 1349 | // Return structured data - AI Engine handles JSON encoding |
| 1350 | return [ |
| 1351 | 'status' => 'success', |
| 1352 | 'data' => [ |
| 1353 | 'total' => 42, |
| 1354 | 'items' => $items, |
| 1355 | 'metadata' => [ |
| 1356 | 'generated_at' => current_time('mysql'), |
| 1357 | 'cache_hit' => false |
| 1358 | ] |
| 1359 | ], |
| 1360 | 'messages' => [ |
| 1361 | 'Found 42 matching items', |
| 1362 | 'Results limited to first 20' |
| 1363 | ] |
| 1364 | ]; |
| 1365 | ``` |
| 1366 | |
| 1367 | ### Access Control |
| 1368 | |
| 1369 | ```php |
| 1370 | // Control MCP access |
| 1371 | add_filter( 'mwai_allow_mcp', function( $allow, $user_id ) { |
| 1372 | // Only allow specific users |
| 1373 | $allowed_users = [1, 42, 99]; |
| 1374 | return in_array($user_id, $allowed_users); |
| 1375 | }, 10, 2 ); |
| 1376 | ``` |
| 1377 | |
| 1378 | ## Tips for Success |
| 1379 | |
| 1380 | 1. **Start Simple**: Begin with read-only tools before adding write operations |
| 1381 | 2. **Test Thoroughly**: Ensure your tools handle edge cases and invalid inputs |
| 1382 | 3. **Document Well**: Good descriptions save time and improve AI accuracy |
| 1383 | 4. **Security First**: Always validate inputs and check permissions |
| 1384 | 5. **Return Useful Data**: Structure responses for easy AI interpretation |
| 1385 | |
| 1386 | Remember: The MCP system automatically handles JSON-RPC protocol details, so focus on your business logic and return clean, structured data. |
| 1387 | |
| 1388 | --- |
| 1389 | |
| 1390 | # Discussion Context Menu |
| 1391 | |
| 1392 | You can customize the context menu that appears when clicking the three-dot icon on discussions. The menu supports regular items, separators, and custom HTML content. |
| 1393 | |
| 1394 | ## Menu Item Structure |
| 1395 | |
| 1396 | Each menu item can have the following properties: |
| 1397 | |
| 1398 | - `id`: Unique identifier for the item (required for regular items) |
| 1399 | - `type`: Item type - 'separator' or 'title' (optional, defaults to regular item) |
| 1400 | - `label`: Text to display (for regular items and titles) |
| 1401 | - `onClick`: Function called when item is clicked, receives the discussion object |
| 1402 | - `className`: CSS class names (defaults to 'mwai-menu-item') |
| 1403 | - `style`: Inline styles object (optional) |
| 1404 | - `html`: Custom HTML content (overrides label) |
| 1405 | |
| 1406 | ## Examples |
| 1407 | |
| 1408 | ### Add Custom Actions |
| 1409 | |
| 1410 | ```javascript |
| 1411 | // Add a simple alert action |
| 1412 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1413 | items.push({ |
| 1414 | id: 'alert', |
| 1415 | label: 'Show Info', |
| 1416 | onClick: (discussion) => { |
| 1417 | alert(`Discussion ID: ${discussion.chatId}\nMessages: ${discussion.messages.length}`); |
| 1418 | } |
| 1419 | }); |
| 1420 | return items; |
| 1421 | }); |
| 1422 | |
| 1423 | |
| 1424 | // Add multiple items with separator |
| 1425 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1426 | // Add separator before custom items |
| 1427 | items.push({ type: 'separator' }); |
| 1428 | |
| 1429 | // Add title |
| 1430 | items.push({ |
| 1431 | type: 'title', |
| 1432 | label: 'Custom Actions' |
| 1433 | }); |
| 1434 | |
| 1435 | // Add export action |
| 1436 | items.push({ |
| 1437 | id: 'export', |
| 1438 | label: 'Export JSON', |
| 1439 | onClick: (discussion) => { |
| 1440 | const json = JSON.stringify(discussion, null, 2); |
| 1441 | const blob = new Blob([json], { type: 'application/json' }); |
| 1442 | const url = URL.createObjectURL(blob); |
| 1443 | const a = document.createElement('a'); |
| 1444 | a.href = url; |
| 1445 | a.download = `discussion-${discussion.chatId}.json`; |
| 1446 | a.click(); |
| 1447 | } |
| 1448 | }); |
| 1449 | |
| 1450 | // Add copy ID action |
| 1451 | items.push({ |
| 1452 | id: 'copy-id', |
| 1453 | label: 'Copy Chat ID', |
| 1454 | onClick: (discussion) => { |
| 1455 | navigator.clipboard.writeText(discussion.chatId); |
| 1456 | alert('Chat ID copied to clipboard!'); |
| 1457 | } |
| 1458 | }); |
| 1459 | |
| 1460 | return items; |
| 1461 | }); |
| 1462 | |
| 1463 | // Add item with custom HTML and styling |
| 1464 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1465 | items.push({ |
| 1466 | id: 'custom-html', |
| 1467 | html: `<div style="display: flex; align-items: center; gap: 8px;"> |
| 1468 | <span style="font-size: 16px;">📊</span> |
| 1469 | <span>Stats: ${discussion.messages.length} msgs</span> |
| 1470 | </div>`, |
| 1471 | onClick: (discussion) => { |
| 1472 | console.log('Custom item clicked', discussion); |
| 1473 | } |
| 1474 | }); |
| 1475 | return items; |
| 1476 | }); |
| 1477 | |
| 1478 | // Reorder or remove default items |
| 1479 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1480 | // Move delete to top |
| 1481 | const deleteItem = items.find(item => item.id === 'delete'); |
| 1482 | const otherItems = items.filter(item => item.id !== 'delete'); |
| 1483 | return [deleteItem, ...otherItems]; |
| 1484 | }); |
| 1485 | |
| 1486 | // Conditionally show items based on discussion |
| 1487 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1488 | // Only show archive option for discussions with more than 10 messages |
| 1489 | if (discussion.messages.length > 10) { |
| 1490 | items.push({ |
| 1491 | id: 'archive', |
| 1492 | label: 'Archive', |
| 1493 | className: 'mwai-menu-item', |
| 1494 | style: { color: '#0066cc' }, |
| 1495 | onClick: (discussion) => { |
| 1496 | console.log('Archiving discussion:', discussion.chatId); |
| 1497 | // Your archive logic here |
| 1498 | } |
| 1499 | }); |
| 1500 | } |
| 1501 | return items; |
| 1502 | }); |
| 1503 | ``` |
| 1504 | |
| 1505 | ### Complete Example with All Features |
| 1506 | |
| 1507 | ```javascript |
| 1508 | // Comprehensive context menu customization |
| 1509 | MwaiAPI.addFilter('mwai_discussion_menu_items', (items, discussion) => { |
| 1510 | // Keep default items |
| 1511 | const newItems = [...items]; |
| 1512 | |
| 1513 | // Add separator |
| 1514 | newItems.push({ type: 'separator' }); |
| 1515 | |
| 1516 | // Add section title |
| 1517 | newItems.push({ |
| 1518 | type: 'title', |
| 1519 | label: 'Developer Tools' |
| 1520 | }); |
| 1521 | |
| 1522 | // Add debug info item |
| 1523 | newItems.push({ |
| 1524 | id: 'debug', |
| 1525 | label: 'Debug Info', |
| 1526 | onClick: (discussion) => { |
| 1527 | console.log('Discussion Object:', discussion); |
| 1528 | alert(`Chat ID: ${discussion.chatId}\nTitle: ${discussion.title || 'Untitled'}\nMessages: ${discussion.messages.length}`); |
| 1529 | } |
| 1530 | }); |
| 1531 | |
| 1532 | // Add item with custom icon (using emoji as HTML) |
| 1533 | newItems.push({ |
| 1534 | id: 'favorite', |
| 1535 | html: '<span>⭐ Add to Favorites</span>', |
| 1536 | onClick: (discussion) => { |
| 1537 | // Your favorite logic here |
| 1538 | console.log('Added to favorites:', discussion.chatId); |
| 1539 | } |
| 1540 | }); |
| 1541 | |
| 1542 | return newItems; |
| 1543 | }, 20); // Higher priority to run after other filters |
| 1544 | ``` |