π File detail
components/PromptInput/PromptInputFooter.tsx
π§© .tsxπ 191 linesπΎ 33,176 bytesπ text
β Back to All Filesπ― Use case
This file lives under βcomponents/β, which covers shared React UI pieces. It primarily provides a default export (component, class, or entry function). Dependencies touch bun:bundle and React UI. It composes internal code from bridge, context, hooks, ink, and services (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { feature } from 'bun:bundle'; import * as React from 'react'; import { memo, type ReactNode, useMemo, useRef } from 'react'; import { isBridgeEnabled } from '../../bridge/bridgeEnabled.js'; import { getBridgeStatus } from '../../bridge/bridgeStatusUtil.js';
π€ Exports (heuristic)
default
π External import roots
Package roots from from "β¦" (relative paths omitted).
bun:bundlereact
π₯οΈ Source preview
import { feature } from 'bun:bundle';
import * as React from 'react';
import { memo, type ReactNode, useMemo, useRef } from 'react';
import { isBridgeEnabled } from '../../bridge/bridgeEnabled.js';
import { getBridgeStatus } from '../../bridge/bridgeStatusUtil.js';
import { useSetPromptOverlay } from '../../context/promptOverlayContext.js';
import type { VerificationStatus } from '../../hooks/useApiKeyVerification.js';
import type { IDESelection } from '../../hooks/useIdeSelection.js';
import { useSettings } from '../../hooks/useSettings.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { Box, Text } from '../../ink.js';
import type { MCPServerConnection } from '../../services/mcp/types.js';
import { useAppState } from '../../state/AppState.js';
import type { ToolPermissionContext } from '../../Tool.js';
import type { Message } from '../../types/message.js';
import type { PromptInputMode, VimMode } from '../../types/textInputTypes.js';
import type { AutoUpdaterResult } from '../../utils/autoUpdater.js';
import { isFullscreenEnvEnabled } from '../../utils/fullscreen.js';
import { isUndercover } from '../../utils/undercover.js';
import { CoordinatorTaskPanel, useCoordinatorTaskCount } from '../CoordinatorAgentStatus.js';
import { getLastAssistantMessageId, StatusLine, statusLineShouldDisplay } from '../StatusLine.js';
import { Notifications } from './Notifications.js';
import { PromptInputFooterLeftSide } from './PromptInputFooterLeftSide.js';
import { PromptInputFooterSuggestions, type SuggestionItem } from './PromptInputFooterSuggestions.js';
import { PromptInputHelpMenu } from './PromptInputHelpMenu.js';
type Props = {
apiKeyStatus: VerificationStatus;
debug: boolean;
exitMessage: {
show: boolean;
key?: string;
};
vimMode: VimMode | undefined;
mode: PromptInputMode;
autoUpdaterResult: AutoUpdaterResult | null;
isAutoUpdating: boolean;
verbose: boolean;
onAutoUpdaterResult: (result: AutoUpdaterResult) => void;
onChangeIsUpdating: (isUpdating: boolean) => void;
suggestions: SuggestionItem[];
selectedSuggestion: number;
maxColumnWidth?: number;
toolPermissionContext: ToolPermissionContext;
helpOpen: boolean;
suppressHint: boolean;
isLoading: boolean;
tasksSelected: boolean;
teamsSelected: boolean;
bridgeSelected: boolean;
tmuxSelected: boolean;
teammateFooterIndex?: number;
ideSelection: IDESelection | undefined;
mcpClients?: MCPServerConnection[];
isPasting?: boolean;
isInputWrapped?: boolean;
messages: Message[];
isSearching: boolean;
historyQuery: string;
setHistoryQuery: (query: string) => void;
historyFailedMatch: boolean;
onOpenTasksDialog?: (taskId?: string) => void;
};
function PromptInputFooter({
apiKeyStatus,
debug,
exitMessage,
vimMode,
mode,
autoUpdaterResult,
isAutoUpdating,
verbose,
onAutoUpdaterResult,
onChangeIsUpdating,
suggestions,
selectedSuggestion,
maxColumnWidth,
toolPermissionContext,
helpOpen,
suppressHint: suppressHintFromProps,
isLoading,
tasksSelected,
teamsSelected,
bridgeSelected,
tmuxSelected,
teammateFooterIndex,
ideSelection,
mcpClients,
isPasting = false,
isInputWrapped = false,
messages,
isSearching,
historyQuery,
setHistoryQuery,
historyFailedMatch,
onOpenTasksDialog
}: Props): ReactNode {
const settings = useSettings();
const {
columns,
rows
} = useTerminalSize();
const messagesRef = useRef(messages);
messagesRef.current = messages;
const lastAssistantMessageId = useMemo(() => getLastAssistantMessageId(messages), [messages]);
const isNarrow = columns < 80;
// In fullscreen the bottom slot is flexShrink:0, so every row here is a row
// stolen from the ScrollBox. Drop the optional StatusLine first. Non-fullscreen
// has terminal scrollback to absorb overflow, so we never hide StatusLine there.
const isFullscreen = isFullscreenEnvEnabled();
const isShort = isFullscreen && rows < 24;
// Pill highlights when tasks is the active footer item AND no specific
// agent row is selected. When coordinatorTaskIndex >= 0 the pointer has
// moved into CoordinatorTaskPanel, so the pill should un-highlight.
// coordinatorTaskCount === 0 covers the bash-only case (no agent rows
// exist, pill is the only selectable item).
const coordinatorTaskCount = useCoordinatorTaskCount();
const coordinatorTaskIndex = useAppState(s => s.coordinatorTaskIndex);
const pillSelected = tasksSelected && (coordinatorTaskCount === 0 || coordinatorTaskIndex < 0);
// Hide `? for shortcuts` if the user has a custom status line, or during ctrl-r
const suppressHint = suppressHintFromProps || statusLineShouldDisplay(settings) || isSearching;
// Fullscreen: portal data to FullscreenLayout β see promptOverlayContext.tsx
const overlayData = useMemo(() => isFullscreen && suggestions.length ? {
suggestions,
selectedSuggestion,
maxColumnWidth
} : null, [isFullscreen, suggestions, selectedSuggestion, maxColumnWidth]);
useSetPromptOverlay(overlayData);
if (suggestions.length && !isFullscreen) {
return <Box paddingX={2} paddingY={0}>
<PromptInputFooterSuggestions suggestions={suggestions} selectedSuggestion={selectedSuggestion} maxColumnWidth={maxColumnWidth} />
</Box>;
}
if (helpOpen) {
return <PromptInputHelpMenu dimColor={true} fixedWidth={true} paddingX={2} />;
}
return <>
<Box flexDirection={isNarrow ? 'column' : 'row'} justifyContent={isNarrow ? 'flex-start' : 'space-between'} paddingX={2} gap={isNarrow ? 0 : 1}>
<Box flexDirection="column" flexShrink={isNarrow ? 0 : 1}>
{mode === 'prompt' && !isShort && !exitMessage.show && !isPasting && statusLineShouldDisplay(settings) && <StatusLine messagesRef={messagesRef} lastAssistantMessageId={lastAssistantMessageId} vimMode={vimMode} />}
<PromptInputFooterLeftSide exitMessage={exitMessage} vimMode={vimMode} mode={mode} toolPermissionContext={toolPermissionContext} suppressHint={suppressHint} isLoading={isLoading} tasksSelected={pillSelected} teamsSelected={teamsSelected} teammateFooterIndex={teammateFooterIndex} tmuxSelected={tmuxSelected} isPasting={isPasting} isSearching={isSearching} historyQuery={historyQuery} setHistoryQuery={setHistoryQuery} historyFailedMatch={historyFailedMatch} onOpenTasksDialog={onOpenTasksDialog} />
</Box>
<Box flexShrink={1} gap={1}>
{isFullscreen ? null : <Notifications apiKeyStatus={apiKeyStatus} autoUpdaterResult={autoUpdaterResult} debug={debug} isAutoUpdating={isAutoUpdating} verbose={verbose} messages={messages} onAutoUpdaterResult={onAutoUpdaterResult} onChangeIsUpdating={onChangeIsUpdating} ideSelection={ideSelection} mcpClients={mcpClients} isInputWrapped={isInputWrapped} isNarrow={isNarrow} />}
{"external" === 'ant' && isUndercover() && <Text dimColor>undercover</Text>}
<BridgeStatusIndicator bridgeSelected={bridgeSelected} />
</Box>
</Box>
{"external" === 'ant' && <CoordinatorTaskPanel />}
</>;
}
export default memo(PromptInputFooter);
type BridgeStatusProps = {
bridgeSelected: boolean;
};
function BridgeStatusIndicator({
bridgeSelected
}: BridgeStatusProps): React.ReactNode {
if (!feature('BRIDGE_MODE')) return null;
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
const enabled = useAppState(s => s.replBridgeEnabled);
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
const connected = useAppState(s_0 => s_0.replBridgeConnected);
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
const sessionActive = useAppState(s_1 => s_1.replBridgeSessionActive);
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
const reconnecting = useAppState(s_2 => s_2.replBridgeReconnecting);
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
const explicit = useAppState(s_3 => s_3.replBridgeExplicit);
// Failed state is surfaced via notification (useReplBridge), not a footer pill.
if (!isBridgeEnabled() || !enabled) return null;
const status = getBridgeStatus({
error: undefined,
connected,
sessionActive,
reconnecting
});
// For implicit (config-driven) remote, only show the reconnecting state
if (!explicit && status.label !== 'Remote Control reconnecting') {
return null;
}
return <Text color={bridgeSelected ? 'background' : status.color} inverse={bridgeSelected} wrap="truncate">
{status.label}
{bridgeSelected && <Text dimColor> Β· Enter to view</Text>}
</Text>;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiUmVhY3QiLCJtZW1vIiwiUmVhY3ROb2RlIiwidXNlTWVtbyIsInVzZVJlZiIsImlzQnJpZGdlRW5hYmxlZCIsImdldEJyaWRnZVN0YXR1cyIsInVzZVNldFByb21wdE92ZXJsYXkiLCJWZXJpZmljYXRpb25TdGF0dXMiLCJJREVTZWxlY3Rpb24iLCJ1c2VTZXR0aW5ncyIsInVzZVRlcm1pbmFsU2l6ZSIsIkJveCIsIlRleHQiLCJNQ1BTZXJ2ZXJDb25uZWN0aW9uIiwidXNlQXBwU3RhdGUiLCJUb29sUGVybWlzc2lvbkNvbnRleHQiLCJNZXNzYWdlIiwiUHJvbXB0SW5wdXRNb2RlIiwiVmltTW9kZSIsIkF1dG9VcGRhdGVyUmVzdWx0IiwiaXNGdWxsc2NyZWVuRW52RW5hYmxlZCIsImlzVW5kZXJjb3ZlciIsIkNvb3JkaW5hdG9yVGFza1BhbmVsIiwidXNlQ29vcmRpbmF0b3JUYXNrQ291bnQiLCJnZXRMYXN0QXNzaXN0YW50TWVzc2FnZUlkIiwiU3RhdHVzTGluZSIsInN0YXR1c0xpbmVTaG91bGREaXNwbGF5IiwiTm90aWZpY2F0aW9ucyIsIlByb21wdElucHV0Rm9vdGVyTGVmdFNpZGUiLCJQcm9tcHRJbnB1dEZvb3RlclN1Z2dlc3Rpb25zIiwiU3VnZ2VzdGlvbkl0ZW0iLCJQcm9tcHRJbnB1dEhlbHBNZW51IiwiUHJvcHMiLCJhcGlLZXlTdGF0dXMiLCJkZWJ1ZyIsImV4aXRNZXNzYWdlIiwic2hvdyIsImtleSIsInZpbU1vZGUiLCJtb2RlIiwiYXV0b1VwZGF0ZXJSZXN1bHQiLCJpc0F1dG9VcGRhdGluZyIsInZlcmJvc2UiLCJvbkF1dG9VcGRhdGVyUmVzdWx0IiwicmVzdWx0Iiwib25DaGFuZ2VJc1VwZGF0aW5nIiwiaXNVcGRhdGluZyIsInN1Z2dlc3Rpb25zIiwic2VsZWN0ZWRTdWdnZXN0aW9uIiwibWF4Q29sdW1uV2lkdGgiLCJ0b29sUGVybWlzc2lvbkNvbnRleHQiLCJoZWxwT3BlbiIsInN1cHByZXNzSGludCIsImlzTG9hZGluZyIsInRhc2tzU2VsZWN0ZWQiLCJ0ZWFtc1NlbGVjdGVkIiwiYnJpZGdlU2VsZWN0ZWQiLCJ0bXV4U2VsZWN0ZWQiLCJ0ZWFtbWF0ZUZvb3RlckluZGV4IiwiaWRlU2VsZWN0aW9uIiwibWNwQ2xpZW50cyIsImlzUGFzdGluZyIsImlzSW5wdXRXcmFwcGVkIiwibWVzc2FnZXMiLCJpc1NlYXJjaGluZyIsImhpc3RvcnlRdWVyeSIsInNldEhpc3RvcnlRdWVyeSIsInF1ZXJ5IiwiaGlzdG9yeUZhaWxlZE1hdGNoIiwib25PcGVuVGFza3NEaWFsb2ciLCJ0YXNrSWQiLCJQcm9tcHRJbnB1dEZvb3RlciIsInN1cHByZXNzSGludEZyb21Qcm9wcyIsInNldHRpbmdzIiwiY29sdW1ucyIsInJvd3MiLCJtZXNzYWdlc1JlZiIsImN1cnJlbnQiLCJsYXN0QXNzaXN0YW50TWVzc2FnZUlkIiwiaXNOYXJyb3ciLCJpc0Z1bGxzY3JlZW4iLCJpc1Nob3J0IiwiY29vcmRpbmF0b3JUYXNrQ291bnQiLCJjb29yZGluYXRvclRhc2tJbmRleCIsInMiLCJwaWxsU2VsZWN0ZWQiLCJvdmVybGF5RGF0YSIsImxlbmd0aCIsIkJyaWRnZVN0YXR1c1Byb3BzIiwiQnJpZGdlU3RhdHVzSW5kaWNhdG9yIiwiZW5hYmxlZCIsInJlcGxCcmlkZ2VFbmFibGVkIiwiY29ubmVjdGVkIiwicmVwbEJyaWRnZUNvbm5lY3RlZCIsInNlc3Npb25BY3RpdmUiLCJyZXBsQnJpZGdlU2Vzc2lvbkFjdGl2ZSIsInJlY29ubmVjdGluZyIsInJlcGxCcmlkZ2VSZWNvbm5lY3RpbmciLCJleHBsaWNpdCIsInJlcGxCcmlkZ2VFeHBsaWNpdCIsInN0YXR1cyIsImVycm9yIiwidW5kZWZpbmVkIiwibGFiZWwiLCJjb2xvciJdLCJzb3VyY2VzIjpbIlByb21wdElucHV0Rm9vdGVyLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmZWF0dXJlIH0gZnJvbSAnYnVuOmJ1bmRsZSdcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgbWVtbywgdHlwZSBSZWFjdE5vZGUsIHVzZU1lbW8sIHVzZVJlZiB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgaXNCcmlkZ2VFbmFibGVkIH0gZnJvbSAnLi4vLi4vYnJpZGdlL2JyaWRnZUVuYWJsZWQuanMnXG5pbXBvcnQgeyBnZXRCcmlkZ2VTdGF0dXMgfSBmcm9tICcuLi8uLi9icmlkZ2UvYnJpZGdlU3RhdHVzVXRpbC5qcydcbmltcG9ydCB7IHVzZVNldFByb21wdE92ZXJsYXkgfSBmcm9tICcuLi8uLi9jb250ZXh0L3Byb21wdE92ZXJsYXlDb250ZXh0LmpzJ1xuaW1wb3J0IHR5cGUgeyBWZXJpZmljYXRpb25TdGF0dXMgfSBmcm9tICcuLi8uLi9ob29rcy91c2VBcGlLZXlWZXJpZmljYXRpb24uanMnXG5pbXBvcnQgdHlwZSB7IElERVNlbGVjdGlvbiB9IGZyb20gJy4uLy4uL2hvb2tzL3VzZUlkZVNlbGVjdGlvbi5qcydcbmltcG9ydCB7IHVzZVNldHRpbmdzIH0gZnJvbSAnLi4vLi4vaG9va3MvdXNlU2V0dGluZ3MuanMnXG5pbXBvcnQgeyB1c2VUZXJtaW5hbFNpemUgfSBmcm9tICcuLi8uLi9ob29rcy91c2VUZXJtaW5hbFNpemUuanMnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgdHlwZSB7IE1DUFNlcnZlckNvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9tY3AvdHlwZXMuanMnXG5pbXBvcnQgeyB1c2VBcHBTdGF0ZSB9IGZyb20gJy4uLy4uL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHR5cGUgeyBUb29sUGVybWlzc2lvbkNvbnRleHQgfSBmcm9tICcuLi8uLi9Ub29sLmpzJ1xuaW1wb3J0IHR5cGUgeyBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vdHlwZXMvbWVzc2FnZS5qcydcbmltcG9ydCB0eXBlIHsgUHJvbXB0SW5wdXRNb2RlLCBWaW1Nb2RlIH0gZnJvbSAnLi4vLi4vdHlwZXMvdGV4dElucHV0VHlwZXMuanMnXG5pbXBvcnQgdHlwZSB7IEF1dG9VcGRhdGVyUmVzdWx0IH0gZnJvbSAnLi4vLi4vdXRpbHMvYXV0b1VwZGF0ZXIuanMnXG5pbXBvcnQgeyBpc0Z1bGxzY3JlZW5FbnZFbmFibGVkIH0gZnJvbSAnLi4vLi4vdXRpbHMvZnVsbHNjcmVlbi5qcydcbmltcG9ydCB7IGlzVW5kZXJjb3ZlciB9IGZyb20gJy4uLy4uL3V0aWxzL3VuZGVyY292ZXIuanMnXG5pbXBvcnQge1xuICBDb29yZGluYXRvclRhc2tQYW5lbCxcbiAgdXNlQ29vcmRpbmF0b3JUYXNrQ291bnQsXG59IGZyb20gJy4uL0Nvb3JkaW5hdG9yQWdlbnRTdGF0dXMuanMnXG5pbXBvcnQge1xuICBnZXRMYXN0QXNzaXN0YW50TWVzc2FnZUlkLFxuICBTdGF0dXNMaW5lLFxuICBzdGF0dXNMaW5lU2hvdWxkRGlzcGxheSxcbn0gZnJvbSAnLi4vU3RhdHVzTGluZS5qcydcbmltcG9ydCB7IE5vdGlmaWNhdGlvbnMgfSBmcm9tICcuL05vdGlmaWNhdGlvbnMuanMnXG5pbXBvcnQgeyBQcm9tcHRJbnB1dEZvb3RlckxlZnRTaWRlIH0gZnJvbSAnLi9Qcm9tcHRJbnB1dEZvb3RlckxlZnRTaWRlLmpzJ1xuaW1wb3J0IHtcbiAgUHJvbXB0SW5wdXRGb290ZXJTdWdnZXN0aW9ucyxcbiAgdHlwZSBTdWdnZXN0aW9uSXRlbSxcbn0gZnJvbSAnLi9Qcm9tcHRJbnB1dEZvb3RlclN1Z2dlc3Rpb25zLmpzJ1xuaW1wb3J0IHsgUHJvbXB0SW5wdXRIZWxwTWVudSB9IGZyb20gJy4vUHJvbXB0SW5wdXRIZWxwTWVudS5qcydcblxudHlwZSBQcm9wcyA9IHtcbiAgYXBpS2V5U3RhdHVzOiBWZXJpZmljYXRpb25TdGF0dXNcbiAgZGVidWc6IGJvb2xlYW5cbiAgZXhpdE1lc3NhZ2U6IHtcbiAgICBzaG93OiBib29sZWFuXG4gICAga2V5Pzogc3RyaW5nXG4gIH1cbiAgdmltTW9kZTogVmltTW9kZSB8IHVuZGVmaW5lZFxuICBtb2RlOiBQcm9tcHRJbnB1dE1vZGVcbiAgYXV0b1VwZGF0ZXJSZXN1bHQ6IEF1dG9VcGRhdGVyUmVzdWx0IHwgbnVsbFxuICBpc0F1dG9VcGRhdGluZzogYm9vbGVhblxuICB2ZXJib3NlOiBib29sZWFuXG4gIG9uQXV0b1VwZGF0ZXJSZXN1bHQ6IChyZXN1bHQ6IEF1dG9VcGRhdGVyUmVzdWx0KSA9PiB2b2lkXG4gIG9uQ2hhbmdlSXNVcGRhdGluZzogKGlzVXBkYXRpbmc6IGJvb2xlYW4pID0+IHZvaWRcbiAgc3VnZ2VzdGlvbnM6IFN1Z2dlc3Rpb25JdGVtW11cbiAgc2VsZWN0ZWRTdWdnZXN0aW9uOiBudW1iZXJcbiAgbWF4Q29sdW1uV2lkdGg/OiBudW1iZXJcbiAgdG9vbFBlcm1pc3Npb25Db250ZXh0OiBUb29sUGVybWlzc2lvbkNvbnRleHRcbiAgaGVscE9wZW46IGJvb2xlYW5cbiAgc3VwcHJlc3NIaW50OiBib29sZWFuXG4gIGlzTG9hZGluZzogYm9vbGVhblxuICB0YXNrc1NlbGVjdGVkOiBib29sZWFuXG4gIHRlYW1zU2VsZWN0ZWQ6IGJvb2xlYW5cbiAgYnJpZGdlU2VsZWN0ZWQ6IGJvb2xlYW5cbiAgdG11eFNlbGVjdGVkOiBib29sZWFuXG4gIHRlYW1tYXRlRm9vdGVySW5kZXg/OiBudW1iZXJcbiAgaWRlU2VsZWN0aW9uOiBJREVTZWxlY3Rpb24gfCB1bmRlZmluZWRcbiAgbWNwQ2xpZW50cz86IE1DUFNlcnZlckNvbm5lY3Rpb25bXVxuICBpc1Bhc3Rpbmc/OiBib29sZWFuXG4gIGlzSW5wdXRXcmFwcGVkPzogYm9vbGVhblxuICBtZXNzYWdlczogTWVzc2FnZVtdXG4gIGlzU2VhcmNoaW5nOiBib29sZWFuXG4gIGhpc3RvcnlRdWVyeTogc3RyaW5nXG4gIHNldEhpc3RvcnlRdWVyeTogKHF1ZXJ5OiBzdHJpbmcpID0+IHZvaWRcbiAgaGlzdG9yeUZhaWxlZE1hdGNoOiBib29sZWFuXG4gIG9uT3BlblRhc2tzRGlhbG9nPzogKHRhc2tJZD86IHN0cmluZykgPT4gdm9pZFxufVxuXG5mdW5jdGlvbiBQcm9tcHRJbnB1dEZvb3Rlcih7XG4gIGFwaUtleVN0YXR1cyxcbiAgZGVidWcsXG4gIGV4aXRNZXNzYWdlLFxuICB2aW1Nb2RlLFxuICBtb2RlLFxuICBhdXRvVXBkYXRlclJlc3VsdCxcbiAgaXNBdXRvVXBkYXRpbmcsXG4gIHZlcmJvc2UsXG4gIG9uQXV0b1VwZGF0ZXJSZXN1bHQsXG4gIG9uQ2hhbmdlSXNVcGRhdGluZyxcbiAgc3VnZ2VzdGlvbnMsXG4gIHNlbGVjdGVkU3VnZ2VzdGlvbixcbiAgbWF4Q29sdW1uV2lkdGgsXG4gIHRvb2xQZXJtaXNzaW9uQ29udGV4dCxcbiAgaGVscE9wZW4sXG4gIHN1cHByZXNzSGludDogc3VwcHJlc3NIaW50RnJvbVByb3BzLFxuICBpc0xvYWRpbmcsXG4gIHRhc2tzU2VsZWN0ZWQsXG4gIHRlYW1zU2VsZWN0ZWQsXG4gIGJyaWRnZVNlbGVjdGVkLFxuICB0bXV4U2VsZWN0ZWQsXG4gIHRlYW1tYXRlRm9vdGVySW5kZXgsXG4gIGlkZVNlbGVjdGlvbixcbiAgbWNwQ2xpZW50cyxcbiAgaXNQYXN0aW5nID0gZmFsc2UsXG4gIGlzSW5wdXRXcmFwcGVkID0gZmFsc2UsXG4gIG1lc3NhZ2VzLFxuICBpc1NlYXJjaGluZyxcbiAgaGlzdG9yeVF1ZXJ5LFxuICBzZXRIaXN0b3J5UXVlcnksXG4gIGhpc3RvcnlGYWlsZWRNYXRjaCxcbiAgb25PcGVuVGFza3NEaWFsb2csXG59OiBQcm9wcyk6IFJlYWN0Tm9kZSB7XG4gIGNvbnN0IHNldHRpbmdzID0gdXNlU2V0dGluZ3MoKVxuICBjb25zdCB7IGNvbHVtbnMsIHJvd3MgfSA9IHVzZVRlcm1pbmFsU2l6ZSgpXG4gIGNvbnN0IG1lc3NhZ2VzUmVmID0gdXNlUmVmKG1lc3NhZ2VzKVxuICBtZXNzYWdlc1JlZi5jdXJyZW50ID0gbWVzc2FnZXNcbiAgY29uc3QgbGFzdEFzc2lzdGFudE1lc3NhZ2VJZCA9IHVzZU1lbW8oXG4gICAgKCkgPT4gZ2V0TGFzdEFzc2lzdGFudE1lc3NhZ2VJZChtZXNzYWdlcyksXG4gICAgW21lc3NhZ2VzXSxcbiAgKVxuICBjb25zdCBpc05hcnJvdyA9IGNvbHVtbnMgPCA4MFxuICAvLyBJbiBmdWxsc2NyZWVuIHRoZSBib3R0b20gc2xvdCBpcyBmbGV4U2hyaW5rOjAsIHNvIGV2ZXJ5IHJvdyBoZXJlIGlzIGEgcm93XG4gIC8vIHN0b2xlbiBmcm9tIHRoZSBTY3JvbGxCb3guIERyb3AgdGhlIG9wdGlvbmFsIFN0YXR1c0xpbmUgZmlyc3QuIE5vbi1mdWxsc2NyZWVuXG4gIC8vIGhhcyB0ZXJtaW5hbCBzY3JvbGxiYWNrIHRvIGFic29yYiBvdmVyZmxvdywgc28gd2UgbmV2ZXIgaGlkZSBTdGF0dXNMaW5lIHRoZXJlLlxuICBjb25zdCBpc0Z1bGxzY3JlZW4gPSBpc0Z1bGxzY3JlZW5FbnZFbmFibGVkKClcbiAgY29uc3QgaXNTaG9ydCA9IGlzRnVsbHNjcmVlbiAmJiByb3dzIDwgMjRcblxuICAvLyBQaWxsIGhpZ2hsaWdodHMgd2hlbiB0YXNrcyBpcyB0aGUgYWN0aXZlIGZvb3RlciBpdGVtIEFORCBubyBzcGVjaWZpY1xuICAvLyBhZ2VudCByb3cgaXMgc2VsZWN0ZWQuIFdoZW4gY29vcmRpbmF0b3JUYXNrSW5kZXggPj0gMCB0aGUgcG9pbnRlciBoYXNcbiAgLy8gbW92ZWQgaW50byBDb29yZGluYXRvclRhc2tQYW5lbCwgc28gdGhlIHBpbGwgc2hvdWxkIHVuLWhpZ2hsaWdodC5cbiAgLy8gY29vcmRpbmF0b3JUYXNrQ291bnQgPT09IDAgY292ZXJzIHRoZSBiYXNoLW9ubHkgY2FzZSAobm8gYWdlbnQgcm93c1xuICAvLyBleGlzdCwgcGlsbCBpcyB0aGUgb25seSBzZWxlY3RhYmxlIGl0ZW0pLlxuICBjb25zdCBjb29yZGluYXRvclRhc2tDb3VudCA9IHVzZUNvb3JkaW5hdG9yVGFza0NvdW50KClcbiAgY29uc3QgY29vcmRpbmF0b3JUYXNrSW5kZXggPSB1c2VBcHBTdGF0ZShzID0+IHMuY29vcmRpbmF0b3JUYXNrSW5kZXgpXG4gIGNvbnN0IHBpbGxTZWxlY3RlZCA9XG4gICAgdGFza3NTZWxlY3RlZCAmJiAoY29vcmRpbmF0b3JUYXNrQ291bnQgPT09IDAgfHwgY29vcmRpbmF0b3JUYXNrSW5kZXggPCAwKVxuXG4gIC8vIEhpZGUgYD8gZm9yIHNob3J0Y3V0c2AgaWYgdGhlIHVzZXIgaGFzIGEgY3VzdG9tIHN0YXR1cyBsaW5lLCBvciBkdXJpbmcgY3RybC1yXG4gIGNvbnN0IHN1cHByZXNzSGludCA9XG4gICAgc3VwcHJlc3NIaW50RnJvbVByb3BzIHx8IHN0YXR1c0xpbmVTaG91bGREaXNwbGF5KHNldHRpbmdzKSB8fCBpc1NlYXJjaGluZ1xuICAvLyBGdWxsc2NyZWVuOiBwb3J0YWwgZGF0YSB0byBGdWxsc2NyZWVuTGF5b3V0IOKAlCBzZWUgcHJvbXB0T3ZlcmxheUNvbnRleHQudHN4XG4gIGNvbnN0IG92ZXJsYXlEYXRhID0gdXNlTWVtbyhcbiAgICAoKSA9PlxuICAgICAgaXNGdWxsc2NyZWVuICYmIHN1Z2dlc3Rpb25zLmxlbmd0aFxuICAgICAgICA/IHsgc3VnZ2VzdGlvbnMsIHNlbGVjdGVkU3VnZ2VzdGlvbiwgbWF4Q29sdW1uV2lkdGggfVxuICAgICAgICA6IG51bGwsXG4gICAgW2lzRnVsbHNjcmVlbiwgc3VnZ2VzdGlvbnMsIHNlbGVjdGVkU3VnZ2VzdGlvbiwgbWF4Q29sdW1uV2lkdGhdLFxuICApXG4gIHVzZVNldFByb21wdE92ZXJsYXkob3ZlcmxheURhdGEpXG5cbiAgaWYgKHN1Z2dlc3Rpb25zLmxlbmd0aCAmJiAhaXNGdWxsc2NyZWVuKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxCb3ggcGFkZGluZ1g9ezJ9IHBhZGRpbmdZPXswfT5cbiAgICAgICAgPFByb21wdElucHV0Rm9vdGVyU3VnZ2VzdGlvbnNcbiAgICAgICAgICBzdWdnZXN0aW9ucz17c3VnZ2VzdGlvbnN9XG4gICAgICAgICAgc2VsZWN0ZWRTdWdnZXN0aW9uPXtzZWxlY3RlZFN1Z2dlc3Rpb259XG4gICAgICAgICAgbWF4Q29sdW1uV2lkdGg9e21heENvbHVtbldpZHRofVxuICAgICAgICAvPlxuICAgICAgPC9Cb3g+XG4gICAgKVxuICB9XG5cbiAgaWYgKGhlbHBPcGVuKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxQcm9tcHRJbnB1dEhlbHBNZW51IGRpbUNvbG9yPXt0cnVlfSBmaXhlZFdpZHRoPXt0cnVlfSBwYWRkaW5nWD17Mn0gLz5cbiAgICApXG4gIH1cblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8Qm94XG4gICAgICAgIGZsZXhEaXJlY3Rpb249e2lzTmFycm93ID8gJ2NvbHVtbicgOiAncm93J31cbiAgICAgICAganVzdGlmeUNvbnRlbnQ9e2lzTmFycm93ID8gJ2ZsZXgtc3RhcnQnIDogJ3NwYWNlLWJldHdlZW4nfVxuICAgICAgICBwYWRkaW5nWD17Mn1cbiAgICAgICAgZ2FwPXtpc05hcnJvdyA/IDAgOiAxfVxuICAgICAgPlxuICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBmbGV4U2hyaW5rPXtpc05hcnJvdyA/IDAgOiAxfT5cbiAgICAgICAgICB7bW9kZSA9PT0gJ3Byb21wdCcgJiZcbiAgICAgICAgICAgICFpc1Nob3J0ICYmXG4gICAgICAgICAgICAhZXhpdE1lc3NhZ2Uuc2hvdyAmJlxuICAgICAgICAgICAgIWlzUGFzdGluZyAmJlxuICAgICAgICAgICAgc3RhdHVzTGluZVNob3VsZERpc3BsYXkoc2V0dGluZ3MpICYmIChcbiAgICAgICAgICAgICAgPFN0YXR1c0xpbmVcbiAgICAgICAgICAgICAgICBtZXNzYWdlc1JlZj17bWVzc2FnZXNSZWZ9XG4gICAgICAgICAgICAgICAgbGFzdEFzc2lzdGFudE1lc3NhZ2VJZD17bGFzdEFzc2lzdGFudE1lc3NhZ2VJZH1cbiAgICAgICAgICAgICAgICB2aW1Nb2RlPXt2aW1Nb2RlfVxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKX1cbiAgICAgICAgICA8UHJvbXB0SW5wdXRGb290ZXJMZWZ0U2lkZVxuICAgICAgICAgICAgZXhpdE1lc3NhZ2U9e2V4aXRNZXNzYWdlfVxuICAgICAgICAgICAgdmltTW9kZT17dmltTW9kZX1cbiAgICAgICAgICAgIG1vZGU9e21vZGV9XG4gICAgICAgICAgICB0b29sUGVybWlzc2lvbkNvbnRleHQ9e3Rvb2xQZXJtaXNzaW9uQ29udGV4dH1cbiAgICAgICAgICAgIHN1cHByZXNzSGludD17c3VwcHJlc3NIaW50fVxuICAgICAgICAgICAgaXNMb2FkaW5nPXtpc0xvYWRpbmd9XG4gICAgICAgICAgICB0YXNrc1NlbGVjdGVkPXtwaWxsU2VsZWN0ZWR9XG4gICAgICAgICAgICB0ZWFtc1NlbGVjdGVkPXt0ZWFtc1NlbGVjdGVkfVxuICAgICAgICAgICAgdGVhbW1hdGVGb290ZXJJbmRleD17dGVhbW1hdGVGb290ZXJJbmRleH1cbiAgICAgICAgICAgIHRtdXhTZWxlY3RlZD17dG11eFNlbGVjdGVkfVxuICAgICAgICAgICAgaXNQYXN0aW5nPXtpc1Bhc3Rpbmd9XG4gICAgICAgICAgICBpc1NlYXJjaGluZz17aXNTZWFyY2hpbmd9XG4gICAgICAgICAgICBoaXN0b3J5UXVlcnk9e2hpc3RvcnlRdWVyeX1cbiAgICAgICAgICAgIHNldEhpc3RvcnlRdWVyeT17c2V0SGlzdG9yeVF1ZXJ5fVxuICAgICAgICAgICAgaGlzdG9yeUZhaWxlZE1hdGNoPXtoaXN0b3J5RmFpbGVkTWF0Y2h9XG4gICAgICAgICAgICBvbk9wZW5UYXNrc0RpYWxvZz17b25PcGVuVGFza3NEaWFsb2d9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9Cb3g+XG4gICAgICAgIDxCb3ggZmxleFNocmluaz17MX0gZ2FwPXsxfT5cbiAgICAgICAgICB7aXNGdWxsc2NyZWVuID8gbnVsbCA6IChcbiAgICAgICAgICAgIDxOb3RpZmljYXRpb25zXG4gICAgICAgICAgICAgIGFwaUtleVN0YXR1cz17YXBpS2V5U3RhdHVzfVxuICAgICAgICAgICAgICBhdXRvVXBkYXRlclJlc3VsdD17YXV0b1VwZGF0ZXJSZXN1bHR9XG4gICAgICAgICAgICAgIGRlYnVnPXtkZWJ1Z31cbiAgICAgICAgICAgICAgaXNBdXRvVXBkYXRpbmc9e2lzQXV0b1VwZGF0aW5nfVxuICAgICAgICAgICAgICB2ZXJib3NlPXt2ZXJib3NlfVxuICAgICAgICAgICAgICBtZXNzYWdlcz17bWVzc2FnZXN9XG4gICAgICAgICAgICAgIG9uQXV0b1VwZGF0ZXJSZXN1bHQ9e29uQXV0b1VwZGF0ZXJSZXN1bHR9XG4gICAgICAgICAgICAgIG9uQ2hhbmdlSXNVcGRhdGluZz17b25DaGFuZ2VJc1VwZGF0aW5nfVxuICAgICAgICAgICAgICBpZGVTZWxlY3Rpb249e2lkZVNlbGVjdGlvbn1cbiAgICAgICAgICAgICAgbWNwQ2xpZW50cz17bWNwQ2xpZW50c31cbiAgICAgICAgICAgICAgaXNJbnB1dFdyYXBwZWQ9e2lzSW5wdXRXcmFwcGVkfVxuICAgICAgICAgICAgICBpc05hcnJvdz17aXNOYXJyb3d9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICl9XG4gICAgICAgICAge1wiZXh0ZXJuYWxcIiA9PT0gJ2FudCcgJiYgaXNVbmRlcmNvdmVyKCkgJiYgKFxuICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+dW5kZXJjb3ZlcjwvVGV4dD5cbiAgICAgICAgICApfVxuICAgICAgICAgIDxCcmlkZ2VTdGF0dXNJbmRpY2F0b3IgYnJpZGdlU2VsZWN0ZWQ9e2JyaWRnZVNlbGVjdGVkfSAvPlxuICAgICAgICA8L0JveD5cbiAgICAgIDwvQm94PlxuICAgICAge1wiZXh0ZXJuYWxcIiA9PT0gJ2FudCcgJiYgPENvb3JkaW5hdG9yVGFza1BhbmVsIC8+fVxuICAgIDwvPlxuICApXG59XG5cbmV4cG9ydCBkZWZhdWx0IG1lbW8oUHJvbXB0SW5wdXRGb290ZXIpXG5cbnR5cGUgQnJpZGdlU3RhdHVzUHJvcHMgPSB7XG4gIGJyaWRnZVNlbGVjdGVkOiBib29sZWFuXG59XG5cbmZ1bmN0aW9uIEJyaWRnZVN0YXR1c0luZGljYXRvcih7XG4gIGJyaWRnZVNlbGVjdGVkLFxufTogQnJpZGdlU3RhdHVzUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBpZiAoIWZlYXR1cmUoJ0JSSURHRV9NT0RFJykpIHJldHVybiBudWxsXG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29ycmVjdG5lc3MvdXNlSG9va0F0VG9wTGV2ZWw6IGZlYXR1cmUoKSBpcyBhIGNvbXBpbGUtdGltZSBjb25zdGFudFxuICBjb25zdCBlbmFibGVkID0gdXNlQXBwU3RhdGUocyA9PiBzLnJlcGxCcmlkZ2VFbmFibGVkKVxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gIGNvbnN0IGNvbm5lY3RlZCA9IHVzZUFwcFN0YXRlKHMgPT4gcy5yZXBsQnJpZGdlQ29ubmVjdGVkKVxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gIGNvbnN0IHNlc3Npb25BY3RpdmUgPSB1c2VBcHBTdGF0ZShzID0+IHMucmVwbEJyaWRnZVNlc3Npb25BY3RpdmUpXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L2NvcnJlY3RuZXNzL3VzZUhvb2tBdFRvcExldmVsOiBmZWF0dXJlKCkgaXMgYSBjb21waWxlLXRpbWUgY29uc3RhbnRcbiAgY29uc3QgcmVjb25uZWN0aW5nID0gdXNlQXBwU3RhdGUocyA9PiBzLnJlcGxCcmlkZ2VSZWNvbm5lY3RpbmcpXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L2NvcnJlY3RuZXNzL3VzZUhvb2tBdFRvcExldmVsOiBmZWF0dXJlKCkgaXMgYSBjb21waWxlLXRpbWUgY29uc3RhbnRcbiAgY29uc3QgZXhwbGljaXQgPSB1c2VBcHBTdGF0ZShzID0+IHMucmVwbEJyaWRnZUV4cGxpY2l0KVxuXG4gIC8vIEZhaWxlZCBzdGF0ZSBpcyBzdXJmYWNlZCB2aWEgbm90aWZpY2F0aW9uICh1c2VSZXBsQnJpZGdlKSwgbm90IGEgZm9vdGVyIHBpbGwuXG4gIGlmICghaXNCcmlkZ2VFbmFibGVkKCkgfHwgIWVuYWJsZWQpIHJldHVybiBudWxsXG5cbiAgY29uc3Qgc3RhdHVzID0gZ2V0QnJpZGdlU3RhdHVzKHtcbiAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgIGNvbm5lY3RlZCxcbiAgICBzZXNzaW9uQWN0aXZlLFxuICAgIHJlY29ubmVjdGluZyxcbiAgfSlcblxuICAvLyBGb3IgaW1wbGljaXQgKGNvbmZpZy1kcml2ZW4pIHJlbW90ZSwgb25seSBzaG93IHRoZSByZWNvbm5lY3Rpbmcgc3RhdGVcbiAgaWYgKCFleHBsaWNpdCAmJiBzdGF0dXMubGFiZWwgIT09ICdSZW1vdGUgQ29udHJvbCByZWNvbm5lY3RpbmcnKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPFRleHRcbiAgICAgIGNvbG9yPXticmlkZ2VTZWxlY3RlZCA/ICdiYWNrZ3JvdW5kJyA6IHN0YXR1cy5jb2xvcn1cbiAgICAgIGludmVyc2U9e2JyaWRnZVNlbGVjdGVkfVxuICAgICAgd3JhcD1cInRydW5jYXRlXCJcbiAgICA+XG4gICAgICB7c3RhdHVzLmxhYmVsfVxuICAgICAge2JyaWRnZVNlbGVjdGVkICYmIDxUZXh0IGRpbUNvbG9yPiDCtyBFbnRlciB0byB2aWV3PC9UZXh0Pn1cbiAgICA8L1RleHQ+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsT0FBTyxRQUFRLFlBQVk7QUFDcEMsT0FBTyxLQUFLQyxLQUFLLE1BQU0sT0FBTztBQUM5QixTQUFTQyxJQUFJLEVBQUUsS0FBS0MsU0FBUyxFQUFFQyxPQUFPLEVBQUVDLE1BQU0sUUFBUSxPQUFPO0FBQzdELFNBQVNDLGVBQWUsUUFBUSwrQkFBK0I7QUFDL0QsU0FBU0MsZUFBZSxRQUFRLGtDQUFrQztBQUNsRSxTQUFTQyxtQkFBbUIsUUFBUSx1Q0FBdUM7QUFDM0UsY0FBY0Msa0JBQWtCLFFBQVEsc0NBQXNDO0FBQzlFLGNBQWNDLFlBQVksUUFBUSxnQ0FBZ0M7QUFD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