| @@ -266,9 +266,9 @@ | ||
| 266 | 266 | 'properties' => array( |
| 267 | 267 | 'answer_type' => array( |
| 268 | 268 | 'type' => 'string', |
| 269 | 269 | 'enum' => array( 'entity', 'navigation', 'chat' ), |
| 270 | - 'description' => 'Classification of the answer: "entity" when you identified a specific post/page/comment the user was asking about. "navigation" when the user asked where to find something in wp-admin and you are returning admin_links. "chat" for conversational responses that don\'t involve finding content or navigation (e.g. greetings, clarifications, "I couldn\'t find anything").', | |
| 270 | + 'description' => 'Classification of the answer: "entity" when you identified a specific post/page/comment the user was asking about. "navigation" when you are returning admin_links: wp-admin destinations or plugin install links. "chat" for everything else, including summaries of tool results (error logs, site info), greetings, clarifications and "I couldn\'t find anything".', | |
| 271 | 271 | ), |
| 272 | 272 | 'message' => array( |
| 273 | 273 | 'type' => 'string', |
| 274 | 274 | 'description' => 'A friendly, conversational response to show the user. Write in first person like a helpful assistant (e.g. "I found your Málaga post — this one", "Here\'s where you manage categories"). NOT a search-engine sentence ("Match found").', |
| @@ -771,9 +771,9 @@ | ||
| 771 | 771 | |
| 772 | 772 | return array( |
| 773 | 773 | 'id' => $entity_id, |
| 774 | 774 | 'type' => $post->post_type, |
| 775 | - 'title' => wp_strip_all_tags( $post->post_title ), | |
| 775 | + 'title' => openstation_plain_text_title( $post->post_title ), | |
| 776 | 776 | 'status' => $post->post_status, |
| 777 | 777 | 'date' => $post->post_date ? substr( $post->post_date, 0, 10 ) : '', |
| 778 | 778 | 'url' => (string) get_permalink( $post ), |
| 779 | 779 | 'edit_url' => (string) get_edit_post_link( $entity_id, 'raw' ), |
| @@ -808,9 +808,9 @@ | ||
| 808 | 808 | 'id' => $entity_id, |
| 809 | 809 | 'type' => 'comment', |
| 810 | 810 | 'excerpt' => openstation_ai_search_excerpt( $comment->comment_content ), |
| 811 | 811 | 'post_id' => (int) $comment->comment_post_ID, |
| 812 | - 'post_title' => wp_strip_all_tags( $parent_post->post_title ), | |
| 812 | + 'post_title' => openstation_plain_text_title( $parent_post->post_title ), | |
| 813 | 813 | 'post_url' => (string) get_permalink( $parent_post ), |
| 814 | 814 | 'url' => (string) get_comment_link( $comment ), |
| 815 | 815 | 'edit_url' => current_user_can( 'edit_comment', $entity_id ) |
| 816 | 816 | ? admin_url( 'comment.php?action=editcomment&c=' . $entity_id ) |
| @@ -1084,18 +1084,17 @@ | ||
| 1084 | 1084 | 1. **Find content** they've written (posts, pages, comments) by describing it in natural language. |
| 1085 | 1085 | 2. **Navigate wp-admin** when they ask where to find something (\"where are the categories?\", \"how do I manage users?\"). |
| 1086 | 1086 | 3. **Recommend plugins** from the official WordPress.org directory when they need extra functionality. |
| 1087 | 1087 | 4. **Check the site's error log** when they're troubleshooting something. |
| 1088 | -5. **Answer anything else your tools can** — you may have more tools than the ones described below (WordPress and other plugins register their own, e.g. site / user / environment / version info). Your actual tool list is authoritative: whenever a tool can answer the request, call it and summarise the result, even if it isn't in the list below. | |
| 1088 | +5. **Answer anything else your tools can** — you may have more tools than the ones named here (WordPress and other plugins register their own, e.g. site / user / environment / version info). Your actual tool list is authoritative: whenever a tool can answer the request, call it and summarise the result, even if it isn't named here. | |
| 1089 | 1089 | 6. **Chat** — only when no tool fits, answer conversationally. |
| 1090 | 1090 | |
| 1091 | 1091 | Tone: warm, concise, helpful. First person (\"I found this post…\", \"Here's where you'll find that…\"). Not a search engine tone — no \"Match found\" or robot phrasing. |
| 1092 | 1092 | |
| 1093 | -Tools (your actual tool list may include more than these — use any that fit the request): | |
| 1094 | -- search_posts / search_pages / search_comments / search_comments_by_post(post_id, query, offset): keyword content-lookup tools backed by WordPress's native search. Distil the user's description into the essential search keywords and pass them as `query` (e.g. \"that long post about making paella\" → query \"paella\"). Inspect the returned title + excerpt and stop once you find a good match. If has_more is true and nothing matched, call the same tool with next_offset (reuse the same query), or try different keywords. When the query mentions BOTH a post and a comment on that post, call search_posts first to identify the post, THEN search_comments_by_post with the ID. If keyword search returns nothing, broaden or simplify the keywords before giving up. | |
| 1095 | -- list_admin_pages: returns the full catalog of wp-admin destinations. Call once per navigation query, then select the 1-3 most relevant entries. | |
| 1096 | -- search_wporg_plugins(query): searches the official WordPress.org plugin directory. Use when the user asks for a plugin recommendation (\"a plugin for X\", \"is there a plugin that does Y?\"). Returns up to 10 plugins with ratings, install counts, and admin install URLs. Present the best 3-5 as admin_links with titles like \"Plugin Name · 5M+ installs · 4.8★\" (rating is 0-100, divide by 20 to get stars). | |
| 1097 | -- get_php_error_log(lines): reads the tail of the site's PHP error log. Admin-only (the tool itself checks). Use when the user asks \"any errors?\", \"check the logs\", \"what's broken?\", troubleshooting. Each entry has { timestamp, level, message }. Summarise the most important errors (Fatal > Warning > Notice) in your message; don't copy-paste everything. | |
| 1093 | +How to work the tools (your actual tool list is authoritative; use any tool that fits the request): | |
| 1094 | +- Content lookups: stop once a returned title and excerpt clearly match. If nothing matched, page on with the next offset or try broader, simpler keywords before telling the user you found nothing. | |
| 1095 | +- Plugin recommendations: present the best 3-5 as admin_links titled like \"Plugin Name · 5M+ installs · 4.8★\". | |
| 1096 | +- Error logs: summarise the most important errors first (fatal, then warnings, then notices) instead of copying entries. | |
| 1098 | 1097 | |
| 1099 | 1098 | Choosing which track: |
| 1100 | 1099 | - \"I remember a post/page/comment about X\" → the corresponding search_* tool. |
| 1101 | 1100 | - \"where can I find X?\", \"how do I manage Y?\", \"create/add/new …\", \"take me to …\", \"open …\", \"switch/activate …\", or any navigate/do intent → list_admin_pages, then suggest the 1-3 best destinations as admin_links (answer_type \"navigation\"). You suggest the link; the user opens it — never assume it's opened. |
| @@ -1806,15 +1805,15 @@ | ||
| 1806 | 1805 | // instructions block — no tool guidance, since this run has none. |
| 1807 | 1806 | $instructions = ' |
| 1808 | 1807 | You are the same friendly WordPress assistant that just dispatched a command on behalf of the user. You now have the result of that command. |
| 1809 | 1808 | |
| 1810 | -Write a SHORT reply (one or two sentences, first person, warm and conversational) describing what happened. Match the voice the site owner set in their system prompt — do not restart small talk, just confirm what you did. | |
| 1809 | +Write a short reply (one or two sentences, first person, warm and conversational) describing what happened. Match the voice the site owner set in their system prompt — do not restart small talk, just confirm what you did. | |
| 1811 | 1810 | |
| 1812 | 1811 | Rules: |
| 1813 | 1812 | - If the outcome looks successful, confirm plainly. Example: "Done — your office light is on now." |
| 1814 | 1813 | - If the outcome looks like an error (has an `error` field, a failure message, or obviously negative content), apologise briefly and paraphrase what went wrong. Do not invent details the outcome did not include. |
| 1815 | -- Do NOT recommend the user try something else unless the outcome explicitly suggests it. | |
| 1816 | -- Do NOT describe the tool mechanism ("I called command_turn_light") — the user only cares about the real-world effect. | |
| 1814 | +- Suggest a next step only when the outcome itself suggests one. | |
| 1815 | +- Describe the real-world effect, not the tool mechanism ("I called command_turn_light"). | |
| 1817 | 1816 | '; |
| 1818 | 1817 | |
| 1819 | 1818 | $system_prompt_text = isset( $extra['system_prompt_text'] ) && is_string( $extra['system_prompt_text'] ) ? $extra['system_prompt_text'] : ''; |
| 1820 | 1819 | $system_prompt_mode = isset( $extra['system_prompt_mode'] ) && in_array( $extra['system_prompt_mode'], array( 'append', 'replace' ), true ) |
| @@ -2304,8 +2303,9 @@ | ||
| 2304 | 2303 | 'short_description' => wp_strip_all_tags( $p['short_description'] ?? '' ), |
| 2305 | 2304 | 'version' => (string) ( $p['version'] ?? '' ), |
| 2306 | 2305 | 'author' => wp_strip_all_tags( $p['author'] ?? '' ), |
| 2307 | 2306 | 'rating' => (int) ( $p['rating'] ?? 0 ), // 0-100 |
| 2307 | + 'stars' => round( ( (int) ( $p['rating'] ?? 0 ) ) / 20, 1 ), // 0-5, as wordpress.org shows it | |
| 2308 | 2308 | 'num_ratings' => (int) ( $p['num_ratings'] ?? 0 ), |
| 2309 | 2309 | 'active_installs' => (int) ( $p['active_installs'] ?? 0 ), |
| 2310 | 2310 | 'last_updated' => (string) ( $p['last_updated'] ?? '' ), |
| 2311 | 2311 | 'requires' => (string) ( $p['requires'] ?? '' ), |