mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 17:46:58 +10:00
201 lines
21 KiB
TypeScript
201 lines
21 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
|||
|
|
import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
|
|||
|
|
import React from 'react';
|
|||
|
|
import { CtrlOToExpand } from '../../components/CtrlOToExpand.js';
|
|||
|
|
import { FallbackToolUseErrorMessage } from '../../components/FallbackToolUseErrorMessage.js';
|
|||
|
|
import { MessageResponse } from '../../components/MessageResponse.js';
|
|||
|
|
import { TOOL_SUMMARY_MAX_LENGTH } from '../../constants/toolLimits.js';
|
|||
|
|
import { Box, Text } from '../../ink.js';
|
|||
|
|
import type { ToolProgressData } from '../../Tool.js';
|
|||
|
|
import type { ProgressMessage } from '../../types/message.js';
|
|||
|
|
import { FILE_NOT_FOUND_CWD_NOTE, getDisplayPath } from '../../utils/file.js';
|
|||
|
|
import { truncate } from '../../utils/format.js';
|
|||
|
|
import { extractTag } from '../../utils/messages.js';
|
|||
|
|
|
|||
|
|
// Reusable component for search result summaries
|
|||
|
|
function SearchResultSummary(t0) {
|
|||
|
|
const $ = _c(26);
|
|||
|
|
const {
|
|||
|
|
count,
|
|||
|
|
countLabel,
|
|||
|
|
secondaryCount,
|
|||
|
|
secondaryLabel,
|
|||
|
|
content,
|
|||
|
|
verbose
|
|||
|
|
} = t0;
|
|||
|
|
let t1;
|
|||
|
|
if ($[0] !== count) {
|
|||
|
|
t1 = <Text bold={true}>{count} </Text>;
|
|||
|
|
$[0] = count;
|
|||
|
|
$[1] = t1;
|
|||
|
|
} else {
|
|||
|
|
t1 = $[1];
|
|||
|
|
}
|
|||
|
|
let t2;
|
|||
|
|
if ($[2] !== count || $[3] !== countLabel) {
|
|||
|
|
t2 = count === 0 || count > 1 ? countLabel : countLabel.slice(0, -1);
|
|||
|
|
$[2] = count;
|
|||
|
|
$[3] = countLabel;
|
|||
|
|
$[4] = t2;
|
|||
|
|
} else {
|
|||
|
|
t2 = $[4];
|
|||
|
|
}
|
|||
|
|
let t3;
|
|||
|
|
if ($[5] !== t1 || $[6] !== t2) {
|
|||
|
|
t3 = <Text>Found {t1}{t2}</Text>;
|
|||
|
|
$[5] = t1;
|
|||
|
|
$[6] = t2;
|
|||
|
|
$[7] = t3;
|
|||
|
|
} else {
|
|||
|
|
t3 = $[7];
|
|||
|
|
}
|
|||
|
|
const primaryText = t3;
|
|||
|
|
let t4;
|
|||
|
|
if ($[8] !== secondaryCount || $[9] !== secondaryLabel) {
|
|||
|
|
t4 = secondaryCount !== undefined && secondaryLabel ? <Text>{" "}across <Text bold={true}>{secondaryCount} </Text>{secondaryCount === 0 || secondaryCount > 1 ? secondaryLabel : secondaryLabel.slice(0, -1)}</Text> : null;
|
|||
|
|
$[8] = secondaryCount;
|
|||
|
|
$[9] = secondaryLabel;
|
|||
|
|
$[10] = t4;
|
|||
|
|
} else {
|
|||
|
|
t4 = $[10];
|
|||
|
|
}
|
|||
|
|
const secondaryText = t4;
|
|||
|
|
if (verbose) {
|
|||
|
|
let t5;
|
|||
|
|
if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
|
|||
|
|
t5 = <Text dimColor={true}> ⎿ </Text>;
|
|||
|
|
$[11] = t5;
|
|||
|
|
} else {
|
|||
|
|
t5 = $[11];
|
|||
|
|
}
|
|||
|
|
let t6;
|
|||
|
|
if ($[12] !== primaryText || $[13] !== secondaryText) {
|
|||
|
|
t6 = <Box flexDirection="row"><Text>{t5}{primaryText}{secondaryText}</Text></Box>;
|
|||
|
|
$[12] = primaryText;
|
|||
|
|
$[13] = secondaryText;
|
|||
|
|
$[14] = t6;
|
|||
|
|
} else {
|
|||
|
|
t6 = $[14];
|
|||
|
|
}
|
|||
|
|
let t7;
|
|||
|
|
if ($[15] !== content) {
|
|||
|
|
t7 = <Box marginLeft={5}><Text>{content}</Text></Box>;
|
|||
|
|
$[15] = content;
|
|||
|
|
$[16] = t7;
|
|||
|
|
} else {
|
|||
|
|
t7 = $[16];
|
|||
|
|
}
|
|||
|
|
let t8;
|
|||
|
|
if ($[17] !== t6 || $[18] !== t7) {
|
|||
|
|
t8 = <Box flexDirection="column">{t6}{t7}</Box>;
|
|||
|
|
$[17] = t6;
|
|||
|
|
$[18] = t7;
|
|||
|
|
$[19] = t8;
|
|||
|
|
} else {
|
|||
|
|
t8 = $[19];
|
|||
|
|
}
|
|||
|
|
return t8;
|
|||
|
|
}
|
|||
|
|
let t5;
|
|||
|
|
if ($[20] !== count) {
|
|||
|
|
t5 = count > 0 && <CtrlOToExpand />;
|
|||
|
|
$[20] = count;
|
|||
|
|
$[21] = t5;
|
|||
|
|
} else {
|
|||
|
|
t5 = $[21];
|
|||
|
|
}
|
|||
|
|
let t6;
|
|||
|
|
if ($[22] !== primaryText || $[23] !== secondaryText || $[24] !== t5) {
|
|||
|
|
t6 = <MessageResponse height={1}><Text>{primaryText}{secondaryText} {t5}</Text></MessageResponse>;
|
|||
|
|
$[22] = primaryText;
|
|||
|
|
$[23] = secondaryText;
|
|||
|
|
$[24] = t5;
|
|||
|
|
$[25] = t6;
|
|||
|
|
} else {
|
|||
|
|
t6 = $[25];
|
|||
|
|
}
|
|||
|
|
return t6;
|
|||
|
|
}
|
|||
|
|
type Output = {
|
|||
|
|
mode?: 'content' | 'files_with_matches' | 'count';
|
|||
|
|
numFiles: number;
|
|||
|
|
filenames: string[];
|
|||
|
|
content?: string;
|
|||
|
|
numLines?: number; // For content mode
|
|||
|
|
numMatches?: number; // For count mode
|
|||
|
|
};
|
|||
|
|
export function renderToolUseMessage({
|
|||
|
|
pattern,
|
|||
|
|
path
|
|||
|
|
}: Partial<{
|
|||
|
|
pattern: string;
|
|||
|
|
path?: string;
|
|||
|
|
}>, {
|
|||
|
|
verbose
|
|||
|
|
}: {
|
|||
|
|
verbose: boolean;
|
|||
|
|
}): React.ReactNode {
|
|||
|
|
if (!pattern) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
const parts = [`pattern: "${pattern}"`];
|
|||
|
|
if (path) {
|
|||
|
|
parts.push(`path: "${verbose ? path : getDisplayPath(path)}"`);
|
|||
|
|
}
|
|||
|
|
return parts.join(', ');
|
|||
|
|
}
|
|||
|
|
export function renderToolUseErrorMessage(result: ToolResultBlockParam['content'], {
|
|||
|
|
verbose
|
|||
|
|
}: {
|
|||
|
|
verbose: boolean;
|
|||
|
|
}): React.ReactNode {
|
|||
|
|
if (!verbose && typeof result === 'string' && extractTag(result, 'tool_use_error')) {
|
|||
|
|
const errorMessage = extractTag(result, 'tool_use_error');
|
|||
|
|
if (errorMessage?.includes(FILE_NOT_FOUND_CWD_NOTE)) {
|
|||
|
|
return <MessageResponse>
|
|||
|
|
<Text color="error">File not found</Text>
|
|||
|
|
</MessageResponse>;
|
|||
|
|
}
|
|||
|
|
return <MessageResponse>
|
|||
|
|
<Text color="error">Error searching files</Text>
|
|||
|
|
</MessageResponse>;
|
|||
|
|
}
|
|||
|
|
return <FallbackToolUseErrorMessage result={result} verbose={verbose} />;
|
|||
|
|
}
|
|||
|
|
export function renderToolResultMessage({
|
|||
|
|
mode = 'files_with_matches',
|
|||
|
|
filenames,
|
|||
|
|
numFiles,
|
|||
|
|
content,
|
|||
|
|
numLines,
|
|||
|
|
numMatches
|
|||
|
|
}: Output, _progressMessagesForMessage: ProgressMessage<ToolProgressData>[], {
|
|||
|
|
verbose
|
|||
|
|
}: {
|
|||
|
|
verbose: boolean;
|
|||
|
|
}): React.ReactNode {
|
|||
|
|
if (mode === 'content') {
|
|||
|
|
return <SearchResultSummary count={numLines ?? 0} countLabel="lines" content={content} verbose={verbose} />;
|
|||
|
|
}
|
|||
|
|
if (mode === 'count') {
|
|||
|
|
return <SearchResultSummary count={numMatches ?? 0} countLabel="matches" secondaryCount={numFiles} secondaryLabel="files" content={content} verbose={verbose} />;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// files_with_matches mode
|
|||
|
|
const fileListContent = filenames.map(filename => filename).join('\n');
|
|||
|
|
return <SearchResultSummary count={numFiles} countLabel="files" content={fileListContent} verbose={verbose} />;
|
|||
|
|
}
|
|||
|
|
export function getToolUseSummary(input: Partial<{
|
|||
|
|
pattern: string;
|
|||
|
|
path?: string;
|
|||
|
|
glob?: string;
|
|||
|
|
type?: string;
|
|||
|
|
output_mode?: 'content' | 'files_with_matches' | 'count';
|
|||
|
|
head_limit?: number;
|
|||
|
|
}> | undefined): string | null {
|
|||
|
|
if (!input?.pattern) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
return truncate(input.pattern, TOOL_SUMMARY_MAX_LENGTH);
|
|||
|
|
}
|
|||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJUb29sUmVzdWx0QmxvY2tQYXJhbSIsIlJlYWN0IiwiQ3RybE9Ub0V4cGFuZCIsIkZhbGxiYWNrVG9vbFVzZUVycm9yTWVzc2FnZSIsIk1lc3NhZ2VSZXNwb25zZSIsIlRPT0xfU1VNTUFSWV9NQVhfTEVOR1RIIiwiQm94IiwiVGV4dCIsIlRvb2xQcm9ncmVzc0RhdGEiLCJQcm9ncmVzc01lc3NhZ2UiLCJGSUxFX05PVF9GT1VORF9DV0RfTk9URSIsImdldERpc3BsYXlQYXRoIiwidHJ1bmNhdGUiLCJleHRyYWN0VGFnIiwiU2VhcmNoUmVzdWx0U3VtbWFyeSIsInQwIiwiJCIsIl9jIiwiY291bnQiLCJjb3VudExhYmVsIiwic2Vjb25kYXJ5Q291bnQiLCJzZWNvbmRhcnlMYWJlbCIsImNvbnRlbnQiLCJ2ZXJib3NlIiwidDEiLCJ0MiIsInNsaWNlIiwidDMiLCJwcmltYXJ5VGV4dCIsInQ0IiwidW5kZWZpbmVkIiwic2Vjb25kYXJ5VGV4dCIsInQ1IiwiU3ltYm9sIiwiZm9yIiwidDYiLCJ0NyIsInQ4IiwiT3V0cHV0IiwibW9kZSIsIm51bUZpbGVzIiwiZmlsZW5hbWVzIiwibnVtTGluZXMiLCJudW1NYXRjaGVzIiwicmVuZGVyVG9vbFVzZU1lc3NhZ2UiLCJwYXR0ZXJuIiwicGF0aCIsIlBhcnRpYWwiLCJSZWFjdE5vZGUiLCJwYXJ0cyIsInB1c2giLCJqb2luIiwicmVuZGVyVG9vbFVzZUVycm9yTWVzc2FnZSIsInJlc3VsdCIsImVycm9yTWVzc2FnZSIsImluY2x1ZGVzIiwicmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2UiLCJfcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJmaWxlTGlzdENvbnRlbnQiLCJtYXAiLCJmaWxlbmFtZSIsImdldFRvb2xVc2VTdW1tYXJ5IiwiaW5wdXQiLCJnbG9iIiwidHlwZSIsIm91dHB1dF9tb2RlIiwiaGVhZF9saW1pdCJdLCJzb3VyY2VzIjpbIlVJLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFRvb2xSZXN1bHRCbG9ja1BhcmFtIH0gZnJvbSAnQGFudGhyb3BpYy1haS9zZGsvcmVzb3VyY2VzL2luZGV4Lm1qcydcbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IEN0cmxPVG9FeHBhbmQgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL0N0cmxPVG9FeHBhbmQuanMnXG5pbXBvcnQgeyBGYWxsYmFja1Rvb2xVc2VFcnJvck1lc3NhZ2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL0ZhbGxiYWNrVG9vbFVzZUVycm9yTWVzc2FnZS5qcydcbmltcG9ydCB7IE1lc3NhZ2VSZXNwb25zZSB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvTWVzc2FnZVJlc3BvbnNlLmpzJ1xuaW1wb3J0IHsgVE9PTF9TVU1NQVJZX01BWF9MRU5HVEggfSBmcm9tICcuLi8uLi9jb25zdGFudHMvdG9vbExpbWl0cy5qcydcbmltcG9ydCB7IEJveCwgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB0eXBlIHsgVG9vbFByb2dyZXNzRGF0YSB9IGZyb20gJy4uLy4uL1Rvb2wuanMnXG5pbXBvcnQgdHlwZSB7IFByb2dyZXNzTWVzc2FnZSB9IGZyb20gJy4uLy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgeyBGSUxFX05PVF9GT1VORF9DV0RfTk9URSwgZ2V0RGlzcGxheVBhdGggfSBmcm9tICcuLi8uLi91dGlscy9maWxlLmpzJ1xuaW1wb3J0IHsgdHJ1bmNhdGUgfSBmcm9tICcuLi8uLi91dGlscy9mb3JtYXQuanMnXG5pbXBvcnQgeyBleHRyYWN0VGFnIH0gZnJvbSAnLi4vLi4vdXRpbHMvbWVzc2FnZXMuanMnXG5cbi8vIFJldXNhYmxlIGNvbXBvbmVudCBmb3Igc2VhcmNoIHJlc3VsdCBzdW1tYXJpZXNcbmZ1bmN0aW9uIFNlYXJjaFJlc3VsdFN1bW1hcnkoe1xuICBjb3VudCxcbiAgY291bnRMYWJlbCxcbiAgc2Vjb25kYXJ5Q291bnQsXG4gIHNlY29uZGFyeUxhYmVsLFxuICBjb250ZW50LFxuICB2ZXJib3NlLFxufToge1xuICBjb3VudDogbnVtYmVyXG4gIGNvdW50TGFiZWw6IHN0cmluZ1xuICBzZWNvbmRhcnlDb3VudD86IG51bWJlclxuICBzZWNvbmRhcnlMYWJlbD86IHN0cmluZ1xuICBjb250ZW50Pzogc3RyaW5nXG4gIHZlcmJvc2U6IGJvb2xlYW5cbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBwcmltYXJ5VGV4dCA9IChcbiAgICA8VGV4dD5cbiAgICAgIEZvdW5kIDxUZXh0IGJvbGQ+e2NvdW50fSA8L1RleHQ+XG4gICAgICB7Y291bnQgPT09IDAgfHwgY291bnQgPiAxID8gY291bnRMYWJlbCA6IGNvdW50TGFiZWwuc2xpY2UoMCwgLTEpfVxuICAgIDwvVGV4dD5cbiAgKVxuXG4gIGNvbnN0IHNlY29uZGFyeVRleHQgPVxuICAgIHNlY29uZGFyeUNvdW50ICE9PSB1bmRlZmluZWQgJiYgc2Vjb25kYXJ5TGFiZWwgPyAoXG4gICAgICA8VGV4dD5cbiAgICAgICAgeycgJ31cbiAgICAgICAgYWNyb3NzIDxUZXh0IGJvbGQ+e3NlY29uZGFyeUNvdW50fSA8L1RleHQ+XG4gICAgICAgIHtzZWNvbmRhcnlDb3VudCA9PT0gMCB8fCBzZWNvbmRhcnlDb3VudCA+IDFcbiAgICAgICAgICA/IHNlY29uZGFyeUxhYmVsXG4gICAgICAgICAgOiBzZWNvbmRhcnlMYWJlbC5zbGljZSgwLCAtMSl9XG4gICAgICA8L1RleHQ+XG4gICAgKSA6IG51bGxcblxuICBpZiAodmVyYm9zZSkge1xuICAgIHJldHVybiAoXG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwicm93XCI+XG4gICAgICAgICAgPFRleHQ+XG4gICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj4mbmJzcDsmbmJzcDvijr8gJm5ic3A7PC9UZXh0PlxuICAgICAgICAgICAge3ByaW1hcnlUZXh0fVxuICAgICAgICAgICAge3NlY29uZGFyeVRleHR9XG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICAgPEJveCBtYXJnaW5MZWZ0PXs1fT5cbiAgICAgICAgICA8VGV4dD57Y29udGVudH08L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgPC9Cb3g+XG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIChcbiAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICA8VGV4dD5cbiAgICAgICAge3ByaW1hcnlUZXh0fVxuICAgICAgICB7c2Vjb25kYXJ5VGV4dH0ge2NvdW50ID4gMCAmJiA8Q3RybE9Ub0V4cGFuZCAvPn1cbiAgICAgIDwvVGV4dD5cbiAgICA8L01lc3NhZ2VSZXNwb25
|