| 1 |
<?php |
| 2 |
/** Cooperative messaging: the connected agent polls; WordPress cannot wake a stopped client. */ |
| 3 |
if ( ! defined( 'ABSPATH' ) ) { exit; } |
| 4 |
function bkbg_external_conversation( $s ) { |
| 5 |
$library = bkbg_chat_read( $s['user'], $s['post'] ); |
| 6 |
$messages = $library['chats'][ $s['chat_id'] ?? '' ]['messages'] ?? array(); |
| 7 |
return array_values( array_map( function ( $m ) { return array_intersect_key( $m, array_flip( array( 'role', 'text', 'status', 'id' ) ) ); }, array_slice( $messages, -100 ) ) ); |
| 8 |
} |
| 9 |
function bkbg_external_message( $request, $editor = false ) { |
| 10 |
$id = $request['id']; $text = $request['text']; $role = $editor ? 'user' : $request['role']; |
| 11 |
if ( ! bkbg_chat_valid_id( $id ) || ! is_string( $text ) || ! trim( $text ) || strlen( $text ) > 24000 || ! in_array( $role, array( 'user', 'assistant' ), true ) ) { return bkbg_external_error( 'Supply a unique id, role and message text (up to 24 KB).' ); } |
| 12 |
$result = bkbg_external_change( $request['session'], function ( &$s ) use ( $id, $text, $role, $editor, $request ) { |
| 13 |
$messages = $s['messages'] ?? array(); |
| 14 |
if ( isset( $messages[ $id ] ) ) { |
| 15 |
$m = $messages[ $id ]; |
| 16 |
return $m['text'] === $text && $m['role'] === $role && $m['source'] === ( $editor ? 'panel' : 'agent' ) ? $m : bkbg_external_error( 'Message id belongs to different content.', 409 ); |
| 17 |
} |
| 18 |
if ( count( $messages ) >= 300 ) { return bkbg_external_error( 'Message capacity reached. Reconnect to continue this saved chat.', 409 ); } |
| 19 |
$m = array( 'id' => $id, 'role' => $role, 'text' => $text, 'external' => true, 'source' => $editor ? 'panel' : 'agent', 'status' => $editor ? 'queued' : 'received', 'created' => microtime( true ) * 1000 ); |
| 20 |
$s['messages'][ $id ] = $m; |
| 21 |
if ( ! $editor ) { $s['agent_seen'] = time(); } |
| 22 |
return $m; |
| 23 |
} ); |
| 24 |
if ( is_wp_error( $result ) ) { return $result; } |
| 25 |
$saved = bkbg_chat_append( bkbg_external_read( $request['session'] ), $result ); |
| 26 |
return is_wp_error( $saved ) ? $saved : $result; |
| 27 |
} |
| 28 |
function bkbg_external_inbox( $request ) { |
| 29 |
return bkbg_external_change( $request['session'], function ( &$s ) { |
| 30 |
$s['agent_seen'] = time(); |
| 31 |
return array( 'messages' => array_values( array_filter( $s['messages'] ?? array(), function ( $m ) { return 'panel' === $m['source'] && 'queued' === $m['status']; } ) ) ); |
| 32 |
} ); |
| 33 |
} |
| 34 |
function bkbg_external_ack_message( $request ) { |
| 35 |
$result = bkbg_external_change( $request['session'], function ( &$s ) use ( $request ) { |
| 36 |
$id = $request['message']; |
| 37 |
if ( empty( $s['messages'][ $id ] ) || 'panel' !== $s['messages'][ $id ]['source'] ) { return bkbg_external_error( 'Unknown inbox message.', 404 ); } |
| 38 |
$s['messages'][ $id ]['status'] = 'read'; $s['agent_seen'] = time(); |
| 39 |
return $s['messages'][ $id ]; |
| 40 |
} ); |
| 41 |
if ( is_wp_error( $result ) ) { return $result; } |
| 42 |
$saved = bkbg_chat_append( bkbg_external_read( $request['session'] ), $result ); |
| 43 |
return is_wp_error( $saved ) ? $saved : $result; |
| 44 |
} |
| 45 |
add_action( 'rest_api_init', function () { |
| 46 |
$base = '/ai/external/(?P<session>[a-f0-9]{32})'; |
| 47 |
register_rest_route( 'blockenberg/v1', $base . '/messages', array( 'methods' => 'POST', 'callback' => 'bkbg_external_message', 'permission_callback' => function ( $r ) { return bkbg_external_authorize( $r ); } ) ); |
| 48 |
register_rest_route( 'blockenberg/v1', $base . '/outbox', array( 'methods' => 'POST', 'callback' => function ( $r ) { return bkbg_external_message( $r, true ); }, 'permission_callback' => function ( $r ) { return bkbg_external_authorize( $r, true ); } ) ); |
| 49 |
register_rest_route( 'blockenberg/v1', $base . '/inbox', array( 'methods' => 'GET', 'callback' => 'bkbg_external_inbox', 'permission_callback' => function ( $r ) { return bkbg_external_authorize( $r ); } ) ); |
| 50 |
register_rest_route( 'blockenberg/v1', $base . '/inbox/(?P<message>[a-zA-Z0-9_-]{8,80})/ack', array( 'methods' => 'POST', 'callback' => 'bkbg_external_ack_message', 'permission_callback' => function ( $r ) { return bkbg_external_authorize( $r ); } ) ); |
| 51 |
} ); |
| 52 |
|