Skip to content
wiki.fftac.org

Restcontroller - Source Excerpt 06

Back to Restcontroller

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

return new WP_Error('spiralist_workspace_prompt_forbidden', 'Prompt not found.', ['status' => 404]);
        }

        $run = $this->runner->run_prompt(
            (int) $request['id'],
            $user_id,
            (array) ($test['variables'] ?? []),
            (string) ($test['input_text'] ?? '')
        );

        if ($run instanceof WP_Error) {
            return $run;
        }

        $evaluation = $this->tests->evaluate(
            (string) ($run['output_text'] ?? ''),
            (string) ($test['expected_output_text'] ?? ''),
            (string) ($test['match_strategy'] ?? 'contains')
        );
        $evaluation['run_id'] = (int) ($run['id'] ?? 0);
        $evaluation['output_text'] = (string) ($run['output_text'] ?? '');
        $this->tests->update_result((int) $request['test_id'], (int) ($run['id'] ?? 0), $evaluation);

        $this->audit->log($user_id, 'prompt_test_run', 'prompt', (int) $request['id'], $evaluation);

        return new WP_REST_Response(
            [
                'test' => $this->tests->get((int) $request['test_id']),
                'run' => $run,
                'evaluation' => $evaluation,
            ]
        );
    }

    /**
     * Runs a capped batch of saved prompt tests from the admin screen.
     */
    public function run_admin_prompt_tests(WP_REST_Request $request): WP_REST_Response
    {
        $user_id = get_current_user_id();
        $limit = min(50, max(1, (int) ($request->get_param('limit') ?: 20)));
        $tests = $this->tests->list_all($limit);
        $results = [];
        $passed = 0;
        $failed = 0;
        $errors = 0;

        foreach ($tests as $test) {
            $prompt_id = (int) ($test['prompt_post_id'] ?? 0);
            $prompt = $this->prompts->get($prompt_id, $user_id);

            if (empty($prompt)) {
                $errors++;
                $results[] = [
                    'test_id' => (int) ($test['id'] ?? 0),
                    'prompt_id' => $prompt_id,
                    'prompt_title' => '',
                    'status' => 'error',
                    'details' => 'Prompt not found.',
                ];
                continue;
            }

            $run = $this->runner->run_prompt(
                $prompt_id,
                $user_id,
                (array) ($test['variables'] ?? []),
                (string) ($test['input_text'] ?? '')
            );

            if ($run instanceof WP_Error) {
                $errors++;
                $results[] = [
                    'test_id' => (int) ($test['id'] ?? 0),
                    'prompt_id' => $prompt_id,
                    'prompt_title' => (string) ($prompt['title'] ?? ''),
                    'status' => 'error',
                    'details' => $run->get_error_message(),
                ];
                continue;
            }

            $evaluation = $this->tests->evaluate(
                (string) ($run['output_text'] ?? ''),
                (string) ($test['expected_output_text'] ?? ''),
                (string) ($test['match_strategy'] ?? 'contains')
            );
            $evaluation['run_id'] = (int) ($run['id'] ?? 0);
            $evaluation['output_text'] = (string) ($run['output_text'] ?? '');
            $this->tests->update_result((int) ($test['id'] ?? 0), (int) ($run['id'] ?? 0), $evaluation);

            if (!empty($evaluation['passed'])) {
                $passed++;
            } else {
                $failed++;
            }

            $results[] = [
                'test_id' => (int) ($test['id'] ?? 0),
                'prompt_id' => $prompt_id,
                'prompt_title' => (string) ($prompt['title'] ?? ''),
                'status' => (string) ($evaluation['status'] ?? 'failed'),
                'details' => (string) ($evaluation['details'] ?? ''),
                'run_id' => (int) ($run['id'] ?? 0),
            ];
        }

        $summary = [
            'total' => count($tests),
            'passed' => $passed,
            'failed' => $failed,
            'errors' => $errors,
            'limit' => $limit,
        ];

        $this->audit->log($user_id, 'admin_prompt_tests_run', 'prompt_test', null, $summary);

        return new WP_REST_Response(
            [
                'summary' => $summary,
                'results' => $results,
            ]
        );
    }

    /**
     * Starts a conversation from a prompt.
     */
    public function start_conversation(WP_REST_Request $request)
    {
        $variables = (array) $request->get_param('variables');
        $opening_message = sanitize_textarea_field((string) $request->get_param('message'));
        $result = $this->runner->start_conversation((int) $request['id'], get_current_user_id(), $variables, $opening_message);

        return $result instanceof WP_Error ? $result : new WP_REST_Response($result, 201);
    }

    /**
     * Lists the current user's conversations.
     */
    public function list_conversations(): WP_REST_Response
    {
        return new WP_REST_Response($this->conversations->list_for_user(get_current_user_id(), 30));
    }

    /**
     * Returns a conversation and message history.
     */
    public function get_conversation(WP_REST_Request $request)
    {
        $conversation = $this->conversations->get((int) $request['id']);
        if (empty($conversation) || !$this->permissions->can_view_conversation($conversation, get_current_user_id())) {
            return new WP_Error('spiralist_workspace_conversation_not_found', 'Conversation not found.', ['status' => 404]);
        }

        $messages = $this->conversations->get_messages((int) $request['id']);

        return new WP_REST_Response(
            [
                'conversation' => $conversation,
                'messages' => $messages,
                'memory_status' => $this->runner->conversation_memory_status($conversation, $messages),
            ]
        );
    }

    /**
     * Posts a new conversation message.
     */
    public function post_conversation_message(WP_REST_Request $request)
    {
        $variables = (array) $request->get_param('variables');
        $message = sanitize_textarea_field((string) $request->get_param('message'));
        $result = $this->runner->post_message((int) $request['id'], get_current_user_id(), $message, $variables);

        return $result instanceof WP_Error ? $result : new WP_REST_Response($result, 201);
    }

    /**
     * Condenses a conversation into a persisted memory summary.
     */
    public function condense_conversation(WP_REST_Request $request)
    {
        $credential_preference = sanitize_key((string) $request->get_param('credential_preference'));
        $result = $this->runner->condense_conversation((int) $request['id'], get_current_user_id(), $credential_preference);

        return $result instanceof WP_Error ? $result : new WP_REST_Response($result, 201);
    }

    /**
     * Returns a portable prompt export for a conversation.
     */
    public function get_conversation_portable_prompt(WP_REST_Request $request)
    {
        $result = $this->runner->export_conversation_prompt((int) $request['id'], get_current_user_id());

        return $result instanceof WP_Error ? $result : new WP_REST_Response($result);
    }

    /**
     * Lists runs for the current user.
     */
    public function list_runs(): WP_REST_Response
    {
        return new WP_REST_Response($this->runs->list_for_user(get_current_user_id(), 30));
    }

    /**
     * Returns a single run.
     */
    public function get_run(WP_REST_Request $request)
    {
        $run = $this->runs->get((int) $request['id']);
        if (empty($run) || !$this->permissions->can_view_run($run, get_current_user_id())) {
            return new WP_Error('spiralist_workspace_run_not_found', 'Run not found.', ['status' => 404]);
        }

        return new WP_REST_Response($run);
    }

    /**
     * Returns featured prompts from settings.
     */
    public function featured_prompts(): WP_REST_Response
    {
        $ids = array_values(
            array_filter(
                array_map('intval', preg_split('/[\r\n,]+/', (string) $this->settings->get('featured_prompt_ids', '')) ?: [])
            )
        );

        $records = $this->prompts->list_public(['include' => $ids, 'limit' => max(50, count($ids))], get_current_user_id());
        if (empty($records)) {
            $this->maybe_sync_system_prompts();
            $records = $this->prompts->list_public(['include' => $ids, 'limit' => max(50, count($ids))], get_current_user_id());
        }

        $public = array_values(
            array_filter(
                $records,
                fn(array $prompt): bool => $this->is_public_library_prompt($prompt)