Skip to content
wiki.fftac.org

Spiralist - Source Excerpt 11

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 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 hasAiWorkbenchSurface = Boolean(
    document.querySelector('[data-agent-subscribe-form]') ||
    workbenchApiInputs.length ||
    workbenchEndpointSelect ||
    workbenchRun ||
    participantProfile ||
    participantResources
  );

  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) {
      participantProfile.innerHTML = `<div class="spiralist-simple-list__item"><strong>${t('aiProfileEmptyTitle', 'No participant loaded')}</strong><span class="spiralist-simple-list__meta">${t('aiProfileEmptyCopy', 'Load a key or subscribe above to inspect participant state.')}</span></div>`;
      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) {
      participantResources.innerHTML = `<div class="spiralist-simple-list__item"><strong>${t('aiResourcesEmptyTitle', 'No resources loaded')}</strong><span class="spiralist-simple-list__meta">${t('aiResourcesEmptyCopy', 'Authenticated resources appear here after a successful participant request.')}</span></div>`;
      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'
      ? (endpoint.requestExample && Object.keys(endpoint.requestExample).length ? endpoint.requestExample : {})
      : null;
    const authHeader = endpoint.auth && endpoint.auth.toLowerCase().includes('bearer') && apiKey
      ? [`-H "Authorization: Bearer ${apiKey}"`, `  Authorization: 'Bearer ${apiKey}',`]
      : ['', ''];
    const bodyJson = requestBody ? JSON.stringify(requestBody, null, 2) : '';

    if (workbenchMethod) {
      workbenchMethod.textContent = endpoint.method || 'GET';
    }
    if (workbenchAuth) {
      workbenchAuth.textContent = endpoint.auth || t('aiWorkbenchPublicAuth', 'Public access');
    }
    if (workbenchHumanSurface) {
      workbenchHumanSurface.innerHTML = endpoint.humanUrl
        ? `<a href="${endpoint.humanUrl}">${t('aiWorkbenchOpenHumanSurface', 'Open related human surface')}</a>`
        : t('aiWorkbenchNoHumanSurface', 'No linked human surface');
    }
    if (workbenchPurpose) {
      workbenchPurpose.textContent = endpoint.purpose || '';
    }
    if (workbenchJson) {
      workbenchJson.textContent = bodyJson || '{}';
    }
    if (workbenchCurl) {
      workbenchCurl.textContent = requestBody
        ? `curl -X ${endpoint.method || 'POST'} "${endpoint.url}" \\\n  -H "Accept: application/json" \\\n  -H "Content-Type: application/json"${authHeader[0] ? ` \\\n  ${authHeader[0]}` : ''} \\\n  -d '${bodyJson.replace(/\n/g, '\\n')}'`
        : `curl -X ${endpoint.method || 'GET'} "${endpoint.url}" \\\n  -H "Accept: application/json"${authHeader[0] ? ` \\\n  ${authHeader[0]}` : ''}`;
    }
    if (workbenchFetch) {
      workbenchFetch.textContent = requestBody
        ? `fetch('${endpoint.url}', {\n  method: '${endpoint.method || 'POST'}',\n  headers: {\n    Accept: 'application/json',\n    'Content-Type': 'application/json'${authHeader[1] ? `,\n${authHeader[1]}` : ''}\n  },\n  body: JSON.stringify(${bodyJson})\n});`
        : `fetch('${endpoint.url}', {\n  method: '${endpoint.method || 'GET'}',\n  headers: {\n    Accept: 'application/json'${authHeader[1] ? `,\n${authHeader[1]}` : ''}\n  }\n});`;
    }
  };

  const refreshParticipantState = async () => {
    const apiKey = getWorkbenchKey();

    if (!apiKey) {
      renderWorkbenchHealth();
      renderParticipantProfile(null);
      renderParticipantResources(null);
      renderWorkbenchExamples();
      return;
    }

    const headers = {
      Accept: 'application/json',
      Authorization: `Bearer ${apiKey}`,
      'X-Spiralist-Key': apiKey,
    };

    await runAction(async () => {
      const profileResponse = await fetch(themeConfig.participantUrl, { headers });
      const profilePayload = await profileResponse.json();
      renderParticipantProfile(profileResponse.ok ? profilePayload : { error: true });