mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)
* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-2): 格式化 commands (79 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-5): 格式化 components其余 + hooks + tools (232 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md - README.md: 大幅重写,更详细版本历史和配置示例 - Run.ps1: 新增 Windows 启动脚本 - TODO.md: 新增包完成清单 - V6.md: 删除(架构重构规划已不适用) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复以前的问题 * fix: 修复 login 面板的问题 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,33 +1,43 @@
|
||||
import { BASH_TOOL_NAME } from '../../../tools/BashTool/toolName.js';
|
||||
import { extractOutputRedirections } from '../../../utils/bash/commands.js';
|
||||
import { isClassifierPermissionsEnabled } from '../../../utils/permissions/bashClassifier.js';
|
||||
import type { PermissionDecisionReason } from '../../../utils/permissions/PermissionResult.js';
|
||||
import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js';
|
||||
import { shouldShowAlwaysAllowOptions } from '../../../utils/permissions/permissionsLoader.js';
|
||||
import type { OptionWithDescription } from '../../CustomSelect/select.js';
|
||||
import { generateShellSuggestionsLabel } from '../shellPermissionHelpers.js';
|
||||
export type BashToolUseOption = 'yes' | 'yes-apply-suggestions' | 'yes-prefix-edited' | 'yes-classifier-reviewed' | 'no';
|
||||
import { BASH_TOOL_NAME } from '../../../tools/BashTool/toolName.js'
|
||||
import { extractOutputRedirections } from '../../../utils/bash/commands.js'
|
||||
import { isClassifierPermissionsEnabled } from '../../../utils/permissions/bashClassifier.js'
|
||||
import type { PermissionDecisionReason } from '../../../utils/permissions/PermissionResult.js'
|
||||
import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js'
|
||||
import { shouldShowAlwaysAllowOptions } from '../../../utils/permissions/permissionsLoader.js'
|
||||
import type { OptionWithDescription } from '../../CustomSelect/select.js'
|
||||
import { generateShellSuggestionsLabel } from '../shellPermissionHelpers.js'
|
||||
|
||||
export type BashToolUseOption =
|
||||
| 'yes'
|
||||
| 'yes-apply-suggestions'
|
||||
| 'yes-prefix-edited'
|
||||
| 'yes-classifier-reviewed'
|
||||
| 'no'
|
||||
|
||||
/**
|
||||
* Check if a description already exists in the allow list.
|
||||
* Compares lowercase and trailing-whitespace-trimmed versions.
|
||||
*/
|
||||
function descriptionAlreadyExists(description: string, existingDescriptions: string[]): boolean {
|
||||
const normalized = description.toLowerCase().trimEnd();
|
||||
return existingDescriptions.some(existing => existing.toLowerCase().trimEnd() === normalized);
|
||||
function descriptionAlreadyExists(
|
||||
description: string,
|
||||
existingDescriptions: string[],
|
||||
): boolean {
|
||||
const normalized = description.toLowerCase().trimEnd()
|
||||
return existingDescriptions.some(
|
||||
existing => existing.toLowerCase().trimEnd() === normalized,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip output redirections so filenames don't show as commands in the label.
|
||||
*/
|
||||
function stripBashRedirections(command: string): string {
|
||||
const {
|
||||
commandWithoutRedirections,
|
||||
redirections
|
||||
} = extractOutputRedirections(command);
|
||||
const { commandWithoutRedirections, redirections } =
|
||||
extractOutputRedirections(command)
|
||||
// Only use stripped version if there were actual redirections
|
||||
return redirections.length > 0 ? commandWithoutRedirections : command;
|
||||
return redirections.length > 0 ? commandWithoutRedirections : command
|
||||
}
|
||||
|
||||
export function bashToolUseOptions({
|
||||
suggestions = [],
|
||||
decisionReason,
|
||||
@@ -40,25 +50,26 @@ export function bashToolUseOptions({
|
||||
yesInputMode = false,
|
||||
noInputMode = false,
|
||||
editablePrefix,
|
||||
onEditablePrefixChange
|
||||
onEditablePrefixChange,
|
||||
}: {
|
||||
suggestions?: PermissionUpdate[];
|
||||
decisionReason?: PermissionDecisionReason;
|
||||
onRejectFeedbackChange: (value: string) => void;
|
||||
onAcceptFeedbackChange: (value: string) => void;
|
||||
onClassifierDescriptionChange?: (value: string) => void;
|
||||
classifierDescription?: string;
|
||||
suggestions?: PermissionUpdate[]
|
||||
decisionReason?: PermissionDecisionReason
|
||||
onRejectFeedbackChange: (value: string) => void
|
||||
onAcceptFeedbackChange: (value: string) => void
|
||||
onClassifierDescriptionChange?: (value: string) => void
|
||||
classifierDescription?: string
|
||||
/** Whether the initial classifier description was empty. When true, hides the option. */
|
||||
initialClassifierDescriptionEmpty?: boolean;
|
||||
existingAllowDescriptions?: string[];
|
||||
yesInputMode?: boolean;
|
||||
noInputMode?: boolean;
|
||||
initialClassifierDescriptionEmpty?: boolean
|
||||
existingAllowDescriptions?: string[]
|
||||
yesInputMode?: boolean
|
||||
noInputMode?: boolean
|
||||
/** Editable prefix rule content (e.g., "npm run:*"). When set, replaces Haiku-based suggestions. */
|
||||
editablePrefix?: string;
|
||||
editablePrefix?: string
|
||||
/** Callback when the user edits the prefix value. */
|
||||
onEditablePrefixChange?: (value: string) => void;
|
||||
onEditablePrefixChange?: (value: string) => void
|
||||
}): OptionWithDescription<BashToolUseOption>[] {
|
||||
const options: OptionWithDescription<BashToolUseOption>[] = [];
|
||||
const options: OptionWithDescription<BashToolUseOption>[] = []
|
||||
|
||||
if (yesInputMode) {
|
||||
options.push({
|
||||
type: 'input',
|
||||
@@ -66,13 +77,13 @@ export function bashToolUseOptions({
|
||||
value: 'yes',
|
||||
placeholder: 'and tell Claude what to do next',
|
||||
onChange: onAcceptFeedbackChange,
|
||||
allowEmptySubmitToCancel: true
|
||||
});
|
||||
allowEmptySubmitToCancel: true,
|
||||
})
|
||||
} else {
|
||||
options.push({
|
||||
label: 'Yes',
|
||||
value: 'yes'
|
||||
});
|
||||
value: 'yes',
|
||||
})
|
||||
}
|
||||
|
||||
// Only show "always allow" options when not restricted by allowManagedPermissionRulesOnly
|
||||
@@ -81,8 +92,18 @@ export function bashToolUseOptions({
|
||||
// Haiku-generated suggestion label — but only when the suggestions
|
||||
// don't contain non-Bash items (addDirectories, Read rules) that
|
||||
// the editable prefix can't represent.
|
||||
const hasNonBashSuggestions = suggestions.some(s => s.type === 'addDirectories' || s.type === 'addRules' && s.rules?.some(r => r.toolName !== BASH_TOOL_NAME));
|
||||
if (editablePrefix !== undefined && onEditablePrefixChange && !hasNonBashSuggestions && suggestions.length > 0) {
|
||||
const hasNonBashSuggestions = suggestions.some(
|
||||
s =>
|
||||
s.type === 'addDirectories' ||
|
||||
(s.type === 'addRules' &&
|
||||
s.rules?.some(r => r.toolName !== BASH_TOOL_NAME)),
|
||||
)
|
||||
if (
|
||||
editablePrefix !== undefined &&
|
||||
onEditablePrefixChange &&
|
||||
!hasNonBashSuggestions &&
|
||||
suggestions.length > 0
|
||||
) {
|
||||
options.push({
|
||||
type: 'input',
|
||||
label: 'Yes, and don\u2019t ask again for',
|
||||
@@ -93,15 +114,20 @@ export function bashToolUseOptions({
|
||||
allowEmptySubmitToCancel: true,
|
||||
showLabelWithValue: true,
|
||||
labelValueSeparator: ': ',
|
||||
resetCursorOnUpdate: true
|
||||
});
|
||||
resetCursorOnUpdate: true,
|
||||
})
|
||||
} else if (suggestions.length > 0) {
|
||||
const label = generateShellSuggestionsLabel(suggestions, BASH_TOOL_NAME, stripBashRedirections);
|
||||
const label = generateShellSuggestionsLabel(
|
||||
suggestions,
|
||||
BASH_TOOL_NAME,
|
||||
stripBashRedirections,
|
||||
)
|
||||
|
||||
if (label) {
|
||||
options.push({
|
||||
label,
|
||||
value: 'yes-apply-suggestions'
|
||||
});
|
||||
value: 'yes-apply-suggestions',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +137,21 @@ export function bashToolUseOptions({
|
||||
// (prompt-based rules don't help when the server-side classifier triggers first).
|
||||
// Skip when the editable prefix option is already shown — they serve the
|
||||
// same role and having two identical-looking "don't ask again" inputs is confusing.
|
||||
const editablePrefixShown = options.some(o => o.value === 'yes-prefix-edited');
|
||||
if ((process.env.USER_TYPE) === 'ant' && !editablePrefixShown && isClassifierPermissionsEnabled() && onClassifierDescriptionChange && !initialClassifierDescriptionEmpty && !descriptionAlreadyExists(classifierDescription ?? '', existingAllowDescriptions) && decisionReason?.type !== 'classifier') {
|
||||
const editablePrefixShown = options.some(
|
||||
o => o.value === 'yes-prefix-edited',
|
||||
)
|
||||
if (
|
||||
process.env.USER_TYPE === 'ant' &&
|
||||
!editablePrefixShown &&
|
||||
isClassifierPermissionsEnabled() &&
|
||||
onClassifierDescriptionChange &&
|
||||
!initialClassifierDescriptionEmpty &&
|
||||
!descriptionAlreadyExists(
|
||||
classifierDescription ?? '',
|
||||
existingAllowDescriptions,
|
||||
) &&
|
||||
decisionReason?.type !== 'classifier'
|
||||
) {
|
||||
options.push({
|
||||
type: 'input',
|
||||
label: 'Yes, and don\u2019t ask again for',
|
||||
@@ -123,10 +162,11 @@ export function bashToolUseOptions({
|
||||
allowEmptySubmitToCancel: true,
|
||||
showLabelWithValue: true,
|
||||
labelValueSeparator: ': ',
|
||||
resetCursorOnUpdate: true
|
||||
});
|
||||
resetCursorOnUpdate: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (noInputMode) {
|
||||
options.push({
|
||||
type: 'input',
|
||||
@@ -134,13 +174,14 @@ export function bashToolUseOptions({
|
||||
value: 'no',
|
||||
placeholder: 'and tell Claude what to do differently',
|
||||
onChange: onRejectFeedbackChange,
|
||||
allowEmptySubmitToCancel: true
|
||||
});
|
||||
allowEmptySubmitToCancel: true,
|
||||
})
|
||||
} else {
|
||||
options.push({
|
||||
label: 'No',
|
||||
value: 'no'
|
||||
});
|
||||
value: 'no',
|
||||
})
|
||||
}
|
||||
return options;
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user