πŸ“„ File detail

components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx

🧩 .tsxπŸ“ 104 linesπŸ’Ύ 16,409 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 UserToolSuccessMessage β€” mainly types, interfaces, or factory objects. Dependencies touch bun:bundle, figures, React UI, and src. It composes internal code from ink, state, Tool, types, and utils (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 figures from 'figures'; import * as React from 'react'; import { SentryErrorBoundary } from 'src/components/SentryErrorBoundary.js'; import { Box, Text, useTheme } from '../../../ink.js';

πŸ“€ Exports (heuristic)

  • UserToolSuccessMessage

πŸ“š External import roots

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

  • bun:bundle
  • figures
  • react
  • src

πŸ–₯️ Source preview

import { feature } from 'bun:bundle';
import figures from 'figures';
import * as React from 'react';
import { SentryErrorBoundary } from 'src/components/SentryErrorBoundary.js';
import { Box, Text, useTheme } from '../../../ink.js';
import { useAppState } from '../../../state/AppState.js';
import { filterToolProgressMessages, type Tool, type Tools } from '../../../Tool.js';
import type { NormalizedUserMessage, ProgressMessage } from '../../../types/message.js';
import { deleteClassifierApproval, getClassifierApproval, getYoloClassifierApproval } from '../../../utils/classifierApprovals.js';
import type { buildMessageLookups } from '../../../utils/messages.js';
import { MessageResponse } from '../../MessageResponse.js';
import { HookProgressMessage } from '../HookProgressMessage.js';
type Props = {
  message: NormalizedUserMessage;
  lookups: ReturnType<typeof buildMessageLookups>;
  toolUseID: string;
  progressMessagesForMessage: ProgressMessage[];
  style?: 'condensed';
  tool?: Tool;
  tools: Tools;
  verbose: boolean;
  width: number | string;
  isTranscriptMode?: boolean;
};
export function UserToolSuccessMessage({
  message,
  lookups,
  toolUseID,
  progressMessagesForMessage,
  style,
  tool,
  tools,
  verbose,
  width,
  isTranscriptMode
}: Props): React.ReactNode {
  const [theme] = useTheme();
  // Hook stays inside feature() ternary so external builds don't pay a
  // per-scrollback-message store subscription β€” same pattern as
  // UserPromptMessage.tsx.
  const isBriefOnly = feature('KAIROS') || feature('KAIROS_BRIEF') ?
  // biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
  useAppState(s => s.isBriefOnly) : false;

  // Capture classifier approval once on mount, then delete from Map to prevent linear growth.
  // useState lazy initializer ensures the value persists across re-renders.
  const [classifierRule] = React.useState(() => getClassifierApproval(toolUseID));
  const [yoloReason] = React.useState(() => getYoloClassifierApproval(toolUseID));
  React.useEffect(() => {
    deleteClassifierApproval(toolUseID);
  }, [toolUseID]);
  if (!message.toolUseResult || !tool) {
    return null;
  }

  // Resumed transcripts deserialize toolUseResult via raw JSON.parse with no
  // validation (parseJSONL). A partial/corrupt/old-format result crashes
  // renderToolResultMessage on first field access (anthropics/claude-code#39817).
  // Validate against outputSchema before rendering β€” mirrors CollapsedReadSearchContent.
  const parsedOutput = tool.outputSchema?.safeParse(message.toolUseResult);
  if (parsedOutput && !parsedOutput.success) {
    return null;
  }
  const toolResult = parsedOutput?.data ?? message.toolUseResult;
  const renderedMessage = tool.renderToolResultMessage?.(toolResult as never, filterToolProgressMessages(progressMessagesForMessage), {
    style,
    theme,
    tools,
    verbose,
    isTranscriptMode,
    isBriefOnly,
    input: lookups.toolUseByToolUseID.get(toolUseID)?.input
  }) ?? null;

  // Don't render anything if the tool result message is null
  if (renderedMessage === null) {
    return null;
  }

  // Tools that return '' from userFacingName opt out of tool chrome and
  // render like plain assistant text. Skip the tool-result width constraint
  // so MarkdownTable's SAFETY_MARGIN=4 (tuned for the assistant-text 2-col
  // dot gutter) holds β€” otherwise tables wrap their box-drawing chars.
  const rendersAsAssistantText = tool.userFacingName(undefined) === '';
  return <Box flexDirection="column">
      <Box flexDirection="column" width={rendersAsAssistantText ? undefined : width}>
        {renderedMessage}
        {feature('BASH_CLASSIFIER') ? classifierRule && <MessageResponse height={1}>
                <Text dimColor>
                  <Text color="success">{figures.tick}</Text>
                  {' Auto-approved \u00b7 matched '}
                  {`"${classifierRule}"`}
                </Text>
              </MessageResponse> : null}
        {feature('TRANSCRIPT_CLASSIFIER') ? yoloReason && <MessageResponse height={1}>
                <Text dimColor>Allowed by auto mode classifier</Text>
              </MessageResponse> : null}
      </Box>
      <SentryErrorBoundary>
        <HookProgressMessage hookEvent="PostToolUse" lookups={lookups} toolUseID={toolUseID} verbose={verbose} isTranscriptMode={isTranscriptMode} />
      </SentryErrorBoundary>
    </Box>;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiZmlndXJlcyIsIlJlYWN0IiwiU2VudHJ5RXJyb3JCb3VuZGFyeSIsIkJveCIsIlRleHQiLCJ1c2VUaGVtZSIsInVzZUFwcFN0YXRlIiwiZmlsdGVyVG9vbFByb2dyZXNzTWVzc2FnZXMiLCJUb29sIiwiVG9vbHMiLCJOb3JtYWxpemVkVXNlck1lc3NhZ2UiLCJQcm9ncmVzc01lc3NhZ2UiLCJkZWxldGVDbGFzc2lmaWVyQXBwcm92YWwiLCJnZXRDbGFzc2lmaWVyQXBwcm92YWwiLCJnZXRZb2xvQ2xhc3NpZmllckFwcHJvdmFsIiwiYnVpbGRNZXNzYWdlTG9va3VwcyIsIk1lc3NhZ2VSZXNwb25zZSIsIkhvb2tQcm9ncmVzc01lc3NhZ2UiLCJQcm9wcyIsIm1lc3NhZ2UiLCJsb29rdXBzIiwiUmV0dXJuVHlwZSIsInRvb2xVc2VJRCIsInByb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlIiwic3R5bGUiLCJ0b29sIiwidG9vbHMiLCJ2ZXJib3NlIiwid2lkdGgiLCJpc1RyYW5zY3JpcHRNb2RlIiwiVXNlclRvb2xTdWNjZXNzTWVzc2FnZSIsIlJlYWN0Tm9kZSIsInRoZW1lIiwiaXNCcmllZk9ubHkiLCJzIiwiY2xhc3NpZmllclJ1bGUiLCJ1c2VTdGF0ZSIsInlvbG9SZWFzb24iLCJ1c2VFZmZlY3QiLCJ0b29sVXNlUmVzdWx0IiwicGFyc2VkT3V0cHV0Iiwib3V0cHV0U2NoZW1hIiwic2FmZVBhcnNlIiwic3VjY2VzcyIsInRvb2xSZXN1bHQiLCJkYXRhIiwicmVuZGVyZWRNZXNzYWdlIiwicmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2UiLCJpbnB1dCIsInRvb2xVc2VCeVRvb2xVc2VJRCIsImdldCIsInJlbmRlcnNBc0Fzc2lzdGFudFRleHQiLCJ1c2VyRmFjaW5nTmFtZSIsInVuZGVmaW5lZCIsInRpY2siXSwic291cmNlcyI6WyJVc2VyVG9vbFN1Y2Nlc3NNZXNzYWdlLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmZWF0dXJlIH0gZnJvbSAnYnVuOmJ1bmRsZSdcbmltcG9ydCBmaWd1cmVzIGZyb20gJ2ZpZ3VyZXMnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IFNlbnRyeUVycm9yQm91bmRhcnkgfSBmcm9tICdzcmMvY29tcG9uZW50cy9TZW50cnlFcnJvckJvdW5kYXJ5LmpzJ1xuaW1wb3J0IHsgQm94LCBUZXh0LCB1c2VUaGVtZSB9IGZyb20gJy4uLy4uLy4uL2luay5qcydcbmltcG9ydCB7IHVzZUFwcFN0YXRlIH0gZnJvbSAnLi4vLi4vLi4vc3RhdGUvQXBwU3RhdGUuanMnXG5pbXBvcnQge1xuICBmaWx0ZXJUb29sUHJvZ3Jlc3NNZXNzYWdlcyxcbiAgdHlwZSBUb29sLFxuICB0eXBlIFRvb2xzLFxufSBmcm9tICcuLi8uLi8uLi9Ub29sLmpzJ1xuaW1wb3J0IHR5cGUge1xuICBOb3JtYWxpemVkVXNlck1lc3NhZ2UsXG4gIFByb2dyZXNzTWVzc2FnZSxcbn0gZnJvbSAnLi4vLi4vLi4vdHlwZXMvbWVzc2FnZS5qcydcbmltcG9ydCB7XG4gIGRlbGV0ZUNsYXNzaWZpZXJBcHByb3ZhbCxcbiAgZ2V0Q2xhc3NpZmllckFwcHJvdmFsLFxuICBnZXRZb2xvQ2xhc3NpZmllckFwcHJvdmFsLFxufSBmcm9tICcuLi8uLi8uLi91dGlscy9jbGFzc2lmaWVyQXBwcm92YWxzLmpzJ1xuaW1wb3J0IHR5cGUgeyBidWlsZE1lc3NhZ2VMb29rdXBzIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvbWVzc2FnZXMuanMnXG5pbXBvcnQgeyBNZXNzYWdlUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9NZXNzYWdlUmVzcG9uc2UuanMnXG5pbXBvcnQgeyBIb29rUHJvZ3Jlc3NNZXNzYWdlIH0gZnJvbSAnLi4vSG9va1Byb2dyZXNzTWVzc2FnZS5qcydcblxudHlwZSBQcm9wcyA9IHtcbiAgbWVzc2FnZTogTm9ybWFsaXplZFVzZXJNZXNzYWdlXG4gIGxvb2t1cHM6IFJldHVyblR5cGU8dHlwZW9mIGJ1aWxkTWVzc2FnZUxvb2t1cHM+XG4gIHRvb2xVc2VJRDogc3RyaW5nXG4gIHByb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlOiBQcm9ncmVzc01lc3NhZ2VbXVxuICBzdHlsZT86ICdjb25kZW5zZWQnXG4gIHRvb2w/OiBUb29sXG4gIHRvb2xzOiBUb29sc1xuICB2ZXJib3NlOiBib29sZWFuXG4gIHdpZHRoOiBudW1iZXIgfCBzdHJpbmdcbiAgaXNUcmFuc2NyaXB0TW9kZT86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFVzZXJUb29sU3VjY2Vzc01lc3NhZ2Uoe1xuICBtZXNzYWdlLFxuICBsb29rdXBzLFxuICB0b29sVXNlSUQsXG4gIHByb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlLFxuICBzdHlsZSxcbiAgdG9vbCxcbiAgdG9vbHMsXG4gIHZlcmJvc2UsXG4gIHdpZHRoLFxuICBpc1RyYW5zY3JpcHRNb2RlLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBbdGhlbWVdID0gdXNlVGhlbWUoKVxuICAvLyBIb29rIHN0YXlzIGluc2lkZSBmZWF0dXJlKCkgdGVybmFyeSBzbyBleHRlcm5hbCBidWlsZHMgZG9uJ3QgcGF5IGFcbiAgLy8gcGVyLXNjcm9sbGJhY2stbWVzc2FnZSBzdG9yZSBzdWJzY3JpcHRpb24g4oCUIHNhbWUgcGF0dGVybiBhc1xuICAvLyBVc2VyUHJvbXB0TWVzc2FnZS50c3guXG4gIGNvbnN0IGlzQnJpZWZPbmx5ID1cbiAgICBmZWF0dXJlKCdLQUlST1MnKSB8fCBmZWF0dXJlKCdLQUlST1NfQlJJRUYnKVxuICAgICAgPyAvLyBiaW9tZS1pZ25vcmUgbGludC9jb3JyZWN0bmVzcy91c2VIb29rQXRUb3BMZXZlbDogZmVhdHVyZSgpIGlzIGEgY29tcGlsZS10aW1lIGNvbnN0YW50XG4gICAgICAgIHVzZUFwcFN0YXRlKHMgPT4gcy5pc0JyaWVmT25seSlcbiAgICAgIDogZmFsc2VcblxuICAvLyBDYXB0dXJlIGNsYXNzaWZpZXIgYXBwcm92YWwgb25jZSBvbiBtb3VudCwgdGhlbiBkZWxldGUgZnJvbSBNYXAgdG8gcHJldmVudCBsaW5lYXIgZ3Jvd3RoLlxuICAvLyB1c2VTdGF0ZSBsYXp5IGluaXRpYWxpemVyIGVuc3VyZXMgdGhlIHZhbHVlIHBlcnNpc3RzIGFjcm9zcyByZS1yZW5kZXJzLlxuICBjb25zdCBbY2xhc3NpZmllclJ1bGVdID0gUmVhY3QudXNlU3RhdGUoKCkgPT5cbiAgICBnZXRDbGFzc2lmaWVyQXBwcm92YWwodG9vbFVzZUlEKSxcbiAgKVxuICBjb25zdCBbeW9sb1JlYXNvbl0gPSBSZWFjdC51c2VTdGF0ZSgoKSA9PlxuICAgIGdldFlvbG9DbGFzc2lmaWVyQXBwcm92YWwodG9vbFVzZUlEKSxcbiAgKVxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGRlbGV0ZUNsYXNzaWZpZXJBcHByb3ZhbCh0b29sVXNlSUQpXG4gIH0sIFt0b29sVXNlSURdKVxuXG4gIGlmICghbWVzc2FnZS50b29sVXNlUmVzdWx0IHx8ICF0b29sKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vIFJlc3VtZWQgdHJhbnNjcmlwdHMgZGVzZXJpYWxpemUgdG9vbFVzZVJlc3VsdCB2aWEgcmF3IEpTT04ucGFyc2Ugd2l0aCBub1xuICAvLyB2YWxpZGF0aW9uIChwYXJzZUpTT05MKS4gQSBwYXJ0aWFsL2NvcnJ1cHQvb2xkLWZvcm1hdCByZXN1bHQgY3Jhc2hlc1xuICAvLyByZW5kZXJUb29sUmVzdWx0TWVzc2FnZSBvbiBmaXJzdCBmaWVsZCBhY2Nlc3MgKGFudGhyb3BpY3MvY2xhdWRlLWNvZGUjMzk4MTcpLlxuICAvLyBWYWxpZGF0ZSBhZ2FpbnN0IG91dHB1dFNjaGVtYSBiZWZvcmUgcmVuZGVyaW5nIOKAlCBtaXJyb3JzIENvbGxhcHNlZFJlYWRTZWFyY2hDb250ZW50LlxuICBjb25zdCBwYXJzZWRPdXRwdXQgPSB0b29sLm91dHB1dFNjaGVtYT8uc2FmZVBhcnNlKG1lc3NhZ2UudG9vbFVzZVJlc3VsdClcbiAgaWYgKHBhcnNlZE91dHB1dCAmJiAhcGFyc2VkT3V0cHV0LnN1Y2Nlc3MpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGNvbnN0IHRvb2xSZXN1bHQgPSBwYXJzZWRPdXRwdXQ/LmRhdGEgPz8gbWVzc2FnZS50b29sVXNlUmVzdWx0XG5cbiAgY29uc3QgcmVuZGVyZWRNZXNzYWdlID1cbiAgICB0b29sLnJlbmRlclRvb2xSZXN1bHRNZXNzYWdlPy4oXG4gICAgICB0b29sUmVzdWx0IGFzIG5ldmVyLFxuICAgICAgZmlsdGVyVG9vbFByb2dyZXNzTWVzc2FnZXMocHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UpLFxuICAgICAge1xuICAgICAgICBzdHlsZSxcbiAgICAgICAgdGhlbWUsXG4gICAgICAgIHRvb2xzLFxuICAgICAgICB2ZXJib3NlLFxuICAgICAgICBpc1RyYW5zY3JpcHRNb2RlLFxuICAgICAgICBpc0JyaWVmT25seSxcbiAgICAgICAgaW5wdXQ6IGxvb2t1cHMudG9vbFVzZUJ5VG9vbFVzZUlELmdldCh0b29sVXNlSUQpPy5pbnB1dCxcbiAgICAgIH0sXG4gICAgKSA/PyBudWxsXG5cbiAgLy8gRG9uJ3QgcmVuZGVyIGFueXRoaW5nIGlmIHRoZSB0b29sIHJlc3VsdCBtZXNzYWdlIGlzIG51bGxcbiAgaWYgKHJlbmRlcmVkTWVzc2FnZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvLyBUb29scyB0aGF0IHJldHVybiAnJyBmcm9tIHVzZXJGYWNpbmdOYW1lIG9wdCBvdXQgb2YgdG9vbCBjaHJvbWUgYW5kXG4gIC8vIHJlbmRlciBsaWtlIHBsYWluIGFzc2lzdGFudCB0ZXh0LiBTa2lwIHRoZSB0b29sLXJlc3VsdCB3aWR0aCBjb25zdHJhaW50XG4gIC8vIHNvIE1hcmtkb3duVGFibGUncyBTQUZFVFlfTUFSR0lOPTQgKHR1bmVkIGZvciB0aGUgYXNzaXN0YW50LXRleHQgMi1jb2xcbiAgLy8gZG90IGd1dHRlcikgaG9sZHMg4oCUIG90aGVyd2lzZSB0YWJsZXMgd3JhcCB0aGVpciBib3gtZHJhd2luZyBjaGFycy5cbiAgY29uc3QgcmVuZGVyc0FzQXNzaXN0YW50VGV4dCA9IHRvb2wudXNlckZhY2luZ05hbWUodW5kZWZpbmVkKSA9PT0gJydcblxuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgPEJveFxuICAgICAgICBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCJcbiAgICAgICAgd2lkdGg9e3JlbmRlcnNBc0Fzc2lzdGFudFRleHQgPyB1bmRlZmluZWQgOiB3aWR0aH1cbiAgICAgID5cbiAgICAgICAge3JlbmRlcmVkTWVzc2FnZX1cbiAgICAgICAge2ZlYXR1cmUoJ0JBU0hfQ0xBU1NJRklFUicpXG4gICAgICAgICAgPyBjbGFzc2lmaWVyUnVsZSAmJiAoXG4gICAgICAgICAgICAgIDxNZXNzYWdlUmVzcG9uc2UgaGVpZ2h0PXsxfT5cbiAgICAgICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwic3VjY2Vzc1wiPntmaWd1cmVzLnRpY2t9PC9UZXh0PlxuICAgICAgICAgICAgICAgICAgeycgQXV0by1hcHByb3ZlZCBcXHUwMGI3IG1hdGNoZWQgJ31cbiAgICAgICAgICAgICAgICAgIHtgXCIke2NsYXNzaWZpZXJSdWxlfVwiYH1cbiAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogbnVsbH1cbiAgICAgICAge2ZlYXR1cmUoJ1RSQU5TQ1JJUFRfQ0xBU1NJRklFUicpXG4gICAgICAgICAgPyB5b2xvUmVhc29uICYmIChcbiAgICAgICAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPkFsbG93ZWQgYnkgYXV0byBtb2RlIGNsYXNzaWZpZXI8L1RleHQ+XG4gICAgICAgICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogbnVsbH1cbiAgICAgIDwvQm94PlxuICAgICAgPFNlbnRyeUVycm9yQm91bmRhcnk+XG4gICAgICAgIDxIb29rUHJvZ3Jlc3NNZXNzYWdlXG4gICAgICAgICAgaG9va0V2ZW50PVwiUG9zdFRvb2xVc2VcIlxuICAgICAgICAgIGxvb2t1cHM9e2xvb2t1cHN9XG4gICAgICAgICAgdG9vbFVzZUlEPXt0b29sVXNlSUR9XG4gICAgICAgICAgdmVyYm9zZT17dmVyYm9zZX1cbiAgICAgICAgICBpc1RyYW5zY3JpcHRNb2RlPXtpc1RyYW5zY3JpcHRNb2RlfVxuICAgICAgICAvPlxuICAgICAgPC9TZW50cnlFcnJvckJvdW5kYXJ5PlxuICAgIDwvQm94PlxuICApXG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLE9BQU8sUUFBUSxZQUFZO0FBQ3BDLE9BQU9DLE9BQU8sTUFBTSxTQUFTO0FBQzdCLE9BQU8sS0FBS0MsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsbUJBQW1CLFFBQVEsdUNBQXVDO0FBQzNFLFNBQVNDLEdBQUcsRUFBRUMsSUFBSSxFQUFFQyxRQUFRLFFBQVEsaUJBQWlCO0FBQ3JELFNBQVNDLFdBQVcsUUFBUSw0QkFBNEI7QUFDeEQsU0FDRUMsMEJBQTBCLEVBQzFCLEtBQUtDLElBQUksRUFDVCxLQUFLQyxLQUFLLFFBQ0wsa0JBQWtCO0FBQ3pCLGNBQ0VDLHFCQUFxQixFQUNyQkMsZUFBZSxRQUNWLDJCQUEyQjtBQUNsQyxTQUNFQyx3QkFBd0IsRUFDeEJDLHFCQUFxQixFQUNyQkMseUJBQXlCLFFBQ3BCLHVDQUF1QztBQUM5QyxjQUFjQyxtQkFBbUIsUUFBUSw0QkFBNEI7QUFDckUsU0FBU0MsZUFBZSxRQUFRLDBCQUEwQjtBQUMxRCxTQUFTQyxtQkFBbUIsUUFBUSwyQkFBMkI7QUFFL0QsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLE9BQU8sRUFBRVQscUJBQXFCO0VBQzlCVSxPQUFPLEVBQUVDLFVBQVUsQ0FBQyxPQUFPTixt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