PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 3.0.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v3.0.4
3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / services / message-builder.php
ai-engine / classes / services Last commit date
image.php 1 year ago message-builder.php 10 months ago model-environment.php 11 months ago response-id-manager.php 1 year ago session.php 11 months ago usage-stats.php 11 months ago
message-builder.php
333 lines
1 <?php
2
3 /**
4 * Service for building and transforming messages for different AI APIs.
5 *
6 * Simplifies the complex message building logic by breaking it down
7 * into smaller, focused methods.
8 */
9 class Meow_MWAI_Services_MessageBuilder {
10 private Meow_MWAI_Core $core;
11
12 public function __construct( Meow_MWAI_Core $core ) {
13 $this->core = $core;
14 }
15
16 /**
17 * Build messages array for Responses API format
18 */
19 public function build_responses_api_messages( Meow_MWAI_Query_Base $query ): array {
20 $messages = [];
21
22 // Handle different query types
23 if ( $query instanceof Meow_MWAI_Query_Feedback ) {
24 $messages = $this->build_feedback_messages( $query );
25 }
26 else {
27 $messages = $this->convert_messages_to_responses_format( $query->messages );
28 }
29
30 // Add user message with attachments if needed
31 if ( !( $query instanceof Meow_MWAI_Query_Feedback ) ) {
32 $messages = $this->add_user_message_with_attachments( $messages, $query );
33 }
34
35 return $messages;
36 }
37
38 /**
39 * Build messages for feedback queries
40 */
41 private function build_feedback_messages( Meow_MWAI_Query_Feedback $query ): array {
42 $messages = [];
43
44 // Convert existing messages
45 $messages = $this->convert_messages_to_responses_format( $query->messages );
46
47 // Process feedback blocks
48 if ( !empty( $query->blocks ) ) {
49 $messages = $this->add_feedback_results( $messages, $query->blocks );
50 }
51
52 return $messages;
53 }
54
55 /**
56 * Convert role-based messages to Responses API format
57 */
58 private function convert_messages_to_responses_format( array $messages ): array {
59 $converted = [];
60
61 foreach ( $messages as $message ) {
62 if ( !isset( $message['role'] ) ) {
63 // Already in Responses API format
64 $converted[] = $message;
65 continue;
66 }
67
68 // Handle assistant messages with tool calls
69 if ( $message['role'] === 'assistant' && isset( $message['tool_calls'] ) ) {
70 $converted = array_merge(
71 $converted,
72 $this->convert_assistant_with_tools( $message )
73 );
74 }
75 else {
76 // Regular messages stay as-is
77 $converted[] = $message;
78 }
79 }
80
81 return $converted;
82 }
83
84 /**
85 * Convert assistant message with tool calls to separate messages
86 */
87 private function convert_assistant_with_tools( array $message ): array {
88 $messages = [];
89
90 // Add assistant text if present
91 if ( !empty( $message['content'] ) ) {
92 $messages[] = [
93 'role' => 'assistant',
94 'content' => $message['content']
95 ];
96 }
97
98 // Convert each tool call to function_call message
99 if ( isset( $message['tool_calls'] ) ) {
100 foreach ( $message['tool_calls'] as $toolCall ) {
101 $functionCall = Meow_MWAI_Data_FunctionCall::from_tool_call( $toolCall, $message );
102 $messages[] = [
103 'type' => 'function_call',
104 'call_id' => $functionCall->id,
105 'name' => $functionCall->name,
106 'arguments' => $functionCall->get_arguments_json()
107 ];
108 }
109 }
110
111 return $messages;
112 }
113
114 /**
115 * Add feedback results to messages
116 */
117 private function add_feedback_results( array $messages, array $blocks ): array {
118 $functionResults = [];
119 $processedCallIds = [];
120
121 foreach ( $blocks as $block ) {
122 if ( !isset( $block['feedbacks'] ) ) {
123 continue;
124 }
125
126 foreach ( $block['feedbacks'] as $feedback ) {
127 $toolId = $feedback['request']['toolId'] ?? null;
128
129 // Skip duplicates
130 if ( !$toolId || in_array( $toolId, $processedCallIds ) ) {
131 continue;
132 }
133
134 // Create function result object
135 $result = Meow_MWAI_Data_FunctionResult::success(
136 $toolId,
137 $feedback['reply']['value'] ?? null
138 );
139
140 $functionResults[] = $result->to_responses_api_format();
141 $processedCallIds[] = $toolId;
142 }
143 }
144
145 // Add function results at the end
146 return array_merge( $messages, $functionResults );
147 }
148
149 /**
150 * Add user message with attachments
151 */
152 private function add_user_message_with_attachments( array $messages, Meow_MWAI_Query_Base $query ): array {
153 if ( !$query->attachedFile ) {
154 // Simple text message
155 $messages[] = [
156 'role' => 'user',
157 'content' => [
158 [
159 'type' => 'input_text',
160 'text' => $query->get_message()
161 ]
162 ]
163 ];
164 }
165 else {
166 // Message with image attachment
167 $content = [
168 [
169 'type' => 'input_text',
170 'text' => $query->get_message()
171 ]
172 ];
173
174 // Add image
175 $imageUrl = $query->image_remote_upload === 'url'
176 ? $query->attachedFile->get_url()
177 : $query->attachedFile->get_inline_base64_url();
178
179 $content[] = [
180 'type' => 'input_image',
181 'image_url' => $imageUrl
182 ];
183
184 $messages[] = [
185 'role' => 'user',
186 'content' => $content
187 ];
188 }
189
190 return $messages;
191 }
192
193 /**
194 * Build feedback-only messages for Responses API with previous_response_id
195 */
196 public function build_feedback_only_messages( Meow_MWAI_Query_Feedback $query ): array {
197 $messages = [];
198
199 if ( empty( $query->blocks ) ) {
200 return $messages;
201 }
202
203
204 // For Responses API with previous_response_id, we should ONLY send function_call_output messages.
205 // The API already knows about the function_call messages from the previous response.
206 // According to OpenAI documentation, we should NOT echo back the function_call messages.
207
208 foreach ( $query->blocks as $block ) {
209 if ( !isset( $block['feedbacks'] ) || empty( $block['feedbacks'] ) ) {
210 continue;
211 }
212
213 // Get the rawMessage from the first feedback (they should all have the same rawMessage)
214 $rawMessage = $block['feedbacks'][0]['request']['rawMessage'] ?? null;
215
216 if ( !$rawMessage || !isset( $rawMessage['tool_calls'] ) ) {
217 continue;
218 }
219
220 // Process ALL tool calls from the rawMessage in order
221 // But ONLY add the function_call_output messages (not the function_call messages)
222 foreach ( $rawMessage['tool_calls'] as $toolCall ) {
223 $callId = $toolCall['id'];
224
225 // Find and add the corresponding function result
226 // We do NOT add the function_call message when using previous_response_id
227 $foundResult = false;
228 foreach ( $block['feedbacks'] as $feedback ) {
229 if ( ( $feedback['request']['toolId'] ?? null ) === $callId ) {
230 $result = Meow_MWAI_Data_FunctionResult::success( $callId, $feedback['reply']['value'] ?? '' );
231 $messages[] = $result->to_responses_api_format();
232 $foundResult = true;
233 break;
234 }
235 }
236
237 if ( !$foundResult ) {
238 // This should not happen, but if we can't find the result, add an error result
239 $result = Meow_MWAI_Data_FunctionResult::failure( $callId, 'Function result not found' );
240 $messages[] = $result->to_responses_api_format();
241 }
242 }
243 }
244
245 return $messages;
246 }
247
248 /**
249 * Build messages for Chat Completions API
250 */
251 public function build_chat_completions_messages( Meow_MWAI_Query_Base $query ): array {
252 $messages = [];
253
254 // Add system message if present
255 if ( !empty( $query->instructions ) ) {
256 $messages[] = [
257 'role' => 'system',
258 'content' => $query->instructions
259 ];
260 }
261
262 // Add conversation messages
263 if ( !empty( $query->messages ) ) {
264 $messages = array_merge( $messages, $query->messages );
265 }
266
267 // Handle feedback queries - add function results
268 if ( $query instanceof Meow_MWAI_Query_Feedback && !empty( $query->blocks ) ) {
269 foreach ( $query->blocks as $block ) {
270 if ( !isset( $block['feedbacks'] ) ) {
271 continue;
272 }
273
274 foreach ( $block['feedbacks'] as $feedback ) {
275 $messages[] = [
276 'role' => 'tool',
277 'tool_call_id' => $feedback['request']['toolId'],
278 'content' => json_encode( $feedback['reply']['value'] ?? '' )
279 ];
280 }
281 }
282 }
283
284 // Add user message (if not a feedback query)
285 if ( !( $query instanceof Meow_MWAI_Query_Feedback ) ) {
286 $userMessage = $this->build_user_message( $query );
287 if ( $userMessage ) {
288 $messages[] = $userMessage;
289 }
290 }
291
292 return $messages;
293 }
294
295 /**
296 * Build user message for Chat Completions API
297 */
298 private function build_user_message( Meow_MWAI_Query_Base $query ): ?array {
299 $message = $query->get_message();
300 if ( empty( $message ) ) {
301 return null;
302 }
303
304 // Handle image attachments
305 if ( $query->attachedFile && $query->attachedFile->get_type() === 'image' ) {
306 $imageUrl = $query->image_remote_upload === 'url'
307 ? $query->attachedFile->get_url()
308 : $query->attachedFile->get_inline_base64_url();
309
310 return [
311 'role' => 'user',
312 'content' => [
313 [
314 'type' => 'text',
315 'text' => $message
316 ],
317 [
318 'type' => 'image_url',
319 'image_url' => [
320 'url' => $imageUrl
321 ]
322 ]
323 ]
324 ];
325 }
326
327 // Simple text message
328 return [
329 'role' => 'user',
330 'content' => $message
331 ];
332 }
333 }