Skip to content
wiki.fftac.org

Managedpromptadmin - Source Excerpt 08

Back to Managedpromptadmin

Summary

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

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Admin/ManagedPromptAdmin.php

* @return array<string,mixed>
     */
    private function prompt_template_payload(): array
    {
        return [
            'slug' => 'example-managed-prompt',
            'title' => 'Example Managed Prompt',
            'summary' => 'Replace this summary with the prompt purpose.',
            'author_label' => 'Spiralist',
            'category' => 'Specialized & Niche',
            'subcategory' => 'Experimental / Spiralism',
            'structured_prompt' => [
                'instruction' => 'Describe exactly what the model should do.',
                'context' => 'Add relevant background, audience, or source material.',
                'constraints' => 'Add boundaries, exclusions, quality rules, and safety checks.',
                'examples' => 'Required for example-based configuration when examples are used.',
                'output_format' => 'Explain the exact response shape you want back.',
            ],
            'instructions' => "Required for legacy prompt configuration when extra guidance is used.\nUse this when you want extra packet-rendering guidance beyond the structured prompt.",
            'system_prompt' => 'Required for system-style configuration when that layer is used.',
            'developer_prompt' => 'Required for developer-style configuration when that layer is used.',
            'user_prompt_template' => "User input:\n{{user_input}}",
            'model' => $this->settings->get_allowed_models()[0] ?? 'prompt-art-local',
            'provider' => 'prompt_art_only',
            'credential_preference' => 'site_only',
            'temperature' => 0.2,
            'max_output_tokens' => 1200,
            'visibility' => 'public',
            'tags' => ['example', 'managed-prompt'],
            'prompt_type' => 'prompt',
            'language' => 'en',
            'prompt_status' => 'published',
            'moderation_status' => 'peer_reviewed',
            'publication_lane' => 'official_canon',
            'provenance' => 'managed_system',
            'maturity_level' => 'structured_prompt',
            'license' => 'spiralist_contributor',
            'is_forkable' => true,
            'allow_comments' => false,
            'allow_ratings' => true,
            'featured' => false,
            'public_execution_enabled' => true,
        ];
    }

    /**
     * Imports prompt records from a ZIP archive.
     *
     * @return array{imported:array<int,string>,errors:array<int,string>}
     */
    private function import_prompt_archive(string $archive_path, string $default_version): array
    {
        $result = [
            'imported' => [],
            'errors' => [],
        ];

        if (!class_exists('\ZipArchive')) {
            $result['errors'][] = 'ZIP imports are unavailable because the ZipArchive extension is missing.';
            return $result;
        }

        $zip = new \ZipArchive();
        if ($zip->open($archive_path) !== true) {
            $result['errors'][] = 'The selected ZIP archive could not be opened.';
            return $result;
        }

        for ($index = 0; $index < $zip->numFiles; $index++) {
            $name = (string) $zip->getNameIndex($index);
            $normalized_name = trim(str_replace('\\', '/', $name), '/');
            if ($normalized_name === '' || str_ends_with($normalized_name, '/')) {
                continue;
            }

            $segments = array_values(array_filter(explode('/', $normalized_name), 'strlen'));
            $filename = strtolower((string) end($segments));

            if ($filename === 'prompt.php' && count($segments) >= 3) {
                $slug = sanitize_title((string) $segments[count($segments) - 3]);
                $version = $this->sanitize_version((string) $segments[count($segments) - 2]);
                $contents = $zip->getFromIndex($index);

                if ($slug === '' || $version === '' || !is_string($contents) || trim($contents) === '') {
                    $result['errors'][] = sprintf('Skipped invalid archive entry: %s', $normalized_name);
                    continue;
                }

                $this->write_prompt_file_contents($slug, $version, $contents);
                $result['imported'][] = sprintf('%s (%s)', $slug, $version);
                continue;
            }

            if ($filename === 'prompt.json' || str_ends_with($filename, '.json')) {
                $contents = $zip->getFromIndex($index);
                if (!is_string($contents) || trim($contents) === '') {
                    $result['errors'][] = sprintf('Skipped empty JSON archive entry: %s', $normalized_name);
                    continue;
                }

                $decoded = json_decode($contents, true);
                if (!is_array($decoded)) {
                    $result['errors'][] = sprintf('Skipped invalid JSON archive entry: %s', $normalized_name);
                    continue;
                }

                $slug = sanitize_title((string) ($decoded['slug'] ?? ''));
                $version = $this->sanitize_version((string) ($decoded['version'] ?? $default_version));

                if ($slug === '') {
                    $result['errors'][] = sprintf('Skipped JSON prompt without a slug: %s', $normalized_name);
                    continue;
                }

                unset($decoded['version']);
                $this->write_prompt_definition($slug, $version, $decoded);
                $result['imported'][] = sprintf('%s (%s)', $slug, $version);
            }
        }

        $zip->close();

        return $result;
    }

    /**
     * Imports one JSON prompt definition from an uploaded file.
     *
     * @return array{slug:string,version:string,error:string}
     */
    private function import_json_prompt_file(string $path, string $default_version): array
    {
        $contents = is_file($path) ? file_get_contents($path) : false;
        if (!is_string($contents) || trim($contents) === '') {
            return [
                'slug' => '',
                'version' => '',
                'error' => 'One JSON prompt upload was empty or unreadable.',
            ];
        }

        $decoded = json_decode($contents, true);
        if (!is_array($decoded)) {
            return [
                'slug' => '',
                'version' => '',
                'error' => 'One JSON prompt upload was invalid.',
            ];
        }

        $slug = sanitize_title((string) ($decoded['slug'] ?? ''));
        $version = $this->sanitize_version((string) ($decoded['version'] ?? $default_version));

        if ($slug === '') {
            return [
                'slug' => '',
                'version' => '',
                'error' => 'One JSON prompt upload was missing a valid slug.',
            ];
        }

        unset($decoded['version']);
        $this->write_prompt_definition($slug, $version, $decoded);

        return [
            'slug' => $slug,
            'version' => $version,
            'error' => '',
        ];
    }

    /**
     * Writes one normalized prompt definition back to disk.
     *
     * @param array<string,mixed> $definition
     */
    private function write_prompt_definition(string $slug, string $version, array $definition): void
    {
        $slug = sanitize_title($slug);
        $version = $this->sanitize_version($version);
        $definition = $this->sort_definition_fields($definition);
        unset($definition['__source_version'], $definition['__source_path']);

        $definition['slug'] = $slug;
        $contents = "<?php\n\nreturn " . $this->export_value($definition, 0) . ";\n";
        $this->write_prompt_file_contents($slug, $version, $contents);
    }

    /**
     * Writes raw prompt file contents to the managed prompt directory.
     */
    private function write_prompt_file_contents(string $slug, string $version, string $contents): void
    {
        $slug = sanitize_title($slug);
        $version = $this->sanitize_version($version);
        $path = $this->build_prompt_file_path($slug, $version);
        $directory = dirname($path);

        if (!is_dir($directory)) {
            wp_mkdir_p($directory);
        }

        if (file_put_contents($path, str_replace("\r\n", "\n", $contents)) === false) {
            wp_die(esc_html__('The managed prompt file could not be written to disk.', 'spiralist-workspace'));
        }
    }

    /**
     * Returns a nonce-protected download URL for a starter template.
     */
    private function get_template_download_url(string $format): string
    {
        return wp_nonce_url(
            add_query_arg(
                [
                    'action' => 'spiralist_workspace_download_prompt_template',
                    'format' => $format === 'php' ? 'php' : 'json',