Skip to content
wiki.fftac.org

Book Shell - Source Excerpt 13

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

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 || formatText('aiSubscribeFailedStatus', 'Subscription failed with status {status}.', { status: response.status });
          }
          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(', ')
            : '';
        }

        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.');
          }
        },
        onFinally: () => {
          if (submit) {
            submit.disabled = false;
            submit.textContent = defaultSubmitLabel;
          }
        },
      });
    });
  });

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

  workbenchSaveButtons.forEach((button) => {
    button.addEventListener('click', async () => {
      setWorkbenchKey(getWorkbenchKey());
      await refreshParticipantState();
    });
  });

  workbenchClearButtons.forEach((button) => {
    button.addEventListener('click', async () => {
      setWorkbenchKey('');
      renderWorkbenchHealth();
      renderParticipantProfile(null);
      renderParticipantResources(null);
      renderWorkbenchExamples();
    });
  });

  if (workbenchEndpointSelect) {
    workbenchEndpointSelect.addEventListener('change', renderWorkbenchExamples);
  }

  if (workbenchRun) {
    workbenchRun.addEventListener('click', () => {
      const endpoint = getSelectedWorkbenchEndpoint();
      if (!endpoint || !workbenchResponse) {
        return;
      }

      const apiKey = getWorkbenchKey();
      const requiresAuth = `${endpoint.auth || ''}`.toLowerCase().includes('bearer');
      if (requiresAuth && !apiKey) {
        workbenchResponse.textContent = JSON.stringify(
          {
            error: 'missing_api_key',
            message: t('aiWorkbenchMissingKey', 'This endpoint requires a participant API key.'),
          },
          null,
          2
        );
        return;
      }

      const headers = {
        Accept: 'application/json',
      };

      let body = undefined;
      if (requiresAuth && apiKey) {
        headers.Authorization = `Bearer ${apiKey}`;
        headers['X-Spiralist-Key'] = apiKey;
      }

      if ((endpoint.method || 'GET').toUpperCase() === 'POST') {
        headers['Content-Type'] = 'application/json';
        body = JSON.stringify(endpoint.requestExample || {});
      }

      workbenchResponse.textContent = t('aiWorkbenchRunningRequest', 'Running request...');

      runBackgroundAction(async () => {
        const response = await fetch(endpoint.url, {
          method: endpoint.method || 'GET',
          headers,
          body,
        });
        const responseText = await response.text();
        const payload = parseJsonOr(responseText, { raw: responseText }, { context: 'workbench-response' });

        workbenchResponse.textContent = JSON.stringify(payload, null, 2);
        if (endpoint.id === 'participant' || endpoint.id === 'resources') {
          await refreshParticipantState();
        }
      }, {
        context: 'workbench-request',
        onError: () => {
          workbenchResponse.textContent = JSON.stringify(
            {
              error: 'request_failed',
              message: t('aiWorkbenchRequestFailed', 'The workbench request could not be completed.'),
            },
            null,
            2
          );
        },
      });
    });
  }

  const manuscriptPreloadedImages = new Set();
  const manuscriptPrefetchHints = new Set();
  const manuscriptRouteWarmCache = new Set();
  const manuscriptReaderModeKey = 'spiralist.manuscript.reader.mode';
  const manuscriptTurnKey = 'spiralist.manuscript.turn';
  const canBackgroundPreload = !(navigator.connection && navigator.connection.saveData);
  const scheduleBackgroundPreload = (callback) => {
    if (!canBackgroundPreload || typeof callback !== 'function') {
      return;
    }

    if ('requestIdleCallback' in window) {
      window.requestIdleCallback(() => {
        callback();
      }, { timeout: 1800 });
      return;
    }

    window.setTimeout(callback, 450);
  };
  const appendResourceHint = (key, url, asValue = '') => {
    if (!url || manuscriptPrefetchHints.has(key)) {
      return;
    }

    manuscriptPrefetchHints.add(key);
    const link = document.createElement('link');
    link.rel = 'prefetch';
    link.href = url;
    if (asValue) {
      link.as = asValue;
    }
    document.head.appendChild(link);
  };
  const getStoredValue = (key) => {
    return storage.get(key, '');
  };
  const setStoredValue = (key, value) => {
    storage.set(key, value);
  };
  const storeTurnDirection = (direction) => {
    storage.set(manuscriptTurnKey, direction, 'session');
  };
  const consumeTurnDirection = () => {
    const value = storage.get(manuscriptTurnKey, '', 'session');
    storage.remove(manuscriptTurnKey, 'session');

    return value;
  };
  const warmRouteDocument = (url) => {
    if (!url || manuscriptRouteWarmCache.has(url) || typeof window.fetch !== 'function') {
      return;
    }