/ components / messages / UserTeammateMessage.tsx
UserTeammateMessage.tsx
  1  import { c as _c } from "react/compiler-runtime";
  2  import type { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
  3  import figures from 'figures';
  4  import * as React from 'react';
  5  import { TEAMMATE_MESSAGE_TAG } from '../../constants/xml.js';
  6  import { Ansi, Box, Text, type TextProps } from '../../ink.js';
  7  import { toInkColor } from '../../utils/ink.js';
  8  import { jsonParse } from '../../utils/slowOperations.js';
  9  import { isShutdownApproved } from '../../utils/teammateMailbox.js';
 10  import { MessageResponse } from '../MessageResponse.js';
 11  import { tryRenderPlanApprovalMessage } from './PlanApprovalMessage.js';
 12  import { tryRenderShutdownMessage } from './ShutdownMessage.js';
 13  import { tryRenderTaskAssignmentMessage } from './TaskAssignmentMessage.js';
 14  type Props = {
 15    addMargin: boolean;
 16    param: TextBlockParam;
 17    isTranscriptMode?: boolean;
 18  };
 19  type ParsedMessage = {
 20    teammateId: string;
 21    content: string;
 22    color?: string;
 23    summary?: string;
 24  };
 25  const TEAMMATE_MSG_REGEX = new RegExp(`<${TEAMMATE_MESSAGE_TAG}\\s+teammate_id="([^"]+)"(?:\\s+color="([^"]+)")?(?:\\s+summary="([^"]+)")?>\\n?([\\s\\S]*?)\\n?<\\/${TEAMMATE_MESSAGE_TAG}>`, 'g');
 26  
 27  /**
 28   * Parse all teammate messages from XML format:
 29   * <teammate-message teammate_id="alice" color="red" summary="Brief update">message content</teammate-message>
 30   * Supports multiple messages in a single text block.
 31   */
 32  function parseTeammateMessages(text: string): ParsedMessage[] {
 33    const messages: ParsedMessage[] = [];
 34    // Use matchAll to find all matches (this is a RegExp method, not child_process)
 35    for (const match of text.matchAll(TEAMMATE_MSG_REGEX)) {
 36      if (match[1] && match[4]) {
 37        messages.push({
 38          teammateId: match[1],
 39          color: match[2],
 40          // may be undefined
 41          summary: match[3],
 42          // may be undefined
 43          content: match[4].trim()
 44        });
 45      }
 46    }
 47    return messages;
 48  }
 49  function getDisplayName(teammateId: string): string {
 50    if (teammateId === 'leader') {
 51      return 'leader';
 52    }
 53    return teammateId;
 54  }
 55  export function UserTeammateMessage({
 56    addMargin,
 57    param: {
 58      text
 59    },
 60    isTranscriptMode
 61  }: Props): React.ReactNode {
 62    const messages = parseTeammateMessages(text).filter(msg => {
 63      // Pre-filter shutdown lifecycle messages to avoid empty wrapper
 64      // Box elements creating blank lines between model turns
 65      if (isShutdownApproved(msg.content)) {
 66        return false;
 67      }
 68      try {
 69        const parsed = jsonParse(msg.content);
 70        if (parsed?.type === 'teammate_terminated') return false;
 71      } catch {
 72        // Not JSON, keep the message
 73      }
 74      return true;
 75    });
 76    if (messages.length === 0) {
 77      return null;
 78    }
 79    return <Box flexDirection="column" marginTop={addMargin ? 1 : 0} width="100%">
 80        {messages.map((msg_0, index) => {
 81        const inkColor = toInkColor(msg_0.color);
 82        const displayName = getDisplayName(msg_0.teammateId);
 83  
 84        // Try to render as plan approval message (request or response)
 85        const planApprovalElement = tryRenderPlanApprovalMessage(msg_0.content, displayName);
 86        if (planApprovalElement) {
 87          return <React.Fragment key={index}>{planApprovalElement}</React.Fragment>;
 88        }
 89  
 90        // Try to render as shutdown message (request or rejected)
 91        const shutdownElement = tryRenderShutdownMessage(msg_0.content);
 92        if (shutdownElement) {
 93          return <React.Fragment key={index}>{shutdownElement}</React.Fragment>;
 94        }
 95  
 96        // Try to render as task assignment message
 97        const taskAssignmentElement = tryRenderTaskAssignmentMessage(msg_0.content);
 98        if (taskAssignmentElement) {
 99          return <React.Fragment key={index}>{taskAssignmentElement}</React.Fragment>;
100        }
101  
102        // Try to parse as structured JSON message
103        let parsedIdleNotification: {
104          type?: string;
105        } | null = null;
106        try {
107          parsedIdleNotification = jsonParse(msg_0.content);
108        } catch {
109          // Not JSON
110        }
111  
112        // Hide idle notifications - they are processed silently
113        if (parsedIdleNotification?.type === 'idle_notification') {
114          return null;
115        }
116  
117        // Task completed notification - show which task was completed
118        if (parsedIdleNotification?.type === 'task_completed') {
119          const taskCompleted = parsedIdleNotification as {
120            type: string;
121            from: string;
122            taskId: string;
123            taskSubject?: string;
124          };
125          return <Box key={index} flexDirection="column" marginTop={1}>
126                <Text color={inkColor}>{`@${displayName}${figures.pointer}`}</Text>
127                <MessageResponse>
128                  <Text color="success">✓</Text>
129                  <Text>
130                    {' '}
131                    Completed task #{taskCompleted.taskId}
132                    {taskCompleted.taskSubject && <Text dimColor> ({taskCompleted.taskSubject})</Text>}
133                  </Text>
134                </MessageResponse>
135              </Box>;
136        }
137  
138        // Default: plain text message (truncated)
139        return <TeammateMessageContent key={index} displayName={displayName} inkColor={inkColor} content={msg_0.content} summary={msg_0.summary} isTranscriptMode={isTranscriptMode} />;
140      })}
141      </Box>;
142  }
143  type TeammateMessageContentProps = {
144    displayName: string;
145    inkColor: TextProps['color'];
146    content: string;
147    summary?: string;
148    isTranscriptMode?: boolean;
149  };
150  export function TeammateMessageContent(t0) {
151    const $ = _c(14);
152    const {
153      displayName,
154      inkColor,
155      content,
156      summary,
157      isTranscriptMode
158    } = t0;
159    const t1 = `@${displayName}${figures.pointer}`;
160    let t2;
161    if ($[0] !== inkColor || $[1] !== t1) {
162      t2 = <Text color={inkColor}>{t1}</Text>;
163      $[0] = inkColor;
164      $[1] = t1;
165      $[2] = t2;
166    } else {
167      t2 = $[2];
168    }
169    let t3;
170    if ($[3] !== summary) {
171      t3 = summary && <Text> {summary}</Text>;
172      $[3] = summary;
173      $[4] = t3;
174    } else {
175      t3 = $[4];
176    }
177    let t4;
178    if ($[5] !== t2 || $[6] !== t3) {
179      t4 = <Box>{t2}{t3}</Box>;
180      $[5] = t2;
181      $[6] = t3;
182      $[7] = t4;
183    } else {
184      t4 = $[7];
185    }
186    let t5;
187    if ($[8] !== content || $[9] !== isTranscriptMode) {
188      t5 = isTranscriptMode && <Box paddingLeft={2}><Text><Ansi>{content}</Ansi></Text></Box>;
189      $[8] = content;
190      $[9] = isTranscriptMode;
191      $[10] = t5;
192    } else {
193      t5 = $[10];
194    }
195    let t6;
196    if ($[11] !== t4 || $[12] !== t5) {
197      t6 = <Box flexDirection="column" marginTop={1}>{t4}{t5}</Box>;
198      $[11] = t4;
199      $[12] = t5;
200      $[13] = t6;
201    } else {
202      t6 = $[13];
203    }
204    return t6;
205  }
206  //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJUZXh0QmxvY2tQYXJhbSIsImZpZ3VyZXMiLCJSZWFjdCIsIlRFQU1NQVRFX01FU1NBR0VfVEFHIiwiQW5zaSIsIkJveCIsIlRleHQiLCJUZXh0UHJvcHMiLCJ0b0lua0NvbG9yIiwianNvblBhcnNlIiwiaXNTaHV0ZG93bkFwcHJvdmVkIiwiTWVzc2FnZVJlc3BvbnNlIiwidHJ5UmVuZGVyUGxhbkFwcHJvdmFsTWVzc2FnZSIsInRyeVJlbmRlclNodXRkb3duTWVzc2FnZSIsInRyeVJlbmRlclRhc2tBc3NpZ25tZW50TWVzc2FnZSIsIlByb3BzIiwiYWRkTWFyZ2luIiwicGFyYW0iLCJpc1RyYW5zY3JpcHRNb2RlIiwiUGFyc2VkTWVzc2FnZSIsInRlYW1tYXRlSWQiLCJjb250ZW50IiwiY29sb3IiLCJzdW1tYXJ5IiwiVEVBTU1BVEVfTVNHX1JFR0VYIiwiUmVnRXhwIiwicGFyc2VUZWFtbWF0ZU1lc3NhZ2VzIiwidGV4dCIsIm1lc3NhZ2VzIiwibWF0Y2giLCJtYXRjaEFsbCIsInB1c2giLCJ0cmltIiwiZ2V0RGlzcGxheU5hbWUiLCJVc2VyVGVhbW1hdGVNZXNzYWdlIiwiUmVhY3ROb2RlIiwiZmlsdGVyIiwibXNnIiwicGFyc2VkIiwidHlwZSIsImxlbmd0aCIsIm1hcCIsImluZGV4IiwiaW5rQ29sb3IiLCJkaXNwbGF5TmFtZSIsInBsYW5BcHByb3ZhbEVsZW1lbnQiLCJzaHV0ZG93bkVsZW1lbnQiLCJ0YXNrQXNzaWdubWVudEVsZW1lbnQiLCJwYXJzZWRJZGxlTm90aWZpY2F0aW9uIiwidGFza0NvbXBsZXRlZCIsImZyb20iLCJ0YXNrSWQiLCJ0YXNrU3ViamVjdCIsInBvaW50ZXIiLCJUZWFtbWF0ZU1lc3NhZ2VDb250ZW50UHJvcHMiLCJUZWFtbWF0ZU1lc3NhZ2VDb250ZW50IiwidDAiLCIkIiwiX2MiLCJ0MSIsInQyIiwidDMiLCJ0NCIsInQ1IiwidDYiXSwic291cmNlcyI6WyJVc2VyVGVhbW1hdGVNZXNzYWdlLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFRleHRCbG9ja1BhcmFtIH0gZnJvbSAnQGFudGhyb3BpYy1haS9zZGsvcmVzb3VyY2VzL2luZGV4Lm1qcydcbmltcG9ydCBmaWd1cmVzIGZyb20gJ2ZpZ3VyZXMnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IFRFQU1NQVRFX01FU1NBR0VfVEFHIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL3htbC5qcydcbmltcG9ydCB7IEFuc2ksIEJveCwgVGV4dCwgdHlwZSBUZXh0UHJvcHMgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyB0b0lua0NvbG9yIH0gZnJvbSAnLi4vLi4vdXRpbHMvaW5rLmpzJ1xuaW1wb3J0IHsganNvblBhcnNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvc2xvd09wZXJhdGlvbnMuanMnXG5pbXBvcnQgeyBpc1NodXRkb3duQXBwcm92ZWQgfSBmcm9tICcuLi8uLi91dGlscy90ZWFtbWF0ZU1haWxib3guanMnXG5pbXBvcnQgeyBNZXNzYWdlUmVzcG9uc2UgfSBmcm9tICcuLi9NZXNzYWdlUmVzcG9uc2UuanMnXG5pbXBvcnQgeyB0cnlSZW5kZXJQbGFuQXBwcm92YWxNZXNzYWdlIH0gZnJvbSAnLi9QbGFuQXBwcm92YWxNZXNzYWdlLmpzJ1xuaW1wb3J0IHsgdHJ5UmVuZGVyU2h1dGRvd25NZXNzYWdlIH0gZnJvbSAnLi9TaHV0ZG93bk1lc3NhZ2UuanMnXG5pbXBvcnQgeyB0cnlSZW5kZXJUYXNrQXNzaWdubWVudE1lc3NhZ2UgfSBmcm9tICcuL1Rhc2tBc3NpZ25tZW50TWVzc2FnZS5qcydcblxudHlwZSBQcm9wcyA9IHtcbiAgYWRkTWFyZ2luOiBib29sZWFuXG4gIHBhcmFtOiBUZXh0QmxvY2tQYXJhbVxuICBpc1RyYW5zY3JpcHRNb2RlPzogYm9vbGVhblxufVxuXG50eXBlIFBhcnNlZE1lc3NhZ2UgPSB7XG4gIHRlYW1tYXRlSWQ6IHN0cmluZ1xuICBjb250ZW50OiBzdHJpbmdcbiAgY29sb3I/OiBzdHJpbmdcbiAgc3VtbWFyeT86IHN0cmluZ1xufVxuXG5jb25zdCBURUFNTUFURV9NU0dfUkVHRVggPSBuZXcgUmVnRXhwKFxuICBgPCR7VEVBTU1BVEVfTUVTU0FHRV9UQUd9XFxcXHMrdGVhbW1hdGVfaWQ9XCIoW15cIl0rKVwiKD86XFxcXHMrY29sb3I9XCIoW15cIl0rKVwiKT8oPzpcXFxccytzdW1tYXJ5PVwiKFteXCJdKylcIik/PlxcXFxuPyhbXFxcXHNcXFxcU10qPylcXFxcbj88XFxcXC8ke1RFQU1NQVRFX01FU1NBR0VfVEFHfT5gLFxuICAnZycsXG4pXG5cbi8qKlxuICogUGFyc2UgYWxsIHRlYW1tYXRlIG1lc3NhZ2VzIGZyb20gWE1MIGZvcm1hdDpcbiAqIDx0ZWFtbWF0ZS1tZXNzYWdlIHRlYW1tYXRlX2lkPVwiYWxpY2VcIiBjb2xvcj1cInJlZFwiIHN1bW1hcnk9XCJCcmllZiB1cGRhdGVcIj5tZXNzYWdlIGNvbnRlbnQ8L3RlYW1tYXRlLW1lc3NhZ2U+XG4gKiBTdXBwb3J0cyBtdWx0aXBsZSBtZXNzYWdlcyBpbiBhIHNpbmdsZSB0ZXh0IGJsb2NrLlxuICovXG5mdW5jdGlvbiBwYXJzZVRlYW1tYXRlTWVzc2FnZXModGV4dDogc3RyaW5nKTogUGFyc2VkTWVzc2FnZVtdIHtcbiAgY29uc3QgbWVzc2FnZXM6IFBhcnNlZE1lc3NhZ2VbXSA9IFtdXG4gIC8vIFVzZSBtYXRjaEFsbCB0byBmaW5kIGFsbCBtYXRjaGVzICh0aGlzIGlzIGEgUmVnRXhwIG1ldGhvZCwgbm90IGNoaWxkX3Byb2Nlc3MpXG4gIGZvciAoY29uc3QgbWF0Y2ggb2YgdGV4dC5tYXRjaEFsbChURUFNTUFURV9NU0dfUkVHRVgpKSB7XG4gICAgaWYgKG1hdGNoWzFdICYmIG1hdGNoWzRdKSB7XG4gICAgICBtZXNzYWdlcy5wdXNoKHtcbiAgICAgICAgdGVhbW1hdGVJZDogbWF0Y2hbMV0sXG4gICAgICAgIGNvbG9yOiBtYXRjaFsyXSwgLy8gbWF5IGJlIHVuZGVmaW5lZFxuICAgICAgICBzdW1tYXJ5OiBtYXRjaFszXSwgLy8gbWF5IGJlIHVuZGVmaW5lZFxuICAgICAgICBjb250ZW50OiBtYXRjaFs0XS50cmltKCksXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtZXNzYWdlc1xufVxuXG5mdW5jdGlvbiBnZXREaXNwbGF5TmFtZSh0ZWFtbWF0ZUlkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodGVhbW1hdGVJZCA9PT0gJ2xlYWRlcicpIHtcbiAgICByZXR1cm4gJ2xlYWRlcidcbiAgfVxuICByZXR1cm4gdGVhbW1hdGVJZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gVXNlclRlYW1tYXRlTWVzc2FnZSh7XG4gIGFkZE1hcmdpbixcbiAgcGFyYW06IHsgdGV4dCB9LFxuICBpc1RyYW5zY3JpcHRNb2RlLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBtZXNzYWdlcyA9IHBhcnNlVGVhbW1hdGVNZXNzYWdlcyh0ZXh0KS5maWx0ZXIobXNnID0+IHtcbiAgICAvLyBQcmUtZmlsdGVyIHNodXRkb3duIGxpZmVjeWNsZSBtZXNzYWdlcyB0byBhdm9pZCBlbXB0eSB3cmFwcGVyXG4gICAgLy8gQm94IGVsZW1lbnRzIGNyZWF0aW5nIGJsYW5rIGxpbmVzIGJldHdlZW4gbW9kZWwgdHVybnNcbiAgICBpZiAoaXNTaHV0ZG93bkFwcHJvdmVkKG1zZy5jb250ZW50KSkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBqc29uUGFyc2UobXNnLmNvbnRlbnQpXG4gICAgICBpZiAocGFyc2VkPy50eXBlID09PSAndGVhbW1hdGVfdGVybWluYXRlZCcpIHJldHVybiBmYWxzZVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gTm90IEpTT04sIGtlZXAgdGhlIG1lc3NhZ2VcbiAgICB9XG4gICAgcmV0dXJuIHRydWVcbiAgfSlcbiAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiIG1hcmdpblRvcD17YWRkTWFyZ2luID8gMSA6IDB9IHdpZHRoPVwiMTAwJVwiPlxuICAgICAge21lc3NhZ2VzLm1hcCgobXNnLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBpbmtDb2xvciA9IHRvSW5rQ29sb3IobXNnLmNvbG9yKVxuICAgICAgICBjb25zdCBkaXNwbGF5TmFtZSA9IGdldERpc3BsYXlOYW1lKG1zZy50ZWFtbWF0ZUlkKVxuXG4gICAgICAgIC8vIFRyeSB0byByZW5kZXIgYXMgcGxhbiBhcHByb3ZhbCBtZXNzYWdlIChyZXF1ZXN0IG9yIHJlc3BvbnNlKVxuICAgICAgICBjb25zdCBwbGFuQXBwcm92YWxFbGVtZW50ID0gdHJ5UmVuZGVyUGxhbkFwcHJvdmFsTWVzc2FnZShcbiAgICAgICAgICBtc2cuY29udGVudCxcbiAgICAgICAgICBkaXNwbGF5TmFtZSxcbiAgICAgICAgKVxuICAgICAgICBpZiAocGxhbkFwcHJvdmFsRWxlbWVudCkge1xuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8UmVhY3QuRnJhZ21lbnQga2V5PXtpbmRleH0+e3BsYW5BcHByb3ZhbEVsZW1lbnR9PC9SZWFjdC5GcmFnbWVudD5cbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcnkgdG8gcmVuZGVyIGFzIHNodXRkb3duIG1lc3NhZ2UgKHJlcXVlc3Qgb3IgcmVqZWN0ZWQpXG4gICAgICAgIGNvbnN0IHNodXRkb3duRWxlbWVudCA9IHRyeVJlbmRlclNodXRkb3duTWVzc2FnZShtc2cuY29udGVudClcbiAgICAgICAgaWYgKHNodXRkb3duRWxlbWVudCkge1xuICAgICAgICAgIHJldHVybiA8UmVhY3QuRnJhZ21lbnQga2V5PXtpbmRleH0+e3NodXRkb3duRWxlbWVudH08L1JlYWN0LkZyYWdtZW50PlxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJ5IHRvIHJlbmRlciBhcyB0YXNrIGFzc2lnbm1lbnQgbWVzc2FnZVxuICAgICAgICBjb25zdCB0YXNrQXNzaWdubWVudEVsZW1lbnQgPSB0cnlSZW5kZXJUYXNrQXNzaWdubWVudE1lc3NhZ2UoXG4gICAgICAgICAgbXNnLmNvbnRlbnQsXG4gICAgICAgIClcbiAgICAgICAgaWYgKHRhc2tBc3NpZ25tZW50RWxlbWVudCkge1xuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8UmVhY3QuRnJhZ21lbnQga2V5PXtpbmRleH0+e3Rhc2tBc3NpZ25tZW50RWxlbWVudH08L1JlYWN0LkZyYWdtZW50PlxuICAgICAgICAgIClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyeSB0byBwYXJzZSBhcyBzdHJ1Y3R1cmVkIEpTT04gbWVzc2FnZVxuICAgICAgICBsZXQgcGFyc2VkSWRsZU5vdGlmaWNhdGlvbjogeyB0eXBlPzogc3RyaW5nIH0gfCBudWxsID0gbnVsbFxuICAgICAgICB0cnkge1xuICAgICAgICAgIHBhcnNlZElkbGVOb3RpZmljYXRpb24gPSBqc29uUGFyc2UobXNnLmNvbnRlbnQpXG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIE5vdCBKU09OXG4gICAgICAgIH1cblxuICAgICAgICAvLyBIaWRlIGlkbGUgbm90aWZpY2F0aW9ucyAtIHRoZXkgYXJlIHByb2Nlc3NlZCBzaWxlbnRseVxuICAgICAgICBpZiAocGFyc2VkSWRsZU5vdGlmaWNhdGlvbj8udHlwZSA9PT0gJ2lkbGVfbm90aWZpY2F0aW9uJykge1xuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cblxuICAgICAgICAvLyBUYXNrIGNvbXBsZXRlZCBub3RpZmljYXRpb24gLSBzaG93IHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZFxuICAgICAgICBpZiAocGFyc2VkSWRsZU5vdGlmaWNhdGlvbj8udHlwZSA9PT0gJ3Rhc2tfY29tcGxldGVkJykge1xuICAgICAgICAgIGNvbnN0IHRhc2tDb21wbGV0ZWQgPSBwYXJzZWRJZGxlTm90aWZpY2F0aW9uIGFzIHtcbiAgICAgICAgICAgIHR5cGU6IHN0cmluZ1xuICAgICAgICAgICAgZnJvbTogc3RyaW5nXG4gICAgICAgICAgICB0YXNrSWQ6IHN0cmluZ1xuICAgICAgICAgICAgdGFza1N1YmplY3Q/OiBzdHJpbmdcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxCb3gga2V5PXtpbmRleH0gZmxleERpcmVjdGlvbj1cImNvbHVtblwiIG1hcmdpblRvcD17MX0+XG4gICAgICAgICAgICAgIDxUZXh0XG4gICAgICAgICAgICAgICAgY29sb3I9e2lua0NvbG9yfVxuICAgICAgICAgICAgICA+e2BAJHtkaXNwbGF5TmFtZX0ke2ZpZ3VyZXMucG9pbnRlcn1gfTwvVGV4dD5cbiAgICAgICAgICAgICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgICAgICAgICAgICA8VGV4dCBjb2xvcj1cInN1Y2Nlc3NcIj7inJM8L1RleHQ+XG4gICAgICAgICAgICAgICAgPFRleHQ+XG4gICAgICAgICAgICAgICAgICB7JyAnfVxuICAgICAgICAgICAgICAgICAgQ29tcGxldGVkIHRhc2sgI3t0YXNrQ29tcGxldGVkLnRhc2tJZH1cbiAgICAgICAgICAgICAgICAgIHt0YXNrQ29tcGxldGVkLnRhc2tTdWJqZWN0ICYmIChcbiAgICAgICAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+ICh7dGFza0NvbXBsZXRlZC50YXNrU3ViamVjdH0pPC9UZXh0PlxuICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmYXVsdDogcGxhaW4gdGV4dCBtZXNzYWdlICh0cnVuY2F0ZWQpXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgPFRlYW1tYXRlTWVzc2FnZUNvbnRlbnRcbiAgICAgICAgICAgIGtleT17aW5kZXh9XG4gICAgICAgICAgICBkaXNwbGF5TmFtZT17ZGlzcGxheU5hbWV9XG4gICAgICAgICAgICBpbmtDb2xvcj17aW5rQ29sb3J9XG4gICAgICAgICAgICBjb250ZW50PXttc2cuY29udGVudH1cbiAgICAgICAgICAgIHN1bW1hcnk9e21zZy5zdW1tYXJ5fVxuICAgICAgICAgICAgaXNUcmFuc2NyaXB0TW9kZT17aXNUcmFuc2NyaXB0TW9kZX1cbiAgICAgICAgICAvPlxuICAgICAgICApXG4gICAgICB9KX1cbiAgICA8L0JveD5cbiAgKVxufVxuXG50eXBlIFRlYW1tYXRlTWVzc2FnZUNvbnRlbnRQcm9wcyA9IHtcbiAgZGlzcGxheU5hbWU6IHN0cmluZ1xuICBpbmtDb2xvcjogVGV4dFByb3BzWydjb2xvciddXG4gIGNvbnRlbnQ6IHN0cmluZ1xuICBzdW1tYXJ5Pzogc3RyaW5nXG4gIGlzVHJhbnNjcmlwdE1vZGU/OiBib29sZWFuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBUZWFtbWF0ZU1lc3NhZ2VDb250ZW50KHtcbiAgZGlzcGxheU5hbWUsXG4gIGlua0NvbG9yLFxuICBjb250ZW50LFxuICBzdW1tYXJ5LFxuICBpc1RyYW5zY3JpcHRNb2RlLFxufTogVGVhbW1hdGVNZXNzYWdlQ29udGVudFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgcmV0dXJuIChcbiAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBtYXJnaW5Ub3A9ezF9PlxuICAgICAgPEJveD5cbiAgICAgICAgPFRleHQgY29sb3I9e2lua0NvbG9yfT57YEAke2Rpc3BsYXlOYW1lfSR7ZmlndXJlcy5wb2ludGVyfWB9PC9UZXh0PlxuICAgICAgICB7c3VtbWFyeSAmJiA8VGV4dD4ge3N1bW1hcnl9PC9UZXh0Pn1cbiAgICAgIDwvQm94PlxuICAgICAge2lzVHJhbnNjcmlwdE1vZGUgJiYgKFxuICAgICAgICA8Qm94IHBhZGRpbmdMZWZ0PXsyfT5cbiAgICAgICAgICA8VGV4dD5cbiAgICAgICAgICAgIDxBbnNpPntjb250ZW50fTwvQW5zaT5cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgKX1cbiAgICA8L0JveD5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsY0FBY0EsY0FBYyxRQUFRLHVDQUF1QztBQUMzRSxPQUFPQyxPQUFPLE1BQU0sU0FBUztBQUM3QixPQUFPLEtBQUtDLEtBQUssTUFBTSxPQUFPO0FBQzlCLFNBQVNDLG9CQUFvQixRQUFRLHdCQUF3QjtBQUM3RCxTQUFTQyxJQUFJLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxFQUFFLEtBQUtDLFNBQVMsUUFBUSxjQUFjO0FBQzlELFNBQVNDLFVBQVUsUUFBUSxvQkFBb0I7QUFDL0MsU0FBU0MsU0FBUyxRQUFRLCtCQUErQjtBQUN6RCxTQUFTQyxrQkFBa0IsUUFBUSxnQ0FBZ0M7QUFDbkUsU0FBU0MsZUFBZSxRQUFRLHVCQUF1QjtBQUN2RCxTQUFTQyw0QkFBNEIsUUFBUSwwQkFBMEI7QUFDdkUsU0FBU0Msd0JBQXdCLFFBQVEsc0JBQXNCO0FBQy9ELFNBQVNDLDhCQUE4QixRQUFRLDRCQUE0QjtBQUUzRSxLQUFLQyxLQUFLLEdBQUc7RUFDWEMsU0FBUyxFQUFFLE9BQU87RUFDbEJDLEtBQUssRUFBRWpCLGNBQWM7RUFDckJrQixnQkFBZ0IsQ0FBQyxFQUFFLE9BQU87QUFDNUIsQ0FBQztBQUVELEtBQUtDLGFBQWEsR0FBRztFQUNuQkMsVUFBVSxFQUFFLE1BQU07RUFDbEJDLE9BQU8sRUFBRSxNQUFNO0VBQ2ZDLEtBQUssQ0FBQyxFQUFFLE1BQU07RUFDZEMsT0FBTyxDQUFDLEVBQUUsTUFBTTtBQUNsQixDQUFDO0FBRUQsTUFBTUMsa0JBQWtCLEdBQUcsSUFBSUMsTUFBTSxDQUNuQyxJQUFJdEIsb0JBQW9CLHVHQUF1R0Esb0JBQW9CLEdBQUcsRUFDdEosR0FDRixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTdUIscUJBQXFCQSxDQUFDQyxJQUFJLEVBQUUsTUFBTSxD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