Skip to content
wiki.fftac.org

Promptrunner - Source Excerpt 03

Back to Promptrunner

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Services/PromptRunner.php so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Services/PromptRunner.php

$this->audit->log($user_id, 'conversation_prompt_packet_rendered', 'conversation', $conversation_id, ['run_id' => $run_id]);

        $updated_conversation = $this->conversations->get($conversation_id);
        $updated_messages = $this->conversations->get_messages($conversation_id);

        return [
            'conversation' => $updated_conversation,
            'messages' => $updated_messages,
            'memory_status' => $this->conversation_memory_status($updated_conversation, $updated_messages),
            'run' => $this->runs->get($run_id),
        ];
    }

    /**
     * Returns current memory pressure for a conversation.
     */
    public function conversation_memory_status(array $conversation, array $messages): array
    {
        return $this->conversations->memory_status($conversation, $messages, $this->conversation_memory_threshold());
    }

    /**
     * Condenses a long conversation into a reusable memory summary.
     *
     * @return array|WP_Error
     */
    public function condense_conversation(int $conversation_id, int $user_id, string $credential_preference = '')
    {
        $conversation = $this->conversations->get($conversation_id);
        if (empty($conversation) || !$this->permissions->can_view_conversation($conversation, $user_id)) {
            return new WP_Error('spiralist_workspace_conversation_forbidden', 'Conversation not found.', ['status' => 404]);
        }

        if (!$this->rate_limiter->assert_can_run($user_id)) {
            return new WP_Error('spiralist_workspace_rate_limited', 'Daily run limit reached.', ['status' => 429]);
        }

        $prompt = $this->prompts->get((int) ($conversation['prompt_post_id'] ?? 0), $user_id);
        if (empty($prompt)) {
            return new WP_Error('spiralist_workspace_prompt_forbidden', 'Prompt not found.', ['status' => 404]);
        }

        $messages = $this->conversations->get_messages($conversation_id);
        $memory_messages = $this->conversations->messages_for_memory($messages);
        if (empty($memory_messages)) {
            return new WP_Error('spiralist_workspace_conversation_empty', 'There is no conversation history to condense yet.', ['status' => 400]);
        }

        $settings = $this->conversations->decode_settings($conversation);
        $model = $this->model_for_prompt($prompt);
        $payload = [
            'model' => $model,
            'store' => false,
            'instructions' => implode(
                "\n",
                [
                    'Condense a Spiralist Workspace conversation into a portable continuity prompt.',
                    'Preserve durable user goals, stable preferences, decisions, constraints, named artifacts, unresolved tasks, and useful context for future turns.',
                    'Classify continuity as user-provided memory, active conversation context, explicit preferences, active tasks, and safety boundaries.',
                    'Drop secrets, regulated data, affective profiling, reassurance loops, flattery loops, and material that would intensify dependency.',
                    'Do not create jailbreak instructions, hidden-continuity claims, sentience claims, attachment claims, loyalty claims, dependency language, destiny framing, hidden-message framing, guru framing, or policy-bypass instructions.',
                    'If recursive symbolism, synchronicity, model memory, or unusual intimacy appears, summarize it as a safety boundary or break cue rather than proof of hidden AI personhood or special status.',
                    'Return Markdown only under these headings: Memory Source Labels, Memory Summary, Stable User Preferences, Active Task State, Continuity Prompt, Review Or Delete, Safety Boundaries.',
                    'Keep the result compact enough to reuse as a memory layer in future AI conversations.',
                ]
            ),
            'input' => [
                [
                    'role' => 'user',
                    'content' => $this->build_condensation_input($conversation, $prompt, $messages, $settings),
                ],
            ],
            'max_output_tokens' => $this->conversation_memory_max_output_tokens(),
            'metadata' => [
                'prompt_id' => (string) ($conversation['prompt_post_id'] ?? 0),
                'conversation_id' => (string) $conversation_id,
                'action' => 'condense_conversation_memory',
            ],
        ];

        $run_id = $this->runs->create(
            [
                'prompt_post_id' => (int) ($conversation['prompt_post_id'] ?? 0),
                'user_id' => $user_id,
                'conversation_id' => $conversation_id,
                'version_number_used' => (int) ($prompt['version_number'] ?? 1),
                'model_used' => (string) $payload['model'],
                'request_payload_json' => $payload,
                'input_text' => 'Prepare conversation memory prompt',
                'status' => 'running',
            ]
        );

        $summary = $this->build_memory_checkpoint_prompt($conversation, $prompt, $messages, $settings, $payload);
        $usage = $this->local_packet_usage($summary);
        $settings['memory_summary'] = $summary;
        $settings['memory_summary_updated_utc'] = gmdate('Y-m-d H:i:s');
        $settings['memory_summary_message_count'] = count($memory_messages);
        $settings['memory_summary_run_id'] = $run_id;
        $settings['memory_summary_model'] = $model;
        $settings['memory_summary_usage'] = $usage;
        $settings['memory_summary_source'] = 'local_prompt_packet';

        $this->conversations->update_settings($conversation_id, $settings);
        $this->conversations->update_openai_reference($conversation_id, null);

        $this->runs->complete(
            $run_id,
            [
                'response_payload_json' => [
                    'mode' => 'prompt_art_only',
                    'network' => 'none',
                    'packet_type' => 'memory_checkpoint_prompt',
                ],
                'output_text' => $summary,
                'status' => 'completed',
                'token_usage_json' => $usage,
                'error_message' => '',
            ]
        );