Frontendcontroller - Source Excerpt 04
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Web/FrontendController.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Web/FrontendController.php
'exchangeSectionInstruction' => $ui_text('workspace.js.exchange.section.instruction', 'Instruction'),
'exchangeSectionContext' => $ui_text('workspace.js.exchange.section.context', 'Context'),
'exchangeSectionConstraints' => $ui_text('workspace.js.exchange.section.constraints', 'Constraints'),
'exchangeSectionExamples' => $ui_text('workspace.js.exchange.section.examples', 'Examples'),
'exchangeSectionOutputFormat' => $ui_text('workspace.js.exchange.section.output_format', 'Output Format'),
'exchangeSectionSystemPrompt' => $ui_text('workspace.js.exchange.section.system_prompt', 'System Prompt'),
'exchangeSectionDeveloperPrompt' => $ui_text('workspace.js.exchange.section.developer_prompt', 'Developer Prompt'),
'exchangeSectionUserPromptTemplate' => $ui_text('workspace.js.exchange.section.user_prompt_template', 'User Prompt Template'),
'exchangeSectionExpectedOutputNotes' => $ui_text('workspace.js.exchange.section.expected_output_notes', 'Expected Output Notes'),
'exchangeSectionFailureModes' => $ui_text('workspace.js.exchange.section.failure_modes', 'Failure Modes'),
'exchangeSectionSampleOutput' => $ui_text('workspace.js.exchange.section.sample_output', 'Sample Output'),
'exchangeSectionSource' => $ui_text('workspace.js.exchange.section.source', 'Source'),
'exchangeFieldHumanUrl' => $ui_text('workspace.js.exchange.field.human_url', 'Human URL'),
'exchangeFieldPublicApiUrl' => $ui_text('workspace.js.exchange.field.public_api_url', 'Public API URL'),
],
]
);
}
/**
* Maps workspace routes to plugin templates.
*/
public function template_include(string $template): string
{
$route = (string) get_query_var('spiralist_workspace_route');
if ($route === '') {
return $template;
}
$map = [
'library' => SPIRALIST_WORKSPACE_DIR . 'templates/library.php',
'prompt' => SPIRALIST_WORKSPACE_DIR . 'templates/prompt.php',
'workspace' => SPIRALIST_WORKSPACE_DIR . 'templates/workspace.php',
'members' => SPIRALIST_WORKSPACE_DIR . 'templates/members.php',
'profile' => SPIRALIST_WORKSPACE_DIR . 'templates/profile.php',
'run' => SPIRALIST_WORKSPACE_DIR . 'templates/run.php',
'conversation' => SPIRALIST_WORKSPACE_DIR . 'templates/conversation.php',
];
if (!isset($map[$route])) {
return $template;
}
return $map[$route];
}
/**
* Outputs JSON alias responses for /api/* convenience routes.
*/
public function handle_api_alias(): void
{
$route = (string) get_query_var('spiralist_workspace_route');
if ($route !== 'api') {
return;
}
$type = sanitize_key((string) get_query_var('spiralist_workspace_api'));
$user_id = get_current_user_id();
$payload = [];
if ($type === 'prompts') {
$records = $this->prompts->list(['limit' => 50], $user_id);
$records = array_values(
array_filter(
$records,
function (array $prompt) use ($user_id): bool {
if ($user_id > 0) {
return $this->permissions->can_view_prompt($prompt, $user_id);
}
return (string) ($prompt['visibility'] ?? '') === 'public';
}
)
);
$payload = array_map(fn(array $prompt): array => $this->prompts->for_api($prompt, false), $records);
} elseif ($type === 'runs') {
if ($user_id <= 0) {
$this->render_json(['error' => 'Authentication required.'], 401);
}
$payload = $this->runs->list_for_user($user_id, 50);
} elseif ($type === 'conversations') {
if ($user_id <= 0) {
$this->render_json(['error' => 'Authentication required.'], 401);
}
$payload = $this->conversations->list_for_user($user_id, 50);
} else {
$this->render_json(['error' => 'Not found.'], 404);
}
$this->render_json($payload, 200);
}
/**
* Returns whether the current request is one of the plugin routes.
*/
public function is_workspace_request(): bool
{
return (string) get_query_var('spiralist_workspace_route') !== '';
}
/**
* Returns prompt detail context for templates.
*/
public function prompt_context(): array
{
$slug = (string) get_query_var('spiralist_workspace_prompt_slug');
$user_id = get_current_user_id();
$prompt = $this->prompts->find_by_slug($slug, $user_id);
if (empty($prompt) || !$this->permissions->can_view_prompt($prompt, $user_id)) {
$this->force_404();
}
$prompt['appeal_summary'] = $this->appeals->summary_for_prompt((int) $prompt['id']);
$prompt['review_summary'] = $this->current_review_summary((int) $prompt['id'], $prompt['appeal_summary']);
$prompt['governance_summary'] = PromptGovernanceSummary::build(
$prompt,
$prompt['review_summary'],
$prompt['appeal_summary']
);
return [
'prompt' => $prompt,
'versions' => $this->versions->list_for_prompt((int) $prompt['id'], 10),
'execution_history' => $this->runs->list_for_prompt((int) $prompt['id'], 8),
'tests' => $this->tests->list_for_prompt((int) $prompt['id'], 20),
'shares' => $this->permissions->can_share_prompt($prompt, $user_id) ? $this->shares->list_for_prompt((int) $prompt['id']) : [],
'review_items' => $this->reviews->list_for_prompt((int) $prompt['id'], 12),
'appeal_items' => $this->appeals->list_for_prompt((int) $prompt['id'], 12),
'viewer_can_review' => $this->permissions->can_review_prompts($user_id),
'viewer_review' => $user_id > 0 && $this->permissions->can_review_prompts($user_id)
? $this->reviews->find_for_prompt_and_user((int) $prompt['id'], $user_id, 'peer')
: [],
'viewer_can_appeal' => $this->permissions->can_file_prompt_appeal($prompt, $user_id),
'viewer_appeal' => $user_id > 0 ? $this->appeals->find_open_for_prompt_and_user((int) $prompt['id'], $user_id) : [],
'viewer_can_resolve_appeals' => $this->permissions->can_resolve_prompt_appeals($user_id),
'featured_prompts' => $this->featured_prompt_records(4),
];
}
/**
* Returns workspace dashboard context.
*/
public function workspace_context(): array
{
$user_id = get_current_user_id();
$favorite_ids = $user_id > 0 ? $this->favorites->list_prompt_ids_for_user($user_id) : [];
$review_queue = $this->review_queue_context($user_id, 10);
$appeal_queue = $this->appeal_queue_context($user_id, 10);
return [
'my_prompts' => $user_id > 0 ? $this->prompts->list(['owner_user_id' => $user_id, 'limit' => 12], $user_id) : [],
'shared_with_me' => $user_id > 0 ? $this->shared_prompts_for_user($user_id) : [],
'public_library' => $this->public_prompts(8),
'favorites' => $user_id > 0 ? $this->prompts->list(['include' => $favorite_ids, 'limit' => 12], $user_id) : [],
'forks' => $user_id > 0 ? $this->forks_for_user($user_id) : [],
'runs' => $user_id > 0 ? $this->runs->list_for_user($user_id, 8) : [],
'conversations' => $user_id > 0 ? $this->conversations->list_for_user($user_id, 8) : [],
'audit' => $user_id > 0 && $this->permissions->is_admin($user_id) ? $this->audit->recent(8) : [],
'categories' => PromptCategoryRegistry::for_api(),
'top_prompts' => $this->top_performing_prompts(6),
'can_review_prompts' => $this->permissions->can_review_prompts($user_id),
'review_queue' => $review_queue['items'],
'review_queue_counts' => $review_queue['counts'],
'can_resolve_prompt_appeals' => $this->permissions->can_resolve_prompt_appeals($user_id),
'appeal_queue' => $appeal_queue['items'],
'appeal_queue_counts' => $appeal_queue['counts'],
'participant_state' => $user_id > 0 ? $this->reputation->get($user_id) : [],
];
}
/**
* Returns member library context.
*/
public function members_context(): array
{