$limit * 2) { $text = mb_substr($text, 0, mb_strlen($text, 'UTF-8') - 1, 'UTF-8'); } return $text; } public static function fact(int $id): array|WP_Error { $post = get_post($id); if (!$post || !TheDotDevAgenticBridge_Content_Metadata::is_artifact_eligible($post)) { return new WP_Error('question_source', __('This page is no longer eligible. Run the local check again.', 'agentic-bridge')); } $text = self::bounded_text(trim(wp_strip_all_tags(strip_shortcodes($post->post_content), true)), 2000); if ($text === '') return new WP_Error('question_empty', __('This page has no text to send.', 'agentic-bridge')); $url = get_permalink($post); if (!is_string($url) || !filter_var($url, FILTER_VALIDATE_URL) || !preg_match('#^https?://#i', $url) || strlen(mb_convert_encoding($url, 'UTF-16LE', 'UTF-8')) > 4096) { return new WP_Error('question_url', __('This page needs a valid public URL before testing.', 'agentic-bridge')); } $label = trim(wp_strip_all_tags($post->post_title)); return ['id'=>'page-' . $id, 'label'=>self::bounded_text($label !== '' ? $label : __('Untitled page', 'agentic-bridge'), 240), 'value'=>$text, 'url'=>$url, 'withheld'=>false, 'privateOrIneligible'=>false]; } public static function disclosure(string $question, array $fact): string { return hash('sha256', (string) wp_json_encode([$question, $fact])); } public static function prepare(string $question, int $id, string $reviewed, string $operation, bool $consent): array|WP_Error { if (!current_user_can('manage_options') || !$consent) return new WP_Error('question_consent', __('Review and approve the exact text before sending.', 'agentic-bridge')); if (!defined('TDAB_WP_SCENARIO_ENABLED') || TDAB_WP_SCENARIO_ENABLED !== true) return new WP_Error('question_disabled', __('Hosted question testing is not enabled on this site.', 'agentic-bridge')); if (mb_strlen($question) < 8 || mb_strlen($question) > 300 || strlen(mb_convert_encoding($question, 'UTF-16LE', 'UTF-8')) > 1000 || !preg_match('/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i', $operation)) return new WP_Error('question_invalid', __('Run the local check again before sending.', 'agentic-bridge')); $fact = self::fact($id); if (is_wp_error($fact)) return $fact; if (!hash_equals(self::disclosure($question, $fact), $reviewed)) return new WP_Error('question_changed', __('The question or source changed. Review it again before sending.', 'agentic-bridge')); return ['schemaVersion'=>'1.0', 'consent'=>true, 'request'=>['question'=>$question, 'mode'=>'provider_context', 'questionAssessment'=>true, 'selectedSourceRef'=>$fact['id'], 'operationKey'=>$operation], 'facts'=>[$fact]]; } }