| @@ -193,14 +193,22 @@ | ||
| 193 | 193 | 'methods' => WP_REST_Server::CREATABLE, |
| 194 | 194 | 'permission_callback' => 'openstation_agents_rest_invoke_permission', |
| 195 | 195 | 'callback' => 'openstation_agents_rest_invoke', |
| 196 | 196 | 'args' => array( |
| 197 | - 'message' => array( | |
| 197 | + 'async' => array( | |
| 198 | + 'type' => 'boolean', | |
| 199 | + 'default' => false, | |
| 200 | + ), | |
| 201 | + 'requestId' => array( | |
| 202 | + 'type' => 'string', | |
| 203 | + 'format' => 'uuid', | |
| 204 | + ), | |
| 205 | + 'message' => array( | |
| 198 | 206 | 'type' => 'string', |
| 199 | 207 | 'required' => true, |
| 200 | 208 | 'sanitize_callback' => 'sanitize_textarea_field', |
| 201 | 209 | ), |
| 202 | - 'source' => array( | |
| 210 | + 'source' => array( | |
| 203 | 211 | 'type' => 'string', |
| 204 | 212 | 'default' => 'chat', |
| 205 | 213 | 'enum' => array( 'chat', 'drag', 'send-to' ), |
| 206 | 214 | 'sanitize_callback' => 'sanitize_key', |
| @@ -208,9 +216,9 @@ | ||
| 208 | 216 | // Prior conversation turns, oldest first. Without these |
| 209 | 217 | // every message is a contextless run — a follow-up like |
| 210 | 218 | // "yes, do it" would be resolved against nothing and the |
| 211 | 219 | // agent could act on the wrong entity entirely. |
| 212 | - 'history' => array( | |
| 220 | + 'history' => array( | |
| 213 | 221 | 'type' => 'array', |
| 214 | 222 | 'default' => array(), |
| 215 | 223 | 'items' => array( |
| 216 | 224 | 'type' => 'object', |
| @@ -471,10 +479,11 @@ | ||
| 471 | 479 | |
| 472 | 480 | $source = (string) $request['source']; |
| 473 | 481 | |
| 474 | 482 | // Per-agent gate. The route's `permission_callback` cannot run this |
| 475 | - // one: it has no access to the resolved agent, and the capability an | |
| 476 | - // agent requires is a property of that agent's trigger config. | |
| 483 | + // one: it has no access to the resolved agent, and the capabilities an | |
| 484 | + // agent requires are a property of that agent's trigger config. The | |
| 485 | + // gate applies all of them whatever `source` the request names. | |
| 477 | 486 | if ( ! openstation_agent_user_can_invoke_agent( (int) $user->ID, $source ) ) { |
| 478 | 487 | return new WP_Error( |
| 479 | 488 | 'openstation_agents_forbidden', |
| 480 | 489 | __( 'You do not have permission to invoke this agent.', 'desktop-mode' ), |
| @@ -481,8 +490,12 @@ | ||
| 481 | 490 | array( 'status' => rest_authorization_required_code() ) |
| 482 | 491 | ); |
| 483 | 492 | } |
| 484 | 493 | |
| 494 | + if ( $request['async'] ) { | |
| 495 | + return openstation_agents_rest_enqueue_job( $request ); | |
| 496 | + } | |
| 497 | + | |
| 485 | 498 | $result = openstation_agent_invoke( |
| 486 | 499 | (int) $user->ID, |
| 487 | 500 | (string) $request['message'], |
| 488 | 501 | array( |
| @@ -602,9 +615,9 @@ | ||
| 602 | 615 | |
| 603 | 616 | return array( |
| 604 | 617 | 'id' => (int) $user->ID, |
| 605 | 618 | 'slug' => $slug, |
| 606 | - 'name' => (string) $user->display_name, | |
| 619 | + 'name' => openstation_plain_text_title( $user->display_name ), | |
| 607 | 620 | 'description' => openstation_agent_get_description( (int) $user->ID ), |
| 608 | 621 | 'instructions' => openstation_agent_get_instructions( (int) $user->ID ), |
| 609 | 622 | 'role' => $role, |
| 610 | 623 | 'abilities' => openstation_agent_get_abilities( (int) $user->ID ), |