更新大量 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:
claude-code-best
2026-04-04 23:24:27 +08:00
committed by GitHub
parent 02694918b5
commit 5b1a52b8e0
559 changed files with 103807 additions and 101817 deletions

View File

@@ -1,36 +1,43 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode, useCallback, useMemo, useState } from 'react';
import { Box, Text } from '../../ink.js';
import type { KeybindingAction } from '../../keybindings/types.js';
import { useKeybindings } from '../../keybindings/useKeybinding.js';
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from '../../services/analytics/index.js';
import { useSetAppState } from '../../state/AppState.js';
import { type OptionWithDescription, Select } from '../CustomSelect/select.js';
export type FeedbackType = 'accept' | 'reject';
import React, { type ReactNode, useCallback, useMemo, useState } from 'react'
import { Box, Text } from '../../ink.js'
import type { KeybindingAction } from '../../keybindings/types.js'
import { useKeybindings } from '../../keybindings/useKeybinding.js'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from '../../services/analytics/index.js'
import { useSetAppState } from '../../state/AppState.js'
import { type OptionWithDescription, Select } from '../CustomSelect/select.js'
export type FeedbackType = 'accept' | 'reject'
export type PermissionPromptOption<T extends string> = {
value: T;
label: ReactNode;
value: T
label: ReactNode
feedbackConfig?: {
type: FeedbackType;
placeholder?: string;
};
keybinding?: KeybindingAction;
};
type: FeedbackType
placeholder?: string
}
keybinding?: KeybindingAction
}
export type ToolAnalyticsContext = {
toolName: string;
isMcp: boolean;
};
toolName: string
isMcp: boolean
}
export type PermissionPromptProps<T extends string> = {
options: PermissionPromptOption<T>[];
onSelect: (value: T, feedback?: string) => void;
onCancel?: () => void;
question?: string | ReactNode;
toolAnalyticsContext?: ToolAnalyticsContext;
};
options: PermissionPromptOption<T>[]
onSelect: (value: T, feedback?: string) => void
onCancel?: () => void
question?: string | ReactNode
toolAnalyticsContext?: ToolAnalyticsContext
}
const DEFAULT_PLACEHOLDERS: Record<FeedbackType, string> = {
accept: 'tell Claude what to do next',
reject: 'tell Claude what to do differently'
};
reject: 'tell Claude what to do differently',
}
/**
* Shared component for permission prompts with optional feedback input.
@@ -42,294 +49,219 @@ const DEFAULT_PLACEHOLDERS: Record<FeedbackType, string> = {
* - Analytics events for feedback interactions
* - Transforming options to Select-compatible format
*/
export function PermissionPrompt(t0) {
const $ = _c(54);
const {
options,
onSelect,
onCancel,
question: t1,
toolAnalyticsContext
} = t0;
const question = t1 === undefined ? "Do you want to proceed?" : t1;
const setAppState = useSetAppState();
const [acceptFeedback, setAcceptFeedback] = useState("");
const [rejectFeedback, setRejectFeedback] = useState("");
const [acceptInputMode, setAcceptInputMode] = useState(false);
const [rejectInputMode, setRejectInputMode] = useState(false);
const [focusedValue, setFocusedValue] = useState(null);
const [acceptFeedbackModeEntered, setAcceptFeedbackModeEntered] = useState(false);
const [rejectFeedbackModeEntered, setRejectFeedbackModeEntered] = useState(false);
let t2;
if ($[0] !== focusedValue || $[1] !== options) {
let t3;
if ($[3] !== focusedValue) {
t3 = opt => opt.value === focusedValue;
$[3] = focusedValue;
$[4] = t3;
} else {
t3 = $[4];
}
t2 = options.find(t3);
$[0] = focusedValue;
$[1] = options;
$[2] = t2;
} else {
t2 = $[2];
}
const focusedOption = t2;
const focusedFeedbackType = focusedOption?.feedbackConfig?.type;
const showTabHint = focusedFeedbackType === "accept" && !acceptInputMode || focusedFeedbackType === "reject" && !rejectInputMode;
let t3;
if ($[5] !== acceptInputMode || $[6] !== options || $[7] !== rejectInputMode) {
let t4;
if ($[9] !== acceptInputMode || $[10] !== rejectInputMode) {
t4 = opt_0 => {
const {
value,
label,
feedbackConfig
} = opt_0;
if (!feedbackConfig) {
return {
label,
value
};
}
const {
type,
placeholder
} = feedbackConfig;
const isInputMode = type === "accept" ? acceptInputMode : rejectInputMode;
const onChange = type === "accept" ? setAcceptFeedback : setRejectFeedback;
const defaultPlaceholder = DEFAULT_PLACEHOLDERS[type];
if (isInputMode) {
return {
type: "input" as const,
label,
value,
placeholder: placeholder ?? defaultPlaceholder,
onChange,
allowEmptySubmitToCancel: true
};
}
export function PermissionPrompt<T extends string>({
options,
onSelect,
onCancel,
question = 'Do you want to proceed?',
toolAnalyticsContext,
}: PermissionPromptProps<T>): React.ReactNode {
const setAppState = useSetAppState()
const [acceptFeedback, setAcceptFeedback] = useState('')
const [rejectFeedback, setRejectFeedback] = useState('')
const [acceptInputMode, setAcceptInputMode] = useState(false)
const [rejectInputMode, setRejectInputMode] = useState(false)
const [focusedValue, setFocusedValue] = useState<T | null>(null)
// Track whether user ever entered feedback mode (persists after collapse)
const [acceptFeedbackModeEntered, setAcceptFeedbackModeEntered] =
useState(false)
const [rejectFeedbackModeEntered, setRejectFeedbackModeEntered] =
useState(false)
// Find which option is focused and whether it has feedback config
const focusedOption = options.find(opt => opt.value === focusedValue)
const focusedFeedbackType = focusedOption?.feedbackConfig?.type
// Show Tab hint when focused on a feedback-enabled option that's not already in input mode
const showTabHint =
(focusedFeedbackType === 'accept' && !acceptInputMode) ||
(focusedFeedbackType === 'reject' && !rejectInputMode)
// Transform options to Select-compatible format
const selectOptions = useMemo((): OptionWithDescription<T>[] => {
return options.map(opt => {
const { value, label, feedbackConfig } = opt
// No feedback config = simple option
if (!feedbackConfig) {
return {
label,
value
};
};
$[9] = acceptInputMode;
$[10] = rejectInputMode;
$[11] = t4;
} else {
t4 = $[11];
}
t3 = options.map(t4);
$[5] = acceptInputMode;
$[6] = options;
$[7] = rejectInputMode;
$[8] = t3;
} else {
t3 = $[8];
}
const selectOptions = t3;
let t4;
if ($[12] !== acceptInputMode || $[13] !== options || $[14] !== rejectInputMode || $[15] !== toolAnalyticsContext?.isMcp || $[16] !== toolAnalyticsContext?.toolName) {
t4 = value_0 => {
const option = options.find(opt_1 => opt_1.value === value_0);
if (!option?.feedbackConfig) {
return;
value,
}
}
const {
type: type_0
} = option.feedbackConfig;
const { type, placeholder } = feedbackConfig
const isInputMode = type === 'accept' ? acceptInputMode : rejectInputMode
const onChange = type === 'accept' ? setAcceptFeedback : setRejectFeedback
const defaultPlaceholder = DEFAULT_PLACEHOLDERS[type]
// When in input mode, show input field
if (isInputMode) {
return {
type: 'input' as const,
label,
value,
placeholder: placeholder ?? defaultPlaceholder,
onChange,
allowEmptySubmitToCancel: true,
}
}
// Not in input mode - show simple option
return {
label,
value,
}
})
}, [options, acceptInputMode, rejectInputMode])
// Handle Tab key to toggle input mode
const handleInputModeToggle = useCallback(
(value: T) => {
const option = options.find(opt => opt.value === value)
if (!option?.feedbackConfig) return
const { type } = option.feedbackConfig
const analyticsProps = {
toolName: toolAnalyticsContext?.toolName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
isMcp: toolAnalyticsContext?.isMcp ?? false
};
if (type_0 === "accept") {
toolName:
toolAnalyticsContext?.toolName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
isMcp: toolAnalyticsContext?.isMcp ?? false,
}
if (type === 'accept') {
if (acceptInputMode) {
setAcceptInputMode(false);
logEvent("tengu_accept_feedback_mode_collapsed", analyticsProps);
setAcceptInputMode(false)
logEvent('tengu_accept_feedback_mode_collapsed', analyticsProps)
} else {
setAcceptInputMode(true);
setAcceptFeedbackModeEntered(true);
logEvent("tengu_accept_feedback_mode_entered", analyticsProps);
setAcceptInputMode(true)
setAcceptFeedbackModeEntered(true)
logEvent('tengu_accept_feedback_mode_entered', analyticsProps)
}
} else {
if (type_0 === "reject") {
if (rejectInputMode) {
setRejectInputMode(false);
logEvent("tengu_reject_feedback_mode_collapsed", analyticsProps);
} else {
setRejectInputMode(true);
setRejectFeedbackModeEntered(true);
logEvent("tengu_reject_feedback_mode_entered", analyticsProps);
}
} else if (type === 'reject') {
if (rejectInputMode) {
setRejectInputMode(false)
logEvent('tengu_reject_feedback_mode_collapsed', analyticsProps)
} else {
setRejectInputMode(true)
setRejectFeedbackModeEntered(true)
logEvent('tengu_reject_feedback_mode_entered', analyticsProps)
}
}
};
$[12] = acceptInputMode;
$[13] = options;
$[14] = rejectInputMode;
$[15] = toolAnalyticsContext?.isMcp;
$[16] = toolAnalyticsContext?.toolName;
$[17] = t4;
} else {
t4 = $[17];
}
const handleInputModeToggle = t4;
let t5;
if ($[18] !== acceptFeedback || $[19] !== acceptFeedbackModeEntered || $[20] !== onSelect || $[21] !== options || $[22] !== rejectFeedback || $[23] !== rejectFeedbackModeEntered || $[24] !== toolAnalyticsContext?.isMcp || $[25] !== toolAnalyticsContext?.toolName) {
t5 = value_1 => {
const option_0 = options.find(opt_2 => opt_2.value === value_1);
if (!option_0) {
return;
}
let feedback;
if (option_0.feedbackConfig) {
const rawFeedback = option_0.feedbackConfig.type === "accept" ? acceptFeedback : rejectFeedback;
const trimmedFeedback = rawFeedback.trim();
},
[options, acceptInputMode, rejectInputMode, toolAnalyticsContext],
)
// Handle selection
const handleSelect = useCallback(
(value: T) => {
const option = options.find(opt => opt.value === value)
if (!option) return
// Get feedback if applicable
let feedback: string | undefined
if (option.feedbackConfig) {
const rawFeedback =
option.feedbackConfig.type === 'accept'
? acceptFeedback
: rejectFeedback
const trimmedFeedback = rawFeedback.trim()
if (trimmedFeedback) {
feedback = trimmedFeedback;
feedback = trimmedFeedback
}
const analyticsProps_0 = {
toolName: toolAnalyticsContext?.toolName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
// Log accept/reject submission with feedback context
const analyticsProps = {
toolName:
toolAnalyticsContext?.toolName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
isMcp: toolAnalyticsContext?.isMcp ?? false,
has_instructions: !!trimmedFeedback,
instructions_length: trimmedFeedback?.length ?? 0,
entered_feedback_mode: option_0.feedbackConfig.type === "accept" ? acceptFeedbackModeEntered : rejectFeedbackModeEntered
};
if (option_0.feedbackConfig.type === "accept") {
logEvent("tengu_accept_submitted", analyticsProps_0);
} else {
if (option_0.feedbackConfig.type === "reject") {
logEvent("tengu_reject_submitted", analyticsProps_0);
}
entered_feedback_mode:
option.feedbackConfig.type === 'accept'
? acceptFeedbackModeEntered
: rejectFeedbackModeEntered,
}
if (option.feedbackConfig.type === 'accept') {
logEvent('tengu_accept_submitted', analyticsProps)
} else if (option.feedbackConfig.type === 'reject') {
logEvent('tengu_reject_submitted', analyticsProps)
}
}
onSelect(value_1, feedback);
};
$[18] = acceptFeedback;
$[19] = acceptFeedbackModeEntered;
$[20] = onSelect;
$[21] = options;
$[22] = rejectFeedback;
$[23] = rejectFeedbackModeEntered;
$[24] = toolAnalyticsContext?.isMcp;
$[25] = toolAnalyticsContext?.toolName;
$[26] = t5;
} else {
t5 = $[26];
}
const handleSelect = t5;
let handlers;
if ($[27] !== handleSelect || $[28] !== options) {
handlers = {};
for (const opt_3 of options) {
if (opt_3.keybinding) {
handlers[opt_3.keybinding] = () => handleSelect(opt_3.value);
onSelect(value, feedback)
},
[
options,
acceptFeedback,
rejectFeedback,
onSelect,
toolAnalyticsContext,
acceptFeedbackModeEntered,
rejectFeedbackModeEntered,
],
)
// Register keybinding handlers for options that have a keybinding set
const keybindingHandlers = useMemo(() => {
const handlers: Record<string, () => void> = {}
for (const opt of options) {
if (opt.keybinding) {
handlers[opt.keybinding] = () => handleSelect(opt.value)
}
}
$[27] = handleSelect;
$[28] = options;
$[29] = handlers;
} else {
handlers = $[29];
}
const keybindingHandlers = handlers;
let t6;
if ($[30] === Symbol.for("react.memo_cache_sentinel")) {
t6 = {
context: "Confirmation"
};
$[30] = t6;
} else {
t6 = $[30];
}
useKeybindings(keybindingHandlers, t6);
let t7;
if ($[31] !== onCancel || $[32] !== setAppState) {
t7 = () => {
logEvent("tengu_permission_request_escape", {});
setAppState(_temp);
onCancel?.();
};
$[31] = onCancel;
$[32] = setAppState;
$[33] = t7;
} else {
t7 = $[33];
}
const handleCancel = t7;
let t8;
if ($[34] !== question) {
t8 = typeof question === "string" ? <Text>{question}</Text> : question;
$[34] = question;
$[35] = t8;
} else {
t8 = $[35];
}
let t9;
if ($[36] !== acceptFeedback || $[37] !== acceptInputMode || $[38] !== options || $[39] !== rejectFeedback || $[40] !== rejectInputMode) {
t9 = value_2 => {
const newOption = options.find(opt_4 => opt_4.value === value_2);
if (newOption?.feedbackConfig?.type !== "accept" && acceptInputMode && !acceptFeedback.trim()) {
setAcceptInputMode(false);
}
if (newOption?.feedbackConfig?.type !== "reject" && rejectInputMode && !rejectFeedback.trim()) {
setRejectInputMode(false);
}
setFocusedValue(value_2);
};
$[36] = acceptFeedback;
$[37] = acceptInputMode;
$[38] = options;
$[39] = rejectFeedback;
$[40] = rejectInputMode;
$[41] = t9;
} else {
t9 = $[41];
}
let t10;
if ($[42] !== handleCancel || $[43] !== handleInputModeToggle || $[44] !== handleSelect || $[45] !== selectOptions || $[46] !== t9) {
t10 = <Select options={selectOptions} inlineDescriptions={true} onChange={handleSelect} onCancel={handleCancel} onFocus={t9} onInputModeToggle={handleInputModeToggle} />;
$[42] = handleCancel;
$[43] = handleInputModeToggle;
$[44] = handleSelect;
$[45] = selectOptions;
$[46] = t9;
$[47] = t10;
} else {
t10 = $[47];
}
const t11 = showTabHint && " \xB7 Tab to amend";
let t12;
if ($[48] !== t11) {
t12 = <Box marginTop={1}><Text dimColor={true}>Esc to cancel{t11}</Text></Box>;
$[48] = t11;
$[49] = t12;
} else {
t12 = $[49];
}
let t13;
if ($[50] !== t10 || $[51] !== t12 || $[52] !== t8) {
t13 = <Box flexDirection="column">{t8}{t10}{t12}</Box>;
$[50] = t10;
$[51] = t12;
$[52] = t8;
$[53] = t13;
} else {
t13 = $[53];
}
return t13;
}
function _temp(prev) {
return {
...prev,
attribution: {
...prev.attribution,
escapeCount: prev.attribution.escapeCount + 1
}
};
return handlers
}, [options, handleSelect])
useKeybindings(keybindingHandlers, { context: 'Confirmation' })
// Handle cancel (Esc)
const handleCancel = useCallback(() => {
logEvent('tengu_permission_request_escape', {})
// Increment escape count for attribution tracking
setAppState(prev => ({
...prev,
attribution: {
...prev.attribution,
escapeCount: prev.attribution.escapeCount + 1,
},
}))
onCancel?.()
}, [onCancel, setAppState])
return (
<Box flexDirection="column">
{typeof question === 'string' ? <Text>{question}</Text> : question}
<Select
options={selectOptions}
inlineDescriptions
onChange={handleSelect}
onCancel={handleCancel}
onFocus={value => {
// Reset input mode when navigating away, but only if no text typed
const newOption = options.find(opt => opt.value === value)
if (
newOption?.feedbackConfig?.type !== 'accept' &&
acceptInputMode &&
!acceptFeedback.trim()
) {
setAcceptInputMode(false)
}
if (
newOption?.feedbackConfig?.type !== 'reject' &&
rejectInputMode &&
!rejectFeedback.trim()
) {
setRejectInputMode(false)
}
setFocusedValue(value)
}}
onInputModeToggle={handleInputModeToggle}
/>
<Box marginTop={1}>
<Text dimColor>Esc to cancel{showTabHint && ' · Tab to amend'}</Text>
</Box>
</Box>
)
}