πŸ“„ File detail

components/mcp/MCPStdioServerMenu.tsx

🧩 .tsxπŸ“ 177 linesπŸ’Ύ 28,394 bytesπŸ“ text
← Back to All Files

🎯 Use case

This file lives under β€œcomponents/”, which covers shared React UI pieces. On the API surface it exposes MCPStdioServerMenu β€” mainly types, interfaces, or factory objects. Dependencies touch figures and React UI. It composes internal code from commands, hooks, ink, services, and state (relative imports).

Generated from folder role, exports, dependency roots, and inline comments β€” not hand-reviewed for every path.

🧠 Inline summary

import figures from 'figures'; import React, { useState } from 'react'; import type { CommandResultDisplay } from '../../commands.js'; import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js'; import { Box, color, Text, useTheme } from '../../ink.js';

πŸ“€ Exports (heuristic)

  • MCPStdioServerMenu

πŸ“š External import roots

Package roots from from "…" (relative paths omitted).

  • figures
  • react

πŸ–₯️ Source preview

import figures from 'figures';
import React, { useState } from 'react';
import type { CommandResultDisplay } from '../../commands.js';
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js';
import { Box, color, Text, useTheme } from '../../ink.js';
import { getMcpConfigByName } from '../../services/mcp/config.js';
import { useMcpReconnect, useMcpToggleEnabled } from '../../services/mcp/MCPConnectionManager.js';
import { describeMcpConfigFilePath, filterMcpPromptsByServer } from '../../services/mcp/utils.js';
import { useAppState } from '../../state/AppState.js';
import { errorMessage } from '../../utils/errors.js';
import { capitalize } from '../../utils/stringUtils.js';
import { ConfigurableShortcutHint } from '../ConfigurableShortcutHint.js';
import { Select } from '../CustomSelect/index.js';
import { Byline } from '../design-system/Byline.js';
import { KeyboardShortcutHint } from '../design-system/KeyboardShortcutHint.js';
import { Spinner } from '../Spinner.js';
import { CapabilitiesSection } from './CapabilitiesSection.js';
import type { StdioServerInfo } from './types.js';
import { handleReconnectError, handleReconnectResult } from './utils/reconnectHelpers.js';
type Props = {
  server: StdioServerInfo;
  serverToolsCount: number;
  onViewTools: () => void;
  onCancel: () => void;
  onComplete: (result?: string, options?: {
    display?: CommandResultDisplay;
  }) => void;
  borderless?: boolean;
};
export function MCPStdioServerMenu({
  server,
  serverToolsCount,
  onViewTools,
  onCancel,
  onComplete,
  borderless = false
}: Props): React.ReactNode {
  const [theme] = useTheme();
  const exitState = useExitOnCtrlCDWithKeybindings();
  const mcp = useAppState(s => s.mcp);
  const reconnectMcpServer = useMcpReconnect();
  const toggleMcpServer = useMcpToggleEnabled();
  const [isReconnecting, setIsReconnecting] = useState(false);
  const handleToggleEnabled = React.useCallback(async () => {
    const wasEnabled = server.client.type !== 'disabled';
    try {
      await toggleMcpServer(server.name);
      // Return to the server list so user can continue managing other servers
      onCancel();
    } catch (err) {
      const action = wasEnabled ? 'disable' : 'enable';
      onComplete(`Failed to ${action} MCP server '${server.name}': ${errorMessage(err)}`);
    }
  }, [server.client.type, server.name, toggleMcpServer, onCancel, onComplete]);
  const capitalizedServerName = capitalize(String(server.name));

  // Count MCP prompts for this server (skills are shown in /skills, not here)
  const serverCommandsCount = filterMcpPromptsByServer(mcp.commands, server.name).length;
  const menuOptions = [];

  // Only show "View tools" if server is not disabled and has tools
  if (server.client.type !== 'disabled' && serverToolsCount > 0) {
    menuOptions.push({
      label: 'View tools',
      value: 'tools'
    });
  }

  // Only show reconnect option if the server is not disabled
  if (server.client.type !== 'disabled') {
    menuOptions.push({
      label: 'Reconnect',
      value: 'reconnectMcpServer'
    });
  }
  menuOptions.push({
    label: server.client.type !== 'disabled' ? 'Disable' : 'Enable',
    value: 'toggle-enabled'
  });

  // If there are no other options, add a back option so Select handles escape
  if (menuOptions.length === 0) {
    menuOptions.push({
      label: 'Back',
      value: 'back'
    });
  }
  if (isReconnecting) {
    return <Box flexDirection="column" gap={1} padding={1}>
        <Text color="text">
          Reconnecting to <Text bold>{server.name}</Text>
        </Text>
        <Box>
          <Spinner />
          <Text> Restarting MCP server process</Text>
        </Box>
        <Text dimColor>This may take a few moments.</Text>
      </Box>;
  }
  return <Box flexDirection="column">
      <Box flexDirection="column" paddingX={1} borderStyle={borderless ? undefined : 'round'}>
        <Box marginBottom={1}>
          <Text bold>{capitalizedServerName} MCP Server</Text>
        </Box>

        <Box flexDirection="column" gap={0}>
          <Box>
            <Text bold>Status: </Text>
            {server.client.type === 'disabled' ? <Text>{color('inactive', theme)(figures.radioOff)} disabled</Text> : server.client.type === 'connected' ? <Text>{color('success', theme)(figures.tick)} connected</Text> : server.client.type === 'pending' ? <>
                <Text dimColor>{figures.radioOff}</Text>
                <Text> connecting…</Text>
              </> : <Text>{color('error', theme)(figures.cross)} failed</Text>}
          </Box>

          <Box>
            <Text bold>Command: </Text>
            <Text dimColor>{server.config.command}</Text>
          </Box>

          {server.config.args && server.config.args.length > 0 && <Box>
              <Text bold>Args: </Text>
              <Text dimColor>{server.config.args.join(' ')}</Text>
            </Box>}

          <Box>
            <Text bold>Config location: </Text>
            <Text dimColor>
              {describeMcpConfigFilePath(getMcpConfigByName(server.name)?.scope ?? 'dynamic')}
            </Text>
          </Box>

          {server.client.type === 'connected' && <CapabilitiesSection serverToolsCount={serverToolsCount} serverPromptsCount={serverCommandsCount} serverResourcesCount={mcp.resources[server.name]?.length || 0} />}

          {server.client.type === 'connected' && serverToolsCount > 0 && <Box>
              <Text bold>Tools: </Text>
              <Text dimColor>{serverToolsCount} tools</Text>
            </Box>}
        </Box>

        {menuOptions.length > 0 && <Box marginTop={1}>
            <Select options={menuOptions} onChange={async value => {
          if (value === 'tools') {
            onViewTools();
          } else if (value === 'reconnectMcpServer') {
            setIsReconnecting(true);
            try {
              const result = await reconnectMcpServer(server.name);
              const {
                message
              } = handleReconnectResult(result, server.name);
              onComplete?.(message);
            } catch (err_0) {
              onComplete?.(handleReconnectError(err_0, server.name));
            } finally {
              setIsReconnecting(false);
            }
          } else if (value === 'toggle-enabled') {
            await handleToggleEnabled();
          } else if (value === 'back') {
            onCancel();
          }
        }} onCancel={onCancel} />
          </Box>}
      </Box>

      <Box marginTop={1}>
        <Text dimColor italic>
          {exitState.pending ? <>Press {exitState.keyName} again to exit</> : <Byline>
              <KeyboardShortcutHint shortcut="↑↓" action="navigate" />
              <KeyboardShortcutHint shortcut="Enter" action="select" />
              <ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="back" />
            </Byline>}
        </Text>
      </Box>
    </Box>;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmaWd1cmVzIiwiUmVhY3QiLCJ1c2VTdGF0ZSIsIkNvbW1hbmRSZXN1bHREaXNwbGF5IiwidXNlRXhpdE9uQ3RybENEV2l0aEtleWJpbmRpbmdzIiwiQm94IiwiY29sb3IiLCJUZXh0IiwidXNlVGhlbWUiLCJnZXRNY3BDb25maWdCeU5hbWUiLCJ1c2VNY3BSZWNvbm5lY3QiLCJ1c2VNY3BUb2dnbGVFbmFibGVkIiwiZGVzY3JpYmVNY3BDb25maWdGaWxlUGF0aCIsImZpbHRlck1jcFByb21wdHNCeVNlcnZlciIsInVzZUFwcFN0YXRlIiwiZXJyb3JNZXNzYWdlIiwiY2FwaXRhbGl6ZSIsIkNvbmZpZ3VyYWJsZVNob3J0Y3V0SGludCIsIlNlbGVjdCIsIkJ5bGluZSIsIktleWJvYXJkU2hvcnRjdXRIaW50IiwiU3Bpbm5lciIsIkNhcGFiaWxpdGllc1NlY3Rpb24iLCJTdGRpb1NlcnZlckluZm8iLCJoYW5kbGVSZWNvbm5lY3RFcnJvciIsImhhbmRsZVJlY29ubmVjdFJlc3VsdCIsIlByb3BzIiwic2VydmVyIiwic2VydmVyVG9vbHNDb3VudCIsIm9uVmlld1Rvb2xzIiwib25DYW5jZWwiLCJvbkNvbXBsZXRlIiwicmVzdWx0Iiwib3B0aW9ucyIsImRpc3BsYXkiLCJib3JkZXJsZXNzIiwiTUNQU3RkaW9TZXJ2ZXJNZW51IiwiUmVhY3ROb2RlIiwidGhlbWUiLCJleGl0U3RhdGUiLCJtY3AiLCJzIiwicmVjb25uZWN0TWNwU2VydmVyIiwidG9nZ2xlTWNwU2VydmVyIiwiaXNSZWNvbm5lY3RpbmciLCJzZXRJc1JlY29ubmVjdGluZyIsImhhbmRsZVRvZ2dsZUVuYWJsZWQiLCJ1c2VDYWxsYmFjayIsIndhc0VuYWJsZWQiLCJjbGllbnQiLCJ0eXBlIiwibmFtZSIsImVyciIsImFjdGlvbiIsImNhcGl0YWxpemVkU2VydmVyTmFtZSIsIlN0cmluZyIsInNlcnZlckNvbW1hbmRzQ291bnQiLCJjb21tYW5kcyIsImxlbmd0aCIsIm1lbnVPcHRpb25zIiwicHVzaCIsImxhYmVsIiwidmFsdWUiLCJ1bmRlZmluZWQiLCJyYWRpb09mZiIsInRpY2siLCJjcm9zcyIsImNvbmZpZyIsImNvbW1hbmQiLCJhcmdzIiwiam9pbiIsInNjb3BlIiwicmVzb3VyY2VzIiwibWVzc2FnZSIsInBlbmRpbmciLCJrZXlOYW1lIl0sInNvdXJjZXMiOlsiTUNQU3RkaW9TZXJ2ZXJNZW51LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZmlndXJlcyBmcm9tICdmaWd1cmVzJ1xuaW1wb3J0IFJlYWN0LCB7IHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IENvbW1hbmRSZXN1bHREaXNwbGF5IH0gZnJvbSAnLi4vLi4vY29tbWFuZHMuanMnXG5pbXBvcnQgeyB1c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MgfSBmcm9tICcuLi8uLi9ob29rcy91c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MuanMnXG5pbXBvcnQgeyBCb3gsIGNvbG9yLCBUZXh0LCB1c2VUaGVtZSB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB7IGdldE1jcENvbmZpZ0J5TmFtZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL21jcC9jb25maWcuanMnXG5pbXBvcnQge1xuICB1c2VNY3BSZWNvbm5lY3QsXG4gIHVzZU1jcFRvZ2dsZUVuYWJsZWQsXG59IGZyb20gJy4uLy4uL3NlcnZpY2VzL21jcC9NQ1BDb25uZWN0aW9uTWFuYWdlci5qcydcbmltcG9ydCB7XG4gIGRlc2NyaWJlTWNwQ29uZmlnRmlsZVBhdGgsXG4gIGZpbHRlck1jcFByb21wdHNCeVNlcnZlcixcbn0gZnJvbSAnLi4vLi4vc2VydmljZXMvbWNwL3V0aWxzLmpzJ1xuaW1wb3J0IHsgdXNlQXBwU3RhdGUgfSBmcm9tICcuLi8uLi9zdGF0ZS9BcHBTdGF0ZS5qcydcbmltcG9ydCB7IGVycm9yTWVzc2FnZSB9IGZyb20gJy4uLy4uL3V0aWxzL2Vycm9ycy5qcydcbmltcG9ydCB7IGNhcGl0YWxpemUgfSBmcm9tICcuLi8uLi91dGlscy9zdHJpbmdVdGlscy5qcydcbmltcG9ydCB7IENvbmZpZ3VyYWJsZVNob3J0Y3V0SGludCB9IGZyb20gJy4uL0NvbmZpZ3VyYWJsZVNob3J0Y3V0SGludC5qcydcbmltcG9ydCB7IFNlbGVjdCB9IGZyb20gJy4uL0N1c3RvbVNlbGVjdC9pbmRleC5qcydcbmltcG9ydCB7IEJ5bGluZSB9IGZyb20gJy4uL2Rlc2lnbi1zeXN0ZW0vQnlsaW5lLmpzJ1xuaW1wb3J0IHsgS2V5Ym9hcmRTaG9ydGN1dEhpbnQgfSBmcm9tICcuLi9kZXNpZ24tc3lzdGVtL0tleWJvYXJkU2hvcnRjdXRIaW50LmpzJ1xuaW1wb3J0IHsgU3Bpbm5lciB9IGZyb20gJy4uL1NwaW5uZXIuanMnXG5pbXBvcnQgeyBDYXBhYmlsaXRpZXNTZWN0aW9uIH0gZnJvbSAnLi9DYXBhYmlsaXRpZXNTZWN0aW9uLmpzJ1xuaW1wb3J0IHR5cGUgeyBTdGRpb1NlcnZlckluZm8gfSBmcm9tICcuL3R5cGVzLmpzJ1xuaW1wb3J0IHtcbiAgaGFuZGxlUmVjb25uZWN0RXJyb3IsXG4gIGhhbmRsZVJlY29ubmVjdFJlc3VsdCxcbn0gZnJvbSAnLi91dGlscy9yZWNvbm5lY3RIZWxwZXJzLmpzJ1xuXG50eXBlIFByb3BzID0ge1xuICBzZXJ2ZXI6IFN0ZGlvU2VydmVySW5mb1xuICBzZXJ2ZXJUb29sc0NvdW50OiBudW1iZXJcbiAgb25WaWV3VG9vbHM6ICgpID0+IHZvaWRcbiAgb25DYW5jZWw6ICgpID0+IHZvaWRcbiAgb25Db21wbGV0ZTogKFxuICAgIHJlc3VsdD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogeyBkaXNwbGF5PzogQ29tbWFuZFJlc3VsdERpc3BsYXkgfSxcbiAgKSA9PiB2b2lkXG4gIGJvcmRlcmxlc3M/OiBib29sZWFuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBNQ1BTdGRpb1NlcnZlck1lbnUoe1xuICBzZXJ2ZXIsXG4gIHNlcnZlclRvb2xzQ291bnQsXG4gIG9uVmlld1Rvb2xzLFxuICBvbkNhbmNlbCxcbiAgb25Db21wbGV0ZSxcbiAgYm9yZGVybGVzcyA9IGZhbHNlLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBbdGhlbWVdID0gdXNlVGhlbWUoKVxuICBjb25zdCBleGl0U3RhdGUgPSB1c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MoKVxuICBjb25zdCBtY3AgPSB1c2VBcHBTdGF0ZShzID0+IHMubWNwKVxuICBjb25zdCByZWNvbm5lY3RNY3BTZXJ2ZXIgPSB1c2VNY3BSZWNvbm5lY3QoKVxuICBjb25zdCB0b2dnbGVNY3BTZXJ2ZXIgPSB1c2VNY3BUb2dnbGVFbmFibGVkKClcbiAgY29uc3QgW2lzUmVjb25uZWN0aW5nLCBzZXRJc1JlY29ubmVjdGluZ10gPSB1c2VTdGF0ZShmYWxzZSlcblxuICBjb25zdCBoYW5kbGVUb2dnbGVFbmFibGVkID0gUmVhY3QudXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHdhc0VuYWJsZWQgPSBzZXJ2ZXIuY2xpZW50LnR5cGUgIT09ICdkaXNhYmxlZCdcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0b2dnbGVNY3BTZXJ2ZXIoc2VydmVyLm5hbWUpXG4gICAgICAvLyBSZXR1cm4gdG8gdGhlIHNlcnZlciBsaXN0IHNvIHVzZXIgY2FuIGNvbnRpbnVlIG1hbmFnaW5nIG90aGVyIHNlcnZlcnNcbiAgICAgIG9uQ2FuY2VsKClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IGFjdGlvbiA9IHdhc0VuYWJsZWQgPyAnZGlzYWJsZScgOiAnZW5hYmxlJ1xuICAgICAgb25Db21wbGV0ZShcbiAgICAgICAgYEZhaWxlZCB0byAke2FjdGlvbn0gTUNQIHNlcnZlciAnJHtzZXJ2ZXIubmFtZX0nOiAke2Vycm9yTWVzc2FnZShlcnIpfWAsXG4gICAgICApXG4gICAgfVxuICB9LCBbc2VydmVyLmNsaWVudC50eXBlLCBzZXJ2ZXIubmFtZSwgdG9nZ2xlTWNwU2VydmVyLCBvbkNhbmNlbCwgb25Db21wbGV0ZV0pXG5cbiAgY29uc3QgY2FwaXRhbGl6ZWRTZXJ2ZXJOYW1lID0gY2FwaXRhbGl6ZShTdHJpbmcoc2VydmVyLm5hbWUpKVxuXG4gIC8vIENvdW50IE1DUCBwcm9tcHRzIGZvciB0aGlzIHNlcnZlciAoc2tpbGxzIGFyZSBzaG93biBpbiAvc2tpbGxzLCBub3QgaGVyZSlcbiAgY29uc3Qgc2VydmVyQ29tbWFuZHNDb3VudCA9IGZpbHRlck1jcFByb21wdHNCeVNlcnZlcihcbiAgICBtY3AuY29tbWFuZHMsXG4gICAgc2VydmVyLm5hbWUsXG4gICkubGVuZ3RoXG5cbiAgY29uc3QgbWVudU9wdGlvbnMgPSBbXVxuXG4gIC8vIE9ubHkgc2hvdyBcIlZpZXcgdG9vbHNcIiBpZiBzZXJ2ZXIgaXMgbm90IGRpc2FibGVkIGFuZCBoYXMgdG9vbHNcbiAgaWYgKHNlcnZlci5jbGllbnQudHlwZSAhPT0gJ2Rpc2FibGVkJyAmJiBzZXJ2ZXJUb29sc0NvdW50ID4gMCkge1xuICAgIG1lbnVPcHRpb25zLnB1c2goe1xuICAgICAgbGFiZWw6ICdWaWV3IHRvb2xzJyxcbiAgICAgIHZhbHVlOiAndG9vbHMnLFxuICAgIH0pXG4gIH1cblxuICAvLyBPbmx5IHNob3cgcmVjb25uZWN0IG9wdGlvbiBpZiB0aGUgc2VydmVyIGlzIG5vdCBkaXNhYmxlZFxuICBpZiAoc2VydmVyLmNsaWVudC50eXBlICE9PSAnZGlzYWJsZWQnKSB7XG4gICAgbWVudU9wdGlvbnMucHVzaCh7XG4gICAgICBsYWJlbDogJ1JlY29ubmVjdCcsXG4gICAgICB2YWx1ZTogJ3JlY29ubmVjdE1jcFNlcnZlcicsXG4gICAgfSlcbiAgfVxuXG4gIG1lbnVPcHRpb25zLnB1c2goe1xuICAgIGxhYmVsOiBzZXJ2ZXIuY2xpZW50LnR5cGUgIT09ICdkaXNhYmxlZCcgPyAnRGlzYWJsZScgOiAnRW5hYmxlJyxcbiAgICB2YWx1ZTogJ3RvZ2dsZS1lbmFibGVkJyxcbiAgfSlcblxuICAvLyBJZiB0aGVyZSBhcmUgbm8gb3RoZXIgb3B0aW9ucywgYWRkIGEgYmFjayBvcHRpb24gc28gU2VsZWN0IGhhbmRsZXMgZXNjYXBlXG4gIGlmIChtZW51T3B0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICBtZW51T3B0aW9ucy5wdXNoKHtcbiAgICAgIGxhYmVsOiAnQmFjaycsXG4gICAgICB2YWx1ZTogJ2JhY2snLFxuICAgIH0pXG4gIH1cblxuICBpZiAoaXNSZWNvbm5lY3RpbmcpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgZ2FwPXsxfSBwYWRkaW5nPXsxfT5cbiAgICAgICAgPFRleHQgY29sb3I9XCJ0ZXh0XCI+XG4gICAgICAgICAgUmVjb25uZWN0aW5nIHRvIDxUZXh0IGJvbGQ+e3NlcnZlci5uYW1lfTwvVGV4dD5cbiAgICAgICAgPC9UZXh0PlxuICAgICAgICA8Qm94PlxuICAgICAgICAgIDxTcGlubmVyIC8+XG4gICAgICAgICAgPFRleHQ+IFJlc3RhcnRpbmcgTUNQIHNlcnZlciBwcm9jZXNzPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICAgPFRleHQgZGltQ29sb3I+VGhpcyBtYXkgdGFrZSBhIGZldyBtb21lbnRzLjwvVGV4dD5cbiAgICAgIDwvQm94PlxuICAgIClcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCI+XG4gICAgICA8Qm94XG4gICAgICAgIGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIlxuICAgICAgICBwYWRkaW5nWD17MX1cbiAgICAgICAgYm9yZGVyU3R5bGU9e2JvcmRlcmxlc3MgPyB1bmRlZmluZWQgOiAncm91bmQnfVxuICAgICAgPlxuICAgICAgICA8Qm94IG1hcmdpbkJvdHRvbT17MX0+XG4gICAgICAgICAgPFRleHQgYm9sZD57Y2FwaXRhbGl6ZWRTZXJ2ZXJOYW1lfSBNQ1AgU2VydmVyPC9UZXh0PlxuICAgICAgICA8L0JveD5cblxuICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBnYXA9ezB9PlxuICAgICAgICAgIDxCb3g+XG4gICAgICAgICAgICA8VGV4dCBib2xkPlN0YXR1czogPC9UZXh0PlxuICAgICAgICAgICAge3NlcnZlci5jbGllbnQudHlwZSA9PT0gJ2Rpc2FibGVkJyA/IChcbiAgICAgICAgICAgICAgPFRleHQ+e2NvbG9yKCdpbmFjdGl2ZScsIHRoZW1lKShmaWd1cmVzLnJhZGlvT2ZmKX0gZGlzYWJsZWQ8L1RleHQ+XG4gICAgICAgICAgICApIDogc2VydmVyLmNsaWVudC50eXBlID09PSAnY29ubmVjdGVkJyA/IChcbiAgICAgICAgICAgICAgPFRleHQ+e2NvbG9yKCdzdWNjZXNzJywgdGhlbWUpKGZpZ3VyZXMudGljayl9IGNvbm5lY3RlZDwvVGV4dD5cbiAgICAgICAgICAgICkgOiBzZXJ2ZXIuY2xpZW50LnR5cGUgPT09ICdwZW5kaW5nJyA/IChcbiAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj57ZmlndXJlcy5yYWRpb09mZn08L1RleHQ+XG4gICAgICAgICAgICAgICAgPFRleHQ+IGNvbm5lY3RpbmfigKY8L1RleHQ+XG4gICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICAgPFRleHQ+e2NvbG9yKCdlcnJvcicsIHRoZW1lKShmaWd1cmVzLmNyb3NzKX0gZmFpbGVkPC9UZXh0PlxuICAgICAgICAgICAgKX1cbiAgICAgICAgICA8L0JveD5cblxuICAgICAgICAgIDxCb3g+XG4gICAgICAgICAgICA8VGV4dCBib2xkPkNvbW1hbmQ6IDwvVGV4dD5cbiAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPntzZXJ2ZXIuY29uZmlnLmNvbW1hbmR9PC9UZXh0PlxuICAgICAgICAgIDwvQm94PlxuXG4gICAgICAgICAge3NlcnZlci5jb25maWcuYXJncyAmJiBzZXJ2ZXIuY29uZmlnLmFyZ3MubGVuZ3RoID4gMCAmJiAoXG4gICAgICAgICAgICA8Qm94PlxuICAgICAgICAgICAgICA8VGV4dCBib2xkPkFyZ3M6IDwvVGV4dD5cbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+e3NlcnZlci5jb25maWcuYXJncy5qb2luKCcgJyl9PC9UZXh0PlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKX1cblxuICAgICAgICAgIDxCb3g+XG4gICAgICAgICAgICA8VGV4dCBib2xkPkNvbmZpZyBsb2NhdGlvbjogPC9UZXh0PlxuICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgIHtkZXNjcmliZU1jcENvbmZpZ0ZpbGVQYXRoKFxuICAgICAgICAgICAgICAgIGdldE1jcENvbmZpZ0J5TmFtZShzZXJ2ZXIubmFtZSk/LnNjb3BlID8/ICdkeW5hbWljJyxcbiAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8L0JveD5cblxuICAgICAgICAgIHtzZXJ2ZXIuY2xpZW50LnR5cGUgPT09ICdjb25uZWN0ZWQnICYmIChcbiAgICAgICAgICAgIDxDYXBhYmlsaXRpZXNTZWN0aW9uXG4gICAgICAgICAgICAgIHNlcnZlclRvb2xzQ291bnQ9e3NlcnZlclRvb2xzQ291bnR9XG4gICAgICAgICAgICAgIHNlcnZlclByb21wdHNDb3VudD17c2VydmVyQ29tbWFuZHNDb3VudH1cbiAgICAgICAgICAgICAgc2VydmVyUmVzb3VyY2VzQ291bnQ9e21jcC5yZXNvdXJjZXNbc2VydmVyLm5hbWVdPy5sZW5ndGggfHwgMH1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgKX1cblxuICAgICAgICAgIHtzZXJ2ZXIuY2xpZW50LnR5cGUgPT09ICdjb25uZWN0ZWQnICYmIHNlcnZlclRvb2xzQ291bnQgPiAwICYmIChcbiAgICAgICAgICAgIDxCb3g+XG4gICAgICAgICAgICAgIDxUZXh0IGJvbGQ+VG9vbHM6IDwvVGV4dD5cbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+e3NlcnZlclRvb2xzQ291bnR9IHRvb2xzPC9UZXh0PlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKX1cbiAgICAgICAgPC9Cb3g+XG5cbiAgICAgICAge21lbnVPcHRpb25zLmxlbmd0aCA+IDAgJiYgKFxuICAgICAgICAgIDxCb3ggbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICAgIDxTZWxlY3RcbiAgICAgICAgICAgICAgb3B0aW9ucz17bWVudU9wdGlvbnN9XG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXthc3luYyB2YWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSAndG9vbHMnKSB7XG4gICAgICAgICAgICAgICAgICBvblZpZXdUb29scygpXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ3JlY29ubmVjdE1jcFNlcnZlcicpIHtcbiAgICAgICAgICAgICAgICAgIHNldElzUmVjb25uZWN0aW5nKHRydWUpXG4gICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZWNvbm5lY3RNY3BTZXJ2ZXIoc2VydmVyLm5hbWUpXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgbWVzc2FnZSB9ID0gaGFuZGxlUmVjb25uZWN0UmVzdWx0KFxuICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICBvbkNvbXBsZXRlPy4obWVzc2FnZSlcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICBvbkNvbXBsZXRlPy4oaGFuZGxlUmVjb25uZWN0RXJyb3IoZXJyLCBzZXJ2ZXIubmFtZSkpXG4gICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICBzZXRJc1JlY29ubmVjdGluZyhmYWxzZSlcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAndG9nZ2xlLWVuYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICBhd2FpdCBoYW5kbGVUb2dnbGVFbmFibGVkKClcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAnYmFjaycpIHtcbiAgICAgICAgICAgICAgICAgIG9uQ2FuY2VsKClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgIG9uQ2FuY2VsPXtvbkNhbmNlbH1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9Cb3g+XG4gICAgICAgICl9XG4gICAgICA8L0JveD5cblxuICAgICAgPEJveCBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICA8VGV4dCBkaW1Db2xvciBpdGFsaWM+XG4gICAgICAgICAge2V4aXRTdGF0ZS5wZW5kaW5nID8gKFxuICAgICAgICAgICAgPD5QcmVzcyB7ZXhpdFN0YXRlLmtleU5hbWV9IGFnYWluIHRvIGV4aXQ8Lz5cbiAgICAgICAgICApIDogKFxuICAgICAgICAgICAgPEJ5bGluZT5cbiAgICAgICAgICAgICAgPEtleWJvYXJkU2hvcnRjdXRIaW50IHNob3J0Y3V0PVwi4oaR4oaTXCIgYWN0aW9uPVwibmF2aWdhdGVcIiAvPlxuICAgICAgICAgICAgICA8S2V5Ym9hcmRTaG9ydGN1dEhpbnQgc2hvcnRjdXQ9XCJFbnRlclwiIGFjdGlvbj1cInNlbGVjdFwiIC8+XG4gICAgICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgICAgICBhY3Rpb249XCJjb25maXJtOm5vXCJcbiAgICAgICAgICAgICAgICBjb250ZXh0PVwiQ29uZmlybWF0aW9uXCJcbiAgICAgICAgICAgICAgICBmYWxsYmFjaz1cIkVzY1wiXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJiYWNrXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvQnlsaW5lPlxuICAgICAgICAgICl9XG4g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