UserPromptMessage.tsx
components/messages/UserPromptMessage.tsx
80
Lines
15172
Bytes
1
Exports
12
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 ui-flow. It contains 80 lines, 12 detected imports, and 1 detected exports.
Important relationships
- components/messages/AdvisorMessage.tsx
- components/messages/AssistantRedactedThinkingMessage.tsx
- components/messages/AssistantTextMessage.tsx
- components/messages/AssistantThinkingMessage.tsx
- components/messages/AssistantToolUseMessage.tsx
- components/messages/AttachmentMessage.tsx
- components/messages/CollapsedReadSearchContent.tsx
- components/messages/CompactBoundaryMessage.tsx
Detected exports
UserPromptMessage
Keywords
featuretextreactusebrieflayoutisbriefonlytimestampprompttailviewingagenttaskidkairos
Detected imports
bun:bundle@anthropic-ai/sdk/resources/index.mjsreact../../bootstrap/state.js../../ink.js../../services/analytics/growthbook.js../../state/AppState.js../../utils/envUtils.js../../utils/log.js../../utils/stringUtils.js../messageActions.js./HighlightedThinkingText.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import { feature } from 'bun:bundle';
import type { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
import React, { useContext, useMemo } from 'react';
import { getKairosActive, getUserMsgOptIn } from '../../bootstrap/state.js';
import { Box } from '../../ink.js';
import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js';
import { useAppState } from '../../state/AppState.js';
import { isEnvTruthy } from '../../utils/envUtils.js';
import { logError } from '../../utils/log.js';
import { countCharInString } from '../../utils/stringUtils.js';
import { MessageActionsSelectedContext } from '../messageActions.js';
import { HighlightedThinkingText } from './HighlightedThinkingText.js';
type Props = {
addMargin: boolean;
param: TextBlockParam;
isTranscriptMode?: boolean;
timestamp?: string;
};
// Hard cap on displayed prompt text. Piping large files via stdin
// (e.g. `cat 11k-line-file | claude`) creates a single user message whose
// <Text> node the fullscreen Ink renderer must wrap/output on every frame,
// causing 500ms+ keystroke latency. React.memo skips the React render but
// the Ink output pass still iterates the full mounted text. Non-fullscreen
// avoids this via <Static> (print-and-forget to terminal scrollback).
// Head+tail because `{ cat file; echo prompt; } | claude` puts the user's
// actual question at the end.
const MAX_DISPLAY_CHARS = 10_000;
const TRUNCATE_HEAD_CHARS = 2_500;
const TRUNCATE_TAIL_CHARS = 2_500;
export function UserPromptMessage({
addMargin,
param: {
text
},
isTranscriptMode,
timestamp
}: Props): React.ReactNode {
// REPL.tsx passes isBriefOnly={viewedTeammateTask ? false : isBriefOnly}
// but that prop isn't threaded this deep — replicate the override by
// reading viewingAgentTaskId directly. Computed here (not in the child)
// so the parent Box can drop its backgroundColor: in brief mode the
// child renders a label-style layout, and Box backgroundColor paints
// behind children unconditionally (they can't opt out).
//
// Hooks stay INSIDE feature() ternaries so external builds don't pay
// the per-scrollback-message store subscription (useSyncExternalStore
// bypasses React.memo). Runtime-gated like isBriefEnabled() but inlined
// to avoid pulling BriefTool.ts → prompt.ts tool-name strings into
// external builds.
const isBriefOnly = feature('KAIROS') || feature('KAIROS_BRIEF') ?
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
useAppState(s => s.isBriefOnly) : false;
const viewingAgentTaskId = feature('KAIROS') || feature('KAIROS_BRIEF') ?
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
useAppState(s_0 => s_0.viewingAgentTaskId) : null;
// Hoisted to mount-time — per-message component, re-renders on every scroll.
const briefEnvEnabled = feature('KAIROS') || feature('KAIROS_BRIEF') ?
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
useMemo(() => isEnvTruthy(process.env.CLAUDE_CODE_BRIEF), []) : false;
const useBriefLayout = feature('KAIROS') || feature('KAIROS_BRIEF') ? (getKairosActive() || getUserMsgOptIn() && (briefEnvEnabled || getFeatureValue_CACHED_MAY_BE_STALE('tengu_kairos_brief', false))) && isBriefOnly && !isTranscriptMode && !viewingAgentTaskId : false;
// Truncate before the early return so the hook order is stable.
const displayText = useMemo(() => {
if (text.length <= MAX_DISPLAY_CHARS) return text;
const head = text.slice(0, TRUNCATE_HEAD_CHARS);
const tail = text.slice(-TRUNCATE_TAIL_CHARS);
const hiddenLines = countCharInString(text, '\n', TRUNCATE_HEAD_CHARS) - countCharInString(tail, '\n');
return `${head}\n… +${hiddenLines} lines …\n${tail}`;
}, [text]);
const isSelected = useContext(MessageActionsSelectedContext);
if (!text) {
logError(new Error('No content found in user prompt message'));
return null;
}
return <Box flexDirection="column" marginTop={addMargin ? 1 : 0} backgroundColor={isSelected ? 'messageActionsBackground' : useBriefLayout ? undefined : 'userMessageBackground'} paddingRight={useBriefLayout ? 0 : 1}>
<HighlightedThinkingText text={displayText} useBriefLayout={useBriefLayout} timestamp={useBriefLayout ? timestamp : undefined} />
</Box>;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiVGV4dEJsb2NrUGFyYW0iLCJSZWFjdCIsInVzZUNvbnRleHQiLCJ1c2VNZW1vIiwiZ2V0S2Fpcm9zQWN0aXZlIiwiZ2V0VXNlck1zZ09wdEluIiwiQm94IiwiZ2V0RmVhdHVyZVZhbHVlX0NBQ0hFRF9NQVlfQkVfU1RBTEUiLCJ1c2VBcHBTdGF0ZSIsImlzRW52VHJ1dGh5IiwibG9nRXJyb3IiLCJjb3VudENoYXJJblN0cmluZyIsIk1lc3NhZ2VBY3Rpb25zU2VsZWN0ZWRDb250ZXh0IiwiSGlnaGxpZ2h0ZWRUaGlua2luZ1RleHQiLCJQcm9wcyIsImFkZE1hcmdpbiIsInBhcmFtIiwiaXNUcmFuc2NyaXB0TW9kZSIsInRpbWVzdGFtcCIsIk1BWF9ESVNQTEFZX0NIQVJTIiwiVFJVTkNBVEVfSEVBRF9DSEFSUyIsIlRSVU5DQVRFX1RBSUxfQ0hBUlMiLCJVc2VyUHJvbXB0TWVzc2FnZSIsInRleHQiLCJSZWFjdE5vZGUiLCJpc0JyaWVmT25seSIsInMiLCJ2aWV3aW5nQWdlbnRUYXNrSWQiLCJicmllZkVudkVuYWJsZWQiLCJwcm9jZXNzIiwiZW52IiwiQ0xBVURFX0NPREVfQlJJRUYiLCJ1c2VCcmllZkxheW91dCIsImRpc3BsYXlUZXh0IiwibGVuZ3RoIiwiaGVhZCIsInNsaWNlIiwidGFpbCIsImhpZGRlbkxpbmVzIiwiaXNTZWxlY3RlZCIsIkVycm9yIiwidW5kZWZpbmVkIl0sInNvdXJjZXMiOlsiVXNlclByb21wdE1lc3NhZ2UudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGZlYXR1cmUgfSBmcm9tICdidW46YnVuZGxlJ1xuaW1wb3J0IHR5cGUgeyBUZXh0QmxvY2tQYXJhbSB9IGZyb20gJ0BhbnRocm9waWMtYWkvc2RrL3Jlc291cmNlcy9pbmRleC5tanMnXG5pbXBvcnQgUmVhY3QsIHsgdXNlQ29udGV4dCwgdXNlTWVtbyB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgZ2V0S2Fpcm9zQWN0aXZlLCBnZXRVc2VyTXNnT3B0SW4gfSBmcm9tICcuLi8uLi9ib290c3RyYXAvc3RhdGUuanMnXG5pbXBvcnQgeyBCb3ggfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBnZXRGZWF0dXJlVmFsdWVfQ0FDSEVEX01BWV9CRV9TVEFMRSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9ncm93dGhib29rLmpzJ1xuaW1wb3J0IHsgdXNlQXBwU3RhdGUgfSBmcm9tICcuLi8uLi9zdGF0ZS9BcHBTdGF0ZS5qcydcbmltcG9ydCB7IGlzRW52VHJ1dGh5IH0gZnJvbSAnLi4vLi4vdXRpbHMvZW52VXRpbHMuanMnXG5pbXBvcnQgeyBsb2dFcnJvciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcydcbmltcG9ydCB7IGNvdW50Q2hhckluU3RyaW5nIH0gZnJvbSAnLi4vLi4vdXRpbHMvc3RyaW5nVXRpbHMuanMnXG5pbXBvcnQgeyBNZXNzYWdlQWN0aW9uc1NlbGVjdGVkQ29udGV4dCB9IGZyb20gJy4uL21lc3NhZ2VBY3Rpb25zLmpzJ1xuaW1wb3J0IHsgSGlnaGxpZ2h0ZWRUaGlua2luZ1RleHQgfSBmcm9tICcuL0hpZ2hsaWdodGVkVGhpbmtpbmdUZXh0LmpzJ1xuXG50eXBlIFByb3BzID0ge1xuICBhZGRNYXJnaW46IGJvb2xlYW5cbiAgcGFyYW06IFRleHRCbG9ja1BhcmFtXG4gIGlzVHJhbnNjcmlwdE1vZGU/OiBib29sZWFuXG4gIHRpbWVzdGFtcD86IHN0cmluZ1xufVxuXG4vLyBIYXJkIGNhcCBvbiBkaXNwbGF5ZWQgcHJvbXB0IHRleHQuIFBpcGluZyBsYXJnZSBmaWxlcyB2aWEgc3RkaW5cbi8vIChlLmcuIGBjYXQgMTFrLWxpbmUtZmlsZSB8IGNsYXVkZWApIGNyZWF0ZXMgYSBzaW5nbGUgdXNlciBtZXNzYWdlIHdob3NlXG4vLyA8VGV4dD4gbm9kZSB0aGUgZnVsbHNjcmVlbiBJbmsgcmVuZGVyZXIgbXVzdCB3cmFwL291dHB1dCBvbiBldmVyeSBmcmFtZSxcbi8vIGNhdXNpbmcgNTAwbXMrIGtleXN0cm9rZSBsYXRlbmN5LiBSZWFjdC5tZW1vIHNraXBzIHRoZSBSZWFjdCByZW5kZXIgYnV0XG4vLyB0aGUgSW5rIG91dHB1dCBwYXNzIHN0aWxsIGl0ZXJhdGVzIHRoZSBmdWxsIG1vdW50ZWQgdGV4dC4gTm9uLWZ1bGxzY3JlZW5cbi8vIGF2b2lkcyB0aGlzIHZpYSA8U3RhdGljPiAocHJpbnQtYW5kLWZvcmdldCB0byB0ZXJtaW5hbCBzY3JvbGxiYWNrKS5cbi8vIEhlYWQrdGFpbCBiZWNhdXNlIGB7IGNhdCBmaWxlOyBlY2hvIHByb21wdDsgfSB8IGNsYXVkZWAgcHV0cyB0aGUgdXNlcidzXG4vLyBhY3R1YWwgcXVlc3Rpb24gYXQgdGhlIGVuZC5cbmNvbnN0IE1BWF9ESVNQTEFZX0NIQVJTID0gMTBfMDAwXG5jb25zdCBUUlVOQ0FURV9IRUFEX0NIQVJTID0gMl81MDBcbmNvbnN0IFRSVU5DQVRFX1RBSUxfQ0hBUlMgPSAyXzUwMFxuXG5leHBvcnQgZnVuY3Rpb24gVXNlclByb21wdE1lc3NhZ2Uoe1xuICBhZGRNYXJnaW4sXG4gIHBhcmFtOiB7IHRleHQgfSxcbiAgaXNUcmFuc2NyaXB0TW9kZSxcbiAgdGltZXN0YW1wLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAvLyBSRVBMLnRzeCBwYXNzZXMgaXNCcmllZk9ubHk9e3ZpZXdlZFRlYW1tYXRlVGFzayA/IGZhbHNlIDogaXNCcmllZk9ubHl9XG4gIC8vIGJ1dCB0aGF0IHByb3AgaXNuJ3QgdGhyZWFkZWQgdGhpcyBkZWVwIOKAlCByZXBsaWNhdGUgdGhlIG92ZXJyaWRlIGJ5XG4gIC8vIHJlYWRpbmcgdmlld2luZ0FnZW50VGFza0lkIGRpcmVjdGx5LiBDb21wdXRlZCBoZXJlIChub3QgaW4gdGhlIGNoaWxkKVxuICAvLyBzbyB0aGUgcGFyZW50IEJveCBjYW4gZHJvcCBpdHMgYmFja2dyb3VuZENvbG9yOiBpbiBicmllZiBtb2RlIHRoZVxuICAvLyBjaGlsZCByZW5kZXJzIGEgbGFiZWwtc3R5bGUgbGF5b3V0LCBhbmQgQm94IGJhY2tncm91bmRDb2xvciBwYWludHNcbiAgLy8gYmVoaW5kIGNoaWxkcmVuIHVuY29uZGl0aW9uYWxseSAodGhleSBjYW4ndCBvcHQgb3V0KS5cbiAgLy9cbiAgLy8gSG9va3Mgc3RheSBJTlNJREUgZmVhdHVyZSgpIHRlcm5hcmllcyBzbyBleHRlcm5hbCBidWlsZHMgZG9uJ3QgcGF5XG4gIC8vIHRoZSBwZXItc2Nyb2xsYmFjay1tZXNzYWdlIHN0b3JlIHN1YnNjcmlwdGlvbiAodXNlU3luY0V4dGVybmFsU3RvcmVcbiAgLy8gYnlwYXNzZXMgUmVhY3QubWVtbykuIFJ1bnRpbWUtZ2F0ZWQgbGlrZSBpc0JyaWVmRW5hYmxlZCgpIGJ1dCBpbmxpbmVkXG4gIC8vIHRvIGF2b2lkIHB1bGxpbmcgQnJpZWZUb29sLnRzIOKGkiBwcm9tcHQudHMgdG9vbC1uYW1lIHN0cmluZ3MgaW50b1xuICAvLyBleHRlcm5hbCBidWlsZHMuXG4gIGNvbnN0IGlzQnJpZWZPbmx5ID1cbiAgICBmZWF0dXJlKCdLQUlST1MnKSB8fCBmZWF0dXJlKCdLQUlST1NfQlJJRUYnKVxuICAgICAgPyAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gICAgICAgIHVzZUFwcFN0YXRlKHMgPT4gcy5pc0JyaWVmT25seSlcbiAgICAgIDogZmFsc2VcbiAgY29uc3Qgdmlld2luZ0FnZW50VGFza0lkID1cbiAgICBmZWF0dXJlKCdLQUlST1MnKSB8fCBmZWF0dXJlKCdLQUlST1NfQlJJRUYnKVxuICAgICAgPyAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gICAgICAgIHVzZUFwcFN0YXRlKHMgPT4gcy52aWV3aW5nQWdlbnRUYXNrSWQpXG4gICAgICA6IG51bGxcbiAgLy8gSG9pc3RlZCB0byBtb3VudC10aW1lIOKAlCBwZXItbWVzc2FnZSBjb21wb25lbnQsIHJlLXJlbmRlcnMgb24gZXZlcnkgc2Nyb2xsLlxuICBjb25zdCBicmllZkVudkVuYWJsZWQgPVxuICAgIGZlYXR1cmUoJ0tBSVJPUycpIHx8IGZlYXR1cmUoJ0tBSVJPU19CUklFRicpXG4gICAgICA/IC8vIGJpb21lLWlnbm9yZSBsaW50L2NvcnJlY3RuZXNzL3VzZUhvb2tBdFRvcExldmVsOiBmZWF0dXJlKCkgaXMgYSBjb21waWxlLXRpbWUgY29uc3RhbnRcbiAgICAgICAgdXNlTWVtbygoKSA9PiBpc0VudlRydXRoeShwcm9jZXNzLmVudi5DTEFVREVfQ09ERV9CUklFRiksIFtdKVxuICAgICAgOiBmYWxzZVxuICBjb25zdCB1c2VCcmllZkxheW91dCA9XG4gICAgZmVhdHVyZSgnS0FJUk9TJykgfHwgZmVhdHVyZSgnS0FJUk9TX0JSSUVGJylcbiAgICAgID8gKGdldEthaXJvc0FjdGl2ZSgpIHx8XG4gICAgICAgICAgKGdldFVzZXJNc2dPcHRJbigpICYmXG4gICAgICAgICAgICAoYnJpZWZFbnZFbmFibGVkIHx8XG4gICAgICAgICAgICAgIGdldEZlYXR1cmVWYWx1ZV9DQUNIRURfTUFZX0JFX1NUQUxFKFxuICAgICAgICAgICAgICAgICd0ZW5ndV9rYWlyb3NfYnJpZWYnLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICApKSkpICYmXG4gICAgICAgIGlzQnJpZWZPbmx5ICYmXG4gICAgICAgICFpc1RyYW5zY3JpcHRNb2RlICYmXG4gICAgICAgICF2aWV3aW5nQWdlbnRUYXNrSWRcbiAgICAgIDogZmFsc2VcblxuICAvLyBUcnVuY2F0ZSBiZWZvcmUgdGhlIGVhcmx5IHJldHVybiBzbyB0aGUgaG9vayBvcmRlciBpcyBzdGFibGUuXG4gIGNvbnN0IGRpc3BsYXlUZXh0ID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKHRleHQubGVuZ3RoIDw9IE1BWF9ESVNQTEFZX0NIQVJTKSByZXR1cm4gdGV4dFxuICAgIGNvbnN0IGhlYWQgPSB0ZXh0LnNsaWNlKDAsIFRSVU5DQVRFX0hFQURfQ0hBUlMpXG4gICAgY29uc3QgdGFpbCA9IHRleHQuc2xpY2UoLVRSVU5DQVRFX1RBSUxfQ0hBUlMpXG4gICAgY29uc3QgaGlkZGVuTGluZXMgPVxuICAgICAgY291bnRDaGFySW5TdHJpbmcodGV4dCwgJ1xcbicsIFRSVU5DQVRFX0hFQURfQ0hBUlMpIC1cbiAgICAgIGNvdW50Q2hhckluU3RyaW5nKHRhaWwsICdcXG4nKVxuICAgIHJldHVybiBgJHtoZWFkfVxcbuKApiArJHtoaWRkZW5MaW5lc30gbGluZXMg4oCmXFxuJHt0YWlsfWBcbiAgfSwgW3RleHRdKVxuXG4gIGNvbnN0IGlzU2VsZWN0ZWQgPSB1c2VDb250ZXh0KE1lc3NhZ2VBY3Rpb25zU2VsZWN0ZWRDb250ZXh0KVxuXG4gIGlmICghdGV4dCkge1xuICAgIGxvZ0Vycm9yKG5ldyBFcnJvcignTm8gY29udGVudCBmb3VuZCBpbiB1c2VyIHByb21wdCBtZXNzYWdlJykpXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPEJveFxuICAgICAgZmxleERpcmVjdGlvbj1cImNvbHVtblwiXG4gICAgICBtYXJnaW5Ub3A9e2FkZE1hcmdpbiA/IDEgOiAwfVxuICAgICAgYmFja2dyb3VuZENvbG9yPXtcbiAgICAgICAgaXNTZWxlY3RlZFxuICAgICAgICAgID8gJ21lc3NhZ2VBY3Rpb25zQmFja2dyb3VuZCdcbiAgICAgICAgICA6IHVzZUJyaWVmTGF5b3V0XG4gICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgOiAndXNlck1lc3NhZ2VCYWNrZ3JvdW5kJ1xuICAgICAgfVxuICAgICAgcGFkZGluZ1JpZ2h0PXt1c2VCcmllZkxheW91dCA/IDAgOiAxfVxuICAgID5cbiAgICAgIDxIaWdobGlnaHRlZFRoaW5raW5nVGV4dFxuICAgICAgICB0ZXh0PXtkaXNwbGF5VGV4dH1cbiAgICAgICAgdXNlQnJpZWZMYXlvdXQ9e3VzZUJyaWVmTGF5b3V0fVxuICAgICAgICB0aW1lc3RhbXA9e3VzZUJyaWVmTGF5b3V0ID8gdGltZXN0YW1wIDogdW5kZWZpbmVkfVxuICAgICAgLz5cbiAgICA8L0JveD5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxPQUFPLFFBQVEsWUFBWTtBQUNwQyxjQUFjQyxjQUFjLFFBQVEsdUNBQXVDO0FBQzNFLE9BQU9DLEtBQUssSUFBSUMsVUFBVSxFQUFFQyxPQUFPLFFBQVEsT0FBTztBQUNsRCxTQUFTQyxlQUFlLEVBQUVDLGVBQWUsUUFBUSwwQkFBMEI7QUFDM0UsU0FBU0MsR0FBRyxRQUFRLGNBQWM7QUFDbEMsU0FBU0MsbUNBQW1DLFFBQVEsd0NBQXdDO0FBQzVGLFNBQVNDLFdBQVcsUUFBUSx5QkFBeUI7QUFDckQsU0FBU0MsV0FBVyxRQUFRLHlCQUF5QjtBQUNyRCxTQUFTQyxRQUFRLFFBQVEsb0JBQW9CO0FBQzdDLFNBQVNDLGlCQUFpQixRQUFRLDRCQUE0QjtBQUM5RCxTQUFTQyw2QkFBNkIsUUFBUSxzQkFBc0I7QUFDcEUsU0FBU0MsdUJBQXVCLFFBQVEsOEJBQThCO0FBRXRFLEtBQUtDLEtBQUssR0FBRztFQUNYQyxTQUFTLEVBQUUsT0FBTztFQUNsQkMsS0FBSyxFQUFFaEIsY0FBYztFQUNyQmlCLGdCQUFnQixDQUFDLEVBQUUsT0FBTztFQUMxQkMsU0FBUyxDQUFDLEVBQUUsTUFBTTtBQUNwQixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQyxpQkFBaUIsR0FBRyxNQUFNO0FBQ2hDLE1BQU1DLG1CQUFtQixHQUFHLEtBQUs7QUFDakMsTUFBTUMsbUJBQW1CLEdBQUcsS0FBSztBQUVqQyxPQUFPLFNBQVNDLGlCQUFpQkEsQ0FBQztFQUNoQ1AsU0FBUztFQUNUQyxLQUFLLEVBQUU7SUFBRU87RUFBSyxDQUFDO0VBQ2ZOLGdCQUFnQjtFQUNoQkM7QUFDSyxDQUFOLEVBQUVKLEtBQUssQ0FBQyxFQUFFYixLQUFLLENBQUN1QixTQUFTLENB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