PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.8
1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 0.8.6 All 33 releases
desktop-mode / includes / ai-copilot / settings.php

settings.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.8, at includes/ai-copilot/settings.php

225 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — AI Copilot settings + capability helpers.
4 *
5 * The Copilot no longer stores credentials of its own. WordPress 7.0 owns
6 * provider credentials (Settings → Connectors) and model routing
7 * (`wp_ai_client_prompt()`, which injects the configured key automatically).
8 * These helpers therefore only carry the per-user "AI assistant" toggle
9 * (`ai.enabled`) and expose the Core capability signals the shell uses to
10 * decide whether to surface the assistant at all. Provider + model selection
11 * is delegated entirely to the Core AI Client — nothing is persisted here.
12 *
13 * @package OpenStation
14 */
15
16 defined( 'ABSPATH' ) || exit;
17
18 /**
19 * Returns the AI settings block for a given user.
20 *
21 * `enabled` defaults to `false`: the assistant is opt-in, turned on from
22 * OS Settings → Features (and only enable-able once a provider is configured).
23 * Provider + model selection is left entirely to the Core AI Client.
24 *
25 * @param int $user_id
26 * @return array{ enabled: bool }
27 */
28 function openstation_ai_get_settings( $user_id ) {
29 $os = openstation_get_os_settings( (int) $user_id );
30 $ai = isset( $os['ai'] ) && is_array( $os['ai'] ) ? $os['ai'] : array();
31 return array(
32 'enabled' => isset( $ai['enabled'] ) ? (bool) $ai['enabled'] : false,
33 );
34 }
35
36 /**
37 * Whether the Core AI primitives the Copilot depends on are present.
38 *
39 * The assistant is built on the AI Client (generation), the Connectors API
40 * (credentials) and the Abilities API (tools, adopted in a follow-up). When
41 * any of these is missing — e.g. WordPress < 7.0, or AI disabled site-wide
42 * via `wp_supports_ai()` — the shell hides the assistant entirely.
43 *
44 * @return bool
45 */
46 function openstation_ai_is_available() {
47 return function_exists( 'wp_ai_client_prompt' )
48 && function_exists( 'wp_get_connectors' )
49 && function_exists( 'wp_register_ability' )
50 && function_exists( 'wp_supports_ai' )
51 && wp_supports_ai();
52 }
53
54 /**
55 * Whether a text-generation provider is configured and usable.
56 *
57 * The baseline capability gate: a no-network, deterministic
58 * `is_supported_for_text_generation()` probe against the AI Client registry
59 * (which Core populates from the configured Connectors). This is what plain
60 * text-generation features — e.g. comment scoring, which only needs structured
61 * text output — gate on. The agentic assistant needs more; see
62 * {@see openstation_ai_assistant_provider_configured()}.
63 *
64 * Credentials are supplied by Core from the configured Connector; no API request
65 * is made.
66 *
67 * @return bool
68 */
69 function openstation_ai_provider_configured() {
70 if ( ! openstation_ai_is_available() ) {
71 return false;
72 }
73 return (bool) wp_ai_client_prompt( 'test' )->is_supported_for_text_generation();
74 }
75
76 /**
77 * Whether a provider that can actually run the agentic assistant is configured.
78 *
79 * Follows the AI Client feature-detection guidance: rather than probing a bare
80 * builder, we configure it the way the assistant actually calls the client —
81 * with a function declaration — before the (no-network, deterministic)
82 * `is_supported_for_text_generation()` check. `ModelRequirements::fromPromptData()`
83 * turns the attached declaration into a `functionDeclarations` requirement, so
84 * the check passes only when an available model supports text generation *and*
85 * function calling — the two capabilities the tool loop depends on.
86 *
87 * Falls back to the plain text-generation gate when the SDK's FunctionDeclaration
88 * class isn't present (e.g. older WordPress).
89 *
90 * @return bool
91 */
92 function openstation_ai_assistant_provider_configured() {
93 if ( ! openstation_ai_is_available() ) {
94 return false;
95 }
96
97 $probe = openstation_ai_capability_probe_declaration();
98 if ( ! $probe ) {
99 return openstation_ai_provider_configured();
100 }
101
102 return (bool) wp_ai_client_prompt( 'test' )
103 ->using_function_declarations( $probe )
104 ->is_supported_for_text_generation();
105 }
106
107 /**
108 * Builds a throwaway function declaration used only for capability detection.
109 *
110 * Mirrors the shape of the Copilot's real tool declarations so the AI Client's
111 * support check additionally requires function-calling capability. Returns null
112 * when the SDK class isn't available, letting the caller fall back to a plain
113 * text-generation check.
114 *
115 * @return object|null A `FunctionDeclaration`, or null.
116 */
117 function openstation_ai_capability_probe_declaration() {
118 $class = '\WordPress\AiClient\Tools\DTO\FunctionDeclaration';
119 if ( ! class_exists( $class ) ) {
120 return null;
121 }
122 try {
123 return new $class(
124 'capability_probe',
125 'Feature-detection probe; never invoked.',
126 null
127 );
128 } catch ( \Throwable $e ) {
129 return null;
130 }
131 }
132
133 /**
134 * Whether the AI assistant is active for a given user.
135 *
136 * This is purely the per-user toggle (default off, opt-in). Availability of the Core
137 * APIs and whether a provider key is set are separate, orthogonal checks
138 * ({@see openstation_ai_is_available()} / {@see openstation_ai_provider_configured()})
139 * so callers can distinguish "user turned it off" from "not set up yet".
140 *
141 * @param int $user_id
142 * @return bool
143 */
144 function openstation_ai_is_enabled( $user_id ) {
145 $ai = openstation_ai_get_settings( (int) $user_id );
146 return ! empty( $ai['enabled'] );
147 }
148
149 /**
150 * Builds the `aiAssistant` shell-config payload for a user.
151 *
152 * The client uses this to decide whether to surface the Cmd+K assistant and
153 * its admin-bar icon at all (`available`) and the user's own on/off toggle
154 * (`enabled`). Two capability gates are reported separately:
155 *
156 * - `assistantProviderConfigured` — a provider that supports text generation
157 * *and* function calling (what the agentic assistant needs). Gates the Cmd+K
158 * assistant, its admin-bar icon, and the "AI assistant" toggle in Features.
159 * - `providerConfigured` — the baseline text-generation gate. Comment scoring
160 * (which only needs text output) gates on this; the client uses it for the
161 * "Score new comments with AI" mirror.
162 *
163 * Provider + model selection is delegated to the Core AI Client, so there is no
164 * per-user preference to carry here.
165 *
166 * @param int|null $user_id Defaults to the current user.
167 * @return array{ available: bool, providerConfigured: bool, assistantProviderConfigured: bool, enabled: bool, connectorsUrl: string }
168 */
169 function openstation_ai_assistant_config( $user_id = null ) {
170 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
171
172 $connectors_url = admin_url( 'options-connectors.php' );
173
174 if ( ! openstation_ai_is_available() ) {
175 return array(
176 'available' => false,
177 'providerConfigured' => false,
178 'assistantProviderConfigured' => false,
179 'enabled' => false,
180 'connectorsUrl' => $connectors_url,
181 );
182 }
183
184 $ai = openstation_ai_get_settings( $user_id );
185
186 return array(
187 'available' => true,
188 'providerConfigured' => openstation_ai_provider_configured(),
189 'assistantProviderConfigured' => openstation_ai_assistant_provider_configured(),
190 'enabled' => (bool) $ai['enabled'],
191 'connectorsUrl' => $connectors_url,
192 );
193 }
194
195 /**
196 * REST: GET `desktop-mode/v1/ai/status`.
197 *
198 * Returns the current {@see openstation_ai_assistant_config()} so the shell
199 * can re-check provider availability without a page reload — e.g. after the
200 * user configures an AI provider in Settings → Connectors.
201 */
202 function openstation_register_ai_status_rest_route() {
203 register_rest_route(
204 'desktop-mode/v1',
205 '/ai/status',
206 array(
207 'methods' => WP_REST_Server::READABLE,
208 'callback' => 'openstation_rest_ai_status',
209 'permission_callback' => static function () {
210 return is_user_logged_in() && current_user_can( 'read' );
211 },
212 )
213 );
214 }
215 add_action( 'rest_api_init', 'openstation_register_ai_status_rest_route' );
216
217 /**
218 * REST handler for the AI status probe.
219 *
220 * @return WP_REST_Response
221 */
222 function openstation_rest_ai_status() {
223 return rest_ensure_response( openstation_ai_assistant_config() );
224 }
225