209 return [
'error' =>
'AI request log table is not available.'];
212 $entity = (int) (!empty($this->
conf->entity) ? $this->
conf->entity : 1);
214 $offset = max(0, (
int) ($args[
'offset'] ?? 0));
215 $actioncommId = (int) ($args[
'actioncomm_id'] ?? 0);
216 $collectorId = (int) ($args[
'collector_id'] ?? 0);
217 $messageId = trim((
string) ($args[
'message_id'] ??
''));
218 $contextProfileCode = trim((
string) ($args[
'context_profile_code'] ??
''));
222 $sql =
"SELECT rowid, fk_actioncomm, provider, confidence, status, raw_request_payload, date_request";
223 $sql .=
" FROM ".MAIN_DB_PREFIX.self::TABLE_AI_REQUEST_LOG;
224 $sql .=
" WHERE entity = ".((int) $entity);
225 $sql .=
" AND tool_name = '".$this->db->escape(self::TOOL_NAME).
"'";
227 if ($actioncommId > 0) {
228 $sql .=
" AND fk_actioncomm = ".((int) $actioncommId);
230 if ($collectorId > 0) {
231 $sql .=
" AND raw_request_payload LIKE '%\"collector_id\":".((int) $collectorId).
"%'";
233 if ($messageId !==
'') {
234 $sql .=
" AND raw_request_payload LIKE '%".$this->db->escape($messageId).
"%'";
236 if ($contextProfileCode !==
'') {
237 $sql .=
" AND raw_request_payload LIKE '%".$this->db->escape($contextProfileCode).
"%'";
239 if ($minConfidence !==
null) {
240 $sql .=
" AND confidence >= ".((float) $minConfidence);
242 if ($maxConfidence !==
null) {
243 $sql .=
" AND confidence <= ".((float) $maxConfidence);
246 $sql .=
" ORDER BY rowid DESC";
247 $sql .= $this->db->plimit($limit, $offset);
249 $resql = $this->db->query($sql);
251 return [
'error' =>
'Database error while listing email cleaner runs: '.$this->db->lasterror()];
255 while ($obj = $this->db->fetch_object($resql)) {
256 $inputMetadata = $this->
decodeJsonOrRaw((
string) $obj->raw_request_payload);
258 'ai_request_log_id' => (
int) $obj->rowid,
259 'cleaning_id' => (
int) $obj->rowid,
260 'actioncomm_id' => (
int) $obj->fk_actioncomm,
261 'collector_id' => (!empty($inputMetadata[
'collector_id']) ? (
int) $inputMetadata[
'collector_id'] :
null),
262 'message_id' => (!empty($inputMetadata[
'message_id']) ? (string) $inputMetadata[
'message_id'] :
null),
263 'cleaning_confidence' => (
float) $obj->confidence,
264 'cleaning_model' =>
null,
265 'prompt_code' => (!empty($inputMetadata[
'prompt_code']) ? (string) $inputMetadata[
'prompt_code'] :
null),
266 'prompt_version' => (!empty($inputMetadata[
'prompt_version']) ? (string) $inputMetadata[
'prompt_version'] :
null),
267 'context_profile_code' => (!empty($inputMetadata[
'context_profile_code']) ? (string) $inputMetadata[
'context_profile_code'] :
null),
268 'context_profile_version' => (!empty($inputMetadata[
'context_profile_version']) ? (string) $inputMetadata[
'context_profile_version'] :
null),
269 'status' => (!empty($obj->status) ? (string) $obj->status :
null),
270 'date_creation' => (!empty($obj->date_request) ? (string) $obj->date_request :
null),
273 $this->db->free($resql);
277 'count' => count($items),
280 'actioncomm_id' => ($actioncommId > 0 ? $actioncommId :
null),
281 'collector_id' => ($collectorId > 0 ? $collectorId :
null),
282 'message_id' => ($messageId !==
'' ? $messageId :
null),
283 'context_profile_code' => ($contextProfileCode !==
'' ? $contextProfileCode :
null),
284 'min_confidence' => $minConfidence,
285 'max_confidence' => $maxConfidence,
301 return [
'error' =>
'AI request log table is not available.'];
304 $entity = (int) (!empty($this->
conf->entity) ? $this->
conf->entity : 1);
305 $aiRequestLogId = (int) ($args[
'ai_request_log_id'] ?? ($args[
'cleaning_id'] ?? 0));
306 $messageId = trim((
string) ($args[
'message_id'] ??
''));
307 $collectorId = (int) ($args[
'collector_id'] ?? 0);
309 $sql =
"SELECT rowid, entity, fk_actioncomm, provider, input_hash, output_hash, security_hash, confidence, status, raw_request_payload, raw_response_payload, date_request";
310 $sql .=
" FROM ".MAIN_DB_PREFIX.self::TABLE_AI_REQUEST_LOG;
311 $sql .=
" WHERE entity = ".((int) $entity);
312 $sql .=
" AND tool_name = '".$this->db->escape(self::TOOL_NAME).
"'";
314 if ($aiRequestLogId > 0) {
315 $sql .=
" AND rowid = ".((int) $aiRequestLogId);
316 } elseif ($messageId !==
'') {
317 $sql .=
" AND raw_request_payload LIKE '%".$this->db->escape($messageId).
"%'";
318 if ($collectorId > 0) {
319 $sql .=
" AND raw_request_payload LIKE '%\"collector_id\":".((int) $collectorId).
"%'";
321 $sql .=
" ORDER BY rowid DESC";
323 return [
'error' =>
"Missing selector: use 'ai_request_log_id', 'cleaning_id' or 'message_id'."];
326 $sql .= $this->db->plimit(1);
328 $resql = $this->db->query($sql);
330 return [
'error' =>
'Database error while reading cleaner run: '.$this->db->lasterror()];
332 $obj = $this->db->fetch_object($resql);
333 $this->db->free($resql);
335 return [
'error' =>
'Email cleaner run not found.'];
338 $inputMetadata = $this->
decodeJsonOrRaw((
string) $obj->raw_request_payload);
339 $outputJson = $this->
decodeJsonOrRaw((
string) $obj->raw_response_payload);
340 $handoffJson = (!empty($outputJson[
'handoff_payload_json']) && is_array($outputJson[
'handoff_payload_json'])) ? $outputJson[
'handoff_payload_json'] : array();
343 'ai_request_log_id' => (
int) $obj->rowid,
344 'cleaning_id' => (
int) $obj->rowid,
345 'entity' => (
int) $obj->entity,
346 'actioncomm_id' => (
int) $obj->fk_actioncomm,
347 'collector_id' => (!empty($inputMetadata[
'collector_id']) ? (
int) $inputMetadata[
'collector_id'] : 0),
348 'message_id' => (!empty($inputMetadata[
'message_id']) ? (string) $inputMetadata[
'message_id'] :
''),
349 'raw_hash' => (!empty($inputMetadata[
'raw_hash']) ? (string) $inputMetadata[
'raw_hash'] :
null),
350 'clean_hash' => (!empty($inputMetadata[
'clean_hash']) ? (string) $inputMetadata[
'clean_hash'] :
null),
351 'clean_body' => (!empty($outputJson[
'clean_body']) ? (string) $outputJson[
'clean_body'] :
''),
352 'cleaning_confidence' => (
float) $obj->confidence,
353 'cleaning_model' => (!empty($outputJson[
'cleaning_model']) ? (string) $outputJson[
'cleaning_model'] :
null),
354 'prompt_code' => (!empty($inputMetadata[
'prompt_code']) ? (string) $inputMetadata[
'prompt_code'] :
null),
355 'prompt_version' => (!empty($inputMetadata[
'prompt_version']) ? (string) $inputMetadata[
'prompt_version'] :
null),
356 'context_profile_code' => (!empty($inputMetadata[
'context_profile_code']) ? (string) $inputMetadata[
'context_profile_code'] :
null),
357 'context_profile_version' => (!empty($inputMetadata[
'context_profile_version']) ? (string) $inputMetadata[
'context_profile_version'] :
null),
358 'input_hash' => (!empty($obj->input_hash) ? (string) $obj->input_hash :
null),
359 'output_hash' => (!empty($obj->output_hash) ? (string) $obj->output_hash :
null),
360 'security_hash' => (!empty($obj->security_hash) ? (string) $obj->security_hash :
null),
361 'status' => (!empty($obj->status) ? (string) $obj->status :
null),
362 'raw_request_payload' => $inputMetadata,
363 'cleaning_json' => $outputJson,
364 'handoff_payload_json' => $handoffJson,
365 'date_creation' => (!empty($obj->date_request) ? (string) $obj->date_request :
null),
378 if (!empty($run[
'error'])) {
382 $cleaningJson = (!empty($run[
'cleaning_json']) && is_array($run[
'cleaning_json'])) ? $run[
'cleaning_json'] : array();
383 $handoffJson = (!empty($run[
'handoff_payload_json']) && is_array($run[
'handoff_payload_json'])) ? $run[
'handoff_payload_json'] : array();
384 $emailContext = array();
386 if (!empty($cleaningJson[
'email_context']) && is_array($cleaningJson[
'email_context'])) {
387 $emailContext = $cleaningJson[
'email_context'];
388 } elseif (!empty($handoffJson[
'conversation_context']) && is_array($handoffJson[
'conversation_context'])) {
389 $emailContext = $handoffJson[
'conversation_context'];
393 'ai_request_log_id' => (
int) $run[
'ai_request_log_id'],
394 'cleaning_id' => (
int) $run[
'cleaning_id'],
395 'actioncomm_id' => (
int) $run[
'actioncomm_id'],
396 'collector_id' => (
int) $run[
'collector_id'],
397 'message_id' => (
string) $run[
'message_id'],
398 'email_context' => $emailContext,
399 'cleaning_confidence' => (
float) $run[
'cleaning_confidence'],
400 'context_profile_code' => (!empty($run[
'context_profile_code']) ? (
string) $run[
'context_profile_code'] :
null),
401 'context_profile_version' => (!empty($run[
'context_profile_version']) ? (string) $run[
'context_profile_version'] :
null),
445 if (isset($this->tableExistsCache[$tableWithoutPrefix])) {
446 return $this->tableExistsCache[$tableWithoutPrefix];
449 $full = MAIN_DB_PREFIX.$tableWithoutPrefix;
450 $ok = (bool) count($this->db->DDLInfoTable($full));
451 $this->tableExistsCache[$tableWithoutPrefix] = $ok;