PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 3.3.1
AI Engine – The Chatbot, AI Framework & MCP for WordPress v3.3.1
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 / query / dropped-file.php
ai-engine / classes / query Last commit date
assist-feedback.php 10 months ago assistant.php 6 months ago base.php 6 months ago dropped-file.php 6 months ago edit-image.php 8 months ago embed.php 7 months ago feedback.php 10 months ago function.php 8 months ago image.php 6 months ago parameter.php 1 year ago text.php 6 months ago transcribe.php 8 months ago
dropped-file.php
229 lines
1 <?php
2
3 class Meow_MWAI_Query_DroppedFile {
4 private $data;
5 private $rawData;
6 private $type; // Defines what the data is about ('refId', 'url', or 'data')
7 private $purpose; // Can be 'assistant', 'vision' or 'files' => this needs to be checked
8 private $mimeType; // 'image/jpeg' or any other mime type
9 private $fileId; // The ID of the file in the database
10 public $originalPath; // The original file path (for files loaded from disk)
11
12 public static function from_url( $url, $purpose, $mimeType = null, $fileId = null ) {
13 if ( empty( $mimeType ) ) {
14 $mimeType = Meow_MWAI_Core::get_mime_type( $url );
15 }
16 return new Meow_MWAI_Query_DroppedFile( $url, 'url', $purpose, $mimeType, $fileId );
17 }
18
19 public static function from_data( $data, $purpose, $mimeType = null ) {
20 return new Meow_MWAI_Query_DroppedFile( $data, 'data', $purpose, $mimeType );
21 }
22
23 public static function from_path( $path, $purpose, $mimeType = null ) {
24 // Sanitize path to prevent PHAR deserialization attacks
25 $path = Meow_MWAI_Core::sanitize_file_path( $path );
26 $data = file_get_contents( $path );
27 if ( empty( $mimeType ) ) {
28 $mimeType = Meow_MWAI_Core::get_mime_type( $path );
29 }
30 $droppedFile = new Meow_MWAI_Query_DroppedFile( $data, 'data', $purpose, $mimeType );
31 // Store the original path for filename extraction
32 $droppedFile->originalPath = $path;
33 return $droppedFile;
34 }
35
36 public static function from_refId( $refId, $purpose, $mimeType = null ) {
37 return new Meow_MWAI_Query_DroppedFile( $refId, 'refId', $purpose, $mimeType );
38 }
39
40 /**
41 * Create DroppedFile from provider file_id reference (OpenAI, Anthropic, etc.)
42 *
43 * For PDFs uploaded to provider Files APIs, we only store the file_id
44 * Examples: OpenAI 'file-xxx', Anthropic 'file_xxx'
45 * These are reference-only - the file data lives on the provider's servers
46 * Do NOT try to load file data from these - use get_refId() to get the file_id
47 */
48 public static function from_provider_file_id( $fileId, $purpose, $mimeType = null ) {
49 return new Meow_MWAI_Query_DroppedFile( $fileId, 'provider_file_id', $purpose, $mimeType );
50 }
51
52 /**
53 * @deprecated Use from_provider_file_id() instead
54 * TODO: Remove after March 2026 - Legacy method
55 */
56 public static function from_openai_file_id( $fileId, $purpose, $mimeType = null ) {
57 return self::from_provider_file_id( $fileId, $purpose, $mimeType );
58 }
59
60 public function __construct( $data, $type, $purpose, $mimeType = null, $fileId = null ) {
61 // TODO: Remove after March 2026 - Legacy type support
62 if ( $type === 'openai_file_id' ) {
63 $type = 'provider_file_id';
64 }
65 if ( !empty( $type ) && $type !== 'refId' && $type !== 'url' && $type !== 'data' && $type !== 'provider_file_id' ) {
66 throw new Exception( 'AI Engine: The file type can only be refId, url, data, or provider_file_id.' );
67 }
68 // TODO: Remove after March 2026 - Legacy purpose mapping
69 $legacyPurposes = [ 'vision', 'files', 'transcription', 'code_execution', 'assistant-in' ];
70 if ( in_array( $purpose, $legacyPurposes, true ) ) {
71 $purpose = 'analysis';
72 }
73 if ( !empty( $purpose ) && $purpose !== 'analysis' && $purpose !== 'generated' ) {
74 throw new Exception( 'AI Engine: The file purpose can only be analysis or generated.' );
75 }
76 $this->data = $data;
77 $this->type = $type;
78 $this->purpose = $purpose;
79 $this->mimeType = $mimeType;
80 $this->fileId = $fileId;
81 }
82
83 public function get_url() {
84 if ( $this->type === 'url' ) {
85 return $this->data;
86 }
87 throw new Exception( 'AI Engine: The file is not an URL.' );
88 }
89
90 private function get_raw_data() {
91 if ( !empty( $this->rawData ) ) {
92 return $this->rawData;
93 }
94 if ( $this->type === 'provider_file_id' ) {
95 // Provider file IDs are reference-only (file data lives on provider's servers)
96 // Common mistake: trying to load file data for PDFs in conversation history
97 // Fix: Check file mime type before calling get_data()/get_base64()/get_inline_base64_url()
98 // For PDFs: use get_refId() to get the file_id string instead
99 throw new Exception( 'AI Engine: Cannot get raw data for provider file ID (file_id: ' . $this->data . '). Use get_refId() instead.' );
100 }
101 if ( $this->type === 'refId' ) {
102 global $mwai_core;
103
104 // Prefer loading from disk to avoid HTTP rewrites or CDN issues
105 $path = $mwai_core->files->get_path( $this->data );
106 if ( !empty( $path ) ) {
107 $path = Meow_MWAI_Core::sanitize_file_path( $path );
108 if ( file_exists( $path ) && is_readable( $path ) ) {
109 $data = file_get_contents( $path );
110 if ( $data === false ) {
111 throw new Exception( 'AI Engine: Failed to read file contents for refId: ' . $this->data );
112 }
113 $this->rawData = $data;
114 return $this->rawData;
115 }
116 }
117
118 // Fallback to the public URL if the local path is unavailable
119 $url = $mwai_core->files->get_url( $this->data );
120 if ( empty( $url ) ) {
121 throw new Exception( 'AI Engine: Could not find file URL for refId: ' . $this->data );
122 }
123 $parts = wp_parse_url( $url );
124 if ( !isset( $parts['scheme'] ) || !in_array( $parts['scheme'], [ 'http', 'https' ], true ) ) {
125 throw new Exception( 'Invalid URL scheme; only HTTP/HTTPS allowed.' );
126 }
127 $data = file_get_contents( $url );
128 if ( $data === false ) {
129 throw new Exception( 'AI Engine: Failed to download file contents for refId: ' . $this->data );
130 }
131 $this->rawData = $data;
132 return $this->rawData;
133 }
134 else if ( $this->type === 'url' ) {
135 // Validate URL scheme to prevent SSRF attacks
136 $parts = wp_parse_url( $this->data );
137 if ( !isset( $parts['scheme'] ) || !in_array( $parts['scheme'], [ 'http', 'https' ], true ) ) {
138 throw new Exception( 'Invalid URL scheme; only HTTP/HTTPS allowed.' );
139 }
140
141 $this->rawData = file_get_contents( $this->data );
142 return $this->rawData;
143 }
144 else if ( $this->type === 'data' ) {
145 return $this->data;
146 }
147 throw new Exception( 'AI Engine: The file is not data or an URL.' );
148 }
149
150 public function get_data() {
151 if ( $this->type === 'provider_file_id' ) {
152 // Provider file IDs are just references, no data loading needed
153 throw new Exception( 'AI Engine: Cannot get data for provider file ID. Use get_refId() instead.' );
154 }
155 if ( $this->type === 'refId' || $this->type === 'url' ) {
156 return $this->get_raw_data();
157 }
158 else if ( $this->type === 'data' ) {
159 return $this->data;
160 }
161 throw new Exception( 'AI Engine: The file is not data or an URL.' );
162 }
163
164 public function get_base64() {
165 $data = $this->get_raw_data();
166 return base64_encode( $data );
167 }
168
169 // Will return something like "data:image/jpeg;base64,{data}"
170 public function get_inline_base64_url() {
171 $b64 = $this->get_base64();
172 return "data:{$this->mimeType};base64,{$b64}";
173 }
174
175 public function get_type() {
176 return $this->type;
177 }
178
179 public function get_purpose() {
180 return $this->purpose;
181 }
182
183 public function get_mimeType() {
184 return $this->mimeType;
185 }
186
187 public function is_image() {
188 return strpos( $this->mimeType, 'image' ) !== false;
189 }
190
191 public function get_fileId() {
192 return $this->fileId;
193 }
194
195 public function get_refId() {
196 if ( $this->type === 'refId' || $this->type === 'provider_file_id' ) {
197 return $this->data;
198 }
199 return null;
200 }
201
202 // Return a filename for this file. If the file is an URL, use the basename of
203 // its path. If the file is raw data, generate a generic name based on the mime type.
204 public function get_filename() {
205 // If we have an original path (from from_path), use its basename
206 if ( !empty( $this->originalPath ) ) {
207 return basename( $this->originalPath );
208 }
209 if ( $this->type === 'refId' ) {
210 global $mwai_core;
211 $path = $mwai_core->files->get_path( $this->data );
212 return basename( $path );
213 }
214 if ( $this->type === 'url' ) {
215 $path = parse_url( $this->data, PHP_URL_PATH );
216 return basename( $path );
217 }
218 if ( $this->type === 'data' ) {
219 if ( !empty( $this->mimeType ) ) {
220 $parts = explode( '/', $this->mimeType );
221 $ext = end( $parts );
222 return 'file.' . $ext;
223 }
224 return 'file.bin';
225 }
226 return 'file';
227 }
228 }
229