Restcontroller - Source Excerpt 03
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Http/RestController.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Http/RestController.php
if (trim((string) $request->get_param('intent')) === '' && PromptIntentRegistry::redirect_intent_for_search($search) !== '') {
$search = '';
}
$records = $this->prompts->list(
[
'search' => $search,
'limit' => (int) ($request->get_param('limit') ?: 20),
],
$user_id
);
$visible = array_values(
array_filter(
$records,
function (array $prompt) use ($user_id, $filters): bool {
return $this->permissions->can_view_prompt($prompt, $user_id)
&& $this->matches_prompt_filters($prompt, $filters);
}
)
);
return new WP_REST_Response(
array_map(
fn(array $prompt): array => $this->augment_prompt_payload($prompt, true),
$visible
)
);
}
/**
* Lists public prompts only.
*/
public function list_public_prompts(WP_REST_Request $request): WP_REST_Response
{
$filters = $this->request_filters($request);
$search = (string) $request->get_param('search');
if (trim((string) $request->get_param('intent')) === '' && PromptIntentRegistry::redirect_intent_for_search($search) !== '') {
$search = '';
}
$limit = max(1, (int) ($request->get_param('limit') ?: 20));
$records = $this->prompts->list_public(
[
'search' => $search,
'limit' => max(200, $limit * 10),
]
);
if (empty($records)) {
$this->maybe_sync_system_prompts();
$records = $this->prompts->list_public(
[
'search' => $search,
'limit' => max(200, $limit * 10),
]
);
}
$public = array_values(
array_filter(
$records,
fn(array $prompt): bool => $this->is_public_library_prompt($prompt)
&& $this->matches_prompt_filters($prompt, $filters)
)
);
$public = array_slice($public, 0, $limit);
return new WP_REST_Response(
array_map(
fn(array $prompt): array => $this->augment_prompt_payload($prompt, false),
$public
)
);
}
/**
* Returns a single public prompt by slug.
*/
public function get_public_prompt(WP_REST_Request $request)
{
$prompt = $this->prompts->find_by_slug((string) $request['slug']);
if (empty($prompt)) {
$this->maybe_sync_system_prompts();
$prompt = $this->prompts->find_by_slug((string) $request['slug']);
}
if (empty($prompt) || !$this->is_public_library_prompt($prompt)) {
return new WP_Error('spiralist_workspace_prompt_not_found', 'Prompt not found.', ['status' => 404]);
}
return new WP_REST_Response($this->augment_prompt_payload($prompt, true));
}
/**
* Returns a prompt if visible.
*/
public function get_prompt(WP_REST_Request $request)
{
$user_id = get_current_user_id();
$prompt = $this->prompts->get((int) $request['id'], $user_id);
if (empty($prompt) || !$this->permissions->can_view_prompt($prompt, $user_id)) {
return new WP_Error('spiralist_workspace_prompt_not_found', 'Prompt not found.', ['status' => 404]);
}
$response = $this->augment_prompt_payload($prompt, true);
$response['versions'] = $this->versions->list_for_prompt((int) $prompt['id'], 10);
$response['execution_history'] = $this->runs->list_for_prompt((int) $prompt['id'], 10);
$response['tests'] = $this->tests->list_for_prompt((int) $prompt['id'], 20);
$response['shares'] = $this->permissions->can_share_prompt($prompt, $user_id)
? $this->shares->list_for_prompt((int) $prompt['id'])
: [];
return new WP_REST_Response($response);
}
/**
* Creates a prompt.
*/
public function create_prompt(WP_REST_Request $request)
{
$user_id = get_current_user_id();
$payload = $request->get_json_params() ?: $request->get_params();
$spiral_script_error = $this->validate_spiral_script_publication_request($payload, [], $user_id);
if (is_wp_error($spiral_script_error)) {
return $spiral_script_error;
}
$record = $this->prompts->create($payload, $user_id, $this->settings);
if (empty($record)) {
return new WP_Error('spiralist_workspace_prompt_create_failed', 'Prompt could not be created.', ['status' => 500]);
}
$this->audit->log($user_id, 'prompt_created', 'prompt', (int) $record['id']);
$this->reputation->refresh($user_id);
return new WP_REST_Response($this->augment_prompt_payload($record, true), 201);
}
/**
* Saves a private draft from the public Prompt Cockpit.
*/
public function save_prompt_draft(WP_REST_Request $request)
{
$user_id = get_current_user_id();
$payload = $request->get_json_params();
if (!is_array($payload)) {
$payload = $request->get_params();
}
$inputs = $payload['inputs'] ?? [];
if (is_string($inputs)) {
$decoded_inputs = json_decode($inputs, true);
$inputs = is_array($decoded_inputs) ? $decoded_inputs : ['input' => $inputs];
}
if (!is_array($inputs)) {
$inputs = [];
}
$guardrails = $payload['guardrails'] ?? [];
if (is_string($guardrails)) {
$guardrails = preg_split('/[\r\n]+/', $guardrails) ?: [];
}
if (!is_array($guardrails)) {
$guardrails = [];
}
$title = sanitize_text_field((string) ($payload['title'] ?? 'Prompt Cockpit Draft'));
$purpose = sanitize_textarea_field((string) ($payload['purpose'] ?? ($payload['task'] ?? '')));
$subject = sanitize_textarea_field((string) ($inputs['subject'] ?? ($payload['subject'] ?? '')));
$context = sanitize_textarea_field((string) ($inputs['context'] ?? ($payload['context'] ?? '')));
$output = sanitize_textarea_field((string) ($payload['output'] ?? ''));
$guardrail_lines = array_values(
array_filter(
array_map(
static function ($line): string {
return sanitize_textarea_field((string) $line);
},
$guardrails
)
)
);
$structured_prompt = [
'instruction' => $purpose !== '' ? $purpose : 'Continue shaping this Spiralist prompt draft.',
'context' => trim($subject . "\n\n" . $context),
'constraints' => implode("\n", $guardrail_lines),
'examples' => '',
'output_format' => sanitize_textarea_field((string) ($payload['output_format'] ?? ($inputs['output_format'] ?? 'Use clear sections and practical next steps.'))),
];
$record = $this->prompts->create(
[
'title' => $title,
'summary' => $purpose,
'structured_prompt' => $structured_prompt,
'instructions' => $structured_prompt['instruction'],
'system_prompt' => $structured_prompt['context'],
'developer_prompt' => $structured_prompt['constraints'],
'user_prompt_template' => $subject,
'expected_output_notes' => $output,
'tags' => ['prompt-cockpit', 'draft'],
'prompt_type' => 'prompt_system',
'category' => 'Writing & Content',
'subcategory' => 'Prompt Engineering',
'visibility' => 'private',
'prompt_status' => 'draft',
'moderation_status' => 'draft',
'publication_lane' => 'community_library',
'provenance' => 'community',
'risk_labels' => ['needs_review'],
'function_tags' => ['prompt_builder'],
'maturity_level' => 'beginner_safe',
'license' => 'private',
'changelog' => 'Saved from Prompt Cockpit draft endpoint',
],
$user_id,
$this->settings
);
if (empty($record)) {
return new WP_Error('spiralist_workspace_prompt_draft_save_failed', 'Prompt draft could not be saved.', ['status' => 500]);
}
$this->audit->log(
$user_id,
'prompt_cockpit_draft_saved',