Filehigh importancesource

PromptInputQueuedCommands.tsx

components/PromptInput/PromptInputQueuedCommands.tsx

117
Lines
19587
Bytes
1
Exports
13
Imports
10
Keywords

What this is

This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.

Beginner explanation

This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.

How it is used

Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.

Expert explanation

Architecturally, this file intersects with commands, ui-flow. It contains 117 lines, 13 detected imports, and 1 detected exports.

Important relationships

Detected exports

  • PromptInputQueuedCommands

Keywords

messagenotificationsmessagesmax_visible_notificationscommandsqueuedcommandsreactfiltertasknotificationscontent

Detected imports

  • bun:bundle
  • react
  • react
  • src/ink.js
  • src/state/AppState.js
  • ../../constants/xml.js
  • ../../context/QueuedMessageContext.js
  • ../../hooks/useCommandQueue.js
  • ../../types/textInputTypes.js
  • ../../utils/messageQueueManager.js
  • ../../utils/messages.js
  • ../../utils/slowOperations.js
  • ../Message.js

Source notes

This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.

Open parent directory

Full source

import { feature } from 'bun:bundle';
import * as React from 'react';
import { useMemo } from 'react';
import { Box } from 'src/ink.js';
import { useAppState } from 'src/state/AppState.js';
import { STATUS_TAG, SUMMARY_TAG, TASK_NOTIFICATION_TAG } from '../../constants/xml.js';
import { QueuedMessageProvider } from '../../context/QueuedMessageContext.js';
import { useCommandQueue } from '../../hooks/useCommandQueue.js';
import type { QueuedCommand } from '../../types/textInputTypes.js';
import { isQueuedCommandVisible } from '../../utils/messageQueueManager.js';
import { createUserMessage, EMPTY_LOOKUPS, normalizeMessages } from '../../utils/messages.js';
import { jsonParse } from '../../utils/slowOperations.js';
import { Message } from '../Message.js';
const EMPTY_SET = new Set<string>();

/**
 * Check if a command value is an idle notification that should be hidden.
 * Idle notifications are processed silently without showing to the user.
 */
function isIdleNotification(value: string): boolean {
  try {
    const parsed = jsonParse(value);
    return parsed?.type === 'idle_notification';
  } catch {
    return false;
  }
}

// Maximum number of task notification lines to show
const MAX_VISIBLE_NOTIFICATIONS = 3;

/**
 * Create a synthetic overflow notification message for capped task notifications.
 */
function createOverflowNotificationMessage(count: number): string {
  return `<${TASK_NOTIFICATION_TAG}>
<${SUMMARY_TAG}>+${count} more tasks completed</${SUMMARY_TAG}>
<${STATUS_TAG}>completed</${STATUS_TAG}>
</${TASK_NOTIFICATION_TAG}>`;
}

/**
 * Process queued commands to cap task notifications at MAX_VISIBLE_NOTIFICATIONS lines.
 * Other command types are always shown in full.
 * Idle notifications are filtered out entirely.
 */
