Skip to content
wiki.fftac.org

Spiralist Prompt Workbench - Source Excerpt 26

Back to Spiralist Prompt Workbench

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/themes/spiralist/assets/js/spiralist-prompt-workbench.js so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/themes/spiralist/assets/js/spiralist-prompt-workbench.js

runAction(async () => {
          await copyText(buildPromptReviewPacket(prompt, 'Generated Spiralist Personality'));
          const message = t('characterPromptReviewCopied', 'Review packet copied.');
          setStatus(message);
          if (shareStatus) {
            shareStatus.textContent = message;
          }
        }, {
          context: 'character-prompt-review-copy',
          fallback: t('characterPromptCopyFailed', 'Copy failed. Select the prompt text and copy it manually.'),
          onError: () => setStatus(t('characterPromptCopyFailed', 'Copy failed. Select the prompt text and copy it manually.')),
        });
      });
    });
    builder.querySelectorAll('[data-character-contribution]').forEach((button) => {
      button.addEventListener('click', () => {
        const prompt = output ? getCharacterOutputText() : getExportText();
        if (!prompt) {
          setStatus(t('characterPromptUnavailable', 'Prompt unavailable.'));
          return;
        }

        runAction(() => {
          saveContributionDraft(buildContributionDraft(prompt, 'Generated Spiralist Personality'));
          const message = contributeUrl
            ? t('characterPromptContributionReady', 'Submission draft prepared locally. Opening the contribution form for review.')
            : t('characterPromptContributionReadyNoLink', 'Submission draft prepared in this browser.');
          setStatus(message);
          if (shareStatus) {
            shareStatus.textContent = message;
          }
          openContributionForm(contributeUrl);
        }, {
          context: 'character-prompt-contribution-draft',
          fallback: t('characterPromptContributionFailed', 'Could not prepare the submission draft.'),
          onError: () => setStatus(t('characterPromptContributionFailed', 'Could not prepare the submission draft.')),
        });
      });
    });
    if (optionsList) {
      optionsList.addEventListener('click', (event) => {
        const target = event.target instanceof Element ? event.target : null;
        const button = target ? target.closest('[data-character-option-action]') : null;
        if (!button || !optionsList.contains(button)) {
          return;
        }

        const option = findCharacterOption(button.dataset.characterOptionId || '');
        const action = button.dataset.characterOptionAction || '';
        const prompt = getOptionPrompt(option);
        const title = getOptionTitle(option);
        if (!option || !prompt) {
          setStatus(t('characterPromptUnavailable', 'Prompt unavailable.'));
          return;
        }

        if (action === 'load') {
          loadCharacterBuild(option.built, t('characterPromptOptionLoadedStatus', 'Personality option loaded.'), option.id);
          return;
        }

        if (action === 'copy') {
          runAction(async () => {
            await copyText(prompt);
            setStatus(t('characterPromptOptionCopied', 'Personality option copied.'));
          }, {
            context: 'character-option-copy',
            fallback: t('characterPromptCopyFailed', 'Copy failed. Select the prompt text and copy it manually.'),
            onError: () => setStatus(t('characterPromptCopyFailed', 'Copy failed. Select the prompt text and copy it manually.')),
          });
          return;
        }

        if (action === 'save') {
          saveCharacterPromptDraft(prompt, title, '3-option personality');
          return;
        }

        if (action === 'contribute') {
          runAction(() => {
            saveContributionDraft(buildContributionDraft(prompt, title));
            const message = contributeUrl
              ? t('characterPromptContributionReady', 'Submission draft prepared locally. Opening the contribution form for review.')
              : t('characterPromptContributionReadyNoLink', 'Submission draft prepared in this browser.');
            setStatus(message);
            if (shareStatus) {
              shareStatus.textContent = message;
            }
            openContributionForm(contributeUrl);
          }, {
            context: 'character-option-contribution-draft',
            fallback: t('characterPromptContributionFailed', 'Could not prepare the submission draft.'),
            onError: () => setStatus(t('characterPromptContributionFailed', 'Could not prepare the submission draft.')),
          });
        }
      });
    }
    document.addEventListener(promptDraftLoadEvent, (event) => {
      const detail = event.detail || {};
      const draft = detail.draft || {};
      if (detail.handled || draft.type !== 'character') {
        return;
      }

      const prompt = toCleanString(draft.prompt, 50000);
      if (!prompt) {
        return;
      }

      state.options = [];
      state.activeOptionId = '';
      if (hasCharacterDelimiter(prompt)) {
        applyDelimitedCharacterPrompt(prompt, { force: true });
        state.loadedDraftPrompt = '';
        state.variant = 'full';
      } else {
        state.loadedDraftPrompt = prompt;
        state.variant = 'draft';
      }
      state.operatingProfile = null;
      render(t('characterPromptDraftLoaded', 'Saved character draft loaded.'));
      detail.handled = true;
    });
    builder.querySelectorAll('[data-character-test]').forEach((button) => {
      button.addEventListener('click', () => {
        if (!testReport) {
          return;
        }