mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 08:45:50 +00:00
style: 完成所有文件的lint
This commit is contained in:
@@ -1,60 +1,51 @@
|
||||
import { relative } from 'path'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useDiffInIDE } from '../../../hooks/useDiffInIDE.js'
|
||||
import { Box, Text } from '@anthropic/ink'
|
||||
import type { ToolUseContext } from '../../../Tool.js'
|
||||
import { getLanguageName } from '../../../utils/cliHighlight.js'
|
||||
import { getCwd } from '../../../utils/cwd.js'
|
||||
import {
|
||||
getFsImplementation,
|
||||
safeResolvePath,
|
||||
} from '../../../utils/fsOperations.js'
|
||||
import { expandPath } from '../../../utils/path.js'
|
||||
import type { CompletionType } from '../../../utils/unaryLogging.js'
|
||||
import { Select } from '../../CustomSelect/index.js'
|
||||
import { ShowInIDEPrompt } from '../../ShowInIDEPrompt.js'
|
||||
import { usePermissionRequestLogging } from '../hooks.js'
|
||||
import { PermissionDialog } from '../PermissionDialog.js'
|
||||
import type { ToolUseConfirm } from '../PermissionRequest.js'
|
||||
import type { WorkerBadgeProps } from '../WorkerBadge.js'
|
||||
import type { IDEDiffSupport } from './ideDiffConfig.js'
|
||||
import type {
|
||||
FileOperationType,
|
||||
PermissionOption,
|
||||
} from './permissionOptions.js'
|
||||
import {
|
||||
type ToolInput,
|
||||
useFilePermissionDialog,
|
||||
} from './useFilePermissionDialog.js'
|
||||
import { relative } from 'path';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useDiffInIDE } from '../../../hooks/useDiffInIDE.js';
|
||||
import { Box, Text } from '@anthropic/ink';
|
||||
import type { ToolUseContext } from '../../../Tool.js';
|
||||
import { getLanguageName } from '../../../utils/cliHighlight.js';
|
||||
import { getCwd } from '../../../utils/cwd.js';
|
||||
import { getFsImplementation, safeResolvePath } from '../../../utils/fsOperations.js';
|
||||
import { expandPath } from '../../../utils/path.js';
|
||||
import type { CompletionType } from '../../../utils/unaryLogging.js';
|
||||
import { Select } from '../../CustomSelect/index.js';
|
||||
import { ShowInIDEPrompt } from '../../ShowInIDEPrompt.js';
|
||||
import { usePermissionRequestLogging } from '../hooks.js';
|
||||
import { PermissionDialog } from '../PermissionDialog.js';
|
||||
import type { ToolUseConfirm } from '../PermissionRequest.js';
|
||||
import type { WorkerBadgeProps } from '../WorkerBadge.js';
|
||||
import type { IDEDiffSupport } from './ideDiffConfig.js';
|
||||
import type { FileOperationType, PermissionOption } from './permissionOptions.js';
|
||||
import { type ToolInput, useFilePermissionDialog } from './useFilePermissionDialog.js';
|
||||
|
||||
export type FilePermissionDialogProps<T extends ToolInput = ToolInput> = {
|
||||
// Required props from PermissionRequestProps
|
||||
toolUseConfirm: ToolUseConfirm
|
||||
toolUseContext: ToolUseContext
|
||||
onDone: () => void
|
||||
onReject: () => void
|
||||
toolUseConfirm: ToolUseConfirm;
|
||||
toolUseContext: ToolUseContext;
|
||||
onDone: () => void;
|
||||
onReject: () => void;
|
||||
|
||||
// Dialog customization
|
||||
title: string
|
||||
subtitle?: React.ReactNode
|
||||
question?: string | React.ReactNode
|
||||
content?: React.ReactNode // Can be general content or diff component
|
||||
title: string;
|
||||
subtitle?: React.ReactNode;
|
||||
question?: string | React.ReactNode;
|
||||
content?: React.ReactNode; // Can be general content or diff component
|
||||
|
||||
// Logging
|
||||
completionType?: CompletionType
|
||||
languageName?: string // override — derived from path when omitted
|
||||
completionType?: CompletionType;
|
||||
languageName?: string; // override — derived from path when omitted
|
||||
|
||||
// File/directory operations
|
||||
path: string | null
|
||||
parseInput: (input: unknown) => T
|
||||
operationType?: FileOperationType
|
||||
path: string | null;
|
||||
parseInput: (input: unknown) => T;
|
||||
operationType?: FileOperationType;
|
||||
|
||||
// IDE diff support
|
||||
ideDiffSupport?: IDEDiffSupport<T>
|
||||
ideDiffSupport?: IDEDiffSupport<T>;
|
||||
|
||||
// Worker badge for teammate permission requests
|
||||
workerBadge: WorkerBadgeProps | undefined
|
||||
}
|
||||
workerBadge: WorkerBadgeProps | undefined;
|
||||
};
|
||||
|
||||
export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
toolUseConfirm,
|
||||
@@ -80,28 +71,28 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
const languageName = useMemo(
|
||||
() => languageNameOverride ?? (path ? getLanguageName(path) : 'none'),
|
||||
[languageNameOverride, path],
|
||||
)
|
||||
);
|
||||
const unaryEvent = useMemo(
|
||||
() => ({
|
||||
completion_type: completionType,
|
||||
language_name: languageName,
|
||||
}),
|
||||
[completionType, languageName],
|
||||
)
|
||||
usePermissionRequestLogging(toolUseConfirm, unaryEvent)
|
||||
);
|
||||
usePermissionRequestLogging(toolUseConfirm, unaryEvent);
|
||||
|
||||
const symlinkTarget = useMemo(() => {
|
||||
if (!path || operationType === 'read') {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
const expandedPath = expandPath(path)
|
||||
const fs = getFsImplementation()
|
||||
const { resolvedPath, isSymlink } = safeResolvePath(fs, expandedPath)
|
||||
const expandedPath = expandPath(path);
|
||||
const fs = getFsImplementation();
|
||||
const { resolvedPath, isSymlink } = safeResolvePath(fs, expandedPath);
|
||||
if (isSymlink) {
|
||||
return resolvedPath
|
||||
return resolvedPath;
|
||||
}
|
||||
return null
|
||||
}, [path, operationType])
|
||||
return null;
|
||||
}, [path, operationType]);
|
||||
|
||||
const fileDialogResult = useFilePermissionDialog({
|
||||
filePath: path || '',
|
||||
@@ -112,7 +103,7 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
onReject,
|
||||
parseInput,
|
||||
operationType,
|
||||
})
|
||||
});
|
||||
|
||||
// Use file dialog results for options
|
||||
const {
|
||||
@@ -124,22 +115,19 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
focusedOption,
|
||||
yesInputMode,
|
||||
noInputMode,
|
||||
} = fileDialogResult
|
||||
} = fileDialogResult;
|
||||
|
||||
// Parse input using the provided parser
|
||||
const parsedInput = parseInput(toolUseConfirm.input)
|
||||
const parsedInput = parseInput(toolUseConfirm.input);
|
||||
|
||||
// Set up IDE diff support if enabled. Memoized: getConfig may do disk I/O
|
||||
// (FileWrite's getConfig calls readFileSync for the old-content diff).
|
||||
// Keyed on the raw input — parseInput is a pure Zod parse whose result
|
||||
// depends only on toolUseConfirm.input.
|
||||
const ideDiffConfig = useMemo(
|
||||
() =>
|
||||
ideDiffSupport
|
||||
? ideDiffSupport.getConfig(parseInput(toolUseConfirm.input))
|
||||
: null,
|
||||
() => (ideDiffSupport ? ideDiffSupport.getConfig(parseInput(toolUseConfirm.input)) : null),
|
||||
[ideDiffSupport, toolUseConfirm.input],
|
||||
)
|
||||
);
|
||||
|
||||
// Create diff params based on whether IDE diff is available
|
||||
const diffParams = ideDiffConfig
|
||||
@@ -147,19 +135,16 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
onChange: (
|
||||
option: PermissionOption,
|
||||
input: {
|
||||
file_path: string
|
||||
file_path: string;
|
||||
edits: Array<{
|
||||
old_string: string
|
||||
new_string: string
|
||||
replace_all?: boolean
|
||||
}>
|
||||
old_string: string;
|
||||
new_string: string;
|
||||
replace_all?: boolean;
|
||||
}>;
|
||||
},
|
||||
) => {
|
||||
const transformedInput = ideDiffSupport!.applyChanges(
|
||||
parsedInput,
|
||||
input.edits,
|
||||
)
|
||||
fileDialogResult.onChange(option, transformedInput)
|
||||
const transformedInput = ideDiffSupport!.applyChanges(parsedInput, input.edits);
|
||||
fileDialogResult.onChange(option, transformedInput);
|
||||
},
|
||||
toolUseContext,
|
||||
filePath: ideDiffConfig.filePath,
|
||||
@@ -176,21 +161,19 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
filePath: '',
|
||||
edits: [],
|
||||
editMode: 'single' as const,
|
||||
}
|
||||
};
|
||||
|
||||
const { closeTabInIDE, showingDiffInIDE, ideName } = useDiffInIDE(diffParams)
|
||||
const { closeTabInIDE, showingDiffInIDE, ideName } = useDiffInIDE(diffParams);
|
||||
|
||||
const onChange = (option: PermissionOption, feedback?: string) => {
|
||||
closeTabInIDE?.()
|
||||
fileDialogResult.onChange(option, parsedInput, feedback?.trim())
|
||||
}
|
||||
closeTabInIDE?.();
|
||||
fileDialogResult.onChange(option, parsedInput, feedback?.trim());
|
||||
};
|
||||
|
||||
if (showingDiffInIDE && ideDiffConfig && path) {
|
||||
return (
|
||||
<ShowInIDEPrompt
|
||||
onChange={(option: PermissionOption, _input, feedback?: string) =>
|
||||
onChange(option, feedback)
|
||||
}
|
||||
onChange={(option: PermissionOption, _input, feedback?: string) => onChange(option, feedback)}
|
||||
options={options}
|
||||
filePath={path}
|
||||
input={parsedInput}
|
||||
@@ -204,11 +187,10 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
yesInputMode={yesInputMode}
|
||||
noInputMode={noInputMode}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const isSymlinkOutsideCwd =
|
||||
symlinkTarget != null && relative(getCwd(), symlinkTarget).startsWith('..')
|
||||
const isSymlinkOutsideCwd = symlinkTarget != null && relative(getCwd(), symlinkTarget).startsWith('..');
|
||||
|
||||
const symlinkWarning = symlinkTarget ? (
|
||||
<Box paddingX={1} marginBottom={1}>
|
||||
@@ -218,16 +200,11 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
: `Symlink target: ${symlinkTarget}`}
|
||||
</Text>
|
||||
</Box>
|
||||
) : null
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PermissionDialog
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
innerPaddingX={0}
|
||||
workerBadge={workerBadge}
|
||||
>
|
||||
<PermissionDialog title={title} subtitle={subtitle} innerPaddingX={0} workerBadge={workerBadge}>
|
||||
{symlinkWarning}
|
||||
{content}
|
||||
<Box flexDirection="column" paddingX={1}>
|
||||
@@ -236,21 +213,21 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
options={options}
|
||||
inlineDescriptions
|
||||
onChange={value => {
|
||||
const selected = options.find(opt => opt.value === value)
|
||||
const selected = options.find(opt => opt.value === value);
|
||||
if (selected) {
|
||||
// For reject option
|
||||
if (selected.option.type === 'reject') {
|
||||
const trimmedFeedback = rejectFeedback.trim()
|
||||
onChange(selected.option, trimmedFeedback || undefined)
|
||||
return
|
||||
const trimmedFeedback = rejectFeedback.trim();
|
||||
onChange(selected.option, trimmedFeedback || undefined);
|
||||
return;
|
||||
}
|
||||
// For accept-once option, pass accept feedback if present
|
||||
if (selected.option.type === 'accept-once') {
|
||||
const trimmedFeedback = acceptFeedback.trim()
|
||||
onChange(selected.option, trimmedFeedback || undefined)
|
||||
return
|
||||
const trimmedFeedback = acceptFeedback.trim();
|
||||
onChange(selected.option, trimmedFeedback || undefined);
|
||||
return;
|
||||
}
|
||||
onChange(selected.option)
|
||||
onChange(selected.option);
|
||||
}
|
||||
}}
|
||||
onCancel={() => onChange({ type: 'reject' })}
|
||||
@@ -262,11 +239,10 @@ export function FilePermissionDialog<T extends ToolInput = ToolInput>({
|
||||
<Box paddingX={1} marginTop={1}>
|
||||
<Text dimColor>
|
||||
Esc to cancel
|
||||
{((focusedOption === 'yes' && !yesInputMode) ||
|
||||
(focusedOption === 'no' && !noInputMode)) &&
|
||||
{((focusedOption === 'yes' && !yesInputMode) || (focusedOption === 'no' && !noInputMode)) &&
|
||||
' · Tab to amend'}
|
||||
</Text>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user