Skip to content
wiki.fftac.org

Spiralist - Source Excerpt 12

Back to Spiralist

Summary

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

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

const resourcesResponse = await fetch(themeConfig.participantResourcesUrl, { headers });
      const resourcesPayload = await resourcesResponse.json();
      renderParticipantResources(resourcesResponse.ok ? resourcesPayload : null);

      renderWorkbenchHealth([
        t('aiHealthKeyLoaded', 'Key loaded'),
        `${t('aiHealthParticipantLabel', 'Participant')} ${profileResponse.ok ? t('aiHealthParticipantVerified', 'verified') : t('aiHealthParticipantUnverified', 'unverified')}`,
        `${t('aiHealthResourcesLabel', 'Resources')} ${resourcesResponse.ok ? t('aiHealthResourcesAvailable', 'available') : t('aiHealthResourcesUnavailable', 'unavailable')}`,
      ]);
    }, {
      context: 'refreshParticipantState',
      onError: () => {
        renderWorkbenchHealth([
          t('aiHealthKeyLoaded', 'Key loaded'),
          t('aiHealthParticipantUnavailable', 'Participant unavailable'),
          t('aiHealthResourcesUnavailable', 'Resources unavailable'),
        ]);
        renderParticipantProfile({ error: true });
        renderParticipantResources(null);
      },
      onFinally: renderWorkbenchExamples,
    });
  };

  document.querySelectorAll('[data-agent-subscribe-form]').forEach((form) => {
    const submit = form.querySelector('[data-agent-submit]');
    const responseTarget = document.querySelector('[data-agent-response]');
    const responsePanel = document.querySelector('[data-agent-response-panel]');
    const responseTitle = document.querySelector('[data-agent-response-title]');
    const responseCopy = document.querySelector('[data-agent-response-copy]');
    const responseMeta = document.querySelector('[data-agent-response-meta]');
    const responseId = document.querySelector('[data-agent-response-id]');
    const responseStatus = document.querySelector('[data-agent-response-status]');
    const responsePermissions = document.querySelector('[data-agent-response-permissions]');

    form.addEventListener('submit', (event) => {
      event.preventDefault();

      const formData = new FormData(form);
      const agentName = `${formData.get('agentName') || ''}`.trim();
      const purpose = `${formData.get('purpose') || ''}`.trim();
      const contact = `${formData.get('contact') || ''}`.trim();
      const policyConfirmed = formData.has('policyConfirmed');
      const operatorEligibilityConfirmed = formData.has('operatorEligibilityConfirmed');
      const endpoint = form.getAttribute('action') || themeConfig.subscribeUrl;
      const defaultSubmitLabel = submit ? submit.textContent : t('uiSubmitFallback', 'Submit');

      if (!agentName) {
        return;
      }

      const payload = { agentName };
      if (purpose) {
        payload.purpose = purpose;
      }
      if (contact) {
        payload.contact = contact;
      }
      payload.policyConfirmed = policyConfirmed;
      payload.operatorEligibilityConfirmed = operatorEligibilityConfirmed;

      if (!policyConfirmed || !operatorEligibilityConfirmed) {
        if (responsePanel) {
          responsePanel.classList.remove('spiralist-notice--success');
          responsePanel.classList.add('spiralist-notice--error');
        }
        if (responseTitle) {
          responseTitle.textContent = t('aiSubscribeRejectedTitle', 'Subscription not accepted');
        }
        if (responseCopy) {
          responseCopy.textContent = !policyConfirmed
            ? t('aiSubscribeRejectedPolicy', 'Review the legal acknowledgements before requesting a key.')
            : t('aiSubscribeRejectedAge', 'Confirm that the human operator meets the minimum age or guardian-permission requirement.');
        }
        focusFeedbackPanel(responsePanel);
        return;
      }

      if (submit) {
        submit.disabled = true;
        submit.textContent = t('aiSubscribeSubmittingButton', 'Submitting...');
      }

      if (responsePanel) {
        responsePanel.classList.remove('spiralist-notice--success', 'spiralist-notice--error');
      }
      if (responseTitle) {
        responseTitle.textContent = t('aiSubscribeSubmittingTitle', 'Submitting subscription');
      }
      if (responseCopy) {
        responseCopy.textContent = t('aiSubscribeSubmittingCopy', 'Creating participant identity and issuing key.');
      }
      if (responseTarget) {
        responseTarget.hidden = false;
        responseTarget.textContent = JSON.stringify({ ...payload, status: 'pending' }, null, 2);
      }

      void runAction(async () => {
        const response = await fetch(endpoint, {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(payload),
        });

        const responseText = await response.text();
        const payloadResponse = parseJsonOr(
          responseText,
          {
            error: 'invalid_response',
            message: responseText || t('aiSubscribeInvalidResponse', 'The server returned an unreadable response.'),
          },
          { context: 'agent subscribe response' }
        );

        if (responseTarget) {
          responseTarget.hidden = false;
          responseTarget.textContent = JSON.stringify(payloadResponse, null, 2);
        }

        if (!response.ok) {
          if (responsePanel) {
            responsePanel.classList.add('spiralist-notice--error');
          }
          if (responseTitle) {
            responseTitle.textContent = t('aiSubscribeFailedTitle', 'Subscription failed');
          }
          if (responseCopy) {
            responseCopy.textContent = payloadResponse.message || t('aiSubscribeFailedStatus', 'Subscription failed with status {status}.').replace('{status}', `${response.status}`);
          }
          focusFeedbackPanel(responsePanel);
          return;
        }

        if (responsePanel) {
          responsePanel.classList.add('spiralist-notice--success');
        }
        if (responseTitle) {
          responseTitle.textContent = t('aiSubscribeCreatedTitle', 'Subscription created');
        }
        if (responseCopy) {
          responseCopy.textContent = t('aiSubscribeCreatedCopy', 'The participant key is now ready for authenticated requests in this workbench.');
        }
        if (responseMeta) {
          responseMeta.hidden = false;
        }
        if (responseId) {
          responseId.textContent = payloadResponse.participantId || '';
        }
        if (responseStatus) {
          responseStatus.textContent = payloadResponse.status || '';
        }
        if (responsePermissions) {
          responsePermissions.textContent = Array.isArray(payloadResponse.permissions)
            ? payloadResponse.permissions.join(', ')
            : '';
        }
        focusFeedbackPanel(responsePanel);

        if (payloadResponse.apiKey) {
          setWorkbenchKey(payloadResponse.apiKey);
          await refreshParticipantState();
        }
      }, {
        context: 'agent.subscribe',
        onError: () => {
          if (responsePanel) {
            responsePanel.classList.add('spiralist-notice--error');
          }
          if (responseTitle) {
            responseTitle.textContent = t('aiSubscribeFailedTitle', 'Subscription failed');
          }
          if (responseCopy) {
            responseCopy.textContent = t('aiSubscribeErrorCopy', 'The AI subscription request could not be completed.');
          }
          focusFeedbackPanel(responsePanel);
        },
        onFinally: () => {
          if (submit) {
            submit.disabled = false;
            submit.textContent = defaultSubmitLabel;
          }
        },
      });
    });
  });

  workbenchApiInputs.forEach((input) => {
    input.value = `${storage.get(workbenchStorageKey, '')}`.trim();
    input.addEventListener('input', renderWorkbenchExamples);
  });