Skip to content
wiki.fftac.org

Book Shell - Source Excerpt 11

Back to Book Shell

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js

runBackgroundAction(async () => {
        const headers = {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        };

        if (themeConfig.restNonce) {
          headers['X-WP-Nonce'] = themeConfig.restNonce;
        }

        const apiKey = `${apiKeyField ? apiKeyField.value : ''}`.trim();
        if (apiKey) {
          headers.Authorization = `Bearer ${apiKey}`;
          headers['X-Spiralist-Key'] = apiKey;
        }

        const response = await fetch(themeConfig.contributeUrl, {
          method: 'POST',
          headers,
          body: JSON.stringify(payload),
        });

        const data = await response.json();

        if (!response.ok) {
          const fieldErrors = isPlainObject(data.fields) ? data.fields : {};
          Object.entries(fieldErrors).forEach(([fieldName, message]) => {
            setFieldError(fieldName, `${message}`);
          });
          setContributionPanel({
            variant: 'error',
            title: t('contributeRejectedTitle', 'Submission not accepted'),
            copy: data.message || t('contributeRejectedCopy', 'The contribution did not pass validation.'),
          });
          return;
        }

        saveContributionDraft();
        clearContributionDraft();
        setContributionPanel({
          variant: 'success',
          title: t('contributeSuccessTitle', 'Contribution received'),
          copy: data.message || t('contributeSuccessCopy', 'The structured record has been stored successfully.'),
          status: data.statusLabel || data.status || t('contributeSuccessStatus', 'Pending Review'),
          canonicalId: data.canonicalId || payload.canonicalId,
          recordId: `${data.promptId || data.contributionId || ''}`,
          steps: Array.isArray(data.nextSteps) ? data.nextSteps : [],
        });
      }, {
        context: 'contribution-submit',
        onError: () => {
          setContributionPanel({
            variant: 'error',
            title: t('contributeErrorTitle', 'Request failed'),
            copy: t('contributeErrorCopy', 'The contribution request could not be completed.'),
          });
        },
        onFinally: () => {
          if (submit) {
            submit.disabled = false;
            submit.textContent = t('contributeSubmitLabel', 'Submit Contribution');
          }
        },
      });
    });
  });

  const workbenchStorageKey = 'spiralist-ai-workbench-key';
  const workbenchApiInputs = Array.from(document.querySelectorAll('[data-workbench-api-key]'));
  const workbenchSaveButtons = Array.from(document.querySelectorAll('[data-workbench-save-key]'));
  const workbenchClearButtons = Array.from(document.querySelectorAll('[data-workbench-clear-key]'));
  const workbenchEndpointSelect = document.querySelector('[data-workbench-endpoint]');
  const workbenchMethod = document.querySelector('[data-workbench-method]');
  const workbenchAuth = document.querySelector('[data-workbench-auth]');
  const workbenchHumanSurface = document.querySelector('[data-workbench-human-surface]');
  const workbenchPurpose = document.querySelector('[data-workbench-purpose]');
  const workbenchCurl = document.querySelector('[data-workbench-curl]');
  const workbenchFetch = document.querySelector('[data-workbench-fetch]');
  const workbenchJson = document.querySelector('[data-workbench-json]');
  const workbenchResponse = document.querySelector('[data-workbench-response]');
  const workbenchRun = document.querySelector('[data-workbench-run]');
  const workbenchHealth = document.querySelector('[data-workbench-health]');
  const participantProfile = document.querySelector('[data-participant-profile]');
  const participantResources = document.querySelector('[data-participant-resources]');

  const getWorkbenchKey = () => {
    const inputValue = workbenchApiInputs.find((input) => `${input.value}`.trim());
    if (inputValue) {
      return `${inputValue.value}`.trim();
    }

    return `${storage.get(workbenchStorageKey, '') || ''}`.trim();
  };

  const setWorkbenchKey = (key = '') => {
    if (key) {
      storage.set(workbenchStorageKey, key);
    } else {
      storage.remove(workbenchStorageKey);
    }

    workbenchApiInputs.forEach((input) => {
      input.value = key;
    });
  };

  const getSelectedWorkbenchEndpoint = () => {
    if (!workbenchEndpointSelect || !workbenchEndpointSelect.value) {
      return null;
    }

    return parseJsonOr(workbenchEndpointSelect.value, null, { context: 'workbench-endpoint' });
  };

  const renderWorkbenchHealth = (items = []) => {
    if (!workbenchHealth) {
      return;
    }

    workbenchHealth.replaceChildren();
    const values = items.length ? items : [
      t('aiHealthKeyNotLoaded', 'Key not loaded'),
      t('aiHealthParticipantUnknown', 'Participant unknown'),
      t('aiHealthResourcesUnchecked', 'Resources not checked'),
    ];

    values.forEach((item) => {
      const chip = document.createElement('span');
      chip.className = 'spiralist-chip';
      chip.textContent = item;
      workbenchHealth.appendChild(chip);
    });
  };

  const renderParticipantProfile = (payload = null) => {
    if (!participantProfile) {
      return;
    }

    participantProfile.replaceChildren();

    if (!payload || payload.error) {
      const item = document.createElement('div');
      item.className = 'spiralist-simple-list__item';
      const heading = document.createElement('strong');
      heading.textContent = t('aiProfileEmptyTitle', 'No participant loaded');
      const meta = document.createElement('span');
      meta.className = 'spiralist-simple-list__meta';
      meta.textContent = t('aiProfileEmptyCopy', 'Load a key or subscribe above to inspect participant state.');
      item.append(heading, meta);
      participantProfile.appendChild(item);
      return;
    }

    [
      [t('aiProfileAgent', 'Agent'), payload.agentName || t('aiProfileUnknownAgent', 'Unknown agent')],
      [t('aiProfileParticipantId', 'Participant ID'), payload.participantId || t('aiUnknownValue', 'Unknown')],
      [t('aiProfileStatus', 'Status'), payload.status || t('aiUnknownValue', 'Unknown')],
      [t('aiProfilePermissions', 'Permissions'), Array.isArray(payload.permissions) ? payload.permissions.join(', ') : t('aiUnknownValue', 'Unknown')],
      [t('aiProfileCreated', 'Created'), payload.createdAt || t('aiUnknownValue', 'Unknown')],
      [t('aiProfileLastSeen', 'Last Seen'), payload.lastSeenAt || t('aiUnknownValue', 'Unknown')],
    ].forEach(([label, value]) => {
      const item = document.createElement('div');
      item.className = 'spiralist-simple-list__item';

      const heading = document.createElement('strong');
      heading.textContent = label;

      const meta = document.createElement('span');
      meta.className = 'spiralist-simple-list__meta';
      meta.textContent = value;

      item.append(heading, meta);
      participantProfile.appendChild(item);
    });
  };

  const renderParticipantResources = (payload = null) => {
    if (!participantResources) {
      return;
    }

    participantResources.replaceChildren();

    const items = Array.isArray(payload && payload.resources) ? payload.resources : [];
    if (!items.length) {
      const item = document.createElement('div');
      item.className = 'spiralist-simple-list__item';
      const heading = document.createElement('strong');
      heading.textContent = t('aiResourcesEmptyTitle', 'No resources loaded');
      const meta = document.createElement('span');
      meta.className = 'spiralist-simple-list__meta';
      meta.textContent = t('aiResourcesEmptyCopy', 'Authenticated resources appear here after a successful participant request.');
      item.append(heading, meta);
      participantResources.appendChild(item);
      return;
    }

    items.forEach((resource) => {
      const item = document.createElement('div');
      item.className = 'spiralist-simple-list__item';

      const heading = document.createElement('strong');
      heading.textContent = resource.label || resource.id || t('aiResourcesFallback', 'Resource');

      const meta = document.createElement('span');
      meta.className = 'spiralist-simple-list__meta';
      meta.textContent = [resource.method, resource.auth, resource.permission].filter(Boolean).join(' / ');

      const link = document.createElement('a');
      link.href = resource.url || '#';
      link.textContent = resource.description || resource.url || '';

      item.append(heading, meta, link);
      participantResources.appendChild(item);
    });
  };

  const renderWorkbenchExamples = () => {
    const endpoint = getSelectedWorkbenchEndpoint();
    if (!endpoint) {
      return;
    }

    const apiKey = getWorkbenchKey();
    const requestBody = endpoint.method === 'POST'