PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.5.6
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.5.6
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / REST / AIGlossary.php

AIGlossary.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.5.6, at includes/REST/AIGlossary.php

154 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\REST;
4
5 use WP_REST_Request;
6 use WPDeveloper\BetterDocs\Core\BaseAPI;
7 use WPDeveloper\BetterDocs\Utils\AIUsage;
8
9 /**
10 * Server-side proxy for the "Define Glossaries with AI" feature.
11 *
12 * The glossary admin app used to call OpenAI directly from the browser with the secret
13 * API key — this endpoint moves that call server-side so the key never leaves the site.
14 * Uses the same dynamic model/token settings as Write with AI (write_with_ai_model).
15 */
16 class AIGlossary extends BaseAPI {
17
18 const MAX_TERM_LENGTH = 200;
19 const MAX_INSTRUCTION_LENGTH = 1000;
20
21 public function register() {
22 $this->post(
23 '/ai-glossary',
24 array( $this, 'generate' ),
25 array(
26 'term' => array(
27 'type' => 'string',
28 'required' => true
29 ),
30 'instruction' => array(
31 'type' => 'string',
32 'required' => false,
33 'default' => ''
34 ),
35 'previous_description' => array(
36 'type' => 'string',
37 'required' => false,
38 'default' => ''
39 )
40 )
41 );
42 }
43
44 public function permission_check() {
45 return current_user_can( 'edit_others_posts' );
46 }
47
48 public function generate( WP_REST_Request $request ) {
49 $settings = betterdocs()->settings;
50
51 if ( ! $settings->get( 'enable_glossaries_write_with_ai', true ) ) {
52 return $this->error(
53 'ai_disabled',
54 __( 'Define Glossaries with AI is disabled. Enable it from BetterDocs settings.', 'betterdocs' ),
55 400
56 );
57 }
58
59 $write_ai = betterdocs()->ai_autowrtie;
60 if ( empty( $write_ai ) || empty( $write_ai->get_api_key() ) ) {
61 return $this->error(
62 'ai_no_key',
63 __( 'OpenAI API key is missing. Add one in BetterDocs settings.', 'betterdocs' ),
64 400
65 );
66 }
67
68 $term = trim( wp_strip_all_tags( (string) $request->get_param( 'term' ) ) );
69 $instruction = wp_strip_all_tags( (string) $request->get_param( 'instruction' ) );
70 $previous = wp_strip_all_tags( (string) $request->get_param( 'previous_description' ) );
71
72 if ( $term === '' ) {
73 return $this->error(
74 'ai_empty_term',
75 __( 'Please provide a glossary term.', 'betterdocs' ),
76 400
77 );
78 }
79
80 if ( strlen( $term ) > self::MAX_TERM_LENGTH ) {
81 $term = substr( $term, 0, self::MAX_TERM_LENGTH );
82 }
83 if ( strlen( $instruction ) > self::MAX_INSTRUCTION_LENGTH ) {
84 $instruction = substr( $instruction, 0, self::MAX_INSTRUCTION_LENGTH );
85 }
86
87 $prompt = $this->build_prompt( $term, $previous, $instruction );
88 $system = __( 'You are a helpful assistant that writes concise, accurate glossary definitions.', 'betterdocs' );
89
90 $result = $write_ai->generate_text( $prompt, $system );
91
92 if ( empty( $result['success'] ) ) {
93 $message = isset( $result['error'] ) ? (string) $result['error'] : __( 'Unknown AI error.', 'betterdocs' );
94 return $this->error( 'ai_upstream', $message, 502 );
95 }
96
97 $definition = $this->clean_response( (string) $result['content'] );
98
99 if ( $definition === '' ) {
100 return $this->error(
101 'ai_empty_response',
102 __( 'The AI returned no definition. Try again.', 'betterdocs' ),
103 502
104 );
105 }
106
107 // Glossary terms are taxonomy terms generated before save — no reliable post id.
108 AIUsage::record( 'glossaries_write_with_ai' );
109
110 return $this->success(
111 array(
112 'definition' => $definition,
113 'model' => isset( $result['model'] ) ? $result['model'] : null
114 )
115 );
116 }
117
118 /**
119 * Build the generation prompt. Ported from the former browser-side buildPrompt().
120 */
121 protected function build_prompt( $term, $previous_description, $instruction ) {
122 $instruction = trim( $instruction );
123
124 if ( $instruction !== '' && $previous_description !== '' ) {
125 return implode(
126 "\n",
127 array(
128 sprintf( 'You are revising a glossary definition for the term "%s".', $term ),
129 'Previous definition: ' . $previous_description,
130 'Revise it based on this instruction: ' . $instruction,
131 'Return only the revised definition, 1-2 sentences, plain text, no heading or label.'
132 )
133 );
134 }
135
136 return sprintf(
137 'Write a concise, plain-text glossary definition (1-2 sentences) for the term: %s. Return only the definition — no heading, no label, no quotes.',
138 $term
139 );
140 }
141
142 /**
143 * Strip leading labels / dashes / surrounding quotes. Ported from cleanResponse().
144 */
145 protected function clean_response( $text ) {
146 $text = trim( $text );
147 $text = preg_replace( '/^\s*(glossary term|definition)\s*:\s*/i', '', $text );
148 $text = preg_replace( '/^\s*[-–—]\s*/u', '', $text );
149 $text = preg_replace( '/^["“”\']+|["“”\']+$/u', '', $text );
150
151 return trim( $text );
152 }
153 }
154