function processQueuedCommands(queuedCommands: QueuedCommand[]): QueuedCommand[] {
  // Filter out idle notifications - they are processed silently
  const filteredCommands = queuedCommands.filter(cmd => typeof cmd.value !== 'string' || !isIdleNotification(cmd.value));

  // Separate task notifications from other commands
  const taskNotifications = filteredCommands.filter(cmd => cmd.mode === 'task-notification');
  const otherCommands = filteredCommands.filter(cmd => cmd.mode !== 'task-notification');

  // If notifications fit within limit, return all commands as-is
  if (taskNotifications.length <= MAX_VISIBLE_NOTIFICATIONS) {
    return [...otherCommands, ...taskNotifications];
  }

  // Show first (MAX_VISIBLE_NOTIFICATIONS - 1) notifications, then a summary
  const visibleNotifications = taskNotifications.slice(0, MAX_VISIBLE_NOTIFICATIONS - 1);
  const overflowCount = taskNotifications.length - (MAX_VISIBLE_NOTIFICATIONS - 1);

  // Create synthetic overflow message
  const overflowCommand: QueuedCommand = {
    value: createOverflowNotificationMessage(overflowCount),
    mode: 'task-notification'
  };
  return [...otherCommands, ...visibleNotifications, overflowCommand];
}
function PromptInputQueuedCommandsImpl(): React.ReactNode {
  const queuedCommands = useCommandQueue();
  const viewingAgent = useAppState(s => !!s.viewingAgentTaskId);
  // Brief layout: dim queue items + skip the paddingX (brief messages
  // already indent themselves). Gate mirrors the brief-spinner/message
  // check elsewhere — no teammate-view override needed since this
  // component early-returns when viewing a teammate.
  const useBriefLayout = feature('KAIROS') || feature('KAIROS_BRIEF') ?
  // biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
  useAppState(s_0 => s_0.isBriefOnly) : false;

  // createUserMessage mints a fresh UUID per call; without memoization, streaming
  // re-renders defeat Message's areMessagePropsEqual (compares uuid) → flicker.
  const messages = useMemo(() => {
    if (queuedCommands.length === 0) return null;
    // task-notification is shown via useInboxNotification; most isMeta commands
    // (scheduled tasks, proactive ticks) are system-generated and hidden.
    // Channel messages are the exception — isMeta but shown so the keyboard
    // user sees what arrived.
    const visibleCommands = queuedCommands.filter(isQueuedCommandVisible);
    if (visibleCommands.length === 0) return null;
    const processedCommands = processQueuedCommands(visibleCommands);
    return normalizeMessages(processedCommands.map(cmd => {
      let content = cmd.value;
      if (cmd.mode === 'bash' && typeof content === 'string') {
        content = `<bash-input>${content}</bash-input>`;
      }
      // [Image #N] placeholders are inline in the text value (inserted at
      // paste time), so the queue preview shows them without stub blocks.
      return createUserMessage({
        content
      });
    }));
  }, [queuedCommands]);

  // Don't show leader's queued commands when viewing any agent's transcript
  if (viewingAgent || messages === null) {
    return null;
  }
  return <Box marginTop={1} flexDirection="column">
      {messages.map((message, i) => <QueuedMessageProvider key={i} isFirst={i === 0} useBriefLayout={useBriefLayout}>
          <Message message={message} lookups={EMPTY_LOOKUPS} addMargin={false} tools={[]} commands={[]} verbose={false} inProgressToolUseIDs={EMPTY_SET} progressMessagesForMessage={[]} shouldAnimate={false} shouldShowDot={false} isTranscriptMode={false} isStatic={true} />
        </QueuedMessageProvider>)}
    </Box>;
}
export const PromptInputQueuedCommands = React.memo(PromptInputQueuedCommandsImpl);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiUmVhY3QiLCJ1c2VNZW1vIiwiQm94IiwidXNlQXBwU3RhdGUiLCJTVEFUVVNfVEFHIiwiU1VNTUFSWV9UQUciLCJUQVNLX05PVElGSUNBVElPTl9UQUciLCJRdWV1ZWRNZXNzYWdlUHJvdmlkZXIiLCJ1c2VDb21tYW5kUXVldWUiLCJRdWV1ZWRDb21tYW5kIiwiaXNRdWV1ZWRDb21tYW5kVmlzaWJsZSIsImNyZWF0ZVVzZXJNZXNzYWdlIiwiRU1QVFlfTE9PS1VQUyIsIm5vcm1hbGl6ZU1lc3NhZ2VzIiwianNvblBhcnNlIiwiTWVzc2FnZSIsIkVNUFRZX1NFVCIsIlNldCIsImlzSWRsZU5vdGlmaWNhdGlvbiIsInZhbHVlIiwicGFyc2VkIiwidHlwZSIsIk1BWF9WSVNJQkxFX05PVElGSUNBVElPTlMiLCJjcmVhdGVPdmVyZmxvd05vdGlmaWNhdGlvbk1lc3NhZ2UiLCJjb3VudCIsInByb2Nlc3NRdWV1ZWRDb21tYW5kcyIsInF1ZXVlZENvbW1hbmRzIiwiZmlsdGVyZWRDb21tYW5kcyIsImZpbHRlciIsImNtZCIsInRhc2tOb3RpZmljYXRpb25zIiwibW9kZSIsIm90aGVyQ29tbWFuZHMiLCJsZW5ndGgiLCJ2aXNpYmxlTm90aWZpY2F0aW9ucyIsInNsaWNlIiwib3ZlcmZsb3dDb3VudCIsIm92ZXJmbG93Q29tbWFuZCIsIlByb21wdElucHV0UXVldWVkQ29tbWFuZHNJbXBsIiwiUmVhY3ROb2RlIiwidmlld2luZ0FnZW50IiwicyIsInZpZXdpbmdBZ2VudFRhc2tJZCIsInVzZUJyaWVmTGF5b3V0IiwiaXNCcmllZk9ubHkiLCJtZXNzYWdlcyIsInZpc2libGVDb21tYW5kcyIsInByb2Nlc3NlZENvbW1hbmRzIiwibWFwIiwiY29udGVudCIsIm1lc3NhZ2UiLCJpIiwiUHJvbXB0SW5wdXRRdWV1ZWRDb21tYW5kcyIsIm1lbW8iXSwic291cmNlcyI6WyJQcm9tcHRJbnB1dFF1ZXVlZENvbW1hbmRzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmZWF0dXJlIH0gZnJvbSAnYnVuOmJ1bmRsZSdcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQm94IH0gZnJvbSAnc3JjL2luay5qcydcbmltcG9ydCB7IHVzZUFwcFN0YXRlIH0gZnJvbSAnc3JjL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHtcbiAgU1RBVFVTX1RBRyxcbiAgU1VNTUFSWV9UQUcsXG4gIFRBU0tfTk9USUZJQ0FUSU9OX1RBRyxcbn0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL3htbC5qcydcbmltcG9ydCB7IFF1ZXVlZE1lc3NhZ2VQcm92aWRlciB9IGZyb20gJy4uLy4uL2NvbnRleHQvUXVldWVkTWVzc2FnZUNvbnRleHQuanMnXG5pbXBvcnQgeyB1c2VDb21tYW5kUXVldWUgfSBmcm9tICcuLi8uLi9ob29rcy91c2VDb21tYW5kUXVldWUuanMnXG5pbXBvcnQgdHlwZSB7IFF1ZXVlZENvbW1hbmQgfSBmcm9tICcuLi8uLi90eXBlcy90ZXh0SW5wdXRUeXBlcy5qcydcbmltcG9ydCB7IGlzUXVldWVkQ29tbWFuZFZpc2libGUgfSBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlUXVldWVNYW5hZ2VyLmpzJ1xuaW1wb3J0IHtcbiAgY3JlYXRlVXNlck1lc3NhZ2UsXG4gIEVNUFRZX0xPT0tVUFMsXG4gIG5vcm1hbGl6ZU1lc3NhZ2VzLFxufSBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlcy5qcydcbmltcG9ydCB7IGpzb25QYXJzZSB9IGZyb20gJy4uLy4uL3V0aWxzL3Nsb3dPcGVyYXRpb25zLmpzJ1xuaW1wb3J0IHsgTWVzc2FnZSB9IGZyb20gJy4uL01lc3NhZ2UuanMnXG5cbmNvbnN0IEVNUFRZX1NFVCA9IG5ldyBTZXQ8c3RyaW5nPigpXG5cbi8qKlxuICogQ2hlY2sgaWYgYSBjb21tYW5kIHZhbHVlIGlzIGFuIGlkbGUgbm90aWZpY2F0aW9uIHRoYXQgc2hvdWxkIGJlIGhpZGRlbi5cbiAqIElkbGUgbm90aWZpY2F0aW9ucyBhcmUgcHJvY2Vzc2VkIHNpbGVudGx5IHdpdGhvdXQgc2hvd2luZyB0byB0aGUgdXNlci5cbiAqL1xuZnVuY3Rpb24gaXNJZGxlTm90aWZpY2F0aW9uKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBqc29uUGFyc2UodmFsdWUpXG4gICAgcmV0dXJuIHBhcnNlZD8udHlwZSA9PT0gJ2lkbGVfbm90aWZpY2F0aW9uJ1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG4vLyBNYXhpbXVtIG51bWJlciBvZiB0YXNrIG5vdGlmaWNhdGlvbiBsaW5lcyB0byBzaG93XG5jb25zdCBNQVhfVklTSUJMRV9OT1RJRklDQVRJT05TID0gM1xuXG4vKipcbiAqIENyZWF0ZSBhIHN5bnRoZXRpYyBvdmVyZmxvdyBub3RpZmljYXRpb24gbWVzc2FnZSBmb3IgY2FwcGVkIHRhc2sgbm90aWZpY2F0aW9ucy5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlT3ZlcmZsb3dOb3RpZmljYXRpb25NZXNzYWdlKGNvdW50OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gYDwke1RBU0tfTk9USUZJQ0FUSU9OX1RBR30+XG48JHtTVU1NQVJZX1RBR30+KyR7Y291bnR9IG1vcmUgdGFza3MgY29tcGxldGVkPC8ke1NVTU1BUllfVEFHfT5cbjwke1NUQVRVU19UQUd9PmNvbXBsZXRlZDwvJHtTVEFUVVNfVEFHfT5cbjwvJHtUQVNLX05PVElGSUNBVElPTl9UQUd9PmBcbn1cblxuLyoqXG4gKiBQcm9jZXNzIHF1ZXVlZCBjb21tYW5kcyB0byBjYXAgdGFzayBub3RpZmljYXRpb25zIGF0IE1BWF9WSVNJQkxFX05PVElGSUNBVElPTlMgbGluZXMuXG4gKiBPdGhlciBjb21tYW5kIHR5cGVzIGFyZSBhbHdheXMgc2hvd24gaW4gZnVsbC5cbiAqIElkbGUgbm90aWZpY2F0aW9ucyBhcmUgZmlsdGVyZWQgb3V0IGVudGlyZWx5LlxuICovXG5mdW5jdGlvbiBwcm9jZXNzUXVldWVkQ29tbWFuZHMoXG4gIHF1ZXVlZENvbW1hbmRzOiBRdWV1ZWRDb21tYW5kW10sXG4pOiBRdWV1ZWRDb21tYW5kW10ge1xuICAvLyBGaWx0ZXIgb3V0IGlkbGUgbm90aWZpY2F0aW9ucyAtIHRoZXkgYXJlIHByb2Nlc3NlZCBzaWxlbnRseVxuICBjb25zdCBmaWx0ZXJlZENvbW1hbmRzID0gcXVldWVkQ29tbWFuZHMuZmlsdGVyKFxuICAgIGNtZCA9PiB0eXBlb2YgY21kLnZhbHVlICE9PSAnc3RyaW5nJyB8fCAhaXNJZGxlTm90aWZpY2F0aW9uKGNtZC52YWx1ZSksXG4gIClcblxuICAvLyBTZXBhcmF0ZSB0YXNrIG5vdGlmaWNhdGlvbnMgZnJvbSBvdGhlciBjb21tYW5kc1xuICBjb25zdCB0YXNrTm90aWZpY2F0aW9ucyA9IGZpbHRlcmVkQ29tbWFuZHMuZmlsdGVyKFxuICAgIGNtZCA9PiBjbWQubW9kZSA9PT0gJ3Rhc2stbm90aWZpY2F0aW9uJyxcbiAgKVxuICBjb25zdCBvdGhlckNvbW1hbmRzID0gZmlsdGVyZWRDb21tYW5kcy5maWx0ZXIoXG4gICAgY21kID0+IGNtZC5tb2RlICE9PSAndGFzay1ub3RpZmljYXRpb24nLFxuICApXG5cbiAgLy8gSWYgbm90aWZpY2F0aW9ucyBmaXQgd2l0aGluIGxpbWl0LCByZXR1cm4gYWxsIGNvbW1hbmRzIGFzLWlzXG4gIGlmICh0YXNrTm90aWZpY2F0aW9ucy5sZW5ndGggPD0gTUFYX1ZJU0lCTEVfTk9USUZJQ0FUSU9OUykge1xuICAgIHJldHVybiBbLi4ub3RoZXJDb21tYW5kcywgLi4udGFza05vdGlmaWNhdGlvbnNdXG4gIH1cblxuICAvLyBTaG93IGZpcnN0IChNQVhfVklTSUJMRV9OT1RJRklDQVRJT05TIC0gMSkgbm90aWZpY2F0aW9ucywgdGhlbiBhIHN1bW1hcnlcbiAgY29uc3QgdmlzaWJsZU5vdGlmaWNhdGlvbnMgPSB0YXNrTm90aWZpY2F0aW9ucy5zbGljZShcbiAgICAwLFxuICAgIE1BWF9WSVNJQkxFX05PVElGSUNBVElPTlMgLSAxLFxuICApXG4gIGNvbnN0IG92ZXJmbG93Q291bnQgPVxuICAgIHRhc2tOb3RpZmljYXRpb25zLmxlbmd0aCAtIChNQVhfVklTSUJMRV9OT1RJRklDQVRJT05TIC0gMSlcblxuICAvLyBDcmVhdGUgc3ludGhldGljIG92ZXJmbG93IG1lc3NhZ2VcbiAgY29uc3Qgb3ZlcmZsb3dDb21tYW5kOiBRdWV1ZWRDb21tYW5kID0ge1xuICAgIHZhbHVlOiBjcmVhdGVPdmVyZmxvd05vdGlmaWNhdGlvbk1lc3NhZ2Uob3ZlcmZsb3dDb3VudCksXG4gICAgbW9kZTogJ3Rhc2stbm90aWZpY2F0aW9uJyxcbiAgfVxuXG4gIHJldHVybiBbLi4ub3RoZXJDb21tYW5kcywgLi4udmlzaWJsZU5vdGlmaWNhdGlvbnMsIG92ZXJmbG93Q29tbWFuZF1cbn1cblxuZnVuY3Rpb24gUHJvbXB0SW5wdXRRdWV1ZWRDb21tYW5kc0ltcGwoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3QgcXVldWVkQ29tbWFuZHMgPSB1c2VDb21tYW5kUXVldWUoKVxuICBjb25zdCB2aWV3aW5nQWdlbnQgPSB1c2VBcHBTdGF0ZShzID0+ICEhcy52aWV3aW5nQWdlbnRUYXNrSWQpXG4gIC8vIEJyaWVmIGxheW91dDogZGltIHF1ZXVlIGl0ZW1zICsgc2tpcCB0aGUgcGFkZGluZ1ggKGJyaWVmIG1lc3NhZ2VzXG4gIC8vIGFscmVhZHkgaW5kZW50IHRoZW1zZWx2ZXMpLiBHYXRlIG1pcnJvcnMgdGhlIGJyaWVmLXNwaW5uZXIvbWVzc2FnZVxuICAvLyBjaGVjayBlbHNld2hlcmUg4oCUIG5vIHRlYW1tYXRlLXZpZXcgb3ZlcnJpZGUgbmVlZGVkIHNpbmNlIHRoaXNcbiAgLy8gY29tcG9uZW50IGVhcmx5LXJldHVybnMgd2hlbiB2aWV3aW5nIGEgdGVhbW1hdGUuXG4gIGNvbnN0IHVzZUJyaWVmTGF5b3V0ID1cbiAgICBmZWF0dXJlKCdLQUlST1MnKSB8fCBmZWF0dXJlKCdLQUlST1NfQlJJRUYnKVxuICAgICAgPyAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gICAgICAgIHVzZUFwcFN0YXRlKHMgPT4gcy5pc0JyaWVmT25seSlcbiAgICAgIDogZmFsc2VcblxuICAvLyBjcmVhdGVVc2VyTWVzc2FnZSBtaW50cyBhIGZyZXNoIFVVSUQgcGVyIGNhbGw7IHdpdGhvdXQgbWVtb2l6YXRpb24sIHN0cmVhbWluZ1xuICAvLyByZS1yZW5kZXJzIGRlZmVhdCBNZXNzYWdlJ3MgYXJlTWVzc2FnZVByb3BzRXF1YWwgKGNvbXBhcmVzIHV1aWQpIOKGkiBmbGlja2VyLlxuICBjb25zdCBtZXNzYWdlcyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGlmIChxdWV1ZWRDb21tYW5kcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsXG4gICAgLy8gdGFzay1ub3RpZmljYXRpb24gaXMgc2hvd24gdmlhIHVzZUluYm94Tm90aWZpY2F0aW9uOyBtb3N0IGlzTWV0YSBjb21tYW5kc1xuICAgIC8vIChzY2hlZHVsZWQgdGFza3MsIHByb2FjdGl2ZSB0aWNrcykgYXJlIHN5c3RlbS1nZW5lcmF0ZWQgYW5kIGhpZGRlbi5cbiAgICAvLyBDaGFubmVsIG1lc3NhZ2VzIGFyZSB0aGUgZXhjZXB0aW9uIOKAlCBpc01ldGEgYnV0IHNob3duIHNvIHRoZSBrZXlib2FyZFxuICAgIC8vIHVzZXIgc2VlcyB3aGF0IGFycml2ZWQuXG4gICAgY29uc3QgdmlzaWJsZUNvbW1hbmRzID0gcXVldWVkQ29tbWFuZHMuZmlsdGVyKGlzUXVldWVkQ29tbWFuZFZpc2libGUpXG4gICAgaWYgKHZpc2libGVDb21tYW5kcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsXG4gICAgY29uc3QgcHJvY2Vzc2VkQ29tbWFuZHMgPSBwcm9jZXNzUXVldWVkQ29tbWFuZHModmlzaWJsZUNvbW1hbmRzKVxuICAgIHJldHVybiBub3JtYWxpemVNZXNzYWdlcyhcbiAgICAgIHByb2Nlc3NlZENvbW1hbmRzLm1hcChjbWQgPT4ge1xuICAgICAgICBsZXQgY29udGVudCA9IGNtZC52YWx1ZVxuICAgICAgICBpZiAoY21kLm1vZGUgPT09ICdiYXNoJyAmJiB0eXBlb2YgY29udGVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb250ZW50ID0gYDxiYXNoLWlucHV0PiR7Y29udGVudH08L2Jhc2gtaW5wdXQ+YFxuICAgICAgICB9XG4gICAgICAgIC8vIFtJbWFnZSAjTl0gcGxhY2Vob2xkZXJzIGFyZSBpbmxpbmUgaW4gdGhlIHRleHQgdmFsdWUgKGluc2VydGVkIGF0XG4gICAgICAgIC8vIHBhc3RlIHRpbWUpLCBzbyB0aGUgcXVldWUgcHJldmlldyBzaG93cyB0aGVtIHdpdGhvdXQgc3R1YiBibG9ja3MuXG4gICAgICAgIHJldHVybiBjcmVhdGVVc2VyTWVzc2FnZSh7IGNvbnRlbnQgfSlcbiAgICAgIH0pLFxuICAgIClcbiAgfSwgW3F1ZXVlZENvbW1hbmRzXSlcblxuICAvLyBEb24ndCBzaG93IGxlYWRlcidzIHF1ZXVlZCBjb21tYW5kcyB3aGVuIHZpZXdpbmcgYW55IGFnZW50J3MgdHJhbnNjcmlwdFxuICBpZiAodmlld2luZ0FnZW50IHx8IG1lc3NhZ2VzID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPEJveCBtYXJnaW5Ub3A9ezF9IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgIHttZXNzYWdlcy5tYXAoKG1lc3NhZ2UsIGkpID0+IChcbiAgICAgICAgPFF1ZXVlZE1lc3NhZ2VQcm92aWRlclxuICAgICAgICAgIGtleT17aX1cbiAgICAgICAgICBpc0ZpcnN0PXtpID09PSAwfVxuICAgICAgICAgIHVzZUJyaWVmTGF5b3V0PXt1c2VCcmllZkxheW91dH1cbiAgICAgICAgPlxuICAgICAgICAgIDxNZXNzYWdlXG4gICAgICAgICAgICBtZXNzYWdlPXttZXNzYWdlfVxuICAgICAgICAgICAgbG9va3Vwcz17RU1QVFlfTE9PS1VQU31cbiAgICAgICAgICAgIGFkZE1hcmdpbj17ZmFsc2V9XG4gICAgICAgICAgICB0b29scz17W119XG4gICAgICAgICAgICBjb21tYW5kcz17W119XG4gICAgICAgICAgICB2ZXJib3NlPXtmYWxzZX1cbiAgICAgICAgICAgIGluUHJvZ3Jlc3NUb29sVXNlSURzPXtFTVBUWV9TRVR9XG4gICAgICAgICAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZT17W119XG4gICAgICAgICAgICBzaG91bGRBbmltYXRlPXtmYWxzZX1cbiAgICAgICAgICAgIHNob3VsZFNob3dEb3Q9e2ZhbHNlfVxuICAgICAgICAgICAgaXNUcmFuc2NyaXB0TW9kZT17ZmFsc2V9XG4gICAgICAgICAgICBpc1N0YXRpYz17dHJ1ZX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L1F1ZXVlZE1lc3NhZ2VQcm92aWRlcj5cbiAgICAgICkpfVxuICAgIDwvQm94PlxuICApXG59XG5cbmV4cG9ydCBjb25zdCBQcm9tcHRJbnB1dFF1ZXVlZENvbW1hbmRzID0gUmVhY3QubWVtbyhcbiAgUHJvbXB0SW5wdXRRdWV1ZWRDb21tYW5kc0ltcGwsXG4pXG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLE9BQU8sUUFBUSxZQUFZO0FBQ3BDLE9BQU8sS0FBS0MsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsT0FBTyxRQUFRLE9BQU87QUFDL0IsU0FBU0MsR0FBRyxRQUFRLFlBQVk7QUFDaEMsU0FBU0MsV0FBVyxRQUFRLHVCQUF1QjtBQUNuRCxTQUNFQyxVQUFVLEVBQ1ZDLFdBQVcsRUFDWEMscUJBQXFCLFFBQ2hCLHdCQUF3QjtBQUMvQixTQUFTQyxxQkFBcUIsUUFBUSx1Q0FBdUM7QUFDN0UsU0FBU0MsZUFBZSxRQUFRLGdDQUFnQztBQUNoRSxjQUFjQyxhQUFhLFFBQVEsK0JBQStCO0FBQ2xFLFNBQVNDLHNCQUFzQixRQUFRLG9DQUFvQztBQUMzRSxTQUNFQyxp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