PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
betterdocs / includes / Abilities / ProStubs.php

ProStubs.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.2, at includes/Abilities/ProStubs.php

654 lines 23.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Specifications for the Pro-only tools Free advertises.
4 *
5 * @package BetterDocs
6 * @since 4.9.0
7 */
8
9 namespace WPDeveloper\BetterDocs\Abilities;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly.
13 }
14
15 /**
16 * The five Pro tools, described in full by Free.
17 *
18 * Free registers a {@see StubAbility} from each of these specs so the tool
19 * catalog is the same shape on every BetterDocs site: same names, same labels,
20 * same input schemas, same capabilities. Only the behaviour differs — without
21 * Pro the tool answers with a typed refusal that says exactly what is missing.
22 *
23 * Pro's registrar returns real abilities carrying these same ids, and
24 * `AbilitiesRegistrar::build_abilities()` replaces the stubs by id. Keeping the
25 * specs in one class rather than inline in the registrar is what lets a unit
26 * test assert that Pro's ids and Free's stub ids never drift apart.
27 *
28 * @since 4.9.0
29 */
30 final class ProStubs {
31
32 /**
33 * Every Pro tool spec, in catalog order.
34 *
35 * Input schemas are the **real** ones, so a client can validate a call
36 * before Pro exists. They deliberately do not set `additionalProperties`:
37 * an unknown field should still reach the stub and come back as the
38 * `pro_required` refusal that explains the site, not as a schema error.
39 *
40 * @since 4.9.0
41 *
42 * @return array[] List of specs for {@see StubAbility::__construct()}.
43 */
44 public static function specs(): array {
45 return [
46 [
47 'id' => 'betterdocs-pro/create-knowledge-base',
48 'label' => __( 'Create knowledge base', 'betterdocs' ),
49 'description' => __( 'Create a knowledge base. Groups doc categories under a named knowledge base; pass categories by id or name to file them into it.', 'betterdocs' ),
50 'feature' => __( 'Knowledge bases', 'betterdocs' ),
51 'capability' => 'manage_knowledge_base_terms',
52 'kb_feature' => true,
53 'input_schema' => [
54 'type' => 'object',
55 'properties' => [
56 'name' => [
57 'type' => 'string',
58 'description' => __( 'Name of the knowledge base.', 'betterdocs' )
59 ],
60 'slug' => [
61 'type' => 'string',
62 'description' => __( 'URL slug. Derived from the name when omitted.', 'betterdocs' )
63 ],
64 'description' => [
65 'type' => 'string',
66 'description' => __( 'Short description shown on the knowledge-base listing.', 'betterdocs' )
67 ],
68 'categories' => self::categories_property()
69 ],
70 'required' => [ 'name' ]
71 ],
72 'output_schema' => self::knowledge_base_schema(),
73 'annotations' => self::annotations( false, false, false, 2.0 )
74 ],
75 [
76 'id' => 'betterdocs-pro/update-knowledge-base',
77 'label' => __( 'Update knowledge base', 'betterdocs' ),
78 'description' => __( 'Update a knowledge base. Rename it, change its slug or description, or replace the doc categories filed under it.', 'betterdocs' ),
79 'feature' => __( 'Knowledge bases', 'betterdocs' ),
80 'capability' => 'edit_knowledge_base_terms',
81 'kb_feature' => true,
82 'input_schema' => [
83 'type' => 'object',
84 'properties' => [
85 'id' => [
86 'type' => 'integer',
87 'description' => __( 'Knowledge-base term id.', 'betterdocs' )
88 ],
89 'name' => [
90 'type' => 'string',
91 'description' => __( 'New name.', 'betterdocs' )
92 ],
93 'slug' => [
94 'type' => 'string',
95 'description' => __( 'New URL slug.', 'betterdocs' )
96 ],
97 'description' => [
98 'type' => 'string',
99 'description' => __( 'New description.', 'betterdocs' )
100 ],
101 'categories' => self::categories_property()
102 ],
103 'required' => [ 'id' ]
104 ],
105 'output_schema' => self::knowledge_base_schema(),
106 'annotations' => self::annotations( false, false, true, 2.0 )
107 ],
108 [
109 'id' => 'betterdocs-pro/delete-knowledge-base',
110 'label' => __( 'Delete knowledge base', 'betterdocs' ),
111 'description' => __( 'Delete a knowledge base. The doc categories filed under it are unfiled, never deleted.', 'betterdocs' ),
112 'feature' => __( 'Knowledge bases', 'betterdocs' ),
113 'capability' => 'delete_knowledge_base_terms',
114 'kb_feature' => true,
115 'input_schema' => [
116 'type' => 'object',
117 'properties' => [
118 'id' => [
119 'type' => 'integer',
120 'description' => __( 'Knowledge-base term id.', 'betterdocs' )
121 ]
122 ],
123 'required' => [ 'id' ]
124 ],
125 'output_schema' => [
126 'type' => 'object',
127 'properties' => [
128 'id' => [ 'type' => 'integer' ],
129 'name' => [ 'type' => 'string' ],
130 'slug' => [ 'type' => 'string' ],
131 'deleted' => [ 'type' => 'boolean' ]
132 ]
133 ],
134 'annotations' => self::annotations( false, true, false, 2.0 )
135 ],
136 [
137 'id' => 'betterdocs-pro/list-knowledge-bases',
138 'label' => __( 'List knowledge bases', 'betterdocs' ),
139 'description' => __( 'List the knowledge bases on this site, each with the doc categories filed under it.', 'betterdocs' ),
140 'feature' => __( 'Knowledge bases', 'betterdocs' ),
141 'capability' => 'edit_docs',
142 'kb_feature' => true,
143 'input_schema' => [
144 'type' => 'object',
145 'properties' => [
146 'search' => [
147 'type' => 'string',
148 'description' => __( 'Match knowledge bases whose name contains this text.', 'betterdocs' )
149 ],
150 'page' => [
151 'type' => 'integer',
152 'minimum' => 1,
153 'description' => __( 'Page of results, 1-based.', 'betterdocs' )
154 ],
155 'per_page' => [
156 'type' => 'integer',
157 'minimum' => 1,
158 'maximum' => 100,
159 'description' => __( 'Results per page, up to 100.', 'betterdocs' )
160 ]
161 ],
162 // See GetStatus::get_input_schema(): without a top-level
163 // default an all-optional ability rejects a call that passes
164 // no arguments at all.
165 'default' => []
166 ],
167 'output_schema' => [
168 'type' => 'object',
169 'properties' => [
170 'items' => [
171 'type' => 'array',
172 'items' => self::knowledge_base_schema()
173 ],
174 'total' => [ 'type' => 'integer' ],
175 'total_pages' => [ 'type' => 'integer' ],
176 'page' => [ 'type' => 'integer' ],
177 'per_page' => [ 'type' => 'integer' ]
178 ]
179 ],
180 'annotations' => self::annotations( true, false, true, 1.0 )
181 ],
182 [
183 'id' => 'betterdocs-pro/get-analytics',
184 'label' => __( 'Get analytics', 'betterdocs' ),
185 'description' => __( 'Report site-wide BetterDocs analytics: views and reactions, the leading docs, categories and knowledge bases, and what visitors searched for.', 'betterdocs' ),
186 'feature' => __( 'Site-wide analytics', 'betterdocs' ),
187 'capability' => 'read_docs_analytics',
188 // Analytics does not depend on Multiple Knowledge Base, so the
189 // setting must never appear in its way: its only blocking states
190 // are "Pro is not here" and "Pro is not active".
191 'kb_feature' => false,
192 'input_schema' => [
193 'type' => 'object',
194 'properties' => [
195 'start_date' => self::date_property( __( 'First day to report on, as YYYY-MM-DD.', 'betterdocs' ) ),
196 'end_date' => self::date_property( __( 'Last day to report on, as YYYY-MM-DD.', 'betterdocs' ) ),
197 'per_page' => [
198 'type' => 'integer',
199 'minimum' => 1,
200 'maximum' => 100,
201 'description' => __( 'How many rows each leading-items list returns, up to 100.', 'betterdocs' )
202 ]
203 ],
204 'default' => []
205 ],
206 'output_schema' => [
207 'type' => 'object',
208 'properties' => [
209 'overview' => [ 'type' => 'object' ],
210 'leading_docs' => [ 'type' => 'array' ],
211 'leading_categories' => [ 'type' => 'array' ],
212 'leading_knowledge_bases' => [ 'type' => 'array' ],
213 'search' => [ 'type' => 'object' ]
214 ]
215 ],
216 'annotations' => self::annotations( true, false, true, 1.0 )
217 ],
218 [
219 'id' => 'betterdocs-pro/list-api-references',
220 'label' => __( 'List API references', 'betterdocs' ),
221 'description' => __( 'List the API references on this site, each with its title, slug, status, source and whether its spec has been materialized into docs.', 'betterdocs' ),
222 'feature' => __( 'API documentation', 'betterdocs' ),
223 'capability' => 'manage_options',
224 'kb_feature' => false,
225 'input_schema' => [
226 'type' => 'object',
227 'properties' => [],
228 'default' => []
229 ],
230 'output_schema' => [
231 'type' => 'object',
232 'properties' => [
233 'references' => [ 'type' => 'array' ],
234 'total' => [ 'type' => 'integer' ],
235 'max_references' => [ 'type' => [ 'integer', 'null' ] ]
236 ]
237 ],
238 'annotations' => self::annotations( true, false, true, 1.0 )
239 ],
240 [
241 'id' => 'betterdocs-pro/get-api-reference',
242 'label' => __( 'Get API reference', 'betterdocs' ),
243 'description' => __( 'Read one API reference by id: its settings and, when a spec has been ingested, a summary of the operations it documents.', 'betterdocs' ),
244 'feature' => __( 'API documentation', 'betterdocs' ),
245 'capability' => 'manage_options',
246 'kb_feature' => false,
247 'input_schema' => [
248 'type' => 'object',
249 'properties' => [
250 'id' => [
251 'type' => 'integer',
252 'description' => __( 'API reference id.', 'betterdocs' )
253 ],
254 'include_operations' => [
255 'type' => 'boolean',
256 'description' => __( 'Include a summarized list of the spec operations (method, path, summary).', 'betterdocs' )
257 ],
258 'max_operations' => [
259 'type' => 'integer',
260 'description' => __( 'Cap the number of operations returned when include_operations is true.', 'betterdocs' )
261 ]
262 ],
263 'required' => [ 'id' ]
264 ],
265 'output_schema' => self::api_reference_schema(),
266 'annotations' => self::annotations( true, false, true, 1.0 )
267 ],
268 [
269 'id' => 'betterdocs-pro/create-api-reference',
270 'label' => __( 'Create API reference', 'betterdocs' ),
271 'description' => __( 'Create an API reference. Title, slug and status are optional; the title is filled from the spec\'s info.title when a spec is later ingested and none was set.', 'betterdocs' ),
272 'feature' => __( 'API documentation', 'betterdocs' ),
273 'capability' => 'manage_options',
274 'kb_feature' => false,
275 'input_schema' => [
276 'type' => 'object',
277 'properties' => [
278 'title' => [
279 'type' => 'string',
280 'description' => __( 'Reference title. Optional — filled from the spec when omitted.', 'betterdocs' )
281 ],
282 'slug' => [
283 'type' => 'string',
284 'description' => __( 'URL slug. Derived from the title when omitted.', 'betterdocs' )
285 ],
286 'status' => [
287 'type' => 'string',
288 'enum' => [ 'draft', 'publish' ],
289 'description' => __( 'Publish state. Defaults to draft.', 'betterdocs' )
290 ]
291 ]
292 ],
293 'output_schema' => self::api_reference_schema(),
294 'annotations' => self::annotations( false, false, false, 2.0 )
295 ],
296 [
297 'id' => 'betterdocs-pro/update-api-reference',
298 'label' => __( 'Update API reference', 'betterdocs' ),
299 'description' => __( 'Update an API reference: rename it, change its slug or status, or adjust display settings such as the Try-it panel and code-sample theme.', 'betterdocs' ),
300 'feature' => __( 'API documentation', 'betterdocs' ),
301 'capability' => 'manage_options',
302 'kb_feature' => false,
303 'input_schema' => [
304 'type' => 'object',
305 'properties' => [
306 'id' => [
307 'type' => 'integer',
308 'description' => __( 'API reference id.', 'betterdocs' )
309 ],
310 'title' => [
311 'type' => 'string',
312 'description' => __( 'New title.', 'betterdocs' )
313 ],
314 'slug' => [
315 'type' => 'string',
316 'description' => __( 'New URL slug.', 'betterdocs' )
317 ],
318 'status' => [
319 'type' => 'string',
320 'enum' => [ 'draft', 'publish' ],
321 'description' => __( 'New publish state.', 'betterdocs' )
322 ],
323 'tryit_enabled' => [
324 'type' => 'boolean',
325 'description' => __( 'Show the interactive Try-it panel.', 'betterdocs' )
326 ],
327 'tryit_label' => [
328 'type' => 'string',
329 'description' => __( 'Label for the Try-it button.', 'betterdocs' )
330 ],
331 'code_theme' => [
332 'type' => 'string',
333 'enum' => [ 'light', 'dark' ],
334 'description' => __( 'Code-sample theme.', 'betterdocs' )
335 ]
336 ],
337 'required' => [ 'id' ]
338 ],
339 'output_schema' => self::api_reference_schema(),
340 'annotations' => self::annotations( false, false, true, 2.0 )
341 ],
342 [
343 'id' => 'betterdocs-pro/delete-api-reference',
344 'label' => __( 'Delete API reference', 'betterdocs' ),
345 'description' => __( 'Delete an API reference and its stored spec. Docs already materialized from it are left in place, never deleted.', 'betterdocs' ),
346 'feature' => __( 'API documentation', 'betterdocs' ),
347 'capability' => 'manage_options',
348 'kb_feature' => false,
349 'input_schema' => [
350 'type' => 'object',
351 'properties' => [
352 'id' => [
353 'type' => 'integer',
354 'description' => __( 'API reference id.', 'betterdocs' )
355 ]
356 ],
357 'required' => [ 'id' ]
358 ],
359 'output_schema' => [
360 'type' => 'object',
361 'properties' => [
362 'id' => [ 'type' => 'integer' ],
363 'title' => [ 'type' => 'string' ],
364 'deleted' => [ 'type' => 'boolean' ]
365 ]
366 ],
367 'annotations' => self::annotations( false, true, false, 2.0 )
368 ],
369 [
370 'id' => 'betterdocs-pro/ingest-api-spec',
371 'label' => __( 'Ingest API spec', 'betterdocs' ),
372 'description' => __( 'Ingest an OpenAPI or Postman spec into an API reference. Pass the raw spec text, or a source_url to fetch it from; this replaces any previously ingested spec.', 'betterdocs' ),
373 'feature' => __( 'API documentation', 'betterdocs' ),
374 'capability' => 'manage_options',
375 'kb_feature' => false,
376 'input_schema' => [
377 'type' => 'object',
378 'properties' => [
379 'id' => [
380 'type' => 'integer',
381 'description' => __( 'API reference id to ingest into.', 'betterdocs' )
382 ],
383 'spec' => [
384 'type' => 'string',
385 'description' => __( 'Raw spec document (JSON or YAML). Provide this or source_url.', 'betterdocs' )
386 ],
387 'source_url' => [
388 'type' => 'string',
389 'description' => __( 'URL to fetch the spec from. Provide this or spec.', 'betterdocs' )
390 ],
391 'format' => [
392 'type' => 'string',
393 'enum' => [ 'json', 'yaml' ],
394 'description' => __( 'Serialization of the spec text. Sniffed when omitted.', 'betterdocs' )
395 ]
396 ],
397 'required' => [ 'id' ]
398 ],
399 'output_schema' => [
400 'type' => 'object',
401 'properties' => [
402 'id' => [ 'type' => 'integer' ],
403 'result' => [ 'type' => 'string' ],
404 'source_kind' => [ 'type' => 'string' ],
405 'summary' => [ 'type' => [ 'object', 'null' ] ]
406 ]
407 ],
408 'annotations' => self::annotations( false, false, false, 2.0 )
409 ],
410 [
411 'id' => 'betterdocs-pro/materialize-api-reference',
412 'label' => __( 'Materialize API reference', 'betterdocs' ),
413 'description' => __( 'Turn an ingested API spec into BetterDocs docs, one per operation. Starts a background run and returns its state; call again with action "status" to check progress.', 'betterdocs' ),
414 'feature' => __( 'API documentation', 'betterdocs' ),
415 'capability' => 'manage_options',
416 'kb_feature' => false,
417 'input_schema' => [
418 'type' => 'object',
419 'properties' => [
420 'id' => [
421 'type' => 'integer',
422 'description' => __( 'API reference id.', 'betterdocs' )
423 ],
424 'action' => [
425 'type' => 'string',
426 'enum' => [ 'run', 'status' ],
427 'description' => __( 'run starts materialization; status reports an in-flight or finished run. Defaults to run.', 'betterdocs' )
428 ]
429 ],
430 'required' => [ 'id' ]
431 ],
432 'output_schema' => [
433 'type' => 'object',
434 'properties' => [
435 'id' => [ 'type' => 'integer' ],
436 'state' => [ 'type' => 'string' ],
437 'materialized' => [ 'type' => 'boolean' ],
438 'progress' => [ 'type' => [ 'object', 'null' ] ]
439 ]
440 ],
441 'annotations' => self::annotations( false, false, true, 2.0 )
442 ],
443 [
444 'id' => 'betterdocs-pro/get-search-insights',
445 'label' => __( 'Get search insights', 'betterdocs' ),
446 'description' => __( 'Read what visitors search for in the knowledge base: the most-used search terms and how often each was searched.', 'betterdocs' ),
447 'feature' => __( 'Search insights', 'betterdocs' ),
448 'capability' => 'read_docs_analytics',
449 'kb_feature' => false,
450 'input_schema' => [
451 'type' => 'object',
452 'properties' => [
453 'limit' => [
454 'type' => 'integer',
455 'description' => __( 'How many top search terms to return (default 20, max 100).', 'betterdocs' )
456 ]
457 ],
458 'default' => []
459 ],
460 'output_schema' => [
461 'type' => 'object',
462 'properties' => [
463 'keywords' => [ 'type' => 'array' ],
464 'total' => [ 'type' => 'integer' ]
465 ]
466 ],
467 'annotations' => self::annotations( true, false, true, 1.0 )
468 ],
469 [
470 'id' => 'betterdocs-pro/get-git-sync-status',
471 'label' => __( 'Get Git sync status', 'betterdocs' ),
472 'description' => __( 'Report the Git integration configuration and whether it is connected: provider, repository, branch, folder, file naming and auto-sync. Pass a doc id to also get that doc\'s last sync time and status.', 'betterdocs' ),
473 'feature' => __( 'Git sync', 'betterdocs' ),
474 'capability' => 'manage_options',
475 'kb_feature' => false,
476 'input_schema' => [
477 'type' => 'object',
478 'properties' => [
479 'doc_id' => [
480 'type' => 'integer',
481 'description' => __( 'Optional doc id to report per-document sync state for.', 'betterdocs' )
482 ]
483 ]
484 ],
485 'output_schema' => [
486 'type' => 'object',
487 'properties' => [
488 'enabled' => [ 'type' => 'boolean' ],
489 'connected' => [ 'type' => 'boolean' ],
490 'provider' => [ 'type' => 'string' ],
491 'repository_url' => [ 'type' => 'string' ],
492 'branch' => [ 'type' => 'string' ],
493 'docs_directory' => [ 'type' => 'string' ],
494 'file_naming' => [ 'type' => 'string' ],
495 'auto_sync' => [ 'type' => 'boolean' ],
496 'doc' => [ 'type' => [ 'object', 'null' ] ]
497 ]
498 ],
499 'annotations' => self::annotations( true, false, true, 1.0 )
500 ],
501 [
502 'id' => 'betterdocs-pro/get-related-docs',
503 'label' => __( 'Get related docs', 'betterdocs' ),
504 'description' => __( 'Read the saved related-doc suggestions for a doc — the persisted list shown under the article. Reads the cache only; it does not run the AI engine.', 'betterdocs' ),
505 'feature' => __( 'Related docs', 'betterdocs' ),
506 'capability' => 'edit_docs',
507 'kb_feature' => false,
508 'input_schema' => [
509 'type' => 'object',
510 'properties' => [
511 'doc_id' => [
512 'type' => 'integer',
513 'description' => __( 'Doc id to read related suggestions for.', 'betterdocs' )
514 ]
515 ],
516 'required' => [ 'doc_id' ]
517 ],
518 'output_schema' => [
519 'type' => 'object',
520 'properties' => [
521 'doc_id' => [ 'type' => 'integer' ],
522 'related' => [ 'type' => 'array' ],
523 'generated_at' => [ 'type' => [ 'string', 'integer', 'null' ] ]
524 ]
525 ],
526 'annotations' => self::annotations( true, false, true, 1.0 )
527 ]
528 ];
529 }
530
531 /**
532 * The ids Free advertises, in catalog order. Pro's registrar must return
533 * these exact ids for the by-id replacement to work.
534 *
535 * @since 4.9.0
536 *
537 * @return string[]
538 */
539 public static function ids(): array {
540 return array_column( self::specs(), 'id' );
541 }
542
543 /**
544 * The `categories` input property, shared by create and update: doc
545 * categories addressed by id or by name.
546 *
547 * @since 4.9.0
548 *
549 * @return array
550 */
551 private static function categories_property(): array {
552 return [
553 'type' => 'array',
554 'items' => [ 'type' => [ 'integer', 'string' ] ],
555 'description' => __( 'Doc categories to file under this knowledge base, by term id or by name.', 'betterdocs' )
556 ];
557 }
558
559 /**
560 * A YYYY-MM-DD date input property.
561 *
562 * `pattern` rather than `format`: the REST schema validator WordPress uses
563 * for abilities knows `date-time`, not `date`, and silently ignores formats
564 * it does not know.
565 *
566 * @since 4.9.0
567 *
568 * @param string $description Field description.
569 * @return array
570 */
571 private static function date_property( string $description ): array {
572 return [
573 'type' => 'string',
574 'pattern' => '^\\d{4}-\\d{2}-\\d{2}$',
575 'description' => $description
576 ];
577 }
578
579 /**
580 * The shape one knowledge base comes back as.
581 *
582 * Permissive on purpose: the Abilities API validates an ability's output
583 * against this schema, so nothing is `required` and no
584 * `additionalProperties: false` is set — a Pro build that returns one extra
585 * field must not turn a successful call into a validation error.
586 *
587 * @since 4.9.0
588 *
589 * @return array
590 */
591 private static function knowledge_base_schema(): array {
592 return [
593 'type' => 'object',
594 'properties' => [
595 'id' => [ 'type' => 'integer' ],
596 'name' => [ 'type' => 'string' ],
597 'slug' => [ 'type' => 'string' ],
598 'description' => [ 'type' => 'string' ],
599 'categories' => [ 'type' => 'array' ]
600 ]
601 ];
602 }
603
604 /**
605 * Annotation block in the Abilities API's spelling.
606 *
607 * @since 4.9.0
608 *
609 * @param bool $read_only Whether the tool only reads.
610 * @param bool $destructive Whether the tool destroys data.
611 * @param bool $idempotent Whether repeating the call is harmless.
612 * @param float $priority Ordering hint; 1.0 for reads, 2.0 for writes.
613 * @return array
614 */
615 /**
616 * The shape one API reference comes back as.
617 *
618 * Permissive on purpose, like {@see self::knowledge_base_schema()}: the
619 * Abilities API validates output against this, so nothing is `required` and
620 * a Pro build that adds a field must not fail an otherwise-good call.
621 *
622 * @since 4.9.1
623 *
624 * @return array
625 */
626 private static function api_reference_schema(): array {
627 return [
628 'type' => 'object',
629 'properties' => [
630 'id' => [ 'type' => 'integer' ],
631 'title' => [ 'type' => 'string' ],
632 'slug' => [ 'type' => 'string' ],
633 'status' => [ 'type' => 'string' ],
634 'permalink' => [ 'type' => 'string' ],
635 'source' => [ 'type' => 'string' ],
636 'source_kind' => [ 'type' => 'string' ],
637 'materialized' => [ 'type' => 'boolean' ],
638 'summary' => [ 'type' => [ 'object', 'null' ] ],
639 'operations' => [ 'type' => 'array' ]
640 ]
641 ];
642 }
643
644 private static function annotations( bool $read_only, bool $destructive, bool $idempotent, float $priority ): array {
645 return [
646 'readonly' => $read_only,
647 'destructive' => $destructive,
648 'idempotent' => $idempotent,
649 'priority' => $priority,
650 'openWorldHint' => false
651 ];
652 }
653 }
654