forked from WordPress/wordpress-develop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclass-wp-ai-client-ability-function-resolver.php
More file actions
181 lines (161 loc) · 4.63 KB
/
class-wp-ai-client-ability-function-resolver.php
File metadata and controls
181 lines (161 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?php
/**
* WP AI Client: WP_AI_Client_Ability_Function_Resolver class
*
* @package WordPress
* @subpackage AI
* @since 7.0.0
*/
use WordPress\AiClient\Messages\DTO\Message;
use WordPress\AiClient\Messages\DTO\MessagePart;
use WordPress\AiClient\Messages\DTO\UserMessage;
use WordPress\AiClient\Tools\DTO\FunctionCall;
use WordPress\AiClient\Tools\DTO\FunctionResponse;
/**
* Resolves and executes WordPress Abilities API function calls from AI models.
*
* @since 7.0.0
*/
class WP_AI_Client_Ability_Function_Resolver {
/**
* Prefix used to identify ability function calls.
*
* @since 7.0.0
* @var string
*/
private const ABILITY_PREFIX = 'wpab__';
/**
* Checks if a function call is an ability call.
*
* @since 7.0.0
*
* @param FunctionCall $call The function call to check.
* @return bool True if the function call is an ability call, false otherwise.
*/
public static function is_ability_call( FunctionCall $call ): bool {
$name = $call->getName();
if ( null === $name ) {
return false;
}
return str_starts_with( $name, self::ABILITY_PREFIX );
}
/**
* Executes a WordPress ability from a function call.
*
* @since 7.0.0
*
* @param FunctionCall $call The function call to execute.
* @return FunctionResponse The response from executing the ability.
*/
public static function execute_ability( FunctionCall $call ): FunctionResponse {
$function_name = $call->getName() ?? 'unknown';
$function_id = $call->getId() ?? 'unknown';
if ( ! self::is_ability_call( $call ) ) {
return new FunctionResponse(
$function_id,
$function_name,
array(
'error' => 'Not an ability function call',
'code' => 'invalid_ability_call',
)
);
}
$ability_name = self::function_name_to_ability_name( $function_name );
$ability = wp_get_ability( $ability_name );
if ( ! $ability instanceof WP_Ability ) {
return new FunctionResponse(
$function_id,
$function_name,
array(
'error' => sprintf( 'Ability "%s" not found', $ability_name ),
'code' => 'ability_not_found',
)
);
}
$args = $call->getArgs();
$result = $ability->execute( ! empty( $args ) ? $args : null );
if ( is_wp_error( $result ) ) {
return new FunctionResponse(
$function_id,
$function_name,
array(
'error' => $result->get_error_message(),
'code' => $result->get_error_code(),
'data' => $result->get_error_data(),
)
);
}
return new FunctionResponse(
$function_id,
$function_name,
$result
);
}
/**
* Checks if a message contains any ability function calls.
*
* @since 7.0.0
*
* @param Message $message The message to check.
* @return bool True if the message contains ability calls, false otherwise.
*/
public static function has_ability_calls( Message $message ): bool {
foreach ( $message->getParts() as $part ) {
if ( $part->getType()->isFunctionCall() ) {
$function_call = $part->getFunctionCall();
if ( $function_call instanceof FunctionCall && self::is_ability_call( $function_call ) ) {
return true;
}
}
}
return false;
}
/**
* Executes all ability function calls in a message.
*
* @since 7.0.0
*
* @param Message $message The message containing function calls.
* @return Message A new message with function responses.
*/
public static function execute_abilities( Message $message ): Message {
$response_parts = array();
foreach ( $message->getParts() as $part ) {
if ( $part->getType()->isFunctionCall() ) {
$function_call = $part->getFunctionCall();
if ( $function_call instanceof FunctionCall ) {
$function_response = self::execute_ability( $function_call );
$response_parts[] = new MessagePart( $function_response );
}
}
}
return new UserMessage( $response_parts );
}
/**
* Converts an ability name to a function name.
*
* Transforms "tec/create_event" to "wpab__tec__create_event".
*
* @since 7.0.0
*
* @param string $ability_name The ability name to convert.
* @return string The function name.
*/
public static function ability_name_to_function_name( string $ability_name ): string {
return self::ABILITY_PREFIX . str_replace( '/', '__', $ability_name );
}
/**
* Converts a function name to an ability name.
*
* Transforms "wpab__tec__create_event" to "tec/create_event".
*
* @since 7.0.0
*
* @param string $function_name The function name to convert.
* @return string The ability name.
*/
private static function function_name_to_ability_name( string $function_name ): string {
$without_prefix = substr( $function_name, strlen( self::ABILITY_PREFIX ) );
return str_replace( '__', '/', $without_prefix );
}
}